diff --git a/src/gui/game/GameController.cpp b/src/gui/game/GameController.cpp index b52cb40b3..0cbb2e48e 100644 --- a/src/gui/game/GameController.cpp +++ b/src/gui/game/GameController.cpp @@ -37,6 +37,7 @@ #else #include "lua/TPTScriptInterface.h" #endif +#include "lua/LuaEvents.h" using namespace std; @@ -157,11 +158,6 @@ GameController::GameController(): commandInterface = new TPTScriptInterface(this, gameModel); #endif - ActiveToolChanged(0, gameModel->GetActiveTool(0)); - ActiveToolChanged(1, gameModel->GetActiveTool(1)); - ActiveToolChanged(2, gameModel->GetActiveTool(2)); - ActiveToolChanged(3, gameModel->GetActiveTool(3)); - Client::Ref().AddListener(this); debugInfo.push_back(new DebugParts(0x1, gameModel->GetSimulation())); @@ -626,12 +622,12 @@ void GameController::CutRegion(ui::Point point1, ui::Point point2, bool includeP bool GameController::MouseMove(int x, int y, int dx, int dy) { - return commandInterface->OnMouseMove(x, y, dx, dy); + return commandInterface->HandleEvent(EventTypes::mousemove, new MouseMoveEvent(x, y, dx, dy)); } bool GameController::MouseDown(int x, int y, unsigned button) { - bool ret = commandInterface->OnMouseDown(x, y, button); + bool ret = commandInterface->HandleEvent(EventTypes::mousedown, new MouseDownEvent(x, y, button)); if (ret && yGetPlacingSave() && !gameView->GetPlacingZoom()) { ui::Point point = gameModel->AdjustZoomCoords(ui::Point(x, y)); @@ -653,7 +649,7 @@ bool GameController::MouseDown(int x, int y, unsigned button) bool GameController::MouseUp(int x, int y, unsigned button, char type) { - bool ret = commandInterface->OnMouseUp(x, y, button, type); + bool ret = commandInterface->HandleEvent(EventTypes::mouseup, new MouseUpEvent(x, y, button, type)); if (type) return ret; if (ret && foundSignID != -1 && yGetPlacingSave()) @@ -711,12 +707,17 @@ bool GameController::MouseUp(int x, int y, unsigned button, char type) bool GameController::MouseWheel(int x, int y, int d) { - return commandInterface->OnMouseWheel(x, y, d); + return commandInterface->HandleEvent(EventTypes::mousewheel, new MouseWheelEvent(x, y, d)); +} + +bool GameController::TextInput(String text) +{ + return commandInterface->HandleEvent(EventTypes::textinput, new TextInputEvent(text)); } bool GameController::KeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt) { - bool ret = commandInterface->OnKeyPress(key, scan, repeat, shift, ctrl, alt); + bool ret = commandInterface->HandleEvent(EventTypes::keypress, new KeyEvent(key, scan, repeat, shift, ctrl, alt)); if (repeat) return ret; if (ret) @@ -795,7 +796,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) { - bool ret = commandInterface->OnKeyRelease(key, scan, repeat, shift, ctrl, alt); + bool ret = commandInterface->HandleEvent(EventTypes::keyrelease, new KeyEvent(key, scan, repeat, shift, ctrl, alt)); if (repeat) return ret; if (ret) @@ -832,11 +833,6 @@ bool GameController::KeyRelease(int key, int scan, bool repeat, bool shift, bool return ret; } -bool GameController::MouseTick() -{ - return commandInterface->OnMouseTick(); -} - void GameController::Tick() { if(firstTick) @@ -1150,11 +1146,6 @@ void GameController::RebuildFavoritesMenu() gameModel->BuildFavoritesMenu(); } -void GameController::ActiveToolChanged(int toolSelection, Tool *tool) -{ - commandInterface->OnActiveToolChanged(toolSelection, tool); -} - Tool * GameController::GetActiveTool(int selection) { return gameModel->GetActiveTool(selection); diff --git a/src/gui/game/GameController.h b/src/gui/game/GameController.h index 119aeb408..2431d2495 100644 --- a/src/gui/game/GameController.h +++ b/src/gui/game/GameController.h @@ -64,9 +64,9 @@ public: bool MouseDown(int x, int y, unsigned button); bool MouseUp(int x, int y, unsigned button, char type); bool MouseWheel(int x, int y, int d); + bool TextInput(String text); bool KeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt); bool KeyRelease(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt); - bool MouseTick(); void Tick(); void Exit(); @@ -113,7 +113,6 @@ public: void SetLastTool(Tool * tool); int GetReplaceModeFlags(); void SetReplaceModeFlags(int flags); - void ActiveToolChanged(int toolSelection, Tool *tool); void SetActiveColourPreset(int preset); void SetColour(ui::Colour colour); void SetToolStrength(float value); diff --git a/src/gui/game/GameView.cpp b/src/gui/game/GameView.cpp index d9bc533f8..c1cba9b1e 100644 --- a/src/gui/game/GameView.cpp +++ b/src/gui/game/GameView.cpp @@ -709,8 +709,7 @@ void GameView::NotifyActiveToolsChanged(GameModel * sender) toolButtons[i]->SetSelectionState(-1); } } - //need to do this for all tools every time just in case it wasn't caught if you weren't in the menu a tool was changed to - c->ActiveToolChanged(0, sender->GetActiveTool(0)); + if (sender->GetRenderer()->findingElement) { Tool *active = sender->GetActiveTool(0); @@ -719,9 +718,6 @@ void GameView::NotifyActiveToolsChanged(GameModel * sender) else ren->findingElement = sender->GetActiveTool(0)->GetToolID()%256; } - c->ActiveToolChanged(1, sender->GetActiveTool(1)); - c->ActiveToolChanged(2, sender->GetActiveTool(2)); - c->ActiveToolChanged(3, sender->GetActiveTool(3)); } void GameView::NotifyLastToolChanged(GameModel * sender) @@ -1841,6 +1837,12 @@ void GameView::DoMouseWheel(int x, int y, int d) Window::DoMouseWheel(x, y, d); } +void GameView::DoTextInput(String text) +{ + if (c->TextInput(text)) + Window::DoTextInput(text); +} + void GameView::DoKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt) { if (c->KeyPress(key, scan, repeat, shift, ctrl, alt)) @@ -1853,18 +1855,6 @@ void GameView::DoKeyRelease(int key, int scan, bool repeat, bool shift, bool ctr Window::DoKeyRelease(key, scan, repeat, shift, ctrl, alt); } -void GameView::DoTick(float dt) -{ - //mouse events trigger every frame when mouse is held down, needs to happen here (before things are drawn) so it can clear the point queue if false is returned from a lua mouse event - if (!c->MouseTick()) - { - isMouseDown = false; - selectMode = SelectNone; - drawMode = DrawPoints; - } - Window::DoTick(dt); -} - void GameView::DoDraw() { Window::DoDraw(); diff --git a/src/gui/game/GameView.h b/src/gui/game/GameView.h index 4bba4b869..5a6cd1e35 100644 --- a/src/gui/game/GameView.h +++ b/src/gui/game/GameView.h @@ -198,12 +198,12 @@ public: virtual void OnBlur(); //Top-level handlers, for Lua interface - virtual void DoTick(float dt); virtual void DoDraw(); virtual void DoMouseMove(int x, int y, int dx, int dy); virtual void DoMouseDown(int x, int y, unsigned button); virtual void DoMouseUp(int x, int y, unsigned button); virtual void DoMouseWheel(int x, int y, int d); + virtual void DoTextInput(String text); virtual void DoKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt); virtual void DoKeyRelease(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt); diff --git a/src/lua/CommandInterface.h b/src/lua/CommandInterface.h index 516a3c312..09d338fb6 100644 --- a/src/lua/CommandInterface.h +++ b/src/lua/CommandInterface.h @@ -2,13 +2,16 @@ #define COMMANDINTERFACE_H_ #include "common/String.h" +#include "lua/LuaEvents.h" #include "gui/interface/Engine.h" -//#include "game/GameModel.h" +class Event; class GameModel; class GameController; class Tool; -class CommandInterface { + +class CommandInterface +{ protected: String lastError; GameModel * m; @@ -20,15 +23,11 @@ public: int GetPropertyOffset(ByteString key, FormatType & format); void Log(LogType type, String message); //void AttachGameModel(GameModel * m); - virtual bool OnActiveToolChanged(int toolSelection, Tool * tool) {return true;} - virtual bool OnMouseMove(int x, int y, int dx, int dy) {return true;} - virtual bool OnMouseDown(int x, int y, unsigned button) {return true;} - virtual bool OnMouseUp(int x, int y, unsigned button, char type) {return true;} - virtual bool OnMouseWheel(int x, int y, int d) {return true;} - virtual bool OnKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt) {return true;} - virtual bool OnKeyRelease(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt) {return true;} - virtual bool OnMouseTick() { return true; } + virtual void OnTick() { } + + virtual bool HandleEvent(EventTypes eventType, Event * event) { return true; } + virtual int Command(String command); virtual String FormatCommand(String command); String GetLastError(); diff --git a/src/lua/LegacyLuaAPI.cpp b/src/lua/LegacyLuaAPI.cpp index 7666aa889..8c8bb7d56 100644 --- a/src/lua/LegacyLuaAPI.cpp +++ b/src/lua/LegacyLuaAPI.cpp @@ -243,164 +243,6 @@ int luacon_elementwrite(lua_State* l) return 0; } -bool shortcuts = true; -int luacon_keyevent(int key, int scan, int modifier, int event) -{ - ui::Engine::Ref().LastTick(Platform::GetTime()); - int kycontinue = 1; - lua_State* l=luacon_ci->l; - lua_pushstring(l, "keyfunctions"); - lua_rawget(l, LUA_REGISTRYINDEX); - if(!lua_istable(l, -1)) - { - lua_pop(l, 1); - lua_newtable(l); - lua_pushstring(l, "keyfunctions"); - lua_pushvalue(l, -2); - lua_rawset(l, LUA_REGISTRYINDEX); - } - int len = lua_objlen(l, -1); - for (int i = 1; i <= len && kycontinue; i++) - { - lua_rawgeti(l, -1, i); - if ((modifier & KMOD_CTRL) && (scan < ' ' || scan > '~') && key < 256) - lua_pushlstring(l, (const char*)&key, 1); - else - lua_pushlstring(l, (const char*)&scan, 1); - lua_pushinteger(l, key); - lua_pushinteger(l, modifier); - lua_pushinteger(l, event); - int callret = lua_pcall(l, 4, 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--; - } - luacon_ci->Log(CommandInterface::LogError, luacon_geterror()); - lua_pop(l, 1); - } - else - { - if(!lua_isnoneornil(l, -1)) - kycontinue = lua_toboolean(l, -1); - lua_pop(l, 1); - } - len = lua_objlen(l, -1); - } - lua_pop(l, 1); - return kycontinue && shortcuts; -} - -int luacon_mouseevent(int mx, int my, int mb, int event, int mouse_wheel) -{ - ui::Engine::Ref().LastTick(Platform::GetTime()); - int mpcontinue = 1; - lua_State* l=luacon_ci->l; - lua_pushstring(l, "mousefunctions"); - lua_rawget(l, LUA_REGISTRYINDEX); - if(!lua_istable(l, -1)) - { - lua_pop(l, 1); - lua_newtable(l); - lua_pushstring(l, "mousefunctions"); - lua_pushvalue(l, -2); - lua_rawset(l, LUA_REGISTRYINDEX); - } - int len = lua_objlen(l, -1); - for (int i = 1; i <= len && mpcontinue; i++) - { - lua_rawgeti(l, -1, i); - lua_pushinteger(l, mx); - lua_pushinteger(l, my); - lua_pushinteger(l, mb); - lua_pushinteger(l, event); - lua_pushinteger(l, mouse_wheel); - int callret = lua_pcall(l, 5, 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--; - } - luacon_ci->Log(CommandInterface::LogError, luacon_geterror()); - lua_pop(l, 1); - } - else - { - if(!lua_isnoneornil(l, -1)) - mpcontinue = lua_toboolean(l, -1); - lua_pop(l, 1); - } - len = lua_objlen(l, -1); - } - lua_pop(l, 1); - return mpcontinue; -} - -int luacon_step(int mx, int my) -{ - ui::Engine::Ref().LastTick(Platform::GetTime()); - lua_State* l = luacon_ci->l; - lua_pushinteger(l, my); - lua_pushinteger(l, mx); - lua_setfield(l, tptProperties, "mousex"); - lua_setfield(l, tptProperties, "mousey"); - lua_pushstring(l, "stepfunctions"); - lua_rawget(l, LUA_REGISTRYINDEX); - if (!lua_istable(l, -1)) - { - lua_pop(l, 1); - lua_newtable(l); - lua_pushstring(l, "stepfunctions"); - lua_pushvalue(l, -2); - lua_rawset(l, LUA_REGISTRYINDEX); - } - int len = lua_objlen(l, -1); - for (int i = 1; i <= len; i++) - { - lua_rawgeti(l, -1, i); - int callret = lua_pcall(l, 0, 0, 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--; - } - luacon_ci->Log(CommandInterface::LogError, luacon_geterror()); - lua_pop(l, 1); - } - len = lua_objlen(l, -1); - } - lua_pop(l, 1); - return 0; -} - - int luacon_eval(const char *command) { ui::Engine::Ref().LastTick(Platform::GetTime()); @@ -417,30 +259,6 @@ void luacon_hook(lua_State * l, lua_Debug * ar) } } -int luaL_tostring (lua_State *L, int n) -{ - luaL_checkany(L, n); - switch (lua_type(L, n)) - { - case LUA_TNUMBER: - lua_pushstring(L, lua_tostring(L, n)); - break; - case LUA_TSTRING: - lua_pushvalue(L, n); - break; - case LUA_TBOOLEAN: - lua_pushstring(L, (lua_toboolean(L, n) ? "true" : "false")); - break; - case LUA_TNIL: - lua_pushliteral(L, "nil"); - break; - default: - lua_pushfstring(L, "%s: %p", luaL_typename(L, n), lua_topointer(L, n)); - break; - } - return 1; -} - String luacon_geterror() { luaL_tostring(luacon_ci->l, -1); @@ -449,15 +267,7 @@ String luacon_geterror() return err; } -//TPT Interface methods -int luatpt_test(lua_State* l) -{ - int testint = 0; - testint = luaL_optint(l, 1, 0); - printf("Test successful, got %d\n", testint); - return 0; -} - +//tpt. api methods int luatpt_getelement(lua_State *l) { int t; @@ -1272,19 +1082,6 @@ int luatpt_get_name(lua_State* l) return 1; } -int luatpt_set_shortcuts(lua_State* l) -{ - int acount = lua_gettop(l); - if (acount == 0) - { - lua_pushnumber(l, shortcuts); - return 1; - } - int shortcut = luaL_checkinteger(l, 1); - shortcuts = shortcut?true:false; - return 0; -} - int luatpt_delete(lua_State* l) { int arg1, arg2; @@ -1304,171 +1101,6 @@ int luatpt_delete(lua_State* l) return luaL_error(l,"Invalid coordinates or particle ID"); } -int luatpt_register_step(lua_State* l) -{ - if (lua_isfunction(l, 1)) - { - lua_pushstring(l, "stepfunctions"); - lua_rawget(l, LUA_REGISTRYINDEX); - if (!lua_istable(l, -1)) - { - lua_pop(l, 1); - lua_newtable(l); - lua_pushstring(l, "stepfunctions"); - lua_pushvalue(l, -2); - lua_rawset(l, LUA_REGISTRYINDEX); - } - int c = lua_objlen(l, -1); - lua_pushvalue(l, 1); - lua_rawseti(l, -2, c+1); - } - return 0; -} - -int luatpt_unregister_step(lua_State* l) -{ - if (lua_isfunction(l, 1)) - { - lua_pushstring(l, "stepfunctions"); - lua_rawget(l, LUA_REGISTRYINDEX); - if (!lua_istable(l, -1)) - { - lua_pop(l, -1); - lua_newtable(l); - lua_pushstring(l, "stepfunctions"); - 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, 1, -1)) - { - lua_pop(l, 1); - adjust++; - i--; - } - //else, move everything down if we removed something earlier - else - { - lua_rawseti(l, -2, i); - } - } - } - return 0; -} - -int luatpt_register_keypress(lua_State* l) -{ - if (lua_isfunction(l, 1)) - { - lua_pushstring(l, "keyfunctions"); - lua_rawget(l, LUA_REGISTRYINDEX); - if (!lua_istable(l, -1)) - { - lua_pop(l, 1); - lua_newtable(l); - lua_pushstring(l, "keyfunctions"); - lua_pushvalue(l, -2); - lua_rawset(l, LUA_REGISTRYINDEX); - } - int c = lua_objlen(l, -1); - lua_pushvalue(l, 1); - lua_rawseti(l, -2, c+1); - } - return 0; -} - -int luatpt_unregister_keypress(lua_State* l) -{ - if (lua_isfunction(l, 1)) - { - lua_pushstring(l, "keyfunctions"); - lua_rawget(l, LUA_REGISTRYINDEX); - if (!lua_istable(l, -1)) - { - lua_pop(l, 1); - lua_newtable(l); - lua_pushstring(l, "keyfunctions"); - lua_pushvalue(l, -2); - lua_rawset(l, LUA_REGISTRYINDEX); - } - int c = lua_objlen(l, -1); - int d = 0; - int i = 0; - for (i=1;i<=c;i++) - { - lua_rawgeti(l, -1, i+d); - if (lua_equal(l, 1, -1)) - { - lua_pop(l, 1); - d++; - i--; - } - else - lua_rawseti(l, -2, i); - } - } - return 0; -} - -int luatpt_register_mouseclick(lua_State* l) -{ - if (lua_isfunction(l, 1)) - { - lua_pushstring(l, "mousefunctions"); - lua_rawget(l, LUA_REGISTRYINDEX); - if (!lua_istable(l, -1)) - { - lua_pop(l, 1); - lua_newtable(l); - lua_pushstring(l, "mousefunctions"); - lua_pushvalue(l, -2); - lua_rawset(l, LUA_REGISTRYINDEX); - } - int c = lua_objlen(l, -1); - lua_pushvalue(l, 1); - lua_rawseti(l, -2, c+1); - } - return 0; -} - -int luatpt_unregister_mouseclick(lua_State* l) -{ - if (lua_isfunction(l, 1)) - { - lua_pushstring(l, "mousefunctions"); - lua_rawget(l, LUA_REGISTRYINDEX); - if (!lua_istable(l, -1)) - { - lua_pop(l, 1); - lua_newtable(l); - lua_pushstring(l, "mousefunctions"); - lua_pushvalue(l, -2); - lua_rawset(l, LUA_REGISTRYINDEX); - } - int c = lua_objlen(l, -1); - int d = 0; - int i = 0; - for (i=1;i<=c;i++) - { - lua_rawgeti(l, -1, i+d); - if (lua_equal(l, 1, -1)) - { - lua_pop(l, 1); - d++; - i--; - } - else - lua_rawseti(l, -2, i); - } - } - return 0; -} - int luatpt_input(lua_State* l) { String prompt, title, result, shadow, text; diff --git a/src/lua/LuaCompat.c b/src/lua/LuaCompat.c index 7283b64c9..d3f38ebf0 100644 --- a/src/lua/LuaCompat.c +++ b/src/lua/LuaCompat.c @@ -17,3 +17,28 @@ void lua_pushglobaltable(lua_State *L) } #endif + +// Useful helper function, mainly used for logging +int luaL_tostring(lua_State *L, int n) +{ + luaL_checkany(L, n); + switch (lua_type(L, n)) + { + case LUA_TNUMBER: + lua_pushstring(L, lua_tostring(L, n)); + break; + case LUA_TSTRING: + lua_pushvalue(L, n); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, n) ? "true" : "false")); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + default: + lua_pushfstring(L, "%s: %p", luaL_typename(L, n), lua_topointer(L, n)); + break; + } + return 1; +} diff --git a/src/lua/LuaCompat.h b/src/lua/LuaCompat.h index 307347abb..027929522 100644 --- a/src/lua/LuaCompat.h +++ b/src/lua/LuaCompat.h @@ -29,6 +29,7 @@ LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); #else LUALIB_API void (lua_pushglobaltable) (lua_State *L); #endif +int luaL_tostring(lua_State *L, int n); #ifdef __cplusplus } diff --git a/src/lua/LuaEvents.cpp b/src/lua/LuaEvents.cpp new file mode 100644 index 000000000..ecff5816b --- /dev/null +++ b/src/lua/LuaEvents.cpp @@ -0,0 +1,244 @@ +#include "LuaEvents.h" +#ifdef LUACONSOLE +#include "LuaCompat.h" +#include "LuaScriptInterface.h" + +#include "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 + lua_pushstring(l, str.c_str()); +#endif +} + +TextInputEvent::TextInputEvent(String text): + text(text) +{} + +int TextInputEvent::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)) + { + lua_pushstring(l, eventName.c_str()); + lua_rawget(l, LUA_REGISTRYINDEX); + if (!lua_istable(l, -1)) + { + lua_pop(l, 1); + lua_newtable(l); + lua_pushstring(l, eventName.c_str()); + 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; +} + +#include +int LuaEvents::UnregisterEventHook(lua_State *l, ByteString eventName) +{ + if (lua_isfunction(l, 2)) + { + lua_pushstring(l, eventName.c_str()); + lua_rawget(l, LUA_REGISTRYINDEX); + if (!lua_istable(l, -1)) + { + lua_pop(l, -1); + lua_newtable(l); + lua_pushstring(l, eventName.c_str()); + 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; + lua_pushstring(l, eventName.c_str()); + lua_rawget(l, LUA_REGISTRYINDEX); + if (!lua_istable(l, -1)) + { + lua_pop(l, 1); + lua_newtable(l); + lua_pushstring(l, eventName.c_str()); + 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 = ByteString(luaL_optstring(luacon_ci->l, -1, "failed to execute")).FromUtf8(); + lua_pop(luacon_ci->l, 1); + return err; +} +#endif diff --git a/src/lua/LuaEvents.h b/src/lua/LuaEvents.h new file mode 100644 index 000000000..b57704893 --- /dev/null +++ b/src/lua/LuaEvents.h @@ -0,0 +1,122 @@ +#ifndef LUAEVENTS_H +#define LUAEVENTS_H + +#include "common/String.h" + +class 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; +}; + +class TextInputEvent : public Event +{ + String text; + +public: + TextInputEvent(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; } +}; + +enum EventTypes { + keypress, + keyrelease, + textinput, + mousedown, + mouseup, + mousemove, + mousewheel, + tick +}; + +class LuaEvents +{ +public: + 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); +}; + +#endif // LUAEVENTS_H diff --git a/src/lua/LuaScriptHelper.h b/src/lua/LuaScriptHelper.h index c65d9c74d..f56bfc2bf 100644 --- a/src/lua/LuaScriptHelper.h +++ b/src/lua/LuaScriptHelper.h @@ -9,7 +9,6 @@ extern Graphics * luacon_g; extern Renderer * luacon_ren; extern bool *luacon_currentCommand; -extern int luaL_tostring(lua_State* l, int n); extern String *luacon_lastError; extern int *lua_el_func, *lua_el_mode, *lua_gr_func; @@ -21,9 +20,6 @@ extern int tptElements; //Table for TPT element names extern int tptParts, tptPartsMeta, tptElementTransitions, tptPartsCData, tptPartMeta, tptPart, cIndex; void luacon_hook(lua_State *L, lua_Debug *ar); -int luacon_step(int mx, int my); -int luacon_mouseevent(int mx, int my, int mb, int event, int mouse_wheel); -int luacon_keyevent(int key, int scan, int modifier, int event); int luacon_eval(const char *command); String luacon_geterror(); void luacon_close(); @@ -38,8 +34,7 @@ int luacon_transitionread(lua_State* l); int luacon_transitionwrite(lua_State* l); //int process_command_lua(pixel *vid_buf, char *console, char *console_error); -//Interface -int luatpt_test(lua_State* l); +//tpt. api int luatpt_getelement(lua_State *l); int luacon_graphicsReplacement(GRAPHICS_FUNC_ARGS, int i); @@ -94,15 +89,7 @@ int luatpt_drawline(lua_State* l); int luatpt_textwidth(lua_State* l); int luatpt_get_name(lua_State* l); -int luatpt_set_shortcuts(lua_State* l); - int luatpt_delete(lua_State* l); -int luatpt_register_step(lua_State* l); -int luatpt_unregister_step(lua_State* l); -int luatpt_register_keypress(lua_State* l); -int luatpt_unregister_keypress(lua_State* l); -int luatpt_register_mouseclick(lua_State* l); -int luatpt_unregister_mouseclick(lua_State* l); int luatpt_input(lua_State* l); int luatpt_message_box(lua_State* l); int luatpt_confirm(lua_State* l); diff --git a/src/lua/LuaScriptInterface.cpp b/src/lua/LuaScriptInterface.cpp index 796072197..d0d82e400 100644 --- a/src/lua/LuaScriptInterface.cpp +++ b/src/lua/LuaScriptInterface.cpp @@ -28,14 +28,14 @@ #include "PowderToy.h" #include "LuaBit.h" - -#include "LuaWindow.h" #include "LuaButton.h" -#include "LuaLabel.h" -#include "LuaTextbox.h" #include "LuaCheckbox.h" -#include "LuaSlider.h" +#include "LuaEvents.h" +#include "LuaLabel.h" #include "LuaProgressBar.h" +#include "LuaSlider.h" +#include "LuaTextbox.h" +#include "LuaWindow.h" #ifndef WIN #include @@ -136,11 +136,11 @@ LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m): initGraphicsAPI(); initFileSystemAPI(); initPlatformAPI(); + initEventAPI(); //Old TPT API int currentElementMeta, currentElement; const static struct luaL_Reg tptluaapi [] = { - {"test", &luatpt_test}, {"drawtext", &luatpt_drawtext}, {"create", &luatpt_create}, {"set_pause", &luatpt_setpause}, @@ -164,18 +164,7 @@ LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m): {"drawline", &luatpt_drawline}, {"textwidth", &luatpt_textwidth}, {"get_name", &luatpt_get_name}, - {"set_shortcuts", &luatpt_set_shortcuts}, {"delete", &luatpt_delete}, - {"register_step", &luatpt_register_step}, - {"unregister_step", &luatpt_unregister_step}, - {"register_mouseclick", &luatpt_register_mouseclick}, - {"unregister_mouseclick", &luatpt_unregister_mouseclick}, - {"register_keypress", &luatpt_register_keypress}, - {"unregister_keypress", &luatpt_unregister_keypress}, - {"register_mouseevent", &luatpt_register_mouseclick}, - {"unregister_mouseevent", &luatpt_unregister_mouseclick}, - {"register_keyevent", &luatpt_register_keypress}, - {"unregister_keyevent", &luatpt_unregister_keypress}, {"input", &luatpt_input}, {"message_box", &luatpt_message_box}, {"confirm", &luatpt_confirm}, @@ -226,11 +215,6 @@ LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m): tptProperties = lua_gettop(l); - lua_pushinteger(l, 0); - lua_setfield(l, tptProperties, "mousex"); - lua_pushinteger(l, 0); - lua_setfield(l, tptProperties, "mousey"); - lua_newtable(l); tptPropertiesVersion = lua_gettop(l); lua_pushinteger(l, SAVE_VERSION); @@ -373,19 +357,23 @@ void LuaScriptInterface::SetWindow(ui::Window * window) int LuaScriptInterface::tpt_index(lua_State *l) { ByteString key = luaL_checkstring(l, 2); - if (!key.compare("selectedl")) - return lua_pushstring(l, luacon_selectedl.c_str()), 1; - if (!key.compare("selectedr")) - return lua_pushstring(l, luacon_selectedr.c_str()), 1; - if (!key.compare("selecteda")) - return lua_pushstring(l, luacon_selectedalt.c_str()), 1; - if (!key.compare("selectedreplace")) - return lua_pushstring(l, luacon_selectedreplace.c_str()), 1; - if (!key.compare("brushx")) + if (!key.compare("mousex")) + return lua_pushnumber(l, c->GetView()->GetMousePosition().X), 1; + else if (!key.compare("mousey")) + return lua_pushnumber(l, c->GetView()->GetMousePosition().Y), 1; + else if (!key.compare("selectedl")) + return lua_pushstring(l, m->GetActiveTool(0)->GetIdentifier().c_str()), 1; + else if (!key.compare("selectedr")) + return lua_pushstring(l, m->GetActiveTool(1)->GetIdentifier().c_str()), 1; + else if (!key.compare("selecteda")) + return lua_pushstring(l, m->GetActiveTool(2)->GetIdentifier().c_str()), 1; + else if (!key.compare("selectedreplace")) + return lua_pushstring(l, m->GetActiveTool(3)->GetIdentifier().c_str()), 1; + else if (!key.compare("brushx")) return lua_pushnumber(l, m->GetBrush()->GetRadius().X), 1; - if (!key.compare("brushy")) + else if (!key.compare("brushy")) return lua_pushnumber(l, m->GetBrush()->GetRadius().Y), 1; - if (!key.compare("brushID")) + else if (!key.compare("brushID")) return lua_pushnumber(l, m->GetBrushID()), 1; //if not a special key, return the value in the table @@ -3299,99 +3287,57 @@ int LuaScriptInterface::platform_clipboardPaste(lua_State * l) return 0; } -bool LuaScriptInterface::OnActiveToolChanged(int toolSelection, Tool * tool) + +//// Begin Event API + +void LuaScriptInterface::initEventAPI() { - ByteString identifier; - if (tool) - identifier = tool->GetIdentifier(); - else - identifier = ""; - if (toolSelection == 0) - luacon_selectedl = identifier; - else if (toolSelection == 1) - luacon_selectedr = identifier; - else if (toolSelection == 2) - luacon_selectedalt = identifier; - else if (toolSelection == 3) - luacon_selectedreplace = identifier; - return true; + struct luaL_Reg eventAPIMethods [] = { + {"register", event_register}, + {"unregister", event_unregister}, + {"getmodifiers", event_getmodifiers}, + {NULL, NULL} + }; + luaL_register(l, "event", eventAPIMethods); + + lua_getglobal(l, "event"); + lua_setglobal(l, "evt"); + + lua_pushinteger(l, EventTypes::keypress); lua_setfield(l, -2, "keypress"); + lua_pushinteger(l, EventTypes::keyrelease); lua_setfield(l, -2, "keyrelease"); + lua_pushinteger(l, EventTypes::textinput); lua_setfield(l, -2, "textinput"); + lua_pushinteger(l, EventTypes::mousedown); lua_setfield(l, -2, "mousedown"); + lua_pushinteger(l, EventTypes::mouseup); lua_setfield(l, -2, "mouseup"); + lua_pushinteger(l, EventTypes::mousemove); lua_setfield(l, -2, "mousemove"); + lua_pushinteger(l, EventTypes::mousewheel); lua_setfield(l, -2, "mousewheel"); + lua_pushinteger(l, EventTypes::tick); lua_setfield(l, -2, "tick"); } -bool LuaScriptInterface::OnMouseMove(int x, int y, int dx, int dy) +int LuaScriptInterface::event_register(lua_State * l) { - luacon_mousex = x; - luacon_mousey = y; - return true; + //ByteString eventname = luaL_checkstring(l, 1); + int eventName = luaL_checkinteger(l, 1); + luaL_checktype(l, 2, LUA_TFUNCTION); + return LuaEvents::RegisterEventHook(l, ByteString::Build("tptevents-", eventName)); } -bool LuaScriptInterface::OnMouseDown(int x, int y, unsigned button) +int LuaScriptInterface::event_unregister(lua_State * l) { - if (button == 3) - button = 4; - luacon_mousedown = true; - luacon_mousebutton = button; - luacon_mousex = x; - luacon_mousey = y; - return luacon_mouseevent(x, y, button, LUACON_MDOWN, 0); + //ByteString eventname = luaL_checkstring(l, 1); + int eventName = luaL_checkinteger(l, 1); + luaL_checktype(l, 2, LUA_TFUNCTION); + return LuaEvents::UnregisterEventHook(l, ByteString::Build("tptevents-", eventName)); } -bool LuaScriptInterface::OnMouseUp(int x, int y, unsigned button, char type) +int LuaScriptInterface::event_getmodifiers(lua_State * l) { - luacon_mousebutton = 0; - if (type != 1) - { - luacon_mousex = x; - luacon_mousey = y; - } - if (button == 3) - button = 4; - - // mouse was never down, probably due to fake mouse event - if (!luacon_mousedown) - { - return true; - } - - // fake mouseup event, triggered when mouse drawing is canceled due to moving in / out of the zoom window - if (type == 2) - return luacon_mouseevent(x, y, button, LUACON_MUPZOOM, 0); - - luacon_mousedown = false; - - // fake mouseup event, triggered when user enters another interface while the mouse is down - if (type == 1) - return luacon_mouseevent(x, y, button, LUACON_MUPALT, 0); - else - return luacon_mouseevent(x, y, button, LUACON_MUP, 0); + lua_pushnumber(l, GetModifiers()); + return 1; } -bool LuaScriptInterface::OnMouseWheel(int x, int y, int d) +bool LuaScriptInterface::HandleEvent(EventTypes eventType, Event * event) { - return luacon_mouseevent(x, y, luacon_mousedown?luacon_mousebutton:0, 0, d); -} - -bool LuaScriptInterface::OnKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt) -{ - return luacon_keyevent(key, scan, GetModifiers(), LUACON_KDOWN); -} - -bool LuaScriptInterface::OnKeyRelease(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt) -{ - int modifiers = 0; - if(shift) - modifiers |= 0x001; - if(ctrl) - modifiers |= 0x040; - if(alt) - modifiers |= 0x100; - return luacon_keyevent(key, key < 256 ? key : 0, modifiers, LUACON_KUP); -} - -bool LuaScriptInterface::OnMouseTick() -{ - if (luacon_mousedown) - return luacon_mouseevent(luacon_mousex, luacon_mousey, luacon_mousebutton, LUACON_MPRESS, 0); - return true; + return LuaEvents::HandleEvent(this, event, ByteString::Build("tptevents-", eventType)); } void LuaScriptInterface::OnTick() @@ -3403,7 +3349,7 @@ void LuaScriptInterface::OnTick() lua_setfield(l, -2, "NUM_PARTS"); } lua_pop(l, 1); - luacon_step(luacon_mousex, luacon_mousey); + HandleEvent(EventTypes::tick, new TickEvent()); } int LuaScriptInterface::Command(String command) diff --git a/src/lua/LuaScriptInterface.h b/src/lua/LuaScriptInterface.h index 7b7557155..5270720f0 100644 --- a/src/lua/LuaScriptInterface.h +++ b/src/lua/LuaScriptInterface.h @@ -4,6 +4,7 @@ #include "LuaCompat.h" #include "CommandInterface.h" +#include "lua/LuaEvents.h" #include "simulation/Simulation.h" namespace ui @@ -34,6 +35,7 @@ class Tool; lua_setfield(L, -2, #NAME) class TPTScriptInterface; + class LuaScriptInterface: public CommandInterface { int luacon_mousex, luacon_mousey, luacon_mousebutton; @@ -167,6 +169,11 @@ class LuaScriptInterface: public CommandInterface static int platform_clipboardCopy(lua_State * l); static int platform_clipboardPaste(lua_State * l); + void initEventAPI(); + static int event_register(lua_State * l); + static int event_unregister(lua_State * l); + static int event_getmodifiers(lua_State * l); + public: int tpt_index(lua_State *l); int tpt_newIndex(lua_State *l); @@ -177,15 +184,10 @@ public: ui::Window * Window; lua_State *l; LuaScriptInterface(GameController * c, GameModel * m); - virtual bool OnActiveToolChanged(int toolSelection, Tool * tool); - virtual bool OnMouseMove(int x, int y, int dx, int dy); - virtual bool OnMouseDown(int x, int y, unsigned button); - virtual bool OnMouseUp(int x, int y, unsigned button, char type); - virtual bool OnMouseWheel(int x, int y, int d); - virtual bool OnKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt); - virtual bool OnKeyRelease(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt); - virtual bool OnMouseTick(); + virtual void OnTick(); + virtual bool HandleEvent(EventTypes eventType, Event * event); + virtual void Init(); virtual void SetWindow(ui::Window * window); virtual int Command(String command);