mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-15 00:11:55 +07:00
layout refactoring
This commit is contained in:
@@ -14,23 +14,31 @@ namespace e2d
|
||||
public:
|
||||
class dirty final {};
|
||||
public:
|
||||
ENUM_HPP_CLASS_DECL(haligns, u8,
|
||||
(left)
|
||||
(center)
|
||||
(right)
|
||||
(space_around)
|
||||
(space_evenly)
|
||||
(space_between))
|
||||
|
||||
ENUM_HPP_CLASS_DECL(valigns, u8,
|
||||
(top)
|
||||
(center)
|
||||
(bottom)
|
||||
(space_around)
|
||||
(space_evenly)
|
||||
(space_between))
|
||||
|
||||
ENUM_HPP_CLASS_DECL(directions, u8,
|
||||
(ltr)
|
||||
(rtl))
|
||||
|
||||
ENUM_HPP_CLASS_DECL(align_modes, u8,
|
||||
(flex_start)
|
||||
(center)
|
||||
(flex_end)
|
||||
(space_between)
|
||||
(space_around))
|
||||
|
||||
ENUM_HPP_CLASS_DECL(justify_modes, u8,
|
||||
(flex_start)
|
||||
(center)
|
||||
(flex_end)
|
||||
(space_between)
|
||||
(space_around)
|
||||
(space_evenly))
|
||||
|
||||
ENUM_HPP_CLASS_DECL(flex_wraps, u8,
|
||||
(no_wrap)
|
||||
(wrap)
|
||||
(wrap_reversed))
|
||||
|
||||
ENUM_HPP_CLASS_DECL(flex_directions, u8,
|
||||
(row)
|
||||
(row_reversed)
|
||||
(column)
|
||||
@@ -38,37 +46,38 @@ namespace e2d
|
||||
public:
|
||||
layout() = default;
|
||||
|
||||
layout& halign(haligns value) noexcept;
|
||||
[[nodiscard]] haligns halign() const noexcept;
|
||||
|
||||
layout& valign(valigns value) noexcept;
|
||||
[[nodiscard]] valigns valign() const noexcept;
|
||||
|
||||
layout& direction(directions value) noexcept;
|
||||
[[nodiscard]] directions direction() const noexcept;
|
||||
public:
|
||||
layout& size(const v2f& value) noexcept;
|
||||
[[nodiscard]] const v2f& size() const noexcept;
|
||||
|
||||
layout& margin(const v2f& value) noexcept;
|
||||
[[nodiscard]] const v2f& margin() const noexcept;
|
||||
layout& align_items(align_modes value) noexcept;
|
||||
[[nodiscard]] align_modes align_items() const noexcept;
|
||||
|
||||
layout& padding(const v2f& value) noexcept;
|
||||
[[nodiscard]] const v2f& padding() const noexcept;
|
||||
layout& align_content(align_modes value) noexcept;
|
||||
[[nodiscard]] align_modes align_content() const noexcept;
|
||||
|
||||
layout& justify_content(justify_modes value) noexcept;
|
||||
[[nodiscard]] justify_modes justify_content() const noexcept;
|
||||
|
||||
layout& flex_wrap(flex_wraps value) noexcept;
|
||||
[[nodiscard]] flex_wraps flex_wrap() const noexcept;
|
||||
|
||||
layout& flex_direction(flex_directions value) noexcept;
|
||||
[[nodiscard]] flex_directions flex_direction() const noexcept;
|
||||
private:
|
||||
haligns halign_ = haligns::center;
|
||||
valigns valign_ = valigns::center;
|
||||
directions direction_ = directions::row;
|
||||
private:
|
||||
v2f size_ = v2f::zero();
|
||||
v2f margin_ = v2f::zero();
|
||||
v2f padding_ = v2f::zero();
|
||||
directions direction_ = directions::ltr;
|
||||
align_modes align_items_ = align_modes::flex_start;
|
||||
align_modes align_content_ = align_modes::flex_start;
|
||||
justify_modes justify_content_ = justify_modes::flex_start;
|
||||
flex_wraps flex_wrap_ = flex_wraps::no_wrap;
|
||||
flex_directions flex_direction_ = flex_directions::row;
|
||||
};
|
||||
}
|
||||
|
||||
ENUM_HPP_REGISTER_TRAITS(e2d::layout::haligns)
|
||||
ENUM_HPP_REGISTER_TRAITS(e2d::layout::valigns)
|
||||
ENUM_HPP_REGISTER_TRAITS(e2d::layout::directions)
|
||||
ENUM_HPP_REGISTER_TRAITS(e2d::layout::align_modes)
|
||||
ENUM_HPP_REGISTER_TRAITS(e2d::layout::justify_modes)
|
||||
ENUM_HPP_REGISTER_TRAITS(e2d::layout::flex_wraps)
|
||||
ENUM_HPP_REGISTER_TRAITS(e2d::layout::flex_directions)
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
@@ -109,30 +118,11 @@ namespace e2d
|
||||
static const char* title;
|
||||
|
||||
void operator()(gcomponent<layout>& c) const;
|
||||
void operator()(gcomponent<layout>& c, gizmos_context& ctx) const;
|
||||
};
|
||||
}
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
inline layout& layout::halign(haligns value) noexcept {
|
||||
halign_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline layout::haligns layout::halign() const noexcept {
|
||||
return halign_;
|
||||
}
|
||||
|
||||
inline layout& layout::valign(valigns value) noexcept {
|
||||
valign_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline layout::valigns layout::valign() const noexcept {
|
||||
return valign_;
|
||||
}
|
||||
|
||||
inline layout& layout::direction(directions value) noexcept {
|
||||
direction_ = value;
|
||||
return *this;
|
||||
@@ -142,31 +132,49 @@ namespace e2d
|
||||
return direction_;
|
||||
}
|
||||
|
||||
inline layout& layout::size(const v2f& value) noexcept {
|
||||
size_ = value;
|
||||
inline layout& layout::align_items(align_modes value) noexcept {
|
||||
align_items_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const v2f& layout::size() const noexcept {
|
||||
return size_;
|
||||
inline layout::align_modes layout::align_items() const noexcept {
|
||||
return align_items_;
|
||||
}
|
||||
|
||||
inline layout& layout::margin(const v2f& value) noexcept {
|
||||
margin_ = value;
|
||||
inline layout& layout::align_content(align_modes value) noexcept {
|
||||
align_content_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const v2f& layout::margin() const noexcept {
|
||||
return margin_;
|
||||
inline layout::align_modes layout::align_content() const noexcept {
|
||||
return align_content_;
|
||||
}
|
||||
|
||||
inline layout& layout::padding(const v2f& value) noexcept {
|
||||
padding_ = value;
|
||||
inline layout& layout::justify_content(justify_modes value) noexcept {
|
||||
justify_content_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const v2f& layout::padding() const noexcept {
|
||||
return padding_;
|
||||
inline layout::justify_modes layout::justify_content() const noexcept {
|
||||
return justify_content_;
|
||||
}
|
||||
|
||||
inline layout& layout::flex_wrap(flex_wraps value) noexcept {
|
||||
flex_wrap_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline layout::flex_wraps layout::flex_wrap() const noexcept {
|
||||
return flex_wrap_;
|
||||
}
|
||||
|
||||
inline layout& layout::flex_direction(flex_directions value) noexcept {
|
||||
flex_direction_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline layout::flex_directions layout::flex_direction() const noexcept {
|
||||
return flex_direction_;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,13 +184,12 @@ namespace e2d::layouts
|
||||
gcomponent<layout> unmark_dirty(gcomponent<layout> self);
|
||||
bool is_dirty(const const_gcomponent<layout>& self) noexcept;
|
||||
|
||||
gcomponent<layout> change_halign(gcomponent<layout> self, layout::haligns value);
|
||||
gcomponent<layout> change_valign(gcomponent<layout> self, layout::valigns value);
|
||||
gcomponent<layout> change_direction(gcomponent<layout> self, layout::directions value);
|
||||
|
||||
gcomponent<layout> change_size(gcomponent<layout> self, const v2f& value);
|
||||
gcomponent<layout> change_margin(gcomponent<layout> self, const v2f& value);
|
||||
gcomponent<layout> change_padding(gcomponent<layout> self, const v2f& value);
|
||||
gcomponent<layout> change_align_items(gcomponent<layout> self, layout::align_modes value);
|
||||
gcomponent<layout> change_align_content(gcomponent<layout> self, layout::align_modes value);
|
||||
gcomponent<layout> change_justify_content(gcomponent<layout> self, layout::justify_modes value);
|
||||
gcomponent<layout> change_flex_wrap(gcomponent<layout> self, layout::flex_wraps value);
|
||||
gcomponent<layout> change_flex_direction(gcomponent<layout> self, layout::flex_directions value);
|
||||
|
||||
gcomponent<layout> find_parent_layout(const_gcomponent<layout> self) noexcept;
|
||||
}
|
||||
|
||||
@@ -11,17 +11,23 @@
|
||||
namespace e2d
|
||||
{
|
||||
class widget final {
|
||||
public:
|
||||
class dirty final {};
|
||||
public:
|
||||
widget() = default;
|
||||
|
||||
widget& size(const v2f& value) noexcept;
|
||||
[[nodiscard]] const v2f& size() const noexcept;
|
||||
|
||||
widget& pivot(const v2f& value) noexcept;
|
||||
[[nodiscard]] const v2f& pivot() const noexcept;
|
||||
widget& margin(const v2f& value) noexcept;
|
||||
[[nodiscard]] const v2f& margin() const noexcept;
|
||||
|
||||
widget& padding(const v2f& value) noexcept;
|
||||
[[nodiscard]] const v2f& padding() const noexcept;
|
||||
private:
|
||||
v2f size_ = v2f::zero();
|
||||
v2f pivot_ = v2f::unit() * 0.5f;
|
||||
v2f margin_ = v2f::zero();
|
||||
v2f padding_ = v2f::zero();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -40,6 +46,20 @@ namespace e2d
|
||||
asset_dependencies& dependencies,
|
||||
const collect_context& ctx) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
class factory_loader<widget::dirty> final : factory_loader<> {
|
||||
public:
|
||||
static const char* schema_source;
|
||||
|
||||
bool operator()(
|
||||
widget::dirty& component,
|
||||
const fill_context& ctx) const;
|
||||
|
||||
bool operator()(
|
||||
asset_dependencies& dependencies,
|
||||
const collect_context& ctx) const;
|
||||
};
|
||||
}
|
||||
|
||||
namespace e2d
|
||||
@@ -50,6 +70,7 @@ namespace e2d
|
||||
static const char* title;
|
||||
|
||||
void operator()(gcomponent<widget>& c) const;
|
||||
void operator()(gcomponent<widget>& c, gizmos_context& ctx) const;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -64,12 +85,34 @@ namespace e2d
|
||||
return size_;
|
||||
}
|
||||
|
||||
inline widget& widget::pivot(const v2f& value) noexcept {
|
||||
pivot_ = value;
|
||||
inline widget& widget::margin(const v2f& value) noexcept {
|
||||
margin_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const v2f& widget::pivot() const noexcept {
|
||||
return pivot_;
|
||||
inline const v2f& widget::margin() const noexcept {
|
||||
return margin_;
|
||||
}
|
||||
|
||||
inline widget& widget::padding(const v2f& value) noexcept {
|
||||
padding_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const v2f& widget::padding() const noexcept {
|
||||
return padding_;
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::widgets
|
||||
{
|
||||
gcomponent<widget> mark_dirty(gcomponent<widget> self);
|
||||
gcomponent<widget> unmark_dirty(gcomponent<widget> self);
|
||||
bool is_dirty(const const_gcomponent<widget>& self) noexcept;
|
||||
|
||||
gcomponent<widget> change_size(gcomponent<widget> self, const v2f& value);
|
||||
gcomponent<widget> change_margin(gcomponent<widget> self, const v2f& value);
|
||||
gcomponent<widget> change_padding(gcomponent<widget> self, const v2f& value);
|
||||
|
||||
gcomponent<layout> find_parent_layout(const_gcomponent<widget> self) noexcept;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"prototype" : "widget_prefab.json",
|
||||
"components" : {
|
||||
"named" : {
|
||||
"name" : "layout"
|
||||
|
||||
9
samples/bin/library/prefabs/widget_prefab.json
Normal file
9
samples/bin/library/prefabs/widget_prefab.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"components" : {
|
||||
"named" : {
|
||||
"name" : "widget"
|
||||
},
|
||||
"widget" : {},
|
||||
"widget.dirty" : {}
|
||||
}
|
||||
}
|
||||
@@ -15,14 +15,16 @@
|
||||
"prototype" : "../prefabs/layout_prefab.json",
|
||||
"components" : {
|
||||
"layout" : {
|
||||
"size" : [400,200],
|
||||
"halign" : "space_evenly"
|
||||
"justify_content" : "space_evenly"
|
||||
},
|
||||
"widget" : {
|
||||
"size" : [400,200]
|
||||
}
|
||||
},
|
||||
"children" : [{
|
||||
"prototype" : "../prefabs/layout_prefab.json",
|
||||
"prototype" : "../prefabs/widget_prefab.json",
|
||||
"components" : {
|
||||
"layout" : {
|
||||
"widget" : {
|
||||
"size" : [66,113]
|
||||
}
|
||||
},
|
||||
@@ -35,9 +37,9 @@
|
||||
}
|
||||
}]
|
||||
},{
|
||||
"prototype" : "../prefabs/layout_prefab.json",
|
||||
"prototype" : "../prefabs/widget_prefab.json",
|
||||
"components" : {
|
||||
"layout" : {
|
||||
"widget" : {
|
||||
"size" : [66,113]
|
||||
}
|
||||
},
|
||||
@@ -50,9 +52,9 @@
|
||||
}
|
||||
}]
|
||||
},{
|
||||
"prototype" : "../prefabs/layout_prefab.json",
|
||||
"prototype" : "../prefabs/widget_prefab.json",
|
||||
"components" : {
|
||||
"layout" : {
|
||||
"widget" : {
|
||||
"size" : [66,113]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -9,47 +9,59 @@ local layout = {
|
||||
---@type boolean
|
||||
dirty = false,
|
||||
|
||||
---@type layout_haligns
|
||||
halign = layout.haligns.center,
|
||||
|
||||
---@type layout_valigns
|
||||
valign = layout.valigns.center,
|
||||
|
||||
---@type layout_directions
|
||||
direction = layout.directions.row,
|
||||
direction = layout.directions.ltr,
|
||||
|
||||
---@type v2f
|
||||
size = v2f.zero(),
|
||||
---@type layout_align_modes
|
||||
align_items = layout.align_modes.flex_start,
|
||||
|
||||
---@type v2f
|
||||
margin = v2f.zero(),
|
||||
---@type layout_align_modes
|
||||
align_conten = layout.align_modes.flex_start,
|
||||
|
||||
---@type v2f
|
||||
padding = v2f.zero()
|
||||
}
|
||||
---@type layout_justify_modes
|
||||
justify_content = layout.justify_modes.flex_start,
|
||||
|
||||
---@class layout_haligns
|
||||
layout.haligns = {
|
||||
left = "left",
|
||||
center = "center",
|
||||
right = "right",
|
||||
space_around = "space_around",
|
||||
space_evenly = "space_evenly",
|
||||
space_between = "space_between"
|
||||
}
|
||||
---@type layout_flex_wraps
|
||||
flex_wrap = layout.flex_wraps.no_wrap,
|
||||
|
||||
---@class layout_valigns
|
||||
layout.valigns = {
|
||||
top = "top",
|
||||
center = "center",
|
||||
bottom = "bottom",
|
||||
space_around = "space_around",
|
||||
space_evenly = "space_evenly",
|
||||
space_between = "space_between"
|
||||
---@type layout_flex_directions
|
||||
flex_direction = layout.flex_directions.row
|
||||
}
|
||||
|
||||
---@class layout_directions
|
||||
layout.directions = {
|
||||
ltr = "ltr",
|
||||
rtl = "rtl"
|
||||
}
|
||||
|
||||
---@class layout_align_modes
|
||||
layout.align_modes = {
|
||||
flex_start = "flex_start",
|
||||
center = "center",
|
||||
flex_end = "flex_end",
|
||||
space_between = "space_between",
|
||||
space_around = "space_around"
|
||||
}
|
||||
|
||||
---@class layout_justify_modes
|
||||
layout.justify_modes = {
|
||||
flex_start = "flex_start",
|
||||
center = "center",
|
||||
flex_end = "flex_end",
|
||||
space_between = "space_between",
|
||||
space_around = "space_around",
|
||||
space_evenly = "space_evenly"
|
||||
}
|
||||
|
||||
---@class layout_flex_wraps
|
||||
layout.flex_wraps = {
|
||||
no_wrap = "no_wrap",
|
||||
wrap = "wrap",
|
||||
wrap_reversed = "wrap_reversed"
|
||||
}
|
||||
|
||||
---@class layout_flex_directions
|
||||
layout.flex_directions = {
|
||||
row = "row",
|
||||
row_reversed = "row_reversed",
|
||||
column = "column",
|
||||
|
||||
@@ -6,11 +6,17 @@ local widget = {
|
||||
---@type boolean
|
||||
disabled = false,
|
||||
|
||||
---@type boolean
|
||||
dirty = false,
|
||||
|
||||
---@type v2f
|
||||
size = v2f.zero(),
|
||||
|
||||
---@type v2f
|
||||
pivot = v2f.unit() * 0.5
|
||||
margin = v2f.zero(),
|
||||
|
||||
---@type v2f
|
||||
padding = v2f.zero()
|
||||
}
|
||||
|
||||
---@overload fun(self: widget)
|
||||
|
||||
@@ -67,22 +67,6 @@ namespace e2d::bindings::high
|
||||
}
|
||||
),
|
||||
|
||||
"halign", sol::property(
|
||||
[](const gcomponent<layout>& c) -> layout::haligns {
|
||||
return c->halign();
|
||||
},
|
||||
[](gcomponent<layout>& c, layout::haligns v){
|
||||
layouts::change_halign(c, v);
|
||||
}),
|
||||
|
||||
"valign", sol::property(
|
||||
[](const gcomponent<layout>& c) -> layout::valigns {
|
||||
return c->valign();
|
||||
},
|
||||
[](gcomponent<layout>& c, layout::valigns v){
|
||||
layouts::change_valign(c, v);
|
||||
}),
|
||||
|
||||
"direction", sol::property(
|
||||
[](const gcomponent<layout>& c) -> layout::directions {
|
||||
return c->direction();
|
||||
@@ -91,63 +75,95 @@ namespace e2d::bindings::high
|
||||
layouts::change_direction(c, v);
|
||||
}),
|
||||
|
||||
"size", sol::property(
|
||||
[](const gcomponent<layout>& c) -> v2f {
|
||||
return c->size();
|
||||
"align_items", sol::property(
|
||||
[](const gcomponent<layout>& c) -> layout::align_modes {
|
||||
return c->align_items();
|
||||
},
|
||||
[](gcomponent<layout>& c, const v2f& v){
|
||||
layouts::change_size(c, v);
|
||||
[](gcomponent<layout>& c, layout::align_modes v){
|
||||
layouts::change_align_items(c, v);
|
||||
}),
|
||||
|
||||
"margin", sol::property(
|
||||
[](const gcomponent<layout>& c) -> v2f {
|
||||
return c->margin();
|
||||
"align_content", sol::property(
|
||||
[](const gcomponent<layout>& c) -> layout::align_modes {
|
||||
return c->align_content();
|
||||
},
|
||||
[](gcomponent<layout>& c, const v2f& v){
|
||||
layouts::change_margin(c, v);
|
||||
[](gcomponent<layout>& c, layout::align_modes v){
|
||||
layouts::change_align_content(c, v);
|
||||
}),
|
||||
|
||||
"padding", sol::property(
|
||||
[](const gcomponent<layout>& c) -> v2f {
|
||||
return c->padding();
|
||||
"justify_content", sol::property(
|
||||
[](const gcomponent<layout>& c) -> layout::justify_modes {
|
||||
return c->justify_content();
|
||||
},
|
||||
[](gcomponent<layout>& c, const v2f& v){
|
||||
layouts::change_padding(c, v);
|
||||
[](gcomponent<layout>& c, layout::justify_modes v){
|
||||
layouts::change_justify_content(c, v);
|
||||
}),
|
||||
|
||||
"flex_wrap", sol::property(
|
||||
[](const gcomponent<layout>& c) -> layout::flex_wraps {
|
||||
return c->flex_wrap();
|
||||
},
|
||||
[](gcomponent<layout>& c, layout::flex_wraps v){
|
||||
layouts::change_flex_wrap(c, v);
|
||||
}),
|
||||
|
||||
"flex_direction", sol::property(
|
||||
[](const gcomponent<layout>& c) -> layout::flex_directions {
|
||||
return c->flex_direction();
|
||||
},
|
||||
[](gcomponent<layout>& c, layout::flex_directions v){
|
||||
layouts::change_flex_direction(c, v);
|
||||
})
|
||||
);
|
||||
|
||||
#define LAYOUT_HALIGN_PAIR(x) {#x, layout::haligns::x},
|
||||
l["layout"].get_or_create<sol::table>()
|
||||
.new_enum<layout::haligns>("haligns", {
|
||||
LAYOUT_HALIGN_PAIR(left)
|
||||
LAYOUT_HALIGN_PAIR(center)
|
||||
LAYOUT_HALIGN_PAIR(right)
|
||||
LAYOUT_HALIGN_PAIR(space_around)
|
||||
LAYOUT_HALIGN_PAIR(space_evenly)
|
||||
LAYOUT_HALIGN_PAIR(space_between)
|
||||
});
|
||||
#undef LAYOUT_HALIGN_PAIR
|
||||
|
||||
#define LAYOUT_VALIGN_PAIR(x) {#x, layout::valigns::x},
|
||||
l["layout"].get_or_create<sol::table>()
|
||||
.new_enum<layout::valigns>("valigns", {
|
||||
LAYOUT_VALIGN_PAIR(top)
|
||||
LAYOUT_VALIGN_PAIR(center)
|
||||
LAYOUT_VALIGN_PAIR(bottom)
|
||||
LAYOUT_VALIGN_PAIR(space_around)
|
||||
LAYOUT_VALIGN_PAIR(space_evenly)
|
||||
LAYOUT_VALIGN_PAIR(space_between)
|
||||
});
|
||||
#undef LAYOUT_VALIGN_PAIR
|
||||
|
||||
#define LAYOUT_DIRECTION_PAIR(x) {#x, layout::directions::x},
|
||||
l["layout"].get_or_create<sol::table>()
|
||||
.new_enum<layout::directions>("directions", {
|
||||
LAYOUT_DIRECTION_PAIR(row)
|
||||
LAYOUT_DIRECTION_PAIR(row_reversed)
|
||||
LAYOUT_DIRECTION_PAIR(column)
|
||||
LAYOUT_DIRECTION_PAIR(column_reversed)
|
||||
LAYOUT_DIRECTION_PAIR(ltr)
|
||||
LAYOUT_DIRECTION_PAIR(rtl)
|
||||
});
|
||||
#undef LAYOUT_DIRECTION_PAIR
|
||||
|
||||
#define LAYOUT_ALIGN_MODE_PAIR(x) {#x, layout::align_modes::x},
|
||||
l["layout"].get_or_create<sol::table>()
|
||||
.new_enum<layout::align_modes>("align_modes", {
|
||||
LAYOUT_ALIGN_MODE_PAIR(flex_start)
|
||||
LAYOUT_ALIGN_MODE_PAIR(center)
|
||||
LAYOUT_ALIGN_MODE_PAIR(flex_end)
|
||||
LAYOUT_ALIGN_MODE_PAIR(space_between)
|
||||
LAYOUT_ALIGN_MODE_PAIR(space_around)
|
||||
});
|
||||
#undef LAYOUT_ALIGN_MODE_PAIR
|
||||
|
||||
#define LAYOUT_JUSTIFY_MODE_PAIR(x) {#x, layout::justify_modes::x},
|
||||
l["layout"].get_or_create<sol::table>()
|
||||
.new_enum<layout::justify_modes>("justify_modes", {
|
||||
LAYOUT_JUSTIFY_MODE_PAIR(flex_start)
|
||||
LAYOUT_JUSTIFY_MODE_PAIR(center)
|
||||
LAYOUT_JUSTIFY_MODE_PAIR(flex_end)
|
||||
LAYOUT_JUSTIFY_MODE_PAIR(space_between)
|
||||
LAYOUT_JUSTIFY_MODE_PAIR(space_around)
|
||||
LAYOUT_JUSTIFY_MODE_PAIR(space_evenly)
|
||||
});
|
||||
#undef LAYOUT_JUSTIFY_MODE_PAIR
|
||||
|
||||
#define LAYOUT_FLEX_WRAP_PAIR(x) {#x, layout::flex_wraps::x},
|
||||
l["layout"].get_or_create<sol::table>()
|
||||
.new_enum<layout::flex_wraps>("flex_wraps", {
|
||||
LAYOUT_FLEX_WRAP_PAIR(no_wrap)
|
||||
LAYOUT_FLEX_WRAP_PAIR(wrap)
|
||||
LAYOUT_FLEX_WRAP_PAIR(wrap_reversed)
|
||||
});
|
||||
#undef LAYOUT_FLEX_WRAP_PAIR
|
||||
|
||||
#define LAYOUT_FLEX_DIRECTION_PAIR(x) {#x, layout::flex_directions::x},
|
||||
l["layout"].get_or_create<sol::table>()
|
||||
.new_enum<layout::flex_directions>("flex_directions", {
|
||||
LAYOUT_FLEX_DIRECTION_PAIR(row)
|
||||
LAYOUT_FLEX_DIRECTION_PAIR(row_reversed)
|
||||
LAYOUT_FLEX_DIRECTION_PAIR(column)
|
||||
LAYOUT_FLEX_DIRECTION_PAIR(column_reversed)
|
||||
});
|
||||
#undef LAYOUT_FLEX_DIRECTION_PAIR
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,20 +50,41 @@ namespace e2d::bindings::high
|
||||
}
|
||||
),
|
||||
|
||||
"dirty", sol::property(
|
||||
[](const gcomponent<widget>& c) -> bool {
|
||||
return widgets::is_dirty(c);
|
||||
},
|
||||
[](gcomponent<widget>& c, bool yesno){
|
||||
if ( yesno ) {
|
||||
widgets::mark_dirty(c);
|
||||
} else {
|
||||
widgets::unmark_dirty(c);
|
||||
}
|
||||
}
|
||||
),
|
||||
|
||||
"size", sol::property(
|
||||
[](const gcomponent<widget>& c) -> v2f {
|
||||
return c->size();
|
||||
},
|
||||
[](gcomponent<widget>& c, const v2f& v){
|
||||
c->size(v);
|
||||
widgets::change_size(c, v);
|
||||
}),
|
||||
|
||||
"pivot", sol::property(
|
||||
"margin", sol::property(
|
||||
[](const gcomponent<widget>& c) -> v2f {
|
||||
return c->pivot();
|
||||
return c->margin();
|
||||
},
|
||||
[](gcomponent<widget>& c, const v2f& v){
|
||||
c->pivot(v);
|
||||
widgets::change_margin(c, v);
|
||||
}),
|
||||
|
||||
"padding", sol::property(
|
||||
[](const gcomponent<widget>& c) -> v2f {
|
||||
return c->padding();
|
||||
},
|
||||
[](gcomponent<widget>& c, const v2f& v){
|
||||
widgets::change_padding(c, v);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,37 +15,51 @@ namespace e2d
|
||||
"required" : [],
|
||||
"additionalProperties" : false,
|
||||
"properties" : {
|
||||
"halign" : { "$ref": "#/definitions/haligns" },
|
||||
"valign" : { "$ref": "#/definitions/valigns" },
|
||||
"direction" : { "$ref": "#/definitions/directions" },
|
||||
"size" : { "$ref": "#/common_definitions/v2" },
|
||||
"margin" : { "$ref": "#/common_definitions/v2" },
|
||||
"padding" : { "$ref": "#/common_definitions/v2" }
|
||||
"align_items" : { "$ref": "#/definitions/align_modes" },
|
||||
"align_content" : { "$ref": "#/definitions/align_modes" },
|
||||
"justify_content" : { "$ref": "#/definitions/justify_modes" },
|
||||
"flex_wrap" : { "$ref": "#/definitions/flex_wraps" },
|
||||
"flex_direction" : { "$ref": "#/definitions/flex_directions" }
|
||||
},
|
||||
"definitions" : {
|
||||
"haligns" : {
|
||||
"type" : "string",
|
||||
"enum" : [
|
||||
"left",
|
||||
"center",
|
||||
"right",
|
||||
"space_around",
|
||||
"space_evenly",
|
||||
"space_between"
|
||||
]
|
||||
},
|
||||
"valigns" : {
|
||||
"type" : "string",
|
||||
"enum" : [
|
||||
"top",
|
||||
"center",
|
||||
"bottom",
|
||||
"space_around",
|
||||
"space_evenly",
|
||||
"space_between"
|
||||
]
|
||||
},
|
||||
"directions" : {
|
||||
"type" : "string",
|
||||
"enum" : [
|
||||
"ltr",
|
||||
"rtl"
|
||||
]
|
||||
},
|
||||
"align_modes" : {
|
||||
"type" : "string",
|
||||
"enum" : [
|
||||
"flex_start",
|
||||
"center",
|
||||
"flex_end",
|
||||
"space_between",
|
||||
"space_around"
|
||||
]
|
||||
},
|
||||
"justify_modes" : {
|
||||
"type" : "string",
|
||||
"enum" : [
|
||||
"flex_start",
|
||||
"center",
|
||||
"flex_end",
|
||||
"space_between",
|
||||
"space_around",
|
||||
"space_evenly"
|
||||
]
|
||||
},
|
||||
"flex_wraps" : {
|
||||
"type" : "string",
|
||||
"enum" : [
|
||||
"no_wrap",
|
||||
"wrap",
|
||||
"wrap_reversed"
|
||||
]
|
||||
},
|
||||
"flex_directions" : {
|
||||
"type" : "string",
|
||||
"enum" : [
|
||||
"row",
|
||||
@@ -61,24 +75,6 @@ namespace e2d
|
||||
layout& component,
|
||||
const fill_context& ctx) const
|
||||
{
|
||||
if ( ctx.root.HasMember("halign") ) {
|
||||
layout::haligns halign = component.halign();
|
||||
if ( !json_utils::try_parse_value(ctx.root["halign"], halign) ) {
|
||||
the<debug>().error("LAYOUT: Incorrect formatting of 'halign' property");
|
||||
return false;
|
||||
}
|
||||
component.halign(halign);
|
||||
}
|
||||
|
||||
if ( ctx.root.HasMember("valign") ) {
|
||||
layout::valigns valign = component.valign();
|
||||
if ( !json_utils::try_parse_value(ctx.root["valign"], valign) ) {
|
||||
the<debug>().error("LAYOUT: Incorrect formatting of 'valign' property");
|
||||
return false;
|
||||
}
|
||||
component.valign(valign);
|
||||
}
|
||||
|
||||
if ( ctx.root.HasMember("direction") ) {
|
||||
layout::directions direction = component.direction();
|
||||
if ( !json_utils::try_parse_value(ctx.root["direction"], direction) ) {
|
||||
@@ -88,31 +84,49 @@ namespace e2d
|
||||
component.direction(direction);
|
||||
}
|
||||
|
||||
if ( ctx.root.HasMember("size") ) {
|
||||
v2f size = component.size();
|
||||
if ( !json_utils::try_parse_value(ctx.root["size"], size) ) {
|
||||
the<debug>().error("LAYOUT: Incorrect formatting of 'size' property");
|
||||
if ( ctx.root.HasMember("align_items") ) {
|
||||
layout::align_modes align_items = component.align_items();
|
||||
if ( !json_utils::try_parse_value(ctx.root["align_items"], align_items) ) {
|
||||
the<debug>().error("LAYOUT: Incorrect formatting of 'align_items' property");
|
||||
return false;
|
||||
}
|
||||
component.size(size);
|
||||
component.align_items(align_items);
|
||||
}
|
||||
|
||||
if ( ctx.root.HasMember("margin") ) {
|
||||
v2f margin = component.margin();
|
||||
if ( !json_utils::try_parse_value(ctx.root["margin"], margin) ) {
|
||||
the<debug>().error("LAYOUT: Incorrect formatting of 'margin' property");
|
||||
if ( ctx.root.HasMember("align_content") ) {
|
||||
layout::align_modes align_content = component.align_content();
|
||||
if ( !json_utils::try_parse_value(ctx.root["align_content"], align_content) ) {
|
||||
the<debug>().error("LAYOUT: Incorrect formatting of 'align_content' property");
|
||||
return false;
|
||||
}
|
||||
component.margin(margin);
|
||||
component.align_content(align_content);
|
||||
}
|
||||
|
||||
if ( ctx.root.HasMember("padding") ) {
|
||||
v2f padding = component.padding();
|
||||
if ( !json_utils::try_parse_value(ctx.root["padding"], padding) ) {
|
||||
the<debug>().error("LAYOUT: Incorrect formatting of 'padding' property");
|
||||
if ( ctx.root.HasMember("justify_content") ) {
|
||||
layout::justify_modes justify_content = component.justify_content();
|
||||
if ( !json_utils::try_parse_value(ctx.root["justify_content"], justify_content) ) {
|
||||
the<debug>().error("LAYOUT: Incorrect formatting of 'justify_content' property");
|
||||
return false;
|
||||
}
|
||||
component.padding(padding);
|
||||
component.justify_content(justify_content);
|
||||
}
|
||||
|
||||
if ( ctx.root.HasMember("flex_wrap") ) {
|
||||
layout::flex_wraps flex_wrap = component.flex_wrap();
|
||||
if ( !json_utils::try_parse_value(ctx.root["flex_wrap"], flex_wrap) ) {
|
||||
the<debug>().error("LAYOUT: Incorrect formatting of 'flex_wrap' property");
|
||||
return false;
|
||||
}
|
||||
component.flex_wrap(flex_wrap);
|
||||
}
|
||||
|
||||
if ( ctx.root.HasMember("flex_direction") ) {
|
||||
layout::flex_directions flex_direction = component.flex_direction();
|
||||
if ( !json_utils::try_parse_value(ctx.root["flex_direction"], flex_direction) ) {
|
||||
the<debug>().error("LAYOUT: Incorrect formatting of 'flex_direction' property");
|
||||
return false;
|
||||
}
|
||||
component.flex_direction(flex_direction);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -170,66 +184,40 @@ namespace e2d
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if ( layout::haligns halign = c->halign();
|
||||
imgui_utils::show_enum_combo_box("halign", &halign) )
|
||||
{
|
||||
layouts::change_halign(c, halign);
|
||||
}
|
||||
|
||||
if ( layout::valigns valign = c->valign();
|
||||
imgui_utils::show_enum_combo_box("valign", &valign) )
|
||||
{
|
||||
layouts::change_valign(c, valign);
|
||||
}
|
||||
|
||||
if ( layout::directions direction = c->direction();
|
||||
imgui_utils::show_enum_combo_box("direction", &direction) )
|
||||
{
|
||||
layouts::change_direction(c, direction);
|
||||
}
|
||||
|
||||
if ( v2f size = c->size();
|
||||
ImGui::DragFloat2("size", size.data(), 1.f) )
|
||||
if ( layout::align_modes align_items = c->align_items();
|
||||
imgui_utils::show_enum_combo_box("align_items", &align_items) )
|
||||
{
|
||||
layouts::change_size(c, size);
|
||||
layouts::change_align_items(c, align_items);
|
||||
}
|
||||
|
||||
if ( v2f margin = c->margin();
|
||||
ImGui::DragFloat2("margin", margin.data(), 1.f) )
|
||||
if ( layout::align_modes align_content = c->align_content();
|
||||
imgui_utils::show_enum_combo_box("align_content", &align_content) )
|
||||
{
|
||||
layouts::change_margin(c, margin);
|
||||
layouts::change_align_content(c, align_content);
|
||||
}
|
||||
|
||||
if ( v2f padding = c->padding();
|
||||
ImGui::DragFloat2("padding", padding.data(), 1.f) )
|
||||
if ( layout::justify_modes justify_content = c->justify_content();
|
||||
imgui_utils::show_enum_combo_box("justify_content", &justify_content) )
|
||||
{
|
||||
layouts::change_padding(c, padding);
|
||||
layouts::change_justify_content(c, justify_content);
|
||||
}
|
||||
}
|
||||
|
||||
void component_inspector<layout>::operator()(
|
||||
gcomponent<layout>& c,
|
||||
gizmos_context& ctx) const
|
||||
{
|
||||
ctx.draw_wire_rect(
|
||||
c->size() * 0.5f,
|
||||
c->size(),
|
||||
ctx.selected() ? color32(255,255,255) : color32(127,127,127));
|
||||
if ( layout::flex_wraps flex_wrap = c->flex_wrap();
|
||||
imgui_utils::show_enum_combo_box("flex_wrap", &flex_wrap) )
|
||||
{
|
||||
layouts::change_flex_wrap(c, flex_wrap);
|
||||
}
|
||||
|
||||
if ( ctx.selected() ) {
|
||||
if ( c->margin() != v2f::zero() ) {
|
||||
ctx.draw_wire_rect(
|
||||
c->size() * 0.5f,
|
||||
c->size() + c->margin() * 2.f,
|
||||
ctx.selected() ? color32(255,255,255) : color32(127,127,127));
|
||||
}
|
||||
|
||||
if ( c->padding() != v2f::zero() ) {
|
||||
ctx.draw_wire_rect(
|
||||
c->size() * 0.5f,
|
||||
c->size() - c->padding() * 2.f,
|
||||
ctx.selected() ? color32(255,255,255) : color32(127,127,127));
|
||||
}
|
||||
if ( layout::flex_directions flex_direction = c->flex_direction();
|
||||
imgui_utils::show_enum_combo_box("flex_direction", &flex_direction) )
|
||||
{
|
||||
layouts::change_flex_direction(c, flex_direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,20 +242,6 @@ namespace e2d::layouts
|
||||
return self.owner().component<layout::dirty>().exists();
|
||||
}
|
||||
|
||||
gcomponent<layout> change_halign(gcomponent<layout> self, layout::haligns value) {
|
||||
if ( self ) {
|
||||
self->halign(value);
|
||||
}
|
||||
return mark_dirty(self);
|
||||
}
|
||||
|
||||
gcomponent<layout> change_valign(gcomponent<layout> self, layout::valigns value) {
|
||||
if ( self ) {
|
||||
self->valign(value);
|
||||
}
|
||||
return mark_dirty(self);
|
||||
}
|
||||
|
||||
gcomponent<layout> change_direction(gcomponent<layout> self, layout::directions value) {
|
||||
if ( self ) {
|
||||
self->direction(value);
|
||||
@@ -275,27 +249,38 @@ namespace e2d::layouts
|
||||
return mark_dirty(self);
|
||||
}
|
||||
|
||||
gcomponent<layout> change_size(gcomponent<layout> self, const v2f& value) {
|
||||
gcomponent<layout> change_align_items(gcomponent<layout> self, layout::align_modes value) {
|
||||
if ( self ) {
|
||||
self->size(value);
|
||||
self->align_items(value);
|
||||
}
|
||||
mark_dirty(find_parent_layout(self));
|
||||
return mark_dirty(self);
|
||||
}
|
||||
|
||||
gcomponent<layout> change_margin(gcomponent<layout> self, const v2f& value) {
|
||||
gcomponent<layout> change_align_content(gcomponent<layout> self, layout::align_modes value) {
|
||||
if ( self ) {
|
||||
self->margin(value);
|
||||
self->align_content(value);
|
||||
}
|
||||
mark_dirty(find_parent_layout(self));
|
||||
return mark_dirty(self);
|
||||
}
|
||||
|
||||
gcomponent<layout> change_padding(gcomponent<layout> self, const v2f& value) {
|
||||
gcomponent<layout> change_justify_content(gcomponent<layout> self, layout::justify_modes value) {
|
||||
if ( self ) {
|
||||
self->padding(value);
|
||||
self->justify_content(value);
|
||||
}
|
||||
return mark_dirty(self);
|
||||
}
|
||||
|
||||
gcomponent<layout> change_flex_wrap(gcomponent<layout> self, layout::flex_wraps value) {
|
||||
if ( self ) {
|
||||
self->flex_wrap(value);
|
||||
}
|
||||
return mark_dirty(self);
|
||||
}
|
||||
|
||||
gcomponent<layout> change_flex_direction(gcomponent<layout> self, layout::flex_directions value) {
|
||||
if ( self ) {
|
||||
self->flex_direction(value);
|
||||
}
|
||||
mark_dirty(find_parent_layout(self));
|
||||
return mark_dirty(self);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
|
||||
#include <enduro2d/high/components/widget.hpp>
|
||||
|
||||
#include <enduro2d/high/components/actor.hpp>
|
||||
#include <enduro2d/high/components/layout.hpp>
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
const char* factory_loader<widget>::schema_source = R"json({
|
||||
@@ -14,7 +17,8 @@ namespace e2d
|
||||
"additionalProperties" : false,
|
||||
"properties" : {
|
||||
"size" : { "$ref": "#/common_definitions/v2" },
|
||||
"pivot" : { "$ref": "#/common_definitions/v2" }
|
||||
"margin" : { "$ref": "#/common_definitions/v2" },
|
||||
"padding" : { "$ref": "#/common_definitions/v2" }
|
||||
}
|
||||
})json";
|
||||
|
||||
@@ -31,13 +35,22 @@ namespace e2d
|
||||
component.size(size);
|
||||
}
|
||||
|
||||
if ( ctx.root.HasMember("pivot") ) {
|
||||
v2f pivot = component.pivot();
|
||||
if ( !json_utils::try_parse_value(ctx.root["pivot"], pivot) ) {
|
||||
the<debug>().error("WIDGET: Incorrect formatting of 'pivot' property");
|
||||
if ( ctx.root.HasMember("margin") ) {
|
||||
v2f margin = component.margin();
|
||||
if ( !json_utils::try_parse_value(ctx.root["margin"], margin) ) {
|
||||
the<debug>().error("WIDGET: Incorrect formatting of 'margin' property");
|
||||
return false;
|
||||
}
|
||||
component.pivot(pivot);
|
||||
component.margin(margin);
|
||||
}
|
||||
|
||||
if ( ctx.root.HasMember("padding") ) {
|
||||
v2f padding = component.padding();
|
||||
if ( !json_utils::try_parse_value(ctx.root["padding"], padding) ) {
|
||||
the<debug>().error("WIDGET: Incorrect formatting of 'padding' property");
|
||||
return false;
|
||||
}
|
||||
component.padding(padding);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -52,21 +65,143 @@ namespace e2d
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
const char* factory_loader<widget::dirty>::schema_source = R"json({
|
||||
"type" : "object",
|
||||
"required" : [],
|
||||
"additionalProperties" : false,
|
||||
"properties" : {}
|
||||
})json";
|
||||
|
||||
bool factory_loader<widget::dirty>::operator()(
|
||||
widget::dirty& component,
|
||||
const fill_context& ctx) const
|
||||
{
|
||||
E2D_UNUSED(component, ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool factory_loader<widget::dirty>::operator()(
|
||||
asset_dependencies& dependencies,
|
||||
const collect_context& ctx) const
|
||||
{
|
||||
E2D_UNUSED(dependencies, ctx);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
const char* component_inspector<widget>::title = ICON_FA_VECTOR_SQUARE " widget";
|
||||
|
||||
void component_inspector<widget>::operator()(gcomponent<widget>& c) const {
|
||||
if ( bool dirty = c.owner().component<widget::dirty>().exists();
|
||||
ImGui::Checkbox("dirty", &dirty) )
|
||||
{
|
||||
if ( dirty ) {
|
||||
widgets::mark_dirty(c);
|
||||
} else {
|
||||
widgets::unmark_dirty(c);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if ( v2f size = c->size();
|
||||
ImGui::DragFloat2("size", size.data(), 1.f) )
|
||||
{
|
||||
c->size(size);
|
||||
widgets::change_size(c, size);
|
||||
}
|
||||
|
||||
if ( v2f pivot = c->pivot();
|
||||
ImGui::DragFloat2("pivot", pivot.data(), 0.01f) )
|
||||
if ( v2f margin = c->margin();
|
||||
ImGui::DragFloat2("margin", margin.data(), 1.f) )
|
||||
{
|
||||
c->pivot(pivot);
|
||||
widgets::change_margin(c, margin);
|
||||
}
|
||||
|
||||
if ( v2f padding = c->padding();
|
||||
ImGui::DragFloat2("padding", padding.data(), 1.f) )
|
||||
{
|
||||
widgets::change_padding(c, padding);
|
||||
}
|
||||
}
|
||||
|
||||
void component_inspector<widget>::operator()(
|
||||
gcomponent<widget>& c,
|
||||
gizmos_context& ctx) const
|
||||
{
|
||||
const color32 white_c{255,255,255};
|
||||
const color32 gray_c{255,255,255,127};
|
||||
|
||||
ctx.draw_wire_rect(
|
||||
c->size() * 0.5f,
|
||||
c->size(),
|
||||
ctx.selected() ? white_c : gray_c);
|
||||
|
||||
if ( ctx.selected() ) {
|
||||
if ( c->margin() != v2f::zero() ) {
|
||||
ctx.draw_wire_rect(
|
||||
c->size() * 0.5f,
|
||||
c->size() + c->margin() * 2.f,
|
||||
ctx.selected() ? white_c : gray_c);
|
||||
}
|
||||
|
||||
if ( c->padding() != v2f::zero() ) {
|
||||
ctx.draw_wire_rect(
|
||||
c->size() * 0.5f,
|
||||
c->size() - c->padding() * 2.f,
|
||||
ctx.selected() ? white_c : gray_c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::widgets
|
||||
{
|
||||
gcomponent<widget> mark_dirty(gcomponent<widget> self) {
|
||||
if ( self ) {
|
||||
self.owner().component<widget::dirty>().ensure();
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
gcomponent<widget> unmark_dirty(gcomponent<widget> self) {
|
||||
if ( self ) {
|
||||
self.owner().component<widget::dirty>().remove();
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
bool is_dirty(const const_gcomponent<widget>& self) noexcept {
|
||||
return self.owner().component<widget::dirty>().exists();
|
||||
}
|
||||
|
||||
gcomponent<widget> change_size(gcomponent<widget> self, const v2f& value) {
|
||||
if ( self ) {
|
||||
self->size(value);
|
||||
}
|
||||
return mark_dirty(self);
|
||||
}
|
||||
|
||||
gcomponent<widget> change_margin(gcomponent<widget> self, const v2f& value) {
|
||||
if ( self ) {
|
||||
self->margin(value);
|
||||
}
|
||||
return mark_dirty(self);
|
||||
}
|
||||
|
||||
gcomponent<widget> change_padding(gcomponent<widget> self, const v2f& value) {
|
||||
if ( self ) {
|
||||
self->padding(value);
|
||||
}
|
||||
return mark_dirty(self);
|
||||
}
|
||||
|
||||
gcomponent<layout> find_parent_layout(const_gcomponent<widget> self) noexcept {
|
||||
const_gcomponent<actor> self_actor = self.owner().component<actor>();
|
||||
return self_actor
|
||||
? nodes::find_component_from_parents<layout>(self_actor->node())
|
||||
: gcomponent<layout>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,6 +214,7 @@ namespace e2d
|
||||
.register_component<touchable>("touchable")
|
||||
.register_component<events<touchable_events::event>>("touchable.events")
|
||||
.register_component<widget>("widget")
|
||||
.register_component<widget::dirty>("widget.dirty")
|
||||
;
|
||||
|
||||
safe_module_initialize<inspector>()
|
||||
@@ -241,6 +242,7 @@ namespace e2d
|
||||
.register_component<touchable>("touchable")
|
||||
//.register_component<events<touchable_events::event>>("touchable.events")
|
||||
.register_component<widget>("widget")
|
||||
//.register_component<widget::dirty>("widget.dirty")
|
||||
;
|
||||
|
||||
safe_module_initialize<luasol>();
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <enduro2d/high/components/actor.hpp>
|
||||
#include <enduro2d/high/components/disabled.hpp>
|
||||
#include <enduro2d/high/components/layout.hpp>
|
||||
#include <enduro2d/high/components/widget.hpp>
|
||||
|
||||
#include <3rdparty/yoga/Yoga.h>
|
||||
|
||||
@@ -21,153 +22,119 @@ namespace
|
||||
node_ptr as_item{YGNodeNew(), YGNodeFree};
|
||||
node_ptr as_root{YGNodeNew(), YGNodeFree};
|
||||
};
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace e2d;
|
||||
|
||||
void update_yogo_node(const yogo_node& yn, const layout& l, const actor& a) {
|
||||
switch ( l.direction() ) {
|
||||
case layout::directions::row:
|
||||
YGNodeStyleSetFlexDirection(yn.as_root.get(), YGFlexDirectionRow);
|
||||
break;
|
||||
case layout::directions::row_reversed:
|
||||
YGNodeStyleSetFlexDirection(yn.as_root.get(), YGFlexDirectionRowReverse);
|
||||
break;
|
||||
case layout::directions::column:
|
||||
YGNodeStyleSetFlexDirection(yn.as_root.get(), YGFlexDirectionColumn);
|
||||
break;
|
||||
case layout::directions::column_reversed:
|
||||
YGNodeStyleSetFlexDirection(yn.as_root.get(), YGFlexDirectionColumnReverse);
|
||||
break;
|
||||
YGDirection convert_to_yogo_direction(layout::directions direction) noexcept {
|
||||
switch ( direction ) {
|
||||
case layout::directions::ltr:
|
||||
return YGDirectionLTR;
|
||||
case layout::directions::rtl:
|
||||
return YGDirectionRTL;
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected layout direction");
|
||||
break;
|
||||
return YGDirectionLTR;
|
||||
}
|
||||
}
|
||||
|
||||
switch ( l.direction() ) {
|
||||
case layout::directions::row:
|
||||
case layout::directions::row_reversed:
|
||||
switch ( l.halign() ) {
|
||||
case layout::haligns::left:
|
||||
YGNodeStyleSetJustifyContent(yn.as_root.get(), YGJustifyFlexStart);
|
||||
break;
|
||||
case layout::haligns::center:
|
||||
YGNodeStyleSetJustifyContent(yn.as_root.get(), YGJustifyCenter);
|
||||
break;
|
||||
case layout::haligns::right:
|
||||
YGNodeStyleSetJustifyContent(yn.as_root.get(), YGJustifyFlexEnd);
|
||||
break;
|
||||
case layout::haligns::space_around:
|
||||
YGNodeStyleSetJustifyContent(yn.as_root.get(), YGJustifySpaceAround);
|
||||
break;
|
||||
case layout::haligns::space_evenly:
|
||||
YGNodeStyleSetJustifyContent(yn.as_root.get(), YGJustifySpaceEvenly);
|
||||
break;
|
||||
case layout::haligns::space_between:
|
||||
YGNodeStyleSetJustifyContent(yn.as_root.get(), YGJustifySpaceBetween);
|
||||
break;
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected layout halign");
|
||||
break;
|
||||
}
|
||||
|
||||
switch ( l.valign() ) {
|
||||
case layout::valigns::top:
|
||||
case layout::valigns::space_between:
|
||||
YGNodeStyleSetAlignItems(yn.as_root.get(), YGAlignFlexEnd);
|
||||
break;
|
||||
case layout::valigns::center:
|
||||
case layout::valigns::space_around:
|
||||
case layout::valigns::space_evenly:
|
||||
YGNodeStyleSetAlignItems(yn.as_root.get(), YGAlignCenter);
|
||||
break;
|
||||
case layout::valigns::bottom:
|
||||
YGNodeStyleSetAlignItems(yn.as_root.get(), YGAlignFlexStart);
|
||||
break;
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected layout valign");
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case layout::directions::column:
|
||||
case layout::directions::column_reversed:
|
||||
switch ( l.valign() ) {
|
||||
case layout::valigns::top:
|
||||
YGNodeStyleSetJustifyContent(yn.as_root.get(), YGJustifyFlexEnd);
|
||||
break;
|
||||
case layout::valigns::center:
|
||||
YGNodeStyleSetJustifyContent(yn.as_root.get(), YGJustifyCenter);
|
||||
break;
|
||||
case layout::valigns::bottom:
|
||||
YGNodeStyleSetJustifyContent(yn.as_root.get(), YGJustifyFlexStart);
|
||||
break;
|
||||
case layout::valigns::space_around:
|
||||
YGNodeStyleSetJustifyContent(yn.as_root.get(), YGJustifySpaceAround);
|
||||
break;
|
||||
case layout::valigns::space_evenly:
|
||||
YGNodeStyleSetJustifyContent(yn.as_root.get(), YGJustifySpaceEvenly);
|
||||
break;
|
||||
case layout::valigns::space_between:
|
||||
YGNodeStyleSetJustifyContent(yn.as_root.get(), YGJustifySpaceBetween);
|
||||
break;
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected layout valign");
|
||||
break;
|
||||
}
|
||||
|
||||
switch ( l.halign() ) {
|
||||
case layout::haligns::left:
|
||||
case layout::haligns::space_between:
|
||||
YGNodeStyleSetAlignItems(yn.as_root.get(), YGAlignFlexStart);
|
||||
break;
|
||||
case layout::haligns::center:
|
||||
case layout::haligns::space_around:
|
||||
case layout::haligns::space_evenly:
|
||||
YGNodeStyleSetAlignItems(yn.as_root.get(), YGAlignCenter);
|
||||
break;
|
||||
case layout::haligns::right:
|
||||
YGNodeStyleSetAlignItems(yn.as_root.get(), YGAlignFlexEnd);
|
||||
break;
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected layout halign");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
YGAlign convert_to_yogo_align(layout::align_modes align_mode) noexcept {
|
||||
switch ( align_mode ) {
|
||||
case layout::align_modes::flex_start:
|
||||
return YGAlignFlexStart;
|
||||
case layout::align_modes::center:
|
||||
return YGAlignCenter;
|
||||
case layout::align_modes::flex_end:
|
||||
return YGAlignFlexEnd;
|
||||
case layout::align_modes::space_between:
|
||||
return YGAlignSpaceBetween;
|
||||
case layout::align_modes::space_around:
|
||||
return YGAlignSpaceAround;
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected layout mode");
|
||||
break;
|
||||
E2D_ASSERT_MSG(false, "unexpected layout align mode");
|
||||
return YGAlignFlexStart;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
YGNodeStyleSetWidth(yn.as_root.get(), l.size().x);
|
||||
YGNodeStyleSetHeight(yn.as_root.get(), l.size().y);
|
||||
|
||||
YGNodeStyleSetPadding(yn.as_root.get(), YGEdgeHorizontal, l.padding().x);
|
||||
YGNodeStyleSetPadding(yn.as_root.get(), YGEdgeVertical, l.padding().y);
|
||||
YGJustify convert_to_yogo_justify(layout::justify_modes justify_mode) noexcept {
|
||||
switch ( justify_mode ) {
|
||||
case layout::justify_modes::flex_start:
|
||||
return YGJustifyFlexStart;
|
||||
case layout::justify_modes::center:
|
||||
return YGJustifyCenter;
|
||||
case layout::justify_modes::flex_end:
|
||||
return YGJustifyFlexEnd;
|
||||
case layout::justify_modes::space_between:
|
||||
return YGJustifySpaceBetween;
|
||||
case layout::justify_modes::space_around:
|
||||
return YGJustifySpaceAround;
|
||||
case layout::justify_modes::space_evenly:
|
||||
return YGJustifySpaceEvenly;
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected layout justify mode");
|
||||
return YGJustifyFlexStart;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const v2f& scale = a.node()
|
||||
? a.node()->scale()
|
||||
: v2f::unit();
|
||||
|
||||
YGNodeStyleSetWidth(yn.as_item.get(), l.size().x * scale.x);
|
||||
YGNodeStyleSetHeight(yn.as_item.get(), l.size().y * scale.y);
|
||||
|
||||
YGNodeStyleSetMargin(yn.as_item.get(), YGEdgeHorizontal, l.margin().x * scale.x);
|
||||
YGNodeStyleSetMargin(yn.as_item.get(), YGEdgeVertical, l.margin().y * scale.y);
|
||||
YGWrap convert_to_yogo_flex_wrap(layout::flex_wraps flex_wrap) noexcept {
|
||||
switch ( flex_wrap ) {
|
||||
case layout::flex_wraps::no_wrap:
|
||||
return YGWrapNoWrap;
|
||||
case layout::flex_wraps::wrap:
|
||||
return YGWrapWrap;
|
||||
case layout::flex_wraps::wrap_reversed:
|
||||
return YGWrapWrapReverse;
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected layout flex wrap");
|
||||
return YGWrapNoWrap;
|
||||
}
|
||||
}
|
||||
|
||||
YGFlexDirection convert_to_yogo_flex_direction(layout::flex_directions flex_direction) noexcept {
|
||||
switch ( flex_direction ) {
|
||||
case layout::flex_directions::row:
|
||||
return YGFlexDirectionRow;
|
||||
case layout::flex_directions::row_reversed:
|
||||
return YGFlexDirectionRowReverse;
|
||||
case layout::flex_directions::column:
|
||||
return YGFlexDirectionColumn;
|
||||
case layout::flex_directions::column_reversed:
|
||||
return YGFlexDirectionColumnReverse;
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected layout flex direction");
|
||||
return YGFlexDirectionRow;
|
||||
}
|
||||
}
|
||||
|
||||
void update_yogo_layout(const yogo_node& yn, const layout& l, const widget& w) {
|
||||
YGNodeStyleSetWidth(yn.as_root.get(), w.size().x);
|
||||
YGNodeStyleSetHeight(yn.as_root.get(), w.size().y);
|
||||
|
||||
YGNodeStyleSetPadding(yn.as_root.get(), YGEdgeHorizontal, w.padding().x);
|
||||
YGNodeStyleSetPadding(yn.as_root.get(), YGEdgeVertical, w.padding().y);
|
||||
|
||||
YGNodeStyleSetAlignItems(yn.as_root.get(), convert_to_yogo_align(l.align_items()));
|
||||
YGNodeStyleSetAlignContent(yn.as_root.get(), convert_to_yogo_align(l.align_content()));
|
||||
YGNodeStyleSetJustifyContent(yn.as_root.get(), convert_to_yogo_justify(l.justify_content()));
|
||||
YGNodeStyleSetFlexWrap(yn.as_root.get(), convert_to_yogo_flex_wrap(l.flex_wrap()));
|
||||
YGNodeStyleSetFlexDirection(yn.as_root.get(), convert_to_yogo_flex_direction(l.flex_direction()));
|
||||
}
|
||||
|
||||
void update_yogo_widget(const yogo_node& yn, const widget& w, const actor& a) {
|
||||
const v2f& scale = a.node()
|
||||
? a.node()->scale()
|
||||
: v2f::unit();
|
||||
|
||||
YGNodeStyleSetWidth(yn.as_item.get(), w.size().x * scale.x);
|
||||
YGNodeStyleSetHeight(yn.as_item.get(), w.size().y * scale.y);
|
||||
|
||||
YGNodeStyleSetMargin(yn.as_item.get(), YGEdgeHorizontal, w.margin().x * scale.x);
|
||||
YGNodeStyleSetMargin(yn.as_item.get(), YGEdgeVertical, w.margin().y * scale.y);
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace e2d;
|
||||
|
||||
void process_yogo_nodes(ecs::registry& owner) {
|
||||
void update_yogo_nodes(ecs::registry& owner) {
|
||||
ecsex::remove_all_components_with_disposer<yogo_node>(
|
||||
owner,
|
||||
[](ecs::entity e, const yogo_node&){
|
||||
@@ -175,65 +142,65 @@ namespace
|
||||
a && a->node() && a->node()->owner() )
|
||||
{
|
||||
gcomponent<layout> l{a->node()->owner()};
|
||||
gcomponent<widget> w{a->node()->owner()};
|
||||
layouts::mark_dirty(l);
|
||||
layouts::mark_dirty(layouts::find_parent_layout(l));
|
||||
layouts::mark_dirty(widgets::find_parent_layout(w));
|
||||
}
|
||||
},
|
||||
!ecs::exists_all<
|
||||
}, !ecs::exists_all<
|
||||
actor,
|
||||
layout>() ||
|
||||
ecs::exists_any<
|
||||
widget>()
|
||||
|| ecs::exists_any<
|
||||
disabled<actor>,
|
||||
disabled<layout>>());
|
||||
disabled<widget>>());
|
||||
|
||||
owner.for_joined_components<layout, actor>([](
|
||||
owner.for_joined_components<widget, actor>([](
|
||||
ecs::entity e,
|
||||
const layout&,
|
||||
const widget&,
|
||||
const actor& a)
|
||||
{
|
||||
e.ensure_component<yogo_node>();
|
||||
if ( a.node() && a.node()->owner() ) {
|
||||
gcomponent<layout> l{a.node()->owner()};
|
||||
gcomponent<widget> w{a.node()->owner()};
|
||||
layouts::mark_dirty(l);
|
||||
layouts::mark_dirty(layouts::find_parent_layout(l));
|
||||
layouts::mark_dirty(widgets::find_parent_layout(w));
|
||||
}
|
||||
},
|
||||
!ecs::exists_any<
|
||||
}, !ecs::exists_any<
|
||||
yogo_node,
|
||||
disabled<actor>,
|
||||
disabled<layout>>());
|
||||
disabled<widget>>());
|
||||
}
|
||||
|
||||
void process_dirty_layouts(ecs::registry& owner) {
|
||||
owner.for_joined_components<layout::dirty, yogo_node, layout, actor>([](
|
||||
void update_dirty_layouts(ecs::registry& owner) {
|
||||
owner.for_joined_components<layout::dirty, yogo_node, layout, widget, actor>([](
|
||||
const ecs::const_entity&,
|
||||
const layout::dirty&,
|
||||
const yogo_node& root_yn,
|
||||
const layout& root_l,
|
||||
const widget& root_w,
|
||||
const actor& root_a)
|
||||
{
|
||||
update_yogo_node(root_yn, root_l, root_a);
|
||||
});
|
||||
static thread_local vector<gcomponent<widget>> item_ws;
|
||||
E2D_DEFER([](){ item_ws.clear(); });
|
||||
|
||||
owner.for_joined_components<layout::dirty, yogo_node, actor>([](
|
||||
const ecs::const_entity&,
|
||||
const layout::dirty&,
|
||||
const yogo_node& root_yn,
|
||||
const actor& root_a)
|
||||
{
|
||||
static thread_local vector<gcomponent<layout>> items;
|
||||
E2D_DEFER([](){ items.clear(); });
|
||||
|
||||
nodes::extract_components_from_children<layout>(
|
||||
nodes::extract_components_from_children<widget>(
|
||||
root_a.node(),
|
||||
std::back_inserter(items));
|
||||
std::back_inserter(item_ws));
|
||||
|
||||
E2D_DEFER([&root_yn](){
|
||||
YGNodeRemoveAllChildren(root_yn.as_root.get());
|
||||
});
|
||||
|
||||
for ( const auto& item : items ) {
|
||||
if ( const auto& item_yn = item.owner().component<yogo_node>() ) {
|
||||
update_yogo_layout(root_yn, root_l, root_w);
|
||||
|
||||
for ( const auto& item_w : item_ws ) {
|
||||
const_gcomponent<actor> item_a{item_w.owner()};
|
||||
const_gcomponent<yogo_node> item_yn{item_w.owner()};
|
||||
if ( item_a && item_yn ) {
|
||||
update_yogo_widget(
|
||||
*item_yn,
|
||||
*item_w,
|
||||
*item_a);
|
||||
YGNodeInsertChild(
|
||||
root_yn.as_root.get(),
|
||||
item_yn->as_item.get(),
|
||||
@@ -245,11 +212,11 @@ namespace
|
||||
root_yn.as_root.get(),
|
||||
YGUndefined,
|
||||
YGUndefined,
|
||||
YGDirectionLTR);
|
||||
convert_to_yogo_direction(root_l.direction()));
|
||||
|
||||
for ( const auto& item : items ) {
|
||||
gcomponent<actor> item_a = item.owner().component<actor>();
|
||||
const_gcomponent<yogo_node> item_yn = item.owner().component<yogo_node>();
|
||||
for ( const auto& item_w : item_ws ) {
|
||||
gcomponent<actor> item_a{item_w.owner()};
|
||||
const_gcomponent<yogo_node> item_yn{item_w.owner()};
|
||||
if ( item_a && item_a->node() && item_yn && item_yn->as_item ) {
|
||||
item_a->node()->translation(v2f(
|
||||
YGNodeLayoutGetLeft(item_yn->as_item.get()),
|
||||
@@ -274,8 +241,8 @@ namespace e2d
|
||||
~internal_state() noexcept = default;
|
||||
|
||||
void process_update(ecs::registry& owner) {
|
||||
process_yogo_nodes(owner);
|
||||
process_dirty_layouts(owner);
|
||||
update_yogo_nodes(owner);
|
||||
update_dirty_layouts(owner);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,36 @@
|
||||
|
||||
#include <enduro2d/high/systems/widget_system.hpp>
|
||||
|
||||
#include <enduro2d/high/components/actor.hpp>
|
||||
#include <enduro2d/high/components/disabled.hpp>
|
||||
#include <enduro2d/high/components/layout.hpp>
|
||||
#include <enduro2d/high/components/widget.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace e2d;
|
||||
|
||||
void update_dirty_widgets(ecs::registry& owner) {
|
||||
owner.for_joined_components<widget::dirty, widget, actor>([](
|
||||
const ecs::const_entity&,
|
||||
const widget::dirty&,
|
||||
const widget&,
|
||||
const actor& a)
|
||||
{
|
||||
if ( a.node() && a.node()->owner() ) {
|
||||
gcomponent<layout> l{a.node()->owner()};
|
||||
gcomponent<widget> w{a.node()->owner()};
|
||||
layouts::mark_dirty(l);
|
||||
layouts::mark_dirty(widgets::find_parent_layout(w));
|
||||
}
|
||||
}, !ecs::exists_any<
|
||||
disabled<actor>,
|
||||
disabled<widget>>());
|
||||
|
||||
owner.remove_all_components<widget::dirty>();
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
//
|
||||
@@ -18,7 +48,7 @@ namespace e2d
|
||||
~internal_state() noexcept = default;
|
||||
|
||||
void process_update(ecs::registry& owner) {
|
||||
E2D_UNUSED(owner);
|
||||
update_dirty_widgets(owner);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user