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; } }