From 20c35f2911a98f67296ab1fada80306b1b864dbf Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 22 Apr 2020 06:52:01 +0700 Subject: [PATCH 01/11] add uuid property to prefab, rename prototype to parent --- headers/enduro2d/high/resources/prefab.hpp | 22 ++-- sources/enduro2d/high/assets/prefab_asset.cpp | 106 ++++++++++-------- sources/enduro2d/high/resources/prefab.cpp | 56 +++++---- sources/enduro2d/utils/json_utils.cpp | 6 + untests/bin/library/parent.json | 12 ++ untests/bin/library/prefab.json | 12 +- 6 files changed, 131 insertions(+), 83 deletions(-) create mode 100644 untests/bin/library/parent.json diff --git a/headers/enduro2d/high/resources/prefab.hpp b/headers/enduro2d/high/resources/prefab.hpp index 336290f8..8e5b3f8e 100644 --- a/headers/enduro2d/high/resources/prefab.hpp +++ b/headers/enduro2d/high/resources/prefab.hpp @@ -27,22 +27,30 @@ namespace e2d prefab& assign(prefab&& other) noexcept; prefab& assign(const prefab& other); - prefab& set_prototype(ecs::prototype&& proto) noexcept; - prefab& set_prototype(const ecs::prototype& proto); + prefab& set_uuid(str&& uuid) noexcept; + prefab& set_uuid(const str& uuid); prefab& set_children(vector&& children) noexcept; prefab& set_children(const vector& children); + prefab& set_prototype(ecs::prototype&& prototype) noexcept; + prefab& set_prototype(const ecs::prototype& prototype); + + str& uuid() noexcept; + const str& uuid() const noexcept; + + vector& children() noexcept; + const vector& children() const noexcept; + ecs::prototype& prototype() noexcept; const ecs::prototype& prototype() const noexcept; - - const vector& children() const noexcept; private: - ecs::prototype prototype_; + str uuid_; vector children_; + ecs::prototype prototype_; }; void swap(prefab& l, prefab& r) noexcept; - bool operator==(const prefab& l, const prefab& r) noexcept; - bool operator!=(const prefab& l, const prefab& r) noexcept; + bool operator==(const prefab& l, const prefab& r) = delete; + bool operator!=(const prefab& l, const prefab& r) = delete; } diff --git a/sources/enduro2d/high/assets/prefab_asset.cpp b/sources/enduro2d/high/assets/prefab_asset.cpp index a1af71a7..7028c4b3 100644 --- a/sources/enduro2d/high/assets/prefab_asset.cpp +++ b/sources/enduro2d/high/assets/prefab_asset.cpp @@ -24,12 +24,10 @@ namespace "required" : [], "additionalProperties" : false, "properties" : { - "prototype" : { "$ref": "#/common_definitions/address" }, - "components" : { "type" : "object" }, - "children" : { - "type" : "array", - "items" : { "$ref": "#/definitions/child" } - } + "uuid" : { "$ref": "#/common_definitions/uuid" }, + "parent" : { "$ref": "#/common_definitions/address" }, + "children" : { "$ref": "#/definitions/children" }, + "components" : { "type" : "object" } }, "definitions" : { "child" : { @@ -37,13 +35,15 @@ namespace "required" : [], "additionalProperties" : false, "properties" : { - "prototype" : { "$ref": "#/common_definitions/address" }, - "components" : { "type" : "object" }, - "children" : { - "type" : "array", - "items" : { "$ref": "#/definitions/child" } - } + "uuid" : { "$ref": "#/common_definitions/uuid" }, + "parent" : { "$ref": "#/common_definitions/address" }, + "children" : { "$ref": "#/definitions/children" }, + "components" : { "type" : "object" } } + }, + "children" : { + "type" : "array", + "items" : { "$ref": "#/definitions/child" } } } })json"; @@ -71,9 +71,16 @@ namespace const rapidjson::Value& root, asset_dependencies& dependencies) { - if ( root.HasMember("prototype") ) { + if ( root.HasMember("parent") ) { dependencies.add_dependency( - path::combine(parent_address, root["prototype"].GetString())); + path::combine(parent_address, root["parent"].GetString())); + } + + if ( root.HasMember("children") ) { + const rapidjson::Value& children_root = root["children"]; + for ( rapidjson::SizeType i = 0; i < children_root.Size(); ++i ) { + collect_dependencies(parent_address, children_root[i], dependencies); + } } if ( root.HasMember("components") ) { @@ -83,7 +90,7 @@ namespace ++component_root ) { { - bool success = the().validate_json( + const bool success = the().validate_json( component_root->name.GetString(), component_root->value); if ( !success ) { @@ -94,7 +101,7 @@ namespace factory_loader<>::collect_context ctx( str(parent_address), component_root->value); - bool success = the().collect_dependencies( + const bool success = the().collect_dependencies( component_root->name.GetString(), dependencies, ctx); @@ -104,13 +111,6 @@ namespace } } } - - if ( root.HasMember("children") ) { - const rapidjson::Value& children_root = root["children"]; - for ( rapidjson::SizeType i = 0; i < children_root.Size(); ++i ) { - collect_dependencies(parent_address, children_root[i], dependencies); - } - } } stdex::promise collect_dependencies( @@ -130,38 +130,28 @@ namespace { prefab content; - if ( root.HasMember("prototype") ) { + if ( root.HasMember("uuid") ) { + str uuid = content.uuid(); + if ( !json_utils::try_parse_value(root["uuid"], uuid) ) { + the().error("PREFAB: Incorrect formatting of 'uuid' property"); + throw prefab_asset_loading_exception(); + } + content.set_uuid(std::move(uuid)); + } + + if ( root.HasMember("parent") ) { auto proto_res = dependencies.find_asset( - path::combine(parent_address, root["prototype"].GetString())); + path::combine(parent_address, root["parent"].GetString())); if ( !proto_res ) { - the().error("PREFAB: Dependency 'prototype' is not found:\n" + the().error("PREFAB: Dependency 'parent' is not found:\n" "--> Parent address: %0\n" "--> Dependency address: %1", parent_address, - root["prototype"].GetString()); + root["parent"].GetString()); throw prefab_asset_loading_exception(); } - content = proto_res->content(); - } - - if ( root.HasMember("components") ) { - const rapidjson::Value& components_root = root["components"]; - for ( rapidjson::Value::ConstMemberIterator component_root = components_root.MemberBegin(); - component_root != components_root.MemberEnd(); - ++component_root ) - { - factory_loader<>::fill_context ctx( - str(parent_address), - component_root->value, - dependencies); - bool success = the().fill_prototype( - component_root->name.GetString(), - content.prototype(), - ctx); - if ( !success ) { - throw prefab_asset_loading_exception(); - } - } + content.set_children(proto_res->content().children()); + content.set_prototype(proto_res->content().prototype()); } if ( root.HasMember("children") ) { @@ -178,6 +168,26 @@ namespace content.set_children(std::move(children)); } + if ( root.HasMember("components") ) { + const rapidjson::Value& components_root = root["components"]; + for ( rapidjson::Value::ConstMemberIterator component_root = components_root.MemberBegin(); + component_root != components_root.MemberEnd(); + ++component_root ) + { + factory_loader<>::fill_context ctx( + str(parent_address), + component_root->value, + dependencies); + const bool success = the().fill_prototype( + component_root->name.GetString(), + content.prototype(), + ctx); + if ( !success ) { + throw prefab_asset_loading_exception(); + } + } + } + return content; } } diff --git a/sources/enduro2d/high/resources/prefab.cpp b/sources/enduro2d/high/resources/prefab.cpp index 9589dae9..d17e097b 100644 --- a/sources/enduro2d/high/resources/prefab.cpp +++ b/sources/enduro2d/high/resources/prefab.cpp @@ -25,14 +25,16 @@ namespace e2d } void prefab::clear() noexcept { - prototype_.clear(); + uuid_.clear(); children_.clear(); + prototype_.clear(); } void prefab::swap(prefab& other) noexcept { using std::swap; - swap(prototype_, other.prototype_); + swap(uuid_, other.uuid_); swap(children_, other.children_); + swap(prototype_, other.prototype_); } prefab& prefab::assign(prefab&& other) noexcept { @@ -46,20 +48,21 @@ namespace e2d prefab& prefab::assign(const prefab& other) { if ( this != &other ) { prefab s; - s.prototype_ = other.prototype_; + s.uuid_ = other.uuid_; s.children_ = other.children_; + s.prototype_ = other.prototype_; swap(s); } return *this; } - prefab& prefab::set_prototype(ecs::prototype&& proto) noexcept { - prototype_ = std::move(proto); + prefab& prefab::set_uuid(str&& uuid) noexcept { + uuid_ = std::move(uuid); return *this; } - prefab& prefab::set_prototype(const ecs::prototype& proto) { - prototype_ = proto; + prefab& prefab::set_uuid(const str& uuid) { + uuid_ = uuid; return *this; } @@ -73,6 +76,32 @@ namespace e2d return *this; } + prefab& prefab::set_prototype(ecs::prototype&& prototype) noexcept { + prototype_ = std::move(prototype); + return *this; + } + + prefab& prefab::set_prototype(const ecs::prototype& prototype) { + prototype_ = prototype; + return *this; + } + + str& prefab::uuid() noexcept { + return uuid_; + } + + const str& prefab::uuid() const noexcept { + return uuid_; + } + + vector& prefab::children() noexcept { + return children_; + } + + const vector& prefab::children() const noexcept { + return children_; + } + ecs::prototype& prefab::prototype() noexcept { return prototype_; } @@ -80,10 +109,6 @@ namespace e2d const ecs::prototype& prefab::prototype() const noexcept { return prototype_; } - - const vector& prefab::children() const noexcept { - return children_; - } } namespace e2d @@ -91,13 +116,4 @@ namespace e2d void swap(prefab& l, prefab& r) noexcept { l.swap(r); } - - bool operator==(const prefab& l, const prefab& r) noexcept { - return l.prototype().empty() && l.children().empty() - && r.prototype().empty() && r.children().empty(); - } - - bool operator!=(const prefab& l, const prefab& r) noexcept { - return !(l == r); - } } diff --git a/sources/enduro2d/utils/json_utils.cpp b/sources/enduro2d/utils/json_utils.cpp index 14c960ec..6d81fe0f 100644 --- a/sources/enduro2d/utils/json_utils.cpp +++ b/sources/enduro2d/utils/json_utils.cpp @@ -197,6 +197,12 @@ namespace } }] }, + "guid" : { + "type" : "string", + "minLength" : 36, + "maxLength" : 36, + "pattern" : "^[0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{12}$" + }, "name" : { "type" : "string", "minLength" : 1 diff --git a/untests/bin/library/parent.json b/untests/bin/library/parent.json new file mode 100644 index 00000000..37baa7e8 --- /dev/null +++ b/untests/bin/library/parent.json @@ -0,0 +1,12 @@ +{ + "uuid" : "73740BC4-CE9F-4A7F-A029-4AB65027A8AE", + "components" : { + "named" : { + "name" : "parent" + }, + "circle_collider" : { + "radius" : 5, + "offset" : [4,2] + } + } +} diff --git a/untests/bin/library/prefab.json b/untests/bin/library/prefab.json index baeeaa24..12ad20a9 100644 --- a/untests/bin/library/prefab.json +++ b/untests/bin/library/prefab.json @@ -1,17 +1,13 @@ { + "parent" : "prototype.json", "components" : { - "touchable" : {}, - + "named" : { + "name" : "prefab" + }, "rect_collider" : { "size" : [1,2], "offset" : [2,4] }, - - "circle_collider" : { - "radius" : 5, - "offset" : [4,2] - }, - "polygon_collider" : { "points" : [[1,2],[2,3],[3,4]], "offset" : [8,4] From 906dfcd2928de35fe1b99376a51d0558c3569ecf Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 22 Apr 2020 08:12:17 +0700 Subject: [PATCH 02/11] node: child_at function --- headers/enduro2d/high/node.hpp | 3 +++ .../bin/library/scripts/emmy/high/node.lua | 5 +++++ .../high/bindings/high_binds/node_binds.cpp | 8 ++++++- sources/enduro2d/high/node.cpp | 16 ++++++++++++++ untests/sources/untests_high/node.cpp | 21 +++++++++++++++++++ 5 files changed, 52 insertions(+), 1 deletion(-) diff --git a/headers/enduro2d/high/node.hpp b/headers/enduro2d/high/node.hpp index aee801ac..6890ddc5 100644 --- a/headers/enduro2d/high/node.hpp +++ b/headers/enduro2d/high/node.hpp @@ -125,6 +125,9 @@ namespace e2d node_iptr next_sibling() noexcept; const_node_iptr next_sibling() const noexcept; + + node_iptr child_at(std::size_t index) noexcept; + const_node_iptr child_at(std::size_t index) const noexcept; protected: node() = default; node(gobject owner); diff --git a/samples/bin/library/scripts/emmy/high/node.lua b/samples/bin/library/scripts/emmy/high/node.lua index bb56fd29..00df09ed 100644 --- a/samples/bin/library/scripts/emmy/high/node.lua +++ b/samples/bin/library/scripts/emmy/high/node.lua @@ -140,5 +140,10 @@ function node.send_forward(self) end ---@return boolean function node.bring_to_front(self) end +---@param self node +---@param index integer +---@return node +function node.child_at(self, index) end + ---@type node _G.node = _G.node or node diff --git a/sources/enduro2d/high/bindings/high_binds/node_binds.cpp b/sources/enduro2d/high/bindings/high_binds/node_binds.cpp index 1b204e37..a765eaf2 100644 --- a/sources/enduro2d/high/bindings/high_binds/node_binds.cpp +++ b/sources/enduro2d/high/bindings/high_binds/node_binds.cpp @@ -141,7 +141,13 @@ namespace e2d::bindings::high [](node& n) -> node_iptr { return n.prev_sibling(); }), "next_sibling", sol::property( - [](node& n) -> node_iptr { return n.next_sibling(); }) + [](node& n) -> node_iptr { return n.next_sibling(); }), + + "child_at", [](node& n, i32 index) -> node_iptr { + return index >= 0 + ? n.child_at(math::numeric_cast(index)) + : node_iptr(); + } ); } } diff --git a/sources/enduro2d/high/node.cpp b/sources/enduro2d/high/node.cpp index 162ef303..00199354 100644 --- a/sources/enduro2d/high/node.cpp +++ b/sources/enduro2d/high/node.cpp @@ -414,6 +414,22 @@ namespace e2d } return const_node_iptr(&*iter); } + + node_iptr node::child_at(std::size_t index) noexcept { + node_iptr child = first_child(); + for ( std::size_t i = 0; i < index && child; ++i ) { + child = child->next_sibling(); + } + return child; + } + + const_node_iptr node::child_at(std::size_t index) const noexcept { + const_node_iptr child = first_child(); + for ( std::size_t i = 0; i < index && child; ++i ) { + child = child->next_sibling(); + } + return child; + } } namespace e2d diff --git a/untests/sources/untests_high/node.cpp b/untests/sources/untests_high/node.cpp index 9b6249e7..9a6563fe 100644 --- a/untests/sources/untests_high/node.cpp +++ b/untests/sources/untests_high/node.cpp @@ -429,6 +429,27 @@ TEST_CASE("node") { REQUIRE_FALSE(cn4->next_sibling()); } } + SECTION("child_at") { + auto p = node::create(); + + auto n1 = node::create(p); + auto n2 = node::create(p); + auto n3 = node::create(p); + + REQUIRE(p->child_at(0) == n1); + REQUIRE(p->child_at(1) == n2); + REQUIRE(p->child_at(2) == n3); + REQUIRE_FALSE(p->child_at(3)); + + { + const_node_iptr cp = p; + + REQUIRE(cp->child_at(0) == n1); + REQUIRE(cp->child_at(1) == n2); + REQUIRE(cp->child_at(2) == n3); + REQUIRE_FALSE(cp->child_at(3)); + } + } SECTION("add_child_to_back/add_child_to_front") { auto p = node::create(); auto n1 = node::create(); From 969180f3db83d0596c04cf662d657e4b19961175 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 22 Apr 2020 08:20:53 +0700 Subject: [PATCH 03/11] node: remove_child_at function --- headers/enduro2d/high/node.hpp | 2 ++ .../bin/library/scripts/emmy/high/node.lua | 5 +++++ .../high/bindings/high_binds/node_binds.cpp | 6 ++++++ sources/enduro2d/high/node.cpp | 7 +++++++ untests/sources/untests_high/node.cpp | 21 +++++++++++++++++++ 5 files changed, 41 insertions(+) diff --git a/headers/enduro2d/high/node.hpp b/headers/enduro2d/high/node.hpp index 6890ddc5..d1e40f3e 100644 --- a/headers/enduro2d/high/node.hpp +++ b/headers/enduro2d/high/node.hpp @@ -128,6 +128,8 @@ namespace e2d node_iptr child_at(std::size_t index) noexcept; const_node_iptr child_at(std::size_t index) const noexcept; + + node_iptr remove_child_at(std::size_t index) noexcept; protected: node() = default; node(gobject owner); diff --git a/samples/bin/library/scripts/emmy/high/node.lua b/samples/bin/library/scripts/emmy/high/node.lua index 00df09ed..f60010d5 100644 --- a/samples/bin/library/scripts/emmy/high/node.lua +++ b/samples/bin/library/scripts/emmy/high/node.lua @@ -145,5 +145,10 @@ function node.bring_to_front(self) end ---@return node function node.child_at(self, index) end +---@param self node +---@param index integer +---@return node +function node.remove_child_at(self, index) end + ---@type node _G.node = _G.node or node diff --git a/sources/enduro2d/high/bindings/high_binds/node_binds.cpp b/sources/enduro2d/high/bindings/high_binds/node_binds.cpp index a765eaf2..d1bd51fd 100644 --- a/sources/enduro2d/high/bindings/high_binds/node_binds.cpp +++ b/sources/enduro2d/high/bindings/high_binds/node_binds.cpp @@ -147,6 +147,12 @@ namespace e2d::bindings::high return index >= 0 ? n.child_at(math::numeric_cast(index)) : node_iptr(); + }, + + "remove_child_at", [](node& n, i32 index) -> node_iptr { + return index >= 0 + ? n.remove_child_at(math::numeric_cast(index)) + : node_iptr(); } ); } diff --git a/sources/enduro2d/high/node.cpp b/sources/enduro2d/high/node.cpp index 00199354..fd41bb1f 100644 --- a/sources/enduro2d/high/node.cpp +++ b/sources/enduro2d/high/node.cpp @@ -430,6 +430,13 @@ namespace e2d } return child; } + + node_iptr node::remove_child_at(std::size_t index) noexcept { + node_iptr child = child_at(index); + return remove_child(child) + ? child + : node_iptr(); + } } namespace e2d diff --git a/untests/sources/untests_high/node.cpp b/untests/sources/untests_high/node.cpp index 9a6563fe..9bde1862 100644 --- a/untests/sources/untests_high/node.cpp +++ b/untests/sources/untests_high/node.cpp @@ -450,6 +450,27 @@ TEST_CASE("node") { REQUIRE_FALSE(cp->child_at(3)); } } + SECTION("remove_child_at") { + auto p = node::create(); + + auto n1 = node::create(p); + auto n2 = node::create(p); + auto n3 = node::create(p); + + REQUIRE_FALSE(n1->remove_child_at(0)); + + REQUIRE(p->remove_child_at(1) == n2); + REQUIRE_FALSE(n2->has_parent()); + REQUIRE(p->child_count() == 2u); + + REQUIRE(p->remove_child_at(0) == n1); + REQUIRE_FALSE(n1->has_parent()); + REQUIRE(p->child_count() == 1u); + + REQUIRE(p->remove_child_at(0) == n3); + REQUIRE_FALSE(n3->has_parent()); + REQUIRE(p->child_count() == 0u); + } SECTION("add_child_to_back/add_child_to_front") { auto p = node::create(); auto n1 = node::create(); From db99cd71d3f066ea22632c1dfbf126ed414afc17 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 22 Apr 2020 08:53:01 +0700 Subject: [PATCH 04/11] node: child_index function --- headers/enduro2d/high/node.hpp | 3 ++ .../bin/library/scripts/emmy/high/node.lua | 5 +++ .../high/bindings/high_binds/node_binds.cpp | 4 ++ sources/enduro2d/high/node.cpp | 14 +++++++ untests/sources/untests_high/node.cpp | 42 +++++++++++++++++++ 5 files changed, 68 insertions(+) diff --git a/headers/enduro2d/high/node.hpp b/headers/enduro2d/high/node.hpp index d1e40f3e..ffcb4da0 100644 --- a/headers/enduro2d/high/node.hpp +++ b/headers/enduro2d/high/node.hpp @@ -129,6 +129,9 @@ namespace e2d node_iptr child_at(std::size_t index) noexcept; const_node_iptr child_at(std::size_t index) const noexcept; + std::pair child_index( + const const_node_iptr& child) const noexcept; + node_iptr remove_child_at(std::size_t index) noexcept; protected: node() = default; diff --git a/samples/bin/library/scripts/emmy/high/node.lua b/samples/bin/library/scripts/emmy/high/node.lua index f60010d5..31f23034 100644 --- a/samples/bin/library/scripts/emmy/high/node.lua +++ b/samples/bin/library/scripts/emmy/high/node.lua @@ -145,6 +145,11 @@ function node.bring_to_front(self) end ---@return node function node.child_at(self, index) end +---@param self node +---@param child node +---@return integer, boolean +function node.child_index(self, child) end + ---@param self node ---@param index integer ---@return node diff --git a/sources/enduro2d/high/bindings/high_binds/node_binds.cpp b/sources/enduro2d/high/bindings/high_binds/node_binds.cpp index d1bd51fd..240b9378 100644 --- a/sources/enduro2d/high/bindings/high_binds/node_binds.cpp +++ b/sources/enduro2d/high/bindings/high_binds/node_binds.cpp @@ -149,6 +149,10 @@ namespace e2d::bindings::high : node_iptr(); }, + "child_index", [](node& n, const node_iptr& c) -> std::pair { + return n.child_index(c); + }, + "remove_child_at", [](node& n, i32 index) -> node_iptr { return index >= 0 ? n.remove_child_at(math::numeric_cast(index)) diff --git a/sources/enduro2d/high/node.cpp b/sources/enduro2d/high/node.cpp index fd41bb1f..ae96c15e 100644 --- a/sources/enduro2d/high/node.cpp +++ b/sources/enduro2d/high/node.cpp @@ -431,6 +431,20 @@ namespace e2d return child; } + std::pair node::child_index( + const const_node_iptr& child) const noexcept + { + if ( !child || child->parent_ != this ) { + return {std::size_t(-1), false}; + } + + const auto distance = std::distance( + children_.begin(), + node_children::iterator_to(*child)); + + return {math::numeric_cast(distance), true}; + } + node_iptr node::remove_child_at(std::size_t index) noexcept { node_iptr child = child_at(index); return remove_child(child) diff --git a/untests/sources/untests_high/node.cpp b/untests/sources/untests_high/node.cpp index 9bde1862..3b373524 100644 --- a/untests/sources/untests_high/node.cpp +++ b/untests/sources/untests_high/node.cpp @@ -450,6 +450,48 @@ TEST_CASE("node") { REQUIRE_FALSE(cp->child_at(3)); } } + SECTION("child_index") { + auto p = node::create(); + + auto n1 = node::create(p); + auto n2 = node::create(p); + auto n3 = node::create(p); + + auto p2 = node::create(); + auto n4 = node::create(p2); + + auto n5 = node::create(); + + REQUIRE(p->child_index(n1).second); + REQUIRE(p->child_index(n2).second); + REQUIRE(p->child_index(n3).second); + REQUIRE_FALSE(p->child_index(n4).second); + REQUIRE_FALSE(p->child_index(n5).second); + + REQUIRE(p->child_index(n1).first == 0u); + REQUIRE(p->child_index(n2).first == 1u); + REQUIRE(p->child_index(n3).first == 2u); + + { + const_node_iptr cp = p; + + const_node_iptr cn1 = n1; + const_node_iptr cn2 = n2; + const_node_iptr cn3 = n3; + const_node_iptr cn4 = n4; + const_node_iptr cn5 = n5; + + REQUIRE(cp->child_index(cn1).second); + REQUIRE(cp->child_index(cn2).second); + REQUIRE(cp->child_index(cn3).second); + REQUIRE_FALSE(cp->child_index(cn4).second); + REQUIRE_FALSE(cp->child_index(cn5).second); + + REQUIRE(cp->child_index(cn1).first == 0u); + REQUIRE(cp->child_index(cn2).first == 1u); + REQUIRE(cp->child_index(cn3).first == 2u); + } + } SECTION("remove_child_at") { auto p = node::create(); From 3f8bb69955fcc606d4099132f8d6485430c0a156 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 22 Apr 2020 10:25:02 +0700 Subject: [PATCH 05/11] node: swap_children and swap_children_at functions --- headers/enduro2d/high/node.hpp | 13 ++++- headers/enduro2d/utils/intrusive_list.hpp | 8 ++++ .../bin/library/scripts/emmy/high/node.lua | 22 +++++++-- .../high/bindings/high_binds/node_binds.cpp | 22 ++++++--- sources/enduro2d/high/node.cpp | 46 ++++++++++++++---- untests/sources/untests_high/node.cpp | 48 +++++++++++++++++++ 6 files changed, 137 insertions(+), 22 deletions(-) diff --git a/headers/enduro2d/high/node.hpp b/headers/enduro2d/high/node.hpp index ffcb4da0..375892a2 100644 --- a/headers/enduro2d/high/node.hpp +++ b/headers/enduro2d/high/node.hpp @@ -108,6 +108,17 @@ namespace e2d bool remove_child( const node_iptr& child) noexcept; + node_iptr remove_child_at( + std::size_t index) noexcept; + + bool swap_children( + const node_iptr& child_l, + const node_iptr& child_r) noexcept; + + bool swap_children_at( + std::size_t child_l, + std::size_t child_r) noexcept; + bool send_backward() noexcept; bool bring_to_back() noexcept; @@ -131,8 +142,6 @@ namespace e2d std::pair child_index( const const_node_iptr& child) const noexcept; - - node_iptr remove_child_at(std::size_t index) noexcept; protected: node() = default; node(gobject owner); diff --git a/headers/enduro2d/utils/intrusive_list.hpp b/headers/enduro2d/utils/intrusive_list.hpp index 7bc1fc44..83ea5758 100644 --- a/headers/enduro2d/utils/intrusive_list.hpp +++ b/headers/enduro2d/utils/intrusive_list.hpp @@ -273,6 +273,8 @@ namespace e2d static iterator iterator_to(T& v) noexcept; static const_iterator iterator_to(const T& v) noexcept; + + static void iterator_swap(iterator l, iterator r) noexcept; private: using node_t = intrusive_list_hook; using node_ptr = typename node_t::node_ptr; @@ -496,4 +498,10 @@ namespace e2d E2D_ASSERT(node.is_linked()); return const_iterator(&node); } + + template < typename T, typename Tag > + void intrusive_list::iterator_swap(iterator l, iterator r) noexcept { + E2D_ASSERT(l.node()->is_linked() && r.node()->is_linked()); + intrusive_list_hook::swap_nodes(l.node(), r.node()); + } } diff --git a/samples/bin/library/scripts/emmy/high/node.lua b/samples/bin/library/scripts/emmy/high/node.lua index 31f23034..e20f4b08 100644 --- a/samples/bin/library/scripts/emmy/high/node.lua +++ b/samples/bin/library/scripts/emmy/high/node.lua @@ -124,6 +124,23 @@ function node.add_sibling_after(self, sibling) end ---@return boolean function node.remove_child(self, child) end +---@param self node +---@param index integer +---@return node +function node.remove_child_at(self, index) end + +---@param self node +---@param child_l node +---@param child_r node +---@return boolean +function node.swap_children(self, child_l, child_r) end + +---@param self node +---@param child_l integer +---@param child_r integer +---@return boolean +function node.swap_children_at(self, child_l, child_r) end + ---@param self node ---@return boolean function node.send_backward(self) end @@ -150,10 +167,5 @@ function node.child_at(self, index) end ---@return integer, boolean function node.child_index(self, child) end ----@param self node ----@param index integer ----@return node -function node.remove_child_at(self, index) end - ---@type node _G.node = _G.node or node diff --git a/sources/enduro2d/high/bindings/high_binds/node_binds.cpp b/sources/enduro2d/high/bindings/high_binds/node_binds.cpp index 240b9378..a951a8f2 100644 --- a/sources/enduro2d/high/bindings/high_binds/node_binds.cpp +++ b/sources/enduro2d/high/bindings/high_binds/node_binds.cpp @@ -115,6 +115,22 @@ namespace e2d::bindings::high return n.remove_child(c); }, + "remove_child_at", [](node& n, i32 index) -> node_iptr { + return index >= 0 + ? n.remove_child_at(math::numeric_cast(index)) + : node_iptr(); + }, + + "swap_children", [](node& n, const node_iptr& cl, const node_iptr& cr) -> bool { + return n.swap_children(cl, cr); + }, + + "swap_children_at", [](node& n, i32 cl, i32 cr) -> bool { + return cl >= 0 && cr >= 0 + ? n.swap_children_at(math::numeric_cast(cl), math::numeric_cast(cr)) + : false; + }, + "send_backward", [](node& n) -> bool { return n.send_backward(); }, @@ -151,12 +167,6 @@ namespace e2d::bindings::high "child_index", [](node& n, const node_iptr& c) -> std::pair { return n.child_index(c); - }, - - "remove_child_at", [](node& n, i32 index) -> node_iptr { - return index >= 0 - ? n.remove_child_at(math::numeric_cast(index)) - : node_iptr(); } ); } diff --git a/sources/enduro2d/high/node.cpp b/sources/enduro2d/high/node.cpp index ae96c15e..6811f771 100644 --- a/sources/enduro2d/high/node.cpp +++ b/sources/enduro2d/high/node.cpp @@ -214,7 +214,7 @@ namespace e2d bool node::add_child_to_back( const node_iptr& child) noexcept { - if ( !child ) { + if ( !child || child == this ) { return false; } @@ -233,7 +233,7 @@ namespace e2d bool node::add_child_to_front( const node_iptr& child) noexcept { - if ( !child ) { + if ( !child || child == this ) { return false; } @@ -319,6 +319,41 @@ namespace e2d return true; } + node_iptr node::remove_child_at(std::size_t index) noexcept { + node_iptr child = child_at(index); + return remove_child(child) + ? child + : node_iptr(); + } + + bool node::swap_children( + const node_iptr& child_l, + const node_iptr& child_r) noexcept + { + if ( !child_l || !child_r ) { + return false; + } + + if ( child_l->parent_ != this || child_r->parent_ != this ) { + return false; + } + + node_children::iterator_swap( + node_children::iterator_to(*child_l), + node_children::iterator_to(*child_r)); + + return true; + } + + bool node::swap_children_at( + std::size_t child_l, + std::size_t child_r) noexcept + { + return swap_children( + child_at(child_l), + child_at(child_r)); + } + bool node::send_backward() noexcept { node_iptr prev = prev_sibling(); return prev @@ -444,13 +479,6 @@ namespace e2d return {math::numeric_cast(distance), true}; } - - node_iptr node::remove_child_at(std::size_t index) noexcept { - node_iptr child = child_at(index); - return remove_child(child) - ? child - : node_iptr(); - } } namespace e2d diff --git a/untests/sources/untests_high/node.cpp b/untests/sources/untests_high/node.cpp index 3b373524..bb2730ff 100644 --- a/untests/sources/untests_high/node.cpp +++ b/untests/sources/untests_high/node.cpp @@ -317,6 +317,33 @@ TEST_CASE("node") { REQUIRE_FALSE(n->bring_to_back()); } } + SECTION("swap_children") { + auto p = node::create(); + + auto n1 = node::create(p); + auto n2 = node::create(p); + auto n3 = node::create(p); + + auto p2 = node::create(); + auto n4 = node::create(p2); + + auto n5 = node::create(); + + REQUIRE_FALSE(p->swap_children(n1, node_iptr())); + REQUIRE_FALSE(p->swap_children(node_iptr(), n1)); + REQUIRE_FALSE(p->swap_children(n1, p2)); + REQUIRE_FALSE(p->swap_children(n1, n4)); + REQUIRE_FALSE(p->swap_children(n1, n5)); + + REQUIRE(p->swap_children(n1, n1)); // n1 n2 n3 + REQUIRE(p->swap_children(n1, n2)); // n2 n1 n3 + REQUIRE(p->swap_children(n2, n3)); // n3 n1 n2 + REQUIRE(p->swap_children(n2, n1)); // n3 n2 n1 + + REQUIRE(p->child_at(0u) == n3); + REQUIRE(p->child_at(1u) == n2); + REQUIRE(p->child_at(2u) == n1); + } SECTION("send_forward/bring_to_front") { { auto p = node::create(); @@ -513,6 +540,25 @@ TEST_CASE("node") { REQUIRE_FALSE(n3->has_parent()); REQUIRE(p->child_count() == 0u); } + SECTION("swap_children_at") { + auto p = node::create(); + + auto n1 = node::create(p); + auto n2 = node::create(p); + auto n3 = node::create(p); + + REQUIRE_FALSE(p->swap_children_at(0u, 3u)); + REQUIRE_FALSE(p->swap_children_at(3u, 0u)); + + REQUIRE(p->swap_children_at(0, 0)); // n1 n2 n3 + REQUIRE(p->swap_children_at(0, 1)); // n2 n1 n3 + REQUIRE(p->swap_children_at(0, 2)); // n3 n1 n2 + REQUIRE(p->swap_children_at(2, 1)); // n3 n2 n1 + + REQUIRE(p->child_at(0u) == n3); + REQUIRE(p->child_at(1u) == n2); + REQUIRE(p->child_at(2u) == n1); + } SECTION("add_child_to_back/add_child_to_front") { auto p = node::create(); auto n1 = node::create(); @@ -523,6 +569,7 @@ TEST_CASE("node") { REQUIRE(p->add_child_to_back(n1)); REQUIRE(p->add_child_to_back(n2)); REQUIRE(p->add_child_to_back(n3)); // n3 n2 n1 + REQUIRE_FALSE(p->add_child_to_back(p)); REQUIRE_FALSE(p->add_child_to_back(nullptr)); REQUIRE(n1->prev_sibling() == n2); @@ -558,6 +605,7 @@ TEST_CASE("node") { REQUIRE(p->add_child_to_front(n1)); REQUIRE(p->add_child_to_front(n2)); REQUIRE(p->add_child_to_front(n3)); // n1 n2 n3 + REQUIRE_FALSE(p->add_child_to_front(p)); REQUIRE_FALSE(p->add_child_to_front(nullptr)); REQUIRE(n1->next_sibling() == n2); From 379218055d0b6c9e1c68766067e73f92d28b8106 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 22 Apr 2020 13:00:40 +0700 Subject: [PATCH 06/11] node: add_child_at function --- headers/enduro2d/high/node.hpp | 4 +++ .../bin/library/scripts/emmy/high/node.lua | 6 ++++ .../high/bindings/high_binds/node_binds.cpp | 18 ++++++---- sources/enduro2d/high/node.cpp | 13 +++++++- untests/sources/untests_high/node.cpp | 33 +++++++++++++++++++ 5 files changed, 67 insertions(+), 7 deletions(-) diff --git a/headers/enduro2d/high/node.hpp b/headers/enduro2d/high/node.hpp index 375892a2..9a71c046 100644 --- a/headers/enduro2d/high/node.hpp +++ b/headers/enduro2d/high/node.hpp @@ -85,6 +85,10 @@ namespace e2d bool add_child( const node_iptr& child) noexcept; + bool add_child_at( + const node_iptr& child, + std::size_t index) noexcept; + bool add_child_to_back( const node_iptr& child) noexcept; diff --git a/samples/bin/library/scripts/emmy/high/node.lua b/samples/bin/library/scripts/emmy/high/node.lua index e20f4b08..cdd1506f 100644 --- a/samples/bin/library/scripts/emmy/high/node.lua +++ b/samples/bin/library/scripts/emmy/high/node.lua @@ -87,6 +87,12 @@ function node.remove_all_children(self) end ---@return boolean function node.add_child(self, child) end +---@param self node +---@param child node +---@param index integer +---@return boolean +function node.add_child_at(self, child, index) end + ---@param self node ---@param child node ---@return boolean diff --git a/sources/enduro2d/high/bindings/high_binds/node_binds.cpp b/sources/enduro2d/high/bindings/high_binds/node_binds.cpp index a951a8f2..da9572b7 100644 --- a/sources/enduro2d/high/bindings/high_binds/node_binds.cpp +++ b/sources/enduro2d/high/bindings/high_binds/node_binds.cpp @@ -87,6 +87,12 @@ namespace e2d::bindings::high return n.add_child(c); }, + "add_child_at", [](node& n, const node_iptr& c, i32 i) -> bool { + return i >= 0 + ? n.add_child_at(c, math::numeric_cast(i)) + : false; + }, + "add_child_to_back", [](node& n, const node_iptr& c) -> bool { return n.add_child_to_back(c); }, @@ -115,9 +121,9 @@ namespace e2d::bindings::high return n.remove_child(c); }, - "remove_child_at", [](node& n, i32 index) -> node_iptr { - return index >= 0 - ? n.remove_child_at(math::numeric_cast(index)) + "remove_child_at", [](node& n, i32 i) -> node_iptr { + return i >= 0 + ? n.remove_child_at(math::numeric_cast(i)) : node_iptr(); }, @@ -159,9 +165,9 @@ namespace e2d::bindings::high "next_sibling", sol::property( [](node& n) -> node_iptr { return n.next_sibling(); }), - "child_at", [](node& n, i32 index) -> node_iptr { - return index >= 0 - ? n.child_at(math::numeric_cast(index)) + "child_at", [](node& n, i32 i) -> node_iptr { + return i >= 0 + ? n.child_at(math::numeric_cast(i)) : node_iptr(); }, diff --git a/sources/enduro2d/high/node.cpp b/sources/enduro2d/high/node.cpp index 6811f771..78330fdb 100644 --- a/sources/enduro2d/high/node.cpp +++ b/sources/enduro2d/high/node.cpp @@ -207,10 +207,21 @@ namespace e2d return count; } - bool node::add_child(const node_iptr& child) noexcept { + bool node::add_child( + const node_iptr& child) noexcept + { return add_child_to_front(child); } + bool node::add_child_at( + const node_iptr& child, + std::size_t index) noexcept + { + return index == 0u + ? add_child_to_back(child) + : add_child_after(child_at(index - 1u), child); + } + bool node::add_child_to_back( const node_iptr& child) noexcept { diff --git a/untests/sources/untests_high/node.cpp b/untests/sources/untests_high/node.cpp index bb2730ff..9306eddf 100644 --- a/untests/sources/untests_high/node.cpp +++ b/untests/sources/untests_high/node.cpp @@ -559,6 +559,39 @@ TEST_CASE("node") { REQUIRE(p->child_at(1u) == n2); REQUIRE(p->child_at(2u) == n1); } + SECTION("add_child_at") { + auto p = node::create(); + + auto n1 = node::create(); + auto n2 = node::create(); + auto n3 = node::create(); + auto n4 = node::create(); + + REQUIRE_FALSE(p->add_child_at(p, 0u)); + REQUIRE_FALSE(p->add_child_at(nullptr, 0u)); + REQUIRE_FALSE(p->add_child_at(n1, 1u)); + + REQUIRE(p->add_child_at(n1, 0u)); // n1 + REQUIRE(p->add_child_at(n2, 0u)); // n2 n1 + REQUIRE(p->add_child_at(n3, 2u)); // n2 n1 n3 + REQUIRE(p->add_child_at(n4, 2u)); // n2 n1 n4 n3 + + REQUIRE(p->child_at(0u) == n2); + REQUIRE(p->child_at(1u) == n1); + REQUIRE(p->child_at(2u) == n4); + REQUIRE(p->child_at(3u) == n3); + + REQUIRE_FALSE(p->add_child_at(n1, 5u)); + REQUIRE(p->add_child_at(n1, 4u)); // n2 n4 n3 n1 + REQUIRE(p->add_child_at(n3, 0u)); // n3 n2 n4 n1 + REQUIRE(p->add_child_at(n4, 1u)); // n3 n4 n2 n1 + REQUIRE(p->add_child_at(n4, p->child_index(n4).first)); // n3 n4 n2 n1 + + REQUIRE(p->child_at(0u) == n3); + REQUIRE(p->child_at(1u) == n4); + REQUIRE(p->child_at(2u) == n2); + REQUIRE(p->child_at(3u) == n1); + } SECTION("add_child_to_back/add_child_to_front") { auto p = node::create(); auto n1 = node::create(); From 8e470e1b0929620e21614bdf6010fbe3b9285e94 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 22 Apr 2020 17:39:44 +0700 Subject: [PATCH 07/11] utils: intrusive_list sorting functions --- headers/enduro2d/utils/intrusive_list.hpp | 105 ++++++++++++++++-- .../sources/untests_utils/intrusive_list.cpp | 38 +++++++ 2 files changed, 135 insertions(+), 8 deletions(-) diff --git a/headers/enduro2d/utils/intrusive_list.hpp b/headers/enduro2d/utils/intrusive_list.hpp index 83ea5758..41489fcb 100644 --- a/headers/enduro2d/utils/intrusive_list.hpp +++ b/headers/enduro2d/utils/intrusive_list.hpp @@ -109,6 +109,20 @@ namespace e2d swap_next(l, r); } } + + static void transfer_nodes(node_ptr p, node_ptr b, node_ptr e) noexcept { + if ( b != e ) { + node_ptr prev_p = p->prev_; + node_ptr prev_b = b->prev_; + node_ptr prev_e = e->prev_; + prev_e->next_ = p; + p->prev_ = prev_e; + prev_b->next_ = e; + e->prev_ = prev_b; + prev_p->next_ = b; + b->prev_ = prev_p; + } + } private: node_ptr prev_{nullptr}; node_ptr next_{nullptr}; @@ -252,15 +266,15 @@ namespace e2d void swap(intrusive_list& other) noexcept; template < typename Disposer > - void clear_and_dispose(Disposer&& disposer); + void clear_and_dispose(Disposer disposer); void clear() noexcept; template < typename Disposer > - void pop_back_and_dispose(Disposer&& disposer); + void pop_back_and_dispose(Disposer disposer); void pop_back() noexcept; template < typename Disposer > - void pop_front_and_dispose(Disposer&& disposer); + void pop_front_and_dispose(Disposer disposer); void pop_front() noexcept; void push_back(T& v) noexcept; @@ -268,9 +282,20 @@ namespace e2d iterator insert(const_iterator pos, T& v) noexcept; template < typename Disposer > - iterator erase_and_dispose(const_iterator pos, Disposer&& disposer); + iterator erase_and_dispose(const_iterator pos, Disposer disposer); iterator erase(const_iterator pos) noexcept; + void splice(const_iterator pos, intrusive_list& x) noexcept; + void splice(const_iterator pos, const_iterator f, const_iterator e) noexcept; + + template < typename Predicate > + void merge(intrusive_list& x, Predicate predicate); + void merge(intrusive_list& x); + + template < typename Predicate > + void sort(Predicate predicate); + void sort(); + static iterator iterator_to(T& v) noexcept; static const_iterator iterator_to(const T& v) noexcept; @@ -408,7 +433,7 @@ namespace e2d template < typename T, typename Tag > template < typename Disposer > - void intrusive_list::clear_and_dispose(Disposer&& disposer) { + void intrusive_list::clear_and_dispose(Disposer disposer) { while ( !empty() ) { pop_back_and_dispose(disposer); } @@ -421,7 +446,7 @@ namespace e2d template < typename T, typename Tag > template < typename Disposer > - void intrusive_list::pop_back_and_dispose(Disposer&& disposer) { + void intrusive_list::pop_back_and_dispose(Disposer disposer) { E2D_ASSERT(!empty()); node_ptr node = root_.prev_; node->unlink(); @@ -435,7 +460,7 @@ namespace e2d template < typename T, typename Tag > template < typename Disposer > - void intrusive_list::pop_front_and_dispose(Disposer&& disposer) { + void intrusive_list::pop_front_and_dispose(Disposer disposer) { E2D_ASSERT(!empty()); node_ptr node = root_.next_; node->unlink(); @@ -471,7 +496,7 @@ namespace e2d template < typename T, typename Tag > template < typename Disposer > - typename intrusive_list::iterator intrusive_list::erase_and_dispose(const_iterator pos, Disposer&& disposer) { + typename intrusive_list::iterator intrusive_list::erase_and_dispose(const_iterator pos, Disposer disposer) { node_ptr node = pos.node(); E2D_ASSERT(node != &root_ && node->is_linked()); ++pos; @@ -485,6 +510,70 @@ namespace e2d return erase_and_dispose(pos, null_disposer()); } + template < typename T, typename Tag > + void intrusive_list::splice(const_iterator pos, intrusive_list& x) noexcept { + intrusive_list_hook::transfer_nodes(pos.node(), x.begin().node(), x.end().node()); + } + + template < typename T, typename Tag > + void intrusive_list::splice(const_iterator pos, const_iterator f, const_iterator e) noexcept { + intrusive_list_hook::transfer_nodes(pos.node(), f.node(), e.node()); + } + + template < typename T, typename Tag > + template < typename Predicate > + void intrusive_list::merge(intrusive_list& x, Predicate predicate) { + const_iterator b(cbegin()), e(cend()), ex(x.cend()); + while ( !x.empty() ) { + const_iterator ix(x.cbegin()); + while ( b != e && !predicate(*ix, *b) ) { + ++b; + } + if ( b == e ) { + splice(e, x); + break; + } else { + do { + ++ix; + } while ( ix != ex && predicate(*ix, *b) ); + splice(b, x.begin(), ix); + } + } + } + + template < typename T, typename Tag > + void intrusive_list::merge(intrusive_list& x) { + merge(x, std::less()); + } + + template < typename T, typename Tag > + template < typename Predicate > + void intrusive_list::sort(Predicate predicate) { + if ( root_.next_ != &root_ && root_.next_ != root_.prev_ ) { + intrusive_list left_list; + intrusive_list right_list; + + const_iterator mid(cbegin()), tail(cend()); + while ( (mid != tail) && (++mid != tail) ) { + --tail; + } + + left_list.splice(left_list.cbegin(), cbegin(), mid); + right_list.splice(right_list.cbegin(), *this); + + left_list.sort(predicate); + right_list.sort(predicate); + + splice(cbegin(), left_list); + merge(right_list, predicate); + } + } + + template < typename T, typename Tag > + void intrusive_list::sort() { + sort(std::less()); + } + template < typename T, typename Tag > typename intrusive_list::iterator intrusive_list::iterator_to(T& v) noexcept { node_t& node = static_cast(v); diff --git a/untests/sources/untests_utils/intrusive_list.cpp b/untests/sources/untests_utils/intrusive_list.cpp index 785ac2ef..776ed5e0 100644 --- a/untests/sources/untests_utils/intrusive_list.cpp +++ b/untests/sources/untests_utils/intrusive_list.cpp @@ -7,6 +7,8 @@ #include "_utils.hpp" using namespace e2d; +#include + namespace { struct ilist_tag1 {}; @@ -21,6 +23,10 @@ namespace obj_t() = default; obj_t(int ni) : i(ni) {} }; + + bool operator<(const obj_t& l, const obj_t& r) noexcept { + return l.i < r.i; + } } TEST_CASE("intrusive_list") { @@ -433,4 +439,36 @@ TEST_CASE("intrusive_list") { } } } + SECTION("sort") { + { + std::random_device rd; + std::mt19937 rnd(rd()); + + std::uniform_int_distribution uni_size(0, 1024); + std::uniform_int_distribution uni_number(-65536, 65535); + + const auto pred = [](const obj_t& l, const obj_t& r) noexcept { + return l.i < r.i; + }; + + const auto r_pred = [](const obj_t& l, const obj_t& r) noexcept { + return l.i > r.i; + }; + + for ( std::size_t i = 0; i < 1024; ++i ) { + vector> objs; + intrusive_list l; + for ( u32 b = 0, e = uni_size(rnd); b < e; ++b ) { + objs.push_back(std::make_unique(uni_number(rnd))); + l.push_back(*objs.back()); + } + l.sort(); + REQUIRE(std::is_sorted(l.cbegin(), l.cend())); + l.sort(r_pred); + REQUIRE(std::is_sorted(l.cbegin(), l.cend(), r_pred)); + l.sort(pred); + REQUIRE(std::is_sorted(l.cbegin(), l.cend(), pred)); + } + } + } } From e6596639546b94b1b544016e9bfd01ab44555fe3 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 22 Apr 2020 23:56:01 +0700 Subject: [PATCH 08/11] add mod_children property to prefab asset --- sources/enduro2d/high/assets/prefab_asset.cpp | 87 ++++++++++- untests/bin/library/parent.json | 17 ++- untests/bin/library/prefab.json | 19 ++- untests/sources/untests_high/node.cpp | 14 -- untests/sources/untests_high/prefab.cpp | 136 ++++++++++++++++++ 5 files changed, 249 insertions(+), 24 deletions(-) create mode 100644 untests/sources/untests_high/prefab.cpp diff --git a/sources/enduro2d/high/assets/prefab_asset.cpp b/sources/enduro2d/high/assets/prefab_asset.cpp index 7028c4b3..45d964f9 100644 --- a/sources/enduro2d/high/assets/prefab_asset.cpp +++ b/sources/enduro2d/high/assets/prefab_asset.cpp @@ -27,9 +27,14 @@ namespace "uuid" : { "$ref": "#/common_definitions/uuid" }, "parent" : { "$ref": "#/common_definitions/address" }, "children" : { "$ref": "#/definitions/children" }, + "mod_children" : { "$ref": "#/definitions/mod_children" }, "components" : { "type" : "object" } }, "definitions" : { + "children" : { + "type" : "array", + "items" : { "$ref": "#/definitions/child" } + }, "child" : { "type" : "object", "required" : [], @@ -38,12 +43,24 @@ namespace "uuid" : { "$ref": "#/common_definitions/uuid" }, "parent" : { "$ref": "#/common_definitions/address" }, "children" : { "$ref": "#/definitions/children" }, + "mod_children" : { "$ref": "#/definitions/mod_children" }, "components" : { "type" : "object" } } }, - "children" : { + "mod_children" : { "type" : "array", - "items" : { "$ref": "#/definitions/child" } + "items" : { "$ref": "#/definitions/mod_child" } + }, + "mod_child" : { + "type" : "object", + "required" : [ "uuid" ], + "additionalProperties" : false, + "properties" : { + "uuid" : { "$ref": "#/common_definitions/uuid" }, + "children" : { "$ref": "#/definitions/children" }, + "mod_children" : { "$ref": "#/definitions/mod_children" }, + "components" : { "type" : "object" } + } } } })json"; @@ -83,6 +100,13 @@ namespace } } + if ( root.HasMember("mod_children") ) { + const rapidjson::Value& mod_children_root = root["mod_children"]; + for ( rapidjson::SizeType i = 0; i < mod_children_root.Size(); ++i ) { + collect_dependencies(parent_address, mod_children_root[i], dependencies); + } + } + if ( root.HasMember("components") ) { const rapidjson::Value& components_root = root["components"]; for ( rapidjson::Value::ConstMemberIterator component_root = components_root.MemberBegin(); @@ -123,13 +147,28 @@ namespace return dependencies.load_async(library); } - prefab parse_prefab( + prefab* find_prefab_child(prefab& parent, str_view child_uuid) noexcept { + for ( prefab& child : parent.children() ) { + if ( child.uuid() == child_uuid ) { + return &child; + } + } + + for ( prefab& child : parent.children() ) { + if ( prefab* sub_child = find_prefab_child(child, child_uuid) ) { + return sub_child; + } + } + + return nullptr; + } + + void parse_prefab_inplace( + prefab& content, str_view parent_address, const rapidjson::Value& root, const asset_group& dependencies) { - prefab content; - if ( root.HasMember("uuid") ) { str uuid = content.uuid(); if ( !json_utils::try_parse_value(root["uuid"], uuid) ) { @@ -161,13 +200,39 @@ namespace children.reserve(children_root.Size()); for ( rapidjson::SizeType i = 0; i < children_root.Size(); ++i ) { - children.emplace_back(parse_prefab( - parent_address, children_root[i], dependencies)); + prefab child; + parse_prefab_inplace( + child, + parent_address, + children_root[i], + dependencies); + children.push_back(std::move(child)); } content.set_children(std::move(children)); } + if ( root.HasMember("mod_children") ) { + const rapidjson::Value& mod_children_root = root["mod_children"]; + + for ( rapidjson::SizeType i = 0; i < mod_children_root.Size(); ++i ) { + const rapidjson::Value& mod_child_root = mod_children_root[i]; + E2D_ASSERT(mod_child_root.HasMember("uuid") && mod_child_root["uuid"].IsString()); + prefab* child_prefab = find_prefab_child(content, mod_child_root["uuid"].GetString()); + if ( !child_prefab ) { + the().error("PREFAB: Modifiable child is not found:\n" + "--> Child UUID: %0", + mod_child_root["uuid"].GetString()); + throw prefab_asset_loading_exception(); + } + parse_prefab_inplace( + *child_prefab, + parent_address, + mod_child_root, + dependencies); + } + } + if ( root.HasMember("components") ) { const rapidjson::Value& components_root = root["components"]; for ( rapidjson::Value::ConstMemberIterator component_root = components_root.MemberBegin(); @@ -187,7 +252,15 @@ namespace } } } + } + prefab parse_prefab( + str_view parent_address, + const rapidjson::Value& root, + const asset_group& dependencies) + { + prefab content; + parse_prefab_inplace(content, parent_address, root, dependencies); return content; } } diff --git a/untests/bin/library/parent.json b/untests/bin/library/parent.json index 37baa7e8..afc24701 100644 --- a/untests/bin/library/parent.json +++ b/untests/bin/library/parent.json @@ -8,5 +8,20 @@ "radius" : 5, "offset" : [4,2] } - } + }, + "children" : [{ + "uuid" : "4A93547E-4635-4C2F-9C59-3546E11B1722", + "components" : { + "named" : { + "name" : "child(1)" + } + } + }, { + "uuid" : "58063213-9FC1-457C-B773-B826BE1BE6D7", + "components" : { + "named" : { + "name" : "child(2)" + } + } + }] } diff --git a/untests/bin/library/prefab.json b/untests/bin/library/prefab.json index 12ad20a9..801cc8e8 100644 --- a/untests/bin/library/prefab.json +++ b/untests/bin/library/prefab.json @@ -1,5 +1,5 @@ { - "parent" : "prototype.json", + "parent" : "parent.json", "components" : { "named" : { "name" : "prefab" @@ -12,5 +12,20 @@ "points" : [[1,2],[2,3],[3,4]], "offset" : [8,4] } - } + }, + "mod_children" : [{ + "uuid" : "4A93547E-4635-4C2F-9C59-3546E11B1722", + "components" : { + "widget" : { + "size" : [10,10] + } + } + }, { + "uuid" : "58063213-9FC1-457C-B773-B826BE1BE6D7", + "components" : { + "widget" : { + "size" : [20,20] + } + } + }] } diff --git a/untests/sources/untests_high/node.cpp b/untests/sources/untests_high/node.cpp index 9306eddf..87d72882 100644 --- a/untests/sources/untests_high/node.cpp +++ b/untests/sources/untests_high/node.cpp @@ -9,19 +9,6 @@ using namespace e2d; namespace { - class safe_starter_initializer final : private noncopyable { - public: - safe_starter_initializer() { - modules::initialize(0, nullptr, - starter::parameters( - engine::parameters("world_untests", "enduro2d"))); - } - - ~safe_starter_initializer() noexcept { - modules::shutdown(); - } - }; - class fake_node final : public node { protected: fake_node() : node() { @@ -61,7 +48,6 @@ namespace } TEST_CASE("node") { - safe_starter_initializer initializer; SECTION("empty_node") { auto n = node::create(); REQUIRE(n); diff --git a/untests/sources/untests_high/prefab.cpp b/untests/sources/untests_high/prefab.cpp new file mode 100644 index 00000000..693c642c --- /dev/null +++ b/untests/sources/untests_high/prefab.cpp @@ -0,0 +1,136 @@ +/******************************************************************************* + * This file is part of the "Enduro2D" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2018-2020, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include "_high.hpp" +using namespace e2d; + +namespace +{ + class safe_starter_initializer final : private noncopyable { + public: + safe_starter_initializer() { + modules::initialize(0, nullptr, + starter::parameters( + engine::parameters("prefab_untests", "enduro2d"))); + } + + ~safe_starter_initializer() noexcept { + modules::shutdown(); + } + }; +} + +TEST_CASE("prefab"){ + safe_starter_initializer initializer; + library& l = the(); + { + auto parent_res = l.load_asset("parent.json"); + REQUIRE(parent_res); + REQUIRE(parent_res->content().uuid() == "73740BC4-CE9F-4A7F-A029-4AB65027A8AE"); + + REQUIRE(parent_res->content().children().size() == 2u); + REQUIRE(parent_res->content().children()[0].uuid() == "4A93547E-4635-4C2F-9C59-3546E11B1722"); + REQUIRE(parent_res->content().children()[1].uuid() == "58063213-9FC1-457C-B773-B826BE1BE6D7"); + + auto go = the().instantiate(parent_res->content()); + REQUIRE(go); + + REQUIRE(go.component()); + REQUIRE(go.component()->name() == "parent"); + + REQUIRE(go.component()); + REQUIRE(math::approximately(go.component()->radius(), 5.f)); + REQUIRE(go.component()->offset() == v2f(4.f,2.f)); + + { + node_iptr go_node = go.component() + ? go.component()->node() + : node_iptr(); + + REQUIRE(go_node); + REQUIRE(go_node->owner() == go); + REQUIRE(go_node->child_count() == 2u); + + node_iptr child1 = go_node->child_at(0u); + node_iptr child2 = go_node->child_at(1u); + + REQUIRE(child1); + REQUIRE(child2); + + gobject child1_go = child1->owner(); + gobject child2_go = child2->owner(); + + REQUIRE(child1_go); + REQUIRE(child2_go); + + REQUIRE(child1_go.component()); + REQUIRE(child1_go.component()->name() == "child(1)"); + + REQUIRE(child2_go.component()); + REQUIRE(child2_go.component()->name() == "child(2)"); + } + } + + { + auto prefab_res = l.load_asset("prefab.json"); + REQUIRE(prefab_res); + REQUIRE(prefab_res->content().uuid().empty()); + + REQUIRE(prefab_res->content().children().size() == 2u); + REQUIRE(prefab_res->content().children()[0].uuid() == "4A93547E-4635-4C2F-9C59-3546E11B1722"); + REQUIRE(prefab_res->content().children()[1].uuid() == "58063213-9FC1-457C-B773-B826BE1BE6D7"); + + auto go = the().instantiate(prefab_res->content()); + REQUIRE(go); + + REQUIRE(go.component()); + REQUIRE(go.component()->name() == "prefab"); + + REQUIRE(go.component()); + REQUIRE(go.component()->size() == v2f(1.f,2.f)); + REQUIRE(go.component()->offset() == v2f(2.f,4.f)); + + REQUIRE(go.component()); + REQUIRE(math::approximately(go.component()->radius(), 5.f)); + REQUIRE(go.component()->offset() == v2f(4.f,2.f)); + + REQUIRE(go.component()); + REQUIRE(go.component()->points() == vector{{1,2},{2,3},{3,4}}); + REQUIRE(go.component()->offset() == v2f(8.f,4.f)); + + { + node_iptr go_node = go.component() + ? go.component()->node() + : node_iptr(); + + REQUIRE(go_node); + REQUIRE(go_node->owner() == go); + REQUIRE(go_node->child_count() == 2u); + + node_iptr child1 = go_node->child_at(0u); + node_iptr child2 = go_node->child_at(1u); + + REQUIRE(child1); + REQUIRE(child2); + + gobject child1_go = child1->owner(); + gobject child2_go = child2->owner(); + + REQUIRE(child1_go); + REQUIRE(child2_go); + + REQUIRE(child1_go.component()); + REQUIRE(child1_go.component()->name() == "child(1)"); + + REQUIRE(child1_go.component()); + REQUIRE(child1_go.component()->size() == v2f(10.f, 10.f)); + + REQUIRE(child2_go.component()); + REQUIRE(child2_go.component()->name() == "child(2)"); + REQUIRE(child2_go.component()->size() == v2f(20.f, 20.f)); + } + } +} From b82b743f7613a53fec4bb56857772574ba9e8ce2 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 24 Apr 2020 04:05:59 +0700 Subject: [PATCH 09/11] rename prefab "parent" property to "prefab" --- sources/enduro2d/high/assets/prefab_asset.cpp | 41 +++++++---- .../{prefab.json => prefab_child.json} | 4 +- .../library/{parent.json => prefab_root.json} | 2 +- untests/sources/untests_high/prefab.cpp | 70 ++++++++++--------- 4 files changed, 68 insertions(+), 49 deletions(-) rename untests/bin/library/{prefab.json => prefab_child.json} (90%) rename untests/bin/library/{parent.json => prefab_root.json} (95%) diff --git a/sources/enduro2d/high/assets/prefab_asset.cpp b/sources/enduro2d/high/assets/prefab_asset.cpp index 45d964f9..3270616c 100644 --- a/sources/enduro2d/high/assets/prefab_asset.cpp +++ b/sources/enduro2d/high/assets/prefab_asset.cpp @@ -25,7 +25,7 @@ namespace "additionalProperties" : false, "properties" : { "uuid" : { "$ref": "#/common_definitions/uuid" }, - "parent" : { "$ref": "#/common_definitions/address" }, + "prefab" : { "$ref": "#/common_definitions/address" }, "children" : { "$ref": "#/definitions/children" }, "mod_children" : { "$ref": "#/definitions/mod_children" }, "components" : { "type" : "object" } @@ -41,7 +41,7 @@ namespace "additionalProperties" : false, "properties" : { "uuid" : { "$ref": "#/common_definitions/uuid" }, - "parent" : { "$ref": "#/common_definitions/address" }, + "prefab" : { "$ref": "#/common_definitions/address" }, "children" : { "$ref": "#/definitions/children" }, "mod_children" : { "$ref": "#/definitions/mod_children" }, "components" : { "type" : "object" } @@ -88,9 +88,9 @@ namespace const rapidjson::Value& root, asset_dependencies& dependencies) { - if ( root.HasMember("parent") ) { + if ( root.HasMember("prefab") ) { dependencies.add_dependency( - path::combine(parent_address, root["parent"].GetString())); + path::combine(parent_address, root["prefab"].GetString())); } if ( root.HasMember("children") ) { @@ -147,14 +147,14 @@ namespace return dependencies.load_async(library); } - prefab* find_prefab_child(prefab& parent, str_view child_uuid) noexcept { - for ( prefab& child : parent.children() ) { + prefab* find_prefab_child(prefab& root, str_view child_uuid) noexcept { + for ( prefab& child : root.children() ) { if ( child.uuid() == child_uuid ) { return &child; } } - for ( prefab& child : parent.children() ) { + for ( prefab& child : root.children() ) { if ( prefab* sub_child = find_prefab_child(child, child_uuid) ) { return sub_child; } @@ -178,15 +178,15 @@ namespace content.set_uuid(std::move(uuid)); } - if ( root.HasMember("parent") ) { + if ( root.HasMember("prefab") ) { auto proto_res = dependencies.find_asset( - path::combine(parent_address, root["parent"].GetString())); + path::combine(parent_address, root["prefab"].GetString())); if ( !proto_res ) { - the().error("PREFAB: Dependency 'parent' is not found:\n" + the().error("PREFAB: Dependency 'prefab' is not found:\n" "--> Parent address: %0\n" "--> Dependency address: %1", parent_address, - root["parent"].GetString()); + root["prefab"].GetString()); throw prefab_asset_loading_exception(); } content.set_children(proto_res->content().children()); @@ -217,14 +217,22 @@ namespace for ( rapidjson::SizeType i = 0; i < mod_children_root.Size(); ++i ) { const rapidjson::Value& mod_child_root = mod_children_root[i]; - E2D_ASSERT(mod_child_root.HasMember("uuid") && mod_child_root["uuid"].IsString()); - prefab* child_prefab = find_prefab_child(content, mod_child_root["uuid"].GetString()); + + E2D_ASSERT( + mod_child_root.HasMember("uuid") && + mod_child_root["uuid"].IsString()); + + prefab* const child_prefab = find_prefab_child( + content, + mod_child_root["uuid"].GetString()); + if ( !child_prefab ) { the().error("PREFAB: Modifiable child is not found:\n" "--> Child UUID: %0", mod_child_root["uuid"].GetString()); throw prefab_asset_loading_exception(); } + parse_prefab_inplace( *child_prefab, parent_address, @@ -243,10 +251,12 @@ namespace str(parent_address), component_root->value, dependencies); + const bool success = the().fill_prototype( component_root->name.GetString(), content.prototype(), ctx); + if ( !success ) { throw prefab_asset_loading_exception(); } @@ -260,7 +270,10 @@ namespace const asset_group& dependencies) { prefab content; - parse_prefab_inplace(content, parent_address, root, dependencies); + parse_prefab_inplace( + content, + parent_address, + root, dependencies); return content; } } diff --git a/untests/bin/library/prefab.json b/untests/bin/library/prefab_child.json similarity index 90% rename from untests/bin/library/prefab.json rename to untests/bin/library/prefab_child.json index 801cc8e8..6972a937 100644 --- a/untests/bin/library/prefab.json +++ b/untests/bin/library/prefab_child.json @@ -1,8 +1,8 @@ { - "parent" : "parent.json", + "prefab" : "prefab_root.json", "components" : { "named" : { - "name" : "prefab" + "name" : "child" }, "rect_collider" : { "size" : [1,2], diff --git a/untests/bin/library/parent.json b/untests/bin/library/prefab_root.json similarity index 95% rename from untests/bin/library/parent.json rename to untests/bin/library/prefab_root.json index afc24701..2435de1c 100644 --- a/untests/bin/library/parent.json +++ b/untests/bin/library/prefab_root.json @@ -2,7 +2,7 @@ "uuid" : "73740BC4-CE9F-4A7F-A029-4AB65027A8AE", "components" : { "named" : { - "name" : "parent" + "name" : "root" }, "circle_collider" : { "radius" : 5, diff --git a/untests/sources/untests_high/prefab.cpp b/untests/sources/untests_high/prefab.cpp index 693c642c..2987115f 100644 --- a/untests/sources/untests_high/prefab.cpp +++ b/untests/sources/untests_high/prefab.cpp @@ -27,23 +27,26 @@ TEST_CASE("prefab"){ safe_starter_initializer initializer; library& l = the(); { - auto parent_res = l.load_asset("parent.json"); - REQUIRE(parent_res); - REQUIRE(parent_res->content().uuid() == "73740BC4-CE9F-4A7F-A029-4AB65027A8AE"); + auto prefab_root_res = l.load_asset("prefab_root.json"); + REQUIRE(prefab_root_res); - REQUIRE(parent_res->content().children().size() == 2u); - REQUIRE(parent_res->content().children()[0].uuid() == "4A93547E-4635-4C2F-9C59-3546E11B1722"); - REQUIRE(parent_res->content().children()[1].uuid() == "58063213-9FC1-457C-B773-B826BE1BE6D7"); + const prefab& prefab_root = prefab_root_res->content(); + REQUIRE(prefab_root.uuid() == "73740BC4-CE9F-4A7F-A029-4AB65027A8AE"); - auto go = the().instantiate(parent_res->content()); - REQUIRE(go); + REQUIRE(prefab_root.children().size() == 2u); + REQUIRE(prefab_root.children()[0].uuid() == "4A93547E-4635-4C2F-9C59-3546E11B1722"); + REQUIRE(prefab_root.children()[1].uuid() == "58063213-9FC1-457C-B773-B826BE1BE6D7"); - REQUIRE(go.component()); - REQUIRE(go.component()->name() == "parent"); + auto go = the().instantiate(prefab_root); - REQUIRE(go.component()); - REQUIRE(math::approximately(go.component()->radius(), 5.f)); - REQUIRE(go.component()->offset() == v2f(4.f,2.f)); + { + REQUIRE(go.component()); + REQUIRE(go.component()->name() == "root"); + + REQUIRE(go.component()); + REQUIRE(go.component()->radius() == Approx(5.f)); + REQUIRE(go.component()->offset() == v2f(4.f,2.f)); + } { node_iptr go_node = go.component() @@ -75,31 +78,34 @@ TEST_CASE("prefab"){ } { - auto prefab_res = l.load_asset("prefab.json"); - REQUIRE(prefab_res); - REQUIRE(prefab_res->content().uuid().empty()); + auto prefab_child_res = l.load_asset("prefab_child.json"); + REQUIRE(prefab_child_res); - REQUIRE(prefab_res->content().children().size() == 2u); - REQUIRE(prefab_res->content().children()[0].uuid() == "4A93547E-4635-4C2F-9C59-3546E11B1722"); - REQUIRE(prefab_res->content().children()[1].uuid() == "58063213-9FC1-457C-B773-B826BE1BE6D7"); + const prefab& prefab_child = prefab_child_res->content(); + REQUIRE(prefab_child.uuid().empty()); - auto go = the().instantiate(prefab_res->content()); - REQUIRE(go); + REQUIRE(prefab_child.children().size() == 2u); + REQUIRE(prefab_child.children()[0].uuid() == "4A93547E-4635-4C2F-9C59-3546E11B1722"); + REQUIRE(prefab_child.children()[1].uuid() == "58063213-9FC1-457C-B773-B826BE1BE6D7"); - REQUIRE(go.component()); - REQUIRE(go.component()->name() == "prefab"); + auto go = the().instantiate(prefab_child); - REQUIRE(go.component()); - REQUIRE(go.component()->size() == v2f(1.f,2.f)); - REQUIRE(go.component()->offset() == v2f(2.f,4.f)); + { + REQUIRE(go.component()); + REQUIRE(go.component()->name() == "child"); - REQUIRE(go.component()); - REQUIRE(math::approximately(go.component()->radius(), 5.f)); - REQUIRE(go.component()->offset() == v2f(4.f,2.f)); + REQUIRE(go.component()); + REQUIRE(go.component()->size() == v2f(1.f,2.f)); + REQUIRE(go.component()->offset() == v2f(2.f,4.f)); - REQUIRE(go.component()); - REQUIRE(go.component()->points() == vector{{1,2},{2,3},{3,4}}); - REQUIRE(go.component()->offset() == v2f(8.f,4.f)); + REQUIRE(go.component()); + REQUIRE(go.component()->radius() == Approx(5.f)); + REQUIRE(go.component()->offset() == v2f(4.f,2.f)); + + REQUIRE(go.component()); + REQUIRE(go.component()->points() == vector{{1,2},{2,3},{3,4}}); + REQUIRE(go.component()->offset() == v2f(8.f,4.f)); + } { node_iptr go_node = go.component() From 8c28cab78841d4565e2d358fc10bb4a2071ebed0 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 24 Apr 2020 05:28:09 +0700 Subject: [PATCH 10/11] mod children list of subprefabs --- sources/enduro2d/high/assets/prefab_asset.cpp | 21 +++---- untests/bin/library/prefab_child.json | 35 ++++++++++- untests/sources/untests_high/prefab.cpp | 60 +++++++++++++++++-- 3 files changed, 99 insertions(+), 17 deletions(-) diff --git a/sources/enduro2d/high/assets/prefab_asset.cpp b/sources/enduro2d/high/assets/prefab_asset.cpp index 3270616c..cb564bc8 100644 --- a/sources/enduro2d/high/assets/prefab_asset.cpp +++ b/sources/enduro2d/high/assets/prefab_asset.cpp @@ -117,6 +117,7 @@ namespace const bool success = the().validate_json( component_root->name.GetString(), component_root->value); + if ( !success ) { throw prefab_asset_loading_exception(); } @@ -125,10 +126,12 @@ namespace factory_loader<>::collect_context ctx( str(parent_address), component_root->value); + const bool success = the().collect_dependencies( component_root->name.GetString(), dependencies, ctx); + if ( !success ) { throw prefab_asset_loading_exception(); } @@ -170,11 +173,7 @@ namespace const asset_group& dependencies) { if ( root.HasMember("uuid") ) { - str uuid = content.uuid(); - if ( !json_utils::try_parse_value(root["uuid"], uuid) ) { - the().error("PREFAB: Incorrect formatting of 'uuid' property"); - throw prefab_asset_loading_exception(); - } + str uuid = root["uuid"].GetString(); content.set_uuid(std::move(uuid)); } @@ -196,20 +195,18 @@ namespace if ( root.HasMember("children") ) { const rapidjson::Value& children_root = root["children"]; - vector children; - children.reserve(children_root.Size()); - for ( rapidjson::SizeType i = 0; i < children_root.Size(); ++i ) { + const rapidjson::Value& child_root = children_root[i]; + prefab child; parse_prefab_inplace( child, parent_address, - children_root[i], + child_root, dependencies); - children.push_back(std::move(child)); - } - content.set_children(std::move(children)); + content.children().push_back(std::move(child)); + } } if ( root.HasMember("mod_children") ) { diff --git a/untests/bin/library/prefab_child.json b/untests/bin/library/prefab_child.json index 6972a937..22ea6909 100644 --- a/untests/bin/library/prefab_child.json +++ b/untests/bin/library/prefab_child.json @@ -13,19 +13,52 @@ "offset" : [8,4] } }, + "children" : [{ + "uuid" : "C07CDC21-8D1A-45E5-9321-AC7B6FADA847", + "components" : { + "named" : { + "name" : "child(3)" + } + } + }], "mod_children" : [{ "uuid" : "4A93547E-4635-4C2F-9C59-3546E11B1722", "components" : { "widget" : { "size" : [10,10] } - } + }, + "children" : [{ + "uuid" : "EA1F7728-8061-495E-9E8A-280C5E2979B3", + "prefab" : "prefab_root.json", + "components" : { + "named" : { + "name" : "subchild(1)" + } + } + }] }, { "uuid" : "58063213-9FC1-457C-B773-B826BE1BE6D7", "components" : { "widget" : { "size" : [20,20] } + }, + "children" : [{ + "uuid" : "4DDDD08D-F7B9-4588-8597-3E38051AC433", + "prefab" : "prefab_root.json", + "components" : { + "named" : { + "name" : "subchild(2)" + } + } + }] + }, { + "uuid" : "C07CDC21-8D1A-45E5-9321-AC7B6FADA847", + "components" : { + "widget" : { + "size" : [30,30] + } } }] } diff --git a/untests/sources/untests_high/prefab.cpp b/untests/sources/untests_high/prefab.cpp index 2987115f..0289090d 100644 --- a/untests/sources/untests_high/prefab.cpp +++ b/untests/sources/untests_high/prefab.cpp @@ -74,6 +74,22 @@ TEST_CASE("prefab"){ REQUIRE(child2_go.component()); REQUIRE(child2_go.component()->name() == "child(2)"); + + node_iptr child1_node = child1_go.component() + ? child1_go.component()->node() + : node_iptr(); + + node_iptr child2_node = child2_go.component() + ? child2_go.component()->node() + : node_iptr(); + + REQUIRE(child1_node); + REQUIRE(child1_node->owner() == child1_go); + REQUIRE(child1_node->child_count() == 0u); + + REQUIRE(child2_node); + REQUIRE(child2_node->owner() == child2_go); + REQUIRE(child2_node->child_count() == 0u); } } @@ -84,9 +100,10 @@ TEST_CASE("prefab"){ const prefab& prefab_child = prefab_child_res->content(); REQUIRE(prefab_child.uuid().empty()); - REQUIRE(prefab_child.children().size() == 2u); + REQUIRE(prefab_child.children().size() == 3u); REQUIRE(prefab_child.children()[0].uuid() == "4A93547E-4635-4C2F-9C59-3546E11B1722"); REQUIRE(prefab_child.children()[1].uuid() == "58063213-9FC1-457C-B773-B826BE1BE6D7"); + REQUIRE(prefab_child.children()[2].uuid() == "C07CDC21-8D1A-45E5-9321-AC7B6FADA847"); auto go = the().instantiate(prefab_child); @@ -114,29 +131,64 @@ TEST_CASE("prefab"){ REQUIRE(go_node); REQUIRE(go_node->owner() == go); - REQUIRE(go_node->child_count() == 2u); + REQUIRE(go_node->child_count() == 3u); node_iptr child1 = go_node->child_at(0u); node_iptr child2 = go_node->child_at(1u); + node_iptr child3 = go_node->child_at(2u); REQUIRE(child1); REQUIRE(child2); + REQUIRE(child3); gobject child1_go = child1->owner(); gobject child2_go = child2->owner(); + gobject child3_go = child3->owner(); REQUIRE(child1_go); REQUIRE(child2_go); + REQUIRE(child3_go); REQUIRE(child1_go.component()); - REQUIRE(child1_go.component()->name() == "child(1)"); - REQUIRE(child1_go.component()); + REQUIRE(child1_go.component()->name() == "child(1)"); REQUIRE(child1_go.component()->size() == v2f(10.f, 10.f)); REQUIRE(child2_go.component()); + REQUIRE(child2_go.component()); REQUIRE(child2_go.component()->name() == "child(2)"); REQUIRE(child2_go.component()->size() == v2f(20.f, 20.f)); + + REQUIRE(child3_go.component()); + REQUIRE(child3_go.component()); + REQUIRE(child3_go.component()->name() == "child(3)"); + REQUIRE(child3_go.component()->size() == v2f(30.f, 30.f)); + + node_iptr child1_node = child1_go.component() + ? child1_go.component()->node() + : node_iptr(); + + node_iptr child2_node = child2_go.component() + ? child2_go.component()->node() + : node_iptr(); + + node_iptr child3_node = child3_go.component() + ? child3_go.component()->node() + : node_iptr(); + + REQUIRE(child1_node); + REQUIRE(child1_node->owner() == child1_go); + REQUIRE(child1_node->child_count() == 1u); + REQUIRE(child1_node->first_child()->child_count() == 2u); + + REQUIRE(child2_node); + REQUIRE(child2_node->owner() == child2_go); + REQUIRE(child2_node->child_count() == 1u); + REQUIRE(child2_node->first_child()->child_count() == 2u); + + REQUIRE(child3_node); + REQUIRE(child3_node->owner() == child3_go); + REQUIRE(child3_node->child_count() == 0u); } } } From d70c3d3f3cee49b8cd086126e1ffaf5a1778da0b Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 24 Apr 2020 10:20:13 +0700 Subject: [PATCH 11/11] fix samples for new prefabs --- .../library/prefabs/background_prefab.json | 16 +++++++------- samples/bin/library/prefabs/coin_prefab.json | 2 +- .../bin/library/prefabs/dragon_prefab.json | 2 +- samples/bin/library/prefabs/gnome_prefab.json | 2 +- .../bin/library/prefabs/layout_prefab.json | 2 +- samples/bin/library/prefabs/panel_prefab.json | 2 +- .../bin/library/prefabs/raptor_prefab.json | 2 +- samples/bin/library/prefabs/ship_prefab.json | 2 +- samples/bin/library/scenes/sample_04.json | 20 ++++++++--------- samples/bin/library/scenes/sample_06.json | 10 ++++----- samples/bin/library/scenes/sample_07.json | 10 ++++----- samples/bin/library/scenes/sample_08.json | 17 +++++++------- samples/bin/library/scenes/sample_09.json | 22 +++++++++---------- untests/sources/untests_high/library.cpp | 22 ------------------- 14 files changed, 54 insertions(+), 77 deletions(-) diff --git a/samples/bin/library/prefabs/background_prefab.json b/samples/bin/library/prefabs/background_prefab.json index 5041917d..b932d535 100644 --- a/samples/bin/library/prefabs/background_prefab.json +++ b/samples/bin/library/prefabs/background_prefab.json @@ -5,7 +5,7 @@ } }, "children" : [{ - "prototype" : "sprite_prefab.json", + "prefab" : "sprite_prefab.json", "components" : { "actor" : { "translation" : [-512,0] @@ -15,7 +15,7 @@ } } },{ - "prototype" : "sprite_prefab.json", + "prefab" : "sprite_prefab.json", "components" : { "actor" : { "translation" : [-256,0] @@ -25,7 +25,7 @@ } } },{ - "prototype" : "sprite_prefab.json", + "prefab" : "sprite_prefab.json", "components" : { "actor" : { "translation" : [0,0] @@ -35,7 +35,7 @@ } } },{ - "prototype" : "sprite_prefab.json", + "prefab" : "sprite_prefab.json", "components" : { "actor" : { "translation" : [256,0] @@ -45,7 +45,7 @@ } } },{ - "prototype" : "sprite_prefab.json", + "prefab" : "sprite_prefab.json", "components" : { "actor" : { "translation" : [-512,-256] @@ -55,7 +55,7 @@ } } },{ - "prototype" : "sprite_prefab.json", + "prefab" : "sprite_prefab.json", "components" : { "actor" : { "translation" : [-256,-256] @@ -65,7 +65,7 @@ } } },{ - "prototype" : "sprite_prefab.json", + "prefab" : "sprite_prefab.json", "components" : { "actor" : { "translation" : [0,-256] @@ -75,7 +75,7 @@ } } },{ - "prototype" : "sprite_prefab.json", + "prefab" : "sprite_prefab.json", "components" : { "actor" : { "translation" : [256,-256] diff --git a/samples/bin/library/prefabs/coin_prefab.json b/samples/bin/library/prefabs/coin_prefab.json index 34cbbfb8..6ae01035 100644 --- a/samples/bin/library/prefabs/coin_prefab.json +++ b/samples/bin/library/prefabs/coin_prefab.json @@ -1,5 +1,5 @@ { - "prototype" : "spine_prefab.json", + "prefab" : "spine_prefab.json", "components" : { "named" : { "name" : "coin" diff --git a/samples/bin/library/prefabs/dragon_prefab.json b/samples/bin/library/prefabs/dragon_prefab.json index 0ec77573..d8d8bd5b 100644 --- a/samples/bin/library/prefabs/dragon_prefab.json +++ b/samples/bin/library/prefabs/dragon_prefab.json @@ -1,5 +1,5 @@ { - "prototype" : "spine_prefab.json", + "prefab" : "spine_prefab.json", "components" : { "named" : { "name" : "dragon" diff --git a/samples/bin/library/prefabs/gnome_prefab.json b/samples/bin/library/prefabs/gnome_prefab.json index 91e6d13b..de8e2c1d 100644 --- a/samples/bin/library/prefabs/gnome_prefab.json +++ b/samples/bin/library/prefabs/gnome_prefab.json @@ -1,5 +1,5 @@ { - "prototype" : "model_prefab.json", + "prefab" : "model_prefab.json", "components" : { "named" : { "name" : "gnome" diff --git a/samples/bin/library/prefabs/layout_prefab.json b/samples/bin/library/prefabs/layout_prefab.json index da2dab99..b5b29255 100644 --- a/samples/bin/library/prefabs/layout_prefab.json +++ b/samples/bin/library/prefabs/layout_prefab.json @@ -1,5 +1,5 @@ { - "prototype" : "widget_prefab.json", + "prefab" : "widget_prefab.json", "components" : { "named" : { "name" : "layout" diff --git a/samples/bin/library/prefabs/panel_prefab.json b/samples/bin/library/prefabs/panel_prefab.json index 6c597f5c..7a63a5ed 100644 --- a/samples/bin/library/prefabs/panel_prefab.json +++ b/samples/bin/library/prefabs/panel_prefab.json @@ -1,5 +1,5 @@ { - "prototype" : "sprite_prefab.json", + "prefab" : "sprite_prefab.json", "components" : { "named" : { "name" : "panel" diff --git a/samples/bin/library/prefabs/raptor_prefab.json b/samples/bin/library/prefabs/raptor_prefab.json index 45aab765..964064b2 100644 --- a/samples/bin/library/prefabs/raptor_prefab.json +++ b/samples/bin/library/prefabs/raptor_prefab.json @@ -1,5 +1,5 @@ { - "prototype" : "spine_prefab.json", + "prefab" : "spine_prefab.json", "components" : { "named" : { "name" : "raptor" diff --git a/samples/bin/library/prefabs/ship_prefab.json b/samples/bin/library/prefabs/ship_prefab.json index 6d5f78bc..78b4949e 100644 --- a/samples/bin/library/prefabs/ship_prefab.json +++ b/samples/bin/library/prefabs/ship_prefab.json @@ -1,5 +1,5 @@ { - "prototype" : "sprite_prefab.json", + "prefab" : "sprite_prefab.json", "components" : { "named" : { "name" : "ship" diff --git a/samples/bin/library/scenes/sample_04.json b/samples/bin/library/scenes/sample_04.json index 926befa5..61eb6f04 100644 --- a/samples/bin/library/scenes/sample_04.json +++ b/samples/bin/library/scenes/sample_04.json @@ -1,7 +1,7 @@ { - "prototype" : "../prefabs/scene_prefab.json", + "prefab" : "../prefabs/scene_prefab.json", "children" : [{ - "prototype" : "../prefabs/camera_prefab.json", + "prefab" : "../prefabs/camera_prefab.json", "components" : { "actor" : { "rotation" : 0.5 @@ -14,7 +14,7 @@ } } },{ - "prototype" : "../prefabs/camera_prefab.json", + "prefab" : "../prefabs/camera_prefab.json", "components" : { "actor" : { "rotation" : -0.5 @@ -27,7 +27,7 @@ } } },{ - "prototype" : "../prefabs/camera_prefab.json", + "prefab" : "../prefabs/camera_prefab.json", "components" : { "actor" : { "rotation" : 0.5 @@ -40,7 +40,7 @@ } } },{ - "prototype" : "../prefabs/camera_prefab.json", + "prefab" : "../prefabs/camera_prefab.json", "components" : { "actor" : { "rotation" : -0.5 @@ -53,7 +53,7 @@ } } },{ - "prototype" : "../prefabs/gnome_prefab.json", + "prefab" : "../prefabs/gnome_prefab.json", "components" : { "actor" : { "translation" : [0,0], @@ -64,7 +64,7 @@ } } }, { - "prototype" : "../prefabs/ship_prefab.json", + "prefab" : "../prefabs/ship_prefab.json", "components" : { "sprite_renderer" : { "blending" : "additive" @@ -77,7 +77,7 @@ } }, "children" : [{ - "prototype" : "../prefabs/ship_prefab.json", + "prefab" : "../prefabs/ship_prefab.json", "components" : { "sprite_renderer" : { "tint" : [255,0,0,255] @@ -91,7 +91,7 @@ } }] }, { - "prototype" : "../prefabs/label_bm_prefab.json", + "prefab" : "../prefabs/label_bm_prefab.json", "components" : { "label" : { "text" : "bm font", @@ -108,7 +108,7 @@ } } }, { - "prototype" : "../prefabs/label_sdf_prefab.json", + "prefab" : "../prefabs/label_sdf_prefab.json", "components" : { "label" : { "text" : "sdf font", diff --git a/samples/bin/library/scenes/sample_06.json b/samples/bin/library/scenes/sample_06.json index 26c85800..efca2bbf 100644 --- a/samples/bin/library/scenes/sample_06.json +++ b/samples/bin/library/scenes/sample_06.json @@ -1,9 +1,9 @@ { - "prototype" : "../prefabs/scene_prefab.json", + "prefab" : "../prefabs/scene_prefab.json", "children" : [{ - "prototype" : "../prefabs/camera_prefab.json" + "prefab" : "../prefabs/camera_prefab.json" },{ - "prototype" : "../prefabs/coin_prefab.json", + "prefab" : "../prefabs/coin_prefab.json", "components" : { "actor" : { "translation" : [350,250], @@ -14,7 +14,7 @@ } } }, { - "prototype" : "../prefabs/raptor_prefab.json", + "prefab" : "../prefabs/raptor_prefab.json", "components" : { "actor" : { "translation" : [300,-350], @@ -25,7 +25,7 @@ } } }, { - "prototype" : "../prefabs/dragon_prefab.json", + "prefab" : "../prefabs/dragon_prefab.json", "components" : { "actor" : { "translation" : [-100,0], diff --git a/samples/bin/library/scenes/sample_07.json b/samples/bin/library/scenes/sample_07.json index 21d588e1..873b41a4 100644 --- a/samples/bin/library/scenes/sample_07.json +++ b/samples/bin/library/scenes/sample_07.json @@ -1,16 +1,16 @@ { - "prototype" : "../prefabs/scene_prefab.json", + "prefab" : "../prefabs/scene_prefab.json", "components" : { "behaviour" : { "script" : "../scripts/sample_07/sample_07.lua" } }, "children" : [{ - "prototype" : "../prefabs/camera_prefab.json" + "prefab" : "../prefabs/camera_prefab.json" },{ - "prototype" : "../prefabs/background_prefab.json" + "prefab" : "../prefabs/background_prefab.json" },{ - "prototype" : "../prefabs/gnome_prefab.json", + "prefab" : "../prefabs/gnome_prefab.json", "components" : { "actor" : { "translation" : [0,0], @@ -21,7 +21,7 @@ } } },{ - "prototype" : "../prefabs/label_sdf_prefab.json", + "prefab" : "../prefabs/label_sdf_prefab.json", "components" : { "label" : { "text" : "FPS: ", diff --git a/samples/bin/library/scenes/sample_08.json b/samples/bin/library/scenes/sample_08.json index 31cb13a1..078f7061 100644 --- a/samples/bin/library/scenes/sample_08.json +++ b/samples/bin/library/scenes/sample_08.json @@ -1,12 +1,12 @@ { - "prototype" : "../prefabs/scene_prefab.json", + "prefab" : "../prefabs/scene_prefab.json", "components" : { "behaviour" : { "script" : "../scripts/sample_08/sample_08.lua" } }, "children" : [{ - "prototype" : "../prefabs/camera_prefab.json", + "prefab" : "../prefabs/camera_prefab.json", "components" : { "actor" : { "rotation" : 0.5 @@ -19,7 +19,7 @@ } } },{ - "prototype" : "../prefabs/camera_prefab.json", + "prefab" : "../prefabs/camera_prefab.json", "components" : { "actor" : { "rotation" : -0.5 @@ -32,7 +32,7 @@ } } },{ - "prototype" : "../prefabs/ship_prefab.json", + "prefab" : "../prefabs/ship_prefab.json", "components" : { "named" : { "name" : "ship(1)" @@ -51,7 +51,7 @@ } }, "children" : [{ - "prototype" : "../prefabs/ship_prefab.json", + "prefab" : "../prefabs/ship_prefab.json", "components" : { "named" : { "name" : "ship(11)" @@ -69,11 +69,10 @@ "offset" : [10,15], "radius" : 33 } - }, - "children" : [] + } }] },{ - "prototype" : "../prefabs/ship_prefab.json", + "prefab" : "../prefabs/ship_prefab.json", "components" : { "named" : { "name" : "ship(2)" @@ -113,7 +112,7 @@ } } },{ - "prototype" : "../prefabs/label_sdf_prefab.json", + "prefab" : "../prefabs/label_sdf_prefab.json", "components" : { "named" : { "name" : "label" diff --git a/samples/bin/library/scenes/sample_09.json b/samples/bin/library/scenes/sample_09.json index aefb3066..3ab0df8e 100644 --- a/samples/bin/library/scenes/sample_09.json +++ b/samples/bin/library/scenes/sample_09.json @@ -1,18 +1,18 @@ { - "prototype" : "../prefabs/scene_prefab.json", + "prefab" : "../prefabs/scene_prefab.json", "children" : [{ - "prototype" : "../prefabs/background_prefab.json" + "prefab" : "../prefabs/background_prefab.json" },{ - "prototype" : "../prefabs/camera_prefab.json" + "prefab" : "../prefabs/camera_prefab.json" },{ - "prototype" : "../prefabs/panel_prefab.json", + "prefab" : "../prefabs/panel_prefab.json", "components" : { "sprite_renderer" : { "scale" : [4,2] } }, "children" : [{ - "prototype" : "../prefabs/layout_prefab.json", + "prefab" : "../prefabs/layout_prefab.json", "components" : { "layout" : { "justify_content" : "space_evenly" @@ -22,14 +22,14 @@ } }, "children" : [{ - "prototype" : "../prefabs/widget_prefab.json", + "prefab" : "../prefabs/widget_prefab.json", "components" : { "widget" : { "size" : [66,113] } }, "children" : [{ - "prototype" : "../prefabs/ship_prefab.json", + "prefab" : "../prefabs/ship_prefab.json", "components" : { "actor" : { "translation" : [33,56.5] @@ -37,14 +37,14 @@ } }] },{ - "prototype" : "../prefabs/widget_prefab.json", + "prefab" : "../prefabs/widget_prefab.json", "components" : { "widget" : { "size" : [66,113] } }, "children" : [{ - "prototype" : "../prefabs/ship_prefab.json", + "prefab" : "../prefabs/ship_prefab.json", "components" : { "actor" : { "translation" : [33,56.5] @@ -52,14 +52,14 @@ } }] },{ - "prototype" : "../prefabs/widget_prefab.json", + "prefab" : "../prefabs/widget_prefab.json", "components" : { "widget" : { "size" : [66,113] } }, "children" : [{ - "prototype" : "../prefabs/ship_prefab.json", + "prefab" : "../prefabs/ship_prefab.json", "components" : { "actor" : { "translation" : [33,56.5] diff --git a/untests/sources/untests_high/library.cpp b/untests/sources/untests_high/library.cpp index 6b2178fa..f67a1625 100644 --- a/untests/sources/untests_high/library.cpp +++ b/untests/sources/untests_high/library.cpp @@ -259,28 +259,6 @@ TEST_CASE("library"){ REQUIRE(model_res->content().mesh()->content().indices_submesh_count() == 1); REQUIRE_FALSE(model_res->content().mesh()->content().indices(0).empty()); } - - { - auto prefab_res = l.load_asset("prefab.json"); - REQUIRE(prefab_res); - - ecs::registry w; - ecs::entity e = w.create_entity(prefab_res->content().prototype()); - - REQUIRE(e.exists_component()); - - REQUIRE(e.exists_component()); - REQUIRE(e.get_component().size() == v2f(1.f,2.f)); - REQUIRE(e.get_component().offset() == v2f(2.f,4.f)); - - REQUIRE(e.exists_component()); - REQUIRE(math::approximately(e.get_component().radius(), 5.f)); - REQUIRE(e.get_component().offset() == v2f(4.f,2.f)); - - REQUIRE(e.exists_component()); - REQUIRE(e.get_component().points() == vector{{1,2},{2,3},{3,4}}); - REQUIRE(e.get_component().offset() == v2f(8.f,4.f)); - } } } {