More Lua GuiElement functionality.
parent
1c58797480
commit
9aec996b74
|
@ -5,7 +5,7 @@ zepha.player:set_hud(zepha.gui(function()
|
||||||
Gui.Box {
|
Gui.Box {
|
||||||
-- id = "crosshair",
|
-- id = "crosshair",
|
||||||
|
|
||||||
size = { "22dp", "22dp" },
|
size = { "22px", "22px" },
|
||||||
pos = { "50cw - 50sw", "50ch - 50sh" },
|
pos = { "50cw - 50sw", "50ch - 50sh" },
|
||||||
|
|
||||||
background = "base:crosshair"
|
background = "base:crosshair"
|
||||||
|
|
|
@ -184,8 +184,8 @@ add_library(Zepha_Core
|
||||||
lua/usertype/InventoryList.h
|
lua/usertype/InventoryList.h
|
||||||
lua/usertype/ItemStack.cpp
|
lua/usertype/ItemStack.cpp
|
||||||
lua/usertype/ItemStack.h
|
lua/usertype/ItemStack.h
|
||||||
lua/usertype/LuaGuiElement.cpp
|
lua/usertype/GuiElement.cpp
|
||||||
lua/usertype/LuaGuiElement.h
|
lua/usertype/GuiElement.h
|
||||||
lua/usertype/Player.cpp
|
lua/usertype/Player.cpp
|
||||||
lua/usertype/Player.h
|
lua/usertype/Player.h
|
||||||
lua/usertype/SubgameUsertype.h
|
lua/usertype/SubgameUsertype.h
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
#include "client/graph/mesh/EntityMesh.h"
|
#include "client/graph/mesh/EntityMesh.h"
|
||||||
|
|
||||||
void Gui::BoxElement::updateElement() {
|
void Gui::BoxElement::updateElement() {
|
||||||
const let bgRule = hovered && getStyle(StyleRule::BACKGROUND_HOVER) ?
|
const let bgRule = hovered && getStyle(Prop::BACKGROUND_HOVER) ?
|
||||||
StyleRule::BACKGROUND_HOVER : StyleRule::BACKGROUND;
|
Prop::BACKGROUND_HOVER : Prop::BACKGROUND;
|
||||||
|
|
||||||
let rawBg = getStyle(bgRule);
|
let rawBg = getStyle(bgRule);
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ void Gui::BoxElement::updateElement() {
|
||||||
curBg = rawBg;
|
curBg = rawBg;
|
||||||
|
|
||||||
if (isDirty) {
|
if (isDirty) {
|
||||||
const let bgColor = getStyle<vec4, ValueType::COLOR>(bgRule);
|
const let bgColor = getStyle<vec4, Type::COLOR>(bgRule);
|
||||||
const string bgImage = getStyle<string>(bgRule, "");
|
const string bgImage = getStyle<string>(bgRule, "");
|
||||||
|
|
||||||
let mesh = std::make_unique<EntityMesh>();
|
let mesh = std::make_unique<EntityMesh>();
|
||||||
|
@ -48,7 +48,7 @@ void Gui::BoxElement::updateElement() {
|
||||||
entity.setModel(model);
|
entity.setModel(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
let margin = getStyle<ivec4, ValueType::LENGTH>(StyleRule::MARGIN, {});
|
let margin = getStyle<ivec4, Type::LENGTH>(Prop::MARGIN, {});
|
||||||
|
|
||||||
entity.setScale(vec3(getComputedSize(), 0));
|
entity.setScale(vec3(getComputedSize(), 0));
|
||||||
entity.setPos(vec3(getComputedScreenPos() + ivec2 { margin.x, margin.y }, 0));
|
entity.setPos(vec3(getComputedScreenPos() + ivec2 { margin.x, margin.y }, 0));
|
||||||
|
|
|
@ -8,17 +8,17 @@ Gui::Element::~Element() {
|
||||||
for (let& child : children) child->parent = nullptr;
|
for (let& child : children) child->parent = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Gui::Props& Gui::Element::getProps() const {
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
void Gui::Element::setProps(const Props& props) {
|
void Gui::Element::setProps(const Props& props) {
|
||||||
this->props = props;
|
this->props = props;
|
||||||
updateElement();
|
updateElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gui::Element::setStyle(StyleRule style, const any& value) {
|
void Gui::Element::setProp(Gui::Prop prop, const any& value) {
|
||||||
props.styles.rules[style] = value;
|
props.props[prop] = value;
|
||||||
}
|
|
||||||
|
|
||||||
const optional<any> Gui::Element::getStyleRaw(Gui::StyleRule style) const {
|
|
||||||
return getStyle(style);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sptr<Gui::Element> Gui::Element::get(u32 ind) {
|
sptr<Gui::Element> Gui::Element::get(u32 ind) {
|
||||||
|
@ -26,10 +26,33 @@ sptr<Gui::Element> Gui::Element::get(u32 ind) {
|
||||||
return children[ind];
|
return children[ind];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sptr<Gui::Element> Gui::Element::get(const string& id) {
|
||||||
|
for (let& child : children) {
|
||||||
|
if (child->props.get<string>(Prop::ID) == id) return child;
|
||||||
|
}
|
||||||
|
for (let& child : children) {
|
||||||
|
let res = child->get(id);
|
||||||
|
if (res != nullptr) return res;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void Gui::Element::clear() {
|
void Gui::Element::clear() {
|
||||||
children.clear();
|
children.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Gui::Element::remove() {
|
||||||
|
if (parent) {
|
||||||
|
for (let it = parent->children.begin(); it != parent->children.end(); it++) {
|
||||||
|
if (it->get() == this) {
|
||||||
|
parent->children.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parent = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Gui::Element::onClick(const std::function<void(i32, bool)>& cb) {
|
void Gui::Element::onClick(const std::function<void(i32, bool)>& cb) {
|
||||||
clickCb = cb;
|
clickCb = cb;
|
||||||
}
|
}
|
||||||
|
@ -42,7 +65,7 @@ Gui::ExpressionInfo Gui::Element::getExpr() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
ivec2 Gui::Element::getComputedSize() const {
|
ivec2 Gui::Element::getComputedSize() const {
|
||||||
let size = getStyleWithExpr<vec2, ValueType::LENGTH>(StyleRule::SIZE, vec2(nanf("")),
|
let size = getStyleWithExpr<vec2, Type::LENGTH>(Prop::SIZE, vec2(nanf("")),
|
||||||
{ parent ? parent->computedSize : ivec2 {}, {} });
|
{ parent ? parent->computedSize : ivec2 {}, {} });
|
||||||
if (std::isnan(size.x)) size.x = std::max(layoutSize.x, 0);
|
if (std::isnan(size.x)) size.x = std::max(layoutSize.x, 0);
|
||||||
if (std::isnan(size.y)) size.y = std::max(layoutSize.y, 0);
|
if (std::isnan(size.y)) size.y = std::max(layoutSize.y, 0);
|
||||||
|
@ -50,24 +73,18 @@ ivec2 Gui::Element::getComputedSize() const {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ivec2 Gui::Element::getComputedOuterSize() const {
|
|
||||||
let size = getComputedSize();
|
|
||||||
let margin = getStyle<ivec4, ValueType::LENGTH>(StyleRule::MARGIN, {});
|
|
||||||
return ivec2 { size.x + margin.x + margin.z, size.y + margin.y + margin.w };
|
|
||||||
}
|
|
||||||
|
|
||||||
ivec2 Gui::Element::getComputedContentSize() const {
|
ivec2 Gui::Element::getComputedContentSize() const {
|
||||||
let size = getComputedSize();
|
let size = getComputedSize();
|
||||||
let padding = getStyle<ivec4, ValueType::LENGTH>(StyleRule::PADDING, {});
|
let padding = getStyle<ivec4, Type::LENGTH>(Prop::PADDING, {});
|
||||||
return glm::max(ivec2 { size.x - padding.x - padding.z, size.y - padding.y - padding.w }, 0);
|
return glm::max(ivec2 { size.x - padding.x - padding.z, size.y - padding.y - padding.w }, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ivec2 Gui::Element::getExplicitSize() const {
|
ivec2 Gui::Element::getExplicitSize() const {
|
||||||
return getStyle<ivec2, ValueType::LENGTH>(StyleRule::SIZE, ivec2(-1));
|
return getStyle<ivec2, Type::LENGTH>(Prop::SIZE, ivec2(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
ivec2 Gui::Element::getComputedPos() const {
|
ivec2 Gui::Element::getComputedPos() const {
|
||||||
return getStyle<ivec2, ValueType::LENGTH>(StyleRule::POS, layoutPosition);
|
return getStyle<ivec2, Type::LENGTH>(Prop::POS, layoutPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
ivec2 Gui::Element::getComputedScreenPos() const {
|
ivec2 Gui::Element::getComputedScreenPos() const {
|
||||||
|
@ -91,7 +108,7 @@ bool Gui::Element::handleMouseHover(ivec2 mousePos, bool& pointer) {
|
||||||
bool intersects = mousePos.x >= pos.x && mousePos.x <= pos.x + size.x &&
|
bool intersects = mousePos.x >= pos.x && mousePos.x <= pos.x + size.x &&
|
||||||
mousePos.y >= pos.y && mousePos.y <= pos.y + size.y;
|
mousePos.y >= pos.y && mousePos.y <= pos.y + size.y;
|
||||||
|
|
||||||
let cursor = getStyle<string>(StyleRule::CURSOR);
|
let cursor = getStyle<string>(Prop::CURSOR);
|
||||||
if (intersects && cursor) pointer = *cursor == "pointer";
|
if (intersects && cursor) pointer = *cursor == "pointer";
|
||||||
|
|
||||||
if (hovered != intersects) {
|
if (hovered != intersects) {
|
||||||
|
@ -126,12 +143,12 @@ void Gui::Element::updateElement() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gui::Element::layoutChildren() {
|
void Gui::Element::layoutChildren() {
|
||||||
const string& layout = getStyle<string>(StyleRule::LAYOUT, "");
|
const string& layout = getStyle<string>(Prop::LAYOUT, "");
|
||||||
|
|
||||||
switch (Util::hash(layout.data())) {
|
switch (Util::hash(layout.data())) {
|
||||||
default:
|
default:
|
||||||
case Util::hash("flex"): {
|
case Util::hash("flex"): {
|
||||||
const string& direction = getStyle<string>(StyleRule::DIRECTION, "");
|
const string& direction = getStyle<string>(Prop::DIRECTION, "");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The primary flex direction. Stored as a bool but interpreted as an index into a vec2.
|
* The primary flex direction. Stored as a bool but interpreted as an index into a vec2.
|
||||||
|
@ -140,8 +157,8 @@ void Gui::Element::layoutChildren() {
|
||||||
|
|
||||||
const bool primary = direction != "row";
|
const bool primary = direction != "row";
|
||||||
|
|
||||||
const string& hAlignRaw = getStyle<string>(StyleRule::H_ALIGN, "");
|
const string& hAlignRaw = getStyle<string>(Prop::H_ALIGN, "");
|
||||||
const string& vAlignRaw = getStyle<string>(StyleRule::V_ALIGN, "");
|
const string& vAlignRaw = getStyle<string>(Prop::V_ALIGN, "");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parsed alignment of the horizontal and vertical axes.
|
* Parsed alignment of the horizontal and vertical axes.
|
||||||
|
@ -157,8 +174,8 @@ void Gui::Element::layoutChildren() {
|
||||||
* The element gap across the primary axis.
|
* The element gap across the primary axis.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const i32 gap = getStyle<ivec2, ValueType::LENGTH>(StyleRule::GAP, ivec2(0))[primary];
|
const i32 gap = getStyle<ivec2, Type::LENGTH>(Prop::GAP, ivec2(0))[primary];
|
||||||
const ivec4& padding = getStyle<ivec4, ValueType::LENGTH>(StyleRule::PADDING, ivec4 {});
|
const ivec4& padding = getStyle<ivec4, Type::LENGTH>(Prop::PADDING, ivec4 {});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculates the explicit spaced used up by children across the primary axis,
|
* Calculates the explicit spaced used up by children across the primary axis,
|
||||||
|
@ -174,7 +191,7 @@ void Gui::Element::layoutChildren() {
|
||||||
let childExplicitSize = child->getExplicitSize();
|
let childExplicitSize = child->getExplicitSize();
|
||||||
if (childExplicitSize[primary] != -1) explicitSize += childExplicitSize[primary];
|
if (childExplicitSize[primary] != -1) explicitSize += childExplicitSize[primary];
|
||||||
else implicitCount++;
|
else implicitCount++;
|
||||||
let childMargin = child->getStyle<ivec4, ValueType::LENGTH>(StyleRule::MARGIN, {});
|
let childMargin = child->getStyle<ivec4, Type::LENGTH>(Prop::MARGIN, {});
|
||||||
explicitSize += childMargin[primary] + childMargin[primary + 2];
|
explicitSize += childMargin[primary] + childMargin[primary + 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +218,7 @@ void Gui::Element::layoutChildren() {
|
||||||
|
|
||||||
for (const let& child : children) {
|
for (const let& child : children) {
|
||||||
let childExplicitSize = child->getExplicitSize();
|
let childExplicitSize = child->getExplicitSize();
|
||||||
let childMargin = child->getStyle<ivec4, ValueType::LENGTH>(StyleRule::MARGIN, {});
|
let childMargin = child->getStyle<ivec4, Type::LENGTH>(Prop::MARGIN, {});
|
||||||
|
|
||||||
child->layoutSize[primary] =
|
child->layoutSize[primary] =
|
||||||
(childExplicitSize[primary] == -1 && align[primary] == 2) ? implicitElemSize : 0;
|
(childExplicitSize[primary] == -1 && align[primary] == 2) ? implicitElemSize : 0;
|
||||||
|
@ -227,4 +244,4 @@ void Gui::Element::layoutChildren() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,10 +3,10 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include "client/gui/Gui.h"
|
#include "client/gui/Gui.h"
|
||||||
#include "client/gui/Style.h"
|
|
||||||
#include "world/dim/ent/DrawableEntity.h"
|
#include "world/dim/ent/DrawableEntity.h"
|
||||||
|
|
||||||
#include "util/Types.h"
|
#include "util/Types.h"
|
||||||
|
#include "client/gui/Style.h"
|
||||||
|
|
||||||
class Window;
|
class Window;
|
||||||
class Renderer;
|
class Renderer;
|
||||||
|
@ -25,23 +25,18 @@ namespace Gui {
|
||||||
friend class TextElement;
|
friend class TextElement;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Props {;
|
|
||||||
string id {};
|
|
||||||
vec<string> classes {};
|
|
||||||
Style styles {};
|
|
||||||
};
|
|
||||||
|
|
||||||
Element(Root& root, vec<StyleSheet>& stylesheets): root(root), stylesheets(stylesheets) {}
|
Element(Root& root, vec<StyleSheet>& stylesheets): root(root), stylesheets(stylesheets) {}
|
||||||
|
|
||||||
~Element();
|
~Element();
|
||||||
|
|
||||||
|
/** Gets a reference to the element's props. */
|
||||||
|
const Props& getProps() const;
|
||||||
|
|
||||||
/** Sets the element's props to the struct specified. */
|
/** Sets the element's props to the struct specified. */
|
||||||
virtual void setProps(const Props& props);
|
virtual void setProps(const Props& props);
|
||||||
|
|
||||||
/** Sets a style rule on the element. */
|
/** Sets a style rule on the element. */
|
||||||
virtual void setStyle(StyleRule style, const std::any& value);
|
virtual void setProp(Prop prop, const std::any& value);
|
||||||
|
|
||||||
virtual const optional<any> getStyleRaw(StyleRule style) const;
|
|
||||||
|
|
||||||
/** Recalculates the element based on its props. Call when props or stylesheets change. */
|
/** Recalculates the element based on its props. Call when props or stylesheets change. */
|
||||||
virtual void updateElement();
|
virtual void updateElement();
|
||||||
|
@ -51,6 +46,8 @@ namespace Gui {
|
||||||
|
|
||||||
sptr<Element> get(u32 ind);
|
sptr<Element> get(u32 ind);
|
||||||
|
|
||||||
|
sptr<Element> get(const string& id);
|
||||||
|
|
||||||
template<typename E, std::enable_if_t<std::is_base_of_v<Element, E>, bool> = true>
|
template<typename E, std::enable_if_t<std::is_base_of_v<Element, E>, bool> = true>
|
||||||
sptr<E> get(u32 ind) {
|
sptr<E> get(u32 ind) {
|
||||||
return std::dynamic_pointer_cast<E>(get(ind));
|
return std::dynamic_pointer_cast<E>(get(ind));
|
||||||
|
@ -92,14 +89,13 @@ namespace Gui {
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
void remove();
|
||||||
|
|
||||||
void onClick(const std::function<void(i32, bool)>& cb);
|
void onClick(const std::function<void(i32, bool)>& cb);
|
||||||
|
|
||||||
/** Returns the element's computed size. */
|
/** Returns the element's computed size. */
|
||||||
virtual ivec2 getComputedSize() const;
|
virtual ivec2 getComputedSize() const;
|
||||||
|
|
||||||
/** Returns the element's computed size + margins. */
|
|
||||||
virtual ivec2 getComputedOuterSize() const;
|
|
||||||
|
|
||||||
/** Returns the element's computed content size, which is its size - padding. */
|
/** Returns the element's computed content size, which is its size - padding. */
|
||||||
virtual ivec2 getComputedContentSize() const;
|
virtual ivec2 getComputedContentSize() const;
|
||||||
|
|
||||||
|
@ -113,11 +109,13 @@ namespace Gui {
|
||||||
virtual ivec2 getComputedScreenPos() const;
|
virtual ivec2 getComputedScreenPos() const;
|
||||||
|
|
||||||
/** Gets a style value from the element's styles or the root's stylesheets. */
|
/** Gets a style value from the element's styles or the root's stylesheets. */
|
||||||
const optional<any> getStyle(StyleRule rule) const {
|
const optional<any> getStyle(Prop rule) const {
|
||||||
const optional<any> opt = props.styles.get(rule);
|
const optional<any> opt = props.get(rule);
|
||||||
if (opt) return *opt;
|
if (opt) return *opt;
|
||||||
|
const let& classes = props.get<vec<string>>(Prop::CLASS);
|
||||||
|
if (!classes) return std::nullopt;
|
||||||
for (const let& ss : stylesheets) {
|
for (const let& ss : stylesheets) {
|
||||||
for (const string& className : props.classes) {
|
for (const string& className : *classes) {
|
||||||
const let& styles = ss.find(className);
|
const let& styles = ss.find(className);
|
||||||
if (styles == ss.end()) continue;
|
if (styles == ss.end()) continue;
|
||||||
const optional<any> opt = styles->second.get(rule);
|
const optional<any> opt = styles->second.get(rule);
|
||||||
|
@ -128,14 +126,15 @@ namespace Gui {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a generic value from the element's styles or the root's stylesheets. */
|
/** Gets a generic value from the element's styles or the root's stylesheets. */
|
||||||
template<typename V, ValueType T = ValueType::LITERAL,
|
template<typename V, Type T = Type::LITERAL, std::enable_if_t<T != Type::LENGTH, bool> = true>
|
||||||
std::enable_if_t<T != ValueType::LENGTH, bool> = true>
|
|
||||||
|
|
||||||
const optional<V> getStyle(StyleRule rule) const {
|
const optional<V> getStyle(Prop rule) const {
|
||||||
const optional<V> opt = props.styles.get<V, T>(rule);
|
const optional<V> opt = props.get<V, T>(rule);
|
||||||
if (opt) return *opt;
|
if (opt) return *opt;
|
||||||
|
const let& classes = props.get<vec<string>>(Prop::CLASS);
|
||||||
|
if (!classes) return std::nullopt;
|
||||||
for (const let& ss : stylesheets) {
|
for (const let& ss : stylesheets) {
|
||||||
for (const string& className : props.classes) {
|
for (const string& className : *classes) {
|
||||||
const let& styles = ss.find(className);
|
const let& styles = ss.find(className);
|
||||||
if (styles == ss.end()) continue;
|
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);
|
||||||
|
@ -146,15 +145,16 @@ namespace Gui {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a LENGTH value from the element's styles or the root's stylesheets. */
|
/** Gets a LENGTH value from the element's styles or the root's stylesheets. */
|
||||||
template<typename V, ValueType T = ValueType::LITERAL,
|
template<typename V, Type T = Type::LITERAL, std::enable_if_t<T == Type::LENGTH, bool> = true>
|
||||||
std::enable_if_t<T == ValueType::LENGTH, bool> = true>
|
|
||||||
|
|
||||||
const optional<V> getStyle(StyleRule rule) const {
|
const optional<V> getStyle(Prop rule) const {
|
||||||
ExpressionInfo info = getExpr();
|
ExpressionInfo info = getExpr();
|
||||||
const optional<V> opt = props.styles.get<V, T>(rule, info);
|
const optional<V> opt = props.get<V, T>(rule, info);
|
||||||
if (opt) return *opt;
|
if (opt) return *opt;
|
||||||
|
const let& classes = props.get<vec<string>>(Prop::CLASS);
|
||||||
|
if (!classes) return std::nullopt;
|
||||||
for (const let& ss : stylesheets) {
|
for (const let& ss : stylesheets) {
|
||||||
for (const string& className : props.classes) {
|
for (const string& className : *classes) {
|
||||||
const let& styles = ss.find(className);
|
const let& styles = ss.find(className);
|
||||||
if (styles == ss.end()) continue;
|
if (styles == ss.end()) continue;
|
||||||
const optional<V> opt = styles->second.get<V, T>(rule, info);
|
const optional<V> opt = styles->second.get<V, T>(rule, info);
|
||||||
|
@ -165,14 +165,15 @@ namespace Gui {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a LENGTH value from the element's styles or the root's stylesheets. */
|
/** Gets a LENGTH value from the element's styles or the root's stylesheets. */
|
||||||
template<typename V, ValueType T = ValueType::LITERAL,
|
template<typename V, Type T = Type::LITERAL, std::enable_if_t<T == Type::LENGTH, bool> = true>
|
||||||
std::enable_if_t<T == ValueType::LENGTH, bool> = true>
|
|
||||||
|
|
||||||
const optional<V> getStyleWithExpr(StyleRule rule, const ExpressionInfo& expr) const {
|
const optional<V> getStyleWithExpr(Prop rule, const ExpressionInfo& expr) const {
|
||||||
const optional<V> opt = props.styles.get<V, T>(rule, expr);
|
const optional<V> opt = props.get<V, T>(rule, expr);
|
||||||
if (opt) return *opt;
|
if (opt) return *opt;
|
||||||
|
const let& classes = props.get<vec<string>>(Prop::CLASS);
|
||||||
|
if (!classes) return std::nullopt;
|
||||||
for (const let& ss : stylesheets) {
|
for (const let& ss : stylesheets) {
|
||||||
for (const string& className : props.classes) {
|
for (const string& className : *classes) {
|
||||||
const let& styles = ss.find(className);
|
const let& styles = ss.find(className);
|
||||||
if (styles == ss.end()) continue;
|
if (styles == ss.end()) continue;
|
||||||
const optional<V> opt = styles->second.get<V, T>(rule, expr);
|
const optional<V> opt = styles->second.get<V, T>(rule, expr);
|
||||||
|
@ -183,19 +184,18 @@ namespace Gui {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a style value from the element's styles or the root's stylesheets. */
|
/** Gets a style value from the element's styles or the root's stylesheets. */
|
||||||
template<typename V, ValueType T = ValueType::LITERAL>
|
template<typename V, Type T = Type::LITERAL>
|
||||||
|
|
||||||
const V getStyle(StyleRule rule, V def) const {
|
const V getStyle(Prop rule, V def) const {
|
||||||
const optional<V> opt = getStyle<V, T>(rule);
|
const optional<V> opt = getStyle<V, T>(rule);
|
||||||
if (opt) return *opt;
|
if (opt) return *opt;
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a LENGTH value from the element's styles or the root's stylesheets, with a custom ExpressionInfo. */
|
/** Gets a LENGTH value from the element's styles or the root's stylesheets, with a custom ExpressionInfo. */
|
||||||
template<typename V, ValueType T = ValueType::LITERAL,
|
template<typename V, Type T = Type::LITERAL, std::enable_if_t<T == Type::LENGTH, bool> = true>
|
||||||
std::enable_if_t<T == ValueType::LENGTH, bool> = true>
|
|
||||||
|
|
||||||
const V getStyleWithExpr(StyleRule rule, V def, const ExpressionInfo& info) const {
|
const V getStyleWithExpr(Prop rule, V def, const ExpressionInfo& info) const {
|
||||||
const optional<V> opt = getStyleWithExpr<V, T>(rule, info);
|
const optional<V> opt = getStyleWithExpr<V, T>(rule, info);
|
||||||
if (opt) return *opt;
|
if (opt) return *opt;
|
||||||
return def;
|
return def;
|
||||||
|
|
|
@ -10,17 +10,15 @@ Gui::Root::Root(Window& window, TextureAtlas& atlas) :
|
||||||
body(make_shared<BoxElement>(*this, stylesheets)) {
|
body(make_shared<BoxElement>(*this, stylesheets)) {
|
||||||
const ivec2 size = window.getSize();
|
const ivec2 size = window.getSize();
|
||||||
|
|
||||||
body->setProps({
|
using Expr = Expression;
|
||||||
.id = "body",
|
body->setProps({{
|
||||||
.styles = {{
|
{ Prop::ID, string("body") },
|
||||||
{ StyleRule::SIZE, array<Expression, 2> {
|
{ Prop::SIZE, array<Expr, 2> { Expr(std::to_string(size.x)), Expr(std::to_string(size.y)) }}
|
||||||
Expression(std::to_string(size.x)), Expression(std::to_string(size.y)) }}
|
}});
|
||||||
}}
|
|
||||||
});
|
|
||||||
|
|
||||||
callbacks.emplace_back(window.resize.bind([&](ivec2 size) {
|
callbacks.emplace_back(window.resize.bind([&](ivec2 size) {
|
||||||
body->setStyle(StyleRule::SIZE, array<Expression, 2> {
|
body->setProp(Prop::SIZE, array<Expr, 2> {
|
||||||
Expression(std::to_string(size.x)), Expression(std::to_string(size.y)) });
|
Expr(std::to_string(size.x)), Expr(std::to_string(size.y)) });
|
||||||
Timer t("Resize UI");
|
Timer t("Resize UI");
|
||||||
body->updateElement();
|
body->updateElement();
|
||||||
t.printElapsedMs();
|
t.printElapsedMs();
|
||||||
|
@ -36,7 +34,7 @@ Gui::Root::~Root() {
|
||||||
window.setCursorHand(false);
|
window.setCursorHand(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gui::Root::addStylesheet(const std::unordered_map<string, Style>& sheet) {
|
void Gui::Root::addStylesheet(const StyleSheet& sheet) {
|
||||||
stylesheets.emplace_back(sheet);
|
stylesheets.emplace_back(sheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace Gui {
|
||||||
|
|
||||||
template<typename E, std::enable_if_t<std::is_base_of_v<Element, E>, bool> = true>
|
template<typename E, std::enable_if_t<std::is_base_of_v<Element, E>, bool> = true>
|
||||||
|
|
||||||
sptr<E> create(const Element::Props& props = {}, const vec<sptr<Element>>& children = {}) {
|
sptr<E> create(const Props& props = {}, const vec<sptr<Element>>& children = {}) {
|
||||||
let elem = make_shared<E>(*this, stylesheets);
|
let elem = make_shared<E>(*this, stylesheets);
|
||||||
elem->setProps(props);
|
elem->setProps(props);
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ namespace Gui {
|
||||||
* styles for elements with specific classes.
|
* styles for elements with specific classes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void addStylesheet(const std::unordered_map<string, Style>& sheet);
|
void addStylesheet(const StyleSheet& sheet);
|
||||||
|
|
||||||
/** Processes mouse events. */
|
/** Processes mouse events. */
|
||||||
void update();
|
void update();
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
#include "Style.h"
|
#include "Style.h"
|
||||||
|
|
||||||
const std::unordered_map<string, Gui::StyleRule> Gui::Style::RULE_STRINGS_TO_ENUMS = {
|
const std::unordered_map<string, Gui::Prop> Gui::Props::PROP_NAMES_TO_ENUM = {
|
||||||
{ "pos", StyleRule::POS },
|
{ "id", Prop::ID },
|
||||||
{ "size", StyleRule::SIZE },
|
{ "class", Prop::CLASS },
|
||||||
{ "margin", StyleRule::MARGIN },
|
{ "pos", Prop::POS },
|
||||||
{ "padding", StyleRule::PADDING },
|
{ "size", Prop::SIZE },
|
||||||
{ "gap", StyleRule::GAP },
|
{ "margin", Prop::MARGIN },
|
||||||
{ "layout", StyleRule::LAYOUT },
|
{ "padding", Prop::PADDING },
|
||||||
{ "direction", StyleRule::DIRECTION },
|
{ "gap", Prop::GAP },
|
||||||
{ "h_align", StyleRule::H_ALIGN },
|
{ "layout", Prop::LAYOUT },
|
||||||
{ "v_align", StyleRule::V_ALIGN },
|
{ "direction", Prop::DIRECTION },
|
||||||
{ "cursor", StyleRule::CURSOR },
|
{ "h_align", Prop::H_ALIGN },
|
||||||
{ "overflow", StyleRule::OVERFLOW },
|
{ "v_align", Prop::V_ALIGN },
|
||||||
{ "background", StyleRule::BACKGROUND },
|
{ "cursor", Prop::CURSOR },
|
||||||
{ "background_hover", StyleRule::BACKGROUND_HOVER },
|
{ "overflow", Prop::OVERFLOW },
|
||||||
{ "content", StyleRule::CONTENT },
|
{ "background", Prop::BACKGROUND },
|
||||||
{ "text_size", StyleRule::TEXT_SIZE },
|
{ "background_hover", Prop::BACKGROUND_HOVER },
|
||||||
{ "text_color", StyleRule::TEXT_COLOR }
|
{ "content", Prop::CONTENT },
|
||||||
|
{ "text_size", Prop::TEXT_SIZE },
|
||||||
|
{ "text_color", Prop::TEXT_COLOR }
|
||||||
};
|
};
|
|
@ -5,7 +5,10 @@
|
||||||
#include "client/gui/Expression.h"
|
#include "client/gui/Expression.h"
|
||||||
|
|
||||||
namespace Gui {
|
namespace Gui {
|
||||||
enum class StyleRule {
|
enum class Prop {
|
||||||
|
ID,
|
||||||
|
CLASS,
|
||||||
|
|
||||||
POS,
|
POS,
|
||||||
SIZE,
|
SIZE,
|
||||||
MARGIN,
|
MARGIN,
|
||||||
|
@ -27,25 +30,25 @@ namespace Gui {
|
||||||
TEXT_COLOR
|
TEXT_COLOR
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ValueType {
|
enum class Type {
|
||||||
LITERAL,
|
LITERAL,
|
||||||
COLOR,
|
COLOR,
|
||||||
LENGTH
|
LENGTH
|
||||||
};
|
};
|
||||||
|
|
||||||
class Style {
|
class Props {
|
||||||
public:
|
public:
|
||||||
Style() = default;
|
Props() = default;
|
||||||
Style(const std::unordered_map<StyleRule, any>& rules): rules(rules) {}
|
Props(const std::unordered_map<Prop, any>& props): props(props) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple get. Returns an optional containing an any of
|
* Simple get. Returns an optional containing an any of
|
||||||
* the Rule's value, or an empty optional if the rule is not defined.
|
* the Rule's value, or an empty optional if the rule is not defined.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const optional<any> get(StyleRule rule) const {
|
const optional<any> get(Prop prop) const {
|
||||||
const let it = rules.find(rule);
|
const let it = props.find(prop);
|
||||||
if (it == rules.end()) return std::nullopt;
|
if (it == props.end()) return std::nullopt;
|
||||||
return optional<any>(it->second);
|
return optional<any>(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,14 +57,14 @@ namespace Gui {
|
||||||
* or an empty optional if the rule is not defined, or not the type V.
|
* or an empty optional if the rule is not defined, or not the type V.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<typename V, ValueType T = ValueType::LITERAL, std::enable_if_t<
|
template<typename V, Type T = Type::LITERAL, std::enable_if_t<
|
||||||
!(std::is_integral_v<V> ||
|
!(std::is_integral_v<V> ||
|
||||||
std::is_floating_point_v<V> ||
|
std::is_floating_point_v<V> ||
|
||||||
std::is_same_v<V, string>) &&
|
std::is_same_v<V, string>) &&
|
||||||
T == ValueType::LITERAL, bool> = true>
|
T == Type::LITERAL, bool> = true>
|
||||||
|
|
||||||
const optional<V> get(StyleRule rule) const {
|
const optional<V> get(Prop prop) const {
|
||||||
const optional<any> raw = get(rule);
|
const optional<any> raw = get(prop);
|
||||||
if (!raw || raw->type() != typeid(V)) return std::nullopt;
|
if (!raw || raw->type() != typeid(V)) return std::nullopt;
|
||||||
return any_cast<V>(*raw);
|
return any_cast<V>(*raw);
|
||||||
}
|
}
|
||||||
|
@ -70,15 +73,14 @@ namespace Gui {
|
||||||
* get<O, T> specialization for string-like values.
|
* get<O, T> specialization for string-like values.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<typename S, ValueType T = ValueType::LITERAL, std::enable_if_t<
|
template<typename S, Type T = Type::LITERAL, std::enable_if_t<
|
||||||
std::is_same_v<S, string> &&
|
std::is_same_v<S, string> &&
|
||||||
T == ValueType::LITERAL, bool> = true>
|
T == Type::LITERAL, bool> = true>
|
||||||
|
|
||||||
const optional<S> get(StyleRule rule) const {
|
const optional<S> get(Prop prop) const {
|
||||||
const optional<any> raw = get(rule);
|
const optional<any> raw = get(prop);
|
||||||
if (!raw) return std::nullopt;
|
if (!raw) return std::nullopt;
|
||||||
if (raw->type() == typeid(string)) return any_cast<string>(*raw);
|
if (raw->type() == typeid(string)) return any_cast<string>(*raw);
|
||||||
// if (raw->type() == typeid(const char*)) return any_cast<const char*>(*raw);
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,26 +88,15 @@ namespace Gui {
|
||||||
* get<O, T> specialization for numeric values.
|
* get<O, T> specialization for numeric values.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<typename N, ValueType T = ValueType::LITERAL, std::enable_if_t<
|
template<typename N, Type T = Type::LITERAL, std::enable_if_t<
|
||||||
(std::is_integral_v<N> ||
|
(std::is_integral_v<N> ||
|
||||||
std::is_floating_point_v<N>) &&
|
std::is_floating_point_v<N>) &&
|
||||||
T == ValueType::LITERAL, bool> = true>
|
T == Type::LITERAL, bool> = true>
|
||||||
|
|
||||||
const optional<N> get(StyleRule rule) const {
|
const optional<N> get(Prop prop) const {
|
||||||
const optional<any> raw = get(rule);
|
const optional<any> raw = get(prop);
|
||||||
if (!raw) return std::nullopt;
|
if (!raw) return std::nullopt;
|
||||||
if (raw->type() == typeid(N)) return any_cast<N>(*raw);
|
if (raw->type() == typeid(N)) return any_cast<N>(*raw);
|
||||||
// if (raw->type() == typeid(i8)) return static_cast<N>(any_cast<i8>(*raw));
|
|
||||||
// if (raw->type() == typeid(i16)) return static_cast<N>(any_cast<i16>(*raw));
|
|
||||||
// if (raw->type() == typeid(i32)) return static_cast<N>(any_cast<i32>(*raw));
|
|
||||||
// if (raw->type() == typeid(i64)) return static_cast<N>(any_cast<i64>(*raw));
|
|
||||||
// if (raw->type() == typeid(f32)) return static_cast<N>(any_cast<f32>(*raw));
|
|
||||||
// if (raw->type() == typeid(f64)) return static_cast<N>(any_cast<f64>(*raw));
|
|
||||||
// if (raw->type() == typeid(u8)) return static_cast<N>(any_cast<u8>(*raw));
|
|
||||||
// if (raw->type() == typeid(u16)) return static_cast<N>(any_cast<u16>(*raw));
|
|
||||||
// if (raw->type() == typeid(u32)) return static_cast<N>(any_cast<u32>(*raw));
|
|
||||||
// if (raw->type() == typeid(u64)) return static_cast<N>(any_cast<u64>(*raw));
|
|
||||||
// if (raw->type() == typeid(usize)) return static_cast<N>(any_cast<usize>(*raw));
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,23 +105,18 @@ namespace Gui {
|
||||||
* which is interpreted as a vec4 color from several different formats.
|
* which is interpreted as a vec4 color from several different formats.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<typename V, ValueType C, std::enable_if_t<
|
template<typename V, Type C, std::enable_if_t<
|
||||||
std::is_same_v<V, vec4> &&
|
std::is_same_v<V, vec4> &&
|
||||||
C == ValueType::COLOR, bool> = true>
|
C == Type::COLOR, bool> = true>
|
||||||
|
|
||||||
const optional<V> get(StyleRule rule, optional<V> def = std::nullopt) const {
|
const optional<V> get(Prop prop, optional<V> def = std::nullopt) const {
|
||||||
const optional<any> raw = get(rule);
|
const optional<any> raw = get(prop);
|
||||||
if (!raw) return std::nullopt;
|
if (!raw) return std::nullopt;
|
||||||
if (raw->type() == typeid(void) && def) return *def;
|
if (raw->type() == typeid(void) && def) return *def;
|
||||||
if (raw->type() == typeid(void)) throw std::runtime_error("Field is missing with no default.");
|
if (raw->type() == typeid(void)) throw std::runtime_error("Field is missing with no default.");
|
||||||
if (raw->type() == typeid(vec4)) return any_cast<vec4>(*raw);
|
if (raw->type() == typeid(vec4)) return any_cast<vec4>(*raw);
|
||||||
try {
|
try { if (raw->type() == typeid(string)) return Util::hexToColorVec(any_cast<string>(*raw)); }
|
||||||
if (raw->type() == typeid(string)) return Util::hexToColorVec(any_cast<string>(*raw));
|
catch (std::exception) { return std::nullopt; }
|
||||||
// if (raw->type() == typeid(const char*)) return Util::hexToColorVec(string(any_cast<const char*>(*raw)));
|
|
||||||
}
|
|
||||||
catch (std::exception) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,12 +125,12 @@ namespace Gui {
|
||||||
* which is interpreted as a length.
|
* which is interpreted as a length.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<typename N, ValueType L, std::enable_if_t<
|
template<typename N, Type L, std::enable_if_t<
|
||||||
(std::is_integral_v<N> || std::is_floating_point_v<N>) &&
|
(std::is_integral_v<N> || std::is_floating_point_v<N>) &&
|
||||||
L == ValueType::LENGTH, bool> = true>
|
L == Type::LENGTH, bool> = true>
|
||||||
|
|
||||||
optional<N> get(StyleRule rule, const ExpressionInfo& info) const {
|
optional<N> get(Prop prop, const ExpressionInfo& info) const {
|
||||||
let raw = get<Gui::Expression>(rule);
|
let raw = get<Gui::Expression>(prop);
|
||||||
if (!raw) return std::nullopt;
|
if (!raw) return std::nullopt;
|
||||||
return raw->eval(info);
|
return raw->eval(info);
|
||||||
}
|
}
|
||||||
|
@ -154,13 +140,13 @@ namespace Gui {
|
||||||
* which is interpreted as a length.
|
* which is interpreted as a length.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<typename VN, ValueType L, std::enable_if_t<
|
template<typename VN, Type L, std::enable_if_t<
|
||||||
(std::is_integral_v<typename VN::value_type> || std::is_floating_point_v<typename VN::value_type>) &&
|
(std::is_integral_v<typename VN::value_type> || std::is_floating_point_v<typename VN::value_type>) &&
|
||||||
std::is_same_v<VN, glm::vec<VN::length(), typename VN::value_type>> &&
|
std::is_same_v<VN, glm::vec<VN::length(), typename VN::value_type>> &&
|
||||||
L == ValueType::LENGTH, bool> = true>
|
L == Type::LENGTH, bool> = true>
|
||||||
|
|
||||||
optional<VN> get(StyleRule rule, const ExpressionInfo& info) const {
|
optional<VN> get(Prop prop, const ExpressionInfo& info) const {
|
||||||
let raw = get<array<Gui::Expression, VN::length()>>(rule);
|
let raw = get<array<Gui::Expression, VN::length()>>(prop);
|
||||||
if (!raw) return std::nullopt;
|
if (!raw) return std::nullopt;
|
||||||
VN vec;
|
VN vec;
|
||||||
for (usize i = 0; i < VN::length(); i++) vec[i] = (*raw)[i].eval(info);
|
for (usize i = 0; i < VN::length(); i++) vec[i] = (*raw)[i].eval(info);
|
||||||
|
@ -173,18 +159,18 @@ namespace Gui {
|
||||||
* Throws if the rule is defined to a different type.
|
* Throws if the rule is defined to a different type.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<typename V, ValueType T = ValueType::LITERAL>
|
template<typename V, Type T = Type::LITERAL>
|
||||||
|
|
||||||
const V get(StyleRule rule, V def) const {
|
const V get(Prop prop, V def) const {
|
||||||
const optional<V> raw = get<V, T>(rule);
|
const optional<V> raw = get<V, T>(prop);
|
||||||
if (!raw) return def;
|
if (!raw) return def;
|
||||||
return *raw;
|
return *raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<StyleRule, any> rules {};
|
std::unordered_map<Prop, any> props {};
|
||||||
|
|
||||||
const static std::unordered_map<string, StyleRule> RULE_STRINGS_TO_ENUMS;
|
const static std::unordered_map<string, Prop> PROP_NAMES_TO_ENUM;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::unordered_map<string, Style> StyleSheet;
|
typedef std::unordered_map<string, Props> StyleSheet;
|
||||||
}
|
}
|
|
@ -7,7 +7,7 @@
|
||||||
#include "client/graph/mesh/EntityMesh.h"
|
#include "client/graph/mesh/EntityMesh.h"
|
||||||
|
|
||||||
void Gui::TextElement::updateElement() {
|
void Gui::TextElement::updateElement() {
|
||||||
const string text = getStyle<string>(StyleRule::CONTENT, "");
|
const string text = getStyle<string>(Prop::CONTENT, "");
|
||||||
|
|
||||||
if (!font) font = std::make_unique<Font>(root.atlas, root.atlas["font"]);
|
if (!font) font = std::make_unique<Font>(root.atlas, root.atlas["font"]);
|
||||||
|
|
||||||
|
@ -15,8 +15,8 @@ void Gui::TextElement::updateElement() {
|
||||||
if (hash != newHash) {
|
if (hash != newHash) {
|
||||||
hash = newHash;
|
hash = newHash;
|
||||||
|
|
||||||
vec4 textColor = getStyle<vec4, ValueType::COLOR>(StyleRule::TEXT_COLOR, vec4(1));
|
vec4 textColor = getStyle<vec4, Type::COLOR>(Prop::TEXT_COLOR, vec4(1));
|
||||||
vec4 backgroundColor = getStyle<vec4, ValueType::COLOR>(StyleRule::BACKGROUND, vec4(0));
|
vec4 backgroundColor = getStyle<vec4, Type::COLOR>(Prop::BACKGROUND, vec4(0));
|
||||||
|
|
||||||
u32 ind = 0;
|
u32 ind = 0;
|
||||||
u32 width = 0;
|
u32 width = 0;
|
||||||
|
@ -190,8 +190,8 @@ void Gui::TextElement::updateElement() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let scale = getStyle<f32, ValueType::LENGTH>(StyleRule::TEXT_SIZE, 3.f);
|
let scale = getStyle<f32, Type::LENGTH>(Prop::TEXT_SIZE, 3.f);
|
||||||
let margin = getStyle<ivec4, ValueType::LENGTH>(StyleRule::MARGIN, {});
|
let margin = getStyle<ivec4, Type::LENGTH>(Prop::MARGIN, {});
|
||||||
|
|
||||||
entity.setScale(vec3(scale, scale, 0));
|
entity.setScale(vec3(scale, scale, 0));
|
||||||
entity.setPos(vec3(getComputedScreenPos() + ivec2 { margin.x, margin.y }, 0));
|
entity.setPos(vec3(getComputedScreenPos() + ivec2 { margin.x, margin.y }, 0));
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#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"
|
#include "lua/usertype/GuiElement.h"
|
||||||
|
|
||||||
MenuSandbox::MenuSandbox(Client& client, Gui::Root& root, sptr<Gui::Element> sandboxRoot) :
|
MenuSandbox::MenuSandbox(Client& client, Gui::Root& root, sptr<Gui::Element> sandboxRoot) :
|
||||||
LuaParser(*client.game),
|
LuaParser(*client.game),
|
||||||
|
@ -152,14 +152,12 @@ void MenuSandbox::showError(const string& err) {
|
||||||
|
|
||||||
using Expr = Gui::Expression;
|
using Expr = Gui::Expression;
|
||||||
sandboxRoot->clear();
|
sandboxRoot->clear();
|
||||||
sandboxRoot->append<Gui::TextElement>({
|
sandboxRoot->append<Gui::TextElement>({{
|
||||||
.styles = {{
|
{ Gui::Prop::CONTENT, errPrefixText + err },
|
||||||
{ Gui::StyleRule::CONTENT, errPrefixText + err },
|
{ Gui::Prop::TEXT_SIZE, Expr("2px") },
|
||||||
{ Gui::StyleRule::TEXT_SIZE, Expr("2px") },
|
{ Gui::Prop::SIZE, array<Expr, 2> { Expr("100dp"), Expr("-1") } },
|
||||||
{ Gui::StyleRule::SIZE, array<Expr, 2> { Expr("100dp"), Expr("-1") } },
|
{ Gui::Prop::MARGIN, array<Expr, 4> { Expr("4dp"), Expr("4dp"), Expr("4dp"), Expr("4dp") } }
|
||||||
{ Gui::StyleRule::MARGIN, array<Expr, 4> { Expr("4dp"), Expr("4dp"), Expr("4dp"), Expr("4dp") } }
|
}});
|
||||||
}}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sol::protected_function_result MenuSandbox::errorCallback(sol::protected_function_result r) {
|
sol::protected_function_result MenuSandbox::errorCallback(sol::protected_function_result r) {
|
||||||
|
|
|
@ -19,14 +19,12 @@ ConnectScene::ConnectScene(Client& client, Address addr) : Scene(client),
|
||||||
client.renderer.setClearColor(10, 10, 10);
|
client.renderer.setClearColor(10, 10, 10);
|
||||||
|
|
||||||
using Expr = Gui::Expression;
|
using Expr = Gui::Expression;
|
||||||
status = root.body->append<Gui::TextElement>({
|
status = root.body->append<Gui::TextElement>({{
|
||||||
.styles = {{
|
{ Gui::Prop::TEXT_SIZE, Expr("2px") },
|
||||||
{ Gui::StyleRule::TEXT_SIZE, Expr("2px") },
|
{ Gui::Prop::SIZE, array<Expr, 2> { Expr("100dp"), Expr("-1") } },
|
||||||
{ Gui::StyleRule::SIZE, array<Expr, 2> { Expr("100dp"), Expr("-1") } },
|
{ Gui::Prop::CONTENT, string("`c1Connecting to `b`c0" + addr.toString() + "`r`c1...") },
|
||||||
{ Gui::StyleRule::CONTENT, string("`c1Connecting to `b`c0" + addr.toString() + "`r`c1...") },
|
{ Gui::Prop::MARGIN, array<Expr, 4> { Expr("4dp"), Expr("4dp"), Expr("4dp"), Expr("4dp") } }
|
||||||
{ Gui::StyleRule::MARGIN, array<Expr, 4> { Expr("4dp"), Expr("4dp"), Expr("4dp"), Expr("4dp") } }
|
}});
|
||||||
}}
|
|
||||||
});
|
|
||||||
|
|
||||||
connection.attemptConnect(std::move(addr));
|
connection.attemptConnect(std::move(addr));
|
||||||
}
|
}
|
||||||
|
@ -50,8 +48,8 @@ void ConnectScene::update() {
|
||||||
PacketView p(e.packet);
|
PacketView p(e.packet);
|
||||||
|
|
||||||
if (p.type == Packet::Type::SERVER_INFO) {
|
if (p.type == Packet::Type::SERVER_INFO) {
|
||||||
status->setStyle(Gui::StyleRule::CONTENT, status->getStyle<string>(Gui::StyleRule::CONTENT, "")
|
status->setProp(Gui::Prop::CONTENT, status->getStyle<string>(Gui::Prop::CONTENT, "")
|
||||||
+ "Received server properties.\n");
|
+ "Received server properties.\n");
|
||||||
|
|
||||||
const u32 seed = p.d.read<u32>();
|
const u32 seed = p.d.read<u32>();
|
||||||
std::cout << seed << std::endl;
|
std::cout << seed << std::endl;
|
||||||
|
@ -76,8 +74,9 @@ void ConnectScene::update() {
|
||||||
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
|
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
|
||||||
}
|
}
|
||||||
else if (p.type == Packet::Type::BIOME_IDENTIFIER_LIST) {
|
else if (p.type == Packet::Type::BIOME_IDENTIFIER_LIST) {
|
||||||
status->setStyle(Gui::StyleRule::CONTENT, status->getStyle<string>(Gui::StyleRule::CONTENT, "")
|
status->setProp(Gui::Prop::CONTENT, status->getStyle<string>(Gui::Prop::CONTENT, "")
|
||||||
+ "Received block & biome index-identifier table.\nDownloading mods... ");
|
+
|
||||||
|
"Received block & biome index-identifier table.\nDownloading mods... ");
|
||||||
|
|
||||||
client.game->getBiomes().setIdentifiers(p.d.read<vec<string>>());
|
client.game->getBiomes().setIdentifiers(p.d.read<vec<string>>());
|
||||||
state = State::MODS;
|
state = State::MODS;
|
||||||
|
@ -95,17 +94,19 @@ void ConnectScene::update() {
|
||||||
|
|
||||||
if (p.type == Packet::Type::MODS) {
|
if (p.type == Packet::Type::MODS) {
|
||||||
auto mod = LuaMod(p);
|
auto mod = LuaMod(p);
|
||||||
status->setStyle(Gui::StyleRule::CONTENT, status->getStyle<string>(Gui::StyleRule::CONTENT, "") +
|
status->setProp(Gui::Prop::CONTENT, status->getStyle<string>(Gui::Prop::CONTENT, "") +
|
||||||
(modsFound == 0 ? "" : ", ") + ((modsFound) % 8 == 0 && modsFound != 0 ? "\n" : "") +
|
(modsFound == 0 ? "" : ", ") +
|
||||||
"`c0`u" + mod.config.name + "`r`c1");
|
((modsFound) % 8 == 0 && modsFound != 0 ? "\n" : "") +
|
||||||
|
"`c0`u" + mod.config.name + "`r`c1");
|
||||||
modsFound++;
|
modsFound++;
|
||||||
client.game->getParser().addMod(std::move(mod));
|
client.game->getParser().addMod(std::move(mod));
|
||||||
}
|
}
|
||||||
else if (p.type == Packet::Type::MOD_ORDER) {
|
else if (p.type == Packet::Type::MOD_ORDER) {
|
||||||
client.game->getParser().setModLoadOrder(p.d.read<vec<string>>());
|
client.game->getParser().setModLoadOrder(p.d.read<vec<string>>());
|
||||||
|
|
||||||
status->setStyle(Gui::StyleRule::CONTENT, status->getStyle<string>(Gui::StyleRule::CONTENT, "")
|
status->setProp(Gui::Prop::CONTENT, status->getStyle<string>(Gui::Prop::CONTENT, "")
|
||||||
+ ".\n`c7Done`c1 downloading mods. Received the mods order.\nReceiving media");
|
+
|
||||||
|
".\n`c7Done`c1 downloading mods. Received the mods order.\nReceiving media");
|
||||||
|
|
||||||
state = State::MEDIA;
|
state = State::MEDIA;
|
||||||
Packet resp(Packet::Type::MEDIA);
|
Packet resp(Packet::Type::MEDIA);
|
||||||
|
@ -126,8 +127,8 @@ void ConnectScene::update() {
|
||||||
|
|
||||||
while (t != AssetType::END) {
|
while (t != AssetType::END) {
|
||||||
string assetName = p.d.read<string>();
|
string assetName = p.d.read<string>();
|
||||||
status->setStyle(Gui::StyleRule::CONTENT,
|
status->setProp(Gui::Prop::CONTENT,
|
||||||
status->getStyle<string>(Gui::StyleRule::CONTENT, "") + ".");
|
status->getStyle<string>(Gui::Prop::CONTENT, "") + ".");
|
||||||
|
|
||||||
if (t == AssetType::TEXTURE) {
|
if (t == AssetType::TEXTURE) {
|
||||||
u16 width = p.d.read<u16>();
|
u16 width = p.d.read<u16>();
|
||||||
|
@ -152,8 +153,8 @@ void ConnectScene::update() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (p.type == Packet::Type::MEDIA_DONE) {
|
else if (p.type == Packet::Type::MEDIA_DONE) {
|
||||||
status->setStyle(Gui::StyleRule::CONTENT, status->getStyle<string>(Gui::StyleRule::CONTENT, "")
|
status->setProp(Gui::Prop::CONTENT, status->getStyle<string>(Gui::Prop::CONTENT, "")
|
||||||
+ " `c7Done.`c1\nLoading complete. `c0`bJoining world...\n");
|
+ " `c7Done.`c1\nLoading complete. `c0`bJoining world...\n");
|
||||||
|
|
||||||
state = State::DONE;
|
state = State::DONE;
|
||||||
let gameScene = make_unique<GameScene>(client);
|
let gameScene = make_unique<GameScene>(client);
|
||||||
|
@ -179,8 +180,8 @@ void ConnectScene::handleConnecting() {
|
||||||
|
|
||||||
case ServerConnection::State::FAILED_CONNECT:
|
case ServerConnection::State::FAILED_CONNECT:
|
||||||
state = State::FAILED_CONNECT;
|
state = State::FAILED_CONNECT;
|
||||||
status->setStyle(Gui::StyleRule::CONTENT,
|
status->setProp(Gui::Prop::CONTENT,
|
||||||
status->getStyle<string>(Gui::StyleRule::CONTENT, "") + " `cfFailed to init :(\n");
|
status->getStyle<string>(Gui::Prop::CONTENT, "") + " `cfFailed to init :(\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ServerConnection::State::ATTEMPTING_CONNECT:
|
case ServerConnection::State::ATTEMPTING_CONNECT:
|
||||||
|
@ -189,15 +190,15 @@ void ConnectScene::handleConnecting() {
|
||||||
dotsTime += client.getDelta();
|
dotsTime += client.getDelta();
|
||||||
if (dotsTime > 1) {
|
if (dotsTime > 1) {
|
||||||
dotsTime -= 1;
|
dotsTime -= 1;
|
||||||
status->setStyle(Gui::StyleRule::CONTENT, status->getStyle<string>(Gui::StyleRule::CONTENT, "") + ".");
|
status->setProp(Gui::Prop::CONTENT, status->getStyle<string>(Gui::Prop::CONTENT, "") + ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ServerConnection::State::CONNECTED: {
|
case ServerConnection::State::CONNECTED: {
|
||||||
state = State::PROPERTIES;
|
state = State::PROPERTIES;
|
||||||
status->setStyle(Gui::StyleRule::CONTENT,
|
status->setProp(Gui::Prop::CONTENT,
|
||||||
status->getStyle<string>(Gui::StyleRule::CONTENT, "") + " `c7Connected!~`c1\n");
|
status->getStyle<string>(Gui::Prop::CONTENT, "") + " `c7Connected!~`c1\n");
|
||||||
|
|
||||||
Packet resp(Packet::Type::SERVER_INFO);
|
Packet resp(Packet::Type::SERVER_INFO);
|
||||||
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
|
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
|
||||||
|
|
|
@ -13,14 +13,12 @@ LuaErrorScene::LuaErrorScene(Client& client, const std::string& err) : Scene(cli
|
||||||
client.renderer.window.input.setMouseLocked(false);
|
client.renderer.window.input.setMouseLocked(false);
|
||||||
|
|
||||||
using Expr = Gui::Expression;
|
using Expr = Gui::Expression;
|
||||||
root.body->append<Gui::TextElement>({
|
root.body->append<Gui::TextElement>({{
|
||||||
.styles = {{
|
{ Gui::Prop::TEXT_SIZE, Expr("2px") },
|
||||||
{ Gui::StyleRule::TEXT_SIZE, Expr("2px") },
|
{ Gui::Prop::SIZE, array<Expr, 2> { Expr("100dp"), Expr("-1") } },
|
||||||
{ Gui::StyleRule::SIZE, array<Expr, 2> { Expr("100dp"), Expr("-1") } },
|
{ Gui::Prop::CONTENT, string("`cfEncountered a fatal mod error ;-;\n\n`r") + err },
|
||||||
{ Gui::StyleRule::CONTENT, string("`cfEncountered a fatal mod error ;-;\n\n`r") + err },
|
{ Gui::Prop::MARGIN, array<Expr, 4> { Expr("4dp"), Expr("4dp"), Expr("4dp"), Expr("4dp") } }
|
||||||
{ Gui::StyleRule::MARGIN, array<Expr, 4> { Expr("4dp"), Expr("4dp"), Expr("4dp"), Expr("4dp") } }
|
}});
|
||||||
}}
|
|
||||||
});
|
|
||||||
|
|
||||||
root.body->onClick([&](i32 button, bool down) {
|
root.body->onClick([&](i32 button, bool down) {
|
||||||
if (button != GLFW_MOUSE_BUTTON_1 || !down) return;
|
if (button != GLFW_MOUSE_BUTTON_1 || !down) return;
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
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" }})),
|
sandboxElem(root.create<Gui::BoxElement>()),
|
||||||
sandbox(client, root, sandboxElem) {
|
sandbox(client, root, sandboxElem) {
|
||||||
|
|
||||||
client.renderer.setClearColor(0, 0, 0);
|
client.renderer.setClearColor(0, 0, 0);
|
||||||
|
@ -28,78 +28,68 @@ MainMenuScene::MainMenuScene(Client& client) : Scene(client),
|
||||||
|
|
||||||
root.addStylesheet({
|
root.addStylesheet({
|
||||||
{ "navigation", {{
|
{ "navigation", {{
|
||||||
{ Gui::StyleRule::SIZE, array<Expr, 2> { Expr(""), Expr("18dp") } }
|
{ Gui::Prop::SIZE, array<Expr, 2> { Expr(""), Expr("18dp") } }
|
||||||
}}},
|
}}},
|
||||||
{ "navigationWrap", {{
|
{ "navigationWrap", {{
|
||||||
{ Gui::StyleRule::DIRECTION, string("row") },
|
{ Gui::Prop::DIRECTION, string("row") },
|
||||||
{ Gui::StyleRule::POS, array<Expr, 2> { Expr("0"), Expr("0") } }
|
{ Gui::Prop::POS, array<Expr, 2> { Expr("0"), Expr("0") } }
|
||||||
}}},
|
}}},
|
||||||
{ "navigationBackground", {{
|
{ "navigationBackground", {{
|
||||||
{ Gui::StyleRule::SIZE, array<Expr, 2> { Expr("64dp"), Expr("18dp") } },
|
{ Gui::Prop::SIZE, array<Expr, 2> { Expr("64dp"), Expr("18dp") } },
|
||||||
{ Gui::StyleRule::BACKGROUND, string("menu_bar_bg") }
|
{ Gui::Prop::BACKGROUND, string("menu_bar_bg") }
|
||||||
}}},
|
}}},
|
||||||
{ "navigationButton", {{
|
{ "navigationButton", {{
|
||||||
{ Gui::StyleRule::SIZE, array<Expr, 2> { Expr("16dp"), Expr("16dp") } },
|
{ Gui::Prop::SIZE, array<Expr, 2> { Expr("16dp"), Expr("16dp") } },
|
||||||
{ Gui::StyleRule::CURSOR, string("pointer") }
|
{ Gui::Prop::CURSOR, string("pointer") }
|
||||||
}}}
|
}}}
|
||||||
});
|
});
|
||||||
|
|
||||||
root.body->append(sandboxElem);
|
root.body->append(sandboxElem);
|
||||||
let navigation = root.body->append<Gui::BoxElement>({ .classes = { "navigation" } });
|
let navigation = root.body->append<Gui::BoxElement>({{{ Gui::Prop::CLASS, vec<string> { "navigation" } }}});
|
||||||
let navigationBG = navigation->append<Gui::BoxElement>({ .classes = { "navigationWrap" } });
|
let navigationBG = navigation->append<Gui::BoxElement>({{{ Gui::Prop::CLASS, vec<string> { "navigationWrap" } }}});
|
||||||
|
|
||||||
for (usize i = 0; i < 2000 / Gui::PX_SCALE / 64; i++)
|
for (usize i = 0; i < 2000 / Gui::PX_SCALE / 64; i++)
|
||||||
navigationBG->append<Gui::BoxElement>({ .classes = { "navigationBackground" } });
|
navigationBG->append<Gui::BoxElement>({{{ Gui::Prop::CLASS, vec<string> { "navigationBackground" } }}});
|
||||||
|
|
||||||
let navigationList = navigation->append<Gui::BoxElement>({
|
let navigationList = navigation->append<Gui::BoxElement>({{
|
||||||
.classes = { "navigationWrap" },
|
{ Gui::Prop::CLASS, vec<string> { "navigationWrap" } },
|
||||||
.styles = {{
|
{ Gui::Prop::GAP, array<Expr, 2> { Expr("1dp"), Expr("1dp") } },
|
||||||
{ Gui::StyleRule::PADDING, array<Expr, 4> { Expr("1dp"), Expr("1dp"), Expr("1dp"), Expr("1dp") } },
|
{ Gui::Prop::PADDING, array<Expr, 4> { Expr("1dp"), Expr("1dp"), Expr("1dp"), Expr("1dp") } }
|
||||||
{ Gui::StyleRule::GAP, array<Expr, 2> { Expr("1dp"), Expr("1dp") } }
|
}});
|
||||||
}}
|
|
||||||
});
|
|
||||||
|
|
||||||
navigationList->append<Gui::BoxElement>({
|
navigationList->append<Gui::BoxElement>({{
|
||||||
.classes = { "navigationButton" },
|
{ Gui::Prop::CLASS, vec<string> { "navigationButton" } },
|
||||||
.styles = {{
|
{ Gui::Prop::BACKGROUND, string("crop(0, 0, 16, 16, menu_flag_multiplayer)") },
|
||||||
{ Gui::StyleRule::BACKGROUND, string("crop(0, 0, 16, 16, menu_flag_multiplayer)") },
|
{ Gui::Prop::BACKGROUND_HOVER, string("crop(16, 0, 16, 16, menu_flag_multiplayer)") }
|
||||||
{ Gui::StyleRule::BACKGROUND_HOVER, string("crop(16, 0, 16, 16, menu_flag_multiplayer)") }
|
}});
|
||||||
}}
|
|
||||||
});
|
|
||||||
|
|
||||||
let contentButton = navigationList->append<Gui::BoxElement>({
|
let contentButton = navigationList->append<Gui::BoxElement>({{
|
||||||
.classes = { "navigationButton" },
|
{ Gui::Prop::CLASS, vec<string> { "navigationButton" } },
|
||||||
.styles = {{
|
{ Gui::Prop::BACKGROUND, string("crop(0, 0, 16, 16, menu_flag_content)") },
|
||||||
{ Gui::StyleRule::BACKGROUND, string("crop(0, 0, 16, 16, menu_flag_content)") },
|
{ Gui::Prop::BACKGROUND_HOVER, string("crop(16, 0, 16, 16, menu_flag_content)") }
|
||||||
{ Gui::StyleRule::BACKGROUND_HOVER, string("crop(16, 0, 16, 16, menu_flag_content)") }
|
}});
|
||||||
}}
|
|
||||||
});
|
|
||||||
|
|
||||||
contentButton->onClick([&](u32 button, bool down) {
|
contentButton->onClick([&](u32 button, bool down) {
|
||||||
if (button != GLFW_MOUSE_BUTTON_1 || !down) return;
|
if (button != GLFW_MOUSE_BUTTON_1 || !down) return;
|
||||||
client.scene.setScene(make_unique<ConnectScene>(client, Address { "127.0.0.1" }));
|
client.scene.setScene(make_unique<ConnectScene>(client, Address { "127.0.0.1" }));
|
||||||
});
|
});
|
||||||
|
|
||||||
navigationList->append<Gui::BoxElement>({
|
navigationList->append<Gui::BoxElement>({{
|
||||||
.styles = {{
|
{ Gui::Prop::BACKGROUND, string("#fff5") },
|
||||||
{ Gui::StyleRule::BACKGROUND, string("#fff5") },
|
{ Gui::Prop::SIZE, array<Expr, 2> { Expr("1dp"), Expr("10dp") } },
|
||||||
{ Gui::StyleRule::SIZE, array<Expr, 2> { Expr("1dp"), Expr("10dp") } },
|
{ Gui::Prop::MARGIN, array<Expr, 4> { Expr("2dp"), Expr("3dp"), Expr("2dp"), Expr("3dp") } }
|
||||||
{ Gui::StyleRule::MARGIN, array<Expr, 4> { Expr("2dp"), Expr("3dp"), Expr("2dp"), Expr("3dp") } }
|
}});
|
||||||
}}
|
|
||||||
});
|
|
||||||
|
|
||||||
findSubgames();
|
findSubgames();
|
||||||
|
|
||||||
for (usize i = 0; i < subgames.size(); i++) {
|
for (usize i = 0; i < subgames.size(); i++) {
|
||||||
let& subgame = subgames[i];
|
let& subgame = subgames[i];
|
||||||
|
|
||||||
let elem = navigationList->append<Gui::BoxElement>({
|
let elem = navigationList->append<Gui::BoxElement>({{
|
||||||
.classes = { "navigationButton" },
|
{ Gui::Prop::CLASS, vec<string> { "navigationButton" } },
|
||||||
.styles = {{
|
{ Gui::Prop::BACKGROUND, string("crop(0, 0, 16, 16, " + subgame.iconRef->name + ")") },
|
||||||
{ Gui::StyleRule::BACKGROUND, string("crop(0, 0, 16, 16, " + subgame.iconRef->name + ")") },
|
{ Gui::Prop::BACKGROUND_HOVER, string("crop(16, 0, 16, 16, " + subgame.iconRef->name + ")") }
|
||||||
{ Gui::StyleRule::BACKGROUND_HOVER, string("crop(16, 0, 16, 16, " + subgame.iconRef->name + ")") }
|
}});
|
||||||
}}
|
|
||||||
});
|
|
||||||
|
|
||||||
elem->onClick([&](u32 button, bool down) {
|
elem->onClick([&](u32 button, bool down) {
|
||||||
if (button != GLFW_MOUSE_BUTTON_1 || !down) return;
|
if (button != GLFW_MOUSE_BUTTON_1 || !down) return;
|
||||||
|
@ -115,21 +105,17 @@ MainMenuScene::MainMenuScene(Client& client) : Scene(client),
|
||||||
|
|
||||||
navigationList->append<Gui::BoxElement>();
|
navigationList->append<Gui::BoxElement>();
|
||||||
|
|
||||||
navigationList->append<Gui::BoxElement>({
|
navigationList->append<Gui::BoxElement>({{
|
||||||
.classes = { "navigationButton" },
|
{ Gui::Prop::CLASS, vec<string> { "navigationButton" } },
|
||||||
.styles = {{
|
{ Gui::Prop::BACKGROUND, string("crop(0, 0, 16, 16, menu_flag_settings)") },
|
||||||
{ Gui::StyleRule::BACKGROUND, string("crop(0, 0, 16, 16, menu_flag_settings)") },
|
{ Gui::Prop::BACKGROUND_HOVER, string("crop(16, 0, 16, 16, menu_flag_settings)") }
|
||||||
{ Gui::StyleRule::BACKGROUND_HOVER, string("crop(16, 0, 16, 16, menu_flag_settings)") }
|
}});
|
||||||
}}
|
|
||||||
});
|
|
||||||
|
|
||||||
let closeButton = navigationList->append<Gui::BoxElement>({
|
let closeButton = navigationList->append<Gui::BoxElement>({{
|
||||||
.classes = { "navigationButton" },
|
{ Gui::Prop::CLASS, vec<string> { "navigationButton" } },
|
||||||
.styles = {{
|
{ Gui::Prop::BACKGROUND, string("crop(0, 0, 16, 16, menu_flag_quit)") },
|
||||||
{ Gui::StyleRule::BACKGROUND, string("crop(0, 0, 16, 16, menu_flag_quit)") },
|
{ Gui::Prop::BACKGROUND_HOVER, string("crop(16, 0, 16, 16, menu_flag_quit)") }
|
||||||
{ Gui::StyleRule::BACKGROUND_HOVER, string("crop(16, 0, 16, 16, menu_flag_quit)") }
|
}});
|
||||||
}}
|
|
||||||
});
|
|
||||||
|
|
||||||
closeButton->onClick([](u32 button, bool down) {
|
closeButton->onClick([](u32 button, bool down) {
|
||||||
if (button != GLFW_MOUSE_BUTTON_1 || !down) return;
|
if (button != GLFW_MOUSE_BUTTON_1 || !down) return;
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "usertype/InventoryList.h"
|
#include "usertype/InventoryList.h"
|
||||||
#include "usertype/AnimationManager.h"
|
#include "usertype/AnimationManager.h"
|
||||||
|
|
||||||
#include "usertype/LuaGuiElement.h"
|
#include "usertype/GuiElement.h"
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
#include "modules/Time.h"
|
#include "modules/Time.h"
|
||||||
|
@ -57,17 +57,18 @@ void LocalLuaParser::init(WorldPtr world, PlayerPtr player, Client& client) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const let& line : lines) {
|
for (const let& line : lines) {
|
||||||
usize lineNumStart = line.find(':');
|
usize fileNameStart = line.find('/');
|
||||||
|
if (fileNameStart == string::npos) continue;
|
||||||
|
usize lineNumStart = line.find(':', fileNameStart + 1);
|
||||||
if (lineNumStart == string::npos) continue;
|
if (lineNumStart == string::npos) continue;
|
||||||
usize lineNumEnd = line.find(':', lineNumStart + 1);
|
usize lineNumEnd = line.find(':', lineNumStart + 1);
|
||||||
if (lineNumEnd == string::npos) continue;
|
if (lineNumEnd == string::npos) continue;
|
||||||
|
|
||||||
string fullPath = line.substr(0, lineNumStart);
|
string fullPath = line.substr(0, lineNumStart);
|
||||||
fullPath.erase(std::remove_if(fullPath.begin(), fullPath.end(), isspace), fullPath.end());
|
fullPath.erase(std::remove_if(fullPath.begin(), fullPath.end(), isspace), fullPath.end());
|
||||||
|
|
||||||
usize slashPos = fullPath.find('/');
|
fileNameStart = fullPath.find('/');
|
||||||
if (slashPos == string::npos) continue;
|
string modName = fullPath.substr(0, fileNameStart);
|
||||||
string modName = fullPath.substr(0, slashPos);
|
|
||||||
if (modName == "base") continue;
|
if (modName == "base") continue;
|
||||||
|
|
||||||
let iter = mods.find(modName);
|
let iter = mods.find(modName);
|
||||||
|
|
|
@ -0,0 +1,212 @@
|
||||||
|
#include "GuiElement.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"
|
||||||
|
|
||||||
|
static const Gui::Expression parseObjectToExpr(sol::object value) {
|
||||||
|
if (!value.valid()) return Gui::Expression("");
|
||||||
|
if (value.is<f32>()) return Gui::Expression(std::to_string(value.as<f32>()) + "dp");
|
||||||
|
if (value.is<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 {};
|
||||||
|
|
||||||
|
if (value.is<sol::table>()) {
|
||||||
|
const let& t = value.as<sol::table>();
|
||||||
|
|
||||||
|
vec<Gui::Expression> exprs {};
|
||||||
|
exprs.reserve(t.size());
|
||||||
|
for (usize i = 1; i <= t.size(); i++)
|
||||||
|
exprs.emplace_back(parseObjectToExpr(t.get<sol::object>(i)));
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gui::Prop Api::Usertype::GuiElement::nameToProp(const string& str) {
|
||||||
|
using namespace Gui;
|
||||||
|
|
||||||
|
const let ruleIt = Props::PROP_NAMES_TO_ENUM.find(str);
|
||||||
|
if (ruleIt == Props::PROP_NAMES_TO_ENUM.end())
|
||||||
|
throw std::invalid_argument("Style rule '" + str + "' doesn't exist.");
|
||||||
|
return ruleIt->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
any Api::Usertype::GuiElement::objectToProp(Gui::Prop prop, const sol::object& value) {
|
||||||
|
using namespace Gui;
|
||||||
|
|
||||||
|
switch (prop) {
|
||||||
|
default:
|
||||||
|
throw std::invalid_argument("Unhandled rule! This is an engine error! [1]");
|
||||||
|
|
||||||
|
case Prop::ID:
|
||||||
|
case Prop::LAYOUT:
|
||||||
|
case Prop::DIRECTION:
|
||||||
|
case Prop::H_ALIGN:
|
||||||
|
case Prop::V_ALIGN:
|
||||||
|
case Prop::CURSOR:
|
||||||
|
case Prop::OVERFLOW:
|
||||||
|
case Prop::TEXT_COLOR:
|
||||||
|
case Prop::BACKGROUND:
|
||||||
|
case Prop::BACKGROUND_HOVER:
|
||||||
|
case Prop::CONTENT:
|
||||||
|
return value.as<string>();
|
||||||
|
|
||||||
|
case Prop::POS:
|
||||||
|
case Prop::SIZE:
|
||||||
|
case Prop::GAP:
|
||||||
|
return parseLengthTableVal<2>(value);
|
||||||
|
|
||||||
|
case Prop::MARGIN:
|
||||||
|
case Prop::PADDING:
|
||||||
|
return parseLengthTableVal<4>(value);
|
||||||
|
|
||||||
|
case Prop::TEXT_SIZE:
|
||||||
|
return parseObjectToExpr(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sol::object Api::Usertype::GuiElement::propToObject(Gui::Prop prop, any value, sol::state_view s) {
|
||||||
|
using namespace Gui;
|
||||||
|
|
||||||
|
switch (prop) {
|
||||||
|
default:
|
||||||
|
throw std::invalid_argument("Unhandled rule! This is an engine error! [1]");
|
||||||
|
|
||||||
|
case Prop::LAYOUT:
|
||||||
|
case Prop::DIRECTION:
|
||||||
|
case Prop::H_ALIGN:
|
||||||
|
case Prop::V_ALIGN:
|
||||||
|
case Prop::CURSOR:
|
||||||
|
case Prop::OVERFLOW:
|
||||||
|
// case Prop::TEXT_COLOR:
|
||||||
|
case Prop::BACKGROUND:
|
||||||
|
case Prop::BACKGROUND_HOVER:
|
||||||
|
case Prop::CONTENT:
|
||||||
|
return sol::make_object(s, std::any_cast<string>(value));
|
||||||
|
|
||||||
|
case Prop::POS:
|
||||||
|
case Prop::SIZE:
|
||||||
|
case Prop::GAP:
|
||||||
|
|
||||||
|
// return sol::make_object(s, s.create_table_with(
|
||||||
|
//
|
||||||
|
// ));
|
||||||
|
// return sol::make_object(s, std::any_cast<string>(value));
|
||||||
|
|
||||||
|
case Prop::MARGIN:
|
||||||
|
case Prop::PADDING:
|
||||||
|
// return parseLengthTableVal<4>(value);
|
||||||
|
|
||||||
|
case Prop::TEXT_SIZE:
|
||||||
|
break;
|
||||||
|
throw std::invalid_argument("Unhandled rule! This is an engine error! [1]");
|
||||||
|
// return parseObjectToExpr(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sptr<Gui::Element> Api::Usertype::GuiElement::create(const string& type, sol::table data, Gui::Root& root) {
|
||||||
|
Gui::Props props {};
|
||||||
|
|
||||||
|
for (let& style : data) {
|
||||||
|
if (!style.first.is<string>()) continue;
|
||||||
|
let rule = GuiElement::nameToProp(style.first.as<string>());
|
||||||
|
let value = GuiElement::objectToProp(rule, style.second);
|
||||||
|
props.props[rule] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Api::Usertype::GuiElement::bind(sol::state& lua, sol::table& core, Gui::Root& root) {
|
||||||
|
lua.new_usertype<Gui::Element>("GuiElement",
|
||||||
|
sol::meta_function::construct, sol::factories([&](const string& type, sol::table data) {
|
||||||
|
return GuiElement::create(type, data, root);
|
||||||
|
}),
|
||||||
|
"prepend", [&](sol::this_state s, Gui::Element& self, sol::object child) {
|
||||||
|
if (child.is<sptr<Gui::Element>>()) self.prepend(child.as<sptr<Gui::Element>>());
|
||||||
|
else if (child.is<sol::protected_function>()) {
|
||||||
|
sol::protected_function fn = child.as<sol::protected_function>();
|
||||||
|
sol::table tbl = sol::state_view(s)["zepha"]["__builtin"]["gui_env"];
|
||||||
|
sol::environment env(s, sol::create, tbl);
|
||||||
|
sol::set_environment(env, fn);
|
||||||
|
self.prepend(static_cast<sol::object>(fn()).as<sptr<Gui::Element>>());
|
||||||
|
}
|
||||||
|
else throw std::invalid_argument(
|
||||||
|
"Cannot append() an item that is not an element or a function that returns one.");
|
||||||
|
},
|
||||||
|
"append", [&](sol::this_state s, Gui::Element& self, sol::object child) {
|
||||||
|
if (child.is<sptr<Gui::Element>>()) self.append(child.as<sptr<Gui::Element>>());
|
||||||
|
else if (child.is<sol::protected_function>()) {
|
||||||
|
let fn = child.as<sol::protected_function>();
|
||||||
|
sol::table tbl = sol::state_view(s)["zepha"]["__builtin"]["gui_env"];
|
||||||
|
sol::environment env(s, sol::create, tbl);
|
||||||
|
sol::set_environment(env, fn);
|
||||||
|
self.append(static_cast<sol::object>(fn()).as<sptr<Gui::Element>>());
|
||||||
|
}
|
||||||
|
else throw std::invalid_argument(
|
||||||
|
"append() parameter must be an element or a function that returns one.");
|
||||||
|
},
|
||||||
|
"get", [&](sol::this_state s, Gui::Element& self, sol::object query) -> sol::object {
|
||||||
|
let found = query.is<u32>() ? self.get(query.as<u32>() - 1) : self.get(query.as<string>());
|
||||||
|
if (!found) return sol::nil;
|
||||||
|
return sol::make_object(s, found);
|
||||||
|
},
|
||||||
|
"remove", [&](sol::this_state s, Gui::Element& self, sol::object query) {
|
||||||
|
if (query == sol::nil) self.remove();
|
||||||
|
else if (query.is<u32>()) {
|
||||||
|
let child = self.get(query.as<u32>());
|
||||||
|
if (child) child->remove();
|
||||||
|
}
|
||||||
|
else if (query.is<std::string>()) {
|
||||||
|
let child = self.get(query.as<std::string>());
|
||||||
|
if (child) child->remove();
|
||||||
|
}
|
||||||
|
else if (query.is<sptr<Gui::Element>>()) {
|
||||||
|
query.as<sptr<Gui::Element>>()->remove();
|
||||||
|
}
|
||||||
|
else throw std::invalid_argument(
|
||||||
|
"remove() parameter must be nil, a number, an string, or a Gui element.");
|
||||||
|
},
|
||||||
|
"clear", &Gui::Element::clear,
|
||||||
|
sol::meta_function::new_index, [&](Gui::Element& self, const string& ruleStr, sol::object rawValue) {
|
||||||
|
let rule = GuiElement::nameToProp(ruleStr);
|
||||||
|
let value = GuiElement::objectToProp(rule, rawValue);
|
||||||
|
self.setProp(rule, value);
|
||||||
|
self.updateElement();
|
||||||
|
},
|
||||||
|
sol::meta_function::index, [&](sol::this_state s, Gui::Element& self, const string& ruleStr) {
|
||||||
|
let rule = GuiElement::nameToProp(ruleStr);
|
||||||
|
let value = self.getProps().get(rule);
|
||||||
|
if (!value) return sol::make_object(s, sol::nil);
|
||||||
|
return GuiElement::propToObject(rule, *value, s);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
|
@ -8,13 +8,13 @@ namespace Gui {
|
||||||
class Style;
|
class Style;
|
||||||
class Root;
|
class Root;
|
||||||
class Element;
|
class Element;
|
||||||
enum class StyleRule;
|
enum class Prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Api::Usertype::GuiElement {
|
namespace Api::Usertype::GuiElement {
|
||||||
Gui::StyleRule ruleFromStr(const string& str);
|
Gui::Prop nameToProp(const string& str);
|
||||||
any parseRuleValue(Gui::StyleRule rule, const sol::object& value);
|
any objectToProp(Gui::Prop prop, const sol::object& value);
|
||||||
sol::object styleAnyToObject(Gui::StyleRule rule, optional<any> value, sol::this_state s);
|
sol::object propToObject(Gui::Prop prop, any value, sol::state_view s);
|
||||||
|
|
||||||
std::shared_ptr<Gui::Element> create(const string& type, sol::table data, Gui::Root& root);
|
std::shared_ptr<Gui::Element> create(const string& type, sol::table data, Gui::Root& root);
|
||||||
|
|
|
@ -1,333 +0,0 @@
|
||||||
#include "LuaGuiElement.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"
|
|
||||||
|
|
||||||
static const Gui::Expression parseObjectToExpr(sol::object value) {
|
|
||||||
if (!value.valid()) return Gui::Expression("");
|
|
||||||
if (value.is<f32>()) return Gui::Expression(std::to_string(value.as<f32>()) + "dp");
|
|
||||||
if (value.is<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 {};
|
|
||||||
|
|
||||||
if (value.is<sol::table>()) {
|
|
||||||
const let& t = value.as<sol::table>();
|
|
||||||
|
|
||||||
vec<Gui::Expression> exprs {};
|
|
||||||
exprs.reserve(t.size());
|
|
||||||
for (usize i = 1; i <= t.size(); i++)
|
|
||||||
exprs.emplace_back(parseObjectToExpr(t.get<sol::object>(i)));
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
Gui::StyleRule Api::Usertype::GuiElement::ruleFromStr(const string& str) {
|
|
||||||
using namespace Gui;
|
|
||||||
|
|
||||||
const let ruleIt = Style::RULE_STRINGS_TO_ENUMS.find(str);
|
|
||||||
if (ruleIt == Style::RULE_STRINGS_TO_ENUMS.end())
|
|
||||||
throw std::invalid_argument("Style rule '" + str + "' doesn't exist.");
|
|
||||||
return ruleIt->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
any Api::Usertype::GuiElement::parseRuleValue(Gui::StyleRule rule, const sol::object& value) {
|
|
||||||
using namespace Gui;
|
|
||||||
|
|
||||||
switch (rule) {
|
|
||||||
default:
|
|
||||||
throw std::invalid_argument("Unhandled rule! This is an engine error! [1]");
|
|
||||||
|
|
||||||
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:
|
|
||||||
return value.as<string>();
|
|
||||||
|
|
||||||
case StyleRule::POS:
|
|
||||||
case StyleRule::SIZE:
|
|
||||||
case StyleRule::GAP:
|
|
||||||
return parseLengthTableVal<2>(value);
|
|
||||||
|
|
||||||
case StyleRule::MARGIN:
|
|
||||||
case StyleRule::PADDING:
|
|
||||||
return parseLengthTableVal<4>(value);
|
|
||||||
|
|
||||||
case StyleRule::TEXT_SIZE:
|
|
||||||
return parseObjectToExpr(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sol::object Api::Usertype::GuiElement::styleAnyToObject(Gui::StyleRule rule, optional<any> value, sol::this_state s) {
|
|
||||||
using namespace Gui;
|
|
||||||
|
|
||||||
switch (rule) {
|
|
||||||
default:
|
|
||||||
throw std::invalid_argument("Unhandled rule! This is an engine error! [1]");
|
|
||||||
|
|
||||||
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:
|
|
||||||
return sol::make_object(s, std::any_cast<string>(value));
|
|
||||||
|
|
||||||
case StyleRule::POS:
|
|
||||||
case StyleRule::SIZE:
|
|
||||||
case StyleRule::GAP:
|
|
||||||
// return sol::make_object(s, std::any_cast<string>(value));
|
|
||||||
|
|
||||||
case StyleRule::MARGIN:
|
|
||||||
case StyleRule::PADDING:
|
|
||||||
// return parseLengthTableVal<4>(value);
|
|
||||||
|
|
||||||
case StyleRule::TEXT_SIZE:
|
|
||||||
break;
|
|
||||||
// return parseObjectToExpr(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sptr<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;
|
|
||||||
let rule = GuiElement::ruleFromStr(style.first.as<string>());
|
|
||||||
let value = GuiElement::parseRuleValue(rule, style.second);
|
|
||||||
props.styles.rules[rule] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Api::Usertype::GuiElement::bind(sol::state& lua, sol::table& core, Gui::Root& root) {
|
|
||||||
lua.new_usertype<Gui::Element>("GuiElement",
|
|
||||||
sol::meta_function::construct, sol::factories([&](const string& type, sol::table data) {
|
|
||||||
return GuiElement::create(type, data, root);
|
|
||||||
}),
|
|
||||||
"append", [&](Gui::Element& self, sptr<Gui::Element> child) {
|
|
||||||
self.append(child);
|
|
||||||
},
|
|
||||||
"get", [&](sol::this_state s, Gui::Element& self, sol::object query) -> sol::object {
|
|
||||||
if (query.is<u32>()) {
|
|
||||||
let found = self.get(query.as<u32>() - 1);
|
|
||||||
if (!found) return sol::nil;
|
|
||||||
return sol::make_object(s, found);
|
|
||||||
}
|
|
||||||
else throw std::runtime_error("ID get is unimplemented.");
|
|
||||||
},
|
|
||||||
sol::meta_function::new_index, [&](Gui::Element& self, const string& ruleStr, sol::object rawValue) {
|
|
||||||
let rule = GuiElement::ruleFromStr(ruleStr);
|
|
||||||
let value = GuiElement::parseRuleValue(rule, rawValue);
|
|
||||||
self.setStyle(rule, value);
|
|
||||||
self.updateElement();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
//// 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;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// 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");
|
|
||||||
//}
|
|
|
@ -21,15 +21,15 @@ LocalPlayer::LocalPlayer(SubgamePtr game, LocalWorld& world, DimensionPtr dim, R
|
||||||
renderer(renderer) {
|
renderer(renderer) {
|
||||||
handItemModel.parent = &handModel;
|
handItemModel.parent = &handModel;
|
||||||
|
|
||||||
hud = root.body->append<Gui::BoxElement>({ .styles {{
|
hud = root.body->append<Gui::BoxElement>({{
|
||||||
{ Gui::StyleRule::POS, array<Gui::Expression, 2> { Gui::Expression("0"), Gui::Expression("0") }},
|
{ Gui::Prop::POS, array<Gui::Expression, 2> { Gui::Expression("0"), Gui::Expression("0") }},
|
||||||
{ Gui::StyleRule::SIZE, array<Gui::Expression, 2> { Gui::Expression("100cw"), Gui::Expression("100ch") }}
|
{ Gui::Prop::SIZE, array<Gui::Expression, 2> { Gui::Expression("100cw"), Gui::Expression("100ch") }}
|
||||||
}}});
|
}});
|
||||||
|
|
||||||
menu = root.body->append<Gui::BoxElement>({ .styles {{
|
menu = root.body->append<Gui::BoxElement>({{
|
||||||
{ Gui::StyleRule::POS, array<Gui::Expression, 2> { Gui::Expression("0"), Gui::Expression("0") }},
|
{ Gui::Prop::POS, array<Gui::Expression, 2> { Gui::Expression("0"), Gui::Expression("0") }},
|
||||||
{ Gui::StyleRule::SIZE, array<Gui::Expression, 2> { Gui::Expression("100cw"), Gui::Expression("100ch") }}
|
{ Gui::Prop::SIZE, array<Gui::Expression, 2> { Gui::Expression("100cw"), Gui::Expression("100ch") }}
|
||||||
}}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPlayer::update(f64 delta, vec2 mouseDelta) {
|
void LocalPlayer::update(f64 delta, vec2 mouseDelta) {
|
||||||
|
|
|
@ -66,13 +66,15 @@ for _ = 1, 100 do
|
||||||
end
|
end
|
||||||
|
|
||||||
local particle_wrap = menu:get(1)
|
local particle_wrap = menu:get(1)
|
||||||
for i, pos in ipairs(positions) do
|
zepha.gui(function()
|
||||||
particle_wrap:append(zepha.Gui.Box {
|
for i, pos in ipairs(positions) do
|
||||||
pos = pos,
|
particle_wrap:append(Gui.Box {
|
||||||
background = 'particle_dark',
|
pos = pos,
|
||||||
size = sizes[i]
|
background = 'particle_dark',
|
||||||
})
|
size = sizes[i]
|
||||||
end
|
})
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
local tick = 0
|
local tick = 0
|
||||||
zepha.after(function()
|
zepha.after(function()
|
||||||
|
|
|
@ -1,25 +1,24 @@
|
||||||
local max_messages = 8
|
local max_messages = 8
|
||||||
|
|
||||||
local chat_wrap = zepha.build_gui(function()
|
local chat_wrap = zepha.gui(function()
|
||||||
return Gui.Rect {
|
return Gui.Box {
|
||||||
position = { 4, '100%' },
|
pos = { 4, '100ch - 100sh - 100dp' },
|
||||||
position_anchor = { 0, '200%' },
|
|
||||||
size = { 256, 23 + max_messages * 8 },
|
size = { 256, 23 + max_messages * 8 },
|
||||||
|
|
||||||
Gui.Rect {
|
Gui.Box {
|
||||||
key = 'chat_tabs',
|
id = 'chat_tabs',
|
||||||
position = { 0, -10 }
|
pos = { 0, -10 }
|
||||||
},
|
},
|
||||||
|
|
||||||
Gui.Rect {
|
Gui.Box {
|
||||||
key = 'chat_box',
|
id = 'chat_box',
|
||||||
size = { 256, 2 + max_messages * 8 }
|
size = { 256, 2 + max_messages * 8 }
|
||||||
},
|
},
|
||||||
|
|
||||||
Gui.Rect {
|
Gui.Box {
|
||||||
key = 'chat_input',
|
id = 'chat_input',
|
||||||
size = { 256, 10 },
|
size = { 256, 10 },
|
||||||
position = { 0, 3 + max_messages * 8 }
|
pos = { 0, 3 + max_messages * 8 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
require(_PATH .. 'api')
|
require(_PATH .. 'api')
|
||||||
if zepha.client then runfile(_PATH .. 'gui') end
|
if zepha.client then require(_PATH .. 'gui') end
|
||||||
|
|
||||||
if zepha.server then
|
if zepha.server then
|
||||||
chat.create_channel('chat', { name = 'Chat', icon = '@auri:chat:chat_icon' })
|
chat.create_channel('chat', { name = 'Chat', icon = '@auri:chat:chat_icon' })
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
_G['health'] = {}
|
-- _G['health'] = {}
|
||||||
health.internal = {}
|
-- health.internal = {}
|
||||||
|
--
|
||||||
require(_PATH .. 'api')
|
-- require(_PATH .. 'api')
|
||||||
require(_PATH .. 'interface')
|
-- require(_PATH .. 'interface')
|
||||||
require(_PATH .. 'hooks')
|
-- require(_PATH .. 'hooks')
|
|
@ -14,7 +14,7 @@ function health.internal.update()
|
||||||
|
|
||||||
health.internal._wrapper:remove('@health:component')
|
health.internal._wrapper:remove('@health:component')
|
||||||
health.internal._wrapper:append(function()
|
health.internal._wrapper:append(function()
|
||||||
local elem = Gui.Rect {
|
local elem = Gui.Box {
|
||||||
id = '@health:component',
|
id = '@health:component',
|
||||||
size = { health.internal._width, 9 },
|
size = { health.internal._width, 9 },
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
_G["hot_wheel"] = {}
|
-- _G["hot_wheel"] = {}
|
||||||
|
--
|
||||||
if zepha.server then
|
-- if zepha.server then
|
||||||
require(_PATH .. "register")
|
-- require(_PATH .. "register")
|
||||||
end
|
-- end
|
||||||
|
--
|
||||||
if zepha.client then
|
-- if zepha.client then
|
||||||
require(_PATH .. "interface")
|
-- require(_PATH .. "interface")
|
||||||
require(_PATH .. "keys")
|
-- require(_PATH .. "keys")
|
||||||
end
|
-- end
|
||||||
|
|
|
@ -1,49 +1,45 @@
|
||||||
local chest = zepha.build_gui(function()
|
local chest = zepha.gui(function()
|
||||||
return Gui.Body {
|
return Gui.Box {
|
||||||
background = "#0003",
|
background = "#0003",
|
||||||
|
|
||||||
callbacks = {
|
-- Gui.Rect {
|
||||||
primary = function() zepha.player:close_menu() end,
|
-- key = "inventory",
|
||||||
},
|
-- position = { pc(50), pc(50) },
|
||||||
|
-- position_anchor = { pc(50), pc(32) },
|
||||||
Gui.Rect {
|
-- size = { 218, 160 },
|
||||||
key = "inventory",
|
--
|
||||||
position = { pc(50), pc(50) },
|
-- Gui.Rect {
|
||||||
position_anchor = { pc(50), pc(32) },
|
-- key = "inventory_background",
|
||||||
size = { 218, 160 },
|
--
|
||||||
|
-- position = { 0, 50 },
|
||||||
Gui.Rect {
|
-- size = { 218, 100 },
|
||||||
key = "inventory_background",
|
-- padding = { 20, 10, 8, 10 },
|
||||||
|
-- background = "zeus:inventory:inventory",
|
||||||
position = { 0, 50 },
|
--
|
||||||
size = { 218, 100 },
|
-- Gui.InventoryList {
|
||||||
padding = { 20, 10, 8, 10 },
|
-- position = { 1, 1 },
|
||||||
background = "zeus:inventory:inventory",
|
-- slot_spacing = { 2, 2 },
|
||||||
|
-- source = "current_player",
|
||||||
Gui.InventoryList {
|
-- list = "main",
|
||||||
position = { 1, 1 },
|
-- }
|
||||||
slot_spacing = { 2, 2 },
|
-- },
|
||||||
source = "current_player",
|
--
|
||||||
list = "main",
|
-- Gui.Rect {
|
||||||
}
|
-- key = "chest_background",
|
||||||
},
|
--
|
||||||
|
-- position = { 0, -48 },
|
||||||
Gui.Rect {
|
-- size = { 218, 100 },
|
||||||
key = "chest_background",
|
-- padding = { 20, 10, 8, 10 },
|
||||||
|
-- background = "zeus:inventory:chest",
|
||||||
position = { 0, -48 },
|
--
|
||||||
size = { 218, 100 },
|
-- Gui.InventoryList {
|
||||||
padding = { 20, 10, 8, 10 },
|
-- position = { 1, 1 },
|
||||||
background = "zeus:inventory:chest",
|
-- slot_spacing = { 2, 2 },
|
||||||
|
-- source = "current_player",
|
||||||
Gui.InventoryList {
|
-- list = "main",
|
||||||
position = { 1, 1 },
|
-- }
|
||||||
slot_spacing = { 2, 2 },
|
-- }
|
||||||
source = "current_player",
|
-- }
|
||||||
list = "main",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
|
@ -1,127 +1,135 @@
|
||||||
local menu = zepha.build_gui(function()
|
local menu = zepha.gui(function()
|
||||||
return Gui.Body {
|
return Gui.Box {
|
||||||
background = "#0003",
|
background = "#0003",
|
||||||
|
|
||||||
callbacks = {
|
Gui.Box {
|
||||||
primary = function() zepha.player:close_menu() end,
|
id = "inventory",
|
||||||
},
|
|
||||||
|
|
||||||
Gui.Rect {
|
|
||||||
key = "inventory",
|
|
||||||
position = { pc(50), pc(50) },
|
|
||||||
position_anchor = { pc(50), pc(50) },
|
|
||||||
size = { 342, 187 },
|
size = { 342, 187 },
|
||||||
|
pos = { "50cw - 50sw", "50ch - 50sh" },
|
||||||
|
|
||||||
Gui.Rect {
|
Gui.Box {
|
||||||
key = "backpack",
|
id = "backpack",
|
||||||
|
|
||||||
position = { 1, 0 },
|
pos = { 1, 0 },
|
||||||
size = { 106, 187 },
|
size = { 106, 187 },
|
||||||
padding = { 19, 9, 8, 9 },
|
padding = { 19, 9, 8, 9 },
|
||||||
background = "zeus:inventory:backpack",
|
|
||||||
|
|
||||||
Gui.InventoryList {
|
background = "zeus:inventory:backpack"
|
||||||
position = { 0, 0 },
|
|
||||||
slot_spacing = { 2, 2 },
|
-- Gui.InventoryList {
|
||||||
source = "current_player",
|
-- gap = { 2, 2 },
|
||||||
list = "main",
|
-- pos = { 0, 0 },
|
||||||
},
|
--
|
||||||
Gui.InventoryList {
|
-- list = "main",
|
||||||
position = { 0, 18*3 },
|
-- source = "current_player"
|
||||||
slot_spacing = { 2, 2 },
|
-- },
|
||||||
source = "current_player",
|
-- Gui.InventoryList {
|
||||||
list = "hot_wheel_1",
|
-- gap = { 2, 2 },
|
||||||
},
|
-- pos = { 0, 18 * 3 },
|
||||||
Gui.InventoryList {
|
--
|
||||||
position = { 0, 18*4 },
|
-- list = "hot_wheel_1",
|
||||||
slot_spacing = { 2, 2 },
|
-- source = "current_player"
|
||||||
source = "current_player",
|
-- },
|
||||||
list = "hot_wheel_2",
|
-- Gui.InventoryList {
|
||||||
},
|
-- gap = { 2, 2 },
|
||||||
Gui.InventoryList {
|
-- pos = { 0, 18 * 4 },
|
||||||
position = { 0, 18*5 },
|
--
|
||||||
slot_spacing = { 2, 2 },
|
-- list = "hot_wheel_2",
|
||||||
source = "current_player",
|
-- source = "current_player"
|
||||||
list = "hot_wheel_3",
|
-- },
|
||||||
},
|
-- Gui.InventoryList {
|
||||||
Gui.InventoryList {
|
-- gap = { 2, 2 },
|
||||||
position = { 0, 18*6 },
|
-- pos = { 0, 18 * 5 },
|
||||||
slot_spacing = { 2, 2 },
|
--
|
||||||
source = "current_player",
|
-- list = "hot_wheel_3",
|
||||||
list = "hot_wheel_4",
|
-- source = "current_player"
|
||||||
},
|
-- },
|
||||||
Gui.InventoryList {
|
-- Gui.InventoryList {
|
||||||
position = { 0, 18*7 },
|
-- gap = { 2, 2 },
|
||||||
slot_spacing = { 2, 2 },
|
-- pos = { 0, 18 * 6 },
|
||||||
source = "current_player",
|
--
|
||||||
list = "hot_wheel_5",
|
-- list = "hot_wheel_4",
|
||||||
},
|
-- source = "current_player"
|
||||||
Gui.InventoryList {
|
-- },
|
||||||
position = { 0, 18*8 },
|
-- Gui.InventoryList {
|
||||||
slot_spacing = { 2, 2 },
|
-- gap = { 2, 2 },
|
||||||
source = "current_player",
|
-- pos = { 0, 18 * 7 },
|
||||||
list = "hot_wheel_6",
|
--
|
||||||
}
|
-- list = "hot_wheel_5",
|
||||||
|
-- source = "current_player"
|
||||||
|
-- },
|
||||||
|
-- Gui.InventoryList {
|
||||||
|
-- gap = { 2, 2 },
|
||||||
|
-- pos = { 0, 18*8 },
|
||||||
|
--
|
||||||
|
-- list = "hot_wheel_6",
|
||||||
|
-- source = "current_player"
|
||||||
|
-- }
|
||||||
},
|
},
|
||||||
Gui.Rect {
|
Gui.Box {
|
||||||
key = "player_frame",
|
id = "player_frame",
|
||||||
position = { 105, 0 },
|
|
||||||
|
pos = { 105, 0 },
|
||||||
size = { 106, 187 },
|
size = { 106, 187 },
|
||||||
|
|
||||||
background = "zeus:inventory:player_frame",
|
background = "zeus:inventory:player_frame",
|
||||||
|
|
||||||
Gui.Model {
|
-- Gui.Model {
|
||||||
position = { 52, 150 },
|
-- pos = { 52, 150 },
|
||||||
scale = { 64, 64 },
|
-- size = { 64, 64 },
|
||||||
|
--
|
||||||
type = "model",
|
-- type = "model",
|
||||||
source = "zeus:default:player",
|
-- anim_range = { 0, 100 },
|
||||||
texture = "zeus:default:player",
|
-- source = "zeus:default:player",
|
||||||
anim_range = { 0, 100 }
|
-- texture = "zeus:default:player"
|
||||||
}
|
-- }
|
||||||
},
|
},
|
||||||
Gui.Rect {
|
Gui.Box {
|
||||||
key = "equipment",
|
id = "equipment",
|
||||||
|
|
||||||
position = { 209, 1 },
|
pos = { 209, 1 },
|
||||||
size = { 132, 80 },
|
size = { 132, 80 },
|
||||||
padding = { 18, 8, 8, 8 },
|
padding = { 18, 8, 8, 8 },
|
||||||
background = "zeus:inventory:equipment",
|
background = "zeus:inventory:equipment",
|
||||||
|
|
||||||
Gui.Rect {
|
Gui.Box {
|
||||||
key = "player_clamp",
|
id = "player_clamp",
|
||||||
|
|
||||||
position = { 41, 1 },
|
pos = { 41, 1 },
|
||||||
size = { 34, 52 },
|
size = { 34, 52 },
|
||||||
overflow = "hidden"
|
overflow = "hidden"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Gui.Rect {
|
Gui.Box {
|
||||||
key = "dynamic",
|
id = "dynamic",
|
||||||
|
|
||||||
position = { 209, 80 },
|
pos = { 209, 80 },
|
||||||
size = { 132, 107 },
|
size = { 132, 107 },
|
||||||
padding = { 8, 8, 8, 8 },
|
padding = { 8, 8, 8, 8 },
|
||||||
background = "zeus:inventory:dynamic",
|
background = "zeus:inventory:dynamic"
|
||||||
|
|
||||||
Gui.InventoryList {
|
-- Gui.InventoryList {
|
||||||
position = { 1, 1 },
|
-- gap = { 2, 2 },
|
||||||
slot_spacing = { 2, 2 },
|
-- pos = { 1, 1 },
|
||||||
source = "current_player",
|
--
|
||||||
list = "mod",
|
-- list = "mod",
|
||||||
},
|
-- source = "current_player",
|
||||||
|
-- },
|
||||||
Gui.InventoryList {
|
-- Gui.InventoryList {
|
||||||
position = { 41, 32 },
|
-- gap = { 2, 2 },
|
||||||
slot_spacing = { 2, 2 },
|
-- pos = { 41, 32 },
|
||||||
source = "current_player",
|
--
|
||||||
list = "craft",
|
-- list = "craft",
|
||||||
},
|
-- source = "current_player"
|
||||||
Gui.InventoryList {
|
-- },
|
||||||
position = { 81, 41 },
|
-- Gui.InventoryList {
|
||||||
slot_spacing = { 2, 2 },
|
-- gap = { 2, 2 },
|
||||||
source = "current_player",
|
-- pos = { 81, 41 },
|
||||||
list = "craft_result",
|
--
|
||||||
}
|
-- list = "craft_result",
|
||||||
|
-- source = "current_player"
|
||||||
|
-- }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue