Simplify menu input code

This commit is contained in:
UnknownShadow200 2019-08-08 22:02:42 +10:00
parent 25d6518931
commit 283f753b3e
4 changed files with 184 additions and 209 deletions

View File

@ -109,9 +109,8 @@ struct SaveLevelScreen {
struct MenuOptionsScreen {
MenuScreen_Layout
struct ButtonWidget* buttons;
struct InputValidator* validators;
struct MenuInputDesc* descs;
const char** descriptions;
const char** defaultValues;
int activeI, selectedI, descriptionsCount;
struct ButtonWidget ok, Default;
struct MenuInputWidget input;
@ -176,9 +175,9 @@ static void Menu_Label(void* s, int i, struct TextWidget* label, const String* t
Widget_SetLocation(menu->widgets[i], horAnchor, verAnchor, x, y);
}
static void Menu_Input(void* s, int i, struct MenuInputWidget* input, int width, const String* text, FontDesc* font, struct InputValidator* v, int horAnchor, int verAnchor, int x, int y) {
static void Menu_Input(void* s, int i, struct MenuInputWidget* input, int width, const String* text, FontDesc* font, struct MenuInputDesc* desc, int horAnchor, int verAnchor, int x, int y) {
struct Menu* menu = (struct Menu*)s;
MenuInputWidget_Create(input, width, 30, text, font, v);
MenuInputWidget_Create(input, width, 30, text, font, desc);
menu->widgets[i] = (struct Widget*)input;
Widget_SetLocation(menu->widgets[i], horAnchor, verAnchor, x, y);
@ -954,10 +953,10 @@ static void EditHotkeyScreen_ContextRecreated(void* screen) {
static const String cancel = String_FromConst("Cancel");
struct EditHotkeyScreen* s = (struct EditHotkeyScreen*)screen;
struct InputValidator v;
struct MenuInputDesc desc;
String text; bool existed;
InputValidator_String(v);
MenuInput_String(desc);
existed = s->origHotkey.Trigger != KEY_NONE;
if (existed) {
text = StringsBuffer_UNSAFE_Get(&HotkeysText, s->origHotkey.TextIndex);
@ -973,7 +972,7 @@ static void EditHotkeyScreen_ContextRecreated(void* screen) {
EditHotkeyScreen_RemoveHotkey);
Menu_Back(s, 5, &s->buttons[5], "Cancel", &s->titleFont, Menu_SwitchHotkeys);
Menu_Input(s, 6, &s->input, 500, &text, &s->textFont, &v,
Menu_Input(s, 6, &s->input, 500, &text, &s->textFont, &desc,
ANCHOR_CENTRE, ANCHOR_CENTRE, 0, -35);
}
@ -1006,12 +1005,12 @@ struct Screen* EditHotkeyScreen_MakeInstance(struct HotkeyData original) {
static struct GenLevelScreen GenLevelScreen_Instance;
CC_NOINLINE static int GenLevelScreen_GetInt(struct GenLevelScreen* s, int index) {
struct MenuInputWidget* input = &s->inputs[index];
struct InputValidator* v;
struct MenuInputDesc* desc;
String text = input->base.text;
int value;
v = &input->validator;
if (!v->VTABLE->IsValidValue(v, &text)) return 0;
desc = &input->desc;
if (!desc->VTABLE->IsValidValue(desc, &text)) return 0;
Convert_ParseInt(&text, &value); return value;
}
@ -1063,22 +1062,25 @@ static void GenLevelScreen_InputClick(void* screen, void* input) {
s->selected->base.showCaret = true;
}
static void GenLevelScreen_Input(struct GenLevelScreen* s, int i, int y, bool seed, String* value) {
static void GenLevelScreen_Input(struct GenLevelScreen* s, int i, int y, bool seed, int def) {
String tmp; char tmpBuffer[STRING_SIZE];
struct MenuInputWidget* input = &s->inputs[i];
struct InputValidator v;
struct MenuInputDesc desc;
if (seed) {
InputValidator_Seed(v);
MenuInput_Seed(desc);
} else {
InputValidator_Int(v, 1, 8192);
MenuInput_Int(desc, 1, 8192, def);
}
Menu_Input(s, i, input, 200, value, &s->textFont, &v,
String_InitArray(tmp, tmpBuffer);
desc.VTABLE->GetDefault(&desc, &tmp);
Menu_Input(s, i, input, 200, &tmp, &s->textFont, &desc,
ANCHOR_CENTRE, ANCHOR_CENTRE, 0, y);
input->base.showCaret = false;
input->base.MenuClick = GenLevelScreen_InputClick;
value->length = 0;
}
static void GenLevelScreen_Label(struct GenLevelScreen* s, int i, int x, int y, const char* title) {
@ -1114,18 +1116,12 @@ static void GenLevelScreen_ContextRecreated(void* screen) {
static const String title = String_FromConst("Generate new level");
static const String flat = String_FromConst("Flatgrass");
static const String norm = String_FromConst("Vanilla");
String tmp; char tmpBuffer[STRING_SIZE];
struct GenLevelScreen* s = (struct GenLevelScreen*)screen;
struct GenLevelScreen* s = (struct GenLevelScreen*)screen;
String_InitArray(tmp, tmpBuffer);
String_AppendInt(&tmp, World.Width);
GenLevelScreen_Input(s, 0, -80, false, &tmp);
String_AppendInt(&tmp, World.Height);
GenLevelScreen_Input(s, 1, -40, false, &tmp);
String_AppendInt(&tmp, World.Length);
GenLevelScreen_Input(s, 2, 0, false, &tmp);
GenLevelScreen_Input(s, 3, 40, true, &tmp);
GenLevelScreen_Input(s, 0, -80, false, World.Width);
GenLevelScreen_Input(s, 1, -40, false, World.Height);
GenLevelScreen_Input(s, 2, 0, false, World.Length);
GenLevelScreen_Input(s, 3, 40, true, 0);
GenLevelScreen_Label(s, 0, -150, -80, "Width:");
GenLevelScreen_Label(s, 1, -150, -40, "Height:");
@ -1334,8 +1330,8 @@ static void SaveLevelScreen_ContextRecreated(void* screen) {
static const String mcEdit = String_FromConst("&eCan be imported into MCEdit");
struct SaveLevelScreen* s = (struct SaveLevelScreen*)screen;
struct InputValidator v;
InputValidator_Path(v);
struct MenuInputDesc desc;
MenuInput_Path(desc);
Menu_Button(s, 0, &s->buttons[0], 300, &save, &s->titleFont, SaveLevelScreen_Classic,
ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 20);
@ -1345,7 +1341,7 @@ static void SaveLevelScreen_ContextRecreated(void* screen) {
ANCHOR_CENTRE, ANCHOR_CENTRE, 110, 120);
Menu_Back(s, 3, &s->buttons[2], "Cancel", &s->titleFont, Menu_SwitchPause);
Menu_Input(s, 4, &s->input, 500, &String_Empty, &s->textFont, &v,
Menu_Input(s, 4, &s->input, 500, &String_Empty, &s->textFont, &desc,
ANCHOR_CENTRE, ANCHOR_CENTRE, 0, -30);
s->widgets[5] = NULL; /* description widget placeholder */
}
@ -1962,10 +1958,10 @@ static void MenuOptionsScreen_FreeInput(struct MenuOptionsScreen* s) {
}
static void MenuOptionsScreen_EnterInput(struct MenuOptionsScreen* s) {
struct InputValidator* v = &s->input.validator;
struct MenuInputDesc* desc = &s->input.desc;
String text = s->input.base.text;
if (v->VTABLE->IsValidValue(v, &text)) {
if (desc->VTABLE->IsValidValue(desc, &text)) {
MenuOptionsScreen_Set(s, s->activeI, &text);
}
@ -2077,10 +2073,16 @@ static void MenuOptionsScreen_OK(void* screen, void* widget) {
}
static void MenuOptionsScreen_Default(void* screen, void* widget) {
String value; char valueBuffer[STRING_SIZE];
struct MenuOptionsScreen* s = (struct MenuOptionsScreen*)screen;
String text = String_FromReadonly(s->defaultValues[s->activeI]);
struct MenuInputDesc* desc;
desc = &s->descs[s->activeI];
String_InitArray(value, valueBuffer);
desc->VTABLE->GetDefault(desc, &value);
InputWidget_Clear(&s->input.base);
InputWidget_AppendString(&s->input.base, &text);
InputWidget_AppendString(&s->input.base, &value);
}
static void MenuOptionsScreen_Bool(void* screen, void* widget) {
@ -2105,7 +2107,7 @@ static void MenuOptionsScreen_Enum(void* screen, void* widget) {
struct MenuOptionsScreen* s = (struct MenuOptionsScreen*)screen;
struct ButtonWidget* btn = (struct ButtonWidget*)widget;
int index;
struct InputValidator* v;
struct MenuInputDesc* desc;
const char** names;
int raw, count;
@ -2114,9 +2116,9 @@ static void MenuOptionsScreen_Enum(void* screen, void* widget) {
String_InitArray(value, valueBuffer);
btn->GetValue(&value);
v = &s->validators[index];
names = v->Meta.e.Names;
count = v->Meta.e.Count;
desc = &s->descs[index];
names = desc->meta.e.Names;
count = desc->meta.e.Count;
raw = (Utils_ParseEnum(&value, 0, names, count) + 1) % count;
value = String_FromReadonly(names[raw]);
@ -2140,7 +2142,7 @@ static void MenuOptionsScreen_Input(void* screen, void* widget) {
btn->GetValue(&value);
i = s->widgetsCount;
Menu_Input(s, i - 1, &s->input, 400, &value, &s->textFont, &s->validators[s->activeI],
Menu_Input(s, i - 1, &s->input, 400, &value, &s->textFont, &s->descs[s->activeI],
ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 110);
Menu_Button(s, i - 2, &s->ok, 40, &okay, &s->titleFont, MenuOptionsScreen_OK,
ANCHOR_CENTRE, ANCHOR_CENTRE, 240, 110);
@ -2155,7 +2157,7 @@ static struct ScreenVTABLE MenuOptionsScreen_VTABLE = {
MenuOptionsScreen_OnResize, MenuOptionsScreen_ContextLost, NULL,
};
struct Screen* MenuOptionsScreen_MakeInstance(struct Widget** widgets, int count, struct ButtonWidget* buttons, Event_Void_Callback contextRecreated,
struct InputValidator* validators, const char** defaultValues, const char** descriptions, int descsCount) {
struct MenuInputDesc* descs, const char** descriptions, int descsCount) {
struct MenuOptionsScreen* s = &MenuOptionsScreen_Instance;
s->handlesAllInput = true;
s->closable = true;
@ -2168,8 +2170,7 @@ struct Screen* MenuOptionsScreen_MakeInstance(struct Widget** widgets, int count
s->VTABLE->ContextRecreated = contextRecreated;
s->buttons = buttons;
s->validators = validators;
s->defaultValues = defaultValues;
s->descs = descs;
s->descriptions = descriptions;
s->descriptionsCount = descsCount;
@ -2271,14 +2272,14 @@ static void ClassicOptionsScreen_ContextRecreated(void* screen) {
struct Screen* ClassicOptionsScreen_MakeInstance(void) {
static struct ButtonWidget buttons[11];
static struct InputValidator validators[Array_Elems(buttons)];
static struct MenuInputDesc descs[Array_Elems(buttons)];
static struct Widget* widgets[Array_Elems(buttons)];
InputValidator_Enum(validators[2], ViewDist_Names, VIEW_COUNT);
InputValidator_Enum(validators[7], FpsLimit_Names, FPS_LIMIT_COUNT);
MenuInput_Enum(descs[2], ViewDist_Names, VIEW_COUNT);
MenuInput_Enum(descs[7], FpsLimit_Names, FPS_LIMIT_COUNT);
return MenuOptionsScreen_MakeInstance(widgets, Array_Elems(widgets), buttons,
ClassicOptionsScreen_ContextRecreated, validators, NULL, NULL, 0);
ClassicOptionsScreen_ContextRecreated, descs, NULL, 0);
}
@ -2359,42 +2360,23 @@ static String String_InitAndClear(STRING_REF char* buffer, int capacity) {
struct Screen* EnvSettingsScreen_MakeInstance(void) {
static struct ButtonWidget buttons[11];
static struct InputValidator validators[Array_Elems(buttons)];
static const char* defaultValues[Array_Elems(buttons)];
static struct MenuInputDesc descs[Array_Elems(buttons)];
static struct Widget* widgets[Array_Elems(buttons) + 3];
static char cloudHeightBuffer[STRING_INT_CHARS];
static char edgeHeightBuffer[STRING_INT_CHARS];
String cloudHeight, edgeHeight;
MenuInput_Hex(descs[0], Env_DefaultCloudsCol);
MenuInput_Hex(descs[1], Env_DefaultSkyCol);
MenuInput_Hex(descs[2], Env_DefaultFogCol);
MenuInput_Float(descs[3], 0, 1000, 1);
MenuInput_Int(descs[4], -10000, 10000, World.Height + 2);
cloudHeight = String_InitAndClear(cloudHeightBuffer, STRING_INT_CHARS);
String_AppendInt(&cloudHeight, World.Height + 2);
edgeHeight = String_InitAndClear(edgeHeightBuffer, STRING_INT_CHARS);
String_AppendInt(&edgeHeight, World.Height / 2);
InputValidator_Hex(validators[0]);
defaultValues[0] = ENV_DEFAULT_CLOUDSCOL_HEX;
InputValidator_Hex(validators[1]);
defaultValues[1] = ENV_DEFAULT_SKYCOL_HEX;
InputValidator_Hex(validators[2]);
defaultValues[2] = ENV_DEFAULT_FOGCOL_HEX;
InputValidator_Float(validators[3], 0.00f, 1000.00f);
defaultValues[3] = "1";
InputValidator_Int(validators[4], -10000, 10000);
defaultValues[4] = cloudHeightBuffer;
InputValidator_Hex(validators[5]);
defaultValues[5] = ENV_DEFAULT_SUNCOL_HEX;
InputValidator_Hex(validators[6]);
defaultValues[6] = ENV_DEFAULT_SHADOWCOL_HEX;
InputValidator_Enum(validators[7], Weather_Names, Array_Elems(Weather_Names));
InputValidator_Float(validators[8], -100.00f, 100.00f);
defaultValues[8] = "1";
InputValidator_Int(validators[9], -2048, 2048);
defaultValues[9] = edgeHeightBuffer;
MenuInput_Hex(descs[5], Env_DefaultSunCol);
MenuInput_Hex(descs[6], Env_DefaultShadowCol);
MenuInput_Enum(descs[7], Weather_Names, Array_Elems(Weather_Names));
MenuInput_Float(descs[8], -100, 100, 1);
MenuInput_Int(descs[9], -2048, 2048, World.Height / 2);
return MenuOptionsScreen_MakeInstance(widgets, Array_Elems(widgets), buttons,
EnvSettingsScreen_ContextRecreated, validators, defaultValues, NULL, 0);
EnvSettingsScreen_ContextRecreated, descs, NULL, 0);
}
@ -2455,37 +2437,35 @@ static void GraphicsOptionsScreen_ContextRecreated(void* screen) {
struct Screen* GraphicsOptionsScreen_MakeInstance(void) {
static struct ButtonWidget buttons[7];
static struct InputValidator validators[Array_Elems(buttons)];
static const char* defaultValues[Array_Elems(buttons)];
static struct MenuInputDesc descs[Array_Elems(buttons)];
static struct Widget* widgets[Array_Elems(buttons) + 3];
static const char* descs[Array_Elems(buttons)];
descs[0] = \
static const char* extDescs[Array_Elems(buttons)];
extDescs[0] = \
"&eVSync: &fNumber of frames rendered is at most the monitor's refresh rate.\n" \
"&e30/60/120/144 FPS: &fRenders 30/60/120/144 frames at most each second.\n" \
"&eNoLimit: &fRenders as many frames as possible each second.\n" \
"&cUsing NoLimit mode is discouraged.";
descs[2] = "&cNote: &eSmooth lighting is still experimental and can heavily reduce performance.";
descs[3] = \
extDescs[2] = "&cNote: &eSmooth lighting is still experimental and can heavily reduce performance.";
extDescs[3] = \
"&eNone: &fNo names of players are drawn.\n" \
"&eHovered: &fName of the targeted player is drawn see-through.\n" \
"&eAll: &fNames of all other players are drawn normally.\n" \
"&eAllHovered: &fAll names of players are drawn see-through.\n" \
"&eAllUnscaled: &fAll names of players are drawn see-through without scaling.";
descs[4] = \
extDescs[4] = \
"&eNone: &fNo entity shadows are drawn.\n" \
"&eSnapToBlock: &fA square shadow is shown on block you are directly above.\n" \
"&eCircle: &fA circular shadow is shown across the blocks you are above.\n" \
"&eCircleAll: &fA circular shadow is shown underneath all entities.";
InputValidator_Enum(validators[0], FpsLimit_Names, FPS_LIMIT_COUNT);
InputValidator_Int(validators[1], 8, 4096);
defaultValues[1] = "512";
InputValidator_Enum(validators[3], NameMode_Names, NAME_MODE_COUNT);
InputValidator_Enum(validators[4], ShadowMode_Names, SHADOW_MODE_COUNT);
MenuInput_Enum(descs[0], FpsLimit_Names, FPS_LIMIT_COUNT);
MenuInput_Int(descs[1], 8, 4096, 512);
MenuInput_Enum(descs[3], NameMode_Names, NAME_MODE_COUNT);
MenuInput_Enum(descs[4], ShadowMode_Names, SHADOW_MODE_COUNT);
return MenuOptionsScreen_MakeInstance(widgets, Array_Elems(widgets), buttons,
GraphicsOptionsScreen_ContextRecreated, validators, defaultValues, descs, Array_Elems(descs));
GraphicsOptionsScreen_ContextRecreated, descs, extDescs, Array_Elems(extDescs));
}
@ -2569,21 +2549,16 @@ static void GuiOptionsScreen_ContextRecreated(void* screen) {
struct Screen* GuiOptionsScreen_MakeInstance(void) {
static struct ButtonWidget buttons[11];
static struct InputValidator validators[Array_Elems(buttons)];
static const char* defaultValues[Array_Elems(buttons)];
static struct MenuInputDesc descs[Array_Elems(buttons)];
static struct Widget* widgets[Array_Elems(buttons) + 3];
InputValidator_Float(validators[2], 0.25f, 4.00f);
defaultValues[2] = "1";
InputValidator_Float(validators[3], 0.25f, 4.00f);
defaultValues[3] = "1";
InputValidator_Float(validators[6], 0.25f, 4.00f);
defaultValues[6] = "1";
InputValidator_Int(validators[7], 0, 30);
defaultValues[7] = "10";
MenuInput_Float(descs[2], 0.25f, 4.00f, 1);
MenuInput_Float(descs[3], 0.25f, 4.00f, 1);
MenuInput_Float(descs[6], 0.25f, 4.00f, 1);
MenuInput_Int(descs[7], 0, 30, 10);
return MenuOptionsScreen_MakeInstance(widgets, Array_Elems(widgets), buttons,
GuiOptionsScreen_ContextRecreated, validators, defaultValues, NULL, 0);
GuiOptionsScreen_ContextRecreated, descs, NULL, 0);
}
@ -2718,29 +2693,24 @@ static void HacksSettingsScreen_ContextRecreated(void* screen) {
struct Screen* HacksSettingsScreen_MakeInstance(void) {
static struct ButtonWidget buttons[11];
static struct InputValidator validators[Array_Elems(buttons)];
static const char* defaultValues[Array_Elems(buttons)];
static struct MenuInputDesc descs[Array_Elems(buttons)];
static struct Widget* widgets[Array_Elems(buttons) + 3];
static const char* descs[Array_Elems(buttons)];
descs[2] = "&eIf &fON&e, then the third person cameras will limit\n&etheir zoom distance if they hit a solid block.";
descs[3] = "&eSets how many blocks high you can jump up.\n&eNote: You jump much higher when holding down the Speed key binding.";
descs[7] = \
static const char* extDescs[Array_Elems(buttons)];
extDescs[2] = "&eIf &fON&e, then the third person cameras will limit\n&etheir zoom distance if they hit a solid block.";
extDescs[3] = "&eSets how many blocks high you can jump up.\n&eNote: You jump much higher when holding down the Speed key binding.";
extDescs[7] = \
"&eIf &fON&e, placing blocks that intersect your own position cause\n" \
"&ethe block to be placed, and you to be moved out of the way.\n" \
"&fThis is mainly useful for quick pillaring/towering.";
descs[8] = "&eIf &fOFF&e, you will immediately stop when in noclip\n&emode and no movement keys are held down.";
extDescs[8] = "&eIf &fOFF&e, you will immediately stop when in noclip\n&emode and no movement keys are held down.";
InputValidator_Float(validators[1], 0.10f, 50.00f);
defaultValues[1] = "10";
InputValidator_Float(validators[3], 0.10f, 2048.00f);
/* TODO: User may not always use . for decimal point, need to account for that */
defaultValues[3] = "1.233";
InputValidator_Int(validators[9], 1, 179);
defaultValues[9] = "70";
MenuInput_Float(descs[1], 0.1f, 50, 10);
MenuInput_Float(descs[3], 0.1f, 2048, 1.233f);
MenuInput_Int(descs[9], 1, 179, 70);
struct Screen* s = MenuOptionsScreen_MakeInstance(widgets, Array_Elems(widgets), buttons,
HacksSettingsScreen_ContextRecreated, validators, defaultValues, descs, Array_Elems(buttons));
HacksSettingsScreen_ContextRecreated, descs, extDescs, Array_Elems(extDescs));
s->VTABLE->ContextLost = HacksSettingsScreen_ContextLost;
return s;
}
@ -2818,25 +2788,20 @@ static void MiscOptionsScreen_ContextRecreated(void* screen) {
struct Screen* MiscOptionsScreen_MakeInstance(void) {
static struct ButtonWidget buttons[9];
static struct InputValidator validators[Array_Elems(buttons)];
static const char* defaultValues[Array_Elems(buttons)];
static struct MenuInputDesc descs[Array_Elems(buttons)];
static struct Widget* widgets[Array_Elems(buttons) + 3];
InputValidator_Float(validators[0], 1.00f, 1024.00f);
defaultValues[0] = "5";
InputValidator_Int(validators[1], 0, 100);
defaultValues[1] = "0";
InputValidator_Int(validators[2], 0, 100);
defaultValues[2] = "0";
InputValidator_Int(validators[7], 1, 200);
MenuInput_Float(descs[0], 1, 1024, 5);
MenuInput_Int(descs[1], 0, 100, 0);
MenuInput_Int(descs[2], 0, 100, 0);
#ifdef CC_BUILD_WIN
defaultValues[7] = "40";
MenuInput_Int(descs[7], 1, 200, 40);
#else
defaultValues[7] = "30";
MenuInput_Int(descs[7], 1, 200, 30);
#endif
return MenuOptionsScreen_MakeInstance(widgets, Array_Elems(widgets), buttons,
MiscOptionsScreen_ContextRecreated, validators, defaultValues, NULL, 0);
MiscOptionsScreen_ContextRecreated, descs, NULL, 0);
}
@ -2909,7 +2874,7 @@ struct Screen* NostalgiaScreen_MakeInstance(void) {
static struct Widget* widgets[Array_Elems(buttons) + 1];
return MenuOptionsScreen_MakeInstance(widgets, Array_Elems(widgets), buttons,
NostalgiaScreen_ContextRecreated, NULL, NULL, NULL, 0);
NostalgiaScreen_ContextRecreated, NULL, NULL, 0);
}

View File

@ -1295,111 +1295,124 @@ CC_NOINLINE static void InputWidget_Create(struct InputWidget* w, FontDesc* font
/*########################################################################################################################*
*---------------------------------------------------InputValidator----------------------------------------------------*
*-----------------------------------------------------MenuInputDesc-------------------------------------------------------*
*#########################################################################################################################*/
static void Hex_Range(struct InputValidator* v, String* range) {
static void Hex_Range(struct MenuInputDesc* d, String* range) {
String_AppendConst(range, "&7(#000000 - #FFFFFF)");
}
static bool Hex_ValidChar(struct InputValidator* v, char c) {
static bool Hex_ValidChar(struct MenuInputDesc* d, char c) {
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
}
static bool Hex_ValidString(struct InputValidator* v, const String* s) {
static bool Hex_ValidString(struct MenuInputDesc* d, const String* s) {
return s->length <= 6;
}
static bool Hex_ValidValue(struct InputValidator* v, const String* s) {
static bool Hex_ValidValue(struct MenuInputDesc* d, const String* s) {
PackedCol col;
return PackedCol_TryParseHex(s, &col);
}
struct InputValidatorVTABLE HexValidator_VTABLE = {
Hex_Range, Hex_ValidChar, Hex_ValidString, Hex_ValidValue,
};
static void Int_Range(struct InputValidator* v, String* range) {
String_Format2(range, "&7(%i - %i)", &v->Meta.i.Min, &v->Meta.i.Max);
static void Hex_Default(struct MenuInputDesc* d, String* value) {
PackedCol_ToHex(value, d->meta.h.Default);
}
static bool Int_ValidChar(struct InputValidator* v, char c) {
struct MenuInputVTABLE HexValidator_VTABLE = {
Hex_Range, Hex_ValidChar, Hex_ValidString, Hex_ValidValue, Hex_Default
};
static void Int_Range(struct MenuInputDesc* d, String* range) {
String_Format2(range, "&7(%i - %i)", &d->meta.i.Min, &d->meta.i.Max);
}
static bool Int_ValidChar(struct MenuInputDesc* d, char c) {
return (c >= '0' && c <= '9') || c == '-';
}
static bool Int_ValidString(struct InputValidator* v, const String* s) {
static bool Int_ValidString(struct MenuInputDesc* d, const String* s) {
int value;
if (s->length == 1 && s->buffer[0] == '-') return true; /* input is just a minus sign */
return Convert_ParseInt(s, &value);
}
static bool Int_ValidValue(struct InputValidator* v, const String* s) {
int value, min = v->Meta.i.Min, max = v->Meta.i.Max;
static bool Int_ValidValue(struct MenuInputDesc* d, const String* s) {
int value, min = d->meta.i.Min, max = d->meta.i.Max;
return Convert_ParseInt(s, &value) && min <= value && value <= max;
}
struct InputValidatorVTABLE IntValidator_VTABLE = {
Int_Range, Int_ValidChar, Int_ValidString, Int_ValidValue,
static void Int_Default(struct MenuInputDesc* d, String* value) {
String_AppendInt(value, d->meta.i.Default);
}
struct MenuInputVTABLE IntValidator_VTABLE = {
Int_Range, Int_ValidChar, Int_ValidString, Int_ValidValue, Int_Default
};
static void Seed_Range(struct InputValidator* v, String* range) {
static void Seed_Range(struct MenuInputDesc* d, String* range) {
String_AppendConst(range, "&7(an integer)");
}
static void Seed_NoDefault(struct MenuInputDesc* d, String* value) { }
struct InputValidatorVTABLE SeedValidator_VTABLE = {
Seed_Range, Int_ValidChar, Int_ValidString, Int_ValidValue,
struct MenuInputVTABLE SeedValidator_VTABLE = {
Seed_Range, Int_ValidChar, Int_ValidString, Int_ValidValue, Seed_NoDefault
};
static void Float_Range(struct InputValidator* v, String* range) {
String_Format2(range, "&7(%f2 - %f2)", &v->Meta.f.Min, &v->Meta.f.Max);
static void Float_Range(struct MenuInputDesc* d, String* range) {
String_Format2(range, "&7(%f2 - %f2)", &d->meta.f.Min, &d->meta.f.Max);
}
static bool Float_ValidChar(struct InputValidator* v, char c) {
static bool Float_ValidChar(struct MenuInputDesc* d, char c) {
return (c >= '0' && c <= '9') || c == '-' || c == '.' || c == ',';
}
static bool Float_ValidString(struct InputValidator* v, const String* s) {
static bool Float_ValidString(struct MenuInputDesc* d, const String* s) {
float value;
if (s->length == 1 && Float_ValidChar(v, s->buffer[0])) return true;
if (s->length == 1 && Float_ValidChar(d, s->buffer[0])) return true;
return Convert_ParseFloat(s, &value);
}
static bool Float_ValidValue(struct InputValidator* v, const String* s) {
float value, min = v->Meta.f.Min, max = v->Meta.f.Max;
static bool Float_ValidValue(struct MenuInputDesc* d, const String* s) {
float value, min = d->meta.f.Min, max = d->meta.f.Max;
return Convert_ParseFloat(s, &value) && min <= value && value <= max;
}
struct InputValidatorVTABLE FloatValidator_VTABLE = {
Float_Range, Float_ValidChar, Float_ValidString, Float_ValidValue,
static void Float_Default(struct MenuInputDesc* d, String* value) {
String_AppendFloat(value, d->meta.f.Default, 3);
}
struct MenuInputVTABLE FloatValidator_VTABLE = {
Float_Range, Float_ValidChar, Float_ValidString, Float_ValidValue, Float_Default
};
static void Path_Range(struct InputValidator* v, String* range) {
static void Path_Range(struct MenuInputDesc* d, String* range) {
String_AppendConst(range, "&7(Enter name)");
}
static bool Path_ValidChar(struct InputValidator* v, char c) {
static bool Path_ValidChar(struct MenuInputDesc* d, char c) {
return !(c == '/' || c == '\\' || c == '?' || c == '*' || c == ':'
|| c == '<' || c == '>' || c == '|' || c == '"' || c == '.');
}
static bool Path_ValidString(struct InputValidator* v, const String* s) { return true; }
static bool Path_ValidString(struct MenuInputDesc* d, const String* s) { return true; }
struct InputValidatorVTABLE PathValidator_VTABLE = {
Path_Range, Path_ValidChar, Path_ValidString, Path_ValidString,
struct MenuInputVTABLE PathValidator_VTABLE = {
Path_Range, Path_ValidChar, Path_ValidString, Path_ValidString, Seed_NoDefault
};
static void String_Range(struct InputValidator* v, String* range) {
static void String_Range(struct MenuInputDesc* d, String* range) {
String_AppendConst(range, "&7(Enter text)");
}
static bool String_ValidChar(struct InputValidator* v, char c) {
static bool String_ValidChar(struct MenuInputDesc* d, char c) {
return c != '&';
}
static bool String_ValidString(struct InputValidator* v, const String* s) {
static bool String_ValidString(struct MenuInputDesc* d, const String* s) {
return s->length <= STRING_SIZE;
}
struct InputValidatorVTABLE StringValidator_VTABLE = {
String_Range, String_ValidChar, String_ValidString, String_ValidString,
struct MenuInputVTABLE StringValidator_VTABLE = {
String_Range, String_ValidChar, String_ValidString, String_ValidString, Seed_NoDefault
};
@ -1421,7 +1434,7 @@ static void MenuInputWidget_Render(void* widget, double delta) {
static void MenuInputWidget_RemakeTexture(void* widget) {
String range; char rangeBuffer[STRING_SIZE];
struct MenuInputWidget* w = (struct MenuInputWidget*)widget;
struct InputValidator* v;
struct MenuInputDesc* desc;
struct DrawTextArgs args;
struct Texture* tex;
Size2D size, adjSize;
@ -1435,8 +1448,8 @@ static void MenuInputWidget_RemakeTexture(void* widget) {
w->base.caretAccumulator = 0.0;
String_InitArray(range, rangeBuffer);
v = &w->validator;
v->VTABLE->GetRange(v, &range);
desc = &w->desc;
desc->VTABLE->GetRange(desc, &range);
w->base.width = max(size.Width, w->minWidth);
w->base.height = max(size.Height, w->minHeight);
@ -1467,20 +1480,20 @@ static void MenuInputWidget_RemakeTexture(void* widget) {
static bool MenuInputWidget_AllowedChar(void* widget, char c) {
struct InputWidget* w = (struct InputWidget*)widget;
struct InputValidator* v;
struct MenuInputDesc* desc;
int maxChars;
bool valid;
if (c == '&') return false;
v = &((struct MenuInputWidget*)w)->validator;
desc = &((struct MenuInputWidget*)w)->desc;
if (!v->VTABLE->IsValidChar(v, c)) return false;
if (!desc->VTABLE->IsValidChar(desc, c)) return false;
maxChars = w->GetMaxLines() * INPUTWIDGET_LEN;
if (w->text.length == maxChars) return false;
/* See if the new string is in valid format */
InputWidget_AppendChar(w, c);
valid = v->VTABLE->IsValidString(v, &w->text);
valid = desc->VTABLE->IsValidString(desc, &w->text);
InputWidget_DeleteChar(w);
return valid;
}
@ -1492,13 +1505,13 @@ static struct WidgetVTABLE MenuInputWidget_VTABLE = {
InputWidget_MouseDown, Widget_Mouse, Widget_MouseMove, Widget_MouseScroll,
InputWidget_Reposition,
};
void MenuInputWidget_Create(struct MenuInputWidget* w, int width, int height, const String* text, FontDesc* font, struct InputValidator* validator) {
void MenuInputWidget_Create(struct MenuInputWidget* w, int width, int height, const String* text, FontDesc* font, struct MenuInputDesc* desc) {
InputWidget_Create(&w->base, font, &String_Empty);
w->base.VTABLE = &MenuInputWidget_VTABLE;
w->minWidth = width;
w->minHeight = height;
w->validator = *validator;
w->desc = *desc;
w->base.convertPercents = false;
w->base.padding = 3;

View File

@ -128,50 +128,53 @@ CC_NOINLINE void InputWidget_AppendString(struct InputWidget* w, const String* t
CC_NOINLINE void InputWidget_Append(struct InputWidget* w, char c);
struct InputValidator;
struct InputValidatorVTABLE {
struct MenuInputDesc;
struct MenuInputVTABLE {
/* Returns a description of the range of valid values (e.g. "0 - 100") */
void (*GetRange)(struct InputValidator* v, String* range);
void (*GetRange)(struct MenuInputDesc* d, String* range);
/* Whether the given character is acceptable for this input */
bool (*IsValidChar)(struct InputValidator* v, char c);
bool (*IsValidChar)(struct MenuInputDesc* d, char c);
/* Whether the characters of the given string are acceptable for this input */
/* e.g. for an integer, '-' is only valid for the first character */
bool (*IsValidString)(struct InputValidator* v, const String* s);
bool (*IsValidString)(struct MenuInputDesc* d, const String* s);
/* Whether the characters of the given string produce a valid value */
bool (*IsValidValue)(struct InputValidator* v, const String* s);
bool (*IsValidValue)(struct MenuInputDesc* d, const String* s);
/* Gets the default value for this input. */
void (*GetDefault)(struct MenuInputDesc* d, String* value);
};
struct InputValidator {
struct InputValidatorVTABLE* VTABLE;
struct MenuInputDesc {
struct MenuInputVTABLE* VTABLE;
union {
struct { const char** Names; int Count; } e;
struct { int Min, Max; } i;
struct { float Min, Max; } f;
} Meta;
struct { int Min, Max, Default; } i;
struct { float Min, Max, Default; } f;
struct { PackedCol Default; } h;
} meta;
};
extern struct InputValidatorVTABLE HexValidator_VTABLE;
extern struct InputValidatorVTABLE IntValidator_VTABLE;
extern struct InputValidatorVTABLE SeedValidator_VTABLE;
extern struct InputValidatorVTABLE FloatValidator_VTABLE;
extern struct InputValidatorVTABLE PathValidator_VTABLE;
extern struct InputValidatorVTABLE StringValidator_VTABLE;
extern struct MenuInputVTABLE HexValidator_VTABLE;
extern struct MenuInputVTABLE IntValidator_VTABLE;
extern struct MenuInputVTABLE SeedValidator_VTABLE;
extern struct MenuInputVTABLE FloatValidator_VTABLE;
extern struct MenuInputVTABLE PathValidator_VTABLE;
extern struct MenuInputVTABLE StringValidator_VTABLE;
#define InputValidator_Hex(v) v.VTABLE = &HexValidator_VTABLE;
#define InputValidator_Int(v, lo, hi) v.VTABLE = &IntValidator_VTABLE; v.Meta.i.Min = lo; v.Meta.i.Max = hi;
#define InputValidator_Seed(v) v.VTABLE = &SeedValidator_VTABLE; v.Meta.i.Min = Int32_MinValue; v.Meta.i.Max = Int32_MaxValue;
#define InputValidator_Float(v, lo, hi) v.VTABLE = &FloatValidator_VTABLE; v.Meta.f.Min = lo; v.Meta.f.Max = hi;
#define InputValidator_Path(v) v.VTABLE = &PathValidator_VTABLE;
#define InputValidator_Enum(v, names, count) v.VTABLE = NULL; v.Meta.e.Names = names; v.Meta.e.Count = count;
#define InputValidator_String(v) v.VTABLE = &StringValidator_VTABLE;
#define MenuInput_Hex(v, def) v.VTABLE = &HexValidator_VTABLE; v.meta.h.Default = def;
#define MenuInput_Int(v, lo, hi, def) v.VTABLE = &IntValidator_VTABLE; v.meta.i.Min = lo; v.meta.i.Max = hi; v.meta.i.Default = def;
#define MenuInput_Seed(v) v.VTABLE = &SeedValidator_VTABLE; v.meta.i.Min = Int32_MinValue; v.meta.i.Max = Int32_MaxValue;
#define MenuInput_Float(v, lo, hi, def) v.VTABLE = &FloatValidator_VTABLE; v.meta.f.Min = lo; v.meta.f.Max = hi; v.meta.f.Default = def;
#define MenuInput_Path(v) v.VTABLE = &PathValidator_VTABLE;
#define MenuInput_Enum(v, names, count) v.VTABLE = NULL; v.meta.e.Names = names; v.meta.e.Count = count;
#define MenuInput_String(v) v.VTABLE = &StringValidator_VTABLE;
struct MenuInputWidget {
struct InputWidget base;
int minWidth, minHeight;
struct InputValidator validator;
struct MenuInputDesc desc;
char _textBuffer[INPUTWIDGET_LEN];
};
CC_NOINLINE void MenuInputWidget_Create(struct MenuInputWidget* w, int width, int height, const String* text, FontDesc* font, struct InputValidator* v);
CC_NOINLINE void MenuInputWidget_Create(struct MenuInputWidget* w, int width, int height, const String* text, FontDesc* font, struct MenuInputDesc* d);
struct ChatInputWidget {

View File

@ -117,12 +117,6 @@ extern const char* Weather_Names[3];
extern const PackedCol Env_DefaultSkyCol, Env_DefaultFogCol, Env_DefaultCloudsCol, Env_DefaultSkyboxCol;
extern const PackedCol Env_DefaultSunCol, Env_DefaultShadowCol;
#define ENV_DEFAULT_SKYCOL_HEX "99CCFF"
#define ENV_DEFAULT_FOGCOL_HEX "FFFFFF"
#define ENV_DEFAULT_CLOUDSCOL_HEX "FFFFFF"
#define ENV_DEFAULT_SUNCOL_HEX "FFFFFF"
#define ENV_DEFAULT_SHADOWCOL_HEX "9B9B9B"
/* If url is empty, extracts default texture pack. */
/* Else tries extracting cached texture pack for the given URL, */
/* then asynchronously downloads the texture pack from the given URL. */