diff --git a/panda/src/pgraph/qpnodePath.I b/panda/src/pgraph/qpnodePath.I index 686ee83e4a..64f76a5ece 100644 --- a/panda/src/pgraph/qpnodePath.I +++ b/panda/src/pgraph/qpnodePath.I @@ -20,11 +20,7 @@ //////////////////////////////////////////////////////////////////// // Function: qpNodePath::Default Constructor // Access: Published -// Description: This constructs an empty qpNodePath with no nodes. It -// cannot be extended, since you cannot add nodes without -// first specifying the top node. Use the constructor -// that receives a node if you ever want to do anything -// with this path. +// Description: This constructs an empty qpNodePath with no nodes. //////////////////////////////////////////////////////////////////// INLINE qpNodePath:: qpNodePath() : @@ -35,9 +31,9 @@ qpNodePath() : //////////////////////////////////////////////////////////////////// // Function: qpNodePath::Constructor // Access: Published -// Description: This constructs an empty qpNodePath with a single -// node. An ordinary PandaNode is created with the -// indicated name. +// Description: This constructs a new qpNodePath with a single +// node. An ordinary, unattached PandaNode is created +// with the indicated name. //////////////////////////////////////////////////////////////////// INLINE qpNodePath:: qpNodePath(const string &top_node_name) : @@ -52,35 +48,53 @@ qpNodePath(const string &top_node_name) : // Access: Published // Description: This constructs a NodePath for the indicated node. // If the node does not have any parents, this creates a -// single NodePath; otherwise, it automatically finds +// singleton NodePath; otherwise, it automatically finds // the path from the node to the root. If the node has // multiple paths to the root, one path is chosen -// arbitrarily and a warning message is printed. +// arbitrarily and a warning message is printed (but see +// also NodePath::any_path(), below). //////////////////////////////////////////////////////////////////// INLINE qpNodePath:: -qpNodePath(PandaNode *top_node) : +qpNodePath(PandaNode *node) : _error_type(ET_ok) { - if (top_node != (PandaNode *)NULL) { - _head = top_node->get_generic_component(false); + if (node != (PandaNode *)NULL) { + _head = node->get_generic_component(false); } } +//////////////////////////////////////////////////////////////////// +// Function: qpNodePath::any_path named constructor +// Access: Published, Static +// Description: Returns a new NodePath that represents any arbitrary +// path from the root to the indicated node. This is +// the same thing that would be returned by +// NodePath(node), except that no warning is issued if +// the path is ambiguous. +//////////////////////////////////////////////////////////////////// +INLINE qpNodePath qpNodePath:: +any_path(PandaNode *node) { + qpNodePath result; + if (node != (PandaNode *)NULL) { + result._head = node->get_generic_component(true); + } + return result; +} + //////////////////////////////////////////////////////////////////// // Function: qpNodePath::Constructor // Access: Published // Description: Constructs a NodePath with the indicated parent // NodePath and child node; the child node must be a - // stashed or unstashed child of the parent. //////////////////////////////////////////////////////////////////// INLINE qpNodePath:: -qpNodePath(const qpNodePath &parent, PandaNode *child) : +qpNodePath(const qpNodePath &parent, PandaNode *child_node) : _error_type(ET_fail) { nassertv(!parent.is_empty()); - nassertv(child != (PandaNode *)NULL); - _head = PandaNode::get_component(parent._head, child); + nassertv(child_node != (PandaNode *)NULL); + _head = PandaNode::get_component(parent._head, child_node); nassertv(_head != (qpNodePathComponent *)NULL); if (_head != (qpNodePathComponent *)NULL) { @@ -155,7 +169,7 @@ fail() { //////////////////////////////////////////////////////////////////// // Function: qpNodePath::set_max_search_depth // Access: Published, Static -// Description: Certain operations, such as extend_down_to() or +// Description: Certain operations, such as find() or // find_all_matches(), require a traversal of the scene // graph to search for the target node or nodes. This // traversal does not attempt to detect cycles, so an @@ -252,6 +266,13 @@ node() const { // given key will never be reused for a different // instance (unless the app has been running long enough // that we overflow the integer key value). +// +// There are a few special case circumstances that can +// cause the key for a particular instance to be +// changed. These all involve different instances being +// collapsed into the same instance by some scene graph +// operation (for instance, detaching a node below an +// instanced node). //////////////////////////////////////////////////////////////////// INLINE int qpNodePath:: get_key() const { @@ -350,28 +371,6 @@ ls(ostream &out, int indent_level) const { } } -//////////////////////////////////////////////////////////////////// -// Function: qpNodePath::ls_transitions -// Access: Published -// Description: Lists the hierarchy at and below the referenced node, -// along with the state transitions at each level. -//////////////////////////////////////////////////////////////////// -INLINE void qpNodePath:: -ls_transitions() const { - nassertv(false); -} - -//////////////////////////////////////////////////////////////////// -// Function: qpNodePath::ls_transforms -// Access: Published -// Description: Lists the hierarchy at and below the referenced node, -// along with the transforms at each level. -//////////////////////////////////////////////////////////////////// -INLINE void qpNodePath:: -ls_transforms() const { - nassertv(false); -} - //////////////////////////////////////////////////////////////////// // Function: qpNodePath::get_state // Access: Published @@ -1078,7 +1077,7 @@ compare_to(const qpNodePath &other) const { other.uncollapse_head(); // Nowadays, the NodePathComponents at the head are pointerwise - // equivalent if and only iff the NodePaths are equivalent. So we + // equivalent if and only if the NodePaths are equivalent. So we // only have to compare pointers. return _head - other._head; } diff --git a/panda/src/pgraph/qpnodePath.cxx b/panda/src/pgraph/qpnodePath.cxx index 58152fbff8..876d4c7108 100644 --- a/panda/src/pgraph/qpnodePath.cxx +++ b/panda/src/pgraph/qpnodePath.cxx @@ -357,21 +357,42 @@ attach_new_node(PandaNode *node, int sort) const { void qpNodePath:: remove_node() { nassertv(_error_type != ET_not_found); - if (is_empty() || is_singleton()) { - // If we have no parents, remove_node() is just a do-nothing - // operation; if we have no nodes, maybe we were already removed. - // In either case, quietly do nothing except to ensure the - // qpNodePath is clear. - (*this) = qpNodePath::removed(); - return; + + // If we have no parents, remove_node() is just a do-nothing + // operation; if we have no nodes, maybe we were already removed. + // In either case, quietly do nothing except to ensure the + // qpNodePath is clear. + if (!is_empty() && !is_singleton()) { + uncollapse_head(); + PandaNode::detach(_head); } - uncollapse_head(); - PandaNode::detach(_head); - (*this) = qpNodePath::removed(); } +//////////////////////////////////////////////////////////////////// +// Function: qpNodePath::detach_node +// Access: Published +// Description: Disconnects the referenced node from its parent, but +// does not immediately delete it. The NodePath retains +// a pointer to the node. If there are no other +// instances to the node, this becomes a singleton +// NodePath; otherwise, this NodePath becomes the same +// as another arbitrary instance. +// +// If the NodePath later goes out of scope or is +// reassigned to something else, this will have the same +// effect as remove_node(). +//////////////////////////////////////////////////////////////////// +void qpNodePath:: +detach_node() { + nassertv(_error_type != ET_not_found); + if (!is_empty() && !is_singleton()) { + uncollapse_head(); + PandaNode::detach(_head); + } +} + //////////////////////////////////////////////////////////////////// // Function: qpNodePath::output // Access: Published diff --git a/panda/src/pgraph/qpnodePath.h b/panda/src/pgraph/qpnodePath.h index 53df39798a..ef6797480a 100644 --- a/panda/src/pgraph/qpnodePath.h +++ b/panda/src/pgraph/qpnodePath.h @@ -149,9 +149,11 @@ PUBLISHED: INLINE qpNodePath(); INLINE qpNodePath(const string &top_node_name); - INLINE qpNodePath(PandaNode *top_node); - INLINE qpNodePath(const qpNodePath ©); + INLINE qpNodePath(PandaNode *node); + INLINE static qpNodePath any_path(PandaNode *node); INLINE qpNodePath(const qpNodePath &parent, PandaNode *child_node); + + INLINE qpNodePath(const qpNodePath ©); INLINE void operator = (const qpNodePath ©); INLINE static qpNodePath not_found(); @@ -202,6 +204,7 @@ PUBLISHED: qpNodePath attach_new_node(PandaNode *node, int sort = 0) const; INLINE qpNodePath attach_new_node(const string &name, int sort = 0) const; void remove_node(); + void detach_node(); // Handy ways to look at what's there, and other miscellaneous // operations. @@ -210,8 +213,6 @@ PUBLISHED: INLINE void ls() const; INLINE void ls(ostream &out, int indent_level = 0) const; - INLINE void ls_transitions() const; - INLINE void ls_transforms() const; // Aggregate transform and state information. diff --git a/panda/src/pgraph/qpnodePathComponent.I b/panda/src/pgraph/qpnodePathComponent.I index 84f960d260..cfdc128702 100644 --- a/panda/src/pgraph/qpnodePathComponent.I +++ b/panda/src/pgraph/qpnodePathComponent.I @@ -135,24 +135,3 @@ get_collapsed() const { CDReader cdata(_cycler); return cdata->_next; } - -//////////////////////////////////////////////////////////////////// -// Function: qpNodePathComponent::collapse_with -// Access: Private -// Description: Indicates that this component pointer is no longer -// valid, and that the indicated component should be -// used instead. This is done whenever two -// qpNodePathComponents have been collapsed together due -// to an instance being removed higher up in the graph. -//////////////////////////////////////////////////////////////////// -INLINE void qpNodePathComponent:: -collapse_with(qpNodePathComponent *next) { - nassertv(!is_collapsed()); - nassertv(next != (qpNodePathComponent *)NULL); - CDWriter cdata(_cycler); - cdata->_next = next; - cdata->_length = 0; - - // We indicate a component has been collapsed by setting its length - // to zero. -} diff --git a/panda/src/pgraph/qpnodePathComponent.cxx b/panda/src/pgraph/qpnodePathComponent.cxx index f0e8acc26c..5f979ad960 100644 --- a/panda/src/pgraph/qpnodePathComponent.cxx +++ b/panda/src/pgraph/qpnodePathComponent.cxx @@ -193,3 +193,30 @@ set_top_node() { cdata->_next = (qpNodePathComponent *)NULL; } } + +//////////////////////////////////////////////////////////////////// +// Function: qpNodePathComponent::collapse_with +// Access: Private +// Description: Indicates that this component pointer is no longer +// valid, and that the indicated component should be +// used instead. This is done whenever two +// qpNodePathComponents have been collapsed together due +// to an instance being removed higher up in the graph. +//////////////////////////////////////////////////////////////////// +void qpNodePathComponent:: +collapse_with(qpNodePathComponent *next) { + nassertv(!is_collapsed()); + nassertv(next != (qpNodePathComponent *)NULL); + CDWriter cdata(_cycler); + + // We indicate a component has been collapsed by setting its length + // to zero. + cdata->_next = next; + cdata->_length = 0; + + if (_key != 0 && next->_key == 0) { + // If we had a key set and the other one didn't, it inherits our + // key. Otherwise, we inherit the other's key. + next->_key = _key; + } +} diff --git a/panda/src/pgraph/qpnodePathComponent.h b/panda/src/pgraph/qpnodePathComponent.h index 4205ebb7a2..7ef4dee10a 100644 --- a/panda/src/pgraph/qpnodePathComponent.h +++ b/panda/src/pgraph/qpnodePathComponent.h @@ -68,7 +68,7 @@ public: private: void set_next(qpNodePathComponent *next); void set_top_node(); - INLINE void collapse_with(qpNodePathComponent *next); + void collapse_with(qpNodePathComponent *next); // We don't have to cycle the _node and _key elements, since these // are permanent properties of this object. (Well, the _key is