Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/dgraph/dataGraphTraverser.cxx

Go to the documentation of this file.
00001 // Filename: dataGraphTraverser.cxx
00002 // Created by:  drose (11Mar02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "dataGraphTraverser.h"
00020 #include "dataNode.h"
00021 #include "config_dgraph.h"
00022 #include "dcast.h"
00023 
00024 
00025 ////////////////////////////////////////////////////////////////////
00026 //     Function: DataGraphTraverser::CollectedData::set_data
00027 //       Access: Public
00028 //  Description: Sets the data associated with the indicated parent of
00029 //               this CollectedData object's node.
00030 ////////////////////////////////////////////////////////////////////
00031 void DataGraphTraverser::CollectedData::
00032 set_data(int parent_index, const DataNodeTransmit &data) {
00033   if ((int)_data.size() <= parent_index) {
00034     _data.reserve(parent_index + 1);
00035     while ((int)_data.size() <= parent_index) {
00036       _data.push_back(DataNodeTransmit());
00037     }
00038   }
00039 
00040   nassertv(parent_index >= 0 && parent_index < (int)_data.size());
00041   _data[parent_index] = data;
00042 }
00043 
00044 ////////////////////////////////////////////////////////////////////
00045 //     Function: DataGraphTraverser::Constructor
00046 //       Access: Public
00047 //  Description: 
00048 ////////////////////////////////////////////////////////////////////
00049 DataGraphTraverser::
00050 DataGraphTraverser() {
00051 }
00052 
00053 ////////////////////////////////////////////////////////////////////
00054 //     Function: DataGraphTraverser::Destructor
00055 //       Access: Public
00056 //  Description: 
00057 ////////////////////////////////////////////////////////////////////
00058 DataGraphTraverser::
00059 ~DataGraphTraverser() {
00060 }
00061 
00062 ////////////////////////////////////////////////////////////////////
00063 //     Function: DataGraphTraverser::traverse
00064 //       Access: Public
00065 //  Description: Starts the traversal of the data graph at the
00066 //               indicated root node.
00067 ////////////////////////////////////////////////////////////////////
00068 void DataGraphTraverser::
00069 traverse(PandaNode *node) {
00070   if (node->is_of_type(DataNode::get_class_type())) {
00071     DataNode *data_node = DCAST(DataNode, node);
00072     int num_parents = data_node->get_num_parents();
00073     // We must start the traversal at the root of the graph.
00074     nassertv(num_parents == 0);
00075 
00076     r_transmit(data_node, (DataNodeTransmit *)NULL);
00077 
00078   } else {
00079     traverse_below(node, DataNodeTransmit());
00080   }
00081 
00082   collect_leftovers();
00083 }
00084 
00085 ////////////////////////////////////////////////////////////////////
00086 //     Function: DataGraphTraverser::traverse_below
00087 //       Access: Public
00088 //  Description: Continues the traversal to all the children of the
00089 //               indicated node, passing in the given data, without
00090 //               actually calling transmit_data() on the given node.
00091 ////////////////////////////////////////////////////////////////////
00092 void DataGraphTraverser::
00093 traverse_below(PandaNode *node, const DataNodeTransmit &output) {
00094   PandaNode::Children cr = node->get_children();
00095   int num_children = cr.get_num_children();
00096 
00097   for (int i = 0; i < num_children; i++) {
00098     PandaNode *child_node = cr.get_child(i);
00099     if (child_node->is_of_type(DataNode::get_class_type())) {
00100       DataNode *data_node = DCAST(DataNode, child_node);
00101       // If it's a DataNode-type child, we need to pass it the data.
00102       // Maybe it has only one parent, and can accept the data
00103       // immediately.
00104       int num_parents = data_node->get_num_parents();
00105       if (num_parents == 1) {
00106         // The easy, common case: only one parent.  We make our output
00107         // into a one-element array of inputs by turning it into a
00108         // pointer.
00109         r_transmit(data_node, &output);
00110       } else {
00111         // A more difficult case: multiple parents.  We must collect
00112         // instances together, meaning we must hold onto this node
00113         // until we have reached it through all paths.
00114         CollectedData &collected_data = _multipass_data[data_node];
00115         int parent_index = data_node->find_parent(node);
00116         nassertv(parent_index != -1);
00117 
00118         collected_data.set_data(parent_index, output);
00119         collected_data._num_parents++;
00120         nassertv(collected_data._num_parents <= num_parents);
00121         if (collected_data._num_parents == num_parents) {
00122           // Now we've got all the data; go into the child.
00123           r_transmit(data_node, &collected_data._data[0]);
00124           _multipass_data.erase(data_node);
00125         }
00126       }
00127     } else {
00128       // The child node is not a DataNode-type child.  We continue the
00129       // traversal, but data does not pass through this node, and
00130       // instances are not collected together.  (Although we appear to
00131       // be passing the data through here, it doesn't do any good
00132       // anyway, since the child nodes of this node will not know how
00133       // to interpret the data from a non-DataNode parent.)
00134       traverse_below(child_node, output);
00135     }
00136   }
00137 }
00138 
00139 ////////////////////////////////////////////////////////////////////
00140 //     Function: DataGraphTraverser::collect_leftovers
00141 //       Access: Public
00142 //  Description: Pick up any nodes that didn't get completely
00143 //               traversed.  These must be nodes that have multiple
00144 //               parents, with at least one parent completely outside
00145 //               of the data graph.
00146 ////////////////////////////////////////////////////////////////////
00147 void DataGraphTraverser::
00148 collect_leftovers() {
00149   while (!_multipass_data.empty()) {
00150     MultipassData::iterator mi = _multipass_data.begin();
00151     DataNode *data_node = (*mi).first;
00152     const CollectedData &collected_data = (*mi).second;
00153 
00154     dgraph_cat.warning()
00155       << *data_node << " improperly parented partly outside of data graph.\n";
00156 
00157     r_transmit(data_node, &collected_data._data[0]);
00158     _multipass_data.erase(mi);
00159   }  
00160 }
00161 
00162 ////////////////////////////////////////////////////////////////////
00163 //     Function: DataGraphTraverser::r_transmit
00164 //       Access: Private
00165 //  Description: Part of the recursive implementation of traverse().
00166 //               This transmits the given data into the indicated
00167 //               DataNode, and then sends the output data to each of
00168 //               the node's children.
00169 ////////////////////////////////////////////////////////////////////
00170 void DataGraphTraverser::
00171 r_transmit(DataNode *data_node, const DataNodeTransmit inputs[]) {
00172   DataNodeTransmit output;
00173   output.reserve(data_node->get_num_outputs());
00174   data_node->transmit_data(inputs, output);
00175 
00176   traverse_below(data_node, output);
00177 }

Generated on Fri May 2 00:36:19 2003 for Panda by doxygen1.3