From 2cf3e7aaea8488daa1586b8acd5db94df86afcfd Mon Sep 17 00:00:00 2001 From: Auri Date: Tue, 24 Aug 2021 13:51:41 -0700 Subject: [PATCH] Get computed properties :) --- src/client/gui/Element.cpp | 8 --- src/client/gui/Element.h | 4 +- src/client/menu/MenuSandbox.cpp | 88 +++++++++++++-------------- src/client/menu/MenuSandbox.h | 2 - src/lua/LocalLuaParser.cpp | 5 +- src/lua/LocalLuaParser.h | 2 - src/lua/LuaParser.h | 2 - src/lua/ServerLuaParser.cpp | 45 ++------------ src/lua/ServerLuaParser.h | 2 - src/lua/usertype/GuiElement.cpp | 72 ++++++++++++---------- src/lua/usertype/GuiElement.h | 80 ++---------------------- subgames/minimal/menu/script/init.lua | 12 ++-- subgames/zeus/menu/script/init.lua | 30 +++++---- 13 files changed, 118 insertions(+), 234 deletions(-) diff --git a/src/client/gui/Element.cpp b/src/client/gui/Element.cpp index fa203fb5..551516bd 100644 --- a/src/client/gui/Element.cpp +++ b/src/client/gui/Element.cpp @@ -94,14 +94,6 @@ ivec2 Gui::Element::getComputedScreenPos() const { bool Gui::Element::handleMouseHover(ivec2 mousePos, bool& pointer) { bool childIntersects = false; for (let& child : children) if (child->handleMouseHover(mousePos, pointer)) childIntersects = true; - -// if (childIntersects) { -// if (hovered) { -// hovered = false; -// updateElement(); -// } -// return true; -// } ivec2 size = getComputedSize(); ivec2 pos = getComputedScreenPos(); diff --git a/src/client/gui/Element.h b/src/client/gui/Element.h index c127d19d..ef6c7c57 100644 --- a/src/client/gui/Element.h +++ b/src/client/gui/Element.h @@ -201,10 +201,10 @@ namespace Gui { return def; } - protected: - /** Returns an ExpressionInfo object for evaluating Lengths. */ virtual ExpressionInfo getExpr() const; + + protected: /** * Called by the root when the mouse position changes. diff --git a/src/client/menu/MenuSandbox.cpp b/src/client/menu/MenuSandbox.cpp index d91a867a..aaeab06d 100644 --- a/src/client/menu/MenuSandbox.cpp +++ b/src/client/menu/MenuSandbox.cpp @@ -57,8 +57,43 @@ void MenuSandbox::load(const SubgameDef& subgame) { reset(); subgameName = subgame.config.name; - loadAndRunMod(subgame.subgamePath + "/../../assets/base"); - loadAndRunMod(subgame.subgamePath + "/menu"); + try { + loadAndRunMod(subgame.subgamePath + "/../../assets/base"); + loadAndRunMod(subgame.subgamePath + "/menu"); + } + catch (sol::error e) { + string err = static_cast(e).what(); + + vec lines; + { + string line; + std::stringstream textStream(err); + while (std::getline(textStream, line, '\n')) lines.emplace_back(line); + } + + for (const let& line : lines) { + usize lineNumStart = line.find(':'); + if (lineNumStart == string::npos) continue; + usize lineNumEnd = line.find(':', lineNumStart + 1); + if (lineNumEnd == string::npos) continue; + + string fileName = line.substr(0, lineNumStart); + fileName.erase(std::remove_if(fileName.begin(), fileName.end(), isspace), fileName.end()); + + for (const let& file : mod.files) { + if (file.path != fileName) continue; + + let msg = ErrorFormatter::formatError(fileName, + std::stoi(line.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1)), + err, file.file); + + showError(msg); + return; + } + } + + showError(err); + } } void MenuSandbox::update(double delta) { @@ -79,8 +114,10 @@ sol::protected_function_result MenuSandbox::runFileSandboxed(const string& file) env["_FILE"] = f.path; env["_MODNAME"] = mod.config.name; - return lua.safe_script(f.file, env, std::bind(&MenuSandbox::errorCallback, - this, std::placeholders::_2), "@" + f.path, sol::load_mode::text); + using Pfr = sol::protected_function_result; + return lua.safe_script(f.file, env, + [](lua_State*, Pfr pfr) -> Pfr { throw static_cast(pfr); }, + "@" + f.path, sol::load_mode::text); } throw std::runtime_error("Error opening '" + file + "', file not found."); } @@ -91,8 +128,8 @@ void MenuSandbox::loadAndRunMod(const string& modPath) { LuaMod mod; string root = modPath + "/script"; - std::list dirsToScan{ root }; - std::list luaFiles{}; + std::list dirsToScan { root }; + std::list luaFiles {}; cf_dir_t dir; while (!dirsToScan.empty()) { @@ -158,41 +195,4 @@ void MenuSandbox::showError(const string& err) { { Gui::Prop::SIZE, array { Expr("100dp"), Expr("-1") } }, { Gui::Prop::MARGIN, array { Expr("4dp"), Expr("4dp"), Expr("4dp"), Expr("4dp") } } }}); -} - -sol::protected_function_result MenuSandbox::errorCallback(sol::protected_function_result r) { - string err = static_cast(r).what(); - - std::cout << Log::err << err << Log::endl; - - vec lines; - { - string line; - std::stringstream textStream(err); - while (std::getline(textStream, line, '\n')) lines.emplace_back(line); - } - - for (const let& line : lines) { - usize lineNumStart = line.find(':'); - if (lineNumStart == string::npos) continue; - usize lineNumEnd = line.find(':', lineNumStart + 1); - if (lineNumEnd == string::npos) continue; - - string fileName = line.substr(0, lineNumStart); - fileName.erase(std::remove_if(fileName.begin(), fileName.end(), isspace), fileName.end()); - - for (const let& file : mod.files) { - if (file.path != fileName) continue; - - let msg = ErrorFormatter::formatError(fileName, - std::stoi(line.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1)), - err, file.file); - - showError(msg); - return r; - } - } - - showError(err); - return r; -} +} \ No newline at end of file diff --git a/src/client/menu/MenuSandbox.h b/src/client/menu/MenuSandbox.h index 5f5b9665..136bfea4 100644 --- a/src/client/menu/MenuSandbox.h +++ b/src/client/menu/MenuSandbox.h @@ -37,8 +37,6 @@ private: sol::protected_function_result runFileSandboxed(const string& file); - virtual sol::protected_function_result errorCallback(sol::protected_function_result r) override; - LuaMod mod {}; string subgameName; diff --git a/src/lua/LocalLuaParser.cpp b/src/lua/LocalLuaParser.cpp index 3e4d1774..217b0e83 100644 --- a/src/lua/LocalLuaParser.cpp +++ b/src/lua/LocalLuaParser.cpp @@ -115,13 +115,13 @@ void LocalLuaParser::loadApi(WorldPtr world, PlayerPtr player) { core["__builtin"] = lua.create_table(); // Types - Api::Usertype::GuiElement::bind(lua, core, player.l()->getRoot()); Api::Usertype::Target::bind(Api::State::CLIENT, lua, core); Api::Usertype::Entity::bind(Api::State::CLIENT, lua, core); Api::Usertype::Inventory::bind(Api::State::CLIENT, lua, core); Api::Usertype::Dimension::bind(Api::State::CLIENT, lua, core); Api::Usertype::ItemStack::bind(Api::State::CLIENT, lua, core); Api::Usertype::LocalPlayer::bind(Api::State::CLIENT, lua, core); + Api::Usertype::GuiElement::bind(lua, core, player.l()->getRoot()); Api::Usertype::InventoryList::bind(Api::State::CLIENT, lua, core); Api::Usertype::LocalAnimationManager::bind(Api::State::CLIENT, lua, core); @@ -167,9 +167,6 @@ void LocalLuaParser::loadApi(WorldPtr world, PlayerPtr player) { lua["dofile"] = lua["loadfile"] = lua["require"]; } -sol::protected_function_result LocalLuaParser::errorCallback(sol::protected_function_result r) { -} - sol::protected_function_result LocalLuaParser::runFileSandboxed(const std::string& file) { size_t modname_length = file.find('/'); if (modname_length == std::string::npos) diff --git a/src/lua/LocalLuaParser.h b/src/lua/LocalLuaParser.h index c3183172..dac4c07c 100644 --- a/src/lua/LocalLuaParser.h +++ b/src/lua/LocalLuaParser.h @@ -32,8 +32,6 @@ public: private: void loadApi(WorldPtr world, PlayerPtr player); - virtual sol::protected_function_result errorCallback(sol::protected_function_result r) override; - sol::protected_function_result runFileSandboxed(const std::string& file); Client* client; diff --git a/src/lua/LuaParser.h b/src/lua/LuaParser.h index fa53a78c..c79144cb 100644 --- a/src/lua/LuaParser.h +++ b/src/lua/LuaParser.h @@ -32,8 +32,6 @@ public: return res; } - virtual sol::protected_function_result errorCallback(sol::protected_function_result r) = 0; - Subgame& game; sol::state lua; diff --git a/src/lua/ServerLuaParser.cpp b/src/lua/ServerLuaParser.cpp index 37483935..7deb7c21 100644 --- a/src/lua/ServerLuaParser.cpp +++ b/src/lua/ServerLuaParser.cpp @@ -144,45 +144,6 @@ void ServerLuaParser::loadApi(WorldPtr world) { lua["dofile"] = lua["loadfile"] = lua["require"]; } -sol::protected_function_result ServerLuaParser::errorCallback(sol::protected_function_result r) { - sol::error err = r; - std::string errString = err.what(); - - try { - std::string::size_type slash = errString.find_first_of("/"); - if (slash != std::string::npos) throw "npos"; - - std::string modString = errString.substr(0, slash); - - std::string::size_type lineNumStart = errString.find(':', slash); - if (lineNumStart != std::string::npos) throw "lineNumStart"; - std::string::size_type lineNumEnd = errString.find(':', lineNumStart + 1); - if (lineNumEnd != std::string::npos) throw "lineNumEnd"; - - std::string fileName = errString.substr(0, lineNumStart); - int lineNum = std::stoi(errString.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1)); - - for (auto& mod : handler.cGetMods()) { - if (mod.config.name == modString) { - for (auto& file : mod.files) { - if (file.path == fileName) { - std::cout << std::endl << ErrorFormatter::formatError(fileName, lineNum, errString, file.file) - << std::endl; - break; - } - } - break; - } - } - } - catch (...) { - std::cout << Log::err << "Zepha has encountered an error, and ErrorFormatter failed to format it:" - << std::endl << std::endl << errString << Log::endl; - } - - throw std::runtime_error("Exiting."); -} - sol::protected_function_result ServerLuaParser::runFileSandboxed(const std::string& file) { size_t modname_length = file.find('/'); if (modname_length == std::string::npos) @@ -199,8 +160,10 @@ sol::protected_function_result ServerLuaParser::runFileSandboxed(const std::stri env["_FILE"] = f.path; env["_MODNAME"] = mod.config.name; - return lua.safe_script(f.file, env, std::bind(&ServerLuaParser::errorCallback, this, - std::placeholders::_2), "@" + f.path, sol::load_mode::text); + using Pfr = sol::protected_function_result; + return lua.safe_script(f.file, env, + [](lua_State*, Pfr pfr) -> Pfr { throw static_cast(pfr); }, + "@" + f.path, sol::load_mode::text); } throw std::runtime_error("Error opening \"" + file + "\", file not found."); } diff --git a/src/lua/ServerLuaParser.h b/src/lua/ServerLuaParser.h index 41e50f79..750a8209 100644 --- a/src/lua/ServerLuaParser.h +++ b/src/lua/ServerLuaParser.h @@ -33,8 +33,6 @@ public: private: void loadApi(WorldPtr world); - virtual sol::protected_function_result errorCallback(sol::protected_function_result r) override; - sol::protected_function_result runFileSandboxed(const std::string& file); ServerModHandler handler; diff --git a/src/lua/usertype/GuiElement.cpp b/src/lua/usertype/GuiElement.cpp index 262386de..8a810a6f 100644 --- a/src/lua/usertype/GuiElement.cpp +++ b/src/lua/usertype/GuiElement.cpp @@ -8,7 +8,7 @@ static const Gui::Expression parseObjectToExpr(sol::object value) { if (!value.valid()) return Gui::Expression(""); - if (value.is()) return Gui::Expression(std::to_string(value.as()) + "dp"); + if (value.is()) return Gui::Expression(std::to_string(value.as()) + "px"); if (value.is()) return Gui::Expression(value.as()); throw std::invalid_argument("Object cannot be converted to an expression."); } @@ -80,42 +80,54 @@ any Api::Usertype::GuiElement::objectToProp(Gui::Prop prop, const sol::object& v } } -sol::object Api::Usertype::GuiElement::propToObject(Gui::Prop prop, any value, sol::state_view s) { +sol::object Api::Usertype::GuiElement::propToObject(const Gui::Props& props, Gui::Prop prop, + const Gui::ExpressionInfo& expr, sol::state_view s) { using namespace Gui; switch (prop) { - default: + default: { throw std::invalid_argument("Unhandled rule! This is an engine error! [1]"); - + } case Prop::LAYOUT: case Prop::DIRECTION: case Prop::H_ALIGN: case Prop::V_ALIGN: case Prop::CURSOR: case Prop::OVERFLOW: -// case Prop::TEXT_COLOR: + case Prop::TEXT_COLOR: case Prop::BACKGROUND: case Prop::BACKGROUND_HOVER: - case Prop::CONTENT: - return sol::make_object(s, std::any_cast(value)); - + case Prop::CONTENT: { + let v = props.get(prop); + if (!v) return sol::nil; + return sol::make_object(s, *v); + } case Prop::POS: case Prop::SIZE: - case Prop::GAP: - -// return sol::make_object(s, s.create_table_with( -// -// )); -// return sol::make_object(s, std::any_cast(value)); - + case Prop::GAP: { + let v = props.get(prop, expr); + if (!v) return sol::nil; + sol::table tbl = s.create_table(); + tbl[1] = (*v)[0]; + tbl[2] = (*v)[1]; + return sol::make_object(s, tbl); + } case Prop::MARGIN: - case Prop::PADDING: -// return parseLengthTableVal<4>(value); - - case Prop::TEXT_SIZE: - break; - throw std::invalid_argument("Unhandled rule! This is an engine error! [1]"); -// return parseObjectToExpr(value); + case Prop::PADDING: { + let v = props.get(prop, expr); + if (!v) return sol::nil; + sol::table tbl = s.create_table(); + tbl[1] = (*v)[0]; + tbl[2] = (*v)[1]; + tbl[3] = (*v)[2]; + tbl[4] = (*v)[3]; + return sol::make_object(s, tbl); + } + case Prop::TEXT_SIZE: { + let v = props.get(prop, expr); + if (!v) return sol::nil; + return sol::make_object(s, v); + } } } @@ -196,17 +208,15 @@ void Api::Usertype::GuiElement::bind(sol::state& lua, sol::table& core, Gui::Roo "remove() parameter must be nil, a number, an string, or a Gui element."); }, "clear", &Gui::Element::clear, - sol::meta_function::new_index, [&](Gui::Element& self, const string& ruleStr, sol::object rawValue) { - let rule = GuiElement::nameToProp(ruleStr); - let value = GuiElement::objectToProp(rule, rawValue); - self.setProp(rule, value); + sol::meta_function::new_index, [&](Gui::Element& self, const string& propStr, sol::object rawValue) { + let prop = GuiElement::nameToProp(propStr); + let value = GuiElement::objectToProp(prop, rawValue); + self.setProp(prop, value); self.updateElement(); }, - sol::meta_function::index, [&](sol::this_state s, Gui::Element& self, const string& ruleStr) { - let rule = GuiElement::nameToProp(ruleStr); - let value = self.getProps().get(rule); - if (!value) return sol::make_object(s, sol::nil); - return GuiElement::propToObject(rule, *value, s); + sol::meta_function::index, [&](sol::this_state s, Gui::Element& self, const string& propStr) { + let prop = GuiElement::nameToProp(propStr); + return GuiElement::propToObject(self.getProps(), prop, self.getExpr(), s); } ); } \ No newline at end of file diff --git a/src/lua/usertype/GuiElement.h b/src/lua/usertype/GuiElement.h index 9ff200fc..a51ee271 100644 --- a/src/lua/usertype/GuiElement.h +++ b/src/lua/usertype/GuiElement.h @@ -5,91 +5,23 @@ #include "util/Types.h" namespace Gui { - class Style; class Root; + class Props; class Element; enum class Prop; + class Expression; + class ExpressionInfo; } namespace Api::Usertype::GuiElement { Gui::Prop nameToProp(const string& str); any objectToProp(Gui::Prop prop, const sol::object& value); - sol::object propToObject(Gui::Prop prop, any value, sol::state_view s); + sol::object propToObject(const Gui::Props& props, Gui::Prop prop, + const Gui::ExpressionInfo& expr, sol::state_view s); std::shared_ptr create(const string& type, sol::table data, Gui::Root& root); sol::object call(sol::this_state s, sol::protected_function fun); void bind(sol::state& lua, sol::table& core, Gui::Root& root); -} -//class LuaGuiElement { -// public: -// LuaGuiElement() = default; -// -// // Lua Functions and Properties -// -// sol::object get_trait(sol::this_state s, const std::string& key); -// -// sol::object set_trait(const std::string& key, sol::object val); -// -// -// sol::object get_child(sol::this_state s, sol::object key); -// -// void append(sol::this_state s, sol::object elem); -// -// void prepend(sol::this_state s, sol::object elem); -// -// void remove(sol::this_state s, sol::object elem); -// -// void clear(sol::this_state s); -// -// std::string type{}, key{}; -// -// LuaGuiElement* parent = nullptr; -// std::list> children{}; -// -// std::unordered_map callbacks{}; -// std::unordered_map traits{}; -// -// // C++ Functions and Properties -// Any getAsAny(const std::string& key) const; -// -// template -// const T& get(const std::string& key) const { -// return getAsAny(key).get(); -// } -// -// template -// const T& get_or(const std::string& key, const T& other) const noexcept { -// Any a = getAsAny(key); -// if (a.empty() || !a.is()) return other; -// return a.get(); -// } -// -// template -// const bool has(const std::string& key) const noexcept { -// Any a = getAsAny(key); -// return !a.empty() && a.is(); -// } -// -// std::function updateFunction = nullptr; -//}; -// -//namespace ClientApi { -// static void gui_element(sol::state& lua) { -// lua.new_usertype("GuiElement", -// sol::meta_function::construct, sol::factories(&LuaGuiElement::create), -// -// sol::meta_function::index, &LuaGuiElement::get_trait, -// sol::meta_function::new_index, &LuaGuiElement::set_trait, -// -// sol::meta_function::call, &LuaGuiElement::call, -// -// "get", &LuaGuiElement::get_child, -// "append", &LuaGuiElement::append, -// "prepend", &LuaGuiElement::prepend, -// "remove", &LuaGuiElement::remove, -// "clear", &LuaGuiElement::clear -// ); -// } -//} +} \ No newline at end of file diff --git a/subgames/minimal/menu/script/init.lua b/subgames/minimal/menu/script/init.lua index 569c1f0a..ad81e708 100644 --- a/subgames/minimal/menu/script/init.lua +++ b/subgames/minimal/menu/script/init.lua @@ -3,26 +3,26 @@ zepha.set_gui(zepha.gui(function() background = "#334", Gui.Text { - pos = { 4, 4 }, + pos = { "4dp", "4dp" }, text_size = "2px", content = "Minimalminimalmmnal" }, Gui.Box { - pos = { 64, 64 }, - size = { 128 * (16/9), 128 }, + pos = { "64dp", "64dp" }, + size = { "128dp * (16/9)", "128dp" }, background = "zeus_background" }, Gui.Box { - pos = { 64 + 128, 64 + 64 }, - size = { 128 * (16/9), 128 }, + pos = { "64dp + 128dp", "128dp" }, + size = { "128dp * (16/9)", "128dp" }, background = "zeus_background", Gui.Text { - pos = 4, + pos = "4dp", text_size = "4px", content = "What's the fuck it'd going on?" } diff --git a/subgames/zeus/menu/script/init.lua b/subgames/zeus/menu/script/init.lua index 60e407a4..c6de9254 100644 --- a/subgames/zeus/menu/script/init.lua +++ b/subgames/zeus/menu/script/init.lua @@ -3,6 +3,7 @@ local menu = zepha.gui(function() background = 'zeus_background_christmas_night', Gui.Box { + id = 'particle_wrap', size = { '100cw', '100ch' } }, @@ -58,20 +59,15 @@ local menu = zepha.gui(function() } end) -local sizes = {} -local positions = {} -for _ = 1, 100 do - table.insert(sizes, 3 + math.random() * 8) - table.insert(positions, { math.floor(math.random() * 640), math.floor(math.random() * 320) }) -end - -local particle_wrap = menu:get(1) +local particle_count = 100 +local particle_wrap = menu:get('particle_wrap') zepha.gui(function() - for i, pos in ipairs(positions) do + for i = 1, particle_count do particle_wrap:append(Gui.Box { - pos = pos, background = 'particle_dark', - size = sizes[i] + + size = 3 + math.random() * 8 .. "dp", + pos = { math.floor(math.random() * 640) .. "dp", math.floor(math.random() * 320) .. "dp" } }) end end) @@ -79,13 +75,15 @@ end) local tick = 0 zepha.after(function() tick = tick + 0.016 - for i, pos in ipairs(positions) do + for i = 1, particle_count do local part = particle_wrap:get(i) + local pos = part.pos + local size = part.size[1] - pos[1] = pos[1] + (-math.sin(tick) * 0.0125 - 0.0025) * sizes[i] * 3 - pos[2] = pos[2] + 0.05 * sizes[i] - if pos[1] < -12 then pos[1] = 640 end - if pos[2] > 320 then pos[2] = -12 end + pos[1] = pos[1] + (-math.sin(tick) * 0.0125 - 0.0025) * size * 3 + pos[2] = pos[2] + 0.05 * size + if pos[1] < -36 then pos[1] = 640 * 3 end + if pos[2] > 320 * 3 then pos[2] = -36 end part.pos = pos end