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