Panda3D
|
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 }