Path: blob/master/SonicMania/Objects/Menu/UIDialog.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: UIDialog Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectUIDialog *UIDialog;1011void UIDialog_Update(void)12{13RSDK_THIS(UIDialog);1415StateMachine_Run(self->state);1617UIDialog_HandleButtonPositions();1819if (self->closeDelay > 0) {20if (!--self->closeDelay)21UIDialog_HandleAutoClose();22}23}2425void UIDialog_LateUpdate(void) {}2627void UIDialog_StaticUpdate(void) {}2829void UIDialog_Draw(void)30{31RSDK_THIS(UIDialog);3233UIDialog_DrawBGShapes();3435Vector2 drawPos;36switch (self->lineCount) {37case 0:38case 1:39drawPos.x = (self->position.x + 0x100000) + 0x100000;40drawPos.y = self->position.y - 0x200000;41break;4243case 2:44drawPos.x = (self->position.x + 0x100000) + 0x180000;45drawPos.y = self->position.y - 0x280000;46break;4748case 3:49drawPos.x = (self->position.x + 0x100000) + 0x200000;50drawPos.y = self->position.y - 0x300000;51break;5253default: break;54}5556drawPos.x += self->dialogPos.x;57drawPos.y += self->dialogPos.y;5859int32 w = 0;60int32 count = self->lineCount + 1;61if (count > 0) {62for (int32 i = 0; i < count; ++i) {63int32 start = !i ? 0 : self->lineLength[i - 1] + 1;64int32 len = i >= self->lineCount ? self->textInfo.length : self->lineLength[i];6566int32 width = RSDK.GetStringWidth(UIWidgets->fontFrames, 0, &self->textInfo, start, len, 0);67if (width > w)68w = width;69}70}7172for (int32 i = 0; i < count; ++i) {73int32 offset = -0x8000 * w;7475int32 start = !i ? 0 : self->lineLength[i - 1] + 1;76int32 len = i >= self->lineCount ? self->textInfo.length : self->lineLength[i];7778RSDK.GetStringWidth(UIWidgets->fontFrames, 0, &self->textInfo, start, len, 0);7980drawPos.x += offset;81RSDK.DrawText(&self->animator, &drawPos, &self->textInfo, start, len, 0, 0, NULL, NULL, false);8283drawPos.y += 0x120000;84drawPos.x = drawPos.x - offset - 0x120000;85}86}8788void UIDialog_Create(void *data)89{90RSDK_THIS(UIDialog);9192self->active = ACTIVE_ALWAYS;93self->drawGroup = 15;94self->visible = true;9596if (data)97UIDialog_SetupText(self, data);9899self->buttonCount = 0;100}101102void UIDialog_StageLoad(void)103{104UIDialog->controlStore = NULL;105UIDialog->activeDialog = NULL;106}107108EntityUIDialog *UIDialog_CreateActiveDialog(String *msg)109{110if (UIDialog->activeDialog) {111LogHelpers_Print("EXCEPTION: Called CreateDialog when an activeDialog already existed.");112}113else {114int32 id = RSDK_GET_ENTITY(SLOT_DIALOG, UIDialog)->classID;115116if (id) {117LogHelpers_Print("Can't create UIDialog (%d), entity already exists in slot (class ID: %d)", UIDialog->classID, id);118}119else {120RSDK.ResetEntitySlot(SLOT_DIALOG, UIDialog->classID, msg);121122EntityUIDialog *dialog = RSDK_GET_ENTITY(SLOT_DIALOG, UIDialog);123dialog->position.x = (ScreenInfo->position.x + ScreenInfo->center.x) << 16;124dialog->position.y = (ScreenInfo->position.y + ScreenInfo->center.y) << 16;125UIDialog->activeDialog = dialog;126127return dialog;128}129}130131return NULL;132}133134void UIDialog_SetupText(EntityUIDialog *dialog, String *text)135{136if (text) {137dialog->lineCount = 0;138int32 charPos = 0;139140for (int32 i = 0; i < text->length; ++i) {141if (text->chars[charPos] == '\n' && dialog->lineCount < 3) {142dialog->lineLength[dialog->lineCount] = charPos;143++dialog->lineCount;144}145146++charPos;147}148149RSDK.CopyString(&dialog->textInfo, text);150RSDK.SetSpriteAnimation(UIWidgets->fontFrames, 0, &dialog->animator, true, 0);151RSDK.SetSpriteString(UIWidgets->fontFrames, 0, &dialog->textInfo);152}153}154155void UIDialog_AddButton(uint8 frame, EntityUIDialog *dialog, void (*callback)(void), bool32 closeOnSelect)156{157int32 id = dialog->buttonCount;158159if (dialog->buttonCount < UIDIALOG_OPTION_COUNT) {160dialog->buttonFrames[dialog->buttonCount] = frame;161dialog->callbacks[dialog->buttonCount] = callback;162dialog->closeOnSelect[dialog->buttonCount] = closeOnSelect;163164RSDK.ResetEntitySlot(SLOT_DIALOG_BUTTONS + dialog->buttonCount, UIButton->classID, NULL);165166EntityUIButton *button = RSDK_GET_ENTITY(SLOT_DIALOG_BUTTONS + dialog->buttonCount, UIButton);167button->position.x = (ScreenInfo->position.x + ScreenInfo->center.x) << 16;168button->position.y = (ScreenInfo->position.y + ScreenInfo->center.y) << 16;169RSDK.SetSpriteAnimation(UIWidgets->textFrames, 9, &button->animator, true, frame);170button->textFrames = UIWidgets->textFrames;171172if (frame == DIALOG_CONTINUE)173button->size.x = 0x640000;174else175button->size.x = 0x320000;176button->size.y = 0x180000;177button->actionCB = UIDialog_ButtonActionCB;178button->bgEdgeSize = 24;179button->align = UIBUTTON_ALIGN_CENTER;180button->active = ACTIVE_ALWAYS;181button->drawGroup = dialog->drawGroup;182dialog->buttons[dialog->buttonCount++] = button;183184EntityUIControl *parent = dialog->parent;185if (parent) {186button->parent = (Entity *)parent;187parent->buttons[id] = button;188parent->buttonCount = dialog->buttonCount;189}190}191}192193void UIDialog_Setup(EntityUIDialog *dialog)194{195if (dialog) {196bool32 tookFocus = false;197198Vector2 size;199size.x = ScreenInfo->size.x << 16;200size.y = ScreenInfo->size.y << 16;201foreach_all(UIControl, control)202{203if (control->active == ACTIVE_ALWAYS) {204tookFocus = true;205control->dialogHasFocus = true;206UIDialog->controlStore = control;207UIDialog->controlStateStore = control->state;208foreach_break;209}210}211212control = NULL;213RSDK.ResetEntitySlot(SLOT_DIALOG_UICONTROL, UIControl->classID, &size);214215control = RSDK_GET_ENTITY(SLOT_DIALOG_UICONTROL, UIControl);216#if MANIA_USE_PLUS217control->menuWasSetup = true;218#endif219control->position.x = (ScreenInfo->position.x + ScreenInfo->center.x) << 16;220control->position.y = (ScreenInfo->position.y + ScreenInfo->center.y) << 16;221control->rowCount = 1;222control->columnCount = dialog->buttonCount;223control->buttonID = 0;224control->backPressCB = UIDialog_HandleAutoClose;225control->selectionDisabled = true;226227dialog->parent = control;228if (!tookFocus) {229UIDialog->controlStore = NULL;230UIDialog->controlStateStore = StateMachine_None;231}232233int32 i = 0;234for (; i < UIDIALOG_OPTION_COUNT; ++i) {235if (!dialog->buttons[i])236break;237238dialog->buttons[i]->parent = (Entity *)control;239control->buttons[i] = dialog->buttons[i];240}241242control->buttonCount = i;243dialog->timer = 0;244dialog->state = UIDialog_State_Appear;245}246}247248void UIDialog_CloseOnSel_HandleSelection(EntityUIDialog *dialog, void (*callback)(void))249{250if (dialog && dialog->state != UIDialog_State_Close) {251dialog->parent->selectionDisabled = true;252dialog->timer = 0;253dialog->state = UIDialog_State_Close;254dialog->closeCB = callback;255}256}257258void UIDialog_DrawBGShapes(void)259{260RSDK_THIS(UIDialog);261262RSDK.DrawRect(((ScreenInfo->position.x + ScreenInfo->center.x) << 16) - (self->bgRectSize.x >> 1),263((ScreenInfo->position.y + ScreenInfo->center.y) << 16) - (self->bgRectSize.y >> 1), self->bgRectSize.x, self->bgRectSize.y,264self->useAltColor ? 0x282028 : 0x000000, 0xFF, INK_NONE, false);265266UIWidgets_DrawParallelogram(self->dialogPos.x + ((ScreenInfo->position.x + ScreenInfo->center.x) << 16),267self->dialogPos.y + ((ScreenInfo->position.y + ScreenInfo->center.y) << 16), 0xC8, 0x8F, 0x8F, 0x30, 0xA0, 0xF0);268}269270void UIDialog_HandleButtonPositions(void)271{272RSDK_THIS(UIDialog);273274int32 offsets[] = { 0, 0, 0x80, 0x70 };275276int32 offset = offsets[self->buttonCount] << 16;277int32 x = self->position.x - 0x240000 + self->dialogPos.x - ((offset * MAX(self->buttonCount - 1, 0)) >> 1);278int32 y = self->position.y + 0x2C0000 + self->dialogPos.y;279280for (int32 i = 0; i < UIDIALOG_OPTION_COUNT; ++i) {281if (!self->buttons[i])282break;283284EntityUIButton *button = self->buttons[i];285button->startPos.x = x;286button->startPos.y = y;287button->position.x = x;288button->position.y = y;289290x += offset;291}292}293294void UIDialog_Close(void)295{296RSDK_THIS(UIDialog);297298EntityUIControl *control = self->parent;299300if (control) {301UIControl_SetInactiveMenu(control);302destroyEntity(control);303}304305for (int32 i = 0; i < UIDIALOG_OPTION_COUNT; ++i) {306if (self->buttons[i])307destroyEntity(self->buttons[i]);308}309310EntityUIControl *storedControl = UIDialog->controlStore;311if (storedControl) {312UIControl_SetMenuLostFocus(UIDialog->controlStore);313storedControl->state = UIDialog->controlStateStore;314storedControl->dialogHasFocus = false;315}316317UIDialog->controlStore = NULL;318UIDialog->controlStateStore = StateMachine_None;319UIDialog->activeDialog = NULL;320321StateMachine_Run(self->closeCB);322destroyEntity(self);323}324325bool32 UIDialog_HandleAutoClose(void)326{327EntityUIDialog *entity = UIDialog->activeDialog;328EntityUIControl *control = entity->parent;329330for (int32 i = 0; i < control->buttonCount; ++i) {331int32 frame = entity->buttonFrames[i];332if (frame == DIALOG_NO || frame == DIALOG_CANCEL) {333if (entity->closeOnSelect[i]) {334UIDialog_CloseOnSel_HandleSelection(entity, entity->callbacks[i]);335}336else {337StateMachine_Run(entity->callbacks[i]);338}339340return true;341}342}343344return false;345}346347void UIDialog_ButtonActionCB(void)348{349EntityUIDialog *entity = UIDialog->activeDialog;350351if (entity->parent) {352int32 id = entity->parent->buttonID;353354if (id >= 0 && id < entity->parent->buttonCount) {355if (entity->closeOnSelect[id]) {356UIDialog_CloseOnSel_HandleSelection(entity, entity->callbacks[id]);357}358else {359StateMachine_Run(entity->callbacks[id]);360}361}362}363}364365void UIDialog_State_Appear(void)366{367RSDK_THIS(UIDialog);368369Vector2 pos;370pos.x = 0;371pos.y = 0;372373if (self->timer == 1) {374RSDK.PlaySfx(UIWidgets->sfxWoosh, false, 255);375UIControl_HandleMenuLoseFocus(self->parent);376}377378if (self->timer >= 8) {379if (self->timer >= 16) {380if (self->timer >= 26) {381self->parent->selectionDisabled = false;382self->timer = 0;383self->state = UIDialog_State_Idle;384}385else {386self->bgRectSize.x = ScreenInfo->size.x << 16;387self->bgRectSize.y = 0x900000;388MathHelpers_Lerp2Sin1024(&pos, MAX(((self->timer - 16) << 8) / 10, 0), -0x400000 - (ScreenInfo->size.x << 16), 0, 0, 0);389self->dialogPos = pos;390391if (self->timer - 16 == 1 && self->playEventSfx)392RSDK.PlaySfx(UIWidgets->sfxEvent, false, 255);393394++self->timer;395}396}397else {398self->dialogPos.x = -0x400000 - (ScreenInfo->size.x << 16);399self->dialogPos.y = 0;400MathHelpers_Lerp(&pos, MAX(((self->timer - 8) << 8) / 8, 0), ScreenInfo->size.x << 16, 0x10000, ScreenInfo->size.x << 16, 0x900000);401self->bgRectSize = pos;402403self->timer++;404}405}406else {407self->dialogPos.x = -0x400000 - (ScreenInfo->size.x << 16);408self->dialogPos.y = 0;409MathHelpers_Lerp2Sin1024(&pos, MAX((self->timer << 8) / 8, 0), 0, 0x10000, ScreenInfo->size.x << 16, 0x10000);410self->bgRectSize = pos;411412++self->timer;413}414}415416void UIDialog_State_Idle(void)417{418RSDK_THIS(UIDialog);419420self->bgRectSize.x = ScreenInfo->size.x << 16;421self->bgRectSize.y = 0x900000;422self->dialogPos.x = 0;423self->dialogPos.y = 0;424}425426void UIDialog_State_Close(void)427{428RSDK_THIS(UIDialog);429430if (self->timer >= 8) {431if (self->timer >= 16) {432UIDialog_Close();433}434else {435self->dialogPos.x = (ScreenInfo->size.x + 64) << 16;436self->dialogPos.y = 0;437MathHelpers_Lerp2Sin1024(&self->bgRectSize, MAX(((self->timer - 8) << 8) / 8, 0), ScreenInfo->size.x << 16, 0x900000,438ScreenInfo->size.x << 16, 0);439440++self->timer;441}442}443else {444self->bgRectSize.x = ScreenInfo->size.x << 16;445self->bgRectSize.y = 0x900000;446MathHelpers_LerpSin1024(&self->dialogPos, MAX((self->timer << 8) / 8, 0), 0, 0, (ScreenInfo->size.x + 64) << 16, 0);447448++self->timer;449}450}451452EntityUIDialog *UIDialog_CreateDialogOk(String *text, void (*callback)(void), bool32 closeOnSelect)453{454EntityUIDialog *dialog = UIDialog_CreateActiveDialog(text);455456if (dialog) {457UIDialog_AddButton(DIALOG_OK, dialog, callback, closeOnSelect);458UIDialog_Setup(dialog);459}460461return dialog;462}463EntityUIDialog *UIDialog_CreateDialogYesNo(String *text, void (*callbackYes)(void), void (*callbackNo)(void), bool32 closeOnSelect_Yes,464bool32 closeOnSelect_No)465{466EntityUIDialog *dialog = UIDialog_CreateActiveDialog(text);467468if (dialog) {469UIDialog_AddButton(DIALOG_NO, dialog, callbackNo, closeOnSelect_No);470UIDialog_AddButton(DIALOG_YES, dialog, callbackYes, closeOnSelect_Yes);471UIDialog_Setup(dialog);472}473474return dialog;475}476EntityUIDialog *UIDialog_CreateDialogOkCancel(String *text, void (*callbackOk)(void), void (*callbackCancel)(void), bool32 closeOnSelect_Ok,477bool32 closeOnSelect_Cancel)478{479EntityUIDialog *dialog = UIDialog_CreateActiveDialog(text);480481if (dialog) {482UIDialog_AddButton(DIALOG_OK, dialog, callbackOk, closeOnSelect_Ok);483UIDialog_AddButton(DIALOG_CANCEL, dialog, callbackCancel, closeOnSelect_Cancel);484UIDialog_Setup(dialog);485}486487return dialog;488}489490#if GAME_INCLUDE_EDITOR491void UIDialog_EditorDraw(void) {}492493void UIDialog_EditorLoad(void) {}494#endif495496void UIDialog_Serialize(void) {}497498499