#include "common.h" #ifdef CUSTOM_FRONTEND_OPTIONS #include "frontendoption.h" int numCustomFrontendOptions = 0; FrontendOption *customFrontendOptions; int optionCursor = -1; eMenuScreen currentMenu; void ChangeScreen(eMenuScreen screen, int option, bool fadeIn) { FrontEndMenuManager.m_nPrevScreen = FrontEndMenuManager.m_nCurrScreen; FrontEndMenuManager.m_nCurrScreen = screen; FrontEndMenuManager.m_nCurrOption = option; if (fadeIn) FrontEndMenuManager.m_nMenuFadeAlpha = 0; } void GoBack(bool fadeIn) { int screen = !FrontEndMenuManager.m_bGameNotLoaded ? aScreens[FrontEndMenuManager.m_nCurrScreen].m_PreviousPage[1] : aScreens[FrontEndMenuManager.m_nCurrScreen].m_PreviousPage[0]; int option = !FrontEndMenuManager.m_bGameNotLoaded ? aScreens[FrontEndMenuManager.m_nCurrScreen].m_ParentEntry[1] : aScreens[FrontEndMenuManager.m_nCurrScreen].m_ParentEntry[0]; FrontEndMenuManager.ThingsToDoBeforeGoingBack(); ChangeScreen((eMenuScreen)screen, option, fadeIn); } uint8 GetNumberOfMenuOptions(int screen) { uint8 Rows = 0; for (int i = 0; i < NUM_MENUROWS; i++) { if (aScreens[screen].m_aEntries[i].m_Action == MENUACTION_NOTHING) break; ++Rows; } return Rows; } // Used before populating options, but effective in InitialiseChangedLanguageSettings and debugmenu void RemoveCustomFrontendOptions() { if (numCustomFrontendOptions == 0) return; for (int i = 0; i < MENUPAGES; i++) { for (int j = 0; j < NUM_MENUROWS; j++) { if (aScreens[i].m_aEntries[j].m_Action == MENUACTION_TRIGGERFUNC) { int k; for (k = j; k < NUM_MENUROWS-1; k++) { memcpy(&aScreens[i].m_aEntries[k], &aScreens[i].m_aEntries[k+1], sizeof(CMenuScreen::CMenuEntry)); } aScreens[i].m_aEntries[k].m_Action = MENUACTION_NOTHING; aScreens[i].m_aEntries[k].m_EntryName[0] = '\0'; j--; } } } free(customFrontendOptions); numCustomFrontendOptions = 0; } int8 RegisterNewOption(int screen) { numCustomFrontendOptions++; if (numCustomFrontendOptions == 1) customFrontendOptions = (FrontendOption*)malloc(5 * sizeof(FrontendOption)); else if (numCustomFrontendOptions % 5 == 1) customFrontendOptions = (FrontendOption*)realloc(customFrontendOptions, (numCustomFrontendOptions + 4) * sizeof(FrontendOption)); assert(customFrontendOptions != nil && "Custom frontend options can't be allocated"); uint8 nth = GetNumberOfMenuOptions(screen); if (optionCursor < 0) { if (optionCursor == -1) { if (!strcmp(aScreens[screen].m_aEntries[nth - 1].m_EntryName, "FEDS_TB") || !strcmp(aScreens[screen].m_aEntries[nth - 1].m_EntryName, "FESZ_CA")) { // Move back button one below memcpy(&aScreens[screen].m_aEntries[nth], &aScreens[screen].m_aEntries[nth - 1], sizeof(CMenuScreen::CMenuEntry)); nth--; } } } else { if (aScreens[screen].m_aEntries[optionCursor].m_Action != MENUACTION_NOTHING) { for (int i = nth - 1; i >= optionCursor; i--) { memcpy(&aScreens[screen].m_aEntries[i + 1], &aScreens[screen].m_aEntries[i], sizeof(CMenuScreen::CMenuEntry)); } } nth = optionCursor; optionCursor++; } aScreens[screen].m_aEntries[nth].m_Action = MENUACTION_TRIGGERFUNC; aScreens[screen].m_aEntries[nth].m_TargetMenu = numCustomFrontendOptions - 1; aScreens[screen].m_aEntries[nth].m_EntryName[0] = 1; // just something to fool it return nth; } void FrontendOptionSetPosition(eMenuScreen screen, int8 option) { currentMenu = screen; optionCursor = option; } void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc) { int8 screenOptionOrder = RegisterNewOption(currentMenu); FrontendOption& option = customFrontendOptions[numCustomFrontendOptions - 1]; option.screen = currentMenu; option.type = FEOPTION_SELECT; option.leftText = leftText; option.rightTexts = rightTexts; option.numRightTexts = numRightTexts; option.value = var; option.displayedValue = *var; option.onlyApplyOnEnter = onlyApplyOnEnter; option.changeFunc = changeFunc; option.screenOptionOrder = screenOptionOrder; option.returnPrevPageFunc = returnPrevPageFunc; } void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc drawFunc, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc) { int8 screenOptionOrder = RegisterNewOption(currentMenu); FrontendOption& option = customFrontendOptions[numCustomFrontendOptions - 1]; option.screen = currentMenu; option.type = FEOPTION_DYNAMIC; option.drawFunc = drawFunc; option.buttonPressFunc = buttonPressFunc; option.leftText = leftText; option.onlyApplyOnEnter = false; option.screenOptionOrder = screenOptionOrder; option.returnPrevPageFunc = returnPrevPageFunc; } void FrontendOptionAddRedirect(const wchar* text, eMenuScreen to, int8 selectedOption, bool fadeIn) { int8 screenOptionOrder = RegisterNewOption(currentMenu); FrontendOption &option = customFrontendOptions[numCustomFrontendOptions - 1]; option.screen = currentMenu; option.type = FEOPTION_REDIRECT; option.to = to; option.option = selectedOption; option.fadeIn = fadeIn; option.leftText = text; option.onlyApplyOnEnter = false; option.screenOptionOrder = screenOptionOrder; option.returnPrevPageFunc = nil; } void FrontendOptionAddBackButton(const wchar* text, bool fadeIn) { int8 screenOptionOrder = RegisterNewOption(currentMenu); FrontendOption& option = customFrontendOptions[numCustomFrontendOptions - 1]; option.screen = currentMenu; option.type = FEOPTION_GOBACK; option.fadeIn = fadeIn; option.leftText = text; option.onlyApplyOnEnter = false; option.screenOptionOrder = screenOptionOrder; option.returnPrevPageFunc = nil; } #endif