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.
This commit is contained in:
Tamás Bálint Misius 2022-11-08 13:46:47 +01:00
parent 27ddf78e0c
commit 33edb2e0e4
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
10 changed files with 295 additions and 463 deletions

22
src/common/VariantIndex.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include <variant>
#include <utility>
// https://stackoverflow.com/a/52303671
template<typename VariantType, typename T, std::size_t index = 0>
constexpr std::size_t VariantIndex()
{
static_assert(std::variant_size_v<VariantType> > index, "Type not found in variant");
if constexpr (index == std::variant_size_v<VariantType>)
{
return index;
}
else if constexpr (std::is_same_v<std::variant_alternative_t<index, VariantType>, T>)
{
return index;
}
else
{
return VariantIndex<VariantType, T, index + 1>();
}
}

View File

@ -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 && y<YRES && x<XRES && !gameView->GetPlacingSave() && !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 && y<YRES && x<XRES && !gameView->GetPlacingSave())
@ -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;
}

View File

@ -0,0 +1,98 @@
#pragma once
#include "Config.h"
#include "common/String.h"
#include <variant>
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
>;

View File

@ -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);

View File

@ -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

View File

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

View File

@ -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<int>(PT_NUM, 0);
lua_el_mode = &lua_el_mode_v[0];
gameControllerEventHandlers = std::vector<LuaSmartRef>(std::variant_size<GameControllerEvent>::value, l);
for (auto &ref : gameControllerEventHandlers)
{
lua_newtable(l);
ref.Assign(l, -1);
lua_pop(l, 1);
}
luaCtypeDrawHandlers = std::vector<LuaSmartRef>(PT_NUM, l);
luaCreateHandlers = std::vector<LuaSmartRef>(PT_NUM, l);
luaCreateAllowedHandlers = std::vector<LuaSmartRef>(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<GameControllerEvent, TextInputEvent >()); lua_setfield(l, -2, "textinput" );
lua_pushinteger(l, VariantIndex<GameControllerEvent, TextEditingEvent>()); lua_setfield(l, -2, "textediting");
lua_pushinteger(l, VariantIndex<GameControllerEvent, KeyPressEvent >()); lua_setfield(l, -2, "keypress" );
lua_pushinteger(l, VariantIndex<GameControllerEvent, KeyReleaseEvent >()); lua_setfield(l, -2, "keyrelease" );
lua_pushinteger(l, VariantIndex<GameControllerEvent, MouseDownEvent >()); lua_setfield(l, -2, "mousedown" );
lua_pushinteger(l, VariantIndex<GameControllerEvent, MouseUpEvent >()); lua_setfield(l, -2, "mouseup" );
lua_pushinteger(l, VariantIndex<GameControllerEvent, MouseMoveEvent >()); lua_setfield(l, -2, "mousemove" );
lua_pushinteger(l, VariantIndex<GameControllerEvent, MouseWheelEvent >()); lua_setfield(l, -2, "mousewheel" );
lua_pushinteger(l, VariantIndex<GameControllerEvent, TickEvent >()); lua_setfield(l, -2, "tick" );
lua_pushinteger(l, VariantIndex<GameControllerEvent, BlurEvent >()); lua_setfield(l, -2, "blur" );
lua_pushinteger(l, VariantIndex<GameControllerEvent, CloseEvent >()); lua_setfield(l, -2, "close" );
lua_pushinteger(l, VariantIndex<GameControllerEvent, BeforeSimEvent >()); lua_setfield(l, -2, "beforesim" );
lua_pushinteger(l, VariantIndex<GameControllerEvent, AfterSimEvent >()); 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<TextInputEvent>(&event))
{
tpt_lua_pushString(l, textInputEvent->text);
return 1;
}
else if (auto *textEditingEvent = std::get_if<TextEditingEvent>(&event))
{
tpt_lua_pushString(l, textEditingEvent->text);
return 1;
}
else if (auto *keyPressEvent = std::get_if<KeyPressEvent>(&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<KeyReleaseEvent>(&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<MouseDownEvent>(&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<MouseUpEvent>(&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<MouseMoveEvent>(&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<MouseWheelEvent>(&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();

View File

@ -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<LuaSmartRef> lua_el_func_v, lua_gr_func_v, lua_cd_func_v;
std::vector<int> lua_el_mode_v;
std::vector<LuaSmartRef> 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);

View File

@ -6,7 +6,6 @@ powder_files = files(
'Update.cpp',
'PowderToySDL.cpp',
'lua/CommandInterface.cpp',
'lua/LuaEvents.cpp',
'lua/TPTScriptInterface.cpp',
'lua/TPTSTypes.cpp',
)

View File

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