UI Elements with Live manipulation & garbage collection 🦀

master
Nicole Collings 2020-04-15 13:09:13 -07:00
parent fdd5ae307f
commit af78490c7e
8 changed files with 59 additions and 61 deletions

1
.idea/.gitignore vendored
View File

@ -1,5 +1,6 @@
# Default ignored files
/workspace.xml
/shelf/
# Datasource local storage ignored files
/dataSources.local.xml

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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