215 lines
6.7 KiB
C++
215 lines
6.7 KiB
C++
// Filename: arcChain.cxx
|
|
// Created by: drose (05Jan01)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
|
//
|
|
// All use of this software is subject to the terms of the Panda 3d
|
|
// Software license. You should have received a copy of this license
|
|
// along with this source code; you will also find a current copy of
|
|
// the license at http://www.panda3d.org/license.txt .
|
|
//
|
|
// To contact the maintainers of this program write to
|
|
// panda3d@yahoogroups.com .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "arcChain.h"
|
|
#include "node.h"
|
|
#include "namedNode.h"
|
|
|
|
TypeHandle ArcChain::_type_handle;
|
|
TypeHandle ArcChain::ArcComponent::_type_handle;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ArcChain::ArcComponent::Copy Assignment Operator
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void ArcChain::ArcComponent::
|
|
operator = (const ArcComponent ©) {
|
|
// We have to be careful with the reference counts here,
|
|
// particularly since we might be changing the pointer type from arc
|
|
// pointer to node pointer, or vice-versa, with this assignment.
|
|
|
|
// First, ref the new pointer once, so we don't accidentally delete
|
|
// in the interim.
|
|
if (copy.has_arc()) {
|
|
copy._p._arc->ref();
|
|
copy._p._arc->ref_parent();
|
|
} else {
|
|
copy._p._node->ref();
|
|
}
|
|
|
|
// Now unref the old pointer.
|
|
if (has_arc()) {
|
|
_p._arc->unref_parent();
|
|
unref_delete(_p._arc);
|
|
} else {
|
|
unref_delete(_p._node);
|
|
}
|
|
|
|
// Now reassign the pointers.
|
|
_next = copy._next;
|
|
if (has_arc()) {
|
|
_p._arc = copy._p._arc;
|
|
} else {
|
|
_p._node = copy._p._node;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ArcChain::get_num_nodes
|
|
// Access: Public
|
|
// Description: Returns the number of nodes in the path. This is
|
|
// always one more than the number of arcs (except for
|
|
// a completely empty path).
|
|
////////////////////////////////////////////////////////////////////
|
|
int ArcChain::
|
|
get_num_nodes() const {
|
|
int num = 0;
|
|
ArcComponent *comp = _head;
|
|
while (comp != (ArcComponent *)NULL) {
|
|
num++;
|
|
comp = comp->get_next();
|
|
}
|
|
return num;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ArcChain::get_node
|
|
// Access: Public
|
|
// Description: Returns the nth node of the path, where 0 is the
|
|
// bottom node and get_num_nodes() - 1 is the top node.
|
|
// This requires iterating through the path.
|
|
////////////////////////////////////////////////////////////////////
|
|
Node *ArcChain::
|
|
get_node(int index) const {
|
|
nassertr(index >= 0 && index < get_num_nodes(), NULL);
|
|
|
|
ArcComponent *comp = _head;
|
|
while (index > 0) {
|
|
// If this assertion fails, the index was out of range.
|
|
nassertr(comp != (ArcComponent *)NULL, NULL);
|
|
comp = comp->get_next();
|
|
index--;
|
|
}
|
|
|
|
// If this assertion fails, the index was out of range.
|
|
nassertr(comp != (ArcComponent *)NULL, NULL);
|
|
return comp->get_node();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ArcChain::get_arc
|
|
// Access: Public
|
|
// Description: Returns the nth arc of the path, where 0 is the arc
|
|
// above the bottom node node and get_num_arcs() - 1 is
|
|
// the arc below the top node. This requires iterating
|
|
// through the path.
|
|
////////////////////////////////////////////////////////////////////
|
|
NodeRelation *ArcChain::
|
|
get_arc(int index) const {
|
|
nassertr(index >= 0 && index < get_num_arcs(), NULL);
|
|
|
|
ArcComponent *comp = _head;
|
|
while (index > 0) {
|
|
// If this assertion fails, the index was out of range.
|
|
nassertr(comp != (ArcComponent *)NULL, NULL);
|
|
comp = comp->get_next();
|
|
index--;
|
|
}
|
|
|
|
// If either assertion fails, the index was out of range.
|
|
nassertr(comp != (ArcComponent *)NULL, NULL);
|
|
nassertr(comp->has_arc(), NULL);
|
|
return comp->get_arc();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ArcChain::get_top_node
|
|
// Access: Public
|
|
// Description: Returns the top node of the path, or NULL if the path
|
|
// is empty. This requires iterating through the path.
|
|
////////////////////////////////////////////////////////////////////
|
|
Node *ArcChain::
|
|
get_top_node() const {
|
|
if (is_empty()) {
|
|
return (Node *)NULL;
|
|
}
|
|
|
|
ArcComponent *comp = _head;
|
|
while (!comp->is_top_node()) {
|
|
comp = comp->get_next();
|
|
nassertr(comp != (ArcComponent *)NULL, NULL);
|
|
}
|
|
|
|
return comp->get_node();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ArcChain::r_output
|
|
// Access: Private
|
|
// Description: The recursive implementation of output(), this writes
|
|
// the names of each arc component in order from
|
|
// beginning to end, by first walking to the end of the
|
|
// linked list and then outputting from there.
|
|
////////////////////////////////////////////////////////////////////
|
|
void ArcChain::
|
|
r_output(ostream &out, ArcComponent *comp) const {
|
|
ArcComponent *next = comp->get_next();
|
|
if (next != (ArcComponent *)NULL) {
|
|
// This is not the head of the list; keep going up.
|
|
r_output(out, next);
|
|
out << "/";
|
|
}
|
|
|
|
// Now output this component.
|
|
Node *node = comp->get_node();
|
|
if (node->is_of_type(NamedNode::get_class_type())) {
|
|
NamedNode *named_node = DCAST(NamedNode, node);
|
|
if (named_node->has_name()) {
|
|
out << named_node->get_name();
|
|
} else {
|
|
out << node->get_type();
|
|
}
|
|
} else {
|
|
out << node->get_type();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ArcChain::r_compare_to
|
|
// Access: Private, Static
|
|
// Description: The recursive implementation of compare_to(). Returns
|
|
// < 0 if a sorts before b, > 0 if b sorts before a, or
|
|
// == 0 if they are equivalent.
|
|
////////////////////////////////////////////////////////////////////
|
|
int ArcChain::
|
|
r_compare_to(const ArcComponent *a, const ArcComponent *b) {
|
|
if (a == b) {
|
|
return 0;
|
|
|
|
} else if (a == (const ArcComponent *)NULL) {
|
|
return -1;
|
|
|
|
} else if (b == (const ArcComponent *)NULL) {
|
|
return 1;
|
|
|
|
} else if (a->has_arc() != b->has_arc()) {
|
|
return a->has_arc() - b->has_arc();
|
|
|
|
} else if (a->has_arc() && (a->get_arc() != b->get_arc())) {
|
|
return a->get_arc() - b->get_arc();
|
|
|
|
} else if (!a->has_arc() && (a->get_node() != b->get_node())) {
|
|
return a->get_node() - b->get_node();
|
|
|
|
} else {
|
|
return r_compare_to(a->get_next(), b->get_next());
|
|
}
|
|
}
|
|
|