optimizations, refactor, fixes

This commit is contained in:
MihailRis 2024-05-05 04:14:24 +03:00
parent 3f12d4389d
commit 92f6fd2226
4 changed files with 340 additions and 292 deletions

View File

@ -177,7 +177,9 @@ Document = {}
function Document.new(docname)
return setmetatable({name=docname}, {
__index=function(self, k)
return Element.new(self.name, k)
local elem = Element.new(self.name, k)
rawset(self, k, elem)
return elem
end
})
end

View File

@ -260,6 +260,11 @@ int lua::LuaState::pushglobals() {
return 1;
}
int lua::LuaState::pushcfunction(lua_CFunction function) {
lua_pushcfunction(L, function);
return 1;
}
void lua::LuaState::pop(int n) {
lua_pop(L, n);
}
@ -294,6 +299,14 @@ lua::luanumber lua::LuaState::tonumber(int idx) {
return lua_tonumber(L, idx);
}
glm::vec2 lua::LuaState::tovec2(int idx) {
return lua::tovec2(L, idx);
}
glm::vec4 lua::LuaState::tocolor(int idx) {
return lua::tocolor(L, idx);
}
const char* lua::LuaState::tostring(int idx) {
return lua_tostring(L, idx);
}
@ -462,3 +475,7 @@ void lua::LuaState::dumpStack() {
std::cout << std::endl;
}
}
lua_State* lua::LuaState::getLua() const {
return L;
}

View File

@ -42,12 +42,15 @@ namespace lua {
int pushvalue(const dynamic::Value& value);
int pushnil();
int pushglobals();
int pushcfunction(lua_CFunction function);
void pop(int n=1);
bool getfield(const std::string& name, int idx = -1);
void setfield(const std::string& name, int idx = -2);
bool toboolean(int idx);
luaint tointeger(int idx);
luanumber tonumber(int idx);
glm::vec2 tovec2(int idx);
glm::vec4 tocolor(int idx);
std::unique_ptr<dynamic::Value> tovalue(int idx);
const char* tostring(int idx);
bool isstring(int idx);
@ -68,8 +71,8 @@ namespace lua {
void removeEnvironment(int id);
const std::string storeAnonymous();
bool emit_event(const std::string& name, std::function<int(lua::LuaState*)> args=[](auto*){return 0;});
void dumpStack();
lua_State* getLua() const;
};
}

View File

