Panda3D
Loading...
Searching...
No Matches
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
19using std::string;
20
21TypeHandle 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 */
29make_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 */
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 */
105write_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 */
119write_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 */
133write_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 */
168int DataNode::
169define_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 */
201int DataNode::
202define_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 */
227void DataNode::
228parents_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 */
241void DataNode::
242do_transmit_data(DataGraphTraverser *, const 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 */
250void DataNode::
251reconnect() {
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 */
309write_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 */
317void DataNode::
318fillin(DatagramIterator &scan, BamReader *manager) {
319 PandaNode::fillin(scan, manager);
320}
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition bamReader.h:110
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition bamWriter.h:63
This object supervises the traversal of the data graph and the moving of data from one DataNode to it...
Encapsulates the data generated from (or sent into) any particular DataNode.
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...
void set_data(int index, const EventParameter &data)
Sets the data for the indicated parameter.
bool has_data(int index) const
Returns true if the indicated parameter has been stored, false otherwise.
void reserve(int num_wires)
Tells the DataNodeTransmit object how many wires it is expected to store data for.
The fundamental type of node for the data graph.
Definition dataNode.h:52
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
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
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
virtual PandaNode * make_copy() const
Returns a newly-allocated Node that is a shallow copy of this one.
Definition dataNode.cxx:29
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
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
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
A class to retrieve the individual data elements previously stored in a Datagram.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition datagram.h:38
An optional parameter associated with an event.
A basic node of the scene graph or data graph.
Definition pandaNode.h:65
get_num_parents
Returns the number of parent nodes this node has.
Definition pandaNode.h:118
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
get_parent
Returns the nth parent node of this node.
Definition pandaNode.h:118
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition typedObject.I:28
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.