thunderbrew/src/ui/FrameScript_Object.cpp
2023-01-02 13:17:18 -06:00

190 lines
4.7 KiB
C++

#include "ui/FrameScript_Object.hpp"
#include "util/Lua.hpp"
#include <cstdint>
#include <storm/String.hpp>
int32_t FrameScript_Object::s_objectTypes = 0;
int32_t FrameScript_Object::CreateScriptMetaTable(lua_State* L, void (*a2)(lua_State* L)) {
lua_createtable(L, 0, 0);
lua_pushstring(L, "__index");
lua_createtable(L, 0, 0);
a2(L);
lua_settable(L, -3);
return luaL_ref(L, LUA_REGISTRYINDEX);
}
void FrameScript_Object::FillScriptMethodTable(lua_State *L, FrameScript_Method methods[], int32_t count) {
for (int32_t i = 0; i < count; i++) {
lua_pushstring(L, methods[i].name);
lua_pushcclosure(L, methods[i].method, 0);
lua_settable(L, -3);
}
}
FrameScript_Object::~FrameScript_Object() {
if (this->m_onEvent.luaRef) {
luaL_unref(FrameScript_GetContext(), LUA_REGISTRYINDEX, this->m_onEvent.luaRef);
}
}
const char* FrameScript_Object::GetDisplayName() {
const char* name = this->GetName();
return name ? name : "<unnamed>";
}
FrameScript_Object::ScriptIx* FrameScript_Object::GetScriptByName(const char* name, FrameScript_Object::ScriptData& data) {
if (!SStrCmpI(name, "OnEvent", STORM_MAX_STR)) {
data.wrapper = "return function(self,event,...) %s end";
return &this->m_onEvent;
}
return nullptr;
}
int32_t FrameScript_Object::RegisterScriptEvent(const char* name) {
auto event = FrameScript::s_scriptEventsHash.Ptr(name);
if (!event) {
return 0;
}
if (event->pendingSignalCount) {
auto node = event->unregisterListeners.Head();
while (node) {
if (node->listener == this) {
break;
}
node = node->Next();
}
if (node) {
event->unregisterListeners.DeleteNode(node);
}
}
auto node = event->listeners.Head();
while (node) {
if (node->listener == this) {
break;
}
node = node->Next();
}
if (!node) {
FrameScript_RegisterScriptEvent(this, event);
}
return 1;
}
void FrameScript_Object::RegisterScriptObject(const char* name) {
auto L = FrameScript_GetContext();
if (!this->lua_registered) {
// TODO
// v4 = lua_taintexpected++ == -1;
// v5 = lua_tainted;
// if (!v4 && !lua_taintedclosure) {
// lua_tainted = 0;
// }
lua_createtable(L, 0, 0);
lua_pushnumber(L, 0.0);
lua_pushlightuserdata(L, this);
lua_rawset(L, -3);
int32_t metatable = this->GetScriptMetaTable();
lua_rawgeti(L, LUA_REGISTRYINDEX, metatable);
lua_setmetatable(L, -2);
this->lua_objectRef = luaL_ref(L, LUA_REGISTRYINDEX);
// TODO
// if (lua_taintexpected && !lua_taintedclosure) {
// lua_tainted = v5;
// }
// if (--lua_taintexpected <= 0) {
// lua_taintexpected = 0;
// }
}
this->lua_registered++;
if (name) {
int32_t v8 = 0;
lua_pushstring(L, name);
lua_rawget(L, LUA_GLOBALSINDEX);
if (lua_type(L, -1)) {
v8 = 1;
}
lua_settop(L, -2);
if (!v8) {
lua_rawgeti(L, LUA_REGISTRYINDEX, this->lua_objectRef);
lua_pushstring(L, name);
lua_insert(L, -2);
lua_rawset(L, LUA_GLOBALSINDEX);
}
}
}
void FrameScript_Object::RunScript(ScriptIx const& script, int32_t argCount, const char* a4) {
FrameScript_Execute(script.luaRef, this, argCount, a4 ? a4 : script.unk, nullptr);
}
void FrameScript_Object::UnregisterScriptObject(const char* name) {
auto L = FrameScript_GetContext();
if (this->lua_registered > 0) {
this->lua_registered--;
if (this->lua_registered == 0) {
lua_rawgeti(L, LUA_REGISTRYINDEX, this->lua_objectRef);
lua_pushnumber(L, 0.0);
lua_pushnil(L);
lua_rawset(L, -3);
lua_settop(L, -2);
luaL_unref(L, LUA_REGISTRYINDEX, this->lua_objectRef);
this->lua_objectRef = -2;
}
}
if (name) {
lua_pushnil(L);
lua_pushstring(L, name);
lua_insert(L, -2);
lua_rawset(L, LUA_GLOBALSINDEX);
}
}
FrameScript_Object* FrameScript_GetObjectThis(lua_State* L, int32_t type) {
if (lua_type(L, 1) != LUA_TTABLE) {
luaL_error(L, "Attempt to find 'this' in non-table object (used '.' instead of ':' ?)");
}
lua_rawgeti(L, 1, 0);
auto object = static_cast<FrameScript_Object*>(lua_touserdata(L, -1));
lua_settop(L, -2);
if (!object) {
luaL_error(L, "Attempt to find 'this' in non-framescript object");
}
if (!object->IsA(type)) {
luaL_error(L, "Wrong object type for member function");
}
return object;
}