@ -25,13 +25,19 @@
using namespace gui;
namespace scripting {
extern lua::LuaState* state;
}
struct DocumentNode {
UiDocument* document;
std::shared_ptr<UINode> node;
};
using namespace scripting;
static DocumentNode getDocumentNode(lua_State* L, const std::string& name, const std::string& nodeName) {
auto doc = scripting::engine->getAssets()->getLayout(name);
auto doc = engine->getAssets()->getLayout(name);
if (doc == nullptr) {
luaL_error(L, "document '%s' not found", name.c_str());
}
@ -42,101 +48,6 @@ static DocumentNode getDocumentNode(lua_State* L, const std::string& name, const
return {doc, node};
}
static bool getattr(lua_State* L, TrackBar* bar, const std::string& attr) {
if (bar == nullptr)
return false;
if (attr == "value") {
lua_pushnumber(L, bar->getValue()); return true;
} else if (attr == "min") {
lua_pushnumber(L, bar->getMin()); return true;
} else if (attr == "max") {
lua_pushnumber(L, bar->getMax());
return true;
} else if (attr == "step") {
lua_pushnumber(L, bar->getStep());
return true;
} else if (attr == "trackWidth") {
lua_pushnumber(L, bar->getTrackWidth());
return true;
} else if (attr == "trackColor") {
return lua::pushcolor_arr(L, bar->getTrackColor());
}
return false;
}
static bool setattr(lua_State* L, TrackBar* bar, const std::string& attr) {
if (bar == nullptr)
return false;
if (attr == "value") {
bar->setValue(lua_tonumber(L, 4));
return true;
} else if (attr == "min") {
bar->setMin(lua_tonumber(L, 4));
return true;
} else if (attr == "max") {
bar->setMax(lua_tonumber(L, 4));
return true;
} else if (attr == "step") {
bar->setStep(lua_tonumber(L, 4));
return true;
} else if (attr == "trackWidth") {
bar->setTrackWidth(lua_tonumber(L, 4));
return true;
} else if (attr == "trackColor") {
bar->setTrackColor(lua::tocolor(L, 4));
return true;
}
return false;
}
static bool getattr(lua_State* L, Button* button, const std::string& attr) {
if (button == nullptr)
return false;
if (attr == "text") {
lua_pushstring(L, util::wstr2str_utf8(button->getText()).c_str());
return true;
} else if (attr == "pressedColor") {
return lua::pushcolor_arr(L, button->getPressedColor());
}
return false;
}
static bool getattr(lua_State* L, Label* label, const std::string& attr) {
if (label == nullptr)
return false;
if (attr == "text") {
lua_pushstring(L, util::wstr2str_utf8(label->getText()).c_str());
return true;
}
return false;
}
static bool getattr(lua_State* L, FullCheckBox* box, const std::string& attr) {
if (box == nullptr)
return false;
if (attr == "checked") {
lua_pushboolean(L, box->isChecked());
return true;
}
return false;
}
static bool getattr(lua_State* L, TextBox* box, const std::string& attr) {
if (box == nullptr)
return false;
if (attr == "text") {
lua_pushstring(L, util::wstr2str_utf8(box->getText()).c_str());
return true;
} else if (attr == "placeholder") {
lua_pushstring(L, util::wstr2str_utf8(box->getPlaceholder()).c_str());
return true;
} else if (attr == "valid") {
lua_pushboolean(L, box->validate());
return true;
}
return false;
}
static DocumentNode getDocumentNode(lua_State* L, int idx=1) {
lua_getfield(L, idx, "docname");
lua_getfield(L, idx, "name");
@ -147,107 +58,21 @@ static DocumentNode getDocumentNode(lua_State* L, int idx=1) {
return node;
}
static int menu_back(lua_State* L) {
static int l_menu_back(lua_State* L) {
auto node = getDocumentNode(L);
auto menu = dynamic_cast<Menu*>(node.node.get());
menu->back();
return 0;
}
static int menu_reset(lua_State* L) {
static int l_menu_reset(lua_State* L) {
auto node = getDocumentNode(L);
auto menu = dynamic_cast<Menu*>(node.node.get());
menu->reset();
return 0;
}
static bool getattr(lua_State* L, Menu* menu, const std::string& attr) {
if (menu == nullptr)
return false;
if (attr == "page") {
lua_pushstring(L, menu->getCurrent().name.c_str());
return true;
} else if (attr == "back") {
lua_pushcfunction(L, menu_back);
return true;
} else if (attr == "reset") {
lua_pushcfunction(L, menu_reset);
return true;
}
return false;
}
static bool setattr(lua_State* L, FullCheckBox* box, const std::string& attr) {
if (box == nullptr)
return false;
if (attr == "checked") {
box->setChecked(lua_toboolean(L, 4));
return true;
}
return false;
}
static bool setattr(lua_State* L, Button* button, const std::string& attr) {
if (button == nullptr)
return false;
if (attr == "text") {
button->setText(util::str2wstr_utf8(lua_tostring(L, 4)));
return true;
} else if (attr == "pressedColor") {
button->setPressedColor(lua::tocolor(L, 4));
}
return false;
}
static bool setattr(lua_State* L, TextBox* box, const std::string& attr) {
if (box == nullptr)
return false;
if (attr == "text") {
box->setText(util::str2wstr_utf8(lua_tostring(L, 4)));
return true;
} else if (attr == "placeholder") {
box->setPlaceholder(util::str2wstr_utf8(lua_tostring(L, 4)));
return true;
}
return false;
}
static bool setattr(lua_State* L, Label* label, const std::string& attr) {
if (label == nullptr)
return false;
if (attr == "text") {
label->setText(util::str2wstr_utf8(lua_tostring(L, 4)));
return true;
}
return false;
}
static bool setattr(lua_State* L, Menu* menu, const std::string& attr) {
if (menu == nullptr)
return false;
if (attr == "page") {
menu->setPage(lua_tostring(L, 4));
return true;
}
return false;
}
static bool setattr(lua_State* L, InventoryView* view, const std::string& attr) {
if (view == nullptr)
return false;
if (attr == "inventory") {
auto inventory = scripting::level->inventories->get(lua_tointeger(L, 4));
if (inventory == nullptr) {
view->unbind();
} else {
view->bind(inventory, scripting::content);
}
return true;
}
return false;
}
static int container_add(lua_State* L) {
static int l_container_add(lua_State* L) {
auto docnode = getDocumentNode(L);
auto node = dynamic_cast<Container*>(docnode.node.get());
auto xmlsrc = lua_tostring(L, 2);
@ -261,7 +86,7 @@ static int container_add(lua_State* L) {
return 0;
}
static int container_clear(lua_State* L) {
static int l_container_clear(lua_State* L) {
auto node = getDocumentNode(L, 1);
if (auto container = std::dynamic_pointer_cast<Container>(node.node)) {
container->clear();
@ -269,128 +94,324 @@ static int container_clear(lua_State* L) {
return 0;
}
static bool getattr(lua_State* L, Container* container, const std::string& attr) {
if (container == nullptr)
return false;
if (attr == "add") {
lua_pushcfunction(L, container_add);
return true;
} else if (attr == "clear") {
lua_pushcfunction(L, container_clear);
return true;
}
return false;
}
static bool getattr(lua_State* L, InventoryView* inventory, const std::string& attr) {
if (inventory == nullptr)
return false;
if (attr == "inventory") {
auto inv = inventory->getInventory();
lua_pushinteger(L, inv ? inv->getId() : 0);
return true;
}
return false;
}
static int uinode_move_into(lua_State* L) {
static int l_uinode_move_into(lua_State* L) {
auto node = getDocumentNode(L, 1);
auto dest = getDocumentNode(L, 2);
UINode::moveInto(node.node, std::dynamic_pointer_cast<Container>(dest.node));
return 0;
}
static int l_gui_getattr(lua_State* L) {
auto docname = lua_tostring(L, 1);
auto element = lua_tostring(L, 2);
const std::string attr = lua_tostring(L, 3);
auto docnode = getDocumentNode(L, docname, element);
auto node = docnode.node;
if (attr == "color") {
return lua::pushcolor_arr(L, node->getColor());
} else if (attr == "pos") {
return lua::pushvec2_arr(L, node->getPos());
} else if (attr == "size") {
return lua::pushvec2_arr(L, node->getSize());
} else if (attr == "hoverColor") {
return lua::pushcolor_arr(L, node->getHoverColor());
} else if (attr == "interactive") {
lua_pushboolean(L, node->isInteractive());
return 1;
} else if (attr == "visible") {
lua_pushboolean(L, node->isVisible());
return 1;
} else if (attr == "enabled") {
lua_pushboolean(L, node->isEnabled());
return 1;
} else if (attr == "move_into") {
lua_pushcfunction(L, uinode_move_into);
return 1;
static int p_get_inventory(UINode* node) {
if (auto inventory = dynamic_cast<InventoryView*>(node)) {
auto inv = inventory->getInventory();
return state->pushinteger(inv ? inv->getId() : 0);
}
if (getattr(L, dynamic_cast<Container*>(node.get()), attr))
return 1;
if (getattr(L, dynamic_cast<Button*>(node.get()), attr))
return 1;
if (getattr(L, dynamic_cast<Label*>(node.get()), attr))
return 1;
if (getattr(L, dynamic_cast<TextBox*>(node.get()), attr))
return 1;
if (getattr(L, dynamic_cast<TrackBar*>(node.get()), attr))
return 1;
if (getattr(L, dynamic_cast<FullCheckBox*>(node.get()), attr))
return 1;
if (getattr(L, dynamic_cast<Menu*>(node.get()), attr))
return 1;
if (getattr(L, dynamic_cast<InventoryView*>(node.get()), attr))
return 1;
return 0;
}
static int l_gui_getviewport(lua_State* L) {
lua::pushvec2_arr(L, scripting::engine->getGUI()->getContainer()->getSize());
return 1;
static int p_get_reset(UINode* node) {
if (dynamic_cast<Menu*>(node)) {
return state->pushcfunction(l_menu_reset);
}
return 0;
}
static int p_get_back(UINode* node) {
if (dynamic_cast<Menu*>(node)) {
return state->pushcfunction(l_menu_back);
}
return 0;
}
static int p_get_page(UINode* node) {
if (auto menu = dynamic_cast<Menu*>(node)) {
return state->pushstring(menu->getCurrent().name);
}
return 0;
}
static int p_is_checked(UINode* node) {
if (auto box = dynamic_cast<CheckBox*>(node)) {
return state->pushboolean(box->isChecked());
} else if (auto box = dynamic_cast<FullCheckBox*>(node)) {
return state->pushboolean(box->isChecked());
}
return 0;
}
static int p_get_value(UINode* node) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
return state->pushnumber(bar->getValue());
}
return 0;
}
static int p_get_min(UINode* node) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
return state->pushnumber(bar->getMin());
}
return 0;
}
static int p_get_max(UINode* node) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
return state->pushnumber(bar->getMax());
}
return 0;
}
static int p_get_step(UINode* node) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
return state->pushnumber(bar->getStep());
}
return 0;
}
static int p_get_track_width(UINode* node) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
return state->pushnumber(bar->getTrackWidth());
}
return 0;
}
static int p_get_track_color(UINode* node) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
return lua::pushcolor_arr(state->getLua(), bar->getTrackColor());
}
return 0;
}
static int p_is_valid(UINode* node) {
if (auto box = dynamic_cast<TextBox*>(node)) {
return state->pushboolean(box->validate());
}
return 0;
}
static int p_get_placeholder(UINode* node) {
if (auto box = dynamic_cast<TextBox*>(node)) {
return state->pushstring(util::wstr2str_utf8(box->getPlaceholder()));
}
return 0;
}
static int p_get_text(UINode* node) {
if (auto button = dynamic_cast<Button*>(node)) {
return state->pushstring(util::wstr2str_utf8(button->getText()));
} else if (auto label = dynamic_cast<Label*>(node)) {
return state->pushstring(util::wstr2str_utf8(label->getText()));
} else if (auto box = dynamic_cast<TextBox*>(node)) {
return state->pushstring(util::wstr2str_utf8(box->getText()));
}
return 0;
}
static int p_get_add(UINode* node) {
if (dynamic_cast<Container*>(node)) {
return state->pushcfunction(l_container_add);
}
return 0;
}
static int p_get_clear(UINode* node) {
if (dynamic_cast<Container*>(node)) {
return state->pushcfunction(l_container_clear);
}
return 0;
}
static int p_get_color(UINode* node) {
return lua::pushcolor_arr(state->getLua(), node->getColor());
}
static int p_get_hover_color(UINode* node) {
return lua::pushcolor_arr(state->getLua(), node->getHoverColor());
}
static int p_get_pressed_color(UINode* node) {
return lua::pushcolor_arr(state->getLua(), node->getPressedColor());
}
static int p_get_pos(UINode* node) {
return lua::pushvec2_arr(state->getLua(), node->getPos());
}
static int p_get_size(UINode* node) {
return lua::pushvec2_arr(state->getLua(), node->getSize());
}
static int p_is_interactive(UINode* node) {
return state->pushboolean(node->isInteractive());
}
static int p_is_visible(UINode* node) {
return state->pushboolean(node->isVisible());
}
static int p_is_enabled(UINode* node) {
return state->pushboolean(node->isEnabled());
}
static int p_move_into(UINode* node) {
return state->pushcfunction(l_uinode_move_into);
}
static int l_gui_getattr(lua_State* L) {
auto docname = lua_tostring(L, 1);
auto element = lua_tostring(L, 2);
auto attr = lua_tostring(L, 3);
auto docnode = getDocumentNode(L, docname, element);
auto node = docnode.node;
static const std::unordered_map<std::string_view, std::function<int(UINode*)>> getters {
{"color", p_get_color},
{"hoverColor", p_get_hover_color},
{"pressedColor", p_get_pressed_color},
{"pos", p_get_pos},
{"size", p_get_size},
{"interactive", p_is_interactive},
{"visible", p_is_visible},
{"enabled", p_is_enabled},
{"move_into", p_move_into},
{"add", p_get_add},
{"clear", p_get_clear},
{"placeholder", p_get_placeholder},
{"valid", p_is_valid},
{"text", p_get_text},
{"value", p_get_value},
{"min", p_get_min},
{"max", p_get_max},
{"step", p_get_step},
{"trackWidth", p_get_track_width},
{"trackColor", p_get_track_color},
{"checked", p_is_checked},
{"page", p_get_page},
{"back", p_get_back},
{"reset", p_get_reset},
{"inventory", p_get_inventory},
};
auto func = getters.find(attr);
if (func != getters.end()) {
return func->second(node.get());
}
return 0;
}
static void p_set_color(UINode* node, int idx) {
node->setColor(state->tocolor(idx));
}
static void p_set_hover_color(UINode* node, int idx) {
node->setHoverColor(state->tocolor(idx));
}
static void p_set_pressed_color(UINode* node, int idx) {
node->setPressedColor(state->tocolor(idx));
}
static void p_set_pos(UINode* node, int idx) {
node->setPos(state->tovec2(idx));
}
static void p_set_size(UINode* node, int idx) {
node->setSize(state->tovec2(idx));
}
static void p_set_interactive(UINode* node, int idx) {
node->setInteractive(state->toboolean(idx));
}
static void p_set_visible(UINode* node, int idx) {
node->setVisible(state->toboolean(idx));
}
static void p_set_enabled(UINode* node, int idx) {
node->setEnabled(state->toboolean(idx));
}
static void p_set_placeholder(UINode* node, int idx) {
if (auto box = dynamic_cast<TextBox*>(node)) {
box->setPlaceholder(util::str2wstr_utf8(state->tostring(idx)));
}
}
static void p_set_text(UINode* node, int idx) {
if (auto label = dynamic_cast<Label*>(node)) {
label->setText(util::str2wstr_utf8(state->tostring(idx)));
} else if (auto button = dynamic_cast<Button*>(node)) {
button->setText(util::str2wstr_utf8(state->tostring(idx)));
} else if (auto box = dynamic_cast<TextBox*>(node)) {
box->setText(util::str2wstr_utf8(state->tostring(idx)));
}
}
static void p_set_value(UINode* node, int idx) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
bar->setValue(state->tonumber(idx));
}
}
static void p_set_min(UINode* node, int idx) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
bar->setMin(state->tonumber(idx));
}
}
static void p_set_max(UINode* node, int idx) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
bar->setMax(state->tonumber(idx));
}
}
static void p_set_step(UINode* node, int idx) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
bar->setStep(state->tonumber(idx));
}
}
static void p_set_track_width(UINode* node, int idx) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
bar->setTrackWidth(state->tointeger(idx));
}
}
static void p_set_track_color(UINode* node, int idx) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
bar->setTrackColor(state->tocolor(idx));
}
}
static void p_set_checked(UINode* node, int idx) {
if (auto box = dynamic_cast<CheckBox*>(node)) {
box->setChecked(state->toboolean(idx));
} else if (auto box = dynamic_cast<FullCheckBox*>(node)) {
box->setChecked(state->toboolean(idx));
}
}
static void p_set_page(UINode* node, int idx) {
if (auto menu = dynamic_cast<Menu*>(node)) {
menu->setPage(state->tostring(idx));
}
}
static void p_set_inventory(UINode* node, int idx) {
if (auto view = dynamic_cast<InventoryView*>(node)) {
auto inventory = level->inventories->get(state->tointeger(idx));
if (inventory == nullptr) {
view->unbind();
} else {
view->bind(inventory, content);
}
}
}
static int l_gui_setattr(lua_State* L) {
auto docname = lua_tostring(L, 1);
auto element = lua_tostring(L, 2);
const std::string attr = lua_tostring(L, 3);
auto attr = lua_tostring(L, 3);
auto docnode = getDocumentNode(L, docname, element);
auto node = docnode.node;
if (attr == "pos") {
node->setPos(lua::tovec2(L, 4));
} else if (attr == "size") {
node->setSize(lua::tovec2(L, 4));
} else if (attr == "color") {
node->setColor(lua::tocolor(L, 4));
} else if (attr == "hoverColor") {
node->setHoverColor(lua::tocolor(L, 4));
} else if (attr == "interactive") {
node->setInteractive(lua_toboolean(L, 4));
} else if (attr == "visible") {
node->setVisible(lua_toboolean(L, 4));
} else if (attr == "enabled") {
node->setEnabled(lua_toboolean(L, 4));
} else {
if (setattr(L, dynamic_cast<Button*>(node.get()), attr))
return 0;
if (setattr(L, dynamic_cast<Label*>(node.get()), attr))
return 0;
if (setattr(L, dynamic_cast<TextBox*>(node.get()), attr))
return 0;
if (setattr(L, dynamic_cast<TrackBar*>(node.get()), attr))
return 0;
if (setattr(L, dynamic_cast<FullCheckBox*>(node.get()), attr))
return 0;
if (setattr(L, dynamic_cast<Menu*>(node.get()), attr))
return 0;
if (setattr(L, dynamic_cast<InventoryView*>(node.get()), attr))
return 0;
static const std::unordered_map<std::string_view, std::function<void(UINode*,int)>> setters {
{"color", p_set_color},
{"hoverColor", p_set_hover_color},
{"pressedColor", p_set_pressed_color},
{"pos", p_set_pos},
{"size", p_set_size},
{"interactive", p_set_interactive},
{"visible", p_set_visible},
{"enabled", p_set_enabled},
{"placeholder", p_set_placeholder},
{"text", p_set_text},
{"value", p_set_value},
{"min", p_set_min},
{"max", p_set_max},
{"step", p_set_step},
{"trackWidth", p_set_track_width},
{"trackColor", p_set_track_color},
{"checked", p_set_checked},
{"page", p_set_page},
{"inventory", p_set_inventory},
};
auto func = setters.find(attr);
if (func != setters.end()) {
func->second(node.get(), 4);
}
return 0;
}
@ -439,6 +460,11 @@ static int l_gui_get_locales_info(lua_State* L) {
return 1;
}
static int l_gui_getviewport(lua_State* L) {
lua::pushvec2_arr(L, scripting::engine->getGUI()->getContainer()->getSize());
return 1;
}
const luaL_Reg guilib [] = {
{"get_viewport", lua_wrap_errors<l_gui_getviewport>},
{"getattr", lua_wrap_errors<l_gui_getattr>},