nodePath refinements

This commit is contained in:
David Rose 2002-03-23 19:05:13 +00:00
parent 03ae7a34a7
commit 5954465fbc
6 changed files with 104 additions and 77 deletions

View File

@ -20,11 +20,7 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: qpNodePath::Default Constructor // Function: qpNodePath::Default Constructor
// Access: Published // Access: Published
// Description: This constructs an empty qpNodePath with no nodes. It // Description: This constructs an empty qpNodePath with no nodes.
// 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.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE qpNodePath:: INLINE qpNodePath::
qpNodePath() : qpNodePath() :
@ -35,9 +31,9 @@ qpNodePath() :
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: qpNodePath::Constructor // Function: qpNodePath::Constructor
// Access: Published // Access: Published
// Description: This constructs an empty qpNodePath with a single // Description: This constructs a new qpNodePath with a single
// node. An ordinary PandaNode is created with the // node. An ordinary, unattached PandaNode is created
// indicated name. // with the indicated name.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE qpNodePath:: INLINE qpNodePath::
qpNodePath(const string &top_node_name) : qpNodePath(const string &top_node_name) :
@ -52,35 +48,53 @@ qpNodePath(const string &top_node_name) :
// Access: Published // Access: Published
// Description: This constructs a NodePath for the indicated node. // Description: This constructs a NodePath for the indicated node.
// If the node does not have any parents, this creates a // 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 // the path from the node to the root. If the node has
// multiple paths to the root, one path is chosen // 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:: INLINE qpNodePath::
qpNodePath(PandaNode *top_node) : qpNodePath(PandaNode *node) :
_error_type(ET_ok) _error_type(ET_ok)
{ {
if (top_node != (PandaNode *)NULL) { if (node != (PandaNode *)NULL) {
_head = top_node->get_generic_component(false); _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 // Function: qpNodePath::Constructor
// Access: Published // Access: Published
// Description: Constructs a NodePath with the indicated parent // Description: Constructs a NodePath with the indicated parent
// NodePath and child node; the child node must be a // NodePath and child node; the child node must be a
// stashed or unstashed child of the parent. // stashed or unstashed child of the parent.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE qpNodePath:: INLINE qpNodePath::
qpNodePath(const qpNodePath &parent, PandaNode *child) : qpNodePath(const qpNodePath &parent, PandaNode *child_node) :
_error_type(ET_fail) _error_type(ET_fail)
{ {
nassertv(!parent.is_empty()); nassertv(!parent.is_empty());
nassertv(child != (PandaNode *)NULL); nassertv(child_node != (PandaNode *)NULL);
_head = PandaNode::get_component(parent._head, child); _head = PandaNode::get_component(parent._head, child_node);
nassertv(_head != (qpNodePathComponent *)NULL); nassertv(_head != (qpNodePathComponent *)NULL);
if (_head != (qpNodePathComponent *)NULL) { if (_head != (qpNodePathComponent *)NULL) {
@ -155,7 +169,7 @@ fail() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: qpNodePath::set_max_search_depth // Function: qpNodePath::set_max_search_depth
// Access: Published, Static // 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 // find_all_matches(), require a traversal of the scene
// graph to search for the target node or nodes. This // graph to search for the target node or nodes. This
// traversal does not attempt to detect cycles, so an // traversal does not attempt to detect cycles, so an
@ -252,6 +266,13 @@ node() const {
// given key will never be reused for a different // given key will never be reused for a different
// instance (unless the app has been running long enough // instance (unless the app has been running long enough
// that we overflow the integer key value). // 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:: INLINE int qpNodePath::
get_key() const { 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 // Function: qpNodePath::get_state
// Access: Published // Access: Published
@ -1078,7 +1077,7 @@ compare_to(const qpNodePath &other) const {
other.uncollapse_head(); other.uncollapse_head();
// Nowadays, the NodePathComponents at the head are pointerwise // 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. // only have to compare pointers.
return _head - other._head; return _head - other._head;
} }

View File

@ -357,21 +357,42 @@ attach_new_node(PandaNode *node, int sort) const {
void qpNodePath:: void qpNodePath::
remove_node() { remove_node() {
nassertv(_error_type != ET_not_found); nassertv(_error_type != ET_not_found);
if (is_empty() || is_singleton()) {
// If we have no parents, remove_node() is just a do-nothing // If we have no parents, remove_node() is just a do-nothing
// operation; if we have no nodes, maybe we were already removed. // operation; if we have no nodes, maybe we were already removed.
// In either case, quietly do nothing except to ensure the // In either case, quietly do nothing except to ensure the
// qpNodePath is clear. // qpNodePath is clear.
(*this) = qpNodePath::removed(); if (!is_empty() && !is_singleton()) {
return;
}
uncollapse_head(); uncollapse_head();
PandaNode::detach(_head); PandaNode::detach(_head);
}
(*this) = qpNodePath::removed(); (*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 // Function: qpNodePath::output
// Access: Published // Access: Published

View File

@ -149,9 +149,11 @@ PUBLISHED:
INLINE qpNodePath(); INLINE qpNodePath();
INLINE qpNodePath(const string &top_node_name); INLINE qpNodePath(const string &top_node_name);
INLINE qpNodePath(PandaNode *top_node); INLINE qpNodePath(PandaNode *node);
INLINE qpNodePath(const qpNodePath &copy); INLINE static qpNodePath any_path(PandaNode *node);
INLINE qpNodePath(const qpNodePath &parent, PandaNode *child_node); INLINE qpNodePath(const qpNodePath &parent, PandaNode *child_node);
INLINE qpNodePath(const qpNodePath &copy);
INLINE void operator = (const qpNodePath &copy); INLINE void operator = (const qpNodePath &copy);
INLINE static qpNodePath not_found(); INLINE static qpNodePath not_found();
@ -202,6 +204,7 @@ PUBLISHED:
qpNodePath attach_new_node(PandaNode *node, int sort = 0) const; qpNodePath attach_new_node(PandaNode *node, int sort = 0) const;
INLINE qpNodePath attach_new_node(const string &name, int sort = 0) const; INLINE qpNodePath attach_new_node(const string &name, int sort = 0) const;
void remove_node(); void remove_node();
void detach_node();
// Handy ways to look at what's there, and other miscellaneous // Handy ways to look at what's there, and other miscellaneous
// operations. // operations.
@ -210,8 +213,6 @@ PUBLISHED:
INLINE void ls() const; INLINE void ls() const;
INLINE void ls(ostream &out, int indent_level = 0) 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. // Aggregate transform and state information.

View File

@ -135,24 +135,3 @@ get_collapsed() const {
CDReader cdata(_cycler); CDReader cdata(_cycler);
return cdata->_next; 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.
}

View File

@ -193,3 +193,30 @@ set_top_node() {
cdata->_next = (qpNodePathComponent *)NULL; 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;
}
}

View File

@ -68,7 +68,7 @@ public:
private: private:
void set_next(qpNodePathComponent *next); void set_next(qpNodePathComponent *next);
void set_top_node(); 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 // We don't have to cycle the _node and _key elements, since these
// are permanent properties of this object. (Well, the _key is // are permanent properties of this object. (Well, the _key is