Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/Menu/UIButton.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: UIButton Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectUIButton *UIButton;
11
12
void UIButton_Update(void)
13
{
14
RSDK_THIS(UIButton);
15
16
self->touchPosSizeS.x = self->size.x;
17
self->touchPosOffsetS.x = 0;
18
self->touchPosOffsetS.y = 0;
19
self->touchPosSizeS.x += 3 * self->size.y;
20
self->touchPosSizeS.y = self->size.y + 0x60000;
21
22
if (self->textFrames != UIWidgets->textFrames || self->startListID != self->listID || self->startFrameID != self->frameID
23
|| self->isDisabled != self->disabled) {
24
if (self->disabled)
25
RSDK.SetSpriteAnimation(UIWidgets->textFrames, 7, &self->animator, true, 0);
26
else
27
RSDK.SetSpriteAnimation(UIWidgets->textFrames, self->listID, &self->animator, true, self->frameID);
28
29
self->textFrames = UIWidgets->textFrames;
30
self->startListID = self->listID;
31
self->startFrameID = self->frameID;
32
self->isDisabled = self->disabled;
33
}
34
35
EntityUIButton *choice = UIButton_GetChoicePtr(self, self->selection);
36
if (choice)
37
choice->visible = true;
38
39
StateMachine_Run(self->state);
40
41
EntityUIControl *parent = (EntityUIControl *)self->parent;
42
if (parent && self->state == UIButton_State_HandleButtonEnter
43
&& (parent->state != UIControl_ProcessInputs || parent->buttons[parent->buttonID] != self)) {
44
self->isSelected = false;
45
UIButton_ButtonLeaveCB();
46
}
47
}
48
49
void UIButton_LateUpdate(void) {}
50
51
void UIButton_StaticUpdate(void) {}
52
53
void UIButton_Draw(void)
54
{
55
RSDK_THIS(UIButton);
56
57
Vector2 drawPos;
58
int32 width = (self->size.x + self->size.y) >> 16;
59
60
drawPos.x = self->position.x - self->buttonBounceOffset;
61
drawPos.y = self->position.y - self->buttonBounceOffset;
62
#if MANIA_USE_PLUS
63
UIWidgets_DrawParallelogram(drawPos.x, drawPos.y, width, self->size.y >> 16, self->bgEdgeSize, (UIWidgets->buttonColor >> 16) & 0xFF,
64
(UIWidgets->buttonColor >> 8) & 0xFF, (UIWidgets->buttonColor) & 0xFF);
65
#else
66
UIWidgets_DrawParallelogram(drawPos.x, drawPos.y, width, self->size.y >> 16, self->bgEdgeSize, 0xF0, 0xF0, 0xF0);
67
#endif
68
69
drawPos.x = self->position.x + self->buttonBounceOffset;
70
drawPos.y = self->position.y + self->buttonBounceOffset;
71
UIWidgets_DrawParallelogram(drawPos.x, drawPos.y, width, self->size.y >> 16, self->bgEdgeSize, 0x00, 0x00, 0x00);
72
73
if (self->textVisible) {
74
drawPos.x = self->buttonBounceOffset + self->position.x;
75
drawPos.y = self->buttonBounceOffset + self->position.y;
76
drawPos.y += self->textBounceOffset;
77
78
switch (self->align) {
79
case UIBUTTON_ALIGN_LEFT: drawPos.x += -0x60000 - (self->size.x >> 1); break;
80
81
case UIBUTTON_ALIGN_CENTER: break;
82
83
case UIBUTTON_ALIGN_RIGHT:
84
drawPos.x -= 0x60000;
85
drawPos.x += self->size.x >> 1;
86
break;
87
}
88
89
if (self->disabled && self->align == UIBUTTON_ALIGN_LEFT)
90
drawPos.x += 0x150000;
91
92
RSDK.DrawSprite(&self->animator, &drawPos, false);
93
}
94
}
95
96
void UIButton_Create(void *data)
97
{
98
RSDK_THIS(UIButton);
99
100
if (!SceneInfo->inEditor) {
101
self->drawGroup = 2;
102
self->visible = !self->invisible;
103
self->active = ACTIVE_BOUNDS;
104
self->updateRange.x = TO_FIXED(128);
105
self->updateRange.y = TO_FIXED(64);
106
self->bgEdgeSize = self->size.y >> 16;
107
self->size.y = abs(self->size.y);
108
109
self->processButtonCB = UIButton_ProcessButtonCB;
110
self->touchCB = UIButton_ProcessTouchCB_Single;
111
self->selectedCB = UIButton_SelectedCB;
112
self->failCB = UIButton_FailCB;
113
self->buttonEnterCB = UIButton_ButtonEnterCB;
114
self->buttonLeaveCB = UIButton_ButtonLeaveCB;
115
self->checkButtonEnterCB = UIButton_CheckButtonEnterCB;
116
self->checkSelectedCB = UIButton_CheckSelectedCB;
117
118
self->textVisible = true;
119
RSDK.SetSpriteAnimation(UIWidgets->textFrames, self->listID, &self->animator, true, self->frameID);
120
self->textFrames = UIWidgets->textFrames;
121
self->startListID = self->listID;
122
self->startFrameID = self->frameID;
123
124
int32 slot = RSDK.GetEntitySlot(self) - self->choiceCount;
125
for (int32 i = 0; i < self->choiceCount; ++i) {
126
EntityUIButton *item = RSDK_GET_ENTITY(slot + i, UIButton);
127
128
if ((UIChoice && item->classID == UIChoice->classID) || (UIVsRoundPicker && item->classID == UIVsRoundPicker->classID)
129
#if GAME_VERSION != VER_100
130
|| (UIResPicker && item->classID == UIResPicker->classID) || (UIWinSize && item->classID == UIWinSize->classID)
131
#endif
132
) {
133
item->parent = (Entity *)self;
134
}
135
136
if (i) {
137
item->position.x = self->firstChoicePos.x;
138
item->position.y = self->firstChoicePos.y;
139
item->active = ACTIVE_NEVER;
140
}
141
else {
142
self->firstChoicePos.x = item->position.x;
143
self->firstChoicePos.y = item->position.y;
144
}
145
}
146
}
147
}
148
149
void UIButton_StageLoad(void) {}
150
151
void UIButton_ManageChoices(EntityUIButton *button)
152
{
153
for (int32 i = 0; i < button->choiceCount; ++i) {
154
EntityUIButton *choice = RSDK_GET_ENTITY(i % button->choiceCount - button->choiceCount + RSDK.GetEntitySlot(button), UIButton);
155
if (button->choiceCount > 0
156
&& (choice->classID == UIChoice->classID || choice->classID == UIVsRoundPicker->classID
157
#if GAME_VERSION != VER_100
158
|| choice->classID == UIResPicker->classID || choice->classID == UIWinSize->classID
159
#endif
160
)) {
161
162
choice->visible = i == button->selection;
163
choice->active = i == button->selection ? ACTIVE_NORMAL : ACTIVE_NEVER;
164
}
165
}
166
}
167
168
EntityUIButton *UIButton_GetChoicePtr(EntityUIButton *button, int32 selection)
169
{
170
if (button->choiceCount <= 0)
171
return NULL;
172
173
EntityUIButton *choice = RSDK_GET_ENTITY(RSDK.GetEntitySlot(button) - button->choiceCount + (selection % button->choiceCount), UIButton);
174
if (choice->classID == UIChoice->classID || choice->classID == UIVsRoundPicker->classID
175
#if GAME_VERSION != VER_100
176
|| choice->classID == UIResPicker->classID || choice->classID == UIWinSize->classID
177
#endif
178
) {
179
return choice;
180
}
181
182
return NULL;
183
}
184
185
void UIButton_SetChoiceSelectionWithCB(EntityUIButton *button, int32 selection)
186
{
187
if (button->choiceCount) {
188
189
EntityUIButton *curChoice = UIButton_GetChoicePtr(button, button->selection);
190
if (curChoice) {
191
if (curChoice->classID == UIChoice->classID) {
192
EntityUIChoice *choice = (EntityUIChoice *)curChoice;
193
choice->textBounceOffset = 0;
194
choice->buttonBounceOffset = 0;
195
choice->isSelected = false;
196
choice->state = UIChoice_State_HandleButtonLeave;
197
}
198
else if (curChoice->classID == UIVsRoundPicker->classID) {
199
UIVsRoundPicker_SetChoiceInactive((EntityUIVsRoundPicker *)curChoice);
200
}
201
#if GAME_VERSION != VER_100
202
else if (curChoice->classID == UIResPicker->classID) {
203
UIResPicker_SetChoiceInactive((EntityUIResPicker *)curChoice);
204
}
205
else if (curChoice->classID == UIWinSize->classID) {
206
UIWinSize_SetChoiceInactive((EntityUIWinSize *)curChoice);
207
}
208
#endif
209
210
curChoice->active = ACTIVE_NEVER;
211
}
212
213
button->selection = selection;
214
215
EntityUIChoice *newChoice = (EntityUIChoice *)UIButton_GetChoicePtr(button, selection);
216
if (newChoice) {
217
if (button->state == UIButton_State_HandleButtonEnter || button->state == UIButton_State_Selected) {
218
UIChoice_SetChoiceActive(newChoice);
219
}
220
else {
221
newChoice->active = ACTIVE_BOUNDS;
222
newChoice->visible = true;
223
UIChoice_SetChoiceInactive(newChoice);
224
}
225
}
226
227
if (button->choiceChangeCB) {
228
Entity *entStore = SceneInfo->entity;
229
SceneInfo->entity = (Entity *)button;
230
#if RETRO_USE_MOD_LOADER
231
StateMachine_Run(button->choiceChangeCB);
232
#else
233
button->choiceChangeCB();
234
#endif
235
SceneInfo->entity = entStore;
236
}
237
}
238
}
239
240
void UIButton_SetChoiceSelection(EntityUIButton *button, int32 selection)
241
{
242
if (button->choiceCount) {
243
244
EntityUIButton *choicePtr = UIButton_GetChoicePtr(button, button->selection);
245
if (choicePtr) {
246
if (choicePtr->classID == UIChoice->classID) {
247
EntityUIChoice *choice = (EntityUIChoice *)choicePtr;
248
choice->textBounceOffset = 0;
249
choice->buttonBounceOffset = 0;
250
choice->isSelected = false;
251
choice->state = UIChoice_State_HandleButtonLeave;
252
}
253
else if (choicePtr->classID == UIVsRoundPicker->classID) {
254
UIVsRoundPicker_SetChoiceInactive((EntityUIVsRoundPicker *)choicePtr);
255
}
256
#if GAME_VERSION != VER_100
257
else if (choicePtr->classID == UIResPicker->classID) {
258
UIResPicker_SetChoiceInactive((EntityUIResPicker *)choicePtr);
259
}
260
else if (choicePtr->classID == UIWinSize->classID) {
261
UIWinSize_SetChoiceInactive((EntityUIWinSize *)choicePtr);
262
}
263
#endif
264
265
choicePtr->active = ACTIVE_NEVER;
266
}
267
268
button->selection = selection;
269
EntityUIButton *newChoice = UIButton_GetChoicePtr(button, selection);
270
newChoice->active = ACTIVE_NORMAL;
271
}
272
}
273
274
void *UIButton_GetActionCB(void)
275
{
276
RSDK_THIS(UIButton);
277
278
EntityUIButton *choice = UIButton_GetChoicePtr(self, self->selection);
279
if (!choice)
280
return self->actionCB;
281
282
if (!UIChoice || self->choiceCount <= 0 || !choice->actionCB)
283
return self->actionCB;
284
285
return choice->actionCB;
286
}
287
288
void UIButton_FailCB(void) { RSDK.PlaySfx(UIWidgets->sfxFail, false, 255); }
289
290
void UIButton_ProcessButtonCB_Scroll(void)
291
{
292
RSDK_THIS(UIButton);
293
294
EntityUIControl *control = (EntityUIControl *)self->parent;
295
296
#if MANIA_USE_PLUS
297
UIControl_SetTargetPos(control, self->position.x, self->position.y);
298
#else
299
control->targetPos.y = self->position.y;
300
#endif
301
302
if (!UIControl_isMoving(control)) {
303
int32 rowID = 0;
304
int32 colID = 0;
305
306
if (control->rowCount && control->columnCount)
307
rowID = control->buttonID / control->columnCount;
308
309
if (control->columnCount)
310
colID = control->buttonID % control->columnCount;
311
312
bool32 changedSelection = false;
313
if (control->rowCount > 1) {
314
if (UIControl->anyUpPress) {
315
--rowID;
316
changedSelection = true;
317
}
318
319
if (UIControl->anyDownPress) {
320
++rowID;
321
changedSelection = true;
322
}
323
}
324
325
if (UIControl->anyLeftPress) {
326
--colID;
327
changedSelection = true;
328
}
329
330
if (UIControl->anyRightPress) {
331
++colID;
332
changedSelection = true;
333
}
334
335
if (changedSelection) {
336
#if MANIA_USE_PLUS
337
if (control->noWrap) {
338
int32 rowCount = control->rowCount;
339
int32 colCount = control->columnCount;
340
341
if (rowID < control->rowCount)
342
rowCount = rowID;
343
344
if (rowCount >= 0) {
345
if (rowID >= control->rowCount)
346
rowID = control->rowCount;
347
}
348
else {
349
rowID = 0;
350
}
351
352
if (colID < control->columnCount)
353
colCount = colID;
354
355
if (colCount >= 0) {
356
if (colID >= control->columnCount)
357
colID = control->columnCount;
358
}
359
else {
360
colID = 0;
361
}
362
}
363
else {
364
#endif
365
if (rowID < 0)
366
rowID += control->rowCount;
367
368
if (rowID >= control->rowCount)
369
rowID -= control->rowCount;
370
371
if (colID < 0)
372
colID += control->columnCount;
373
374
if (colID >= control->columnCount)
375
colID -= control->columnCount;
376
#if MANIA_USE_PLUS
377
}
378
#endif
379
380
int32 id = control->buttonCount - 1;
381
if (colID + rowID * control->columnCount < id)
382
id = colID + rowID * control->columnCount;
383
384
if (control->buttonID != id) {
385
control->buttonID = id;
386
StateMachine_Run(self->buttonLeaveCB);
387
RSDK.PlaySfx(UIWidgets->sfxBleep, false, 0xFF);
388
}
389
}
390
else {
391
bool32 hasNoAction = true;
392
if (UIControl->anyConfirmPress) {
393
if (self->disabled) {
394
StateMachine_Run(self->failCB);
395
}
396
else {
397
hasNoAction = !self->actionCB;
398
}
399
}
400
401
if (hasNoAction) {
402
if (!self->isSelected) {
403
if (control->buttonID == UIControl_GetButtonID(control, self) && control->state == UIControl_ProcessInputs
404
&& !control->dialogHasFocus) {
405
StateMachine_Run(self->buttonEnterCB);
406
}
407
}
408
}
409
else {
410
StateMachine_Run(self->selectedCB);
411
}
412
}
413
}
414
}
415
416
bool32 UIButton_ProcessTouchCB_Multi(void)
417
{
418
RSDK_THIS(UIButton);
419
420
EntityUIControl *control = (EntityUIControl *)self->parent;
421
422
bool32 touched = false;
423
int32 lastTouchID = -1;
424
uint32 lastTouchDist = 0xFFFFFFFF;
425
426
for (int32 i = 0; i < self->touchPosCount; ++i) {
427
Vector2 touchPosSize = self->touchPosSizeM[i];
428
Vector2 touchPosOffset = self->touchPosOffsetM[i];
429
430
if (TouchInfo->count) {
431
int32 screenX = ScreenInfo->position.x << 16;
432
int32 screenY = ScreenInfo->position.y << 16;
433
434
for (int32 t = 0; t < TouchInfo->count; ++t) {
435
int32 x = abs(touchPosOffset.x + self->position.x - (screenX - (int32)((TouchInfo->x[t] * ScreenInfo->size.x) * -65536.0f)));
436
int32 y = abs(touchPosOffset.y + self->position.y - (screenY - (int32)((TouchInfo->y[t] * ScreenInfo->size.y) * -65536.0f)));
437
int32 x1 = touchPosSize.x >> 1;
438
int32 y1 = touchPosSize.y >> 1;
439
440
if (x < x1 && y < y1) {
441
touched = true;
442
443
if ((uint32)((touchPosSize.x >> 16) * (touchPosSize.y >> 16)) < lastTouchDist) {
444
lastTouchDist = (touchPosSize.x >> 16) * (touchPosSize.y >> 16);
445
lastTouchID = i;
446
}
447
}
448
}
449
}
450
else {
451
if (self->touchPressed && self->touchPosID == i && !self->disabled) {
452
if (!UIControl_isMoving(control)) {
453
StateMachine_Run(self->touchPosCallbacks[i]);
454
}
455
}
456
}
457
}
458
459
self->touchPosID = lastTouchID;
460
self->touchPressed = touched;
461
462
return touched;
463
}
464
465
bool32 UIButton_ProcessTouchCB_Single(void)
466
{
467
RSDK_THIS(UIButton);
468
469
EntityUIControl *control = (EntityUIControl *)self->parent;
470
471
bool32 touched = false;
472
if (self->classID != UIButton->classID || !self->invisible) {
473
if (TouchInfo->count) {
474
int32 screenX = (ScreenInfo->position.x << 16);
475
int32 screenY = (ScreenInfo->position.y << 16);
476
int32 sizeX = self->touchPosSizeS.x >> 1;
477
int32 sizeY = self->touchPosSizeS.y >> 1;
478
479
for (int32 i = 0; i < TouchInfo->count; ++i) {
480
int32 x = screenX - ((TouchInfo->x[i] * ScreenInfo->size.x) * -65536.0f);
481
int32 y = screenY - ((TouchInfo->y[i] * ScreenInfo->size.y) * -65536.0f);
482
483
int32 touchX = abs(self->touchPosOffsetS.x + self->position.x - x);
484
int32 touchY = abs(self->touchPosOffsetS.y + self->position.y - y);
485
if (touchX < sizeX && touchY < sizeY)
486
touched = true;
487
}
488
}
489
else {
490
if (self->touchPressed && !UIControl_isMoving(control)) {
491
if (self->disabled) {
492
StateMachine_Run(self->failCB);
493
}
494
else {
495
self->isSelected = false;
496
StateMachine(actionCB) = NULL;
497
498
if (self->classID == UIButton->classID)
499
actionCB = UIButton_GetActionCB();
500
else
501
actionCB = self->actionCB;
502
503
if (actionCB) {
504
StateMachine_Run(self->selectedCB);
505
}
506
}
507
}
508
}
509
}
510
511
if (!touched) {
512
if (!self->touchPressed && self->checkButtonEnterCB()) {
513
for (int32 i = 0; i < control->buttonCount; ++i) {
514
if (self == control->buttons[i] && control->buttonID != i) {
515
self->isSelected = false;
516
StateMachine_Run(self->buttonLeaveCB);
517
518
break;
519
}
520
}
521
}
522
}
523
524
bool32 childTouched = false;
525
self->touchPressed = touched;
526
if (self->classID == UIButton->classID && self->choiceCount > 0) {
527
EntityUIButton *entPtr = UIButton_GetChoicePtr(self, self->selection);
528
if (entPtr) {
529
Entity *entStore = SceneInfo->entity;
530
SceneInfo->entity = (Entity *)entPtr;
531
if (entPtr->touchCB)
532
childTouched = entPtr->touchCB();
533
SceneInfo->entity = entStore;
534
}
535
}
536
537
return touched || childTouched;
538
}
539
540
void UIButton_ProcessButtonCB(void)
541
{
542
RSDK_THIS(UIButton);
543
544
EntityUIControl *control = (EntityUIControl *)self->parent;
545
EntityUIButton *choice = UIButton_GetChoicePtr(self, self->selection);
546
547
int32 columnID = 0, rowID = 0;
548
if (control->rowCount && control->columnCount)
549
rowID = control->buttonID / control->columnCount;
550
551
if (control->columnCount)
552
columnID = control->buttonID % control->columnCount;
553
554
bool32 movedV = false;
555
if (control->rowCount > 1) {
556
if (UIControl->anyUpPress) {
557
movedV = true;
558
--rowID;
559
}
560
561
if (UIControl->anyDownPress) {
562
movedV = true;
563
rowID++;
564
}
565
}
566
567
int32 selection = self->selection;
568
bool32 movedH = 0;
569
570
if (choice && self->choiceCount == 1 && choice->processButtonCB && !self->choiceDir && !self->disabled) {
571
Entity *entStore = SceneInfo->entity;
572
SceneInfo->entity = (Entity *)choice;
573
#if RETRO_USE_MOD_LOADER
574
StateMachine_Run(choice->processButtonCB);
575
#else
576
choice->processButtonCB();
577
#endif
578
SceneInfo->entity = entStore;
579
}
580
else {
581
if (UIControl->anyLeftPress) {
582
if (self->choiceCount <= 0 || self->choiceDir || self->disabled) {
583
if (control->columnCount > 1) {
584
movedV = true;
585
columnID--;
586
}
587
588
movedH = false;
589
}
590
else {
591
if (--selection < 0) {
592
while (selection < 0) selection += self->choiceCount;
593
}
594
choice = UIButton_GetChoicePtr(self, selection);
595
596
while ((choice && choice->disabled) && selection != self->selection) {
597
if (--selection < 0) {
598
while (selection < 0) selection += self->choiceCount;
599
}
600
601
choice = UIButton_GetChoicePtr(self, selection);
602
}
603
604
movedH = true;
605
}
606
}
607
608
if (UIControl->anyRightPress) {
609
if (self->choiceCount <= 0 || self->choiceDir || self->disabled) {
610
if (control->columnCount > 1) {
611
++columnID;
612
movedV = true;
613
}
614
615
movedH = false;
616
}
617
else {
618
selection = (selection + 1) % self->choiceCount;
619
choice = UIButton_GetChoicePtr(self, selection);
620
621
while ((choice && choice->disabled) && selection != self->selection) {
622
selection = (selection + 1) % self->choiceCount;
623
624
choice = UIButton_GetChoicePtr(self, selection);
625
}
626
627
movedH = true;
628
}
629
}
630
}
631
632
if (movedH) {
633
if (selection < 0)
634
selection += self->choiceCount;
635
636
if (selection >= self->choiceCount)
637
selection -= self->choiceCount;
638
639
if (selection != self->selection) {
640
UIButton_SetChoiceSelectionWithCB(self, selection);
641
RSDK.PlaySfx(UIWidgets->sfxBleep, false, 255);
642
}
643
}
644
645
if (movedV) {
646
#if MANIA_USE_PLUS
647
if (control->noWrap) {
648
int32 count = control->rowCount;
649
if (rowID < control->rowCount)
650
count = rowID;
651
652
if (rowID >= control->rowCount)
653
rowID = control->rowCount;
654
else if (count < 0)
655
rowID = 0;
656
657
count = control->columnCount;
658
if (columnID < control->columnCount)
659
count = columnID;
660
661
if (columnID >= control->columnCount)
662
columnID = control->columnCount;
663
else if (count < 0)
664
columnID = 0;
665
}
666
else {
667
#endif
668
if (rowID < 0)
669
rowID += control->rowCount;
670
671
if (rowID >= control->rowCount)
672
rowID -= control->rowCount;
673
674
if (columnID < 0)
675
columnID += control->columnCount;
676
677
if (columnID >= control->columnCount)
678
columnID -= control->columnCount;
679
#if MANIA_USE_PLUS
680
}
681
#endif
682
683
int32 id = columnID + control->columnCount * rowID;
684
685
if (id >= control->buttonCount - 1)
686
id = control->buttonCount - 1;
687
688
if (control->buttonID != id && self != control->buttons[id]) {
689
control->buttonID = id;
690
UIButton_ButtonLeaveCB();
691
RSDK.PlaySfx(UIWidgets->sfxBleep, false, 255);
692
}
693
}
694
else {
695
StateMachine(actionCB) = UIButton_GetActionCB();
696
697
if (UIControl->anyConfirmPress && (!UIChoice || actionCB)) {
698
if (self->disabled || (self->choiceCount > 0 && choice->disabled))
699
RSDK.PlaySfx(UIWidgets->sfxFail, false, 255);
700
else
701
UIButton_SelectedCB();
702
}
703
else {
704
if (self->state != UIButton_State_HandleButtonEnter && self->state != UIButton_State_Selected) {
705
if (control->buttonID == columnID + rowID * control->columnCount && control->state == UIControl_ProcessInputs)
706
UIButton_ButtonEnterCB();
707
}
708
}
709
}
710
}
711
712
bool32 UIButton_CheckButtonEnterCB(void)
713
{
714
RSDK_THIS(UIButton);
715
716
return self->state == UIButton_State_HandleButtonEnter;
717
}
718
719
bool32 UIButton_CheckSelectedCB(void)
720
{
721
RSDK_THIS(UIButton);
722
723
return self->state == UIButton_State_Selected;
724
}
725
726
void UIButton_ButtonEnterCB(void)
727
{
728
RSDK_THIS(UIButton);
729
730
if (self->state != UIButton_State_HandleButtonEnter) {
731
self->textBounceOffset = 0;
732
self->buttonBounceOffset = 0;
733
self->textBounceVelocity = -0x20000;
734
self->buttonBounceVelocity = -0x20000;
735
self->state = UIButton_State_HandleButtonEnter;
736
737
if (UIChoice) {
738
EntityUIButton *choicePtr = UIButton_GetChoicePtr(self, self->selection);
739
740
if (choicePtr) {
741
if (choicePtr->classID == UIChoice->classID) {
742
UIChoice_SetChoiceActive((EntityUIChoice *)choicePtr);
743
}
744
745
if (choicePtr->classID == UIVsRoundPicker->classID) {
746
UIVsRoundPicker_SetChoiceActive((EntityUIVsRoundPicker *)choicePtr);
747
}
748
749
#if GAME_VERSION != VER_100
750
if (choicePtr->classID == UIResPicker->classID) {
751
UIResPicker_SetChoiceActive((EntityUIResPicker *)choicePtr);
752
}
753
754
if (choicePtr->classID == UIWinSize->classID) {
755
UIWinSize_SetChoiceActive((EntityUIWinSize *)choicePtr);
756
}
757
#endif
758
}
759
}
760
}
761
}
762
763
void UIButton_ButtonLeaveCB(void)
764
{
765
RSDK_THIS(UIButton);
766
767
self->state = UIButton_State_HandleButtonLeave;
768
769
if (UIChoice) {
770
EntityUIButton *widget = UIButton_GetChoicePtr(self, self->selection);
771
if (widget) {
772
if (widget->classID == UIChoice->classID) {
773
((EntityUIChoice *)widget)->textBounceOffset = 0;
774
((EntityUIChoice *)widget)->buttonBounceOffset = 0;
775
widget->isSelected = false;
776
widget->state = UIChoice_State_HandleButtonLeave;
777
}
778
else if (widget->classID == UIVsRoundPicker->classID) {
779
UIVsRoundPicker_SetChoiceInactive((EntityUIVsRoundPicker *)widget);
780
}
781
#if GAME_VERSION != VER_100
782
else if (widget->classID == UIResPicker->classID) {
783
UIResPicker_SetChoiceInactive((EntityUIResPicker *)widget);
784
}
785
else if (widget->classID == UIWinSize->classID) {
786
UIWinSize_SetChoiceInactive((EntityUIWinSize *)widget);
787
}
788
#endif
789
}
790
}
791
}
792
793
void UIButton_SelectedCB(void)
794
{
795
RSDK_THIS(UIButton);
796
797
EntityUIControl *parent = (EntityUIControl *)self->parent;
798
EntityUIButton *choice = UIButton_GetChoicePtr(self, self->selection);
799
800
if (self->clearParentState || (choice && choice->classID == UIChoice->classID && choice->buttonBounceVelocity))
801
parent->state = StateMachine_None;
802
803
if (self->assignsP1) {
804
#if MANIA_USE_PLUS
805
int32 id = API_GetFilteredInputDeviceID(false, false, 0);
806
#else
807
int32 id = API_GetFilteredInputDeviceID(INPUT_NONE);
808
#endif
809
API_ResetInputSlotAssignments();
810
API_AssignInputSlotToDevice(CONT_P1, id);
811
}
812
813
if (self->freeBindP2)
814
API_AssignInputSlotToDevice(CONT_P2, INPUT_AUTOASSIGN);
815
816
parent->backoutTimer = 30;
817
818
if (self->transition) {
819
StateMachine(actionCB) = self->actionCB;
820
if (UIChoice && self->choiceCount > 0 && choice)
821
actionCB = choice->actionCB;
822
823
UITransition_StartTransition(actionCB, 14);
824
}
825
826
if (self->stopMusic)
827
Music_Stop();
828
829
self->timer = 0;
830
self->state = UIButton_State_Selected;
831
RSDK.PlaySfx(UIWidgets->sfxAccept, false, 255);
832
}
833
834
void UIButton_State_HandleButtonLeave(void)
835
{
836
RSDK_THIS(UIButton);
837
838
if (self->textBounceOffset) {
839
int32 offset = -(self->textBounceOffset / abs(self->textBounceOffset));
840
self->textBounceOffset += offset << 16;
841
842
if (offset < 0 && self->textBounceOffset < 0)
843
self->textBounceOffset = 0;
844
else if (offset > 0 && self->textBounceOffset > 0)
845
self->textBounceOffset = 0;
846
}
847
848
if (self->buttonBounceOffset) {
849
int32 offset = -(self->buttonBounceOffset / abs(self->buttonBounceOffset));
850
self->buttonBounceOffset += offset << 16;
851
852
if (offset < 0 && self->buttonBounceOffset < 0)
853
self->buttonBounceOffset = 0;
854
else if (offset > 0 && self->buttonBounceOffset > 0)
855
self->buttonBounceOffset = 0;
856
}
857
}
858
859
void UIButton_State_HandleButtonEnter(void)
860
{
861
RSDK_THIS(UIButton);
862
863
self->textBounceVelocity += 0x4000;
864
self->textBounceOffset += self->textBounceVelocity;
865
866
if (self->textBounceOffset >= 0 && self->textBounceVelocity > 0) {
867
self->textBounceOffset = 0;
868
self->textBounceVelocity = 0;
869
}
870
871
self->buttonBounceVelocity += 0x4800;
872
self->buttonBounceOffset += self->buttonBounceVelocity;
873
874
if (self->buttonBounceOffset >= -0x20000 && self->buttonBounceVelocity > 0) {
875
self->buttonBounceOffset = -0x20000;
876
self->buttonBounceVelocity = 0;
877
}
878
}
879
880
void UIButton_State_Selected(void)
881
{
882
RSDK_THIS(UIButton);
883
884
UIButton_State_HandleButtonEnter();
885
886
if (++self->timer == 30) {
887
self->timer = 0;
888
889
if (!self->transition) {
890
StateMachine(actionCB) = UIButton_GetActionCB();
891
StateMachine_Run(actionCB);
892
}
893
894
self->state = UIButton_State_HandleButtonEnter;
895
}
896
897
self->textVisible = !((self->timer >> 1) & 1);
898
}
899
900
#if GAME_INCLUDE_EDITOR
901
void UIButton_EditorDraw(void)
902
{
903
RSDK_THIS(UIButton);
904
905
int32 sizeY = self->size.y;
906
907
if (self->disabled)
908
RSDK.SetSpriteAnimation(UIWidgets->textFrames, 7, &self->animator, true, 0);
909
else
910
RSDK.SetSpriteAnimation(UIWidgets->textFrames, self->listID, &self->animator, true, self->frameID);
911
912
self->textFrames = UIWidgets->textFrames;
913
self->startListID = self->listID;
914
self->startFrameID = self->frameID;
915
916
self->drawGroup = 2;
917
self->updateRange.x = 0x800000;
918
self->updateRange.y = 0x400000;
919
self->bgEdgeSize = self->size.y >> 16;
920
self->size.y = abs(self->size.y);
921
self->textVisible = true;
922
923
self->inkEffect = self->invisible ? INK_BLEND : INK_NONE;
924
UIButton_Draw();
925
926
self->size.y = sizeY;
927
928
if (showGizmos()) {
929
RSDK_DRAWING_OVERLAY(true);
930
931
int32 slot = RSDK.GetEntitySlot(self) - self->choiceCount;
932
for (int32 i = 0; i < self->choiceCount; ++i) {
933
EntityUIButton *item = RSDK_GET_ENTITY(slot + i, UIButton);
934
935
if (item)
936
DrawHelpers_DrawArrow(self->position.x, self->position.y, item->position.x, item->position.y, i ? 0xFFFF00 : 0xE0E0E0, INK_NONE,
937
0xFF);
938
}
939
940
RSDK_DRAWING_OVERLAY(false);
941
}
942
}
943
944
void UIButton_EditorLoad(void)
945
{
946
RSDK_ACTIVE_VAR(UIButton, align);
947
RSDK_ENUM_VAR("Left", UIBUTTON_ALIGN_LEFT);
948
RSDK_ENUM_VAR("Center", UIBUTTON_ALIGN_CENTER);
949
RSDK_ENUM_VAR("Right", UIBUTTON_ALIGN_RIGHT);
950
}
951
#endif
952
953
void UIButton_Serialize(void)
954
{
955
RSDK_EDITABLE_VAR(UIButton, VAR_BOOL, disabled);
956
RSDK_EDITABLE_VAR(UIButton, VAR_VECTOR2, size);
957
RSDK_EDITABLE_VAR(UIButton, VAR_ENUM, listID);
958
RSDK_EDITABLE_VAR(UIButton, VAR_ENUM, frameID);
959
RSDK_EDITABLE_VAR(UIButton, VAR_ENUM, align);
960
RSDK_EDITABLE_VAR(UIButton, VAR_ENUM, choiceCount);
961
RSDK_EDITABLE_VAR(UIButton, VAR_UINT8, choiceDir);
962
RSDK_EDITABLE_VAR(UIButton, VAR_BOOL, invisible);
963
RSDK_EDITABLE_VAR(UIButton, VAR_BOOL, assignsP1);
964
RSDK_EDITABLE_VAR(UIButton, VAR_BOOL, freeBindP2);
965
RSDK_EDITABLE_VAR(UIButton, VAR_BOOL, transition);
966
RSDK_EDITABLE_VAR(UIButton, VAR_BOOL, stopMusic);
967
}
968
969