mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-14 16:09:06 +07:00
node helper functions refactoring
This commit is contained in:
@@ -125,16 +125,6 @@ namespace e2d
|
||||
|
||||
node_iptr next_sibling() noexcept;
|
||||
const_node_iptr next_sibling() const noexcept;
|
||||
|
||||
template < typename F >
|
||||
void for_each_child(F&& f);
|
||||
template < typename F >
|
||||
void for_each_child(F&& f) const;
|
||||
|
||||
template < typename F >
|
||||
void for_each_child_reversed(F&& f);
|
||||
template < typename F >
|
||||
void for_each_child_reversed(F&& f) const;
|
||||
protected:
|
||||
node() = default;
|
||||
node(gobject owner);
|
||||
@@ -161,76 +151,114 @@ namespace e2d
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
template < typename Iter >
|
||||
std::size_t extract_nodes(const node_iptr& root, Iter iter);
|
||||
template < typename Iter >
|
||||
std::size_t extract_nodes(const const_node_iptr& root, Iter iter);
|
||||
class options final {
|
||||
public:
|
||||
options() = default;
|
||||
|
||||
template < typename Iter >
|
||||
std::size_t extract_nodes_reversed(const node_iptr& root, Iter iter);
|
||||
template < typename Iter >
|
||||
std::size_t extract_nodes_reversed(const const_node_iptr& root, Iter iter);
|
||||
options& reversed(bool value) noexcept;
|
||||
options& recursive(bool value) noexcept;
|
||||
options& include_root(bool value) noexcept;
|
||||
|
||||
template < typename Iter >
|
||||
std::size_t extract_parents(const node_iptr& root, Iter iter);
|
||||
template < typename Iter >
|
||||
std::size_t extract_parents(const const_node_iptr& root, Iter iter);
|
||||
|
||||
template < typename Iter >
|
||||
std::size_t extract_parents_reversed(const node_iptr& root, Iter iter);
|
||||
template < typename Iter >
|
||||
std::size_t extract_parents_reversed(const const_node_iptr& root, Iter iter);
|
||||
[[nodiscard]] bool reversed() const noexcept;
|
||||
[[nodiscard]] bool recursive() const noexcept;
|
||||
[[nodiscard]] bool include_root() const noexcept;
|
||||
private:
|
||||
enum flag_masks : u8 {
|
||||
fm_reversed = 1u << 0,
|
||||
fm_recursive = 1u << 1,
|
||||
fm_include_root = 1u << 2,
|
||||
};
|
||||
private:
|
||||
std::underlying_type_t<flag_masks> flags_{};
|
||||
};
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
vector<node_iptr> extract_nodes(const node_iptr& root);
|
||||
vector<const_node_iptr> extract_nodes(const const_node_iptr& root);
|
||||
template < typename Node, typename F >
|
||||
bool for_each_child(
|
||||
const intrusive_ptr<Node>& root,
|
||||
F&& f,
|
||||
const options& opts = options());
|
||||
|
||||
vector<node_iptr> extract_nodes_reversed(const node_iptr& root);
|
||||
vector<const_node_iptr> extract_nodes_reversed(const const_node_iptr& root);
|
||||
|
||||
vector<node_iptr> extract_parents(const node_iptr& root);
|
||||
vector<const_node_iptr> extract_parents(const const_node_iptr& root);
|
||||
|
||||
vector<node_iptr> extract_parents_reversed(const node_iptr& root);
|
||||
vector<const_node_iptr> extract_parents_reversed(const const_node_iptr& root);
|
||||
template < typename Node, typename F >
|
||||
bool for_each_parent(
|
||||
const intrusive_ptr<Node>& root,
|
||||
F&& f,
|
||||
const options& opts = options());
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
template < typename F >
|
||||
void for_extracted_nodes(const node_iptr& root, F&& f);
|
||||
template < typename F >
|
||||
void for_extracted_nodes(const const_node_iptr& root, F&& f);
|
||||
template < typename Node, typename Iter >
|
||||
std::size_t extract_parents(
|
||||
const intrusive_ptr<Node>& root,
|
||||
Iter iter,
|
||||
const options& opts = options());
|
||||
|
||||
template < typename F >
|
||||
void for_extracted_nodes_reversed(const node_iptr& root, F&& f);
|
||||
template < typename F >
|
||||
void for_extracted_nodes_reversed(const const_node_iptr& root, F&& f);
|
||||
|
||||
template < typename F >
|
||||
void for_extracted_parents(const node_iptr& parents, F&& f);
|
||||
template < typename F >
|
||||
void for_extracted_parents(const const_node_iptr& parents, F&& f);
|
||||
|
||||
template < typename F >
|
||||
void for_extracted_parents_reversed(const node_iptr& parents, F&& f);
|
||||
template < typename F >
|
||||
void for_extracted_parents_reversed(const const_node_iptr& parents, F&& f);
|
||||
template < typename Node, typename Iter >
|
||||
std::size_t extract_children(
|
||||
const intrusive_ptr<Node>& root,
|
||||
Iter iter,
|
||||
const options& opts = options());
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
template < typename Component >
|
||||
gcomponent<Component> get_component_in_parent(const const_node_iptr& root);
|
||||
template < typename Component, typename Iter >
|
||||
std::size_t get_components_in_parent(const const_node_iptr& root, Iter iter);
|
||||
template < typename Node, typename F >
|
||||
bool for_extracted_parents(
|
||||
const intrusive_ptr<Node>& root,
|
||||
F&& f,
|
||||
const options& opts = options());
|
||||
|
||||
template < typename Component >
|
||||
gcomponent<Component> get_component_in_children(const const_node_iptr& root);
|
||||
template < typename Component, typename Iter >
|
||||
std::size_t get_components_in_children(const const_node_iptr& root, Iter iter);
|
||||
template < typename Node, typename F >
|
||||
bool for_extracted_children(
|
||||
const intrusive_ptr<Node>& root,
|
||||
F&& f,
|
||||
const options& opts = options());
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
template < typename Component, typename Node, typename Iter >
|
||||
std::size_t extract_components_from_parents(
|
||||
const intrusive_ptr<Node>& root,
|
||||
Iter iter,
|
||||
const options& opts = options());
|
||||
|
||||
template < typename Component, typename Node, typename Iter >
|
||||
std::size_t extract_components_from_children(
|
||||
const intrusive_ptr<Node>& root,
|
||||
Iter iter,
|
||||
const options& opts = options());
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
template < typename Component, typename Node, typename F >
|
||||
bool for_extracted_components_from_parents(
|
||||
const intrusive_ptr<Node>& root,
|
||||
F&& f,
|
||||
const options& opts = options());
|
||||
|
||||
template < typename Component, typename Node, typename F >
|
||||
bool for_extracted_components_from_children(
|
||||
const intrusive_ptr<Node>& root,
|
||||
F&& f,
|
||||
const options& opts = options());
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
template < typename Component, typename Node >
|
||||
gcomponent<Component> find_component_from_parents(
|
||||
const intrusive_ptr<Node>& root,
|
||||
const options& opts = options());
|
||||
|
||||
template < typename Component, typename Node >
|
||||
gcomponent<Component> find_component_from_children(
|
||||
const intrusive_ptr<Node>& root,
|
||||
const options& opts = options());
|
||||
}
|
||||
|
||||
#include "node.inl"
|
||||
|
||||
@@ -8,388 +8,327 @@
|
||||
|
||||
#include "node.hpp"
|
||||
|
||||
namespace e2d
|
||||
namespace e2d::nodes::impl
|
||||
{
|
||||
template < typename F >
|
||||
void node::for_each_child(F&& f) {
|
||||
for ( auto iter = children_.begin(); iter != children_.end(); ++iter ) {
|
||||
f(node_iptr(&*iter));
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void node::for_each_child(F&& f) const {
|
||||
for ( auto iter = children_.begin(); iter != children_.end(); ++iter ) {
|
||||
f(const_node_iptr(&*iter));
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void node::for_each_child_reversed(F&& f) {
|
||||
for ( auto iter = children_.rbegin(); iter != children_.rend(); ++iter ) {
|
||||
f(node_iptr(&*iter));
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void node::for_each_child_reversed(F&& f) const {
|
||||
for ( auto iter = children_.rbegin(); iter != children_.rend(); ++iter ) {
|
||||
f(const_node_iptr(&*iter));
|
||||
template < typename F, typename... Args >
|
||||
bool invoke_with_force_bool(F&& f, Args&&... args) {
|
||||
if constexpr ( std::is_invocable_r_v<bool, F, Args...> ) {
|
||||
return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
|
||||
} else {
|
||||
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
template < typename Iter >
|
||||
std::size_t extract_nodes(const node_iptr& root, Iter iter) {
|
||||
std::size_t count{0u};
|
||||
if ( root ) {
|
||||
++count;
|
||||
iter++ = root;
|
||||
root->for_each_child([&iter, &count](const node_iptr& child){
|
||||
count += extract_nodes(child, iter);
|
||||
});
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template < typename Iter >
|
||||
std::size_t extract_nodes(const const_node_iptr& root, Iter iter) {
|
||||
std::size_t count{0u};
|
||||
if ( root ) {
|
||||
++count;
|
||||
iter++ = root;
|
||||
root->for_each_child([&iter, &count](const const_node_iptr& child){
|
||||
count += extract_nodes(child, iter);
|
||||
});
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template < typename Iter >
|
||||
std::size_t extract_nodes_reversed(const node_iptr& root, Iter iter) {
|
||||
std::size_t count{0u};
|
||||
if ( root ) {
|
||||
root->for_each_child_reversed([&iter, &count](const node_iptr& child){
|
||||
count += extract_nodes_reversed(child, iter);
|
||||
});
|
||||
++count;
|
||||
iter++ = root;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template < typename Iter >
|
||||
std::size_t extract_nodes_reversed(const const_node_iptr& root, Iter iter) {
|
||||
std::size_t count{0u};
|
||||
if ( root ) {
|
||||
root->for_each_child_reversed([&iter, &count](const const_node_iptr& child){
|
||||
count += extract_nodes_reversed(child, iter);
|
||||
});
|
||||
++count;
|
||||
iter++ = root;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
template < typename Iter >
|
||||
std::size_t extract_parents(const node_iptr& root, Iter iter) {
|
||||
std::size_t count{0u};
|
||||
if ( root ) {
|
||||
++count;
|
||||
iter++ = root;
|
||||
count += extract_parents(root->parent(), iter);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template < typename Iter >
|
||||
std::size_t extract_parents(const const_node_iptr& root, Iter iter) {
|
||||
std::size_t count{0u};
|
||||
if ( root ) {
|
||||
++count;
|
||||
iter++ = root;
|
||||
count += extract_parents(root->parent(), iter);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template < typename Iter >
|
||||
std::size_t extract_parents_reversed(const node_iptr& root, Iter iter) {
|
||||
std::size_t count{0u};
|
||||
if ( root ) {
|
||||
count += extract_parents(root->parent(), iter);
|
||||
++count;
|
||||
iter++ = root;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template < typename Iter >
|
||||
std::size_t extract_parents_reversed(const const_node_iptr& root, Iter iter) {
|
||||
std::size_t count{0u};
|
||||
if ( root ) {
|
||||
count += extract_parents(root->parent(), iter);
|
||||
++count;
|
||||
iter++ = root;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
template < typename F >
|
||||
void for_extracted_nodes(const node_iptr& root, F&& f) {
|
||||
//TODO(BlackMat): replace it to frame allocator
|
||||
static thread_local vector<node_iptr> nodes;
|
||||
|
||||
const std::size_t begin_index = nodes.size();
|
||||
E2D_DEFER([begin_index](){
|
||||
nodes.erase(
|
||||
nodes.begin() + begin_index,
|
||||
nodes.end());
|
||||
});
|
||||
|
||||
extract_nodes(
|
||||
root,
|
||||
std::back_inserter(nodes));
|
||||
|
||||
const std::size_t end_index = nodes.size();
|
||||
for ( std::size_t i = begin_index; i < end_index; ++i ) {
|
||||
f(nodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void for_extracted_nodes(const const_node_iptr& root, F&& f) {
|
||||
//TODO(BlackMat): replace it to frame allocator
|
||||
static thread_local vector<const_node_iptr> nodes;
|
||||
|
||||
const std::size_t begin_index = nodes.size();
|
||||
E2D_DEFER([begin_index](){
|
||||
nodes.erase(
|
||||
nodes.begin() + begin_index,
|
||||
nodes.end());
|
||||
});
|
||||
|
||||
extract_nodes(
|
||||
root,
|
||||
std::back_inserter(nodes));
|
||||
|
||||
const std::size_t end_index = nodes.size();
|
||||
for ( std::size_t i = begin_index; i < end_index; ++i ) {
|
||||
f(nodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void for_extracted_nodes_reversed(const node_iptr& root, F&& f) {
|
||||
//TODO(BlackMat): replace it to frame allocator
|
||||
static thread_local vector<node_iptr> nodes;
|
||||
|
||||
const std::size_t begin_index = nodes.size();
|
||||
E2D_DEFER([begin_index](){
|
||||
nodes.erase(
|
||||
nodes.begin() + begin_index,
|
||||
nodes.end());
|
||||
});
|
||||
|
||||
extract_nodes_reversed(
|
||||
root,
|
||||
std::back_inserter(nodes));
|
||||
|
||||
const std::size_t end_index = nodes.size();
|
||||
for ( std::size_t i = begin_index; i < end_index; ++i ) {
|
||||
f(nodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void for_extracted_nodes_reversed(const const_node_iptr& root, F&& f) {
|
||||
//TODO(BlackMat): replace it to frame allocator
|
||||
static thread_local vector<const_node_iptr> nodes;
|
||||
|
||||
const std::size_t begin_index = nodes.size();
|
||||
E2D_DEFER([begin_index](){
|
||||
nodes.erase(
|
||||
nodes.begin() + begin_index,
|
||||
nodes.end());
|
||||
});
|
||||
|
||||
extract_nodes_reversed(
|
||||
root,
|
||||
std::back_inserter(nodes));
|
||||
|
||||
const std::size_t end_index = nodes.size();
|
||||
for ( std::size_t i = begin_index; i < end_index; ++i ) {
|
||||
f(nodes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
template < typename F >
|
||||
void for_extracted_parents(const node_iptr& root, F&& f) {
|
||||
//TODO(BlackMat): replace it to frame allocator
|
||||
static thread_local vector<node_iptr> parents;
|
||||
|
||||
const std::size_t begin_index = parents.size();
|
||||
E2D_DEFER([begin_index](){
|
||||
parents.erase(
|
||||
parents.begin() + begin_index,
|
||||
parents.end());
|
||||
});
|
||||
|
||||
extract_parents(
|
||||
root,
|
||||
std::back_inserter(parents));
|
||||
|
||||
const std::size_t end_index = parents.size();
|
||||
for ( std::size_t i = begin_index; i < end_index; ++i ) {
|
||||
f(parents[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void for_extracted_parents(const const_node_iptr& root, F&& f) {
|
||||
//TODO(BlackMat): replace it to frame allocator
|
||||
static thread_local vector<const_node_iptr> parents;
|
||||
|
||||
const std::size_t begin_index = parents.size();
|
||||
E2D_DEFER([begin_index](){
|
||||
parents.erase(
|
||||
parents.begin() + begin_index,
|
||||
parents.end());
|
||||
});
|
||||
|
||||
extract_parents(
|
||||
root,
|
||||
std::back_inserter(parents));
|
||||
|
||||
const std::size_t end_index = parents.size();
|
||||
for ( std::size_t i = begin_index; i < end_index; ++i ) {
|
||||
f(parents[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void for_extracted_parents_reversed(const node_iptr& root, F&& f) {
|
||||
//TODO(BlackMat): replace it to frame allocator
|
||||
static thread_local vector<node_iptr> parents;
|
||||
|
||||
const std::size_t begin_index = parents.size();
|
||||
E2D_DEFER([begin_index](){
|
||||
parents.erase(
|
||||
parents.begin() + begin_index,
|
||||
parents.end());
|
||||
});
|
||||
|
||||
extract_parents_reversed(
|
||||
root,
|
||||
std::back_inserter(parents));
|
||||
|
||||
const std::size_t end_index = parents.size();
|
||||
for ( std::size_t i = begin_index; i < end_index; ++i ) {
|
||||
f(parents[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void for_extracted_parents_reversed(const const_node_iptr& root, F&& f) {
|
||||
//TODO(BlackMat): replace it to frame allocator
|
||||
static thread_local vector<const_node_iptr> parents;
|
||||
|
||||
const std::size_t begin_index = parents.size();
|
||||
E2D_DEFER([begin_index](){
|
||||
parents.erase(
|
||||
parents.begin() + begin_index,
|
||||
parents.end());
|
||||
});
|
||||
|
||||
extract_parents_reversed(
|
||||
root,
|
||||
std::back_inserter(parents));
|
||||
|
||||
const std::size_t end_index = parents.size();
|
||||
for ( std::size_t i = begin_index; i < end_index; ++i ) {
|
||||
f(parents[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
template < typename Component >
|
||||
gcomponent<Component> get_component_in_parent(const const_node_iptr& root) {
|
||||
template < typename Node, typename F >
|
||||
bool for_each_child(
|
||||
const intrusive_ptr<Node>& root,
|
||||
F&& f,
|
||||
const options& opts)
|
||||
{
|
||||
if ( !root ) {
|
||||
return {};
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( auto component = root->owner().component<Component>() ) {
|
||||
return component;
|
||||
}
|
||||
if ( opts.reversed() ) {
|
||||
for ( auto child = root->last_child(); child; child = child->prev_sibling() ) {
|
||||
if ( opts.recursive() && !for_each_child(child, f, options(opts).include_root(false)) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return get_component_in_parent<Component>(root->parent());
|
||||
}
|
||||
if ( !impl::invoke_with_force_bool(f, child) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template < typename Component, typename Iter >
|
||||
std::size_t get_components_in_parent(const const_node_iptr& root, Iter iter) {
|
||||
std::size_t count{0u};
|
||||
if ( opts.include_root() && !impl::invoke_with_force_bool(f, root) ) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ( opts.include_root() && !impl::invoke_with_force_bool(f, root) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !root ) {
|
||||
return count;
|
||||
}
|
||||
for ( auto child = root->first_child(); child; child = child->next_sibling() ) {
|
||||
if ( !impl::invoke_with_force_bool(f, child) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( auto component = root->owner().component<Component>() ) {
|
||||
++count;
|
||||
iter++ = component;
|
||||
}
|
||||
|
||||
return count + get_components_in_parent<Component>(root->parent(), iter);
|
||||
}
|
||||
|
||||
template < typename Component >
|
||||
gcomponent<Component> get_component_in_children(const const_node_iptr& root) {
|
||||
if ( !root ) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if ( auto component = root->owner().component<Component>() ) {
|
||||
return component;
|
||||
}
|
||||
|
||||
for ( const_node_iptr child = root->first_child(); child; child = child->next_sibling() ) {
|
||||
if ( auto component = get_component_in_children<Component>(child) ) {
|
||||
return component;
|
||||
if ( opts.recursive() && !for_each_child(child, f, options(opts).include_root(false)) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
return true;
|
||||
}
|
||||
|
||||
template < typename Component, typename Iter >
|
||||
std::size_t get_components_in_children(const const_node_iptr& root, Iter iter) {
|
||||
std::size_t count{0u};
|
||||
|
||||
template < typename Node, typename F >
|
||||
bool for_each_parent(
|
||||
const intrusive_ptr<Node>& root,
|
||||
F&& f,
|
||||
const options& opts)
|
||||
{
|
||||
if ( !root ) {
|
||||
return count;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( auto component = root->owner().component<Component>() ) {
|
||||
if ( opts.reversed() ) {
|
||||
if ( root->has_parent() ) {
|
||||
if ( opts.recursive() && !for_each_parent(root->parent(), f, options(opts).include_root(false)) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !impl::invoke_with_force_bool(f, root->parent()) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( opts.include_root() && !impl::invoke_with_force_bool(f, root) ) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ( opts.include_root() && !impl::invoke_with_force_bool(f, root) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( root->has_parent() ) {
|
||||
if ( !impl::invoke_with_force_bool(f, root->parent()) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( opts.recursive() && !for_each_parent(root->parent(), f, options(opts).include_root(false)) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
template < typename Node, typename Iter >
|
||||
std::size_t extract_parents(
|
||||
const intrusive_ptr<Node>& root,
|
||||
Iter iter,
|
||||
const options& opts)
|
||||
{
|
||||
std::size_t count{0u};
|
||||
for_each_parent(root, [&count, &iter](const auto& parent){
|
||||
++count;
|
||||
iter++ = component;
|
||||
}
|
||||
|
||||
for ( const_node_iptr child = root->first_child(); child; child = child->next_sibling() ) {
|
||||
count += get_components_in_children<Component>(child, iter);
|
||||
}
|
||||
iter++ = parent;
|
||||
}, opts);
|
||||
return count;
|
||||
}
|
||||
|
||||
template < typename Node, typename Iter >
|
||||
std::size_t extract_children(
|
||||
const intrusive_ptr<Node>& root,
|
||||
Iter iter,
|
||||
const options& opts)
|
||||
{
|
||||
std::size_t count{0u};
|
||||
for_each_child(root, [&count, &iter](const auto& child){
|
||||
++count;
|
||||
iter++ = child;
|
||||
}, opts);
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
template < typename Node, typename F >
|
||||
bool for_extracted_parents(
|
||||
const intrusive_ptr<Node>& root,
|
||||
F&& f,
|
||||
const options& opts)
|
||||
{
|
||||
//TODO(BlackMat): replace it to frame allocator
|
||||
static thread_local vector<intrusive_ptr<Node>> parents;
|
||||
|
||||
const std::size_t begin_index = parents.size();
|
||||
E2D_DEFER([begin_index](){
|
||||
parents.erase(
|
||||
parents.begin() + begin_index,
|
||||
parents.end());
|
||||
});
|
||||
|
||||
extract_parents(
|
||||
root,
|
||||
std::back_inserter(parents),
|
||||
opts);
|
||||
|
||||
const std::size_t end_index = parents.size();
|
||||
for ( std::size_t i = begin_index; i < end_index; ++i ) {
|
||||
if ( !impl::invoke_with_force_bool(f, parents[i]) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template < typename Node, typename F >
|
||||
bool for_extracted_children(
|
||||
const intrusive_ptr<Node>& root,
|
||||
F&& f,
|
||||
const options& opts)
|
||||
{
|
||||
//TODO(BlackMat): replace it to frame allocator
|
||||
static thread_local vector<intrusive_ptr<Node>> children;
|
||||
|
||||
const std::size_t begin_index = children.size();
|
||||
E2D_DEFER([begin_index](){
|
||||
children.erase(
|
||||
children.begin() + begin_index,
|
||||
children.end());
|
||||
});
|
||||
|
||||
extract_children(
|
||||
root,
|
||||
std::back_inserter(children),
|
||||
opts);
|
||||
|
||||
const std::size_t end_index = children.size();
|
||||
for ( std::size_t i = begin_index; i < end_index; ++i ) {
|
||||
if ( !impl::invoke_with_force_bool(f, children[i]) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
template < typename Component, typename Node, typename Iter >
|
||||
std::size_t extract_components_from_parents(
|
||||
const intrusive_ptr<Node>& root,
|
||||
Iter iter,
|
||||
const options& opts)
|
||||
{
|
||||
std::size_t count{0u};
|
||||
for_each_parent(root, [&count, &iter](const auto& parent){
|
||||
if ( auto component = parent->owner().template component<Component>() ) {
|
||||
++count;
|
||||
iter++ = component;
|
||||
}
|
||||
}, opts);
|
||||
return count;
|
||||
}
|
||||
|
||||
template < typename Component, typename Node, typename Iter >
|
||||
std::size_t extract_components_from_children(
|
||||
const intrusive_ptr<Node>& root,
|
||||
Iter iter,
|
||||
const options& opts)
|
||||
{
|
||||
std::size_t count{0u};
|
||||
for_each_child(root, [&count, &iter](const auto& child){
|
||||
if ( auto component = child->owner().template component<Component>() ) {
|
||||
++count;
|
||||
iter++ = component;
|
||||
}
|
||||
}, opts);
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
template < typename Component, typename Node, typename F >
|
||||
bool for_extracted_components_from_parents(
|
||||
const intrusive_ptr<Node>& root,
|
||||
F&& f,
|
||||
const options& opts)
|
||||
{
|
||||
//TODO(BlackMat): replace it to frame allocator
|
||||
static thread_local vector<gcomponent<Component>> components;
|
||||
|
||||
const std::size_t begin_index = components.size();
|
||||
E2D_DEFER([begin_index](){
|
||||
components.erase(
|
||||
components.begin() + begin_index,
|
||||
components.end());
|
||||
});
|
||||
|
||||
extract_components_from_parents<Component>(
|
||||
root,
|
||||
std::back_inserter(components),
|
||||
opts);
|
||||
|
||||
const std::size_t end_index = components.size();
|
||||
for ( std::size_t i = begin_index; i < end_index; ++i ) {
|
||||
if ( !impl::invoke_with_force_bool(f, components[i]) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template < typename Component, typename Node, typename F >
|
||||
bool for_extracted_components_from_children(
|
||||
const intrusive_ptr<Node>& root,
|
||||
F&& f,
|
||||
const options& opts)
|
||||
{
|
||||
//TODO(BlackMat): replace it to frame allocator
|
||||
static thread_local vector<gcomponent<Component>> components;
|
||||
|
||||
const std::size_t begin_index = components.size();
|
||||
E2D_DEFER([begin_index](){
|
||||
components.erase(
|
||||
components.begin() + begin_index,
|
||||
components.end());
|
||||
});
|
||||
|
||||
extract_components_from_children<Component>(
|
||||
root,
|
||||
std::back_inserter(components),
|
||||
opts);
|
||||
|
||||
const std::size_t end_index = components.size();
|
||||
for ( std::size_t i = begin_index; i < end_index; ++i ) {
|
||||
if ( !impl::invoke_with_force_bool(f, components[i]) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
template < typename Component, typename Node >
|
||||
gcomponent<Component> find_component_from_parents(
|
||||
const intrusive_ptr<Node>& root,
|
||||
const options& opts)
|
||||
{
|
||||
gcomponent<Component> component;
|
||||
for_each_parent(root, [&component](const auto& child){
|
||||
return !(component = child->owner().template component<Component>());
|
||||
}, opts);
|
||||
return component;
|
||||
}
|
||||
|
||||
template < typename Component, typename Node >
|
||||
gcomponent<Component> find_component_from_children(
|
||||
const intrusive_ptr<Node>& root,
|
||||
const options& opts)
|
||||
{
|
||||
gcomponent<Component> component;
|
||||
for_each_child(root, [&component](const auto& child){
|
||||
return !(component = child->owner().template component<Component>());
|
||||
}, opts);
|
||||
return component;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include <enduro2d/high/node.hpp>
|
||||
#include <enduro2d/high/world.hpp>
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
@@ -446,54 +445,36 @@ namespace e2d
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
vector<node_iptr> extract_nodes(const node_iptr& root) {
|
||||
vector<node_iptr> nodes;
|
||||
extract_nodes(root, std::back_inserter(nodes));
|
||||
return nodes;
|
||||
options& options::reversed(bool value) noexcept {
|
||||
if ( value != reversed() ) {
|
||||
math::flip_flags_inplace(flags_, fm_reversed);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
vector<const_node_iptr> extract_nodes(const const_node_iptr& root) {
|
||||
vector<const_node_iptr> nodes;
|
||||
extract_nodes(root, std::back_inserter(nodes));
|
||||
return nodes;
|
||||
options& options::recursive(bool value) noexcept {
|
||||
if ( value != recursive() ) {
|
||||
math::flip_flags_inplace(flags_, fm_recursive);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
vector<node_iptr> extract_nodes_reversed(const node_iptr& root) {
|
||||
vector<node_iptr> nodes;
|
||||
extract_nodes_reversed(root, std::back_inserter(nodes));
|
||||
return nodes;
|
||||
options& options::include_root(bool value) noexcept {
|
||||
if ( value != include_root() ) {
|
||||
math::flip_flags_inplace(flags_, fm_include_root);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
vector<const_node_iptr> extract_nodes_reversed(const const_node_iptr& root) {
|
||||
vector<const_node_iptr> nodes;
|
||||
extract_nodes_reversed(root, std::back_inserter(nodes));
|
||||
return nodes;
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d::nodes
|
||||
{
|
||||
vector<node_iptr> extract_parents(const node_iptr& child) {
|
||||
vector<node_iptr> parents;
|
||||
extract_parents(child, std::back_inserter(parents));
|
||||
return parents;
|
||||
}
|
||||
|
||||
vector<const_node_iptr> extract_parents(const const_node_iptr& child) {
|
||||
vector<const_node_iptr> parents;
|
||||
extract_parents(child, std::back_inserter(parents));
|
||||
return parents;
|
||||
}
|
||||
|
||||
vector<node_iptr> extract_parents_reversed(const node_iptr& child) {
|
||||
vector<node_iptr> parents;
|
||||
extract_parents_reversed(child, std::back_inserter(parents));
|
||||
return parents;
|
||||
}
|
||||
|
||||
vector<const_node_iptr> extract_parents_reversed(const const_node_iptr& child) {
|
||||
vector<const_node_iptr> parents;
|
||||
extract_parents_reversed(child, std::back_inserter(parents));
|
||||
return parents;
|
||||
bool options::reversed() const noexcept {
|
||||
return math::check_any_flags(flags_, fm_reversed);
|
||||
}
|
||||
|
||||
bool options::recursive() const noexcept {
|
||||
return math::check_any_flags(flags_, fm_recursive);
|
||||
}
|
||||
|
||||
bool options::include_root() const noexcept {
|
||||
return math::check_any_flags(flags_, fm_include_root);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,9 +30,9 @@ namespace
|
||||
const scene&,
|
||||
const actor& scn_a)
|
||||
{
|
||||
nodes::for_extracted_nodes(scn_a.node(), [&ctx](const const_node_iptr& node){
|
||||
nodes::for_extracted_children(scn_a.node(), [&ctx](const const_node_iptr& node){
|
||||
ctx.draw(node);
|
||||
});
|
||||
}, nodes::options().recursive(true).include_root(true));
|
||||
};
|
||||
|
||||
ecsex::for_extracted_sorted_components<scene, actor>(
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace
|
||||
}
|
||||
|
||||
if ( tree_node_opened ) {
|
||||
root->for_each_child([&e, &i, &w](const node_iptr& child){
|
||||
nodes::for_each_child(root, [&e, &i, &w](const node_iptr& child){
|
||||
show_tree_for_node(e, i, w, child);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -142,32 +142,36 @@ namespace
|
||||
}
|
||||
|
||||
void shutdown_instance(gobject& inst) noexcept {
|
||||
if ( gcomponent<actor> inst_a{inst}; inst_a ) {
|
||||
nodes::for_extracted_nodes(inst_a->node(), [](const node_iptr& node){
|
||||
if ( gcomponent<behaviour> inst_b{node->owner()}; inst_b ) {
|
||||
behaviours::call_meta_method(
|
||||
*inst_b,
|
||||
"on_shutdown",
|
||||
node->owner());
|
||||
}
|
||||
});
|
||||
gcomponent<actor> inst_a = inst.component<actor>();
|
||||
if ( !inst_a ) {
|
||||
return;
|
||||
}
|
||||
nodes::for_extracted_components_from_children<behaviour>(
|
||||
inst_a->node(),
|
||||
[](gcomponent<behaviour>& inst_b){
|
||||
behaviours::call_meta_method(
|
||||
*inst_b,
|
||||
"on_shutdown",
|
||||
inst_b.owner());
|
||||
}, nodes::options().recursive(true).include_root(true));
|
||||
}
|
||||
|
||||
void start_instance(gobject& inst) {
|
||||
if ( gcomponent<actor> inst_a{inst}; inst_a ) {
|
||||
nodes::for_extracted_nodes(inst_a->node(), [&inst](const node_iptr& node){
|
||||
if ( gcomponent<behaviour> inst_b{node->owner()}; inst_b ) {
|
||||
const auto result = behaviours::call_meta_method(
|
||||
*inst_b,
|
||||
"on_start",
|
||||
node->owner());
|
||||
if ( result == behaviours::call_result::failed ) {
|
||||
inst.component<disabled<behaviour>>().assign();
|
||||
}
|
||||
}
|
||||
});
|
||||
gcomponent<actor> inst_a = inst.component<actor>();
|
||||
if ( !inst_a ) {
|
||||
return;
|
||||
}
|
||||
nodes::for_extracted_components_from_children<behaviour>(
|
||||
inst_a->node(),
|
||||
[&inst](gcomponent<behaviour>& inst_b){
|
||||
const auto result = behaviours::call_meta_method(
|
||||
*inst_b,
|
||||
"on_start",
|
||||
inst_b.owner());
|
||||
if ( result == behaviours::call_result::failed ) {
|
||||
inst.component<disabled<behaviour>>().assign();
|
||||
}
|
||||
}, nodes::options().recursive(true).include_root(true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -595,7 +595,7 @@ TEST_CASE("node") {
|
||||
node::create(p)};
|
||||
{
|
||||
std::size_t count = 0;
|
||||
p->for_each_child([&ns, &count](const node_iptr& n){
|
||||
nodes::for_each_child(p, [&ns, &count](const node_iptr& n){
|
||||
REQUIRE(ns[count++] == n);
|
||||
});
|
||||
REQUIRE(count == 3);
|
||||
@@ -603,7 +603,7 @@ TEST_CASE("node") {
|
||||
{
|
||||
const_node_iptr cp = p;
|
||||
std::size_t count = 0;
|
||||
cp->for_each_child([&ns, &count](const const_node_iptr& n){
|
||||
nodes::for_each_child(cp, [&ns, &count](const const_node_iptr& n){
|
||||
REQUIRE(ns[count++] == n);
|
||||
});
|
||||
REQUIRE(count == 3);
|
||||
@@ -617,13 +617,19 @@ TEST_CASE("node") {
|
||||
const vector<node_iptr> ns{p, c1, c2, c3};
|
||||
{
|
||||
vector<node_iptr> ns2;
|
||||
REQUIRE(4u == nodes::extract_nodes(p, std::back_inserter(ns2)));
|
||||
REQUIRE(4u == nodes::extract_children(
|
||||
p,
|
||||
std::back_inserter(ns2),
|
||||
nodes::options().recursive(true).include_root(true)));
|
||||
REQUIRE(ns == ns2);
|
||||
}
|
||||
{
|
||||
const_node_iptr cp = p;
|
||||
vector<const_node_iptr> ns2;
|
||||
REQUIRE(4u == nodes::extract_nodes(cp, std::back_inserter(ns2)));
|
||||
REQUIRE(4u == nodes::extract_children(
|
||||
cp,
|
||||
std::back_inserter(ns2),
|
||||
nodes::options().recursive(true).include_root(true)));
|
||||
REQUIRE(ns.size() == ns2.size());
|
||||
for ( std::size_t i = 0; i < ns.size(); ++i ) {
|
||||
REQUIRE(ns[i] == ns2[i]);
|
||||
|
||||
Reference in New Issue
Block a user