basic layout system impl

This commit is contained in:
BlackMATov
2020-02-07 11:13:20 +07:00
parent d584224223
commit 7075fb4fb4
5 changed files with 210 additions and 69 deletions

View File

@@ -13,36 +13,36 @@ namespace e2d
class layout final { class layout final {
public: public:
ENUM_HPP_CLASS_DECL(modes, u8, ENUM_HPP_CLASS_DECL(modes, u8,
(vertical) (horizontal)
(horizontal)) (vertical))
ENUM_HPP_CLASS_DECL(valigns, u8,
(top)
(center)
(bottom))
ENUM_HPP_CLASS_DECL(haligns, u8, ENUM_HPP_CLASS_DECL(haligns, u8,
(left) (left)
(center) (center)
(right)) (right))
ENUM_HPP_CLASS_DECL(valigns, u8,
(top)
(center)
(bottom))
public: public:
layout() = default; layout() = default;
layout& mode(modes value) noexcept; layout& mode(modes value) noexcept;
[[nodiscard]] modes mode() const noexcept; [[nodiscard]] modes mode() const noexcept;
layout& valign(valigns value) noexcept;
[[nodiscard]] valigns valign() const noexcept;
layout& halign(haligns value) noexcept; layout& halign(haligns value) noexcept;
[[nodiscard]] haligns halign() const noexcept; [[nodiscard]] haligns halign() const noexcept;
layout& valign(valigns value) noexcept;
[[nodiscard]] valigns valign() const noexcept;
layout& spacing(f32 value) noexcept; layout& spacing(f32 value) noexcept;
[[nodiscard]] f32 spacing() const noexcept; [[nodiscard]] f32 spacing() const noexcept;
private: private:
modes mode_ = modes::vertical; modes mode_ = modes::horizontal;
valigns valign_ = valigns::center;
haligns halign_ = haligns::center; haligns halign_ = haligns::center;
valigns valign_ = valigns::center;
f32 spacing_ = 0.f; f32 spacing_ = 0.f;
}; };
@@ -123,15 +123,6 @@ namespace e2d
return mode_; return mode_;
} }
inline layout& layout::valign(valigns value) noexcept {
valign_ = value;
return *this;
}
inline layout::valigns layout::valign() const noexcept {
return valign_;
}
inline layout& layout::halign(haligns value) noexcept { inline layout& layout::halign(haligns value) noexcept {
halign_ = value; halign_ = value;
return *this; return *this;
@@ -141,6 +132,15 @@ namespace e2d
return halign_; 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::spacing(f32 value) noexcept { inline layout& layout::spacing(f32 value) noexcept {
spacing_ = value; spacing_ = value;
return *this; return *this;

View File

@@ -13,29 +13,22 @@ local layout = {
disabled = false, disabled = false,
---@type layout_modes ---@type layout_modes
mode = layout.modes.vertical, mode = layout.modes.horizontal,
---@type layout_valigns
valign = layout.valigns.center,
---@type layout_haligns ---@type layout_haligns
halign = layout.haligns.center, halign = layout.haligns.center,
---@type layout_valigns
valign = layout.valigns.center,
---@type number ---@type number
spacing = 0.0 spacing = 0.0
} }
---@class layout_modes ---@class layout_modes
layout.modes = { layout.modes = {
vertical = "vertical", horizontal = "horizontal",
horizontal = "horizontal" vertical = "vertical"
}
---@class layout_valigns
layout.valigns = {
top = "top",
center = "center",
bottom = "bottom"
} }
---@class layout_haligns ---@class layout_haligns
@@ -45,6 +38,13 @@ layout.haligns = {
right = "right" right = "right"
} }
---@class layout_valigns
layout.valigns = {
top = "top",
center = "center",
bottom = "bottom"
}
---@overload fun(self: layout) ---@overload fun(self: layout)
---@param self layout ---@param self layout
function layout.enable(self) end function layout.enable(self) end

View File

@@ -58,14 +58,6 @@ namespace e2d::bindings::high
c->mode(v); c->mode(v);
}), }),
"valign", sol::property(
[](const gcomponent<layout>& c) -> layout::valigns {
return c->valign();
},
[](gcomponent<layout>& c, layout::valigns v){
c->valign(v);
}),
"halign", sol::property( "halign", sol::property(
[](const gcomponent<layout>& c) -> layout::haligns { [](const gcomponent<layout>& c) -> layout::haligns {
return c->halign(); return c->halign();
@@ -74,6 +66,14 @@ namespace e2d::bindings::high
c->halign(v); c->halign(v);
}), }),
"valign", sol::property(
[](const gcomponent<layout>& c) -> layout::valigns {
return c->valign();
},
[](gcomponent<layout>& c, layout::valigns v){
c->valign(v);
}),
"spacing", sol::property( "spacing", sol::property(
[](const gcomponent<layout>& c) -> f32 { [](const gcomponent<layout>& c) -> f32 {
return c->spacing(); return c->spacing();

View File

@@ -14,24 +14,16 @@ namespace e2d
"additionalProperties" : false, "additionalProperties" : false,
"properties" : { "properties" : {
"mode" : { "$ref": "#/definitions/modes" }, "mode" : { "$ref": "#/definitions/modes" },
"valign" : { "$ref": "#/definitions/valigns" },
"halign" : { "$ref": "#/definitions/haligns" }, "halign" : { "$ref": "#/definitions/haligns" },
"valign" : { "$ref": "#/definitions/valigns" },
"spacing" : { "type" : "number" } "spacing" : { "type" : "number" }
}, },
"definitions" : { "definitions" : {
"modes" : { "modes" : {
"type" : "string", "type" : "string",
"enum" : [ "enum" : [
"vertical", "horizontal",
"horizontal" "vertical"
]
},
"valigns" : {
"type" : "string",
"enum" : [
"top",
"center",
"bottom"
] ]
}, },
"haligns" : { "haligns" : {
@@ -41,6 +33,14 @@ namespace e2d
"center", "center",
"right" "right"
] ]
},
"valigns" : {
"type" : "string",
"enum" : [
"top",
"center",
"bottom"
]
} }
} }
})json"; })json";
@@ -58,15 +58,6 @@ namespace e2d
component.mode(mode); component.mode(mode);
} }
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("halign") ) { if ( ctx.root.HasMember("halign") ) {
layout::haligns halign = component.halign(); layout::haligns halign = component.halign();
if ( !json_utils::try_parse_value(ctx.root["halign"], halign) ) { if ( !json_utils::try_parse_value(ctx.root["halign"], halign) ) {
@@ -76,6 +67,15 @@ namespace e2d
component.halign(halign); 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("spacing") ) { if ( ctx.root.HasMember("spacing") ) {
f32 spacing = component.spacing(); f32 spacing = component.spacing();
if ( !json_utils::try_parse_value(ctx.root["spacing"], spacing) ) { if ( !json_utils::try_parse_value(ctx.root["spacing"], spacing) ) {
@@ -144,18 +144,18 @@ namespace e2d
c->mode(mode); c->mode(mode);
} }
if ( layout::valigns valign = c->valign();
imgui_utils::show_enum_combo_box("valign", &valign) )
{
c->valign(valign);
}
if ( layout::haligns halign = c->halign(); if ( layout::haligns halign = c->halign();
imgui_utils::show_enum_combo_box("halign", &halign) ) imgui_utils::show_enum_combo_box("halign", &halign) )
{ {
c->halign(halign); c->halign(halign);
} }
if ( layout::valigns valign = c->valign();
imgui_utils::show_enum_combo_box("valign", &valign) )
{
c->valign(valign);
}
if ( f32 spacing = c->spacing(); if ( f32 spacing = c->spacing();
ImGui::DragFloat("spacing", &spacing, 1.f) ) ImGui::DragFloat("spacing", &spacing, 1.f) )
{ {

View File

@@ -6,8 +6,141 @@
#include <enduro2d/high/systems/layout_system.hpp> #include <enduro2d/high/systems/layout_system.hpp>
#include <enduro2d/high/components/actor.hpp>
#include <enduro2d/high/components/disabled.hpp>
#include <enduro2d/high/components/layout.hpp> #include <enduro2d/high/components/layout.hpp>
namespace
{
using namespace e2d;
bool is_layout_item_enabled(const const_gcomponent<layout_item>& item) noexcept {
const auto filter = !ecs::exists_any<
disabled<actor>,
disabled<layout_item>
>() && ecs::exists_all<
actor,
layout_item
>();
return item
|| filter(item.owner().raw_entity())
|| item.owner().component<actor>()->node();
}
void update_layout_items(const layout& layout, const const_node_iptr& layout_node) {
static thread_local vector<gcomponent<layout_item>> items;
E2D_DEFER([](){ items.clear(); });
nodes::extract_components_from_children<layout_item>(
layout_node,
std::back_inserter(items));
//
// layout size
//
v2f layout_size = v2f::zero();
for ( std::size_t i = 0; i < items.size(); ++i ) {
const gcomponent<layout_item>& item = items[i];
if ( !is_layout_item_enabled(item) ) {
continue;
}
layout_size += item->size();
if ( i > 0u ) {
layout_size += layout.spacing();
}
}
//
// cursor offsets
//
v2f item_cursor = v2f::zero();
v2f size_offset_mul = v2f::zero();
v2f cursor_offset_mul = v2f::zero();
if ( layout.mode() == layout::modes::horizontal ) {
cursor_offset_mul = v2f::unit_x();
switch ( layout.halign() ) {
case layout::haligns::left:
item_cursor = 0.0f * layout_size.x * cursor_offset_mul;
break;
case layout::haligns::center:
item_cursor = -0.5f * layout_size.x * cursor_offset_mul;
break;
case layout::haligns::right:
item_cursor = -1.0f * layout_size.x * cursor_offset_mul;
break;
default:
E2D_ASSERT_MSG(false, "unexpected layout halign");
}
switch ( layout.valign() ) {
case layout::valigns::top:
size_offset_mul = -1.0f * v2f::unit_y();
break;
case layout::valigns::center:
size_offset_mul = -0.5f * v2f::unit_y();
break;
case layout::valigns::bottom:
size_offset_mul = 0.0f * v2f::unit_y();
break;
default:
E2D_ASSERT_MSG(false, "unexpected layout valign");
}
} else if ( layout.mode() == layout::modes::vertical ) {
cursor_offset_mul = v2f::unit_y();
switch ( layout.valign() ) {
case layout::valigns::top:
item_cursor = -1.0f * layout_size.y * cursor_offset_mul;
break;
case layout::valigns::center:
item_cursor = -0.5f * layout_size.y * cursor_offset_mul;
break;
case layout::valigns::bottom:
item_cursor = 0.0f * layout_size.y * cursor_offset_mul;
break;
default:
E2D_ASSERT_MSG(false, "unexpected layout valign");
}
switch ( layout.halign() ) {
case layout::haligns::left:
size_offset_mul = 0.0f * v2f::unit_x();
break;
case layout::haligns::center:
size_offset_mul = -0.5f * v2f::unit_x();
break;
case layout::haligns::right:
size_offset_mul = -1.0f * v2f::unit_x();
break;
default:
E2D_ASSERT_MSG(false, "unexpected layout halign");
}
} else {
E2D_ASSERT_MSG(false, "unexpected layout mode");
}
//
// placing
//
for ( std::size_t i = 0; i < items.size(); ++i ) {
const gcomponent<layout_item>& item = items[i];
if ( !is_layout_item_enabled(item) ) {
continue;
}
const node_iptr& item_node = item.owner().component<actor>()->node();
item_node->translation(item_cursor + item->size() * size_offset_mul);
item_cursor += (item->size() + layout.spacing()) * cursor_offset_mul;
}
}
}
namespace e2d namespace e2d
{ {
// //
@@ -20,7 +153,15 @@ namespace e2d
~internal_state() noexcept = default; ~internal_state() noexcept = default;
void process_update(ecs::registry& owner) { void process_update(ecs::registry& owner) {
E2D_UNUSED(owner); owner.for_joined_components<layout, actor>([](
const ecs::const_entity&,
const layout& layout,
const actor& layout_actor)
{
update_layout_items(layout, layout_actor.node());
}, !ecs::exists_any<
disabled<actor>,
disabled<layout>>());
} }
}; };