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

panda/src/dgraph/dataNode.cxx

Go to the documentation of this file.
00001 // Filename: dataNode.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 "dataNode.h"
00020 #include "dataNodeTransmit.h"
00021 #include "config_dgraph.h"
00022 #include "dcast.h"
00023 
00024 TypeHandle DataNode::_type_handle;
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //     Function: DataNode::make_copy
00028 //       Access: Public, Virtual
00029 //  Description: Returns a newly-allocated Node that is a shallow copy
00030 //               of this one.  It will be a different Node pointer,
00031 //               but its internal data may or may not be shared with
00032 //               that of the original Node.
00033 ////////////////////////////////////////////////////////////////////
00034 PandaNode *DataNode::
00035 make_copy() const {
00036   return new DataNode(*this);
00037 }
00038 
00039 ////////////////////////////////////////////////////////////////////
00040 //     Function: DataNode::transmit_data
00041 //       Access: Public
00042 //  Description: Collects the data from all of the parent nodes and
00043 //               puts it into one DataNodeTransmit object, for
00044 //               processing; calls do_transmit_data() to read all the
00045 //               inputs and put the result into the indicated output.
00046 ////////////////////////////////////////////////////////////////////
00047 void DataNode::
00048 transmit_data(const DataNodeTransmit inputs[],
00049               DataNodeTransmit &output) {
00050   DataNodeTransmit new_input;
00051   new_input.reserve(get_num_inputs());
00052 
00053   DataConnections::const_iterator ci;
00054   for (ci = _data_connections.begin(); ci != _data_connections.end(); ++ci) {
00055     const DataConnection &connect = (*ci);
00056     const EventParameter &data = 
00057       inputs[connect._parent_index].get_data(connect._output_index);
00058     new_input.set_data(connect._input_index, data);
00059   }
00060 
00061 #ifndef NDEBUG
00062   if (dgraph_cat.is_spam()) {
00063     bool any_data = false;
00064     Wires::const_iterator wi;
00065     for (wi = _input_wires.begin(); wi != _input_wires.end(); ++wi) {
00066       const string &name = (*wi).first;
00067       const WireDef &def = (*wi).second;
00068       if (new_input.has_data(def._index)) {
00069         if (!any_data) {
00070           dgraph_cat.spam()
00071             << *this << " receives:\n";
00072           any_data = true;
00073         }
00074         dgraph_cat.spam(false) 
00075           << "  " << name << " = " << new_input.get_data(def._index)
00076           << "\n";
00077       }
00078     }
00079   }
00080 #endif  // NDEBUG
00081 
00082   do_transmit_data(new_input, output);
00083 
00084 #ifndef NDEBUG
00085   if (dgraph_cat.is_spam()) {
00086     bool any_data = false;
00087     Wires::const_iterator wi;
00088     for (wi = _output_wires.begin(); wi != _output_wires.end(); ++wi) {
00089       const string &name = (*wi).first;
00090       const WireDef &def = (*wi).second;
00091       if (output.has_data(def._index)) {
00092         if (!any_data) {
00093           dgraph_cat.spam()
00094             << *this << " transmits:\n";
00095           any_data = true;
00096         }
00097         dgraph_cat.spam(false) 
00098           << "  " << name << " = " << output.get_data(def._index)
00099           << "\n";
00100       }
00101     }
00102   }
00103 #endif  // NDEBUG
00104 }
00105 
00106 ////////////////////////////////////////////////////////////////////
00107 //     Function: DataNode::write_inputs
00108 //       Access: Published
00109 //  Description: Writes to the indicated ostream a list of all the
00110 //               inputs this DataNode might expect to receive.
00111 ////////////////////////////////////////////////////////////////////
00112 void DataNode::
00113 write_inputs(ostream &out) const {
00114   Wires::const_iterator wi;
00115   for (wi = _input_wires.begin(); wi != _input_wires.end(); ++wi) {
00116     const string &name = (*wi).first;
00117     const WireDef &def = (*wi).second;
00118     out << name << " " << def._data_type << "\n";
00119   }
00120 }
00121 
00122 ////////////////////////////////////////////////////////////////////
00123 //     Function: DataNode::write_outputs
00124 //       Access: Published
00125 //  Description: Writes to the indicated ostream a list of all the
00126 //               outputs this DataNode might generate.
00127 ////////////////////////////////////////////////////////////////////
00128 void DataNode::
00129 write_outputs(ostream &out) const {
00130   Wires::const_iterator wi;
00131   for (wi = _output_wires.begin(); wi != _output_wires.end(); ++wi) {
00132     const string &name = (*wi).first;
00133     const WireDef &def = (*wi).second;
00134     out << name << " " << def._data_type << "\n";
00135   }
00136 }
00137 
00138 ////////////////////////////////////////////////////////////////////
00139 //     Function: DataNode::write_connections
00140 //       Access: Published
00141 //  Description: Writes to the indicated ostream a list of all the
00142 //               connections currently showing between this DataNode
00143 //               and its parent(s).
00144 ////////////////////////////////////////////////////////////////////
00145 void DataNode::
00146 write_connections(ostream &out) const {
00147   DataConnections::const_iterator ci;
00148   for (ci = _data_connections.begin(); ci != _data_connections.end(); ++ci) {
00149     const DataConnection &connect = (*ci);
00150     nassertv(connect._parent_index >= 0 && connect._parent_index < get_num_parents());
00151 
00152     // Now we have to search exhaustively for the input with the
00153     // matching index number.
00154     Wires::const_iterator wi;
00155     bool found = false;
00156     for (wi = _input_wires.begin(); wi != _input_wires.end() && !found; ++wi) {
00157       const string &name = (*wi).first;
00158       const WireDef &def = (*wi).second;
00159       if (def._index == connect._input_index) {
00160         out << name << " " << def._data_type << " from " 
00161             << *get_parent(connect._parent_index) << "\n";
00162         found = true;
00163       }
00164     }
00165     nassertv(found);
00166   }
00167 }
00168 
00169 ////////////////////////////////////////////////////////////////////
00170 //     Function: DataNode::define_input
00171 //       Access: Protected
00172 //  Description: Adds a new input wire with the given name and the
00173 //               indicated data type.  The data type should be the
00174 //               TypeHandle for some type that derives from
00175 //               TypedReferenceCount, e.g. EventStoreInt,
00176 //               EventStoreDouble, or some fancier data type like
00177 //               Texture.
00178 //
00179 //               If there is already an input wire defined with the
00180 //               indicated name, its type is changed.
00181 //
00182 //               The return value is the index into the "input"
00183 //               parameter to do_transmit_data() that can be used to
00184 //               access the input data.
00185 ////////////////////////////////////////////////////////////////////
00186 int DataNode::
00187 define_input(const string &name, TypeHandle data_type) {
00188   // We shouldn't already be connected.
00189   nassertr(_data_connections.empty(), 0);
00190 
00191   Wires::iterator wi;
00192   wi = _input_wires.find(name);
00193   if (wi != _input_wires.end()) {
00194     // This wire already existed; modify it and return the original
00195     // index.
00196     WireDef &def = (*wi).second;
00197     def._data_type = data_type;
00198     return def._index;
00199   }
00200 
00201   // This wire did not already exist; add it.
00202   WireDef &def = _input_wires[name];
00203   def._data_type = data_type;
00204   def._index = _input_wires.size() - 1;
00205   return def._index;
00206 }
00207 
00208 ////////////////////////////////////////////////////////////////////
00209 //     Function: DataNode::define_output
00210 //       Access: Protected
00211 //  Description: Adds a new output wire with the given name and the
00212 //               indicated data type.  The data type should be the
00213 //               TypeHandle for some type that derives from
00214 //               TypedReferenceCount, e.g. EventStoreInt,
00215 //               EventStoreDouble, or some fancier data type like
00216 //               Texture.
00217 //
00218 //               If there is already an output wire defined with the
00219 //               indicated name, its type is changed.
00220 //
00221 //               The return value is the index into the "output"
00222 //               parameter to do_transmit_data() where the output data
00223 //               should be stored.
00224 ////////////////////////////////////////////////////////////////////
00225 int DataNode::
00226 define_output(const string &name, TypeHandle data_type) {
00227   // We shouldn't already be connected.
00228   nassertr(_data_connections.empty(), 0);
00229 
00230   Wires::iterator wi;
00231   wi = _output_wires.find(name);
00232   if (wi != _output_wires.end()) {
00233     // This wire already existed; modify it and return the original
00234     // index.
00235     WireDef &def = (*wi).second;
00236     def._data_type = data_type;
00237     return def._index;
00238   }
00239 
00240   // This wire did not already exist; add it.
00241   WireDef &def = _output_wires[name];
00242   def._data_type = data_type;
00243   def._index = _output_wires.size() - 1;
00244   return def._index;
00245 }
00246 
00247 ////////////////////////////////////////////////////////////////////
00248 //     Function: DataNode::parents_changed
00249 //       Access: Protected, Virtual
00250 //  Description: Called after a scene graph update that either adds or
00251 //               remove parents from this node, this just provides a
00252 //               hook for derived PandaNode objects that need to
00253 //               update themselves based on the set of parents the
00254 //               node has.
00255 ////////////////////////////////////////////////////////////////////
00256 void DataNode::
00257 parents_changed() {
00258   reconnect();
00259 }
00260 
00261 ////////////////////////////////////////////////////////////////////
00262 //     Function: DataNode::do_transmit_data
00263 //       Access: Protected, Virtual
00264 //  Description: The virtual implementation of transmit_data().  This
00265 //               function receives an array of input parameters and
00266 //               should generate an array of output parameters.  The
00267 //               input parameters may be accessed with the index
00268 //               numbers returned by the define_input() calls that
00269 //               were made earlier (presumably in the constructor);
00270 //               likewise, the output parameters should be set with
00271 //               the index numbers returned by the define_output()
00272 //               calls.
00273 ////////////////////////////////////////////////////////////////////
00274 void DataNode::
00275 do_transmit_data(const DataNodeTransmit &, DataNodeTransmit &) {
00276 }
00277 
00278 ////////////////////////////////////////////////////////////////////
00279 //     Function: DataNode::reconnect
00280 //       Access: Private
00281 //  Description: Establishes the input(s) that this DataNode has in
00282 //               common with its parents' output(s).  Builds up the
00283 //               _data_connections list correspondingly.
00284 ////////////////////////////////////////////////////////////////////
00285 void DataNode::
00286 reconnect() {
00287   int num_parents = get_num_parents();
00288   _data_connections.clear();
00289   // Look for each input among one of the parents.
00290   int num_datanode_parents = 0;
00291 
00292   Wires::const_iterator wi;
00293   for (wi = _input_wires.begin(); wi != _input_wires.end(); ++wi) {
00294     const string &name = (*wi).first;
00295     const WireDef &input_def = (*wi).second;
00296 
00297     int num_found = 0;
00298     for (int i = 0; i < num_parents; i++) {
00299       PandaNode *parent_node = get_parent(i);
00300       if (parent_node->is_of_type(DataNode::get_class_type())) {
00301         DataNode *data_node = DCAST(DataNode, parent_node);
00302         num_datanode_parents++;
00303         Wires::const_iterator pi;
00304         pi = data_node->_output_wires.find(name);
00305         if (pi != data_node->_output_wires.end()) {
00306           const WireDef &output_def = (*pi).second;
00307           num_found++;
00308           if (output_def._data_type != input_def._data_type) {
00309             dgraph_cat.warning()
00310               << "Ignoring mismatched type for connection " << name 
00311               << " between " << *data_node << " and " << *this << "\n";
00312           } else if (num_found == 1) {
00313             DataConnection dc;
00314             dc._parent_index = i;
00315             dc._output_index = output_def._index;
00316             dc._input_index = input_def._index;
00317             _data_connections.push_back(dc);
00318           }
00319         }
00320       }
00321     }
00322 
00323     if (num_found > 1) {
00324       dgraph_cat.warning()
00325         << "Multiple connections found for " << name << " into " << *this
00326         << "\n";
00327     }
00328   }
00329             
00330   if (_data_connections.empty() && get_num_inputs() != 0 && 
00331       num_datanode_parents != 0) {
00332     dgraph_cat.warning()
00333       << "No data connected to " << *this << "\n";
00334   }
00335 }

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