Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/Menu/UIChoice.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: UIChoice Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectUIChoice *UIChoice;
11
12
void UIChoice_Update(void)
13
{
14
RSDK_THIS(UIChoice);
15
16
EntityUIButton *parent = (EntityUIButton *)self->parent;
17
bool32 disabled = self->disabled;
18
19
self->touchPosSizeS.x = self->size.x;
20
self->touchPosSizeS.y = self->size.y;
21
self->touchPosOffsetS.y = 0;
22
self->touchPosSizeS.x = (self->touchPosSizeS.x + 3 * self->size.y) >> 1;
23
self->touchPosSizeS.y = self->size.y + 0x60000;
24
self->touchPosOffsetS.x = -(self->touchPosSizeS.x >> 1);
25
26
if (parent && (disabled || parent->disabled))
27
disabled = true;
28
29
if (self->aniFrames != UIWidgets->textFrames || self->isDisabled != disabled) {
30
if (disabled)
31
RSDK.SetSpriteAnimation(UIWidgets->textFrames, 7, &self->labelAnimator, true, 0);
32
else
33
RSDK.SetSpriteAnimation(UIWidgets->textFrames, self->listID, &self->labelAnimator, true, self->frameID);
34
35
self->aniFrames = UIWidgets->textFrames;
36
self->isDisabled = disabled;
37
}
38
39
StateMachine_Run(self->state);
40
41
if (parent && parent->state == UIButton_State_HandleButtonLeave) {
42
self->textBounceOffset = 0;
43
self->buttonBounceOffset = 0;
44
self->isSelected = false;
45
self->state = UIChoice_State_HandleButtonLeave;
46
}
47
}
48
49
void UIChoice_LateUpdate(void) {}
50
51
void UIChoice_StaticUpdate(void) {}
52
53
void UIChoice_Draw(void)
54
{
55
RSDK_THIS(UIChoice);
56
57
Vector2 drawPos;
58
int32 size = (self->size.x + self->size.y) >> 16;
59
60
drawPos.x = self->position.x;
61
drawPos.y = self->position.y;
62
drawPos.x -= self->buttonBounceOffset;
63
drawPos.y -= self->buttonBounceOffset;
64
#if MANIA_USE_PLUS
65
UIWidgets_DrawParallelogram(drawPos.x, drawPos.y, size, self->size.y >> 16, self->bgEdgeSize, (UIWidgets->buttonColor >> 16) & 0xFF,
66
(UIWidgets->buttonColor >> 8) & 0xFF, (UIWidgets->buttonColor) & 0xFF);
67
#else
68
UIWidgets_DrawParallelogram(drawPos.x, drawPos.y, size, self->size.y >> 16, self->bgEdgeSize, 0xF0, 0xF0, 0xF0);
69
#endif
70
71
drawPos.x = self->position.x;
72
drawPos.y = self->position.y;
73
drawPos.x += self->buttonBounceOffset;
74
drawPos.y += self->buttonBounceOffset;
75
UIWidgets_DrawParallelogram(drawPos.x, drawPos.y, size, self->size.y >> 16, self->bgEdgeSize, 0x00, 0x00, 0x00);
76
77
EntityUIButton *parent = (EntityUIButton *)self->parent;
78
if (self->arrowWidth > 0 && self->isSelected && !(self->disabled || parent->disabled)) {
79
drawPos.x = self->position.x;
80
drawPos.y = self->position.y;
81
drawPos.y += self->textBounceOffset;
82
drawPos.x -= self->arrowWidth << 15;
83
drawPos.x += self->buttonBounceOffset;
84
drawPos.y += self->buttonBounceOffset;
85
RSDK.DrawSprite(&self->leftArrowAnimator, &drawPos, false);
86
87
drawPos.x = self->position.x;
88
drawPos.y = self->position.y;
89
drawPos.y += self->textBounceOffset;
90
drawPos.x += self->arrowWidth << 15;
91
drawPos.x += self->buttonBounceOffset;
92
drawPos.y += self->buttonBounceOffset;
93
RSDK.DrawSprite(&self->rightArrowAnimator, &drawPos, false);
94
}
95
96
if (self->textVisible) {
97
drawPos.x = self->position.x;
98
drawPos.y = self->position.y;
99
drawPos.y = self->textBounceOffset + self->position.y;
100
drawPos.x = self->buttonBounceOffset + self->position.x;
101
drawPos.y += self->buttonBounceOffset;
102
103
switch (self->align) {
104
case UIBUTTON_ALIGN_LEFT: drawPos.x += -0x60000 - (self->size.x >> 1); break;
105
106
default:
107
case UIBUTTON_ALIGN_CENTER: break;
108
109
case UIBUTTON_ALIGN_RIGHT: drawPos.x += (self->size.x >> 1) - 0x60000; break;
110
}
111
112
if (self->auxIcon)
113
RSDK.DrawSprite(&self->iconAnimator, &drawPos, false);
114
115
if (!self->noText)
116
RSDK.DrawSprite(&self->labelAnimator, &drawPos, false);
117
}
118
}
119
120
void UIChoice_Create(void *data)
121
{
122
RSDK_THIS(UIChoice);
123
124
if (!SceneInfo->inEditor) {
125
self->visible = true;
126
self->drawGroup = 2;
127
self->active = ACTIVE_NEVER;
128
self->updateRange.x = 0x800000;
129
self->updateRange.y = 0x400000;
130
self->bgEdgeSize = self->size.y >> 16;
131
self->size.y = abs(self->size.y);
132
self->textVisible = true;
133
134
self->touchCB = UIChoice_CheckTouch;
135
136
self->aniFrames = UIWidgets->textFrames;
137
RSDK.SetSpriteAnimation(UIWidgets->textFrames, self->listID, &self->labelAnimator, true, self->frameID);
138
RSDK.SetSpriteAnimation(UIChoice->aniFrames, self->auxListID, &self->iconAnimator, true, self->auxFrameID);
139
RSDK.SetSpriteAnimation(UIWidgets->uiFrames, 2, &self->leftArrowAnimator, true, 0);
140
RSDK.SetSpriteAnimation(UIWidgets->uiFrames, 2, &self->rightArrowAnimator, true, 1);
141
}
142
}
143
144
void UIChoice_StageLoad(void) { UIChoice->aniFrames = RSDK.LoadSpriteAnimation("UI/SaveSelect.bin", SCOPE_STAGE); }
145
146
void UIChoice_SetChoiceActive(EntityUIChoice *choice)
147
{
148
if (choice) {
149
EntityUIButton *parent = (EntityUIButton *)choice->parent;
150
151
choice->active = ACTIVE_BOUNDS;
152
if (!parent->disabled)
153
choice->visible = true;
154
155
choice->textBounceOffset = 0;
156
choice->buttonBounceOffset = 0;
157
choice->textBounceVelocity = -0x20000;
158
choice->buttonBounceVelocity = -0x20000;
159
choice->isSelected = true;
160
choice->state = UIChoice_State_HandleButtonEnter;
161
}
162
}
163
164
void UIChoice_SetChoiceInactive(EntityUIChoice *choice)
165
{
166
if (choice) {
167
choice->textBounceOffset = 0;
168
choice->buttonBounceOffset = 0;
169
choice->isSelected = false;
170
choice->state = UIChoice_State_HandleButtonLeave;
171
}
172
}
173
174
void UIChoice_TouchedCB_Left(void)
175
{
176
RSDK_THIS(UIChoice);
177
178
EntityUIButton *parent = (EntityUIButton *)self->parent;
179
180
int32 selection = parent->selection;
181
if (--selection < 0) {
182
while (selection < 0) selection += parent->choiceCount;
183
}
184
EntityUIButton *choice = UIButton_GetChoicePtr(parent, selection);
185
186
while ((choice && choice->disabled) && selection != parent->selection) {
187
if (--selection < 0) {
188
while (selection < 0) selection += parent->choiceCount;
189
}
190
191
choice = UIButton_GetChoicePtr(parent, selection);
192
}
193
194
if (selection != parent->selection) {
195
UIButton_SetChoiceSelectionWithCB(parent, selection);
196
RSDK.PlaySfx(UIWidgets->sfxBleep, false, 255);
197
}
198
}
199
200
void UIChoice_TouchedCB_Right(void)
201
{
202
RSDK_THIS(UIChoice);
203
204
EntityUIButton *parent = (EntityUIButton *)self->parent;
205
206
int32 selection = (parent->selection + 1) % parent->choiceCount;
207
EntityUIButton *choice = UIButton_GetChoicePtr(parent, selection);
208
209
while ((choice && choice->disabled) && selection != parent->selection) {
210
selection = (selection + 1) % parent->choiceCount;
211
choice = UIButton_GetChoicePtr(parent, selection);
212
}
213
214
if (selection != parent->selection) {
215
UIButton_SetChoiceSelectionWithCB(parent, selection);
216
RSDK.PlaySfx(UIWidgets->sfxBleep, false, 255);
217
}
218
}
219
220
bool32 UIChoice_CheckTouch(void)
221
{
222
RSDK_THIS(UIChoice);
223
224
void (*callbacks[2])(void);
225
Vector2 touchStart[2];
226
Vector2 touchEnd[2];
227
228
callbacks[0] = UIChoice_TouchedCB_Left;
229
callbacks[1] = UIChoice_TouchedCB_Right;
230
231
touchStart[0].x = self->touchPosSizeS.x;
232
touchStart[0].y = self->touchPosSizeS.y;
233
touchStart[1].x = self->touchPosSizeS.x;
234
touchStart[1].y = self->touchPosSizeS.y;
235
236
touchEnd[0].x = self->touchPosOffsetS.x;
237
touchEnd[0].y = self->touchPosOffsetS.y;
238
touchEnd[1].x = -self->touchPosOffsetS.x;
239
touchEnd[1].y = self->touchPosOffsetS.y;
240
241
bool32 pressed = false;
242
for (int32 i = 0; i < 2; ++i) {
243
if (TouchInfo->count) {
244
int32 sizeX = touchStart[i].x >> 1;
245
int32 sizeY = touchStart[i].y >> 1;
246
247
for (int32 t = 0; t < TouchInfo->count; ++t) {
248
int32 x = (ScreenInfo->position.x << 16) - ((TouchInfo->x[t] * ScreenInfo->size.x) * -65536.0f);
249
int32 y = (ScreenInfo->position.y << 16) - ((TouchInfo->y[t] * ScreenInfo->size.y) * -65536.0f);
250
251
int32 touchX = abs(touchEnd[i].x + self->position.x - x);
252
int32 touchY = abs(touchEnd[i].y + self->position.y - y);
253
if (touchX < sizeX && touchY < sizeY) {
254
self->touchID = i;
255
pressed = true;
256
}
257
}
258
}
259
else if (self->touchPressed && self->touchID == i && !self->disabled) {
260
#if RETRO_USE_MOD_LOADER
261
StateMachine_Run(callbacks[i]);
262
#else
263
callbacks[i]();
264
#endif
265
}
266
}
267
268
self->touchPressed = pressed;
269
270
return pressed;
271
}
272
273
void UIChoice_State_HandleButtonLeave(void)
274
{
275
RSDK_THIS(UIChoice);
276
277
if (self->textBounceOffset) {
278
int32 offset = -(self->textBounceOffset / abs(self->textBounceOffset));
279
self->textBounceOffset += offset << 15;
280
281
if (offset < 0 && self->textBounceOffset < 0)
282
self->textBounceOffset = 0;
283
else if (offset > 0 && self->textBounceOffset > 0)
284
self->textBounceOffset = 0;
285
}
286
287
if (self->buttonBounceOffset) {
288
int32 offset = -(self->buttonBounceOffset / abs(self->buttonBounceOffset));
289
self->buttonBounceOffset += offset << 16;
290
291
if (offset < 0 && self->buttonBounceOffset < 0)
292
self->buttonBounceOffset = 0;
293
else if (offset > 0 && self->buttonBounceOffset > 0)
294
self->buttonBounceOffset = 0;
295
}
296
}
297
298
void UIChoice_State_HandleButtonEnter(void)
299
{
300
RSDK_THIS(UIChoice);
301
302
self->textBounceVelocity += 0x4000;
303
self->textBounceOffset += self->textBounceVelocity;
304
305
if (self->textBounceOffset >= 0 && self->textBounceVelocity > 0) {
306
self->textBounceOffset = 0;
307
self->textBounceVelocity = 0;
308
}
309
310
self->buttonBounceVelocity += 0x4800;
311
self->buttonBounceOffset += self->buttonBounceVelocity;
312
313
if (self->buttonBounceOffset >= -0x20000 && self->buttonBounceVelocity > 0) {
314
self->buttonBounceOffset = -0x20000;
315
self->buttonBounceVelocity = 0;
316
}
317
}
318
319
#if GAME_INCLUDE_EDITOR
320
void UIChoice_EditorDraw(void)
321
{
322
RSDK_THIS(UIChoice);
323
324
int32 sizeY = self->size.y;
325
326
self->drawGroup = 2;
327
self->updateRange.x = 0x800000;
328
self->updateRange.y = 0x400000;
329
self->bgEdgeSize = self->size.y >> 16;
330
self->size.y = abs(self->size.y);
331
self->textVisible = true;
332
self->aniFrames = UIWidgets->textFrames;
333
334
RSDK.SetSpriteAnimation(UIWidgets->textFrames, self->listID, &self->labelAnimator, true, self->frameID);
335
RSDK.SetSpriteAnimation(UIChoice->aniFrames, self->auxListID, &self->iconAnimator, true, self->auxFrameID);
336
RSDK.SetSpriteAnimation(UIWidgets->uiFrames, 2, &self->leftArrowAnimator, true, 0);
337
RSDK.SetSpriteAnimation(UIWidgets->uiFrames, 2, &self->rightArrowAnimator, true, 1);
338
339
self->isSelected = showGizmos();
340
// Crash prevention
341
self->parent = (Entity *)self;
342
343
UIChoice_Draw();
344
345
self->size.y = sizeY;
346
}
347
348
void UIChoice_EditorLoad(void)
349
{
350
UIChoice->aniFrames = RSDK.LoadSpriteAnimation("UI/SaveSelect.bin", SCOPE_STAGE);
351
352
RSDK_ACTIVE_VAR(UIChoice, align);
353
RSDK_ENUM_VAR("Left", UIBUTTON_ALIGN_LEFT);
354
RSDK_ENUM_VAR("Center", UIBUTTON_ALIGN_CENTER);
355
RSDK_ENUM_VAR("Right", UIBUTTON_ALIGN_RIGHT);
356
}
357
#endif
358
359
void UIChoice_Serialize(void)
360
{
361
RSDK_EDITABLE_VAR(UIChoice, VAR_BOOL, disabled);
362
RSDK_EDITABLE_VAR(UIChoice, VAR_VECTOR2, size);
363
RSDK_EDITABLE_VAR(UIChoice, VAR_ENUM, listID);
364
RSDK_EDITABLE_VAR(UIChoice, VAR_ENUM, frameID);
365
RSDK_EDITABLE_VAR(UIChoice, VAR_BOOL, noText);
366
RSDK_EDITABLE_VAR(UIChoice, VAR_BOOL, auxIcon);
367
RSDK_EDITABLE_VAR(UIChoice, VAR_ENUM, auxListID);
368
RSDK_EDITABLE_VAR(UIChoice, VAR_ENUM, auxFrameID);
369
RSDK_EDITABLE_VAR(UIChoice, VAR_ENUM, align);
370
RSDK_EDITABLE_VAR(UIChoice, VAR_ENUM, arrowWidth);
371
}
372
373