summaryrefslogtreecommitdiffstats
path: root/src/extras
diff options
context:
space:
mode:
Diffstat (limited to 'src/extras')
-rw-r--r--src/extras/frontendoption.cpp173
-rw-r--r--src/extras/frontendoption.h87
2 files changed, 260 insertions, 0 deletions
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