UI Elements with Live manipulation & garbage collection 🦀
parent
fdd5ae307f
commit
af78490c7e
|
@ -1,5 +1,6 @@
|
|||
# Default ignored files
|
||||
/workspace.xml
|
||||
/shelf/
|
||||
|
||||
# Datasource local storage ignored files
|
||||
/dataSources.local.xml
|
|
@ -13,8 +13,8 @@
|
|||
GuiBuilder::GuiBuilder(TextureAtlas& textures, ModelStore& models, std::shared_ptr<GuiContainer> root) :
|
||||
textures(textures), models(models), root(root) {}
|
||||
|
||||
void GuiBuilder::setGuiRoot(LuaGuiElement& menu) {
|
||||
elements = &menu;
|
||||
void GuiBuilder::setGuiRoot(std::shared_ptr<LuaGuiElement> menu) {
|
||||
elements = menu;
|
||||
}
|
||||
|
||||
void GuiBuilder::build(glm::ivec2 winBounds) {
|
||||
|
@ -34,17 +34,12 @@ void GuiBuilder::create(LuaGuiElement& element, std::shared_ptr<GuiComponent> pa
|
|||
if (!component) throw std::runtime_error("GuiBuilder failed to create component: " + element.key);
|
||||
parent->add(component);
|
||||
|
||||
for (auto& child : element.children) create(child, component, component->getScale());
|
||||
for (auto& child : element.children) create(*child, component, component->getScale());
|
||||
}
|
||||
|
||||
std::shared_ptr<GuiComponent> GuiBuilder::createComponent(LuaGuiElement& elem, glm::ivec2 bounds) {
|
||||
std::shared_ptr<GuiComponent> c = nullptr;
|
||||
|
||||
if (elem.key == "wee") {
|
||||
auto a = elem.getAsAny("position");
|
||||
std::cout << a.get<glm::vec2>().x << ", " << a.get<glm::vec2>().y << std::endl;
|
||||
}
|
||||
|
||||
switch (Util::hash(elem.type.c_str())) {
|
||||
default: break;
|
||||
case Util::hash("Body"): {
|
||||
|
@ -92,7 +87,6 @@ void GuiBuilder::clearCallbacks(std::shared_ptr<GuiComponent> component) {
|
|||
}
|
||||
|
||||
void GuiBuilder::elementUpdated() {
|
||||
std::cout << "rebuilding ui " << std::endl;
|
||||
build();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ public:
|
|||
struct ComponentCallbacks { GuiComponent::callback left {}, right {}, hover {}; };
|
||||
|
||||
GuiBuilder(TextureAtlas& textures, ModelStore& models, std::shared_ptr<GuiContainer> root);
|
||||
void setGuiRoot(LuaGuiElement& menu);
|
||||
void setGuiRoot(std::shared_ptr<LuaGuiElement> menu);
|
||||
void build(glm::ivec2 winBounds = {});
|
||||
void clear(bool deleteRoot = true);
|
||||
|
||||
|
@ -33,7 +33,7 @@ protected:
|
|||
|
||||
std::shared_ptr<GuiContainer> root = nullptr;
|
||||
|
||||
LuaGuiElement* elements = nullptr;
|
||||
std::shared_ptr<LuaGuiElement> elements = nullptr;
|
||||
unsigned int keyInd = 0;
|
||||
|
||||
glm::ivec2 winBounds {};
|
||||
|
|
|
@ -8,16 +8,31 @@
|
|||
|
||||
#include "../../../game/hud/SerialGui.h"
|
||||
|
||||
LuaGuiElement::LuaGuiElement(const std::string& type, sol::table data) :
|
||||
type(type) {
|
||||
//LuaGuiElement::LuaGuiElement(const std::string& type, sol::table data) :
|
||||
// type(type) {
|
||||
//
|
||||
// for (const auto& pair : data) {
|
||||
// if (pair.first.is<float>()) {
|
||||
// if (!pair.second.is<std::shared_ptr<LuaGuiElement>>()) throw std::runtime_error("Child is not a GuiElement.");
|
||||
// children.push_back(pair.second.as<std::shared_ptr<LuaGuiElement>>());
|
||||
// }
|
||||
// else if (pair.first.is<std::string>()) set_trait(pair.first.as<std::string>(), pair.second);
|
||||
// }
|
||||
//}
|
||||
|
||||
std::shared_ptr<LuaGuiElement> LuaGuiElement::create(const std::string& type, sol::table data) {
|
||||
auto elem = std::make_shared<LuaGuiElement>();
|
||||
elem->type = type;
|
||||
|
||||
for (const auto& pair : data) {
|
||||
if (pair.first.is<float>()) {
|
||||
if (!pair.second.is<LuaGuiElement>()) throw std::runtime_error("Child is not a GuiElement.");
|
||||
children.push_back(pair.second.as<LuaGuiElement>());
|
||||
if (!pair.second.is<std::shared_ptr<LuaGuiElement>>()) throw std::runtime_error("Child is not a GuiElement.");
|
||||
elem->children.push_back(pair.second.as<std::shared_ptr<LuaGuiElement>>());
|
||||
}
|
||||
else if (pair.first.is<std::string>()) set_trait(pair.first.as<std::string>(), pair.second);
|
||||
else if (pair.first.is<std::string>()) elem->set_trait(pair.first.as<std::string>(), pair.second);
|
||||
}
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
sol::object LuaGuiElement::get_trait(sol::this_state s, const std::string& key) {
|
||||
|
@ -37,15 +52,8 @@ sol::object LuaGuiElement::set_trait(const std::string& key, sol::object val) {
|
|||
this->key = val.as<std::string>();
|
||||
}
|
||||
else {
|
||||
if (val.is<sol::table>()) {
|
||||
std::cout << key << "t: " << val.as<sol::table>().get<float>(1) << ", " << val.as<sol::table>().get<float>(2) << std::endl;
|
||||
}
|
||||
traits.erase(key);
|
||||
traits.emplace(key, val);
|
||||
if (val.is<sol::table>()) {
|
||||
sol::table v = traits.at(key).as<sol::table>();
|
||||
std::cout << key << "tv: " << v.get<float>(1) << ", " << v.get<float>(2) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (updateFunction) updateFunction();
|
||||
|
@ -60,34 +68,42 @@ sol::object LuaGuiElement::call(sol::this_state s, sol::function fun) {
|
|||
return fun(this);
|
||||
}
|
||||
|
||||
sol::object LuaGuiElement::find(sol::this_state s, const std::string& key) {
|
||||
for (auto& child : children) {
|
||||
if (child.key == key) return sol::make_object<LuaGuiElement>(s, child);
|
||||
sol::object LuaGuiElement::get_child(sol::this_state s, sol::object key) {
|
||||
if (key.is<float>() && key.as<float>() <= children.size()) {
|
||||
auto begin = children.begin();
|
||||
std::advance(begin, key.as<float>() - 1);
|
||||
return sol::make_object<std::shared_ptr<LuaGuiElement>>(s, *begin);
|
||||
}
|
||||
else if (key.is<std::string>()) {
|
||||
for (auto &child : children) {
|
||||
if (child->key == key.as<std::string>()) return sol::make_object<std::shared_ptr<LuaGuiElement>>(s, child);
|
||||
}
|
||||
|
||||
for (auto &child : children) {
|
||||
auto recurse = child->get_child(s, key);
|
||||
if (recurse) return recurse;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& child : children) {
|
||||
auto recurse = child.find(s, key);
|
||||
if (recurse) return recurse;
|
||||
}
|
||||
return sol::nil;
|
||||
}
|
||||
|
||||
void LuaGuiElement::append(sol::this_state s, sol::object elem) {
|
||||
if (elem.is<LuaGuiElement>()) children.push_back(elem.as<LuaGuiElement>());
|
||||
else if (elem.is<sol::function>()) children.push_back(call(s, elem.as<sol::function>()).as<LuaGuiElement>());
|
||||
if (elem.is<LuaGuiElement>()) children.push_back(elem.as<std::shared_ptr<LuaGuiElement>>());
|
||||
else if (elem.is<sol::function>()) children.push_back(call(s, elem.as<sol::function>()).as<std::shared_ptr<LuaGuiElement>>());
|
||||
else throw std::runtime_error("Append arg is not an element or a function to generate one.");
|
||||
|
||||
if (updateFunction) updateFunction();
|
||||
children.back().updateFunction = updateFunction;
|
||||
children.back()->updateFunction = updateFunction;
|
||||
}
|
||||
|
||||
void LuaGuiElement::prepend(sol::this_state s, sol::object elem) {
|
||||
if (elem.is<LuaGuiElement>()) children.insert(children.begin(), elem.as<LuaGuiElement>());
|
||||
else if (elem.is<sol::function>()) children.insert(children.begin(), call(s, elem.as<sol::function>()).as<LuaGuiElement>());
|
||||
if (elem.is<LuaGuiElement>()) children.insert(children.begin(), elem.as<std::shared_ptr<LuaGuiElement>>());
|
||||
else if (elem.is<sol::function>()) children.insert(children.begin(), call(s, elem.as<sol::function>()).as<std::shared_ptr<LuaGuiElement>>());
|
||||
else throw std::runtime_error("Append arg is not an element or a function to generate one.");
|
||||
|
||||
if (updateFunction) updateFunction();
|
||||
children.front().updateFunction = updateFunction;
|
||||
children.front()->updateFunction = updateFunction;
|
||||
}
|
||||
|
||||
void LuaGuiElement::remove(sol::optional<LuaGuiElement> elem) {
|
||||
|
@ -97,7 +113,7 @@ void LuaGuiElement::remove(sol::optional<LuaGuiElement> elem) {
|
|||
}
|
||||
else {
|
||||
for (const auto it = children.cbegin(); it != children.cend();) {
|
||||
if (it->key == elem->key) {
|
||||
if ((*it)->key == elem->key) {
|
||||
children.erase(it);
|
||||
if (updateFunction) updateFunction();
|
||||
return;
|
||||
|
|
|
@ -11,14 +11,16 @@
|
|||
|
||||
class LuaGuiElement {
|
||||
public:
|
||||
LuaGuiElement(const std::string& type, sol::table data);
|
||||
LuaGuiElement() = default;
|
||||
|
||||
// Lua Functions and Properties
|
||||
static std::shared_ptr<LuaGuiElement> create(const std::string& type, sol::table data);
|
||||
|
||||
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 call(sol::this_state s, sol::function fun);
|
||||
sol::object find(sol::this_state s, const std::string& key);
|
||||
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);
|
||||
|
@ -27,7 +29,7 @@ public:
|
|||
std::string type {}, key {};
|
||||
|
||||
LuaGuiElement* parent = nullptr;
|
||||
std::list<LuaGuiElement> children {};
|
||||
std::list<std::shared_ptr<LuaGuiElement>> children {};
|
||||
|
||||
std::unordered_map<std::string, sol::function> callbacks {};
|
||||
std::unordered_map<std::string, sol::object> traits {};
|
||||
|
@ -54,14 +56,14 @@ public:
|
|||
namespace ClientApi {
|
||||
static void gui_element(sol::state& lua) {
|
||||
lua.new_usertype<LuaGuiElement>("GuiElement",
|
||||
sol::constructors<LuaGuiElement(std::string, sol::object)>(),
|
||||
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,
|
||||
|
||||
"find", &LuaGuiElement::find,
|
||||
"get", &LuaGuiElement::get_child,
|
||||
"append", &LuaGuiElement::append,
|
||||
"prepend", &LuaGuiElement::prepend,
|
||||
"remove", &LuaGuiElement::remove
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
namespace MenuApi {
|
||||
void set_gui(GuiBuilder& builder, glm::ivec2& win, sol::state& lua, sol::table& core) {
|
||||
core.set_function("set_gui", [&](LuaGuiElement& gui) {
|
||||
core.set_function("set_gui", [&](std::shared_ptr<LuaGuiElement> gui) {
|
||||
builder.setGuiRoot(gui);
|
||||
builder.build(win);
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@ local gui = zepha.build_gui(function()
|
|||
|
||||
Gui.Text {
|
||||
position = { 4, 4 },
|
||||
content = "Minimal Subgame"
|
||||
content = "Minimalminimalmmnal"
|
||||
},
|
||||
|
||||
Gui.Rect {
|
||||
|
@ -22,25 +22,10 @@ local gui = zepha.build_gui(function()
|
|||
background = "zeus_background",
|
||||
|
||||
Gui.Text {
|
||||
content = "What's the fuck is going on?"
|
||||
content = "What's the fuck it'd going on?"
|
||||
}
|
||||
},
|
||||
|
||||
Gui.Rect {
|
||||
position = { 0, 0 },
|
||||
size = { 32, 32 },
|
||||
background = "#f00",
|
||||
key = "wee"
|
||||
}
|
||||
}
|
||||
end)
|
||||
|
||||
zepha.set_gui(gui)
|
||||
|
||||
local menu = gui:find("wee")
|
||||
|
||||
zepha.delay(function()
|
||||
print("updating position")
|
||||
menu.position = {menu.position[1] + 16, menu.position[2] + 16}
|
||||
return true
|
||||
end, 1)
|
||||
zepha.set_gui(gui)
|
Binary file not shown.
After Width: | Height: | Size: 597 B |
Loading…
Reference in New Issue