Remove SerialGuiElement, use LuaGuiElement in GuiBuilder

master
Nicole Collings 2020-04-13 18:10:39 -07:00
parent afa1b5621d
commit 49d9ad73ae
25 changed files with 255 additions and 291 deletions

View File

@ -320,6 +320,6 @@ set(ZEPHA_SRC
game/inventory/InventoryList.h
lua/api/modules/time.h
util/net/PacketView.cpp
util/net/PacketView.h lua/api/modules/create_structure.h util/Any.h game/scene/world/graph/MeshFarMap.cpp game/scene/world/graph/MeshFarMap.h def/gen/MapGenProps.cpp def/gen/MapGenProps.h def/gen/FarMapGen.cpp def/gen/FarMapGen.h def/gen/FarMapJob.h game/scene/world/graph/FarMeshGenerator.cpp game/scene/world/graph/FarMeshGenerator.h game/scene/world/FarMapMeshDetails.h lua/api/usertype/cGuiElement.h lua/api/class/LocalGuiElement.cpp lua/api/class/LocalGuiElement.h)
util/net/PacketView.h lua/api/modules/create_structure.h util/Any.h game/scene/world/graph/MeshFarMap.cpp game/scene/world/graph/MeshFarMap.h def/gen/MapGenProps.cpp def/gen/MapGenProps.h def/gen/FarMapGen.cpp def/gen/FarMapGen.h def/gen/FarMapJob.h game/scene/world/graph/FarMeshGenerator.cpp game/scene/world/graph/FarMeshGenerator.h game/scene/world/FarMapMeshDetails.h lua/api/class/LuaGuiElement.cpp lua/api/class/LuaGuiElement.h)
add_library (Zepha_Core ${ZEPHA_SRC})

View File

@ -8,7 +8,7 @@
#include "components/compound/GuiInventoryList.h"
std::shared_ptr<GuiComponent> GameGuiBuilder::createComponent(const SerialGui::Element& elem, glm::ivec2 bounds) {
std::shared_ptr<GuiComponent> GameGuiBuilder::createComponent(const LuaGuiElement& elem, glm::ivec2 bounds) {
auto c = GuiBuilder::createComponent(elem, bounds);
if (c != nullptr) return c;
@ -22,14 +22,14 @@ std::shared_ptr<GuiComponent> GameGuiBuilder::createComponent(const SerialGui::E
if (!c) return nullptr;
if (elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::PRIMARY)])
c->setCallback(GuiComponent::CallbackType::PRIMARY, elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::PRIMARY)]);
if (elem.callbacks.count("primary")) c->setCallback(GuiComponent::CallbackType::PRIMARY, [=](bool b, glm::vec2 v) {
elem.callbacks.at("primary")(b, LuaParser::luaVec(elem.callbacks.at("primary").lua_state(), {v.x, v.y, 0})); });
if (elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::SECONDARY)])
c->setCallback(GuiComponent::CallbackType::SECONDARY, elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::SECONDARY)]);
if (elem.callbacks.count("secondary")) c->setCallback(GuiComponent::CallbackType::SECONDARY, [=](bool b, glm::vec2 v) {
elem.callbacks.at("secondary")(b, LuaParser::luaVec(elem.callbacks.at("secondary").lua_state(), {v.x, v.y, 0})); });
if (elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::HOVER)])
c->setCallback(GuiComponent::CallbackType::HOVER, elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::HOVER)]);
if (elem.callbacks.count("hover")) c->setCallback(GuiComponent::CallbackType::HOVER, [=](bool b, glm::vec2 v) {
elem.callbacks.at("hover")(b, LuaParser::luaVec(elem.callbacks.at("hover").lua_state(), {v.x, v.y, 0})); });
return c;
}

View File

