From be638a497387e417b3b825cb2e6fde4fa5f72fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Wed, 19 Aug 2020 20:30:57 +0300 Subject: [PATCH 1/2] Revert "remove CFO" This reverts commit 0418ba597bc53d08d0244188f4623ebadfdd2876. --- src/core/Frontend.cpp | 150 ++++++++++++++++++++++++++++- src/core/Frontend.h | 5 +- src/core/Game.cpp | 5 + src/core/MenuScreens.cpp | 21 +---- src/core/config.h | 1 + src/core/re3.cpp | 112 ++++++++++++++++++++++ src/extras/frontendoption.cpp | 173 ++++++++++++++++++++++++++++++++++ src/extras/frontendoption.h | 87 +++++++++++++++++ 8 files changed, 533 insertions(+), 21 deletions(-) create mode 100644 src/extras/frontendoption.cpp create mode 100644 src/extras/frontendoption.h diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index d82c5df4..0c813cbb 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -36,6 +36,7 @@ #include "Stats.h" #include "Messages.h" #include "FileLoader.h" +#include "frontendoption.h" #define TIDY_UP_PBP // ProcessButtonPresses #define MAX_VISIBLE_LIST_ROW 30 @@ -431,12 +432,46 @@ CMenuManager::ThingsToDoBeforeGoingBack() if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) || (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS)) { m_nTotalListRow = 0; } + +#ifdef CUSTOM_FRONTEND_OPTIONS + for (int i = 0; i < numCustomFrontendOptions; i++) { + FrontendOption &option = customFrontendOptions[i]; + if (option.type != FEOPTION_REDIRECT && option.type != FEOPTION_GOBACK && m_nCurrScreen == option.screen) { + if (option.returnPrevPageFunc) + option.returnPrevPageFunc(); + + if (m_nCurrOption == option.screenOptionOrder && option.type == FEOPTION_DYNAMIC) + option.buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); + + if (option.onlyApplyOnEnter) + option.displayedValue = *option.value; + } + } +#endif } int8 CMenuManager::GetPreviousPageOption() { +#ifndef CUSTOM_FRONTEND_OPTIONS return !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry[1] : aScreens[m_nCurrScreen].m_ParentEntry[0]; +#else + int8 prevPage = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0]; + + if (prevPage == -1) // Game also does same + return 0; + + prevPage = prevPage == MENUPAGE_NONE ? (!m_bGameNotLoaded ? MENUPAGE_PAUSE_MENU : MENUPAGE_START_MENU) : prevPage; + + for (int i = 0; i < NUM_MENUROWS; i++) { + if (aScreens[prevPage].m_aEntries[i].m_TargetMenu == m_nCurrScreen) { + return i; + } + } + + // Couldn't find current screen option on previous page, use default behaviour (maybe save-related screen?) + return !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry[1] : aScreens[m_nCurrScreen].m_ParentEntry[0]; +#endif } // ------ Functions not in the game/inlined ends @@ -955,7 +990,14 @@ CMenuManager::Draw() } #endif +#ifdef CUSTOM_FRONTEND_OPTIONS + static int lastOption = m_nCurrOption; +#endif + for (int i = 0; i < NUM_MENUROWS; ++i) { +#ifdef CUSTOM_FRONTEND_OPTIONS + bool isOptionDisabled = false; +#endif if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != MENUACTION_LABEL && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0] != '\0') { wchar *rightText = nil; wchar *leftText; @@ -1232,6 +1274,29 @@ CMenuManager::Draw() rightText = TheText.Get(gPS2alphaTest ? "FEM_ON" : "FEM_OFF"); break; #endif +#ifdef CUSTOM_FRONTEND_OPTIONS + case MENUACTION_TRIGGERFUNC: + FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu]; + if (m_nCurrScreen == option.screen && i == option.screenOptionOrder) { + leftText = (wchar*)option.leftText; + if (option.type == FEOPTION_SELECT) { + if (option.displayedValue >= option.numRightTexts || option.displayedValue < 0) + option.displayedValue = 0; + + rightText = (wchar*)option.rightTexts[option.displayedValue]; + + } else if (option.type == FEOPTION_DYNAMIC) { + if (option.drawFunc) { + rightText = option.drawFunc(&isOptionDisabled); + } + } + } else { + debug("A- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, i, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu, option.screen, option.screenOptionOrder); + assert(0 && "Custom frontend options is borked"); + } + + break; +#endif } float nextItemY = headerHeight + nextYToUse; @@ -1318,7 +1383,11 @@ CMenuManager::Draw() || !strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FED_AAS") #endif ) - && !m_bGameNotLoaded) + && !m_bGameNotLoaded +#ifdef CUSTOM_FRONTEND_OPTIONS + || isOptionDisabled +#endif + ) CFont::SetColor(CRGBA(155, 117, 6, FadeIn(255))); CFont::PrintString(MENU_X_RIGHT_ALIGNED(columnWidth - textLayer), itemY, rightText); @@ -1428,6 +1497,20 @@ CMenuManager::Draw() } #endif +#ifdef CUSTOM_FRONTEND_OPTIONS + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_TRIGGERFUNC) { + FrontendOption &option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu]; + if (option.onlyApplyOnEnter && m_nCurrOption != i) + option.displayedValue = *option.value; + + if (m_nCurrOption != lastOption && lastOption == i) { + FrontendOption &oldOption = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[lastOption].m_TargetMenu]; + if (oldOption.type == FEOPTION_DYNAMIC) + oldOption.buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); + } + } +#endif + // Sliders int lastActiveBarX; switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { @@ -1471,6 +1554,10 @@ CMenuManager::Draw() } } +#ifdef CUSTOM_FRONTEND_OPTIONS + lastOption = m_nCurrOption; +#endif + switch (m_nCurrScreen) { case MENUPAGE_CONTROLLER_SETTINGS: case MENUPAGE_SOUND_SETTINGS: @@ -3128,6 +3215,10 @@ CMenuManager::InitialiseChangedLanguageSettings() default: break; } + +#ifdef CUSTOM_FRONTEND_OPTIONS + CustomFrontendOptionsPopulate(); +#endif } } @@ -5005,6 +5096,33 @@ CMenuManager::ProcessButtonPresses(void) RequestFrontEndShutDown(); RetryMission(2, 0); return; +#endif +#ifdef CUSTOM_FRONTEND_OPTIONS + case MENUACTION_TRIGGERFUNC: + FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu]; + if (m_nCurrScreen == option.screen && m_nCurrOption == option.screenOptionOrder) { + if (option.type == FEOPTION_SELECT) { + if (!option.onlyApplyOnEnter) { + option.displayedValue++; + if (option.displayedValue >= option.numRightTexts || option.displayedValue < 0) + option.displayedValue = 0; + } + option.changeFunc(option.displayedValue); + *option.value = option.displayedValue; + + } else if (option.type == FEOPTION_DYNAMIC) { + option.buttonPressFunc(FEOPTION_ACTION_SELECT); + } else if (option.type == FEOPTION_REDIRECT) { + ChangeScreen(option.to, option.option, true, option.fadeIn); + } else if (option.type == FEOPTION_GOBACK) { + goBack = true; + } + } else { + debug("B- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, m_nCurrOption, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, option.screen, option.screenOptionOrder); + assert(0 && "Custom frontend options are borked"); + } + + break; #endif } } @@ -5236,6 +5354,36 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); SaveSettings(); break; +#ifdef CUSTOM_FRONTEND_OPTIONS + case MENUACTION_TRIGGERFUNC: + FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu]; + if (m_nCurrScreen == option.screen && m_nCurrOption == option.screenOptionOrder) { + if (option.type == FEOPTION_SELECT) { + if (changeValueBy > 0) { + option.displayedValue++; + if (option.displayedValue >= option.numRightTexts) + option.displayedValue = 0; + } else { + option.displayedValue--; + if (option.displayedValue < 0) + option.displayedValue = option.numRightTexts - 1; + } + if (!option.onlyApplyOnEnter) { + option.changeFunc(option.displayedValue); + *option.value = option.displayedValue; + } + } else if (option.type == FEOPTION_DYNAMIC) { + option.buttonPressFunc(changeValueBy > 0 ? FEOPTION_ACTION_RIGHT : FEOPTION_ACTION_LEFT); + } + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); + } + else { + debug("C- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, m_nCurrOption, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, option.screen, option.screenOptionOrder); + assert(0 && "Custom frontend options are borked"); + } + + break; +#endif } ProcessOnOffMenuOptions(); if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { diff --git a/src/core/Frontend.h b/src/core/Frontend.h index cf112b3d..fa3652a1 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -381,6 +381,9 @@ enum eMenuAction #ifdef CUTSCENE_BORDERS_SWITCH MENUACTION_CUTSCENEBORDERS, #endif +#ifdef CUSTOM_FRONTEND_OPTIONS + MENUACTION_TRIGGERFUNC +#endif }; enum eCheckHover @@ -475,7 +478,7 @@ struct CMenuScreen int32 m_Action; // eMenuAction char m_EntryName[8]; int32 m_SaveSlot; // eSaveSlot - int32 m_TargetMenu; // eMenuScreen + int32 m_TargetMenu; // eMenuScreen // FrontendOption ID if it's a custom option } m_aEntries[NUM_MENUROWS]; }; diff --git a/src/core/Game.cpp b/src/core/Game.cpp index a95c479a..c0530709 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -86,6 +86,7 @@ #include "ZoneCull.h" #include "Zones.h" #include "debugmenu.h" +#include "frontendoption.h" #include "postfx.h" #include "custompipes.h" @@ -292,6 +293,10 @@ bool CGame::InitialiseOnceAfterRW(void) DMAudio.SetEffectsFadeVol(127); DMAudio.SetMusicFadeVol(127); CWorld::Players[0].SetPlayerSkin(CMenuManager::m_PrefsSkinFile); + +#ifdef CUSTOM_FRONTEND_OPTIONS + CustomFrontendOptionsPopulate(); +#endif return true; } diff --git a/src/core/MenuScreens.cpp b/src/core/MenuScreens.cpp index 5dfcc8fe..02c004b3 100644 --- a/src/core/MenuScreens.cpp +++ b/src/core/MenuScreens.cpp @@ -2,6 +2,8 @@ #include "Frontend.h" #ifdef PC_MENU +// If you want to add new options, please don't do that here and see CustomFrontendOptionsPopulate in re3.cpp. + #ifdef CUTSCENE_BORDERS_SWITCH #define MENU_CUTSCENE_BORDERS_SWITCH(screen) MENUACTION_CUTSCENEBORDERS, "FEM_CSB", SAVESLOT_NONE, screen, #else @@ -45,11 +47,7 @@ CMenuScreen aScreens[] = { { "", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, }, // MENUPAGE_STATS = 1 -#ifdef MENU_MAP - { "FET_STA", 1, MENUPAGE_NONE, MENUPAGE_NONE, 5, 3, -#else { "FET_STA", 1, MENUPAGE_NONE, MENUPAGE_NONE, 5, 2, -#endif MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, }, @@ -62,11 +60,7 @@ CMenuScreen aScreens[] = { }, // MENUPAGE_BRIEFS = 3 -#ifdef MENU_MAP - { "FET_BRE", 1, MENUPAGE_NONE, MENUPAGE_NONE, 6, 4, -#else { "FET_BRE", 1, MENUPAGE_NONE, MENUPAGE_NONE, 6, 3, -#endif MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, }, @@ -381,11 +375,7 @@ CMenuScreen aScreens[] = { }, // MENUPAGE_OPTIONS = 41 -#ifdef MENU_MAP - { "FET_OPT", 1, MENUPAGE_NONE, MENUPAGE_NONE, 1, 5, -#else { "FET_OPT", 1, MENUPAGE_NONE, MENUPAGE_NONE, 1, 4, -#endif MENUACTION_CHANGEMENU, "FET_CTL", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, MENUACTION_LOADRADIO, "FET_AUD", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, MENUACTION_CHANGEMENU, "FET_DIS", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, @@ -398,11 +388,7 @@ CMenuScreen aScreens[] = { }, // MENUPAGE_EXIT = 42 -#ifdef MENU_MAP - { "FET_QG", 1, MENUPAGE_NONE, MENUPAGE_NONE, 2, 6, -#else { "FET_QG", 1, MENUPAGE_NONE, MENUPAGE_NONE, 2, 5, -#endif MENUACTION_LABEL, "FEQ_SRE", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_DONTCANCEL, "FEM_NO", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_CANCELGAME, "FEM_YES", SAVESLOT_NONE, MENUPAGE_NONE, @@ -463,9 +449,6 @@ CMenuScreen aScreens[] = { { "FET_PAU", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, MENUACTION_RESUME, "FEM_RES", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_CHANGEMENU, "FEN_STA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, -#ifdef MENU_MAP - MENUACTION_CHANGEMENU, "FEG_MAP", SAVESLOT_NONE, MENUPAGE_MAP, -#endif MENUACTION_CHANGEMENU, "FEP_STA", SAVESLOT_NONE, MENUPAGE_STATS, MENUACTION_CHANGEMENU, "FEP_BRI", SAVESLOT_NONE, MENUPAGE_BRIEFS, MENUACTION_CHANGEMENU, "FET_OPT", SAVESLOT_NONE, MENUPAGE_OPTIONS, diff --git a/src/core/config.h b/src/core/config.h index 8e91853d..ac3ba109 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -248,6 +248,7 @@ enum Config { # define SCROLLABLE_STATS_PAGE // only draggable by mouse atm # define TRIANGLE_BACK_BUTTON //# define CIRCLE_BACK_BUTTON +# define CUSTOM_FRONTEND_OPTIONS # define GRAPHICS_MENU_OPTIONS #endif diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 27ec336d..dd116e27 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -71,6 +71,115 @@ mysrand(unsigned int seed) myrand_seed = seed; } +#ifdef CUSTOM_FRONTEND_OPTIONS +#include "frontendoption.h" +#include "platform.h" + +void ReloadFrontendOptions(void) +{ + CustomFrontendOptionsPopulate(); +} + +#ifdef MORE_LANGUAGES +void LangPolSelect(int8 action) +{ + if (action == FEOPTION_ACTION_SELECT) { + FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_POLISH; + FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true; + FrontEndMenuManager.InitialiseChangedLanguageSettings(); + FrontEndMenuManager.SaveSettings(); + } +} + +void LangRusSelect(int8 action) +{ + if (action == FEOPTION_ACTION_SELECT) { + FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_RUSSIAN; + FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true; + FrontEndMenuManager.InitialiseChangedLanguageSettings(); + FrontEndMenuManager.SaveSettings(); + } +} + +void LangJapSelect(int8 action) +{ + if (action == FEOPTION_ACTION_SELECT) { + FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_JAPANESE; + FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true; + FrontEndMenuManager.InitialiseChangedLanguageSettings(); + FrontEndMenuManager.SaveSettings(); + } +} +#endif + +/*#ifdef IMPROVED_VIDEOMODE +void ScreenModeChange(int8 displayedValue) +{ + if (displayedValue != FrontEndMenuManager.m_nPrefsWindowed) { + FrontEndMenuManager.m_nPrefsWindowed = displayedValue; + _psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode); // apply same resolution + FrontEndMenuManager.SetHelperText(0); + FrontEndMenuManager.SaveSettings(); + } +} +#endif*/ + +#ifdef FREE_CAM +void ToggleFreeCam(int8 action) +{ + if (action == FEOPTION_ACTION_SELECT) { + TheCamera.bFreeCam = !TheCamera.bFreeCam; + FrontEndMenuManager.SaveSettings(); + } +} +#endif + +//#ifdef CUTSCENE_BORDERS_SWITCH +//void BorderModeChange(int8 displayedValue) +//{ +// CMenuManager::m_PrefsCutsceneBorders = !!displayedValue; +// FrontEndMenuManager.SaveSettings(); +//} +//#endif + +// Reloaded on language change, so you can use hardcoded wchar* and TheText.Get with peace of mind +void +CustomFrontendOptionsPopulate(void) +{ + RemoveCustomFrontendOptions(); // if exist + +#ifdef MORE_LANGUAGES + FrontendOptionSetPosition(MENUPAGE_LANGUAGE_SETTINGS); + FrontendOptionAddDynamic(TheText.Get("FEL_POL"), nil, LangPolSelect, nil); + FrontendOptionAddDynamic(TheText.Get("FEL_RUS"), nil, LangRusSelect, nil); + FrontendOptionAddDynamic(TheText.Get("FEL_JAP"), nil, LangJapSelect, nil); +#endif + +/*#ifdef IMPROVED_VIDEOMODE + static const wchar *screenModes[] = { (wchar*)L"FULLSCREEN", (wchar*)L"WINDOWED" }; + FrontendOptionSetPosition(MENUPAGE_GRAPHICS_SETTINGS, 8); + FrontendOptionAddSelect(TheText.Get("SCRFOR"), screenModes, 2, (int8*)&FrontEndMenuManager.m_nPrefsWindowed, true, ScreenModeChange, nil); +#endif*/ + +#ifdef MENU_MAP + FrontendOptionSetPosition(MENUPAGE_PAUSE_MENU, 2); + FrontendOptionAddRedirect(TheText.Get("FEG_MAP"), MENUPAGE_MAP); +#endif + +#ifdef FREE_CAM + static const wchar *text = (wchar*)L"TOGGLE FREE CAM"; + FrontendOptionSetPosition(MENUPAGE_CONTROLLER_PC, 1); + FrontendOptionAddDynamic(text, nil, ToggleFreeCam, nil); +#endif + +/*#ifdef CUTSCENE_BORDERS_SWITCH + static const wchar *off_on[] = { TheText.Get("FEM_OFF"), TheText.Get("FEM_ON") }; + FrontendOptionSetPosition(MENUPAGE_DISPLAY_SETTINGS, 3); + FrontendOptionAddSelect((const wchar *)L"CUTSCENE BORDERS", off_on, 2, (int8 *)&CMenuManager::m_PrefsCutsceneBorders, false, BorderModeChange, nil); +#endif*/ +} +#endif + #ifdef DEBUGMENU void WeaponCheat(); void HealthCheat(); @@ -405,6 +514,9 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Debug", "Catalina Fly Away", CHeli::MakeCatalinaHeliFlyAway); DebugMenuAddVarBool8("Debug", "Script Heli On", &CHeli::ScriptHeliOn, nil); +#ifdef CUSTOM_FRONTEND_OPTIONS + DebugMenuAddCmd("Debug", "Reload custom frontend options", ReloadFrontendOptions); +#endif DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", &CPed::bPopHeadsOnHeadshot, nil); DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start); DebugMenuAddCmd("Debug", "Stop Credits", CCredits::Stop); diff --git a/src/extras/frontendoption.cpp b/src/extras/frontendoption.cpp new file mode 100644 index 00000000..51814f35 --- /dev/null +++ b/src/extras/frontendoption.cpp @@ -0,0 +1,173 @@ +#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 \ No newline at end of file diff --git a/src/extras/frontendoption.h b/src/extras/frontendoption.h new file mode 100644 index 00000000..7cfc09a7 --- /dev/null +++ b/src/extras/frontendoption.h @@ -0,0 +1,87 @@ +#pragma once +#include "common.h" + +#ifdef CUSTOM_FRONTEND_OPTIONS +#include "Frontend.h" + +// Warning: All of the code relies on that you won't use more then NUM_MENUROWS(18) options on one page. Also congrats if you can make 18 options visible at once. + + +// Static/select: User allocates variable, passes it to function and it's set automatically from input among the strings given to function, +// then you can handle ChangeFunc and ReturnPrevPageFunc if needed. +// +// Dynamic: Function doesn't accept value pointer, user should do operations with handling ButtonPressFunc. +// Right-side text can be set via DrawFunc, which is called on every draw. ReturnPrevPageFunc is also here if needed. + +#define FEOPTION_SELECT 0 +#define FEOPTION_DYNAMIC 1 +#define FEOPTION_REDIRECT 2 +#define FEOPTION_GOBACK 3 + +#define FEOPTION_ACTION_LEFT 0 +#define FEOPTION_ACTION_RIGHT 1 +#define FEOPTION_ACTION_SELECT 2 +#define FEOPTION_ACTION_FOCUSLOSS 3 + +void RemoveCustomFrontendOptions(); +void CustomFrontendOptionsPopulate(); + +// for static and dynamic options +typedef void (*ReturnPrevPageFunc)(); + +// for static options +typedef void (*ChangeFunc)(int8 displayedValue); // called before updating the value + +// for dynamic options +typedef wchar* (*DrawFunc)(bool* disabled); // should return pointer to right text. *disabled = true will make it dark yellow +typedef void (*ButtonPressFunc)(int8 action); // see FEOPTION_ACTIONs above + +struct FrontendOption +{ + int8 type; + int8 screenOptionOrder; + eMenuScreen screen; + const wchar* leftText; + ReturnPrevPageFunc returnPrevPageFunc; + + union { + // Only for dynamic + struct { + DrawFunc drawFunc; + ButtonPressFunc buttonPressFunc; + }; + + // Only for static/select + struct { + const wchar** rightTexts; + int8 numRightTexts; + int8 *value; + int8 displayedValue; // if onlyApplyOnEnter enabled + bool onlyApplyOnEnter; + ChangeFunc changeFunc; + }; + + // Only for redirect + struct { + eMenuScreen to; + int8 option; + bool fadeIn; + }; + }; +}; + +extern int numCustomFrontendOptions; +extern FrontendOption* customFrontendOptions; + +// To be used in ButtonPressFunc / ChangeFunc(but that would be weird): +void ChangeScreen(eMenuScreen screen, int option = 0, bool fadeIn = true); +void GoBack(bool fadeIn = true); + +// If option is positive number, all calls will increase it before using it (you can think it as cursor). -1 means before the back button, -2 is end of page +void FrontendOptionSetPosition(eMenuScreen screen, int8 option = -1); + +void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc); +void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc rightTextDrawFunc, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc); +void FrontendOptionAddRedirect(const wchar* text, eMenuScreen to, int8 selectedOption = 0, bool fadeIn = true); +void FrontendOptionAddBackButton(const wchar* text, bool fadeIn = true); +#endif \ No newline at end of file From 082c4caecfb542e93f5a9a942e51b555e0035279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Mon, 24 Aug 2020 22:42:26 +0300 Subject: [PATCH 2/2] new frontend customization --- src/core/Cam.cpp | 2 +- src/core/Frontend.cpp | 714 +++++++++++++++------------------- src/core/Frontend.h | 48 +-- src/core/MenuScreens.cpp | 92 +---- src/core/config.h | 2 +- src/core/re3.cpp | 276 +++++++++++-- src/extras/frontendoption.cpp | 243 +++++++++--- src/extras/frontendoption.h | 121 ++++-- 8 files changed, 856 insertions(+), 642 deletions(-) diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index fcffce9b..3e016667 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -30,7 +30,7 @@ bool PrintDebugCode = false; int16 DebugCamMode; #ifdef FREE_CAM -bool CCamera::bFreeCam; +bool CCamera::bFreeCam = false; int nPreviousMode = -1; #endif diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index d1196042..fbefe354 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -116,7 +116,6 @@ int32 CMenuManager::m_PrefsSfxVolume = 102; bool CMenuManager::m_PrefsCutsceneBorders = true; #endif - #ifdef MULTISAMPLING int8 CMenuManager::m_nPrefsMSAALevel = 0; int8 CMenuManager::m_nDisplayMSAALevel = 0; @@ -160,10 +159,6 @@ int32 MouseButtonJustClicked; int32 JoyButtonJustClicked; //int32 *pControlTemp = 0; -#ifdef PS2_ALPHA_TEST -extern bool gPS2alphaTest; -#endif - #ifndef MASTER bool CMenuManager::m_PrefsMarketing = false; bool CMenuManager::m_PrefsDisableTutorials = false; @@ -402,27 +397,40 @@ CMenuManager::PageDownList(bool playSoundOnSuccess) } } +#ifdef CUSTOM_FRONTEND_OPTIONS +bool ScreenHasOption(int screen, const char* gxtKey) +{ + for (int i = 0; i < NUM_MENUROWS; i++) { + if (strcmp(gxtKey, aScreens[screen].m_aEntries[i].m_EntryName) == 0) + return true; + } + return false; +} +#endif + void CMenuManager::ThingsToDoBeforeGoingBack() { if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && strcmp(m_aSkinName, m_PrefsSkinFile) != 0) { CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); +#ifdef CUSTOM_FRONTEND_OPTIONS + } else if (ScreenHasOption(m_nCurrScreen, "FEA_3DH")) { +#else } else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { +#endif if (m_nPrefsAudio3DProviderIndex != -1) m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); #ifdef TIDY_UP_PBP DMAudio.StopFrontEndTrack(); OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); #endif -#ifdef GRAPHICS_MENU_OPTIONS - } else if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { + +#ifdef CUSTOM_FRONTEND_OPTIONS + } else if (ScreenHasOption(m_nCurrScreen, "FED_RES")) { #else } else if (m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS) { #endif m_nDisplayVideoMode = m_nPrefsVideoMode; -#ifdef MULTISAMPLING - m_nDisplayMSAALevel = m_nPrefsMSAALevel; -#endif } if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { @@ -440,11 +448,22 @@ CMenuManager::ThingsToDoBeforeGoingBack() if (option.returnPrevPageFunc) option.returnPrevPageFunc(); - if (m_nCurrOption == option.screenOptionOrder && option.type == FEOPTION_DYNAMIC) - option.buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); + if (m_nCurrOption == option.screenOptionOrder && (option.type == FEOPTION_DYNAMIC || option.type == FEOPTION_BUILTIN_ACTION)) + if(option.buttonPressFunc) + option.buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); - if (option.onlyApplyOnEnter) - option.displayedValue = *option.value; + if (option.type == FEOPTION_SELECT && option.onlyApplyOnEnter && option.lastSavedValue != option.displayedValue) + option.displayedValue = *option.value = option.lastSavedValue; + } + } + + if (m_nCurrScreen > lastOgScreen) { + for (int i = 0; i < numCustomFrontendScreens; i++) { + FrontendScreen& screen = customFrontendScreens[i]; + if (m_nCurrScreen == screen.id && screen.returnPrevPageFunc) { + screen.returnPrevPageFunc(); + break; + } } } #endif @@ -464,7 +483,12 @@ CMenuManager::GetPreviousPageOption() prevPage = prevPage == MENUPAGE_NONE ? (!m_bGameNotLoaded ? MENUPAGE_PAUSE_MENU : MENUPAGE_START_MENU) : prevPage; for (int i = 0; i < NUM_MENUROWS; i++) { - if (aScreens[prevPage].m_aEntries[i].m_TargetMenu == m_nCurrScreen) { + if (aScreens[prevPage].m_aEntries[i].m_SaveSlot == SAVESLOT_CFO) { + FrontendOption &option = customFrontendOptions[aScreens[prevPage].m_aEntries[i].m_TargetMenu]; + if(option.type == FEOPTION_REDIRECT && option.to == m_nCurrScreen) { + return i; + } + } else if (aScreens[prevPage].m_aEntries[i].m_TargetMenu == m_nCurrScreen) { return i; } } @@ -879,9 +903,6 @@ CMenuManager::Draw() case MENUPAGE_CONTROLLER_PC_OLD4: case MENUPAGE_CONTROLLER_DEBUG: case MENUPAGE_MOUSE_CONTROLS: -#ifdef GRAPHICS_MENU_OPTIONS - case MENUPAGE_GRAPHICS_SETTINGS: -#endif columnWidth = 50; headerHeight = 0; lineHeight = 20; @@ -937,12 +958,43 @@ CMenuManager::Draw() break; #endif default: - columnWidth = 320; - headerHeight = 40; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - CFont::SetCentreOn(); +#ifdef CUSTOM_FRONTEND_OPTIONS + bool custom = m_nCurrScreen > lastOgScreen; + if (custom) { + for (int i = 0; i < numCustomFrontendScreens; i++) { + FrontendScreen& screen = customFrontendScreens[i]; + if (m_nCurrScreen == screen.id) { + columnWidth = screen.columnWidth; + headerHeight = screen.headerHeight; + lineHeight = screen.lineHeight; + CFont::SetFontStyle(FONT_LOCALE(screen.font)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = screen.fontScaleX), MENU_Y(MENU_TEXT_SIZE_Y = screen.fontScaleY)); + if (screen.alignment == FESCREEN_LEFT_ALIGN) { + CFont::SetCentreOff(); + CFont::SetRightJustifyOff(); + } else if (screen.alignment == FESCREEN_RIGHT_ALIGN) { + CFont::SetCentreOff(); + CFont::SetRightJustifyOn(); + } else { + CFont::SetRightJustifyOff(); + CFont::SetCentreOn(); + } + break; + } + if (i == numCustomFrontendScreens - 1) + custom = false; + } + } + if (!custom) +#endif + { + columnWidth = 320; + headerHeight = 40; + lineHeight = 24; + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); + CFont::SetCentreOn(); + } break; } @@ -1014,6 +1066,12 @@ CMenuManager::Draw() leftText = TheText.Get(gString); } } else { +#ifdef CUSTOM_FRONTEND_OPTIONS + if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot == SAVESLOT_CFO){ + FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu]; + leftText = (wchar*)option.leftText; + } else +#endif leftText = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName); } @@ -1180,40 +1238,21 @@ CMenuManager::Draw() AsciiToUnicode(_psGetVideoModeList()[m_nDisplayVideoMode], unicodeTemp); rightText = unicodeTemp; break; -#ifdef IMPROVED_VIDEOMODE - case MENUACTION_SCREENFORMAT: - rightText = TheText.Get(FrontEndMenuManager.m_nSelectedScreenMode ? "FED_WND" : "FED_FLS"); - break; -#endif -#ifdef MULTISAMPLING - case MENUACTION_MULTISAMPLING: - switch (m_nDisplayMSAALevel) { - case 0: - rightText = TheText.Get("FEM_OFF"); - break; - default: - sprintf(gString, "%iX", 1 << (m_nDisplayMSAALevel)); - AsciiToUnicode(gString, unicodeTemp); - rightText = unicodeTemp; - break; - } - break; -#endif -#ifdef NO_ISLAND_LOADING - case MENUACTION_ISLANDLOADING: - switch (m_DisplayIslandLoading) { - case ISLAND_LOADING_LOW: - rightText = TheText.Get("FEM_LOW"); - break; - case ISLAND_LOADING_MEDIUM: - rightText = TheText.Get("FEM_MED"); - break; - case ISLAND_LOADING_HIGH: - rightText = TheText.Get("FEM_HIG"); - break; - } - break; -#endif +//#ifdef NO_ISLAND_LOADING +// case MENUACTION_ISLANDLOADING: +// switch (m_DisplayIslandLoading) { +// case ISLAND_LOADING_LOW: +// rightText = TheText.Get("FEM_LOW"); +// break; +// case ISLAND_LOADING_MEDIUM: +// rightText = TheText.Get("FEM_MED"); +// break; +// case ISLAND_LOADING_HIGH: +// rightText = TheText.Get("FEM_HIG"); +// break; +// } +// break; +//#endif case MENUACTION_AUDIOHW: if (m_nPrefsAudio3DProviderIndex == -1) rightText = TheText.Get("FEA_NAH"); @@ -1264,22 +1303,15 @@ CMenuManager::Draw() case MENUACTION_MOUSESTEER: rightText = TheText.Get(CVehicle::m_bDisableMouseSteering ? "FEM_OFF" : "FEM_ON"); break; -#ifdef CUTSCENE_BORDERS_SWITCH - case MENUACTION_CUTSCENEBORDERS: - rightText = TheText.Get(m_PrefsCutsceneBorders ? "FEM_ON" : "FEM_OFF"); - break; -#endif -#ifdef PS2_ALPHA_TEST - case MENUACTION_PS2_ALPHA_TEST: - rightText = TheText.Get(gPS2alphaTest ? "FEM_ON" : "FEM_OFF"); - break; -#endif #ifdef CUSTOM_FRONTEND_OPTIONS case MENUACTION_TRIGGERFUNC: FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu]; if (m_nCurrScreen == option.screen && i == option.screenOptionOrder) { - leftText = (wchar*)option.leftText; if (option.type == FEOPTION_SELECT) { + // To whom manipulate option.value of static options externally (like RestoreDef functions) + if (*option.value != option.lastSavedValue) + option.displayedValue = option.lastSavedValue = *option.value; + if (option.displayedValue >= option.numRightTexts || option.displayedValue < 0) option.displayedValue = 0; @@ -1287,7 +1319,7 @@ CMenuManager::Draw() } else if (option.type == FEOPTION_DYNAMIC) { if (option.drawFunc) { - rightText = option.drawFunc(&isOptionDisabled); + rightText = option.drawFunc(&isOptionDisabled, m_nCurrOption == i); } } } else { @@ -1375,15 +1407,7 @@ CMenuManager::Draw() CFont::SetRightJustifyOn(); if(textLayer == 1) - if((!strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FED_RES") -#ifdef IMPROVED_VIDEOMODE - || !strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FEM_SCF") -#endif -#ifdef MULTISAMPLING - || !strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FED_AAS") -#endif - ) - && !m_bGameNotLoaded + if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FED_RES") && !m_bGameNotLoaded #ifdef CUSTOM_FRONTEND_OPTIONS || isOptionDisabled #endif @@ -1407,24 +1431,12 @@ CMenuManager::Draw() if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES") && m_nHelperTextMsgId == 1) ResetHelperText(); } -#ifdef IMPROVED_VIDEOMODE - if (m_nSelectedScreenMode == m_nPrefsWindowed) { - if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEM_SCF") && m_nHelperTextMsgId == 1) - ResetHelperText(); - } -#endif -#ifdef MULTISAMPLING - if (m_nDisplayMSAALevel == m_nPrefsMSAALevel) { - if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_AAS") && m_nHelperTextMsgId == 1) - ResetHelperText(); - } -#endif -#ifdef NO_ISLAND_LOADING - if (m_DisplayIslandLoading == m_PrefsIslandLoading) { - if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEM_ISL") && m_nHelperTextMsgId == 1) - ResetHelperText(); - } -#endif +//#ifdef NO_ISLAND_LOADING +// if (m_DisplayIslandLoading == m_PrefsIslandLoading) { +// if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEM_ISL") && m_nHelperTextMsgId == 1) +// ResetHelperText(); +// } +//#endif if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) { if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH")) SetHelperText(1); @@ -1433,27 +1445,19 @@ CMenuManager::Draw() if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES")) SetHelperText(1); } -#ifdef IMPROVED_VIDEOMODE - if (m_nSelectedScreenMode != m_nPrefsWindowed) { - if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEM_SCF")) - SetHelperText(1); - } -#endif -#ifdef MULTISAMPLING - if (m_nDisplayMSAALevel != m_nPrefsMSAALevel) { - if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_AAS")) - SetHelperText(1); - } -#endif -#ifdef NO_ISLAND_LOADING - if (m_DisplayIslandLoading != m_PrefsIslandLoading) { - if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEM_ISL")) - SetHelperText(1); - } -#endif +//#ifdef NO_ISLAND_LOADING +// if (m_DisplayIslandLoading != m_PrefsIslandLoading) { +// if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEM_ISL")) +// SetHelperText(1); +// } +//#endif if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) { if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") != 0 - && m_nCurrScreen == MENUPAGE_SOUND_SETTINGS && m_nPrefsAudio3DProviderIndex != -1) { + // To make assigning built-in actions to new custom options possible. +#ifndef CUSTOM_FRONTEND_OPTIONS + && m_nCurrScreen == MENUPAGE_SOUND_SETTINGS +#endif + && m_nPrefsAudio3DProviderIndex != -1) { m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); SetHelperText(3); @@ -1461,52 +1465,46 @@ CMenuManager::Draw() } if (m_nDisplayVideoMode != m_nPrefsVideoMode) { if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES") != 0 -#ifdef GRAPHICS_MENU_OPTIONS - && m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { + // To make assigning built-in actions to new custom options possible. +#ifdef CUSTOM_FRONTEND_OPTIONS + && ScreenHasOption(m_nCurrScreen, "FED_RES") #else - && m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS) { + && m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS #endif + ){ m_nDisplayVideoMode = m_nPrefsVideoMode; SetHelperText(3); } } -#ifdef IMPROVED_VIDEOMODE - if (m_nSelectedScreenMode != m_nPrefsWindowed) { - if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEM_SCF") != 0 -#ifdef GRAPHICS_MENU_OPTIONS - && m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { -#else - && m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS) { -#endif - m_nSelectedScreenMode = m_nPrefsWindowed; - SetHelperText(3); - } - } -#endif -#ifdef MULTISAMPLING - if (m_nSelectedScreenMode != m_nPrefsWindowed) { - if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_AAS") != 0 -#ifdef GRAPHICS_MENU_OPTIONS - && m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { -#else - && m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS) { -#endif - m_nDisplayMSAALevel = m_nPrefsMSAALevel; - SetHelperText(3); - } - } -#endif #ifdef CUSTOM_FRONTEND_OPTIONS - if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_TRIGGERFUNC) { + if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot == SAVESLOT_CFO) { FrontendOption &option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu]; - if (option.onlyApplyOnEnter && m_nCurrOption != i) - option.displayedValue = *option.value; + if (option.type == FEOPTION_SELECT) { + if (option.onlyApplyOnEnter){ + if (m_nCurrOption != i) { + if (option.displayedValue != option.lastSavedValue) + SetHelperText(3); // Restored original value + +// option.displayedValue = option.lastSavedValue = *option.value; + + } else { + if (option.displayedValue != *option.value) + SetHelperText(1); // Enter to apply + else if (m_nHelperTextMsgId == 1) + ResetHelperText(); // Applied + } + } + } if (m_nCurrOption != lastOption && lastOption == i) { FrontendOption &oldOption = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[lastOption].m_TargetMenu]; - if (oldOption.type == FEOPTION_DYNAMIC) - oldOption.buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); + if (oldOption.type == FEOPTION_DYNAMIC || oldOption.type == FEOPTION_BUILTIN_ACTION) + if(oldOption.buttonPressFunc) + oldOption.buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); + + if (oldOption.onlyApplyOnEnter && oldOption.type == FEOPTION_SELECT) + oldOption.displayedValue = oldOption.lastSavedValue = *oldOption.value; } } #endif @@ -1565,11 +1563,21 @@ CMenuManager::Draw() case MENUPAGE_SKIN_SELECT: case MENUPAGE_CONTROLLER_PC: case MENUPAGE_MOUSE_CONTROLS: -#ifdef GRAPHICS_MENU_OPTIONS - case MENUPAGE_GRAPHICS_SETTINGS: -#endif DisplayHelperText(); break; +#ifdef CUSTOM_FRONTEND_OPTIONS + default: + if (m_nCurrScreen > lastOgScreen) { + for (int i = 0; i < numCustomFrontendScreens; i++) { + FrontendScreen& screen = customFrontendScreens[i]; + if (m_nCurrScreen == screen.id && screen.showLeftRightHelper) { + DisplayHelperText(); + break; + } + } + } + break; +#endif } if (m_nCurrScreen == MENUPAGE_CONTROLLER_SETTINGS) @@ -2558,7 +2566,22 @@ CMenuManager::DrawFrontEndNormal() previousSprite = MENUSPRITE_PLAYERSET; break; default: - previousSprite = MENUSPRITE_MAINMENU; +#ifdef CUSTOM_FRONTEND_OPTIONS + bool custom = m_nPrevScreen > lastOgScreen; + if (custom) { + for (int i = 0; i < numCustomFrontendScreens; i++) { + FrontendScreen& screen = customFrontendScreens[i]; + if (m_nPrevScreen == screen.id) { + previousSprite = screen.sprite; + break; + } + if (i == numCustomFrontendScreens - 1) + custom = false; + } + } + if (!custom) +#endif + previousSprite = MENUSPRITE_MAINMENU; break; } @@ -2608,6 +2631,20 @@ CMenuManager::DrawFrontEndNormal() case MENUPAGE_OPTIONS: currentSprite = MENUSPRITE_PLAYERSET; break; +#ifdef CUSTOM_FRONTEND_OPTIONS + default: + bool custom = m_nCurrScreen > lastOgScreen; + if (custom) { + for (int i = 0; i < numCustomFrontendScreens; i++) { + FrontendScreen& screen = customFrontendScreens[i]; + if (m_nCurrScreen == screen.id) { + currentSprite = screen.sprite; + break; + } + } + } + break; +#endif } if (m_nMenuFadeAlpha < 255) { @@ -3368,23 +3405,19 @@ CMenuManager::LoadSettings() CFileMgr::Read(fileHandle, m_PrefsSkinFile, 256); CFileMgr::Read(fileHandle, (char*)&m_ControlMethod, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsLanguage, 1); -#ifdef FREE_CAM - CFileMgr::Read(fileHandle, (char*)&TheCamera.bFreeCam, 1); -#endif -#ifdef CUTSCENE_BORDERS_SWITCH - CFileMgr::Read(fileHandle, (char *)&CMenuManager::m_PrefsCutsceneBorders, 1); -#endif -#ifdef MULTISAMPLING - CFileMgr::Read(fileHandle, (char *)&m_nPrefsMSAALevel, 1); - m_nDisplayMSAALevel = m_nPrefsMSAALevel; +#ifdef CUSTOM_FRONTEND_OPTIONS + for (int i = 0; i < numCustomFrontendOptions; i++) { + FrontendOption& option = customFrontendOptions[i]; + if (option.save) { + CFileMgr::Read(fileHandle, (char*)option.value, 1); + option.lastSavedValue = option.displayedValue = *option.value; + } + } #endif #ifdef NO_ISLAND_LOADING CFileMgr::Read(fileHandle, (char *)&CMenuManager::m_PrefsIslandLoading, 1); CMenuManager::m_DisplayIslandLoading = CMenuManager::m_PrefsIslandLoading; #endif -#ifdef PS2_ALPHA_TEST - CFileMgr::Read(fileHandle, (char *)&gPS2alphaTest, 1); -#endif // PS2_ALPHA_TEST } } @@ -3475,21 +3508,17 @@ CMenuManager::SaveSettings() CFileMgr::Write(fileHandle, m_PrefsSkinFile, 256); CFileMgr::Write(fileHandle, (char*)&m_ControlMethod, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsLanguage, 1); -#ifdef FREE_CAM - CFileMgr::Write(fileHandle, (char*)&TheCamera.bFreeCam, 1); -#endif -#ifdef CUTSCENE_BORDERS_SWITCH - CFileMgr::Write(fileHandle, (char *)&CMenuManager::m_PrefsCutsceneBorders, 1); -#endif -#ifdef MULTISAMPLING - CFileMgr::Write(fileHandle, (char *)&CMenuManager::m_nPrefsMSAALevel, 1); +#ifdef CUSTOM_FRONTEND_OPTIONS + for (int i = 0; i < numCustomFrontendOptions; i++) { + FrontendOption &option = customFrontendOptions[i]; + if (option.save) { + CFileMgr::Write(fileHandle, (char*)option.value, 1); + } + } #endif #ifdef NO_ISLAND_LOADING CFileMgr::Write(fileHandle, (char *)&CMenuManager::m_PrefsIslandLoading, 1); #endif -#ifdef PS2_ALPHA_TEST - CFileMgr::Write(fileHandle, (char *)&gPS2alphaTest, 1); -#endif // PS2_ALPHA_TEST } CFileMgr::CloseFile(fileHandle); @@ -4808,65 +4837,45 @@ CMenuManager::ProcessButtonPresses(void) SaveSettings(); } break; -#ifdef IMPROVED_VIDEOMODE - case MENUACTION_SCREENFORMAT: - if (m_nSelectedScreenMode != m_nPrefsWindowed) { - m_nPrefsWindowed = m_nSelectedScreenMode; - _psSelectScreenVM(m_nPrefsVideoMode); - SetHelperText(0); - SaveSettings(); - } - break; -#endif -#ifdef MULTISAMPLING - case MENUACTION_MULTISAMPLING: - if (m_nDisplayMSAALevel != m_nPrefsMSAALevel) { - m_nPrefsMSAALevel = m_nDisplayMSAALevel; - _psSelectScreenVM(m_nPrefsVideoMode); - SetHelperText(0); - SaveSettings(); - } - break; -#endif -#ifdef NO_ISLAND_LOADING - case MENUACTION_ISLANDLOADING: - if (m_DisplayIslandLoading != m_PrefsIslandLoading) { - if (!m_bGameNotLoaded) { - if (m_DisplayIslandLoading > ISLAND_LOADING_LOW) { - if (m_DisplayIslandLoading == ISLAND_LOADING_HIGH) - CStreaming::RemoveIslandsNotUsed(LEVEL_GENERIC); - if (m_PrefsIslandLoading == ISLAND_LOADING_LOW) { - if (CGame::currLevel != LEVEL_INDUSTRIAL) - CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL); - if (CGame::currLevel != LEVEL_COMMERCIAL) - CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL); - if (CGame::currLevel != LEVEL_SUBURBAN) - CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN); - CCollision::bAlreadyLoaded = true; - m_PrefsIslandLoading = m_DisplayIslandLoading; - CStreaming::RequestBigBuildings(CGame::currLevel); - } else if (m_PrefsIslandLoading == ISLAND_LOADING_HIGH) { - m_PrefsIslandLoading = m_DisplayIslandLoading; - CStreaming::RequestIslands(CGame::currLevel); - } else - m_PrefsIslandLoading = m_DisplayIslandLoading; - } else { // low - m_PrefsIslandLoading = m_DisplayIslandLoading; - CCollision::bAlreadyLoaded = false; - CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); - CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); - CStreaming::RemoveUnusedBuildings(CGame::currLevel); - CStreaming::RequestIslands(CGame::currLevel); - } - - CStreaming::LoadAllRequestedModels(true); - } else - m_PrefsIslandLoading = m_DisplayIslandLoading; - SetHelperText(0); - SaveSettings(); - } - break; -#endif +//#ifdef NO_ISLAND_LOADING +// case MENUACTION_ISLANDLOADING: +// if (m_DisplayIslandLoading != m_PrefsIslandLoading) { +// if (!m_bGameNotLoaded) { +// if (m_DisplayIslandLoading > ISLAND_LOADING_LOW) { +// if (m_DisplayIslandLoading == ISLAND_LOADING_HIGH) +// CStreaming::RemoveIslandsNotUsed(LEVEL_GENERIC); +// if (m_PrefsIslandLoading == ISLAND_LOADING_LOW) { +// if (CGame::currLevel != LEVEL_INDUSTRIAL) +// CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL); +// if (CGame::currLevel != LEVEL_COMMERCIAL) +// CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL); +// if (CGame::currLevel != LEVEL_SUBURBAN) +// CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN); +// CCollision::bAlreadyLoaded = true; +// m_PrefsIslandLoading = m_DisplayIslandLoading; +// CStreaming::RequestBigBuildings(CGame::currLevel); +// } else if (m_PrefsIslandLoading == ISLAND_LOADING_HIGH) { +// m_PrefsIslandLoading = m_DisplayIslandLoading; +// CStreaming::RequestIslands(CGame::currLevel); +// } else +// m_PrefsIslandLoading = m_DisplayIslandLoading; +// } else { // low +// m_PrefsIslandLoading = m_DisplayIslandLoading; +// CCollision::bAlreadyLoaded = false; +// CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); +// CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); +// CStreaming::RemoveUnusedBuildings(CGame::currLevel); +// CStreaming::RequestIslands(CGame::currLevel); +// } +// +// CStreaming::LoadAllRequestedModels(true); +// } else +// m_PrefsIslandLoading = m_DisplayIslandLoading; +// SetHelperText(0); +// SaveSettings(); +// } +// break; +//#endif case MENUACTION_AUDIOHW: { int selectedProvider = m_nPrefsAudio3DProviderIndex; @@ -4913,7 +4922,6 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.SetRadioInCar(m_PrefsRadioStation); DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); SaveSettings(); -#ifndef GRAPHICS_MENU_OPTIONS } else if (m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS) { m_PrefsFrameLimiter = true; m_PrefsBrightness = 256; @@ -4928,121 +4936,55 @@ CMenuManager::ProcessButtonPresses(void) if (_dwOperatingSystemVersion == OS_WIN98) { CMBlur::BlurOn = false; CMBlur::MotionBlurClose(); - } - else { + } else { CMBlur::BlurOn = true; CMBlur::MotionBlurOpen(Scene.camera); } #else CMBlur::BlurOn = true; #endif -#ifdef CUTSCENE_BORDERS_SWITCH - m_PrefsCutsceneBorders = true; -#endif -#ifdef NO_ISLAND_LOADING - m_DisplayIslandLoading = ISLAND_LOADING_LOW; - if (!m_bGameNotLoaded) { - if (m_DisplayIslandLoading > ISLAND_LOADING_LOW) { - if (m_DisplayIslandLoading == ISLAND_LOADING_HIGH) - CStreaming::RemoveIslandsNotUsed(LEVEL_GENERIC); - if (m_PrefsIslandLoading == ISLAND_LOADING_LOW) { - if (CGame::currLevel != LEVEL_INDUSTRIAL) - CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL); - if (CGame::currLevel != LEVEL_COMMERCIAL) - CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL); - if (CGame::currLevel != LEVEL_SUBURBAN) - CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN); - CCollision::bAlreadyLoaded = true; - m_PrefsIslandLoading = m_DisplayIslandLoading; - CStreaming::RequestBigBuildings(CGame::currLevel); - } else if (m_PrefsIslandLoading == ISLAND_LOADING_HIGH) { - m_PrefsIslandLoading = m_DisplayIslandLoading; - CStreaming::RequestIslands(CGame::currLevel); - } else - m_PrefsIslandLoading = m_DisplayIslandLoading; - } else { // low - m_PrefsIslandLoading = m_DisplayIslandLoading; - CCollision::bAlreadyLoaded = false; - CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); - CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); - CStreaming::RemoveUnusedBuildings(CGame::currLevel); - CStreaming::RequestIslands(CGame::currLevel); - } +#ifdef CUSTOM_FRONTEND_OPTIONS + extern void RestoreDefGraphics(int8); + extern void RestoreDefDisplay(int8); - CStreaming::LoadAllRequestedModels(true); - } else - m_PrefsIslandLoading = m_DisplayIslandLoading; -#endif // NO_ISLAND_LOADING -#ifdef PS2_ALPHA_TEST - gPS2alphaTest = false; -#endif // PS2_ALPHA_TEST + RestoreDefGraphics(FEOPTION_ACTION_SELECT); + RestoreDefDisplay(FEOPTION_ACTION_SELECT); +#endif +//#ifdef NO_ISLAND_LOADING +// m_DisplayIslandLoading = ISLAND_LOADING_LOW; +// if (!m_bGameNotLoaded) { +// if (m_DisplayIslandLoading > ISLAND_LOADING_LOW) { +// if (m_DisplayIslandLoading == ISLAND_LOADING_HIGH) +// CStreaming::RemoveIslandsNotUsed(LEVEL_GENERIC); +// if (m_PrefsIslandLoading == ISLAND_LOADING_LOW) { +// if (CGame::currLevel != LEVEL_INDUSTRIAL) +// CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL); +// if (CGame::currLevel != LEVEL_COMMERCIAL) +// CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL); +// if (CGame::currLevel != LEVEL_SUBURBAN) +// CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN); +// CCollision::bAlreadyLoaded = true; +// m_PrefsIslandLoading = m_DisplayIslandLoading; +// CStreaming::RequestBigBuildings(CGame::currLevel); +// } else if (m_PrefsIslandLoading == ISLAND_LOADING_HIGH) { +// m_PrefsIslandLoading = m_DisplayIslandLoading; +// CStreaming::RequestIslands(CGame::currLevel); +// } else +// m_PrefsIslandLoading = m_DisplayIslandLoading; +// } else { // low +// m_PrefsIslandLoading = m_DisplayIslandLoading; +// CCollision::bAlreadyLoaded = false; +// CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); +// CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); +// CStreaming::RemoveUnusedBuildings(CGame::currLevel); +// CStreaming::RequestIslands(CGame::currLevel); +// } +// +// CStreaming::LoadAllRequestedModels(true); +// } else +// m_PrefsIslandLoading = m_DisplayIslandLoading; +//#endif // NO_ISLAND_LOADING SaveSettings(); -#else - } else if (m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS) { - m_PrefsBrightness = 256; - m_PrefsShowSubtitles = true; -#ifdef CUTSCENE_BORDERS_SWITCH - m_PrefsCutsceneBorders = true; -#endif - SaveSettings(); - } else if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { - m_PrefsFrameLimiter = true; - m_PrefsUseWideScreen = false; - m_PrefsVsyncDisp = true; - m_PrefsLOD = 1.2f; - m_PrefsVsync = true; - CRenderer::ms_lodDistScale = 1.2f; - m_nDisplayVideoMode = m_nPrefsVideoMode; -#ifdef GTA3_1_1_PATCH - if (_dwOperatingSystemVersion == OS_WIN98) { - CMBlur::BlurOn = false; - CMBlur::MotionBlurClose(); - } else { - CMBlur::BlurOn = true; - CMBlur::MotionBlurOpen(Scene.camera); - } -#else - CMBlur::BlurOn = true; -#endif // GTA3_1_1_PATCH -#ifdef NO_ISLAND_LOADING - m_DisplayIslandLoading = ISLAND_LOADING_LOW; - if (!m_bGameNotLoaded) { - if (m_DisplayIslandLoading > ISLAND_LOADING_LOW) { - if (m_DisplayIslandLoading == ISLAND_LOADING_HIGH) - CStreaming::RemoveIslandsNotUsed(LEVEL_GENERIC); - if (m_PrefsIslandLoading == ISLAND_LOADING_LOW) { - if (CGame::currLevel != LEVEL_INDUSTRIAL) - CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL); - if (CGame::currLevel != LEVEL_COMMERCIAL) - CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL); - if (CGame::currLevel != LEVEL_SUBURBAN) - CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN); - CCollision::bAlreadyLoaded = true; - m_PrefsIslandLoading = m_DisplayIslandLoading; - CStreaming::RequestBigBuildings(CGame::currLevel); - } else if (m_PrefsIslandLoading == ISLAND_LOADING_HIGH) { - m_PrefsIslandLoading = m_DisplayIslandLoading; - CStreaming::RequestIslands(CGame::currLevel); - } else - m_PrefsIslandLoading = m_DisplayIslandLoading; - } else { // low - m_PrefsIslandLoading = m_DisplayIslandLoading; - CCollision::bAlreadyLoaded = false; - CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); - CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); - CStreaming::RemoveUnusedBuildings(CGame::currLevel); - CStreaming::RequestIslands(CGame::currLevel); - } - - CStreaming::LoadAllRequestedModels(true); - } else - m_PrefsIslandLoading = m_DisplayIslandLoading; -#endif // NO_ISLAND_LOADING -#ifdef PS2_ALPHA_TEST - gPS2alphaTest = false; -#endif // PS2_ALPHA_TEST - SaveSettings(); -#endif // GRAPHICS_MENU_OPTIONS } else if ((m_nCurrScreen != MENUPAGE_SKIN_SELECT_OLD) && (m_nCurrScreen == MENUPAGE_CONTROLLER_PC)) { ControlsManager.MakeControllerActionsBlank(); ControlsManager.InitDefaultControlConfiguration(); @@ -5112,7 +5054,7 @@ CMenuManager::ProcessButtonPresses(void) option.displayedValue = 0; } option.changeFunc(option.displayedValue); - *option.value = option.displayedValue; + *option.value = option.lastSavedValue = option.displayedValue; } else if (option.type == FEOPTION_DYNAMIC) { option.buttonPressFunc(FEOPTION_ACTION_SELECT); @@ -5131,6 +5073,14 @@ CMenuManager::ProcessButtonPresses(void) } } ProcessOnOffMenuOptions(); +#ifdef CUSTOM_FRONTEND_OPTIONS + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot == SAVESLOT_CFO) { + FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu]; + if (option.type == FEOPTION_BUILTIN_ACTION && option.buttonPressFunc) { + option.buttonPressFunc(FEOPTION_ACTION_SELECT); + } + } +#endif } if (goBack) { @@ -5301,41 +5251,15 @@ CMenuManager::ProcessButtonPresses(void) } } break; -#ifdef IMPROVED_VIDEOMODE - case MENUACTION_SCREENFORMAT: - if (m_bGameNotLoaded) { - FrontEndMenuManager.m_nSelectedScreenMode = !FrontEndMenuManager.m_nSelectedScreenMode; - } - break; -#endif -#ifdef MULTISAMPLING - case MENUACTION_MULTISAMPLING: - if (m_bGameNotLoaded) { - m_nDisplayMSAALevel += changeValueBy; - - int i = 0; - int maxAA = RwD3D8EngineGetMaxMultiSamplingLevels(); - while (maxAA != 1) { - i++; - maxAA >>= 1; - } - - if (m_nDisplayMSAALevel < 0) - m_nDisplayMSAALevel = i; - else if (m_nDisplayMSAALevel > i) - m_nDisplayMSAALevel = 0; - } - break; -#endif -#ifdef NO_ISLAND_LOADING - case MENUACTION_ISLANDLOADING: - m_DisplayIslandLoading += changeValueBy; - if (m_DisplayIslandLoading > ISLAND_LOADING_HIGH) - m_DisplayIslandLoading = ISLAND_LOADING_LOW; - else if (m_DisplayIslandLoading < ISLAND_LOADING_LOW) - m_DisplayIslandLoading = ISLAND_LOADING_HIGH; - break; -#endif +//#ifdef NO_ISLAND_LOADING +// case MENUACTION_ISLANDLOADING: +// m_DisplayIslandLoading += changeValueBy; +// if (m_DisplayIslandLoading > ISLAND_LOADING_HIGH) +// m_DisplayIslandLoading = ISLAND_LOADING_LOW; +// else if (m_DisplayIslandLoading < ISLAND_LOADING_LOW) +// m_DisplayIslandLoading = ISLAND_LOADING_HIGH; +// break; +//#endif case MENUACTION_AUDIOHW: if (m_nPrefsAudio3DProviderIndex != -1) { m_nPrefsAudio3DProviderIndex += changeValueBy; @@ -5374,7 +5298,7 @@ CMenuManager::ProcessButtonPresses(void) } if (!option.onlyApplyOnEnter) { option.changeFunc(option.displayedValue); - *option.value = option.displayedValue; + *option.value = option.lastSavedValue = option.displayedValue; } } else if (option.type == FEOPTION_DYNAMIC) { option.buttonPressFunc(changeValueBy > 0 ? FEOPTION_ACTION_RIGHT : FEOPTION_ACTION_LEFT); @@ -5501,20 +5425,6 @@ CMenuManager::ProcessOnOffMenuOptions() DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); SaveSettings(); break; -#ifdef CUTSCENE_BORDERS_SWITCH - case MENUACTION_CUTSCENEBORDERS: - m_PrefsCutsceneBorders = !m_PrefsCutsceneBorders; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - SaveSettings(); - break; -#endif -#ifdef PS2_ALPHA_TEST - case MENUACTION_PS2_ALPHA_TEST: - gPS2alphaTest = !gPS2alphaTest; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - SaveSettings(); - break; -#endif } } @@ -6354,20 +6264,6 @@ CMenuManager::ConstructStatLine(int rowIdx) #undef STAT_LINE } -#if 0 -uint8 CMenuManager::GetNumberOfMenuOptions() -{ - uint8 Rows = -1; - for (int i = 0; i < NUM_MENUROWS; i++) { - if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_NOTHING) - break; - - ++Rows; - } - return Rows; -} -#endif - #undef GetBackJustUp #undef GetBackJustDown #undef ChangeScreen diff --git a/src/core/Frontend.h b/src/core/Frontend.h index fa3652a1..848148e7 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -155,7 +155,10 @@ enum eSaveSlot SAVESLOT_6, SAVESLOT_7, SAVESLOT_8, - SAVESLOT_LABEL = 36 + SAVESLOT_LABEL = 36, +#ifdef CUSTOM_FRONTEND_OPTIONS + SAVESLOT_CFO +#endif }; #ifdef MENU_MAP @@ -235,14 +238,15 @@ enum eMenuScreen MENUPAGE_KEYBOARD_CONTROLS = 55, MENUPAGE_MOUSE_CONTROLS = 56, MENUPAGE_MISSION_RETRY = 57, - MENUPAGE_58 = 58, #ifdef MENU_MAP - MENUPAGE_MAP = 59, -#endif -#ifdef GRAPHICS_MENU_OPTIONS - MENUPAGE_GRAPHICS_SETTINGS, + MENUPAGE_MAP, #endif + MENUPAGE_UNK, // 58 in game. Map page is added above, because last screen in CMenuScreens should always be empty to make CFO work +#ifdef CUSTOM_FRONTEND_OPTIONS + MENUPAGES = 65 // for some room to add more screen +#else MENUPAGES +#endif }; enum eMenuAction @@ -362,25 +366,13 @@ enum eMenuAction MENUACTION_UNK112, MENUACTION_REJECT_RETRY, MENUACTION_UNK114, -#ifdef IMPROVED_VIDEOMODE - MENUACTION_SCREENFORMAT, -#endif -#ifdef ANISOTROPIC_FILTERING - MENUACTION_MIPMAPS, - MENUACTION_TEXTURE_FILTERING, -#endif -#ifdef MULTISAMPLING - MENUACTION_MULTISAMPLING, -#endif -#ifdef NO_ISLAND_LOADING - MENUACTION_ISLANDLOADING, -#endif -#ifdef PS2_ALPHA_TEST - MENUACTION_PS2_ALPHA_TEST, -#endif -#ifdef CUTSCENE_BORDERS_SWITCH - MENUACTION_CUTSCENEBORDERS, -#endif +//#ifdef ANISOTROPIC_FILTERING +// MENUACTION_MIPMAPS, +// MENUACTION_TEXTURE_FILTERING, +//#endif +//#ifdef NO_ISLAND_LOADING +// MENUACTION_ISLANDLOADING, +//#endif #ifdef CUSTOM_FRONTEND_OPTIONS MENUACTION_TRIGGERFUNC #endif @@ -469,7 +461,7 @@ struct BottomBarOption struct CMenuScreen { char m_ScreenName[8]; - int32 unk; // 2 on MENUPAGE_MULTIPLAYER_START, 1 on everywhere else + int32 unk; // 2 on MENUPAGE_MULTIPLAYER_START, 1 on everywhere else, 0 on unused. int32 m_PreviousPage[2]; // eMenuScreen int32 m_ParentEntry[2]; // row @@ -704,8 +696,6 @@ public: void PageUpList(bool); void PageDownList(bool); int8 GetPreviousPageOption(); - - // uint8 GetNumberOfMenuOptions(); }; #ifndef IMPROVED_VIDEOMODE @@ -713,6 +703,6 @@ VALIDATE_SIZE(CMenuManager, 0x564); #endif extern CMenuManager FrontEndMenuManager; -extern CMenuScreen aScreens[]; +extern CMenuScreen aScreens[MENUPAGES]; #endif \ No newline at end of file diff --git a/src/core/MenuScreens.cpp b/src/core/MenuScreens.cpp index 02c004b3..533fc755 100644 --- a/src/core/MenuScreens.cpp +++ b/src/core/MenuScreens.cpp @@ -4,45 +4,7 @@ // If you want to add new options, please don't do that here and see CustomFrontendOptionsPopulate in re3.cpp. -#ifdef CUTSCENE_BORDERS_SWITCH -#define MENU_CUTSCENE_BORDERS_SWITCH(screen) MENUACTION_CUTSCENEBORDERS, "FEM_CSB", SAVESLOT_NONE, screen, -#else -#define MENU_CUTSCENE_BORDERS_SWITCH(screen) -#endif - -#ifdef IMPROVED_VIDEOMODE -#define MENU_IMPROVED_VIDEOMODE(screen) MENUACTION_SCREENFORMAT, "FEM_SCF", SAVESLOT_NONE, screen, -#else -#define MENU_IMPROVED_VIDEOMODE(screen) -#endif - -#ifdef ANISOTROPIC_FILTERING -#define MENU_MIPMAPS(screen) MENUACTION_MIPMAPS, "FED_MIP", SAVESLOT_NONE, screen, -#define MENU_TEXTURE_FILTERING(screen) MENUACTION_TEXTURE_FILTERING, "FED_FIL", SAVESLOT_NONE, screen, -#else -#define MENU_MIPMAPS(screen) -#define MENU_TEXTURE_FILTERING(screen) -#endif - -#ifdef MULTISAMPLING -#define MENU_MULTISAMPLING(screen) MENUACTION_MULTISAMPLING, "FED_AAS", SAVESLOT_NONE, screen, -#else -#define MENU_MULTISAMPLING(screen) -#endif - -#ifdef NO_ISLAND_LOADING -#define MENU_ISLAND_LOADING(screen) MENUACTION_ISLANDLOADING, "FEM_ISL", SAVESLOT_NONE, screen, -#else -#define MENU_ISLAND_LOADING(screen) -#endif - -#ifdef PS2_ALPHA_TEST -#define MENU_PS2_ALPHA_TEST(screen) MENUACTION_PS2_ALPHA_TEST, "FEM_2PR", SAVESLOT_NONE, screen, -#else -#define MENU_PS2_ALPHA_TEST(screen) -#endif - -CMenuScreen aScreens[] = { +CMenuScreen aScreens[MENUPAGES] = { // MENUPAGE_NONE = 0 { "", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, }, @@ -85,7 +47,6 @@ CMenuScreen aScreens[] = { }, // MENUPAGE_DISPLAY_SETTINGS = 6 -#ifndef GRAPHICS_MENU_OPTIONS { "FET_DIS", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 2, 2, MENUACTION_BRIGHTNESS, "FED_BRI", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, MENUACTION_DRAWDIST, "FEM_LOD", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, @@ -93,28 +54,11 @@ CMenuScreen aScreens[] = { MENUACTION_FRAMELIMIT, "FEM_FRM", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, MENUACTION_TRAILS, "FED_TRA", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, MENUACTION_SUBTITLES, "FED_SUB", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, - MENU_CUTSCENE_BORDERS_SWITCH(MENUPAGE_DISPLAY_SETTINGS) - MENU_MIPMAPS(MENUPAGE_DISPLAY_SETTINGS) - MENU_TEXTURE_FILTERING(MENUPAGE_DISPLAY_SETTINGS) - MENU_ISLAND_LOADING(MENUPAGE_DISPLAY_SETTINGS) - MENU_PS2_ALPHA_TEST(MENUPAGE_DISPLAY_SETTINGS) - MENU_MULTISAMPLING(MENUPAGE_DISPLAY_SETTINGS) MENUACTION_WIDESCREEN, "FED_WIS", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, - MENU_IMPROVED_VIDEOMODE(MENUPAGE_DISPLAY_SETTINGS) MENUACTION_SCREENRES, "FED_RES", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, }, -#else - { "FET_DIS", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 2, 2, - MENUACTION_BRIGHTNESS, "FED_BRI", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, - MENUACTION_SUBTITLES, "FED_SUB", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, - MENU_CUTSCENE_BORDERS_SWITCH(MENUPAGE_DISPLAY_SETTINGS) - MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, -#endif // GRAPHICS_MENU_OPTIONS - // MENUPAGE_LANGUAGE_SETTINGS = 7 { "FET_LAN", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 3, 3, @@ -379,9 +323,6 @@ CMenuScreen aScreens[] = { MENUACTION_CHANGEMENU, "FET_CTL", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, MENUACTION_LOADRADIO, "FET_AUD", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, MENUACTION_CHANGEMENU, "FET_DIS", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, -#ifdef GRAPHICS_MENU_OPTIONS - MENUACTION_CHANGEMENU, "FET_GRA", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, -#endif MENUACTION_CHANGEMENU, "FET_LAN", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, MENUACTION_PLAYERSETUP, "FET_PSU", SAVESLOT_NONE, MENUPAGE_SKIN_SELECT, MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, @@ -493,38 +434,19 @@ CMenuScreen aScreens[] = { }, #endif - // MENUPAGE_58 = 58 - { "", 0, MENUPAGE_NONE, MENUPAGE_NONE, 0, 0, - - }, - #ifdef MENU_MAP - // MENUPAGE_MAP = 59 + // MENUPAGE_MAP { "FEG_MAP", 1, MENUPAGE_NONE, MENUPAGE_NONE, 5, 2, MENUACTION_UNK110, "", SAVESLOT_NONE, MENUPAGE_NONE, // to prevent cross/enter to go back MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, }, #endif -#ifdef GRAPHICS_MENU_OPTIONS - // MENUPAGE_GRAPHICS_SETTINGS = 60 - { "FET_GRA", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 2, 2, - MENUACTION_DRAWDIST, "FEM_LOD", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, - MENUACTION_FRAMESYNC, "FEM_VSC", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, - MENUACTION_FRAMELIMIT, "FEM_FRM", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, - MENUACTION_TRAILS, "FED_TRA", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, - MENUACTION_WIDESCREEN, "FED_WIS", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, - MENU_MIPMAPS(MENUPAGE_GRAPHICS_SETTINGS) - MENU_TEXTURE_FILTERING(MENUPAGE_GRAPHICS_SETTINGS) - MENU_ISLAND_LOADING(MENUPAGE_GRAPHICS_SETTINGS) - MENU_PS2_ALPHA_TEST(MENUPAGE_GRAPHICS_SETTINGS) - MENU_MULTISAMPLING(MENUPAGE_GRAPHICS_SETTINGS) - MENU_IMPROVED_VIDEOMODE(MENUPAGE_GRAPHICS_SETTINGS) - MENUACTION_SCREENRES, "FED_RES", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, - MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, -#endif + // MENUPAGE_UNK + { "", 0, MENUPAGE_NONE, MENUPAGE_NONE, 0, 0, + + }, + }; #endif \ No newline at end of file diff --git a/src/core/config.h b/src/core/config.h index b0d89fac..498be8f3 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -250,7 +250,7 @@ enum Config { # define TRIANGLE_BACK_BUTTON //# define CIRCLE_BACK_BUTTON # define CUSTOM_FRONTEND_OPTIONS -# define GRAPHICS_MENU_OPTIONS +# define GRAPHICS_MENU_OPTIONS // otherwise Advanced Options menu will appear if Display is full #endif // Script diff --git a/src/core/re3.cpp b/src/core/re3.cpp index dd116e27..2922f73e 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -74,12 +74,124 @@ mysrand(unsigned int seed) #ifdef CUSTOM_FRONTEND_OPTIONS #include "frontendoption.h" #include "platform.h" +#include "Font.h" void ReloadFrontendOptions(void) { CustomFrontendOptionsPopulate(); } +void RestoreDefGraphics(int8 action) { + if (action != FEOPTION_ACTION_SELECT) + return; + + #ifdef PS2_ALPHA_TEST + gPS2alphaTest = false; + #endif + #ifdef MULTISAMPLING + FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel = 0; + #endif + #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those + CMenuManager::m_PrefsFrameLimiter = true; + CMenuManager::m_PrefsVsyncDisp = true; + CMenuManager::m_PrefsVsync = true; + CMenuManager::m_PrefsUseWideScreen = false; + FrontEndMenuManager.m_nDisplayVideoMode = FrontEndMenuManager.m_nPrefsVideoMode; + #ifdef GTA3_1_1_PATCH + if (_dwOperatingSystemVersion == OS_WIN98) { + CMBlur::BlurOn = false; + CMBlur::MotionBlurClose(); + } else { + CMBlur::BlurOn = true; + CMBlur::MotionBlurOpen(Scene.camera); + } + #else + CMBlur::BlurOn = true; + #endif + FrontEndMenuManager.SaveSettings(); + #endif +} + +void RestoreDefDisplay(int8 action) { + if (action != FEOPTION_ACTION_SELECT) + return; + + #ifdef CUTSCENE_BORDERS_SWITCH + CMenuManager::m_PrefsCutsceneBorders = true; + #endif + #ifdef FREE_CAM + TheCamera.bFreeCam = false; + #endif + #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those + CMenuManager::m_PrefsBrightness = 256; + CMenuManager::m_PrefsLOD = 1.2f; + CRenderer::ms_lodDistScale = 1.2f; + CMenuManager::m_PrefsShowSubtitles = true; + FrontEndMenuManager.SaveSettings(); + #endif +} + +#ifdef MULTISAMPLING +void MultiSamplingGoBack() { + FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel; +} + +void MultiSamplingButtonPress(int8 action) { + if (action == FEOPTION_ACTION_SELECT) { + if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) { + FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel; + _psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode); + FrontEndMenuManager.SetHelperText(0); + FrontEndMenuManager.SaveSettings(); + } + } else if (action == FEOPTION_ACTION_LEFT || action == FEOPTION_ACTION_RIGHT) { + if (FrontEndMenuManager.m_bGameNotLoaded) { + FrontEndMenuManager.m_nDisplayMSAALevel += (action == FEOPTION_ACTION_RIGHT ? 1 : -1); + + int i = 0; + int maxAA = RwD3D8EngineGetMaxMultiSamplingLevels(); + while (maxAA != 1) { + i++; + maxAA >>= 1; + } + + if (FrontEndMenuManager.m_nDisplayMSAALevel < 0) + FrontEndMenuManager.m_nDisplayMSAALevel = i; + else if (FrontEndMenuManager.m_nDisplayMSAALevel > i) + FrontEndMenuManager.m_nDisplayMSAALevel = 0; + } + } else if (action == FEOPTION_ACTION_FOCUSLOSS) { + if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) { + FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel; + FrontEndMenuManager.SetHelperText(3); + } + } +} + +wchar* MultiSamplingDraw(bool *disabled, bool userHovering) { + static wchar unicodeTemp[64]; + if (userHovering) { + if (FrontEndMenuManager.m_nDisplayMSAALevel == FrontEndMenuManager.m_nPrefsMSAALevel) { + if (FrontEndMenuManager.m_nHelperTextMsgId == 1) // Press enter to apply + FrontEndMenuManager.ResetHelperText(); + } else { + FrontEndMenuManager.SetHelperText(1); + } + } + if (!FrontEndMenuManager.m_bGameNotLoaded) + *disabled = true; + + switch (FrontEndMenuManager.m_nDisplayMSAALevel) { + case 0: + return TheText.Get("FEM_OFF"); + default: + sprintf(gString, "%iX", 1 << (FrontEndMenuManager.m_nDisplayMSAALevel)); + AsciiToUnicode(gString, unicodeTemp); + return unicodeTemp; + } +} +#endif + #ifdef MORE_LANGUAGES void LangPolSelect(int8 action) { @@ -112,7 +224,7 @@ void LangJapSelect(int8 action) } #endif -/*#ifdef IMPROVED_VIDEOMODE +#ifdef IMPROVED_VIDEOMODE void ScreenModeChange(int8 displayedValue) { if (displayedValue != FrontEndMenuManager.m_nPrefsWindowed) { @@ -122,61 +234,155 @@ void ScreenModeChange(int8 displayedValue) FrontEndMenuManager.SaveSettings(); } } -#endif*/ +#endif #ifdef FREE_CAM -void ToggleFreeCam(int8 action) +void FreeCamChange(int8 displayedValue) { - if (action == FEOPTION_ACTION_SELECT) { - TheCamera.bFreeCam = !TheCamera.bFreeCam; - FrontEndMenuManager.SaveSettings(); - } + TheCamera.bFreeCam = !!displayedValue; + FrontEndMenuManager.SaveSettings(); } #endif -//#ifdef CUTSCENE_BORDERS_SWITCH -//void BorderModeChange(int8 displayedValue) -//{ -// CMenuManager::m_PrefsCutsceneBorders = !!displayedValue; -// FrontEndMenuManager.SaveSettings(); -//} -//#endif +#ifdef CUTSCENE_BORDERS_SWITCH +void BorderModeChange(int8 displayedValue) +{ + CMenuManager::m_PrefsCutsceneBorders = !!displayedValue; + FrontEndMenuManager.SaveSettings(); +} +#endif -// Reloaded on language change, so you can use hardcoded wchar* and TheText.Get with peace of mind +#ifdef PS2_ALPHA_TEST +void PS2AlphaTestChange(int8 displayedValue) +{ + gPS2alphaTest = !!displayedValue; + FrontEndMenuManager.SaveSettings(); +} +#endif + + +// Important: Make sure to read the warnings/informations in frontendoption.h!! void CustomFrontendOptionsPopulate(void) { RemoveCustomFrontendOptions(); // if exist + // -- Graphics/display seperation preperation starts - don't add options in here! +#ifdef GRAPHICS_MENU_OPTIONS + int graphicsMenu = FrontendScreenAdd("FET_GRA", MENUSPRITE_MAINMENU, MENUPAGE_OPTIONS, 50, 0, 20, + FONT_HEADING, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, true); + + int newDisplayMenu = FrontendScreenAdd("FET_DIS", MENUSPRITE_MAINMENU, MENUPAGE_OPTIONS, 50, 0, 20, + FONT_HEADING, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, true); + + FrontendOptionSetCursor(MENUPAGE_OPTIONS, 2, true); + FrontendOptionAddRedirect(TheText.Get("FET_DIS"), newDisplayMenu, 0); + FrontendOptionSetCursor(MENUPAGE_OPTIONS, 3); + FrontendOptionAddRedirect(TheText.Get("FET_GRA"), graphicsMenu, 0); + +#define SWITCH_TO_GRAPHICS_MENU FrontendOptionSetCursor(graphicsMenu, -1); +#define SWITCH_TO_DISPLAY_MENU FrontendOptionSetCursor(newDisplayMenu, -1); +#define CLONE_OPTION(a, b, c, d) FrontendOptionAddBuiltinAction(a, b, c, d); +#define ADD_BACK FrontendOptionAddBackButton(TheText.Get("FEDS_TB")); +#define ADD_RESTORE_DEFAULTS(a) FrontendOptionAddDynamic(TheText.Get("FET_DEF"), nil, nil, a, nil); +#else + int advancedDisplayMenu = FrontendScreenAdd("FET_ADV", MENUSPRITE_MAINMENU, MENUPAGE_DISPLAY_SETTINGS, 50, 0, 20, + FONT_HEADING, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, true); + bool movedToAdvMenu = false; + +#define SWITCH_TO_GRAPHICS_MENU \ + if (GetNumberOfMenuOptions(MENUPAGE_DISPLAY_SETTINGS) >= 12) { \ + FrontendOptionSetCursor(advancedDisplayMenu, -1); \ + movedToAdvMenu = true; \ + } else { \ + FrontendOptionSetCursor(MENUPAGE_DISPLAY_SETTINGS, -3); \ + } + +#define SWITCH_TO_DISPLAY_MENU SWITCH_TO_GRAPHICS_MENU +#define CLONE_OPTION(a, b, c, d) +#define ADD_BACK +#define ADD_RESTORE_DEFAULTS(a) +#endif + // -- Graphics/display seperation preperation end + + static const wchar* off_on[] = { TheText.Get("FEM_OFF"), TheText.Get("FEM_ON") }; + #ifdef MORE_LANGUAGES - FrontendOptionSetPosition(MENUPAGE_LANGUAGE_SETTINGS); - FrontendOptionAddDynamic(TheText.Get("FEL_POL"), nil, LangPolSelect, nil); - FrontendOptionAddDynamic(TheText.Get("FEL_RUS"), nil, LangRusSelect, nil); - FrontendOptionAddDynamic(TheText.Get("FEL_JAP"), nil, LangJapSelect, nil); + FrontendOptionSetCursor(MENUPAGE_LANGUAGE_SETTINGS, -2); + FrontendOptionAddDynamic(TheText.Get("FEL_POL"), nil, nil, LangPolSelect, nil); + FrontendOptionAddDynamic(TheText.Get("FEL_RUS"), nil, nil, LangRusSelect, nil); + FrontendOptionAddDynamic(TheText.Get("FEL_JAP"), nil, nil, LangJapSelect, nil); #endif -/*#ifdef IMPROVED_VIDEOMODE - static const wchar *screenModes[] = { (wchar*)L"FULLSCREEN", (wchar*)L"WINDOWED" }; - FrontendOptionSetPosition(MENUPAGE_GRAPHICS_SETTINGS, 8); - FrontendOptionAddSelect(TheText.Get("SCRFOR"), screenModes, 2, (int8*)&FrontEndMenuManager.m_nPrefsWindowed, true, ScreenModeChange, nil); -#endif*/ - #ifdef MENU_MAP - FrontendOptionSetPosition(MENUPAGE_PAUSE_MENU, 2); + FrontendOptionSetCursor(MENUPAGE_PAUSE_MENU, 2); FrontendOptionAddRedirect(TheText.Get("FEG_MAP"), MENUPAGE_MAP); #endif -#ifdef FREE_CAM - static const wchar *text = (wchar*)L"TOGGLE FREE CAM"; - FrontendOptionSetPosition(MENUPAGE_CONTROLLER_PC, 1); - FrontendOptionAddDynamic(text, nil, ToggleFreeCam, nil); + // -- Start of graphics menu - add options in display order! + + SWITCH_TO_GRAPHICS_MENU + CLONE_OPTION(TheText.Get("FED_RES"), MENUACTION_SCREENRES, nil, nil); + CLONE_OPTION(TheText.Get("FED_WIS"), MENUACTION_WIDESCREEN, nil, nil) + +#ifdef IMPROVED_VIDEOMODE + static const wchar* screenModes[] = { (wchar*)L"FULLSCREEN", (wchar*)L"WINDOWED" }; + // Storing isn't enabled because it's handled in Frontend + FrontendOptionAddSelect(TheText.Get("FEM_SCF"), screenModes, 2, (int8*)&FrontEndMenuManager.m_nPrefsWindowed, true, ScreenModeChange, nil); #endif -/*#ifdef CUTSCENE_BORDERS_SWITCH - static const wchar *off_on[] = { TheText.Get("FEM_OFF"), TheText.Get("FEM_ON") }; - FrontendOptionSetPosition(MENUPAGE_DISPLAY_SETTINGS, 3); - FrontendOptionAddSelect((const wchar *)L"CUTSCENE BORDERS", off_on, 2, (int8 *)&CMenuManager::m_PrefsCutsceneBorders, false, BorderModeChange, nil); -#endif*/ + CLONE_OPTION(TheText.Get("FEM_VSC"), MENUACTION_FRAMESYNC, nil, nil); + CLONE_OPTION(TheText.Get("FEM_FRM"), MENUACTION_FRAMELIMIT, nil, nil); + +#ifdef MULTISAMPLING + SWITCH_TO_GRAPHICS_MENU + FrontendOptionAddDynamic(TheText.Get("FED_AAS"), MultiSamplingDraw, (int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, MultiSamplingButtonPress, MultiSamplingGoBack, true); +#endif + + CLONE_OPTION(TheText.Get("FED_TRA"), MENUACTION_TRAILS, nil, nil); + +#ifdef PS2_ALPHA_TEST + SWITCH_TO_GRAPHICS_MENU + FrontendOptionAddSelect(TheText.Get("FEM_2PR"), off_on, 2, (int8*)&gPS2alphaTest, false, PS2AlphaTestChange, nil, true); +#endif + + ADD_RESTORE_DEFAULTS(RestoreDefGraphics) + ADD_BACK + + // ---- End of Graphics Menu ---- + + // -- Start of Display menu - add options in display order! + + SWITCH_TO_DISPLAY_MENU + CLONE_OPTION(TheText.Get("FED_BRI"), MENUACTION_BRIGHTNESS, nil, nil); + CLONE_OPTION(TheText.Get("FEM_LOD"), MENUACTION_DRAWDIST, nil, nil); + +#ifdef CUTSCENE_BORDERS_SWITCH + SWITCH_TO_DISPLAY_MENU + FrontendOptionAddSelect(TheText.Get("FEM_CSB"), off_on, 2, (int8 *)&CMenuManager::m_PrefsCutsceneBorders, false, BorderModeChange, nil, true); +#endif + +#ifdef FREE_CAM + SWITCH_TO_DISPLAY_MENU + static const wchar* text = (wchar*)L"FREE CAM"; + FrontendOptionAddSelect(text, off_on, 2, (int8*)&TheCamera.bFreeCam, false, FreeCamChange, nil, true); +#endif + + CLONE_OPTION(TheText.Get("FED_SUB"), MENUACTION_SUBTITLES, nil, nil); + + // Add link to advanced graphics menu if it's filled. +#ifndef GRAPHICS_MENU_OPTIONS + if (movedToAdvMenu) { + FrontendOptionSetCursor(MENUPAGE_DISPLAY_SETTINGS, -3); + FrontendOptionAddRedirect(TheText.Get("FET_ADV"), advancedDisplayMenu, 0); + + FrontendOptionSetCursor(advancedDisplayMenu, -1); + FrontendOptionAddBackButton(TheText.Get("FEDS_TB")); + } +#endif + + ADD_RESTORE_DEFAULTS(RestoreDefDisplay) + ADD_BACK } #endif diff --git a/src/extras/frontendoption.cpp b/src/extras/frontendoption.cpp index 51814f35..3214bbfd 100644 --- a/src/extras/frontendoption.cpp +++ b/src/extras/frontendoption.cpp @@ -2,14 +2,24 @@ #ifdef CUSTOM_FRONTEND_OPTIONS #include "frontendoption.h" +#include "Text.h" int numCustomFrontendOptions = 0; FrontendOption *customFrontendOptions; -int optionCursor = -1; -eMenuScreen currentMenu; +int numCustomFrontendScreens = 0; +FrontendScreen* customFrontendScreens; -void ChangeScreen(eMenuScreen screen, int option, bool fadeIn) +int numFrontendOptionReplacements = 0; +CMenuScreen::CMenuEntry* frontendOptionReplacements; + +int lastOgScreen = MENUPAGES; // means no new pages + +int optionCursor = -2; +int currentMenu; +bool optionOverwrite = false; + +void ChangeScreen(int screen, int option, bool fadeIn) { FrontEndMenuManager.m_nPrevScreen = FrontEndMenuManager.m_nCurrScreen; FrontEndMenuManager.m_nCurrScreen = screen; @@ -27,7 +37,7 @@ void GoBack(bool fadeIn) FrontEndMenuManager.ThingsToDoBeforeGoingBack(); - ChangeScreen((eMenuScreen)screen, option, fadeIn); + ChangeScreen(screen, option, fadeIn); } uint8 @@ -43,31 +53,89 @@ GetNumberOfMenuOptions(int screen) return Rows; } +uint8 +GetLastMenuScreen() +{ + uint8 page = -1; + for (int i = 0; i < MENUPAGES; i++) { + if (strcmp(aScreens[i].m_ScreenName, "") == 0 && aScreens[i].unk == 0) + break; + + ++page; + } + return page; +} + // Used before populating options, but effective in InitialiseChangedLanguageSettings and debugmenu void RemoveCustomFrontendOptions() { - if (numCustomFrontendOptions == 0) + if (numCustomFrontendOptions != 0) { + + for (int i = 0; i < MENUPAGES; i++) { + for (int j = 0; j < NUM_MENUROWS; j++) { + if (aScreens[i].m_aEntries[j].m_SaveSlot == SAVESLOT_CFO) { + int ogOptionId = customFrontendOptions[aScreens[i].m_aEntries[j].m_TargetMenu].ogOptionId; + if (ogOptionId == -1) { + 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_SaveSlot = SAVESLOT_NONE; + aScreens[i].m_aEntries[k].m_EntryName[0] = '\0'; + j--; + } else { + memcpy(&aScreens[i].m_aEntries[j], &frontendOptionReplacements[ogOptionId], sizeof(CMenuScreen::CMenuEntry)); + } + } + } + } + free(customFrontendOptions); + numCustomFrontendOptions = 0; + + if (numFrontendOptionReplacements != 0) { + free(frontendOptionReplacements); + numFrontendOptionReplacements = 0; + } + } + + if (numCustomFrontendScreens == 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--; - } + if (i > lastOgScreen) { + aScreens[i].m_ScreenName[0] = '\0'; + aScreens[i].unk = 0; } } - free(customFrontendOptions); - numCustomFrontendOptions = 0; + free(customFrontendScreens); + numCustomFrontendScreens = 0; + lastOgScreen = MENUPAGES; } -int8 RegisterNewOption(int screen) +int8 RegisterNewScreen(char *name, int prevPage) +{ + if (lastOgScreen == MENUPAGES) + lastOgScreen = GetLastMenuScreen(); + + numCustomFrontendScreens++; + if (numCustomFrontendScreens == 1) + customFrontendScreens = (FrontendScreen*)malloc(5 * sizeof(FrontendScreen)); + else if (numCustomFrontendScreens % 5 == 1) + customFrontendScreens = (FrontendScreen*)realloc(customFrontendScreens, (numCustomFrontendScreens + 4) * sizeof(FrontendScreen)); + + assert(customFrontendScreens != nil && "Custom frontend screens can't be allocated"); + + int id = lastOgScreen + numCustomFrontendScreens; + assert(id < MENUPAGES && "No room for new custom frontend screens! Increase MENUPAGES"); + strncpy(aScreens[id].m_ScreenName, name, 8); + aScreens[id].m_PreviousPage[0] = aScreens[id].m_PreviousPage[1] = prevPage; + aScreens[id].unk = 1; + return id; +} + +int8 RegisterNewOption() { numCustomFrontendOptions++; if (numCustomFrontendOptions == 1) @@ -77,97 +145,154 @@ int8 RegisterNewOption(int screen) assert(customFrontendOptions != nil && "Custom frontend options can't be allocated"); - uint8 nth = GetNumberOfMenuOptions(screen); + uint8 numOptions = GetNumberOfMenuOptions(currentMenu); + uint8 curIdx; 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++; - } + optionCursor = curIdx = numOptions + optionCursor + 1; + } else + curIdx = 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; + if (!optionOverwrite) { + if (aScreens[currentMenu].m_aEntries[curIdx].m_Action != MENUACTION_NOTHING) { + for (int i = numOptions - 1; i >= curIdx; i--) { + memcpy(&aScreens[currentMenu].m_aEntries[i + 1], &aScreens[currentMenu].m_aEntries[i], sizeof(CMenuScreen::CMenuEntry)); + } + } + } + optionCursor++; + + if (optionOverwrite) { + numFrontendOptionReplacements++; + if (numFrontendOptionReplacements == 1) + frontendOptionReplacements = (CMenuScreen::CMenuEntry*)malloc(5 * sizeof(CMenuScreen::CMenuEntry)); + else if (numFrontendOptionReplacements % 5 == 1) + frontendOptionReplacements = (CMenuScreen::CMenuEntry*)realloc(frontendOptionReplacements, (numFrontendOptionReplacements + 4) * sizeof(CMenuScreen::CMenuEntry)); + + memcpy(&frontendOptionReplacements[numFrontendOptionReplacements - 1], &aScreens[currentMenu].m_aEntries[curIdx], sizeof(CMenuScreen::CMenuEntry)); + customFrontendOptions[numCustomFrontendOptions - 1].ogOptionId = numFrontendOptionReplacements - 1; + } else { + customFrontendOptions[numCustomFrontendOptions - 1].ogOptionId = -1; + } + customFrontendOptions[numCustomFrontendOptions - 1].screen = currentMenu; + + aScreens[currentMenu].m_aEntries[curIdx].m_Action = MENUACTION_TRIGGERFUNC; + aScreens[currentMenu].m_aEntries[curIdx].m_SaveSlot = SAVESLOT_CFO; + aScreens[currentMenu].m_aEntries[curIdx].m_TargetMenu = numCustomFrontendOptions - 1; + aScreens[currentMenu].m_aEntries[curIdx].m_EntryName[0] = 1; // just something to fool it + return curIdx; } -void FrontendOptionSetPosition(eMenuScreen screen, int8 option) +void FrontendOptionSetCursor(int screen, int8 option, bool overwrite) { currentMenu = screen; optionCursor = option; + optionOverwrite = overwrite; } -void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc) -{ - int8 screenOptionOrder = RegisterNewOption(currentMenu); +void FrontendOptionAddBuiltinAction(const wchar* leftText, int action, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc) { + int8 screenOptionOrder = RegisterNewOption(); + + FrontendOption& option = customFrontendOptions[numCustomFrontendOptions - 1]; + + // To fool the Frontend, we will still display the text passed via first param. + switch (action) { + case MENUACTION_SCREENRES: + strcpy(aScreens[currentMenu].m_aEntries[screenOptionOrder].m_EntryName, "FED_RES"); + break; + case MENUACTION_AUDIOHW: + strcpy(aScreens[currentMenu].m_aEntries[screenOptionOrder].m_EntryName, "FEA_3DH"); + break; + } + aScreens[currentMenu].m_aEntries[screenOptionOrder].m_Action = action; + option.type = FEOPTION_BUILTIN_ACTION; + option.buttonPressFunc = buttonPressFunc; + TextCopy(option.leftText, leftText); + option.screenOptionOrder = screenOptionOrder; + option.returnPrevPageFunc = returnPrevPageFunc; + option.save = false; +} + +void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, bool save) +{ + int8 screenOptionOrder = RegisterNewOption(); FrontendOption& option = customFrontendOptions[numCustomFrontendOptions - 1]; - option.screen = currentMenu; option.type = FEOPTION_SELECT; - option.leftText = leftText; + TextCopy(option.leftText, leftText); option.rightTexts = rightTexts; option.numRightTexts = numRightTexts; option.value = var; option.displayedValue = *var; + option.lastSavedValue = *var; + option.save = save; option.onlyApplyOnEnter = onlyApplyOnEnter; option.changeFunc = changeFunc; option.screenOptionOrder = screenOptionOrder; option.returnPrevPageFunc = returnPrevPageFunc; } -void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc drawFunc, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc) +void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc drawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, bool save) { - int8 screenOptionOrder = RegisterNewOption(currentMenu); + int8 screenOptionOrder = RegisterNewOption(); FrontendOption& option = customFrontendOptions[numCustomFrontendOptions - 1]; - option.screen = currentMenu; option.type = FEOPTION_DYNAMIC; option.drawFunc = drawFunc; option.buttonPressFunc = buttonPressFunc; - option.leftText = leftText; - option.onlyApplyOnEnter = false; + TextCopy(option.leftText, leftText); + option.value = var; + option.save = save; option.screenOptionOrder = screenOptionOrder; option.returnPrevPageFunc = returnPrevPageFunc; } -void FrontendOptionAddRedirect(const wchar* text, eMenuScreen to, int8 selectedOption, bool fadeIn) +void FrontendOptionAddRedirect(const wchar* text, int to, int8 selectedOption, bool fadeIn) { - int8 screenOptionOrder = RegisterNewOption(currentMenu); + int8 screenOptionOrder = RegisterNewOption(); 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; + TextCopy(option.leftText, text); option.screenOptionOrder = screenOptionOrder; option.returnPrevPageFunc = nil; + option.save = false; } void FrontendOptionAddBackButton(const wchar* text, bool fadeIn) { - int8 screenOptionOrder = RegisterNewOption(currentMenu); + int8 screenOptionOrder = RegisterNewOption(); FrontendOption& option = customFrontendOptions[numCustomFrontendOptions - 1]; - option.screen = currentMenu; option.type = FEOPTION_GOBACK; option.fadeIn = fadeIn; - option.leftText = text; - option.onlyApplyOnEnter = false; + TextCopy(option.leftText, text); option.screenOptionOrder = screenOptionOrder; option.returnPrevPageFunc = nil; + option.save = false; +} + +uint8 FrontendScreenAdd(char* gxtKey, eMenuSprites sprite, int prevPage, int columnWidth, int headerHeight, int lineHeight, + int8 font, float fontScaleX, float fontScaleY, int8 alignment, bool showLeftRightHelper, ReturnPrevPageFunc returnPrevPageFunc) { + + uint8 screenOrder = RegisterNewScreen(gxtKey, prevPage); + + FrontendScreen &screen = customFrontendScreens[numCustomFrontendScreens - 1]; + screen.id = screenOrder; + screen.sprite = sprite; + screen.prevPage = prevPage; + strncpy(screen.name, gxtKey, 8); + screen.columnWidth = columnWidth; + screen.headerHeight = headerHeight; + screen.lineHeight = lineHeight; + screen.font = font; + screen.fontScaleX = fontScaleX; + screen.fontScaleY = fontScaleY; + screen.alignment = alignment; + screen.returnPrevPageFunc = returnPrevPageFunc; + + return screenOrder; } #endif \ No newline at end of file diff --git a/src/extras/frontendoption.h b/src/extras/frontendoption.h index 7cfc09a7..9608870b 100644 --- a/src/extras/frontendoption.h +++ b/src/extras/frontendoption.h @@ -4,48 +4,102 @@ #ifdef CUSTOM_FRONTEND_OPTIONS #include "Frontend.h" -// Warning: All of the code relies on that you won't use more then NUM_MENUROWS(18) options on one page. Also congrats if you can make 18 options visible at once. +// Warning: +// All of the code relies on that you won't use more then NUM_MENUROWS(18) options on one page. +// Also congrats if you can make 18 options visible at once. + +// About texts: +// All text parameters accept wchar(including hardcoded wchar* and TheText.Get) +// except FrontendScreenAdd(it's char[8] by the design of Frontend). +// All texts reload if custom options reloaded too, which includes language changes and via live reload feature in debug menu! + +// Execute direction: +// All of the calls below eventually manipulate the aScreens array, so keep in mind to add/replace options in order, +// i.e. don't set cursor to 8 first and then 3. + +// Live reload: +// You can add/change/undo the new options in-game if you use VS. Change what you want, build the changed bits via "Edit and Continue", +// and hit the "Reload custom frontend options" from debug menu. Or call CustomFrontendOptionsPopulate() from somewhere else. -// Static/select: User allocates variable, passes it to function and it's set automatically from input among the strings given to function, -// then you can handle ChangeFunc and ReturnPrevPageFunc if needed. +// -- Option types // -// Dynamic: Function doesn't accept value pointer, user should do operations with handling ButtonPressFunc. -// Right-side text can be set via DrawFunc, which is called on every draw. ReturnPrevPageFunc is also here if needed. +// Static/select: You allocate the variable, pass it to function and game sets it from user input among the strings given to function, +// then you can handle ChangeFunc(only called on enter if onlyApplyOnEnter set, or set immediately) +// and ReturnPrevPageFunc optionally. You can store the option in gta3.set if you pass true to corresponding parameter. +// +// Dynamic: Passing variable to function is only needed if you want to store it, otherwise you should do +// all the operations with ButtonPressFunc, this includes allocating the variable. +// Left-side text is passed while creating and static, but ofc right-side text is dynamic - +// you should return it in DrawFunc, which is called on every draw. ReturnPrevPageFunc is also here if needed. +// +// Redirect: Redirection to another screen. selectedOption parameter is the highlighted option user will see after the redirection. +// +// Built-in action: As the name suggests, any action that game has built-in. But as an extra you can set the option text, +// and can be informed on button press/focus loss via buttonPressFunc. ReturnPrevPageFunc is also here. #define FEOPTION_SELECT 0 #define FEOPTION_DYNAMIC 1 #define FEOPTION_REDIRECT 2 #define FEOPTION_GOBACK 3 +#define FEOPTION_BUILTIN_ACTION 4 +// -- Returned via ButtonPressFunc() action param. #define FEOPTION_ACTION_LEFT 0 #define FEOPTION_ACTION_RIGHT 1 #define FEOPTION_ACTION_SELECT 2 #define FEOPTION_ACTION_FOCUSLOSS 3 -void RemoveCustomFrontendOptions(); -void CustomFrontendOptionsPopulate(); +// -- Passed via FrontendScreenAdd() +#define FESCREEN_CENTER 0 +#define FESCREEN_LEFT_ALIGN 1 +#define FESCREEN_RIGHT_ALIGN 2 -// for static and dynamic options +// -- Callbacks + +// pretty much in everything I guess, and optional in all of them typedef void (*ReturnPrevPageFunc)(); // for static options -typedef void (*ChangeFunc)(int8 displayedValue); // called before updating the value +typedef void (*ChangeFunc)(int8 displayedValue); // called before updating the value. + // only called on enter if onlyApplyOnEnter set, otherwise called on every value change // for dynamic options -typedef wchar* (*DrawFunc)(bool* disabled); // should return pointer to right text. *disabled = true will make it dark yellow +typedef wchar* (*DrawFunc)(bool* disabled, bool userHovering); // you must return a pointer for right text. + // you can also set *disabled if you want to gray it out. typedef void (*ButtonPressFunc)(int8 action); // see FEOPTION_ACTIONs above +struct FrontendScreen +{ + int id; + char name[8]; + eMenuSprites sprite; + int prevPage; + int columnWidth; + int headerHeight; + int lineHeight; + int8 font; + float fontScaleX; + float fontScaleY; + int8 alignment; + bool showLeftRightHelper; + ReturnPrevPageFunc returnPrevPageFunc; +}; + struct FrontendOption { int8 type; int8 screenOptionOrder; - eMenuScreen screen; - const wchar* leftText; + int32 screen; + wchar leftText[64]; ReturnPrevPageFunc returnPrevPageFunc; + int8* value; + int8 displayedValue; // only if onlyApplyOnEnter enabled for now + bool save; + int32 ogOptionId; // for replacements, see overwrite parameter of SetCursor union { - // Only for dynamic + // Only for dynamic / built-in action struct { DrawFunc drawFunc; ButtonPressFunc buttonPressFunc; @@ -55,33 +109,54 @@ struct FrontendOption struct { const wchar** rightTexts; int8 numRightTexts; - int8 *value; - int8 displayedValue; // if onlyApplyOnEnter enabled bool onlyApplyOnEnter; ChangeFunc changeFunc; + int8 lastSavedValue; // only if onlyApplyOnEnter enabled }; // Only for redirect struct { - eMenuScreen to; + int to; int8 option; bool fadeIn; }; }; }; +// -- Internal things +void RemoveCustomFrontendOptions(); +void CustomFrontendOptionsPopulate(); + +extern int lastOgScreen; // for reloading + extern int numCustomFrontendOptions; extern FrontendOption* customFrontendOptions; -// To be used in ButtonPressFunc / ChangeFunc(but that would be weird): -void ChangeScreen(eMenuScreen screen, int option = 0, bool fadeIn = true); +extern int numCustomFrontendScreens; +extern FrontendScreen* customFrontendScreens; + +// -- To be used in ButtonPressFunc / ChangeFunc(this one would be weird): +void ChangeScreen(int screen, int option = 0, bool fadeIn = true); void GoBack(bool fadeIn = true); -// If option is positive number, all calls will increase it before using it (you can think it as cursor). -1 means before the back button, -2 is end of page -void FrontendOptionSetPosition(eMenuScreen screen, int8 option = -1); +uint8 GetNumberOfMenuOptions(int screen); -void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc); -void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc rightTextDrawFunc, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc); -void FrontendOptionAddRedirect(const wchar* text, eMenuScreen to, int8 selectedOption = 0, bool fadeIn = true); +// -- Placing the cursor to append/overwrite option +// +// Done via FrontendOptionSetCursor(screen, position, overwrite = false), parameters explained below: +// Screen: as the name suggests. Also accepts the screen IDs returned from FrontendScreenAdd. +// Option: if positive, next AddOption call will put the option to there and progress the cursor. +// if negative, cursor will be placed on bottom-(pos+1), so -1 means the very bottom, -2 means before the back button etc. +// Overwrite: Use to overwrite the options, not appending a new one. AddOption calls will still progress the cursor. + +void FrontendOptionSetCursor(int screen, int8 option, bool overwrite = false); + +// var is optional in AddDynamic, you can enable save parameter if you pass one, otherwise pass nil/0 +void FrontendOptionAddBuiltinAction(const wchar* leftText, int action, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc); +void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, bool save = false); +void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc rightTextDrawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, bool save = false); +void FrontendOptionAddRedirect(const wchar* text, int to, int8 selectedOption = 0, bool fadeIn = true); void FrontendOptionAddBackButton(const wchar* text, bool fadeIn = true); + +uint8 FrontendScreenAdd(char* gxtKey, eMenuSprites sprite, int prevPage, int columnWidth, int headerHeight, int lineHeight, int8 font, float fontScaleX, float fontScaleY, int8 alignment, bool showLeftRightHelper, ReturnPrevPageFunc returnPrevPageFunc = nil); #endif \ No newline at end of file