From 33edb2e0e4baad54ed75f471747e3db41ee19881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20B=C3=A1lint=20Misius?= Date: Tue, 8 Nov 2022 13:46:47 +0100 Subject: [PATCH] Refactor GameController events More precisely, refactor the code responsible for routing these GameController events to the Lua side. The issue with the previous solution was it relied on preprocessor macros to switch between Lua-ful and Lua-less builds. --- src/common/VariantIndex.h | 22 +++ src/gui/game/GameController.cpp | 32 ++-- src/gui/game/GameControllerEvents.h | 98 +++++++++++ src/lua/CommandInterface.h | 5 +- src/lua/LuaEvents.cpp | 252 ---------------------------- src/lua/LuaEvents.h | 160 ------------------ src/lua/LuaScriptInterface.cpp | 179 +++++++++++++++++--- src/lua/LuaScriptInterface.h | 5 +- src/meson.build | 1 - src/simulation/Simulation.cpp | 4 +- 10 files changed, 295 insertions(+), 463 deletions(-) create mode 100644 src/common/VariantIndex.h create mode 100644 src/gui/game/GameControllerEvents.h delete mode 100644 src/lua/LuaEvents.cpp delete mode 100644 src/lua/LuaEvents.h diff --git a/src/common/VariantIndex.h b/src/common/VariantIndex.h new file mode 100644 index 000000000..4544fcd50 --- /dev/null +++ b/src/common/VariantIndex.h @@ -0,0 +1,22 @@ +#pragma once +#include +#include + +// https://stackoverflow.com/a/52303671 +template +constexpr std::size_t VariantIndex() +{ + static_assert(std::variant_size_v > index, "Type not found in variant"); + if constexpr (index == std::variant_size_v) + { + return index; + } + else if constexpr (std::is_same_v, T>) + { + return index; + } + else + { + return VariantIndex(); + } +} diff --git a/src/gui/game/GameController.cpp b/src/gui/game/GameController.cpp index ba27f5394..fc8e00676 100644 --- a/src/gui/game/GameController.cpp +++ b/src/gui/game/GameController.cpp @@ -13,9 +13,9 @@ #include "RenderPreset.h" #include "Tool.h" +#include "GameControllerEvents.h" #ifdef LUACONSOLE # include "lua/LuaScriptInterface.h" -# include "lua/LuaEvents.h" #else # include "lua/TPTScriptInterface.h" #endif @@ -521,14 +521,12 @@ void GameController::CutRegion(ui::Point point1, ui::Point point2) bool GameController::MouseMove(int x, int y, int dx, int dy) { - MouseMoveEvent ev(x, y, dx, dy); - return commandInterface->HandleEvent(LuaEvents::mousemove, &ev); + return commandInterface->HandleEvent(MouseMoveEvent{ x, y, dx, dy }); } bool GameController::MouseDown(int x, int y, unsigned button) { - MouseDownEvent ev(x, y, button); - bool ret = commandInterface->HandleEvent(LuaEvents::mousedown, &ev); + bool ret = commandInterface->HandleEvent(MouseDownEvent{ x, y, button }); if (ret && yGetPlacingSave() && !gameView->GetPlacingZoom()) { ui::Point point = gameModel->AdjustZoomCoords(ui::Point(x, y)); @@ -551,8 +549,7 @@ bool GameController::MouseDown(int x, int y, unsigned button) bool GameController::MouseUp(int x, int y, unsigned button, MouseupReason reason) { - MouseUpEvent ev(x, y, button, reason); - bool ret = commandInterface->HandleEvent(LuaEvents::mouseup, &ev); + bool ret = commandInterface->HandleEvent(MouseUpEvent{ x, y, button, reason }); if (reason != mouseUpNormal) return ret; if (ret && foundSignID != -1 && yGetPlacingSave()) @@ -601,26 +598,22 @@ bool GameController::MouseUp(int x, int y, unsigned button, MouseupReason reason bool GameController::MouseWheel(int x, int y, int d) { - MouseWheelEvent ev(x, y, d); - return commandInterface->HandleEvent(LuaEvents::mousewheel, &ev); + return commandInterface->HandleEvent(MouseWheelEvent{ x, y, d }); } bool GameController::TextInput(String text) { - TextInputEvent ev(text); - return commandInterface->HandleEvent(LuaEvents::textinput, &ev); + return commandInterface->HandleEvent(TextInputEvent{ text }); } bool GameController::TextEditing(String text) { - TextEditingEvent ev(text); - return commandInterface->HandleEvent(LuaEvents::textediting, &ev); + return commandInterface->HandleEvent(TextEditingEvent{ text }); } bool GameController::KeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt) { - KeyEvent ev(key, scan, repeat, shift, ctrl, alt); - bool ret = commandInterface->HandleEvent(LuaEvents::keypress, &ev); + bool ret = commandInterface->HandleEvent(KeyPressEvent{ key, scan, repeat, shift, ctrl, alt }); if (repeat) return ret; if (ret) @@ -699,8 +692,7 @@ bool GameController::KeyPress(int key, int scan, bool repeat, bool shift, bool c bool GameController::KeyRelease(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt) { - KeyEvent ev(key, scan, repeat, shift, ctrl, alt); - bool ret = commandInterface->HandleEvent(LuaEvents::keyrelease, &ev); + bool ret = commandInterface->HandleEvent(KeyReleaseEvent{ key, scan, repeat, shift, ctrl, alt }); if (repeat) return ret; if (ret) @@ -773,14 +765,12 @@ void GameController::Blur() { // Tell lua that mouse is up (even if it really isn't) MouseUp(0, 0, 0, mouseUpBlur); - BlurEvent ev; - commandInterface->HandleEvent(LuaEvents::blur, &ev); + commandInterface->HandleEvent(BlurEvent{}); } void GameController::Exit() { - CloseEvent ev; - commandInterface->HandleEvent(LuaEvents::close, &ev); + commandInterface->HandleEvent(CloseEvent{}); gameView->CloseActiveWindow(); HasDone = true; } diff --git a/src/gui/game/GameControllerEvents.h b/src/gui/game/GameControllerEvents.h new file mode 100644 index 000000000..8004e0fb3 --- /dev/null +++ b/src/gui/game/GameControllerEvents.h @@ -0,0 +1,98 @@ +#pragma once +#include "Config.h" +#include "common/String.h" +#include + +struct TextInputEvent +{ + String text; +}; + +struct TextEditingEvent +{ + String text; +}; + +struct KeyEvent +{ + int key; + int scan; + bool repeat; + bool shift; + bool ctrl; + bool alt; +}; + +struct KeyPressEvent : public KeyEvent +{ +}; + +struct KeyReleaseEvent : public KeyEvent +{ +}; + +struct MouseDownEvent +{ + int x; + int y; + unsigned int button; +}; + +struct MouseUpEvent +{ + int x; + int y; + unsigned int button; + int reason; +}; + +struct MouseMoveEvent +{ + int x; + int y; + int dx; + int dy; +}; + +struct MouseWheelEvent +{ + int x; + int y; + int d; +}; + +struct TickEvent +{ +}; + +struct BlurEvent +{ +}; + +struct CloseEvent +{ +}; + +struct BeforeSimEvent +{ +}; + +struct AfterSimEvent +{ +}; + +using GameControllerEvent = std::variant< + TextInputEvent, + TextEditingEvent, + KeyPressEvent, + KeyReleaseEvent, + MouseDownEvent, + MouseUpEvent, + MouseMoveEvent, + MouseWheelEvent, + TickEvent, + BlurEvent, + CloseEvent, + BeforeSimEvent, + AfterSimEvent +>; diff --git a/src/lua/CommandInterface.h b/src/lua/CommandInterface.h index 5bca2d9ea..692b31a8e 100644 --- a/src/lua/CommandInterface.h +++ b/src/lua/CommandInterface.h @@ -2,9 +2,8 @@ #include "Config.h" #include "common/String.h" -#include "lua/LuaEvents.h" +#include "gui/game/GameControllerEvents.h" -class Event; class GameModel; class GameController; class Tool; @@ -25,7 +24,7 @@ public: virtual void OnTick() { } - virtual bool HandleEvent(LuaEvents::EventTypes eventType, Event * event) { return true; } + virtual bool HandleEvent(const GameControllerEvent &event) { return true; } virtual int Command(String command); virtual String FormatCommand(String command); diff --git a/src/lua/LuaEvents.cpp b/src/lua/LuaEvents.cpp deleted file mode 100644 index 495f85cde..000000000 --- a/src/lua/LuaEvents.cpp +++ /dev/null @@ -1,252 +0,0 @@ -#include "LuaEvents.h" -#ifdef LUACONSOLE -# include "LuaCompat.h" -# include "LuaScriptInterface.h" -# include "common/Platform.h" -# include "gui/interface/Engine.h" -#endif - -void Event::PushInteger(lua_State * l, int num) -{ -#ifdef LUACONSOLE - lua_pushinteger(l, num); -#endif -} - -void Event::PushBoolean(lua_State * l, bool flag) -{ -#ifdef LUACONSOLE - lua_pushboolean(l, flag); -#endif -} - -void Event::PushString(lua_State * l, ByteString str) -{ -#ifdef LUACONSOLE - tpt_lua_pushByteString(l, str); -#endif -} - -TextInputEvent::TextInputEvent(String text): - text(text) -{} - -int TextInputEvent::PushToStack(lua_State * l) -{ - PushString(l, text.ToUtf8()); - return 1; -} - -TextEditingEvent::TextEditingEvent(String text): - text(text) -{} - -int TextEditingEvent::PushToStack(lua_State * l) -{ - PushString(l, text.ToUtf8()); - return 1; -} - -KeyEvent::KeyEvent(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt): - key(key), - scan(scan), - repeat(repeat), - shift(shift), - ctrl(ctrl), - alt(alt) -{} - -int KeyEvent::PushToStack(lua_State * l) -{ - PushInteger(l, key); - PushInteger(l, scan); - PushBoolean(l, repeat); - PushBoolean(l, shift); - PushBoolean(l, ctrl); - PushBoolean(l, alt); - - return 6; -} - -MouseDownEvent::MouseDownEvent(int x, int y, int button): - x(x), - y(y), - button(button) -{} - -int MouseDownEvent::PushToStack(lua_State * l) -{ - PushInteger(l, x); - PushInteger(l, y); - PushInteger(l, button); - - return 3; -} - -MouseUpEvent::MouseUpEvent(int x, int y, int button, int reason): - x(x), - y(y), - button(button), - reason(reason) -{} - -int MouseUpEvent::PushToStack(lua_State * l) -{ - PushInteger(l, x); - PushInteger(l, y); - PushInteger(l, button); - PushInteger(l, reason); - - return 4; -} - -MouseMoveEvent::MouseMoveEvent(int x, int y, int dx, int dy): - x(x), - y(y), - dx(dx), - dy(dy) -{} - -int MouseMoveEvent::PushToStack(lua_State * l) -{ - PushInteger(l, x); - PushInteger(l, y); - PushInteger(l, dx); - PushInteger(l, dy); - - return 4; -} - -MouseWheelEvent::MouseWheelEvent(int x, int y, int d): - x(x), - y(y), - d(d) -{} - -int MouseWheelEvent::PushToStack(lua_State * l) -{ - PushInteger(l, x); - PushInteger(l, y); - PushInteger(l, d); - - return 3; -} - -#ifdef LUACONSOLE -int LuaEvents::RegisterEventHook(lua_State *l, ByteString eventName) -{ - if (lua_isfunction(l, 2)) - { - tpt_lua_pushByteString(l, eventName); - lua_rawget(l, LUA_REGISTRYINDEX); - if (!lua_istable(l, -1)) - { - lua_pop(l, 1); - lua_newtable(l); - tpt_lua_pushByteString(l, eventName); - lua_pushvalue(l, -2); - lua_rawset(l, LUA_REGISTRYINDEX); - } - int c = lua_objlen(l, -1); - lua_pushvalue(l, 2); - lua_rawseti(l, -2, c + 1); - } - lua_pushvalue(l, 2); - return 1; -} - -int LuaEvents::UnregisterEventHook(lua_State *l, ByteString eventName) -{ - if (lua_isfunction(l, 2)) - { - tpt_lua_pushByteString(l, eventName); - lua_rawget(l, LUA_REGISTRYINDEX); - if (!lua_istable(l, -1)) - { - lua_pop(l, -1); - lua_newtable(l); - tpt_lua_pushByteString(l, eventName); - lua_pushvalue(l, -2); - lua_rawset(l, LUA_REGISTRYINDEX); - } - int len = lua_objlen(l, -1); - int adjust = 0; - for (int i = 1; i <= len; i++) - { - lua_rawgeti(l, -1, i + adjust); - // unregister the function - if (lua_equal(l, 2, -1)) - { - lua_pop(l, 1); - adjust++; - i--; - } - // Update the function index in the table if we've removed a previous function - else if (adjust) - lua_rawseti(l, -2, i); - else - lua_pop(l, 1); - } - } - return 0; -} - -bool LuaEvents::HandleEvent(LuaScriptInterface *luacon_ci, Event *event, ByteString eventName) -{ - ui::Engine::Ref().LastTick(Platform::GetTime()); - bool cont = true; - lua_State* l = luacon_ci->l; - tpt_lua_pushByteString(l, eventName); - lua_rawget(l, LUA_REGISTRYINDEX); - if (!lua_istable(l, -1)) - { - lua_pop(l, 1); - lua_newtable(l); - tpt_lua_pushByteString(l, eventName); - lua_pushvalue(l, -2); - lua_rawset(l, LUA_REGISTRYINDEX); - } - int len = lua_objlen(l, -1); - for (int i = 1; i <= len && cont; i++) - { - lua_rawgeti(l, -1, i); - int numArgs = event->PushToStack(l); - int callret = lua_pcall(l, numArgs, 1, 0); - if (callret) - { - if (luacon_geterror(luacon_ci) == "Error: Script not responding") - { - ui::Engine::Ref().LastTick(Platform::GetTime()); - for (int j = i; j <= len - 1; j++) - { - lua_rawgeti(l, -2, j + 1); - lua_rawseti(l, -3, j); - } - lua_pushnil(l); - lua_rawseti(l, -3, len); - i--; - } - luacon_ci->Log(CommandInterface::LogError, luacon_geterror(luacon_ci)); - lua_pop(l, 1); - } - else - { - if (!lua_isnoneornil(l, -1)) - cont = lua_toboolean(l, -1); - lua_pop(l, 1); - } - len = lua_objlen(l, -1); - } - lua_pop(l, 1); - return cont; -} - - -String LuaEvents::luacon_geterror(LuaScriptInterface * luacon_ci) -{ - luaL_tostring(luacon_ci->l, -1); - String err = tpt_lua_optString(luacon_ci->l, -1, "failed to execute"); - lua_pop(luacon_ci->l, 1); - return err; -} -#endif diff --git a/src/lua/LuaEvents.h b/src/lua/LuaEvents.h deleted file mode 100644 index 76f6eb467..000000000 --- a/src/lua/LuaEvents.h +++ /dev/null @@ -1,160 +0,0 @@ -#pragma once -#include "Config.h" - -#include "common/String.h" - -struct lua_State; -class LuaScriptInterface; - -class Event -{ -protected: - void PushInteger(lua_State * l, int num); - void PushBoolean(lua_State * l, bool flag); - void PushString(lua_State * l, ByteString str); - -public: - virtual int PushToStack(lua_State * l) = 0; - virtual ~Event() = default; -}; - -class TextInputEvent : public Event -{ - String text; - -public: - TextInputEvent(String text); - - int PushToStack(lua_State * l) override; -}; - -class TextEditingEvent : public Event -{ - String text; - -public: - TextEditingEvent(String text); - - int PushToStack(lua_State * l) override; -}; - -class KeyEvent : public Event -{ - int key; - int scan; - bool repeat; - bool shift; - bool ctrl; - bool alt; - -public: - KeyEvent(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt); - - int PushToStack(lua_State * l) override; -}; - -class MouseDownEvent : public Event -{ - int x; - int y; - int button; - -public: - MouseDownEvent(int x, int y, int button); - - int PushToStack(lua_State * l) override; -}; - -class MouseUpEvent : public Event -{ - int x; - int y; - int button; - int reason; - -public: - MouseUpEvent(int x, int y, int button, int reason); - - int PushToStack(lua_State * l) override; -}; - -class MouseMoveEvent : public Event -{ - int x; - int y; - int dx; - int dy; - -public: - MouseMoveEvent(int x, int y, int dx, int dy); - - int PushToStack(lua_State * l) override; -}; - -class MouseWheelEvent : public Event -{ - int x; - int y; - int d; - -public: - MouseWheelEvent(int x, int y, int d); - - int PushToStack(lua_State * l) override; -}; - -class TickEvent : public Event -{ -public: - int PushToStack(lua_State *l) override { return 0; } -}; - -class BlurEvent : public Event -{ -public: - int PushToStack(lua_State *l) override { return 0; } -}; - -class CloseEvent : public Event -{ -public: - int PushToStack(lua_State *l) override { return 0; } -}; - -class BeforeSimEvent : public Event -{ -public: - int PushToStack(lua_State *l) override { return 0; } -}; - -class AfterSimEvent : public Event -{ -public: - int PushToStack(lua_State *l) override { return 0; } -}; - -class LuaEvents -{ -public: - enum EventTypes { - keypress, - keyrelease, - textinput, - textediting, - mousedown, - mouseup, - mousemove, - mousewheel, - tick, - blur, - close, - beforesim, - aftersim, - }; - - static int RegisterEventHook(lua_State *l, ByteString eventName); - static int UnregisterEventHook(lua_State *l, ByteString eventName); - static bool HandleEvent(LuaScriptInterface *luacon_ci, Event *event, ByteString eventName); - - static String luacon_geterror(LuaScriptInterface *luacon_ci); -}; diff --git a/src/lua/LuaScriptInterface.cpp b/src/lua/LuaScriptInterface.cpp index e67196b18..8ccd33ba0 100644 --- a/src/lua/LuaScriptInterface.cpp +++ b/src/lua/LuaScriptInterface.cpp @@ -3,6 +3,7 @@ #include "client/http/Request.h" // includes curl.h, needs to come first to silence a warning on windows #include "bzip2/bz2wrap.h" +#include "common/VariantIndex.h" #include "LuaScriptInterface.h" @@ -18,7 +19,6 @@ #include "LuaBit.h" #include "LuaButton.h" #include "LuaCheckbox.h" -#include "LuaEvents.h" #include "LuaLabel.h" #include "LuaProgressBar.h" #include "LuaSlider.h" @@ -420,6 +420,14 @@ tpt.partsdata = nil"); lua_el_mode_v = std::vector(PT_NUM, 0); lua_el_mode = &lua_el_mode_v[0]; + gameControllerEventHandlers = std::vector(std::variant_size::value, l); + for (auto &ref : gameControllerEventHandlers) + { + lua_newtable(l); + ref.Assign(l, -1); + lua_pop(l, 1); + } + luaCtypeDrawHandlers = std::vector(PT_NUM, l); luaCreateHandlers = std::vector(PT_NUM, l); luaCreateAllowedHandlers = std::vector(PT_NUM, l); @@ -4156,33 +4164,60 @@ void LuaScriptInterface::initEventAPI() lua_getglobal(l, "event"); lua_setglobal(l, "evt"); - lua_pushinteger(l, LuaEvents::keypress); lua_setfield(l, -2, "keypress"); - lua_pushinteger(l, LuaEvents::keyrelease); lua_setfield(l, -2, "keyrelease"); - lua_pushinteger(l, LuaEvents::textinput); lua_setfield(l, -2, "textinput"); - lua_pushinteger(l, LuaEvents::textediting); lua_setfield(l, -2, "textediting"); - lua_pushinteger(l, LuaEvents::mousedown); lua_setfield(l, -2, "mousedown"); - lua_pushinteger(l, LuaEvents::mouseup); lua_setfield(l, -2, "mouseup"); - lua_pushinteger(l, LuaEvents::mousemove); lua_setfield(l, -2, "mousemove"); - lua_pushinteger(l, LuaEvents::mousewheel); lua_setfield(l, -2, "mousewheel"); - lua_pushinteger(l, LuaEvents::tick); lua_setfield(l, -2, "tick"); - lua_pushinteger(l, LuaEvents::blur); lua_setfield(l, -2, "blur"); - lua_pushinteger(l, LuaEvents::close); lua_setfield(l, -2, "close"); - lua_pushinteger(l, LuaEvents::beforesim); lua_setfield(l, -2, "beforesim"); - lua_pushinteger(l, LuaEvents::aftersim); lua_setfield(l, -2, "aftersim"); + lua_pushinteger(l, VariantIndex()); lua_setfield(l, -2, "textinput" ); + lua_pushinteger(l, VariantIndex()); lua_setfield(l, -2, "textediting"); + lua_pushinteger(l, VariantIndex()); lua_setfield(l, -2, "keypress" ); + lua_pushinteger(l, VariantIndex()); lua_setfield(l, -2, "keyrelease" ); + lua_pushinteger(l, VariantIndex()); lua_setfield(l, -2, "mousedown" ); + lua_pushinteger(l, VariantIndex()); lua_setfield(l, -2, "mouseup" ); + lua_pushinteger(l, VariantIndex()); lua_setfield(l, -2, "mousemove" ); + lua_pushinteger(l, VariantIndex()); lua_setfield(l, -2, "mousewheel" ); + lua_pushinteger(l, VariantIndex()); lua_setfield(l, -2, "tick" ); + lua_pushinteger(l, VariantIndex()); lua_setfield(l, -2, "blur" ); + lua_pushinteger(l, VariantIndex()); lua_setfield(l, -2, "close" ); + lua_pushinteger(l, VariantIndex()); lua_setfield(l, -2, "beforesim" ); + lua_pushinteger(l, VariantIndex()); lua_setfield(l, -2, "aftersim" ); } int LuaScriptInterface::event_register(lua_State * l) { - int eventName = luaL_checkinteger(l, 1); + int eventType = luaL_checkinteger(l, 1); luaL_checktype(l, 2, LUA_TFUNCTION); - return LuaEvents::RegisterEventHook(l, ByteString::Build("tptevents-", eventName)); + if (eventType < 0 || eventType >= int(luacon_ci->gameControllerEventHandlers.size())) + { + luaL_error(l, "Invalid event type: %i", lua_tointeger(l, 1)); + } + luacon_ci->gameControllerEventHandlers[eventType].Push(l); + auto length = lua_objlen(l, -1); + lua_pushvalue(l, 2); + lua_rawseti(l, -2, length + 1); + lua_pushvalue(l, 2); + return 1; } int LuaScriptInterface::event_unregister(lua_State * l) { - int eventName = luaL_checkinteger(l, 1); + int eventType = luaL_checkinteger(l, 1); luaL_checktype(l, 2, LUA_TFUNCTION); - return LuaEvents::UnregisterEventHook(l, ByteString::Build("tptevents-", eventName)); + if (eventType < 0 || eventType >= int(luacon_ci->gameControllerEventHandlers.size())) + { + luaL_error(l, "Invalid event type: %i", lua_tointeger(l, 1)); + } + luacon_ci->gameControllerEventHandlers[eventType].Push(l); + auto length = lua_objlen(l, -1); + int skip = 0; + for (auto i = 1U; i <= length; ++i) + { + lua_rawgeti(l, -1, i); + if (!skip && lua_equal(l, -1, 2)) + { + skip = 1; + } + lua_pop(l, 1); + lua_rawgeti(l, -1, i + skip); + lua_rawseti(l, -2, i); + } + return 0; } int LuaScriptInterface::event_getmodifiers(lua_State * l) @@ -4494,9 +4529,109 @@ void LuaScriptInterface::initHttpAPI() lua_setglobal(l, "http"); } -bool LuaScriptInterface::HandleEvent(LuaEvents::EventTypes eventType, Event * event) +static int PushGameControllerEvent(lua_State * l, const GameControllerEvent &event) { - return LuaEvents::HandleEvent(this, event, ByteString::Build("tptevents-", eventType)); + if (auto *textInputEvent = std::get_if(&event)) + { + tpt_lua_pushString(l, textInputEvent->text); + return 1; + } + else if (auto *textEditingEvent = std::get_if(&event)) + { + tpt_lua_pushString(l, textEditingEvent->text); + return 1; + } + else if (auto *keyPressEvent = std::get_if(&event)) + { + lua_pushinteger(l, keyPressEvent->key); + lua_pushinteger(l, keyPressEvent->scan); + lua_pushboolean(l, keyPressEvent->repeat); + lua_pushboolean(l, keyPressEvent->shift); + lua_pushboolean(l, keyPressEvent->ctrl); + lua_pushboolean(l, keyPressEvent->alt); + return 6; + } + else if (auto *keyReleaseEvent = std::get_if(&event)) + { + lua_pushinteger(l, keyReleaseEvent->key); + lua_pushinteger(l, keyReleaseEvent->scan); + lua_pushboolean(l, keyReleaseEvent->repeat); + lua_pushboolean(l, keyReleaseEvent->shift); + lua_pushboolean(l, keyReleaseEvent->ctrl); + lua_pushboolean(l, keyReleaseEvent->alt); + return 6; + } + else if (auto *mouseDownEvent = std::get_if(&event)) + { + lua_pushinteger(l, mouseDownEvent->x); + lua_pushinteger(l, mouseDownEvent->y); + lua_pushinteger(l, mouseDownEvent->button); + return 3; + } + else if (auto *mouseUpEvent = std::get_if(&event)) + { + lua_pushinteger(l, mouseUpEvent->x); + lua_pushinteger(l, mouseUpEvent->y); + lua_pushinteger(l, mouseUpEvent->button); + lua_pushinteger(l, mouseUpEvent->reason); + return 4; + } + else if (auto *mouseMoveEvent = std::get_if(&event)) + { + lua_pushinteger(l, mouseMoveEvent->x); + lua_pushinteger(l, mouseMoveEvent->y); + lua_pushinteger(l, mouseMoveEvent->dx); + lua_pushinteger(l, mouseMoveEvent->dy); + return 4; + } + else if (auto *mouseWheelEvent = std::get_if(&event)) + { + lua_pushinteger(l, mouseWheelEvent->x); + lua_pushinteger(l, mouseWheelEvent->y); + lua_pushinteger(l, mouseWheelEvent->d); + return 3; + } + return 0; +} + +bool LuaScriptInterface::HandleEvent(const GameControllerEvent &event) +{ + ui::Engine::Ref().LastTick(Platform::GetTime()); + bool cont = true; + gameControllerEventHandlers[event.index()].Push(l); + int len = lua_objlen(l, -1); + for (int i = 1; i <= len && cont; i++) + { + lua_rawgeti(l, -1, i); + int numArgs = PushGameControllerEvent(l, event); + int callret = lua_pcall(l, numArgs, 1, 0); + if (callret) + { + if (luacon_geterror() == "Error: Script not responding") + { + ui::Engine::Ref().LastTick(Platform::GetTime()); + for (int j = i; j <= len - 1; j++) + { + lua_rawgeti(l, -2, j + 1); + lua_rawseti(l, -3, j); + } + lua_pushnil(l); + lua_rawseti(l, -3, len); + i--; + } + Log(CommandInterface::LogError, luacon_geterror()); + lua_pop(l, 1); + } + else + { + if (!lua_isnoneornil(l, -1)) + cont = lua_toboolean(l, -1); + lua_pop(l, 1); + } + len = lua_objlen(l, -1); + } + lua_pop(l, 1); + return cont; } void LuaScriptInterface::OnTick() @@ -4508,8 +4643,7 @@ void LuaScriptInterface::OnTick() lua_setfield(l, -2, "NUM_PARTS"); } lua_pop(l, 1); - TickEvent ev; - HandleEvent(LuaEvents::tick, &ev); + HandleEvent(TickEvent{}); } int LuaScriptInterface::Command(String command) @@ -4806,6 +4940,7 @@ LuaScriptInterface::~LuaScriptInterface() { luaCreateAllowedHandlers.clear(); luaCreateHandlers.clear(); luaCtypeDrawHandlers.clear(); + gameControllerEventHandlers.clear(); lua_el_mode_v.clear(); lua_el_func_v.clear(); lua_gr_func_v.clear(); diff --git a/src/lua/LuaScriptInterface.h b/src/lua/LuaScriptInterface.h index ba91cd3db..e8eaad9cf 100644 --- a/src/lua/LuaScriptInterface.h +++ b/src/lua/LuaScriptInterface.h @@ -5,7 +5,7 @@ #include "LuaSmartRef.h" #include "CommandInterface.h" -#include "lua/LuaEvents.h" +#include "gui/game/GameControllerEvents.h" #include "simulation/StructProperty.h" #include "simulation/ElementDefs.h" @@ -194,6 +194,7 @@ class LuaScriptInterface: public CommandInterface std::vector lua_el_func_v, lua_gr_func_v, lua_cd_func_v; std::vector lua_el_mode_v; + std::vector gameControllerEventHandlers; public: int tpt_index(lua_State *l); @@ -212,7 +213,7 @@ public: void custom_init_can_move(); void OnTick() override; - bool HandleEvent(LuaEvents::EventTypes eventType, Event * event) override; + bool HandleEvent(const GameControllerEvent &event) override; void Init(); void SetWindow(ui::Window * window); diff --git a/src/meson.build b/src/meson.build index f34b863a7..1aee21f8b 100644 --- a/src/meson.build +++ b/src/meson.build @@ -6,7 +6,6 @@ powder_files = files( 'Update.cpp', 'PowderToySDL.cpp', 'lua/CommandInterface.cpp', - 'lua/LuaEvents.cpp', 'lua/TPTScriptInterface.cpp', 'lua/TPTSTypes.cpp', ) diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index b30e41ceb..f92b684e0 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -4999,7 +4999,7 @@ void Simulation::BeforeSim() if (!sys_pause||framerender) { #ifdef LUACONSOLE - luacon_ci->HandleEvent(LuaEvents::beforesim, new BeforeSimEvent()); + luacon_ci->HandleEvent(BeforeSimEvent{}); #endif air->update_air(); @@ -5204,7 +5204,7 @@ void Simulation::AfterSim() } #ifdef LUACONSOLE - luacon_ci->HandleEvent(LuaEvents::aftersim, new AfterSimEvent()); + luacon_ci->HandleEvent(AfterSimEvent{}); #endif }