@ -14,7 +14,7 @@ public:
GameGuiBuilder(LocalInventoryRefs& refs, ClientGame& defs, std::shared_ptr<GuiContainer> root) :
defs(defs), refs(refs), GuiBuilder(defs.textures, defs.models, root) {};
std::shared_ptr<GuiComponent> createComponent(const SerialGui::Element& elem, glm::ivec2 bounds) override;
std::shared_ptr<GuiComponent> createComponent(const LuaGuiElement& elem, glm::ivec2 bounds) override;
private:
LocalInventoryRefs& refs;
ClientGame& defs;

View File

@ -13,83 +13,22 @@
GuiBuilder::GuiBuilder(TextureAtlas& textures, ModelStore& models, std::shared_ptr<GuiContainer> root) :
textures(textures), models(models), root(root) {}
void GuiBuilder::setGuiRoot(sol::state_view state, LocalGuiElement& menu) {
keyInd = 0;
serialized = recursivelyDeserialize(state, menu);
}
SerialGui::Element GuiBuilder::recursivelyDeserialize(sol::state_view state, LocalGuiElement& elem) {
std::string key = (elem.key.size() ? elem.key : "__UNKEYED_COMPONENT_" + std::to_string(keyInd++));
SerialGui::Element element(elem.type, key);
for (const auto& trait : elem.traits) {
auto key = trait.first;
if (trait.second.is<std::string>()) {
element.addTrait(key, Any::from<std::string>(trait.second.as<std::string>()));
}
else if (trait.second.is<sol::table>()) {
if (trait.second.as<sol::table>().size() == 2) {
auto x = trait.second.as<sol::table>().get<sol::object>(1);
auto y = trait.second.as<sol::table>().get<sol::object>(2);
glm::vec2 values = {};
if (x.is<float>()) values.x = x.as<float>();
else if (x.is<std::string>()) values.x = SerialGui::toDouble(x.as<std::string>());
if (y.is<float>()) values.y = y.as<float>();
else if (y.is<std::string>()) values.y = SerialGui::toDouble(y.as<std::string>());
element.addTrait(key, Any::from<glm::vec2>(values));
}
else if (trait.second.as<sol::table>().size() == 4) {
auto x = trait.second.as<sol::table>().get<sol::object>(1);
auto y = trait.second.as<sol::table>().get<sol::object>(2);
auto z = trait.second.as<sol::table>().get<sol::object>(3);
auto w = trait.second.as<sol::table>().get<sol::object>(4);
glm::vec4 values = {};
if (x.is<float>()) values.x = x.as<float>();
else if (x.is<std::string>()) values.x = SerialGui::toDouble(x.as<std::string>());
if (y.is<float>()) values.y = y.as<float>();
else if (y.is<std::string>()) values.y = SerialGui::toDouble(y.as<std::string>());
if (z.is<float>()) values.z = z.as<float>();
else if (z.is<std::string>()) values.z = SerialGui::toDouble(z.as<std::string>());
if (w.is<float>()) values.w = w.as<float>();
else if (w.is<std::string>()) values.w = SerialGui::toDouble(w.as<std::string>());
element.addTrait(key, Any::from<glm::vec4>(values));
}
}
}
if (elem.callbacks.count("primary"))
element.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::PRIMARY)] = [=](bool down, glm::ivec2 pos) {
elem.callbacks.at("primary")(down, LuaParser::luaVec(state, {pos.x, pos.y, 0})); };
if (elem.callbacks.count("secondary"))
element.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::SECONDARY)] = [=](bool down, glm::ivec2 pos) {
elem.callbacks.at("secondary")(down, LuaParser::luaVec(state, {pos.x, pos.y, 0})); };
if (elem.callbacks.count("secondary"))
element.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::HOVER)] = [=](bool down, glm::ivec2 pos) {
elem.callbacks.at("hover")(down, LuaParser::luaVec(state, {pos.x, pos.y, 0})); };
for (auto& child : elem.children) element.children.push_back(recursivelyDeserialize(state, child));
return element;
void GuiBuilder::setGuiRoot(sol::state_view state, LuaGuiElement& menu) {
elements = &menu;
}
void GuiBuilder::build(glm::ivec2 winBounds) {
clear(false);
if (serialized.type != "")
recursivelyCreate(serialized, root, winBounds);
if (elements) recursivelyCreate(*elements, root, winBounds);
}
void GuiBuilder::clear(bool deleteRoot) {
recursivelyClearCallbacks(root);
root->empty();
if (deleteRoot) serialized = {"", ""};
if (deleteRoot) elements = nullptr;
}
void GuiBuilder::recursivelyCreate(const SerialGui::Element& element, std::shared_ptr<GuiComponent> parent, glm::ivec2 bounds) {
void GuiBuilder::recursivelyCreate(const LuaGuiElement& element, std::shared_ptr<GuiComponent> parent, glm::ivec2 bounds) {
auto component = createComponent(element, bounds);
if (!component) throw std::runtime_error("GuiBuilder failed to create component: " + element.key);
parent->add(component);
@ -107,7 +46,7 @@ void GuiBuilder::recursivelyClearCallbacks(std::shared_ptr<GuiComponent> compone
}
}
std::shared_ptr<GuiComponent> GuiBuilder::createComponent(const SerialGui::Element& elem, glm::ivec2 bounds) {
std::shared_ptr<GuiComponent> GuiBuilder::createComponent(const LuaGuiElement& elem, glm::ivec2 bounds) {
std::shared_ptr<GuiComponent> c = nullptr;
switch (Util::hash(elem.type.c_str())) {
@ -134,14 +73,14 @@ std::shared_ptr<GuiComponent> GuiBuilder::createComponent(const SerialGui::Eleme
if (!c) return nullptr;
if (elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::PRIMARY)])
c->setCallback(GuiComponent::CallbackType::PRIMARY, elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::PRIMARY)]);
if (elem.callbacks.count("primary")) c->setCallback(GuiComponent::CallbackType::PRIMARY, [=](bool b, glm::vec2 v) {
elem.callbacks.at("primary")(b, LuaParser::luaVec(elem.callbacks.at("primary").lua_state(), {v.x, v.y, 0})); });
if (elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::SECONDARY)])
c->setCallback(GuiComponent::CallbackType::SECONDARY, elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::SECONDARY)]);
if (elem.callbacks.count("secondary")) c->setCallback(GuiComponent::CallbackType::SECONDARY, [=](bool b, glm::vec2 v) {
elem.callbacks.at("secondary")(b, LuaParser::luaVec(elem.callbacks.at("secondary").lua_state(), {v.x, v.y, 0})); });
if (elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::HOVER)])
c->setCallback(GuiComponent::CallbackType::HOVER, elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::HOVER)]);
if (elem.callbacks.count("hover")) c->setCallback(GuiComponent::CallbackType::HOVER, [=](bool b, glm::vec2 v) {
elem.callbacks.at("hover")(b, LuaParser::luaVec(elem.callbacks.at("hover").lua_state(), {v.x, v.y, 0})); });
return c;
}

View File

@ -7,7 +7,7 @@
#include "SerialGui.h"
#include "components/GuiComponent.h"
#include "../../def/ClientGame.h"
#include "../../lua/api/class/LocalGuiElement.h"
#include "../../lua/api/class/LuaGuiElement.h"
class GuiContainer;
@ -16,22 +16,21 @@ public:
struct ComponentCallbacks { GuiComponent::callback left {}, right {}, hover {}; };
GuiBuilder(TextureAtlas& textures, ModelStore& models, std::shared_ptr<GuiContainer> root);
void setGuiRoot(sol::state_view state, LocalGuiElement& menu);
void setGuiRoot(sol::state_view state, LuaGuiElement& menu);
void build(glm::ivec2 winBounds);
void clear(bool deleteRoot = true);
~GuiBuilder();
protected:
SerialGui::Element recursivelyDeserialize(sol::state_view state, LocalGuiElement& elem);
void recursivelyCreate(const SerialGui::Element& element, std::shared_ptr<GuiComponent> parent, glm::ivec2 bounds);
void recursivelyCreate(const LuaGuiElement& element, std::shared_ptr<GuiComponent> parent, glm::ivec2 bounds);
static void recursivelyClearCallbacks(std::shared_ptr<GuiComponent> component);
virtual std::shared_ptr<GuiComponent> createComponent(const SerialGui::Element& elem, glm::ivec2 bounds);
virtual std::shared_ptr<GuiComponent> createComponent(const LuaGuiElement& elem, glm::ivec2 bounds);
TextureAtlas& textures;
ModelStore& models;
std::shared_ptr<GuiContainer> root = nullptr;
SerialGui::Element serialized = {"", ""};
LuaGuiElement* elements = nullptr;
unsigned int keyInd = 0;
};

