#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; } 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"_i18n) // probably not a good idea { 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