Panda3D

dataNode.cxx
Go to the documentation of this file.
1 /**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file dataNode.cxx
10 * @author drose
11 * @date 2002-03-11
12 */
13
14 #include "dataNode.h"
15 #include "dataNodeTransmit.h"
16 #include "config_dgraph.h"
17 #include "dcast.h"
18
19 using std::string;
20
21 TypeHandle DataNode::_type_handle;
22
23 /**
24 * Returns a newly-allocated Node that is a shallow copy of this one. It will
25 * be a different Node pointer, but its internal data may or may not be shared
26 * with that of the original Node.
27 */
28 PandaNode *DataNode::
29 make_copy() const {
30 return new DataNode(*this);
31 }
32
33 /**
34 * Collects the data from all of the parent nodes and puts it into one
35 * DataNodeTransmit object, for processing; calls do_transmit_data() to read
36 * all the inputs and put the result into the indicated output.
37 */
38 void DataNode::
39 transmit_data(DataGraphTraverser *trav,
40 const DataNodeTransmit inputs[],
41 DataNodeTransmit &output) {
42 DataNodeTransmit new_input;
43 new_input.reserve(get_num_inputs());
44
45 DataConnections::const_iterator ci;
46 for (ci = _data_connections.begin(); ci != _data_connections.end(); ++ci) {
47 const DataConnection &connect = (*ci);
48 const EventParameter &data =
49 inputs[connect._parent_index].get_data(connect._output_index);
50 if (!data.is_empty()) {
51 new_input.set_data(connect._input_index, data);
52 }
53 }
54
55 #ifndef NDEBUG
56 if (dgraph_cat.is_spam()) {
57 bool any_data = false;
58 Wires::const_iterator wi;
59 for (wi = _input_wires.begin(); wi != _input_wires.end(); ++wi) {
60 const string &name = (*wi).first;
61 const WireDef &def = (*wi).second;
62 if (new_input.has_data(def._index)) {
63 if (!any_data) {
64 dgraph_cat.spam()
65 << *this << " receives:\n";
66 any_data = true;
67 }
68 dgraph_cat.spam(false)
69 << " " << name << " = " << new_input.get_data(def._index)
70 << "\n";
71 }
72 }
73 }
74 #endif // NDEBUG
75
76 do_transmit_data(trav, new_input, output);
77
78 #ifndef NDEBUG
79 if (dgraph_cat.is_spam()) {
80 bool any_data = false;
81 Wires::const_iterator wi;
82 for (wi = _output_wires.begin(); wi != _output_wires.end(); ++wi) {
83 const string &name = (*wi).first;
84 const WireDef &def = (*wi).second;
85 if (output.has_data(def._index)) {
86 if (!any_data) {
87 dgraph_cat.spam()
88 << *this << " transmits:\n";
89 any_data = true;
90 }
91 dgraph_cat.spam(false)
92 << " " << name << " = " << output.get_data(def._index)
93 << "\n";
94 }
95 }
96 }
97 #endif // NDEBUG
98 }
99
100 /**
101 * Writes to the indicated ostream a list of all the inputs this DataNode
102 * might expect to receive.
103 */
104 void DataNode::
105 write_inputs(std::ostream &out) const {
106 Wires::const_iterator wi;
107 for (wi = _input_wires.begin(); wi != _input_wires.end(); ++wi) {
108 const string &name = (*wi).first;
109 const WireDef &def = (*wi).second;
110 out << name << " " << def._data_type << "\n";
111 }
112 }
113
114 /**
115 * Writes to the indicated ostream a list of all the outputs this DataNode
116 * might generate.
117 */
118 void DataNode::
119 write_outputs(std::ostream &out) const {
120 Wires::const_iterator wi;
121 for (wi = _output_wires.begin(); wi != _output_wires.end(); ++wi) {
122 const string &name = (*wi).first;
123 const WireDef &def = (*wi).second;
124 out << name << " " << def._data_type << "\n";
125 }
126 }
127
128 /**
129 * Writes to the indicated ostream a list of all the connections currently
130 * showing between this DataNode and its parent(s).
131 */
132 void DataNode::
133 write_connections(std::ostream &out) const {
134 DataConnections::const_iterator ci;
135 for (ci = _data_connections.begin(); ci != _data_connections.end(); ++ci) {
136 const DataConnection &connect = (*ci);
137 nassertv(connect._parent_index >= 0 && connect._parent_index < get_num_parents());
138
139 // Now we have to search exhaustively for the input with the matching
140 // index number.
141 Wires::const_iterator wi;
142 bool found = false;
143 for (wi = _input_wires.begin(); wi != _input_wires.end() && !found; ++wi) {
144 const string &name = (*wi).first;
145 const WireDef &def = (*wi).second;
146 if (def._index == connect._input_index) {
147 out << name << " " << def._data_type << " from "
148 << *get_parent(connect._parent_index) << "\n";
149 found = true;
150 }
151 }
152 nassertv(found);
153 }
154 }
155
156 /**
157 * Adds a new input wire with the given name and the indicated data type. The
158 * data type should be the TypeHandle for some type that derives from
159 * TypedReferenceCount, e.g. EventStoreInt, EventStoreDouble, or some fancier
160 * data type like Texture.
161 *
162 * If there is already an input wire defined with the indicated name, its type
163 * is changed.
164 *
165 * The return value is the index into the "input" parameter to
166 * do_transmit_data() that can be used to access the input data.
167 */
168 int DataNode::
169 define_input(const string &name, TypeHandle data_type) {
170 // We shouldn't already be connected.
171 nassertr(_data_connections.empty(), 0);
172
173 Wires::iterator wi;
174 wi = _input_wires.find(name);
175 if (wi != _input_wires.end()) {
176 // This wire already existed; modify it and return the original index.
177 WireDef &def = (*wi).second;
178 def._data_type = data_type;
179 return def._index;
180 }
181
182 // This wire did not already exist; add it.
183 WireDef &def = _input_wires[name];
184 def._data_type = data_type;
185 def._index = _input_wires.size() - 1;
186 return def._index;
187 }
188
189 /**
190 * Adds a new output wire with the given name and the indicated data type.
191 * The data type should be the TypeHandle for some type that derives from
192 * TypedReferenceCount, e.g. EventStoreInt, EventStoreDouble, or some fancier
193 * data type like Texture.
194 *
195 * If there is already an output wire defined with the indicated name, its
196 * type is changed.
197 *
198 * The return value is the index into the "output" parameter to
199 * do_transmit_data() where the output data should be stored.
200 */
201 int DataNode::
202 define_output(const string &name, TypeHandle data_type) {
203 // We shouldn't already be connected.
204 nassertr(_data_connections.empty(), 0);
205
206 Wires::iterator wi;
207 wi = _output_wires.find(name);
208 if (wi != _output_wires.end()) {
209 // This wire already existed; modify it and return the original index.
210 WireDef &def = (*wi).second;
211 def._data_type = data_type;
212 return def._index;
213 }
214
215 // This wire did not already exist; add it.
216 WireDef &def = _output_wires[name];
217 def._data_type = data_type;
218 def._index = _output_wires.size() - 1;
219 return def._index;
220 }
221
222 /**
223 * Called after a scene graph update that either adds or remove parents from
224 * this node, this just provides a hook for derived PandaNode objects that
225 * need to update themselves based on the set of parents the node has.
226 */
227 void DataNode::
228 parents_changed() {
229 PandaNode::parents_changed();
230 reconnect();
231 }
232
233 /**
234 * The virtual implementation of transmit_data(). This function receives an
235 * array of input parameters and should generate an array of output
236 * parameters. The input parameters may be accessed with the index numbers
237 * returned by the define_input() calls that were made earlier (presumably in
238 * the constructor); likewise, the output parameters should be set with the
239 * index numbers returned by the define_output() calls.
240 */
241 void DataNode::
242 do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &,
243 DataNodeTransmit &) {
244 }
245
246 /**
247 * Establishes the input(s) that this DataNode has in common with its parents'
248 * output(s). Builds up the _data_connections list correspondingly.
249 */
250 void DataNode::
251 reconnect() {
252 int num_parents = get_num_parents();
253 _data_connections.clear();
254 // Look for each input among one of the parents.
255 int num_datanode_parents = 0;
256
257 Wires::const_iterator wi;
258 for (wi = _input_wires.begin(); wi != _input_wires.end(); ++wi) {
259 const string &name = (*wi).first;
260 const WireDef &input_def = (*wi).second;
261
262 int num_found = 0;
263 for (int i = 0; i < num_parents; i++) {
264 PandaNode *parent_node = get_parent(i);
265 if (parent_node->is_of_type(DataNode::get_class_type())) {
266 DataNode *data_node = DCAST(DataNode, parent_node);
267 num_datanode_parents++;
268 Wires::const_iterator pi;
269 pi = data_node->_output_wires.find(name);
270 if (pi != data_node->_output_wires.end()) {
271 const WireDef &output_def = (*pi).second;
272 num_found++;
273 if (output_def._data_type != input_def._data_type) {
274 dgraph_cat.warning()
275 << "Ignoring mismatched type for connection " << name
276 << " between " << *data_node << " and " << *this << "\n";
277 } else {
278 DataConnection dc;
279 dc._parent_index = i;
280 dc._output_index = output_def._index;
281 dc._input_index = input_def._index;
282 _data_connections.push_back(dc);
283 }
284 }
285 }
286 }
287
288 if (num_found > 1) {
289 if (dgraph_cat.is_debug()) {
290 dgraph_cat.debug()
291 << "Multiple connections found for " << name << " into " << *this
292 << "\n";
293 }
294 }
295 }
296
297 if (_data_connections.empty() && get_num_inputs() != 0 &&
298 num_datanode_parents != 0) {
299 dgraph_cat.warning()
300 << "No data connected to " << *this << "\n";
301 }
302 }
303
304 /**
305 * Writes the contents of this object to the datagram for shipping out to a
306 * Bam file.
307 */
308 void DataNode::
309 write_datagram(BamWriter *manager, Datagram &dg) {
310 PandaNode::write_datagram(manager, dg);
311 }
312
313 /**
314 * This internal function is called by make_from_bam to read in all of the
315 * relevant data from the BamFile for the new Lens.
316 */
317 void DataNode::
318 fillin(DatagramIterator &scan, BamReader *manager) {
319 PandaNode::fillin(scan, manager);
320 }
BamReader
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
BamWriter
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
DataGraphTraverser
This object supervises the traversal of the data graph and the moving of data from one DataNode to it...
Definition: dataGraphTraverser.h:32
DataNodeTransmit
Encapsulates the data generated from (or sent into) any particular DataNode.
Definition: dataNodeTransmit.h:32
DataNodeTransmit::get_data
const EventParameter & get_data(int index) const
Extracts the data for the indicated index, if it has been stored, or the empty parameter if it has no...
Definition: dataNodeTransmit.I:52
DataNodeTransmit::set_data
void set_data(int index, const EventParameter &data)
Sets the data for the indicated parameter.
Definition: dataNodeTransmit.I:75
DataNodeTransmit::has_data
bool has_data(int index) const
Returns true if the indicated parameter has been stored, false otherwise.
Definition: dataNodeTransmit.I:64
DataNodeTransmit::reserve
void reserve(int num_wires)
Tells the DataNodeTransmit object how many wires it is expected to store data for.
Definition: dataNodeTransmit.I:43
DataNode
The fundamental type of node for the data graph.
Definition: dataNode.h:52
DataNode::write_inputs
void write_inputs(std::ostream &out) const
Writes to the indicated ostream a list of all the inputs this DataNode might expect to receive.
Definition: dataNode.cxx:105
DataNode::write_connections
void write_connections(std::ostream &out) const
Writes to the indicated ostream a list of all the connections currently showing between this DataNode...
Definition: dataNode.cxx:133
DataNode::get_num_inputs
int get_num_inputs() const
Returns the number of different inputs that have been defined for this node using define_input().
Definition: dataNode.I:39
DataNode::make_copy
virtual PandaNode * make_copy() const
Returns a newly-allocated Node that is a shallow copy of this one.
Definition: dataNode.cxx:29
DataNode::transmit_data
void transmit_data(DataGraphTraverser *trav, const DataNodeTransmit inputs[], DataNodeTransmit &output)
Collects the data from all of the parent nodes and puts it into one DataNodeTransmit object,...
Definition: dataNode.cxx:39
DataNode::write_datagram
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: dataNode.cxx:309
DataNode::write_outputs
void write_outputs(std::ostream &out) const
Writes to the indicated ostream a list of all the outputs this DataNode might generate.
Definition: dataNode.cxx:119
DatagramIterator
A class to retrieve the individual data elements previously stored in a Datagram.
Definition: datagramIterator.h:27
Datagram
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
EventParameter
An optional parameter associated with an event.
Definition: eventParameter.h:35
PandaNode
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
PandaNode::get_num_parents
get_num_parents
Returns the number of parent nodes this node has.
Definition: pandaNode.h:118
PandaNode::write_datagram
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: pandaNode.cxx:3583
PandaNode::get_parent
get_parent
Returns the nth parent node of this node.
Definition: pandaNode.h:118
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
TypedObject::is_of_type
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
config_dgraph.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
dataNodeTransmit.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
dataNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
dcast.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.