View File

@ -16,43 +16,11 @@
#include <glm/vec2.hpp>
#include <glm/vec4.hpp>
#include <sol2/sol.hpp>
#include "../../util/Any.h"
#include <iostream>
#include "../../util/Any.h"
#include "../../lua/api/class/LuaGuiElement.h"
namespace SerialGui {
class Element {
public:
Element(const std::string& type, const std::string& key) : type(type), key(key) {};
std::string type;
std::string key;
void addTrait(const std::string& key, const Any& any) {
traits.emplace(key, any);
}
template <typename T> const T& get(const std::string& key) const {
if (!traits.count(key)) throw std::logic_error("Key missing from table");
return traits.at(key).get<T>();
}
template <typename T> const T& get_or(const std::string& key, const T& other) const noexcept {
if (!traits.count(key)) return other;
return traits.at(key).get_or<T>(other);
}
template <typename T> const bool has(const std::string& key) const noexcept {
if (!traits.count(key)) return false;
return traits.at(key).is<T>();
}
std::array<std::function<void(bool, glm::ivec2)>, 3> callbacks = {{nullptr, nullptr, nullptr}};
std::vector<SerialGui::Element> children {};
private:
std::map<std::string, Any> traits {};
};
const float SCALE_MODIFIER = 3;
namespace {
@ -107,7 +75,7 @@ namespace SerialGui {
template <typename T> static T calcNumbers(const T in, glm::ivec2 multiple = {}) {};
template <typename T> static T get(const SerialGui::Element& elem, const std::string& req, glm::ivec2 multiple = {}) {
template <typename T> static T get(const LuaGuiElement& elem, const std::string& req, glm::ivec2 multiple = {}) {
if (!elem.has<T>(req)) return T{};
return calcNumbers<T>(elem.get<T>(req), multiple);
}

View File

@ -9,7 +9,7 @@
GuiModel::GuiModel(const std::string &key) : GuiComponent(key) {}
std::shared_ptr<GuiModel> GuiModel::fromSerialized(const SerialGui::Element& elem, TextureAtlas& textures, ModelStore& models, glm::ivec2 bounds) {
std::shared_ptr<GuiModel> GuiModel::fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, ModelStore& models, glm::ivec2 bounds) {
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
glm::vec2 scale = SerialGui::get<glm::vec2>(elem, "scale");
glm::vec2 anim_range = SerialGui::get<glm::vec2>(elem, "anim_range");

View File

@ -18,7 +18,7 @@ public:
GuiModel() = default;
GuiModel(const std::string& key);
static std::shared_ptr<GuiModel> fromSerialized(const SerialGui::Element& elem, TextureAtlas& textures, ModelStore& models, glm::ivec2 bounds);
static std::shared_ptr<GuiModel> fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, ModelStore& models, glm::ivec2 bounds);
void create(glm::vec2 scale, std::shared_ptr<Model> model);
void update(double delta) override;

View File

@ -10,7 +10,7 @@
GuiRect::GuiRect(const std::string &key) : GuiComponent(key) {}
std::shared_ptr<GuiRect> GuiRect::fromSerialized(const SerialGui::Element& elem, TextureAtlas& textures, glm::ivec2 bounds) {
std::shared_ptr<GuiRect> GuiRect::fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds) {
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
glm::vec2 offset = SerialGui::get<glm::vec2>(elem, "position_anchor");
glm::vec2 size = SerialGui::get<glm::vec2>(elem, "size", bounds);

View File

@ -4,12 +4,9 @@
#pragma once
#include <memory>
#include "../GuiComponent.h"
#include "../../SerialGui.h"
#include "../../../../def/texture/AtlasRef.h"
#include "../../../../lua/api/class/LuaGuiElement.h"
class ClientGame;
@ -18,7 +15,7 @@ public:
GuiRect() = default;
GuiRect(const std::string& key);
static std::shared_ptr<GuiRect> fromSerialized(const SerialGui::Element& elem, TextureAtlas& textures, glm::ivec2 bounds);
static std::shared_ptr<GuiRect> fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds);
void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 color);
void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 tl, glm::vec4 tr, glm::vec4 bl, glm::vec4 br);

View File

@ -23,7 +23,7 @@ void GuiText::create(glm::vec2 scale, glm::vec4 padding, glm::vec4 bgcolor, glm:
setText("");
}
std::shared_ptr<GuiText> GuiText::fromSerialized(const SerialGui::Element& elem, TextureAtlas& textures, glm::ivec2 bounds) {
std::shared_ptr<GuiText> GuiText::fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds) {
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
glm::vec2 offset = SerialGui::get<glm::vec2>(elem, "position_anchor");
glm::vec2 size = SerialGui::get<glm::vec2>(elem, "size", bounds);

View File

@ -17,7 +17,7 @@ public:
GuiText() = default;
explicit GuiText(const std::string& key);
static std::shared_ptr<GuiText> fromSerialized(const SerialGui::Element& elem, TextureAtlas& textures, glm::ivec2 bounds);
static std::shared_ptr<GuiText> fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds);
void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 bgcolor, glm::vec4 color, Font font);

View File

@ -9,7 +9,7 @@
GuiImageButton::GuiImageButton(const std::string &key) : GuiRect(key) {}
std::shared_ptr<GuiImageButton> GuiImageButton::fromSerialized(const SerialGui::Element& elem, TextureAtlas& textures, glm::ivec2 bounds) {
std::shared_ptr<GuiImageButton> GuiImageButton::fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds) {
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
glm::vec2 offset = SerialGui::get<glm::vec2>(elem, "position_anchor");
glm::vec2 size = SerialGui::get<glm::vec2>(elem, "size", bounds);

View File

@ -11,7 +11,7 @@ public:
GuiImageButton() = default;
GuiImageButton(const std::string& key);
static std::shared_ptr<GuiImageButton> fromSerialized(const SerialGui::Element& elem, TextureAtlas& textures, glm::ivec2 bounds);
static std::shared_ptr<GuiImageButton> fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds);
void create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr<AtlasRef> texture, std::shared_ptr<AtlasRef> hoverTexture);

