From 65abf5fbb7ccef203d614210fccd5db858a68923 Mon Sep 17 00:00:00 2001 From: harrand Date: Sun, 3 Sep 2023 20:31:24 +0100 Subject: [PATCH] [transform_hierarchy] documentation pass for transform_hierarchy --- src/tz/core/data/transform_hierarchy.hpp | 90 ++++++++++++++++++++++-- src/tz/core/data/transform_hierarchy.inl | 1 + 2 files changed, 84 insertions(+), 7 deletions(-) diff --git a/src/tz/core/data/transform_hierarchy.hpp b/src/tz/core/data/transform_hierarchy.hpp index ecbaa1882f..f6d023b712 100644 --- a/src/tz/core/data/transform_hierarchy.hpp +++ b/src/tz/core/data/transform_hierarchy.hpp @@ -7,12 +7,20 @@ namespace tz { + /** + * @ingroup tz_core + * Represents a node within a transform hierarchy. + **/ template struct transform_node { + /// User-data. You can use this for whatever you wish. Must be at least moveable. mutable T data; + /// Local transform, relative to its parent. If there is no parent, then this represents the global transform aswell. mutable tz::trs local_transform = {}; + /// Index of the node that is this node's parent, or nullopt if this node has no parent. std::optional parent = std::nullopt; + /// List of all indices representing this node's children. std::vector children = {}; }; @@ -25,32 +33,100 @@ namespace tz class transform_hierarchy { public: + /// Node type + using node = transform_node; + /// Create a new, empty hierarchy. transform_hierarchy() = default; + /** + * Retrieves the number of nodes within the hierarchy. + * @return Number of nodes in the hierarchy. + **/ std::size_t size() const; + /** + * Query as to whether the hierarchy has nodes. + * @return True if `this->size() == 0`, otherwise false. + **/ bool empty() const{return this->size() == 0;} + /** + * Remove all nodes from the hierarchy, emptying it. + * @note Invalidates all node indices. + **/ void clear(); + /** + * Retrieve a vector containing indices corresponding to all the root nodes. + * @return Vector containing indices of root nodes (nodes without a parent). + **/ std::vector get_root_node_ids() const; // returns id of the new node. + /** + * Add a new node to the hierarchy. + * @param local_transform Local transform of the node, local to its parent (if it has one). You can change this at any time. + * @param data Data payload of the node. You can change this at any time. + * @param parent Optional index of the parent. If the node has no parent, omit this parameter, or set it to `nullopt`. + * @return Index of the newly-created node. + **/ unsigned int add_node(tz::trs local_transform = {}, T data = {}, std::optional parent = std::nullopt); // returns offset to be applied to the previous hierarchy's set of nodes to get their corresponding node ids // within this hierarchy + /** + * Add all of the nodes of another hierarchy to this hierarchy, preserving structure. + * @param tree Hierarchy whose nodes should be copied into this hierarchy. + * @note The root nodes of the provided hierarchy will remain root nodes in this hierarchy. To attach these to an existing node, see @ref add_hierarchy_onto + * @return Integer representing the offset that should be applied to each index of the previous tree. i.e `tree.get_node(i)` corresponds to `this->get_node(i+n)`, where `n` is the return value of this method. + **/ unsigned int add_hierarchy(const transform_hierarchy& tree); + /** + * Add all of the nodes of another hierarchy onto a particular node of this hierarchy, preserving structure. + * @param tree Hierarchy whose nodes should be copied into this hierarchy. + * @param node_id A valid node index for *this* hierarchy, where all the nodes of the provided hierarchy will be attached to. + * @note This is similar to @ref add_hierarchy but root nodes of the provided hierarchy will be attached to the targeted node instead. + * @return Integer representing the offset that should be applied to each index of the previous tree. i.e `tree.get_node(i)` corresponds to `this->get_node(i+n)`, where `n` is the return value of this method. + */ unsigned int add_hierarchy_onto(const transform_hierarchy& tree, unsigned int node_id); + /** + * Take a copy of a particular node, and create a new hierarchy with that as the only root node. + * @param id Index corresponding to the node which should become the root node of the resultant hierarchy. + * @return Hierarchy, where the node corresponding to `id` is the root node, aswell as copies all of its children and descendants. + * @note The global transform of the node is preserved. That is - the global transform of the node within this hierarchy will be equal to the local transform of the root node of the new hierarchy. + **/ transform_hierarchy export_node(unsigned int id) const; + /** + * Retrieve the node corresponding to the given index. + * @param id Index corresponding to the node to retrieve. + * @return Node corresponding to the provided index. + * @pre `id` < `this->size()`, otherwise the behaviour is undefined. + **/ const transform_node& get_node(unsigned int id) const; + /** + * Retrieve the global transform of the node corresponding to the provided id. + * @param id Index corresponding to the node to calculate the global transform. + * @return TRS representing the global transform of the `id`'th node. + **/ tz::trs get_global_transform(unsigned int id) const; - - // invoke callback for each child of the node `id` + /** + * Invoke a callback for each child of the node corresponding to `id`. + * @param id Index corresponding to the node whose children to iterate over. + * @param callback Callback to be invoked with the current child's node index. Guaranteed to be invoked on the initial caller thread. + **/ void iterate_children(unsigned int id, tz::action auto callback) const; - // invoke callback for each descendant (children and their children, recursively) of the node `id` + /** + * Invoke a callback for each descendent of the node corresponding to `id`. A descendent is a node that is either a child, grandchild etc... of the provided node. + * @param id Index corresponding to the node whose descendants to iterate over. + * @param callback Callback to be invoked with the current descendant's node index. Guaranteed to be invoked on the initial caller thread. + **/ void iterate_descendants(unsigned int id, tz::action auto callback) const; // invoke callback for each ancestor (parent, their parent, etc...) of the node `id` + /** + * Invoke a callback for each ancestor of the node corresponding to `id`. An ancestor is a node that is either a parent, grandparent etc... of the provided node. + * @param id Index corresponding to the node whose ancestors to iterate over. + * @param callback Callback to be invoked with the current ancestor's node index. Guaranteed to be invoked on the initial caller thread. + **/ void iterate_ancestors(unsigned int id, tz::action auto callback) const; - // iterate through all nodes in order, starting with root nodes. depth first traversal. - // callback *will* be called a number of times equal to `this->size()`. in graph theory it - // could be invoked more, however a transform hierarchy means a node has 1 parent max, so - // it will always be exactly equal. + /** + * Invoke a callback for each node within the hierarchy, in-order. Depth-first traversal. + * @param callback Callback to be invoked exactly once for each node in the hierarchy. Guaranteed to be invoked on the initial caller thread. + **/ void iterate_nodes(tz::action auto callback) const; void dbgui(); diff --git a/src/tz/core/data/transform_hierarchy.inl b/src/tz/core/data/transform_hierarchy.inl index c45ab277cd..0a3df556c8 100644 --- a/src/tz/core/data/transform_hierarchy.inl +++ b/src/tz/core/data/transform_hierarchy.inl @@ -129,6 +129,7 @@ namespace tz template const transform_node& transform_hierarchy::get_node(unsigned int id) const { + tz::assert(id < this->nodes.size(), "Invalid node id %u", id); return this->nodes[id]; }