From 329a387fdfab403bfd8fadef025510ee1081e38f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Thu, 28 May 2020 03:07:26 +0300 Subject: [PATCH] Frontend customization functions, freecam toggle, minor things --- src/control/Script.cpp | 13 +- src/core/Cam.cpp | 2 +- src/core/Frontend.cpp | 227 +++++++++++++------- src/core/Frontend.h | 17 +- src/core/Game.cpp | 6 +- src/core/{MenuScreens.h => MenuScreens.cpp} | 36 +--- src/core/config.h | 1 + src/core/main.cpp | 1 - src/core/re3.cpp | 98 +++++++++ src/extras/frontendoption.cpp | 163 ++++++++++++++ src/extras/frontendoption.h | 86 ++++++++ src/skel/glfw/glfw.cpp | 2 +- 12 files changed, 531 insertions(+), 121 deletions(-) rename src/core/{MenuScreens.h => MenuScreens.cpp} (95%) create mode 100644 src/extras/frontendoption.cpp create mode 100644 src/extras/frontendoption.h diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 1ea970c4..c52b28c6 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -1,4 +1,3 @@ -#define WITHWINDOWS // for our script loading hack #include "common.h" #include "Script.h" @@ -504,10 +503,22 @@ void CRunningScript::Init() } #ifdef USE_DEBUG_SCRIPT_LOADER +#ifdef _WIN32 +#include +#endif int open_script() { static int scriptToLoad = 0; + // Doesn't work because of CGame::Initialise is blocking + /* + if (glfwGetKey(PSGLOBAL(window), GLFW_KEY_G) == GLFW_PRESS) + scriptToLoad = 0; + if (glfwGetKey(PSGLOBAL(window), GLFW_KEY_R) == GLFW_PRESS) + scriptToLoad = 1; + if (glfwGetKey(PSGLOBAL(window), GLFW_KEY_D) == GLFW_PRESS) + scriptToLoad = 2; + */ #ifdef _WIN32 if (GetAsyncKeyState('G') & 0x8000) scriptToLoad = 0; diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index 247e77ce..6347e111 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -29,7 +29,7 @@ bool PrintDebugCode = false; int16 DebugCamMode; #ifdef FREE_CAM -bool CCamera::bFreeCam = true; +bool CCamera::bFreeCam; int nPreviousMode = -1; #endif diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index d58d0576..710fc692 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -23,7 +23,6 @@ #include "GenericGameStorage.h" #include "Script.h" #include "Camera.h" -#include "MenuScreens.h" #include "ControllerConfig.h" #include "Vehicle.h" #include "MBlur.h" @@ -36,6 +35,7 @@ #include "Stats.h" #include "Messages.h" #include "FileLoader.h" +#include "frontendoption.h" #define TIDY_UP_PBP // ProcessButtonPresses #define MAX_VISIBLE_LIST_ROW 30 @@ -382,7 +382,7 @@ CMenuManager::PageDownList(bool playSoundOnSuccess) } inline void -CMenuManager::ThingsToDoBeforeLeavingPage() +CMenuManager::ThingsToDoBeforeGoingBack() { if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && strcmp(m_aSkinName, m_PrefsSkinFile) != 0) { CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); @@ -395,9 +395,6 @@ CMenuManager::ThingsToDoBeforeLeavingPage() #endif } else if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { m_nDisplayVideoMode = m_nPrefsVideoMode; -#ifdef IMPROVED_VIDEOMODE - m_nSelectedScreenMode = m_nPrefsWindowed; -#endif } if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { @@ -407,6 +404,43 @@ CMenuManager::ThingsToDoBeforeLeavingPage() 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 (option.onlyApplyOnEnter) + option.displayedValue = *option.value; + } + } +#endif +} + +inline 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 @@ -923,6 +957,9 @@ CMenuManager::Draw() #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; @@ -1105,17 +1142,6 @@ CMenuManager::Draw() AsciiToUnicode(_psGetVideoModeList()[m_nDisplayVideoMode], unicodeTemp); rightText = unicodeTemp; break; -#ifdef IMPROVED_VIDEOMODE - case MENUACTION_SCREENMODE: - if (m_nSelectedScreenMode == 0) - sprintf(asciiTemp, "FULLSCREEN"); - else - sprintf(asciiTemp, "WINDOWED"); - - AsciiToUnicode(asciiTemp, unicodeTemp); - rightText = unicodeTemp; - break; -#endif case MENUACTION_AUDIOHW: if (m_nPrefsAudio3DProviderIndex == -1) rightText = TheText.Get("FEA_NAH"); @@ -1166,6 +1192,28 @@ CMenuManager::Draw() case MENUACTION_MOUSESTEER: rightText = TheText.Get(CVehicle::m_bDisableMouseSteering ? "FEM_OFF" : "FEM_ON"); break; +#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) { + option.drawFunc(unicodeTemp, &isOptionDisabled); + rightText = unicodeTemp; + } + } + } else + assert(0 && "Custom frontend options is borked"); + + break; +#endif } float nextItemY = headerHeight + nextYToUse; @@ -1244,7 +1292,11 @@ CMenuManager::Draw() CFont::SetRightJustifyOn(); if(!strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FED_RES") - && !m_bGameNotLoaded && textLayer == 1) { + && !m_bGameNotLoaded && textLayer == 1 +#ifdef CUSTOM_FRONTEND_OPTIONS + || isOptionDisabled +#endif + ) { CFont::SetColor(CRGBA(155, 117, 6, FadeIn(255))); } CFont::PrintString(MENU_X_RIGHT_ALIGNED(columnWidth - textLayer), itemY, rightText); @@ -1287,12 +1339,12 @@ CMenuManager::Draw() SetHelperText(3); } } -#ifdef IMPROVED_VIDEOMODE - if (m_nSelectedScreenMode != m_nPrefsWindowed) { - if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "SCRFOR") != 0 - && m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { - m_nSelectedScreenMode = m_nPrefsWindowed; - } + +#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; } #endif @@ -2993,6 +3045,11 @@ CMenuManager::InitialiseChangedLanguageSettings() default: break; } + +#ifdef CUSTOM_FRONTEND_OPTIONS + RemoveCustomFrontendOptions(); + CustomFrontendOptionsPopulate(); +#endif } } @@ -3138,6 +3195,9 @@ 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 } } @@ -3228,6 +3288,9 @@ 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 } CFileMgr::CloseFile(fileHandle); @@ -4322,10 +4385,12 @@ CMenuManager::ProcessButtonPresses(void) CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); SaveSettings(); } else { - if (!m_bGameNotLoaded) - ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[1], aScreens[m_nCurrScreen].m_ParentEntry[1], true, true); - else - ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[0], aScreens[m_nCurrScreen].m_ParentEntry[0], true, true); +#ifndef TIDY_UP_PBP + ChangeScreen(!m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0], + GetPreviousPageOption(), true, true); +#else + goBack = true; +#endif } } else if (m_nCurrScreen != MENUPAGE_MULTIPLAYER_FIND_GAME) { option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; @@ -4377,26 +4442,6 @@ CMenuManager::ProcessButtonPresses(void) InitialiseChangedLanguageSettings(); SaveSettings(); break; -#ifdef MORE_LANGUAGES - case MENUACTION_LANG_PL: - m_PrefsLanguage = LANGUAGE_POLISH; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_RUS: - m_PrefsLanguage = LANGUAGE_RUSSIAN; - m_bFrontEnd_ReloadObrTxtGxt = true; - CMenuManager::InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_JAP: - m_PrefsLanguage = LANGUAGE_JAPANESE; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; -#endif case MENUACTION_POPULATESLOTS_CHANGEMENU: PcSaveHelper.PopulateSlotInfo(); @@ -4426,10 +4471,8 @@ CMenuManager::ProcessButtonPresses(void) if (strncmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEDS_TB", 8) == 0) { #ifndef TIDY_UP_PBP ResetHelperText(); - if (!m_bGameNotLoaded) - ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[1], aScreens[m_nCurrScreen].m_ParentEntry[1], true, true); - else - ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[0], aScreens[m_nCurrScreen].m_ParentEntry[0], true, true); + ChangeScreen(!m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0], + GetPreviousPageOption(), true, true); #else goBack = true; break; @@ -4536,16 +4579,6 @@ CMenuManager::ProcessButtonPresses(void) SaveSettings(); } break; -#ifdef IMPROVED_VIDEOMODE - case MENUACTION_SCREENMODE: - if (m_nSelectedScreenMode != m_nPrefsWindowed) { - m_nPrefsWindowed = m_nSelectedScreenMode; - _psSelectScreenVM(m_nPrefsVideoMode); // apply same resolution - SetHelperText(0); - SaveSettings(); - } - break; -#endif case MENUACTION_AUDIOHW: { int selectedProvider = m_nPrefsAudio3DProviderIndex; @@ -4661,6 +4694,31 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); OutputDebugString("STARTED PLAYING FRONTEND AUDIO TRACK"); 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 (!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 + assert(0 && "Custom frontend options are borked"); + + break; +#endif } } ProcessOnOffMenuOptions(); @@ -4693,7 +4751,7 @@ CMenuManager::ProcessButtonPresses(void) #endif RequestFrontEndShutDown(); } - // It's now in ThingsToDoBeforeLeavingPage() + // It's now in ThingsToDoBeforeGoingBack() #ifndef TIDY_UP_PBP else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { DMAudio.StopFrontEndTrack(); @@ -4702,10 +4760,10 @@ CMenuManager::ProcessButtonPresses(void) #endif int oldScreen = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0]; - int oldOption = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry[1] : aScreens[m_nCurrScreen].m_ParentEntry[0]; + int oldOption = GetPreviousPageOption(); if (oldScreen != -1) { - ThingsToDoBeforeLeavingPage(); + ThingsToDoBeforeGoingBack(); #ifdef PS2_LIKE_MENU if (!bottomBarActive && @@ -4803,11 +4861,11 @@ CMenuManager::ProcessButtonPresses(void) if (changeValueBy > 0) { m_PrefsUseWideScreen++; if (m_PrefsUseWideScreen > 2) - m_PrefsUseWideScreen = 2; + m_PrefsUseWideScreen = 0; } else { m_PrefsUseWideScreen--; if (m_PrefsUseWideScreen < 0) - m_PrefsUseWideScreen = 0; + m_PrefsUseWideScreen = 2; } DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); SaveSettings(); @@ -4834,12 +4892,6 @@ CMenuManager::ProcessButtonPresses(void) } } break; -#ifdef IMPROVED_VIDEOMODE - case MENUACTION_SCREENMODE: - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); - m_nSelectedScreenMode = !m_nSelectedScreenMode; - break; -#endif case MENUACTION_AUDIOHW: if (m_nPrefsAudio3DProviderIndex != -1) { m_nPrefsAudio3DProviderIndex += changeValueBy; @@ -4862,6 +4914,34 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 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_SUCCESS, 0); + } + else + assert(0 && "Custom frontend options are borked"); + + break; +#endif } ProcessOnOffMenuOptions(); if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { @@ -5083,7 +5163,7 @@ CMenuManager::SwitchMenuOnAndOff() bottomBarActive = false; #endif #ifdef FIX_BUGS - ThingsToDoBeforeLeavingPage(); + ThingsToDoBeforeGoingBack(); #endif ShutdownJustMenu(); SaveSettings(); @@ -5830,3 +5910,4 @@ uint8 CMenuManager::GetNumberOfMenuOptions() #undef GetBackJustUp #undef GetBackJustDown +#undef ChangeScreen diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 89517528..6f68de33 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -366,13 +366,8 @@ enum eMenuAction MENUACTION_UNK108, MENUACTION_UNK109, MENUACTION_UNK110, -#ifdef MORE_LANGUAGES - MENUACTION_LANG_PL, - MENUACTION_LANG_RUS, - MENUACTION_LANG_JAP, -#endif -#ifdef IMPROVED_VIDEOMODE - MENUACTION_SCREENMODE +#ifdef CUSTOM_FRONTEND_OPTIONS + MENUACTION_TRIGGERFUNC #endif }; @@ -468,7 +463,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]; }; @@ -647,12 +642,13 @@ public: int GetNumOptionsCntrlConfigScreens(); int ConstructStatLine(int); - // New (not in function or inlined in the game) - void ThingsToDoBeforeLeavingPage(); + // New (inlined ones and the ones we can't believe it's not inlined) + void ThingsToDoBeforeGoingBack(); void ScrollUpListByOne(); void ScrollDownListByOne(); void PageUpList(bool); void PageDownList(bool); + int8 GetPreviousPageOption(); // uint8 GetNumberOfMenuOptions(); }; @@ -662,3 +658,4 @@ VALIDATE_SIZE(CMenuManager, 0x564); #endif extern CMenuManager FrontEndMenuManager; +extern CMenuScreen aScreens[]; \ No newline at end of file diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 33afc956..7983a7c3 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -85,8 +85,7 @@ #include "ZoneCull.h" #include "Zones.h" #include "debugmenu.h" - - +#include "frontendoption.h" eLevelName CGame::currLevel; bool CGame::bDemoMode = true; @@ -234,6 +233,9 @@ bool CGame::InitialiseOnceAfterRW(void) DMAudio.SetMusicFadeVol(127); CWorld::Players[0].SetPlayerSkin(CMenuManager::m_PrefsSkinFile); +#ifdef CUSTOM_FRONTEND_OPTIONS + CustomFrontendOptionsPopulate(); +#endif return true; } diff --git a/src/core/MenuScreens.h b/src/core/MenuScreens.cpp similarity index 95% rename from src/core/MenuScreens.h rename to src/core/MenuScreens.cpp index 6c2ebdb8..ca561af8 100644 --- a/src/core/MenuScreens.h +++ b/src/core/MenuScreens.cpp @@ -1,17 +1,12 @@ -#pragma once +#include "common.h" +#include "Frontend.h" -// TODO: There are some missing/wrong entries in here. - -const CMenuScreen aScreens[] = { +CMenuScreen aScreens[] = { // MENUPAGE_NONE = 0 { "", 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, }, @@ -24,11 +19,7 @@ const 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, }, @@ -62,9 +53,6 @@ const CMenuScreen aScreens[] = { MENUACTION_SUBTITLES, "FED_SUB", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, MENUACTION_WIDESCREEN, "FED_WIS", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, MENUACTION_SCREENRES, "FED_RES", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, -#ifdef IMPROVED_VIDEOMODE - MENUACTION_SCREENMODE, "SCRFOR", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, -#endif MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, }, @@ -76,11 +64,6 @@ const CMenuScreen aScreens[] = { MENUACTION_LANG_GER, "FEL_GER", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LANG_ITA, "FEL_ITA", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LANG_SPA, "FEL_SPA", SAVESLOT_NONE, MENUPAGE_NONE, -#ifdef MORE_LANGUAGES - MENUACTION_LANG_PL, "FEL_POL", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_LANG_RUS, "FEL_RUS", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_LANG_JAP, "FEL_JAP", SAVESLOT_NONE, MENUPAGE_NONE, -#endif MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, }, @@ -333,11 +316,7 @@ const 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_GRAPHICS_SETTINGS, @@ -347,11 +326,7 @@ const 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_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_CANCELGAME, "FEM_YES", SAVESLOT_NONE, MENUPAGE_NONE, @@ -412,9 +387,6 @@ const 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, @@ -463,4 +435,4 @@ const CMenuScreen aScreens[] = { MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, }, #endif -}; +}; \ No newline at end of file diff --git a/src/core/config.h b/src/core/config.h index f43067d7..b7a811a0 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -196,6 +196,7 @@ enum Config { #define USE_TXD_CDIMAGE // generate and load textures from txd.img #define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number //#define USE_TEXTURE_POOL +#define CUSTOM_FRONTEND_OPTIONS // Particle //#define PC_PARTICLE diff --git a/src/core/main.cpp b/src/core/main.cpp index 666758c8..b5e222be 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -95,7 +95,6 @@ void TheGame(void); void DebugMenuPopulate(void); #endif - void ValidateVersion() { diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 883caec5..df394056 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -27,6 +27,7 @@ #include "Radar.h" #include "debugmenu.h" #include "Frontend.h" +#include "Text.h" #ifndef _WIN32 #include "assert.h" @@ -66,6 +67,100 @@ mysrand(unsigned int seed) myrand_seed = seed; } +#ifdef CUSTOM_FRONTEND_OPTIONS +#include "frontendoption.h" +#include "platform.h" + +void ReloadFrontendOptions(void) +{ + RemoveCustomFrontendOptions(); + CustomFrontendOptionsPopulate(); +} + +#ifdef MORE_LANGUAGES +void LangPolSelect(int8 action) +{ + if (action == FEOPTION_ACTION_SELECT) { + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_POLISH; + FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true; + FrontEndMenuManager.InitialiseChangedLanguageSettings(); + FrontEndMenuManager.SaveSettings(); + } +} + +void LangRusSelect(int8 action) +{ + if (action == FEOPTION_ACTION_SELECT) { + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_RUSSIAN; + FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true; + FrontEndMenuManager.InitialiseChangedLanguageSettings(); + FrontEndMenuManager.SaveSettings(); + } +} + +void LangJapSelect(int8 action) +{ + if (action == FEOPTION_ACTION_SELECT) { + FrontEndMenuManager.m_PrefsLanguage = 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 + +// Reloaded on language change, so you can use hardcoded wchar* and TheText.Get with peace of mind +void +CustomFrontendOptionsPopulate(void) +{ +#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 +} +#endif + #ifdef DEBUGMENU void WeaponCheat(); void HealthCheat(); @@ -382,6 +477,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 #ifdef TOGGLEABLE_BETA_FEATURES DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", &CPed::bPopHeadsOnHeadshot, nil); DebugMenuAddVarBool8("Debug", "Toggle peds running to phones to report crimes", &CPed::bMakePedsRunToPhonesToReportCrimes, nil); diff --git a/src/extras/frontendoption.cpp b/src/extras/frontendoption.cpp new file mode 100644 index 00000000..7b7ad229 --- /dev/null +++ b/src/extras/frontendoption.cpp @@ -0,0 +1,163 @@ +#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 reloading in InitialiseChangedLanguageSettings and debugmenu +void +RemoveCustomFrontendOptions() +{ + 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) { + aScreens[i].m_aEntries[j].m_Action = MENUACTION_NOTHING; + aScreens[i].m_aEntries[j].m_EntryName[0] = '\0'; + } + } + } + free(customFrontendOptions); + numCustomFrontendOptions = 0; +} + +int8 RegisterNewOption(int screen) +{ + numCustomFrontendOptions++; + if (numCustomFrontendOptions == 1) + customFrontendOptions = (FrontendOption*)malloc(numCustomFrontendOptions * sizeof(FrontendOption)); + else + customFrontendOptions = (FrontendOption*)realloc(customFrontendOptions, numCustomFrontendOptions * sizeof(FrontendOption)); + + 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..6c6ac20c --- /dev/null +++ b/src/extras/frontendoption.h @@ -0,0 +1,86 @@ +#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 + +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 void (*DrawFunc)(wchar* out, bool* disabled); // parameters should be set by user, both is allocated. disabled option will be 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 diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 21115585..3ef0ab63 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -1747,7 +1747,7 @@ void CapturePad(RwInt32 padID) void joysChangeCB(int jid, int event) { - if (event == GLFW_CONNECTED) + if (event == GLFW_CONNECTED && !IsThisJoystickBlacklisted(jid)) { if (PSGLOBAL(joy1id) == -1) PSGLOBAL(joy1id) = jid;