View File

@ -9,7 +9,7 @@
#include "../../../../def/texture/Font.h"
GuiInventoryList::GuiInventoryList(const std::string &key) : GuiContainer(key) {}
std::shared_ptr<GuiInventoryList> GuiInventoryList::fromSerialized(SerialGui::Element elem, ClientGame &game,
std::shared_ptr<GuiInventoryList> GuiInventoryList::fromSerialized(const LuaGuiElement& elem, ClientGame &game,
glm::ivec2 bounds, LocalInventoryRefs& refs) {
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);

View File

@ -19,7 +19,7 @@ public:
GuiInventoryList(const std::string& key);
~GuiInventoryList() override;
static std::shared_ptr<GuiInventoryList> fromSerialized(SerialGui::Element elem, ClientGame &game,
static std::shared_ptr<GuiInventoryList> fromSerialized(const LuaGuiElement& elem, ClientGame &game,
glm::ivec2 bounds, LocalInventoryRefs& refs);
void create(glm::vec2 scale, glm::vec4 padding, glm::ivec2 innerPadding,

View File

@ -9,7 +9,7 @@
#include "../../../lua/api/menu/mSetGui.h"
#include "../../../lua/api/menu/mStartGame.h"
#include "../../../lua/api/usertype/cGuiElement.h"
#include "../../../lua/api/class/LuaGuiElement.h"
MenuSandbox::MenuSandbox(glm::ivec2 &win, ClientState& state, std::shared_ptr<GuiContainer> container) :
win(win),

View File

@ -1,87 +0,0 @@
//
// Created by aurailus on 2020-04-12.
//
#include "LocalGuiElement.h"
LocalGuiElement::LocalGuiElement(const std::string& type, sol::table data) :
type(type) {
for (const auto& pair : data) {
if (pair.first.is<float>()) {
if (!pair.second.is<LocalGuiElement>()) throw std::runtime_error("Child is not a GuiElement.");
children.push_back(pair.second.as<LocalGuiElement>());
}
else if (pair.first.is<std::string>()) set(pair.first.as<std::string>(), pair.second);
}
}
sol::object LocalGuiElement::get(sol::this_state s, const std::string& key) {
if (key == "key") return sol::make_object<std::string>(s, this->key);
if (key == "type") return sol::make_object<std::string>(s, this->type);
if (traits.count(key)) return traits[key];
return sol::nil;
}
sol::object LocalGuiElement::set(const std::string& key, sol::object val) {
if (key == "callbacks") {
callbacks.clear();
for (auto pair : val.as<sol::table>()) callbacks[pair.first.as<std::string>()] = pair.second.as<sol::function>();
return val;
}
if ((!traits.count(key) || traits.at(key) != val) && updateFunction) updateFunction(id);
traits[key] = val;
return val;
}
sol::object LocalGuiElement::call(sol::this_state s, sol::function fun) {
sol::table tbl = sol::state_view(s)["zepha"]["__builtin"]["gui_env"];
sol::environment env(s, sol::create, tbl);
sol::set_environment(env, fun);
return fun(this);
}
sol::object LocalGuiElement::find(sol::this_state s, const std::string& key) {
for (auto& child : children) if (child.key == key) return sol::make_object<LocalGuiElement>(s, child);
for (auto& child : children) {
auto recurse = child.find(s, key);
if (recurse) return recurse;
}
return sol::nil;
}
void LocalGuiElement::append(sol::this_state s, sol::object elem) {
if (elem.is<LocalGuiElement>()) children.push_back(elem.as<LocalGuiElement>());
else if (elem.is<sol::function>()) children.push_back(call(s, elem.as<sol::function>()).as<LocalGuiElement>());
else throw std::runtime_error("Append arg is not an element or a function to generate one.");
if (updateFunction) updateFunction(id);
}
void LocalGuiElement::prepend(sol::this_state s, sol::object elem) {
if (elem.is<LocalGuiElement>()) children.insert(children.begin(), elem.as<LocalGuiElement>());
else if (elem.is<sol::function>()) children.insert(children.begin(), call(s, elem.as<sol::function>()).as<LocalGuiElement>());
else throw std::runtime_error("Append arg is not an element or a function to generate one.");
if (updateFunction) updateFunction(id);
}
void LocalGuiElement::remove(sol::optional<LocalGuiElement> elem) {
if (!elem) {
if (parent != nullptr) parent->remove(sol::make_optional<LocalGuiElement>(*this));
else throw std::runtime_error("Tried to remove self from nil parent.");
}
else {
for (const auto it = children.cbegin(); it != children.cend();) {
if (it->key == elem->key) {
children.erase(it);
if (updateFunction) updateFunction(id);
return;
}
}
}
}

View File

@ -1,36 +0,0 @@
//
// Created by aurailus on 2020-04-12.
//
#pragma once
#include <list>
#include <sol2/sol.hpp>
class LocalGuiElement {
public:
LocalGuiElement(const std::string& type, sol::table data);
sol::object get(sol::this_state s, const std::string& key);
sol::object set(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);
void append(sol::this_state s, sol::object elem);
void prepend(sol::this_state s, sol::object elem);
void remove(sol::optional<LocalGuiElement> elem);
std::string type {}, key {};
LocalGuiElement* parent = nullptr;
std::list<LocalGuiElement> children {};
std::unordered_map<std::string, sol::function> callbacks {};
std::unordered_map<std::string, sol::object> traits {};
// Internal data
unsigned int id = 0;
std::function<void(unsigned int id)> updateFunction = nullptr;
};

View File

@ -0,0 +1,132 @@
//
// Created by aurailus on 2020-04-12.
//
#include <glm/vec2.hpp>
#include "LuaGuiElement.h"
#include "../../../game/hud/SerialGui.h"
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<LuaGuiElement>()) throw std::runtime_error("Child is not a GuiElement.");
children.push_back(pair.second.as<LuaGuiElement>());
}
else if (pair.first.is<std::string>()) set_trait(pair.first.as<std::string>(), pair.second);
}
}
sol::object LuaGuiElement::get_trait(sol::this_state s, const std::string& key) {
if (key == "key") return sol::make_object<std::string>(s, this->key);
if (key == "type") return sol::make_object<std::string>(s, this->type);
if (traits.count(key)) return traits[key];
return sol::nil;
}
sol::object LuaGuiElement::set_trait(const std::string& key, sol::object val) {
if (key == "callbacks") {
callbacks.clear();
for (auto pair : val.as<sol::table>()) callbacks[pair.first.as<std::string>()] = pair.second.as<sol::function>();
return val;
}
// if ((!traits.count(key) || traits.at(key) != val) && updateFunction) updateFunction(id);
traits[key] = val;
return val;
}
sol::object LuaGuiElement::call(sol::this_state s, sol::function fun) {
sol::table tbl = sol::state_view(s)["zepha"]["__builtin"]["gui_env"];
sol::environment env(s, sol::create, tbl);
sol::set_environment(env, 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);
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>());
else throw std::runtime_error("Append arg is not an element or a function to generate one.");
// if (updateFunction) updateFunction(id);
}
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>());
else throw std::runtime_error("Append arg is not an element or a function to generate one.");
// if (updateFunction) updateFunction(id);
}
void LuaGuiElement::remove(sol::optional<LuaGuiElement> elem) {
if (!elem) {
if (parent != nullptr) parent->remove(sol::make_optional<LuaGuiElement>(*this));
else throw std::runtime_error("Tried to remove self from nil parent.");
}
else {
for (const auto it = children.cbegin(); it != children.cend();) {
if (it->key == elem->key) {
children.erase(it);
// if (updateFunction) updateFunction(id);
return;
}
}
}
}
Any LuaGuiElement::getAsAny(const std::string &key) const noexcept {
if (!traits.count(key)) return Any();
auto object = traits.at(key);
if (object.is<std::string>()) return Any::from<std::string>(object.as<std::string>());
else if (object.is<sol::table>()) {
auto table = object.as<sol::table>();
if (table.size() == 2) {
auto x = table.get<sol::object>(1);
auto y = table.get<sol::object>(2);
glm::vec2 values = {};
if (x.is<float>()) values.x = x.as<float>();
else if (x.is<std::string>()) values.x = SerialGui::toDouble(x.as<std::string>());
if (y.is<float>()) values.y = y.as<float>();
else if (y.is<std::string>()) values.y = SerialGui::toDouble(y.as<std::string>());
return Any::from<glm::vec2>(values);
}
else if (table.size() == 4) {
auto x = table.get<sol::object>(1);
auto y = table.get<sol::object>(2);
auto z = table.get<sol::object>(3);
auto w = table.get<sol::object>(4);
glm::vec4 values = {};
if (x.is<float>()) values.x = x.as<float>();
else if (x.is<std::string>()) values.x = SerialGui::toDouble(x.as<std::string>());
if (y.is<float>()) values.y = y.as<float>();
else if (y.is<std::string>()) values.y = SerialGui::toDouble(y.as<std::string>());
if (z.is<float>()) values.z = z.as<float>();
else if (z.is<std::string>()) values.z = SerialGui::toDouble(z.as<std::string>());
if (w.is<float>()) values.w = w.as<float>();
else if (w.is<std::string>()) values.w = SerialGui::toDouble(w.as<std::string>());
return Any::from<glm::vec4>(values);
}
}
}

View File

@ -0,0 +1,68 @@
//
// Created by aurailus on 2020-04-12.
//
#pragma once
#include <list>
#include <sol2/sol.hpp>
#include "../../../util/Any.h"
class LuaGuiElement {
public:
LuaGuiElement(const std::string& type, sol::table data);
// 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 call(sol::this_state s, sol::function fun);
sol::object find(sol::this_state s, const std::string& key);
void append(sol::this_state s, sol::object elem);
void prepend(sol::this_state s, sol::object elem);
void remove(sol::optional<LuaGuiElement> elem);
std::string type {}, key {};
LuaGuiElement* parent = nullptr;
std::list<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 noexcept;
template <typename T> const T& get(const std::string& key) const {
Any a = getAsAny(key);
return a.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>();
}
};
namespace ClientApi {
static void gui_element(sol::state& lua) {
lua.new_usertype<LuaGuiElement>("GuiElement",
sol::constructors<LuaGuiElement(std::string, sol::object)>(),
sol::meta_function::index, &LuaGuiElement::get_trait,
sol::meta_function::new_index, &LuaGuiElement::set_trait,
sol::meta_function::call, &LuaGuiElement::call,
"find", &LuaGuiElement::find,
"append", &LuaGuiElement::append,
"prepend", &LuaGuiElement::prepend,
"remove", &LuaGuiElement::remove
);
}
}

View File

@ -5,12 +5,12 @@
#pragma once
#include <sol2/sol.hpp>
#include "../class/LocalGuiElement.h"
#include "../class/LuaGuiElement.h"
#include "../../../game/hud/GuiBuilder.h"
namespace MenuApi {
void set_gui(GuiBuilder& builder, glm::ivec2& win, sol::state& lua, sol::table& core) {
core.set_function("set_gui", [&](sol::this_state s, LocalGuiElement& gui) {
core.set_function("set_gui", [&](sol::this_state s, LuaGuiElement& gui) {
builder.setGuiRoot(sol::state_view(s), gui);
builder.build(win);
});

View File

@ -1,26 +0,0 @@
//
// Created by aurailus on 2020-04-12.
//
#pragma once
#include <sol2/sol.hpp>
#include "../class/LocalGuiElement.h"
namespace ClientApi {
static void gui_element(sol::state& lua) {
lua.new_usertype<LocalGuiElement>("GuiElement",
sol::constructors<LocalGuiElement(std::string, sol::object)>(),
sol::meta_function::index, &LocalGuiElement::get,
sol::meta_function::new_index, &LocalGuiElement::set,
sol::meta_function::call, &LocalGuiElement::call,
"find", &LocalGuiElement::find,
"append", &LocalGuiElement::append,
"prepend", &LocalGuiElement::prepend,
"remove", &LocalGuiElement::remove
);
}
}

View File

@ -11,7 +11,7 @@
#include "LocalLuaParser.h"
// Usertypes
#include "../api/usertype/cGuiElement.h"
#include "../api/class/LuaGuiElement.h"
#include "../api/usertype/cItemStack.h"
#include "../api/usertype/cLocalPlayer.h"
#include "../api/usertype/cLuaEntity.h"

View File

@ -44,4 +44,14 @@ menu:append(function()
}
end)
zepha.set_gui(menu)
zepha.set_gui(menu)
zepha.delay(function()
menu(function()
menu:append(Gui.Rect {
position = {0, 0},
size = {32, 32},
background = "#f00"
})
end)
end, 5)