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
// 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;
}

View File

@ -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

View File

@ -149,9 +149,11 @@ PUBLISHED:
INLINE qpNodePath();
INLINE qpNodePath(const string &top_node_name);
INLINE qpNodePath(PandaNode *top_node);
INLINE qpNodePath(const qpNodePath &copy);
INLINE qpNodePath(PandaNode *node);
INLINE static qpNodePath any_path(PandaNode *node);
INLINE qpNodePath(const qpNodePath &parent, PandaNode *child_node);
INLINE qpNodePath(const qpNodePath &copy);
INLINE void operator = (const qpNodePath &copy);
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.

View File

@ -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.
}

View File

@ -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;
}
}

View File

@ -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