Path: blob/master/SonicMania/Objects/Menu/UIButton.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: UIButton Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectUIButton *UIButton;1011void UIButton_Update(void)12{13RSDK_THIS(UIButton);1415self->touchPosSizeS.x = self->size.x;16self->touchPosOffsetS.x = 0;17self->touchPosOffsetS.y = 0;18self->touchPosSizeS.x += 3 * self->size.y;19self->touchPosSizeS.y = self->size.y + 0x60000;2021if (self->textFrames != UIWidgets->textFrames || self->startListID != self->listID || self->startFrameID != self->frameID22|| self->isDisabled != self->disabled) {23if (self->disabled)24RSDK.SetSpriteAnimation(UIWidgets->textFrames, 7, &self->animator, true, 0);25else26RSDK.SetSpriteAnimation(UIWidgets->textFrames, self->listID, &self->animator, true, self->frameID);2728self->textFrames = UIWidgets->textFrames;29self->startListID = self->listID;30self->startFrameID = self->frameID;31self->isDisabled = self->disabled;32}3334EntityUIButton *choice = UIButton_GetChoicePtr(self, self->selection);35if (choice)36choice->visible = true;3738StateMachine_Run(self->state);3940EntityUIControl *parent = (EntityUIControl *)self->parent;41if (parent && self->state == UIButton_State_HandleButtonEnter42&& (parent->state != UIControl_ProcessInputs || parent->buttons[parent->buttonID] != self)) {43self->isSelected = false;44UIButton_ButtonLeaveCB();45}46}4748void UIButton_LateUpdate(void) {}4950void UIButton_StaticUpdate(void) {}5152void UIButton_Draw(void)53{54RSDK_THIS(UIButton);5556Vector2 drawPos;57int32 width = (self->size.x + self->size.y) >> 16;5859drawPos.x = self->position.x - self->buttonBounceOffset;60drawPos.y = self->position.y - self->buttonBounceOffset;61#if MANIA_USE_PLUS62UIWidgets_DrawParallelogram(drawPos.x, drawPos.y, width, self->size.y >> 16, self->bgEdgeSize, (UIWidgets->buttonColor >> 16) & 0xFF,63(UIWidgets->buttonColor >> 8) & 0xFF, (UIWidgets->buttonColor) & 0xFF);64#else65UIWidgets_DrawParallelogram(drawPos.x, drawPos.y, width, self->size.y >> 16, self->bgEdgeSize, 0xF0, 0xF0, 0xF0);66#endif6768drawPos.x = self->position.x + self->buttonBounceOffset;69drawPos.y = self->position.y + self->buttonBounceOffset;70UIWidgets_DrawParallelogram(drawPos.x, drawPos.y, width, self->size.y >> 16, self->bgEdgeSize, 0x00, 0x00, 0x00);7172if (self->textVisible) {73drawPos.x = self->buttonBounceOffset + self->position.x;74drawPos.y = self->buttonBounceOffset + self->position.y;75drawPos.y += self->textBounceOffset;7677switch (self->align) {78case UIBUTTON_ALIGN_LEFT: drawPos.x += -0x60000 - (self->size.x >> 1); break;7980case UIBUTTON_ALIGN_CENTER: break;8182case UIBUTTON_ALIGN_RIGHT:83drawPos.x -= 0x60000;84drawPos.x += self->size.x >> 1;85break;86}8788if (self->disabled && self->align == UIBUTTON_ALIGN_LEFT)89drawPos.x += 0x150000;9091RSDK.DrawSprite(&self->animator, &drawPos, false);92}93}9495void UIButton_Create(void *data)96{97RSDK_THIS(UIButton);9899if (!SceneInfo->inEditor) {100self->drawGroup = 2;101self->visible = !self->invisible;102self->active = ACTIVE_BOUNDS;103self->updateRange.x = TO_FIXED(128);104self->updateRange.y = TO_FIXED(64);105self->bgEdgeSize = self->size.y >> 16;106self->size.y = abs(self->size.y);107108self->processButtonCB = UIButton_ProcessButtonCB;109self->touchCB = UIButton_ProcessTouchCB_Single;110self->selectedCB = UIButton_SelectedCB;111self->failCB = UIButton_FailCB;112self->buttonEnterCB = UIButton_ButtonEnterCB;113self->buttonLeaveCB = UIButton_ButtonLeaveCB;114self->checkButtonEnterCB = UIButton_CheckButtonEnterCB;115self->checkSelectedCB = UIButton_CheckSelectedCB;116117self->textVisible = true;118RSDK.SetSpriteAnimation(UIWidgets->textFrames, self->listID, &self->animator, true, self->frameID);119self->textFrames = UIWidgets->textFrames;120self->startListID = self->listID;121self->startFrameID = self->frameID;122123int32 slot = RSDK.GetEntitySlot(self) - self->choiceCount;124for (int32 i = 0; i < self->choiceCount; ++i) {125EntityUIButton *item = RSDK_GET_ENTITY(slot + i, UIButton);126127if ((UIChoice && item->classID == UIChoice->classID) || (UIVsRoundPicker && item->classID == UIVsRoundPicker->classID)128#if GAME_VERSION != VER_100129|| (UIResPicker && item->classID == UIResPicker->classID) || (UIWinSize && item->classID == UIWinSize->classID)130#endif131) {132item->parent = (Entity *)self;133}134135if (i) {136item->position.x = self->firstChoicePos.x;137item->position.y = self->firstChoicePos.y;138item->active = ACTIVE_NEVER;139}140else {141self->firstChoicePos.x = item->position.x;142self->firstChoicePos.y = item->position.y;143}144}145}146}147148void UIButton_StageLoad(void) {}149150void UIButton_ManageChoices(EntityUIButton *button)151{152for (int32 i = 0; i < button->choiceCount; ++i) {153EntityUIButton *choice = RSDK_GET_ENTITY(i % button->choiceCount - button->choiceCount + RSDK.GetEntitySlot(button), UIButton);154if (button->choiceCount > 0155&& (choice->classID == UIChoice->classID || choice->classID == UIVsRoundPicker->classID156#if GAME_VERSION != VER_100157|| choice->classID == UIResPicker->classID || choice->classID == UIWinSize->classID158#endif159)) {160161choice->visible = i == button->selection;162choice->active = i == button->selection ? ACTIVE_NORMAL : ACTIVE_NEVER;163}164}165}166167EntityUIButton *UIButton_GetChoicePtr(EntityUIButton *button, int32 selection)168{169if (button->choiceCount <= 0)170return NULL;171172EntityUIButton *choice = RSDK_GET_ENTITY(RSDK.GetEntitySlot(button) - button->choiceCount + (selection % button->choiceCount), UIButton);173if (choice->classID == UIChoice->classID || choice->classID == UIVsRoundPicker->classID174#if GAME_VERSION != VER_100175|| choice->classID == UIResPicker->classID || choice->classID == UIWinSize->classID176#endif177) {178return choice;179}180181return NULL;182}183184void UIButton_SetChoiceSelectionWithCB(EntityUIButton *button, int32 selection)185{186if (button->choiceCount) {187188EntityUIButton *curChoice = UIButton_GetChoicePtr(button, button->selection);189if (curChoice) {190if (curChoice->classID == UIChoice->classID) {191EntityUIChoice *choice = (EntityUIChoice *)curChoice;192choice->textBounceOffset = 0;193choice->buttonBounceOffset = 0;194choice->isSelected = false;195choice->state = UIChoice_State_HandleButtonLeave;196}197else if (curChoice->classID == UIVsRoundPicker->classID) {198UIVsRoundPicker_SetChoiceInactive((EntityUIVsRoundPicker *)curChoice);199}200#if GAME_VERSION != VER_100201else if (curChoice->classID == UIResPicker->classID) {202UIResPicker_SetChoiceInactive((EntityUIResPicker *)curChoice);203}204else if (curChoice->classID == UIWinSize->classID) {205UIWinSize_SetChoiceInactive((EntityUIWinSize *)curChoice);206}207#endif208209curChoice->active = ACTIVE_NEVER;210}211212button->selection = selection;213214EntityUIChoice *newChoice = (EntityUIChoice *)UIButton_GetChoicePtr(button, selection);215if (newChoice) {216if (button->state == UIButton_State_HandleButtonEnter || button->state == UIButton_State_Selected) {217UIChoice_SetChoiceActive(newChoice);218}219else {220newChoice->active = ACTIVE_BOUNDS;221newChoice->visible = true;222UIChoice_SetChoiceInactive(newChoice);223}224}225226if (button->choiceChangeCB) {227Entity *entStore = SceneInfo->entity;228SceneInfo->entity = (Entity *)button;229#if RETRO_USE_MOD_LOADER230StateMachine_Run(button->choiceChangeCB);231#else232button->choiceChangeCB();233#endif234SceneInfo->entity = entStore;235}236}237}238239void UIButton_SetChoiceSelection(EntityUIButton *button, int32 selection)240{241if (button->choiceCount) {242243EntityUIButton *choicePtr = UIButton_GetChoicePtr(button, button->selection);244if (choicePtr) {245if (choicePtr->classID == UIChoice->classID) {246EntityUIChoice *choice = (EntityUIChoice *)choicePtr;247choice->textBounceOffset = 0;248choice->buttonBounceOffset = 0;249choice->isSelected = false;250choice->state = UIChoice_State_HandleButtonLeave;251}252else if (choicePtr->classID == UIVsRoundPicker->classID) {253UIVsRoundPicker_SetChoiceInactive((EntityUIVsRoundPicker *)choicePtr);254}255#if GAME_VERSION != VER_100256else if (choicePtr->classID == UIResPicker->classID) {257UIResPicker_SetChoiceInactive((EntityUIResPicker *)choicePtr);258}259else if (choicePtr->classID == UIWinSize->classID) {260UIWinSize_SetChoiceInactive((EntityUIWinSize *)choicePtr);261}262#endif263264choicePtr->active = ACTIVE_NEVER;265}266267button->selection = selection;268EntityUIButton *newChoice = UIButton_GetChoicePtr(button, selection);269newChoice->active = ACTIVE_NORMAL;270}271}272273void *UIButton_GetActionCB(void)274{275RSDK_THIS(UIButton);276277EntityUIButton *choice = UIButton_GetChoicePtr(self, self->selection);278if (!choice)279return self->actionCB;280281if (!UIChoice || self->choiceCount <= 0 || !choice->actionCB)282return self->actionCB;283284return choice->actionCB;285}286287void UIButton_FailCB(void) { RSDK.PlaySfx(UIWidgets->sfxFail, false, 255); }288289void UIButton_ProcessButtonCB_Scroll(void)290{291RSDK_THIS(UIButton);292293EntityUIControl *control = (EntityUIControl *)self->parent;294295#if MANIA_USE_PLUS296UIControl_SetTargetPos(control, self->position.x, self->position.y);297#else298control->targetPos.y = self->position.y;299#endif300301if (!UIControl_isMoving(control)) {302int32 rowID = 0;303int32 colID = 0;304305if (control->rowCount && control->columnCount)306rowID = control->buttonID / control->columnCount;307308if (control->columnCount)309colID = control->buttonID % control->columnCount;310311bool32 changedSelection = false;312if (control->rowCount > 1) {313if (UIControl->anyUpPress) {314--rowID;315changedSelection = true;316}317318if (UIControl->anyDownPress) {319++rowID;320changedSelection = true;321}322}323324if (UIControl->anyLeftPress) {325--colID;326changedSelection = true;327}328329if (UIControl->anyRightPress) {330++colID;331changedSelection = true;332}333334if (changedSelection) {335#if MANIA_USE_PLUS336if (control->noWrap) {337int32 rowCount = control->rowCount;338int32 colCount = control->columnCount;339340if (rowID < control->rowCount)341rowCount = rowID;342343if (rowCount >= 0) {344if (rowID >= control->rowCount)345rowID = control->rowCount;346}347else {348rowID = 0;349}350351if (colID < control->columnCount)352colCount = colID;353354if (colCount >= 0) {355if (colID >= control->columnCount)356colID = control->columnCount;357}358else {359colID = 0;360}361}362else {363#endif364if (rowID < 0)365rowID += control->rowCount;366367if (rowID >= control->rowCount)368rowID -= control->rowCount;369370if (colID < 0)371colID += control->columnCount;372373if (colID >= control->columnCount)374colID -= control->columnCount;375#if MANIA_USE_PLUS376}377#endif378379int32 id = control->buttonCount - 1;380if (colID + rowID * control->columnCount < id)381id = colID + rowID * control->columnCount;382383if (control->buttonID != id) {384control->buttonID = id;385StateMachine_Run(self->buttonLeaveCB);386RSDK.PlaySfx(UIWidgets->sfxBleep, false, 0xFF);387}388}389else {390bool32 hasNoAction = true;391if (UIControl->anyConfirmPress) {392if (self->disabled) {393StateMachine_Run(self->failCB);394}395else {396hasNoAction = !self->actionCB;397}398}399400if (hasNoAction) {401if (!self->isSelected) {402if (control->buttonID == UIControl_GetButtonID(control, self) && control->state == UIControl_ProcessInputs403&& !control->dialogHasFocus) {404StateMachine_Run(self->buttonEnterCB);405}406}407}408else {409StateMachine_Run(self->selectedCB);410}411}412}413}414415bool32 UIButton_ProcessTouchCB_Multi(void)416{417RSDK_THIS(UIButton);418419EntityUIControl *control = (EntityUIControl *)self->parent;420421bool32 touched = false;422int32 lastTouchID = -1;423uint32 lastTouchDist = 0xFFFFFFFF;424425for (int32 i = 0; i < self->touchPosCount; ++i) {426Vector2 touchPosSize = self->touchPosSizeM[i];427Vector2 touchPosOffset = self->touchPosOffsetM[i];428429if (TouchInfo->count) {430int32 screenX = ScreenInfo->position.x << 16;431int32 screenY = ScreenInfo->position.y << 16;432433for (int32 t = 0; t < TouchInfo->count; ++t) {434int32 x = abs(touchPosOffset.x + self->position.x - (screenX - (int32)((TouchInfo->x[t] * ScreenInfo->size.x) * -65536.0f)));435int32 y = abs(touchPosOffset.y + self->position.y - (screenY - (int32)((TouchInfo->y[t] * ScreenInfo->size.y) * -65536.0f)));436int32 x1 = touchPosSize.x >> 1;437int32 y1 = touchPosSize.y >> 1;438439if (x < x1 && y < y1) {440touched = true;441442if ((uint32)((touchPosSize.x >> 16) * (touchPosSize.y >> 16)) < lastTouchDist) {443lastTouchDist = (touchPosSize.x >> 16) * (touchPosSize.y >> 16);444lastTouchID = i;445}446}447}448}449else {450if (self->touchPressed && self->touchPosID == i && !self->disabled) {451if (!UIControl_isMoving(control)) {452StateMachine_Run(self->touchPosCallbacks[i]);453}454}455}456}457458self->touchPosID = lastTouchID;459self->touchPressed = touched;460461return touched;462}463464bool32 UIButton_ProcessTouchCB_Single(void)465{466RSDK_THIS(UIButton);467468EntityUIControl *control = (EntityUIControl *)self->parent;469470bool32 touched = false;471if (self->classID != UIButton->classID || !self->invisible) {472if (TouchInfo->count) {473int32 screenX = (ScreenInfo->position.x << 16);474int32 screenY = (ScreenInfo->position.y << 16);475int32 sizeX = self->touchPosSizeS.x >> 1;476int32 sizeY = self->touchPosSizeS.y >> 1;477478for (int32 i = 0; i < TouchInfo->count; ++i) {479int32 x = screenX - ((TouchInfo->x[i] * ScreenInfo->size.x) * -65536.0f);480int32 y = screenY - ((TouchInfo->y[i] * ScreenInfo->size.y) * -65536.0f);481482int32 touchX = abs(self->touchPosOffsetS.x + self->position.x - x);483int32 touchY = abs(self->touchPosOffsetS.y + self->position.y - y);484if (touchX < sizeX && touchY < sizeY)485touched = true;486}487}488else {489if (self->touchPressed && !UIControl_isMoving(control)) {490if (self->disabled) {491StateMachine_Run(self->failCB);492}493else {494self->isSelected = false;495StateMachine(actionCB) = NULL;496497if (self->classID == UIButton->classID)498actionCB = UIButton_GetActionCB();499else500actionCB = self->actionCB;501502if (actionCB) {503StateMachine_Run(self->selectedCB);504}505}506}507}508}509510if (!touched) {511if (!self->touchPressed && self->checkButtonEnterCB()) {512for (int32 i = 0; i < control->buttonCount; ++i) {513if (self == control->buttons[i] && control->buttonID != i) {514self->isSelected = false;515StateMachine_Run(self->buttonLeaveCB);516517break;518}519}520}521}522523bool32 childTouched = false;524self->touchPressed = touched;525if (self->classID == UIButton->classID && self->choiceCount > 0) {526EntityUIButton *entPtr = UIButton_GetChoicePtr(self, self->selection);527if (entPtr) {528Entity *entStore = SceneInfo->entity;529SceneInfo->entity = (Entity *)entPtr;530if (entPtr->touchCB)531childTouched = entPtr->touchCB();532SceneInfo->entity = entStore;533}534}535536return touched || childTouched;537}538539void UIButton_ProcessButtonCB(void)540{541RSDK_THIS(UIButton);542543EntityUIControl *control = (EntityUIControl *)self->parent;544EntityUIButton *choice = UIButton_GetChoicePtr(self, self->selection);545546int32 columnID = 0, rowID = 0;547if (control->rowCount && control->columnCount)548rowID = control->buttonID / control->columnCount;549550if (control->columnCount)551columnID = control->buttonID % control->columnCount;552553bool32 movedV = false;554if (control->rowCount > 1) {555if (UIControl->anyUpPress) {556movedV = true;557--rowID;558}559560if (UIControl->anyDownPress) {561movedV = true;562rowID++;563}564}565566int32 selection = self->selection;567bool32 movedH = 0;568569if (choice && self->choiceCount == 1 && choice->processButtonCB && !self->choiceDir && !self->disabled) {570Entity *entStore = SceneInfo->entity;571SceneInfo->entity = (Entity *)choice;572#if RETRO_USE_MOD_LOADER573StateMachine_Run(choice->processButtonCB);574#else575choice->processButtonCB();576#endif577SceneInfo->entity = entStore;578}579else {580if (UIControl->anyLeftPress) {581if (self->choiceCount <= 0 || self->choiceDir || self->disabled) {582if (control->columnCount > 1) {583movedV = true;584columnID--;585}586587movedH = false;588}589else {590if (--selection < 0) {591while (selection < 0) selection += self->choiceCount;592}593choice = UIButton_GetChoicePtr(self, selection);594595while ((choice && choice->disabled) && selection != self->selection) {596if (--selection < 0) {597while (selection < 0) selection += self->choiceCount;598}599600choice = UIButton_GetChoicePtr(self, selection);601}602603movedH = true;604}605}606607if (UIControl->anyRightPress) {608if (self->choiceCount <= 0 || self->choiceDir || self->disabled) {609if (control->columnCount > 1) {610++columnID;611movedV = true;612}613614movedH = false;615}616else {617selection = (selection + 1) % self->choiceCount;618choice = UIButton_GetChoicePtr(self, selection);619620while ((choice && choice->disabled) && selection != self->selection) {621selection = (selection + 1) % self->choiceCount;622623choice = UIButton_GetChoicePtr(self, selection);624}625626movedH = true;627}628}629}630631if (movedH) {632if (selection < 0)633selection += self->choiceCount;634635if (selection >= self->choiceCount)636selection -= self->choiceCount;637638if (selection != self->selection) {639UIButton_SetChoiceSelectionWithCB(self, selection);640RSDK.PlaySfx(UIWidgets->sfxBleep, false, 255);641}642}643644if (movedV) {645#if MANIA_USE_PLUS646if (control->noWrap) {647int32 count = control->rowCount;648if (rowID < control->rowCount)649count = rowID;650651if (rowID >= control->rowCount)652rowID = control->rowCount;653else if (count < 0)654rowID = 0;655656count = control->columnCount;657if (columnID < control->columnCount)658count = columnID;659660if (columnID >= control->columnCount)661columnID = control->columnCount;662else if (count < 0)663columnID = 0;664}665else {666#endif667if (rowID < 0)668rowID += control->rowCount;669670if (rowID >= control->rowCount)671rowID -= control->rowCount;672673if (columnID < 0)674columnID += control->columnCount;675676if (columnID >= control->columnCount)677columnID -= control->columnCount;678#if MANIA_USE_PLUS679}680#endif681682int32 id = columnID + control->columnCount * rowID;683684if (id >= control->buttonCount - 1)685id = control->buttonCount - 1;686687if (control->buttonID != id && self != control->buttons[id]) {688control->buttonID = id;689UIButton_ButtonLeaveCB();690RSDK.PlaySfx(UIWidgets->sfxBleep, false, 255);691}692}693else {694StateMachine(actionCB) = UIButton_GetActionCB();695696if (UIControl->anyConfirmPress && (!UIChoice || actionCB)) {697if (self->disabled || (self->choiceCount > 0 && choice->disabled))698RSDK.PlaySfx(UIWidgets->sfxFail, false, 255);699else700UIButton_SelectedCB();701}702else {703if (self->state != UIButton_State_HandleButtonEnter && self->state != UIButton_State_Selected) {704if (control->buttonID == columnID + rowID * control->columnCount && control->state == UIControl_ProcessInputs)705UIButton_ButtonEnterCB();706}707}708}709}710711bool32 UIButton_CheckButtonEnterCB(void)712{713RSDK_THIS(UIButton);714715return self->state == UIButton_State_HandleButtonEnter;716}717718bool32 UIButton_CheckSelectedCB(void)719{720RSDK_THIS(UIButton);721722return self->state == UIButton_State_Selected;723}724725void UIButton_ButtonEnterCB(void)726{727RSDK_THIS(UIButton);728729if (self->state != UIButton_State_HandleButtonEnter) {730self->textBounceOffset = 0;731self->buttonBounceOffset = 0;732self->textBounceVelocity = -0x20000;733self->buttonBounceVelocity = -0x20000;734self->state = UIButton_State_HandleButtonEnter;735736if (UIChoice) {737EntityUIButton *choicePtr = UIButton_GetChoicePtr(self, self->selection);738739if (choicePtr) {740if (choicePtr->classID == UIChoice->classID) {741UIChoice_SetChoiceActive((EntityUIChoice *)choicePtr);742}743744if (choicePtr->classID == UIVsRoundPicker->classID) {745UIVsRoundPicker_SetChoiceActive((EntityUIVsRoundPicker *)choicePtr);746}747748#if GAME_VERSION != VER_100749if (choicePtr->classID == UIResPicker->classID) {750UIResPicker_SetChoiceActive((EntityUIResPicker *)choicePtr);751}752753if (choicePtr->classID == UIWinSize->classID) {754UIWinSize_SetChoiceActive((EntityUIWinSize *)choicePtr);755}756#endif757}758}759}760}761762void UIButton_ButtonLeaveCB(void)763{764RSDK_THIS(UIButton);765766self->state = UIButton_State_HandleButtonLeave;767768if (UIChoice) {769EntityUIButton *widget = UIButton_GetChoicePtr(self, self->selection);770if (widget) {771if (widget->classID == UIChoice->classID) {772((EntityUIChoice *)widget)->textBounceOffset = 0;773((EntityUIChoice *)widget)->buttonBounceOffset = 0;774widget->isSelected = false;775widget->state = UIChoice_State_HandleButtonLeave;776}777else if (widget->classID == UIVsRoundPicker->classID) {778UIVsRoundPicker_SetChoiceInactive((EntityUIVsRoundPicker *)widget);779}780#if GAME_VERSION != VER_100781else if (widget->classID == UIResPicker->classID) {782UIResPicker_SetChoiceInactive((EntityUIResPicker *)widget);783}784else if (widget->classID == UIWinSize->classID) {785UIWinSize_SetChoiceInactive((EntityUIWinSize *)widget);786}787#endif788}789}790}791792void UIButton_SelectedCB(void)793{794RSDK_THIS(UIButton);795796EntityUIControl *parent = (EntityUIControl *)self->parent;797EntityUIButton *choice = UIButton_GetChoicePtr(self, self->selection);798799if (self->clearParentState || (choice && choice->classID == UIChoice->classID && choice->buttonBounceVelocity))800parent->state = StateMachine_None;801802if (self->assignsP1) {803#if MANIA_USE_PLUS804int32 id = API_GetFilteredInputDeviceID(false, false, 0);805#else806int32 id = API_GetFilteredInputDeviceID(INPUT_NONE);807#endif808API_ResetInputSlotAssignments();809API_AssignInputSlotToDevice(CONT_P1, id);810}811812if (self->freeBindP2)813API_AssignInputSlotToDevice(CONT_P2, INPUT_AUTOASSIGN);814815parent->backoutTimer = 30;816817if (self->transition) {818StateMachine(actionCB) = self->actionCB;819if (UIChoice && self->choiceCount > 0 && choice)820actionCB = choice->actionCB;821822UITransition_StartTransition(actionCB, 14);823}824825if (self->stopMusic)826Music_Stop();827828self->timer = 0;829self->state = UIButton_State_Selected;830RSDK.PlaySfx(UIWidgets->sfxAccept, false, 255);831}832833void UIButton_State_HandleButtonLeave(void)834{835RSDK_THIS(UIButton);836837if (self->textBounceOffset) {838int32 offset = -(self->textBounceOffset / abs(self->textBounceOffset));839self->textBounceOffset += offset << 16;840841if (offset < 0 && self->textBounceOffset < 0)842self->textBounceOffset = 0;843else if (offset > 0 && self->textBounceOffset > 0)844self->textBounceOffset = 0;845}846847if (self->buttonBounceOffset) {848int32 offset = -(self->buttonBounceOffset / abs(self->buttonBounceOffset));849self->buttonBounceOffset += offset << 16;850851if (offset < 0 && self->buttonBounceOffset < 0)852self->buttonBounceOffset = 0;853else if (offset > 0 && self->buttonBounceOffset > 0)854self->buttonBounceOffset = 0;855}856}857858void UIButton_State_HandleButtonEnter(void)859{860RSDK_THIS(UIButton);861862self->textBounceVelocity += 0x4000;863self->textBounceOffset += self->textBounceVelocity;864865if (self->textBounceOffset >= 0 && self->textBounceVelocity > 0) {866self->textBounceOffset = 0;867self->textBounceVelocity = 0;868}869870self->buttonBounceVelocity += 0x4800;871self->buttonBounceOffset += self->buttonBounceVelocity;872873if (self->buttonBounceOffset >= -0x20000 && self->buttonBounceVelocity > 0) {874self->buttonBounceOffset = -0x20000;875self->buttonBounceVelocity = 0;876}877}878879void UIButton_State_Selected(void)880{881RSDK_THIS(UIButton);882883UIButton_State_HandleButtonEnter();884885if (++self->timer == 30) {886self->timer = 0;887888if (!self->transition) {889StateMachine(actionCB) = UIButton_GetActionCB();890StateMachine_Run(actionCB);891}892893self->state = UIButton_State_HandleButtonEnter;894}895896self->textVisible = !((self->timer >> 1) & 1);897}898899#if GAME_INCLUDE_EDITOR900void UIButton_EditorDraw(void)901{902RSDK_THIS(UIButton);903904int32 sizeY = self->size.y;905906if (self->disabled)907RSDK.SetSpriteAnimation(UIWidgets->textFrames, 7, &self->animator, true, 0);908else909RSDK.SetSpriteAnimation(UIWidgets->textFrames, self->listID, &self->animator, true, self->frameID);910911self->textFrames = UIWidgets->textFrames;912self->startListID = self->listID;913self->startFrameID = self->frameID;914915self->drawGroup = 2;916self->updateRange.x = 0x800000;917self->updateRange.y = 0x400000;918self->bgEdgeSize = self->size.y >> 16;919self->size.y = abs(self->size.y);920self->textVisible = true;921922self->inkEffect = self->invisible ? INK_BLEND : INK_NONE;923UIButton_Draw();924925self->size.y = sizeY;926927if (showGizmos()) {928RSDK_DRAWING_OVERLAY(true);929930int32 slot = RSDK.GetEntitySlot(self) - self->choiceCount;931for (int32 i = 0; i < self->choiceCount; ++i) {932EntityUIButton *item = RSDK_GET_ENTITY(slot + i, UIButton);933934if (item)935DrawHelpers_DrawArrow(self->position.x, self->position.y, item->position.x, item->position.y, i ? 0xFFFF00 : 0xE0E0E0, INK_NONE,9360xFF);937}938939RSDK_DRAWING_OVERLAY(false);940}941}942943void UIButton_EditorLoad(void)944{945RSDK_ACTIVE_VAR(UIButton, align);946RSDK_ENUM_VAR("Left", UIBUTTON_ALIGN_LEFT);947RSDK_ENUM_VAR("Center", UIBUTTON_ALIGN_CENTER);948RSDK_ENUM_VAR("Right", UIBUTTON_ALIGN_RIGHT);949}950#endif951952void UIButton_Serialize(void)953{954RSDK_EDITABLE_VAR(UIButton, VAR_BOOL, disabled);955RSDK_EDITABLE_VAR(UIButton, VAR_VECTOR2, size);956RSDK_EDITABLE_VAR(UIButton, VAR_ENUM, listID);957RSDK_EDITABLE_VAR(UIButton, VAR_ENUM, frameID);958RSDK_EDITABLE_VAR(UIButton, VAR_ENUM, align);959RSDK_EDITABLE_VAR(UIButton, VAR_ENUM, choiceCount);960RSDK_EDITABLE_VAR(UIButton, VAR_UINT8, choiceDir);961RSDK_EDITABLE_VAR(UIButton, VAR_BOOL, invisible);962RSDK_EDITABLE_VAR(UIButton, VAR_BOOL, assignsP1);963RSDK_EDITABLE_VAR(UIButton, VAR_BOOL, freeBindP2);964RSDK_EDITABLE_VAR(UIButton, VAR_BOOL, transition);965RSDK_EDITABLE_VAR(UIButton, VAR_BOOL, stopMusic);966}967968969