Get computed properties :)

master
Auri 2021-08-24 13:51:41 -07:00
parent 9aec996b74
commit 2cf3e7aaea
13 changed files with 118 additions and 234 deletions

View File

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

View File

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

View File

@ -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<sol::error>(e).what();
vec<string> 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<sol::error>(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<string> dirsToScan{ root };
std::list<string> luaFiles{};
std::list<string> dirsToScan { root };
std::list<string> luaFiles {};
cf_dir_t dir;
while (!dirsToScan.empty()) {
@ -158,41 +195,4 @@ void MenuSandbox::showError(const string& err) {
{ Gui::Prop::SIZE, array<Expr, 2> { Expr("100dp"), Expr("-1") } },
{ Gui::Prop::MARGIN, array<Expr, 4> { Expr("4dp"), Expr("4dp"), Expr("4dp"), Expr("4dp") } }
}});
}
sol::protected_function_result MenuSandbox::errorCallback(sol::protected_function_result r) {
string err = static_cast<sol::error>(r).what();
std::cout << Log::err << err << Log::endl;
vec<string> 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;
}
}

View File

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

View File

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

View File

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

View File

@ -32,8 +32,6 @@ public:
return res;
}
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) = 0;
Subgame& game;
sol::state lua;

View File

@ -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<sol::error>(pfr); },
"@" + f.path, sol::load_mode::text);
}
throw std::runtime_error("Error opening \"" + file + "\", file not found.");
}

View File

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

View File

@ -8,7 +8,7 @@
static const Gui::Expression parseObjectToExpr(sol::object value) {
if (!value.valid()) return Gui::Expression("");
if (value.is<f32>()) return Gui::Expression(std::to_string(value.as<f32>()) + "dp");
if (value.is<f32>()) return Gui::Expression(std::to_string(value.as<f32>()) + "px");
if (value.is<string>()) return Gui::Expression(value.as<string>());
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<string>(value));
case Prop::CONTENT: {
let v = props.get<string>(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<string>(value));
case Prop::GAP: {
let v = props.get<vec2, Gui::Type::LENGTH>(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<vec4, Gui::Type::LENGTH>(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<f32, Gui::Type::LENGTH>(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);
}
);
}

View File

@ -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<Gui::Element> 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<std::shared_ptr<LuaGuiElement>> children{};
//
// std::unordered_map<std::string, sol::function> callbacks{};
// std::unordered_map<std::string, sol::object> traits{};
//
// // C++ Functions and Properties
// Any getAsAny(const std::string& key) const;
//
// template<typename T>
// const T& get(const std::string& key) const {
// return getAsAny(key).get<T>();
// }
//
// template<typename T>
// const T& get_or(const std::string& key, const T& other) const noexcept {
// Any a = getAsAny(key);
// if (a.empty() || !a.is<T>()) return other;
// return a.get<T>();
// }
//
// template<typename T>
// const bool has(const std::string& key) const noexcept {
// Any a = getAsAny(key);
// return !a.empty() && a.is<T>();
// }
//
// std::function<void()> updateFunction = nullptr;
//};
//
//namespace ClientApi {
// static void gui_element(sol::state& lua) {
// lua.new_usertype<Gui::Element>("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
// );
// }
//}
}

View File

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

View File

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