|
|
@@ -11,9 +11,11 @@
|
|
|
#include <datagram.h>
|
|
|
#include <indent.h>
|
|
|
|
|
|
+NodeConnection Node::_empty_connection;
|
|
|
TypeHandle Node::_type_handle;
|
|
|
Node* const Node::Null = (Node*)0L;
|
|
|
|
|
|
+
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: Node::Constructor
|
|
|
// Access: Public
|
|
|
@@ -26,7 +28,11 @@ Node() {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: Node::Copy Constructor
|
|
|
// Access: Public
|
|
|
-// Description:
|
|
|
+// Description: The Node copy constructor does not copy children.
|
|
|
+// Use copy_subgraph() if you want a deep copy of the
|
|
|
+// node and all of its children. Also, you should use
|
|
|
+// make_copy() if you just want a typed copy of the Node
|
|
|
+// (without children).
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
Node::
|
|
|
Node(const Node ©) :
|
|
|
@@ -59,22 +65,23 @@ Node::
|
|
|
// We'd better not have any arcs pointing into this node, since
|
|
|
// we're destructing it now. If we do, the destructor was called in
|
|
|
// error.
|
|
|
- UpRelations::iterator uri;
|
|
|
- for (uri = _parents.begin(); uri != _parents.end(); ++uri) {
|
|
|
- nassertv((*uri).second.empty());
|
|
|
+ int i;
|
|
|
+ for (i = 0; i < max_node_graphs; i++) {
|
|
|
+ UpRelationPointers &urp = _connections[i].get_up();
|
|
|
+ nassertv(urp.empty());
|
|
|
}
|
|
|
|
|
|
- DownRelations::iterator dri;
|
|
|
- for (dri = _children.begin(); dri != _children.end(); ++dri) {
|
|
|
- DownRelationPointers &drp = (*dri).second;
|
|
|
+ // Now disconnect all the child arcs.
|
|
|
+ for (i = 0; i < max_node_graphs; i++) {
|
|
|
+ DownRelationPointers &drp = _connections[i].get_down();
|
|
|
|
|
|
DownRelationPointers::iterator drpi;
|
|
|
for (drpi = drp.begin(); drpi != drp.end(); ++drpi) {
|
|
|
- PT(NodeRelation) relation = (*drpi);
|
|
|
+ NodeRelation *arc = (*drpi);
|
|
|
|
|
|
// This deletes the arc and anything below it through the magic
|
|
|
// of reference-counting.
|
|
|
- relation->detach_below();
|
|
|
+ arc->detach_below();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -168,12 +175,8 @@ transform_changed(NodeRelation *) {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
int Node::
|
|
|
get_num_parents(TypeHandle type) const {
|
|
|
- UpRelations::const_iterator uri;
|
|
|
- uri = _parents.find(type);
|
|
|
- if (uri == _parents.end()) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- return (*uri).second.size();
|
|
|
+ const UpRelationPointers &urp = find_connection(type).get_up();
|
|
|
+ return urp.size();
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -185,12 +188,10 @@ get_num_parents(TypeHandle type) const {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
NodeRelation *Node::
|
|
|
get_parent(TypeHandle type, int index) const {
|
|
|
- UpRelations::const_iterator uri;
|
|
|
- uri = _parents.find(type);
|
|
|
- nassertr(uri != _parents.end(), (NodeRelation *)NULL);
|
|
|
- nassertr(index >= 0 && index < (int)(*uri).second.size(),
|
|
|
+ const UpRelationPointers &urp = find_connection(type).get_up();
|
|
|
+ nassertr(index >= 0 && index < (int)urp.size(),
|
|
|
(NodeRelation *)NULL);
|
|
|
- return (*uri).second[index];
|
|
|
+ return urp[index];
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -202,12 +203,8 @@ get_parent(TypeHandle type, int index) const {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
int Node::
|
|
|
get_num_children(TypeHandle type) const {
|
|
|
- DownRelations::const_iterator dri;
|
|
|
- dri = _children.find(type);
|
|
|
- if (dri == _children.end()) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- return (*dri).second.size();
|
|
|
+ const DownRelationPointers &drp = find_connection(type).get_down();
|
|
|
+ return drp.size();
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -219,12 +216,10 @@ get_num_children(TypeHandle type) const {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
NodeRelation *Node::
|
|
|
get_child(TypeHandle type, int index) const {
|
|
|
- DownRelations::const_iterator dri;
|
|
|
- dri = _children.find(type);
|
|
|
- nassertr(dri != _children.end(), (NodeRelation *)NULL);
|
|
|
- nassertr(index >= 0 && index < (int)(*dri).second.size(),
|
|
|
+ const DownRelationPointers &drp = find_connection(type).get_down();
|
|
|
+ nassertr(index >= 0 && index < (int)drp.size(),
|
|
|
(NodeRelation *)NULL);
|
|
|
- return (*dri).second[index];
|
|
|
+ return drp[index];
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -274,6 +269,49 @@ write(ostream &out, int indent_level) const {
|
|
|
}
|
|
|
|
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Node::p_find_connection
|
|
|
+// Access: Private
|
|
|
+// Description: The non-inline implementation of find_connection().
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+const NodeConnection &Node::
|
|
|
+p_find_connection(TypeHandle graph_type) const {
|
|
|
+ // _connections[0] is already tested by the inline implementation.
|
|
|
+ for (int i = 1; i < max_node_graphs; i++) {
|
|
|
+ if (_connections[i].get_graph_type() == graph_type) {
|
|
|
+ return _connections[i];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return _empty_connection;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Node::p_update_connection
|
|
|
+// Access: Private
|
|
|
+// Description: The non-inline implementation of update_connection().
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+NodeConnection *Node::
|
|
|
+p_update_connection(TypeHandle graph_type) {
|
|
|
+ // _connections[0] is already tested by the inline implementation.
|
|
|
+ int i;
|
|
|
+ for (i = 1; i < max_node_graphs; i++) {
|
|
|
+ if (_connections[i].get_graph_type() == graph_type) {
|
|
|
+ return &_connections[i];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // No such connection; can we create a new one?
|
|
|
+ for (i = 0; i < max_node_graphs; i++) {
|
|
|
+ if (_connections[i].is_empty()) {
|
|
|
+ _connections[i].set_graph_type(graph_type);
|
|
|
+ return &_connections[i];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Too bad.
|
|
|
+ return (NodeConnection *)NULL;
|
|
|
+}
|
|
|
+
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: Node::propagate_stale_bound
|
|
|
// Access: Protected, Virtual
|
|
|
@@ -284,10 +322,8 @@ write(ostream &out, int indent_level) const {
|
|
|
void Node::
|
|
|
propagate_stale_bound() {
|
|
|
// Mark all of our parent arcs, in all graphs, stale as well.
|
|
|
- UpRelations::const_iterator uri;
|
|
|
- for (uri = _parents.begin(); uri != _parents.end(); ++uri) {
|
|
|
- const UpRelationPointers &urp = (*uri).second;
|
|
|
-
|
|
|
+ for (int i = 0; i < max_node_graphs; i++) {
|
|
|
+ const UpRelationPointers &urp = _connections[i].get_up();
|
|
|
UpRelationPointers::const_iterator urpi;
|
|
|
for (urpi = urp.begin(); urpi != urp.end(); ++urpi) {
|
|
|
(*urpi)->mark_bound_stale();
|
|
|
@@ -324,10 +360,10 @@ r_copy_subgraph(TypeHandle graph_type, Node::InstanceMap &inst_map) const {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: Node::r_copy_children
|
|
|
// Access: Protected, Virtual
|
|
|
-// Description: This is called by r_deep_copy(); the copy has already
|
|
|
-// been made of this particular node (and this is the
|
|
|
-// copy); this function's job is to copy all of the
|
|
|
-// children from the original.
|
|
|
+// Description: This is called by r_copy_subgraph(); the copy has
|
|
|
+// already been made of this particular node (and this
|
|
|
+// is the copy); this function's job is to copy all of
|
|
|
+// the children from the original.
|
|
|
//
|
|
|
// Note that it includes the parameter inst_map, which
|
|
|
// is a map type, and is not (and cannot be) exported
|
|
|
@@ -339,39 +375,35 @@ r_copy_subgraph(TypeHandle graph_type, Node::InstanceMap &inst_map) const {
|
|
|
void Node::
|
|
|
r_copy_children(const Node *from, TypeHandle graph_type,
|
|
|
Node::InstanceMap &inst_map) {
|
|
|
- DownRelations::const_iterator dri;
|
|
|
- dri = from->_children.find(graph_type);
|
|
|
- if (dri != from->_children.end()) {
|
|
|
- const DownRelationPointers &drp = (*dri).second;
|
|
|
+ const DownRelationPointers &drp =
|
|
|
+ from->find_connection(graph_type).get_down();
|
|
|
+ DownRelationPointers::const_iterator drpi;
|
|
|
+ for (drpi = drp.begin(); drpi != drp.end(); ++drpi) {
|
|
|
+ NodeRelation *source_arc = (*drpi);
|
|
|
+ Node *source_child = source_arc->get_child();
|
|
|
+ nassertv(source_child != (Node *)NULL);
|
|
|
|
|
|
- DownRelationPointers::const_iterator drpi;
|
|
|
- for (drpi = drp.begin(); drpi != drp.end(); ++drpi) {
|
|
|
- NodeRelation *source_arc = (*drpi);
|
|
|
- Node *source_child = source_arc->get_child();
|
|
|
- nassertv(source_child != (Node *)NULL);
|
|
|
-
|
|
|
- Node *dest_child;
|
|
|
-
|
|
|
- // Check to see if we have already copied this child. If we
|
|
|
- // have, use the copy. In this way, a subgraph that contains
|
|
|
- // instances will be correctly duplicated into another subgraph
|
|
|
- // that also contains its own instances.
|
|
|
- InstanceMap::const_iterator ci;
|
|
|
- ci = inst_map.find(source_child);
|
|
|
- if (ci != inst_map.end()) {
|
|
|
- dest_child = (*ci).second;
|
|
|
- } else {
|
|
|
- dest_child = source_child->r_copy_subgraph(graph_type, inst_map);
|
|
|
- inst_map[source_child] = dest_child;
|
|
|
- }
|
|
|
-
|
|
|
- NodeRelation *dest_arc =
|
|
|
- NodeRelation::create_typed_arc(graph_type, this, dest_child);
|
|
|
- nassertv(dest_arc != (NodeRelation *)NULL);
|
|
|
- nassertv(dest_arc->is_exact_type(graph_type));
|
|
|
-
|
|
|
- dest_arc->copy_transitions_from(source_arc);
|
|
|
+ Node *dest_child;
|
|
|
+
|
|
|
+ // Check to see if we have already copied this child. If we
|
|
|
+ // have, use the copy. In this way, a subgraph that contains
|
|
|
+ // instances will be correctly duplicated into another subgraph
|
|
|
+ // that also contains its own instances.
|
|
|
+ InstanceMap::const_iterator ci;
|
|
|
+ ci = inst_map.find(source_child);
|
|
|
+ if (ci != inst_map.end()) {
|
|
|
+ dest_child = (*ci).second;
|
|
|
+ } else {
|
|
|
+ dest_child = source_child->r_copy_subgraph(graph_type, inst_map);
|
|
|
+ inst_map[source_child] = dest_child;
|
|
|
}
|
|
|
+
|
|
|
+ NodeRelation *dest_arc =
|
|
|
+ NodeRelation::create_typed_arc(graph_type, this, dest_child);
|
|
|
+ nassertv(dest_arc != (NodeRelation *)NULL);
|
|
|
+ nassertv(dest_arc->is_exact_type(graph_type));
|
|
|
+
|
|
|
+ dest_arc->copy_transitions_from(source_arc);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -389,18 +421,29 @@ write_datagram(BamWriter *manager, Datagram &me) {
|
|
|
// write out all of the UpRelations then writing any node in a graph
|
|
|
// would cause the entire graph to be written out.
|
|
|
|
|
|
- me.add_uint16(_children.size());
|
|
|
+ // First, count up the number of NodeConnections that are nonempty.
|
|
|
+ int num_connections = 0;
|
|
|
+ int i;
|
|
|
+ for (i = 0; i < max_node_graphs; i++) {
|
|
|
+ if (!_connections[i].is_empty()) {
|
|
|
+ num_connections++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ me.add_uint16(num_connections);
|
|
|
|
|
|
- DownRelations::iterator dri;
|
|
|
- for (dri = _children.begin(); dri != _children.end(); ++dri) {
|
|
|
- manager->write_handle(me, (*dri).first);
|
|
|
+ // Now write them out.
|
|
|
+ for (i = 0; i < max_node_graphs; i++) {
|
|
|
+ if (!_connections[i].is_empty()) {
|
|
|
+ manager->write_handle(me, _connections[i].get_graph_type());
|
|
|
|
|
|
- DownRelationPointers &drp = (*dri).second;
|
|
|
- me.add_uint16(drp.size());
|
|
|
- DownRelationPointers::iterator drpi;
|
|
|
- for (drpi = drp.begin(); drpi != drp.end(); ++drpi) {
|
|
|
- NodeRelation *relation = (*drpi);
|
|
|
- manager->write_pointer(me, relation);
|
|
|
+ const DownRelationPointers &drp = _connections[i].get_down();
|
|
|
+ me.add_uint16(drp.size());
|
|
|
+ DownRelationPointers::const_iterator drpi;
|
|
|
+ for (drpi = drp.begin(); drpi != drp.end(); ++drpi) {
|
|
|
+ NodeRelation *relation = (*drpi);
|
|
|
+ manager->write_pointer(me, relation);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -420,28 +463,37 @@ complete_pointers(vector_typedWriteable &plist, BamReader *manager) {
|
|
|
// the arcs are completely responsible for adding themselves to
|
|
|
// our list); we only need to return the number of pointers we
|
|
|
// expected to receive.
|
|
|
- return _num_pointers;
|
|
|
+
|
|
|
+ // As of 5/7/01, we no longer store this number, as a memory
|
|
|
+ // optimization. This means bams before 3.3 cannot be reliably
|
|
|
+ // loaded.
|
|
|
+
|
|
|
+ graph_cat.warning()
|
|
|
+ << "Unable to reliably load bam version "
|
|
|
+ << manager->get_file_major_ver() << "."
|
|
|
+ << manager->get_file_minor_ver() << "\n";
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
// Beginning at bam version 3.3, we are responsible for adding our
|
|
|
// child arcs directly.
|
|
|
|
|
|
- int i = 0;
|
|
|
+ int count = 0;
|
|
|
|
|
|
- DownRelations::iterator dri;
|
|
|
- for (dri = _children.begin(); dri != _children.end(); ++dri) {
|
|
|
- DownRelationPointers &drp = (*dri).second;
|
|
|
+ for (int i = 0; i < max_node_graphs; i++) {
|
|
|
+ if (!_connections[i].is_empty()) {
|
|
|
+ DownRelationPointers &drp = _connections[i].get_down();
|
|
|
|
|
|
- DownRelationPointers::iterator drpi;
|
|
|
- for (drpi = drp.begin(); drpi != drp.end(); ++drpi) {
|
|
|
- nassertr(i < _num_pointers, _num_pointers);
|
|
|
- (*drpi) = DCAST(NodeRelation, plist[i]);
|
|
|
- i++;
|
|
|
+ DownRelationPointers::iterator drpi;
|
|
|
+ for (drpi = drp.begin(); drpi != drp.end(); ++drpi) {
|
|
|
+ (*drpi) = DCAST(NodeRelation, plist[count]);
|
|
|
+ count++;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- nassertr(i == _num_pointers, _num_pointers);
|
|
|
- return _num_pointers;
|
|
|
+ return count;
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -450,8 +502,7 @@ complete_pointers(vector_typedWriteable &plist, BamReader *manager) {
|
|
|
// Description: Factory method to generate a node object
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
TypedWriteable* Node::
|
|
|
-make_Node(const FactoryParams ¶ms)
|
|
|
-{
|
|
|
+make_Node(const FactoryParams ¶ms) {
|
|
|
Node *me = new Node;
|
|
|
BamReader *manager;
|
|
|
Datagram packet;
|
|
|
@@ -477,14 +528,12 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|
|
// In bam versions before 3.3, we only need to count up the total
|
|
|
// number of arcs across all types, because we don't add the arc
|
|
|
// pointers explicitly here.
|
|
|
- _num_pointers = 0;
|
|
|
int num_types = scan.get_uint16();
|
|
|
|
|
|
while (num_types > 0) {
|
|
|
int num_arcs = scan.get_uint16();
|
|
|
while (num_arcs > 0) {
|
|
|
manager->read_pointer(scan, this);
|
|
|
- _num_pointers++;
|
|
|
num_arcs--;
|
|
|
}
|
|
|
num_types--;
|
|
|
@@ -494,24 +543,38 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|
|
// Beginning at bam version 3.3, we do all the reading of our
|
|
|
// children arcs of all types, which means we need to record the
|
|
|
// numbers of each type of children. We do this by recording a
|
|
|
- // series of NULL pointers, rather than depending on
|
|
|
- // _num_pointers.
|
|
|
-
|
|
|
- _num_pointers = 0;
|
|
|
- int num_types = scan.get_uint16();
|
|
|
-
|
|
|
- while (num_types > 0) {
|
|
|
+ // series of NULL pointers in our NodeConnections.
|
|
|
+
|
|
|
+ int num_connections = scan.get_uint16();
|
|
|
+ if (num_connections > max_node_graphs) {
|
|
|
+ // Oops, too many graph types in this bam file. We'll have to
|
|
|
+ // discard some.
|
|
|
+ graph_cat.error()
|
|
|
+ << "Bam file specifies " << num_connections << " graph types for "
|
|
|
+ << *this << "; this version of Panda can only support "
|
|
|
+ << max_node_graphs << " simultaneous graph types.\n";
|
|
|
+ }
|
|
|
+ for (int i = 0; i < num_connections; i++) {
|
|
|
TypeHandle type = manager->read_handle(scan);
|
|
|
+
|
|
|
+ if (i < max_node_graphs) {
|
|
|
+ _connections[i].set_graph_type(type);
|
|
|
|
|
|
- DownRelationPointers &drp = _children[type];
|
|
|
- int num_arcs = scan.get_uint16();
|
|
|
- while (num_arcs > 0) {
|
|
|
- manager->read_pointer(scan, this);
|
|
|
- drp.push_back((NodeRelation *)NULL);
|
|
|
- _num_pointers++;
|
|
|
- num_arcs--;
|
|
|
+ DownRelationPointers &drp = _connections[i].get_down();
|
|
|
+ int num_arcs = scan.get_uint16();
|
|
|
+ while (num_arcs > 0) {
|
|
|
+ manager->read_pointer(scan, this);
|
|
|
+ drp.push_back((NodeRelation *)NULL);
|
|
|
+ num_arcs--;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // Read and discard.
|
|
|
+ int num_arcs = scan.get_uint16();
|
|
|
+ while (num_arcs > 0) {
|
|
|
+ manager->skip_pointer(scan);
|
|
|
+ num_arcs--;
|
|
|
+ }
|
|
|
}
|
|
|
- num_types--;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -522,8 +585,7 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|
|
// Description: Factory method to generate a node object
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void Node::
|
|
|
-register_with_read_factory(void)
|
|
|
-{
|
|
|
+register_with_read_factory(void) {
|
|
|
BamReader::get_factory()->register_factory(get_class_type(), make_Node);
|
|
|
}
|
|
|
|
|
|
@@ -540,16 +602,12 @@ find_arc(Node *parent, Node *child, TypeHandle graph_type) {
|
|
|
// the parent arc, on the assumption there are likely to be fewer
|
|
|
// parents than children.
|
|
|
|
|
|
- UpRelations::const_iterator uri = child->_parents.find(graph_type);
|
|
|
-
|
|
|
- if (uri != child->_parents.end()) {
|
|
|
- const UpRelationPointers &urp = (*uri).second;
|
|
|
- UpRelationPointers::const_iterator urpi;
|
|
|
- for (urpi = urp.begin(); urpi != urp.end(); ++urpi) {
|
|
|
- if ((*urpi)->get_parent() == parent &&
|
|
|
- (*urpi)->get_child() == child) {
|
|
|
- return (*urpi);
|
|
|
- }
|
|
|
+ const UpRelationPointers &urp = child->find_connection(graph_type).get_up();
|
|
|
+ UpRelationPointers::const_iterator urpi;
|
|
|
+ for (urpi = urp.begin(); urpi != urp.end(); ++urpi) {
|
|
|
+ NodeRelation *arc = (*urpi);
|
|
|
+ if (arc->get_parent() == parent && arc->get_child() == child) {
|
|
|
+ return arc;
|
|
|
}
|
|
|
}
|
|
|
|