From f91d91d6e81194010dc9838091dc0fd71403ceaa Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 11 Feb 2017 00:36:53 +0100 Subject: [PATCH 01/19] - all optionmenu items scriptified, but not integrated yet. --- src/c_bind.cpp | 45 + src/c_cvars.cpp | 50 + src/c_dispatch.cpp | 8 + src/menu/colorpickermenu.cpp | 16 +- src/menu/joystickmenu.cpp | 150 ++- src/menu/menu.cpp | 14 + src/menu/menudef.cpp | 105 +- src/menu/messagebox.cpp | 9 + src/menu/optionmenu.cpp | 9 +- src/menu/optionmenuitems.h | 184 +-- src/menu/videomenu.cpp | 27 +- src/scripting/backend/codegen.cpp | 1 + wadsrc/static/zscript.txt | 6 +- wadsrc/static/zscript/base.txt | 47 + .../static/zscript/menu/colorpickermenu.txt | 41 + wadsrc/static/zscript/menu/joystickmenu.txt | 191 +++ wadsrc/static/zscript/menu/menu.txt | 93 +- wadsrc/static/zscript/menu/menuitembase.txt | 12 +- .../static/zscript/menu/optionmenuitems.txt | 1152 +++++++++++++++++ 19 files changed, 1953 insertions(+), 207 deletions(-) create mode 100644 wadsrc/static/zscript/menu/joystickmenu.txt create mode 100644 wadsrc/static/zscript/menu/optionmenuitems.txt diff --git a/src/c_bind.cpp b/src/c_bind.cpp index 5c1b18323..1c3fd5413 100644 --- a/src/c_bind.cpp +++ b/src/c_bind.cpp @@ -44,6 +44,7 @@ #include "i_system.h" #include "d_event.h" #include "w_wad.h" +#include "templates.h" #include #include @@ -261,6 +262,21 @@ static const char *ConfigKeyName(int keynum) // //============================================================================= +DEFINE_ACTION_FUNCTION(FKeyBindings, SetBind) +{ + PARAM_SELF_STRUCT_PROLOGUE(FKeyBindings); + PARAM_INT(k); + PARAM_STRING(cmd); + self->SetBind(k, cmd); + return 0; +} + +//============================================================================= +// +// +// +//============================================================================= + void C_NameKeys (char *str, int first, int second) { int c = 0; @@ -284,6 +300,16 @@ void C_NameKeys (char *str, int first, int second) *str = '\0'; } +DEFINE_ACTION_FUNCTION(FKeyBindings, NameKeys) +{ + PARAM_PROLOGUE; + PARAM_INT(k1); + PARAM_INT(k2); + char buffer[120]; + C_NameKeys(buffer, k1, k2); + ACTION_RETURN_STRING(buffer); +} + //============================================================================= // // @@ -445,6 +471,17 @@ int FKeyBindings::GetKeysForCommand (const char *cmd, int *first, int *second) return c; } +DEFINE_ACTION_FUNCTION(FKeyBindings, GetKeysForCommand) +{ + PARAM_SELF_STRUCT_PROLOGUE(FKeyBindings); + PARAM_STRING(cmd); + int k1, k2, c; + self->GetKeysForCommand(cmd.GetChars(), &k1, &k2); + if (numret > 0) ret[0].SetInt(k1); + if (numret > 1) ret[1].SetInt(k1); + return MIN(numret, 2); +} + //============================================================================= // // @@ -464,6 +501,14 @@ void FKeyBindings::UnbindACommand (const char *str) } } +DEFINE_ACTION_FUNCTION(FKeyBindings, UnbindACommand) +{ + PARAM_SELF_STRUCT_PROLOGUE(FKeyBindings); + PARAM_STRING(cmd); + self->UnbindACommand(cmd); + return 0; +} + //============================================================================= // // diff --git a/src/c_cvars.cpp b/src/c_cvars.cpp index 768392c6c..ed9b0f29a 100644 --- a/src/c_cvars.cpp +++ b/src/c_cvars.cpp @@ -202,6 +202,36 @@ DEFINE_ACTION_FUNCTION(_CVar, GetString) ACTION_RETURN_STRING(v.String); } +DEFINE_ACTION_FUNCTION(_CVar, SetInt) +{ + PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); + PARAM_INT(val); + UCVarValue v; + v.Int = val; + self->SetGenericRep(v, CVAR_Int); + return 0; +} + +DEFINE_ACTION_FUNCTION(_CVar, SetFloat) +{ + PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); + PARAM_FLOAT(val); + UCVarValue v; + v.Float = val; + self->SetGenericRep(v, CVAR_Float); + return 0; +} + +DEFINE_ACTION_FUNCTION(_CVar, SetString) +{ + PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); + PARAM_STRING(val); + UCVarValue v; + v.String = val.GetChars(); + self->SetGenericRep(v, CVAR_String); + return 0; +} + bool FBaseCVar::ToBool (UCVarValue value, ECVarType type) { switch (type) @@ -643,6 +673,12 @@ void FBaseCVar::DisableCallbacks () m_UseCallback = false; } +DEFINE_ACTION_FUNCTION(_CVar, GetRealType) +{ + PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); + ACTION_RETURN_INT(self->GetRealType()); +} + // // Boolean cvar implementation // @@ -1082,6 +1118,13 @@ void FBaseCVar::ResetToDefault () } } +DEFINE_ACTION_FUNCTION(_CVar, ResetToDefault) +{ + PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); + self->ResetToDefault(); + return 0; +} + // // Flag cvar implementation // @@ -1487,6 +1530,13 @@ FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev) return var; } +DEFINE_ACTION_FUNCTION(_CVar, FindCVar) +{ + PARAM_PROLOGUE; + PARAM_NAME(name); + ACTION_RETURN_POINTER(FindCVar(name, nullptr)); +} + FBaseCVar *FindCVarSub (const char *var_name, int namelen) { FBaseCVar *var; diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index 52ea3d63a..8bd83ed15 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -662,6 +662,14 @@ void C_DoCommand (const char *cmd, int keynum) } } +DEFINE_ACTION_FUNCTION(_Console, DoCommand) +{ + PARAM_PROLOGUE; + PARAM_STRING(cmd); + C_DoCommand(cmd); + return 0; +} + void AddCommandString (char *cmd, int keynum) { char *brkpt; diff --git a/src/menu/colorpickermenu.cpp b/src/menu/colorpickermenu.cpp index 7fc3e2ecd..d337eb82a 100644 --- a/src/menu/colorpickermenu.cpp +++ b/src/menu/colorpickermenu.cpp @@ -81,14 +81,14 @@ public: // This menu uses some featurs that are hard to implement in an external control lump // so it creates its own list of menu items. desc->mItems.Resize(mStartItem+8); - desc->mItems[mStartItem+0] = new DOptionMenuItemStaticText(name, false); - desc->mItems[mStartItem+1] = new DOptionMenuItemStaticText(" ", false); - desc->mItems[mStartItem+2] = new DOptionMenuSliderVar("Red", &mRed, 0, 255, 15, 0); - desc->mItems[mStartItem+3] = new DOptionMenuSliderVar("Green", &mGreen, 0, 255, 15, 0); - desc->mItems[mStartItem+4] = new DOptionMenuSliderVar("Blue", &mBlue, 0, 255, 15, 0); - desc->mItems[mStartItem+5] = new DOptionMenuItemStaticText(" ", false); - desc->mItems[mStartItem+6] = new DOptionMenuItemCommand("Undo changes", "undocolorpic"); - desc->mItems[mStartItem+7] = new DOptionMenuItemStaticText(" ", false); + desc->mItems[mStartItem+0] = new DOptionMenuItemStaticText_(name, false); + desc->mItems[mStartItem+1] = new DOptionMenuItemStaticText_(" ", false); + desc->mItems[mStartItem+2] = new DOptionMenuSliderVar_("Red", &mRed, 0, 255, 15, 0); + desc->mItems[mStartItem+3] = new DOptionMenuSliderVar_("Green", &mGreen, 0, 255, 15, 0); + desc->mItems[mStartItem+4] = new DOptionMenuSliderVar_("Blue", &mBlue, 0, 255, 15, 0); + desc->mItems[mStartItem+5] = new DOptionMenuItemStaticText_(" ", false); + desc->mItems[mStartItem+6] = new DOptionMenuItemCommand_("Undo changes", "undocolorpic"); + desc->mItems[mStartItem+7] = new DOptionMenuItemStaticText_(" ", false); for (auto &p : desc->mItems) { GC::WriteBarrier(p); diff --git a/src/menu/joystickmenu.cpp b/src/menu/joystickmenu.cpp index 61f81bb60..50f49463c 100644 --- a/src/menu/joystickmenu.cpp +++ b/src/menu/joystickmenu.cpp @@ -58,6 +58,74 @@ static TArray Joysticks; IJoystickConfig *SELECTED_JOYSTICK; +DEFINE_ACTION_FUNCTION(DMenu, GetCurrentJoystickConfig) +{ + ACTION_RETURN_POINTER(SELECTED_JOYSTICK); +} + +DEFINE_ACTION_FUNCTION(IJoystickConfig, GetSensitivity) +{ + PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig); + ACTION_RETURN_FLOAT(self->GetSensitivity()); +} + +DEFINE_ACTION_FUNCTION(IJoystickConfig, SetSensitivity) +{ + PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig); + PARAM_FLOAT(sens); + self->SetSensitivity((float)sens); + return 0; +} + +DEFINE_ACTION_FUNCTION(IJoystickConfig, GetAxisScale) +{ + PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig); + PARAM_INT(axis); + ACTION_RETURN_FLOAT(self->GetAxisScale(axis)); +} + +DEFINE_ACTION_FUNCTION(IJoystickConfig, SetAxisScale) +{ + PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig); + PARAM_INT(axis); + PARAM_FLOAT(sens); + self->SetAxisScale(axis, (float)sens); + return 0; +} + +DEFINE_ACTION_FUNCTION(IJoystickConfig, GetAxisDeadZone) +{ + PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig); + PARAM_INT(axis); + ACTION_RETURN_FLOAT(self->GetAxisDeadZone(axis)); +} + +DEFINE_ACTION_FUNCTION(IJoystickConfig, SetAxisDeadZone) +{ + PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig); + PARAM_INT(axis); + PARAM_FLOAT(dz); + self->SetAxisDeadZone(axis, (float)dz); + return 0; +} + +DEFINE_ACTION_FUNCTION(IJoystickConfig, GetAxisMap) +{ + PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig); + PARAM_INT(axis); + ACTION_RETURN_INT(self->GetAxisMap(axis)); +} + +DEFINE_ACTION_FUNCTION(IJoystickConfig, SetAxisMap) +{ + PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig); + PARAM_INT(axis); + PARAM_INT(map); + self->SetAxisMap(axis, (EJoyAxis)map); + return 0; +} + + DOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy); //============================================================================= @@ -66,11 +134,11 @@ DOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy); // //============================================================================= -class DOptionMenuSliderJoySensitivity : public DOptionMenuSliderBase +class DOptionMenuSliderJoySensitivity_ : public DOptionMenuSliderBase_ { public: - DOptionMenuSliderJoySensitivity(const char *label, double min, double max, double step, int showval) - : DOptionMenuSliderBase(label, min, max, step, showval) + DOptionMenuSliderJoySensitivity_(const char *label, double min, double max, double step, int showval) + : DOptionMenuSliderBase_(label, min, max, step, showval) { } @@ -91,14 +159,14 @@ public: // //============================================================================= -class DOptionMenuSliderJoyScale : public DOptionMenuSliderBase +class DOptionMenuSliderJoyScale_ : public DOptionMenuSliderBase_ { int mAxis; int mNeg; public: - DOptionMenuSliderJoyScale(const char *label, int axis, double min, double max, double step, int showval) - : DOptionMenuSliderBase(label, min, max, step, showval) + DOptionMenuSliderJoyScale_(const char *label, int axis, double min, double max, double step, int showval) + : DOptionMenuSliderBase_(label, min, max, step, showval) { mAxis = axis; mNeg = 1; @@ -123,14 +191,14 @@ public: // //============================================================================= -class DOptionMenuSliderJoyDeadZone : public DOptionMenuSliderBase +class DOptionMenuSliderJoyDeadZone_ : public DOptionMenuSliderBase_ { int mAxis; int mNeg; public: - DOptionMenuSliderJoyDeadZone(const char *label, int axis, double min, double max, double step, int showval) - : DOptionMenuSliderBase(label, min, max, step, showval) + DOptionMenuSliderJoyDeadZone_(const char *label, int axis, double min, double max, double step, int showval) + : DOptionMenuSliderBase_(label, min, max, step, showval) { mAxis = axis; mNeg = 1; @@ -155,13 +223,13 @@ public: // //============================================================================= -class DOptionMenuItemJoyMap : public DOptionMenuItemOptionBase +class DOptionMenuItemJoyMap_ : public DOptionMenuItemOptionBase_ { int mAxis; public: - DOptionMenuItemJoyMap(const char *label, int axis, const char *values, int center) - : DOptionMenuItemOptionBase(label, "none", values, NULL, center) + DOptionMenuItemJoyMap_(const char *label, int axis, const char *values, int center) + : DOptionMenuItemOptionBase_(label, "none", values, NULL, center) { mAxis = axis; } @@ -206,13 +274,13 @@ public: // //============================================================================= -class DOptionMenuItemInverter : public DOptionMenuItemOptionBase +class DOptionMenuItemInverter_ : public DOptionMenuItemOptionBase_ { int mAxis; public: - DOptionMenuItemInverter(const char *label, int axis, int center) - : DOptionMenuItemOptionBase(label, "none", "YesNo", NULL, center) + DOptionMenuItemInverter_(const char *label, int axis, int center) + : DOptionMenuItemOptionBase_(label, "none", "YesNo", NULL, center) { mAxis = axis; } @@ -244,13 +312,13 @@ IMPLEMENT_CLASS(DJoystickConfigMenu, false, false) // //============================================================================= -class DOptionMenuItemJoyConfigMenu : public DOptionMenuItemSubmenu +class DOptionMenuItemJoyConfigMenu_ : public DOptionMenuItemSubmenu_ { - DECLARE_CLASS(DOptionMenuItemJoyConfigMenu, DOptionMenuItemSubmenu) + DECLARE_CLASS(DOptionMenuItemJoyConfigMenu_, DOptionMenuItemSubmenu_) IJoystickConfig *mJoy; public: - DOptionMenuItemJoyConfigMenu(const char *label = nullptr, IJoystickConfig *joy = nullptr) - : DOptionMenuItemSubmenu(label, "JoystickConfigMenu") + DOptionMenuItemJoyConfigMenu_(const char *label = nullptr, IJoystickConfig *joy = nullptr) + : DOptionMenuItemSubmenu_(label, "JoystickConfigMenu") { mJoy = joy; } @@ -258,11 +326,11 @@ public: bool Activate() { UpdateJoystickConfigMenu(mJoy); - return DOptionMenuItemSubmenu::Activate(); + return DOptionMenuItemSubmenu_::Activate(); } }; -IMPLEMENT_CLASS(DOptionMenuItemJoyConfigMenu, false, false) +IMPLEMENT_CLASS(DOptionMenuItemJoyConfigMenu_, false, false) /*======================================= @@ -282,7 +350,7 @@ DOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy) if (joy == NULL) { opt->mTitle = "Configure Controller"; - it = new DOptionMenuItemStaticText("Invalid controller specified for menu", false); + it = new DOptionMenuItemStaticText_("Invalid controller specified for menu", false); opt->mItems.Push(it); } else @@ -291,34 +359,34 @@ DOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy) SELECTED_JOYSTICK = joy; - it = new DOptionMenuSliderJoySensitivity("Overall sensitivity", 0, 2, 0.1, 3); + it = new DOptionMenuSliderJoySensitivity_("Overall sensitivity", 0, 2, 0.1, 3); opt->mItems.Push(it); - it = new DOptionMenuItemStaticText(" ", false); + it = new DOptionMenuItemStaticText_(" ", false); opt->mItems.Push(it); if (joy->GetNumAxes() > 0) { - it = new DOptionMenuItemStaticText("Axis Configuration", true); + it = new DOptionMenuItemStaticText_("Axis Configuration", true); opt->mItems.Push(it); for (int i = 0; i < joy->GetNumAxes(); ++i) { - it = new DOptionMenuItemStaticText(" ", false); + it = new DOptionMenuItemStaticText_(" ", false); opt->mItems.Push(it); - it = new DOptionMenuItemJoyMap(joy->GetAxisName(i), i, "JoyAxisMapNames", false); + it = new DOptionMenuItemJoyMap_(joy->GetAxisName(i), i, "JoyAxisMapNames", false); opt->mItems.Push(it); - it = new DOptionMenuSliderJoyScale("Overall sensitivity", i, 0, 4, 0.1, 3); + it = new DOptionMenuSliderJoyScale_("Overall sensitivity", i, 0, 4, 0.1, 3); opt->mItems.Push(it); - it = new DOptionMenuItemInverter("Invert", i, false); + it = new DOptionMenuItemInverter_("Invert", i, false); opt->mItems.Push(it); - it = new DOptionMenuSliderJoyDeadZone("Dead Zone", i, 0, 0.9, 0.05, 3); + it = new DOptionMenuSliderJoyDeadZone_("Dead Zone", i, 0, 0.9, 0.05, 3); opt->mItems.Push(it); } } else { - it = new DOptionMenuItemStaticText("No configurable axes", false); + it = new DOptionMenuItemStaticText_("No configurable axes", false); opt->mItems.Push(it); } } @@ -368,40 +436,40 @@ void UpdateJoystickMenu(IJoystickConfig *selected) } // Todo: Block joystick for changing this one. - it = new DOptionMenuItemOption("Enable controller support", "use_joystick", "YesNo", NULL, false); + it = new DOptionMenuItemOption_("Enable controller support", "use_joystick", "YesNo", NULL, false); opt->mItems.Push(it); #ifdef _WIN32 - it = new DOptionMenuItemOption("Enable DirectInput controllers", "joy_dinput", "YesNo", NULL, false); + it = new DOptionMenuItemOption_("Enable DirectInput controllers", "joy_dinput", "YesNo", NULL, false); opt->mItems.Push(it); - it = new DOptionMenuItemOption("Enable XInput controllers", "joy_xinput", "YesNo", NULL, false); + it = new DOptionMenuItemOption_("Enable XInput controllers", "joy_xinput", "YesNo", NULL, false); opt->mItems.Push(it); - it = new DOptionMenuItemOption("Enable raw PlayStation 2 adapters", "joy_ps2raw", "YesNo", NULL, false); + it = new DOptionMenuItemOption_("Enable raw PlayStation 2 adapters", "joy_ps2raw", "YesNo", NULL, false); opt->mItems.Push(it); #endif - it = new DOptionMenuItemStaticText(" ", false); + it = new DOptionMenuItemStaticText_(" ", false); opt->mItems.Push(it); if (Joysticks.Size() == 0) { - it = new DOptionMenuItemStaticText("No controllers detected", false); + it = new DOptionMenuItemStaticText_("No controllers detected", false); opt->mItems.Push(it); if (!use_joystick) { - it = new DOptionMenuItemStaticText("Controller support must be", false); + it = new DOptionMenuItemStaticText_("Controller support must be", false); opt->mItems.Push(it); - it = new DOptionMenuItemStaticText("enabled to detect any", false); + it = new DOptionMenuItemStaticText_("enabled to detect any", false); opt->mItems.Push(it); } } else { - it = new DOptionMenuItemStaticText("Configure controllers:", false); + it = new DOptionMenuItemStaticText_("Configure controllers:", false); opt->mItems.Push(it); for (int i = 0; i < (int)Joysticks.Size(); ++i) { - it = new DOptionMenuItemJoyConfigMenu(Joysticks[i]->GetName(), Joysticks[i]); + it = new DOptionMenuItemJoyConfigMenu_(Joysticks[i]->GetName(), Joysticks[i]); opt->mItems.Push(it); if (i == itemnum) opt->mSelectedItem = opt->mItems.Size(); } diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 1f3ac189e..62ea9daa3 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -70,6 +70,12 @@ CVAR(Int, m_use_mouse, 2, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Int, m_show_backbutton, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) DMenu *DMenu::CurrentMenu; + +DEFINE_ACTION_FUNCTION(DMenu, GetCurrentMenu) +{ + ACTION_RETURN_POINTER(DMenu::CurrentMenu); +} + int DMenu::MenuTime; FGameStartup GameStartupInfo; @@ -559,6 +565,14 @@ void M_SetMenu(FName menu, int param) M_ClearMenus(); } +DEFINE_ACTION_FUNCTION(DMenu, SetMenu) +{ + PARAM_PROLOGUE; + PARAM_NAME(menu); + PARAM_INT(mparam); + M_SetMenu(menu, mparam); + return 0; +} //============================================================================= // // diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 835189317..1a7657676 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -54,6 +54,8 @@ #include "optionmenuitems.h" + + void ClearSaveGames(); MenuDescriptorList MenuDescriptors; @@ -65,6 +67,71 @@ bool mustPrintErrors; void I_BuildALDeviceList(FOptionValues *opt); +DEFINE_ACTION_FUNCTION(FOptionValues, GetCount) +{ + PARAM_PROLOGUE; + PARAM_NAME(grp); + int cnt = 0; + FOptionValues **pGrp = OptionValues.CheckKey(grp); + if (pGrp != nullptr) + { + cnt = (*pGrp)->mValues.Size(); + } + ACTION_RETURN_INT(cnt); +} + +DEFINE_ACTION_FUNCTION(FOptionValues, GetValue) +{ + PARAM_PROLOGUE; + PARAM_NAME(grp); + PARAM_UINT(index); + double val = 0; + FOptionValues **pGrp = OptionValues.CheckKey(grp); + if (pGrp != nullptr) + { + if (index < (*pGrp)->mValues.Size()) + { + val = (*pGrp)->mValues[index].Value; + } + } + ACTION_RETURN_FLOAT(val); +} + +DEFINE_ACTION_FUNCTION(FOptionValues, GetTextValue) +{ + PARAM_PROLOGUE; + PARAM_NAME(grp); + PARAM_UINT(index); + FString val; + FOptionValues **pGrp = OptionValues.CheckKey(grp); + if (pGrp != nullptr) + { + if (index < (*pGrp)->mValues.Size()) + { + val = (*pGrp)->mValues[index].TextValue; + } + } + ACTION_RETURN_STRING(val); +} + +DEFINE_ACTION_FUNCTION(FOptionValues, GetText) +{ + PARAM_PROLOGUE; + PARAM_NAME(grp); + PARAM_UINT(index); + FString val; + FOptionValues **pGrp = OptionValues.CheckKey(grp); + if (pGrp != nullptr) + { + if (index < (*pGrp)->mValues.Size()) + { + val = (*pGrp)->mValues[index].Text; + } + } + ACTION_RETURN_STRING(val); +} + + static void DeinitMenus() { { @@ -724,7 +791,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) FString label = sc.String; sc.MustGetStringName(","); sc.MustGetString(); - DOptionMenuItem *it = new DOptionMenuItemSubmenu(label, sc.String); + DOptionMenuItem *it = new DOptionMenuItemSubmenu_(label, sc.String); desc->mItems.Push(it); } else if (sc.Compare("Option")) @@ -749,7 +816,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) center = sc.Number; } } - DOptionMenuItem *it = new DOptionMenuItemOption(label, cvar, values, check, center); + DOptionMenuItem *it = new DOptionMenuItemOption_(label, cvar, values, check, center); desc->mItems.Push(it); } else if (sc.Compare("Command")) @@ -758,7 +825,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) FString label = sc.String; sc.MustGetStringName(","); sc.MustGetString(); - DOptionMenuItem *it = new DOptionMenuItemCommand(label, sc.String); + DOptionMenuItem *it = new DOptionMenuItemCommand_(label, sc.String); desc->mItems.Push(it); } else if (sc.Compare("SafeCommand")) @@ -775,7 +842,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) sc.MustGetString(); prompt = sc.String; } - DOptionMenuItem *it = new DOptionMenuItemSafeCommand(label, command, prompt); + DOptionMenuItem *it = new DOptionMenuItemSafeCommand_(label, command, prompt); desc->mItems.Push(it); } else if (sc.Compare("Control") || sc.Compare("MapControl")) @@ -785,7 +852,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) FString label = sc.String; sc.MustGetStringName(","); sc.MustGetString(); - DOptionMenuItem *it = new DOptionMenuItemControl(label, sc.String, map? &AutomapBindings : &Bindings); + DOptionMenuItem *it = new DOptionMenuItemControl_(label, sc.String, map? &AutomapBindings : &Bindings); desc->mItems.Push(it); } else if (sc.Compare("ColorPicker")) @@ -794,7 +861,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) FString label = sc.String; sc.MustGetStringName(","); sc.MustGetString(); - DOptionMenuItem *it = new DOptionMenuItemColorPicker(label, sc.String); + DOptionMenuItem *it = new DOptionMenuItemColorPicker_(label, sc.String); desc->mItems.Push(it); } else if (sc.Compare("StaticText")) @@ -802,7 +869,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) sc.MustGetString(); FString label = sc.String; EColorRange cr = ParseOptionColor(sc, desc); - DOptionMenuItem *it = new DOptionMenuItemStaticText(label, cr); + DOptionMenuItem *it = new DOptionMenuItemStaticText_(label, cr); desc->mItems.Push(it); } else if (sc.Compare("StaticTextSwitchable")) @@ -816,7 +883,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) sc.MustGetString(); FName action = sc.String; EColorRange cr = ParseOptionColor(sc, desc); - DOptionMenuItem *it = new DOptionMenuItemStaticTextSwitchable(label, label2, action, cr); + DOptionMenuItem *it = new DOptionMenuItemStaticTextSwitchable_(label, label2, action, cr); desc->mItems.Push(it); } else if (sc.Compare("Slider")) @@ -841,13 +908,13 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) sc.MustGetNumber(); showvalue = sc.Number; } - DOptionMenuItem *it = new DOptionMenuSliderCVar(text, action, min, max, step, showvalue); + DOptionMenuItem *it = new DOptionMenuSliderCVar_(text, action, min, max, step, showvalue); desc->mItems.Push(it); } else if (sc.Compare("screenresolution")) { sc.MustGetString(); - DOptionMenuItem *it = new DOptionMenuScreenResolutionLine(sc.String); + DOptionMenuItem *it = new DOptionMenuScreenResolutionLine_(sc.String); desc->mItems.Push(it); } // [TP] -- Text input widget @@ -866,7 +933,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) check = sc.String; } - DOptionMenuItem* it = new DOptionMenuTextField( label, cvar, check ); + DOptionMenuItem* it = new DOptionMenuTextField_( label, cvar, check ); desc->mItems.Push( it ); } // [TP] -- Number input widget @@ -903,7 +970,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) } } - DOptionMenuItem* it = new DOptionMenuNumberField( label, cvar, + DOptionMenuItem* it = new DOptionMenuNumberField_( label, cvar, minimum, maximum, step, check ); desc->mItems.Push( it ); } @@ -1118,7 +1185,7 @@ static void BuildEpisodeMenu() GC::WriteBarrier(od); for(unsigned i = 0; i < AllEpisodes.Size(); i++) { - DOptionMenuItemSubmenu *it = new DOptionMenuItemSubmenu(AllEpisodes[i].mEpisodeName, "Skillmenu", i); + DOptionMenuItemSubmenu_ *it = new DOptionMenuItemSubmenu_(AllEpisodes[i].mEpisodeName, "Skillmenu", i); od->mItems.Push(it); GC::WriteBarrier(od, it); } @@ -1257,13 +1324,13 @@ static void BuildPlayerclassMenu() const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type); if (pname != nullptr) { - DOptionMenuItemSubmenu *it = new DOptionMenuItemSubmenu(pname, "Episodemenu", i); + DOptionMenuItemSubmenu_ *it = new DOptionMenuItemSubmenu_(pname, "Episodemenu", i); od->mItems.Push(it); GC::WriteBarrier(od, it); } } } - DOptionMenuItemSubmenu *it = new DOptionMenuItemSubmenu("Random", "Episodemenu", -1); + DOptionMenuItemSubmenu_ *it = new DOptionMenuItemSubmenu_("Random", "Episodemenu", -1); od->mItems.Push(it); GC::WriteBarrier(od, it); } @@ -1344,14 +1411,14 @@ static void InitKeySections() for (unsigned i = 0; i < KeySections.Size(); i++) { FKeySection *sect = &KeySections[i]; - DOptionMenuItem *item = new DOptionMenuItemStaticText(" ", false); + DOptionMenuItem *item = new DOptionMenuItemStaticText_(" ", false); menu->mItems.Push(item); - item = new DOptionMenuItemStaticText(sect->mTitle, true); + item = new DOptionMenuItemStaticText_(sect->mTitle, true); menu->mItems.Push(item); for (unsigned j = 0; j < sect->mActions.Size(); j++) { FKeyAction *act = §->mActions[j]; - item = new DOptionMenuItemControl(act->mTitle, act->mAction, &Bindings); + item = new DOptionMenuItemControl_(act->mTitle, act->mAction, &Bindings); menu->mItems.Push(item); } } @@ -1542,7 +1609,7 @@ fail: { pItemText = skill.MenuNamesForPlayerClass.CheckKey(gs->PlayerClass); } - li = new DOptionMenuItemSubmenu(pItemText? *pItemText : skill.MenuName, action, i); + li = new DOptionMenuItemSubmenu_(pItemText? *pItemText : skill.MenuName, action, i); od->mItems.Push(li); GC::WriteBarrier(od, li); if (!done) diff --git a/src/menu/messagebox.cpp b/src/menu/messagebox.cpp index 8494d2192..a910ad3ad 100644 --- a/src/menu/messagebox.cpp +++ b/src/menu/messagebox.cpp @@ -725,3 +725,12 @@ void M_StartMessage(const char *message, int messagemode, FName action) M_ActivateMenu(newmenu); } +DEFINE_ACTION_FUNCTION(DMenu, StartMessage) +{ + PARAM_PROLOGUE; + PARAM_STRING(msg); + PARAM_INT(mode); + PARAM_NAME_DEF(action); + M_StartMessage(msg, mode, action); + return 0; +} \ No newline at end of file diff --git a/src/menu/optionmenu.cpp b/src/menu/optionmenu.cpp index 40524ac0c..a7f4acc7f 100644 --- a/src/menu/optionmenu.cpp +++ b/src/menu/optionmenu.cpp @@ -64,6 +64,7 @@ void M_DrawConText (int color, int x, int y, const char *str) TAG_DONE); } + IMPLEMENT_CLASS(DOptionMenu, false, false) IMPLEMENT_POINTERS_START(DOptionMenu) @@ -475,13 +476,6 @@ void DOptionMenu::Drawer () Super::Drawer(); } - -//============================================================================= -// -// base class for menu items -// -//============================================================================= - int DOptionMenuItem::Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected) { return indent; @@ -527,7 +521,6 @@ void DOptionMenuItem::drawLabel(int indent, int y, EColorRange color, bool graye } - void DOptionMenuDescriptor::CalcIndent() { // calculate the menu indent diff --git a/src/menu/optionmenuitems.h b/src/menu/optionmenuitems.h index a7c16ec8c..6b3fd2e26 100644 --- a/src/menu/optionmenuitems.h +++ b/src/menu/optionmenuitems.h @@ -46,15 +46,15 @@ void M_SetVideoMode(); // //============================================================================= -class DOptionMenuItemSubmenu : public DOptionMenuItem +class DOptionMenuItemSubmenu_ : public DOptionMenuItem { - DECLARE_CLASS(DOptionMenuItemSubmenu, DOptionMenuItem) + DECLARE_CLASS(DOptionMenuItemSubmenu_, DOptionMenuItem) int mParam; protected: - DOptionMenuItemSubmenu() { } + DOptionMenuItemSubmenu_() { } public: - DOptionMenuItemSubmenu(const char *label, const char *menu, int param = 0) + DOptionMenuItemSubmenu_(const char *label, const char *menu, int param = 0) : DOptionMenuItem(label, menu) { mParam = param; @@ -75,7 +75,7 @@ public: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuItemSubmenu, false, false) +IMPLEMENT_CLASS(DOptionMenuItemSubmenu_, false, false) #endif //============================================================================= @@ -84,14 +84,14 @@ IMPLEMENT_CLASS(DOptionMenuItemSubmenu, false, false) // //============================================================================= -class DOptionMenuItemCommand : public DOptionMenuItemSubmenu +class DOptionMenuItemCommand_ : public DOptionMenuItemSubmenu_ { - DECLARE_CLASS(DOptionMenuItemCommand, DOptionMenuItem) + DECLARE_CLASS(DOptionMenuItemCommand_, DOptionMenuItem) protected: - DOptionMenuItemCommand() { } + DOptionMenuItemCommand_() { } public: - DOptionMenuItemCommand(const char *label, const char *menu) - : DOptionMenuItemSubmenu(label, menu) + DOptionMenuItemCommand_(const char *label, const char *menu) + : DOptionMenuItemSubmenu_(label, menu) { } @@ -105,7 +105,7 @@ public: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuItemCommand, false, false) +IMPLEMENT_CLASS(DOptionMenuItemCommand_, false, false) #endif //============================================================================= @@ -114,17 +114,17 @@ IMPLEMENT_CLASS(DOptionMenuItemCommand, false, false) // //============================================================================= -class DOptionMenuItemSafeCommand : public DOptionMenuItemCommand +class DOptionMenuItemSafeCommand_ : public DOptionMenuItemCommand_ { - DECLARE_CLASS(DOptionMenuItemSafeCommand, DOptionMenuItemCommand) + DECLARE_CLASS(DOptionMenuItemSafeCommand_, DOptionMenuItemCommand_) // action is a CCMD - DOptionMenuItemSafeCommand() { } + DOptionMenuItemSafeCommand_() { } protected: FString mPrompt; public: - DOptionMenuItemSafeCommand(const char *label, const char *menu, const char *prompt) - : DOptionMenuItemCommand(label, menu) + DOptionMenuItemSafeCommand_(const char *label, const char *menu, const char *prompt) + : DOptionMenuItemCommand_(label, menu) , mPrompt(prompt) { } @@ -136,7 +136,7 @@ public: C_DoCommand(mAction); return true; } - return DOptionMenuItemCommand::MenuEvent(mkey, fromcontroller); + return DOptionMenuItemCommand_::MenuEvent(mkey, fromcontroller); } bool Activate() @@ -165,7 +165,7 @@ public: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuItemSafeCommand, false, false) +IMPLEMENT_CLASS(DOptionMenuItemSafeCommand_, false, false) #endif //============================================================================= @@ -174,16 +174,16 @@ IMPLEMENT_CLASS(DOptionMenuItemSafeCommand, false, false) // //============================================================================= -class DOptionMenuItemOptionBase : public DOptionMenuItem +class DOptionMenuItemOptionBase_ : public DOptionMenuItem { - DECLARE_ABSTRACT_CLASS(DOptionMenuItemOptionBase, DOptionMenuItem) + DECLARE_ABSTRACT_CLASS(DOptionMenuItemOptionBase_, DOptionMenuItem) protected: // action is a CVAR FName mValues; // Entry in OptionValues table FBaseCVar *mGrayCheck; int mCenter; - DOptionMenuItemOptionBase() {} + DOptionMenuItemOptionBase_() {} public: enum @@ -191,7 +191,7 @@ public: OP_VALUES = 0x11001 }; - DOptionMenuItemOptionBase(const char *label, const char *menu, const char *values, const char *graycheck, int center) + DOptionMenuItemOptionBase_(const char *label, const char *menu, const char *values, const char *graycheck, int center) : DOptionMenuItem(label, menu) { mValues = values; @@ -286,7 +286,7 @@ public: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuItemOptionBase, true, false) +IMPLEMENT_CLASS(DOptionMenuItemOptionBase_, true, false) #endif //============================================================================= @@ -295,17 +295,17 @@ IMPLEMENT_CLASS(DOptionMenuItemOptionBase, true, false) // //============================================================================= -class DOptionMenuItemOption : public DOptionMenuItemOptionBase +class DOptionMenuItemOption_ : public DOptionMenuItemOptionBase_ { - DECLARE_CLASS(DOptionMenuItemOption, DOptionMenuItemOptionBase) + DECLARE_CLASS(DOptionMenuItemOption_, DOptionMenuItemOptionBase_) // action is a CVAR FBaseCVar *mCVar; - DOptionMenuItemOption() {} + DOptionMenuItemOption_() {} public: - DOptionMenuItemOption(const char *label, const char *menu, const char *values, const char *graycheck, int center) - : DOptionMenuItemOptionBase(label, menu, values, graycheck, center) + DOptionMenuItemOption_(const char *label, const char *menu, const char *values, const char *graycheck, int center) + : DOptionMenuItemOptionBase_(label, menu, values, graycheck, center) { mCVar = FindCVar(mAction, NULL); } @@ -367,7 +367,7 @@ public: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuItemOption, false, false) +IMPLEMENT_CLASS(DOptionMenuItemOption_, false, false) #endif //============================================================================= @@ -440,17 +440,17 @@ IMPLEMENT_CLASS(DEnterKey, true, false) // //============================================================================= -class DOptionMenuItemControl : public DOptionMenuItem +class DOptionMenuItemControl_ : public DOptionMenuItem { - DECLARE_CLASS(DOptionMenuItemControl, DOptionMenuItemOption) + DECLARE_CLASS(DOptionMenuItemControl_, DOptionMenuItemOption_) FKeyBindings *mBindings; int mInput; bool mWaiting; - DOptionMenuItemControl() {} + DOptionMenuItemControl_() {} public: - DOptionMenuItemControl(const char *label, const char *menu, FKeyBindings *bindings) + DOptionMenuItemControl_(const char *label, const char *menu, FKeyBindings *bindings) : DOptionMenuItem(label, menu) { mBindings = bindings; @@ -514,7 +514,7 @@ public: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuItemControl, false, false) +IMPLEMENT_CLASS(DOptionMenuItemControl_, false, false) #endif //============================================================================= // @@ -522,20 +522,20 @@ IMPLEMENT_CLASS(DOptionMenuItemControl, false, false) // //============================================================================= -class DOptionMenuItemStaticText : public DOptionMenuItem +class DOptionMenuItemStaticText_ : public DOptionMenuItem { - DECLARE_CLASS(DOptionMenuItemStaticText, DOptionMenuItem) + DECLARE_CLASS(DOptionMenuItemStaticText_, DOptionMenuItem) EColorRange mColor; - DOptionMenuItemStaticText() {} + DOptionMenuItemStaticText_() {} public: - DOptionMenuItemStaticText(const char *label, bool header) + DOptionMenuItemStaticText_(const char *label, bool header) : DOptionMenuItem(label, NAME_None, true) { mColor = header ? OptionSettings.mFontColorHeader : OptionSettings.mFontColor; } - DOptionMenuItemStaticText(const char *label, EColorRange cr) + DOptionMenuItemStaticText_(const char *label, EColorRange cr) : DOptionMenuItem(label, NAME_None, true) { mColor = cr; @@ -555,7 +555,7 @@ public: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuItemStaticText, false, false) +IMPLEMENT_CLASS(DOptionMenuItemStaticText_, false, false) #endif //============================================================================= @@ -564,16 +564,16 @@ IMPLEMENT_CLASS(DOptionMenuItemStaticText, false, false) // //============================================================================= -class DOptionMenuItemStaticTextSwitchable : public DOptionMenuItem +class DOptionMenuItemStaticTextSwitchable_ : public DOptionMenuItem { - DECLARE_CLASS(DOptionMenuItemStaticTextSwitchable, DOptionMenuItem) + DECLARE_CLASS(DOptionMenuItemStaticTextSwitchable_, DOptionMenuItem) EColorRange mColor; FString mAltText; int mCurrent; - DOptionMenuItemStaticTextSwitchable() {} + DOptionMenuItemStaticTextSwitchable_() {} public: - DOptionMenuItemStaticTextSwitchable(const char *label, const char *label2, FName action, EColorRange cr) + DOptionMenuItemStaticTextSwitchable_(const char *label, const char *label2, FName action, EColorRange cr) : DOptionMenuItem(label, action, true) { mColor = cr; @@ -618,7 +618,7 @@ public: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuItemStaticTextSwitchable, false, false) +IMPLEMENT_CLASS(DOptionMenuItemStaticTextSwitchable_, false, false) #endif //============================================================================= @@ -627,9 +627,9 @@ IMPLEMENT_CLASS(DOptionMenuItemStaticTextSwitchable, false, false) // //============================================================================= -class DOptionMenuSliderBase : public DOptionMenuItem +class DOptionMenuSliderBase_ : public DOptionMenuItem { - DECLARE_ABSTRACT_CLASS(DOptionMenuSliderBase, DOptionMenuItem) + DECLARE_ABSTRACT_CLASS(DOptionMenuSliderBase_, DOptionMenuItem) // action is a CVAR double mMin, mMax, mStep; int mShowValue; @@ -637,9 +637,9 @@ class DOptionMenuSliderBase : public DOptionMenuItem int mSliderShort; protected: - DOptionMenuSliderBase() {} + DOptionMenuSliderBase_() {} public: - DOptionMenuSliderBase(const char *label, double min, double max, double step, int showval) + DOptionMenuSliderBase_(const char *label, double min, double max, double step, int showval) : DOptionMenuItem(label, NAME_None) { mMin = min; @@ -768,7 +768,7 @@ public: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuSliderBase, true, false) +IMPLEMENT_CLASS(DOptionMenuSliderBase_, true, false) #endif //============================================================================= @@ -777,15 +777,15 @@ IMPLEMENT_CLASS(DOptionMenuSliderBase, true, false) // //============================================================================= -class DOptionMenuSliderCVar : public DOptionMenuSliderBase +class DOptionMenuSliderCVar_ : public DOptionMenuSliderBase_ { - DECLARE_CLASS(DOptionMenuSliderCVar, DOptionMenuSliderBase) + DECLARE_CLASS(DOptionMenuSliderCVar_, DOptionMenuSliderBase_) FBaseCVar *mCVar; - DOptionMenuSliderCVar() {} + DOptionMenuSliderCVar_() {} public: - DOptionMenuSliderCVar(const char *label, const char *menu, double min, double max, double step, int showval) - : DOptionMenuSliderBase(label, min, max, step, showval) + DOptionMenuSliderCVar_(const char *label, const char *menu, double min, double max, double step, int showval) + : DOptionMenuSliderBase_(label, min, max, step, showval) { mCVar = FindCVar(menu, NULL); } @@ -814,7 +814,7 @@ public: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuSliderCVar, false, false) +IMPLEMENT_CLASS(DOptionMenuSliderCVar_, false, false) #endif //============================================================================= @@ -823,16 +823,16 @@ IMPLEMENT_CLASS(DOptionMenuSliderCVar, false, false) // //============================================================================= -class DOptionMenuSliderVar : public DOptionMenuSliderBase +class DOptionMenuSliderVar_ : public DOptionMenuSliderBase_ { - DECLARE_CLASS(DOptionMenuSliderVar, DOptionMenuSliderBase) + DECLARE_CLASS(DOptionMenuSliderVar_, DOptionMenuSliderBase_) float *mPVal; - DOptionMenuSliderVar() {} + DOptionMenuSliderVar_() {} public: - DOptionMenuSliderVar(const char *label, float *pVal, double min, double max, double step, int showval) - : DOptionMenuSliderBase(label, min, max, step, showval) + DOptionMenuSliderVar_(const char *label, float *pVal, double min, double max, double step, int showval) + : DOptionMenuSliderBase_(label, min, max, step, showval) { mPVal = pVal; } @@ -849,7 +849,7 @@ public: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuSliderVar, false, false) +IMPLEMENT_CLASS(DOptionMenuSliderVar_, false, false) #endif //============================================================================= @@ -858,12 +858,12 @@ IMPLEMENT_CLASS(DOptionMenuSliderVar, false, false) // //============================================================================= -class DOptionMenuItemColorPicker : public DOptionMenuItem +class DOptionMenuItemColorPicker_ : public DOptionMenuItem { - DECLARE_CLASS(DOptionMenuItemColorPicker, DOptionMenuItem) + DECLARE_CLASS(DOptionMenuItemColorPicker_, DOptionMenuItem) FColorCVar *mCVar; - DOptionMenuItemColorPicker() {} + DOptionMenuItemColorPicker_() {} public: enum @@ -871,7 +871,7 @@ public: CPF_RESET = 0x20001, }; - DOptionMenuItemColorPicker(const char *label, const char *menu) + DOptionMenuItemColorPicker_(const char *label, const char *menu) : DOptionMenuItem(label, menu) { FBaseCVar *cv = FindCVar(menu, NULL); @@ -924,19 +924,19 @@ public: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuItemColorPicker, false, false) +IMPLEMENT_CLASS(DOptionMenuItemColorPicker_, false, false) #endif -class DOptionMenuScreenResolutionLine : public DOptionMenuItem +class DOptionMenuScreenResolutionLine_ : public DOptionMenuItem { - DECLARE_CLASS(DOptionMenuScreenResolutionLine, DOptionMenuItem) + DECLARE_CLASS(DOptionMenuScreenResolutionLine_, DOptionMenuItem) FString mResTexts[3]; int mSelection; int mHighlight; int mMaxValid; - DOptionMenuScreenResolutionLine() {} + DOptionMenuScreenResolutionLine_() {} public: enum @@ -946,7 +946,7 @@ public: SRL_HIGHLIGHT = 0x30004, }; - DOptionMenuScreenResolutionLine(const char *action) + DOptionMenuScreenResolutionLine_(const char *action) : DOptionMenuItem("", action) { mSelection = 0; @@ -1072,25 +1072,25 @@ public: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuScreenResolutionLine, false, false) +IMPLEMENT_CLASS(DOptionMenuScreenResolutionLine_, false, false) #endif //============================================================================= // -// [TP] DOptionMenuFieldBase +// [TP] DOptionMenuFieldBase_ // // Base class for input fields // //============================================================================= -class DOptionMenuFieldBase : public DOptionMenuItem +class DOptionMenuFieldBase_ : public DOptionMenuItem { - DECLARE_ABSTRACT_CLASS(DOptionMenuFieldBase, DOptionMenuItem) + DECLARE_ABSTRACT_CLASS(DOptionMenuFieldBase_, DOptionMenuItem) protected: - DOptionMenuFieldBase() {} + DOptionMenuFieldBase_() {} public: - DOptionMenuFieldBase ( const char* label, const char* menu, const char* graycheck ) : + DOptionMenuFieldBase_ ( const char* label, const char* menu, const char* graycheck ) : DOptionMenuItem ( label, menu ), mCVar ( FindCVar( mAction, NULL )), mGrayCheck (( graycheck && strlen( graycheck )) ? FindCVar( graycheck, NULL ) : NULL ) {} @@ -1155,25 +1155,25 @@ protected: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuFieldBase, true, false) +IMPLEMENT_CLASS(DOptionMenuFieldBase_, true, false) #endif //============================================================================= // -// [TP] DOptionMenuTextField +// [TP] DOptionMenuTextField_ // // A text input field widget, for use with string CVars. // //============================================================================= -class DOptionMenuTextField : public DOptionMenuFieldBase +class DOptionMenuTextField_ : public DOptionMenuFieldBase_ { - DECLARE_CLASS(DOptionMenuTextField, DOptionMenuFieldBase) + DECLARE_CLASS(DOptionMenuTextField_, DOptionMenuFieldBase_) - DOptionMenuTextField() {} + DOptionMenuTextField_() {} public: - DOptionMenuTextField ( const char *label, const char* menu, const char* graycheck ) : - DOptionMenuFieldBase ( label, menu, graycheck ), + DOptionMenuTextField_ ( const char *label, const char* menu, const char* graycheck ) : + DOptionMenuFieldBase_ ( label, menu, graycheck ), mEntering ( false ) {} FString Represent() @@ -1196,7 +1196,7 @@ public: int newindent = screen->GetWidth() - tlen - CURSORSPACE; if (newindent < indent) indent = newindent; } - return DOptionMenuFieldBase::Draw(desc, y, indent, selected); + return DOptionMenuFieldBase_::Draw(desc, y, indent, selected); } bool MenuEvent ( int mkey, bool fromcontroller ) @@ -1237,7 +1237,7 @@ private: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuTextField, false, false) +IMPLEMENT_CLASS(DOptionMenuTextField_, false, false) #endif //============================================================================= @@ -1249,15 +1249,15 @@ IMPLEMENT_CLASS(DOptionMenuTextField, false, false) // //============================================================================= -class DOptionMenuNumberField : public DOptionMenuFieldBase +class DOptionMenuNumberField_ : public DOptionMenuFieldBase_ { - DECLARE_CLASS(DOptionMenuNumberField, DOptionMenuFieldBase) + DECLARE_CLASS(DOptionMenuNumberField_, DOptionMenuFieldBase_) - DOptionMenuNumberField() {} + DOptionMenuNumberField_() {} public: - DOptionMenuNumberField ( const char *label, const char* menu, float minimum, float maximum, + DOptionMenuNumberField_ ( const char *label, const char* menu, float minimum, float maximum, float step, const char* graycheck ) - : DOptionMenuFieldBase ( label, menu, graycheck ), + : DOptionMenuFieldBase_ ( label, menu, graycheck ), mMinimum ( minimum ), mMaximum ( maximum ), mStep ( step ) @@ -1308,5 +1308,5 @@ private: }; #ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuNumberField, false, false) +IMPLEMENT_CLASS(DOptionMenuNumberField_, false, false) #endif diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp index 6737f832e..882e8b593 100644 --- a/src/menu/videomenu.cpp +++ b/src/menu/videomenu.cpp @@ -109,11 +109,11 @@ CUSTOM_CVAR (Bool, vid_tft, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) { if (self) { - it->SetString(DOptionMenuItemOptionBase::OP_VALUES, "RatiosTFT"); + it->SetString(DOptionMenuItemOptionBase_::OP_VALUES, "RatiosTFT"); } else { - it->SetString(DOptionMenuItemOptionBase::OP_VALUES, "Ratios"); + it->SetString(DOptionMenuItemOptionBase_::OP_VALUES, "Ratios"); } } } @@ -148,9 +148,9 @@ public: mDesc->mSelectedItem < (int)mDesc->mItems.Size()) { int sel; - bool selected = mDesc->mItems[mDesc->mSelectedItem]->GetValue(DOptionMenuScreenResolutionLine::SRL_SELECTION, &sel); + bool selected = mDesc->mItems[mDesc->mSelectedItem]->GetValue(DOptionMenuScreenResolutionLine_::SRL_SELECTION, &sel); bool res = Super::MenuEvent(mkey, fromcontroller); - if (selected) mDesc->mItems[mDesc->mSelectedItem]->SetValue(DOptionMenuScreenResolutionLine::SRL_SELECTION, sel); + if (selected) mDesc->mItems[mDesc->mSelectedItem]->SetValue(DOptionMenuScreenResolutionLine_::SRL_SELECTION, sel); return res; } return Super::MenuEvent(mkey, fromcontroller); @@ -239,7 +239,7 @@ static void BuildModesList (int hiwidth, int hiheight, int hi_bits) DOptionMenuItem *it = opt->GetItem((ENamedName)i); if (it != NULL) { - it->SetValue(DOptionMenuScreenResolutionLine::SRL_HIGHLIGHT, -1); + it->SetValue(DOptionMenuScreenResolutionLine_::SRL_HIGHLIGHT, -1); for (c = 0; c < 3; c++) { bool haveMode = false; @@ -260,16 +260,16 @@ static void BuildModesList (int hiwidth, int hiheight, int hi_bits) { if (width == hiwidth && height == hiheight) { - it->SetValue(DOptionMenuScreenResolutionLine::SRL_SELECTION, c); - it->SetValue(DOptionMenuScreenResolutionLine::SRL_HIGHLIGHT, c); + it->SetValue(DOptionMenuScreenResolutionLine_::SRL_SELECTION, c); + it->SetValue(DOptionMenuScreenResolutionLine_::SRL_HIGHLIGHT, c); } mysnprintf (strtemp, countof(strtemp), "%dx%d%s", width, height, letterbox?TEXTCOLOR_BROWN" LB":""); - it->SetString(DOptionMenuScreenResolutionLine::SRL_INDEX+c, strtemp); + it->SetString(DOptionMenuScreenResolutionLine_::SRL_INDEX+c, strtemp); } else { - it->SetString(DOptionMenuScreenResolutionLine::SRL_INDEX+c, ""); + it->SetString(DOptionMenuScreenResolutionLine_::SRL_INDEX+c, ""); } } } @@ -360,11 +360,11 @@ static bool GetSelectedSize (int *width, int *height) int line = opt->mSelectedItem; int hsel; DOptionMenuItem *it = opt->mItems[line]; - if (it->GetValue(DOptionMenuScreenResolutionLine::SRL_SELECTION, &hsel)) + if (it->GetValue(DOptionMenuScreenResolutionLine_::SRL_SELECTION, &hsel)) { char buffer[32]; char *breakpt; - if (it->GetString(DOptionMenuScreenResolutionLine::SRL_INDEX+hsel, buffer, sizeof(buffer))) + if (it->GetString(DOptionMenuScreenResolutionLine_::SRL_INDEX+hsel, buffer, sizeof(buffer))) { *width = (int)strtoll (buffer, &breakpt, 10); *height = (int)strtoll (breakpt+1, NULL, 10); @@ -397,6 +397,11 @@ void M_SetVideoMode() SetModesMenu (NewWidth, NewHeight, NewBits); } +DEFINE_ACTION_FUNCTION(DMenu, SetVideoMode) +{ + M_SetVideoMode(); + return 0; +} //============================================================================= // // diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 1307693cf..eb4ed2e47 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -154,6 +154,7 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos) { if (ReturnProto->ReturnTypes[i] != proto->ReturnTypes[i]) { // Incompatible + Printf("Return type %s mismatch with %s\n", ReturnProto->ReturnTypes[i]->DescriptiveName(), proto->ReturnTypes[i]->DescriptiveName()); fail = true; break; } diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index ea6d581e1..551d909c5 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -7,8 +7,10 @@ #include "zscript/actor_checks.txt" #include "zscript/menu/menu.txt" -//#include "zscript/menu/menuitembase.txt" -#include "zscript/menu/colorpickermenu.txt" +#include "zscript/menu/menuitembase.txt" +#include "zscript/menu/optionmenuitems.txt" +#include "zscript/menu/optionmenuitems.txt" +#include "zscript/menu/joystickmenu.txt" #include "zscript/inventory/inventory.txt" #include "zscript/inventory/inv_misc.txt" diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 8e77c3212..2fe42d31a 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -158,6 +158,37 @@ struct Font native CR_CYAN, NUM_TEXT_COLORS }; + + const TEXTCOLOR_BRICK = "\034A"; + const TEXTCOLOR_TAN = "\034B"; + const TEXTCOLOR_GRAY = "\034C"; + const TEXTCOLOR_GREY = "\034C"; + const TEXTCOLOR_GREEN = "\034D"; + const TEXTCOLOR_BROWN = "\034E"; + const TEXTCOLOR_GOLD = "\034F"; + const TEXTCOLOR_RED = "\034G"; + const TEXTCOLOR_BLUE = "\034H"; + const TEXTCOLOR_ORANGE = "\034I"; + const TEXTCOLOR_WHITE = "\034J"; + const TEXTCOLOR_YELLOW = "\034K"; + const TEXTCOLOR_UNTRANSLATED = "\034L"; + const TEXTCOLOR_BLACK = "\034M"; + const TEXTCOLOR_LIGHTBLUE = "\034N"; + const TEXTCOLOR_CREAM = "\034O"; + const TEXTCOLOR_OLIVE = "\034P"; + const TEXTCOLOR_DARKGREEN = "\034Q"; + const TEXTCOLOR_DARKRED = "\034R"; + const TEXTCOLOR_DARKBROWN = "\034S"; + const TEXTCOLOR_PURPLE = "\034T"; + const TEXTCOLOR_DARKGRAY = "\034U"; + const TEXTCOLOR_CYAN = "\034V"; + + const TEXTCOLOR_NORMAL = "\034-"; + const TEXTCOLOR_BOLD = "\034+"; + + const TEXTCOLOR_CHAT = "\034*"; + const TEXTCOLOR_TEAMCHAT = "\034!"; + native int GetCharWidth(int code); native int StringWidth(String code); @@ -173,6 +204,7 @@ struct Console native { native static void HideConsole(); native static void MidPrint(Font fontname, string textlabel, bool bold = false); + native static void DoCommand(String cmd); } struct DamageTypeDefinition native @@ -182,9 +214,24 @@ struct DamageTypeDefinition native struct CVar native { + enum ECVarType + { + CVAR_Bool, + CVAR_Int, + CVAR_Float, + CVAR_String, + CVAR_Color, + }; + + native static CVar FindCVar(Name name); native int GetInt(); native double GetFloat(); native String GetString(); + native void SetInt(int v); + native void SetFloat(double v); + native void SetString(String s); + native int GetRealType(); + native int ResetToDefault(); } struct GameInfoStruct native diff --git a/wadsrc/static/zscript/menu/colorpickermenu.txt b/wadsrc/static/zscript/menu/colorpickermenu.txt index 30c2a183e..ff21e1b8e 100644 --- a/wadsrc/static/zscript/menu/colorpickermenu.txt +++ b/wadsrc/static/zscript/menu/colorpickermenu.txt @@ -32,6 +32,35 @@ ** */ + +//============================================================================= +// +// This is only used by the color picker +// +//============================================================================= + +class OptionMenuSliderVar : OptionMenuSliderBase +{ + int mIndex; + + void Init(String label, int index, double min, double max, double step, int showval) + { + Super.Init(label, min, max, step, showval); + mIndex = index; + } + + override double GetSliderValue() + { + return ColorpickerMenu(Menu.GetCurrentMenu()).GetColor(mIndex); + } + + override void SetSliderValue(double val) + { + ColorpickerMenu(Menu.GetCurrentMenu()).setColor(mIndex, val); + } +} + + class ColorpickerMenu : Menu native { native float mRed; @@ -45,6 +74,18 @@ class ColorpickerMenu : Menu native native CVar mCVar; + double GetColor(int index) + { + double v = index == 0? mRed : index == 1? mGreen : mBlue; + return v; + } + + void SetColor(int index, double val) + { + if (index == 0) mRed = val; + else if (index == 1) mGreen = val; + else mBlue = val; + } //============================================================================= // // diff --git a/wadsrc/static/zscript/menu/joystickmenu.txt b/wadsrc/static/zscript/menu/joystickmenu.txt new file mode 100644 index 000000000..3d4085467 --- /dev/null +++ b/wadsrc/static/zscript/menu/joystickmenu.txt @@ -0,0 +1,191 @@ +//============================================================================= +// +// +// +//============================================================================= + +class OptionMenuSliderJoySensitivity : OptionMenuSliderBase +{ + void Init(String label, double min, double max, double step, int showval) + { + Super.Init(label, min, max, step, showval); + } + + override double GetSliderValue() + { + return Menu.GetCurrentJoystickConfig().GetSensitivity(); + } + + override void SetSliderValue(double val) + { + Menu.GetCurrentJoystickConfig().SetSensitivity(val); + } +} + +//============================================================================= +// +// +// +//============================================================================= + +class OptionMenuSliderJoyScale : OptionMenuSliderBase +{ + int mAxis; + int mNeg; + + void Init(String label, int axis, double min, double max, double step, int showval) + { + Super.Init(label, min, max, step, showval); + mAxis = axis; + mNeg = 1; + } + + override double GetSliderValue() + { + double d = Menu.GetCurrentJoystickConfig().GetAxisScale(mAxis); + mNeg = d < 0? -1:1; + return d; + } + + override void SetSliderValue(double val) + { + Menu.GetCurrentJoystickConfig().SetAxisScale(mAxis, val * mNeg); + } +} + +//============================================================================= +// +// +// +//============================================================================= + +class OptionMenuSliderJoyDeadZone : OptionMenuSliderBase +{ + int mAxis; + int mNeg; + + + void Init(String label, int axis, double min, double max, double step, int showval) + { + Super.Init(label, min, max, step, showval); + mAxis = axis; + mNeg = 1; + } + + override double GetSliderValue() + { + double d = Menu.GetCurrentJoystickConfig().GetAxisDeadZone(mAxis); + mNeg = d < 0? -1:1; + return d; + } + + override void SetSliderValue(double val) + { + Menu.GetCurrentJoystickConfig().SetAxisDeadZone(mAxis, val * mNeg); + } +} + +//============================================================================= +// +// +// +//============================================================================= + +class OptionMenuItemJoyMap : OptionMenuItemOptionBase +{ + int mAxis; + + void Init(String label, int axis, String values, int center) + { + Super.Init(label, 'none', values, null, center); + mAxis = axis; + } + + override int GetSelection() + { + double f = Menu.GetCurrentJoystickConfig().GetAxisMap(mAxis); + let opt = OptionValues.GetCount(mValues); + if (opt > 0) + { + // Map from joystick axis to menu selection. + for(int i = 0; i < opt; i++) + { + if (f ~== OptionValues.GetValue(mValues, i)) + { + return i; + } + } + } + return -1; + } + + override void SetSelection(int selection) + { + let opt = OptionValues.GetCount(mValues); + // Map from menu selection to joystick axis. + if (opt == 0 || selection >= opt) + { + selection = JoystickConfig.JOYAXIS_None; + } + else + { + selection = OptionValues.GetValue(mValues, selection); + } + Menu.GetCurrentJoystickConfig().SetAxisMap(mAxis, selection); + } +} + +//============================================================================= +// +// +// +//============================================================================= + +class OptionMenuItemInverter : OptionMenuItemOptionBase +{ + int mAxis; + + + void Init(String label, int axis, int center) + { + Super.Init(label, "none", "YesNo", NULL, center); + mAxis = axis; + } + + override int GetSelection() + { + float f = Menu.GetCurrentJoystickConfig().GetAxisScale(mAxis); + return f > 0? 0:1; + } + + override void SetSelection(int Selection) + { + let f = abs(Menu.GetCurrentJoystickConfig().GetAxisScale(mAxis)); + if (Selection) f*=-1; + Menu.GetCurrentJoystickConfig().SetAxisScale(mAxis, f); + } +} + +//============================================================================= +// +// Executes a CCMD, action is a CCMD name +// +//============================================================================= + +class OptionMenuItemJoyConfigMenu : OptionMenuItemSubmenu +{ + JoystickConfig mJoy; + + void Init(String label = "", JoystickConfig joy = null) + { + Super.Init(label, "JoystickConfigMenu"); + mJoy = joy; + } + + override bool Activate() + { + //UpdateJoystickConfigMenu(mJoy); + return Super.Activate(); + } +} + diff --git a/wadsrc/static/zscript/menu/menu.txt b/wadsrc/static/zscript/menu/menu.txt index c759e8351..85cf747c3 100644 --- a/wadsrc/static/zscript/menu/menu.txt +++ b/wadsrc/static/zscript/menu/menu.txt @@ -1,4 +1,48 @@ +struct KeyBindings native +{ + native static String NameKeys(int k1, int k2); + + native int, int GetKeysForCommand(String cmd); + native void SetBind(int key, String cmd); + native void UnbindACommand (String str); +} + +struct OptionValues native +{ + native static int GetCount(Name group); + native static String GetText(Name group, int index); + native static double GetValue(Name group, int index); + native static String GetTextValue(Name group, int index); +} + +struct JoystickConfig native +{ + enum EJoyAxis + { + JOYAXIS_None = -1, + JOYAXIS_Yaw, + JOYAXIS_Pitch, + JOYAXIS_Forward, + JOYAXIS_Side, + JOYAXIS_Up, + // JOYAXIS_Roll, // Ha ha. No roll for you. + NUM_JOYAXIS, + }; + + native float GetSensitivity(); + native void SetSensitivity(float scale); + + native float GetAxisScale(int axis); + native void SetAxisScale(int axis, float scale); + + native float GetAxisDeadZone(int axis); + native void SetAxisDeadZone(int axis, float zone); + + native int GetAxisMap(int axis); + native void SetAxisMap(int axis, int gameaxis); +} + class Menu : Object native { enum EMenuKey @@ -30,16 +74,27 @@ class Menu : Object native }; //native static int MenuTime(); + native static void SetVideoMode(); + native static Menu GetCurrentMenu(); + native static JoystickConfig GetCurrentJoystickConfig(); + native static void SetMenu(Name mnu, int param = 0); + native static void StartMessage(String msg, int mode = 0, Name command = 'none'); + native virtual bool MenuEvent (int mkey, bool fromcontroller); native virtual bool MouseEvent(int type, int mx, int my); native virtual void Drawer(); - void MenuSound(Sound snd) + static void MenuSound(Sound snd) { S_Sound (snd, CHAN_VOICE | CHAN_UI, snd_menuvolume, ATTN_NONE); } + static void DrawConText (int color, int x, int y, String str) + { + screen.DrawText (ConFont, color, x, y, str, DTA_CellX, 8 * CleanXfac_1, DTA_CellY, 8 * CleanYfac_1); + } + } class MenuDescriptor : Object native @@ -49,17 +104,6 @@ class MenuDescriptor : Object native native Class mClass; } -class MenuItemBase : object native -{ - native int mXpos, mYpos; - native Name mAction; - native bool mEnabled; - - // making this virtual now would require exporting all classes at once. - native /*virtual*/ bool MenuEvent (int mkey, bool fromcontroller); - -} - struct FOptionMenuSettings { int mTitleColor; @@ -96,14 +140,6 @@ class OptionMenuDescriptor : MenuDescriptor native } } -class OptionMenuItem : MenuItemBase native -{ - native String mLabel; - native bool mCentered; - - //native void drawLabel(int indent, int y, EColorRange color, bool grayed = false); -} - class OptionMenu : Menu native { native bool CanScrollUp; @@ -111,5 +147,22 @@ class OptionMenu : Menu native native int VisBottom; native OptionMenuItem mFocusControl; native OptionMenuDescriptor mDesc; + + + void SetFocus(OptionMenuItem fc) + { + mFocusControl = fc; + } + + bool CheckFocus(OptionMenuItem fc) + { + return mFocusControl == fc; + } + + void ReleaseFocus() + { + mFocusControl = null; + } + } diff --git a/wadsrc/static/zscript/menu/menuitembase.txt b/wadsrc/static/zscript/menu/menuitembase.txt index e92f17fcf..9015aa758 100644 --- a/wadsrc/static/zscript/menu/menuitembase.txt +++ b/wadsrc/static/zscript/menu/menuitembase.txt @@ -6,12 +6,11 @@ class MenuItemBase : Object native { - protected int mXpos, mYpos; - protected Name mAction; + protected native int mXpos, mYpos; + protected native Name mAction; + native bool mEnabled; - bool mEnabled; - - protected void Init(int xpos = 0, int ypos = 0, Name actionname = 'None') + void Init(int xpos = 0, int ypos = 0, Name actionname = 'None') { mXpos = xpos; mYpos = ypos; @@ -30,7 +29,8 @@ class MenuItemBase : Object native virtual bool SetValue(int i, int value) { return false; } virtual bool, int GetValue(int i) { return false, 0; } virtual void Enable(bool on) { mEnabled = on; } - virtual bool MenuEvent (int mkey, bool fromcontroller) { return false; } + // this can only be made scripted once all items are converted, because it is called from the colorpicker menu. +native virtual bool MenuEvent (int mkey, bool fromcontroller);// { return false; } virtual bool MouseEvent(int type, int x, int y) { return false; } virtual bool CheckHotkey(int c) { return false; } virtual int GetWidth() { return 0; } diff --git a/wadsrc/static/zscript/menu/optionmenuitems.txt b/wadsrc/static/zscript/menu/optionmenuitems.txt new file mode 100644 index 000000000..920576878 --- /dev/null +++ b/wadsrc/static/zscript/menu/optionmenuitems.txt @@ -0,0 +1,1152 @@ +/* +** optionmenuitems.txt +** Control items for option menus +** +**--------------------------------------------------------------------------- +** Copyright 2010-2017 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +class OptionMenuItem : MenuItemBase native +{ + + native String mLabel; + native bool mCentered; + + void Init(String label, String command, bool center = false) + { + Super.Init(0, 0, command); + mLabel = label; + mCentered = center; + } + + protected void drawLabel(int indent, int y, int color, bool grayed = false) + { + String label = Stringtable.Localize(mLabel); + int overlay = grayed? Color(96,48,0,0) : 0; + + int x; + int w = SmallFont.StringWidth(label) * CleanXfac_1; + if (!mCentered) x = indent - w; + else x = (screen.GetWidth() - w) / 2; + screen.DrawText (SmallFont, color, x, y, label, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay); + } + + virtual int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) + { + return indent; + } + + int CursorSpace() + { + return (14 * CleanXfac_1); + } + + override bool Selectable() + { + return true; + } + + virtual int GetIndent() + { + if (mCentered) return 0; + return SmallFont.StringWidth(Stringtable.Localize(mLabel)); + } + + override bool MouseEvent(int type, int x, int y) + { + if (Selectable() && type == Menu.MOUSE_Release) + { + return Menu.GetCurrentMenu().MenuEvent(Menu.MKEY_Enter, true); + } + return false; + } +} + +//============================================================================= +// +// opens a submenu, command is a submenu name +// +//============================================================================= + +class OptionMenuItemSubmenu : OptionMenuItem +{ + int mParam; + void Init(String label, Name command, int param = 0) + { + Super.init(label, command); + mParam = param; + } + + override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) + { + drawLabel(indent, y, selected? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColorMore); + return indent; + } + + override bool Activate() + { + Menu.MenuSound("menu/choose"); + Menu.SetMenu(mAction, mParam); + return true; + } +} + +//============================================================================= +// +// Executes a CCMD, command is a CCMD name +// +//============================================================================= + +class OptionMenuItemCommand : OptionMenuItemSubmenu +{ + void Init(String label, Name command) + { + Super.Init(label, command); + } + + override bool Activate() + { + Menu.MenuSound("menu/choose"); + Console.DoCommand(mAction); + return true; + } + +} + +//============================================================================= +// +// Executes a CCMD after confirmation, command is a CCMD name +// +//============================================================================= + +class OptionMenuItemSafeCommand : OptionMenuItemCommand +{ + String mPrompt; + + + void Init(String label, Name command, String prompt) + { + Super.Init(label, command); + mPrompt = prompt; + } + + override bool MenuEvent (int mkey, bool fromcontroller) + { + if (mkey == Menu.MKEY_MBYes) + { + Console.DoCommand(mAction); + return true; + } + return Super.MenuEvent(mkey, fromcontroller); + } + + override bool Activate() + { + String msg = mPrompt.Length() > 0 ? mPrompt : "$SAFEMESSAGE"; + msg = StringTable.Localize(msg); + String actionLabel = StringTable.localize(mLabel); + + String FullString; + FullString.Format("%s%s%s\n\n%s", TEXTCOLOR_WHITE, actionLabel, TEXTCOLOR_NORMAL, msg); + + Menu.StartMessage(FullString, 0); + return true; + } +} + +//============================================================================= +// +// Base class for option lists +// +//============================================================================= + +class OptionMenuItemOptionBase : OptionMenuItem +{ + // command is a CVAR + Name mValues; // Entry in OptionValues table + CVar mGrayCheck; + int mCenter; + + const OP_VALUES = 0x11001; + + void Init(String label, Name command, Name values, CVar graycheck, int center) + { + Super.Init(label, command); + mValues = values; + mGrayCheck = graycheck; + mCenter = center; + } + + override bool SetString(int i, String newtext) + { + if (i == OP_VALUES) + { + int cnt = OptionValues.GetCount(mValues); + if (cnt >= 0) + { + mValues = newtext; + int s = GetSelection(); + if (s >= cnt) s = 0; + SetSelection(s); // readjust the CVAR if its value is outside the range now + return true; + } + } + return false; + } + + //============================================================================= + virtual int GetSelection() + { + return 0; + } + + virtual void SetSelection(int Selection) + { + } + + //============================================================================= + override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) + { + bool grayed = mGrayCheck != null && !(mGrayCheck.GetInt()); + + if (mCenter) + { + indent = (screen.GetWidth() / 2); + } + drawLabel(indent, y, selected? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor, grayed); + + int overlay = grayed? Color(96,48,0,0) : 0; + int Selection = GetSelection(); + String text = StringTable.Localize(OptionValues.GetText(mValues, Selection)); + if (text.Length() == 0) text = "Unknown"; + screen.DrawText (SmallFont, OptionMenuSettings.mFontColorValue, indent + CursorSpace(), y, text, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay); + return indent; + } + + //============================================================================= + override bool MenuEvent (int mkey, bool fromcontroller) + { + int cnt = OptionValues.GetCount(mValues); + if (cnt > 0) + { + int Selection = GetSelection(); + if (mkey == Menu.MKEY_Left) + { + if (Selection == -1) Selection = 0; + else if (--Selection < 0) Selection = cnt - 1; + } + else if (mkey == Menu.MKEY_Right || mkey == Menu.MKEY_Enter) + { + if (++Selection >= cnt) Selection = 0; + } + else + { + return Super.MenuEvent(mkey, fromcontroller); + } + SetSelection(Selection); + Menu.MenuSound("menu/change"); + } + else + { + return Super.MenuEvent(mkey, fromcontroller); + } + return true; + } + + override bool Selectable() + { + return mGrayCheck == null || mGrayCheck.GetInt(); + } +} + +//============================================================================= +// +// Change a CVAR, command is the CVAR name +// +//============================================================================= + +class OptionMenuItemOption : OptionMenuItemOptionBase +{ + CVar mCVar; + + void Init(String label, Name command, String values, CVar graycheck, int center) + { + Super.Init(label, command, values, graycheck, center); + mCVar = CVar.FindCVar(mAction); + } + + //============================================================================= + override int GetSelection() + { + int Selection = -1; + int cnt = OptionValues.GetCount(mValues); + if (cnt > 0 && mCVar != null) + { + if (OptionValues.GetText(mValues, 0).Length() > 0) + { + let f = mCVar.GetFloat(); + for(int i = 0; i < cnt; i++) + { + if (f ~== OptionValues.GetValue(mValues, i)) + { + Selection = i; + break; + } + } + } + else + { + String cv = mCVar.GetString(); + for(int i = 0; i < cnt; i++) + { + if (cv ~== OptionValues.GetTextValue(mValues, i)) + { + Selection = i; + break; + } + } + } + } + return Selection; + } + + override void SetSelection(int Selection) + { + int cnt = OptionValues.GetCount(mValues); + if (cnt > 0 && mCVar != null) + { + if (OptionValues.GetText(mValues, 0).Length() > 0) + { + mCVar.SetFloat(OptionValues.GetValue(mValues, Selection)); + } + else + { + mCVar.SetString(OptionValues.GetTextValue(mValues, Selection)); + } + } + } +} + +//============================================================================= +// +// This class is used to capture the key to be used as the new key binding +// for a control item +// +//============================================================================= + +/* This will have to wait. +class DEnterKey : Menu +{ + DECLARE_CLASS(DEnterKey, Menu) + + int *pKey; + + + DEnterKey(Menu *parent, int *keyptr) + : Menu(parent) + { + pKey = keyptr; + SetMenuMessage(1); + menuactive = MENU_WaitKey; // There should be a better way to disable GUI capture... + } + + bool TranslateKeyboardEvents() + { + return false; + } + + void SetMenuMessage(int which) + { + if (mParentMenu.IsKindOf(RUNTIME_CLASS(OptionMenu))) + { + OptionMenu *m = barrier_cast(mParentMenu); + MenuItemBase *it = m.GetItem(NAME_Controlmessage); + if (it != null) + { + it.SetValue(0, which); + } + } + } + + bool Responder(event_t *ev) + { + if (ev.type == EV_KeyDown) + { + *pKey = ev.data1; + menuactive = MENU_On; + SetMenuMessage(0); + Close(); + mParentMenu.CallMenuEvent((ev.data1 == KEY_ESCAPE)? Menu.MKEY_Abort : Menu.MKEY_Input, 0); + return true; + } + return false; + } + + void Drawer() + { + mParentMenu.CallDrawer(); + } +}; + +#ifndef NO_IMP +IMPLEMENT_CLASS(DEnterKey, true, false) +#endif +*/ + +//============================================================================= +// +// // Edit a key binding, Action is the CCMD to bind +// +//============================================================================= + +class OptionMenuItemControl : OptionMenuItem +{ + KeyBindings mBindings; + int mInput; + bool mWaiting; + + void Init(String label, Name command, KeyBindings bindings) + { + Super.init(label, command); + mBindings = bindings; + mWaiting = false; + } + + //============================================================================= + override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) + { + drawLabel(indent, y, mWaiting? OptionMenuSettings.mFontColorHighlight: + (selected? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor)); + + String description; + int Key1, Key2; + + [Key1, Key2] = mBindings.GetKeysForCommand(mAction); + description = KeyBindings.NameKeys (Key1, Key2); + if (description.Length() > 0) + { + Menu.DrawConText(Font.CR_WHITE, indent + CursorSpace(), y + (OptionMenuSettings.mLinespacing-8)*CleanYfac_1, description); + } + else + { + screen.DrawText(SmallFont, Font.CR_BLACK, indent + CursorSpace(), y + (OptionMenuSettings.mLinespacing-8)*CleanYfac_1, "---", DTA_CleanNoMove_1, true); + } + return indent; + } + + //============================================================================= + override bool MenuEvent(int mkey, bool fromcontroller) + { + if (mkey == Menu.MKEY_Input) + { + mWaiting = false; + mBindings.SetBind(mInput, mAction); + return true; + } + else if (mkey == Menu.MKEY_Clear) + { + mBindings.UnbindACommand(mAction); + return true; + } + else if (mkey == Menu.MKEY_Abort) + { + mWaiting = false; + return true; + } + return false; + } + + override bool Activate() + { + Menu.MenuSound("menu/choose"); + mWaiting = true; + //Menu *input = new DEnterKey(Menu.CurrentMenu, &mInput); + //M_ActivateMenu(input); + return true; + } +} + +//============================================================================= +// +// +// +//============================================================================= + +class OptionMenuItemStaticText : OptionMenuItem +{ + int mColor; + + void Init(String label, int cr = -1, bool header = false) + { + Super.Init(label, 'None', true); + mColor = cr >= 0? cr : header ? OptionMenuSettings.mFontColorHeader : OptionMenuSettings.mFontColor; + } + + override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) + { + drawLabel(indent, y, mColor); + return -1; + } + + override bool Selectable() + { + return false; + } + +} + +//============================================================================= +// +// +// +//============================================================================= + +class OptionMenuItemStaticTextSwitchable : OptionMenuItem +{ + int mColor; + String mAltText; + int mCurrent; + + void Init(String label, String label2, Name command, int cr) + { + Super.Init(label, command, true); + mColor = cr; + mAltText = label2; + mCurrent = 0; + } + + override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) + { + String txt = StringTable.Localize(mCurrent? mAltText : mLabel); + int w = SmallFont.StringWidth(txt) * CleanXfac_1; + int x = (screen.GetWidth() - w) / 2; + screen.DrawText (SmallFont, mColor, x, y, txt, DTA_CleanNoMove_1, true); + return -1; + } + + override bool SetValue(int i, int val) + { + if (i == 0) + { + mCurrent = val; + return true; + } + return false; + } + + override bool SetString(int i, String newtext) + { + if (i == 0) + { + mAltText = newtext; + return true; + } + return false; + } + + override bool Selectable() + { + return false; + } +} + +//============================================================================= +// +// +// +//============================================================================= + +class OptionMenuSliderBase : OptionMenuItem +{ + // command is a CVAR + double mMin, mMax, mStep; + int mShowValue; + int mDrawX; + int mSliderShort; + + void Init(String label, double min, double max, double step, int showval) + { + Super.Init(label, 'None'); + mMin = min; + mMax = max; + mStep = step; + mShowValue = showval; + mDrawX = 0; + mSliderShort = 0; + } + + virtual double GetSliderValue() + { + return 0; + } + + virtual void SetSliderValue(double val) + { + } + + //============================================================================= + // + // Draw a slider. Set fracdigits negative to not display the current value numerically. + // + //============================================================================= + + private void DrawSlider (int x, int y, double min, double max, double cur, int fracdigits, int indent) + { + String formater = String.format("%%.%f", fracdigits); // The format function cannot do the '%.*f' syntax. + String textbuf; + double range; + int maxlen = 0; + int right = x + (12*8 + 4) * CleanXfac_1; + int cy = y + (OptionMenuSettings.mLinespacing-8)*CleanYfac_1; + + range = max - min; + double ccur = clamp(cur, min, max) - min; + + if (fracdigits >= 0) + { + textbuf = String.format(formater, max); + maxlen = SmallFont.StringWidth(textbuf) * CleanXfac_1; + } + + mSliderShort = right + maxlen > screen.GetWidth(); + + if (!mSliderShort) + { + Menu.DrawConText(Font.CR_WHITE, x, cy, "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12"); + Menu.DrawConText(Font.CR_ORANGE, x + int((5 + ((ccur * 78) / range)) * CleanXfac_1), cy, "\x13"); + } + else + { + // On 320x200 we need a shorter slider + Menu.DrawConText(Font.CR_WHITE, x, cy, "\x10\x11\x11\x11\x11\x11\x12"); + Menu.DrawConText(Font.CR_ORANGE, x + int((5 + ((ccur * 38) / range)) * CleanXfac_1), cy, "\x13"); + right -= 5*8*CleanXfac_1; + } + + if (fracdigits >= 0 && right + maxlen <= screen.GetWidth()) + { + textbuf = String.format(formater, cur); + screen.DrawText(SmallFont, Font.CR_DARKGRAY, right, y, textbuf, DTA_CleanNoMove_1, true); + } + } + + + //============================================================================= + override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) + { + drawLabel(indent, y, selected? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor); + mDrawX = indent + CursorSpace(); + DrawSlider (mDrawX, y, mMin, mMax, GetSliderValue(), mShowValue, indent); + return indent; + } + + //============================================================================= + override bool MenuEvent (int mkey, bool fromcontroller) + { + double value = GetSliderValue(); + + if (mkey == Menu.MKEY_Left) + { + value -= mStep; + } + else if (mkey == Menu.MKEY_Right) + { + value += mStep; + } + else + { + return OptionMenuItem.MenuEvent(mkey, fromcontroller); + } + if (value ~== 0) value = 0; // This is to prevent formatting anomalies with very small values + SetSliderValue(clamp(value, mMin, mMax)); + Menu.MenuSound("menu/change"); + return true; + } + + override bool MouseEvent(int type, int x, int y) + { + let lm = OptionMenu(Menu.GetCurrentMenu()); + if (type != Menu.MOUSE_Click) + { + if (!lm.CheckFocus(self)) return false; + } + if (type == Menu.MOUSE_Release) + { + lm.ReleaseFocus(); + } + + int slide_left = mDrawX+8*CleanXfac_1; + int slide_right = slide_left + (10*8*CleanXfac_1 >> mSliderShort); // 12 char cells with 8 pixels each. + + if (type == Menu.MOUSE_Click) + { + if (x < slide_left || x >= slide_right) return true; + } + + x = clamp(x, slide_left, slide_right); + double v = mMin + ((x - slide_left) * (mMax - mMin)) / (slide_right - slide_left); + if (v != GetSliderValue()) + { + SetSliderValue(v); + //Menu.MenuSound("menu/change"); + } + if (type == Menu.MOUSE_Click) + { + lm.SetFocus(self); + } + return true; + } + +} + +//============================================================================= +// +// +// +//============================================================================= + +class OptionMenuSliderCVar : OptionMenuSliderBase +{ + CVar mCVar; + + void Init(String label, Name command, double min, double max, double step, int showval) + { + Super.Init(label, min, max, step, showval); + mCVar =CVar.FindCVar(command); + } + + override double GetSliderValue() + { + if (mCVar != null) + { + return mCVar.GetFloat(); + } + else + { + return 0; + } + } + + override void SetSliderValue(double val) + { + if (mCVar != null) + { + mCVar.SetFloat(val); + } + } +} + +//============================================================================= +// +// // Edit a key binding, Action is the CCMD to bind +// +//============================================================================= + +class OptionMenuItemColorPicker : OptionMenuItem +{ + CVar mCVar; + + const CPF_RESET = 0x20001; + + void Init(String label, Name command) + { + Super.Init(label, command); + CVar cv = CVar.FindCVar(command); + if (cv != null && cv.GetRealType() == CVar.CVAR_Color) cv = null; + mCVar = cv; + } + + //============================================================================= + override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) + { + drawLabel(indent, y, selected? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor); + + if (mCVar != null) + { + int box_x = indent + CursorSpace(); + int box_y = y + CleanYfac_1; + screen.Clear (box_x, box_y, box_x + 32*CleanXfac_1, box_y + OptionMenuSettings.mLinespacing*CleanYfac_1, -1, mCVar.GetInt() | 0xff000000); + } + return indent; + } + + override bool SetValue(int i, int v) + { + if (i == CPF_RESET && mCVar != null) + { + mCVar.ResetToDefault(); + return true; + } + return false; + } + + override bool Activate() + { + if (mCVar != null) + { + Menu.MenuSound("menu/choose"); + /* + Menu *picker = StartPickerMenu(Menu.CurrentMenu, mLabel, mCVar); + if (picker != null) + { + M_ActivateMenu(picker); + return true; + } + */ + } + return false; + } +} + + +class OptionMenuScreenResolutionLine : OptionMenuItem +{ + String mResTexts[3]; + int mSelection; + int mHighlight; + int mMaxValid; + + enum EValues + { + SRL_INDEX = 0x30000, + SRL_SELECTION = 0x30003, + SRL_HIGHLIGHT = 0x30004, + }; + + void Init(String command) + { + Super.Init("", command); + mSelection = 0; + mHighlight = -1; + } + + override bool SetValue(int i, int v) + { + if (i == SRL_SELECTION) + { + mSelection = v; + return true; + } + else if (i == SRL_HIGHLIGHT) + { + mHighlight = v; + return true; + } + return false; + } + + override bool, int GetValue(int i) + { + if (i == SRL_SELECTION) + { + return true, mSelection; + } + return false, 0; + } + + override bool SetString(int i, String newtext) + { + if (i >= SRL_INDEX && i <= SRL_INDEX+2) + { + mResTexts[i-SRL_INDEX] = newtext; + if (mResTexts[0].Length() == 0) mMaxValid = -1; + else if (mResTexts[1].Length() == 0) mMaxValid = 0; + else if (mResTexts[2].Length() == 0) mMaxValid = 1; + else mMaxValid = 2; + return true; + } + return false; + } + + override bool, String GetString(int i) + { + if (i >= SRL_INDEX && i <= SRL_INDEX+2) + { + return true, mResTexts[i-SRL_INDEX]; + } + return false, ""; + } + + override bool MenuEvent (int mkey, bool fromcontroller) + { + if (mkey == Menu.MKEY_Left) + { + if (--mSelection < 0) mSelection = mMaxValid; + Menu.MenuSound ("menu/cursor"); + return true; + } + else if (mkey == Menu.MKEY_Right) + { + if (++mSelection > mMaxValid) mSelection = 0; + Menu.MenuSound ("menu/cursor"); + return true; + } + else + { + return Super.MenuEvent(mkey, fromcontroller); + } + return false; + } + + override bool MouseEvent(int type, int x, int y) + { + int colwidth = screen.GetWidth() / 3; + mSelection = x / colwidth; + return Super.MouseEvent(type, x, y); + } + + override bool Activate() + { + Menu.MenuSound("menu/choose"); + Menu.SetVideoMode(); + return true; + } + + override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) + { + int colwidth = screen.GetWidth() / 3; + int col; + + for (int x = 0; x < 3; x++) + { + if (selected && mSelection == x) + col = OptionMenuSettings.mFontColorSelection; + else if (x == mHighlight) + col = OptionMenuSettings.mFontColorHighlight; + else + col = OptionMenuSettings.mFontColorValue; + + screen.DrawText (SmallFont, col, colwidth * x + 20 * CleanXfac_1, y, mResTexts[x], DTA_CleanNoMove_1, true); + } + return colwidth * mSelection + 20 * CleanXfac_1 - CursorSpace(); + } + + override bool Selectable() + { + return mMaxValid >= 0; + } + + override void Ticker() + { + if (Selectable() && mSelection > mMaxValid) + { + mSelection = mMaxValid; + } + } +} + +//============================================================================= +// +// [TP] OptionMenuFieldBase +// +// Base class for input fields +// +//============================================================================= + +class OptionMenuFieldBase : OptionMenuItem +{ + void Init (String label, Name command, CVar graycheck = null) + { + Super.Init(label, command); + mCVar = CVar.FindCVar(mAction); + mGrayCheck = graycheck; + } + + String GetCVarString() + { + if (mCVar == null) + return ""; + + return mCVar.GetString(); + } + + virtual String Represent() + { + return GetCVarString(); + } + + override int Draw (OptionMenuDescriptor d, int y, int indent, bool selected) + { + bool grayed = mGrayCheck != null && !mGrayCheck.GetInt(); + drawLabel(indent, y, selected ? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor, grayed); + int overlay = grayed? Color(96, 48, 0, 0) : 0; + + screen.DrawText(SmallFont, OptionMenuSettings.mFontColorValue, indent + CursorSpace(), y, Represent(), DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay); + return indent; + } + + override bool, String GetString (int i) + { + if (i == 0) + { + return true, GetCVarString(); + } + return false, ""; + } + + override bool SetString (int i, String s) + { + if (i == 0) + { + if (mCVar) mCVar.SetString(s); + return true; + } + return false; + } + + + CVar mCVar; + CVar mGrayCheck; +} + +//============================================================================= +// +// [TP] OptionMenuTextField +// +// A text input field widget, for use with string CVars. +// +//============================================================================= + +class OptionMenuTextField : OptionMenuFieldBase +{ + void Init (String label, Name command, CVar graycheck = null) + { + Super.Init(label, command, graycheck); + mEntering = false; + } + + override String Represent() + { + if (mEntering) return mEditName .. ((gameinfo.gametype & GAME_DoomStrifeChex) ? "_" : "["); + else return GetCVarString(); + } + + override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) + { + if (mEntering) + { + // reposition the text so that the cursor is visible when in entering mode. + String text = Represent(); + int tlen = SmallFont.StringWidth(text) * CleanXfac_1; + int newindent = screen.GetWidth() - tlen - CursorSpace(); + if (newindent < indent) indent = newindent; + } + return Super.Draw(desc, y, indent, selected); + } + + override bool MenuEvent (int mkey, bool fromcontroller) + { + if (mkey == Menu.MKEY_Enter) + { + Menu.MenuSound("menu/choose"); + mEditName = GetCVarString(); + mEntering = true; + + //Menu* input = new DTextEnterMenu (Menu.CurrentMenu, mEditName, sizeof mEditName, 2, fromcontroller); + //M_ActivateMenu(input); + //OpenTextEnterMenu(mEditName, 2, fromcontroller); // needs a native workaround until menu creation is scriptable. + return true; + } + else if (mkey == Menu.MKEY_Input) + { + if (mCVar) mCVar.SetString(mEditName); + mEntering = false; + return true; + } + else if (mkey == Menu.MKEY_Abort) + { + mEntering = false; + return true; + } + + return Super.MenuEvent(mkey, fromcontroller); + } + + bool mEntering; + String mEditName; +} + + +//============================================================================= +// +// [TP] FOptionMenuNumberField +// +// A numeric input field widget, for use with number CVars where sliders are inappropriate (i.e. +// where the user is interested in the exact value specifically) +// +//============================================================================= + +class OptionMenuNumberField : OptionMenuFieldBase +{ + void Init (String label, Name command, float minimum, float maximum, float step, CVar graycheck = null) + { + Super.Init(label, command, graycheck); + mMinimum = min(minimum, maximum); + mMaximum = max(minimum, maximum); + mStep = max(1, step); + } + + override String Represent() + { + if (mCVar == null) return ""; + return String.format("%.3f", mCVar.GetFloat()); + } + + + override bool MenuEvent (int mkey, bool fromcontroller) + { + if (mCVar) + { + float value = mCVar.GetFloat(); + + if (mkey == Menu.MKEY_Left) + { + value -= mStep; + if (value < mMinimum) value = mMaximum; + } + else if (mkey == Menu.MKEY_Right || mkey == Menu.MKEY_Enter) + { + value += mStep; + if (value > mMaximum) value = mMinimum; + } + else + return Super.MenuEvent(mkey, fromcontroller); + + mCVar.SetFloat(value); + Menu.MenuSound("menu/change"); + } + + return true; + } + + float mMinimum; + float mMaximum; + float mStep; +} + From 947b625c5032f77b9c85f0e88223aa26c4346a80 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 11 Feb 2017 16:11:48 +0100 Subject: [PATCH 02/19] - all menu items scriptified, but not yet active. --- src/dobjtype.cpp | 9 +- src/menu/listmenu.cpp | 50 +- src/menu/menu.cpp | 22 + src/menu/menu.h | 77 +-- src/menu/menudef.cpp | 32 +- src/menu/playerdisplay.cpp | 20 +- src/menu/playermenu.cpp | 70 +-- src/p_states.cpp | 34 ++ src/p_user.cpp | 12 + src/r_data/r_translate.cpp | 57 +++ src/scripting/backend/codegen.cpp | 18 +- src/scripting/thingdef_data.cpp | 8 + src/scripting/zscript/zcc-parse.lemon | 4 + src/textures/texturemanager.cpp | 34 ++ src/v_draw.cpp | 11 + src/v_font.cpp | 5 + wadsrc/static/zscript.txt | 6 +- wadsrc/static/zscript/base.txt | 18 +- wadsrc/static/zscript/constants.txt | 1 + wadsrc/static/zscript/menu/joystickmenu.txt | 36 +- wadsrc/static/zscript/menu/listmenuitems.txt | 266 ++++++++++ wadsrc/static/zscript/menu/menu.txt | 52 +- wadsrc/static/zscript/menu/menuitembase.txt | 24 - .../static/zscript/menu/optionmenuitems.txt | 2 +- wadsrc/static/zscript/menu/playerdisplay.txt | 286 +++++++++++ wadsrc/static/zscript/menu/playermenu.txt | 470 ++++++++++++++++++ wadsrc/static/zscript/shared/player.txt | 9 + 27 files changed, 1469 insertions(+), 164 deletions(-) create mode 100644 wadsrc/static/zscript/menu/listmenuitems.txt create mode 100644 wadsrc/static/zscript/menu/playerdisplay.txt create mode 100644 wadsrc/static/zscript/menu/playermenu.txt diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 25e27b846..1e6211976 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3167,11 +3167,14 @@ void PClass::InitializeDefaults() assert(ParentClass != nullptr); ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults); - for (const PField *field : Fields) + if (Defaults != nullptr) { - if (!(field->Flags & VARF_Native)) + for (const PField *field : Fields) { - field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); + if (!(field->Flags & VARF_Native)) + { + field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); + } } } } diff --git a/src/menu/listmenu.cpp b/src/menu/listmenu.cpp index 2ade7d220..b039f46e0 100644 --- a/src/menu/listmenu.cpp +++ b/src/menu/listmenu.cpp @@ -389,16 +389,16 @@ int DMenuItemBase::GetWidth() // static patch // //============================================================================= -IMPLEMENT_CLASS(DListMenuItemStaticPatch, false, false) +IMPLEMENT_CLASS(DListMenuItemStaticPatch_, false, false) -DListMenuItemStaticPatch::DListMenuItemStaticPatch(int x, int y, FTextureID patch, bool centered) +DListMenuItemStaticPatch_::DListMenuItemStaticPatch_(int x, int y, FTextureID patch, bool centered) : DMenuItemBase(x, y) { mTexture = patch; mCentered = centered; } -void DListMenuItemStaticPatch::Drawer(bool selected) +void DListMenuItemStaticPatch_::Drawer(bool selected) { if (!mTexture.Exists()) { @@ -425,9 +425,9 @@ void DListMenuItemStaticPatch::Drawer(bool selected) // static text // //============================================================================= -IMPLEMENT_CLASS(DListMenuItemStaticText, false, false) +IMPLEMENT_CLASS(DListMenuItemStaticText_, false, false) -DListMenuItemStaticText::DListMenuItemStaticText(int x, int y, const char *text, FFont *font, EColorRange color, bool centered) +DListMenuItemStaticText_::DListMenuItemStaticText_(int x, int y, const char *text, FFont *font, EColorRange color, bool centered) : DMenuItemBase(x, y) { mText = text; @@ -436,7 +436,7 @@ DListMenuItemStaticText::DListMenuItemStaticText(int x, int y, const char *text, mCentered = centered; } -void DListMenuItemStaticText::Drawer(bool selected) +void DListMenuItemStaticText_::Drawer(bool selected) { if (mText.IsNotEmpty()) { @@ -462,9 +462,9 @@ void DListMenuItemStaticText::Drawer(bool selected) // base class for selectable items // //============================================================================= -IMPLEMENT_CLASS(DListMenuItemSelectable, false, false) +IMPLEMENT_CLASS(DListMenuItemSelectable_, false, false) -DListMenuItemSelectable::DListMenuItemSelectable(int x, int y, int height, FName action, int param) +DListMenuItemSelectable_::DListMenuItemSelectable_(int x, int y, int height, FName action, int param) : DMenuItemBase(x, y, action) { mHeight = height; @@ -472,34 +472,34 @@ DListMenuItemSelectable::DListMenuItemSelectable(int x, int y, int height, FName mHotkey = 0; } -bool DListMenuItemSelectable::CheckCoordinate(int x, int y) +bool DListMenuItemSelectable_::CheckCoordinate(int x, int y) { return mEnabled && y >= mYpos && y < mYpos + mHeight; // no x check here } -bool DListMenuItemSelectable::Selectable() +bool DListMenuItemSelectable_::Selectable() { return mEnabled; } -bool DListMenuItemSelectable::Activate() +bool DListMenuItemSelectable_::Activate() { M_SetMenu(mAction, mParam); return true; } -FName DListMenuItemSelectable::GetAction(int *pparam) +FName DListMenuItemSelectable_::GetAction(int *pparam) { if (pparam != NULL) *pparam = mParam; return mAction; } -bool DListMenuItemSelectable::CheckHotkey(int c) +bool DListMenuItemSelectable_::CheckHotkey(int c) { return c == tolower(mHotkey); } -bool DListMenuItemSelectable::MouseEvent(int type, int x, int y) +bool DListMenuItemSelectable_::MouseEvent(int type, int x, int y) { if (type == DMenu::MOUSE_Release) { @@ -516,10 +516,10 @@ bool DListMenuItemSelectable::MouseEvent(int type, int x, int y) // text item // //============================================================================= -IMPLEMENT_CLASS(DListMenuItemText, false, false) +IMPLEMENT_CLASS(DListMenuItemText_, false, false) -DListMenuItemText::DListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, EColorRange color2, FName child, int param) -: DListMenuItemSelectable(x, y, height, child, param) +DListMenuItemText_::DListMenuItemText_(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, EColorRange color2, FName child, int param) +: DListMenuItemSelectable_(x, y, height, child, param) { mText = ncopystring(text); mFont = font; @@ -528,7 +528,7 @@ DListMenuItemText::DListMenuItemText(int x, int y, int height, int hotkey, const mHotkey = hotkey; } -void DListMenuItemText::OnDestroy() +void DListMenuItemText_::OnDestroy() { if (mText != NULL) { @@ -536,7 +536,7 @@ void DListMenuItemText::OnDestroy() } } -void DListMenuItemText::Drawer(bool selected) +void DListMenuItemText_::Drawer(bool selected) { const char *text = mText; if (text != NULL) @@ -546,7 +546,7 @@ void DListMenuItemText::Drawer(bool selected) } } -int DListMenuItemText::GetWidth() +int DListMenuItemText_::GetWidth() { const char *text = mText; if (text != NULL) @@ -563,21 +563,21 @@ int DListMenuItemText::GetWidth() // patch item // //============================================================================= -IMPLEMENT_CLASS(DListMenuItemPatch, false, false) +IMPLEMENT_CLASS(DListMenuItemPatch_, false, false) -DListMenuItemPatch::DListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param) -: DListMenuItemSelectable(x, y, height, child, param) +DListMenuItemPatch_::DListMenuItemPatch_(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param) +: DListMenuItemSelectable_(x, y, height, child, param) { mHotkey = hotkey; mTexture = patch; } -void DListMenuItemPatch::Drawer(bool selected) +void DListMenuItemPatch_::Drawer(bool selected) { screen->DrawTexture (TexMan(mTexture), mXpos, mYpos, DTA_Clean, true, TAG_DONE); } -int DListMenuItemPatch::GetWidth() +int DListMenuItemPatch_::GetWidth() { return mTexture.isValid() ? TexMan[mTexture]->GetScaledWidth() diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 62ea9daa3..d28bc5496 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -78,6 +78,11 @@ DEFINE_ACTION_FUNCTION(DMenu, GetCurrentMenu) int DMenu::MenuTime; +DEFINE_ACTION_FUNCTION(DMenu, MenuTime) +{ + ACTION_RETURN_INT(DMenu::MenuTime); +} + FGameStartup GameStartupInfo; EMenuState menuactive; bool M_DemoNoPlay; @@ -1099,6 +1104,23 @@ DEFINE_FIELD(DMenuItemBase, mYpos) DEFINE_FIELD(DMenuItemBase, mAction) DEFINE_FIELD(DMenuItemBase, mEnabled) +DEFINE_FIELD(DListMenuDescriptor, mItems) +DEFINE_FIELD(DListMenuDescriptor, mSelectedItem) +DEFINE_FIELD(DListMenuDescriptor, mSelectOfsX) +DEFINE_FIELD(DListMenuDescriptor, mSelectOfsY) +DEFINE_FIELD(DListMenuDescriptor, mSelector) +DEFINE_FIELD(DListMenuDescriptor, mDisplayTop) +DEFINE_FIELD(DListMenuDescriptor, mXpos) +DEFINE_FIELD(DListMenuDescriptor, mYpos) +DEFINE_FIELD(DListMenuDescriptor, mWLeft) +DEFINE_FIELD(DListMenuDescriptor, mWRight) +DEFINE_FIELD(DListMenuDescriptor, mLinespacing) +DEFINE_FIELD(DListMenuDescriptor, mAutoselect) +DEFINE_FIELD(DListMenuDescriptor, mFont) +DEFINE_FIELD(DListMenuDescriptor, mFontColor) +DEFINE_FIELD(DListMenuDescriptor, mFontColor2) +DEFINE_FIELD(DListMenuDescriptor, mCenter) + DEFINE_FIELD(DOptionMenuDescriptor, mItems) DEFINE_FIELD(DOptionMenuDescriptor, mTitle) DEFINE_FIELD(DOptionMenuDescriptor, mSelectedItem) diff --git a/src/menu/menu.h b/src/menu/menu.h index e8d5b9a82..3af5e0efb 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -243,6 +243,11 @@ public: virtual void Close(); virtual bool MouseEvent(int type, int x, int y); + virtual void SetFocus(DMenuItemBase *fc) {} + virtual bool CheckFocus(DMenuItemBase *fc) { return false; } + virtual void ReleaseFocus() {} + + bool CallMenuEvent(int mkey, bool fromcontroller); bool CallMouseEvent(int type, int x, int y); void CallDrawer(); @@ -301,31 +306,31 @@ public: void SetX(int x) { mXpos = x; } }; -class DListMenuItemStaticPatch : public DMenuItemBase +class DListMenuItemStaticPatch_ : public DMenuItemBase { - DECLARE_CLASS(DListMenuItemStaticPatch, DMenuItemBase) + DECLARE_CLASS(DListMenuItemStaticPatch_, DMenuItemBase) protected: FTextureID mTexture; bool mCentered; - DListMenuItemStaticPatch() {} + DListMenuItemStaticPatch_() {} public: - DListMenuItemStaticPatch(int x, int y, FTextureID patch, bool centered); + DListMenuItemStaticPatch_(int x, int y, FTextureID patch, bool centered); void Drawer(bool selected); }; -class DListMenuItemStaticText : public DMenuItemBase +class DListMenuItemStaticText_ : public DMenuItemBase { - DECLARE_CLASS(DListMenuItemStaticText, DMenuItemBase) + DECLARE_CLASS(DListMenuItemStaticText_, DMenuItemBase) protected: FString mText; FFont *mFont; EColorRange mColor; bool mCentered; - DListMenuItemStaticText() {} + DListMenuItemStaticText_() {} public: - DListMenuItemStaticText(int x, int y, const char *text, FFont *font, EColorRange color, bool centered); + DListMenuItemStaticText_(int x, int y, const char *text, FFont *font, EColorRange color, bool centered); void Drawer(bool selected); }; @@ -335,9 +340,9 @@ public: // //============================================================================= -class DListMenuItemPlayerDisplay : public DMenuItemBase +class DListMenuItemPlayerDisplay_ : public DMenuItemBase { - DECLARE_CLASS(DListMenuItemPlayerDisplay, DMenuItemBase) + DECLARE_CLASS(DListMenuItemPlayerDisplay_, DMenuItemBase) DListMenuDescriptor *mOwner; FTexture *mBackdrop; @@ -359,7 +364,7 @@ class DListMenuItemPlayerDisplay : public DMenuItemBase void UpdateRandomClass(); void UpdateTranslation(); - DListMenuItemPlayerDisplay() {} + DListMenuItemPlayerDisplay_() {} public: enum @@ -371,7 +376,7 @@ public: PDF_TRANSLATE = 0x10005, }; - DListMenuItemPlayerDisplay(DListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action); + DListMenuItemPlayerDisplay_(DListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action); void OnDestroy() override; virtual void Ticker(); virtual void Drawer(bool selected); @@ -385,17 +390,17 @@ public: // //============================================================================= -class DListMenuItemSelectable : public DMenuItemBase +class DListMenuItemSelectable_ : public DMenuItemBase { - DECLARE_CLASS(DListMenuItemSelectable, DMenuItemBase) + DECLARE_CLASS(DListMenuItemSelectable_, DMenuItemBase) protected: int mHotkey; int mHeight; int mParam; - DListMenuItemSelectable() {} + DListMenuItemSelectable_() {} public: - DListMenuItemSelectable(int x, int y, int height, FName childmenu, int mParam = -1); + DListMenuItemSelectable_(int x, int y, int height, FName childmenu, int mParam = -1); bool CheckCoordinate(int x, int y); bool Selectable(); bool CheckHotkey(int c); @@ -404,30 +409,30 @@ public: FName GetAction(int *pparam); }; -class DListMenuItemText : public DListMenuItemSelectable +class DListMenuItemText_ : public DListMenuItemSelectable_ { - DECLARE_CLASS(DListMenuItemText, DListMenuItemSelectable) + DECLARE_CLASS(DListMenuItemText_, DListMenuItemSelectable_) const char *mText; FFont *mFont; EColorRange mColor; EColorRange mColorSelected; - DListMenuItemText() {} + DListMenuItemText_() {} public: - DListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, EColorRange color2, FName child, int param = 0); + DListMenuItemText_(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, EColorRange color2, FName child, int param = 0); void OnDestroy() override; void Drawer(bool selected); int GetWidth(); }; -class DListMenuItemPatch : public DListMenuItemSelectable +class DListMenuItemPatch_ : public DListMenuItemSelectable_ { - DECLARE_CLASS(DListMenuItemPatch, DListMenuItemSelectable) + DECLARE_CLASS(DListMenuItemPatch_, DListMenuItemSelectable_) FTextureID mTexture; - DListMenuItemPatch() {} + DListMenuItemPatch_() {} public: - DListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param = 0); + DListMenuItemPatch_(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param = 0); void Drawer(bool selected); int GetWidth(); }; @@ -438,9 +443,9 @@ public: // //============================================================================= -class DPlayerNameBox : public DListMenuItemSelectable +class DPlayerNameBox_ : public DListMenuItemSelectable_ { - DECLARE_CLASS(DPlayerNameBox, DListMenuItemSelectable) + DECLARE_CLASS(DPlayerNameBox_, DListMenuItemSelectable_) FString mText; FFont *mFont; EColorRange mFontColor; @@ -451,10 +456,10 @@ class DPlayerNameBox : public DListMenuItemSelectable void DrawBorder (int x, int y, int len); - DPlayerNameBox() {} + DPlayerNameBox_() {} public: - DPlayerNameBox(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action); + DPlayerNameBox_(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action); bool SetString(int i, const char *s); bool GetString(int i, char *s, int len); void Drawer(bool selected); @@ -467,9 +472,9 @@ public: // //============================================================================= -class DValueTextItem : public DListMenuItemSelectable +class DValueTextItem_ : public DListMenuItemSelectable_ { - DECLARE_CLASS(DValueTextItem, DListMenuItemSelectable) + DECLARE_CLASS(DValueTextItem_, DListMenuItemSelectable_) TArray mSelections; FString mText; int mSelection; @@ -477,10 +482,10 @@ class DValueTextItem : public DListMenuItemSelectable EColorRange mFontColor; EColorRange mFontColor2; - DValueTextItem() {} + DValueTextItem_() {} public: - DValueTextItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values); + DValueTextItem_(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values); bool SetString(int i, const char *s); bool SetValue(int i, int value); bool GetValue(int i, int *pvalue); @@ -494,9 +499,9 @@ public: // //============================================================================= -class DSliderItem : public DListMenuItemSelectable +class DSliderItem_ : public DListMenuItemSelectable_ { - DECLARE_CLASS(DSliderItem, DListMenuItemSelectable) + DECLARE_CLASS(DSliderItem_, DListMenuItemSelectable_) FString mText; FFont *mFont; EColorRange mFontColor; @@ -506,10 +511,10 @@ class DSliderItem : public DListMenuItemSelectable void DrawSlider (int x, int y); - DSliderItem() {} + DSliderItem_() {} public: - DSliderItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step); + DSliderItem_(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step); bool SetValue(int i, int value); bool GetValue(int i, int *pvalue); bool MenuEvent (int mkey, bool fromcontroller); diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 1a7657676..05bb16007 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -348,7 +348,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) sc.MustGetString(); FTextureID tex = GetMenuTexture(sc.String); - DMenuItemBase *it = new DListMenuItemStaticPatch(x, y, tex, centered); + DMenuItemBase *it = new DListMenuItemStaticPatch_(x, y, tex, centered); desc->mItems.Push(it); } else if (sc.Compare("StaticText") || sc.Compare("StaticTextCentered")) @@ -369,7 +369,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) cr = V_FindFontColor(sc.String); if (cr == CR_UNTRANSLATED && !sc.Compare("untranslated")) cr = desc->mFontColor; } - DMenuItemBase *it = new DListMenuItemStaticText(x, y, label, desc->mFont, cr, centered); + DMenuItemBase *it = new DListMenuItemStaticText_(x, y, label, desc->mFont, cr, centered); desc->mItems.Push(it); } else if (sc.Compare("PatchItem")) @@ -389,7 +389,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) param = sc.Number; } - DMenuItemBase *it = new DListMenuItemPatch(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, tex, action, param); + DMenuItemBase *it = new DListMenuItemPatch_(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, tex, action, param); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; @@ -411,7 +411,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) param = sc.Number; } - DMenuItemBase *it = new DListMenuItemText(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, param); + DMenuItemBase *it = new DListMenuItemText_(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, param); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; @@ -468,7 +468,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) action = sc.String; } } - DListMenuItemPlayerDisplay *it = new DListMenuItemPlayerDisplay(desc, x, y, c1, c2, noportrait, action); + DListMenuItemPlayerDisplay_ *it = new DListMenuItemPlayerDisplay_(desc, x, y, c1, c2, noportrait, action); desc->mItems.Push(it); } else if (sc.Compare("PlayerNameBox")) @@ -480,7 +480,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) int ofs = sc.Number; sc.MustGetStringName(","); sc.MustGetString(); - DMenuItemBase *it = new DPlayerNameBox(desc->mXpos, desc->mYpos, desc->mLinespacing, ofs, text, desc->mFont, desc->mFontColor, sc.String); + DMenuItemBase *it = new DPlayerNameBox_(desc->mXpos, desc->mYpos, desc->mLinespacing, ofs, text, desc->mFont, desc->mFontColor, sc.String); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; @@ -498,7 +498,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) sc.MustGetString(); values = sc.String; } - DMenuItemBase *it = new DValueTextItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, values); + DMenuItemBase *it = new DValueTextItem_(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, values); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; @@ -519,7 +519,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) sc.MustGetStringName(","); sc.MustGetNumber(); int step = sc.Number; - DMenuItemBase *it = new DSliderItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, action, min, max, step); + DMenuItemBase *it = new DSliderItem_(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, action, min, max, step); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; @@ -1144,12 +1144,12 @@ static void BuildEpisodeMenu() if (AllEpisodes[i].mPicName.IsNotEmpty()) { FTextureID tex = GetMenuTexture(AllEpisodes[i].mPicName); - it = new DListMenuItemPatch(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, + it = new DListMenuItemPatch_(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, tex, NAME_Skillmenu, i); } else { - it = new DListMenuItemText(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, + it = new DListMenuItemText_(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, AllEpisodes[i].mEpisodeName, ld->mFont, ld->mFontColor, ld->mFontColor2, NAME_Skillmenu, i); } ld->mItems.Push(it); @@ -1242,7 +1242,7 @@ static void BuildPlayerclassMenu() if (numclassitems <= 1) { // create a dummy item that auto-chooses the default class. - DListMenuItemText *it = new DListMenuItemText(0, 0, 0, 'p', "player", + DListMenuItemText_ *it = new DListMenuItemText_(0, 0, 0, 'p', "player", ld->mFont,ld->mFontColor, ld->mFontColor2, NAME_Episodemenu, -1000); ld->mAutoselect = ld->mItems.Push(it); success = true; @@ -1268,7 +1268,7 @@ static void BuildPlayerclassMenu() const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type); if (pname != nullptr) { - DListMenuItemText *it = new DListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname, + DListMenuItemText_ *it = new DListMenuItemText_(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname, pname, ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, i); ld->mItems.Push(it); ld->mYpos += ld->mLinespacing; @@ -1278,7 +1278,7 @@ static void BuildPlayerclassMenu() } if (n > 1 && !gameinfo.norandomplayerclass) { - DListMenuItemText *it = new DListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, 'r', + DListMenuItemText_ *it = new DListMenuItemText_(ld->mXpos, ld->mYpos, ld->mLinespacing, 'r', "$MNU_RANDOM", ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, -1); ld->mItems.Push(it); } @@ -1287,7 +1287,7 @@ static void BuildPlayerclassMenu() const char *pname = GetPrintableDisplayName(PlayerClasses[0].Type); if (pname != nullptr) { - DListMenuItemText *it = new DListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname, + DListMenuItemText_ *it = new DListMenuItemText_(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname, pname, ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, 0); ld->mItems.Push(it); } @@ -1548,13 +1548,13 @@ void M_StartupSkillMenu(FGameStartup *gs) if (skill.PicName.Len() != 0 && pItemText == nullptr) { FTextureID tex = GetMenuTexture(skill.PicName); - li = new DListMenuItemPatch(ld->mXpos, y, ld->mLinespacing, skill.Shortcut, tex, action, i); + li = new DListMenuItemPatch_(ld->mXpos, y, ld->mLinespacing, skill.Shortcut, tex, action, i); } else { EColorRange color = (EColorRange)skill.GetTextColor(); if (color == CR_UNTRANSLATED) color = ld->mFontColor; - li = new DListMenuItemText(x, y, ld->mLinespacing, skill.Shortcut, + li = new DListMenuItemText_(x, y, ld->mLinespacing, skill.Shortcut, pItemText? *pItemText : skill.MenuName, ld->mFont, color,ld->mFontColor2, action, i); } ld->mItems.Push(li); diff --git a/src/menu/playerdisplay.cpp b/src/menu/playerdisplay.cpp index 4b01ab398..5cd0f7815 100644 --- a/src/menu/playerdisplay.cpp +++ b/src/menu/playerdisplay.cpp @@ -54,8 +54,8 @@ // // //============================================================================= -IMPLEMENT_CLASS(DListMenuItemPlayerDisplay, false, false) -DListMenuItemPlayerDisplay::DListMenuItemPlayerDisplay(DListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action) +IMPLEMENT_CLASS(DListMenuItemPlayerDisplay_, false, false) +DListMenuItemPlayerDisplay_::DListMenuItemPlayerDisplay_(DListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action) : DMenuItemBase(x, y, action) { mOwner = menu; @@ -90,7 +90,7 @@ DListMenuItemPlayerDisplay::DListMenuItemPlayerDisplay(DListMenuDescriptor *menu // //============================================================================= -void DListMenuItemPlayerDisplay::OnDestroy() +void DListMenuItemPlayerDisplay_::OnDestroy() { } @@ -100,7 +100,7 @@ void DListMenuItemPlayerDisplay::OnDestroy() // //============================================================================= -void DListMenuItemPlayerDisplay::UpdateRandomClass() +void DListMenuItemPlayerDisplay_::UpdateRandomClass() { if (--mRandomTimer < 0) { @@ -126,7 +126,7 @@ void DListMenuItemPlayerDisplay::UpdateRandomClass() // //============================================================================= -void DListMenuItemPlayerDisplay::UpdateTranslation() +void DListMenuItemPlayerDisplay_::UpdateTranslation() { int PlayerColor = players[consoleplayer].userinfo.GetColor(); int PlayerSkin = players[consoleplayer].userinfo.GetSkin(); @@ -146,7 +146,7 @@ void DListMenuItemPlayerDisplay::UpdateTranslation() // //============================================================================= -void DListMenuItemPlayerDisplay::SetPlayerClass(int classnum, bool force) +void DListMenuItemPlayerDisplay_::SetPlayerClass(int classnum, bool force) { if (classnum < 0 || classnum >= (int)PlayerClasses.Size ()) { @@ -176,7 +176,7 @@ void DListMenuItemPlayerDisplay::SetPlayerClass(int classnum, bool force) // //============================================================================= -bool DListMenuItemPlayerDisplay::UpdatePlayerClass() +bool DListMenuItemPlayerDisplay_::UpdatePlayerClass() { if (mOwner->mSelectedItem >= 0) { @@ -198,7 +198,7 @@ bool DListMenuItemPlayerDisplay::UpdatePlayerClass() // //============================================================================= -bool DListMenuItemPlayerDisplay::SetValue(int i, int value) +bool DListMenuItemPlayerDisplay_::SetValue(int i, int value) { switch (i) { @@ -230,7 +230,7 @@ bool DListMenuItemPlayerDisplay::SetValue(int i, int value) // //============================================================================= -void DListMenuItemPlayerDisplay::Ticker() +void DListMenuItemPlayerDisplay_::Ticker() { if (mClassNum < 0) UpdateRandomClass(); @@ -250,7 +250,7 @@ void DListMenuItemPlayerDisplay::Ticker() // //============================================================================= -void DListMenuItemPlayerDisplay::Drawer(bool selected) +void DListMenuItemPlayerDisplay_::Drawer(bool selected) { if (mMode == 0 && !UpdatePlayerClass()) { diff --git a/src/menu/playermenu.cpp b/src/menu/playermenu.cpp index ee8ea1853..1621e3eba 100644 --- a/src/menu/playermenu.cpp +++ b/src/menu/playermenu.cpp @@ -60,10 +60,10 @@ EXTERN_CVAR (Bool, cl_run) // Player's name // //============================================================================= -IMPLEMENT_CLASS(DPlayerNameBox, false, false) +IMPLEMENT_CLASS(DPlayerNameBox_, false, false) -DPlayerNameBox::DPlayerNameBox(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action) -: DListMenuItemSelectable(x, y, height, action) +DPlayerNameBox_::DPlayerNameBox_(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action) +: DListMenuItemSelectable_(x, y, height, action) { mText = text; mFont = font; @@ -79,7 +79,7 @@ DPlayerNameBox::DPlayerNameBox(int x, int y, int height, int frameofs, const cha // //============================================================================= -bool DPlayerNameBox::SetString(int i, const char *s) +bool DPlayerNameBox_::SetString(int i, const char *s) { if (i == 0) { @@ -90,8 +90,8 @@ bool DPlayerNameBox::SetString(int i, const char *s) return false; } -bool DPlayerNameBox::GetString(int i, char *s, int len) -{ +bool DPlayerNameBox_::GetString(int i, char *s, int len) +{ if (i == 0) { strncpy(s, mPlayerName, len); @@ -107,7 +107,7 @@ bool DPlayerNameBox::GetString(int i, char *s, int len) // //============================================================================= -void DPlayerNameBox::DrawBorder (int x, int y, int len) +void DPlayerNameBox_::DrawBorder (int x, int y, int len) { FTexture *left = TexMan[TexMan.CheckForTexture("M_LSLEFT", FTexture::TEX_MiscPatch)]; FTexture *mid = TexMan[TexMan.CheckForTexture("M_LSCNTR", FTexture::TEX_MiscPatch)]; @@ -146,7 +146,7 @@ void DPlayerNameBox::DrawBorder (int x, int y, int len) // //============================================================================= -void DPlayerNameBox::Drawer(bool selected) +void DPlayerNameBox_::Drawer(bool selected) { const char *text = mText; if (text != NULL) @@ -182,7 +182,7 @@ void DPlayerNameBox::Drawer(bool selected) // //============================================================================= -bool DPlayerNameBox::MenuEvent(int mkey, bool fromcontroller) +bool DPlayerNameBox_::MenuEvent(int mkey, bool fromcontroller) { if (mkey == MKEY_Enter) { @@ -212,10 +212,10 @@ bool DPlayerNameBox::MenuEvent(int mkey, bool fromcontroller) // items for the player menu // //============================================================================= -IMPLEMENT_CLASS(DValueTextItem, false, false) +IMPLEMENT_CLASS(DValueTextItem_, false, false) -DValueTextItem::DValueTextItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values) -: DListMenuItemSelectable(x, y, height, action) +DValueTextItem_::DValueTextItem_(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values) +: DListMenuItemSelectable_(x, y, height, action) { mText = text; mFont = font; @@ -241,7 +241,7 @@ DValueTextItem::DValueTextItem(int x, int y, int height, const char *text, FFont // //============================================================================= -bool DValueTextItem::SetString(int i, const char *s) +bool DValueTextItem_::SetString(int i, const char *s) { // should actually use the index... FString str = s; @@ -256,7 +256,7 @@ bool DValueTextItem::SetString(int i, const char *s) // //============================================================================= -bool DValueTextItem::SetValue(int i, int value) +bool DValueTextItem_::SetValue(int i, int value) { if (i == 0) { @@ -266,7 +266,7 @@ bool DValueTextItem::SetValue(int i, int value) return false; } -bool DValueTextItem::GetValue(int i, int *pvalue) +bool DValueTextItem_::GetValue(int i, int *pvalue) { if (i == 0) { @@ -282,7 +282,7 @@ bool DValueTextItem::GetValue(int i, int *pvalue) // //============================================================================= -bool DValueTextItem::MenuEvent (int mkey, bool fromcontroller) +bool DValueTextItem_::MenuEvent (int mkey, bool fromcontroller) { if (mSelections.Size() > 1) { @@ -308,7 +308,7 @@ bool DValueTextItem::MenuEvent (int mkey, bool fromcontroller) // //============================================================================= -void DValueTextItem::Drawer(bool selected) +void DValueTextItem_::Drawer(bool selected) { const char *text = mText; @@ -329,10 +329,10 @@ void DValueTextItem::Drawer(bool selected) // items for the player menu // //============================================================================= -IMPLEMENT_CLASS(DSliderItem, false, false) +IMPLEMENT_CLASS(DSliderItem_, false, false) -DSliderItem::DSliderItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step) -: DListMenuItemSelectable(x, y, height, action) +DSliderItem_::DSliderItem_(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step) +: DListMenuItemSelectable_(x, y, height, action) { mText = text; mFont = font; @@ -349,7 +349,7 @@ DSliderItem::DSliderItem(int x, int y, int height, const char *text, FFont *font // //============================================================================= -bool DSliderItem::SetValue(int i, int value) +bool DSliderItem_::SetValue(int i, int value) { if (i == 0) { @@ -359,7 +359,7 @@ bool DSliderItem::SetValue(int i, int value) return false; } -bool DSliderItem::GetValue(int i, int *pvalue) +bool DSliderItem_::GetValue(int i, int *pvalue) { if (i == 0) { @@ -375,7 +375,7 @@ bool DSliderItem::GetValue(int i, int *pvalue) // //============================================================================= -bool DSliderItem::MenuEvent (int mkey, bool fromcontroller) +bool DSliderItem_::MenuEvent (int mkey, bool fromcontroller) { if (mkey == MKEY_Left) { @@ -398,7 +398,7 @@ bool DSliderItem::MenuEvent (int mkey, bool fromcontroller) // //============================================================================= -bool DSliderItem::MouseEvent(int type, int x, int y) +bool DSliderItem_::MouseEvent(int type, int x, int y) { DListMenu *lm = static_cast(DMenu::CurrentMenu); if (type != DMenu::MOUSE_Click) @@ -438,7 +438,7 @@ bool DSliderItem::MouseEvent(int type, int x, int y) // //============================================================================= -void DSliderItem::DrawSlider (int x, int y) +void DSliderItem_::DrawSlider (int x, int y) { int range = mMaxrange - mMinrange; int cur = mSelection - mMinrange; @@ -464,7 +464,7 @@ void DSliderItem::DrawSlider (int x, int y) // //============================================================================= -void DSliderItem::Drawer(bool selected) +void DSliderItem_::Drawer(bool selected) { const char *text = mText; @@ -536,14 +536,14 @@ void DPlayerMenu::Init(DMenu *parent, DListMenuDescriptor *desc) li = GetItem(NAME_Playerdisplay); if (li != NULL) { - li->SetValue(DListMenuItemPlayerDisplay::PDF_ROTATION, 0); - li->SetValue(DListMenuItemPlayerDisplay::PDF_MODE, 1); - li->SetValue(DListMenuItemPlayerDisplay::PDF_TRANSLATE, 1); - li->SetValue(DListMenuItemPlayerDisplay::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum()); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_ROTATION, 0); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_MODE, 1); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_TRANSLATE, 1); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum()); if (PlayerClass != NULL && !(GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN) && players[consoleplayer].userinfo.GetPlayerClassNum() != -1) { - li->SetValue(DListMenuItemPlayerDisplay::PDF_SKIN, players[consoleplayer].userinfo.GetSkin()); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_SKIN, players[consoleplayer].userinfo.GetSkin()); } } @@ -658,7 +658,7 @@ bool DPlayerMenu::Responder (event_t *ev) DMenuItemBase *li = GetItem(NAME_Playerdisplay); if (li != NULL) { - li->SetValue(DListMenuItemPlayerDisplay::PDF_ROTATION, mRotation); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_ROTATION, mRotation); } return true; } @@ -812,7 +812,7 @@ void DPlayerMenu::UpdateSkins() li = GetItem(NAME_Playerdisplay); if (li != NULL) { - li->SetValue(DListMenuItemPlayerDisplay::PDF_SKIN, skin); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_SKIN, skin); } } UpdateTranslation(); @@ -908,7 +908,7 @@ void DPlayerMenu::ClassChanged (DMenuItemBase *li) li = GetItem(NAME_Playerdisplay); if (li != NULL) { - li->SetValue(DListMenuItemPlayerDisplay::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum()); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum()); } } } @@ -939,7 +939,7 @@ void DPlayerMenu::SkinChanged (DMenuItemBase *li) li = GetItem(NAME_Playerdisplay); if (li != NULL) { - li->SetValue(DListMenuItemPlayerDisplay::PDF_SKIN, sel); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_SKIN, sel); } } } diff --git a/src/p_states.cpp b/src/p_states.cpp index 221ff6ced..3602cfc81 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -51,6 +51,40 @@ FStateLabelStorage StateLabels; // actor. States are archived by recording the actor they belong // to and the index into that actor's list of states. + +//========================================================================== +// +// This wraps everything needed to get a current sprite from a state into +// one single script function. +// +//========================================================================== + +DEFINE_ACTION_FUNCTION(FState, GetSpriteTexture) +{ + PARAM_SELF_STRUCT_PROLOGUE(FState); + PARAM_INT(rotation); + PARAM_INT_DEF(skin); + PARAM_FLOAT_DEF(scalex); + PARAM_FLOAT_DEF(scaley); + + spriteframe_t *sprframe; + if (skin == 0) + { + sprframe = &SpriteFrames[sprites[self->sprite].spriteframes + self->GetFrame()]; + } + else + { + sprframe = &SpriteFrames[sprites[skins[skin].sprite].spriteframes + self->GetFrame()]; + scalex = skins[skin].Scale.X; + scaley = skins[skin].Scale.Y; + } + if (numret > 0) ret[0].SetInt(sprframe->Texture[rotation].GetIndex()); + if (numret > 1) ret[1].SetInt(!!(sprframe->Flip & (1 << rotation))); + if (numret > 2) ret[2].SetVector2(DVector2(scalex, scaley)); + return MIN(3, numret); +} + + //========================================================================== // // Find the actor that a state belongs to. diff --git a/src/p_user.cpp b/src/p_user.cpp index 0860796ef..6e7d7c8ec 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -60,6 +60,7 @@ #include "p_spec.h" #include "virtual.h" #include "g_levellocals.h" +#include "r_data/r_translate.h" static FRandom pr_skullpop ("SkullPop"); @@ -142,6 +143,13 @@ bool FPlayerClass::CheckSkin (int skin) return false; } +DEFINE_ACTION_FUNCTION(FPlayerClass, CheckSkin) +{ + PARAM_SELF_STRUCT_PROLOGUE(FPlayerClass); + PARAM_INT(skin); + ACTION_RETURN_BOOL(self->CheckSkin(skin)); +} + //=========================================================================== // // GetDisplayName @@ -3341,3 +3349,7 @@ DEFINE_FIELD_X(PlayerInfo, player_t, cmd) DEFINE_FIELD_X(PlayerInfo, player_t, original_cmd) DEFINE_FIELD_X(PlayerInfo, player_t, userinfo) DEFINE_FIELD_X(PlayerInfo, player_t, weapons) + +DEFINE_FIELD(FPlayerClass, Type) +DEFINE_FIELD(FPlayerClass, Flags) +DEFINE_FIELD(FPlayerClass, Skins) diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index 64f490b30..bd31d9a30 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -1200,6 +1200,63 @@ void R_GetPlayerTranslation (int color, const FPlayerColorSet *colorset, FPlayer R_CreatePlayerTranslation (h, s, v, colorset, skin, table, NULL, NULL); } + +DEFINE_ACTION_FUNCTION(_Translation, SetPlayerTranslation) +{ + PARAM_PROLOGUE; + PARAM_UINT(tgroup); + PARAM_UINT(tnum); + PARAM_UINT(pnum); + PARAM_POINTER(cls, FPlayerClass); + + if (pnum >= MAXPLAYERS || tgroup >= NUM_TRANSLATION_TABLES || tnum >= translationtables[tgroup].Size()) + { + ACTION_RETURN_BOOL(false); + } + auto self = &players[pnum]; + int PlayerColor = self->userinfo.GetColor(); + int PlayerSkin = self->userinfo.GetSkin(); + int PlayerColorset = self->userinfo.GetColorSet(); + + if (cls != nullptr) + { + PlayerSkin = R_FindSkin(skins[PlayerSkin].name, int(cls - &PlayerClasses[0])); + R_GetPlayerTranslation(PlayerColor, GetColorSet(cls->Type, PlayerColorset), + &skins[PlayerSkin], translationtables[tgroup][tnum]); + } + ACTION_RETURN_BOOL(true); +} + +//---------------------------------------------------------------------------- +// +// +// +//---------------------------------------------------------------------------- + +struct FTranslation +{ + PalEntry colors[256]; +}; + +DEFINE_ACTION_FUNCTION(_Translation, SetTranslation) +{ + PARAM_SELF_STRUCT_PROLOGUE(FTranslation); + PARAM_UINT(tgroup); + PARAM_UINT(tnum); + if (tgroup >= NUM_TRANSLATION_TABLES || tnum >= translationtables[tgroup].Size()) + { + ACTION_RETURN_BOOL(false); + } + auto remap = translationtables[tgroup][tnum]; + int i = 0; + for (auto p : self->colors) + { + remap->Palette[i] = p; + remap->Remap[i] = ColorMatcher.Pick(p); + } + ACTION_RETURN_BOOL(true); +} + //---------------------------------------------------------------------------- // // diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index eb4ed2e47..d6b89c1a0 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -2456,7 +2456,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) ExpEmit FxAssign::Emit(VMFunctionBuilder *build) { static const BYTE loadops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP }; - assert(ValueType->GetRegType() == Right->ValueType->GetRegType()); + assert(Base->ValueType->GetRegType() == Right->ValueType->GetRegType()); ExpEmit pointer = Base->Emit(build); Address = pointer; @@ -2974,6 +2974,12 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) delete this; return nullptr; } + if (!left->ValueType || !right->ValueType) + { + ScriptPosition.Message(MSG_ERROR, "ValueType not set"); + delete this; + return nullptr; + } if (left->IsVector() || right->IsVector()) { @@ -3552,6 +3558,16 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) goto error; } } + else if (left->IsPointer() && static_cast(left->ValueType)->PointedType == right->ValueType) + { + bool writable; + if (!right->RequestAddress(ctx, &writable)) goto error; + } + else if (right->IsPointer() && static_cast(right->ValueType)->PointedType == left->ValueType) + { + bool writable; + if (!left->RequestAddress(ctx, &writable)) goto error; + } else { goto error; diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 8cd10b75d..c736b5487 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -754,6 +754,10 @@ void InitThingdef() sectorportalstruct->Size = sizeof(FSectorPortal); sectorportalstruct->Align = alignof(FSectorPortal); + auto playerclassstruct = NewNativeStruct("PlayerClass", nullptr); + playerclassstruct->Size = sizeof(FPlayerClass); + playerclassstruct->Align = alignof(FPlayerClass); + // set up the lines array in the sector struct. This is a bit messy because the type system is not prepared to handle a pointer to an array of pointers to a native struct even remotely well... // As a result, the size has to be set to something large and arbritrary because it can change between maps. This will need some serious improvement when things get cleaned up. sectorstruct->AddNativeField("lines", NewPointer(NewResizableArray(NewPointer(linestruct, false)), false), myoffsetof(sector_t, Lines), VARF_Native); @@ -789,6 +793,10 @@ void InitThingdef() PField *aacf = new PField("AllActorClasses", aact, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&PClassActor::AllActorClasses); Namespaces.GlobalNamespace->Symbols.AddSymbol(aacf); + auto plrcls = NewPointer(NewResizableArray(playerclassstruct), false); + PField *plrclsf = new PField("PlayerClasses", plrcls, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&PlayerClasses); + Namespaces.GlobalNamespace->Symbols.AddSymbol(plrclsf); + // set up a variable for the DEH data PStruct *dstruct = NewNativeStruct("DehInfo", nullptr); PField *dehf = new PField("deh", dstruct, VARF_Native | VARF_Static, (intptr_t)&deh); diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index bae828493..6d3e8a856 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -12,6 +12,10 @@ static void SetNodeLine(ZCC_TreeNode *name, ZCCToken &tok) static void SetNodeLine(ZCC_TreeNode *name, ZCC_TreeNode *node) { + if (name == nullptr || node == nullptr) + { + I_Error("Fatal parse error"); + } name->SourceLoc = node->SourceLoc; } diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 114919df9..bbbb016ea 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -1189,6 +1189,40 @@ int FTextureManager::CountLumpTextures (int lumpnum) return 0; } +//========================================================================== +// +// +// +//========================================================================== + +DEFINE_ACTION_FUNCTION(_TexMan, GetSize) +{ + PARAM_PROLOGUE; + PARAM_INT(texid); + auto tex = TexMan[FSetTextureID(texid)]; + int x, y; + if (tex != nullptr) + { + x = tex->GetWidth(); + y = tex->GetHeight(); + } + else x = y = -1; + if (numret > 0) ret[0].SetInt(x); + if (numret > 1) ret[1].SetInt(x); + return MIN(numret, 2); +} + +DEFINE_ACTION_FUNCTION(_TexMan, GetScaledSize) +{ + PARAM_PROLOGUE; + PARAM_INT(texid); + auto tex = TexMan[FSetTextureID(texid)]; + if (tex != nullptr) + { + ACTION_RETURN_VEC2(DVector2(tex->GetScaledWidthDouble(), tex->GetScaledHeightDouble())); + } + ACTION_RETURN_VEC2(DVector2(-1, -1)); +} //========================================================================== // diff --git a/src/v_draw.cpp b/src/v_draw.cpp index d2b09b0d1..ca5e1fa37 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -1716,6 +1716,17 @@ void V_DrawFrame (int left, int top, int width, int height) screen->DrawTexture (TexMan[border->br], left+width, top+height, TAG_DONE); } +DEFINE_ACTION_FUNCTION(_Screen, DrawFrame) +{ + PARAM_PROLOGUE; + PARAM_INT(x); + PARAM_INT(y); + PARAM_INT(w); + PARAM_INT(h); + V_DrawFrame(x, y, w, h); + return 0; +} + //========================================================================== // // V_DrawBorder diff --git a/src/v_font.cpp b/src/v_font.cpp index 669054001..a82bd16c1 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -2739,3 +2739,8 @@ void V_ClearFonts() SmallFont = SmallFont2 = BigFont = ConFont = IntermissionFont = NULL; } +DEFINE_ACTION_FUNCTION(FFont, GetCursor) +{ + PARAM_SELF_STRUCT_PROLOGUE(FFont); + ACTION_RETURN_STRING(FString(self->GetCursor())); +} \ No newline at end of file diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 551d909c5..8774f2a7b 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -6,11 +6,13 @@ #include "zscript/actor.txt" #include "zscript/actor_checks.txt" -#include "zscript/menu/menu.txt" #include "zscript/menu/menuitembase.txt" -#include "zscript/menu/optionmenuitems.txt" +#include "zscript/menu/menu.txt" +#include "zscript/menu/listmenuitems.txt" #include "zscript/menu/optionmenuitems.txt" #include "zscript/menu/joystickmenu.txt" +#include "zscript/menu/playerdisplay.txt" +#include "zscript/menu/playermenu.txt" #include "zscript/inventory/inventory.txt" #include "zscript/inventory/inv_misc.txt" diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 2fe42d31a..1465f5b3a 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -42,6 +42,8 @@ struct TexMan native static TextureID CheckForTexture(String name, int usetype, int flags = TryAny); native static void ReplaceTextures(String from, String to, int flags); + native static int, int GetSize(TextureID tex); + native static Vector2 GetScaledSize(TextureID tex); } enum DrawTextureTags @@ -118,7 +120,7 @@ struct Screen native native static vararg void DrawTexture(TextureID tex, bool animate, double x, double y, ...); native static vararg void DrawChar(Font font, int normalcolor, double x, double y, int character, ...); native static vararg void DrawText(Font font, int normalcolor, double x, double y, String text, ...); - + native static void DrawFrame(int x, int y, int w, int h); } class BrokenLines : Object native @@ -193,6 +195,7 @@ struct Font native native int GetCharWidth(int code); native int StringWidth(String code); native int GetHeight(); + native String GetCursor(); native static int FindFontColor(Name color); native static Font FindFont(Name fontname); @@ -200,6 +203,18 @@ struct Font native native static BrokenLines BreakLines(String text, int maxlen); } +struct Translation +{ + Color colors[256]; + + native bool SetTranslation(int group, int num); + native static bool SetPlayerTranslation(int group, int num, int plrnum, PlayerClass pclass); + static int MakeID(int group, int num) + { + return (group << 16) + num; + } +} + struct Console native { native static void HideConsole(); @@ -429,6 +444,7 @@ struct State native native int DistanceTo(state other); native bool ValidateSpriteFrame(); + native TextureID, bool, Vector2 GetSpriteTexture(int rotation, int skin = 0, Vector2 scale = (0,0)); } struct F3DFloor native diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index f31493077..ef2c4521f 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1,6 +1,7 @@ // for flag changer functions. const FLAG_NO_CHANGE = -1; const MAXPLAYERS = 8; +const MAXPLAYERNAME = 15; enum EStateUseFlags { diff --git a/wadsrc/static/zscript/menu/joystickmenu.txt b/wadsrc/static/zscript/menu/joystickmenu.txt index 3d4085467..57f5226e7 100644 --- a/wadsrc/static/zscript/menu/joystickmenu.txt +++ b/wadsrc/static/zscript/menu/joystickmenu.txt @@ -1,3 +1,37 @@ +/* +** joystickmenu.cpp +** The joystick configuration menus +** +**--------------------------------------------------------------------------- +** Copyright 2010-2017 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + //============================================================================= // // @@ -129,7 +163,7 @@ class OptionMenuItemJoyMap : OptionMenuItemOptionBase } else { - selection = OptionValues.GetValue(mValues, selection); + selection = int(OptionValues.GetValue(mValues, selection)); } Menu.GetCurrentJoystickConfig().SetAxisMap(mAxis, selection); } diff --git a/wadsrc/static/zscript/menu/listmenuitems.txt b/wadsrc/static/zscript/menu/listmenuitems.txt new file mode 100644 index 000000000..ddf7b6f47 --- /dev/null +++ b/wadsrc/static/zscript/menu/listmenuitems.txt @@ -0,0 +1,266 @@ +/* +** listmenu.cpp +** A simple menu consisting of a list of items +** +**--------------------------------------------------------------------------- +** Copyright 2010-2017 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + + +class ListMenuItem : MenuItemBase +{ + void DrawSelector(int xofs, int yofs, TextureID tex) + { + if (tex.isNull()) + { + if ((Menu.MenuTime() % 8) < 6) + { + screen.DrawText(ConFont, OptionMenuSettings.mFontColorSelection, + (mXpos + xofs - 160) * CleanXfac + screen.GetWidth() / 2, + (mYpos + yofs - 100) * CleanYfac + screen.GetHeight() / 2, + "\xd", + DTA_CellX, 8 * CleanXfac, + DTA_CellY, 8 * CleanYfac + ); + } + } + else + { + screen.DrawTexture (tex, mXpos + xofs, mYpos + yofs, DTA_Clean, true); + } + } +} + +//============================================================================= +// +// static patch +// +//============================================================================= + +class ListMenuItemStaticPatch : ListMenuItem +{ + TextureID mTexture; + bool mCentered; + + void Init(int x, int y, TextureID patch, bool centered) + { + Super.Init(x, y); + mTexture = patch; + mCentered = centered; + } + + override void Drawer(bool selected) + { + if (!mTexture.Exists()) + { + return; + } + + int x = mXpos; + Vector2 vec = TexMan.GetScaledSize(mTexture); + if (mYpos >= 0) + { + if (mCentered) x -= int(vec.X) / 2; + screen.DrawTexture (mTexture, true, x, mYpos, DTA_Clean, true); + } + else + { + int x = (mXpos - 160) * CleanXfac + (Screen.GetWidth()>>1); + if (mCentered) x -= (int(vec.X) * CleanXfac)/2; + screen.DrawTexture (mTexture, true, x, -mYpos*CleanYfac, DTA_CleanNoMove, true); + } + } +} + +//============================================================================= +// +// static text +// +//============================================================================= + +class ListMenuItemStaticText : ListMenuItem +{ + String mText; + Font mFont; + int mColor; + bool mCentered; + + void Init(int x, int y, String text, Font font, int color, bool centered) + { + Super.Init(x, y); + mText = text; + mFont = font; + mColor = color; + mCentered = centered; + } + + override void Drawer(bool selected) + { + if (mText.Length() != 0) + { + String text = Stringtable.Localize(mText); + if (mYpos >= 0) + { + int x = mXpos; + if (mCentered) x -= mFont.StringWidth(text)/2; + screen.DrawText(mFont, mColor, x, mYpos, text, DTA_Clean, true); + } + else + { + int x = (mXpos - 160) * CleanXfac + (Screen.GetWidth() >> 1); + if (mCentered) x -= (mFont.StringWidth(text) * CleanXfac)/2; + screen.DrawText (mFont, mColor, x, -mYpos*CleanYfac, text, DTA_CleanNoMove, true); + } + } + } +} + +//============================================================================= +// +// selectable items +// +//============================================================================= + +class ListMenuItemSelectable : ListMenuItem +{ + int mHotkey; + int mHeight; + int mParam; + + void Init(int x, int y, int height, Name childmenu, int param = -1) + { + Super.Init(x, y, childmenu); + mHeight = height; + mParam = param; + mHotkey = 0; + } + + override bool CheckCoordinate(int x, int y) + { + return mEnabled && y >= mYpos && y < mYpos + mHeight; // no x check here + } + + override bool Selectable() + { + return mEnabled; + } + + override bool CheckHotkey(int c) + { + return c == mHotkey; + } + + override bool Activate() + { + Menu.SetMenu(mAction, mParam); + return true; + } + + override bool MouseEvent(int type, int x, int y) + { + if (type == Menu.MOUSE_Release) + { + let m = Menu.GetCurrentMenu(); + if (m != NULL && m.MenuEvent(Menu.MKEY_Enter, true)) + { + return true; + } + } + return false; + } + + override Name, int GetAction() + { + return mAction, mParam; + } +} + +//============================================================================= +// +// text item +// +//============================================================================= + +class ListMenuItemText : ListMenuItemSelectable +{ + String mText; + Font mFont; + int mColor; + int mColorSelected; + + void Init(int x, int y, int height, int hotkey, String text, Font font, int color, int color2, Name child, int param = 0) + { + Super.Init(x, y, height, child, param); + mText = text; + mFont = font; + mColor = color; + mColorSelected = color2; + mHotkey = hotkey; + } + + override void Drawer(bool selected) + { + screen.DrawText(mFont, selected ? mColorSelected : mColor, mXpos, mYpos, mText, DTA_Clean, true); + } + + override int GetWidth() + { + return min(1, mFont.StringWidth(StringTable.Localize(mText))); + } +} + +//============================================================================= +// +// patch item +// +//============================================================================= + +class ListMenuItemPatch : ListMenuItemSelectable +{ + TextureID mTexture; + + void Init(int x, int y, int height, int hotkey, TextureID patch, Name child, int param = 0) + { + Super.Init(x, y, height, child, param); + mHotkey = hotkey; + mTexture = patch; + } + + override void Drawer(bool selected) + { + screen.DrawTexture (mTexture, true, mXpos, mYpos, DTA_Clean, true); + } + + override int GetWidth() + { + return TexMan.GetSize(mTexture); + } + +} + diff --git a/wadsrc/static/zscript/menu/menu.txt b/wadsrc/static/zscript/menu/menu.txt index 85cf747c3..511615fea 100644 --- a/wadsrc/static/zscript/menu/menu.txt +++ b/wadsrc/static/zscript/menu/menu.txt @@ -73,13 +73,16 @@ class Menu : Object native MOUSE_Release }; - //native static int MenuTime(); + native static int MenuTime(); native static void SetVideoMode(); native static Menu GetCurrentMenu(); native static JoystickConfig GetCurrentJoystickConfig(); native static void SetMenu(Name mnu, int param = 0); native static void StartMessage(String msg, int mode = 0, Name command = 'none'); + virtual void SetFocus(MenuItemBase fc) {} + virtual bool CheckFocus(MenuItemBase fc) { return false; } + virtual void ReleaseFocus() {} native virtual bool MenuEvent (int mkey, bool fromcontroller); native virtual bool MouseEvent(int type, int mx, int my); @@ -104,6 +107,40 @@ class MenuDescriptor : Object native native Class mClass; } +class ListMenuDescriptor : MenuDescriptor native +{ + native Array mItems; + native int mSelectedItem; + native int mSelectOfsX; + native int mSelectOfsY; + native TextureID mSelector; + native int mDisplayTop; + native int mXpos, mYpos; + native int mWLeft, mWRight; + native int mLinespacing; // needs to be stored for dynamically created menus + native int mAutoselect; // this can only be set by internal menu creation functions + native Font mFont; + native int mFontColor; + native int mFontColor2; + native bool mCenter; + + void Reset() + { + // Reset the default settings (ignore all other values in the struct) + mSelectOfsX = 0; + mSelectOfsY = 0; + mSelector.SetInvalid(); + mDisplayTop = 0; + mXpos = 0; + mYpos = 0; + mLinespacing = 0; + mNetgameMessage = ""; + mFont = NULL; + mFontColor = Font.CR_UNTRANSLATED; + mFontColor2 = Font.CR_UNTRANSLATED; + } +} + struct FOptionMenuSettings { int mTitleColor; @@ -148,20 +185,17 @@ class OptionMenu : Menu native native OptionMenuItem mFocusControl; native OptionMenuDescriptor mDesc; - - void SetFocus(OptionMenuItem fc) + override void SetFocus(MenuItemBase fc) { - mFocusControl = fc; + mFocusControl = OptionMenuItem(fc); } - - bool CheckFocus(OptionMenuItem fc) + override bool CheckFocus(MenuItemBase fc) { return mFocusControl == fc; } - - void ReleaseFocus() + override void ReleaseFocus() { - mFocusControl = null; + mFocusControl = NULL; } } diff --git a/wadsrc/static/zscript/menu/menuitembase.txt b/wadsrc/static/zscript/menu/menuitembase.txt index 9015aa758..2840b41b9 100644 --- a/wadsrc/static/zscript/menu/menuitembase.txt +++ b/wadsrc/static/zscript/menu/menuitembase.txt @@ -38,29 +38,5 @@ native virtual bool MenuEvent (int mkey, bool fromcontroller);// { return false; virtual int GetY() { return mYpos; } virtual int GetX() { return mXpos; } virtual void SetX(int x) { mXpos = x; } - - /* - virtual void DrawSelector(int xofs, int yofs, TextureID tex) - { - if (tex.isNull()) - { - if ((Menu.MenuTime() % 8) < 6) - { - screen.DrawText(ConFont, OptionSettings.mFontColorSelection, - (mXpos + xofs - 160) * CleanXfac + screen.GetWidth() / 2, - (mYpos + yofs - 100) * CleanYfac + screen.GetHeight() / 2, - "\xd", - DTA_CellX, 8 * CleanXfac, - DTA_CellY, 8 * CleanYfac, - TAG_DONE); - } - } - else - { - screen.DrawTexture (tex, mXpos + xofs, mYpos + yofs, DTA_Clean, true, TAG_DONE); - } - } - */ - } diff --git a/wadsrc/static/zscript/menu/optionmenuitems.txt b/wadsrc/static/zscript/menu/optionmenuitems.txt index 920576878..85687d715 100644 --- a/wadsrc/static/zscript/menu/optionmenuitems.txt +++ b/wadsrc/static/zscript/menu/optionmenuitems.txt @@ -1043,7 +1043,7 @@ class OptionMenuTextField : OptionMenuFieldBase override String Represent() { - if (mEntering) return mEditName .. ((gameinfo.gametype & GAME_DoomStrifeChex) ? "_" : "["); + if (mEntering) return mEditName .. SmallFont.GetCursor(); else return GetCVarString(); } diff --git a/wadsrc/static/zscript/menu/playerdisplay.txt b/wadsrc/static/zscript/menu/playerdisplay.txt new file mode 100644 index 000000000..7665df516 --- /dev/null +++ b/wadsrc/static/zscript/menu/playerdisplay.txt @@ -0,0 +1,286 @@ +/* +** playerdisplay.cpp +** The player display for the player setup and class selection screen +** +**--------------------------------------------------------------------------- +** Copyright 2010-2017 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +//============================================================================= +// +// the player sprite window +// +//============================================================================= + +class ListMenuItemPlayerDisplay : ListMenuItem +{ + ListMenuDescriptor mOwner; + TextureID mBackdrop; + PlayerClass mPlayerClass; + State mPlayerState; + int mPlayerTics; + bool mNoportrait; + int8 mRotation; + int8 mMode; // 0: automatic (used by class selection), 1: manual (used by player setup) + int8 mTranslate; + int mSkin; + int mRandomClass; + int mRandomTimer; + int mClassNum; + + enum EPDFlags + { + PDF_ROTATION = 0x10001, + PDF_SKIN = 0x10002, + PDF_CLASS = 0x10003, + PDF_MODE = 0x10004, + PDF_TRANSLATE = 0x10005, + }; + + //============================================================================= + // + // + // + //============================================================================= + void Init(ListMenuDescriptor menu, int x, int y, Color c1, Color c2, bool np, Name command) + { + Super.Init(x, y, command); + mOwner = menu; + + Translation trans; + for (int i = 0; i < 256; i++) + { + int r = c1.r + c2.r * i / 255; + int g = c1.g + c2.g * i / 255; + int b = c1.b + c2.b * i / 255; + trans.colors[i] = Color(255, r, g, b); + } + trans.SetTranslation(TRANSLATION_Players, MAXPLAYERS + 1); + + mBackdrop = TexMan.CheckForTexture("PlayerBackdrop", TexMan.Type_MiscPatch); + mPlayerClass = NULL; + mPlayerState = NULL; + mNoportrait = np; + mMode = 0; + mRotation = 0; + mTranslate = false; + mSkin = 0; + mRandomClass = 0; + mRandomTimer = 0; + mClassNum = -1; + } + + private void UpdatePlayer(int classnum) + { + mPlayerClass = PlayerClasses[classnum]; + mPlayerState = GetDefaultByType (mPlayerClass.Type).SeeState; + if (mPlayerState == NULL) + { // No see state, so try spawn state. + mPlayerState = GetDefaultByType (mPlayerClass.Type).SpawnState; + } + mPlayerTics = mPlayerState != NULL ? mPlayerState.Tics : -1; + } + + //============================================================================= + // + // + // + //============================================================================= + + private void UpdateRandomClass() + { + if (--mRandomTimer < 0) + { + if (++mRandomClass >= PlayerClasses.Size ()) mRandomClass = 0; + UpdatePlayer(mRandomClass); + mPlayerTics = mPlayerState != NULL ? mPlayerState.Tics : -1; + mRandomTimer = 6; + + // Since the newly displayed class may use a different translation + // range than the old one, we need to update the translation, too. + Translation.SetPlayerTranslation(TRANSLATION_Players, MAXPLAYERS, consoleplayer, mPlayerClass); + } + } + + //============================================================================= + // + // + // + //============================================================================= + + void SetPlayerClass(int classnum, bool force = false) + { + if (classnum < 0 || classnum >= PlayerClasses.Size ()) + { + if (mClassNum != -1) + { + mClassNum = -1; + mRandomTimer = 0; + UpdateRandomClass(); + } + } + else if (mPlayerClass != PlayerClasses[classnum] || force) + { + UpdatePlayer(classnum); + mClassNum = classnum; + } + } + + //============================================================================= + // + // + // + //============================================================================= + + bool UpdatePlayerClass() + { + if (mOwner.mSelectedItem >= 0) + { + int classnum; + Name seltype; + + [seltype, classnum] = mOwner.mItems[mOwner.mSelectedItem].GetAction(); + + if (seltype != 'Episodemenu') return false; + if (PlayerClasses.Size() == 0) return false; + + SetPlayerClass(classnum); + return true; + } + return false; + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool SetValue(int i, int value) + { + switch (i) + { + case PDF_MODE: + mMode = value; + return true; + + case PDF_ROTATION: + mRotation = value; + return true; + + case PDF_TRANSLATE: + mTranslate = value; + + case PDF_CLASS: + SetPlayerClass(value, true); + break; + + case PDF_SKIN: + mSkin = value; + break; + } + return false; + } + + //============================================================================= + // + // + // + //============================================================================= + + override void Ticker() + { + if (mClassNum < 0) UpdateRandomClass(); + + if (mPlayerState != NULL && mPlayerState.Tics != -1 && mPlayerState.NextState != NULL) + { + if (--mPlayerTics <= 0) + { + mPlayerState = mPlayerState.NextState; + mPlayerTics = mPlayerState.Tics; + } + } + } + + //============================================================================= + // + // + // + //============================================================================= + + override void Drawer(bool selected) + { + if (mMode == 0 && !UpdatePlayerClass()) + { + return; + } + let playdef = GetDefaultByType((class)(mPlayerClass.Type)); + + Name portrait = playdef.Portrait; + + if (portrait != 'None' && !mNoportrait) + { + TextureID texid = TexMan.CheckForTexture(portrait, TexMan.Type_MiscPatch); + screen.DrawTexture (texid, true, mXpos, mYpos, DTA_Clean, true); + } + int x = (mXpos - 160) * CleanXfac + (screen.GetWidth() >> 1); + int y = (mYpos - 100) * CleanYfac + (screen.GetHeight() >> 1); + + screen.DrawTexture(mBackdrop, false, x, y - 1, + DTA_DestWidth, 72 * CleanXfac, + DTA_DestHeight, 80 * CleanYfac, + DTA_TranslationIndex, Translation.MakeID(TRANSLATION_Players, MAXPLAYERS + 1), + DTA_Masked, true); + + Screen.DrawFrame (x, y, 72*CleanXfac, 80*CleanYfac-1); + + if (mPlayerState != NULL) + { + Vector2 Scale; + TextureID sprite; + bool flip; + + [sprite, flip, Scale] = mPlayerState.GetSpriteTexture(mRotation, mSkin, playdef.Scale); + + if (sprite.IsValid()) + { + int trans = mTranslate? Translation.MakeID(TRANSLATION_Players, MAXPLAYERS) : 0; + let tscale = TexMan.GetScaledSize(sprite); + Scale.X *= CleanXfac * tscale.X; + Scale.Y *= CleanYfac * tscale.Y; + + screen.DrawTexture (sprite, false, + x + 36*CleanXfac, y + 71*CleanYfac, + DTA_DestWidthF, Scale.X, DTA_DestHeightF, Scale.Y, + DTA_TranslationIndex, trans, + DTA_FlipX, flip); + } + } + } +} \ No newline at end of file diff --git a/wadsrc/static/zscript/menu/playermenu.txt b/wadsrc/static/zscript/menu/playermenu.txt new file mode 100644 index 000000000..338772b6b --- /dev/null +++ b/wadsrc/static/zscript/menu/playermenu.txt @@ -0,0 +1,470 @@ +/* +** playermenu.txt +** The player setup menu +** +**--------------------------------------------------------------------------- +** Copyright 2001-2010 Randy Heit +** Copyright 2010-2017 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +//============================================================================= +// +// items for the player menu +// +//============================================================================= + +class PlayerNameBox : ListMenuItemSelectable +{ + String mText; + Font mFont; + int mFontColor; + int mFrameSize; + String mPlayerName; + String mEditName; + bool mEntering; + + //============================================================================= + // + // Player's name + // + //============================================================================= + + void Init(int x, int y, int height, int frameofs, String text, Font font, int color, Name command) + { + Super.Init(x, y, height, command); + mText = text; + mFont = font; + mFontColor = color; + mFrameSize = frameofs; + mPlayerName = ""; + mEntering = false; + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool SetString(int i, String s) + { + if (i == 0) + { + mPlayerName = s.Mid(0, MAXPLAYERNAME); + return true; + } + return false; + } + + override bool, String GetString(int i) + { + if (i == 0) + { + return true, mPlayerName; + } + return false, ""; + } + + //============================================================================= + // + // [RH] Width of the border is variable + // + //============================================================================= + + protected void DrawBorder (int x, int y, int len) + { + let left = TexMan.CheckForTexture("M_LSLEFT", TexMan.Type_MiscPatch); + let mid = TexMan.CheckForTexture("M_LSCNTR", TexMan.Type_MiscPatch); + let right = TexMan.CheckForTexture("M_LSRGHT", TexMan.Type_MiscPatch); + if (left.IsValid() && right.IsValid() && mid.IsValid()) + { + int i; + + screen.DrawTexture (left, false, x-8, y+7, DTA_Clean, true); + + for (i = 0; i < len; i++) + { + screen.DrawTexture (mid, false, x, y+7, DTA_Clean, true); + x += 8; + } + + screen.DrawTexture (right, false, x, y+7, DTA_Clean, true); + } + else + { + let slot = TexMan.CheckForTexture("M_FSLOT", TexMan.Type_MiscPatch); + if (slot.IsValid()) + { + screen.DrawTexture (slot, false, x, y+1, DTA_Clean, true); + } + else + { + screen.Clear(x, y, x + len, y + SmallFont.GetHeight() * 3/2, 0); + } + } + } + + //============================================================================= + // + // + // + //============================================================================= + + override void Drawer(bool selected) + { + String text = StringTable.Localize(mText); + if (text.Length() > 0) + { + screen.DrawText(mFont, selected? OptionMenuSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true); + } + + // Draw player name box + int x = mXpos + mFont.StringWidth(text) + 16 + mFrameSize; + DrawBorder (x, mYpos - mFrameSize, MAXPLAYERNAME+1); + if (!mEntering) + { + screen.DrawText (SmallFont, Font.CR_UNTRANSLATED, x + mFrameSize, mYpos, mPlayerName, DTA_Clean, true); + } + else + { + let printit = mEditName .. SmallFont.GetCursor(); + screen.DrawText (SmallFont, Font.CR_UNTRANSLATED, x + mFrameSize, mYpos, printit, DTA_Clean, true); + } + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool MenuEvent(int mkey, bool fromcontroller) + { + if (mkey == Menu.MKEY_Enter) + { + Menu.MenuSound ("menu/choose"); + mEditName = mPlayerName; + mEntering = true; + //DMenu *input = new DTextEnterMenu(Menu.CurrentMenu, mEditName, MAXPLAYERNAME, 2, fromcontroller); + //M_ActivateMenu(input); + return true; + } + else if (mkey == Menu.MKEY_Input) + { + mPlayerName = mEditName; + mEntering = false; + return true; + } + else if (mkey == Menu.MKEY_Abort) + { + mEntering = false; + return true; + } + return false; + } + +} + +//============================================================================= +// +// items for the player menu +// +//============================================================================= + +class DValueTextItem : ListMenuItemSelectable +{ + Array mSelections; + String mText; + int mSelection; + Font mFont; + int mFontColor; + int mFontColor2; + + //============================================================================= + // + // items for the player menu + // + //============================================================================= + + void Init(int x, int y, int height, String text, Font font, int color, int valuecolor, Name command, Name values) + { + Super.Init(x, y, height, command); + mText = text; + mFont = font; + mFontColor = color; + mFontColor2 = valuecolor; + mSelection = 0; + let cnt = OptionValues.GetCount(values); + for(int i = 0; i < cnt; i++) + { + SetString(i, OptionValues.GetText(values, i)); + } + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool SetString(int i, String s) + { + // should actually use the index... + if (i==0) mSelections.Clear(); + mSelections.Push(s); + return true; + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool SetValue(int i, int value) + { + if (i == 0) + { + mSelection = value; + return true; + } + return false; + } + + override bool, int GetValue(int i) + { + if (i == 0) + { + return true, mSelection; + } + return false, 0; + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool MenuEvent (int mkey, bool fromcontroller) + { + if (mSelections.Size() > 1) + { + if (mkey == Menu.MKEY_Left) + { + Menu.MenuSound("menu/change"); + if (--mSelection < 0) mSelection = mSelections.Size() - 1; + return true; + } + else if (mkey == Menu.MKEY_Right || mkey == Menu.MKEY_Enter) + { + Menu.MenuSound("menu/change"); + if (++mSelection >= mSelections.Size()) mSelection = 0; + return true; + } + } + return (mkey == Menu.MKEY_Enter); // needs to eat enter keys so that Activate won't get called + } + + //============================================================================= + // + // + // + //============================================================================= + + override void Drawer(bool selected) + { + String text = Stringtable.Localize(mText); + screen.DrawText(mFont, selected? OptionMenuSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true); + + int x = mXpos + mFont.StringWidth(text) + 8; + if (mSelections.Size() > 0) + { + screen.DrawText(mFont, mFontColor2, x, mYpos, mSelections[mSelection], DTA_Clean, true); + } + } + +} + +//============================================================================= +// +// items for the player menu +// +//============================================================================= + +class DSliderItem : ListMenuItemSelectable +{ + String mText; + Font mFont; + int mFontColor; + int mMinrange, mMaxrange; + int mStep; + int mSelection; + + //============================================================================= + // + // items for the player menu + // + //============================================================================= + + void Init(int x, int y, int height, String text, Font font, int color, Name command, int min, int max, int step) + { + Super.Init(x, y, height, command); + mText = text; + mFont = font; + mFontColor = color; + mSelection = 0; + mMinrange = min; + mMaxrange = max; + mStep = step; + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool SetValue(int i, int value) + { + if (i == 0) + { + mSelection = value; + return true; + } + return false; + } + + override bool, int GetValue(int i) + { + if (i == 0) + { + return true, mSelection; + } + return false, 0; + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool MenuEvent (int mkey, bool fromcontroller) + { + if (mkey == Menu.MKEY_Left) + { + Menu.MenuSound("menu/change"); + if ((mSelection -= mStep) < mMinrange) mSelection = mMinrange; + return true; + } + else if (mkey == Menu.MKEY_Right || mkey == Menu.MKEY_Enter) + { + Menu.MenuSound("menu/change"); + if ((mSelection += mStep) > mMaxrange) mSelection = mMaxrange; + return true; + } + return false; + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool MouseEvent(int type, int x, int y) + { + let lm = Menu.GetCurrentMenu(); + if (type != Menu.MOUSE_Click) + { + if (!lm.CheckFocus(self)) return false; + } + if (type == Menu.MOUSE_Release) + { + lm.ReleaseFocus(); + } + + int slide_left = SmallFont.StringWidth ("Green") + 8 + mXpos; + int slide_right = slide_left + 12*8; // 12 char cells with 8 pixels each. + + if (type == Menu.MOUSE_Click) + { + if (x < slide_left || x >= slide_right) return true; + } + + x = clamp(x, slide_left, slide_right); + int v = mMinrange + (x - slide_left) * (mMaxrange - mMinrange) / (slide_right - slide_left); + if (v != mSelection) + { + mSelection = v; + Menu.MenuSound("menu/change"); + } + if (type == Menu.MOUSE_Click) + { + lm.SetFocus(self); + } + return true; + } + + //============================================================================= + // + // + // + //============================================================================= + + protected void DrawSlider (int x, int y) + { + int range = mMaxrange - mMinrange; + int cur = mSelection - mMinrange; + + x = (x - 160) * CleanXfac + screen.GetWidth() / 2; + y = (y - 100) * CleanYfac + screen.GetHeight() / 2; + + screen.DrawText (ConFont, Font.CR_WHITE, x, y, "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12", DTA_CellX, 8 * CleanXfac, DTA_CellY, 8 * CleanYfac); + screen.DrawText (ConFont, Font.CR_ORANGE, x + (5 + (int)((cur * 78) / range)) * CleanXfac, y, "\x13", DTA_CellX, 8 * CleanXfac, DTA_CellY, 8 * CleanYfac); + } + + //============================================================================= + // + // + // + //============================================================================= + + override void Drawer(bool selected) + { + String text = StringTable.Localize(mText); + + screen.DrawText(mFont, selected? OptionMenuSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true); + + int x = SmallFont.StringWidth ("Green") + 8 + mXpos; + int x2 = SmallFont.StringWidth (text) + 8 + mXpos; + DrawSlider (MAX(x2, x), mYpos); + } +} \ No newline at end of file diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index dc1d1ba1d..7b8ba8f30 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -313,3 +313,12 @@ userinfo_t userinfo; native void BringUpWeapon(); } + +struct PlayerClass native +{ + native class Type; + native uint Flags; + native Array Skins; + + native bool CheckSkin(int skin); +} From fc4e1ffcdfed24fb22618fe1ccdb72ff2c5728e8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 11 Feb 2017 17:20:12 +0100 Subject: [PATCH 03/19] - separated the savegame menu code into an internal class managing the savegame data and the actual menu. The manager class cannot be scriptified because it provides the internal implementation which may change at some point in the future. It also encapsulates all access to the file level because if that part is not protected, modders could write malware mods. --- src/g_game.cpp | 2 +- src/menu/loadsavemenu.cpp | 693 +++++++++++++++++++------------------- src/menu/menu.h | 32 +- src/menu/menudef.cpp | 2 +- src/menu/messagebox.cpp | 19 +- 5 files changed, 392 insertions(+), 356 deletions(-) diff --git a/src/g_game.cpp b/src/g_game.cpp index 9417f40b9..44c727b72 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -2307,7 +2307,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio WriteZip(filename, savegame_filenames, savegame_content); - M_NotifyNewSave (filename.GetChars(), description, okForQuicksave); + savegameManager.NotifyNewSave (filename.GetChars(), description, okForQuicksave); // delete the JSON buffers we created just above. Everything else will // either still be needed or taken care of automatically. diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index 8d9dc15e9..74c943480 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -4,7 +4,7 @@ ** **--------------------------------------------------------------------------- ** Copyright 2001-2010 Randy Heit -** Copyright 2010 Christoph Oelckers +** Copyright 2010-2017 Christoph Oelckers ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -50,116 +50,47 @@ #include "resourcefiles/resourcefile.h" - - -class DLoadSaveMenu : public DListMenu -{ - DECLARE_CLASS(DLoadSaveMenu, DListMenu) - friend void ClearSaveGames(); - -protected: - static TArray SaveGames; - static int LastSaved; - static int LastAccessed; - - int Selected; - int TopItem; - - - int savepicLeft; - int savepicTop; - int savepicWidth; - int savepicHeight; - - int rowHeight; - int listboxLeft; - int listboxTop; - int listboxWidth; - - int listboxRows; - int listboxHeight; - int listboxRight; - int listboxBottom; - - int commentLeft; - int commentTop; - int commentWidth; - int commentHeight; - int commentRight; - int commentBottom; - - // this needs to be kept in memory so that the texture can access it when it needs to. - FileReader *currentSavePic; - TArray SavePicData; - - - static int InsertSaveNode (FSaveGameNode *node); - static void ReadSaveStrings (); - - - FTexture *SavePic; - FBrokenLines *SaveComment; - bool mEntering; - char savegamestring[SAVESTRINGSIZE]; - - DLoadSaveMenu(DMenu *parent = NULL, DListMenuDescriptor *desc = NULL); - void OnDestroy() override; - - int RemoveSaveSlot (int index); - void UnloadSaveData (); - void ClearSaveStuff (); - void ExtractSaveData (int index); - void Drawer (); - bool MenuEvent (int mkey, bool fromcontroller); - bool MouseEvent(int type, int x, int y); - bool Responder(event_t *ev); - -public: - static void NotifyNewSave (const char *file, const char *title, bool okForQuicksave); - -}; - -IMPLEMENT_CLASS(DLoadSaveMenu, false, false) - -TArray DLoadSaveMenu::SaveGames; -int DLoadSaveMenu::LastSaved = -1; -int DLoadSaveMenu::LastAccessed = -1; - -FSaveGameNode *quickSaveSlot; - //============================================================================= // -// Save data maintenance (stored statically) +// This should remain native because exposing 'remove' would allow +// the creation of actual malware mods! // //============================================================================= -void ClearSaveGames() +void SavegameManager::DeleteEntry(int Selected) { - for(unsigned i=0;ibNoDelete) - delete DLoadSaveMenu::SaveGames[i]; - } - DLoadSaveMenu::SaveGames.Clear(); + remove(SaveGames[Selected]->Filename.GetChars()); } //============================================================================= // -// Save data maintenance (stored statically) +// Save data maintenance // //============================================================================= -int DLoadSaveMenu::RemoveSaveSlot (int index) +void SavegameManager::ClearSaveGames() +{ + for (unsigned i = 0; ibNoDelete) + delete SaveGames[i]; + } + SaveGames.Clear(); +} + +//============================================================================= +// +// Save data maintenance +// +//============================================================================= + +int SavegameManager::RemoveSaveSlot(int index) { FSaveGameNode *file = SaveGames[index]; if (quickSaveSlot == SaveGames[index]) { - quickSaveSlot = NULL; - } - if (Selected == index) - { - Selected = -1; + quickSaveSlot = nullptr; } if (!file->bNoDelete) delete file; SaveGames.Delete(index); @@ -173,7 +104,7 @@ int DLoadSaveMenu::RemoveSaveSlot (int index) // //============================================================================= -int DLoadSaveMenu::InsertSaveNode (FSaveGameNode *node) +int SavegameManager::InsertSaveNode(FSaveGameNode *node) { if (SaveGames.Size() == 0) { @@ -187,10 +118,10 @@ int DLoadSaveMenu::InsertSaveNode (FSaveGameNode *node) else { // Add node at top of list unsigned int i; - for(i = 0; i < SaveGames.Size(); i++) + for (i = 0; i < SaveGames.Size(); i++) { if (SaveGames[i]->bOldVersion || - stricmp (node->Title, SaveGames[i]->Title) <= 0) + stricmp(node->Title, SaveGames[i]->Title) <= 0) { break; } @@ -200,7 +131,6 @@ int DLoadSaveMenu::InsertSaveNode (FSaveGameNode *node) } } - //============================================================================= // // M_ReadSaveStrings @@ -209,7 +139,7 @@ int DLoadSaveMenu::InsertSaveNode (FSaveGameNode *node) // //============================================================================= -void DLoadSaveMenu::ReadSaveStrings () +void SavegameManager::ReadSaveStrings() { if (SaveGames.Size() == 0) { @@ -218,15 +148,15 @@ void DLoadSaveMenu::ReadSaveStrings () FString filter; LastSaved = LastAccessed = -1; - quickSaveSlot = NULL; - filter = G_BuildSaveName ("*." SAVEGAME_EXT, -1); - filefirst = I_FindFirst (filter.GetChars(), &c_file); + quickSaveSlot = nullptr; + filter = G_BuildSaveName("*." SAVEGAME_EXT, -1); + filefirst = I_FindFirst(filter.GetChars(), &c_file); if (filefirst != ((void *)(-1))) { do { // I_FindName only returns the file's name and not its full path - FString filepath = G_BuildSaveName (I_FindName(&c_file), -1); + FString filepath = G_BuildSaveName(I_FindName(&c_file), -1); FResourceFile *savegame = FResourceFile::OpenResourceFile(filepath, nullptr, true, true); if (savegame != nullptr) @@ -290,12 +220,12 @@ void DLoadSaveMenu::ReadSaveStrings () } else // check for old formats. { - FILE *file = fopen (filepath, "rb"); - if (file != NULL) + FILE *file = fopen(filepath, "rb"); + if (file != nullptr) { PNGHandle *png; char sig[16]; - char title[SAVESTRINGSIZE+1]; + char title[SAVESTRINGSIZE + 1]; bool oldVer = true; bool addIt = false; bool missing = false; @@ -310,10 +240,10 @@ void DLoadSaveMenu::ReadSaveStrings () title[SAVESTRINGSIZE] = 0; - if (NULL != (png = M_VerifyPNG (file))) + if (nullptr != (png = M_VerifyPNG(file))) { - char *ver = M_GetPNGText (png, "ZDoom Save Version"); - if (ver != NULL) + char *ver = M_GetPNGText(png, "ZDoom Save Version"); + if (ver != nullptr) { // An old version if (!M_GetPNGText(png, "Title", title, SAVESTRINGSIZE)) @@ -327,23 +257,23 @@ void DLoadSaveMenu::ReadSaveStrings () } else { - fseek (file, 0, SEEK_SET); - if (fread (sig, 1, 16, file) == 16) + fseek(file, 0, SEEK_SET); + if (fread(sig, 1, 16, file) == 16) { - if (strncmp (sig, "ZDOOMSAVE", 9) == 0) + if (strncmp(sig, "ZDOOMSAVE", 9) == 0) { - if (fread (title, 1, SAVESTRINGSIZE, file) == SAVESTRINGSIZE) + if (fread(title, 1, SAVESTRINGSIZE, file) == SAVESTRINGSIZE) { addIt = true; } } else { - memcpy (title, sig, 16); - if (fread (title + 16, 1, SAVESTRINGSIZE-16, file) == SAVESTRINGSIZE-16 && - fread (sig, 1, 16, file) == 16 && - strncmp (sig, "ZDOOMSAVE", 9) == 0) + memcpy(title, sig, 16); + if (fread(title + 16, 1, SAVESTRINGSIZE - 16, file) == SAVESTRINGSIZE - 16 && + fread(sig, 1, 16, file) == 16 && + strncmp(sig, "ZDOOMSAVE", 9) == 0) { addIt = true; } @@ -357,50 +287,49 @@ void DLoadSaveMenu::ReadSaveStrings () node->Filename = filepath; node->bOldVersion = true; node->bMissingWads = false; - memcpy (node->Title, title, SAVESTRINGSIZE); - InsertSaveNode (node); + memcpy(node->Title, title, SAVESTRINGSIZE); + InsertSaveNode(node); } - fclose (file); + fclose(file); } } - } while (I_FindNext (filefirst, &c_file) == 0); - I_FindClose (filefirst); + } while (I_FindNext(filefirst, &c_file) == 0); + I_FindClose(filefirst); } } } - //============================================================================= // // // //============================================================================= -void DLoadSaveMenu::NotifyNewSave (const char *file, const char *title, bool okForQuicksave) +void SavegameManager::NotifyNewSave(const char *file, const char *title, bool okForQuicksave) { FSaveGameNode *node; - if (file == NULL) + if (file == nullptr) return; - ReadSaveStrings (); + ReadSaveStrings(); // See if the file is already in our list - for (unsigned i=0; iFilename.Compare (file) == 0) + if (node->Filename.Compare(file) == 0) #else - if (node->Filename.CompareNoCase (file) == 0) + if (node->Filename.CompareNoCase(file) == 0) #endif { - strcpy (node->Title, title); + strcpy(node->Title, title); node->bOldVersion = false; node->bMissingWads = false; if (okForQuicksave) { - if (quickSaveSlot == NULL) quickSaveSlot = node; + if (quickSaveSlot == nullptr) quickSaveSlot = node; LastAccessed = LastSaved = i; } return; @@ -408,107 +337,71 @@ void DLoadSaveMenu::NotifyNewSave (const char *file, const char *title, bool okF } node = new FSaveGameNode; - strcpy (node->Title, title); + strcpy(node->Title, title); node->Filename = file; node->bOldVersion = false; node->bMissingWads = false; - int index = InsertSaveNode (node); + int index = InsertSaveNode(node); if (okForQuicksave) { - if (quickSaveSlot == NULL) quickSaveSlot = node; + if (quickSaveSlot == nullptr) quickSaveSlot = node; LastAccessed = LastSaved = index; } } -void M_NotifyNewSave (const char *file, const char *title, bool okForQuicksave) +//============================================================================= +// +// Loads the savegame +// +//============================================================================= + +void SavegameManager::LoadSavegame(int Selected) { - DLoadSaveMenu::NotifyNewSave(file, title, okForQuicksave); -} - -//============================================================================= -// -// End of static savegame maintenance code -// -//============================================================================= - -DLoadSaveMenu::DLoadSaveMenu(DMenu *parent, DListMenuDescriptor *desc) -: DListMenu(parent, desc) -{ - ReadSaveStrings(); - - savepicLeft = 10; - savepicTop = 54*CleanYfac; - savepicWidth = 216*screen->GetWidth()/640; - savepicHeight = 135*screen->GetHeight()/400; - - rowHeight = (SmallFont->GetHeight() + 1) * CleanYfac; - listboxLeft = savepicLeft + savepicWidth + 14; - listboxTop = savepicTop; - listboxWidth = screen->GetWidth() - listboxLeft - 10; - int listboxHeight1 = screen->GetHeight() - listboxTop - 10; - listboxRows = (listboxHeight1 - 1) / rowHeight; - listboxHeight = listboxRows * rowHeight + 1; - listboxRight = listboxLeft + listboxWidth; - listboxBottom = listboxTop + listboxHeight; - currentSavePic = nullptr; - - commentLeft = savepicLeft; - commentTop = savepicTop + savepicHeight + 16; - commentWidth = savepicWidth; - commentHeight = (51+(screen->GetHeight()>200?10:0))*CleanYfac; - commentRight = commentLeft + commentWidth; - commentBottom = commentTop + commentHeight; -} - -void DLoadSaveMenu::OnDestroy() -{ - if (currentSavePic != nullptr) delete currentSavePic; - currentSavePic = nullptr; - ClearSaveStuff (); - Super::OnDestroy(); -} - -//============================================================================= -// -// -// -//============================================================================= - -void DLoadSaveMenu::UnloadSaveData () -{ - if (SavePic != nullptr) - { - delete SavePic; - } - if (SaveComment != nullptr) - { - V_FreeBrokenLines (SaveComment); - } - if (currentSavePic != nullptr) - { - delete currentSavePic; - } - - SavePic = nullptr; - SaveComment = nullptr; - currentSavePic = nullptr; - SavePicData.Clear(); -} - -//============================================================================= -// -// -// -//============================================================================= - -void DLoadSaveMenu::ClearSaveStuff () -{ - UnloadSaveData(); + G_LoadGame(SaveGames[Selected]->Filename.GetChars(), true); if (quickSaveSlot == (FSaveGameNode*)1) { - quickSaveSlot = NULL; + quickSaveSlot = SaveGames[Selected]; } + M_ClearMenus(); + V_SetBorderNeedRefresh(); + LastAccessed = Selected; +} + +//============================================================================= +// +// +// +//============================================================================= + +void SavegameManager::DoSave(int Selected, const char *savegamestring) +{ + if (Selected != 0) + { + auto node = SaveGames[Selected]; + G_SaveGame(node->Filename.GetChars(), savegamestring); + } + else + { + // Find an unused filename and save as that + FString filename; + int i; + FILE *test; + + for (i = 0;; ++i) + { + filename = G_BuildSaveName("save", i); + test = fopen(filename, "rb"); + if (test == nullptr) + { + break; + } + fclose(test); + } + G_SaveGame(filename, savegamestring); + } + M_ClearMenus(); + V_SetBorderNeedRefresh(); } //============================================================================= @@ -517,12 +410,12 @@ void DLoadSaveMenu::ClearSaveStuff () // //============================================================================= -void DLoadSaveMenu::ExtractSaveData (int index) +void SavegameManager::ExtractSaveData(int index) { FResourceFile *resf; FSaveGameNode *node; - UnloadSaveData (); + UnloadSaveData(); if ((unsigned)index < SaveGames.Size() && (node = SaveGames[index]) && @@ -548,8 +441,8 @@ void DLoadSaveMenu::ExtractSaveData (int index) comment = time; if (time.Len() > 0) comment += "\n\n"; comment += pcomment; - - SaveComment = V_BreakLines (SmallFont, 216*screen->GetWidth()/640/CleanXfac, comment.GetChars()); + + SaveComment = V_BreakLines(SmallFont, WindowSize, comment.GetChars()); // Extract pic FResourceLump *pic = resf->FindLump("savepic.png"); @@ -592,6 +485,181 @@ void DLoadSaveMenu::ExtractSaveData (int index) // //============================================================================= +void SavegameManager::UnloadSaveData() +{ + if (SavePic != nullptr) + { + delete SavePic; + } + if (SaveComment != nullptr) + { + V_FreeBrokenLines(SaveComment); + } + if (currentSavePic != nullptr) + { + delete currentSavePic; + } + + SavePic = nullptr; + SaveComment = nullptr; + currentSavePic = nullptr; + SavePicData.Clear(); +} + +//============================================================================= +// +// +// +//============================================================================= + +void SavegameManager::ClearSaveStuff() +{ + UnloadSaveData(); + if (quickSaveSlot == (FSaveGameNode*)1) + { + quickSaveSlot = nullptr; + } +} + + +//============================================================================= +// +// +// +//============================================================================= + +bool SavegameManager::DrawSavePic(int x, int y, int w, int h) +{ + if (SavePic == nullptr) return false; + screen->DrawTexture(SavePic, x, y, DTA_DestWidth, w, DTA_DestHeight, h, DTA_Masked, false, TAG_DONE); + return true; +} + +//============================================================================= +// +// +// +//============================================================================= + +void SavegameManager::SetFileInfo(int Selected) +{ + if (!SaveGames[Selected]->Filename.IsEmpty()) + { + char workbuf[512]; + + mysnprintf(workbuf, countof(workbuf), "File on disk:\n%s", SaveGames[Selected]->Filename.GetChars()); + if (SaveComment != nullptr) + { + V_FreeBrokenLines(SaveComment); + } + SaveComment = V_BreakLines(SmallFont, WindowSize, workbuf); + } +} + +SavegameManager savegameManager; + + + + +class DLoadSaveMenu : public DListMenu +{ + DECLARE_CLASS(DLoadSaveMenu, DListMenu) + +protected: + + SavegameManager *manager; + + int Selected; + int TopItem; + + + int savepicLeft; + int savepicTop; + int savepicWidth; + int savepicHeight; + + int rowHeight; + int listboxLeft; + int listboxTop; + int listboxWidth; + + int listboxRows; + int listboxHeight; + int listboxRight; + int listboxBottom; + + int commentLeft; + int commentTop; + int commentWidth; + int commentHeight; + int commentRight; + int commentBottom; + + // this needs to be kept in memory so that the texture can access it when it needs to. + bool mEntering; + char savegamestring[SAVESTRINGSIZE]; + + DLoadSaveMenu(DMenu *parent = nullptr, DListMenuDescriptor *desc = nullptr); + void OnDestroy() override; + + void Drawer (); + bool MenuEvent (int mkey, bool fromcontroller); + bool MouseEvent(int type, int x, int y); + bool Responder(event_t *ev); +}; + +IMPLEMENT_CLASS(DLoadSaveMenu, false, false) + + + +//============================================================================= +// +// End of static savegame maintenance code +// +//============================================================================= + +DLoadSaveMenu::DLoadSaveMenu(DMenu *parent, DListMenuDescriptor *desc) +: DListMenu(parent, desc) +{ + manager = &savegameManager; + manager->ReadSaveStrings(); + + savepicLeft = 10; + savepicTop = 54*CleanYfac; + savepicWidth = 216*screen->GetWidth()/640; + savepicHeight = 135*screen->GetHeight()/400; + manager->WindowSize = savepicWidth; + + rowHeight = (SmallFont->GetHeight() + 1) * CleanYfac; + listboxLeft = savepicLeft + savepicWidth + 14; + listboxTop = savepicTop; + listboxWidth = screen->GetWidth() - listboxLeft - 10; + int listboxHeight1 = screen->GetHeight() - listboxTop - 10; + listboxRows = (listboxHeight1 - 1) / rowHeight; + listboxHeight = listboxRows * rowHeight + 1; + listboxRight = listboxLeft + listboxWidth; + listboxBottom = listboxTop + listboxHeight; + + commentLeft = savepicLeft; + commentTop = savepicTop + savepicHeight + 16; + commentWidth = savepicWidth; + commentHeight = (51+(screen->GetHeight()>200?10:0))*CleanYfac; + commentRight = commentLeft + commentWidth; + commentBottom = commentTop + commentHeight; +} + +void DLoadSaveMenu::OnDestroy() +{ + manager->ClearSaveStuff (); + Super::OnDestroy(); +} + +//============================================================================= +// +// +// +//============================================================================= + void DLoadSaveMenu::Drawer () { Super::Drawer(); @@ -608,23 +676,15 @@ void DLoadSaveMenu::Drawer () } V_DrawFrame (savepicLeft, savepicTop, savepicWidth, savepicHeight); - if (SavePic != NULL) - { - screen->DrawTexture(SavePic, savepicLeft, savepicTop, - DTA_DestWidth, savepicWidth, - DTA_DestHeight, savepicHeight, - DTA_Masked, false, - TAG_DONE); - } - else + if (!manager->DrawSavePic(savepicLeft, savepicTop, savepicWidth, savepicHeight)) { screen->Clear (savepicLeft, savepicTop, savepicLeft+savepicWidth, savepicTop+savepicHeight, 0, 0); - if (SaveGames.Size() > 0) + if (manager->SaveGames.Size() > 0) { const char *text = - (Selected == -1 || !SaveGames[Selected]->bOldVersion) + (Selected == -1 || !manager->SaveGames[Selected]->bOldVersion) ? GStrings("MNU_NOPICTURE") : GStrings("MNU_DIFFVERSION"); const int textlen = SmallFont->StringWidth (text)*CleanXfac; @@ -637,15 +697,15 @@ void DLoadSaveMenu::Drawer () // Draw comment area V_DrawFrame (commentLeft, commentTop, commentWidth, commentHeight); screen->Clear (commentLeft, commentTop, commentRight, commentBottom, 0, 0); - if (SaveComment != NULL) + if (manager->SaveComment != nullptr) { - // I'm not sure why SaveComment would go NULL in this loop, but I got - // a crash report where it was NULL when i reached 1, so now I check + // I'm not sure why SaveComment would go nullptr in this loop, but I got + // a crash report where it was nullptr when i reached 1, so now I check // for that. - for (i = 0; SaveComment != NULL && SaveComment[i].Width >= 0 && i < 6; ++i) + for (i = 0; manager->SaveComment != nullptr && manager->SaveComment[i].Width >= 0 && i < 6; ++i) { screen->DrawText (SmallFont, CR_GOLD, commentLeft, commentTop - + SmallFont->GetHeight()*i*CleanYfac, SaveComment[i].Text, + + SmallFont->GetHeight()*i*CleanYfac, manager->SaveComment[i].Text, DTA_CleanNoMove, true, TAG_DONE); } } @@ -654,7 +714,7 @@ void DLoadSaveMenu::Drawer () V_DrawFrame (listboxLeft, listboxTop, listboxWidth, listboxHeight); screen->Clear (listboxLeft, listboxTop, listboxRight, listboxBottom, 0, 0); - if (SaveGames.Size() == 0) + if (manager->SaveGames.Size() == 0) { const char * text = GStrings("MNU_NOFILES"); const int textlen = SmallFont->StringWidth (text)*CleanXfac; @@ -665,10 +725,10 @@ void DLoadSaveMenu::Drawer () return; } - for (i = 0, j = TopItem; i < listboxRows && j < SaveGames.Size(); i++,j++) + for (i = 0, j = TopItem; i < listboxRows && j < manager->SaveGames.Size(); i++,j++) { int color; - node = SaveGames[j]; + node = manager->SaveGames[j]; if (node->bOldVersion) { color = CR_BLUE; @@ -732,59 +792,59 @@ bool DLoadSaveMenu::MenuEvent (int mkey, bool fromcontroller) switch (mkey) { case MKEY_Up: - if (SaveGames.Size() > 1) + if (manager->SaveGames.Size() > 1) { if (Selected == -1) Selected = TopItem; else { - if (--Selected < 0) Selected = SaveGames.Size()-1; + if (--Selected < 0) Selected = manager->SaveGames.Size()-1; if (Selected < TopItem) TopItem = Selected; else if (Selected >= TopItem + listboxRows) TopItem = MAX(0, Selected - listboxRows + 1); } - UnloadSaveData (); - ExtractSaveData (Selected); + manager->UnloadSaveData (); + manager->ExtractSaveData (Selected); } return true; case MKEY_Down: - if (SaveGames.Size() > 1) + if (manager->SaveGames.Size() > 1) { if (Selected == -1) Selected = TopItem; else { - if (unsigned(++Selected) >= SaveGames.Size()) Selected = 0; + if (unsigned(++Selected) >= manager->SaveGames.Size()) Selected = 0; if (Selected < TopItem) TopItem = Selected; else if (Selected >= TopItem + listboxRows) TopItem = MAX(0, Selected - listboxRows + 1); } - UnloadSaveData (); - ExtractSaveData (Selected); + manager->UnloadSaveData (); + manager->ExtractSaveData (Selected); } return true; case MKEY_PageDown: - if (SaveGames.Size() > 1) + if (manager->SaveGames.Size() > 1) { - if (TopItem >= (int)SaveGames.Size() - listboxRows) + if (TopItem >= (int)manager->SaveGames.Size() - listboxRows) { TopItem = 0; if (Selected != -1) Selected = 0; } else { - TopItem = MIN(TopItem + listboxRows, SaveGames.Size() - listboxRows); + TopItem = MIN(TopItem + listboxRows, manager->SaveGames.Size() - listboxRows); if (TopItem > Selected && Selected != -1) Selected = TopItem; } - UnloadSaveData (); - ExtractSaveData (Selected); + manager->UnloadSaveData (); + manager->ExtractSaveData (Selected); } return true; case MKEY_PageUp: - if (SaveGames.Size() > 1) + if (manager->SaveGames.Size() > 1) { if (TopItem == 0) { - TopItem = SaveGames.Size() - listboxRows; + TopItem = manager->SaveGames.Size() - listboxRows; if (Selected != -1) Selected = TopItem; } else @@ -792,8 +852,8 @@ bool DLoadSaveMenu::MenuEvent (int mkey, bool fromcontroller) TopItem = MAX(TopItem - listboxRows, 0); if (Selected >= TopItem + listboxRows) Selected = TopItem; } - UnloadSaveData (); - ExtractSaveData (Selected); + manager->UnloadSaveData (); + manager->ExtractSaveData (Selected); } return true; @@ -802,18 +862,18 @@ bool DLoadSaveMenu::MenuEvent (int mkey, bool fromcontroller) case MKEY_MBYes: { - if ((unsigned)Selected < SaveGames.Size()) + if ((unsigned)Selected < manager->SaveGames.Size()) { - int listindex = SaveGames[0]->bNoDelete? Selected-1 : Selected; - remove (SaveGames[Selected]->Filename.GetChars()); - UnloadSaveData (); - Selected = RemoveSaveSlot (Selected); - ExtractSaveData (Selected); + int listindex = manager->SaveGames[0]->bNoDelete? Selected-1 : Selected; + manager->DeleteEntry(Selected); + manager->UnloadSaveData (); + Selected = manager->RemoveSaveSlot (Selected); + manager->ExtractSaveData (Selected); - if (LastSaved == listindex) LastSaved = -1; - else if (LastSaved > listindex) LastSaved--; - if (LastAccessed == listindex) LastAccessed = -1; - else if (LastAccessed > listindex) LastAccessed--; + if (manager->LastSaved == listindex) manager->LastSaved = -1; + else if (manager->LastSaved > listindex) manager->LastSaved--; + if (manager->LastAccessed == listindex) manager->LastAccessed = -1; + else if (manager->LastAccessed > listindex) manager->LastAccessed--; } return true; } @@ -836,11 +896,11 @@ bool DLoadSaveMenu::MouseEvent(int type, int x, int y) { int lineno = (y - listboxTop) / rowHeight; - if (TopItem + lineno < (int)SaveGames.Size()) + if (TopItem + lineno < (int)manager->SaveGames.Size()) { Selected = TopItem + lineno; - UnloadSaveData (); - ExtractSaveData (Selected); + manager->UnloadSaveData (); + manager->ExtractSaveData (Selected); if (type == MOUSE_Release) { if (MenuEvent(MKEY_Enter, true)) @@ -868,22 +928,12 @@ bool DLoadSaveMenu::Responder (event_t *ev) { if (ev->subtype == EV_GUI_KeyDown) { - if ((unsigned)Selected < SaveGames.Size()) + if ((unsigned)Selected < manager->SaveGames.Size()) { switch (ev->data1) { case GK_F1: - if (!SaveGames[Selected]->Filename.IsEmpty()) - { - char workbuf[512]; - - mysnprintf (workbuf, countof(workbuf), "File on disk:\n%s", SaveGames[Selected]->Filename.GetChars()); - if (SaveComment != NULL) - { - V_FreeBrokenLines (SaveComment); - } - SaveComment = V_BreakLines (SmallFont, 216*screen->GetWidth()/640/CleanXfac, workbuf); - } + manager->SetFileInfo(Selected); return true; case GK_DEL: @@ -891,7 +941,7 @@ bool DLoadSaveMenu::Responder (event_t *ev) { FString EndString; EndString.Format("%s" TEXTCOLOR_WHITE "%s" TEXTCOLOR_NORMAL "?\n\n%s", - GStrings("MNU_DELETESG"), SaveGames[Selected]->Title, GStrings("PRESSYN")); + GStrings("MNU_DELETESG"), manager->SaveGames[Selected]->Title, GStrings("PRESSYN")); M_StartMessage (EndString, 0); } return true; @@ -905,7 +955,7 @@ bool DLoadSaveMenu::Responder (event_t *ev) } else if (ev->subtype == EV_GUI_WheelDown) { - if (TopItem < (int)SaveGames.Size() - listboxRows) TopItem++; + if (TopItem < (int)manager->SaveGames.Size() - listboxRows) TopItem++; return true; } } @@ -927,9 +977,8 @@ class DSaveMenu : public DLoadSaveMenu public: - DSaveMenu(DMenu *parent = NULL, DListMenuDescriptor *desc = NULL); + DSaveMenu(DMenu *parent = nullptr, DListMenuDescriptor *desc = nullptr); void OnDestroy() override; - void DoSave (FSaveGameNode *node); bool Responder (event_t *ev); bool MenuEvent (int mkey, bool fromcontroller); @@ -949,17 +998,17 @@ DSaveMenu::DSaveMenu(DMenu *parent, DListMenuDescriptor *desc) { strcpy (NewSaveNode.Title, GStrings["NEWSAVE"]); NewSaveNode.bNoDelete = true; - SaveGames.Insert(0, &NewSaveNode); + manager->SaveGames.Insert(0, &NewSaveNode); TopItem = 0; - if (LastSaved == -1) + if (manager->LastSaved == -1) { Selected = 0; } else { - Selected = LastSaved + 1; + Selected = manager->LastSaved + 1; } - ExtractSaveData (Selected); + manager->ExtractSaveData (Selected); } //============================================================================= @@ -970,50 +1019,15 @@ DSaveMenu::DSaveMenu(DMenu *parent, DListMenuDescriptor *desc) void DSaveMenu::OnDestroy() { - if (SaveGames[0] == &NewSaveNode) + if (manager->SaveGames[0] == &NewSaveNode) { - SaveGames.Delete(0); + manager->SaveGames.Delete(0); if (Selected == 0) Selected = -1; else Selected--; } Super::OnDestroy(); } -//============================================================================= -// -// -// -//============================================================================= - -void DSaveMenu::DoSave (FSaveGameNode *node) -{ - if (node != &NewSaveNode) - { - G_SaveGame (node->Filename.GetChars(), savegamestring); - } - else - { - // Find an unused filename and save as that - FString filename; - int i; - FILE *test; - - for (i = 0;; ++i) - { - filename = G_BuildSaveName ("save", i); - test = fopen (filename, "rb"); - if (test == NULL) - { - break; - } - fclose (test); - } - G_SaveGame (filename, savegamestring); - } - M_ClearMenus(); - V_SetBorderNeedRefresh(); -} - //============================================================================= // // @@ -1035,7 +1049,7 @@ bool DSaveMenu::MenuEvent (int mkey, bool fromcontroller) { if (Selected != 0) { - strcpy (savegamestring, SaveGames[Selected]->Title); + strcpy (savegamestring, manager->SaveGames[Selected]->Title); } else { @@ -1048,7 +1062,7 @@ bool DSaveMenu::MenuEvent (int mkey, bool fromcontroller) else if (mkey == MKEY_Input) { mEntering = false; - DoSave(SaveGames[Selected]); + manager->DoSave(Selected, savegamestring); } else if (mkey == MKEY_Abort) { @@ -1079,7 +1093,7 @@ bool DSaveMenu::Responder (event_t *ev) case 'N': Selected = TopItem = 0; - UnloadSaveData (); + manager->UnloadSaveData (); return true; } } @@ -1099,7 +1113,7 @@ class DLoadMenu : public DLoadSaveMenu public: - DLoadMenu(DMenu *parent = NULL, DListMenuDescriptor *desc = NULL); + DLoadMenu(DMenu *parent = nullptr, DListMenuDescriptor *desc = nullptr); bool MenuEvent (int mkey, bool fromcontroller); }; @@ -1117,11 +1131,11 @@ DLoadMenu::DLoadMenu(DMenu *parent, DListMenuDescriptor *desc) : DLoadSaveMenu(parent, desc) { TopItem = 0; - if (LastAccessed != -1) + if (manager->LastAccessed != -1) { - Selected = LastAccessed; + Selected = manager->LastAccessed; } - ExtractSaveData (Selected); + manager->ExtractSaveData (Selected); } @@ -1137,21 +1151,14 @@ bool DLoadMenu::MenuEvent (int mkey, bool fromcontroller) { return true; } - if (Selected == -1 || SaveGames.Size() == 0) + if (Selected == -1 || manager->SaveGames.Size() == 0) { return false; } if (mkey == MKEY_Enter) { - G_LoadGame (SaveGames[Selected]->Filename.GetChars(), true); - if (quickSaveSlot == (FSaveGameNode*)1) - { - quickSaveSlot = SaveGames[Selected]; - } - M_ClearMenus(); - V_SetBorderNeedRefresh(); - LastAccessed = Selected; + manager->LoadSavegame(Selected); return true; } return false; diff --git a/src/menu/menu.h b/src/menu/menu.h index 3af5e0efb..7ffb1aab8 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -22,6 +22,7 @@ class FFont; enum EColorRange : int; class FPlayerClass; class FKeyBindings; +struct FBrokenLines; enum EMenuKey { @@ -66,7 +67,37 @@ struct FSaveGameNode FSaveGameNode() { bNoDelete = false; } }; +struct SavegameManager +{ + TArray SaveGames; + int LastSaved = -1; + int LastAccessed = -1; + int WindowSize = 0; + FSaveGameNode *quickSaveSlot = nullptr; + FileReader *currentSavePic = nullptr; + TArray SavePicData; + + FTexture *SavePic = nullptr; + FBrokenLines *SaveComment = nullptr; + + void ClearSaveGames(); + int InsertSaveNode(FSaveGameNode *node); + int RemoveSaveSlot(int index); + void ReadSaveStrings(); + void NotifyNewSave(const char *file, const char *title, bool okForQuicksave); + void LoadSavegame(int Selected); + void DoSave(int Selected, const char *savegamestring); + void DeleteEntry(int Selected); + void ExtractSaveData(int index); + void UnloadSaveData(); + void ClearSaveStuff(); + bool DrawSavePic(int x, int y, int w, int h); + void SetFileInfo(int Selected); + +}; + +extern SavegameManager savegameManager; //============================================================================= // @@ -707,7 +738,6 @@ void M_StartupSkillMenu(FGameStartup *gs); int M_GetDefaultSkill(); void M_StartControlPanel (bool makeSound); void M_SetMenu(FName menu, int param = -1); -void M_NotifyNewSave (const char *file, const char *title, bool okForQuicksave); void M_StartMessage(const char *message, int messagemode, FName action = NAME_None); DMenu *StartPickerMenu(DMenu *parent, const char *name, FColorCVar *cvar); void M_RefreshModesList (); diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 05bb16007..86f168747 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -148,7 +148,7 @@ static void DeinitMenus() MenuDescriptors.Clear(); OptionValues.Clear(); DMenu::CurrentMenu = nullptr; - ClearSaveGames(); + savegameManager.ClearSaveGames(); } static FTextureID GetMenuTexture(const char* const name) diff --git a/src/menu/messagebox.cpp b/src/menu/messagebox.cpp index a910ad3ad..e15940acb 100644 --- a/src/menu/messagebox.cpp +++ b/src/menu/messagebox.cpp @@ -47,7 +47,6 @@ #include "g_game.h" -extern FSaveGameNode *quickSaveSlot; EXTERN_CVAR (Bool, saveloadconfirmation) // [mxd] class DMessageBoxMenu : public DMenu @@ -549,7 +548,7 @@ DQuickSaveMenu::DQuickSaveMenu(bool playsound) { FString tempstring; - tempstring.Format(GStrings("QSPROMPT"), quickSaveSlot->Title); + tempstring.Format(GStrings("QSPROMPT"), savegameManager.quickSaveSlot->Title); Init(NULL, tempstring, 0, playsound); } @@ -563,7 +562,7 @@ void DQuickSaveMenu::HandleResult(bool res) { if (res) { - G_SaveGame (quickSaveSlot->Filename.GetChars(), quickSaveSlot->Title); + G_SaveGame (savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->Title); S_Sound (CHAN_VOICE | CHAN_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE); M_ClearMenus(); } @@ -591,7 +590,7 @@ CCMD (quicksave) if (gamestate != GS_LEVEL) return; - if (quickSaveSlot == NULL) + if (savegameManager.quickSaveSlot == NULL) { S_Sound(CHAN_VOICE | CHAN_UI, "menu/activate", snd_menuvolume, ATTN_NONE); M_StartControlPanel(false); @@ -602,7 +601,7 @@ CCMD (quicksave) // [mxd]. Just save the game, no questions asked. if (!saveloadconfirmation) { - G_SaveGame(quickSaveSlot->Filename.GetChars(), quickSaveSlot->Title); + G_SaveGame(savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->Title); return; } @@ -645,7 +644,7 @@ DQuickLoadMenu::DQuickLoadMenu(bool playsound) { FString tempstring; - tempstring.Format(GStrings("QLPROMPT"), quickSaveSlot->Title); + tempstring.Format(GStrings("QLPROMPT"), savegameManager.quickSaveSlot->Title); Init(NULL, tempstring, 0, playsound); } @@ -659,7 +658,7 @@ void DQuickLoadMenu::HandleResult(bool res) { if (res) { - G_LoadGame (quickSaveSlot->Filename.GetChars()); + G_LoadGame (savegameManager.quickSaveSlot->Filename.GetChars()); S_Sound (CHAN_VOICE | CHAN_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE); M_ClearMenus(); } @@ -685,11 +684,11 @@ CCMD (quickload) return; } - if (quickSaveSlot == NULL) + if (savegameManager.quickSaveSlot == NULL) { M_StartControlPanel(true); // signal that whatever gets loaded should be the new quicksave - quickSaveSlot = (FSaveGameNode *)1; + savegameManager.quickSaveSlot = (FSaveGameNode *)1; M_SetMenu(NAME_Loadgamemenu); return; } @@ -697,7 +696,7 @@ CCMD (quickload) // [mxd]. Just load the game, no questions asked. if (!saveloadconfirmation) { - G_LoadGame(quickSaveSlot->Filename.GetChars()); + G_LoadGame(savegameManager.quickSaveSlot->Filename.GetChars()); return; } From 2a5b26c27cd967faf46bbb3e52e0838028d5ee5f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 11 Feb 2017 21:28:48 +0100 Subject: [PATCH 04/19] - removed native option menu controls. Note that this commit will not compile! --- src/d_main.cpp | 8 +- src/menu/colorpickermenu.cpp | 16 +- src/menu/joystickmenu.cpp | 242 +--- src/menu/menu.cpp | 21 +- src/menu/menu.h | 40 +- src/menu/menudef.cpp | 312 ++--- src/menu/optionmenu.cpp | 51 +- src/menu/optionmenuitems.h | 1208 ----------------- src/menu/videomenu.cpp | 41 +- wadsrc/static/zscript/menu/joystickmenu.txt | 2 +- wadsrc/static/zscript/menu/menuitembase.txt | 3 + .../static/zscript/menu/optionmenuitems.txt | 23 +- 12 files changed, 236 insertions(+), 1731 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index e0cbcbefa..b5d5e7032 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2523,7 +2523,10 @@ void D_DoomMain (void) // Create replacements for dehacked pickups FinishDehPatch(); - + + if (!batchrun) Printf("M_Init: Init menus.\n"); + M_Init(); + // clean up the compiler symbols which are not needed any longer. RemoveUnusedSymbols(); @@ -2541,9 +2544,6 @@ void D_DoomMain (void) bglobal.spawn_tries = 0; bglobal.wanted_botnum = bglobal.getspawned.Size(); - if (!batchrun) Printf ("M_Init: Init menus.\n"); - M_Init (); - if (!batchrun) Printf ("P_Init: Init Playloop state.\n"); StartScreen->LoadingStatus ("Init game engine", 0x3f); AM_StaticInit(); diff --git a/src/menu/colorpickermenu.cpp b/src/menu/colorpickermenu.cpp index d337eb82a..d0718c1a9 100644 --- a/src/menu/colorpickermenu.cpp +++ b/src/menu/colorpickermenu.cpp @@ -81,14 +81,14 @@ public: // This menu uses some featurs that are hard to implement in an external control lump // so it creates its own list of menu items. desc->mItems.Resize(mStartItem+8); - desc->mItems[mStartItem+0] = new DOptionMenuItemStaticText_(name, false); - desc->mItems[mStartItem+1] = new DOptionMenuItemStaticText_(" ", false); - desc->mItems[mStartItem+2] = new DOptionMenuSliderVar_("Red", &mRed, 0, 255, 15, 0); - desc->mItems[mStartItem+3] = new DOptionMenuSliderVar_("Green", &mGreen, 0, 255, 15, 0); - desc->mItems[mStartItem+4] = new DOptionMenuSliderVar_("Blue", &mBlue, 0, 255, 15, 0); - desc->mItems[mStartItem+5] = new DOptionMenuItemStaticText_(" ", false); - desc->mItems[mStartItem+6] = new DOptionMenuItemCommand_("Undo changes", "undocolorpic"); - desc->mItems[mStartItem+7] = new DOptionMenuItemStaticText_(" ", false); + desc->mItems[mStartItem+0] = CreateOptionMenuItemStaticText(name, false); + desc->mItems[mStartItem+1] = CreateOptionMenuItemStaticText(" ", false); + desc->mItems[mStartItem+2] = CreateOptionMenuSliderVar("Red", 0, 0, 255, 15, 0); + desc->mItems[mStartItem+3] = CreateOptionMenuSliderVar("Green", 1, 0, 255, 15, 0); + desc->mItems[mStartItem+4] = CreateOptionMenuSliderVar("Blue", 2, 0, 255, 15, 0); + desc->mItems[mStartItem+5] = CreateOptionMenuItemStaticText(" ", false); + desc->mItems[mStartItem+6] = CreateOptionMenuItemCommand("Undo changes", "undocolorpic"); + desc->mItems[mStartItem+7] = CreateOptionMenuItemStaticText(" ", false); for (auto &p : desc->mItems) { GC::WriteBarrier(p); diff --git a/src/menu/joystickmenu.cpp b/src/menu/joystickmenu.cpp index 50f49463c..24474bc43 100644 --- a/src/menu/joystickmenu.cpp +++ b/src/menu/joystickmenu.cpp @@ -128,177 +128,6 @@ DEFINE_ACTION_FUNCTION(IJoystickConfig, SetAxisMap) DOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy); -//============================================================================= -// -// -// -//============================================================================= - -class DOptionMenuSliderJoySensitivity_ : public DOptionMenuSliderBase_ -{ -public: - DOptionMenuSliderJoySensitivity_(const char *label, double min, double max, double step, int showval) - : DOptionMenuSliderBase_(label, min, max, step, showval) - { - } - - double GetSliderValue() - { - return SELECTED_JOYSTICK->GetSensitivity(); - } - - void SetSliderValue(double val) - { - SELECTED_JOYSTICK->SetSensitivity(float(val)); - } -}; - -//============================================================================= -// -// -// -//============================================================================= - -class DOptionMenuSliderJoyScale_ : public DOptionMenuSliderBase_ -{ - int mAxis; - int mNeg; - -public: - DOptionMenuSliderJoyScale_(const char *label, int axis, double min, double max, double step, int showval) - : DOptionMenuSliderBase_(label, min, max, step, showval) - { - mAxis = axis; - mNeg = 1; - } - - double GetSliderValue() - { - double d = SELECTED_JOYSTICK->GetAxisScale(mAxis); - mNeg = d < 0? -1:1; - return d; - } - - void SetSliderValue(double val) - { - SELECTED_JOYSTICK->SetAxisScale(mAxis, float(val * mNeg)); - } -}; - -//============================================================================= -// -// -// -//============================================================================= - -class DOptionMenuSliderJoyDeadZone_ : public DOptionMenuSliderBase_ -{ - int mAxis; - int mNeg; - -public: - DOptionMenuSliderJoyDeadZone_(const char *label, int axis, double min, double max, double step, int showval) - : DOptionMenuSliderBase_(label, min, max, step, showval) - { - mAxis = axis; - mNeg = 1; - } - - double GetSliderValue() - { - double d = SELECTED_JOYSTICK->GetAxisDeadZone(mAxis); - mNeg = d < 0? -1:1; - return d; - } - - void SetSliderValue(double val) - { - SELECTED_JOYSTICK->SetAxisDeadZone(mAxis, float(val * mNeg)); - } -}; - -//============================================================================= -// -// -// -//============================================================================= - -class DOptionMenuItemJoyMap_ : public DOptionMenuItemOptionBase_ -{ - int mAxis; -public: - - DOptionMenuItemJoyMap_(const char *label, int axis, const char *values, int center) - : DOptionMenuItemOptionBase_(label, "none", values, NULL, center) - { - mAxis = axis; - } - - int GetSelection() - { - double f = SELECTED_JOYSTICK->GetAxisMap(mAxis); - FOptionValues **opt = OptionValues.CheckKey(mValues); - if (opt != NULL && *opt != NULL) - { - // Map from joystick axis to menu selection. - for(unsigned i = 0; i < (*opt)->mValues.Size(); i++) - { - if (fabs(f - (*opt)->mValues[i].Value) < FLT_EPSILON) - { - return i; - } - } - } - return -1; - } - - void SetSelection(int selection) - { - FOptionValues **opt = OptionValues.CheckKey(mValues); - // Map from menu selection to joystick axis. - if (opt == NULL || *opt == NULL || (unsigned)selection >= (*opt)->mValues.Size()) - { - selection = JOYAXIS_None; - } - else - { - selection = (int)(*opt)->mValues[selection].Value; - } - SELECTED_JOYSTICK->SetAxisMap(mAxis, (EJoyAxis)selection); - } -}; - -//============================================================================= -// -// -// -//============================================================================= - -class DOptionMenuItemInverter_ : public DOptionMenuItemOptionBase_ -{ - int mAxis; -public: - - DOptionMenuItemInverter_(const char *label, int axis, int center) - : DOptionMenuItemOptionBase_(label, "none", "YesNo", NULL, center) - { - mAxis = axis; - } - - int GetSelection() - { - float f = SELECTED_JOYSTICK->GetAxisScale(mAxis); - return f > 0? 0:1; - } - - void SetSelection(int Selection) - { - float f = fabsf(SELECTED_JOYSTICK->GetAxisScale(mAxis)); - if (Selection) f*=-1; - SELECTED_JOYSTICK->SetAxisScale(mAxis, f); - } -}; - class DJoystickConfigMenu : public DOptionMenu { DECLARE_CLASS(DJoystickConfigMenu, DOptionMenu) @@ -306,33 +135,6 @@ class DJoystickConfigMenu : public DOptionMenu IMPLEMENT_CLASS(DJoystickConfigMenu, false, false) -//============================================================================= -// -// Executes a CCMD, action is a CCMD name -// -//============================================================================= - -class DOptionMenuItemJoyConfigMenu_ : public DOptionMenuItemSubmenu_ -{ - DECLARE_CLASS(DOptionMenuItemJoyConfigMenu_, DOptionMenuItemSubmenu_) - IJoystickConfig *mJoy; -public: - DOptionMenuItemJoyConfigMenu_(const char *label = nullptr, IJoystickConfig *joy = nullptr) - : DOptionMenuItemSubmenu_(label, "JoystickConfigMenu") - { - mJoy = joy; - } - - bool Activate() - { - UpdateJoystickConfigMenu(mJoy); - return DOptionMenuItemSubmenu_::Activate(); - } -}; - -IMPLEMENT_CLASS(DOptionMenuItemJoyConfigMenu_, false, false) - - /*======================================= * * Joystick Menu @@ -345,12 +147,12 @@ DOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy) if (desc != NULL && (*desc)->IsKindOf(RUNTIME_CLASS(DOptionMenuDescriptor))) { DOptionMenuDescriptor *opt = (DOptionMenuDescriptor *)*desc; - DOptionMenuItem *it; + DMenuItemBase *it; opt->mItems.Clear(); if (joy == NULL) { opt->mTitle = "Configure Controller"; - it = new DOptionMenuItemStaticText_("Invalid controller specified for menu", false); + it = CreateOptionMenuItemStaticText("Invalid controller specified for menu", false); opt->mItems.Push(it); } else @@ -359,34 +161,34 @@ DOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy) SELECTED_JOYSTICK = joy; - it = new DOptionMenuSliderJoySensitivity_("Overall sensitivity", 0, 2, 0.1, 3); + it = CreateOptionMenuSliderJoySensitivity("Overall sensitivity", 0, 2, 0.1, 3); opt->mItems.Push(it); - it = new DOptionMenuItemStaticText_(" ", false); + it = CreateOptionMenuItemStaticText(" ", false); opt->mItems.Push(it); if (joy->GetNumAxes() > 0) { - it = new DOptionMenuItemStaticText_("Axis Configuration", true); + it = CreateOptionMenuItemStaticText("Axis Configuration", true); opt->mItems.Push(it); for (int i = 0; i < joy->GetNumAxes(); ++i) { - it = new DOptionMenuItemStaticText_(" ", false); + it = CreateOptionMenuItemStaticText(" ", false); opt->mItems.Push(it); - it = new DOptionMenuItemJoyMap_(joy->GetAxisName(i), i, "JoyAxisMapNames", false); + it = CreateOptionMenuItemJoyMap(joy->GetAxisName(i), i, "JoyAxisMapNames", false); opt->mItems.Push(it); - it = new DOptionMenuSliderJoyScale_("Overall sensitivity", i, 0, 4, 0.1, 3); + it = CreateOptionMenuSliderJoyScale("Overall sensitivity", i, 0, 4, 0.1, 3); opt->mItems.Push(it); - it = new DOptionMenuItemInverter_("Invert", i, false); + it = CreateOptionMenuItemInverter("Invert", i, false); opt->mItems.Push(it); - it = new DOptionMenuSliderJoyDeadZone_("Dead Zone", i, 0, 0.9, 0.05, 3); + it = CreateOptionMenuSliderJoyDeadZone("Dead Zone", i, 0, 0.9, 0.05, 3); opt->mItems.Push(it); } } else { - it = new DOptionMenuItemStaticText_("No configurable axes", false); + it = CreateOptionMenuItemStaticText("No configurable axes", false); opt->mItems.Push(it); } } @@ -412,7 +214,7 @@ void UpdateJoystickMenu(IJoystickConfig *selected) if (desc != NULL && (*desc)->IsKindOf(RUNTIME_CLASS(DOptionMenuDescriptor))) { DOptionMenuDescriptor *opt = (DOptionMenuDescriptor *)*desc; - DOptionMenuItem *it; + DMenuItemBase *it; opt->mItems.Clear(); int i; @@ -436,40 +238,40 @@ void UpdateJoystickMenu(IJoystickConfig *selected) } // Todo: Block joystick for changing this one. - it = new DOptionMenuItemOption_("Enable controller support", "use_joystick", "YesNo", NULL, false); + it = CreateOptionMenuItemOption("Enable controller support", "use_joystick", "YesNo", NULL, false); opt->mItems.Push(it); #ifdef _WIN32 - it = new DOptionMenuItemOption_("Enable DirectInput controllers", "joy_dinput", "YesNo", NULL, false); + it = CreateOptionMenuItemOption("Enable DirectInput controllers", "joy_dinput", "YesNo", NULL, false); opt->mItems.Push(it); - it = new DOptionMenuItemOption_("Enable XInput controllers", "joy_xinput", "YesNo", NULL, false); + it = CreateOptionMenuItemOption("Enable XInput controllers", "joy_xinput", "YesNo", NULL, false); opt->mItems.Push(it); - it = new DOptionMenuItemOption_("Enable raw PlayStation 2 adapters", "joy_ps2raw", "YesNo", NULL, false); + it = CreateOptionMenuItemOption("Enable raw PlayStation 2 adapters", "joy_ps2raw", "YesNo", NULL, false); opt->mItems.Push(it); #endif - it = new DOptionMenuItemStaticText_(" ", false); + it = CreateOptionMenuItemStaticText(" ", false); opt->mItems.Push(it); if (Joysticks.Size() == 0) { - it = new DOptionMenuItemStaticText_("No controllers detected", false); + it = CreateOptionMenuItemStaticText("No controllers detected", false); opt->mItems.Push(it); if (!use_joystick) { - it = new DOptionMenuItemStaticText_("Controller support must be", false); + it = CreateOptionMenuItemStaticText("Controller support must be", false); opt->mItems.Push(it); - it = new DOptionMenuItemStaticText_("enabled to detect any", false); + it = CreateOptionMenuItemStaticText("enabled to detect any", false); opt->mItems.Push(it); } } else { - it = new DOptionMenuItemStaticText_("Configure controllers:", false); + it = CreateOptionMenuItemStaticText("Configure controllers:", false); opt->mItems.Push(it); for (int i = 0; i < (int)Joysticks.Size(); ++i) { - it = new DOptionMenuItemJoyConfigMenu_(Joysticks[i]->GetName(), Joysticks[i]); + it = CreateOptionMenuItemJoyConfigMenu(Joysticks[i]->GetName(), Joysticks[i]); opt->mItems.Push(it); if (i == itemnum) opt->mSelectedItem = opt->mItems.Size(); } diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index d28bc5496..98c2de36d 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -1093,7 +1093,6 @@ CCMD(reset2saved) //native void OptionMenuDescriptor.CalcIndent(); //native OptionMenuItem OptionMenuDescriptor.GetItem(Name iname); -//native void OptionMenuItem.drawLabel(int indent, int y, EColorRange color, bool grayed = false); DEFINE_FIELD(DMenuDescriptor, mMenuName) DEFINE_FIELD(DMenuDescriptor, mNetgameMessage) @@ -1131,8 +1130,8 @@ DEFINE_FIELD(DOptionMenuDescriptor, mIndent) DEFINE_FIELD(DOptionMenuDescriptor, mPosition) DEFINE_FIELD(DOptionMenuDescriptor, mDontDim) -DEFINE_FIELD(DOptionMenuItem, mLabel) -DEFINE_FIELD(DOptionMenuItem, mCentered) +//DEFINE_FIELD(DMenuItemBase, mLabel) +//DEFINE_FIELD(DMenuItemBase, mCentered) DEFINE_FIELD(DOptionMenu, CanScrollUp) DEFINE_FIELD(DOptionMenu, CanScrollDown) @@ -1148,3 +1147,19 @@ DEFINE_FIELD(FOptionMenuSettings, mFontColorHeader) DEFINE_FIELD(FOptionMenuSettings, mFontColorHighlight) DEFINE_FIELD(FOptionMenuSettings, mFontColorSelection) DEFINE_FIELD(FOptionMenuSettings, mLinespacing) + + +struct IJoystickConfig; +DMenuItemBase * CreateOptionMenuItemStaticText(const char *name, bool v); +DMenuItemBase * CreateOptionMenuSliderVar(const char *name, int index, double min, double max, double step, int showval); +DMenuItemBase * CreateOptionMenuItemCommand(const char * label, FName cmd); +DMenuItemBase * CreateOptionMenuItemOption(const char * label, FName cmd, FName values, FBaseCVar *graycheck, bool center); +DMenuItemBase * CreateOptionMenuItemJoyConfigMenu(const char *label, IJoystickConfig *joy); +DMenuItemBase * CreateOptionMenuItemJoyMap(const char *label, int axis, FName values, bool center); +DMenuItemBase * CreateOptionMenuSliderJoySensitivity(const char * label, double min, double max, double step, int showval); +DMenuItemBase * CreateOptionMenuSliderJoyScale(const char *label, int axis, double min, double max, double step, int showval); +DMenuItemBase * CreateOptionMenuItemInverter(const char *label, int axis, int center); +DMenuItemBase * CreateOptionMenuSliderJoyDeadZone(const char *label, int axis, double min, double max, double step, int showval); + +DMenuItemBase * CreateOptionMenuItemSubmenu(const char *label, FName cmd, int center); +DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBindings *bindings); diff --git a/src/menu/menu.h b/src/menu/menu.h index 7ffb1aab8..429a2b4f4 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -118,7 +118,6 @@ public: }; class DMenuItemBase; -class DOptionMenuItem; class DListMenuDescriptor : public DMenuDescriptor { @@ -176,7 +175,7 @@ class DOptionMenuDescriptor : public DMenuDescriptor DECLARE_CLASS(DOptionMenuDescriptor, DMenuDescriptor) public: - TArray mItems; + TArray mItems; FString mTitle; int mSelectedItem; int mDrawTop; @@ -187,7 +186,7 @@ public: bool mDontDim; void CalcIndent(); - DOptionMenuItem *GetItem(FName name); + DMenuItemBase *GetItem(FName name); void Reset() { // Reset the default settings (ignore all other values in the struct) @@ -330,11 +329,14 @@ public: virtual bool MouseEvent(int type, int x, int y); virtual bool CheckHotkey(int c); virtual int GetWidth(); + virtual int GetIndent() { return 0; } + virtual int Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected) { return indent; } void DrawSelector(int xofs, int yofs, FTextureID tex); void OffsetPositionY(int ydelta) { mYpos += ydelta; } int GetY() { return mYpos; } int GetX() { return mXpos; } void SetX(int x) { mXpos = x; } + }; class DListMenuItemStaticPatch_ : public DMenuItemBase @@ -598,16 +600,17 @@ public: // //============================================================================= -class DOptionMenuItem : public DMenuItemBase +/* +class DMenuItemBase : public DMenuItemBase { - DECLARE_ABSTRACT_CLASS(DOptionMenuItem, DMenuItemBase) + DECLARE_ABSTRACT_CLASS(DMenuItemBase, DMenuItemBase) public: FString mLabel; bool mCentered; void drawLabel(int indent, int y, EColorRange color, bool grayed = false); - DOptionMenuItem(const char *text = nullptr, FName action = NAME_None, bool center = false) + DMenuItemBase(const char *text = nullptr, FName action = NAME_None, bool center = false) : DMenuItemBase(0, 0, action) { mLabel = text; @@ -618,7 +621,8 @@ public: virtual bool Selectable(); virtual int GetIndent(); virtual bool MouseEvent(int type, int x, int y); -}; +}; +*/ //============================================================================= // @@ -657,11 +661,11 @@ public: // needs to be public for script access bool CanScrollUp; bool CanScrollDown; int VisBottom; - DOptionMenuItem *mFocusControl; + DMenuItemBase *mFocusControl; DOptionMenuDescriptor *mDesc; //public: - DOptionMenuItem *GetItem(FName name); + DMenuItemBase *GetItem(FName name); DOptionMenu(DMenu *parent = NULL, DOptionMenuDescriptor *desc = NULL); virtual void Init(DMenu *parent = NULL, DOptionMenuDescriptor *desc = NULL); int FirstSelectable(); @@ -671,11 +675,11 @@ public: // needs to be public for script access void Ticker (); void Drawer (); const DOptionMenuDescriptor *GetDescriptor() const { return mDesc; } - void SetFocus(DOptionMenuItem *fc) + void SetFocus(DMenuItemBase *fc) { mFocusControl = fc; } - bool CheckFocus(DOptionMenuItem *fc) + bool CheckFocus(DMenuItemBase *fc) { return mFocusControl == fc; } @@ -745,4 +749,18 @@ void M_InitVideoModesMenu (); void M_MarkMenus(); +struct IJoystickConfig; +DMenuItemBase * CreateOptionMenuItemStaticText(const char *name, bool v); +DMenuItemBase * CreateOptionMenuSliderVar(const char *name, int index, double min, double max, double step, int showval); +DMenuItemBase * CreateOptionMenuItemCommand(const char * label, FName cmd); +DMenuItemBase * CreateOptionMenuItemOption(const char * label, FName cmd, FName values, FBaseCVar *graycheck, bool center); +DMenuItemBase * CreateOptionMenuItemSubmenu(const char *label, FName cmd, int center); +DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBindings *bindings); +DMenuItemBase * CreateOptionMenuItemJoyConfigMenu(const char *label, IJoystickConfig *joy); +DMenuItemBase * CreateOptionMenuItemJoyMap(const char *label, int axis, FName values, bool center); +DMenuItemBase * CreateOptionMenuSliderJoySensitivity(const char * label, double min, double max, double step, int showval); +DMenuItemBase * CreateOptionMenuSliderJoyScale(const char *label, int axis, double min, double max, double step, int showval); +DMenuItemBase * CreateOptionMenuItemInverter(const char *label, int axis, int center); +DMenuItemBase * CreateOptionMenuSliderJoyDeadZone(const char *label, int axis, double min, double max, double step, int showval); + #endif diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 86f168747..51f2e4788 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -785,198 +785,114 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) sc.MustGetNumber(); desc->mIndent = sc.Number; } - else if (sc.Compare("Submenu")) - { - sc.MustGetString(); - FString label = sc.String; - sc.MustGetStringName(","); - sc.MustGetString(); - DOptionMenuItem *it = new DOptionMenuItemSubmenu_(label, sc.String); - desc->mItems.Push(it); - } - else if (sc.Compare("Option")) - { - sc.MustGetString(); - FString label = sc.String; - sc.MustGetStringName(","); - sc.MustGetString(); - FString cvar = sc.String; - sc.MustGetStringName(","); - sc.MustGetString(); - FString values = sc.String; - FString check; - int center = 0; - if (sc.CheckString(",")) - { - sc.MustGetString(); - if (*sc.String != 0) check = sc.String; - if (sc.CheckString(",")) - { - sc.MustGetNumber(); - center = sc.Number; - } - } - DOptionMenuItem *it = new DOptionMenuItemOption_(label, cvar, values, check, center); - desc->mItems.Push(it); - } - else if (sc.Compare("Command")) - { - sc.MustGetString(); - FString label = sc.String; - sc.MustGetStringName(","); - sc.MustGetString(); - DOptionMenuItem *it = new DOptionMenuItemCommand_(label, sc.String); - desc->mItems.Push(it); - } - else if (sc.Compare("SafeCommand")) - { - sc.MustGetString(); - FString label = sc.String; - sc.MustGetStringName(","); - sc.MustGetString(); - FString command = sc.String; - FString prompt; - // Check for optional custom prompt - if (sc.CheckString(",")) - { - sc.MustGetString(); - prompt = sc.String; - } - DOptionMenuItem *it = new DOptionMenuItemSafeCommand_(label, command, prompt); - desc->mItems.Push(it); - } - else if (sc.Compare("Control") || sc.Compare("MapControl")) - { - bool map = sc.Compare("MapControl"); - sc.MustGetString(); - FString label = sc.String; - sc.MustGetStringName(","); - sc.MustGetString(); - DOptionMenuItem *it = new DOptionMenuItemControl_(label, sc.String, map? &AutomapBindings : &Bindings); - desc->mItems.Push(it); - } - else if (sc.Compare("ColorPicker")) - { - sc.MustGetString(); - FString label = sc.String; - sc.MustGetStringName(","); - sc.MustGetString(); - DOptionMenuItem *it = new DOptionMenuItemColorPicker_(label, sc.String); - desc->mItems.Push(it); - } - else if (sc.Compare("StaticText")) - { - sc.MustGetString(); - FString label = sc.String; - EColorRange cr = ParseOptionColor(sc, desc); - DOptionMenuItem *it = new DOptionMenuItemStaticText_(label, cr); - desc->mItems.Push(it); - } - else if (sc.Compare("StaticTextSwitchable")) - { - sc.MustGetString(); - FString label = sc.String; - sc.MustGetStringName(","); - sc.MustGetString(); - FString label2 = sc.String; - sc.MustGetStringName(","); - sc.MustGetString(); - FName action = sc.String; - EColorRange cr = ParseOptionColor(sc, desc); - DOptionMenuItem *it = new DOptionMenuItemStaticTextSwitchable_(label, label2, action, cr); - desc->mItems.Push(it); - } - else if (sc.Compare("Slider")) - { - sc.MustGetString(); - FString text = sc.String; - sc.MustGetStringName(","); - sc.MustGetString(); - FString action = sc.String; - sc.MustGetStringName(","); - sc.MustGetFloat(); - double min = sc.Float; - sc.MustGetStringName(","); - sc.MustGetFloat(); - double max = sc.Float; - sc.MustGetStringName(","); - sc.MustGetFloat(); - double step = sc.Float; - int showvalue = 1; - if (sc.CheckString(",")) - { - sc.MustGetNumber(); - showvalue = sc.Number; - } - DOptionMenuItem *it = new DOptionMenuSliderCVar_(text, action, min, max, step, showvalue); - desc->mItems.Push(it); - } - else if (sc.Compare("screenresolution")) - { - sc.MustGetString(); - DOptionMenuItem *it = new DOptionMenuScreenResolutionLine_(sc.String); - desc->mItems.Push(it); - } - // [TP] -- Text input widget - else if ( sc.Compare( "TextField" )) - { - sc.MustGetString(); - FString label = sc.String; - sc.MustGetStringName( "," ); - sc.MustGetString(); - FString cvar = sc.String; - FString check; - - if ( sc.CheckString( "," )) - { - sc.MustGetString(); - check = sc.String; - } - - DOptionMenuItem* it = new DOptionMenuTextField_( label, cvar, check ); - desc->mItems.Push( it ); - } - // [TP] -- Number input widget - else if ( sc.Compare( "NumberField" )) - { - sc.MustGetString(); - FString label = sc.String; - sc.MustGetStringName( "," ); - sc.MustGetString(); - FString cvar = sc.String; - float minimum = 0.0f; - float maximum = 100.0f; - float step = 1.0f; - FString check; - - if ( sc.CheckString( "," )) - { - sc.MustGetFloat(); - minimum = (float) sc.Float; - sc.MustGetStringName( "," ); - sc.MustGetFloat(); - maximum = (float) sc.Float; - - if ( sc.CheckString( "," )) - { - sc.MustGetFloat(); - step = (float) sc.Float; - - if ( sc.CheckString( "," )) - { - sc.MustGetString(); - check = sc.String; - } - } - } - - DOptionMenuItem* it = new DOptionMenuNumberField_( label, cvar, - minimum, maximum, step, check ); - desc->mItems.Push( it ); - } else { - sc.ScriptError("Unknown keyword '%s'", sc.String); + bool success = false; + FStringf buildname("OptionMenuItem%s", sc.String); + // Handle one special case: MapControl maps to Control with one parameter different + FKeyBindings *bind = sc.Compare("MapControl") ? &AutomapBindings : &Bindings; + PClass *cls = PClass::FindClass(buildname); + if (cls != nullptr && cls->IsDescendantOf("OptionMenuItem")) + { + auto func = dyn_cast(cls->Symbols.FindSymbol("Init", false)); + if (func != nullptr && !(func->Variants[0].Flags & (VARF_Protected | VARF_Private))) // skip internal classes which have a protexted init method. + { + auto &args = func->Variants[0].Proto->ArgumentTypes; + TArray params; + + params.Push(0); + auto TypeCVar = NewPointer(NewNativeStruct("CVar", nullptr)); + auto TypeBind = NewPointer(NewNativeStruct("KeyBindings", nullptr)); + for (unsigned i = 1; i < args.Size(); i++) + { + sc.MustGetString(); + if (args[i] == TypeString) + { + params.Push(sc.String); + } + else if (args[i] == TypeName) + { + params.Push(FName(sc.String).GetIndex()); + } + else if (args[i] == TypeColor) + { + params.Push(V_GetColor(nullptr, sc)); + } + else if (args[i]->IsKindOf(RUNTIME_CLASS(PInt))) + { + char *endp; + int v = (int)strtoll(sc.String, &endp, 0); + if (*endp != 0) + { + // special check for font color ranges. + v = V_FindFontColor(sc.String); + if (v == CR_UNTRANSLATED && !sc.Compare("untranslated")) + { + // todo: check other data types that may get used. + sc.ScriptError("Integer expected, got %s", sc.String); + } + } + if (args[i] == TypeBool) v = !!v; + params.Push(v); + } + else if (args[i]->IsKindOf(RUNTIME_CLASS(PInt))) + { + char *endp; + double v = strtod(sc.String, &endp); + if (*endp != 0) + { + sc.ScriptError("Float expected, got %s", sc.String); + } + params.Push(v); + } + else if (args[i] == TypeCVar) + { + auto cv = FindCVar(sc.String, nullptr); + if (cv == nullptr && *sc.String) + { + sc.ScriptError("Unknown CVar %s", sc.String); + } + params.Push(cv); + } + else + { + sc.ScriptError("Invalid parameter type %s for menu item", args[i]->DescriptiveName()); + } + if (sc.CheckString(",")) + { + if (i == args.Size() - 1) + { + sc.ScriptError("Too many parameters for %s", cls->TypeName.GetChars()); + } + } + else + { + if (args[i + 1] == TypeBind) + { + // Bindings are not parsed, they just get tacked on. + params.Push(bind); + i++; + } + if (i < args.Size() - 1 && !(func->Variants[0].ArgFlags[i + 1] & VARF_Optional)) + { + sc.ScriptError("Insufficient parameters for %s", cls->TypeName.GetChars()); + } + break; + } + } + /* + DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew(); + params[0] = item; + GlobalVMStack.Call(func->Variants[0].Implementation, ¶ms[0], params.Size(), nullptr, 0); + desc->mItems.Push((DMenuItemBase*)item); + */ + success = true; + } + } + if (!success) + { + sc.ScriptError("Unknown keyword '%s'", sc.String); + } } } for (auto &p : desc->mItems) @@ -1185,7 +1101,7 @@ static void BuildEpisodeMenu() GC::WriteBarrier(od); for(unsigned i = 0; i < AllEpisodes.Size(); i++) { - DOptionMenuItemSubmenu_ *it = new DOptionMenuItemSubmenu_(AllEpisodes[i].mEpisodeName, "Skillmenu", i); + auto it = CreateOptionMenuItemSubmenu(AllEpisodes[i].mEpisodeName, "Skillmenu", i); od->mItems.Push(it); GC::WriteBarrier(od, it); } @@ -1324,13 +1240,13 @@ static void BuildPlayerclassMenu() const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type); if (pname != nullptr) { - DOptionMenuItemSubmenu_ *it = new DOptionMenuItemSubmenu_(pname, "Episodemenu", i); + auto it = CreateOptionMenuItemSubmenu(pname, "Episodemenu", i); od->mItems.Push(it); GC::WriteBarrier(od, it); } } } - DOptionMenuItemSubmenu_ *it = new DOptionMenuItemSubmenu_("Random", "Episodemenu", -1); + auto it = CreateOptionMenuItemSubmenu("Random", "Episodemenu", -1); od->mItems.Push(it); GC::WriteBarrier(od, it); } @@ -1411,14 +1327,14 @@ static void InitKeySections() for (unsigned i = 0; i < KeySections.Size(); i++) { FKeySection *sect = &KeySections[i]; - DOptionMenuItem *item = new DOptionMenuItemStaticText_(" ", false); + DMenuItemBase *item = CreateOptionMenuItemStaticText(" ", false); menu->mItems.Push(item); - item = new DOptionMenuItemStaticText_(sect->mTitle, true); + item = CreateOptionMenuItemStaticText(sect->mTitle, true); menu->mItems.Push(item); for (unsigned j = 0; j < sect->mActions.Size(); j++) { FKeyAction *act = §->mActions[j]; - item = new DOptionMenuItemControl_(act->mTitle, act->mAction, &Bindings); + item = CreateOptionMenuItemControl(act->mTitle, act->mAction, &Bindings); menu->mItems.Push(item); } } @@ -1599,7 +1515,7 @@ fail: for(unsigned int i = 0; i < AllSkills.Size(); i++) { FSkillInfo &skill = AllSkills[i]; - DOptionMenuItem *li; + DMenuItemBase *li; // Using a different name for skills that must be confirmed makes handling this easier. const char *action = (skill.MustConfirm && !AllEpisodes[gs->Episode].mNoSkill) ? "StartgameConfirm" : "Startgame"; @@ -1609,7 +1525,7 @@ fail: { pItemText = skill.MenuNamesForPlayerClass.CheckKey(gs->PlayerClass); } - li = new DOptionMenuItemSubmenu_(pItemText? *pItemText : skill.MenuName, action, i); + li = CreateOptionMenuItemSubmenu(pItemText? *pItemText : skill.MenuName, action, i); od->mItems.Push(li); GC::WriteBarrier(od, li); if (!done) diff --git a/src/menu/optionmenu.cpp b/src/menu/optionmenu.cpp index a7f4acc7f..bc4c7974e 100644 --- a/src/menu/optionmenu.cpp +++ b/src/menu/optionmenu.cpp @@ -129,10 +129,8 @@ int DOptionMenu::FirstSelectable() // // //============================================================================= -IMPLEMENT_CLASS(DOptionMenuItem, true, false) - -DOptionMenuItem *DOptionMenu::GetItem(FName name) +DMenuItemBase *DOptionMenu::GetItem(FName name) { for(unsigned i=0;imItems.Size(); i++) { @@ -476,51 +474,6 @@ void DOptionMenu::Drawer () Super::Drawer(); } -int DOptionMenuItem::Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected) -{ - return indent; -} - -bool DOptionMenuItem::Selectable() -{ - return true; -} - -bool DOptionMenuItem::MouseEvent(int type, int x, int y) -{ - if (Selectable() && type == DMenu::MOUSE_Release) - { - return DMenu::CurrentMenu->CallMenuEvent(MKEY_Enter, true); - } - return false; -} - -int DOptionMenuItem::GetIndent() -{ - if (mCentered) - { - return 0; - } - const char *label = mLabel.GetChars(); - if (*label == '$') label = GStrings(label+1); - return SmallFont->StringWidth(label); -} - -void DOptionMenuItem::drawLabel(int indent, int y, EColorRange color, bool grayed) -{ - const char *label = mLabel.GetChars(); - if (*label == '$') label = GStrings(label+1); - - int overlay = grayed? MAKEARGB(96,48,0,0) : 0; - - int x; - int w = SmallFont->StringWidth(label) * CleanXfac_1; - if (!mCentered) x = indent - w; - else x = (screen->GetWidth() - w) / 2; - screen->DrawText (SmallFont, color, x, y, label, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay, TAG_DONE); -} - - void DOptionMenuDescriptor::CalcIndent() { // calculate the menu indent @@ -540,7 +493,7 @@ void DOptionMenuDescriptor::CalcIndent() // //============================================================================= -DOptionMenuItem *DOptionMenuDescriptor::GetItem(FName name) +DMenuItemBase *DOptionMenuDescriptor::GetItem(FName name) { for(unsigned i=0;i= (int)(*opt)->mValues.Size()) s = 0; - SetSelection(s); // readjust the CVAR if its value is outside the range now - return true; - } - } - return false; - } - - //============================================================================= - virtual int GetSelection() = 0; - virtual void SetSelection(int Selection) = 0; - - //============================================================================= - int Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected) - { - bool grayed = mGrayCheck != NULL && !(mGrayCheck->GetGenericRep(CVAR_Bool).Bool); - - if (mCenter) - { - indent = (screen->GetWidth() / 2); - } - drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor, grayed); - - int overlay = grayed? MAKEARGB(96,48,0,0) : 0; - const char *text; - int Selection = GetSelection(); - FOptionValues **opt = OptionValues.CheckKey(mValues); - if (Selection < 0 || opt == NULL || *opt == NULL) - { - text = "Unknown"; - } - else - { - text = (*opt)->mValues[Selection].Text; - } - if (*text == '$') text = GStrings(text + 1); - screen->DrawText (SmallFont, OptionSettings.mFontColorValue, indent + CURSORSPACE, y, - text, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay, TAG_DONE); - return indent; - } - - //============================================================================= - bool MenuEvent (int mkey, bool fromcontroller) - { - FOptionValues **opt = OptionValues.CheckKey(mValues); - if (opt != NULL && *opt != NULL && (*opt)->mValues.Size() > 0) - { - int Selection = GetSelection(); - if (mkey == MKEY_Left) - { - if (Selection == -1) Selection = 0; - else if (--Selection < 0) Selection = (*opt)->mValues.Size()-1; - } - else if (mkey == MKEY_Right || mkey == MKEY_Enter) - { - if (++Selection >= (int)(*opt)->mValues.Size()) Selection = 0; - } - else - { - return DOptionMenuItem::MenuEvent(mkey, fromcontroller); - } - SetSelection(Selection); - S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE); - } - else - { - return DOptionMenuItem::MenuEvent(mkey, fromcontroller); - } - return true; - } - - bool Selectable() - { - return !(mGrayCheck != NULL && !(mGrayCheck->GetGenericRep(CVAR_Bool).Bool)); - } -}; - -#ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuItemOptionBase_, true, false) -#endif - -//============================================================================= -// -// Change a CVAR, action is the CVAR name -// -//============================================================================= - -class DOptionMenuItemOption_ : public DOptionMenuItemOptionBase_ -{ - DECLARE_CLASS(DOptionMenuItemOption_, DOptionMenuItemOptionBase_) - // action is a CVAR - FBaseCVar *mCVar; - - DOptionMenuItemOption_() {} -public: - - DOptionMenuItemOption_(const char *label, const char *menu, const char *values, const char *graycheck, int center) - : DOptionMenuItemOptionBase_(label, menu, values, graycheck, center) - { - mCVar = FindCVar(mAction, NULL); - } - - //============================================================================= - int GetSelection() - { - int Selection = -1; - FOptionValues **opt = OptionValues.CheckKey(mValues); - if (opt != NULL && *opt != NULL && mCVar != NULL && (*opt)->mValues.Size() > 0) - { - if ((*opt)->mValues[0].TextValue.IsEmpty()) - { - UCVarValue cv = mCVar->GetGenericRep(CVAR_Float); - for(unsigned i = 0; i < (*opt)->mValues.Size(); i++) - { - if (fabs(cv.Float - (*opt)->mValues[i].Value) < FLT_EPSILON) - { - Selection = i; - break; - } - } - } - else - { - const char *cv = mCVar->GetHumanString(); - for(unsigned i = 0; i < (*opt)->mValues.Size(); i++) - { - if ((*opt)->mValues[i].TextValue.CompareNoCase(cv) == 0) - { - Selection = i; - break; - } - } - } - } - return Selection; - } - - void SetSelection(int Selection) - { - UCVarValue value; - FOptionValues **opt = OptionValues.CheckKey(mValues); - if (opt != NULL && *opt != NULL && mCVar != NULL && (*opt)->mValues.Size() > 0) - { - if ((*opt)->mValues[0].TextValue.IsEmpty()) - { - value.Float = (float)(*opt)->mValues[Selection].Value; - mCVar->SetGenericRep (value, CVAR_Float); - } - else - { - value.String = (*opt)->mValues[Selection].TextValue.LockBuffer(); - mCVar->SetGenericRep (value, CVAR_String); - (*opt)->mValues[Selection].TextValue.UnlockBuffer(); - } - } - } -}; - -#ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuItemOption_, false, false) -#endif - //============================================================================= // // This class is used to capture the key to be used as the new key binding @@ -434,879 +102,3 @@ public: IMPLEMENT_CLASS(DEnterKey, true, false) #endif -//============================================================================= -// -// // Edit a key binding, Action is the CCMD to bind -// -//============================================================================= - -class DOptionMenuItemControl_ : public DOptionMenuItem -{ - DECLARE_CLASS(DOptionMenuItemControl_, DOptionMenuItemOption_) - FKeyBindings *mBindings; - int mInput; - bool mWaiting; - - DOptionMenuItemControl_() {} -public: - - DOptionMenuItemControl_(const char *label, const char *menu, FKeyBindings *bindings) - : DOptionMenuItem(label, menu) - { - mBindings = bindings; - mWaiting = false; - } - - - //============================================================================= - int Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected) - { - drawLabel(indent, y, mWaiting? OptionSettings.mFontColorHighlight: - (selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor)); - - char description[64]; - int Key1, Key2; - - mBindings->GetKeysForCommand(mAction, &Key1, &Key2); - C_NameKeys (description, Key1, Key2); - if (description[0]) - { - M_DrawConText(CR_WHITE, indent + CURSORSPACE, y + (OptionSettings.mLinespacing-8)*CleanYfac_1, description); - } - else - { - screen->DrawText(SmallFont, CR_BLACK, indent + CURSORSPACE, y + (OptionSettings.mLinespacing-8)*CleanYfac_1, "---", - DTA_CleanNoMove_1, true, TAG_DONE); - } - return indent; - } - - //============================================================================= - bool MenuEvent(int mkey, bool fromcontroller) - { - if (mkey == MKEY_Input) - { - mWaiting = false; - mBindings->SetBind(mInput, mAction); - return true; - } - else if (mkey == MKEY_Clear) - { - mBindings->UnbindACommand(mAction); - return true; - } - else if (mkey == MKEY_Abort) - { - mWaiting = false; - return true; - } - return false; - } - - bool Activate() - { - S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE); - mWaiting = true; - DMenu *input = new DEnterKey(DMenu::CurrentMenu, &mInput); - M_ActivateMenu(input); - return true; - } -}; - -#ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuItemControl_, false, false) -#endif -//============================================================================= -// -// -// -//============================================================================= - -class DOptionMenuItemStaticText_ : public DOptionMenuItem -{ - DECLARE_CLASS(DOptionMenuItemStaticText_, DOptionMenuItem) - EColorRange mColor; - - DOptionMenuItemStaticText_() {} -public: - DOptionMenuItemStaticText_(const char *label, bool header) - : DOptionMenuItem(label, NAME_None, true) - { - mColor = header ? OptionSettings.mFontColorHeader : OptionSettings.mFontColor; - } - - DOptionMenuItemStaticText_(const char *label, EColorRange cr) - : DOptionMenuItem(label, NAME_None, true) - { - mColor = cr; - } - - int Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected) - { - drawLabel(indent, y, mColor); - return -1; - } - - bool Selectable() - { - return false; - } - -}; - -#ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuItemStaticText_, false, false) -#endif - -//============================================================================= -// -// -// -//============================================================================= - -class DOptionMenuItemStaticTextSwitchable_ : public DOptionMenuItem -{ - DECLARE_CLASS(DOptionMenuItemStaticTextSwitchable_, DOptionMenuItem) - EColorRange mColor; - FString mAltText; - int mCurrent; - - DOptionMenuItemStaticTextSwitchable_() {} -public: - DOptionMenuItemStaticTextSwitchable_(const char *label, const char *label2, FName action, EColorRange cr) - : DOptionMenuItem(label, action, true) - { - mColor = cr; - mAltText = label2; - mCurrent = 0; - } - - int Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected) - { - const char *txt = mCurrent? mAltText.GetChars() : mLabel.GetChars(); - if (*txt == '$') txt = GStrings(txt + 1); - int w = SmallFont->StringWidth(txt) * CleanXfac_1; - int x = (screen->GetWidth() - w) / 2; - screen->DrawText (SmallFont, mColor, x, y, txt, DTA_CleanNoMove_1, true, TAG_DONE); - return -1; - } - - bool SetValue(int i, int val) - { - if (i == 0) - { - mCurrent = val; - return true; - } - return false; - } - - bool SetString(int i, const char *newtext) - { - if (i == 0) - { - mAltText = newtext; - return true; - } - return false; - } - - bool Selectable() - { - return false; - } -}; - -#ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuItemStaticTextSwitchable_, false, false) -#endif - -//============================================================================= -// -// -// -//============================================================================= - -class DOptionMenuSliderBase_ : public DOptionMenuItem -{ - DECLARE_ABSTRACT_CLASS(DOptionMenuSliderBase_, DOptionMenuItem) - // action is a CVAR - double mMin, mMax, mStep; - int mShowValue; - int mDrawX; - int mSliderShort; - -protected: - DOptionMenuSliderBase_() {} -public: - DOptionMenuSliderBase_(const char *label, double min, double max, double step, int showval) - : DOptionMenuItem(label, NAME_None) - { - mMin = min; - mMax = max; - mStep = step; - mShowValue = showval; - mDrawX = 0; - mSliderShort = 0; - } - - virtual double GetSliderValue() = 0; - virtual void SetSliderValue(double val) = 0; - - //============================================================================= - // - // Draw a slider. Set fracdigits negative to not display the current value numerically. - // - //============================================================================= - - void DrawSlider (int x, int y, double min, double max, double cur, int fracdigits, int indent) - { - char textbuf[16]; - double range; - int maxlen = 0; - int right = x + (12*8 + 4) * CleanXfac_1; - int cy = y + (OptionSettings.mLinespacing-8)*CleanYfac_1; - - range = max - min; - double ccur = clamp(cur, min, max) - min; - - if (fracdigits >= 0) - { - mysnprintf(textbuf, countof(textbuf), "%.*f", fracdigits, max); - maxlen = SmallFont->StringWidth(textbuf) * CleanXfac_1; - } - - mSliderShort = right + maxlen > screen->GetWidth(); - - if (!mSliderShort) - { - M_DrawConText(CR_WHITE, x, cy, "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12"); - M_DrawConText(CR_ORANGE, x + int((5 + ((ccur * 78) / range)) * CleanXfac_1), cy, "\x13"); - } - else - { - // On 320x200 we need a shorter slider - M_DrawConText(CR_WHITE, x, cy, "\x10\x11\x11\x11\x11\x11\x12"); - M_DrawConText(CR_ORANGE, x + int((5 + ((ccur * 38) / range)) * CleanXfac_1), cy, "\x13"); - right -= 5*8*CleanXfac_1; - } - - if (fracdigits >= 0 && right + maxlen <= screen->GetWidth()) - { - mysnprintf(textbuf, countof(textbuf), "%.*f", fracdigits, cur); - screen->DrawText(SmallFont, CR_DARKGRAY, right, y, textbuf, DTA_CleanNoMove_1, true, TAG_DONE); - } - } - - - //============================================================================= - int Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected) - { - drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor); - mDrawX = indent + CURSORSPACE; - DrawSlider (mDrawX, y, mMin, mMax, GetSliderValue(), mShowValue, indent); - return indent; - } - - //============================================================================= - bool MenuEvent (int mkey, bool fromcontroller) - { - double value = GetSliderValue(); - - if (mkey == MKEY_Left) - { - value -= mStep; - } - else if (mkey == MKEY_Right) - { - value += mStep; - } - else - { - return DOptionMenuItem::MenuEvent(mkey, fromcontroller); - } - if (fabs(value) < FLT_EPSILON) value = 0; - SetSliderValue(clamp(value, mMin, mMax)); - S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE); - return true; - } - - bool MouseEvent(int type, int x, int y) - { - DOptionMenu *lm = static_cast(DMenu::CurrentMenu); - if (type != DMenu::MOUSE_Click) - { - if (!lm->CheckFocus(this)) return false; - } - if (type == DMenu::MOUSE_Release) - { - lm->ReleaseFocus(); - } - - int slide_left = mDrawX+8*CleanXfac_1; - int slide_right = slide_left + (10*8*CleanXfac_1 >> mSliderShort); // 12 char cells with 8 pixels each. - - if (type == DMenu::MOUSE_Click) - { - if (x < slide_left || x >= slide_right) return true; - } - - x = clamp(x, slide_left, slide_right); - double v = mMin + ((x - slide_left) * (mMax - mMin)) / (slide_right - slide_left); - if (v != GetSliderValue()) - { - SetSliderValue(v); - //S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE); - } - if (type == DMenu::MOUSE_Click) - { - lm->SetFocus(this); - } - return true; - } - -}; - -#ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuSliderBase_, true, false) -#endif - -//============================================================================= -// -// -// -//============================================================================= - -class DOptionMenuSliderCVar_ : public DOptionMenuSliderBase_ -{ - DECLARE_CLASS(DOptionMenuSliderCVar_, DOptionMenuSliderBase_) - FBaseCVar *mCVar; - - DOptionMenuSliderCVar_() {} -public: - DOptionMenuSliderCVar_(const char *label, const char *menu, double min, double max, double step, int showval) - : DOptionMenuSliderBase_(label, min, max, step, showval) - { - mCVar = FindCVar(menu, NULL); - } - - double GetSliderValue() - { - if (mCVar != NULL) - { - return mCVar->GetGenericRep(CVAR_Float).Float; - } - else - { - return 0; - } - } - - void SetSliderValue(double val) - { - if (mCVar != NULL) - { - UCVarValue value; - value.Float = (float)val; - mCVar->SetGenericRep(value, CVAR_Float); - } - } -}; - -#ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuSliderCVar_, false, false) -#endif - -//============================================================================= -// -// -// -//============================================================================= - -class DOptionMenuSliderVar_ : public DOptionMenuSliderBase_ -{ - DECLARE_CLASS(DOptionMenuSliderVar_, DOptionMenuSliderBase_) - float *mPVal; - - DOptionMenuSliderVar_() {} -public: - - DOptionMenuSliderVar_(const char *label, float *pVal, double min, double max, double step, int showval) - : DOptionMenuSliderBase_(label, min, max, step, showval) - { - mPVal = pVal; - } - - double GetSliderValue() - { - return *mPVal; - } - - void SetSliderValue(double val) - { - *mPVal = (float)val; - } -}; - -#ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuSliderVar_, false, false) -#endif - -//============================================================================= -// -// // Edit a key binding, Action is the CCMD to bind -// -//============================================================================= - -class DOptionMenuItemColorPicker_ : public DOptionMenuItem -{ - DECLARE_CLASS(DOptionMenuItemColorPicker_, DOptionMenuItem) - FColorCVar *mCVar; - - DOptionMenuItemColorPicker_() {} -public: - - enum - { - CPF_RESET = 0x20001, - }; - - DOptionMenuItemColorPicker_(const char *label, const char *menu) - : DOptionMenuItem(label, menu) - { - FBaseCVar *cv = FindCVar(menu, NULL); - if (cv != NULL && cv->GetRealType() == CVAR_Color) - { - mCVar = (FColorCVar*)cv; - } - else mCVar = NULL; - } - - //============================================================================= - int Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected) - { - drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor); - - if (mCVar != NULL) - { - int box_x = indent + CURSORSPACE; - int box_y = y + CleanYfac_1; - screen->Clear (box_x, box_y, box_x + 32*CleanXfac_1, box_y + OptionSettings.mLinespacing*CleanYfac_1, - -1, (uint32)*mCVar | 0xff000000); - } - return indent; - } - - bool SetValue(int i, int v) - { - if (i == CPF_RESET && mCVar != NULL) - { - mCVar->ResetToDefault(); - return true; - } - return false; - } - - bool Activate() - { - if (mCVar != NULL) - { - S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE); - DMenu *picker = StartPickerMenu(DMenu::CurrentMenu, mLabel, mCVar); - if (picker != NULL) - { - M_ActivateMenu(picker); - return true; - } - } - return false; - } -}; - -#ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuItemColorPicker_, false, false) -#endif - -class DOptionMenuScreenResolutionLine_ : public DOptionMenuItem -{ - DECLARE_CLASS(DOptionMenuScreenResolutionLine_, DOptionMenuItem) - - FString mResTexts[3]; - int mSelection; - int mHighlight; - int mMaxValid; - - DOptionMenuScreenResolutionLine_() {} -public: - - enum - { - SRL_INDEX = 0x30000, - SRL_SELECTION = 0x30003, - SRL_HIGHLIGHT = 0x30004, - }; - - DOptionMenuScreenResolutionLine_(const char *action) - : DOptionMenuItem("", action) - { - mSelection = 0; - mHighlight = -1; - } - - bool SetValue(int i, int v) - { - if (i == SRL_SELECTION) - { - mSelection = v; - return true; - } - else if (i == SRL_HIGHLIGHT) - { - mHighlight = v; - return true; - } - return false; - } - - bool GetValue(int i, int *v) - { - if (i == SRL_SELECTION) - { - *v = mSelection; - return true; - } - return false; - } - - bool SetString(int i, const char *newtext) - { - if (i >= SRL_INDEX && i <= SRL_INDEX+2) - { - mResTexts[i-SRL_INDEX] = newtext; - if (mResTexts[0].IsEmpty()) mMaxValid = -1; - else if (mResTexts[1].IsEmpty()) mMaxValid = 0; - else if (mResTexts[2].IsEmpty()) mMaxValid = 1; - else mMaxValid = 2; - return true; - } - return false; - } - - bool GetString(int i, char *s, int len) - { - if (i >= SRL_INDEX && i <= SRL_INDEX+2) - { - strncpy(s, mResTexts[i-SRL_INDEX], len-1); - s[len-1] = 0; - return true; - } - return false; - } - - bool MenuEvent (int mkey, bool fromcontroller) - { - if (mkey == MKEY_Left) - { - if (--mSelection < 0) mSelection = mMaxValid; - S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE); - return true; - } - else if (mkey == MKEY_Right) - { - if (++mSelection > mMaxValid) mSelection = 0; - S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE); - return true; - } - else - { - return DOptionMenuItem::MenuEvent(mkey, fromcontroller); - } - return false; - } - - bool MouseEvent(int type, int x, int y) - { - int colwidth = screen->GetWidth() / 3; - mSelection = x / colwidth; - return DOptionMenuItem::MouseEvent(type, x, y); - } - - bool Activate() - { - S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE); - M_SetVideoMode(); - return true; - } - - int Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected) - { - int colwidth = screen->GetWidth() / 3; - EColorRange color; - - for (int x = 0; x < 3; x++) - { - if (selected && mSelection == x) - color = OptionSettings.mFontColorSelection; - else if (x == mHighlight) - color = OptionSettings.mFontColorHighlight; - else - color = OptionSettings.mFontColorValue; - - screen->DrawText (SmallFont, color, colwidth * x + 20 * CleanXfac_1, y, mResTexts[x], DTA_CleanNoMove_1, true, TAG_DONE); - } - return colwidth * mSelection + 20 * CleanXfac_1 - CURSORSPACE; - } - - bool Selectable() - { - return mMaxValid >= 0; - } - - void Ticker() - { - if (Selectable() && mSelection > mMaxValid) - { - mSelection = mMaxValid; - } - } -}; - -#ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuScreenResolutionLine_, false, false) -#endif - -//============================================================================= -// -// [TP] DOptionMenuFieldBase_ -// -// Base class for input fields -// -//============================================================================= - -class DOptionMenuFieldBase_ : public DOptionMenuItem -{ - DECLARE_ABSTRACT_CLASS(DOptionMenuFieldBase_, DOptionMenuItem) - -protected: - DOptionMenuFieldBase_() {} -public: - DOptionMenuFieldBase_ ( const char* label, const char* menu, const char* graycheck ) : - DOptionMenuItem ( label, menu ), - mCVar ( FindCVar( mAction, NULL )), - mGrayCheck (( graycheck && strlen( graycheck )) ? FindCVar( graycheck, NULL ) : NULL ) {} - - const char* GetCVarString() - { - if ( mCVar == NULL ) - return ""; - - return mCVar->GetHumanString(); - } - - virtual FString Represent() - { - return GetCVarString(); - } - - int Draw ( DOptionMenuDescriptor*, int y, int indent, bool selected ) - { - bool grayed = mGrayCheck != NULL && !( mGrayCheck->GetGenericRep( CVAR_Bool ).Bool ); - drawLabel( indent, y, selected ? OptionSettings.mFontColorSelection : OptionSettings.mFontColor, grayed ); - int overlay = grayed? MAKEARGB( 96, 48, 0, 0 ) : 0; - - screen->DrawText( SmallFont, OptionSettings.mFontColorValue, indent + CURSORSPACE, y, - Represent().GetChars(), DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay, TAG_DONE ); - return indent; - } - - bool GetString ( int i, char* s, int len ) - { - if ( i == 0 ) - { - strncpy( s, GetCVarString(), len ); - s[len - 1] = '\0'; - return true; - } - - return false; - } - - bool SetString ( int i, const char* s ) - { - if ( i == 0 ) - { - if ( mCVar ) - { - UCVarValue vval; - vval.String = s; - mCVar->SetGenericRep( vval, CVAR_String ); - } - - return true; - } - - return false; - } - -protected: - // Action is a CVar in this class and derivatives. - FBaseCVar* mCVar; - FBaseCVar* mGrayCheck; -}; - -#ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuFieldBase_, true, false) -#endif - -//============================================================================= -// -// [TP] DOptionMenuTextField_ -// -// A text input field widget, for use with string CVars. -// -//============================================================================= - -class DOptionMenuTextField_ : public DOptionMenuFieldBase_ -{ - DECLARE_CLASS(DOptionMenuTextField_, DOptionMenuFieldBase_) - - DOptionMenuTextField_() {} -public: - DOptionMenuTextField_ ( const char *label, const char* menu, const char* graycheck ) : - DOptionMenuFieldBase_ ( label, menu, graycheck ), - mEntering ( false ) {} - - FString Represent() - { - FString text = mEntering ? mEditName : GetCVarString(); - - if ( mEntering ) - text += ( gameinfo.gametype & GAME_DoomStrifeChex ) ? '_' : '['; - - return text; - } - - int Draw(DOptionMenuDescriptor*desc, int y, int indent, bool selected) - { - if (mEntering) - { - // reposition the text so that the cursor is visible when in entering mode. - FString text = Represent(); - int tlen = SmallFont->StringWidth(text) * CleanXfac_1; - int newindent = screen->GetWidth() - tlen - CURSORSPACE; - if (newindent < indent) indent = newindent; - } - return DOptionMenuFieldBase_::Draw(desc, y, indent, selected); - } - - bool MenuEvent ( int mkey, bool fromcontroller ) - { - if ( mkey == MKEY_Enter ) - { - S_Sound( CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE ); - strcpy( mEditName, GetCVarString() ); - mEntering = true; - DMenu* input = new DTextEnterMenu ( DMenu::CurrentMenu, mEditName, sizeof mEditName, 2, fromcontroller ); - M_ActivateMenu( input ); - return true; - } - else if ( mkey == MKEY_Input ) - { - if ( mCVar ) - { - UCVarValue vval; - vval.String = mEditName; - mCVar->SetGenericRep( vval, CVAR_String ); - } - - mEntering = false; - return true; - } - else if ( mkey == MKEY_Abort ) - { - mEntering = false; - return true; - } - - return DOptionMenuItem::MenuEvent( mkey, fromcontroller ); - } - -private: - bool mEntering; - char mEditName[128]; -}; - -#ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuTextField_, false, false) -#endif - -//============================================================================= -// -// [TP] FOptionMenuNumberField -// -// A numeric input field widget, for use with number CVars where sliders are inappropriate (i.e. -// where the user is interested in the exact value specifically) -// -//============================================================================= - -class DOptionMenuNumberField_ : public DOptionMenuFieldBase_ -{ - DECLARE_CLASS(DOptionMenuNumberField_, DOptionMenuFieldBase_) - - DOptionMenuNumberField_() {} -public: - DOptionMenuNumberField_ ( const char *label, const char* menu, float minimum, float maximum, - float step, const char* graycheck ) - : DOptionMenuFieldBase_ ( label, menu, graycheck ), - mMinimum ( minimum ), - mMaximum ( maximum ), - mStep ( step ) - { - if ( mMaximum <= mMinimum ) - swapvalues( mMinimum, mMaximum ); - - if ( mStep <= 0 ) - mStep = 1; - } - - bool MenuEvent ( int mkey, bool fromcontroller ) - { - if ( mCVar ) - { - float value = mCVar->GetGenericRep( CVAR_Float ).Float; - - if ( mkey == MKEY_Left ) - { - value -= mStep; - - if ( value < mMinimum ) - value = mMaximum; - } - else if ( mkey == MKEY_Right || mkey == MKEY_Enter ) - { - value += mStep; - - if ( value > mMaximum ) - value = mMinimum; - } - else - return DOptionMenuItem::MenuEvent( mkey, fromcontroller ); - - UCVarValue vval; - vval.Float = value; - mCVar->SetGenericRep( vval, CVAR_Float ); - S_Sound( CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE ); - } - - return true; - } - -private: - float mMinimum; - float mMaximum; - float mStep; -}; - -#ifndef NO_IMP -IMPLEMENT_CLASS(DOptionMenuNumberField_, false, false) -#endif diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp index 882e8b593..0ecb23b87 100644 --- a/src/menu/videomenu.cpp +++ b/src/menu/videomenu.cpp @@ -101,19 +101,21 @@ CUSTOM_CVAR (Int, menu_screenratios, -1, CVAR_ARCHIVE) CUSTOM_CVAR (Bool, vid_tft, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) { + const int OptionMenuItemOptionBase_OP_VALUES = 0x11001; + DOptionMenuDescriptor *opt = GetVideoModeMenu(); if (opt != NULL) { - DOptionMenuItem *it = opt->GetItem("menu_screenratios"); + DMenuItemBase *it = opt->GetItem("menu_screenratios"); if (it != NULL) { if (self) { - it->SetString(DOptionMenuItemOptionBase_::OP_VALUES, "RatiosTFT"); + it->SetString(OptionMenuItemOptionBase_OP_VALUES, "RatiosTFT"); } else { - it->SetString(DOptionMenuItemOptionBase_::OP_VALUES, "Ratios"); + it->SetString(OptionMenuItemOptionBase_OP_VALUES, "Ratios"); } } } @@ -131,6 +133,15 @@ CUSTOM_CVAR (Bool, vid_tft, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // //============================================================================= +struct OptionMenuItemScreenResolution // temporary workaround +{ + enum EValues + { + SRL_INDEX = 0x30000, + SRL_SELECTION = 0x30003, + SRL_HIGHLIGHT = 0x30004, + }; +}; class DVideoModeMenu : public DOptionMenu { DECLARE_CLASS(DVideoModeMenu, DOptionMenu) @@ -148,9 +159,9 @@ public: mDesc->mSelectedItem < (int)mDesc->mItems.Size()) { int sel; - bool selected = mDesc->mItems[mDesc->mSelectedItem]->GetValue(DOptionMenuScreenResolutionLine_::SRL_SELECTION, &sel); + bool selected = mDesc->mItems[mDesc->mSelectedItem]->GetValue(OptionMenuItemScreenResolution::SRL_SELECTION, &sel); bool res = Super::MenuEvent(mkey, fromcontroller); - if (selected) mDesc->mItems[mDesc->mSelectedItem]->SetValue(DOptionMenuScreenResolutionLine_::SRL_SELECTION, sel); + if (selected) mDesc->mItems[mDesc->mSelectedItem]->SetValue(OptionMenuItemScreenResolution::SRL_SELECTION, sel); return res; } return Super::MenuEvent(mkey, fromcontroller); @@ -236,10 +247,10 @@ static void BuildModesList (int hiwidth, int hiheight, int hi_bits) { for (i = NAME_res_0; i<= NAME_res_9; i++) { - DOptionMenuItem *it = opt->GetItem((ENamedName)i); + DMenuItemBase *it = opt->GetItem((ENamedName)i); if (it != NULL) { - it->SetValue(DOptionMenuScreenResolutionLine_::SRL_HIGHLIGHT, -1); + it->SetValue(OptionMenuItemScreenResolution::SRL_HIGHLIGHT, -1); for (c = 0; c < 3; c++) { bool haveMode = false; @@ -260,16 +271,16 @@ static void BuildModesList (int hiwidth, int hiheight, int hi_bits) { if (width == hiwidth && height == hiheight) { - it->SetValue(DOptionMenuScreenResolutionLine_::SRL_SELECTION, c); - it->SetValue(DOptionMenuScreenResolutionLine_::SRL_HIGHLIGHT, c); + it->SetValue(OptionMenuItemScreenResolution::SRL_SELECTION, c); + it->SetValue(OptionMenuItemScreenResolution::SRL_HIGHLIGHT, c); } mysnprintf (strtemp, countof(strtemp), "%dx%d%s", width, height, letterbox?TEXTCOLOR_BROWN" LB":""); - it->SetString(DOptionMenuScreenResolutionLine_::SRL_INDEX+c, strtemp); + it->SetString(OptionMenuItemScreenResolution::SRL_INDEX+c, strtemp); } else { - it->SetString(DOptionMenuScreenResolutionLine_::SRL_INDEX+c, ""); + it->SetString(OptionMenuItemScreenResolution::SRL_INDEX+c, ""); } } } @@ -359,12 +370,12 @@ static bool GetSelectedSize (int *width, int *height) { int line = opt->mSelectedItem; int hsel; - DOptionMenuItem *it = opt->mItems[line]; - if (it->GetValue(DOptionMenuScreenResolutionLine_::SRL_SELECTION, &hsel)) + DMenuItemBase *it = opt->mItems[line]; + if (it->GetValue(OptionMenuItemScreenResolution::SRL_SELECTION, &hsel)) { char buffer[32]; char *breakpt; - if (it->GetString(DOptionMenuScreenResolutionLine_::SRL_INDEX+hsel, buffer, sizeof(buffer))) + if (it->GetString(OptionMenuItemScreenResolution::SRL_INDEX+hsel, buffer, sizeof(buffer))) { *width = (int)strtoll (buffer, &breakpt, 10); *height = (int)strtoll (breakpt+1, NULL, 10); @@ -428,7 +439,7 @@ static void SetModesMenu (int w, int h, int bits) DOptionMenuDescriptor *opt = GetVideoModeMenu(); if (opt != NULL) { - DOptionMenuItem *it; + DMenuItemBase *it; if (testingmode <= 1) { it = opt->GetItem(NAME_VMEnterText); diff --git a/wadsrc/static/zscript/menu/joystickmenu.txt b/wadsrc/static/zscript/menu/joystickmenu.txt index 57f5226e7..2e37aadf6 100644 --- a/wadsrc/static/zscript/menu/joystickmenu.txt +++ b/wadsrc/static/zscript/menu/joystickmenu.txt @@ -129,7 +129,7 @@ class OptionMenuItemJoyMap : OptionMenuItemOptionBase { int mAxis; - void Init(String label, int axis, String values, int center) + void Init(String label, int axis, Name values, int center) { Super.Init(label, 'none', values, null, center); mAxis = axis; diff --git a/wadsrc/static/zscript/menu/menuitembase.txt b/wadsrc/static/zscript/menu/menuitembase.txt index 2840b41b9..6123cabd8 100644 --- a/wadsrc/static/zscript/menu/menuitembase.txt +++ b/wadsrc/static/zscript/menu/menuitembase.txt @@ -38,5 +38,8 @@ native virtual bool MenuEvent (int mkey, bool fromcontroller);// { return false; virtual int GetY() { return mYpos; } virtual int GetX() { return mXpos; } virtual void SetX(int x) { mXpos = x; } + virtual int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) { return indent; } + + } diff --git a/wadsrc/static/zscript/menu/optionmenuitems.txt b/wadsrc/static/zscript/menu/optionmenuitems.txt index 85687d715..c3e6e0bd1 100644 --- a/wadsrc/static/zscript/menu/optionmenuitems.txt +++ b/wadsrc/static/zscript/menu/optionmenuitems.txt @@ -57,11 +57,6 @@ class OptionMenuItem : MenuItemBase native screen.DrawText (SmallFont, color, x, y, label, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay); } - virtual int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) - { - return indent; - } - int CursorSpace() { return (14 * CleanXfac_1); @@ -195,7 +190,7 @@ class OptionMenuItemOptionBase : OptionMenuItem const OP_VALUES = 0x11001; - void Init(String label, Name command, Name values, CVar graycheck, int center) + protected void Init(String label, Name command, Name values, CVar graycheck, int center) { Super.Init(label, command); mValues = values; @@ -295,7 +290,7 @@ class OptionMenuItemOption : OptionMenuItemOptionBase { CVar mCVar; - void Init(String label, Name command, String values, CVar graycheck, int center) + void Init(String label, Name command, Name values, CVar graycheck = null, int center = 0) { Super.Init(label, command, values, graycheck, center); mCVar = CVar.FindCVar(mAction); @@ -590,7 +585,7 @@ class OptionMenuSliderBase : OptionMenuItem int mDrawX; int mSliderShort; - void Init(String label, double min, double max, double step, int showval) + protected void Init(String label, double min, double max, double step, int showval) { Super.Init(label, 'None'); mMin = min; @@ -731,11 +726,11 @@ class OptionMenuSliderBase : OptionMenuItem // //============================================================================= -class OptionMenuSliderCVar : OptionMenuSliderBase +class OptionMenuItemSlider : OptionMenuSliderBase { CVar mCVar; - void Init(String label, Name command, double min, double max, double step, int showval) + void Init(String label, Name command, double min, double max, double step, int showval = 1) { Super.Init(label, min, max, step, showval); mCVar =CVar.FindCVar(command); @@ -825,7 +820,7 @@ class OptionMenuItemColorPicker : OptionMenuItem } -class OptionMenuScreenResolutionLine : OptionMenuItem +class OptionMenuItemScreenResolution : OptionMenuItem { String mResTexts[3]; int mSelection; @@ -1033,7 +1028,7 @@ class OptionMenuFieldBase : OptionMenuItem // //============================================================================= -class OptionMenuTextField : OptionMenuFieldBase +class OptionMenuItemTextField : OptionMenuFieldBase { void Init (String label, Name command, CVar graycheck = null) { @@ -1102,9 +1097,9 @@ class OptionMenuTextField : OptionMenuFieldBase // //============================================================================= -class OptionMenuNumberField : OptionMenuFieldBase +class OptionMenuItemNumberField : OptionMenuFieldBase { - void Init (String label, Name command, float minimum, float maximum, float step, CVar graycheck = null) + void Init (String label, Name command, float minimum = 0, float maximum = 100, float step = 1, CVar graycheck = null) { Super.Init(label, command, graycheck); mMinimum = min(minimum, maximum); From ee1217c8c751605a88eeaaf78fb7256f574d749c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Feb 2017 01:18:49 +0100 Subject: [PATCH 05/19] - everything compiles again, now to make it work again with all menu widgets 100% scripted. --- src/menu/listmenu.cpp | 305 ------------- src/menu/menu.cpp | 385 +++++++++++++++- src/menu/menu.h | 296 +----------- src/menu/menudef.cpp | 284 +++++------- src/menu/playerdisplay.cpp | 320 ------------- src/menu/playermenu.cpp | 448 +------------------ wadsrc/static/zscript/menu/listmenuitems.txt | 51 ++- wadsrc/static/zscript/menu/menuitembase.txt | 12 +- wadsrc/static/zscript/menu/playerdisplay.txt | 2 +- wadsrc/static/zscript/menu/playermenu.txt | 66 ++- 10 files changed, 640 insertions(+), 1529 deletions(-) diff --git a/src/menu/listmenu.cpp b/src/menu/listmenu.cpp index b039f46e0..adb630375 100644 --- a/src/menu/listmenu.cpp +++ b/src/menu/listmenu.cpp @@ -279,308 +279,3 @@ void DListMenu::Drawer () // //============================================================================= IMPLEMENT_CLASS(DMenuItemBase, true, false) - -bool DMenuItemBase::CheckCoordinate(int x, int y) -{ - return false; -} - -void DMenuItemBase::Ticker() -{ -} - -void DMenuItemBase::Drawer(bool selected) -{ -} - -bool DMenuItemBase::Selectable() -{ - return false; -} - -void DMenuItemBase::DrawSelector(int xofs, int yofs, FTextureID tex) -{ - if (tex.isNull()) - { - if ((DMenu::MenuTime%8) < 6) - { - screen->DrawText(ConFont, OptionSettings.mFontColorSelection, - (mXpos + xofs - 160) * CleanXfac + screen->GetWidth() / 2, - (mYpos + yofs - 100) * CleanYfac + screen->GetHeight() / 2, - "\xd", - DTA_CellX, 8 * CleanXfac, - DTA_CellY, 8 * CleanYfac, - TAG_DONE); - } - } - else - { - screen->DrawTexture (TexMan(tex), mXpos + xofs, mYpos + yofs, DTA_Clean, true, TAG_DONE); - } -} - -bool DMenuItemBase::Activate() -{ - return false; // cannot be activated -} - -FName DMenuItemBase::GetAction(int *pparam) -{ - return mAction; -} - -bool DMenuItemBase::SetString(int i, const char *s) -{ - return false; -} - -bool DMenuItemBase::GetString(int i, char *s, int len) -{ - return false; -} - -bool DMenuItemBase::SetValue(int i, int value) -{ - return false; -} - -bool DMenuItemBase::GetValue(int i, int *pvalue) -{ - return false; -} - -void DMenuItemBase::Enable(bool on) -{ - mEnabled = on; -} - -bool DMenuItemBase::MenuEvent(int mkey, bool fromcontroller) -{ - return false; -} - -DEFINE_ACTION_FUNCTION(DMenuItemBase, MenuEvent) -{ - PARAM_SELF_PROLOGUE(DMenuItemBase); - PARAM_INT(key); - PARAM_BOOL(fromcontroller); - ACTION_RETURN_BOOL(self->MenuEvent(key, fromcontroller)); -} - - -bool DMenuItemBase::MouseEvent(int type, int x, int y) -{ - return false; -} - -bool DMenuItemBase::CheckHotkey(int c) -{ - return false; -} - -int DMenuItemBase::GetWidth() -{ - return 0; -} - - -//============================================================================= -// -// static patch -// -//============================================================================= -IMPLEMENT_CLASS(DListMenuItemStaticPatch_, false, false) - -DListMenuItemStaticPatch_::DListMenuItemStaticPatch_(int x, int y, FTextureID patch, bool centered) -: DMenuItemBase(x, y) -{ - mTexture = patch; - mCentered = centered; -} - -void DListMenuItemStaticPatch_::Drawer(bool selected) -{ - if (!mTexture.Exists()) - { - return; - } - - int x = mXpos; - FTexture *tex = TexMan(mTexture); - if (mYpos >= 0) - { - if (mCentered) x -= tex->GetScaledWidth()/2; - screen->DrawTexture (tex, x, mYpos, DTA_Clean, true, TAG_DONE); - } - else - { - int x = (mXpos - 160) * CleanXfac + (SCREENWIDTH>>1); - if (mCentered) x -= (tex->GetScaledWidth()*CleanXfac)/2; - screen->DrawTexture (tex, x, -mYpos*CleanYfac, DTA_CleanNoMove, true, TAG_DONE); - } -} - -//============================================================================= -// -// static text -// -//============================================================================= -IMPLEMENT_CLASS(DListMenuItemStaticText_, false, false) - -DListMenuItemStaticText_::DListMenuItemStaticText_(int x, int y, const char *text, FFont *font, EColorRange color, bool centered) -: DMenuItemBase(x, y) -{ - mText = text; - mFont = font; - mColor = color; - mCentered = centered; -} - -void DListMenuItemStaticText_::Drawer(bool selected) -{ - if (mText.IsNotEmpty()) - { - const char *text = mText; - if (*text == '$') text = GStrings(text+1); - if (mYpos >= 0) - { - int x = mXpos; - if (mCentered) x -= mFont->StringWidth(text)/2; - screen->DrawText(mFont, mColor, x, mYpos, text, DTA_Clean, true, TAG_DONE); - } - else - { - int x = (mXpos - 160) * CleanXfac + (SCREENWIDTH>>1); - if (mCentered) x -= (mFont->StringWidth(text)*CleanXfac)/2; - screen->DrawText (mFont, mColor, x, -mYpos*CleanYfac, text, DTA_CleanNoMove, true, TAG_DONE); - } - } -} - -//============================================================================= -// -// base class for selectable items -// -//============================================================================= -IMPLEMENT_CLASS(DListMenuItemSelectable_, false, false) - -DListMenuItemSelectable_::DListMenuItemSelectable_(int x, int y, int height, FName action, int param) -: DMenuItemBase(x, y, action) -{ - mHeight = height; - mParam = param; - mHotkey = 0; -} - -bool DListMenuItemSelectable_::CheckCoordinate(int x, int y) -{ - return mEnabled && y >= mYpos && y < mYpos + mHeight; // no x check here -} - -bool DListMenuItemSelectable_::Selectable() -{ - return mEnabled; -} - -bool DListMenuItemSelectable_::Activate() -{ - M_SetMenu(mAction, mParam); - return true; -} - -FName DListMenuItemSelectable_::GetAction(int *pparam) -{ - if (pparam != NULL) *pparam = mParam; - return mAction; -} - -bool DListMenuItemSelectable_::CheckHotkey(int c) -{ - return c == tolower(mHotkey); -} - -bool DListMenuItemSelectable_::MouseEvent(int type, int x, int y) -{ - if (type == DMenu::MOUSE_Release) - { - if (NULL != DMenu::CurrentMenu && DMenu::CurrentMenu->MenuEvent(MKEY_Enter, true)) - { - return true; - } - } - return false; -} - -//============================================================================= -// -// text item -// -//============================================================================= -IMPLEMENT_CLASS(DListMenuItemText_, false, false) - -DListMenuItemText_::DListMenuItemText_(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, EColorRange color2, FName child, int param) -: DListMenuItemSelectable_(x, y, height, child, param) -{ - mText = ncopystring(text); - mFont = font; - mColor = color; - mColorSelected = color2; - mHotkey = hotkey; -} - -void DListMenuItemText_::OnDestroy() -{ - if (mText != NULL) - { - delete [] mText; - } -} - -void DListMenuItemText_::Drawer(bool selected) -{ - const char *text = mText; - if (text != NULL) - { - if (*text == '$') text = GStrings(text+1); - screen->DrawText(mFont, selected ? mColorSelected : mColor, mXpos, mYpos, text, DTA_Clean, true, TAG_DONE); - } -} - -int DListMenuItemText_::GetWidth() -{ - const char *text = mText; - if (text != NULL) - { - if (*text == '$') text = GStrings(text+1); - return mFont->StringWidth(text); - } - return 1; -} - - -//============================================================================= -// -// patch item -// -//============================================================================= -IMPLEMENT_CLASS(DListMenuItemPatch_, false, false) - -DListMenuItemPatch_::DListMenuItemPatch_(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param) -: DListMenuItemSelectable_(x, y, height, child, param) -{ - mHotkey = hotkey; - mTexture = patch; -} - -void DListMenuItemPatch_::Drawer(bool selected) -{ - screen->DrawTexture (TexMan(mTexture), mXpos, mYpos, DTA_Clean, true, TAG_DONE); -} - -int DListMenuItemPatch_::GetWidth() -{ - return mTexture.isValid() - ? TexMan[mTexture]->GetScaledWidth() - : 0; -} - diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 98c2de36d..720a327dd 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -1150,16 +1150,377 @@ DEFINE_FIELD(FOptionMenuSettings, mLinespacing) struct IJoystickConfig; -DMenuItemBase * CreateOptionMenuItemStaticText(const char *name, bool v); -DMenuItemBase * CreateOptionMenuSliderVar(const char *name, int index, double min, double max, double step, int showval); -DMenuItemBase * CreateOptionMenuItemCommand(const char * label, FName cmd); -DMenuItemBase * CreateOptionMenuItemOption(const char * label, FName cmd, FName values, FBaseCVar *graycheck, bool center); -DMenuItemBase * CreateOptionMenuItemJoyConfigMenu(const char *label, IJoystickConfig *joy); -DMenuItemBase * CreateOptionMenuItemJoyMap(const char *label, int axis, FName values, bool center); -DMenuItemBase * CreateOptionMenuSliderJoySensitivity(const char * label, double min, double max, double step, int showval); -DMenuItemBase * CreateOptionMenuSliderJoyScale(const char *label, int axis, double min, double max, double step, int showval); -DMenuItemBase * CreateOptionMenuItemInverter(const char *label, int axis, int center); -DMenuItemBase * CreateOptionMenuSliderJoyDeadZone(const char *label, int axis, double min, double max, double step, int showval); +DMenuItemBase * CreateOptionMenuItemStaticText(const char *name, bool v) +{ + auto c = PClass::FindClass("OptionMenuItemStaticText"); + auto p = c->CreateNew(); + VMValue params[] = { p, FString(name), v }; + auto f = dyn_cast(c->Symbols.FindSymbol("Init", false)); + GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); + return (DMenuItemBase*)p; +} + +DMenuItemBase * CreateOptionMenuSliderVar(const char *name, int index, double min, double max, double step, int showval) +{ + auto c = PClass::FindClass("OptionMenuItemSliderVar"); + auto p = c->CreateNew(); + VMValue params[] = { p, FString(name), index, min, max, step, showval }; + auto f = dyn_cast(c->Symbols.FindSymbol("Init", false)); + GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); + return (DMenuItemBase*)p; +} + +DMenuItemBase * CreateOptionMenuItemCommand(const char * label, FName cmd) +{ + auto c = PClass::FindClass("OptionMenuItemCommand"); + auto p = c->CreateNew(); + VMValue params[] = { p, FString(label), cmd.GetIndex() }; + auto f = dyn_cast(c->Symbols.FindSymbol("Init", false)); + GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); + return (DMenuItemBase*)p; +} + +DMenuItemBase * CreateOptionMenuItemOption(const char * label, FName cmd, FName values, FBaseCVar *graycheck, bool center) +{ + auto c = PClass::FindClass("OptionMenuItemOption"); + auto p = c->CreateNew(); + VMValue params[] = { p, FString(label), cmd.GetIndex(), values.GetIndex(), graycheck, center }; + auto f = dyn_cast(c->Symbols.FindSymbol("Init", false)); + GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); + return (DMenuItemBase*)p; +} + +DMenuItemBase * CreateOptionMenuItemJoyConfigMenu(const char *label, IJoystickConfig *joy) +{ + auto c = PClass::FindClass("OptionMenuItemJoyConfigMenu"); + auto p = c->CreateNew(); + VMValue params[] = { p, FString(label), joy }; + auto f = dyn_cast(c->Symbols.FindSymbol("Init", false)); + GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); + return (DMenuItemBase*)p; +} + +DMenuItemBase * CreateOptionMenuItemJoyMap(const char *label, int axis, FName values, bool center) +{ + auto c = PClass::FindClass("OptionMenuItemJoyMap"); + auto p = c->CreateNew(); + VMValue params[] = { p, FString(label), axis, values.GetIndex(), center }; + auto f = dyn_cast(c->Symbols.FindSymbol("Init", false)); + GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); + return (DMenuItemBase*)p; +} + +DMenuItemBase * CreateOptionMenuSliderJoySensitivity(const char * label, double min, double max, double step, int showval) +{ + auto c = PClass::FindClass("OptionMenuSliderJoySensitivity"); + auto p = c->CreateNew(); + VMValue params[] = { p, FString(label), min, max, step, showval }; + auto f = dyn_cast(c->Symbols.FindSymbol("Init", false)); + GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); + return (DMenuItemBase*)p; +} + +DMenuItemBase * CreateOptionMenuSliderJoyScale(const char *label, int axis, double min, double max, double step, int showval) +{ + auto c = PClass::FindClass("OptionMenuSliderJoyScale"); + auto p = c->CreateNew(); + VMValue params[] = { p, FString(label), min, max, step, showval }; + auto f = dyn_cast(c->Symbols.FindSymbol("Init", false)); + GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); + return (DMenuItemBase*)p; +} + +DMenuItemBase * CreateOptionMenuItemInverter(const char *label, int axis, int center) +{ + auto c = PClass::FindClass("OptionMenuItemInverter"); + auto p = c->CreateNew(); + VMValue params[] = { p, FString(label), axis, center }; + auto f = dyn_cast(c->Symbols.FindSymbol("Init", false)); + GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); + return (DMenuItemBase*)p; +} + +DMenuItemBase * CreateOptionMenuSliderJoyDeadZone(const char *label, int axis, double min, double max, double step, int showval) +{ + auto c = PClass::FindClass("OptionMenuSliderJoyDeadZone"); + auto p = c->CreateNew(); + VMValue params[] = { p, FString(label), min, max, step, showval }; + auto f = dyn_cast(c->Symbols.FindSymbol("Init", false)); + GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); + return (DMenuItemBase*)p; +} + +DMenuItemBase * CreateOptionMenuItemSubmenu(const char *label, FName cmd, int center) +{ + auto c = PClass::FindClass("OptionMenuItemSubmenu"); + auto p = c->CreateNew(); + VMValue params[] = { p, FString(label), cmd.GetIndex(), center }; + auto f = dyn_cast(c->Symbols.FindSymbol("Init", false)); + GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); + return (DMenuItemBase*)p; +} + +DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBindings *bindings) +{ + auto c = PClass::FindClass("OptionMenuItemControl"); + auto p = c->CreateNew(); + VMValue params[] = { p, FString(label), cmd.GetIndex(), bindings }; + auto f = dyn_cast(c->Symbols.FindSymbol("Init", false)); + GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); + return (DMenuItemBase*)p; +} + +DMenuItemBase * CreateListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID tex, FName command, int param) +{ + auto c = PClass::FindClass("ListMenuItemPatch"); + auto p = c->CreateNew(); + VMValue params[] = { p, x, y, height, tex.GetIndex(), hotkey, command.GetIndex(), param }; + auto f = dyn_cast(c->Symbols.FindSymbol("InitDirect", false)); + GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); + return (DMenuItemBase*)p; +} + +DMenuItemBase * CreateListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, PalEntry color1, PalEntry color2, FName command, int param) +{ + auto c = PClass::FindClass("ListMenuItemText"); + auto p = c->CreateNew(); + VMValue params[] = { p, x, y, height, hotkey, text, font, int(color1.d), int(color2.d), command.GetIndex(), param }; + auto f = dyn_cast(c->Symbols.FindSymbol("InitDirect", false)); + GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); + return (DMenuItemBase*)p; +} + +bool DMenuItemBase::CheckCoordinate(int x, int y) +{ + IFVIRTUAL(DMenuItemBase, CheckCoordinate) + { + VMValue params[] = { (DObject*)this, x, y }; + int retval; + VMReturn ret(&retval); + GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr); + return !!retval; + } + return false; +} + +void DMenuItemBase::Ticker() +{ + IFVIRTUAL(DMenuItemBase, Ticker) + { + VMValue params[] = { (DObject*)this }; + GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr); + } +} + +void DMenuItemBase::Drawer(bool selected) +{ + IFVIRTUAL(DMenuItemBase, Ticker) + { + VMValue params[] = { (DObject*)this, selected }; + GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr); + } +} + +bool DMenuItemBase::Selectable() +{ + IFVIRTUAL(DMenuItemBase, Selectable) + { + VMValue params[] = { (DObject*)this }; + int retval; + VMReturn ret(&retval); + GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr); + return !!retval; + } + return false; +} + +bool DMenuItemBase::Activate() +{ + IFVIRTUAL(DMenuItemBase, Activate) + { + VMValue params[] = { (DObject*)this }; + int retval; + VMReturn ret(&retval); + GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr); + return !!retval; + } + return false; +} +FName DMenuItemBase::GetAction(int *pparam) +{ + IFVIRTUAL(DMenuItemBase, GetAction) + { + VMValue params[] = { (DObject*)this }; + int retval[2]; + VMReturn ret[2]; ret[0].IntAt(&retval[0]); ret[1].IntAt(&retval[1]); + GlobalVMStack.Call(func, params, countof(params), ret, 2, nullptr); + return !!retval; + } + return NAME_None; +} + +bool DMenuItemBase::SetString(int i, const char *s) +{ + IFVIRTUAL(DMenuItemBase, SetString) + { + VMValue params[] = { (DObject*)this, i, FString(s) }; + int retval; + VMReturn ret(&retval); + GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr); + return !!retval; + } + return false; +} + +bool DMenuItemBase::GetString(int i, char *s, int len) +{ + IFVIRTUAL(DMenuItemBase, GetString) + { + VMValue params[] = { (DObject*)this, i }; + int retval; + FString retstr; + VMReturn ret[2]; ret[0].IntAt(&retval); ret[1].StringAt(&retstr); + GlobalVMStack.Call(func, params, countof(params), ret, 2, nullptr); + strncpy(s, retstr, len); + return !!retval; + } + return false; +} + + +bool DMenuItemBase::SetValue(int i, int value) +{ + IFVIRTUAL(DMenuItemBase, SetValue) + { + VMValue params[] = { (DObject*)this, i, value }; + int retval; + VMReturn ret(&retval); + GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr); + return !!retval; + } + return false; +} + +bool DMenuItemBase::GetValue(int i, int *pvalue) +{ + IFVIRTUAL(DMenuItemBase, GetValue) + { + VMValue params[] = { (DObject*)this }; + int retval[2]; + VMReturn ret[2]; ret[0].IntAt(&retval[0]); ret[1].IntAt(&retval[1]); + GlobalVMStack.Call(func, params, countof(params), ret, 2, nullptr); + *pvalue = retval[1]; + return !!retval[0]; + } + return false; +} + + +void DMenuItemBase::Enable(bool on) +{ + IFVIRTUAL(DMenuItemBase, Enable) + { + VMValue params[] = { (DObject*)this, on }; + GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr); + } +} + +bool DMenuItemBase::MenuEvent(int mkey, bool fromcontroller) +{ + IFVIRTUAL(DMenuItemBase, MenuEvent) + { + VMValue params[] = { (DObject*)this, mkey, fromcontroller }; + int retval; + VMReturn ret(&retval); + GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr); + return !!retval; + } + return false; +} + +bool DMenuItemBase::MouseEvent(int type, int x, int y) +{ + IFVIRTUAL(DMenuItemBase, MouseEvent) + { + VMValue params[] = { (DObject*)this, x, y }; + int retval; + VMReturn ret(&retval); + GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr); + return !!retval; + } + return false; +} + +bool DMenuItemBase::CheckHotkey(int c) +{ + IFVIRTUAL(DMenuItemBase, CheckHotkey) + { + VMValue params[] = { (DObject*)this, c }; + int retval; + VMReturn ret(&retval); + GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr); + return !!retval; + } + return false; +} + +int DMenuItemBase::GetWidth() +{ + IFVIRTUAL(DMenuItemBase, GetWidth) + { + VMValue params[] = { (DObject*)this }; + int retval; + VMReturn ret(&retval); + GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr); + return retval; + } + return false; +} + +int DMenuItemBase::GetIndent() +{ + IFVIRTUAL(DMenuItemBase, GetIndent) + { + VMValue params[] = { (DObject*)this }; + int retval; + VMReturn ret(&retval); + GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr); + return retval; + } + return false; +} + +int DMenuItemBase::Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected) +{ + IFVIRTUAL(DMenuItemBase, Draw) + { + VMValue params[] = { (DObject*)this, desc, y, indent, selected }; + int retval; + VMReturn ret(&retval); + GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr); + return retval; + } + return false; +} + +void DMenuItemBase::DrawSelector(int xofs, int yofs, FTextureID tex) +{ + if (tex.isNull()) + { + if ((DMenu::MenuTime % 8) < 6) + { + screen->DrawText(ConFont, OptionSettings.mFontColorSelection, + (mXpos + xofs - 160) * CleanXfac + screen->GetWidth() / 2, + (mYpos + yofs - 100) * CleanYfac + screen->GetHeight() / 2, + "\xd", + DTA_CellX, 8 * CleanXfac, + DTA_CellY, 8 * CleanYfac, + TAG_DONE); + } + } + else + { + screen->DrawTexture(TexMan(tex), mXpos + xofs, mYpos + yofs, DTA_Clean, true, TAG_DONE); + } +} -DMenuItemBase * CreateOptionMenuItemSubmenu(const char *label, FName cmd, int center); -DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBindings *bindings); diff --git a/src/menu/menu.h b/src/menu/menu.h index 429a2b4f4..e4d449237 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -302,259 +302,35 @@ class DMenuItemBase : public DObject DECLARE_CLASS(DMenuItemBase, DObject) public: int mXpos, mYpos; - FName mAction; - + FNameNoInit mAction; bool mEnabled; - DMenuItemBase(int xpos = 0, int ypos = 0, FName action = NAME_None) - { - mXpos = xpos; - mYpos = ypos; - mAction = action; - mEnabled = true; - } - - virtual bool CheckCoordinate(int x, int y); - virtual void Ticker(); - virtual void Drawer(bool selected); - virtual bool Selectable(); - virtual bool Activate(); - virtual FName GetAction(int *pparam); - virtual bool SetString(int i, const char *s); - virtual bool GetString(int i, char *s, int len); - virtual bool SetValue(int i, int value); - virtual bool GetValue(int i, int *pvalue); - virtual void Enable(bool on); - virtual bool MenuEvent (int mkey, bool fromcontroller); - virtual bool MouseEvent(int type, int x, int y); - virtual bool CheckHotkey(int c); - virtual int GetWidth(); - virtual int GetIndent() { return 0; } - virtual int Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected) { return indent; } - void DrawSelector(int xofs, int yofs, FTextureID tex); + bool CheckCoordinate(int x, int y); + void Ticker(); + void Drawer(bool selected); + bool Selectable(); + bool Activate(); + FName GetAction(int *pparam); + bool SetString(int i, const char *s); + bool GetString(int i, char *s, int len); + bool SetValue(int i, int value); + bool GetValue(int i, int *pvalue); + void Enable(bool on); + bool MenuEvent (int mkey, bool fromcontroller); + bool MouseEvent(int type, int x, int y); + bool CheckHotkey(int c); + int GetWidth(); + int GetIndent(); + int Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected); void OffsetPositionY(int ydelta) { mYpos += ydelta; } int GetY() { return mYpos; } int GetX() { return mXpos; } void SetX(int x) { mXpos = x; } + void DrawSelector(int xofs, int yofs, FTextureID tex); + }; -class DListMenuItemStaticPatch_ : public DMenuItemBase -{ - DECLARE_CLASS(DListMenuItemStaticPatch_, DMenuItemBase) -protected: - FTextureID mTexture; - bool mCentered; - - DListMenuItemStaticPatch_() {} -public: - DListMenuItemStaticPatch_(int x, int y, FTextureID patch, bool centered); - void Drawer(bool selected); -}; - -class DListMenuItemStaticText_ : public DMenuItemBase -{ - DECLARE_CLASS(DListMenuItemStaticText_, DMenuItemBase) -protected: - FString mText; - FFont *mFont; - EColorRange mColor; - bool mCentered; - - DListMenuItemStaticText_() {} -public: - DListMenuItemStaticText_(int x, int y, const char *text, FFont *font, EColorRange color, bool centered); - void Drawer(bool selected); -}; - -//============================================================================= -// -// the player sprite window -// -//============================================================================= - -class DListMenuItemPlayerDisplay_ : public DMenuItemBase -{ - DECLARE_CLASS(DListMenuItemPlayerDisplay_, DMenuItemBase) - - DListMenuDescriptor *mOwner; - FTexture *mBackdrop; - FRemapTable mRemap; - FPlayerClass *mPlayerClass; - FState *mPlayerState; - int mPlayerTics; - bool mNoportrait; - BYTE mRotation; - BYTE mMode; // 0: automatic (used by class selection), 1: manual (used by player setup) - BYTE mTranslate; - int mSkin; - int mRandomClass; - int mRandomTimer; - int mClassNum; - - void SetPlayerClass(int classnum, bool force = false); - bool UpdatePlayerClass(); - void UpdateRandomClass(); - void UpdateTranslation(); - - DListMenuItemPlayerDisplay_() {} -public: - - enum - { - PDF_ROTATION = 0x10001, - PDF_SKIN = 0x10002, - PDF_CLASS = 0x10003, - PDF_MODE = 0x10004, - PDF_TRANSLATE = 0x10005, - }; - - DListMenuItemPlayerDisplay_(DListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action); - void OnDestroy() override; - virtual void Ticker(); - virtual void Drawer(bool selected); - bool SetValue(int i, int value); -}; - - -//============================================================================= -// -// selectable items -// -//============================================================================= - -class DListMenuItemSelectable_ : public DMenuItemBase -{ - DECLARE_CLASS(DListMenuItemSelectable_, DMenuItemBase) -protected: - int mHotkey; - int mHeight; - int mParam; - - DListMenuItemSelectable_() {} -public: - DListMenuItemSelectable_(int x, int y, int height, FName childmenu, int mParam = -1); - bool CheckCoordinate(int x, int y); - bool Selectable(); - bool CheckHotkey(int c); - bool Activate(); - bool MouseEvent(int type, int x, int y); - FName GetAction(int *pparam); -}; - -class DListMenuItemText_ : public DListMenuItemSelectable_ -{ - DECLARE_CLASS(DListMenuItemText_, DListMenuItemSelectable_) - const char *mText; - FFont *mFont; - EColorRange mColor; - EColorRange mColorSelected; - - DListMenuItemText_() {} -public: - DListMenuItemText_(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, EColorRange color2, FName child, int param = 0); - void OnDestroy() override; - void Drawer(bool selected); - int GetWidth(); -}; - -class DListMenuItemPatch_ : public DListMenuItemSelectable_ -{ - DECLARE_CLASS(DListMenuItemPatch_, DListMenuItemSelectable_) - FTextureID mTexture; - - DListMenuItemPatch_() {} -public: - DListMenuItemPatch_(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param = 0); - void Drawer(bool selected); - int GetWidth(); -}; - -//============================================================================= -// -// items for the player menu -// -//============================================================================= - -class DPlayerNameBox_ : public DListMenuItemSelectable_ -{ - DECLARE_CLASS(DPlayerNameBox_, DListMenuItemSelectable_) - FString mText; - FFont *mFont; - EColorRange mFontColor; - int mFrameSize; - char mPlayerName[MAXPLAYERNAME+1]; - char mEditName[MAXPLAYERNAME+2]; - bool mEntering; - - void DrawBorder (int x, int y, int len); - - DPlayerNameBox_() {} -public: - - DPlayerNameBox_(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action); - bool SetString(int i, const char *s); - bool GetString(int i, char *s, int len); - void Drawer(bool selected); - bool MenuEvent (int mkey, bool fromcontroller); -}; - -//============================================================================= -// -// items for the player menu -// -//============================================================================= - -class DValueTextItem_ : public DListMenuItemSelectable_ -{ - DECLARE_CLASS(DValueTextItem_, DListMenuItemSelectable_) - TArray mSelections; - FString mText; - int mSelection; - FFont *mFont; - EColorRange mFontColor; - EColorRange mFontColor2; - - DValueTextItem_() {} -public: - - DValueTextItem_(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values); - bool SetString(int i, const char *s); - bool SetValue(int i, int value); - bool GetValue(int i, int *pvalue); - bool MenuEvent (int mkey, bool fromcontroller); - void Drawer(bool selected); -}; - -//============================================================================= -// -// items for the player menu -// -//============================================================================= - -class DSliderItem_ : public DListMenuItemSelectable_ -{ - DECLARE_CLASS(DSliderItem_, DListMenuItemSelectable_) - FString mText; - FFont *mFont; - EColorRange mFontColor; - int mMinrange, mMaxrange; - int mStep; - int mSelection; - - void DrawSlider (int x, int y); - - DSliderItem_() {} -public: - - DSliderItem_(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step); - bool SetValue(int i, int value); - bool GetValue(int i, int *pvalue); - bool MenuEvent (int mkey, bool fromcontroller); - void Drawer(bool selected); - bool MouseEvent(int type, int x, int y); -}; - //============================================================================= // // list menu class runs a menu described by a DListMenuDescriptor @@ -594,36 +370,6 @@ public: }; -//============================================================================= -// -// base class for menu items -// -//============================================================================= - -/* -class DMenuItemBase : public DMenuItemBase -{ - DECLARE_ABSTRACT_CLASS(DMenuItemBase, DMenuItemBase) -public: - FString mLabel; - bool mCentered; - - void drawLabel(int indent, int y, EColorRange color, bool grayed = false); - - DMenuItemBase(const char *text = nullptr, FName action = NAME_None, bool center = false) - : DMenuItemBase(0, 0, action) - { - mLabel = text; - mCentered = center; - } - - virtual int Draw(DOptionMenuDescriptor *desc, int y, int indent, bool selected); - virtual bool Selectable(); - virtual int GetIndent(); - virtual bool MouseEvent(int type, int x, int y); -}; -*/ - //============================================================================= // // @@ -762,5 +508,7 @@ DMenuItemBase * CreateOptionMenuSliderJoySensitivity(const char * label, double DMenuItemBase * CreateOptionMenuSliderJoyScale(const char *label, int axis, double min, double max, double step, int showval); DMenuItemBase * CreateOptionMenuItemInverter(const char *label, int axis, int center); DMenuItemBase * CreateOptionMenuSliderJoyDeadZone(const char *label, int axis, double min, double max, double step, int showval); +DMenuItemBase * CreateListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID tex, FName command, int param); +DMenuItemBase * CreateListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, PalEntry color1, PalEntry color2, FName command, int param); #endif diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 51f2e4788..fe0314c1b 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -336,87 +336,6 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) sc.MustGetNumber(); desc->mWRight = sc.Number; } - else if (sc.Compare("StaticPatch") || sc.Compare("StaticPatchCentered")) - { - bool centered = sc.Compare("StaticPatchCentered"); - sc.MustGetNumber(); - int x = sc.Number; - sc.MustGetStringName(","); - sc.MustGetNumber(); - int y = sc.Number; - sc.MustGetStringName(","); - sc.MustGetString(); - FTextureID tex = GetMenuTexture(sc.String); - - DMenuItemBase *it = new DListMenuItemStaticPatch_(x, y, tex, centered); - desc->mItems.Push(it); - } - else if (sc.Compare("StaticText") || sc.Compare("StaticTextCentered")) - { - bool centered = sc.Compare("StaticTextCentered"); - sc.MustGetNumber(); - int x = sc.Number; - sc.MustGetStringName(","); - sc.MustGetNumber(); - int y = sc.Number; - sc.MustGetStringName(","); - sc.MustGetString(); - FString label = sc.String; - EColorRange cr = desc->mFontColor; - if (sc.CheckString(",")) - { - sc.MustGetString(); - cr = V_FindFontColor(sc.String); - if (cr == CR_UNTRANSLATED && !sc.Compare("untranslated")) cr = desc->mFontColor; - } - DMenuItemBase *it = new DListMenuItemStaticText_(x, y, label, desc->mFont, cr, centered); - desc->mItems.Push(it); - } - else if (sc.Compare("PatchItem")) - { - sc.MustGetString(); - FTextureID tex = GetMenuTexture(sc.String); - sc.MustGetStringName(","); - sc.MustGetString(); - int hotkey = sc.String[0]; - sc.MustGetStringName(","); - sc.MustGetString(); - FName action = sc.String; - int param = 0; - if (sc.CheckString(",")) - { - sc.MustGetNumber(); - param = sc.Number; - } - - DMenuItemBase *it = new DListMenuItemPatch_(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, tex, action, param); - desc->mItems.Push(it); - desc->mYpos += desc->mLinespacing; - if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; - } - else if (sc.Compare("TextItem")) - { - sc.MustGetString(); - FString text = sc.String; - sc.MustGetStringName(","); - sc.MustGetString(); - int hotkey = sc.String[0]; - sc.MustGetStringName(","); - sc.MustGetString(); - FName action = sc.String; - int param = 0; - if (sc.CheckString(",")) - { - sc.MustGetNumber(); - param = sc.Number; - } - - DMenuItemBase *it = new DListMenuItemText_(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, param); - desc->mItems.Push(it); - desc->mYpos += desc->mLinespacing; - if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; - - } else if (sc.Compare("Font")) { sc.MustGetString(); @@ -443,88 +362,124 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) sc.MustGetString(); desc->mNetgameMessage = sc.String; } - else if (sc.Compare("PlayerDisplay")) + else { - bool noportrait = false; - FName action = NAME_None; - sc.MustGetNumber(); - int x = sc.Number; - sc.MustGetStringName(","); - sc.MustGetNumber(); - int y = sc.Number; - sc.MustGetStringName(","); - sc.MustGetString(); - PalEntry c1 = V_GetColor(nullptr, sc); - sc.MustGetStringName(","); - sc.MustGetString(); - PalEntry c2 = V_GetColor(nullptr, sc); - if (sc.CheckString(",")) + bool success = false; + FStringf buildname("ListMenuItem%s", sc.String); + PClass *cls = PClass::FindClass(buildname); + if (cls != nullptr && cls->IsDescendantOf("ListMenuItem")) { - sc.MustGetNumber(); - noportrait = !!sc.Number; - if (sc.CheckString(",")) + auto func = dyn_cast(cls->Symbols.FindSymbol("Init", false)); + if (func != nullptr && !(func->Variants[0].Flags & (VARF_Protected | VARF_Private))) // skip internal classes which have a protexted init method. { - sc.MustGetString(); - action = sc.String; + auto &args = func->Variants[0].Proto->ArgumentTypes; + TArray params; + int start = 1; + + params.Push(0); + if (args.Size() > 1 && args[1] == NewPointer(PClass::FindClass("ListMenuDescriptor"))) + { + params.Push(desc); + start = 2; + } + auto TypeCVar = NewPointer(NewNativeStruct("CVar", nullptr)); + + for (unsigned i = 1; i < args.Size(); i++) + { + sc.MustGetString(); + if (args[i] == TypeString) + { + params.Push(sc.String); + } + else if (args[i] == TypeName) + { + params.Push(FName(sc.String).GetIndex()); + } + else if (args[i] == TypeColor) + { + params.Push(V_GetColor(nullptr, sc)); + } + else if (args[i] == TypeFont) + { + params.Push(FFont::FindFont(sc.String)); + } + else if (args[i]->IsKindOf(RUNTIME_CLASS(PInt))) + { + char *endp; + int v = (int)strtoll(sc.String, &endp, 0); + if (*endp != 0) + { + // special check for font color ranges. + v = V_FindFontColor(sc.String); + if (v == CR_UNTRANSLATED && !sc.Compare("untranslated")) + { + // todo: check other data types that may get used. + sc.ScriptError("Integer expected, got %s", sc.String); + } + } + if (args[i] == TypeBool) v = !!v; + params.Push(v); + } + else if (args[i]->IsKindOf(RUNTIME_CLASS(PFloat))) + { + char *endp; + double v = strtod(sc.String, &endp); + if (*endp != 0) + { + sc.ScriptError("Float expected, got %s", sc.String); + } + params.Push(v); + } + else if (args[i] == TypeCVar) + { + auto cv = FindCVar(sc.String, nullptr); + if (cv == nullptr && *sc.String) + { + sc.ScriptError("Unknown CVar %s", sc.String); + } + params.Push(cv); + } + else + { + sc.ScriptError("Invalid parameter type %s for menu item", args[i]->DescriptiveName()); + } + if (sc.CheckString(",")) + { + if (i == args.Size() - 1) + { + sc.ScriptError("Too many parameters for %s", cls->TypeName.GetChars()); + } + } + else + { + if (i < args.Size() - 1 && !(func->Variants[0].ArgFlags[i + 1] & VARF_Optional)) + { + sc.ScriptError("Insufficient parameters for %s", cls->TypeName.GetChars()); + } + break; + } + } + /* + DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew(); + params[0] = item; + GlobalVMStack.Call(func->Variants[0].Implementation, ¶ms[0], params.Size(), nullptr, 0); + desc->mItems.Push((DMenuItemBase*)item); + */ + if (cls->IsDescendantOf("ListMenuItemSelectable")) + { + desc->mYpos += desc->mLinespacing; + if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size() - 1; + } + success = true; } } - DListMenuItemPlayerDisplay_ *it = new DListMenuItemPlayerDisplay_(desc, x, y, c1, c2, noportrait, action); - desc->mItems.Push(it); - } - else if (sc.Compare("PlayerNameBox")) - { - sc.MustGetString(); - FString text = sc.String; - sc.MustGetStringName(","); - sc.MustGetNumber(); - int ofs = sc.Number; - sc.MustGetStringName(","); - sc.MustGetString(); - DMenuItemBase *it = new DPlayerNameBox_(desc->mXpos, desc->mYpos, desc->mLinespacing, ofs, text, desc->mFont, desc->mFontColor, sc.String); - desc->mItems.Push(it); - desc->mYpos += desc->mLinespacing; - if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; - } - else if (sc.Compare("ValueText")) - { - sc.MustGetString(); - FString text = sc.String; - sc.MustGetStringName(","); - sc.MustGetString(); - FName action = sc.String; - FName values; - if (sc.CheckString(",")) + if (!success) { - sc.MustGetString(); - values = sc.String; + sc.ScriptError("Unknown keyword '%s'", sc.String); } - DMenuItemBase *it = new DValueTextItem_(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, values); - desc->mItems.Push(it); - desc->mYpos += desc->mLinespacing; - if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; + } - else if (sc.Compare("Slider")) - { - sc.MustGetString(); - FString text = sc.String; - sc.MustGetStringName(","); - sc.MustGetString(); - FString action = sc.String; - sc.MustGetStringName(","); - sc.MustGetNumber(); - int min = sc.Number; - sc.MustGetStringName(","); - sc.MustGetNumber(); - int max = sc.Number; - sc.MustGetStringName(","); - sc.MustGetNumber(); - int step = sc.Number; - DMenuItemBase *it = new DSliderItem_(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, action, min, max, step); - desc->mItems.Push(it); - desc->mYpos += desc->mLinespacing; - if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; - } - else + { sc.ScriptError("Unknown keyword '%s'", sc.String); } @@ -835,7 +790,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) if (args[i] == TypeBool) v = !!v; params.Push(v); } - else if (args[i]->IsKindOf(RUNTIME_CLASS(PInt))) + else if (args[i]->IsKindOf(RUNTIME_CLASS(PFloat))) { char *endp; double v = strtod(sc.String, &endp); @@ -1060,12 +1015,11 @@ static void BuildEpisodeMenu() if (AllEpisodes[i].mPicName.IsNotEmpty()) { FTextureID tex = GetMenuTexture(AllEpisodes[i].mPicName); - it = new DListMenuItemPatch_(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, - tex, NAME_Skillmenu, i); + it = CreateListMenuItemPatch(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, tex, NAME_Skillmenu, i); } else { - it = new DListMenuItemText_(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, + it = CreateListMenuItemText(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, AllEpisodes[i].mEpisodeName, ld->mFont, ld->mFontColor, ld->mFontColor2, NAME_Skillmenu, i); } ld->mItems.Push(it); @@ -1158,7 +1112,7 @@ static void BuildPlayerclassMenu() if (numclassitems <= 1) { // create a dummy item that auto-chooses the default class. - DListMenuItemText_ *it = new DListMenuItemText_(0, 0, 0, 'p', "player", + auto it = CreateListMenuItemText(0, 0, 0, 'p', "player", ld->mFont,ld->mFontColor, ld->mFontColor2, NAME_Episodemenu, -1000); ld->mAutoselect = ld->mItems.Push(it); success = true; @@ -1184,7 +1138,7 @@ static void BuildPlayerclassMenu() const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type); if (pname != nullptr) { - DListMenuItemText_ *it = new DListMenuItemText_(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname, + auto it = CreateListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname, pname, ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, i); ld->mItems.Push(it); ld->mYpos += ld->mLinespacing; @@ -1194,7 +1148,7 @@ static void BuildPlayerclassMenu() } if (n > 1 && !gameinfo.norandomplayerclass) { - DListMenuItemText_ *it = new DListMenuItemText_(ld->mXpos, ld->mYpos, ld->mLinespacing, 'r', + auto it = CreateListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, 'r', "$MNU_RANDOM", ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, -1); ld->mItems.Push(it); } @@ -1203,7 +1157,7 @@ static void BuildPlayerclassMenu() const char *pname = GetPrintableDisplayName(PlayerClasses[0].Type); if (pname != nullptr) { - DListMenuItemText_ *it = new DListMenuItemText_(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname, + auto it = CreateListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname, pname, ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, 0); ld->mItems.Push(it); } @@ -1464,13 +1418,13 @@ void M_StartupSkillMenu(FGameStartup *gs) if (skill.PicName.Len() != 0 && pItemText == nullptr) { FTextureID tex = GetMenuTexture(skill.PicName); - li = new DListMenuItemPatch_(ld->mXpos, y, ld->mLinespacing, skill.Shortcut, tex, action, i); + li = CreateListMenuItemPatch(ld->mXpos, y, ld->mLinespacing, skill.Shortcut, tex, action, i); } else { EColorRange color = (EColorRange)skill.GetTextColor(); if (color == CR_UNTRANSLATED) color = ld->mFontColor; - li = new DListMenuItemText_(x, y, ld->mLinespacing, skill.Shortcut, + li = CreateListMenuItemText(x, y, ld->mLinespacing, skill.Shortcut, pItemText? *pItemText : skill.MenuName, ld->mFont, color,ld->mFontColor2, action, i); } ld->mItems.Push(li); diff --git a/src/menu/playerdisplay.cpp b/src/menu/playerdisplay.cpp index 5cd0f7815..e69de29bb 100644 --- a/src/menu/playerdisplay.cpp +++ b/src/menu/playerdisplay.cpp @@ -1,320 +0,0 @@ -/* -** playerdisplay.cpp -** The player display for the player setup and class selection screen -** -**--------------------------------------------------------------------------- -** Copyright 2010 Christoph Oelckers -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#include "doomtype.h" -#include "doomstat.h" -#include "d_player.h" -#include "templates.h" -#include "menu/menu.h" -#include "colormatcher.h" -#include "textures/textures.h" -#include "w_wad.h" -#include "v_font.h" -#include "v_video.h" -#include "g_level.h" -#include "gi.h" -#include "r_defs.h" -#include "r_state.h" -#include "r_data/r_translate.h" - - -//============================================================================= -// -// -// -//============================================================================= -IMPLEMENT_CLASS(DListMenuItemPlayerDisplay_, false, false) -DListMenuItemPlayerDisplay_::DListMenuItemPlayerDisplay_(DListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action) -: DMenuItemBase(x, y, action) -{ - mOwner = menu; - - FRemapTable *bdremap = translationtables[TRANSLATION_Players][MAXPLAYERS + 1]; - for (int i = 0; i < 256; i++) - { - int r = c1.r + c2.r * i / 255; - int g = c1.g + c2.g * i / 255; - int b = c1.b + c2.b * i / 255; - bdremap->Remap[i] = ColorMatcher.Pick (r, g, b); - bdremap->Palette[i] = PalEntry(255, r, g, b); - } - auto id = TexMan.CheckForTexture("PlayerBackdrop", FTexture::TEX_MiscPatch); - mBackdrop = TexMan[id]; - mPlayerClass = NULL; - mPlayerState = NULL; - mNoportrait = np; - mMode = 0; - mRotation = 0; - mTranslate = false; - mSkin = 0; - mRandomClass = 0; - mRandomTimer = 0; - mClassNum = -1; -} - - -//============================================================================= -// -// -// -//============================================================================= - -void DListMenuItemPlayerDisplay_::OnDestroy() -{ -} - -//============================================================================= -// -// -// -//============================================================================= - -void DListMenuItemPlayerDisplay_::UpdateRandomClass() -{ - if (--mRandomTimer < 0) - { - if (++mRandomClass >= (int)PlayerClasses.Size ()) mRandomClass = 0; - mPlayerClass = &PlayerClasses[mRandomClass]; - mPlayerState = GetDefaultByType (mPlayerClass->Type)->SeeState; - if (mPlayerState == NULL) - { // No see state, so try spawn state. - mPlayerState = GetDefaultByType (mPlayerClass->Type)->SpawnState; - } - mPlayerTics = mPlayerState != NULL ? mPlayerState->GetTics() : -1; - mRandomTimer = 6; - - // Since the newly displayed class may used a different translation - // range than the old one, we need to update the translation, too. - UpdateTranslation(); - } -} - -//============================================================================= -// -// -// -//============================================================================= - -void DListMenuItemPlayerDisplay_::UpdateTranslation() -{ - int PlayerColor = players[consoleplayer].userinfo.GetColor(); - int PlayerSkin = players[consoleplayer].userinfo.GetSkin(); - int PlayerColorset = players[consoleplayer].userinfo.GetColorSet(); - - if (mPlayerClass != NULL) - { - PlayerSkin = R_FindSkin (skins[PlayerSkin].name, int(mPlayerClass - &PlayerClasses[0])); - R_GetPlayerTranslation(PlayerColor, GetColorSet(mPlayerClass->Type, PlayerColorset), - &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); - } -} - -//============================================================================= -// -// -// -//============================================================================= - -void DListMenuItemPlayerDisplay_::SetPlayerClass(int classnum, bool force) -{ - if (classnum < 0 || classnum >= (int)PlayerClasses.Size ()) - { - if (mClassNum != -1) - { - mClassNum = -1; - mRandomTimer = 0; - UpdateRandomClass(); - } - } - else if (mPlayerClass != &PlayerClasses[classnum] || force) - { - mPlayerClass = &PlayerClasses[classnum]; - mPlayerState = GetDefaultByType (mPlayerClass->Type)->SeeState; - if (mPlayerState == NULL) - { // No see state, so try spawn state. - mPlayerState = GetDefaultByType (mPlayerClass->Type)->SpawnState; - } - mPlayerTics = mPlayerState != NULL ? mPlayerState->GetTics() : -1; - mClassNum = classnum; - } -} - -//============================================================================= -// -// -// -//============================================================================= - -bool DListMenuItemPlayerDisplay_::UpdatePlayerClass() -{ - if (mOwner->mSelectedItem >= 0) - { - int classnum; - FName seltype = mOwner->mItems[mOwner->mSelectedItem]->GetAction(&classnum); - - if (seltype != NAME_Episodemenu) return false; - if (PlayerClasses.Size() == 0) return false; - - SetPlayerClass(classnum); - return true; - } - return false; -} - -//============================================================================= -// -// -// -//============================================================================= - -bool DListMenuItemPlayerDisplay_::SetValue(int i, int value) -{ - switch (i) - { - case PDF_MODE: - mMode = value; - return true; - - case PDF_ROTATION: - mRotation = value; - return true; - - case PDF_TRANSLATE: - mTranslate = value; - - case PDF_CLASS: - SetPlayerClass(value, true); - break; - - case PDF_SKIN: - mSkin = value; - break; - } - return false; -} - -//============================================================================= -// -// -// -//============================================================================= - -void DListMenuItemPlayerDisplay_::Ticker() -{ - if (mClassNum < 0) UpdateRandomClass(); - - if (mPlayerState != NULL && mPlayerState->GetTics () != -1 && mPlayerState->GetNextState () != NULL) - { - if (--mPlayerTics <= 0) - { - mPlayerState = mPlayerState->GetNextState(); - mPlayerTics = mPlayerState->GetTics(); - } - } -} - -//============================================================================= -// -// -// -//============================================================================= - -void DListMenuItemPlayerDisplay_::Drawer(bool selected) -{ - if (mMode == 0 && !UpdatePlayerClass()) - { - return; - } - - FName portrait = ((APlayerPawn*)GetDefaultByType(mPlayerClass->Type))->Portrait; - - if (portrait != NAME_None && !mNoportrait) - { - FTextureID texid = TexMan.CheckForTexture(portrait.GetChars(), FTexture::TEX_MiscPatch); - if (texid.isValid()) - { - FTexture *tex = TexMan(texid); - if (tex != NULL) - { - screen->DrawTexture (tex, mXpos, mYpos, DTA_Clean, true, TAG_DONE); - return; - } - } - } - int x = (mXpos - 160) * CleanXfac + (SCREENWIDTH>>1); - int y = (mYpos - 100) * CleanYfac + (SCREENHEIGHT>>1); - - screen->DrawTexture(mBackdrop, x, y - 1, - DTA_DestWidth, 72 * CleanXfac, - DTA_DestHeight, 80 * CleanYfac, - DTA_TranslationIndex, TRANSLATION(TRANSLATION_Players, MAXPLAYERS + 1), - DTA_Masked, true, - TAG_DONE); - - V_DrawFrame (x, y, 72*CleanXfac, 80*CleanYfac-1); - - spriteframe_t *sprframe = NULL; - DVector2 Scale; - - if (mPlayerState != NULL) - { - if (mSkin == 0) - { - sprframe = &SpriteFrames[sprites[mPlayerState->sprite].spriteframes + mPlayerState->GetFrame()]; - Scale = GetDefaultByType(mPlayerClass->Type)->Scale; - } - else - { - sprframe = &SpriteFrames[sprites[skins[mSkin].sprite].spriteframes + mPlayerState->GetFrame()]; - Scale = skins[mSkin].Scale; - } - } - - if (sprframe != NULL) - { - FTexture *tex = TexMan(sprframe->Texture[mRotation]); - if (tex != NULL && tex->UseType != FTexture::TEX_Null) - { - int trans = mTranslate? TRANSLATION(TRANSLATION_Players, MAXPLAYERS) : 0; - screen->DrawTexture (tex, - x + 36*CleanXfac, y + 71*CleanYfac, - DTA_DestWidthF, tex->GetScaledWidthDouble() * CleanXfac * Scale.X, - DTA_DestHeightF, tex->GetScaledHeightDouble() * CleanYfac * Scale.Y, - DTA_TranslationIndex, trans, - DTA_FlipX, sprframe->Flip & (1 << mRotation), - TAG_DONE); - } - } -} - diff --git a/src/menu/playermenu.cpp b/src/menu/playermenu.cpp index 1621e3eba..3a1376052 100644 --- a/src/menu/playermenu.cpp +++ b/src/menu/playermenu.cpp @@ -55,428 +55,6 @@ EXTERN_CVAR (Float, autoaim) EXTERN_CVAR(Bool, neverswitchonpickup) EXTERN_CVAR (Bool, cl_run) -//============================================================================= -// -// Player's name -// -//============================================================================= -IMPLEMENT_CLASS(DPlayerNameBox_, false, false) - -DPlayerNameBox_::DPlayerNameBox_(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action) -: DListMenuItemSelectable_(x, y, height, action) -{ - mText = text; - mFont = font; - mFontColor = color; - mFrameSize = frameofs; - mPlayerName[0] = 0; - mEntering = false; -} - -//============================================================================= -// -// -// -//============================================================================= - -bool DPlayerNameBox_::SetString(int i, const char *s) -{ - if (i == 0) - { - strncpy(mPlayerName, s, MAXPLAYERNAME); - mPlayerName[MAXPLAYERNAME] = 0; - return true; - } - return false; -} - -bool DPlayerNameBox_::GetString(int i, char *s, int len) -{ - if (i == 0) - { - strncpy(s, mPlayerName, len); - s[len] = 0; - return true; - } - return false; -} - -//============================================================================= -// -// [RH] Width of the border is variable -// -//============================================================================= - -void DPlayerNameBox_::DrawBorder (int x, int y, int len) -{ - FTexture *left = TexMan[TexMan.CheckForTexture("M_LSLEFT", FTexture::TEX_MiscPatch)]; - FTexture *mid = TexMan[TexMan.CheckForTexture("M_LSCNTR", FTexture::TEX_MiscPatch)]; - FTexture *right = TexMan[TexMan.CheckForTexture("M_LSRGHT", FTexture::TEX_MiscPatch)]; - if (left != NULL && right != NULL && mid != NULL) - { - int i; - - screen->DrawTexture (left, x-8, y+7, DTA_Clean, true, TAG_DONE); - - for (i = 0; i < len; i++) - { - screen->DrawTexture (mid, x, y+7, DTA_Clean, true, TAG_DONE); - x += 8; - } - - screen->DrawTexture (right, x, y+7, DTA_Clean, true, TAG_DONE); - } - else - { - FTexture *slot = TexMan[TexMan.CheckForTexture("M_FSLOT", FTexture::TEX_MiscPatch)]; - if (slot != NULL) - { - screen->DrawTexture (slot, x, y+1, DTA_Clean, true, TAG_DONE); - } - else - { - screen->Clear(x, y, x + len, y + SmallFont->GetHeight() * 3/2, -1, 0); - } - } -} - -//============================================================================= -// -// -// -//============================================================================= - -void DPlayerNameBox_::Drawer(bool selected) -{ - const char *text = mText; - if (text != NULL) - { - if (*text == '$') text = GStrings(text+1); - screen->DrawText(mFont, selected? OptionSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true, TAG_DONE); - } - - // Draw player name box - int x = mXpos + mFont->StringWidth(text) + 16 + mFrameSize; - DrawBorder (x, mYpos - mFrameSize, MAXPLAYERNAME+1); - if (!mEntering) - { - screen->DrawText (SmallFont, CR_UNTRANSLATED, x + mFrameSize, mYpos, mPlayerName, - DTA_Clean, true, TAG_DONE); - } - else - { - size_t l = strlen(mEditName); - mEditName[l] = SmallFont->GetCursor(); - mEditName[l+1] = 0; - - screen->DrawText (SmallFont, CR_UNTRANSLATED, x + mFrameSize, mYpos, mEditName, - DTA_Clean, true, TAG_DONE); - - mEditName[l] = 0; - } -} - -//============================================================================= -// -// -// -//============================================================================= - -bool DPlayerNameBox_::MenuEvent(int mkey, bool fromcontroller) -{ - if (mkey == MKEY_Enter) - { - S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE); - strcpy(mEditName, mPlayerName); - mEntering = true; - DMenu *input = new DTextEnterMenu(DMenu::CurrentMenu, mEditName, MAXPLAYERNAME, 2, fromcontroller); - M_ActivateMenu(input); - return true; - } - else if (mkey == MKEY_Input) - { - strcpy(mPlayerName, mEditName); - mEntering = false; - return true; - } - else if (mkey == MKEY_Abort) - { - mEntering = false; - return true; - } - return false; -} - -//============================================================================= -// -// items for the player menu -// -//============================================================================= -IMPLEMENT_CLASS(DValueTextItem_, false, false) - -DValueTextItem_::DValueTextItem_(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values) -: DListMenuItemSelectable_(x, y, height, action) -{ - mText = text; - mFont = font; - mFontColor = color; - mFontColor2 = valuecolor; - mSelection = 0; - if (values != NAME_None) - { - FOptionValues **opt = OptionValues.CheckKey(values); - if (opt != NULL) - { - for(unsigned i=0;i<(*opt)->mValues.Size(); i++) - { - SetString(i, (*opt)->mValues[i].Text); - } - } - } -} - -//============================================================================= -// -// -// -//============================================================================= - -bool DValueTextItem_::SetString(int i, const char *s) -{ - // should actually use the index... - FString str = s; - if (i==0) mSelections.Clear(); - mSelections.Push(str); - return true; -} - -//============================================================================= -// -// -// -//============================================================================= - -bool DValueTextItem_::SetValue(int i, int value) -{ - if (i == 0) - { - mSelection = value; - return true; - } - return false; -} - -bool DValueTextItem_::GetValue(int i, int *pvalue) -{ - if (i == 0) - { - *pvalue = mSelection; - return true; - } - return false; -} - -//============================================================================= -// -// -// -//============================================================================= - -bool DValueTextItem_::MenuEvent (int mkey, bool fromcontroller) -{ - if (mSelections.Size() > 1) - { - if (mkey == MKEY_Left) - { - S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE); - if (--mSelection < 0) mSelection = mSelections.Size() - 1; - return true; - } - else if (mkey == MKEY_Right || mkey == MKEY_Enter) - { - S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE); - if (++mSelection >= (int)mSelections.Size()) mSelection = 0; - return true; - } - } - return (mkey == MKEY_Enter); // needs to eat enter keys so that Activate won't get called -} - -//============================================================================= -// -// -// -//============================================================================= - -void DValueTextItem_::Drawer(bool selected) -{ - const char *text = mText; - - if (*text == '$') text = GStrings(text+1); - screen->DrawText(mFont, selected? OptionSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true, TAG_DONE); - - int x = mXpos + mFont->StringWidth(text) + 8; - if (mSelections.Size() > 0) - { - const char *mOptValue = mSelections[mSelection]; - if (*mOptValue == '$') mOptValue = GStrings(mOptValue + 1); - screen->DrawText(mFont, mFontColor2, x, mYpos, mOptValue, DTA_Clean, true, TAG_DONE); - } -} - -//============================================================================= -// -// items for the player menu -// -//============================================================================= -IMPLEMENT_CLASS(DSliderItem_, false, false) - -DSliderItem_::DSliderItem_(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step) -: DListMenuItemSelectable_(x, y, height, action) -{ - mText = text; - mFont = font; - mFontColor = color; - mSelection = 0; - mMinrange = min; - mMaxrange = max; - mStep = step; -} - -//============================================================================= -// -// -// -//============================================================================= - -bool DSliderItem_::SetValue(int i, int value) -{ - if (i == 0) - { - mSelection = value; - return true; - } - return false; -} - -bool DSliderItem_::GetValue(int i, int *pvalue) -{ - if (i == 0) - { - *pvalue = mSelection; - return true; - } - return false; -} - -//============================================================================= -// -// -// -//============================================================================= - -bool DSliderItem_::MenuEvent (int mkey, bool fromcontroller) -{ - if (mkey == MKEY_Left) - { - S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE); - if ((mSelection -= mStep) < mMinrange) mSelection = mMinrange; - return true; - } - else if (mkey == MKEY_Right || mkey == MKEY_Enter) - { - S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE); - if ((mSelection += mStep) > mMaxrange) mSelection = mMaxrange; - return true; - } - return false; -} - -//============================================================================= -// -// -// -//============================================================================= - -bool DSliderItem_::MouseEvent(int type, int x, int y) -{ - DListMenu *lm = static_cast(DMenu::CurrentMenu); - if (type != DMenu::MOUSE_Click) - { - if (!lm->CheckFocus(this)) return false; - } - if (type == DMenu::MOUSE_Release) - { - lm->ReleaseFocus(); - } - - int slide_left = SmallFont->StringWidth ("Green") + 8 + mXpos; - int slide_right = slide_left + 12*8; // 12 char cells with 8 pixels each. - - if (type == DMenu::MOUSE_Click) - { - if (x < slide_left || x >= slide_right) return true; - } - - x = clamp(x, slide_left, slide_right); - int v = mMinrange + Scale(x - slide_left, mMaxrange - mMinrange, slide_right - slide_left); - if (v != mSelection) - { - mSelection = v; - S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE); - } - if (type == DMenu::MOUSE_Click) - { - lm->SetFocus(this); - } - return true; -} - -//============================================================================= -// -// -// -//============================================================================= - -void DSliderItem_::DrawSlider (int x, int y) -{ - int range = mMaxrange - mMinrange; - int cur = mSelection - mMinrange; - - x = (x - 160) * CleanXfac + screen->GetWidth() / 2; - y = (y - 100) * CleanYfac + screen->GetHeight() / 2; - - screen->DrawText (ConFont, CR_WHITE, x, y, - "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12", - DTA_CellX, 8 * CleanXfac, - DTA_CellY, 8 * CleanYfac, - TAG_DONE); - screen->DrawText (ConFont, CR_ORANGE, x + (5 + (int)((cur * 78) / range)) * CleanXfac, y, - "\x13", - DTA_CellX, 8 * CleanXfac, - DTA_CellY, 8 * CleanYfac, - TAG_DONE); -} - -//============================================================================= -// -// -// -//============================================================================= - -void DSliderItem_::Drawer(bool selected) -{ - const char *text = mText; - - if (*text == '$') text = GStrings(text+1); - screen->DrawText(mFont, selected? OptionSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true, TAG_DONE); - - int x = SmallFont->StringWidth ("Green") + 8 + mXpos; - int x2 = SmallFont->StringWidth (text) + 8 + mXpos; - DrawSlider (MAX(x2, x), mYpos); -} - - //============================================================================= // // @@ -524,6 +102,14 @@ IMPLEMENT_CLASS(DPlayerMenu, false, false) // // //============================================================================= +enum EPDFlags +{ + ListMenuItemPlayerDisplay_PDF_ROTATION = 0x10001, + ListMenuItemPlayerDisplay_PDF_SKIN = 0x10002, + ListMenuItemPlayerDisplay_PDF_CLASS = 0x10003, + ListMenuItemPlayerDisplay_PDF_MODE = 0x10004, + ListMenuItemPlayerDisplay_PDF_TRANSLATE = 0x10005, +}; void DPlayerMenu::Init(DMenu *parent, DListMenuDescriptor *desc) { @@ -536,14 +122,14 @@ void DPlayerMenu::Init(DMenu *parent, DListMenuDescriptor *desc) li = GetItem(NAME_Playerdisplay); if (li != NULL) { - li->SetValue(DListMenuItemPlayerDisplay_::PDF_ROTATION, 0); - li->SetValue(DListMenuItemPlayerDisplay_::PDF_MODE, 1); - li->SetValue(DListMenuItemPlayerDisplay_::PDF_TRANSLATE, 1); - li->SetValue(DListMenuItemPlayerDisplay_::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum()); + li->SetValue(ListMenuItemPlayerDisplay_PDF_ROTATION, 0); + li->SetValue(ListMenuItemPlayerDisplay_PDF_MODE, 1); + li->SetValue(ListMenuItemPlayerDisplay_PDF_TRANSLATE, 1); + li->SetValue(ListMenuItemPlayerDisplay_PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum()); if (PlayerClass != NULL && !(GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN) && players[consoleplayer].userinfo.GetPlayerClassNum() != -1) { - li->SetValue(DListMenuItemPlayerDisplay_::PDF_SKIN, players[consoleplayer].userinfo.GetSkin()); + li->SetValue(ListMenuItemPlayerDisplay_PDF_SKIN, players[consoleplayer].userinfo.GetSkin()); } } @@ -658,7 +244,7 @@ bool DPlayerMenu::Responder (event_t *ev) DMenuItemBase *li = GetItem(NAME_Playerdisplay); if (li != NULL) { - li->SetValue(DListMenuItemPlayerDisplay_::PDF_ROTATION, mRotation); + li->SetValue(ListMenuItemPlayerDisplay_PDF_ROTATION, mRotation); } return true; } @@ -812,7 +398,7 @@ void DPlayerMenu::UpdateSkins() li = GetItem(NAME_Playerdisplay); if (li != NULL) { - li->SetValue(DListMenuItemPlayerDisplay_::PDF_SKIN, skin); + li->SetValue(ListMenuItemPlayerDisplay_PDF_SKIN, skin); } } UpdateTranslation(); @@ -908,7 +494,7 @@ void DPlayerMenu::ClassChanged (DMenuItemBase *li) li = GetItem(NAME_Playerdisplay); if (li != NULL) { - li->SetValue(DListMenuItemPlayerDisplay_::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum()); + li->SetValue(ListMenuItemPlayerDisplay_PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum()); } } } @@ -939,7 +525,7 @@ void DPlayerMenu::SkinChanged (DMenuItemBase *li) li = GetItem(NAME_Playerdisplay); if (li != NULL) { - li->SetValue(DListMenuItemPlayerDisplay_::PDF_SKIN, sel); + li->SetValue(ListMenuItemPlayerDisplay_PDF_SKIN, sel); } } } diff --git a/wadsrc/static/zscript/menu/listmenuitems.txt b/wadsrc/static/zscript/menu/listmenuitems.txt index ddf7b6f47..eae172e73 100644 --- a/wadsrc/static/zscript/menu/listmenuitems.txt +++ b/wadsrc/static/zscript/menu/listmenuitems.txt @@ -68,7 +68,7 @@ class ListMenuItemStaticPatch : ListMenuItem TextureID mTexture; bool mCentered; - void Init(int x, int y, TextureID patch, bool centered) + void Init(int x, int y, TextureID patch, bool centered = false) { Super.Init(x, y); mTexture = patch; @@ -98,6 +98,14 @@ class ListMenuItemStaticPatch : ListMenuItem } } +class ListMenuItemStatucPatchCentered : ListMenuItemStaticPatch +{ + void Init(int x, int y, TextureID patch) + { + Super.Init(x, y, patch, true); + } +} + //============================================================================= // // static text @@ -111,7 +119,7 @@ class ListMenuItemStaticText : ListMenuItem int mColor; bool mCentered; - void Init(int x, int y, String text, Font font, int color, bool centered) + void Init(int x, int y, String text, Font font, int color, bool centered = false) { Super.Init(x, y); mText = text; @@ -141,6 +149,14 @@ class ListMenuItemStaticText : ListMenuItem } } +class ListMenuItemStatucTextCentered : ListMenuItemStaticText +{ + void Init(int x, int y, String text, Font font, int color) + { + Super.Init(x, y, text, font, color, true); + } +} + //============================================================================= // // selectable items @@ -153,7 +169,7 @@ class ListMenuItemSelectable : ListMenuItem int mHeight; int mParam; - void Init(int x, int y, int height, Name childmenu, int param = -1) + protected void Init(int x, int y, int height, Name childmenu, int param = -1) { Super.Init(x, y, childmenu); mHeight = height; @@ -207,21 +223,31 @@ class ListMenuItemSelectable : ListMenuItem // //============================================================================= -class ListMenuItemText : ListMenuItemSelectable +class ListMenuItemTextItem : ListMenuItemSelectable { String mText; Font mFont; int mColor; int mColorSelected; - void Init(int x, int y, int height, int hotkey, String text, Font font, int color, int color2, Name child, int param = 0) + void Init(ListMenuDescriptor desc, String text, String hotkey, Name child, int param = 0) + { + Super.Init(desc.mXpos, desc.mYpos, desc.mLinespacing, child, param); + mText = text; + mFont = desc.mFont; + mColor = desc.mFontColor; + mColorSelected = desc.mFontcolor2; + mHotkey = hotkey.CharAt(0); + } + + void InitDirect(int x, int y, int height, String hotkey, String text, Font font, int color, int color2, Name child, int param = 0) { Super.Init(x, y, height, child, param); mText = text; mFont = font; mColor = color; mColorSelected = color2; - mHotkey = hotkey; + mHotkey = hotkey.CharAt(0); } override void Drawer(bool selected) @@ -241,14 +267,21 @@ class ListMenuItemText : ListMenuItemSelectable // //============================================================================= -class ListMenuItemPatch : ListMenuItemSelectable +class ListMenuItemPatchItem : ListMenuItemSelectable { TextureID mTexture; - void Init(int x, int y, int height, int hotkey, TextureID patch, Name child, int param = 0) + void Init(ListMenuDescriptor desc, TextureID patch, String hotkey, Name child, int param = 0) + { + Super.Init(desc.mXpos, desc.mYpos, desc.mLinespacing, child, param); + mHotkey = hotkey.CharAt(0); + mTexture = patch; + } + + void InitDirect(int x, int y, int height, TextureID patch, String hotkey, Name child, int param = 0) { Super.Init(x, y, height, child, param); - mHotkey = hotkey; + mHotkey = hotkey.CharAt(0); mTexture = patch; } diff --git a/wadsrc/static/zscript/menu/menuitembase.txt b/wadsrc/static/zscript/menu/menuitembase.txt index 6123cabd8..cdc67b611 100644 --- a/wadsrc/static/zscript/menu/menuitembase.txt +++ b/wadsrc/static/zscript/menu/menuitembase.txt @@ -29,17 +29,15 @@ class MenuItemBase : Object native virtual bool SetValue(int i, int value) { return false; } virtual bool, int GetValue(int i) { return false, 0; } virtual void Enable(bool on) { mEnabled = on; } - // this can only be made scripted once all items are converted, because it is called from the colorpicker menu. -native virtual bool MenuEvent (int mkey, bool fromcontroller);// { return false; } + virtual bool MenuEvent (int mkey, bool fromcontroller) { return false; } virtual bool MouseEvent(int type, int x, int y) { return false; } virtual bool CheckHotkey(int c) { return false; } virtual int GetWidth() { return 0; } - virtual void OffsetPositionY(int ydelta) { mYpos += ydelta; } - virtual int GetY() { return mYpos; } - virtual int GetX() { return mXpos; } - virtual void SetX(int x) { mXpos = x; } virtual int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) { return indent; } - + void OffsetPositionY(int ydelta) { mYpos += ydelta; } + int GetY() { return mYpos; } + int GetX() { return mXpos; } + void SetX(int x) { mXpos = x; } } diff --git a/wadsrc/static/zscript/menu/playerdisplay.txt b/wadsrc/static/zscript/menu/playerdisplay.txt index 7665df516..18d81bb19 100644 --- a/wadsrc/static/zscript/menu/playerdisplay.txt +++ b/wadsrc/static/zscript/menu/playerdisplay.txt @@ -68,7 +68,7 @@ class ListMenuItemPlayerDisplay : ListMenuItem // // //============================================================================= - void Init(ListMenuDescriptor menu, int x, int y, Color c1, Color c2, bool np, Name command) + void Init(ListMenuDescriptor menu, Name command, int x, int y, Color c1, Color c2, bool np = false) { Super.Init(x, y, command); mOwner = menu; diff --git a/wadsrc/static/zscript/menu/playermenu.txt b/wadsrc/static/zscript/menu/playermenu.txt index 338772b6b..9a21530d6 100644 --- a/wadsrc/static/zscript/menu/playermenu.txt +++ b/wadsrc/static/zscript/menu/playermenu.txt @@ -39,7 +39,7 @@ // //============================================================================= -class PlayerNameBox : ListMenuItemSelectable +class ListMenuItemPlayerNameBox : ListMenuItemSelectable { String mText; Font mFont; @@ -55,6 +55,23 @@ class PlayerNameBox : ListMenuItemSelectable // //============================================================================= + void Init(ListMenuDescriptor desc, String text, int frameofs, Name command) + { + Super.Init(desc.mXpos, desc.mYpos, desc.mLinespacing, command); + mText = text; + mFont = font; + mFontColor = color; + mFrameSize = frameofs; + mPlayerName = ""; + mEntering = false; + } + + //============================================================================= + // + // Player's name + // + //============================================================================= + void Init(int x, int y, int height, int frameofs, String text, Font font, int color, Name command) { Super.Init(x, y, height, command); @@ -197,7 +214,7 @@ class PlayerNameBox : ListMenuItemSelectable // //============================================================================= -class DValueTextItem : ListMenuItemSelectable +class ListMenuItemValueText : ListMenuItemSelectable { Array mSelections; String mText; @@ -212,7 +229,28 @@ class DValueTextItem : ListMenuItemSelectable // //============================================================================= - void Init(int x, int y, int height, String text, Font font, int color, int valuecolor, Name command, Name values) + void Init(ListMenuDescriptor desc, String text, Name command, Name values = 'None') + { + Super.Init(desc.mXpos, desc.mYpos, desc.mLinespacing, command); + mText = text; + mFont = desc.mFont; + mFontColor = desc.mFontColor; + mFontColor2 = desc.mFontColor2; + mSelection = 0; + let cnt = OptionValues.GetCount(values); + for(int i = 0; i < cnt; i++) + { + SetString(i, OptionValues.GetText(values, i)); + } + } + + //============================================================================= + // + // items for the player menu + // + //============================================================================= + + void InitDirect(int x, int y, int height, String text, Font font, int color, int valuecolor, Name command, Name values) { Super.Init(x, y, height, command); mText = text; @@ -318,7 +356,7 @@ class DValueTextItem : ListMenuItemSelectable // //============================================================================= -class DSliderItem : ListMenuItemSelectable +class ListMenuItemSlider : ListMenuItemSelectable { String mText; Font mFont; @@ -333,7 +371,25 @@ class DSliderItem : ListMenuItemSelectable // //============================================================================= - void Init(int x, int y, int height, String text, Font font, int color, Name command, int min, int max, int step) + void Init(ListMenuItemDescriptor desc, String text, Name command, int min, int max, int step) + { + Super.Init(desc.mXpos, desc.mYpos, desc.mLinespacing, command); + mText = text; + mFont = desc.mFont; + mFontColor = desc.mFontColor; + mSelection = 0; + mMinrange = min; + mMaxrange = max; + mStep = step; + } + + //============================================================================= + // + // items for the player menu + // + //============================================================================= + + void InitDirect(int x, int y, int height, String text, Font font, int color, Name command, int min, int max, int step) { Super.Init(x, y, height, command); mText = text; From c01107181a285625a2addc92dfcc0585d2ac1a72 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 12 Feb 2017 11:26:25 +0200 Subject: [PATCH 06/19] Reset sound position only when there is no listener https://mantis.zdoom.org/view.php?id=206 https://mantis.zdoom.org/view.php?id=248 --- src/s_sound.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/s_sound.cpp b/src/s_sound.cpp index bae1fbaf6..f01d3288c 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -692,6 +692,7 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, else { listenpos.Zero(); + pos->Zero(); pgroup = 0; } @@ -711,7 +712,6 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, { case SOURCE_None: default: - pos->Zero(); break; case SOURCE_Actor: From 9482c3e6398709272d7139c33e43f7f28211c4fc Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 11 Feb 2017 23:29:09 +0100 Subject: [PATCH 07/19] Fixed voxel clipping bug --- src/r_things.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index 3d0ce269e..b4ee5edbb 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2071,7 +2071,7 @@ void R_DrawSprite (vissprite_t *spr) // [RH] rewrote this to be based on which part of the sector is really visible double scale = InvZtoScale * spr->idepth; - double hzb = DBL_MIN, hzt = DBL_MAX; + double hzb = -DBL_MAX, hzt = DBL_MAX; if (spr->bIsVoxel && spr->floorclip != 0) { From bb6def820f6e7af5dbd0131a28078246fa4866c6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Feb 2017 14:04:48 +0100 Subject: [PATCH 08/19] - everything compiles and mostly works again. --- src/CMakeLists.txt | 1 - src/dobjtype.cpp | 18 +++--- src/menu/listmenu.cpp | 2 +- src/menu/menu.cpp | 9 +-- src/menu/menudef.cpp | 59 ++++++++----------- src/menu/playerdisplay.cpp | 0 src/scripting/thingdef_data.cpp | 7 +++ wadsrc/static/zscript/menu/listmenuitems.txt | 28 ++++++--- wadsrc/static/zscript/menu/menuitembase.txt | 6 ++ .../static/zscript/menu/optionmenuitems.txt | 56 ++++++++++++++---- wadsrc/static/zscript/menu/playerdisplay.txt | 2 +- wadsrc/static/zscript/menu/playermenu.txt | 8 +-- 12 files changed, 119 insertions(+), 77 deletions(-) delete mode 100644 src/menu/playerdisplay.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d079c68b2..9448006e4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -848,7 +848,6 @@ set( FASTMATH_PCH_SOURCES menu/menuinput.cpp menu/messagebox.cpp menu/optionmenu.cpp - menu/playerdisplay.cpp menu/playermenu.cpp menu/readthis.cpp menu/videomenu.cpp diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 1e6211976..53ca1f335 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -1985,7 +1985,7 @@ void PDynArray::DestroyValue(void *addr) const void PDynArray::SetDefaultValue(void *base, unsigned offset, TArray *special) const { - memset((char*)base + offset, 0, sizeof(FArray)); // same as constructing an empty array. + if (base != nullptr) memset((char*)base + offset, 0, sizeof(FArray)); // same as constructing an empty array. if (special != nullptr) { special->Push(std::make_pair(this, offset)); @@ -3047,6 +3047,10 @@ DObject *PClass::CreateNew() const else memset (mem, 0, Size); + if (ConstructNative == nullptr) + { + I_Error("Attempt to instantiate abstract class %s.", TypeName.GetChars()); + } ConstructNative (mem); ((DObject *)mem)->SetClass (const_cast(this)); InitializeSpecials(mem, Defaults); @@ -3165,16 +3169,12 @@ void PClass::InitializeDefaults() { // Copy parent values from the parent defaults. assert(ParentClass != nullptr); - ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults); - - if (Defaults != nullptr) + if (Defaults != nullptr) ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults); + for (const PField *field : Fields) { - for (const PField *field : Fields) + if (!(field->Flags & VARF_Native)) { - if (!(field->Flags & VARF_Native)) - { - field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); - } + field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); } } } diff --git a/src/menu/listmenu.cpp b/src/menu/listmenu.cpp index adb630375..18c627359 100644 --- a/src/menu/listmenu.cpp +++ b/src/menu/listmenu.cpp @@ -278,4 +278,4 @@ void DListMenu::Drawer () // base class for menu items // //============================================================================= -IMPLEMENT_CLASS(DMenuItemBase, true, false) +IMPLEMENT_CLASS(DMenuItemBase, false, false) diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 720a327dd..6b137d12a 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -1130,9 +1130,6 @@ DEFINE_FIELD(DOptionMenuDescriptor, mIndent) DEFINE_FIELD(DOptionMenuDescriptor, mPosition) DEFINE_FIELD(DOptionMenuDescriptor, mDontDim) -//DEFINE_FIELD(DMenuItemBase, mLabel) -//DEFINE_FIELD(DMenuItemBase, mCentered) - DEFINE_FIELD(DOptionMenu, CanScrollUp) DEFINE_FIELD(DOptionMenu, CanScrollDown) DEFINE_FIELD(DOptionMenu, VisBottom) @@ -1272,7 +1269,7 @@ DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBi DMenuItemBase * CreateListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID tex, FName command, int param) { - auto c = PClass::FindClass("ListMenuItemPatch"); + auto c = PClass::FindClass("ListMenuItemPatchItem"); auto p = c->CreateNew(); VMValue params[] = { p, x, y, height, tex.GetIndex(), hotkey, command.GetIndex(), param }; auto f = dyn_cast(c->Symbols.FindSymbol("InitDirect", false)); @@ -1282,7 +1279,7 @@ DMenuItemBase * CreateListMenuItemPatch(int x, int y, int height, int hotkey, FT DMenuItemBase * CreateListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, PalEntry color1, PalEntry color2, FName command, int param) { - auto c = PClass::FindClass("ListMenuItemText"); + auto c = PClass::FindClass("ListMenuItemTextItem"); auto p = c->CreateNew(); VMValue params[] = { p, x, y, height, hotkey, text, font, int(color1.d), int(color2.d), command.GetIndex(), param }; auto f = dyn_cast(c->Symbols.FindSymbol("InitDirect", false)); @@ -1314,7 +1311,7 @@ void DMenuItemBase::Ticker() void DMenuItemBase::Drawer(bool selected) { - IFVIRTUAL(DMenuItemBase, Ticker) + IFVIRTUAL(DMenuItemBase, Drawer) { VMValue params[] = { (DObject*)this, selected }; GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr); diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index fe0314c1b..aec60af91 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -384,12 +384,12 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) } auto TypeCVar = NewPointer(NewNativeStruct("CVar", nullptr)); - for (unsigned i = 1; i < args.Size(); i++) + for (unsigned i = start; i < args.Size(); i++) { sc.MustGetString(); if (args[i] == TypeString) { - params.Push(sc.String); + params.Push(FString(sc.String)); } else if (args[i] == TypeName) { @@ -401,7 +401,21 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) } else if (args[i] == TypeFont) { - params.Push(FFont::FindFont(sc.String)); + auto f = FFont::FindFont(sc.String); + if (f == nullptr) + { + sc.ScriptError("Unknown font %s", sc.String); + } + params.Push(f); + } + else if (args[i] == TypeTextureID) + { + auto f = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch); + if (!f.isValid()) + { + sc.ScriptError("Unknown texture %s", sc.String); + } + params.Push(f.GetIndex()); } else if (args[i]->IsKindOf(RUNTIME_CLASS(PInt))) { @@ -459,12 +473,11 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) break; } } - /* DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew(); params[0] = item; GlobalVMStack.Call(func->Variants[0].Implementation, ¶ms[0], params.Size(), nullptr, 0); desc->mItems.Push((DMenuItemBase*)item); - */ + if (cls->IsDescendantOf("ListMenuItemSelectable")) { desc->mYpos += desc->mLinespacing; @@ -477,11 +490,6 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) { sc.ScriptError("Unknown keyword '%s'", sc.String); } - - } - - { - sc.ScriptError("Unknown keyword '%s'", sc.String); } } for (auto &p : desc->mItems) @@ -664,21 +672,6 @@ static void ParseOptionSettings(FScanner &sc) // //============================================================================= -static EColorRange ParseOptionColor(FScanner &sc, DOptionMenuDescriptor *desc) -{ - EColorRange cr = OptionSettings.mFontColor; - if (sc.CheckString(",")) - { - sc.MustGetString(); - cr = V_FindFontColor(sc.String); - if (cr == CR_UNTRANSLATED && !sc.Compare("untranslated") && isdigit(sc.String[0])) - { - if (strtoll(sc.String, nullptr, 0)) cr = OptionSettings.mFontColorHeader; - } - } - return cr; -} - static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) { sc.MustGetStringName("{"); @@ -745,7 +738,6 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) bool success = false; FStringf buildname("OptionMenuItem%s", sc.String); // Handle one special case: MapControl maps to Control with one parameter different - FKeyBindings *bind = sc.Compare("MapControl") ? &AutomapBindings : &Bindings; PClass *cls = PClass::FindClass(buildname); if (cls != nullptr && cls->IsDescendantOf("OptionMenuItem")) { @@ -757,13 +749,12 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) params.Push(0); auto TypeCVar = NewPointer(NewNativeStruct("CVar", nullptr)); - auto TypeBind = NewPointer(NewNativeStruct("KeyBindings", nullptr)); for (unsigned i = 1; i < args.Size(); i++) { sc.MustGetString(); if (args[i] == TypeString) { - params.Push(sc.String); + params.Push(FString(sc.String)); } else if (args[i] == TypeName) { @@ -786,6 +777,8 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) // todo: check other data types that may get used. sc.ScriptError("Integer expected, got %s", sc.String); } + // Color ranges need to be marked for option menu items to support an older feature where a boolean number could be passed instead. + v |= 0x12340000; } if (args[i] == TypeBool) v = !!v; params.Push(v); @@ -822,12 +815,6 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) } else { - if (args[i + 1] == TypeBind) - { - // Bindings are not parsed, they just get tacked on. - params.Push(bind); - i++; - } if (i < args.Size() - 1 && !(func->Variants[0].ArgFlags[i + 1] & VARF_Optional)) { sc.ScriptError("Insufficient parameters for %s", cls->TypeName.GetChars()); @@ -835,12 +822,12 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) break; } } - /* + DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew(); params[0] = item; GlobalVMStack.Call(func->Variants[0].Implementation, ¶ms[0], params.Size(), nullptr, 0); desc->mItems.Push((DMenuItemBase*)item); - */ + success = true; } } diff --git a/src/menu/playerdisplay.cpp b/src/menu/playerdisplay.cpp deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index c736b5487..1aa35895d 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -55,6 +55,7 @@ #include "r_sky.h" #include "v_font.h" #include "v_video.h" +#include "c_bind.h" #include "menu/menu.h" static TArray properties; @@ -797,6 +798,12 @@ void InitThingdef() PField *plrclsf = new PField("PlayerClasses", plrcls, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&PlayerClasses); Namespaces.GlobalNamespace->Symbols.AddSymbol(plrclsf); + auto bindcls = NewNativeStruct("KeyBindings", nullptr); + PField *binding = new PField("Bindings", bindcls, VARF_Native | VARF_Static, (intptr_t)&Bindings); + Namespaces.GlobalNamespace->Symbols.AddSymbol(binding); + binding = new PField("AutomapBindings", bindcls, VARF_Native | VARF_Static, (intptr_t)&AutomapBindings); + Namespaces.GlobalNamespace->Symbols.AddSymbol(binding); + // set up a variable for the DEH data PStruct *dstruct = NewNativeStruct("DehInfo", nullptr); PField *dehf = new PField("deh", dstruct, VARF_Native | VARF_Static, (intptr_t)&deh); diff --git a/wadsrc/static/zscript/menu/listmenuitems.txt b/wadsrc/static/zscript/menu/listmenuitems.txt index eae172e73..8920e617b 100644 --- a/wadsrc/static/zscript/menu/listmenuitems.txt +++ b/wadsrc/static/zscript/menu/listmenuitems.txt @@ -98,7 +98,7 @@ class ListMenuItemStaticPatch : ListMenuItem } } -class ListMenuItemStatucPatchCentered : ListMenuItemStaticPatch +class ListMenuItemStaticPatchCentered : ListMenuItemStaticPatch { void Init(int x, int y, TextureID patch) { @@ -119,7 +119,16 @@ class ListMenuItemStaticText : ListMenuItem int mColor; bool mCentered; - void Init(int x, int y, String text, Font font, int color, bool centered = false) + void Init(ListMenuDescriptor desc, int x, int y, String text, int color = Font.CR_UNTRANSLATED) + { + Super.Init(x, y); + mText = text; + mFont = desc.mFont; + mColor = color >= 0? color : desc.mFontColor; + mCentered = false; + } + + void InitDirect(int x, int y, String text, Font font, int color = Font.CR_UNTRANSLATED, bool centered = false) { Super.Init(x, y); mText = text; @@ -149,11 +158,12 @@ class ListMenuItemStaticText : ListMenuItem } } -class ListMenuItemStatucTextCentered : ListMenuItemStaticText +class ListMenuItemStaticTextCentered : ListMenuItemStaticText { - void Init(int x, int y, String text, Font font, int color) + void Init(ListMenuDescriptor desc, int x, int y, String text, int color = -1) { - Super.Init(x, y, text, font, color, true); + Super.Init(desc, x, y, text, color); + mCentered = true; } } @@ -237,7 +247,7 @@ class ListMenuItemTextItem : ListMenuItemSelectable mFont = desc.mFont; mColor = desc.mFontColor; mColorSelected = desc.mFontcolor2; - mHotkey = hotkey.CharAt(0); + mHotkey = hotkey.CharCodeAt(0); } void InitDirect(int x, int y, int height, String hotkey, String text, Font font, int color, int color2, Name child, int param = 0) @@ -247,7 +257,7 @@ class ListMenuItemTextItem : ListMenuItemSelectable mFont = font; mColor = color; mColorSelected = color2; - mHotkey = hotkey.CharAt(0); + mHotkey = hotkey.CharCodeAt(0); } override void Drawer(bool selected) @@ -274,14 +284,14 @@ class ListMenuItemPatchItem : ListMenuItemSelectable void Init(ListMenuDescriptor desc, TextureID patch, String hotkey, Name child, int param = 0) { Super.Init(desc.mXpos, desc.mYpos, desc.mLinespacing, child, param); - mHotkey = hotkey.CharAt(0); + mHotkey = hotkey.CharCodeAt(0); mTexture = patch; } void InitDirect(int x, int y, int height, TextureID patch, String hotkey, Name child, int param = 0) { Super.Init(x, y, height, child, param); - mHotkey = hotkey.CharAt(0); + mHotkey = hotkey.CharCodeAt(0); mTexture = patch; } diff --git a/wadsrc/static/zscript/menu/menuitembase.txt b/wadsrc/static/zscript/menu/menuitembase.txt index cdc67b611..de5f05a42 100644 --- a/wadsrc/static/zscript/menu/menuitembase.txt +++ b/wadsrc/static/zscript/menu/menuitembase.txt @@ -33,6 +33,7 @@ class MenuItemBase : Object native virtual bool MouseEvent(int type, int x, int y) { return false; } virtual bool CheckHotkey(int c) { return false; } virtual int GetWidth() { return 0; } + virtual int GetIndent() { return 0; } virtual int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) { return indent; } void OffsetPositionY(int ydelta) { mYpos += ydelta; } @@ -41,3 +42,8 @@ class MenuItemBase : Object native void SetX(int x) { mXpos = x; } } +// this is only used to parse font color ranges in MENUDEF +enum MenudefColorRange +{ + NO_COLOR = -1 +} \ No newline at end of file diff --git a/wadsrc/static/zscript/menu/optionmenuitems.txt b/wadsrc/static/zscript/menu/optionmenuitems.txt index c3e6e0bd1..89cdbdd3c 100644 --- a/wadsrc/static/zscript/menu/optionmenuitems.txt +++ b/wadsrc/static/zscript/menu/optionmenuitems.txt @@ -32,11 +32,10 @@ ** */ -class OptionMenuItem : MenuItemBase native +class OptionMenuItem : MenuItemBase { - - native String mLabel; - native bool mCentered; + String mLabel; + bool mCentered; void Init(String label, String command, bool center = false) { @@ -67,7 +66,7 @@ class OptionMenuItem : MenuItemBase native return true; } - virtual int GetIndent() + override int GetIndent() { if (mCentered) return 0; return SmallFont.StringWidth(Stringtable.Localize(mLabel)); @@ -145,7 +144,7 @@ class OptionMenuItemSafeCommand : OptionMenuItemCommand String mPrompt; - void Init(String label, Name command, String prompt) + void Init(String label, Name command, String prompt = "") { Super.Init(label, command); mPrompt = prompt; @@ -420,7 +419,7 @@ IMPLEMENT_CLASS(DEnterKey, true, false) // //============================================================================= -class OptionMenuItemControl : OptionMenuItem +class OptionMenuItemControlBase : OptionMenuItem { KeyBindings mBindings; int mInput; @@ -487,6 +486,22 @@ class OptionMenuItemControl : OptionMenuItem } } +class OptionMenuItemControl : OptionMenuItemControlBase +{ + void Init(String label, Name command) + { + Super.Init(label, command, Bindings); + } +} + +class OptionMenuItemMapControl : OptionMenuItemControlBase +{ + void Init(String label, Name command) + { + Super.Init(label, command, AutomapBindings); + } +} + //============================================================================= // // @@ -497,10 +512,19 @@ class OptionMenuItemStaticText : OptionMenuItem { int mColor; - void Init(String label, int cr = -1, bool header = false) + // this function is only for use from MENUDEF, it needs to do some strange things with the color for backwards compatibility. + void Init(String label, int cr = -1) { Super.Init(label, 'None', true); - mColor = cr >= 0? cr : header ? OptionMenuSettings.mFontColorHeader : OptionMenuSettings.mFontColor; + mColor = OptionMenuSettings.mFontColor; + if ((cr & 0xffff0000) == 0x12340000) mColor = cr & 0xffff; + else if (cr > 0) mColor = OptionMenuSettings.mFontColorHeader; + } + + void InitDirect(String label, int cr) + { + Super.Init(label, 'None', true); + mColor = cr; } override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) @@ -528,7 +552,19 @@ class OptionMenuItemStaticTextSwitchable : OptionMenuItem String mAltText; int mCurrent; - void Init(String label, String label2, Name command, int cr) + // this function is only for use from MENUDEF, it needs to do some strange things with the color for backwards compatibility. + void Init(String label, String label2, Name command, int cr = -1) + { + Super.Init(label, command, true); + mAltText = label2; + mCurrent = 0; + + mColor = OptionMenuSettings.mFontColor; + if ((cr & 0xffff0000) == 0x12340000) mColor = cr & 0xffff; + else if (cr > 0) mColor = OptionMenuSettings.mFontColorHeader; + } + + void InitDirect(String label, String label2, Name command, int cr) { Super.Init(label, command, true); mColor = cr; diff --git a/wadsrc/static/zscript/menu/playerdisplay.txt b/wadsrc/static/zscript/menu/playerdisplay.txt index 18d81bb19..e13e9fb54 100644 --- a/wadsrc/static/zscript/menu/playerdisplay.txt +++ b/wadsrc/static/zscript/menu/playerdisplay.txt @@ -68,7 +68,7 @@ class ListMenuItemPlayerDisplay : ListMenuItem // // //============================================================================= - void Init(ListMenuDescriptor menu, Name command, int x, int y, Color c1, Color c2, bool np = false) + void Init(ListMenuDescriptor menu, int x, int y, Color c1, Color c2, bool np = false, Name command = 'None' ) { Super.Init(x, y, command); mOwner = menu; diff --git a/wadsrc/static/zscript/menu/playermenu.txt b/wadsrc/static/zscript/menu/playermenu.txt index 9a21530d6..6b055e0a0 100644 --- a/wadsrc/static/zscript/menu/playermenu.txt +++ b/wadsrc/static/zscript/menu/playermenu.txt @@ -59,8 +59,8 @@ class ListMenuItemPlayerNameBox : ListMenuItemSelectable { Super.Init(desc.mXpos, desc.mYpos, desc.mLinespacing, command); mText = text; - mFont = font; - mFontColor = color; + mFont = desc.mFont; + mFontColor = desc.mFontColor; mFrameSize = frameofs; mPlayerName = ""; mEntering = false; @@ -72,7 +72,7 @@ class ListMenuItemPlayerNameBox : ListMenuItemSelectable // //============================================================================= - void Init(int x, int y, int height, int frameofs, String text, Font font, int color, Name command) + void InitDirect(int x, int y, int height, int frameofs, String text, Font font, int color, Name command) { Super.Init(x, y, height, command); mText = text; @@ -371,7 +371,7 @@ class ListMenuItemSlider : ListMenuItemSelectable // //============================================================================= - void Init(ListMenuItemDescriptor desc, String text, Name command, int min, int max, int step) + void Init(ListMenuDescriptor desc, String text, Name command, int min, int max, int step) { Super.Init(desc.mXpos, desc.mYpos, desc.mLinespacing, command); mText = text; From 4562695854abe745cc5e867cf930ed2fd3a4d4ba Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Feb 2017 14:28:38 +0100 Subject: [PATCH 09/19] - fixed stringtable access in menus. --- src/v_text.cpp | 4 +++- wadsrc/static/zscript/base.txt | 2 +- wadsrc/static/zscript/menu/optionmenuitems.txt | 5 +++-- wadsrc/static/zscript/strife/coin.txt | 2 +- wadsrc/static/zscript/strife/thingstoblowup.txt | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/v_text.cpp b/src/v_text.cpp index 85b3de7db..a80a566ab 100644 --- a/src/v_text.cpp +++ b/src/v_text.cpp @@ -141,6 +141,8 @@ void DCanvas::DrawTextCommon(FFont *font, int normalcolor, double x, double y, c int kerning; FTexture *pic; + assert(string[0] != '$'); + if (parms.celly == 0) parms.celly = font->GetHeight() + 1; parms.celly *= parms.scaley; @@ -240,7 +242,7 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawText) PARAM_STRING(chr); VMVa_List args = { param + 5, 0, numparam - 5 }; - const char *txt = chr[0] == '$' ? GStrings(chr) : chr.GetChars(); + const char *txt = chr[0] == '$' ? GStrings(&chr[1]) : chr.GetChars(); screen->DrawText(font, cr, x, y, txt, args); return 0; } diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 1465f5b3a..e7820583b 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -409,7 +409,7 @@ struct LevelLocals native struct StringTable native { - native static String Localize(String val, bool prefixed = false); + native static String Localize(String val, bool prefixed = true); } // a few values of this need to be readable by the play code. diff --git a/wadsrc/static/zscript/menu/optionmenuitems.txt b/wadsrc/static/zscript/menu/optionmenuitems.txt index 89cdbdd3c..7c482e3e9 100644 --- a/wadsrc/static/zscript/menu/optionmenuitems.txt +++ b/wadsrc/static/zscript/menu/optionmenuitems.txt @@ -47,6 +47,7 @@ class OptionMenuItem : MenuItemBase protected void drawLabel(int indent, int y, int color, bool grayed = false) { String label = Stringtable.Localize(mLabel); + int overlay = grayed? Color(96,48,0,0) : 0; int x; @@ -302,7 +303,7 @@ class OptionMenuItemOption : OptionMenuItemOptionBase int cnt = OptionValues.GetCount(mValues); if (cnt > 0 && mCVar != null) { - if (OptionValues.GetText(mValues, 0).Length() > 0) + if (OptionValues.GetTextValue(mValues, 0).Length() == 0) { let f = mCVar.GetFloat(); for(int i = 0; i < cnt; i++) @@ -335,7 +336,7 @@ class OptionMenuItemOption : OptionMenuItemOptionBase int cnt = OptionValues.GetCount(mValues); if (cnt > 0 && mCVar != null) { - if (OptionValues.GetText(mValues, 0).Length() > 0) + if (OptionValues.GetTextValue(mValues, 0).Length() == 0) { mCVar.SetFloat(OptionValues.GetValue(mValues, Selection)); } diff --git a/wadsrc/static/zscript/strife/coin.txt b/wadsrc/static/zscript/strife/coin.txt index b94a3f1d1..b6a83ecf2 100644 --- a/wadsrc/static/zscript/strife/coin.txt +++ b/wadsrc/static/zscript/strife/coin.txt @@ -31,7 +31,7 @@ class Coin : Inventory } else { - String msg = StringTable.Localize("TXT_XGOLD"); + String msg = StringTable.Localize("$TXT_XGOLD"); msg.Replace("%d", "" .. Amount); return msg; } diff --git a/wadsrc/static/zscript/strife/thingstoblowup.txt b/wadsrc/static/zscript/strife/thingstoblowup.txt index bb268838c..a2b515efb 100644 --- a/wadsrc/static/zscript/strife/thingstoblowup.txt +++ b/wadsrc/static/zscript/strife/thingstoblowup.txt @@ -27,7 +27,7 @@ extend class Actor } } - String msgid = "TXT_QUEST_" .. questitem; + String msgid = "$TXT_QUEST_" .. questitem; String msg = StringTable.Localize(msgid); if (msg != msgid) // if both are identical there was no message of this name in the stringtable. From 03283de4e806da1f664533693d3454ded6fe421e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Feb 2017 16:02:55 +0100 Subject: [PATCH 10/19] - fixed issues with option menu items. - fixed the octal parser in strbin. - remove 'new' token because it gets in the way. --- src/c_console.cpp | 8 ++++++++ src/c_cvars.cpp | 2 +- src/cmdlib.cpp | 16 ++++++++-------- src/menu/menu.cpp | 2 +- src/sc_man_scanner.re | 2 -- src/sc_man_tokens.h | 1 - src/scripting/thingdef_data.cpp | 2 +- src/scripting/vm/vm.h | 2 +- wadsrc/static/zscript/base.txt | 1 + wadsrc/static/zscript/menu/optionmenuitems.txt | 12 +++++------- 10 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/c_console.cpp b/src/c_console.cpp index 493625bf9..42b6034f2 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -1332,6 +1332,14 @@ DEFINE_ACTION_FUNCTION(_Console, HideConsole) return 0; } +DEFINE_ACTION_FUNCTION(_Console, Printf) +{ + PARAM_PROLOGUE; + FString s = FStringFormat(param, defaultparam, numparam, ret, numret); + Printf("%s\n", s.GetChars()); + return 0; +} + static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) { int data1 = ev->data1; diff --git a/src/c_cvars.cpp b/src/c_cvars.cpp index ed9b0f29a..c79a76fb3 100644 --- a/src/c_cvars.cpp +++ b/src/c_cvars.cpp @@ -192,7 +192,7 @@ DEFINE_ACTION_FUNCTION(_CVar, GetFloat) { PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); auto v = self->GetGenericRep(CVAR_Float); - ACTION_RETURN_FLOAT(v.Int); + ACTION_RETURN_FLOAT(v.Float); } DEFINE_ACTION_FUNCTION(_CVar, GetString) diff --git a/src/cmdlib.cpp b/src/cmdlib.cpp index 266ef47be..f7fb94510 100644 --- a/src/cmdlib.cpp +++ b/src/cmdlib.cpp @@ -614,16 +614,16 @@ int strbin (char *str) case '6': case '7': c = 0; - for (i = 0; i < 3; i++) { - c <<= 3; + for (i = 0; i < 2; i++) + { + p++; if (*p >= '0' && *p <= '7') - c += *p-'0'; + c = (c << 3) + *p - '0'; else { p--; break; } - p++; } *str++ = c; break; @@ -717,16 +717,16 @@ FString strbin1 (const char *start) case '6': case '7': c = 0; - for (i = 0; i < 3; i++) { - c <<= 3; + for (i = 0; i < 2; i++) + { + p++; if (*p >= '0' && *p <= '7') - c += *p-'0'; + c = (c << 3) + *p - '0'; else { p--; break; } - p++; } result << c; break; diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 6b137d12a..a598a45e9 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -1402,7 +1402,7 @@ bool DMenuItemBase::GetValue(int i, int *pvalue) { IFVIRTUAL(DMenuItemBase, GetValue) { - VMValue params[] = { (DObject*)this }; + VMValue params[] = { (DObject*)this, i }; int retval[2]; VMReturn ret[2]; ret[0].IntAt(&retval[0]); ret[1].IntAt(&retval[1]); GlobalVMStack.Call(func, params, countof(params), ret, 2, nullptr); diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index ae35935f5..d4a1254d6 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -142,8 +142,6 @@ std2: 'true' { RET(TK_True); } 'false' { RET(TK_False); } 'none' { RET(TK_None); } - 'new' { RET(TK_New); } - 'instanceof' { RET(TK_InstanceOf); } 'auto' { RET(TK_Auto); } 'exec' { RET(TK_Exec); } 'property' { RET(TK_Property); } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index 9f88e2242..0227dffa9 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -81,7 +81,6 @@ xx(TK_ForEach, "'foreach'") xx(TK_True, "'true'") xx(TK_False, "'false'") xx(TK_None, "'none'") -xx(TK_New, "'new'") xx(TK_InstanceOf, "'instanceof'") xx(TK_Auto, "'auto'") xx(TK_Exec, "'exec'") diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 1aa35895d..819cfd178 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -1009,7 +1009,7 @@ DEFINE_ACTION_FUNCTION(FStringStruct, Replace) return 0; } -static FString FStringFormat(VM_ARGS) +FString FStringFormat(VM_ARGS) { assert(param[0].Type == REGT_STRING); FString fmtstring = param[0].s().GetChars(); diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 36619ef5b..aa191c34e 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -1213,6 +1213,6 @@ class PFunction; VMFunction *FindVMFunction(PClass *cls, const char *name); #define DECLARE_VMFUNC(cls, name) static VMFunction *name; if (name == nullptr) name = FindVMFunction(RUNTIME_CLASS(cls), #name); - +FString FStringFormat(VM_ARGS); #endif diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index e7820583b..b7b356cca 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -219,6 +219,7 @@ struct Console native { native static void HideConsole(); native static void MidPrint(Font fontname, string textlabel, bool bold = false); + native static vararg void Printf(string fmt, ...); native static void DoCommand(String cmd); } diff --git a/wadsrc/static/zscript/menu/optionmenuitems.txt b/wadsrc/static/zscript/menu/optionmenuitems.txt index 7c482e3e9..61d8794ce 100644 --- a/wadsrc/static/zscript/menu/optionmenuitems.txt +++ b/wadsrc/static/zscript/menu/optionmenuitems.txt @@ -168,8 +168,7 @@ class OptionMenuItemSafeCommand : OptionMenuItemCommand String actionLabel = StringTable.localize(mLabel); String FullString; - FullString.Format("%s%s%s\n\n%s", TEXTCOLOR_WHITE, actionLabel, TEXTCOLOR_NORMAL, msg); - + FullString = String.Format("%s%s%s\n\n%s", TEXTCOLOR_WHITE, actionLabel, TEXTCOLOR_NORMAL, msg); Menu.StartMessage(FullString, 0); return true; } @@ -187,7 +186,7 @@ class OptionMenuItemOptionBase : OptionMenuItem Name mValues; // Entry in OptionValues table CVar mGrayCheck; int mCenter; - + const OP_VALUES = 0x11001; protected void Init(String label, Name command, Name values, CVar graycheck, int center) @@ -650,7 +649,7 @@ class OptionMenuSliderBase : OptionMenuItem private void DrawSlider (int x, int y, double min, double max, double cur, int fracdigits, int indent) { - String formater = String.format("%%.%f", fracdigits); // The format function cannot do the '%.*f' syntax. + String formater = String.format("%%.%df", fracdigits); // The format function cannot do the '%.*f' syntax. String textbuf; double range; int maxlen = 0; @@ -810,7 +809,7 @@ class OptionMenuItemColorPicker : OptionMenuItem { Super.Init(label, command); CVar cv = CVar.FindCVar(command); - if (cv != null && cv.GetRealType() == CVar.CVAR_Color) cv = null; + if (cv != null && cv.GetRealType() != CVar.CVAR_Color) cv = null; mCVar = cv; } @@ -823,7 +822,7 @@ class OptionMenuItemColorPicker : OptionMenuItem { int box_x = indent + CursorSpace(); int box_y = y + CleanYfac_1; - screen.Clear (box_x, box_y, box_x + 32*CleanXfac_1, box_y + OptionMenuSettings.mLinespacing*CleanYfac_1, -1, mCVar.GetInt() | 0xff000000); + screen.Clear (box_x, box_y, box_x + 32*CleanXfac_1, box_y + OptionMenuSettings.mLinespacing*CleanYfac_1, mCVar.GetInt() | 0xff000000); } return indent; } @@ -1102,7 +1101,6 @@ class OptionMenuItemTextField : OptionMenuFieldBase //Menu* input = new DTextEnterMenu (Menu.CurrentMenu, mEditName, sizeof mEditName, 2, fromcontroller); //M_ActivateMenu(input); - //OpenTextEnterMenu(mEditName, 2, fromcontroller); // needs a native workaround until menu creation is scriptable. return true; } else if (mkey == Menu.MKEY_Input) From 2e9c1ec3f3aaa740e62f08b58bc173ae72aa879f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Feb 2017 16:48:29 +0100 Subject: [PATCH 11/19] - fixed translation setup for player backdrop. - fixed return value of GetAction method of menu controls. --- src/menu/menu.cpp | 6 +- src/r_data/r_translate.cpp | 58 ++++++++---------- wadsrc/static/zscript/base.txt | 2 +- wadsrc/static/zscript/menu/playerdisplay.txt | 62 +++++++++++--------- 4 files changed, 63 insertions(+), 65 deletions(-) diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index a598a45e9..4251ebf9f 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -1271,7 +1271,7 @@ DMenuItemBase * CreateListMenuItemPatch(int x, int y, int height, int hotkey, FT { auto c = PClass::FindClass("ListMenuItemPatchItem"); auto p = c->CreateNew(); - VMValue params[] = { p, x, y, height, tex.GetIndex(), hotkey, command.GetIndex(), param }; + VMValue params[] = { p, x, y, height, tex.GetIndex(), FString(char(hotkey)), command.GetIndex(), param }; auto f = dyn_cast(c->Symbols.FindSymbol("InitDirect", false)); GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); return (DMenuItemBase*)p; @@ -1281,7 +1281,7 @@ DMenuItemBase * CreateListMenuItemText(int x, int y, int height, int hotkey, con { auto c = PClass::FindClass("ListMenuItemTextItem"); auto p = c->CreateNew(); - VMValue params[] = { p, x, y, height, hotkey, text, font, int(color1.d), int(color2.d), command.GetIndex(), param }; + VMValue params[] = { p, x, y, height, FString(char(hotkey)), text, font, int(color1.d), int(color2.d), command.GetIndex(), param }; auto f = dyn_cast(c->Symbols.FindSymbol("InitDirect", false)); GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); return (DMenuItemBase*)p; @@ -1351,7 +1351,7 @@ FName DMenuItemBase::GetAction(int *pparam) int retval[2]; VMReturn ret[2]; ret[0].IntAt(&retval[0]); ret[1].IntAt(&retval[1]); GlobalVMStack.Call(func, params, countof(params), ret, 2, nullptr); - return !!retval; + return ENamedName(retval[0]); } return NAME_None; } diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index bd31d9a30..0f4d58e6d 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -740,8 +740,6 @@ void R_InitTranslationTables () } // The menu player also gets a separate translation table PushIdentityTable(TRANSLATION_Players); - // This one is for the backdrop in the menu - PushIdentityTable(TRANSLATION_Players); // The three standard translations from Doom or Heretic (seven for Strife), // plus the generic ice translation. @@ -1227,36 +1225,6 @@ DEFINE_ACTION_FUNCTION(_Translation, SetPlayerTranslation) ACTION_RETURN_BOOL(true); } -//---------------------------------------------------------------------------- -// -// -// -//---------------------------------------------------------------------------- - -struct FTranslation -{ - PalEntry colors[256]; -}; - -DEFINE_ACTION_FUNCTION(_Translation, SetTranslation) -{ - PARAM_SELF_STRUCT_PROLOGUE(FTranslation); - PARAM_UINT(tgroup); - PARAM_UINT(tnum); - if (tgroup >= NUM_TRANSLATION_TABLES || tnum >= translationtables[tgroup].Size()) - { - ACTION_RETURN_BOOL(false); - } - auto remap = translationtables[tgroup][tnum]; - int i = 0; - for (auto p : self->colors) - { - remap->Palette[i] = p; - remap->Remap[i] = ColorMatcher.Pick(p); - } - ACTION_RETURN_BOOL(true); -} - //---------------------------------------------------------------------------- // // @@ -1364,3 +1332,29 @@ void R_ParseTrnslate() } } } + +//---------------------------------------------------------------------------- +// +// +// +//---------------------------------------------------------------------------- + +struct FTranslation +{ + PalEntry colors[256]; +}; + +DEFINE_ACTION_FUNCTION(_Translation, AddTranslation) +{ + PARAM_SELF_STRUCT_PROLOGUE(FTranslation); + + FRemapTable NewTranslation; + memcpy(&NewTranslation.Palette[0], self->colors, 256 * sizeof(PalEntry)); + for (int i = 0; i < 256; i++) + { + NewTranslation.Remap[i] = ColorMatcher.Pick(self->colors[i]); + } + int trans = NewTranslation.StoreTranslation(TRANSLATION_Custom); + ACTION_RETURN_INT(trans); +} + diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index b7b356cca..1e0d7c251 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -207,7 +207,7 @@ struct Translation { Color colors[256]; - native bool SetTranslation(int group, int num); + native int AddTranslation(); native static bool SetPlayerTranslation(int group, int num, int plrnum, PlayerClass pclass); static int MakeID(int group, int num) { diff --git a/wadsrc/static/zscript/menu/playerdisplay.txt b/wadsrc/static/zscript/menu/playerdisplay.txt index e13e9fb54..492ba978c 100644 --- a/wadsrc/static/zscript/menu/playerdisplay.txt +++ b/wadsrc/static/zscript/menu/playerdisplay.txt @@ -53,6 +53,7 @@ class ListMenuItemPlayerDisplay : ListMenuItem int mRandomClass; int mRandomTimer; int mClassNum; + int mTranslation; enum EPDFlags { @@ -81,7 +82,7 @@ class ListMenuItemPlayerDisplay : ListMenuItem int b = c1.b + c2.b * i / 255; trans.colors[i] = Color(255, r, g, b); } - trans.SetTranslation(TRANSLATION_Players, MAXPLAYERS + 1); + mTranslation = trans.AddTranslation(); mBackdrop = TexMan.CheckForTexture("PlayerBackdrop", TexMan.Type_MiscPatch); mPlayerClass = NULL; @@ -249,37 +250,40 @@ class ListMenuItemPlayerDisplay : ListMenuItem TextureID texid = TexMan.CheckForTexture(portrait, TexMan.Type_MiscPatch); screen.DrawTexture (texid, true, mXpos, mYpos, DTA_Clean, true); } - int x = (mXpos - 160) * CleanXfac + (screen.GetWidth() >> 1); - int y = (mYpos - 100) * CleanYfac + (screen.GetHeight() >> 1); - - screen.DrawTexture(mBackdrop, false, x, y - 1, - DTA_DestWidth, 72 * CleanXfac, - DTA_DestHeight, 80 * CleanYfac, - DTA_TranslationIndex, Translation.MakeID(TRANSLATION_Players, MAXPLAYERS + 1), - DTA_Masked, true); - - Screen.DrawFrame (x, y, 72*CleanXfac, 80*CleanYfac-1); - - if (mPlayerState != NULL) + else { - Vector2 Scale; - TextureID sprite; - bool flip; - - [sprite, flip, Scale] = mPlayerState.GetSpriteTexture(mRotation, mSkin, playdef.Scale); - - if (sprite.IsValid()) + int x = (mXpos - 160) * CleanXfac + (screen.GetWidth() >> 1); + int y = (mYpos - 100) * CleanYfac + (screen.GetHeight() >> 1); + + screen.DrawTexture(mBackdrop, false, x, y - 1, + DTA_DestWidth, 72 * CleanXfac, + DTA_DestHeight, 80 * CleanYfac, + DTA_TranslationIndex, mTranslation, + DTA_Masked, true); + + Screen.DrawFrame (x, y, 72*CleanXfac, 80*CleanYfac-1); + + if (mPlayerState != NULL) { - int trans = mTranslate? Translation.MakeID(TRANSLATION_Players, MAXPLAYERS) : 0; - let tscale = TexMan.GetScaledSize(sprite); - Scale.X *= CleanXfac * tscale.X; - Scale.Y *= CleanYfac * tscale.Y; + Vector2 Scale; + TextureID sprite; + bool flip; - screen.DrawTexture (sprite, false, - x + 36*CleanXfac, y + 71*CleanYfac, - DTA_DestWidthF, Scale.X, DTA_DestHeightF, Scale.Y, - DTA_TranslationIndex, trans, - DTA_FlipX, flip); + [sprite, flip, Scale] = mPlayerState.GetSpriteTexture(mRotation, mSkin, playdef.Scale); + + if (sprite.IsValid()) + { + int trans = mTranslate? Translation.MakeID(TRANSLATION_Players, MAXPLAYERS) : 0; + let tscale = TexMan.GetScaledSize(sprite); + Scale.X *= CleanXfac * tscale.X; + Scale.Y *= CleanYfac * tscale.Y; + + screen.DrawTexture (sprite, false, + x + 36*CleanXfac, y + 71*CleanYfac, + DTA_DestWidthF, Scale.X, DTA_DestHeightF, Scale.Y, + DTA_TranslationIndex, trans, + DTA_FlipX, flip); + } } } } From dbf35306965909ff9247d461e1c68e2e53ef8830 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Feb 2017 18:38:23 +0100 Subject: [PATCH 12/19] - the keybinding control works again, this time fully scripted. --- src/c_bind.cpp | 3 +- src/d_main.cpp | 7 ++ src/dobject.h | 1 + src/doomstat.h | 2 +- src/menu/colorpickermenu.cpp | 3 - src/menu/joystickmenu.cpp | 4 - src/menu/menu.cpp | 57 +++++++++- src/menu/menu.h | 6 +- src/menu/menudef.cpp | 2 - src/menu/menuinput.cpp | 2 + src/menu/optionmenuitems.h | 104 ------------------ src/menu/videomenu.cpp | 4 - src/scripting/backend/codegen.cpp | 3 +- src/scripting/thingdef_data.cpp | 3 + src/scripting/vm/vmexec.h | 7 +- src/scripting/zscript/zcc_compile.cpp | 4 + wadsrc/static/zscript/base.txt | 31 +++++- wadsrc/static/zscript/menu/menu.txt | 22 +++- .../static/zscript/menu/optionmenuitems.txt | 58 +++++----- 19 files changed, 161 insertions(+), 162 deletions(-) delete mode 100644 src/menu/optionmenuitems.h diff --git a/src/c_bind.cpp b/src/c_bind.cpp index 1c3fd5413..e6c76ab06 100644 --- a/src/c_bind.cpp +++ b/src/c_bind.cpp @@ -282,6 +282,7 @@ void C_NameKeys (char *str, int first, int second) int c = 0; *str = 0; + if (second == first) second = 0; if (first) { c++; @@ -478,7 +479,7 @@ DEFINE_ACTION_FUNCTION(FKeyBindings, GetKeysForCommand) int k1, k2, c; self->GetKeysForCommand(cmd.GetChars(), &k1, &k2); if (numret > 0) ret[0].SetInt(k1); - if (numret > 1) ret[1].SetInt(k1); + if (numret > 1) ret[1].SetInt(k2); return MIN(numret, 2); } diff --git a/src/d_main.cpp b/src/d_main.cpp index b5d5e7032..56b602637 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2830,3 +2830,10 @@ void FStartupScreen::NetMessage(char const *,...) {} void FStartupScreen::NetDone(void) {} bool FStartupScreen::NetLoop(bool (*)(void *),void *) { return false; } +DEFINE_FIELD_X(InputEvent, event_t, type) +DEFINE_FIELD_X(InputEvent, event_t, subtype) +DEFINE_FIELD_X(InputEvent, event_t, data1) +DEFINE_FIELD_X(InputEvent, event_t, data2) +DEFINE_FIELD_X(InputEvent, event_t, data3) +DEFINE_FIELD_X(InputEvent, event_t, x) +DEFINE_FIELD_X(InputEvent, event_t, y) diff --git a/src/dobject.h b/src/dobject.h index 6797d2436..670605093 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -204,6 +204,7 @@ enum EObjectFlags OF_Sentinel = 1 << 10, // Object is serving as the sentinel in a ring list OF_Transient = 1 << 11, // Object should not be archived (references to it will be nulled on disk) OF_Released = 1 << 12, // Object was released from the GC system and should not be processed by GC function + OF_Abstract = 1 << 13, // Marks a class that cannot be created with CreateNew }; template class TObjPtr; diff --git a/src/doomstat.h b/src/doomstat.h index 22ee4fdb4..ee7b7d210 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -101,7 +101,7 @@ EXTERN_CVAR (Float, snd_musicvolume) // maximum volume for music // Status flags for refresh. // -enum EMenuState +enum EMenuState : int { MENU_Off, // Menu is closed MENU_On, // Menu is opened diff --git a/src/menu/colorpickermenu.cpp b/src/menu/colorpickermenu.cpp index d0718c1a9..bbd52f438 100644 --- a/src/menu/colorpickermenu.cpp +++ b/src/menu/colorpickermenu.cpp @@ -48,9 +48,6 @@ #include "d_event.h" #include "d_gui.h" -#define NO_IMP -#include "menu/optionmenuitems.h" - class DColorPickerMenu : public DOptionMenu { DECLARE_CLASS(DColorPickerMenu, DOptionMenu) diff --git a/src/menu/joystickmenu.cpp b/src/menu/joystickmenu.cpp index 24474bc43..9e9aacde8 100644 --- a/src/menu/joystickmenu.cpp +++ b/src/menu/joystickmenu.cpp @@ -51,10 +51,6 @@ #include "i_music.h" #include "m_joy.h" -#define NO_IMP -#include "optionmenuitems.h" - - static TArray Joysticks; IJoystickConfig *SELECTED_JOYSTICK; diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 4251ebf9f..0653cc9ec 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -191,6 +191,26 @@ bool DMenu::Responder (event_t *ev) return false; } +DEFINE_ACTION_FUNCTION(DMenu, Responder) +{ + PARAM_SELF_PROLOGUE(DMenu); + PARAM_POINTER(ev, event_t); + ACTION_RETURN_BOOL(self->Responder(ev)); +} + +bool DMenu::CallResponder(event_t *ev) +{ + IFVIRTUAL(DMenu, Responder) + { + VMValue params[] = { (DObject*)this, ev}; + int retval; + VMReturn ret(&retval); + GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr); + return !!retval; + } + else return Responder(ev); +} + //============================================================================= // // @@ -386,6 +406,20 @@ void DMenu::CallDrawer() else Drawer(); } +DEFINE_ACTION_FUNCTION(DMenu, Close) +{ + PARAM_SELF_PROLOGUE(DMenu); + self->Close(); + return 0; +} + +DEFINE_ACTION_FUNCTION(DMenu, GetItem) +{ + PARAM_SELF_PROLOGUE(DMenu); + PARAM_NAME(name); + ACTION_RETURN_POINTER(self->GetItem(name)); +} + bool DMenu::DimAllowed() @@ -395,6 +429,14 @@ bool DMenu::DimAllowed() bool DMenu::TranslateKeyboardEvents() { + IFVIRTUAL(DMenu, TranslateKeyboardEvents) + { + VMValue params[] = { (DObject*)this }; + int retval; + VMReturn ret(&retval); + GlobalVMStack.Call(func, params, countof(params), &ret, 1, nullptr); + return !!retval; + } return true; } @@ -444,6 +486,13 @@ void M_ActivateMenu(DMenu *menu) GC::WriteBarrier(DMenu::CurrentMenu); } +DEFINE_ACTION_FUNCTION(DMenu, ActivateMenu) +{ + PARAM_SELF_PROLOGUE(DMenu); + M_ActivateMenu(self); + return 0; +} + //============================================================================= // // @@ -631,7 +680,7 @@ bool M_Responder (event_t *ev) } // pass everything else on to the current menu - return DMenu::CurrentMenu->Responder(ev); + return DMenu::CurrentMenu->CallResponder(ev); } else if (DMenu::CurrentMenu->TranslateKeyboardEvents()) { @@ -652,7 +701,7 @@ bool M_Responder (event_t *ev) default: if (!keyup) { - return DMenu::CurrentMenu->Responder(ev); + return DMenu::CurrentMenu->CallResponder(ev); } break; } @@ -739,7 +788,7 @@ bool M_Responder (event_t *ev) return true; } } - return DMenu::CurrentMenu->Responder(ev) || !keyup; + return DMenu::CurrentMenu->CallResponder(ev) || !keyup; } else if (MenuEnabled) { @@ -1094,6 +1143,8 @@ CCMD(reset2saved) //native void OptionMenuDescriptor.CalcIndent(); //native OptionMenuItem OptionMenuDescriptor.GetItem(Name iname); +DEFINE_FIELD(DMenu, mParentMenu) + DEFINE_FIELD(DMenuDescriptor, mMenuName) DEFINE_FIELD(DMenuDescriptor, mNetgameMessage) DEFINE_FIELD(DMenuDescriptor, mClass) diff --git a/src/menu/menu.h b/src/menu/menu.h index e4d449237..1d7f6def9 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -269,7 +269,7 @@ public: virtual void Ticker (); virtual void Drawer (); virtual bool DimAllowed (); - virtual bool TranslateKeyboardEvents(); + /*virtual */bool TranslateKeyboardEvents(); virtual void Close(); virtual bool MouseEvent(int type, int x, int y); @@ -277,7 +277,9 @@ public: virtual bool CheckFocus(DMenuItemBase *fc) { return false; } virtual void ReleaseFocus() {} + virtual DMenuItemBase *GetItem(FName name) { return nullptr; } + bool CallResponder(event_t *ev); bool CallMenuEvent(int mkey, bool fromcontroller); bool CallMouseEvent(int type, int x, int y); void CallDrawer(); @@ -466,7 +468,7 @@ public: void Drawer (); bool MenuEvent (int mkey, bool fromcontroller); bool Responder(event_t *ev); - bool TranslateKeyboardEvents(); + //bool TranslateKeyboardEvents(); bool MouseEvent(int type, int x, int y); }; diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index aec60af91..f02203841 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -52,8 +52,6 @@ #include "i_sound.h" #include "cmdlib.h" -#include "optionmenuitems.h" - void ClearSaveGames(); diff --git a/src/menu/menuinput.cpp b/src/menu/menuinput.cpp index 67f34635e..e28b141a1 100644 --- a/src/menu/menuinput.cpp +++ b/src/menu/menuinput.cpp @@ -96,10 +96,12 @@ DTextEnterMenu::DTextEnterMenu(DMenu *parent, char *textbuffer, int maxlen, int // //============================================================================= +/* bool DTextEnterMenu::TranslateKeyboardEvents() { return mInputGridOkay; } +*/ //============================================================================= // diff --git a/src/menu/optionmenuitems.h b/src/menu/optionmenuitems.h deleted file mode 100644 index b79d5f70e..000000000 --- a/src/menu/optionmenuitems.h +++ /dev/null @@ -1,104 +0,0 @@ -/* -** optionmenuitems.h -** Control items for option menus -** -**--------------------------------------------------------------------------- -** Copyright 2010 Christoph Oelckers -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ -#include "v_text.h" -#include "gstrings.h" - - -void M_DrawConText (int color, int x, int y, const char *str); -void M_SetVideoMode(); - -//============================================================================= -// -// This class is used to capture the key to be used as the new key binding -// for a control item -// -//============================================================================= - -class DEnterKey : public DMenu -{ - DECLARE_CLASS(DEnterKey, DMenu) - - int *pKey; - -public: - DEnterKey(DMenu *parent, int *keyptr) - : DMenu(parent) - { - pKey = keyptr; - SetMenuMessage(1); - menuactive = MENU_WaitKey; // There should be a better way to disable GUI capture... - } - - bool TranslateKeyboardEvents() - { - return false; - } - - void SetMenuMessage(int which) - { - if (mParentMenu->IsKindOf(RUNTIME_CLASS(DOptionMenu))) - { - DOptionMenu *m = barrier_cast(mParentMenu); - DMenuItemBase *it = m->GetItem(NAME_Controlmessage); - if (it != NULL) - { - it->SetValue(0, which); - } - } - } - - bool Responder(event_t *ev) - { - if (ev->type == EV_KeyDown) - { - *pKey = ev->data1; - menuactive = MENU_On; - SetMenuMessage(0); - Close(); - mParentMenu->CallMenuEvent((ev->data1 == KEY_ESCAPE)? MKEY_Abort : MKEY_Input, 0); - return true; - } - return false; - } - - void Drawer() - { - mParentMenu->CallDrawer(); - } -}; - -#ifndef NO_IMP -IMPLEMENT_CLASS(DEnterKey, true, false) -#endif - diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp index 0ecb23b87..1dc3a5c0e 100644 --- a/src/menu/videomenu.cpp +++ b/src/menu/videomenu.cpp @@ -54,10 +54,6 @@ #include "sbar.h" #include "hardware.h" -#define NO_IMP -#include "optionmenuitems.h" - - /*======================================= * * Video Modes Menu diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index d6b89c1a0..d991d1459 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -5069,7 +5069,6 @@ FxExpression *FxNew::Resolve(FCompileContext &ctx) ExpEmit FxNew::Emit(VMFunctionBuilder *build) { - assert(ValueType == val->ValueType); ExpEmit from = val->Emit(build); from.Free(build); ExpEmit to(build, REGT_POINTER); @@ -10167,6 +10166,8 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) ScriptPosition.Message(MSG_OPTERROR, "Unknown class name '%s' of type '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); + delete this; + return nullptr; } else { diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 819cfd178..f257c7c2d 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -882,6 +882,9 @@ void InitThingdef() fieldptr = new PField("CleanHeight_1", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&CleanHeight_1); Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr); + fieldptr = new PField("menuactive", TypeSInt32, VARF_Native | VARF_Static, (intptr_t)&menuactive); + Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr); + fieldptr = new PField("OptionMenuSettings", NewStruct("FOptionMenuSettings", nullptr), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&OptionSettings); Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr); diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index b9f8e81ca..8da2c4d8d 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -785,8 +785,11 @@ begin: OP(NEW_K): OP(NEW): { - PClass *cls = (PClass*)(pc->op == OP_NEW ? reg.a[C] : konsta[C].v); - reg.a[B] = cls->CreateNew(); + b = B; + PClass *cls = (PClass*)(pc->op == OP_NEW ? reg.a[b] : konsta[b].v); + if (cls->ObjectFlags & OF_Abstract) ThrowAbortException(X_OTHER, "Cannot instantiate abstract class %s", cls->TypeName.GetChars()); + reg.a[a] = cls->CreateNew(); + reg.atag[a] = ATAG_OBJECT; NEXTOP; } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 4972e1344..517f62654 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -597,6 +597,10 @@ void ZCCCompiler::CreateClassTypes() c->cls->Type = nullptr; } } + if (c->cls->Flags & ZCC_Abstract) + { + c->Type()->ObjectFlags |= OF_Abstract; + } if (c->Type() == nullptr) c->cls->Type = parent->FindClassTentative(c->NodeName()); c->Type()->bExported = true; // this class is accessible to script side type casts. (The reason for this flag is that types like PInt need to be skipped.) c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type()); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 1e0d7c251..2d79a2916 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -1,3 +1,26 @@ +struct InputEvent native +{ + native uint8 type; + native uint8 subtype; + native int16 data1; // keys / mouse/joystick buttons + native int16 data2; + native int16 data3; + native int x; // mouse/joystick x move + native int y; // mouse/joystick y move + + enum EGenericEvent + { + NoEvent, + KeyDown, // data1: scan code, data2: Qwerty ASCII code + KeyUp, // same + Mouse, // x, y: mouse movement deltas + GUI_Event, // subtype specifies actual event + DeviceChange,// a device has been connected or removed + } + + const KEY_ESCAPE = 0x01; +} + struct TexMan { enum EUseTypes @@ -540,7 +563,7 @@ class Floor : Thinker native floorRaiseInstant, floorMoveToValue, floorRaiseToLowestCeiling, - floorRaiseByTexture, + floorRaiseuint8xture, floorLowerAndChange, floorRaiseAndChange, @@ -548,7 +571,7 @@ class Floor : Thinker native floorRaiseToLowest, floorRaiseToCeiling, floorLowerToLowestCeiling, - floorLowerByTexture, + floorLoweruint8xture, floorLowerToCeiling, donutRaise, @@ -591,8 +614,8 @@ class Ceiling : Thinker native ceilLowerToNearest, ceilRaiseToHighestFloor, ceilRaiseToFloor, - ceilRaiseByTexture, - ceilLowerByTexture, + ceilRaiseuint8xture, + ceilLoweruint8xture, genCeilingChg0, genCeilingChgT, diff --git a/wadsrc/static/zscript/menu/menu.txt b/wadsrc/static/zscript/menu/menu.txt index 511615fea..2f07ffed0 100644 --- a/wadsrc/static/zscript/menu/menu.txt +++ b/wadsrc/static/zscript/menu/menu.txt @@ -73,6 +73,21 @@ class Menu : Object native MOUSE_Release }; + enum EMenuState + { + Off, // Menu is closed + On, // Menu is opened + WaitKey, // Menu is opened and waiting for a key in the controls menu + OnNoPause, // Menu is opened but does not pause the game + }; + + native Menu mParentMenu; + + void Init(Menu parent) + { + mParentMenu = parent; + } + native static int MenuTime(); native static void SetVideoMode(); native static Menu GetCurrentMenu(); @@ -80,13 +95,18 @@ class Menu : Object native native static void SetMenu(Name mnu, int param = 0); native static void StartMessage(String msg, int mode = 0, Name command = 'none'); + virtual bool TranslateKeyboardEvents() { return true; } virtual void SetFocus(MenuItemBase fc) {} virtual bool CheckFocus(MenuItemBase fc) { return false; } virtual void ReleaseFocus() {} - + + native virtual bool Responder(InputEvent ev); native virtual bool MenuEvent (int mkey, bool fromcontroller); native virtual bool MouseEvent(int type, int mx, int my); native virtual void Drawer(); + native void Close(); + native MenuItemBase GetItem(Name n); + native void ActivateMenu(); static void MenuSound(Sound snd) { diff --git a/wadsrc/static/zscript/menu/optionmenuitems.txt b/wadsrc/static/zscript/menu/optionmenuitems.txt index 61d8794ce..69860af57 100644 --- a/wadsrc/static/zscript/menu/optionmenuitems.txt +++ b/wadsrc/static/zscript/menu/optionmenuitems.txt @@ -354,33 +354,29 @@ class OptionMenuItemOption : OptionMenuItemOptionBase // //============================================================================= -/* This will have to wait. -class DEnterKey : Menu +class EnterKey : Menu { - DECLARE_CLASS(DEnterKey, Menu) + OptionMenuItemControlBase mOwner; - int *pKey; - - - DEnterKey(Menu *parent, int *keyptr) - : Menu(parent) + void Init(Menu parent, OptionMenuItemControlBase owner) { - pKey = keyptr; + Super.Init(parent); + mOwner = owner; SetMenuMessage(1); - menuactive = MENU_WaitKey; // There should be a better way to disable GUI capture... + menuactive = Menu.WaitKey; // There should be a better way to disable GUI capture... } - bool TranslateKeyboardEvents() + override bool TranslateKeyboardEvents() { return false; } - void SetMenuMessage(int which) + private void SetMenuMessage(int which) { - if (mParentMenu.IsKindOf(RUNTIME_CLASS(OptionMenu))) + let parent = OptionMenu(mParentMenu); + if (parent != null) { - OptionMenu *m = barrier_cast(mParentMenu); - MenuItemBase *it = m.GetItem(NAME_Controlmessage); + let it = parent.GetItem('Controlmessage'); if (it != null) { it.SetValue(0, which); @@ -388,30 +384,26 @@ class DEnterKey : Menu } } - bool Responder(event_t *ev) + override bool Responder(InputEvent ev) { - if (ev.type == EV_KeyDown) + // This checks raw keys, not GUI keys. + if (ev.type == InputEvent.KeyDown) { - *pKey = ev.data1; - menuactive = MENU_On; + mOwner.SendKey(ev.data1); + menuactive = Menu.On; SetMenuMessage(0); Close(); - mParentMenu.CallMenuEvent((ev.data1 == KEY_ESCAPE)? Menu.MKEY_Abort : Menu.MKEY_Input, 0); + mParentMenu.MenuEvent((ev.data1 == InputEvent.KEY_ESCAPE)? Menu.MKEY_Abort : Menu.MKEY_Input, 0); return true; } return false; } - void Drawer() + override void Drawer() { - mParentMenu.CallDrawer(); + mParentMenu.Drawer(); } -}; - -#ifndef NO_IMP -IMPLEMENT_CLASS(DEnterKey, true, false) -#endif -*/ +} //============================================================================= // @@ -475,13 +467,19 @@ class OptionMenuItemControlBase : OptionMenuItem } return false; } + + void SendKey(int key) + { + mInput = key; + } override bool Activate() { Menu.MenuSound("menu/choose"); mWaiting = true; - //Menu *input = new DEnterKey(Menu.CurrentMenu, &mInput); - //M_ActivateMenu(input); + let input = new("EnterKey"); + input.Init(Menu.GetCurrentMenu(), self); + input.ActivateMenu(); return true; } } From f0e925c5a79728922adf8a85b954125c9713ccea Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Feb 2017 20:20:47 +0100 Subject: [PATCH 13/19] - scripted color picker fully working. --- src/CMakeLists.txt | 1 - src/menu/colorpickermenu.cpp | 151 ------------------ src/menu/menu.cpp | 23 +++ src/menu/optionmenu.cpp | 7 + src/scripting/zscript/zcc_compile.cpp | 1 + wadsrc/static/zscript.txt | 1 + .../static/zscript/menu/colorpickermenu.txt | 75 +++++++-- wadsrc/static/zscript/menu/menu.txt | 47 +++++- .../static/zscript/menu/optionmenuitems.txt | 69 +++++--- 9 files changed, 186 insertions(+), 189 deletions(-) delete mode 100644 src/menu/colorpickermenu.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9448006e4..b41b87cc1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -839,7 +839,6 @@ set( FASTMATH_PCH_SOURCES SkylineBinPack.cpp intermission/intermission.cpp intermission/intermission_parse.cpp - menu/colorpickermenu.cpp menu/joystickmenu.cpp menu/listmenu.cpp menu/loadsavemenu.cpp diff --git a/src/menu/colorpickermenu.cpp b/src/menu/colorpickermenu.cpp deleted file mode 100644 index bbd52f438..000000000 --- a/src/menu/colorpickermenu.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* -** colorpickermenu.cpp -** The color picker menu -** -**--------------------------------------------------------------------------- -** Copyright 2010 Christoph Oelckers -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ -#include - -#include "menu/menu.h" -#include "c_dispatch.h" -#include "w_wad.h" -#include "sc_man.h" -#include "v_font.h" -#include "g_level.h" -#include "d_player.h" -#include "v_video.h" -#include "gi.h" -#include "i_system.h" -#include "c_bind.h" -#include "v_palette.h" -#include "d_event.h" -#include "d_gui.h" - -class DColorPickerMenu : public DOptionMenu -{ - DECLARE_CLASS(DColorPickerMenu, DOptionMenu) - -public: - - float mRed; - float mGreen; - float mBlue; - - int mGridPosX; - int mGridPosY; - - int mStartItem; - - FColorCVar *mCVar; - - DColorPickerMenu(DMenu *parent, const char *name, DOptionMenuDescriptor *desc, FColorCVar *cvar) - { - mStartItem = desc->mItems.Size(); - mRed = (float)RPART(DWORD(*cvar)); - mGreen = (float)GPART(DWORD(*cvar)); - mBlue = (float)BPART(DWORD(*cvar)); - mGridPosX = 0; - mGridPosY = 0; - mCVar = cvar; - - // This menu uses some featurs that are hard to implement in an external control lump - // so it creates its own list of menu items. - desc->mItems.Resize(mStartItem+8); - desc->mItems[mStartItem+0] = CreateOptionMenuItemStaticText(name, false); - desc->mItems[mStartItem+1] = CreateOptionMenuItemStaticText(" ", false); - desc->mItems[mStartItem+2] = CreateOptionMenuSliderVar("Red", 0, 0, 255, 15, 0); - desc->mItems[mStartItem+3] = CreateOptionMenuSliderVar("Green", 1, 0, 255, 15, 0); - desc->mItems[mStartItem+4] = CreateOptionMenuSliderVar("Blue", 2, 0, 255, 15, 0); - desc->mItems[mStartItem+5] = CreateOptionMenuItemStaticText(" ", false); - desc->mItems[mStartItem+6] = CreateOptionMenuItemCommand("Undo changes", "undocolorpic"); - desc->mItems[mStartItem+7] = CreateOptionMenuItemStaticText(" ", false); - for (auto &p : desc->mItems) - { - GC::WriteBarrier(p); - } - desc->mSelectedItem = mStartItem + 2; - Init(parent, desc); - desc->mIndent = 0; - desc->CalcIndent(); - } - - void OnDestroy() override - { - if (mStartItem >= 0) - { - mDesc->mItems.Resize(mStartItem); - UCVarValue val; - val.Int = MAKERGB(int(mRed), int(mGreen), int(mBlue)); - if (mCVar != NULL) mCVar->SetGenericRep (val, CVAR_Int); - mStartItem = -1; - } - } - - void Reset() - { - mRed = (float)RPART(DWORD(*mCVar)); - mGreen = (float)GPART(DWORD(*mCVar)); - mBlue = (float)BPART(DWORD(*mCVar)); - } - -}; - -IMPLEMENT_CLASS(DColorPickerMenu, true, false) - -CCMD(undocolorpic) -{ - if (DMenu::CurrentMenu != NULL && DMenu::CurrentMenu->IsKindOf(RUNTIME_CLASS(DColorPickerMenu))) - { - static_cast(DMenu::CurrentMenu)->Reset(); - } -} - - -DMenu *StartPickerMenu(DMenu *parent, const char *name, FColorCVar *cvar) -{ - DMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_Colorpickermenu); - if (desc != NULL && (*desc)->IsKindOf(RUNTIME_CLASS(DOptionMenuDescriptor))) - { - return new DColorPickerMenu(parent, name, (DOptionMenuDescriptor*)(*desc), cvar); - } - else - { - return NULL; - } -} - - -DEFINE_FIELD(DColorPickerMenu, mRed); -DEFINE_FIELD(DColorPickerMenu, mGreen); -DEFINE_FIELD(DColorPickerMenu, mBlue); -DEFINE_FIELD(DColorPickerMenu, mGridPosX); -DEFINE_FIELD(DColorPickerMenu, mGridPosY); -DEFINE_FIELD(DColorPickerMenu, mStartItem); -DEFINE_FIELD(DColorPickerMenu, mCVar); diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 0653cc9ec..595563c0d 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -107,6 +107,14 @@ IMPLEMENT_CLASS(DMenuDescriptor, false, false) IMPLEMENT_CLASS(DListMenuDescriptor, false, false) IMPLEMENT_CLASS(DOptionMenuDescriptor, false, false) +DEFINE_ACTION_FUNCTION(DMenuDescriptor, GetDescriptor) +{ + PARAM_PROLOGUE; + PARAM_NAME(name); + DMenuDescriptor **desc = MenuDescriptors.CheckKey(name); + auto retn = desc ? *desc : nullptr; + ACTION_RETURN_POINTER(retn); +} size_t DListMenuDescriptor::PropagateMark() { @@ -1139,6 +1147,21 @@ CCMD(reset2saved) } +// This really should be in the script but we can't do scripted CCMDs yet. +CCMD(undocolorpic) +{ + if (DMenu::CurrentMenu != NULL) + { + IFVIRTUALPTR(DMenu::CurrentMenu, DMenu, ResetColor) + { + VMValue params[] = { (DObject*)DMenu::CurrentMenu }; + GlobalVMStack.Call(func, params, countof(params), nullptr, 0, nullptr); + } + } +} + + + //native void OptionMenuDescriptor.CalcIndent(); //native OptionMenuItem OptionMenuDescriptor.GetItem(Name iname); diff --git a/src/menu/optionmenu.cpp b/src/menu/optionmenu.cpp index bc4c7974e..57248f891 100644 --- a/src/menu/optionmenu.cpp +++ b/src/menu/optionmenu.cpp @@ -487,6 +487,13 @@ void DOptionMenuDescriptor::CalcIndent() mIndent = widest + 4; } +DEFINE_ACTION_FUNCTION(DOptionMenuDescriptor, CalcIndent) +{ + PARAM_SELF_PROLOGUE(DOptionMenuDescriptor); + self->CalcIndent(); + return 0; +} + //============================================================================= // // diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 517f62654..500336df5 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -589,6 +589,7 @@ void ZCCCompiler::CreateClassTypes() { Error(c->cls, "Class name %s already exists", c->NodeName().GetChars()); } + else DPrintf(DMSG_SPAMMY, "Created class %s with parent %s\n", c->Type()->TypeName.GetChars(), c->Type()->ParentClass->TypeName.GetChars()); } catch (CRecoverableError &err) { diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 8774f2a7b..637d5b66e 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -10,6 +10,7 @@ #include "zscript/menu/menu.txt" #include "zscript/menu/listmenuitems.txt" #include "zscript/menu/optionmenuitems.txt" +#include "zscript/menu/colorpickermenu.txt" #include "zscript/menu/joystickmenu.txt" #include "zscript/menu/playerdisplay.txt" #include "zscript/menu/playermenu.txt" diff --git a/wadsrc/static/zscript/menu/colorpickermenu.txt b/wadsrc/static/zscript/menu/colorpickermenu.txt index ff21e1b8e..93a2399a5 100644 --- a/wadsrc/static/zscript/menu/colorpickermenu.txt +++ b/wadsrc/static/zscript/menu/colorpickermenu.txt @@ -43,10 +43,11 @@ class OptionMenuSliderVar : OptionMenuSliderBase { int mIndex; - void Init(String label, int index, double min, double max, double step, int showval) + OptionMenuSliderVar Init(String label, int index, double min, double max, double step, int showval) { Super.Init(label, min, max, step, showval); mIndex = index; + return self; } override double GetSliderValue() @@ -60,19 +61,18 @@ class OptionMenuSliderVar : OptionMenuSliderBase } } - -class ColorpickerMenu : Menu native +class ColorpickerMenu : OptionMenu { - native float mRed; - native float mGreen; - native float mBlue; + float mRed; + float mGreen; + float mBlue; - native int mGridPosX; - native int mGridPosY; + int mGridPosX; + int mGridPosY; - native int mStartItem; + int mStartItem; - native CVar mCVar; + CVar mCVar; double GetColor(int index) { @@ -86,6 +86,40 @@ class ColorpickerMenu : Menu native else if (index == 1) mGreen = val; else mBlue = val; } + + //============================================================================= + // + // + // + //============================================================================= + + void Init(Menu parent, String name, OptionMenuDescriptor desc, CVar cv) + { + Super.Init(parent, desc); + + mStartItem = mDesc.mItems.Size(); + mCVar = cv; + + ResetColor(); + mGridPosX = 0; + mGridPosY = 0; + + // This menu uses some features that are hard to implement in an external control lump + // so it creates its own list of menu items. + mDesc.mItems.Resize(mStartItem+8); + mDesc.mItems[mStartItem+0] = new ("OptionMenuItemStaticText").Init(name, false); + mDesc.mItems[mStartItem+1] = new ("OptionMenuItemStaticText").Init(" ", false); + mDesc.mItems[mStartItem+2] = new ("OptionMenuSliderVar").Init("Red", 0, 0, 255, 15, 0); + mDesc.mItems[mStartItem+3] = new ("OptionMenuSliderVar").Init("Green", 1, 0, 255, 15, 0); + mDesc.mItems[mStartItem+4] = new ("OptionMenuSliderVar").Init("Blue", 2, 0, 255, 15, 0); + mDesc.mItems[mStartItem+5] = new ("OptionMenuItemStaticText").Init(" ", false); + mDesc.mItems[mStartItem+6] = new ("OptionMenuItemCommand").Init("Undo changes", "undocolorpic"); + mDesc.mItems[mStartItem+7] = new ("OptionMenuItemStaticText").Init(" ", false); + mDesc.mSelectedItem = mStartItem + 2; + mDesc.mIndent = 0; + mDesc.CalcIndent(); + } + //============================================================================= // // @@ -297,5 +331,24 @@ class ColorpickerMenu : Menu native screen.DrawText (SmallFont, Font.CR_WHITE, x+(48+24-SmallFont.StringWidth("New")/2)*CleanXfac_1, y, "New", DTA_CleanNoMove_1, true); } - + override void OnDestroy() + { + if (mStartItem >= 0) + { + mDesc.mItems.Resize(mStartItem); + if (mCVar != null) mCVar.SetInt(Color(int(mRed), int(mGreen), int(mBlue))); + mStartItem = -1; + } + } + + override void ResetColor() + { + if (mCVar != null) + { + Color clr = Color(mCVar.GetInt()); + mRed = clr.r; + mGreen = clr.g; + mBlue = clr.b; + } + } } \ No newline at end of file diff --git a/wadsrc/static/zscript/menu/menu.txt b/wadsrc/static/zscript/menu/menu.txt index 2f07ffed0..add8c8cb9 100644 --- a/wadsrc/static/zscript/menu/menu.txt +++ b/wadsrc/static/zscript/menu/menu.txt @@ -99,6 +99,7 @@ class Menu : Object native virtual void SetFocus(MenuItemBase fc) {} virtual bool CheckFocus(MenuItemBase fc) { return false; } virtual void ReleaseFocus() {} + virtual void ResetColor() {} native virtual bool Responder(InputEvent ev); native virtual bool MenuEvent (int mkey, bool fromcontroller); @@ -125,6 +126,8 @@ class MenuDescriptor : Object native native Name mMenuName; native String mNetgameMessage; native Class mClass; + + native static MenuDescriptor GetDescriptor(Name n); } class ListMenuDescriptor : MenuDescriptor native @@ -185,7 +188,7 @@ class OptionMenuDescriptor : MenuDescriptor native native int mPosition; native bool mDontDim; - //native void CalcIndent(); + native void CalcIndent(); //native OptionMenuItem GetItem(Name iname); void Reset() { @@ -199,24 +202,64 @@ class OptionMenuDescriptor : MenuDescriptor native class OptionMenu : Menu native { + native OptionMenuDescriptor mDesc; native bool CanScrollUp; native bool CanScrollDown; native int VisBottom; native OptionMenuItem mFocusControl; - native OptionMenuDescriptor mDesc; + + //============================================================================= + // + // + // + //============================================================================= + + void Init(Menu parent, OptionMenuDescriptor desc) + { + mParentMenu = parent; + mDesc = desc; + if (mDesc != NULL && mDesc.mSelectedItem == -1) mDesc.mSelectedItem = FirstSelectable(); + + } + + //============================================================================= + // + // + // + //============================================================================= + + int FirstSelectable() + { + if (mDesc != NULL) + { + // Go down to the first selectable item + int i = -1; + do + { + i++; + } + while (i < mDesc.mItems.Size() && !mDesc.mItems[i].Selectable()); + if (i>=0 && i < mDesc.mItems.Size()) return i; + } + return -1; + } + override void SetFocus(MenuItemBase fc) { mFocusControl = OptionMenuItem(fc); } + override bool CheckFocus(MenuItemBase fc) { return mFocusControl == fc; } + override void ReleaseFocus() { mFocusControl = NULL; } + } diff --git a/wadsrc/static/zscript/menu/optionmenuitems.txt b/wadsrc/static/zscript/menu/optionmenuitems.txt index 69860af57..338c36599 100644 --- a/wadsrc/static/zscript/menu/optionmenuitems.txt +++ b/wadsrc/static/zscript/menu/optionmenuitems.txt @@ -37,7 +37,7 @@ class OptionMenuItem : MenuItemBase String mLabel; bool mCentered; - void Init(String label, String command, bool center = false) + protected void Init(String label, String command, bool center = false) { Super.Init(0, 0, command); mLabel = label; @@ -92,10 +92,11 @@ class OptionMenuItem : MenuItemBase class OptionMenuItemSubmenu : OptionMenuItem { int mParam; - void Init(String label, Name command, int param = 0) + OptionMenuItemSubmenu Init(String label, Name command, int param = 0) { Super.init(label, command); mParam = param; + return self; } override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) @@ -120,9 +121,10 @@ class OptionMenuItemSubmenu : OptionMenuItem class OptionMenuItemCommand : OptionMenuItemSubmenu { - void Init(String label, Name command) + OptionMenuItemCommand Init(String label, Name command) { Super.Init(label, command); + return self; } override bool Activate() @@ -145,10 +147,11 @@ class OptionMenuItemSafeCommand : OptionMenuItemCommand String mPrompt; - void Init(String label, Name command, String prompt = "") + OptionMenuItemSafeCommand Init(String label, Name command, String prompt = "") { Super.Init(label, command); mPrompt = prompt; + return self; } override bool MenuEvent (int mkey, bool fromcontroller) @@ -289,10 +292,11 @@ class OptionMenuItemOption : OptionMenuItemOptionBase { CVar mCVar; - void Init(String label, Name command, Name values, CVar graycheck = null, int center = 0) + OptionMenuItemOption Init(String label, Name command, Name values, CVar graycheck = null, int center = 0) { Super.Init(label, command, values, graycheck, center); mCVar = CVar.FindCVar(mAction); + return self; } //============================================================================= @@ -417,7 +421,7 @@ class OptionMenuItemControlBase : OptionMenuItem int mInput; bool mWaiting; - void Init(String label, Name command, KeyBindings bindings) + protected void Init(String label, Name command, KeyBindings bindings) { Super.init(label, command); mBindings = bindings; @@ -486,17 +490,19 @@ class OptionMenuItemControlBase : OptionMenuItem class OptionMenuItemControl : OptionMenuItemControlBase { - void Init(String label, Name command) + OptionMenuItemControl Init(String label, Name command) { Super.Init(label, command, Bindings); + return self; } } class OptionMenuItemMapControl : OptionMenuItemControlBase { - void Init(String label, Name command) + OptionMenuItemMapControl Init(String label, Name command) { Super.Init(label, command, AutomapBindings); + return self; } } @@ -511,18 +517,20 @@ class OptionMenuItemStaticText : OptionMenuItem int mColor; // this function is only for use from MENUDEF, it needs to do some strange things with the color for backwards compatibility. - void Init(String label, int cr = -1) + OptionMenuItemStaticText Init(String label, int cr = -1) { Super.Init(label, 'None', true); mColor = OptionMenuSettings.mFontColor; if ((cr & 0xffff0000) == 0x12340000) mColor = cr & 0xffff; else if (cr > 0) mColor = OptionMenuSettings.mFontColorHeader; + return self; } - void InitDirect(String label, int cr) + OptionMenuItemStaticText InitDirect(String label, int cr) { Super.Init(label, 'None', true); mColor = cr; + return self; } override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) @@ -551,7 +559,7 @@ class OptionMenuItemStaticTextSwitchable : OptionMenuItem int mCurrent; // this function is only for use from MENUDEF, it needs to do some strange things with the color for backwards compatibility. - void Init(String label, String label2, Name command, int cr = -1) + OptionMenuItemStaticTextSwitchable Init(String label, String label2, Name command, int cr = -1) { Super.Init(label, command, true); mAltText = label2; @@ -560,14 +568,16 @@ class OptionMenuItemStaticTextSwitchable : OptionMenuItem mColor = OptionMenuSettings.mFontColor; if ((cr & 0xffff0000) == 0x12340000) mColor = cr & 0xffff; else if (cr > 0) mColor = OptionMenuSettings.mFontColorHeader; + return self; } - void InitDirect(String label, String label2, Name command, int cr) + OptionMenuItemStaticTextSwitchable InitDirect(String label, String label2, Name command, int cr) { Super.Init(label, command, true); mColor = cr; mAltText = label2; mCurrent = 0; + return self; } override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) @@ -764,10 +774,11 @@ class OptionMenuItemSlider : OptionMenuSliderBase { CVar mCVar; - void Init(String label, Name command, double min, double max, double step, int showval = 1) + OptionMenuItemSlider Init(String label, Name command, double min, double max, double step, int showval = 1) { Super.Init(label, min, max, step, showval); mCVar =CVar.FindCVar(command); + return self; } override double GetSliderValue() @@ -803,12 +814,13 @@ class OptionMenuItemColorPicker : OptionMenuItem const CPF_RESET = 0x20001; - void Init(String label, Name command) + OptionMenuItemColorPicker Init(String label, Name command) { Super.Init(label, command); CVar cv = CVar.FindCVar(command); if (cv != null && cv.GetRealType() != CVar.CVAR_Color) cv = null; mCVar = cv; + return self; } //============================================================================= @@ -840,20 +852,26 @@ class OptionMenuItemColorPicker : OptionMenuItem if (mCVar != null) { Menu.MenuSound("menu/choose"); - /* - Menu *picker = StartPickerMenu(Menu.CurrentMenu, mLabel, mCVar); - if (picker != null) + let desc = MenuDescriptor.GetDescriptor('Colorpickermenu'); + // New color pickers must inherit from the internal one to work here. + if (desc != NULL && (desc.mClass == null || desc.mClass is "ColorPickerMenu")) { - M_ActivateMenu(picker); - return true; + let odesc = OptionMenuDescriptor(desc); + if (odesc != null) + { + let cls = desc.mClass; + if (cls == null) cls = "ColorpickerMenu"; + let picker = ColorpickerMenu(new(cls)); + picker.Init(Menu.GetCurrentMenu(), mLabel, odesc, mCVar); + picker.ActivateMenu(); + return true; + } } - */ } return false; } } - class OptionMenuItemScreenResolution : OptionMenuItem { String mResTexts[3]; @@ -868,11 +886,12 @@ class OptionMenuItemScreenResolution : OptionMenuItem SRL_HIGHLIGHT = 0x30004, }; - void Init(String command) + OptionMenuItemScreenResolution Init(String command) { Super.Init("", command); mSelection = 0; mHighlight = -1; + return self; } override bool SetValue(int i, int v) @@ -1064,10 +1083,11 @@ class OptionMenuFieldBase : OptionMenuItem class OptionMenuItemTextField : OptionMenuFieldBase { - void Init (String label, Name command, CVar graycheck = null) + OptionMenuItemTextField Init (String label, Name command, CVar graycheck = null) { Super.Init(label, command, graycheck); mEntering = false; + return self; } override String Represent() @@ -1132,12 +1152,13 @@ class OptionMenuItemTextField : OptionMenuFieldBase class OptionMenuItemNumberField : OptionMenuFieldBase { - void Init (String label, Name command, float minimum = 0, float maximum = 100, float step = 1, CVar graycheck = null) + OptionMenuItemNumberField Init (String label, Name command, float minimum = 0, float maximum = 100, float step = 1, CVar graycheck = null) { Super.Init(label, command, graycheck); mMinimum = min(minimum, maximum); mMaximum = max(minimum, maximum); mStep = max(1, step); + return self; } override String Represent() From b6ad14a61424a52936f80c5ab3f5f58d89fbff02 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Feb 2017 21:45:37 +0100 Subject: [PATCH 14/19] - made adjustments to text input menu to work with scripts. --- src/d_dehacked.cpp | 2 +- src/g_mapinfo.cpp | 2 +- src/menu/loadsavemenu.cpp | 19 ++--- src/menu/menu.cpp | 6 +- src/menu/menu.h | 11 ++- src/menu/menuinput.cpp | 75 ++++++++++++------- src/scripting/zscript/ast.cpp | 2 +- src/scripting/zscript/zcc_compile.cpp | 2 +- src/zstring.cpp | 6 +- src/zstring.h | 2 +- wadsrc/static/zscript.txt | 1 + .../static/zscript/menu/optionmenuitems.txt | 23 +++--- wadsrc/static/zscript/menu/playermenu.txt | 22 +++--- wadsrc/static/zscript/menu/textentermenu.txt | 15 ++++ 14 files changed, 107 insertions(+), 81 deletions(-) create mode 100644 wadsrc/static/zscript/menu/textentermenu.txt diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 36c32bf5b..9cfd74520 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -2293,7 +2293,7 @@ static int PatchStrings (int dummy) holdstring.StripRight(); if (holdstring.Len() > 0 && holdstring[holdstring.Len()-1] == '\\') { - holdstring.Truncate((long)holdstring.Len()-1); + holdstring.Truncate(holdstring.Len()-1); Line2 = igets (); } else diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index bb641b23b..cbda6568e 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -589,7 +589,7 @@ bool FMapInfoParser::ParseLookupName(FString &dest) } while (sc.CheckString(",")); // strip off the last newline - dest.Truncate(long(dest.Len()-1)); + dest.Truncate(dest.Len()-1); return false; } } diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index 74c943480..ec92a591f 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -598,6 +598,7 @@ protected: // this needs to be kept in memory so that the texture can access it when it needs to. bool mEntering; char savegamestring[SAVESTRINGSIZE]; + DTextEnterMenu *mInput = nullptr; DLoadSaveMenu(DMenu *parent = nullptr, DListMenuDescriptor *desc = nullptr); void OnDestroy() override; @@ -760,15 +761,9 @@ void DLoadSaveMenu::Drawer () } else { + FString s = mInput->GetText() + SmallFont->GetCursor(); screen->DrawText (SmallFont, CR_WHITE, - listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, savegamestring, - DTA_CleanNoMove, true, TAG_DONE); - - char curs[2] = { SmallFont->GetCursor(), 0 }; - screen->DrawText (SmallFont, CR_WHITE, - listboxLeft+1+SmallFont->StringWidth (savegamestring)*CleanXfac, - listboxTop+rowHeight*i+CleanYfac, - curs, + listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, s, DTA_CleanNoMove, true, TAG_DONE); } } @@ -1055,18 +1050,20 @@ bool DSaveMenu::MenuEvent (int mkey, bool fromcontroller) { savegamestring[0] = 0; } - DMenu *input = new DTextEnterMenu(this, savegamestring, SAVESTRINGSIZE, 1, fromcontroller); - M_ActivateMenu(input); + mInput = new DTextEnterMenu(this, savegamestring, SAVESTRINGSIZE, 1, fromcontroller); + M_ActivateMenu(mInput); mEntering = true; } else if (mkey == MKEY_Input) { mEntering = false; - manager->DoSave(Selected, savegamestring); + manager->DoSave(Selected, mInput->GetText()); + mInput = nullptr; } else if (mkey == MKEY_Abort) { mEntering = false; + mInput = nullptr; } return false; } diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 595563c0d..1b93083e1 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -73,7 +73,7 @@ DMenu *DMenu::CurrentMenu; DEFINE_ACTION_FUNCTION(DMenu, GetCurrentMenu) { - ACTION_RETURN_POINTER(DMenu::CurrentMenu); + ACTION_RETURN_OBJECT(DMenu::CurrentMenu); } int DMenu::MenuTime; @@ -113,7 +113,7 @@ DEFINE_ACTION_FUNCTION(DMenuDescriptor, GetDescriptor) PARAM_NAME(name); DMenuDescriptor **desc = MenuDescriptors.CheckKey(name); auto retn = desc ? *desc : nullptr; - ACTION_RETURN_POINTER(retn); + ACTION_RETURN_OBJECT(retn); } size_t DListMenuDescriptor::PropagateMark() @@ -425,7 +425,7 @@ DEFINE_ACTION_FUNCTION(DMenu, GetItem) { PARAM_SELF_PROLOGUE(DMenu); PARAM_NAME(name); - ACTION_RETURN_POINTER(self->GetItem(name)); + ACTION_RETURN_OBJECT(self->GetItem(name)); } diff --git a/src/menu/menu.h b/src/menu/menu.h index 1d7f6def9..9e64fdd8e 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -269,7 +269,7 @@ public: virtual void Ticker (); virtual void Drawer (); virtual bool DimAllowed (); - /*virtual */bool TranslateKeyboardEvents(); + bool TranslateKeyboardEvents(); virtual void Close(); virtual bool MouseEvent(int type, int x, int y); @@ -448,7 +448,8 @@ class DTextEnterMenu : public DMenu { DECLARE_ABSTRACT_CLASS(DTextEnterMenu, DMenu) - char *mEnterString; +public: + FString mEnterString; unsigned int mEnterSize; unsigned int mEnterPos; int mSizeMode; // 1: size is length in chars. 2: also check string width @@ -460,17 +461,15 @@ class DTextEnterMenu : public DMenu // [TP] bool AllowColors; -public: // [TP] Added allowcolors - DTextEnterMenu(DMenu *parent, char *textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors = false); + DTextEnterMenu(DMenu *parent, const char *textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors = false); void Drawer (); bool MenuEvent (int mkey, bool fromcontroller); bool Responder(event_t *ev); - //bool TranslateKeyboardEvents(); bool MouseEvent(int type, int x, int y); - + FString GetText(); }; diff --git a/src/menu/menuinput.cpp b/src/menu/menuinput.cpp index e28b141a1..9a0b717b5 100644 --- a/src/menu/menuinput.cpp +++ b/src/menu/menuinput.cpp @@ -61,6 +61,8 @@ static const char InputGridChars[INPUTGRID_WIDTH * INPUTGRID_HEIGHT] = CVAR(Bool, m_showinputgrid, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +DEFINE_FIELD(DTextEnterMenu, mInputGridOkay) + //============================================================================= // // @@ -68,15 +70,14 @@ CVAR(Bool, m_showinputgrid, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) //============================================================================= // [TP] Added allowcolors -DTextEnterMenu::DTextEnterMenu(DMenu *parent, char *textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors) +DTextEnterMenu::DTextEnterMenu(DMenu *parent, const char *textbuffer, int maxlen, int sizemode, bool showgrid, bool allowcolors) : DMenu(parent) { mEnterString = textbuffer; - mEnterSize = maxlen; - mEnterPos = (unsigned)strlen(textbuffer); + mEnterSize = maxlen < 0 ? UINT_MAX : unsigned(maxlen); mSizeMode = sizemode; mInputGridOkay = showgrid || m_showinputgrid; - if (mEnterPos > 0) + if (mEnterString.IsNotEmpty()) { InputGridX = INPUTGRID_WIDTH - 1; InputGridY = INPUTGRID_HEIGHT - 1; @@ -96,12 +97,17 @@ DTextEnterMenu::DTextEnterMenu(DMenu *parent, char *textbuffer, int maxlen, int // //============================================================================= -/* -bool DTextEnterMenu::TranslateKeyboardEvents() +FString DTextEnterMenu::GetText() { - return mInputGridOkay; + return mEnterString; } -*/ + +//============================================================================= +// +// +// +//============================================================================= + //============================================================================= // @@ -117,21 +123,19 @@ bool DTextEnterMenu::Responder(event_t *ev) if (ev->subtype == EV_GUI_Char) { mInputGridOkay = false; - if (mEnterPos < mEnterSize && + if (mEnterString.Len() < mEnterSize && (mSizeMode == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(mEnterString) < (mEnterSize-1)*8)) { - mEnterString[mEnterPos] = (char)ev->data1; - mEnterString[++mEnterPos] = 0; + mEnterString.AppendFormat("%c", (char)ev->data1); } return true; } char ch = (char)ev->data1; if ((ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat) && ch == '\b') { - if (mEnterPos > 0) + if (mEnterString.IsNotEmpty()) { - mEnterPos--; - mEnterString[mEnterPos] = 0; + mEnterString.Truncate(mEnterString.Len() - 1); } } else if (ev->subtype == EV_GUI_KeyDown) @@ -145,15 +149,15 @@ bool DTextEnterMenu::Responder(event_t *ev) } else if (ch == '\r') { - if (mEnterString[0]) + if (mEnterString.IsNotEmpty()) { // [TP] If we allow color codes, colorize the string now. if (AllowColors) - strbin(mEnterString); + mEnterString = strbin1(mEnterString); DMenu *parent = mParentMenu; - Close(); parent->CallMenuEvent(MKEY_Input, false); + Close(); return true; } } @@ -247,9 +251,9 @@ bool DTextEnterMenu::MenuEvent (int key, bool fromcontroller) return true; case MKEY_Clear: - if (mEnterPos > 0) + if (mEnterString.IsNotEmpty()) { - mEnterString[--mEnterPos] = 0; + mEnterString.Truncate(mEnterString.Len() - 1); } return true; @@ -260,7 +264,7 @@ bool DTextEnterMenu::MenuEvent (int key, bool fromcontroller) ch = InputGridChars[InputGridX + InputGridY * INPUTGRID_WIDTH]; if (ch == 0) // end { - if (mEnterString[0] != '\0') + if (mEnterString.IsNotEmpty()) { DMenu *parent = mParentMenu; Close(); @@ -270,16 +274,15 @@ bool DTextEnterMenu::MenuEvent (int key, bool fromcontroller) } else if (ch == '\b') // bs { - if (mEnterPos > 0) + if (mEnterString.IsNotEmpty()) { - mEnterString[--mEnterPos] = 0; + mEnterString.Truncate(mEnterString.Len() - 1); } } - else if (mEnterPos < mEnterSize && + else if (mEnterString.Len() < mEnterSize && (mSizeMode == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(mEnterString) < (mEnterSize-1)*8)) { - mEnterString[mEnterPos] = ch; - mEnterString[++mEnterPos] = 0; + mEnterString += char(ch); } } return true; @@ -370,4 +373,24 @@ void DTextEnterMenu::Drawer () } } Super::Drawer(); -} \ No newline at end of file +} + + +DEFINE_ACTION_FUNCTION(DTextEnterMenu, Open) +{ + PARAM_PROLOGUE; + PARAM_OBJECT(parent, DMenu); + PARAM_STRING(text); + PARAM_INT(maxlen); + PARAM_INT(sizemode); + PARAM_BOOL(fromcontroller); + auto m = new DTextEnterMenu(parent, text.GetChars(), maxlen, sizemode, fromcontroller, false); + M_ActivateMenu(m); + ACTION_RETURN_OBJECT(m); +} + +DEFINE_ACTION_FUNCTION(DTextEnterMenu, GetText) +{ + PARAM_SELF_PROLOGUE(DTextEnterMenu); + ACTION_RETURN_STRING(self->GetText()); +} diff --git a/src/scripting/zscript/ast.cpp b/src/scripting/zscript/ast.cpp index c4c8a12a5..81c7ff6d3 100644 --- a/src/scripting/zscript/ast.cpp +++ b/src/scripting/zscript/ast.cpp @@ -112,7 +112,7 @@ public: } else { // Move hanging ( characters to the new line - Str.Truncate(long(Str.Len() - ConsecOpens)); + Str.Truncate(Str.Len() - ConsecOpens); NestDepth -= ConsecOpens; } Str << '\n'; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 500336df5..4647e6b26 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2598,7 +2598,7 @@ void ZCCCompiler::CompileStates() statename << FName(part->Id) << '.'; part = static_cast(part->SiblingNext); } while (part != sg->Label); - statename.Truncate((long)statename.Len() - 1); // remove the last '.' in the label name + statename.Truncate(statename.Len() - 1); // remove the last '.' in the label name if (sg->Offset != nullptr) { int offset = IntConstFromNode(sg->Offset, c->Type()); diff --git a/src/zstring.cpp b/src/zstring.cpp index 665b9312e..83a2a20d8 100644 --- a/src/zstring.cpp +++ b/src/zstring.cpp @@ -368,15 +368,15 @@ FString &FString::CopyCStrPart(const char *tail, size_t tailLen) return *this; } -void FString::Truncate(long newlen) +void FString::Truncate(size_t newlen) { - if (newlen <= 0) + if (newlen == 0) { Data()->Release(); NullString.RefCount++; Chars = &NullString.Nothing[0]; } - else if (newlen < (long)Len()) + else if (newlen < Len()) { ReallocBuffer (newlen); Chars[newlen] = '\0'; diff --git a/src/zstring.h b/src/zstring.h index c58fb111a..b925a39b1 100644 --- a/src/zstring.h +++ b/src/zstring.h @@ -301,7 +301,7 @@ public: bool IsEmpty() const { return Len() == 0; } bool IsNotEmpty() const { return Len() != 0; } - void Truncate (long newlen); + void Truncate (size_t newlen); void Remove(size_t index, size_t remlen); int Compare (const FString &other) const { return strcmp (Chars, other.Chars); } diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 637d5b66e..ba5c3d19b 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -14,6 +14,7 @@ #include "zscript/menu/joystickmenu.txt" #include "zscript/menu/playerdisplay.txt" #include "zscript/menu/playermenu.txt" +#include "zscript/menu/textentermenu.txt" #include "zscript/inventory/inventory.txt" #include "zscript/inventory/inv_misc.txt" diff --git a/wadsrc/static/zscript/menu/optionmenuitems.txt b/wadsrc/static/zscript/menu/optionmenuitems.txt index 338c36599..418773903 100644 --- a/wadsrc/static/zscript/menu/optionmenuitems.txt +++ b/wadsrc/static/zscript/menu/optionmenuitems.txt @@ -1083,22 +1083,24 @@ class OptionMenuFieldBase : OptionMenuItem class OptionMenuItemTextField : OptionMenuFieldBase { + TextEnterMenu mEnter; + OptionMenuItemTextField Init (String label, Name command, CVar graycheck = null) { Super.Init(label, command, graycheck); - mEntering = false; + mEnter = null; return self; } override String Represent() { - if (mEntering) return mEditName .. SmallFont.GetCursor(); + if (mEnter) return mEnter.GetText() .. SmallFont.GetCursor(); else return GetCVarString(); } override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) { - if (mEntering) + if (mEnter) { // reposition the text so that the cursor is visible when in entering mode. String text = Represent(); @@ -1114,30 +1116,23 @@ class OptionMenuItemTextField : OptionMenuFieldBase if (mkey == Menu.MKEY_Enter) { Menu.MenuSound("menu/choose"); - mEditName = GetCVarString(); - mEntering = true; - - //Menu* input = new DTextEnterMenu (Menu.CurrentMenu, mEditName, sizeof mEditName, 2, fromcontroller); - //M_ActivateMenu(input); + mEnter = TextEnterMenu.Open(Menu.GetCurrentMenu(), GetCVarString(), -1, 2, fromcontroller); return true; } else if (mkey == Menu.MKEY_Input) { - if (mCVar) mCVar.SetString(mEditName); - mEntering = false; + if (mCVar) mCVar.SetString(mEnter.GetText()); + mEnter = null; return true; } else if (mkey == Menu.MKEY_Abort) { - mEntering = false; + mEnter = null; return true; } return Super.MenuEvent(mkey, fromcontroller); } - - bool mEntering; - String mEditName; } diff --git a/wadsrc/static/zscript/menu/playermenu.txt b/wadsrc/static/zscript/menu/playermenu.txt index 6b055e0a0..389c34043 100644 --- a/wadsrc/static/zscript/menu/playermenu.txt +++ b/wadsrc/static/zscript/menu/playermenu.txt @@ -46,8 +46,7 @@ class ListMenuItemPlayerNameBox : ListMenuItemSelectable int mFontColor; int mFrameSize; String mPlayerName; - String mEditName; - bool mEntering; + TextEnterMenu mEnter; //============================================================================= // @@ -63,7 +62,7 @@ class ListMenuItemPlayerNameBox : ListMenuItemSelectable mFontColor = desc.mFontColor; mFrameSize = frameofs; mPlayerName = ""; - mEntering = false; + mEnter = null; } //============================================================================= @@ -80,7 +79,7 @@ class ListMenuItemPlayerNameBox : ListMenuItemSelectable mFontColor = color; mFrameSize = frameofs; mPlayerName = ""; - mEntering = false; + mEnter = null; } //============================================================================= @@ -164,13 +163,13 @@ class ListMenuItemPlayerNameBox : ListMenuItemSelectable // Draw player name box int x = mXpos + mFont.StringWidth(text) + 16 + mFrameSize; DrawBorder (x, mYpos - mFrameSize, MAXPLAYERNAME+1); - if (!mEntering) + if (!mEnter) { screen.DrawText (SmallFont, Font.CR_UNTRANSLATED, x + mFrameSize, mYpos, mPlayerName, DTA_Clean, true); } else { - let printit = mEditName .. SmallFont.GetCursor(); + let printit = mEnter.GetText() .. SmallFont.GetCursor(); screen.DrawText (SmallFont, Font.CR_UNTRANSLATED, x + mFrameSize, mYpos, printit, DTA_Clean, true); } } @@ -186,21 +185,18 @@ class ListMenuItemPlayerNameBox : ListMenuItemSelectable if (mkey == Menu.MKEY_Enter) { Menu.MenuSound ("menu/choose"); - mEditName = mPlayerName; - mEntering = true; - //DMenu *input = new DTextEnterMenu(Menu.CurrentMenu, mEditName, MAXPLAYERNAME, 2, fromcontroller); - //M_ActivateMenu(input); + mEnter = TextEnterMenu.Open(Menu.GetCurrentMenu(), mPlayerName, MAXPLAYERNAME, 2, fromcontroller); return true; } else if (mkey == Menu.MKEY_Input) { - mPlayerName = mEditName; - mEntering = false; + mPlayerName = mEnter.GetText(); + mEnter = null; return true; } else if (mkey == Menu.MKEY_Abort) { - mEntering = false; + mEnter = null; return true; } return false; diff --git a/wadsrc/static/zscript/menu/textentermenu.txt b/wadsrc/static/zscript/menu/textentermenu.txt new file mode 100644 index 000000000..7974a62bd --- /dev/null +++ b/wadsrc/static/zscript/menu/textentermenu.txt @@ -0,0 +1,15 @@ + +// This is only the parts that are needed to make the menu fully work right now. More to come later. +class TextEnterMenu : Menu native +{ + native bool mInputGridOkay; + + native static TextEnterMenu Open(Menu parent, String text, int maxlen, int sizemode, bool fromcontroller); + native String GetText(); + + + override bool TranslateKeyboardEvents() + { + return mInputGridOkay; + } +} \ No newline at end of file From 9ece757cb34570544051f213a13d6ccca165d8b1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Feb 2017 21:56:01 +0100 Subject: [PATCH 15/19] - OptionMenu.Init must be declared 'virtual' --- wadsrc/static/zscript/menu/menu.txt | 2 +- wadsrc/static/zscript/menu/optionmenuitems.txt | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/zscript/menu/menu.txt b/wadsrc/static/zscript/menu/menu.txt index add8c8cb9..a1af55458 100644 --- a/wadsrc/static/zscript/menu/menu.txt +++ b/wadsrc/static/zscript/menu/menu.txt @@ -214,7 +214,7 @@ class OptionMenu : Menu native // //============================================================================= - void Init(Menu parent, OptionMenuDescriptor desc) + virtual void Init(Menu parent, OptionMenuDescriptor desc) { mParentMenu = parent; mDesc = desc; diff --git a/wadsrc/static/zscript/menu/optionmenuitems.txt b/wadsrc/static/zscript/menu/optionmenuitems.txt index 418773903..4796ce4c9 100644 --- a/wadsrc/static/zscript/menu/optionmenuitems.txt +++ b/wadsrc/static/zscript/menu/optionmenuitems.txt @@ -852,8 +852,12 @@ class OptionMenuItemColorPicker : OptionMenuItem if (mCVar != null) { Menu.MenuSound("menu/choose"); - let desc = MenuDescriptor.GetDescriptor('Colorpickermenu'); + + // This code is a bit complicated because it should allow subclassing the + // colorpicker menu. // New color pickers must inherit from the internal one to work here. + + let desc = MenuDescriptor.GetDescriptor('Colorpickermenu'); if (desc != NULL && (desc.mClass == null || desc.mClass is "ColorPickerMenu")) { let odesc = OptionMenuDescriptor(desc); From 2b977f70e6981980daa4e8171987b9c13ac37a33 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Feb 2017 23:05:39 +0100 Subject: [PATCH 16/19] - scriptified the video mode menu (only the part that extends the actual menu class, the entire thing is basically non-modifiable but this code would otherwise stand in the way of properly handling the rest of the menus.) --- src/menu/menu.cpp | 7 +++ src/menu/videomenu.cpp | 80 ++++++++---------------- wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/base.txt | 31 ++++++++- wadsrc/static/zscript/menu/videomenu.txt | 73 +++++++++++++++++++++ 5 files changed, 137 insertions(+), 55 deletions(-) create mode 100644 wadsrc/static/zscript/menu/videomenu.txt diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 1b93083e1..a64f7b6df 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -93,6 +93,8 @@ int BackbuttonTime; float BackbuttonAlpha; static bool MenuEnabled = true; +void M_InitVideoModes(); + #define KEY_REPEAT_DELAY (TICRATE*5/12) #define KEY_REPEAT_RATE (3) @@ -568,6 +570,11 @@ void M_SetMenu(FName menu, int param) M_StartMessage (GStrings("SAVEDEAD"), 1); return; } + + case NAME_VideoModeMenu: + M_InitVideoModes(); + break; + } // End of special checks diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp index 1dc3a5c0e..dfb08f13c 100644 --- a/src/menu/videomenu.cpp +++ b/src/menu/videomenu.cpp @@ -138,60 +138,6 @@ struct OptionMenuItemScreenResolution // temporary workaround SRL_HIGHLIGHT = 0x30004, }; }; -class DVideoModeMenu : public DOptionMenu -{ - DECLARE_CLASS(DVideoModeMenu, DOptionMenu) - -public: - - DVideoModeMenu() - { - SetModesMenu (screen->VideoWidth, screen->VideoHeight, DisplayBits); - } - - bool MenuEvent(int mkey, bool fromcontroller) - { - if ((mkey == MKEY_Up || mkey == MKEY_Down) && mDesc->mSelectedItem >= 0 && - mDesc->mSelectedItem < (int)mDesc->mItems.Size()) - { - int sel; - bool selected = mDesc->mItems[mDesc->mSelectedItem]->GetValue(OptionMenuItemScreenResolution::SRL_SELECTION, &sel); - bool res = Super::MenuEvent(mkey, fromcontroller); - if (selected) mDesc->mItems[mDesc->mSelectedItem]->SetValue(OptionMenuItemScreenResolution::SRL_SELECTION, sel); - return res; - } - return Super::MenuEvent(mkey, fromcontroller); - } - - bool Responder(event_t *ev) - { - if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_KeyDown && - (ev->data1 == 't' || ev->data1 == 'T')) - { - if (!GetSelectedSize (&NewWidth, &NewHeight)) - { - NewWidth = screen->VideoWidth; - NewHeight = screen->VideoHeight; - } - else - { - OldWidth = screen->VideoWidth; - OldHeight = screen->VideoHeight; - OldBits = DisplayBits; - NewBits = BitTranslate[DummyDepthCvar]; - setmodeneeded = true; - testingmode = I_GetTime(false) + 5 * TICRATE; - S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE); - SetModesMenu (NewWidth, NewHeight, NewBits); - return true; - } - } - return Super::Responder(ev); - } -}; - -IMPLEMENT_CLASS(DVideoModeMenu, false, false) - //============================================================================= // @@ -382,6 +328,27 @@ static bool GetSelectedSize (int *width, int *height) return false; } +DEFINE_ACTION_FUNCTION(DVideoModeMenu, SetSelectedSize) +{ + if (!GetSelectedSize (&NewWidth, &NewHeight)) + { + NewWidth = screen->VideoWidth; + NewHeight = screen->VideoHeight; + ACTION_RETURN_BOOL(false); + } + else + { + OldWidth = screen->VideoWidth; + OldHeight = screen->VideoHeight; + OldBits = DisplayBits; + NewBits = BitTranslate[DummyDepthCvar]; + setmodeneeded = true; + testingmode = I_GetTime(false) + 5 * TICRATE; + SetModesMenu (NewWidth, NewHeight, NewBits); + ACTION_RETURN_BOOL(true); + } +} + //============================================================================= // // @@ -460,3 +427,8 @@ static void SetModesMenu (int w, int h, int bits) } BuildModesList (w, h, bits); } + +void M_InitVideoModes() +{ + SetModesMenu (screen->VideoWidth, screen->VideoHeight, DisplayBits); +} \ No newline at end of file diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index ba5c3d19b..c108b6623 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -15,6 +15,7 @@ #include "zscript/menu/playerdisplay.txt" #include "zscript/menu/playermenu.txt" #include "zscript/menu/textentermenu.txt" +#include "zscript/menu/videomenu.txt" #include "zscript/inventory/inventory.txt" #include "zscript/inventory/inv_misc.txt" diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 2d79a2916..eee20a04f 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -18,6 +18,35 @@ struct InputEvent native DeviceChange,// a device has been connected or removed } + enum EGUIEvent + { + GUI_None, + GUI_KeyDown, // data1: unshifted ASCII, data2: shifted ASCII, data3: modifiers + GUI_KeyRepeat, // same + GUI_KeyUp, // same + GUI_Char, // data1: translated character (for user text input), data2: alt down? + GUI_FirstMouseEvent, + GUI_MouseMove, + GUI_LButtonDown, + GUI_LButtonUp, + GUI_LButtonDblClick, + GUI_MButtonDown, + GUI_MButtonUp, + GUI_MButtonDblClick, + GUI_RButtonDown, + GUI_RButtonUp, + GUI_RButtonDblClick, + GUI_WheelUp, // data3: shift/ctrl/alt + GUI_WheelDown, // " + GUI_WheelRight, // " + GUI_WheelLeft, // " + GUI_BackButtonDown, + GUI_BackButtonUp, + GUI_FwdButtonDown, + GUI_FwdButtonUp, + GUI_LastMouseEvent, + }; + const KEY_ESCAPE = 0x01; } @@ -580,7 +609,7 @@ class Floor : Thinker native waitStair, resetStair, - // Not to be used as parameters to EV_DoFloor() + // Not to be used as parameters to DoFloor() genFloorChg0, genFloorChgT, genFloorChg diff --git a/wadsrc/static/zscript/menu/videomenu.txt b/wadsrc/static/zscript/menu/videomenu.txt new file mode 100644 index 000000000..a162781eb --- /dev/null +++ b/wadsrc/static/zscript/menu/videomenu.txt @@ -0,0 +1,73 @@ +/* +** videomenu.txt +** The video modes menu +** +**--------------------------------------------------------------------------- +** Copyright 2001-2010 Randy Heit +** Copyright 2010-2017 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +//============================================================================= +// +// +// +//============================================================================= + +class VideoModeMenu : OptionMenu +{ + native static bool SetSelectedSize(); + + override bool MenuEvent(int mkey, bool fromcontroller) + { + if ((mkey == MKEY_Up || mkey == MKEY_Down) && mDesc.mSelectedItem >= 0 && mDesc.mSelectedItem < mDesc.mItems.Size()) + { + int sel; + bool selected; + [selected, sel] = mDesc.mItems[mDesc.mSelectedItem].GetValue(OptionMenuItemScreenResolution.SRL_SELECTION); + bool res = Super.MenuEvent(mkey, fromcontroller); + if (selected) mDesc.mItems[mDesc.mSelectedItem].SetValue(OptionMenuItemScreenResolution.SRL_SELECTION, sel); + return res; + } + return Super.MenuEvent(mkey, fromcontroller); + } + + override bool Responder(InputEvent ev) + { + if (ev.type == InputEvent.GUI_Event && ev.subtype == InputEvent.GUI_KeyDown && (ev.data1 == 0x54 || ev.data1 == 0x74)) + { + if (SetSelectedSize()) + { + MenuSound ("menu/choose"); + return true; + } + } + return Super.Responder(ev); + } +} + From 12db190f41a4f74116e2542f9a4fbdf60e538485 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Feb 2017 23:17:05 +0100 Subject: [PATCH 17/19] - scriptified the CVar printers for the gameplay and compatibility menus. --- src/menu/optionmenu.cpp | 46 ----------------------- wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/menu/optionmenu.txt | 31 +++++++++++++++ 3 files changed, 32 insertions(+), 46 deletions(-) create mode 100644 wadsrc/static/zscript/menu/optionmenu.txt diff --git a/src/menu/optionmenu.cpp b/src/menu/optionmenu.cpp index 57248f891..c6165b6e3 100644 --- a/src/menu/optionmenu.cpp +++ b/src/menu/optionmenu.cpp @@ -510,49 +510,3 @@ DMenuItemBase *DOptionMenuDescriptor::GetItem(FName name) return NULL; } - - - -class DGameplayMenu : public DOptionMenu -{ - DECLARE_CLASS(DGameplayMenu, DOptionMenu) - -public: - DGameplayMenu() - {} - - void Drawer () - { - Super::Drawer(); - - char text[64]; - mysnprintf(text, 64, "dmflags = %d dmflags2 = %d", *dmflags, *dmflags2); - screen->DrawText (SmallFont, OptionSettings.mFontColorValue, - (screen->GetWidth() - SmallFont->StringWidth (text) * CleanXfac_1) / 2, 0, text, - DTA_CleanNoMove_1, true, TAG_DONE); - } -}; - -IMPLEMENT_CLASS(DGameplayMenu, false, false) - -class DCompatibilityMenu : public DOptionMenu -{ - DECLARE_CLASS(DCompatibilityMenu, DOptionMenu) - -public: - DCompatibilityMenu() - {} - - void Drawer () - { - Super::Drawer(); - - char text[64]; - mysnprintf(text, 64, "compatflags = %d compatflags2 = %d", *compatflags, *compatflags2); - screen->DrawText (SmallFont, OptionSettings.mFontColorValue, - (screen->GetWidth() - SmallFont->StringWidth (text) * CleanXfac_1) / 2, 0, text, - DTA_CleanNoMove_1, true, TAG_DONE); - } -}; - -IMPLEMENT_CLASS(DCompatibilityMenu, false, false) diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index c108b6623..f0f462880 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -9,6 +9,7 @@ #include "zscript/menu/menuitembase.txt" #include "zscript/menu/menu.txt" #include "zscript/menu/listmenuitems.txt" +#include "zscript/menu/optionmenu.txt" #include "zscript/menu/optionmenuitems.txt" #include "zscript/menu/colorpickermenu.txt" #include "zscript/menu/joystickmenu.txt" diff --git a/wadsrc/static/zscript/menu/optionmenu.txt b/wadsrc/static/zscript/menu/optionmenu.txt new file mode 100644 index 000000000..78feb2336 --- /dev/null +++ b/wadsrc/static/zscript/menu/optionmenu.txt @@ -0,0 +1,31 @@ + + + + + + +class GameplayMenu : OptionMenu +{ + override void Drawer () + { + Super.Drawer(); + + String s = String.Format("dmflags = %d dmflags2 = %d", dmflags, dmflags2); + screen.DrawText (SmallFont, OptionMenuSettings.mFontColorValue, + (screen.GetWidth() - SmallFont.StringWidth (s) * CleanXfac_1) / 2, 0, s, + DTA_CleanNoMove_1, true); + } +} + +class CompatibilityMenu : OptionMenu +{ + override void Drawer () + { + Super.Drawer(); + + String s = String.Format("compatflags = %d compatflags2 = %d", compatflags, compatflags2); + screen.DrawText (SmallFont, OptionMenuSettings.mFontColorValue, + (screen.GetWidth() - SmallFont.StringWidth (s) * CleanXfac_1) / 2, 0, s, + DTA_CleanNoMove_1, true); + } +} From 46c0d27fe7b3e32c21fd637b1672f87d6412e99e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 13 Feb 2017 00:08:20 +0100 Subject: [PATCH 18/19] - scriptified the entire OptionMenu class and all still existing native subclasses. --- src/menu/joystickmenu.cpp | 9 +- src/menu/menu.cpp | 41 +- src/menu/menu.h | 45 +-- src/menu/menudef.cpp | 2 +- src/menu/optionmenu.cpp | 421 +-------------------- src/virtual.h | 2 +- wadsrc/static/zscript/menu/menu.txt | 64 +--- wadsrc/static/zscript/menu/optionmenu.txt | 438 ++++++++++++++++++++++ 8 files changed, 471 insertions(+), 551 deletions(-) diff --git a/src/menu/joystickmenu.cpp b/src/menu/joystickmenu.cpp index 9e9aacde8..eef4aa3bf 100644 --- a/src/menu/joystickmenu.cpp +++ b/src/menu/joystickmenu.cpp @@ -124,13 +124,6 @@ DEFINE_ACTION_FUNCTION(IJoystickConfig, SetAxisMap) DOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy); -class DJoystickConfigMenu : public DOptionMenu -{ - DECLARE_CLASS(DJoystickConfigMenu, DOptionMenu) -}; - -IMPLEMENT_CLASS(DJoystickConfigMenu, false, false) - /*======================================= * * Joystick Menu @@ -295,7 +288,7 @@ void UpdateJoystickMenu(IJoystickConfig *selected) if (i == (int)Joysticks.Size()) { SELECTED_JOYSTICK = NULL; - if (DMenu::CurrentMenu != NULL && DMenu::CurrentMenu->IsKindOf(RUNTIME_CLASS(DJoystickConfigMenu))) + if (DMenu::CurrentMenu != NULL && DMenu::CurrentMenu->IsKindOf("JoystickConfigMenu")) { DMenu::CurrentMenu->Close(); } diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index a64f7b6df..46a0978af 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -378,6 +378,24 @@ void DMenu::Ticker () { } +DEFINE_ACTION_FUNCTION(DMenu, Ticker) +{ + PARAM_SELF_PROLOGUE(DMenu); + self->Drawer(); + return 0; +} + +void DMenu::CallTicker() +{ + IFVIRTUAL(DMenu, Ticker) + { + VMValue params[] = { (DObject*)this }; + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); + } + else Drawer(); +} + + void DMenu::Drawer () { if (this == DMenu::CurrentMenu && BackbuttonAlpha > 0 && m_show_backbutton >= 0 && m_use_mouse) @@ -608,10 +626,14 @@ void M_SetMenu(FName menu, int param) else if ((*desc)->IsKindOf(RUNTIME_CLASS(DOptionMenuDescriptor))) { DOptionMenuDescriptor *ld = static_cast(*desc); - const PClass *cls = ld->mClass == nullptr? RUNTIME_CLASS(DOptionMenu) : ld->mClass; + const PClass *cls = ld->mClass == nullptr? PClass::FindClass("OptionMenu") : ld->mClass; - DOptionMenu *newmenu = (DOptionMenu *)cls->CreateNew(); - newmenu->Init(DMenu::CurrentMenu, ld); + DMenu *newmenu = (DMenu*)cls->CreateNew(); + IFVIRTUALPTRNAME(newmenu, "OptionMenu", Init) + { + VMValue params[3] = { newmenu, DMenu::CurrentMenu, ld }; + GlobalVMStack.Call(func, params, 3, nullptr, 0); + } M_ActivateMenu(newmenu); } return; @@ -847,7 +869,7 @@ void M_Ticker (void) DMenu::MenuTime++; if (DMenu::CurrentMenu != nullptr && menuactive != MENU_Off) { - DMenu::CurrentMenu->Ticker(); + DMenu::CurrentMenu->CallTicker(); for (int i = 0; i < NUM_MKEYS; ++i) { @@ -856,7 +878,7 @@ void M_Ticker (void) if (MenuButtonTickers[i] > 0 && --MenuButtonTickers[i] <= 0) { MenuButtonTickers[i] = KEY_REPEAT_RATE; - DMenu::CurrentMenu->MenuEvent(i, MenuButtonOrigin[i]); + DMenu::CurrentMenu->CallMenuEvent(i, MenuButtonOrigin[i]); } } } @@ -1170,9 +1192,6 @@ CCMD(undocolorpic) -//native void OptionMenuDescriptor.CalcIndent(); -//native OptionMenuItem OptionMenuDescriptor.GetItem(Name iname); - DEFINE_FIELD(DMenu, mParentMenu) DEFINE_FIELD(DMenuDescriptor, mMenuName) @@ -1211,12 +1230,6 @@ DEFINE_FIELD(DOptionMenuDescriptor, mIndent) DEFINE_FIELD(DOptionMenuDescriptor, mPosition) DEFINE_FIELD(DOptionMenuDescriptor, mDontDim) -DEFINE_FIELD(DOptionMenu, CanScrollUp) -DEFINE_FIELD(DOptionMenu, CanScrollDown) -DEFINE_FIELD(DOptionMenu, VisBottom) -DEFINE_FIELD(DOptionMenu, mFocusControl) -DEFINE_FIELD(DOptionMenu, mDesc) - DEFINE_FIELD(FOptionMenuSettings, mTitleColor) DEFINE_FIELD(FOptionMenuSettings, mFontColor) DEFINE_FIELD(FOptionMenuSettings, mFontColorValue) diff --git a/src/menu/menu.h b/src/menu/menu.h index 9e64fdd8e..d6edb861b 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -282,6 +282,7 @@ public: bool CallResponder(event_t *ev); bool CallMenuEvent(int mkey, bool fromcontroller); bool CallMouseEvent(int type, int x, int y); + void CallTicker(); void CallDrawer(); bool MouseEventBack(int type, int x, int y); @@ -394,50 +395,6 @@ typedef TMap< FName, FOptionValues* > FOptionMap; extern FOptionMap OptionValues; -//============================================================================= -// -// Option menu class runs a menu described by a DOptionMenuDescriptor -// -//============================================================================= - -class DOptionMenu : public DMenu -{ - DECLARE_CLASS(DOptionMenu, DMenu) - HAS_OBJECT_POINTERS; - -public: // needs to be public for script access - bool CanScrollUp; - bool CanScrollDown; - int VisBottom; - DMenuItemBase *mFocusControl; - DOptionMenuDescriptor *mDesc; - -//public: - DMenuItemBase *GetItem(FName name); - DOptionMenu(DMenu *parent = NULL, DOptionMenuDescriptor *desc = NULL); - virtual void Init(DMenu *parent = NULL, DOptionMenuDescriptor *desc = NULL); - int FirstSelectable(); - bool Responder (event_t *ev); - bool MenuEvent (int mkey, bool fromcontroller); - bool MouseEvent(int type, int x, int y); - void Ticker (); - void Drawer (); - const DOptionMenuDescriptor *GetDescriptor() const { return mDesc; } - void SetFocus(DMenuItemBase *fc) - { - mFocusControl = fc; - } - bool CheckFocus(DMenuItemBase *fc) - { - return mFocusControl == fc; - } - void ReleaseFocus() - { - mFocusControl = NULL; - } -}; - - //============================================================================= // // Input some text diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index f02203841..9aff4350a 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -700,7 +700,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) { sc.MustGetString(); const PClass *cls = PClass::FindClass(sc.String); - if (cls == nullptr || !cls->IsDescendantOf(RUNTIME_CLASS(DOptionMenu))) + if (cls == nullptr || !cls->IsDescendantOf("OptionMenu")) { sc.ScriptError("Unknown menu class '%s'", sc.String); } diff --git a/src/menu/optionmenu.cpp b/src/menu/optionmenu.cpp index c6165b6e3..acbb3c58e 100644 --- a/src/menu/optionmenu.cpp +++ b/src/menu/optionmenu.cpp @@ -3,7 +3,7 @@ ** Handler class for the option menus and associated items ** **--------------------------------------------------------------------------- -** Copyright 2010 Christoph Oelckers +** Copyright 2010-2017 Christoph Oelckers ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -49,431 +49,12 @@ #include "menu/menu.h" -//============================================================================= -// -// Draws a string in the console font, scaled to the 8x8 cells -// used by the default console font. -// -//============================================================================= - -void M_DrawConText (int color, int x, int y, const char *str) -{ - screen->DrawText (ConFont, color, x, y, str, - DTA_CellX, 8 * CleanXfac_1, - DTA_CellY, 8 * CleanYfac_1, - TAG_DONE); -} - - -IMPLEMENT_CLASS(DOptionMenu, false, false) - -IMPLEMENT_POINTERS_START(DOptionMenu) -IMPLEMENT_POINTER(mFocusControl) -IMPLEMENT_POINTERS_END - //============================================================================= // // // //============================================================================= -DOptionMenu::DOptionMenu(DMenu *parent, DOptionMenuDescriptor *desc) -: DMenu(parent) -{ - CanScrollUp = false; - CanScrollDown = false; - VisBottom = 0; - mFocusControl = NULL; - Init(parent, desc); -} - -//============================================================================= -// -// -// -//============================================================================= - -void DOptionMenu::Init(DMenu *parent, DOptionMenuDescriptor *desc) -{ - mParentMenu = parent; - GC::WriteBarrier(this, parent); - mDesc = desc; - if (mDesc != NULL && mDesc->mSelectedItem == -1) mDesc->mSelectedItem = FirstSelectable(); - -} - -//============================================================================= -// -// -// -//============================================================================= - -int DOptionMenu::FirstSelectable() -{ - if (mDesc != NULL) - { - // Go down to the first selectable item - int i = -1; - do - { - i++; - } - while (i < (int)mDesc->mItems.Size() && !mDesc->mItems[i]->Selectable()); - if (i>=0 && i < (int)mDesc->mItems.Size()) return i; - } - return -1; -} - -//============================================================================= -// -// -// -//============================================================================= - -DMenuItemBase *DOptionMenu::GetItem(FName name) -{ - for(unsigned i=0;imItems.Size(); i++) - { - FName nm = mDesc->mItems[i]->GetAction(NULL); - if (nm == name) return mDesc->mItems[i]; - } - return NULL; -} - -//============================================================================= -// -// -// -//============================================================================= - -bool DOptionMenu::Responder (event_t *ev) -{ - if (ev->type == EV_GUI_Event) - { - if (ev->subtype == EV_GUI_WheelUp) - { - int scrollamt = MIN(2, mDesc->mScrollPos); - mDesc->mScrollPos -= scrollamt; - return true; - } - else if (ev->subtype == EV_GUI_WheelDown) - { - if (CanScrollDown) - { - if (VisBottom < (int)(mDesc->mItems.Size()-2)) - { - mDesc->mScrollPos += 2; - VisBottom += 2; - } - else - { - mDesc->mScrollPos++; - VisBottom++; - } - } - return true; - } - } - return Super::Responder(ev); -} - -//============================================================================= -// -// -// -//============================================================================= - -bool DOptionMenu::MenuEvent (int mkey, bool fromcontroller) -{ - int startedAt = mDesc->mSelectedItem; - - switch (mkey) - { - case MKEY_Up: - if (mDesc->mSelectedItem == -1) - { - mDesc->mSelectedItem = FirstSelectable(); - break; - } - do - { - --mDesc->mSelectedItem; - - if (mDesc->mScrollPos > 0 && - mDesc->mSelectedItem <= mDesc->mScrollTop + mDesc->mScrollPos) - { - mDesc->mScrollPos = MAX(mDesc->mSelectedItem - mDesc->mScrollTop - 1, 0); - } - - if (mDesc->mSelectedItem < 0) - { - // Figure out how many lines of text fit on the menu - int y = mDesc->mPosition; - - if (y <= 0) - { - if (BigFont && mDesc->mTitle.IsNotEmpty()) - { - y = -y + BigFont->GetHeight(); - } - else - { - y = -y; - } - } - y *= CleanYfac_1; - int rowheight = OptionSettings.mLinespacing * CleanYfac_1; - int maxitems = (screen->GetHeight() - rowheight - y) / rowheight + 1; - - mDesc->mScrollPos = MAX (0, (int)mDesc->mItems.Size() - maxitems + mDesc->mScrollTop); - mDesc->mSelectedItem = mDesc->mItems.Size()-1; - } - } - while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt); - break; - - case MKEY_Down: - if (mDesc->mSelectedItem == -1) - { - mDesc->mSelectedItem = FirstSelectable(); - break; - } - do - { - ++mDesc->mSelectedItem; - - if (CanScrollDown && mDesc->mSelectedItem == VisBottom) - { - mDesc->mScrollPos++; - VisBottom++; - } - if (mDesc->mSelectedItem >= (int)mDesc->mItems.Size()) - { - if (startedAt == -1) - { - mDesc->mSelectedItem = -1; - mDesc->mScrollPos = -1; - break; - } - else - { - mDesc->mSelectedItem = 0; - mDesc->mScrollPos = 0; - } - } - } - while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt); - break; - - case MKEY_PageUp: - if (mDesc->mScrollPos > 0) - { - mDesc->mScrollPos -= VisBottom - mDesc->mScrollPos - mDesc->mScrollTop; - if (mDesc->mScrollPos < 0) - { - mDesc->mScrollPos = 0; - } - if (mDesc->mSelectedItem != -1) - { - mDesc->mSelectedItem = mDesc->mScrollTop + mDesc->mScrollPos + 1; - while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable()) - { - if (++mDesc->mSelectedItem >= (int)mDesc->mItems.Size()) - { - mDesc->mSelectedItem = 0; - } - } - if (mDesc->mScrollPos > mDesc->mSelectedItem) - { - mDesc->mScrollPos = mDesc->mSelectedItem; - } - } - } - break; - - case MKEY_PageDown: - if (CanScrollDown) - { - int pagesize = VisBottom - mDesc->mScrollPos - mDesc->mScrollTop; - mDesc->mScrollPos += pagesize; - if (mDesc->mScrollPos + mDesc->mScrollTop + pagesize > (int)mDesc->mItems.Size()) - { - mDesc->mScrollPos = mDesc->mItems.Size() - mDesc->mScrollTop - pagesize; - } - if (mDesc->mSelectedItem != -1) - { - mDesc->mSelectedItem = mDesc->mScrollTop + mDesc->mScrollPos; - while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable()) - { - if (++mDesc->mSelectedItem >= (int)mDesc->mItems.Size()) - { - mDesc->mSelectedItem = 0; - } - } - if (mDesc->mScrollPos > mDesc->mSelectedItem) - { - mDesc->mScrollPos = mDesc->mSelectedItem; - } - } - } - break; - - case MKEY_Enter: - if (mDesc->mSelectedItem >= 0 && mDesc->mItems[mDesc->mSelectedItem]->Activate()) - { - return true; - } - // fall through to default - default: - if (mDesc->mSelectedItem >= 0 && - mDesc->mItems[mDesc->mSelectedItem]->MenuEvent(mkey, fromcontroller)) return true; - return Super::MenuEvent(mkey, fromcontroller); - } - - if (mDesc->mSelectedItem != startedAt) - { - S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE); - } - return true; -} - -//============================================================================= -// -// -// -//============================================================================= - -bool DOptionMenu::MouseEvent(int type, int x, int y) -{ - y = (y / CleanYfac_1) - mDesc->mDrawTop; - - if (mFocusControl) - { - mFocusControl->MouseEvent(type, x, y); - return true; - } - else - { - int yline = (y / OptionSettings.mLinespacing); - if (yline >= mDesc->mScrollTop) - { - yline += mDesc->mScrollPos; - } - if ((unsigned)yline < mDesc->mItems.Size() && mDesc->mItems[yline]->Selectable()) - { - if (yline != mDesc->mSelectedItem) - { - mDesc->mSelectedItem = yline; - //S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE); - } - mDesc->mItems[yline]->MouseEvent(type, x, y); - return true; - } - } - mDesc->mSelectedItem = -1; - return Super::MouseEvent(type, x, y); -} - -//============================================================================= -// -// -// -//============================================================================= - -void DOptionMenu::Ticker () -{ - Super::Ticker(); - for(unsigned i=0;imItems.Size(); i++) - { - mDesc->mItems[i]->Ticker(); - } -} - -//============================================================================= -// -// -// -//============================================================================= - -void DOptionMenu::Drawer () -{ - int y = mDesc->mPosition; - - if (y <= 0) - { - if (BigFont && mDesc->mTitle.IsNotEmpty()) - { - const char *tt = mDesc->mTitle; - if (*tt == '$') tt = GStrings(tt+1); - screen->DrawText (BigFont, OptionSettings.mTitleColor, - (screen->GetWidth() - BigFont->StringWidth(tt) * CleanXfac_1) / 2, 10*CleanYfac_1, - tt, DTA_CleanNoMove_1, true, TAG_DONE); - y = -y + BigFont->GetHeight(); - } - else - { - y = -y; - } - } - mDesc->mDrawTop = y; - int fontheight = OptionSettings.mLinespacing * CleanYfac_1; - y *= CleanYfac_1; - - int indent = mDesc->mIndent; - if (indent > 280) - { // kludge for the compatibility options with their extremely long labels - if (indent + 40 <= CleanWidth_1) - { - indent = (screen->GetWidth() - ((indent + 40) * CleanXfac_1)) / 2 + indent * CleanXfac_1; - } - else - { - indent = screen->GetWidth() - 40 * CleanXfac_1; - } - } - else - { - indent = (indent - 160) * CleanXfac_1 + screen->GetWidth() / 2; - } - - int ytop = y + mDesc->mScrollTop * 8 * CleanYfac_1; - int lastrow = screen->GetHeight() - SmallFont->GetHeight() * CleanYfac_1; - - unsigned i; - for (i = 0; i < mDesc->mItems.Size() && y <= lastrow; i++, y += fontheight) - { - // Don't scroll the uppermost items - if ((int)i == mDesc->mScrollTop) - { - i += mDesc->mScrollPos; - if (i >= mDesc->mItems.Size()) break; // skipped beyond end of menu - } - bool isSelected = mDesc->mSelectedItem == (int)i; - int cur_indent = mDesc->mItems[i]->Draw(mDesc, y, indent, isSelected); - if (cur_indent >= 0 && isSelected && mDesc->mItems[i]->Selectable()) - { - if (((DMenu::MenuTime%8) < 6) || DMenu::CurrentMenu != this) - { - M_DrawConText(OptionSettings.mFontColorSelection, cur_indent + 3 * CleanXfac_1, y+fontheight-9*CleanYfac_1, "\xd"); - } - } - } - - CanScrollUp = (mDesc->mScrollPos > 0); - CanScrollDown = (i < mDesc->mItems.Size()); - VisBottom = i - 1; - - if (CanScrollUp) - { - M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, ytop, "\x1a"); - } - if (CanScrollDown) - { - M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, y - 8*CleanYfac_1, "\x1b"); - } - Super::Drawer(); -} - void DOptionMenuDescriptor::CalcIndent() { // calculate the menu indent diff --git a/src/virtual.h b/src/virtual.h index f0479e663..a25e543ac 100644 --- a/src/virtual.h +++ b/src/virtual.h @@ -22,7 +22,7 @@ inline unsigned GetVirtualIndex(PClass *cls, const char *funcname) #define IFVIRTUALPTRNAME(self, cls, funcname) \ static unsigned VIndex = ~0u; \ if (VIndex == ~0u) { \ - VIndex = GetVirtualIndex(PClass::FindActor(cls), #funcname); \ + VIndex = GetVirtualIndex(PClass::FindClass(cls), #funcname); \ assert(VIndex != ~0u); \ } \ auto clss = self->GetClass(); \ diff --git a/wadsrc/static/zscript/menu/menu.txt b/wadsrc/static/zscript/menu/menu.txt index a1af55458..1d878e112 100644 --- a/wadsrc/static/zscript/menu/menu.txt +++ b/wadsrc/static/zscript/menu/menu.txt @@ -104,6 +104,7 @@ class Menu : Object native native virtual bool Responder(InputEvent ev); native virtual bool MenuEvent (int mkey, bool fromcontroller); native virtual bool MouseEvent(int type, int mx, int my); + native virtual void Ticker(); native virtual void Drawer(); native void Close(); native MenuItemBase GetItem(Name n); @@ -200,66 +201,3 @@ class OptionMenuDescriptor : MenuDescriptor native } } -class OptionMenu : Menu native -{ - native OptionMenuDescriptor mDesc; - native bool CanScrollUp; - native bool CanScrollDown; - native int VisBottom; - native OptionMenuItem mFocusControl; - - //============================================================================= - // - // - // - //============================================================================= - - virtual void Init(Menu parent, OptionMenuDescriptor desc) - { - mParentMenu = parent; - mDesc = desc; - if (mDesc != NULL && mDesc.mSelectedItem == -1) mDesc.mSelectedItem = FirstSelectable(); - - } - - //============================================================================= - // - // - // - //============================================================================= - - int FirstSelectable() - { - if (mDesc != NULL) - { - // Go down to the first selectable item - int i = -1; - do - { - i++; - } - while (i < mDesc.mItems.Size() && !mDesc.mItems[i].Selectable()); - if (i>=0 && i < mDesc.mItems.Size()) return i; - } - return -1; - } - - - override void SetFocus(MenuItemBase fc) - { - mFocusControl = OptionMenuItem(fc); - } - - override bool CheckFocus(MenuItemBase fc) - { - return mFocusControl == fc; - } - - override void ReleaseFocus() - { - mFocusControl = NULL; - } - - -} - diff --git a/wadsrc/static/zscript/menu/optionmenu.txt b/wadsrc/static/zscript/menu/optionmenu.txt index 78feb2336..7d2f34c77 100644 --- a/wadsrc/static/zscript/menu/optionmenu.txt +++ b/wadsrc/static/zscript/menu/optionmenu.txt @@ -1,7 +1,439 @@ +/* +** optionmenu.cpp +** Handler class for the option menus and associated items +** +**--------------------------------------------------------------------------- +** Copyright 2010-2017 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ +class OptionMenu : Menu +{ + OptionMenuDescriptor mDesc; + bool CanScrollUp; + bool CanScrollDown; + int VisBottom; + OptionMenuItem mFocusControl; + //============================================================================= + // + // + // + //============================================================================= + virtual void Init(Menu parent, OptionMenuDescriptor desc) + { + mParentMenu = parent; + mDesc = desc; + if (mDesc != NULL && mDesc.mSelectedItem == -1) mDesc.mSelectedItem = FirstSelectable(); + } + + + //============================================================================= + // + // + // + //============================================================================= + + int FirstSelectable() + { + if (mDesc != NULL) + { + // Go down to the first selectable item + int i = -1; + do + { + i++; + } + while (i < mDesc.mItems.Size() && !mDesc.mItems[i].Selectable()); + if (i>=0 && i < mDesc.mItems.Size()) return i; + } + return -1; + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool Responder (InputEvent ev) + { + if (ev.type == InputEvent.GUI_Event) + { + if (ev.subtype == InputEvent.GUI_WheelUp) + { + int scrollamt = MIN(2, mDesc.mScrollPos); + mDesc.mScrollPos -= scrollamt; + return true; + } + else if (ev.subtype == InputEvent.GUI_WheelDown) + { + if (CanScrollDown) + { + if (VisBottom >= 0 && VisBottom < (mDesc.mItems.Size()-2)) + { + mDesc.mScrollPos += 2; + VisBottom += 2; + } + else + { + mDesc.mScrollPos++; + VisBottom++; + } + } + return true; + } + } + return Super.Responder(ev); + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool MenuEvent (int mkey, bool fromcontroller) + { + int startedAt = mDesc.mSelectedItem; + + switch (mkey) + { + case MKEY_Up: + if (mDesc.mSelectedItem == -1) + { + mDesc.mSelectedItem = FirstSelectable(); + break; + } + do + { + --mDesc.mSelectedItem; + + if (mDesc.mScrollPos > 0 && + mDesc.mSelectedItem <= mDesc.mScrollTop + mDesc.mScrollPos) + { + mDesc.mScrollPos = MAX(mDesc.mSelectedItem - mDesc.mScrollTop - 1, 0); + } + + if (mDesc.mSelectedItem < 0) + { + // Figure out how many lines of text fit on the menu + int y = mDesc.mPosition; + + if (y <= 0) + { + if (BigFont && mDesc.mTitle.Length() > 0) + { + y = -y + BigFont.GetHeight(); + } + else + { + y = -y; + } + } + y *= CleanYfac_1; + int rowheight = OptionMenuSettings.mLinespacing * CleanYfac_1; + int maxitems = (screen.GetHeight() - rowheight - y) / rowheight + 1; + + mDesc.mScrollPos = MAX (0, mDesc.mItems.Size() - maxitems + mDesc.mScrollTop); + mDesc.mSelectedItem = mDesc.mItems.Size()-1; + } + } + while (!mDesc.mItems[mDesc.mSelectedItem].Selectable() && mDesc.mSelectedItem != startedAt); + break; + + case MKEY_Down: + if (mDesc.mSelectedItem == -1) + { + mDesc.mSelectedItem = FirstSelectable(); + break; + } + do + { + ++mDesc.mSelectedItem; + + if (CanScrollDown && mDesc.mSelectedItem == VisBottom) + { + mDesc.mScrollPos++; + VisBottom++; + } + if (mDesc.mSelectedItem >= mDesc.mItems.Size()) + { + if (startedAt == -1) + { + mDesc.mSelectedItem = -1; + mDesc.mScrollPos = -1; + break; + } + else + { + mDesc.mSelectedItem = 0; + mDesc.mScrollPos = 0; + } + } + } + while (!mDesc.mItems[mDesc.mSelectedItem].Selectable() && mDesc.mSelectedItem != startedAt); + break; + + case MKEY_PageUp: + if (mDesc.mScrollPos > 0) + { + mDesc.mScrollPos -= VisBottom - mDesc.mScrollPos - mDesc.mScrollTop; + if (mDesc.mScrollPos < 0) + { + mDesc.mScrollPos = 0; + } + if (mDesc.mSelectedItem != -1) + { + mDesc.mSelectedItem = mDesc.mScrollTop + mDesc.mScrollPos + 1; + while (!mDesc.mItems[mDesc.mSelectedItem].Selectable()) + { + if (++mDesc.mSelectedItem >= mDesc.mItems.Size()) + { + mDesc.mSelectedItem = 0; + } + } + if (mDesc.mScrollPos > mDesc.mSelectedItem) + { + mDesc.mScrollPos = mDesc.mSelectedItem; + } + } + } + break; + + case MKEY_PageDown: + if (CanScrollDown) + { + int pagesize = VisBottom - mDesc.mScrollPos - mDesc.mScrollTop; + mDesc.mScrollPos += pagesize; + if (mDesc.mScrollPos + mDesc.mScrollTop + pagesize > mDesc.mItems.Size()) + { + mDesc.mScrollPos = mDesc.mItems.Size() - mDesc.mScrollTop - pagesize; + } + if (mDesc.mSelectedItem != -1) + { + mDesc.mSelectedItem = mDesc.mScrollTop + mDesc.mScrollPos; + while (!mDesc.mItems[mDesc.mSelectedItem].Selectable()) + { + if (++mDesc.mSelectedItem >= mDesc.mItems.Size()) + { + mDesc.mSelectedItem = 0; + } + } + if (mDesc.mScrollPos > mDesc.mSelectedItem) + { + mDesc.mScrollPos = mDesc.mSelectedItem; + } + } + } + break; + + case MKEY_Enter: + if (mDesc.mSelectedItem >= 0 && mDesc.mItems[mDesc.mSelectedItem].Activate()) + { + return true; + } + // fall through to default + default: + if (mDesc.mSelectedItem >= 0 && + mDesc.mItems[mDesc.mSelectedItem].MenuEvent(mkey, fromcontroller)) return true; + return Super.MenuEvent(mkey, fromcontroller); + } + + if (mDesc.mSelectedItem != startedAt) + { + MenuSound ("menu/cursor"); + } + return true; + } + + + //============================================================================= + // + // + // + //============================================================================= + + override bool MouseEvent(int type, int x, int y) + { + y = (y / CleanYfac_1) - mDesc.mDrawTop; + + if (mFocusControl) + { + mFocusControl.MouseEvent(type, x, y); + return true; + } + else + { + int yline = (y / OptionMenuSettings.mLinespacing); + if (yline >= mDesc.mScrollTop) + { + yline += mDesc.mScrollPos; + } + if (yline >= 0 && yline < mDesc.mItems.Size() && mDesc.mItems[yline].Selectable()) + { + if (yline != mDesc.mSelectedItem) + { + mDesc.mSelectedItem = yline; + //S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE); + } + mDesc.mItems[yline].MouseEvent(type, x, y); + return true; + } + } + mDesc.mSelectedItem = -1; + return Super.MouseEvent(type, x, y); + } + + + //============================================================================= + // + // + // + //============================================================================= + + override void Ticker () + { + Super.Ticker(); + for(int i = 0; i < mDesc.mItems.Size(); i++) + { + mDesc.mItems[i].Ticker(); + } + } + + //============================================================================= + // + // + // + //============================================================================= + + override void Drawer () + { + int y = mDesc.mPosition; + + if (y <= 0) + { + if (BigFont && mDesc.mTitle.Length() > 0) + { + let tt = Stringtable.Localize(mDesc.mTitle); + screen.DrawText (BigFont, OptionMenuSettings.mTitleColor, + (screen.GetWidth() - BigFont.StringWidth(tt) * CleanXfac_1) / 2, 10*CleanYfac_1, + tt, DTA_CleanNoMove_1, true); + y = -y + BigFont.GetHeight(); + } + else + { + y = -y; + } + } + mDesc.mDrawTop = y; + int fontheight = OptionMenuSettings.mLinespacing * CleanYfac_1; + y *= CleanYfac_1; + + int indent = mDesc.mIndent; + if (indent > 280) + { // kludge for the compatibility options with their extremely long labels + if (indent + 40 <= CleanWidth_1) + { + indent = (screen.GetWidth() - ((indent + 40) * CleanXfac_1)) / 2 + indent * CleanXfac_1; + } + else + { + indent = screen.GetWidth() - 40 * CleanXfac_1; + } + } + else + { + indent = (indent - 160) * CleanXfac_1 + screen.GetWidth() / 2; + } + + int ytop = y + mDesc.mScrollTop * 8 * CleanYfac_1; + int lastrow = screen.GetHeight() - SmallFont.GetHeight() * CleanYfac_1; + + int i; + for (i = 0; i < mDesc.mItems.Size() && y <= lastrow; i++) + { + // Don't scroll the uppermost items + if (i == mDesc.mScrollTop) + { + i += mDesc.mScrollPos; + if (i >= mDesc.mItems.Size()) break; // skipped beyond end of menu + } + bool isSelected = mDesc.mSelectedItem == i; + int cur_indent = mDesc.mItems[i].Draw(mDesc, y, indent, isSelected); + if (cur_indent >= 0 && isSelected && mDesc.mItems[i].Selectable()) + { + if (((MenuTime() % 8) < 6) || GetCurrentMenu() != self) + { + DrawConText(OptionMenuSettings.mFontColorSelection, cur_indent + 3 * CleanXfac_1, y+fontheight-9*CleanYfac_1, "\xd"); + } + } + y += fontheight; + } + + CanScrollUp = (mDesc.mScrollPos > 0); + CanScrollDown = (i < mDesc.mItems.Size()); + VisBottom = i - 1; + + if (CanScrollUp) + { + DrawConText(Font.CR_ORANGE, 3 * CleanXfac_1, ytop, "\x1a"); + } + if (CanScrollDown) + { + DrawConText(Font.CR_ORANGE, 3 * CleanXfac_1, y - 8*CleanYfac_1, "\x1b"); + } + Super.Drawer(); + } + + //============================================================================= + // + // + // + //============================================================================= + + override void SetFocus(MenuItemBase fc) + { + mFocusControl = OptionMenuItem(fc); + } + + override bool CheckFocus(MenuItemBase fc) + { + return mFocusControl == fc; + } + + override void ReleaseFocus() + { + mFocusControl = NULL; + } +} class GameplayMenu : OptionMenu @@ -29,3 +461,9 @@ class CompatibilityMenu : OptionMenu DTA_CleanNoMove_1, true); } } + +class JoystickConfigMenu : OptionMenu +{ + // This is not really needed anymore but needs to be kept for old MENUDEFs that keep the entry +} + From 89ef30166d8ba250c8ee4ae470d319516fe1fe15 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 13 Feb 2017 00:25:39 +0100 Subject: [PATCH 19/19] - fixed assembly output for SO instruction. --- src/scripting/vm/vmops.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index 7128f1e43..6f3931531 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -70,8 +70,8 @@ xx(SS, ss, RPRSKI, SS_R, 4, REGT_INT), // store string xx(SS_R, ss, RPRSRI, NOP, 0, 0), xx(SP, sp, RPRPKI, SP_R, 4, REGT_INT), // store pointer xx(SP_R, sp, RPRPRI, NOP, 0, 0), -xx(SO, sp, RPRPKI, SO_R, 4, REGT_INT), // store object pointer with write barrier (only needed for non thinkers and non types -xx(SO_R, sp, RPRPRI, NOP, 0, 0), +xx(SO, so, RPRPKI, SO_R, 4, REGT_INT), // store object pointer with write barrier (only needed for non thinkers and non types) +xx(SO_R, so, RPRPRI, NOP, 0, 0), xx(SV2, sv2, RPRVKI, SV2_R, 4, REGT_INT), // store vector2 xx(SV2_R, sv2, RPRVRI, NOP, 0, 0), xx(SV3, sv3, RPRVKI, SV3_R, 4, REGT_INT), // store vector3