1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
#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.
// About texts:
// All text parameters accept wchar(including hardcoded wchar* and TheText.Get)
// except FrontendScreenAdd(it's char[8] GXT key 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.
// -- Option types
//
// 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 an INI file if you pass the key(as a char array) 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
// -- Passed via FrontendScreenAdd()
#define FESCREEN_CENTER 0
#define FESCREEN_LEFT_ALIGN 1
#define FESCREEN_RIGHT_ALIGN 2
// -- 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.
// only called on enter if onlyApplyOnEnter set, otherwise called on every value change
// for dynamic options
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;
int32 screen;
wchar leftText[128];
ReturnPrevPageFunc returnPrevPageFunc;
int8* value;
int8 displayedValue; // only if onlyApplyOnEnter enabled for now
const char* save;
int32 ogOptionId; // for replacements, see overwrite parameter of SetCursor
union {
// Only for dynamic / built-in action
struct {
DrawFunc drawFunc;
ButtonPressFunc buttonPressFunc;
};
// Only for static/select
struct {
wchar** rightTexts;
int8 numRightTexts;
bool onlyApplyOnEnter;
ChangeFunc changeFunc;
int8 lastSavedValue; // only if onlyApplyOnEnter enabled
};
// Only for redirect
struct {
int to;
int8 option;
bool fadeIn;
};
};
};
// -- Internal things
void RemoveCustomFrontendOptions();
void CustomFrontendOptionsPopulate();
extern int lastOgScreen; // for reloading
extern int numCustomFrontendOptions;
extern FrontendOption* customFrontendOptions;
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);
uint8 GetNumberOfMenuOptions(int screen);
// -- 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, enables you to save them in an INI file(also needs passing char array to saveName param. obv), 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, const char* saveName = nil);
void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc rightTextDrawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, const char* saveName = nil);
void FrontendOptionAddRedirect(const wchar* text, int to, int8 selectedOption = 0, bool fadeIn = true);
void FrontendOptionAddBackButton(const wchar* text, bool fadeIn = true);
uint8 FrontendScreenAdd(const 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
|