Container and self widths, implementation is recursive and slow, fix getComputedSize() by storing elem size in a const.
parent
5bf82c4963
commit
6caef42565
|
@ -17,46 +17,56 @@ void Gui::Element::setStyle(StyleRule style, const std::any& value) {
|
|||
props.styles.rules[style] = value;
|
||||
}
|
||||
|
||||
ivec2 Gui::Element::getComputedSize() {
|
||||
let size = getStyle<ivec2, ValueType::LENGTH>(StyleRule::SIZE, ivec2(-1));
|
||||
if (size.x == -1) size.x = std::max(layoutSize.x, 0);
|
||||
if (size.y == -1) size.y = std::max(layoutSize.y, 0);
|
||||
return size;
|
||||
}
|
||||
|
||||
void Gui::Element::clear() {
|
||||
children.clear();
|
||||
}
|
||||
|
||||
ivec2 Gui::Element::getComputedOuterSize() {
|
||||
void Gui::Element::onClick(const std::function<void(i32, bool)>& cb) {
|
||||
clickCb = cb;
|
||||
}
|
||||
|
||||
Gui::ExpressionInfo Gui::Element::getExpr() const {
|
||||
return {
|
||||
parent ? parent->getComputedSize() : ivec2 {},
|
||||
getComputedSize()
|
||||
};
|
||||
}
|
||||
|
||||
ivec2 Gui::Element::getComputedSize() const {
|
||||
let size = getStyleWithExpr<vec2, ValueType::LENGTH>(StyleRule::SIZE, vec2(nanf("")),
|
||||
{ parent ? parent->getComputedSize() : ivec2 {}, {} });
|
||||
if (std::isnan(size.x)) size.x = std::max(layoutSize.x, 0);
|
||||
if (std::isnan(size.y)) size.y = std::max(layoutSize.y, 0);
|
||||
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() {
|
||||
ivec2 Gui::Element::getComputedContentSize() const {
|
||||
let size = getComputedSize();
|
||||
let padding = getStyle<ivec4, ValueType::LENGTH>(StyleRule::PADDING, {});
|
||||
return glm::max(ivec2 { size.x - padding.x - padding.z, size.y - padding.y - padding.w }, 0);
|
||||
}
|
||||
|
||||
ivec2 Gui::Element::getExplicitSize() {
|
||||
ivec2 Gui::Element::getExplicitSize() const {
|
||||
return getStyle<ivec2, ValueType::LENGTH>(StyleRule::SIZE, ivec2(-1));
|
||||
}
|
||||
|
||||
ivec2 Gui::Element::getComputedPos() {
|
||||
ivec2 Gui::Element::getComputedPos() const {
|
||||
return getStyle<ivec2, ValueType::LENGTH>(StyleRule::POS, layoutPosition);
|
||||
}
|
||||
|
||||
ivec2 Gui::Element::getComputedScreenPos() {
|
||||
ivec2 Gui::Element::getComputedScreenPos() const {
|
||||
return getComputedPos() + parentOffset;
|
||||
}
|
||||
|
||||
bool Gui::Element::handleMouseHover(ivec2 mousePos, bool& pointer) {
|
||||
bool childIntersects = false;
|
||||
for (let& child : children)
|
||||
if (child->handleMouseHover(mousePos, pointer))
|
||||
childIntersects = true;
|
||||
for (let& child : children) if (child->handleMouseHover(mousePos, pointer)) childIntersects = true;
|
||||
|
||||
if (childIntersects) {
|
||||
if (hovered) {
|
||||
|
@ -81,9 +91,17 @@ bool Gui::Element::handleMouseHover(ivec2 mousePos, bool& pointer) {
|
|||
return intersects;
|
||||
}
|
||||
|
||||
bool Gui::Element::handleMouseClick(u32 button, bool down) {
|
||||
for (let& child: children) if (child->handleMouseClick(button, down)) return true;
|
||||
return false;
|
||||
bool Gui::Element::handleMouseClick(ivec2 mousePos, u32 button, bool down) {
|
||||
for (let& child : children) if (child->handleMouseClick(mousePos, button, down)) return true;
|
||||
|
||||
ivec2 size = getComputedSize();
|
||||
ivec2 pos = getComputedScreenPos();
|
||||
bool intersects = mousePos.x >= pos.x && mousePos.x <= pos.x + size.x &&
|
||||
mousePos.y >= pos.y && mousePos.y <= pos.y + size.y;
|
||||
if (!intersects) return false;
|
||||
|
||||
if (clickCb) clickCb(button, down);
|
||||
return clickCb != nullptr;
|
||||
}
|
||||
|
||||
void Gui::Element::draw(Renderer& renderer) {
|
||||
|
@ -160,8 +178,6 @@ void Gui::Element::layoutChildren() {
|
|||
/**
|
||||
* The amount of size each implicitly sized element should occupy.
|
||||
*/
|
||||
|
||||
// std::cout << selfSize << ": " << (selfSize[primary] - explicitSize) << std::endl;
|
||||
|
||||
i32 implicitElemSize = floor((selfSize[primary] - explicitSize) / (std::max)(implicitCount, 1));
|
||||
|
||||
|
@ -193,10 +209,10 @@ void Gui::Element::layoutChildren() {
|
|||
+ gap + childMargin[primary] + childMargin[primary + 2];
|
||||
|
||||
child->parentOffset = selfOffset;
|
||||
|
||||
|
||||
child->updateElement();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <functional>
|
||||
|
||||
#include "client/gui/Gui.h"
|
||||
#include "client/gui/Style.h"
|
||||
|
@ -20,7 +21,9 @@ namespace Gui {
|
|||
*/
|
||||
|
||||
class Element {
|
||||
friend class Root;
|
||||
friend class BoxElement;
|
||||
friend class TextElement;
|
||||
|
||||
public:
|
||||
struct Props {;
|
||||
|
@ -81,23 +84,25 @@ namespace Gui {
|
|||
|
||||
void clear();
|
||||
|
||||
void onClick(const std::function<void(i32, bool)>& cb);
|
||||
|
||||
/** Returns the element's computed size. */
|
||||
virtual ivec2 getComputedSize();
|
||||
virtual ivec2 getComputedSize() const;
|
||||
|
||||
/** Returns the element's computed size + margins. */
|
||||
virtual ivec2 getComputedOuterSize();
|
||||
virtual ivec2 getComputedOuterSize() const;
|
||||
|
||||
/** Returns the element's computed content size, which is its size - padding. */
|
||||
virtual ivec2 getComputedContentSize();
|
||||
virtual ivec2 getComputedContentSize() const;
|
||||
|
||||
/** Returns the element's explicit size. Unspecified dimensions are -1. */
|
||||
virtual ivec2 getExplicitSize();
|
||||
virtual ivec2 getExplicitSize() const;
|
||||
|
||||
/** Returns the element's computed position relative to its parent. */
|
||||
virtual ivec2 getComputedPos();
|
||||
virtual ivec2 getComputedPos() const;
|
||||
|
||||
/** Returns the element's computed position relative to the screen. */
|
||||
virtual ivec2 getComputedScreenPos();
|
||||
virtual ivec2 getComputedScreenPos() const;
|
||||
|
||||
/** Gets a style value from the element's styles or the root's stylesheets. */
|
||||
const optional<any> getStyle(StyleRule rule) const {
|
||||
|
@ -114,8 +119,10 @@ namespace Gui {
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
/** Gets a style value from the element's styles or the root's stylesheets. */
|
||||
template<typename V, ValueType T = ValueType::LITERAL>
|
||||
/** Gets a generic value from the element's styles or the root's stylesheets. */
|
||||
template<typename V, ValueType T = ValueType::LITERAL,
|
||||
std::enable_if_t<T != ValueType::LENGTH, bool> = true>
|
||||
|
||||
const optional<V> getStyle(StyleRule rule) const {
|
||||
const optional<V> opt = props.styles.get<V, T>(rule);
|
||||
if (opt) return *opt;
|
||||
|
@ -129,14 +136,67 @@ namespace Gui {
|
|||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/** Gets a LENGTH value from the element's styles or the root's stylesheets. */
|
||||
template<typename V, ValueType T = ValueType::LITERAL,
|
||||
std::enable_if_t<T == ValueType::LENGTH, bool> = true>
|
||||
|
||||
const optional<V> getStyle(StyleRule rule) const {
|
||||
ExpressionInfo info = getExpr();
|
||||
const optional<V> opt = props.styles.get<V, T>(rule, info);
|
||||
if (opt) return *opt;
|
||||
for (const let& ss : stylesheets) {
|
||||
for (const string& className : props.classes) {
|
||||
const let& styles = ss.find(className);
|
||||
if (styles == ss.end()) continue;
|
||||
const optional<V> opt = styles->second.get<V, T>(rule, info);
|
||||
if (opt) return *opt;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/** Gets a LENGTH value from the element's styles or the root's stylesheets. */
|
||||
template<typename V, ValueType T = ValueType::LITERAL,
|
||||
std::enable_if_t<T == ValueType::LENGTH, bool> = true>
|
||||
|
||||
const optional<V> getStyleWithExpr(StyleRule rule, const ExpressionInfo& expr) const {
|
||||
const optional<V> opt = props.styles.get<V, T>(rule, expr);
|
||||
if (opt) return *opt;
|
||||
for (const let& ss : stylesheets) {
|
||||
for (const string& className : props.classes) {
|
||||
const let& styles = ss.find(className);
|
||||
if (styles == ss.end()) continue;
|
||||
const optional<V> opt = styles->second.get<V, T>(rule, expr);
|
||||
if (opt) return *opt;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/** Gets a style value from the element's styles or the root's stylesheets. */
|
||||
template<typename V, ValueType T = ValueType::LITERAL>
|
||||
|
||||
const V getStyle(StyleRule rule, V def) const {
|
||||
const optional<V> opt = getStyle<V, T>(rule);
|
||||
if (opt) return *opt;
|
||||
return def;
|
||||
}
|
||||
|
||||
/** 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,
|
||||
std::enable_if_t<T == ValueType::LENGTH, bool> = true>
|
||||
|
||||
const V getStyleWithExpr(StyleRule rule, V def, const ExpressionInfo& info) const {
|
||||
const optional<V> opt = getStyleWithExpr<V, T>(rule, info);
|
||||
if (opt) return *opt;
|
||||
return def;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/** Returns an ExpressionInfo object for evaluating Lengths. */
|
||||
virtual ExpressionInfo getExpr() const;
|
||||
|
||||
/**
|
||||
* Called by the root when the mouse position changes.
|
||||
|
@ -150,9 +210,8 @@ namespace Gui {
|
|||
* Triggers a click interaction on the hovered element.
|
||||
*/
|
||||
|
||||
bool handleMouseClick(u32 button, bool down);
|
||||
bool handleMouseClick(ivec2 mousePos, u32 button, bool down);
|
||||
|
||||
protected:
|
||||
Root& root;
|
||||
Props props;
|
||||
vec<StyleSheet>& stylesheets;
|
||||
|
@ -162,6 +221,7 @@ namespace Gui {
|
|||
std::list<sptr<Element>> children;
|
||||
|
||||
bool hovered = false;
|
||||
std::function<void(u32, bool)> clickCb = nullptr;
|
||||
|
||||
/** The screen offset of the parent. */
|
||||
ivec2 parentOffset {};
|
||||
|
|
|
@ -31,14 +31,8 @@ void Gui::Expression::setExpression(string exp) {
|
|||
|
||||
while (exp.size()) {
|
||||
let& c = exp[0];
|
||||
// Number or Unit or Keyword
|
||||
if ((c >= '0' && c <= '9') || c == '.' || (c >= 97 && c <= 122) ||
|
||||
(nextOperatorIsUnary && (c == '+' || c == '-'))) {
|
||||
temp += c;
|
||||
nextOperatorIsUnary = false;
|
||||
}
|
||||
// Binary Operator
|
||||
else if (!nextOperatorIsUnary && (c == '+' || c == '-' || c == '*' || c == '/' || c == '^')) {
|
||||
if (!nextOperatorIsUnary && (c == '+' || c == '-' || c == '*' || c == '/' || c == '^')) {
|
||||
if (temp.size()) {
|
||||
queue.emplace(temp);
|
||||
temp = {};
|
||||
|
@ -81,6 +75,11 @@ void Gui::Expression::setExpression(string exp) {
|
|||
operators.pop();
|
||||
nextOperatorIsUnary = false;
|
||||
}
|
||||
// Number or Unit or Keyword
|
||||
else {
|
||||
temp += c;
|
||||
nextOperatorIsUnary = false;
|
||||
}
|
||||
|
||||
exp.erase(0, 1);
|
||||
}
|
||||
|
@ -105,7 +104,11 @@ void Gui::Expression::setExpression(string exp) {
|
|||
}
|
||||
}
|
||||
|
||||
f32 Gui::Expression::eval() {
|
||||
f32 Gui::Expression::eval(const ExpressionInfo& info) {
|
||||
if (!expression.size()) {
|
||||
return nanf("");
|
||||
}
|
||||
|
||||
std::stack<Token> eval {};
|
||||
|
||||
for (usize i = 0; i < expression.size(); i++) {
|
||||
|
@ -124,28 +127,28 @@ f32 Gui::Expression::eval() {
|
|||
|
||||
switch (t.unit) {
|
||||
default:
|
||||
throw std::logic_error("Tried to operate with a non-operator token.");
|
||||
throw std::logic_error("Tried to operate with a non-operator token! This is an engine error!");
|
||||
case UnitOrOperator::ADD:
|
||||
eval.emplace(a.evalValue() + b.evalValue(), UnitOrOperator::REAL_PIXEL);
|
||||
eval.emplace(a.eval(info) + b.eval(info), UnitOrOperator::RAW);
|
||||
break;
|
||||
case UnitOrOperator::SUBTRACT:
|
||||
eval.emplace(a.evalValue() - b.evalValue(), UnitOrOperator::REAL_PIXEL);
|
||||
eval.emplace(a.eval(info) - b.eval(info), UnitOrOperator::RAW);
|
||||
break;
|
||||
case UnitOrOperator::MULTIPLY:
|
||||
eval.emplace(a.evalValue() * b.evalValue(), UnitOrOperator::REAL_PIXEL);
|
||||
eval.emplace(a.eval(info) * b.eval(info), UnitOrOperator::RAW);
|
||||
break;
|
||||
case UnitOrOperator::DIVIDE:
|
||||
eval.emplace(a.evalValue() / b.evalValue(), UnitOrOperator::REAL_PIXEL);
|
||||
eval.emplace(a.eval(info) / b.eval(info), UnitOrOperator::RAW);
|
||||
break;
|
||||
case UnitOrOperator::EXPONENT:
|
||||
eval.emplace(pow(a.evalValue(), b.evalValue()), UnitOrOperator::REAL_PIXEL);
|
||||
eval.emplace(pow(a.eval(info), b.eval(info)), UnitOrOperator::RAW);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!eval.size()) throw std::runtime_error("Eval stack is empty! This is an engine error!");
|
||||
return eval.top().evalValue();
|
||||
return eval.top().eval(info);
|
||||
}
|
||||
|
||||
const std::unordered_map<char, u8> Gui::Expression::PRECEDENCE {
|
||||
|
@ -178,9 +181,13 @@ Gui::Expression::Token::Token(const string& str) {
|
|||
switch (Util::hash(unitStr.data())) {
|
||||
default: throw std::logic_error("Unknown unit '" + unitStr + "'.");
|
||||
|
||||
case Util::hash("dp"): unit = UnitOrOperator::DISPLAY_PIXEL; return;
|
||||
case Util::hash(""):
|
||||
case Util::hash("px"): unit = UnitOrOperator::REAL_PIXEL; return;
|
||||
case Util::hash("px"): unit = UnitOrOperator::RAW; return;
|
||||
case Util::hash("dp"): unit = UnitOrOperator::DISPLAY_PIXEL; return;
|
||||
case Util::hash("cw"): unit = UnitOrOperator::CONTAINER_WIDTH; return;
|
||||
case Util::hash("ch"): unit = UnitOrOperator::CONTAINER_HEIGHT; return;
|
||||
case Util::hash("sw"): unit = UnitOrOperator::SELF_WIDTH; return;
|
||||
case Util::hash("sh"): unit = UnitOrOperator::SELF_HEIGHT; return;
|
||||
case Util::hash("deg"): unit = UnitOrOperator::DEGREE; return;
|
||||
}
|
||||
}
|
||||
|
@ -189,12 +196,19 @@ bool Gui::Expression::Token::isOperator() {
|
|||
return static_cast<u8>(unit) >= 128;
|
||||
}
|
||||
|
||||
f32 Gui::Expression::Token::evalValue() {
|
||||
f32 Gui::Expression::Token::eval(const ExpressionInfo& info) {
|
||||
switch (unit) {
|
||||
default: throw std::logic_error("Tried to evalValue() on an Operator token.");
|
||||
default: throw std::logic_error("Tried to eval() on an Operator token! This is an engine error!");
|
||||
|
||||
case UnitOrOperator::DISPLAY_PIXEL: return val * Gui::PX_SCALE;
|
||||
case UnitOrOperator::REAL_PIXEL: return val;
|
||||
case UnitOrOperator::RAW: return val;
|
||||
case UnitOrOperator::CONTAINER_WIDTH: {
|
||||
// std::cout << info.containerSize << ":" << val << std::endl;
|
||||
return (val / 100.f) * info.containerSize.x;
|
||||
}
|
||||
case UnitOrOperator::CONTAINER_HEIGHT: return (val / 100.f) * info.containerSize.y;
|
||||
case UnitOrOperator::SELF_WIDTH: return (val / 100.f) * info.selfSize.x;
|
||||
case UnitOrOperator::SELF_HEIGHT: return (val / 100.f) * info.selfSize.y;
|
||||
case UnitOrOperator::DEGREE: return val * M_PI / 180.f;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,19 +6,31 @@
|
|||
#include "util/Types.h"
|
||||
|
||||
namespace Gui {
|
||||
enum class UnitOrOperator: u8 {
|
||||
DISPLAY_PIXEL,
|
||||
REAL_PIXEL,
|
||||
DEGREE,
|
||||
struct ExpressionInfo {
|
||||
ExpressionInfo() = default;
|
||||
ExpressionInfo(ivec2 containerSize, ivec2 selfSize): containerSize(containerSize), selfSize(selfSize) {}
|
||||
|
||||
ADD = 128,
|
||||
SUBTRACT,
|
||||
MULTIPLY,
|
||||
DIVIDE,
|
||||
EXPONENT
|
||||
ivec2 containerSize;
|
||||
ivec2 selfSize;
|
||||
};
|
||||
|
||||
class Expression {
|
||||
enum class UnitOrOperator: u8 {
|
||||
RAW,
|
||||
DISPLAY_PIXEL,
|
||||
CONTAINER_WIDTH,
|
||||
CONTAINER_HEIGHT,
|
||||
SELF_WIDTH,
|
||||
SELF_HEIGHT,
|
||||
DEGREE,
|
||||
|
||||
ADD = 128,
|
||||
SUBTRACT,
|
||||
MULTIPLY,
|
||||
DIVIDE,
|
||||
EXPONENT
|
||||
};
|
||||
|
||||
struct Token {
|
||||
Token() = default;
|
||||
explicit Token(const string& str);
|
||||
|
@ -26,7 +38,7 @@ namespace Gui {
|
|||
|
||||
bool isOperator();
|
||||
|
||||
f32 evalValue();
|
||||
f32 eval(const ExpressionInfo& info);
|
||||
|
||||
f32 val = 0;
|
||||
UnitOrOperator unit;
|
||||
|
@ -38,12 +50,12 @@ namespace Gui {
|
|||
|
||||
void setExpression(string exp);
|
||||
|
||||
f32 eval();
|
||||
f32 eval(const ExpressionInfo& info);
|
||||
|
||||
private:
|
||||
usize hash = 0;
|
||||
|
||||
std::vector<Token> expression;
|
||||
vec<Token> expression;
|
||||
|
||||
const static std::unordered_map<char, u8> PRECEDENCE;
|
||||
};
|
||||
|
|
|
@ -26,7 +26,10 @@ Gui::Root::Root(Window& window, TextureAtlas& atlas) :
|
|||
t.printElapsedMs();
|
||||
});
|
||||
|
||||
// window.input.bindMouseCallback()
|
||||
window.input.bindMouseCallback([&](u32 button, i32 state) {
|
||||
let pos = window.input.getMousePos();
|
||||
body->handleMouseClick(pos, button, state == GLFW_PRESS);
|
||||
});
|
||||
}
|
||||
|
||||
Gui::Root::~Root() {
|
||||
|
|
|
@ -5,7 +5,7 @@ const std::unordered_map<string, Gui::StyleRule> Gui::Style::RULE_STRINGS_TO_ENU
|
|||
{ "size", StyleRule::SIZE },
|
||||
{ "margin", StyleRule::MARGIN },
|
||||
{ "padding", StyleRule::PADDING },
|
||||
{ "GAP", StyleRule::GAP },
|
||||
{ "gap", StyleRule::GAP },
|
||||
{ "layout", StyleRule::LAYOUT },
|
||||
{ "direction", StyleRule::DIRECTION },
|
||||
{ "h_align", StyleRule::H_ALIGN },
|
||||
|
|
|
@ -143,10 +143,10 @@ namespace Gui {
|
|||
(std::is_integral_v<N> || std::is_floating_point_v<N>) &&
|
||||
L == ValueType::LENGTH, bool> = true>
|
||||
|
||||
optional<N> get(StyleRule rule) const {
|
||||
optional<N> get(StyleRule rule, const ExpressionInfo& info) const {
|
||||
let raw = get<Gui::Expression>(rule);
|
||||
if (!raw) return std::nullopt;
|
||||
return raw->eval();
|
||||
return raw->eval(info);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,11 +159,11 @@ namespace Gui {
|
|||
std::is_same_v<VN, glm::vec<VN::length(), typename VN::value_type>> &&
|
||||
L == ValueType::LENGTH, bool> = true>
|
||||
|
||||
optional<VN> get(StyleRule rule) const {
|
||||
optional<VN> get(StyleRule rule, const ExpressionInfo& info) const {
|
||||
let raw = get<array<Gui::Expression, VN::length()>>(rule);
|
||||
if (!raw) return std::nullopt;
|
||||
VN vec;
|
||||
for (usize i = 0; i < VN::length(); i++) vec[i] = (*raw)[i].eval();
|
||||
for (usize i = 0; i < VN::length(); i++) vec[i] = (*raw)[i].eval(info);
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ MenuSandbox::MenuSandbox(Client& client, Gui::Root& root, sptr<Gui::Element> san
|
|||
sandboxRoot(sandboxRoot) {}
|
||||
|
||||
void MenuSandbox::reset() {
|
||||
// container->remove("error");
|
||||
sandboxRoot->clear();
|
||||
core = {};
|
||||
mod = {};
|
||||
|
@ -58,22 +57,12 @@ void MenuSandbox::loadApi() {
|
|||
void MenuSandbox::load(const SubgameDef& subgame) {
|
||||
reset();
|
||||
subgameName = subgame.config.name;
|
||||
|
||||
// try {
|
||||
|
||||
loadAndRunMod(subgame.subgamePath + "/../../assets/base");
|
||||
loadAndRunMod(subgame.subgamePath + "/menu");
|
||||
// }
|
||||
// catch (const std::runtime_error& e) {
|
||||
// showError(e.what(), subgame.config.name);
|
||||
// }
|
||||
}
|
||||
|
||||
void MenuSandbox::windowResized() {
|
||||
// builder.build(win);
|
||||
}
|
||||
|
||||
void MenuSandbox::update(double delta) {
|
||||
// builder.update();
|
||||
core["__builtin"]["update_delayed_functions"]();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,6 @@ public:
|
|||
|
||||
void update(double delta) override;
|
||||
|
||||
void windowResized();
|
||||
|
||||
using LuaParser::update;
|
||||
|
||||
private:
|
||||
|
|
|
@ -87,19 +87,20 @@ MainMenuScene::MainMenuScene(Client& client) : Scene(client),
|
|||
|
||||
for (usize i = 0; i < subgames.size(); i++) {
|
||||
let& subgame = subgames[i];
|
||||
navigationList->append<Gui::BoxElement>({
|
||||
|
||||
let elem = navigationList->append<Gui::BoxElement>({
|
||||
.classes = { "navigationButton" },
|
||||
.styles = {{
|
||||
{ Gui::StyleRule::BACKGROUND, string("crop(0, 0, 16, 16, " + subgame.iconRef->name + ")") },
|
||||
{ Gui::StyleRule::BACKGROUND_HOVER, string("crop(16, 0, 16, 16, " + subgame.iconRef->name + ")") }
|
||||
}}
|
||||
});
|
||||
//
|
||||
// button->setCallback(Element::CallbackType::PRIMARY, [&](bool down, ivec2) {
|
||||
// if (!down) return;
|
||||
// selectedSubgame = &subgame;
|
||||
// sandbox.load(*selectedSubgame);
|
||||
// });
|
||||
|
||||
elem->onClick([&](u32 button, bool down) {
|
||||
if (button != GLFW_MOUSE_BUTTON_1) return;
|
||||
selectedSubgame = &subgame;
|
||||
sandbox.load(*selectedSubgame);
|
||||
});
|
||||
}
|
||||
|
||||
if (subgames.size() > 0) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#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.");
|
||||
|
@ -21,7 +22,8 @@ static const array<Gui::Expression, D> parseLengthTableVal(sol::object value) {
|
|||
|
||||
vec<Gui::Expression> exprs {};
|
||||
exprs.reserve(t.size());
|
||||
for (let& v : t) exprs.emplace_back(parseObjectToExpr(v.second));
|
||||
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++)
|
||||
|
|
|
@ -6,6 +6,7 @@ zepha.set_gui(zepha.gui(function()
|
|||
|
||||
Gui.Text {
|
||||
size = { 64, 4 },
|
||||
pos = { "50cw", 50 },
|
||||
content = "Parentheses"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,52 +1,63 @@
|
|||
local menu = zepha.build_gui(function()
|
||||
local menu = zepha.gui(function()
|
||||
return Gui.Box {
|
||||
background = 'zeus_background_christmas_night',
|
||||
|
||||
Gui.Box {
|
||||
key = 'particle_wrap',
|
||||
size = { '100%', '100%' }
|
||||
-- id = 'particle_wrap',
|
||||
size = { '100cw', '100ch' }
|
||||
},
|
||||
|
||||
Gui.Box {
|
||||
pos = { '20% - 50s%', 0 },
|
||||
size = { 102, '100%' },
|
||||
gap = 4,
|
||||
padding = 8,
|
||||
size = { 102, '100ch' },
|
||||
pos = { '20cw - 50sw', 0 },
|
||||
|
||||
background = '#0135',
|
||||
|
||||
Gui.Box {
|
||||
pos = { 8, 8 },
|
||||
size = { 86, 30 },
|
||||
size = { nil, 30 },
|
||||
margin = { 0, 0, 0, 8 },
|
||||
|
||||
background = 'zeus_logo'
|
||||
},
|
||||
|
||||
Gui.Button {
|
||||
id = 'button_play',
|
||||
Gui.Box {
|
||||
-- id = 'button_play',
|
||||
|
||||
-- callbacks = {
|
||||
-- primary = function() zepha.start_game_local() end
|
||||
-- },
|
||||
|
||||
pos = { 6, 50 },
|
||||
size = { 90, 20 },
|
||||
padding = 5,
|
||||
size = { nil, 20 },
|
||||
|
||||
content = 'Local Play',
|
||||
cursor = "pointer",
|
||||
background = 'crop(0, 0, 90, 20, zeus_button)',
|
||||
background_hover = 'crop(0, 20, 90, 20, zeus_button)'
|
||||
background_hover = 'crop(0, 20, 90, 20, zeus_button)',
|
||||
|
||||
Gui.Text {
|
||||
content = 'Local Play'
|
||||
}
|
||||
},
|
||||
|
||||
Gui.Button {
|
||||
id = 'button_servers',
|
||||
Gui.Box {
|
||||
-- id = 'button_servers',
|
||||
|
||||
-- callbacks = {
|
||||
-- primary = function() zepha.start_game() end
|
||||
-- },
|
||||
|
||||
pos = { 6, 74 },
|
||||
size = { 90, 20 },
|
||||
content = 'Browse Servers',
|
||||
padding = 5,
|
||||
size = { nil, 20 },
|
||||
|
||||
cursor = "pointer",
|
||||
background = 'crop(0, 0, 90, 20, zeus_button)',
|
||||
background_hover = 'crop(0, 20, 90, 20, zeus_button)'
|
||||
background_hover = 'crop(0, 20, 90, 20, zeus_button)',
|
||||
|
||||
Gui.Text {
|
||||
content = 'Browse Servers'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,17 +73,17 @@ end)
|
|||
-- ) end)
|
||||
-- end, 1)
|
||||
|
||||
local particle_wrap = menu:get('particle_wrap')
|
||||
menu(function()
|
||||
for _ = 1, 20 do
|
||||
local scale = 6 + math.random() * 4
|
||||
particle_wrap:append(Gui.Rect {
|
||||
pos = { math.floor(math.random() * 600), math.floor(math.random() * 320) },
|
||||
background = 'particle_dark',
|
||||
size = { scale, scale }
|
||||
})
|
||||
end
|
||||
end)
|
||||
-- local particle_wrap = menu:get('particle_wrap')
|
||||
-- menu(function()
|
||||
-- for _ = 1, 20 do
|
||||
-- local scale = 6 + math.random() * 4
|
||||
-- particle_wrap:append(Gui.Rect {
|
||||
-- pos = { math.floor(math.random() * 600), math.floor(math.random() * 320) },
|
||||
-- background = 'particle_dark',
|
||||
-- size = { scale, scale }
|
||||
-- })
|
||||
-- end
|
||||
-- end)
|
||||
|
||||
-- local tick = 0
|
||||
-- zepha.after(function()
|
||||
|
|
Loading…
Reference in New Issue