Lua parsing of Gui Elements!!!
parent
22bc36c9f2
commit
5bf82c4963
|
@ -5,31 +5,24 @@ setmetatable(env, {__index = _G})
|
||||||
-- create_element
|
-- create_element
|
||||||
-- Build a GUI Element with the provided constructor data, apply the metatable.
|
-- Build a GUI Element with the provided constructor data, apply the metatable.
|
||||||
local function create_element(elem_type, data)
|
local function create_element(elem_type, data)
|
||||||
local elem = GuiElement.new(elem_type, data)
|
return GuiElement.new(elem_type, data)
|
||||||
return elem
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- register_element
|
-- register_element
|
||||||
-- Add an element to the Gui namespace.
|
-- Add an element to the Gui namespace.
|
||||||
local function register_element(key)
|
local function register_element(key)
|
||||||
if type(key) == "table" then
|
if type(key) == "table" then
|
||||||
for _,v in pairs(key) do register_element(v) end
|
for _, v in pairs(key) do register_element(v) end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
env.Gui[key] = function(data) return create_element(key, data) end
|
env.Gui[key] = function(data) return create_element(key, data) end
|
||||||
end
|
end
|
||||||
|
|
||||||
register_element({"Body", "Rect", "Text", "Model", "Button", "InventoryList"})
|
register_element({ "Box", "Text" })
|
||||||
|
|
||||||
-- pc
|
|
||||||
-- Formats a number to be a percent string.
|
|
||||||
env.pc = function(num)
|
|
||||||
return tostring(num) .. "%"
|
|
||||||
end
|
|
||||||
|
|
||||||
-- zepha.build_gui
|
-- zepha.build_gui
|
||||||
-- Allows you to Build UI Elements with the GUI namespace outside of a callback.
|
-- Allows you to Build UI Elements with the GUI namespace outside of a callback.
|
||||||
zepha.build_gui = function(fn)
|
zepha.gui = function(fn)
|
||||||
setfenv(fn, env)
|
setfenv(fn, env)
|
||||||
return fn()
|
return fn()
|
||||||
end
|
end
|
Binary file not shown.
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
|
@ -331,6 +331,6 @@ add_library(Zepha_Core
|
||||||
client/gui/compound/GuiCellGraph.cpp
|
client/gui/compound/GuiCellGraph.cpp
|
||||||
client/gui/compound/GuiCellGraph.h
|
client/gui/compound/GuiCellGraph.h
|
||||||
client/gui/basic/GuiCells.cpp
|
client/gui/basic/GuiCells.cpp
|
||||||
client/gui/basic/GuiCells.h client/gui/Gui.h client/gui/Root.cpp client/gui/Root.h client/gui/BoxElement.cpp client/gui/BoxElement.h client/gui/Gui.cpp client/gui/Style.h client/gui/TextElement.cpp client/gui/TextElement.h client/gui/Expression.cpp client/gui/Expression.h)
|
client/gui/basic/GuiCells.h client/gui/Gui.h client/gui/Root.cpp client/gui/Root.h client/gui/BoxElement.cpp client/gui/BoxElement.h client/gui/Gui.cpp client/gui/Style.h client/gui/TextElement.cpp client/gui/TextElement.h client/gui/Expression.cpp client/gui/Expression.h client/gui/Style.cpp)
|
||||||
|
|
||||||
target_include_directories(Zepha_Core PUBLIC .)
|
target_include_directories(Zepha_Core PUBLIC .)
|
|
@ -16,9 +16,9 @@ Font::Font(TextureAtlas& atlas, std::shared_ptr<AtlasRef> tex) :
|
||||||
getCharWidths(atlas);
|
getCharWidths(atlas);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Font::getCharWidth(char c) {
|
u16 Font::getCharWidth(char c) {
|
||||||
unsigned int index = static_cast<unsigned int>(c) - 32;
|
unsigned int index = static_cast<unsigned int>(c) - 32;
|
||||||
if (index >= amountOfChars) throw std::runtime_error("Invalid char index.");
|
if (index >= C_COUNT) return charWidths[C_COUNT];
|
||||||
return charWidths[index];
|
return charWidths[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,44 +27,44 @@ void Font::getCharWidths(TextureAtlas& atlas) {
|
||||||
|
|
||||||
charWidths[0] = 2;
|
charWidths[0] = 2;
|
||||||
|
|
||||||
for (unsigned int i = 1; i < amountOfChars; i++) {
|
for (u16 i = 1; i < C_COUNT + 1; i++) {
|
||||||
glm::vec2 charPos = { i % 18 * charWidth, std::floor(i / 18) * charHeight };
|
glm::vec2 charPos = { i % 18 * C_WIDTH, std::floor(i / 18) * C_HEIGHT };
|
||||||
|
|
||||||
unsigned int xBase = static_cast<unsigned int>(fontTex->pos.x) + static_cast<unsigned int>(charPos.x);
|
u32 xBase = static_cast<u32>(fontTex->pos.x) + static_cast<u32>(charPos.x);
|
||||||
unsigned int yBase = static_cast<unsigned int>(fontTex->pos.y) + static_cast<unsigned int>(charPos.y);
|
u32 yBase = static_cast<u32>(fontTex->pos.y) + static_cast<u32>(charPos.y);
|
||||||
|
|
||||||
unsigned short width = 0;
|
u16 width = 0;
|
||||||
|
|
||||||
for (unsigned int j = 0; j < charWidth; j++) {
|
for (u16 j = 0; j < C_WIDTH; j++) {
|
||||||
bool empty = true;
|
bool empty = true;
|
||||||
for (unsigned int k = 0; k < charHeight; k++) {
|
for (u16 k = 0; k < C_HEIGHT; k++) {
|
||||||
unsigned int xx = xBase + j;
|
u32 xx = xBase + j;
|
||||||
unsigned int yy = yBase + k;
|
u32 yy = yBase + k;
|
||||||
|
|
||||||
unsigned int offset = yy * static_cast<unsigned int>(atlasSize.x) * 4 + xx * 4 + 3;
|
u32 offset = yy * static_cast<u32>(atlasSize.x) * 4 + xx * 4 + 3;
|
||||||
|
|
||||||
if (data[offset] != 0) {
|
if (data[offset] != 0) {
|
||||||
empty = false;
|
empty = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!empty) width = static_cast<unsigned short>(j);
|
if (!empty) width = static_cast<u16>(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
charWidths[i] = width;
|
charWidths[i] = width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec4 Font::getCharUVs(char c) {
|
vec4 Font::getCharUVs(char c) {
|
||||||
unsigned int index = static_cast<unsigned int>(c) - 32;
|
u16 index = static_cast<u16>(c) - 32;
|
||||||
if (index >= amountOfChars) throw std::runtime_error("Invalid char index.");
|
if (index >= C_COUNT) index = C_COUNT;
|
||||||
|
|
||||||
glm::vec2 charPos = { (index % 18) * charWidth, std::floor(index / 18) * charHeight };
|
vec2 charPos = { (index % 18) * C_WIDTH, std::floor(index / 18) * C_HEIGHT };
|
||||||
glm::vec4 uv = {
|
vec4 uv = {
|
||||||
fontTex->uv.x + (charPos.x) / atlasSize.x,
|
fontTex->uv.x + (charPos.x) / atlasSize.x,
|
||||||
fontTex->uv.y + (charPos.y) / atlasSize.y,
|
fontTex->uv.y + (charPos.y) / atlasSize.y,
|
||||||
fontTex->uv.x + (charPos.x + getCharWidth(c) + 1) / atlasSize.x,
|
fontTex->uv.x + (charPos.x + getCharWidth(c) + 1) / atlasSize.x,
|
||||||
fontTex->uv.y + (charPos.y + charHeight) / atlasSize.y
|
fontTex->uv.y + (charPos.y + C_HEIGHT) / atlasSize.y
|
||||||
};
|
};
|
||||||
|
|
||||||
return uv;
|
return uv;
|
||||||
|
|
|
@ -1,35 +1,29 @@
|
||||||
//
|
|
||||||
// Created by aurailus on 13/08/19.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include "util/Types.h"
|
||||||
#include <glm/vec2.hpp>
|
|
||||||
#include <glm/vec4.hpp>
|
|
||||||
|
|
||||||
class AtlasRef;
|
class AtlasRef;
|
||||||
|
|
||||||
class TextureAtlas;
|
class TextureAtlas;
|
||||||
|
|
||||||
class Font {
|
class Font {
|
||||||
public:
|
public:
|
||||||
Font() = default;
|
Font() = default;
|
||||||
|
|
||||||
Font(TextureAtlas& atlas, std::shared_ptr<AtlasRef> tex);
|
Font(TextureAtlas& atlas, std::shared_ptr<AtlasRef> tex);
|
||||||
|
|
||||||
unsigned int getCharWidth(char c);
|
u16 getCharWidth(char c);
|
||||||
|
|
||||||
glm::vec4 getCharUVs(char c);
|
vec4 getCharUVs(char c);
|
||||||
|
|
||||||
const static unsigned int amountOfChars = 95;
|
constexpr static u16 C_COUNT = 95;
|
||||||
const static unsigned int charWidth = 7;
|
constexpr static u16 C_WIDTH = 7;
|
||||||
const static unsigned int charHeight = 9;
|
constexpr static u16 C_HEIGHT = 9;
|
||||||
private:
|
|
||||||
|
private:
|
||||||
void getCharWidths(TextureAtlas& atlas);
|
void getCharWidths(TextureAtlas& atlas);
|
||||||
|
|
||||||
glm::vec2 atlasSize{};
|
vec2 atlasSize {};
|
||||||
|
|
||||||
std::shared_ptr<AtlasRef> fontTex = nullptr;
|
sptr<AtlasRef> fontTex = nullptr;
|
||||||
std::array<unsigned short, 95> charWidths{};
|
array<u16, C_COUNT + 1> charWidths {};
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,6 +24,10 @@ ivec2 Gui::Element::getComputedSize() {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Gui::Element::clear() {
|
||||||
|
children.clear();
|
||||||
|
}
|
||||||
|
|
||||||
ivec2 Gui::Element::getComputedOuterSize() {
|
ivec2 Gui::Element::getComputedOuterSize() {
|
||||||
let size = getComputedSize();
|
let size = getComputedSize();
|
||||||
let margin = getStyle<ivec4, ValueType::LENGTH>(StyleRule::MARGIN, {});
|
let margin = getStyle<ivec4, ValueType::LENGTH>(StyleRule::MARGIN, {});
|
||||||
|
@ -195,4 +199,4 @@ void Gui::Element::layoutChildren() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,8 @@ namespace Gui {
|
||||||
return elem;
|
return elem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
/** Returns the element's computed size. */
|
/** Returns the element's computed size. */
|
||||||
virtual ivec2 getComputedSize();
|
virtual ivec2 getComputedSize();
|
||||||
|
|
||||||
|
@ -104,6 +106,7 @@ namespace Gui {
|
||||||
for (const let& ss : stylesheets) {
|
for (const let& ss : stylesheets) {
|
||||||
for (const string& className : props.classes) {
|
for (const string& className : props.classes) {
|
||||||
const let& styles = ss.find(className);
|
const let& styles = ss.find(className);
|
||||||
|
if (styles == ss.end()) continue;
|
||||||
const optional<any> opt = styles->second.get(rule);
|
const optional<any> opt = styles->second.get(rule);
|
||||||
if (opt) return *opt;
|
if (opt) return *opt;
|
||||||
}
|
}
|
||||||
|
@ -119,6 +122,7 @@ namespace Gui {
|
||||||
for (const let& ss : stylesheets) {
|
for (const let& ss : stylesheets) {
|
||||||
for (const string& className : props.classes) {
|
for (const string& className : props.classes) {
|
||||||
const let& styles = ss.find(className);
|
const let& styles = ss.find(className);
|
||||||
|
if (styles == ss.end()) continue;
|
||||||
const optional<V> opt = styles->second.get<V, T>(rule);
|
const optional<V> opt = styles->second.get<V, T>(rule);
|
||||||
if (opt) return *opt;
|
if (opt) return *opt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "client/gui/Gui.h"
|
#include "client/gui/Gui.h"
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include "Style.h"
|
||||||
|
|
||||||
|
const std::unordered_map<string, Gui::StyleRule> Gui::Style::RULE_STRINGS_TO_ENUMS = {
|
||||||
|
{ "pos", StyleRule::POS },
|
||||||
|
{ "size", StyleRule::SIZE },
|
||||||
|
{ "margin", StyleRule::MARGIN },
|
||||||
|
{ "padding", StyleRule::PADDING },
|
||||||
|
{ "GAP", StyleRule::GAP },
|
||||||
|
{ "layout", StyleRule::LAYOUT },
|
||||||
|
{ "direction", StyleRule::DIRECTION },
|
||||||
|
{ "h_align", StyleRule::H_ALIGN },
|
||||||
|
{ "v_align", StyleRule::V_ALIGN },
|
||||||
|
{ "cursor", StyleRule::CURSOR },
|
||||||
|
{ "overflow", StyleRule::OVERFLOW },
|
||||||
|
{ "background", StyleRule::BACKGROUND },
|
||||||
|
{ "background_hover", StyleRule::BACKGROUND_HOVER },
|
||||||
|
{ "content", StyleRule::CONTENT },
|
||||||
|
{ "text_size", StyleRule::TEXT_SIZE },
|
||||||
|
{ "text_color", StyleRule::TEXT_COLOR }
|
||||||
|
};
|
|
@ -22,7 +22,9 @@ namespace Gui {
|
||||||
BACKGROUND,
|
BACKGROUND,
|
||||||
BACKGROUND_HOVER,
|
BACKGROUND_HOVER,
|
||||||
|
|
||||||
CONTENT
|
CONTENT,
|
||||||
|
TEXT_SIZE,
|
||||||
|
TEXT_COLOR
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ValueType {
|
enum class ValueType {
|
||||||
|
@ -180,6 +182,8 @@ namespace Gui {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<StyleRule, any> rules {};
|
std::unordered_map<StyleRule, any> rules {};
|
||||||
|
|
||||||
|
const static std::unordered_map<string, StyleRule> RULE_STRINGS_TO_ENUMS;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::unordered_map<string, Style> StyleSheet;
|
typedef std::unordered_map<string, Style> StyleSheet;
|
||||||
|
|
|
@ -36,7 +36,7 @@ void Gui::TextElement::updateElement() {
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 offset = {};
|
vec3 offset = {};
|
||||||
u32 h = Font::charHeight;
|
u32 h = Font::C_HEIGHT;
|
||||||
|
|
||||||
bool bold = false;
|
bool bold = false;
|
||||||
bool italic = false;
|
bool italic = false;
|
||||||
|
@ -192,9 +192,12 @@ void Gui::TextElement::updateElement() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entity.setScale(PX_SCALE * (2/3.f));
|
let scale = getStyle<f32, ValueType::LENGTH>(StyleRule::TEXT_SIZE, 3.f);
|
||||||
// entity.setScale(vec3(getComputedSize() * static_cast<i32>(PX_SCALE), 0));
|
let margin = getStyle<ivec4, ValueType::LENGTH>(StyleRule::MARGIN, {});
|
||||||
entity.setPos(vec3(getComputedScreenPos() * static_cast<i32>(PX_SCALE), 0));
|
|
||||||
|
entity.setScale(vec3(scale, scale, 0));
|
||||||
|
entity.setPos(vec3(getComputedScreenPos() + ivec2 { margin.x, margin.y }, 0));
|
||||||
|
|
||||||
Element::updateElement();
|
Element::updateElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cute_files/cute_files.h>
|
#include <cute_files/cute_files.h>
|
||||||
|
#include <client/gui/TextElement.h>
|
||||||
|
|
||||||
#include "MenuSandbox.h"
|
#include "MenuSandbox.h"
|
||||||
|
|
||||||
|
@ -9,29 +9,25 @@
|
||||||
#include "client/Client.h"
|
#include "client/Client.h"
|
||||||
#include "lua/ErrorFormatter.h"
|
#include "lua/ErrorFormatter.h"
|
||||||
#include "client/menu/SubgameDef.h"
|
#include "client/menu/SubgameDef.h"
|
||||||
#include "client/gui/basic/GuiText.h"
|
|
||||||
#include "client/gui/basic/GuiContainer.h"
|
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
#include "lua/modules/Time.h"
|
#include "lua/modules/Time.h"
|
||||||
#include "lua/modules/mSetGui.h"
|
#include "lua/modules/mSetGui.h"
|
||||||
#include "lua/modules/mStartGame.h"
|
#include "lua/modules/mStartGame.h"
|
||||||
|
#include "lua/usertype/LuaGuiElement.h"
|
||||||
|
|
||||||
MenuSandbox::MenuSandbox(glm::ivec2& win, Client& client, std::shared_ptr<GuiContainer> container) :
|
MenuSandbox::MenuSandbox(Client& client, Gui::Root& root, sptr<Gui::Element> sandboxRoot) :
|
||||||
LuaParser(*client.game),
|
LuaParser(*client.game),
|
||||||
win(win),
|
client(client),
|
||||||
client(client)
|
root(root),
|
||||||
// container(container),
|
sandboxRoot(sandboxRoot) {}
|
||||||
// luaContainer(std::dynamic_pointer_cast<GuiContainer>(container->add(std::make_shared<GuiContainer>("__lua"))))
|
|
||||||
// builder(client.game->textures, client.game->models, luaContainer) {}
|
|
||||||
{}
|
|
||||||
|
|
||||||
void MenuSandbox::reset() {
|
void MenuSandbox::reset() {
|
||||||
// container->remove("error");
|
// container->remove("error");
|
||||||
// builder.clear(true);
|
sandboxRoot->clear();
|
||||||
core = {};
|
core = {};
|
||||||
mod = {};
|
mod = {};
|
||||||
lua = sol::state{};
|
lua = sol::state {};
|
||||||
lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::math, sol::lib::table, sol::lib::debug);
|
lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::math, sol::lib::table, sol::lib::debug);
|
||||||
|
|
||||||
loadApi();
|
loadApi();
|
||||||
|
@ -46,9 +42,10 @@ void MenuSandbox::loadApi() {
|
||||||
|
|
||||||
modules.emplace_back(std::make_unique<Api::Module::Time>(Api::State::CLIENT, lua, core));
|
modules.emplace_back(std::make_unique<Api::Module::Time>(Api::State::CLIENT, lua, core));
|
||||||
|
|
||||||
|
Api::Usertype::GuiElement::bind(lua, core, root);
|
||||||
// ClientApi::gui_element(lua);
|
// ClientApi::gui_element(lua);
|
||||||
|
|
||||||
// MenuApi::set_gui(builder, win, lua, core);
|
MenuApi::set_gui(lua, core, sandboxRoot);
|
||||||
MenuApi::start_game(client, core);
|
MenuApi::start_game(client, core);
|
||||||
|
|
||||||
bindModules();
|
bindModules();
|
||||||
|
@ -60,14 +57,15 @@ void MenuSandbox::loadApi() {
|
||||||
|
|
||||||
void MenuSandbox::load(const SubgameDef& subgame) {
|
void MenuSandbox::load(const SubgameDef& subgame) {
|
||||||
reset();
|
reset();
|
||||||
|
subgameName = subgame.config.name;
|
||||||
|
|
||||||
try {
|
// try {
|
||||||
loadAndRunMod(subgame.subgamePath + "/../../assets/base");
|
loadAndRunMod(subgame.subgamePath + "/../../assets/base");
|
||||||
loadAndRunMod(subgame.subgamePath + "/menu");
|
loadAndRunMod(subgame.subgamePath + "/menu");
|
||||||
}
|
// }
|
||||||
catch (const std::runtime_error& e) {
|
// catch (const std::runtime_error& e) {
|
||||||
showError(e.what(), subgame.config.name);
|
// showError(e.what(), subgame.config.name);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuSandbox::windowResized() {
|
void MenuSandbox::windowResized() {
|
||||||
|
@ -79,7 +77,7 @@ void MenuSandbox::update(double delta) {
|
||||||
core["__builtin"]["update_delayed_functions"]();
|
core["__builtin"]["update_delayed_functions"]();
|
||||||
}
|
}
|
||||||
|
|
||||||
sol::protected_function_result MenuSandbox::runFileSandboxed(const std::string& file) {
|
sol::protected_function_result MenuSandbox::runFileSandboxed(const string& file) {
|
||||||
for (LuaMod::File& f : mod.files) {
|
for (LuaMod::File& f : mod.files) {
|
||||||
if (f.path != file) continue;
|
if (f.path != file) continue;
|
||||||
|
|
||||||
|
@ -94,18 +92,18 @@ sol::protected_function_result MenuSandbox::runFileSandboxed(const std::string&
|
||||||
throw std::runtime_error("Error opening '" + file + "', file not found.");
|
throw std::runtime_error("Error opening '" + file + "', file not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuSandbox::loadAndRunMod(const std::string& modPath) {
|
void MenuSandbox::loadAndRunMod(const string& modPath) {
|
||||||
if (!cf_file_exists(modPath.data())) throw std::runtime_error("Directory not found.");
|
if (!cf_file_exists(modPath.data())) throw std::runtime_error("Directory not found.");
|
||||||
|
|
||||||
LuaMod mod;
|
LuaMod mod;
|
||||||
std::string root = modPath + "/script";
|
string root = modPath + "/script";
|
||||||
|
|
||||||
std::list<std::string> dirsToScan{ root };
|
std::list<string> dirsToScan{ root };
|
||||||
std::list<std::string> luaFiles{};
|
std::list<string> luaFiles{};
|
||||||
|
|
||||||
cf_dir_t dir;
|
cf_dir_t dir;
|
||||||
while (!dirsToScan.empty()) {
|
while (!dirsToScan.empty()) {
|
||||||
std::string dirStr = *dirsToScan.begin();
|
string dirStr = *dirsToScan.begin();
|
||||||
dirsToScan.erase(dirsToScan.begin());
|
dirsToScan.erase(dirsToScan.begin());
|
||||||
|
|
||||||
if (!cf_file_exists(dirStr.data())) throw std::runtime_error("Missing 'script' directory.");
|
if (!cf_file_exists(dirStr.data())) throw std::runtime_error("Missing 'script' directory.");
|
||||||
|
@ -131,9 +129,9 @@ void MenuSandbox::loadAndRunMod(const std::string& modPath) {
|
||||||
|
|
||||||
mod.modPath = modPath;
|
mod.modPath = modPath;
|
||||||
|
|
||||||
for (std::string& file : luaFiles) {
|
for (string& file : luaFiles) {
|
||||||
size_t rootPos = file.find(root);
|
size_t rootPos = file.find(root);
|
||||||
std::string modPath = file;
|
string modPath = file;
|
||||||
|
|
||||||
if (rootPos == std::string::npos)
|
if (rootPos == std::string::npos)
|
||||||
throw std::runtime_error("Attempted to access file \"" + file + "\", which is outside of the mod root.");
|
throw std::runtime_error("Attempted to access file \"" + file + "\", which is outside of the mod root.");
|
||||||
|
@ -142,66 +140,67 @@ void MenuSandbox::loadAndRunMod(const std::string& modPath) {
|
||||||
modPath.resize(modPath.size() - 4);
|
modPath.resize(modPath.size() - 4);
|
||||||
|
|
||||||
std::ifstream t(file);
|
std::ifstream t(file);
|
||||||
std::string fileStr((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
|
string fileStr((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
|
||||||
|
|
||||||
LuaMod::File f{ modPath, fileStr };
|
LuaMod::File f { modPath, fileStr };
|
||||||
mod.files.push_back(f);
|
mod.files.push_back(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string texPath = modPath + "/textures";
|
string texPath = modPath + "/textures";
|
||||||
if (cf_file_exists(texPath.data())) {
|
if (cf_file_exists(texPath.data()))
|
||||||
this->modAssets = client.game->textures.loadDirectory(texPath, false, true);
|
menuAssets = client.game->textures.loadDirectory(texPath, false, true);
|
||||||
}
|
|
||||||
|
|
||||||
this->mod = mod;
|
this->mod = mod;
|
||||||
runFileSandboxed("init");
|
runFileSandboxed("init");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuSandbox::showError(const std::string& what, const std::string& subgame) {
|
void MenuSandbox::showError(const string& err) {
|
||||||
const std::string errPrefixText = "Encountered an error while loading the menu for " + subgame + " ;-;";
|
const string errPrefixText = "`cfEncountered an error while loading the menu for '" + subgameName + "' ;-;\n\n`r";
|
||||||
// Font f(client.game->textures, client.game->textures["font"]);
|
|
||||||
|
using Expr = Gui::Expression;
|
||||||
// auto errWrap = std::make_shared<GuiContainer>("error");
|
sandboxRoot->append<Gui::TextElement>({
|
||||||
// container->add(errWrap);
|
.styles = {{
|
||||||
|
{ Gui::StyleRule::CONTENT, errPrefixText + err },
|
||||||
// auto errPrefix = std::make_shared<GuiText>("error_text");
|
{ Gui::StyleRule::TEXT_SIZE, Expr("2px") },
|
||||||
// errPrefix->create({ 3, 3 }, {}, { 0.7, 0, 0.3, 1 }, { 1, 1, 1, 1 }, f);
|
{ Gui::StyleRule::SIZE, array<Expr, 2> { Expr("100dp"), Expr("-1") } },
|
||||||
// errPrefix->setText(errPrefixText);
|
{ Gui::StyleRule::MARGIN, array<Expr, 4> { Expr("4dp"), Expr("4dp"), Expr("4dp"), Expr("4dp") } }
|
||||||
// errPrefix->setPos({ 8, 16 });
|
}}
|
||||||
// errWrap->add(errPrefix);
|
});
|
||||||
|
|
||||||
// auto errMsg = std::make_shared<GuiText>("error_text");
|
|
||||||
// errMsg->create({ 3, 3 }, {}, {}, { 1, 0.5, 0.6, 1 }, f);
|
|
||||||
// errMsg->setText(what);
|
|
||||||
// errMsg->setPos({ 8, 52 });
|
|
||||||
// errWrap->add(errMsg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sol::protected_function_result MenuSandbox::errorCallback(sol::protected_function_result r) const {
|
sol::protected_function_result MenuSandbox::errorCallback(sol::protected_function_result r) {
|
||||||
sol::error err = r;
|
string err = static_cast<sol::error>(r).what();
|
||||||
std::string errString = err.what();
|
|
||||||
|
|
||||||
try {
|
std::cout << Log::err << err << Log::endl;
|
||||||
std::string::size_type lineNumStart = errString.find(':');
|
|
||||||
if (lineNumStart == std::string::npos) throw std::out_of_range("Improperly formatted error. [0]");
|
vec<string> lines;
|
||||||
std::string::size_type lineNumEnd = errString.find(':', lineNumStart + 1);
|
{
|
||||||
if (lineNumEnd == std::string::npos) throw std::out_of_range("Improperly formatted error. [1]");
|
string line;
|
||||||
|
std::stringstream textStream(err);
|
||||||
std::string fileName = errString.substr(0, lineNumStart);
|
while (std::getline(textStream, line, '\n')) lines.emplace_back(line);
|
||||||
int lineNum = std::stoi(errString.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1));
|
|
||||||
|
|
||||||
for (const LuaMod::File& file : mod.files)
|
|
||||||
if (file.path == fileName)
|
|
||||||
throw std::runtime_error(ErrorFormatter::formatError(fileName, lineNum, errString, file.file));
|
|
||||||
|
|
||||||
throw std::out_of_range("Error thrown outside of handled files. [2]");
|
|
||||||
}
|
}
|
||||||
catch (const std::runtime_error& e) {
|
|
||||||
std::cout << Log::err << e.what() << std::endl;
|
for (const let& line : lines) {
|
||||||
throw;
|
usize lineNumStart = line.find(':');
|
||||||
}
|
if (lineNumStart == string::npos) continue;
|
||||||
catch (const std::out_of_range& e) {
|
usize lineNumEnd = line.find(':', lineNumStart + 1);
|
||||||
std::cout << Log::err << "Failed to format error, " << e.what() << Log::endl;
|
if (lineNumEnd == string::npos) continue;
|
||||||
throw std::runtime_error(errString);
|
|
||||||
|
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) {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include "lua/LuaParser.h"
|
#include "lua/LuaParser.h"
|
||||||
|
|
||||||
#include "lua/LuaMod.h"
|
#include "lua/LuaMod.h"
|
||||||
|
#include "client/gui/Root.h"
|
||||||
|
#include "client/gui/Element.h"
|
||||||
#include "client/gui/GuiBuilder.h"
|
#include "client/gui/GuiBuilder.h"
|
||||||
|
|
||||||
class Client;
|
class Client;
|
||||||
|
@ -16,8 +18,8 @@ class SubgameDef;
|
||||||
class GuiContainer;
|
class GuiContainer;
|
||||||
|
|
||||||
class MenuSandbox : LuaParser {
|
class MenuSandbox : LuaParser {
|
||||||
public:
|
public:
|
||||||
MenuSandbox(glm::ivec2& window, Client& client, std::shared_ptr<GuiContainer> container);
|
MenuSandbox(Client& client, Gui::Root& root, sptr<Gui::Element> sandboxRoot);
|
||||||
|
|
||||||
void load(const SubgameDef& subgame);
|
void load(const SubgameDef& subgame);
|
||||||
|
|
||||||
|
@ -26,28 +28,27 @@ class MenuSandbox : LuaParser {
|
||||||
void windowResized();
|
void windowResized();
|
||||||
|
|
||||||
using LuaParser::update;
|
using LuaParser::update;
|
||||||
private:
|
|
||||||
|
private:
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
void loadApi();
|
void loadApi();
|
||||||
|
|
||||||
void loadAndRunMod(const std::string& modPath);
|
void loadAndRunMod(const string& modPath);
|
||||||
|
|
||||||
void showError(const std::string& what, const std::string& subgame);
|
void showError(const string& err);
|
||||||
|
|
||||||
sol::protected_function_result runFileSandboxed(const std::string& file);
|
sol::protected_function_result runFileSandboxed(const string& file);
|
||||||
|
|
||||||
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) const override;
|
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) override;
|
||||||
|
|
||||||
LuaMod mod {};
|
LuaMod mod {};
|
||||||
std::vector<std::shared_ptr<AtlasRef>> modAssets{};
|
string subgameName;
|
||||||
|
|
||||||
// GuiRoot gui;
|
|
||||||
|
|
||||||
// std::shared_ptr<GuiContainer> container = nullptr;
|
|
||||||
// std::shared_ptr<GuiContainer> luaContainer = nullptr;
|
|
||||||
// GuiBuilder builder;
|
|
||||||
|
|
||||||
Client& client;
|
Client& client;
|
||||||
glm::ivec2& win;
|
|
||||||
|
Gui::Root& root;
|
||||||
|
sptr<Gui::Element> sandboxRoot;
|
||||||
|
vec<sptr<AtlasRef>> menuAssets {};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,36 +17,34 @@
|
||||||
#include "client/gui/compound/GuiImageButton.h"
|
#include "client/gui/compound/GuiImageButton.h"
|
||||||
|
|
||||||
MainMenuScene::MainMenuScene(Client& client) : Scene(client),
|
MainMenuScene::MainMenuScene(Client& client) : Scene(client),
|
||||||
root(client.renderer.window, client.game->textures) {
|
root(client.renderer.window, client.game->textures),
|
||||||
|
sandboxElem(root.create<Gui::BoxElement>({ .classes = { "sandbox" }})),
|
||||||
|
sandbox(client, root, sandboxElem) {
|
||||||
|
|
||||||
client.renderer.setClearColor(0, 0, 0);
|
client.renderer.setClearColor(0, 0, 0);
|
||||||
client.renderer.window.input.setMouseLocked(false);
|
client.renderer.window.input.setMouseLocked(false);
|
||||||
|
|
||||||
root.body->setStyle(Gui::StyleRule::BACKGROUND, string("#123"));
|
using Expr = Gui::Expression;
|
||||||
|
|
||||||
root.addStylesheet({
|
root.addStylesheet({
|
||||||
{ "sandbox", {{
|
|
||||||
{ Gui::StyleRule::H_ALIGN, string("center") },
|
|
||||||
{ Gui::StyleRule::V_ALIGN, string("center") }
|
|
||||||
}}},
|
|
||||||
{ "navigation", {{
|
{ "navigation", {{
|
||||||
{ Gui::StyleRule::SIZE, array<Gui::Expression, 2> { Gui::Expression("-1"), Gui::Expression("18dp") } }
|
{ Gui::StyleRule::SIZE, array<Expr, 2> { Expr("-1"), Expr("18dp") } }
|
||||||
}}},
|
}}},
|
||||||
{ "navigationWrap", {{
|
{ "navigationWrap", {{
|
||||||
{ Gui::StyleRule::DIRECTION, string("row") },
|
{ Gui::StyleRule::DIRECTION, string("row") },
|
||||||
{ Gui::StyleRule::POS, array<Gui::Expression, 2> { Gui::Expression("0"), Gui::Expression("0") } }
|
{ Gui::StyleRule::POS, array<Expr, 2> { Expr("0"), Expr("0") } }
|
||||||
}}},
|
}}},
|
||||||
{ "navigationBackground", {{
|
{ "navigationBackground", {{
|
||||||
{ Gui::StyleRule::SIZE, array<Gui::Expression, 2> { Gui::Expression("64dp"), Gui::Expression("18dp") } },
|
{ Gui::StyleRule::SIZE, array<Expr, 2> { Expr("64dp"), Expr("18dp") } },
|
||||||
{ Gui::StyleRule::BACKGROUND, string("menu_bar_bg") }
|
{ Gui::StyleRule::BACKGROUND, string("menu_bar_bg") }
|
||||||
}}},
|
}}},
|
||||||
{ "navigationButton", {{
|
{ "navigationButton", {{
|
||||||
{ Gui::StyleRule::SIZE, array<Gui::Expression, 2> { Gui::Expression("16dp"), Gui::Expression("16dp") } },
|
{ Gui::StyleRule::SIZE, array<Expr, 2> { Expr("16dp"), Expr("16dp") } },
|
||||||
{ Gui::StyleRule::CURSOR, string("pointer") }
|
{ Gui::StyleRule::CURSOR, string("pointer") }
|
||||||
}}}
|
}}}
|
||||||
});
|
});
|
||||||
|
|
||||||
let sandbox = root.body->append<Gui::BoxElement>({ .classes = { "sandbox" } });
|
root.body->append(sandboxElem);
|
||||||
let navigation = root.body->append<Gui::BoxElement>({ .classes = { "navigation" } });
|
let navigation = root.body->append<Gui::BoxElement>({ .classes = { "navigation" } });
|
||||||
let navigationBG = navigation->append<Gui::BoxElement>({ .classes = { "navigationWrap" } });
|
let navigationBG = navigation->append<Gui::BoxElement>({ .classes = { "navigationWrap" } });
|
||||||
|
|
||||||
|
@ -56,9 +54,8 @@ MainMenuScene::MainMenuScene(Client& client) : Scene(client),
|
||||||
let navigationList = navigation->append<Gui::BoxElement>({
|
let navigationList = navigation->append<Gui::BoxElement>({
|
||||||
.classes = { "navigationWrap" },
|
.classes = { "navigationWrap" },
|
||||||
.styles = {{
|
.styles = {{
|
||||||
{ Gui::StyleRule::PADDING, array<Gui::Expression, 4>
|
{ Gui::StyleRule::PADDING, array<Expr, 4> { Expr("1dp"), Expr("1dp"), Expr("1dp"), Expr("1dp") } },
|
||||||
{ Gui::Expression("1dp"), Gui::Expression("1dp"), Gui::Expression("1dp"), Gui::Expression("1dp") } },
|
{ Gui::StyleRule::GAP, array<Expr, 2> { Expr("1dp"), Expr("1dp") } }
|
||||||
{ Gui::StyleRule::GAP, array<Gui::Expression, 2> { Gui::Expression("1dp"), Gui::Expression("1dp") } }
|
|
||||||
}}
|
}}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -81,9 +78,8 @@ MainMenuScene::MainMenuScene(Client& client) : Scene(client),
|
||||||
navigationList->append<Gui::BoxElement>({
|
navigationList->append<Gui::BoxElement>({
|
||||||
.styles = {{
|
.styles = {{
|
||||||
{ Gui::StyleRule::BACKGROUND, string("#fff5") },
|
{ Gui::StyleRule::BACKGROUND, string("#fff5") },
|
||||||
{ Gui::StyleRule::SIZE, array<Gui::Expression, 2> { Gui::Expression("1dp"), Gui::Expression("10dp") } },
|
{ Gui::StyleRule::SIZE, array<Expr, 2> { Expr("1dp"), Expr("10dp") } },
|
||||||
{ Gui::StyleRule::MARGIN, array<Gui::Expression, 4>
|
{ Gui::StyleRule::MARGIN, array<Expr, 4> { Expr("2dp"), Expr("3dp"), Expr("2dp"), Expr("3dp") } }
|
||||||
{ Gui::Expression("2dp"), Gui::Expression("3dp"), Gui::Expression("2dp"), Gui::Expression("3dp") } }
|
|
||||||
}}
|
}}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -108,7 +104,7 @@ MainMenuScene::MainMenuScene(Client& client) : Scene(client),
|
||||||
|
|
||||||
if (subgames.size() > 0) {
|
if (subgames.size() > 0) {
|
||||||
selectedSubgame = &subgames[0];
|
selectedSubgame = &subgames[0];
|
||||||
// sandbox.load(*selectedSubgame);
|
sandbox.load(*selectedSubgame);
|
||||||
}
|
}
|
||||||
|
|
||||||
navigationList->append<Gui::BoxElement>();
|
navigationList->append<Gui::BoxElement>();
|
||||||
|
|
|
@ -28,11 +28,16 @@ private:
|
||||||
|
|
||||||
/** Find valid subgames in the subgames folder. */
|
/** Find valid subgames in the subgames folder. */
|
||||||
void findSubgames();
|
void findSubgames();
|
||||||
|
|
||||||
|
/** The GUI root. */
|
||||||
|
Gui::Root root;
|
||||||
|
|
||||||
|
/** The GUI sandbox element root. */
|
||||||
|
sptr<Gui::Element> sandboxElem;
|
||||||
|
|
||||||
/** Provides the API for menu mods. */
|
/** Provides the API for menu mods. */
|
||||||
// MenuSandbox sandbox;
|
MenuSandbox sandbox;
|
||||||
Gui::Root root;
|
|
||||||
|
|
||||||
/** A list of found subgames. */
|
/** A list of found subgames. */
|
||||||
vec<SubgameDef> subgames;
|
vec<SubgameDef> subgames;
|
||||||
|
|
||||||
|
|
|
@ -4,23 +4,25 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "ErrorFormatter.h"
|
#include "ErrorFormatter.h"
|
||||||
|
|
||||||
#include "../util/Log.h"
|
std::string ErrorFormatter::formatError(const string& fileName, usize line,
|
||||||
|
const string& stack, string file, bool ansiColors) noexcept {
|
||||||
std::string
|
const string RED = "`cf";
|
||||||
ErrorFormatter::formatError(const string& fileName, usize line, const string& stack, string file,
|
const string LTGRAY = "`c1";
|
||||||
bool ansiColors) noexcept {
|
const string GRAY = "`c2";
|
||||||
const string red = (ansiColors ? Log::red : "");
|
const string BOLD = "`b";
|
||||||
const string unbl = (ansiColors ? Log::unbl : "");
|
const string UNDL = "`u";
|
||||||
const string endl = (ansiColors ? Log::endl : "\n");
|
const string ENDL = "`r\n";
|
||||||
|
|
||||||
std::stringstream out{};
|
std::stringstream out {};
|
||||||
|
|
||||||
// Split the file into lines, and add them to a vector
|
out << BOLD << UNDL << fileName << ".lua" << ENDL << "\n";
|
||||||
vec<string> fileLines{};
|
|
||||||
|
vec<string> fileLines {};
|
||||||
usize pos = 0;
|
usize pos = 0;
|
||||||
string token;
|
string token;
|
||||||
|
|
||||||
|
@ -33,14 +35,28 @@ ErrorFormatter::formatError(const string& fileName, usize line, const string& st
|
||||||
|
|
||||||
while (fileLines.back() == "") fileLines.pop_back();
|
while (fileLines.back() == "") fileLines.pop_back();
|
||||||
|
|
||||||
// Format and add lines to the stringstream
|
usize printStart = (std::max)(0, static_cast<i32>(line - LOOK_AROUND - 1));
|
||||||
for (usize i = (std::max)(static_cast<usize>(0), line - 6); i < (std::min)(fileLines.size(), line + 5); i++) {
|
usize printEnd = (std::min)(fileLines.size(), line + LOOK_AROUND);
|
||||||
for (usize j = 0; j < 3 - std::to_string(i + 1).length(); j++) out << " ";
|
|
||||||
out << red << (i + 1 == line ? unbl : "") << (i + 1) << (i + 1 == line ? " # " : " | ") << fileLines[i] << endl;
|
if (printStart != 0) {
|
||||||
|
for (usize j = 0; j < 3 - std::to_string(printStart).length(); j++) out << " ` ` ";
|
||||||
|
out << GRAY << printStart << " | -- snip --" << ENDL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the stack trace at the bottom
|
for (i32 i = printStart; i < printEnd; i++) {
|
||||||
out << endl << red << stack << endl;
|
for (usize j = 0; j < 3 - std::to_string(i + 1).length(); j++) out << " ` ` ";
|
||||||
|
out << (i + 1 == line ? RED : LTGRAY) << (i + 1)
|
||||||
|
<< (i + 1 == line ? "" : "`cr")
|
||||||
|
<< " | " << (i + 1 == line ? BOLD : "")
|
||||||
|
<< fileLines[i] << ENDL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (printEnd != fileLines.size()) {
|
||||||
|
for (usize j = 0; j < 3 - std::to_string(printEnd + 1).length(); j++) out << " ` ` ";
|
||||||
|
out << GRAY << (printEnd + 1) << " | -- snip --" << ENDL;
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "\n" << BOLD << UNDL << "Traceback" << ENDL << "\n" << RED << stack << ENDL;
|
||||||
|
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,4 +10,6 @@ class ErrorFormatter {
|
||||||
public:
|
public:
|
||||||
static string formatError(const string& fileName, usize line,
|
static string formatError(const string& fileName, usize line,
|
||||||
const string& stack, string file, bool ansiColors = true) noexcept;
|
const string& stack, string file, bool ansiColors = true) noexcept;
|
||||||
|
|
||||||
|
constexpr static i32 LOOK_AROUND = 4;
|
||||||
};
|
};
|
||||||
|
|
|
@ -62,7 +62,7 @@ void LocalLuaParser::loadApi(WorldPtr world, PlayerPtr player) {
|
||||||
core["__builtin"] = lua.create_table();
|
core["__builtin"] = lua.create_table();
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
ClientApi::gui_element(lua);
|
// ClientApi::gui_element(lua);
|
||||||
|
|
||||||
Api::Usertype::Target::bind(Api::State::CLIENT, lua, core);
|
Api::Usertype::Target::bind(Api::State::CLIENT, lua, core);
|
||||||
Api::Usertype::Entity::bind(Api::State::CLIENT, lua, core);
|
Api::Usertype::Entity::bind(Api::State::CLIENT, lua, core);
|
||||||
|
@ -116,7 +116,7 @@ void LocalLuaParser::loadApi(WorldPtr world, PlayerPtr player) {
|
||||||
lua.set_function("runfile", &LocalLuaParser::runFileSandboxed, this);
|
lua.set_function("runfile", &LocalLuaParser::runFileSandboxed, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
sol::protected_function_result LocalLuaParser::errorCallback(sol::protected_function_result r) const {
|
sol::protected_function_result LocalLuaParser::errorCallback(sol::protected_function_result r) {
|
||||||
sol::error err = r;
|
sol::error err = r;
|
||||||
std::string errString = err.what();
|
std::string errString = err.what();
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ class LocalLuaParser : public LuaParser {
|
||||||
private:
|
private:
|
||||||
void loadApi(WorldPtr world, PlayerPtr player);
|
void loadApi(WorldPtr world, PlayerPtr player);
|
||||||
|
|
||||||
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) const override;
|
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) override;
|
||||||
|
|
||||||
sol::protected_function_result runFileSandboxed(const std::string& file);
|
sol::protected_function_result runFileSandboxed(const std::string& file);
|
||||||
|
|
||||||
|
|
|
@ -26,5 +26,5 @@ class LuaKeybindHandler {
|
||||||
std::array<std::vector<sol::protected_function>, 1024> callbacksDown{};
|
std::array<std::vector<sol::protected_function>, 1024> callbacksDown{};
|
||||||
std::array<std::vector<sol::protected_function>, 1024> callbacksUp{};
|
std::array<std::vector<sol::protected_function>, 1024> callbacksUp{};
|
||||||
|
|
||||||
const LocalLuaParser* parser;
|
LocalLuaParser* parser;
|
||||||
};
|
};
|
|
@ -26,13 +26,13 @@ class LuaParser {
|
||||||
void bindModules();
|
void bindModules();
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
sol::protected_function_result safe_function(sol::protected_function f, Args... args) const {
|
sol::protected_function_result safe_function(sol::protected_function f, Args... args) {
|
||||||
auto res = f(args...);
|
auto res = f(args...);
|
||||||
if (!res.valid()) errorCallback(res);
|
if (!res.valid()) errorCallback(res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) const = 0;
|
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) = 0;
|
||||||
|
|
||||||
Subgame& game;
|
Subgame& game;
|
||||||
|
|
||||||
|
|
|
@ -145,7 +145,7 @@ void ServerLuaParser::loadApi(WorldPtr world) {
|
||||||
lua.set_function("runfile", &ServerLuaParser::runFileSandboxed, this);
|
lua.set_function("runfile", &ServerLuaParser::runFileSandboxed, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
sol::protected_function_result ServerLuaParser::errorCallback(sol::protected_function_result r) const {
|
sol::protected_function_result ServerLuaParser::errorCallback(sol::protected_function_result r) {
|
||||||
sol::error err = r;
|
sol::error err = r;
|
||||||
std::string errString = err.what();
|
std::string errString = err.what();
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void loadApi(WorldPtr world);
|
void loadApi(WorldPtr world);
|
||||||
|
|
||||||
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) const override;
|
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) override;
|
||||||
|
|
||||||
sol::protected_function_result runFileSandboxed(const std::string& file);
|
sol::protected_function_result runFileSandboxed(const std::string& file);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
//
|
|
||||||
// Created by aurailus on 2019-12-12.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "lua/Lua.h"
|
#include "lua/Lua.h"
|
||||||
|
@ -10,10 +6,10 @@
|
||||||
class LuaGuiElement;
|
class LuaGuiElement;
|
||||||
|
|
||||||
namespace MenuApi {
|
namespace MenuApi {
|
||||||
// void set_gui(GuiBuilder& builder, glm::ivec2& win, sol::state& lua, sol::table& core) {
|
void set_gui(sol::state& lua, sol::table& core, sptr<Gui::Element>& root) {
|
||||||
// core.set_function("set_gui", [&](std::shared_ptr<LuaGuiElement> gui) {
|
core.set_function("set_gui", [&](sptr<Gui::Element> elem) {
|
||||||
// builder.setGuiRoot(gui);
|
root->clear();
|
||||||
// builder.build(win);
|
root->append(elem);
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,11 @@
|
||||||
#include "../../util/CovariantPtr.h"
|
#include "../../util/CovariantPtr.h"
|
||||||
|
|
||||||
class Subgame;
|
class Subgame;
|
||||||
|
|
||||||
class ItemStack;
|
class ItemStack;
|
||||||
|
|
||||||
namespace Api::Usertype {
|
namespace Api::Usertype {
|
||||||
class ItemStack : SubgameUsertype {
|
class ItemStack : SubgameUsertype {
|
||||||
public:
|
public:
|
||||||
ItemStack() = default;
|
ItemStack() = default;
|
||||||
|
|
||||||
explicit ItemStack(sol::table tbl);
|
explicit ItemStack(sol::table tbl);
|
||||||
|
@ -38,7 +37,7 @@ namespace Api::Usertype {
|
||||||
|
|
||||||
static void bind(State state, sol::state& lua, sol::table& core);
|
static void bind(State state, sol::state& lua, sol::table& core);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string name;
|
std::string name;
|
||||||
unsigned short count;
|
unsigned short count;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,180 +1,297 @@
|
||||||
//
|
|
||||||
// Created by aurailus on 2020-04-12.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <glm/vec2.hpp>
|
|
||||||
|
|
||||||
#include "LuaGuiElement.h"
|
#include "LuaGuiElement.h"
|
||||||
|
|
||||||
#include "client/gui/SerialGui.h"
|
#include "client/gui/Gui.h"
|
||||||
|
#include "client/gui/Root.h"
|
||||||
|
#include "client/gui/Element.h"
|
||||||
|
#include "client/gui/BoxElement.h"
|
||||||
|
#include "client/gui/TextElement.h"
|
||||||
|
|
||||||
std::shared_ptr<LuaGuiElement> LuaGuiElement::create(const std::string& type, sol::table data) {
|
static const Gui::Expression parseObjectToExpr(sol::object value) {
|
||||||
auto elem = std::make_shared<LuaGuiElement>();
|
if (value.is<f32>()) return Gui::Expression(std::to_string(value.as<f32>()) + "dp");
|
||||||
elem->type = type;
|
if (value.is<string>()) return Gui::Expression(value.as<string>());
|
||||||
|
throw std::invalid_argument("Object cannot be converted to an expression.");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <usize D>
|
||||||
|
static const array<Gui::Expression, D> parseLengthTableVal(sol::object value) {
|
||||||
|
array<Gui::Expression, D> arr {};
|
||||||
|
|
||||||
for (const auto& pair : data) {
|
if (value.is<sol::table>()) {
|
||||||
if (pair.first.is<float>()) {
|
const let& t = value.as<sol::table>();
|
||||||
if (!pair.second.is<std::shared_ptr<LuaGuiElement>>()) continue;
|
|
||||||
elem->children.push_back(pair.second.as<std::shared_ptr<LuaGuiElement>>());
|
vec<Gui::Expression> exprs {};
|
||||||
elem->children.back()->parent = elem.get();
|
exprs.reserve(t.size());
|
||||||
}
|
for (let& v : t) exprs.emplace_back(parseObjectToExpr(v.second));
|
||||||
else if (pair.first.is<std::string>()) elem->set_trait(pair.first.as<std::string>(), pair.second);
|
|
||||||
|
for (usize i = 0; i < arr.size() / exprs.size(); i++)
|
||||||
|
for (usize j = 0; j < exprs.size(); j++)
|
||||||
|
arr[j + i * exprs.size()] = exprs[j];
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
let v = parseObjectToExpr(value);
|
||||||
|
for (usize i = 0; i < arr.size(); i++) arr[i] = v;
|
||||||
|
return arr;
|
||||||
|
|
||||||
|
throw std::invalid_argument("Invalid length table configuration.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Api::Usertype::GuiElement::parseRule(const string& ruleStr, const sol::object& value, Gui::Style& styles) {
|
||||||
|
using namespace Gui;
|
||||||
|
|
||||||
|
const let ruleIt = Style::RULE_STRINGS_TO_ENUMS.find(ruleStr);
|
||||||
|
if (ruleIt == Style::RULE_STRINGS_TO_ENUMS.end())
|
||||||
|
throw std::invalid_argument("Style rule '" + ruleStr + "' doesn't exist.");
|
||||||
|
const StyleRule rule = ruleIt->second;
|
||||||
|
|
||||||
|
switch (rule) {
|
||||||
|
default:
|
||||||
|
throw std::invalid_argument("Unhandled rule '" + ruleStr + "'! This is an engine error!");
|
||||||
|
|
||||||
|
case StyleRule::LAYOUT:
|
||||||
|
case StyleRule::DIRECTION:
|
||||||
|
case StyleRule::H_ALIGN:
|
||||||
|
case StyleRule::V_ALIGN:
|
||||||
|
case StyleRule::CURSOR:
|
||||||
|
case StyleRule::OVERFLOW:
|
||||||
|
case StyleRule::TEXT_COLOR:
|
||||||
|
case StyleRule::BACKGROUND:
|
||||||
|
case StyleRule::BACKGROUND_HOVER:
|
||||||
|
case StyleRule::CONTENT:
|
||||||
|
styles.rules[rule] = value.as<string>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StyleRule::POS:
|
||||||
|
case StyleRule::SIZE:
|
||||||
|
case StyleRule::GAP:
|
||||||
|
styles.rules[rule] = parseLengthTableVal<2>(value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StyleRule::MARGIN:
|
||||||
|
case StyleRule::PADDING:
|
||||||
|
styles.rules[rule] = parseLengthTableVal<4>(value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StyleRule::TEXT_SIZE:
|
||||||
|
styles.rules[rule] = parseObjectToExpr(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Gui::Element> Api::Usertype::GuiElement::create(const string& type, sol::table data, Gui::Root& root) {
|
||||||
|
Gui::Element::Props props {};
|
||||||
|
|
||||||
|
for (let& style : data) {
|
||||||
|
if (!style.first.is<string>()) continue;
|
||||||
|
GuiElement::parseRule(style.first.as<string>(), style.second, props.styles);
|
||||||
|
}
|
||||||
|
|
||||||
|
sptr<Gui::Element> elem = nullptr;
|
||||||
|
switch (Util::hash(type.data())) {
|
||||||
|
default: throw std::invalid_argument("Invalid element type '" + type + "'.");
|
||||||
|
case Util::hash("Box"): elem = root.create<Gui::BoxElement>(props); break;
|
||||||
|
case Util::hash("Text"): elem = root.create<Gui::TextElement>(props); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (usize i = 1; i <= data.size(); i++) {
|
||||||
|
const sol::object& child = data.get<sol::object>(i);
|
||||||
|
if (!child.is<sptr<Gui::Element>>()) continue;
|
||||||
|
elem->append(child.as<sptr<Gui::Element>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
return elem;
|
return elem;
|
||||||
}
|
|
||||||
|
|
||||||
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.at(key);
|
// let elem = root.create<Gui::BoxElement>(props);
|
||||||
return sol::nil;
|
// return elem;
|
||||||
}
|
// auto elem = std::make_shared<LuaGuiElement>();
|
||||||
|
|
||||||
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>();
|
|
||||||
}
|
|
||||||
else if (key == "key") {
|
|
||||||
this->key = val.as<std::string>();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
traits.erase(key);
|
|
||||||
traits.emplace(key, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updateFunction) updateFunction();
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
sol::object LuaGuiElement::call(sol::this_state s, sol::protected_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::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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sol::nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LuaGuiElement::append(sol::this_state s, sol::object elem) {
|
|
||||||
if (elem.is<std::shared_ptr<LuaGuiElement>>()) children.push_back(elem.as<std::shared_ptr<LuaGuiElement>>());
|
|
||||||
else if (elem.is<sol::protected_function>())
|
|
||||||
children.push_back(call(s, elem.as<sol::protected_function>()).as<std::shared_ptr<LuaGuiElement>>());
|
|
||||||
else throw std::runtime_error("Append arg is not an element or a function to generate one.");
|
|
||||||
|
|
||||||
children.back()->parent = this;
|
|
||||||
if (updateFunction) updateFunction();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LuaGuiElement::prepend(sol::this_state s, sol::object elem) {
|
|
||||||
if (elem.is<std::shared_ptr<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.");
|
|
||||||
|
|
||||||
children.front()->parent = this;
|
|
||||||
if (updateFunction) updateFunction();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LuaGuiElement::remove(sol::this_state s, sol::object elem) {
|
|
||||||
if (!elem) {
|
|
||||||
if (parent != nullptr) parent->remove(s, sol::make_object<std::string>(s, key));
|
|
||||||
else throw std::runtime_error("Tried to remove self from nil parent.");
|
|
||||||
}
|
|
||||||
else if (elem.is<std::string>()) {
|
|
||||||
auto child = this->get_child(s, sol::make_object<std::string>(s, elem.as<std::string>()));
|
|
||||||
if (child) remove(s, child);
|
|
||||||
}
|
|
||||||
else if (elem.is<std::shared_ptr<LuaGuiElement>>()) {
|
|
||||||
auto parent = elem.as<std::shared_ptr<LuaGuiElement>>()->parent;
|
|
||||||
|
|
||||||
for (auto it = parent->children.cbegin(); it != parent->children.cend(); it++) {
|
|
||||||
if ((*it)->key == elem.as<std::shared_ptr<LuaGuiElement>>()->key) {
|
|
||||||
(*it)->parent = nullptr;
|
|
||||||
(*it)->updateFunction = nullptr;
|
|
||||||
|
|
||||||
parent->children.erase(it);
|
|
||||||
if (parent->updateFunction) parent->updateFunction();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LuaGuiElement::clear(sol::this_state s) {
|
|
||||||
for (auto it = children.cbegin(); it != children.cend();) {
|
|
||||||
(*it)->parent = nullptr;
|
|
||||||
(*it)->updateFunction = nullptr;
|
|
||||||
it = children.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updateFunction) updateFunction();
|
|
||||||
}
|
|
||||||
|
|
||||||
Any LuaGuiElement::getAsAny(const std::string& key) const {
|
|
||||||
if (!traits.count(key)) return Any();
|
|
||||||
// auto object = traits.at(key);
|
|
||||||
//
|
//
|
||||||
// if (object.is<float>()) return Any::from<float>(object.as<float>());
|
// elem->type = type;
|
||||||
// else if (object.is<bool>()) return Any::from<bool>(object.as<bool>());
|
|
||||||
// else 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) {
|
// for (const auto& pair : data) {
|
||||||
// auto x = table.get<sol::object>(1);
|
// if (pair.first.is<float>()) {
|
||||||
// auto y = table.get<sol::object>(2);
|
// if (!pair.second.is<std::shared_ptr<LuaGuiElement>>()) continue;
|
||||||
//
|
// elem->children.push_back(pair.second.as<std::shared_ptr<LuaGuiElement>>());
|
||||||
// glm::vec2 values = {};
|
// elem->children.back()->parent = elem.get();
|
||||||
// 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) {
|
// else if (pair.first.is<std::string>()) elem->set_trait(pair.first.as<std::string>(), pair.second);
|
||||||
// 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 = {};
|
// return elem;
|
||||||
// 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>();
|
void Api::Usertype::GuiElement::bind(sol::state& lua, sol::table& core, Gui::Root& root) {
|
||||||
// else if (y.is<std::string>()) values.y = SerialGui::toDouble(y.as<std::string>());
|
lua.new_usertype<Gui::Element>("GuiElement",
|
||||||
// if (z.is<float>()) values.z = z.as<float>();
|
sol::meta_function::construct, sol::factories([&](const string& type, sol::table data) {
|
||||||
// else if (z.is<std::string>()) values.z = SerialGui::toDouble(z.as<std::string>());
|
return GuiElement::create(type, data, root);
|
||||||
// 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);
|
//// 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
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//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.at(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>();
|
||||||
|
// }
|
||||||
|
// else if (key == "key") {
|
||||||
|
// this->key = val.as<std::string>();
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// traits.erase(key);
|
||||||
|
// traits.emplace(key, val);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (updateFunction) updateFunction();
|
||||||
|
// return val;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//sol::object LuaGuiElement::call(sol::this_state s, sol::protected_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::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;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
throw std::runtime_error("Invalid type requested in getAsAny");
|
// return sol::nil;
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
|
//void LuaGuiElement::append(sol::this_state s, sol::object elem) {
|
||||||
|
// if (elem.is<std::shared_ptr<LuaGuiElement>>()) children.push_back(elem.as<std::shared_ptr<LuaGuiElement>>());
|
||||||
|
// else if (elem.is<sol::protected_function>())
|
||||||
|
// children.push_back(call(s, elem.as<sol::protected_function>()).as<std::shared_ptr<LuaGuiElement>>());
|
||||||
|
// else throw std::runtime_error("Append arg is not an element or a function to generate one.");
|
||||||
|
//
|
||||||
|
// children.back()->parent = this;
|
||||||
|
// if (updateFunction) updateFunction();
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void LuaGuiElement::prepend(sol::this_state s, sol::object elem) {
|
||||||
|
// if (elem.is<std::shared_ptr<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.");
|
||||||
|
//
|
||||||
|
// children.front()->parent = this;
|
||||||
|
// if (updateFunction) updateFunction();
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void LuaGuiElement::remove(sol::this_state s, sol::object elem) {
|
||||||
|
// if (!elem) {
|
||||||
|
// if (parent != nullptr) parent->remove(s, sol::make_object<std::string>(s, key));
|
||||||
|
// else throw std::runtime_error("Tried to remove self from nil parent.");
|
||||||
|
// }
|
||||||
|
// else if (elem.is<std::string>()) {
|
||||||
|
// auto child = this->get_child(s, sol::make_object<std::string>(s, elem.as<std::string>()));
|
||||||
|
// if (child) remove(s, child);
|
||||||
|
// }
|
||||||
|
// else if (elem.is<std::shared_ptr<LuaGuiElement>>()) {
|
||||||
|
// auto parent = elem.as<std::shared_ptr<LuaGuiElement>>()->parent;
|
||||||
|
//
|
||||||
|
// for (auto it = parent->children.cbegin(); it != parent->children.cend(); it++) {
|
||||||
|
// if ((*it)->key == elem.as<std::shared_ptr<LuaGuiElement>>()->key) {
|
||||||
|
// (*it)->parent = nullptr;
|
||||||
|
// (*it)->updateFunction = nullptr;
|
||||||
|
//
|
||||||
|
// parent->children.erase(it);
|
||||||
|
// if (parent->updateFunction) parent->updateFunction();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void LuaGuiElement::clear(sol::this_state s) {
|
||||||
|
// for (auto it = children.cbegin(); it != children.cend();) {
|
||||||
|
// (*it)->parent = nullptr;
|
||||||
|
// (*it)->updateFunction = nullptr;
|
||||||
|
// it = children.erase(it);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (updateFunction) updateFunction();
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//Any LuaGuiElement::getAsAny(const std::string& key) const {
|
||||||
|
// if (!traits.count(key)) return Any();
|
||||||
|
//// auto object = traits.at(key);
|
||||||
|
////
|
||||||
|
//// if (object.is<float>()) return Any::from<float>(object.as<float>());
|
||||||
|
//// else if (object.is<bool>()) return Any::from<bool>(object.as<bool>());
|
||||||
|
//// else 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);
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
//
|
||||||
|
// throw std::runtime_error("Invalid type requested in getAsAny");
|
||||||
|
//}
|
|
@ -1,84 +1,97 @@
|
||||||
//
|
|
||||||
// Created by aurailus on 2020-04-12.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <list>
|
#include "lua/Lua.h"
|
||||||
|
|
||||||
#include "../Lua.h"
|
#include "util/Types.h"
|
||||||
#include "../../util/Any.h"
|
//#include "BaseUsertype.h"
|
||||||
|
//#include "../../util/CovariantPtr.h"
|
||||||
|
|
||||||
class LuaGuiElement {
|
//class Subgame;
|
||||||
public:
|
//class ItemStack;
|
||||||
LuaGuiElement() = default;
|
|
||||||
|
namespace Gui {
|
||||||
|
class Style;
|
||||||
|
class Root;
|
||||||
|
class Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Api::Usertype::GuiElement {
|
||||||
|
void parseRule(const string& ruleStr, const sol::object& value, Gui::Style& styles);
|
||||||
|
|
||||||
// Lua Functions and Properties
|
std::shared_ptr<Gui::Element> create(const string& type, sol::table data, Gui::Root& root);
|
||||||
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::protected_function fun);
|
sol::object call(sol::this_state s, sol::protected_function fun);
|
||||||
|
|
||||||
sol::object get_child(sol::this_state s, sol::object key);
|
void bind(sol::state& lua, sol::table& core, Gui::Root& root);
|
||||||
|
|
||||||
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<LuaGuiElement>("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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
//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
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
|
|
||||||
#include "ItemStack.h"
|
#include "ItemStack.h"
|
||||||
#include "InventoryList.h"
|
#include "InventoryList.h"
|
||||||
#include "LuaGuiElement.h"
|
|
||||||
#include "world/LocalWorld.h"
|
#include "world/LocalWorld.h"
|
||||||
#include "world/ServerWorld.h"
|
#include "world/ServerWorld.h"
|
||||||
#include "world/inv/Inventory.h"
|
#include "world/inv/Inventory.h"
|
||||||
|
@ -168,21 +167,25 @@ bool Api::Usertype::LocalPlayer::is_in_menu() {
|
||||||
return player.l()->isInMenu();
|
return player.l()->isInMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Api::Usertype::LocalPlayer::show_menu(std::shared_ptr<LuaGuiElement> root) {
|
//void Api::Usertype::LocalPlayer::show_menu(std::shared_ptr<LuaGuiElement> root) {
|
||||||
return player.l()->showMenu(root);
|
//// return player.l()->showMenu(root);
|
||||||
}
|
// return;
|
||||||
|
//}
|
||||||
|
|
||||||
void Api::Usertype::LocalPlayer::close_menu() {
|
void Api::Usertype::LocalPlayer::close_menu() {
|
||||||
return player.l()->closeMenu();
|
// return player.l()->closeMenu();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<LuaGuiElement> Api::Usertype::LocalPlayer::get_hud() {
|
//std::shared_ptr<LuaGuiElement> Api::Usertype::LocalPlayer::get_hud() {
|
||||||
return player.l()->getHud();
|
//// return player.l()->getHud();
|
||||||
}
|
// return nullptr;
|
||||||
|
//}
|
||||||
|
|
||||||
void Api::Usertype::LocalPlayer::set_hud(std::shared_ptr<LuaGuiElement> hud) {
|
//void Api::Usertype::LocalPlayer::set_hud(std::shared_ptr<LuaGuiElement> hud) {
|
||||||
player.l()->setHud(hud);
|
//// player.l()->setHud(hud);
|
||||||
}
|
// return;
|
||||||
|
//}
|
||||||
|
|
||||||
void Api::Usertype::LocalPlayer::bind(State, sol::state& lua, sol::table& core) {
|
void Api::Usertype::LocalPlayer::bind(State, sol::state& lua, sol::table& core) {
|
||||||
lua.new_usertype<LocalPlayer>("Player",
|
lua.new_usertype<LocalPlayer>("Player",
|
||||||
|
@ -209,10 +212,10 @@ void Api::Usertype::LocalPlayer::bind(State, sol::state& lua, sol::table& core)
|
||||||
|
|
||||||
"get_dimension", &LocalPlayer::get_dimension,
|
"get_dimension", &LocalPlayer::get_dimension,
|
||||||
|
|
||||||
"show_menu", &LocalPlayer::show_menu,
|
// "show_menu", &LocalPlayer::show_menu,
|
||||||
"close_menu", &LocalPlayer::close_menu,
|
"close_menu", &LocalPlayer::close_menu,
|
||||||
"set_hud", &LocalPlayer::set_hud,
|
// "set_hud", &LocalPlayer::set_hud,
|
||||||
"get_hud", &LocalPlayer::get_hud,
|
// "get_hud", &LocalPlayer::get_hud,
|
||||||
|
|
||||||
"pos", sol::property(&LocalPlayer::get_pos, &LocalPlayer::set_pos),
|
"pos", sol::property(&LocalPlayer::get_pos, &LocalPlayer::set_pos),
|
||||||
"block_pos", sol::property(&LocalPlayer::get_block_pos, &LocalPlayer::set_pos),
|
"block_pos", sol::property(&LocalPlayer::get_block_pos, &LocalPlayer::set_pos),
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include "Dimension.h"
|
#include "Dimension.h"
|
||||||
#include "world/player/LocalPlayer.h"
|
#include "world/player/LocalPlayer.h"
|
||||||
|
|
||||||
class LuaGuiElement;
|
//class LuaGuiElement;
|
||||||
|
|
||||||
namespace Api::Usertype {
|
namespace Api::Usertype {
|
||||||
class ServerPlayer;
|
class ServerPlayer;
|
||||||
|
@ -82,13 +82,13 @@ public:
|
||||||
|
|
||||||
bool is_in_menu();
|
bool is_in_menu();
|
||||||
|
|
||||||
void show_menu(std::shared_ptr<LuaGuiElement> root);
|
// void show_menu(std::shared_ptr<LuaGuiElement> root);
|
||||||
|
|
||||||
void close_menu();
|
void close_menu();
|
||||||
|
|
||||||
std::shared_ptr<LuaGuiElement> get_hud();
|
// std::shared_ptr<LuaGuiElement> get_hud();
|
||||||
|
|
||||||
void set_hud(std::shared_ptr<LuaGuiElement> hud);
|
// void set_hud(std::shared_ptr<LuaGuiElement> hud);
|
||||||
|
|
||||||
static void bind(State state, sol::state& lua, sol::table& core);
|
static void bind(State state, sol::state& lua, sol::table& core);
|
||||||
};
|
};
|
|
@ -100,23 +100,23 @@ bool LocalPlayer::isInMenu() {
|
||||||
// return gameGui.isInMenu();
|
// return gameGui.isInMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPlayer::showMenu(sptr<LuaGuiElement> root) {
|
//void LocalPlayer::showMenu(sptr<LuaGuiElement> root) {
|
||||||
// gameGui.showMenu(root);
|
//// gameGui.showMenu(root);
|
||||||
renderer.window.input.setMouseLocked(false);
|
// renderer.window.input.setMouseLocked(false);
|
||||||
}
|
//}
|
||||||
|
|
||||||
void LocalPlayer::closeMenu() {
|
void LocalPlayer::closeMenu() {
|
||||||
// gameGui.closeMenu();
|
// gameGui.closeMenu();
|
||||||
renderer.window.input.setMouseLocked(true);
|
renderer.window.input.setMouseLocked(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
sptr<LuaGuiElement> LocalPlayer::getHud() {
|
//sptr<LuaGuiElement> LocalPlayer::getHud() {
|
||||||
// return gameGui.getHud();
|
//// return gameGui.getHud();
|
||||||
}
|
//}
|
||||||
|
|
||||||
void LocalPlayer::setHud(sptr<LuaGuiElement> hud) {
|
//void LocalPlayer::setHud(sptr<LuaGuiElement> hud) {
|
||||||
// gameGui.setHud(hud);
|
//// gameGui.setHud(hud);
|
||||||
}
|
//}
|
||||||
|
|
||||||
void LocalPlayer::setHudVisible(bool hudVisible) {
|
void LocalPlayer::setHudVisible(bool hudVisible) {
|
||||||
// gameGui.setVisible(hudVisible);
|
// gameGui.setVisible(hudVisible);
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
|
|
||||||
class Input;
|
class Input;
|
||||||
class Deserializer;
|
class Deserializer;
|
||||||
class LuaGuiElement;
|
|
||||||
class LocalInventory;
|
class LocalInventory;
|
||||||
class LocalInventoryRefs;
|
class LocalInventoryRefs;
|
||||||
enum class NetPlayerField;
|
enum class NetPlayerField;
|
||||||
|
@ -89,7 +88,7 @@ public:
|
||||||
* @param root - The root GUI element to display.
|
* @param root - The root GUI element to display.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void showMenu(sptr<LuaGuiElement> root);
|
// void showMenu(sptr<LuaGuiElement> root);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the currently open menu.
|
* Closes the currently open menu.
|
||||||
|
@ -102,7 +101,7 @@ public:
|
||||||
* @returns the root GUI element of the hud.
|
* @returns the root GUI element of the hud.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sptr<LuaGuiElement> getHud();
|
// sptr<LuaGuiElement> getHud();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the HUD to the specified GUI tree. The hud does not constitute
|
* Sets the HUD to the specified GUI tree. The hud does not constitute
|
||||||
|
@ -111,7 +110,7 @@ public:
|
||||||
* @param hud - The root GUI element to display.
|
* @param hud - The root GUI element to display.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void setHud(sptr<LuaGuiElement> hud);
|
// void setHud(sptr<LuaGuiElement> hud);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the visibility state of the HUD.
|
* Sets the visibility state of the HUD.
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"name": "minimal",
|
|
||||||
"display_name": "Minimal Subgame",
|
|
||||||
"author": "@aurailus",
|
|
||||||
"description": "Minimal subgame for development.",
|
|
||||||
"version": "0.0.1"
|
|
||||||
}
|
|
|
@ -1,31 +1,31 @@
|
||||||
local gui = zepha.build_gui(function()
|
zepha.set_gui(zepha.gui(function()
|
||||||
return Gui.Body {
|
return Gui.Box {
|
||||||
-- background = "#214a21",
|
|
||||||
background = "#334",
|
background = "#334",
|
||||||
|
|
||||||
Gui.Text {
|
Gui.Text {
|
||||||
position = { 4, 4 },
|
pos = { 4, 4 },
|
||||||
|
text_size = "2px",
|
||||||
content = "Minimalminimalmmnal"
|
content = "Minimalminimalmmnal"
|
||||||
},
|
},
|
||||||
|
|
||||||
Gui.Rect {
|
Gui.Box {
|
||||||
position = { 64, 64 },
|
pos = { 64, 64 },
|
||||||
size = { 128 * (16/9), 128 },
|
size = { 128 * (16/9), 128 },
|
||||||
|
|
||||||
background = "zeus_background"
|
background = "zeus_background"
|
||||||
},
|
},
|
||||||
|
|
||||||
Gui.Rect {
|
Gui.Box {
|
||||||
position = { 64 + 128, 64 + 64 },
|
pos = { 64 + 128, 64 + 64 },
|
||||||
size = { 128 * (16/9), 128 },
|
size = { 128 * (16/9), 128 },
|
||||||
|
|
||||||
background = "zeus_background",
|
background = "zeus_background",
|
||||||
|
|
||||||
Gui.Text {
|
Gui.Text {
|
||||||
|
pos = 4,
|
||||||
|
text_size = "4px",
|
||||||
content = "What's the fuck it'd going on?"
|
content = "What's the fuck it'd going on?"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end)
|
end))
|
||||||
|
|
||||||
zepha.set_gui(gui)
|
|
|
@ -1,9 +1,11 @@
|
||||||
zepha.set_gui(zepha.build_gui(function()
|
zepha.set_gui(zepha.gui(function()
|
||||||
return Gui.Body {
|
return Gui.Box {
|
||||||
background = "#124778",
|
background = "#124778",
|
||||||
|
h_align = "center",
|
||||||
|
v_align = "center",
|
||||||
|
|
||||||
Gui.Text {
|
Gui.Text {
|
||||||
position = { 4, 4 },
|
size = { 64, 4 },
|
||||||
content = "Parentheses"
|
content = "Parentheses"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue