Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/Menu/UICarousel.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: UICarousel Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
#if MANIA_USE_PLUS
11
ObjectUICarousel *UICarousel;
12
13
void UICarousel_Update(void) {}
14
15
void UICarousel_LateUpdate(void)
16
{
17
RSDK_THIS(UICarousel);
18
19
if (self->parent) {
20
UICarousel_HandleScrolling();
21
UICarousel_HandleButtonPositions();
22
23
self->offset.x -= self->offset.x >> 2;
24
self->offset.y -= self->offset.y >> 2;
25
26
if (abs(self->offset.y) <= 0x10000)
27
self->offset.y = 0;
28
}
29
}
30
31
void UICarousel_StaticUpdate(void) {}
32
33
void UICarousel_Draw(void) {}
34
35
void UICarousel_Create(void *data)
36
{
37
RSDK_THIS(UICarousel);
38
39
if (!SceneInfo->inEditor) {
40
self->startPos.x = self->position.x;
41
self->startPos.y = self->position.y;
42
self->active = ACTIVE_BOUNDS;
43
44
self->unused1 = 0;
45
self->unused2 = 0;
46
self->unused3 = 0;
47
self->unused4 = 0;
48
49
self->visible = false;
50
self->updateRange.x = 0x800000;
51
self->updateRange.y = 0x800000;
52
self->scrollOffset = -1;
53
self->buttonID = -1;
54
self->minOffset = 0;
55
self->maxOffset = 20;
56
}
57
}
58
59
void UICarousel_StageLoad(void) {}
60
61
void UICarousel_HandleScrolling(void)
62
{
63
RSDK_THIS(UICarousel);
64
65
EntityUIControl *control = (EntityUIControl *)self->parent;
66
int32 buttonID = self->buttonID;
67
68
if (control->buttonID != buttonID) {
69
int32 max = control->buttonCount - 1;
70
bool32 movedUp = false;
71
bool32 movedDown = false;
72
73
if (buttonID != -1) {
74
if (!buttonID && control->buttonID == max) {
75
movedUp = true;
76
}
77
else if (buttonID == max && !control->buttonID) {
78
movedDown = true;
79
}
80
else {
81
if (control->buttonID < buttonID)
82
movedUp = true;
83
else if (control->buttonID > buttonID)
84
movedDown = true;
85
}
86
}
87
88
// Bug Details:
89
// This is HORRIBLY broken when using touch controls
90
// the virtual scrolling expects buttons to only be incremented one at a time
91
// HOWEVER, using touch you can jump to any visible button, which can be jumping 2 or more buttons at a time!!
92
// as a result of that, the scrollOffset & virtualIndex will become misaligned from the visual buttonID and mess up controls and visuals
93
// Fix:
94
// find a way to increment by however many buttons we jumped, rather than just by 1
95
// this is slightly harder than it sounds due to the virtual scroll & wrapping being applied
96
97
int32 scrollOffset = self->scrollOffset;
98
if (movedUp) {
99
--self->virtualIndex;
100
self->scrollOffset = self->virtualIndex - (control->buttonCount >> 1);
101
}
102
else if (movedDown) {
103
++self->virtualIndex;
104
self->scrollOffset = self->virtualIndex - (control->buttonCount >> 1);
105
}
106
107
if (self->maxOffset != -1) {
108
if (self->scrollOffset + control->buttonCount > self->maxOffset + 1)
109
self->scrollOffset = self->maxOffset - control->buttonCount + 1;
110
111
if (self->virtualIndex > self->maxOffset - 1) {
112
self->virtualIndex = self->maxOffset - 1;
113
control->buttonID = buttonID;
114
}
115
}
116
117
if (self->minOffset != -1) {
118
if (self->scrollOffset < self->minOffset - 1)
119
self->scrollOffset = self->minOffset - 1;
120
121
if (self->virtualIndex < self->minOffset) {
122
self->virtualIndex = self->minOffset;
123
control->buttonID = buttonID;
124
}
125
}
126
127
if (self->scrollOffset >= scrollOffset) {
128
if (self->scrollOffset > scrollOffset)
129
self->offset.y += abs(self->shift.y);
130
131
self->buttonID = control->buttonID;
132
}
133
else {
134
self->offset.y -= abs(self->shift.y);
135
self->buttonID = control->buttonID;
136
}
137
}
138
}
139
140
void UICarousel_HandleButtonPositions(void)
141
{
142
RSDK_THIS(UICarousel);
143
144
EntityUIControl *control = (EntityUIControl *)self->parent;
145
146
Vector2 positions[0x10];
147
memset(positions, 0, sizeof(positions));
148
149
for (int32 i = 0; i < control->buttonCount; ++i) {
150
positions[i].x = self->position.x;
151
positions[i].y = self->position.y - (self->shift.y * i);
152
}
153
154
for (int32 i = 0; i < control->buttonCount; ++i) {
155
EntityUIButton *item = control->buttons[i];
156
157
int32 id = (i - self->scrollOffset) % control->buttonCount;
158
if (id < 0)
159
id += control->buttonCount;
160
161
item->position.x = positions[id].x + self->offset.x;
162
item->position.y = positions[id].y + self->offset.y;
163
item->drawGroup = id - control->buttonCount + 12;
164
}
165
}
166
167
#if GAME_INCLUDE_EDITOR
168
void UICarousel_EditorDraw(void)
169
{
170
RSDK_THIS(UICarousel);
171
172
DrawHelpers_DrawRectOutline(self->position.x + self->clipOffset.x, self->position.y + self->clipOffset.y, self->clipSize.x, self->clipSize.y,
173
0xFF0000);
174
}
175
176
void UICarousel_EditorLoad(void) {}
177
#endif
178
179
void UICarousel_Serialize(void)
180
{
181
RSDK_EDITABLE_VAR(UICarousel, VAR_VECTOR2, shift);
182
RSDK_EDITABLE_VAR(UICarousel, VAR_VECTOR2, clipSize);
183
RSDK_EDITABLE_VAR(UICarousel, VAR_VECTOR2, clipOffset);
184
}
185
#endif
186
187