Panda3D
Loading...
Searching...
No Matches
dataGraphTraverser.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 dataGraphTraverser.cxx
10 * @author drose
11 * @date 2002-03-11
12 */
13
14#include "dataGraphTraverser.h"
15#include "dataNode.h"
16#include "config_dgraph.h"
17#include "dcast.h"
18
19
20/**
21 * Sets the data associated with the indicated parent of this CollectedData
22 * object's node.
23 */
24void DataGraphTraverser::CollectedData::
25set_data(int parent_index, const DataNodeTransmit &data) {
26 if ((int)_data.size() <= parent_index) {
27 _data.reserve(parent_index + 1);
28 while ((int)_data.size() <= parent_index) {
29 _data.push_back(DataNodeTransmit());
30 }
31 }
32
33 nassertv(parent_index >= 0 && parent_index < (int)_data.size());
34 _data[parent_index] = data;
35}
36
37/**
38 *
39 */
40DataGraphTraverser::
41DataGraphTraverser(Thread *current_thread) : _current_thread(current_thread) {
42}
43
44/**
45 *
46 */
47DataGraphTraverser::
48~DataGraphTraverser() {
49}
50
51/**
52 * Starts the traversal of the data graph at the indicated root node.
53 */
55traverse(PandaNode *node) {
56 if (node->is_of_type(DataNode::get_class_type())) {
57 DataNode *data_node = DCAST(DataNode, node);
58 // We must start the traversal at the root of the graph.
59 nassertv(data_node->get_num_parents(_current_thread) == 0);
60
61 r_transmit(data_node, nullptr);
62
63 } else {
65 }
66
68}
69
70/**
71 * Continues the traversal to all the children of the indicated node, passing
72 * in the given data, without actually calling transmit_data() on the given
73 * node.
74 */
76traverse_below(PandaNode *node, const DataNodeTransmit &output) {
77 PandaNode::Children cr = node->get_children(_current_thread);
78 int num_children = cr.get_num_children();
79
80 for (int i = 0; i < num_children; i++) {
81 PandaNode *child_node = cr.get_child(i);
82 if (child_node->is_of_type(DataNode::get_class_type())) {
83 DataNode *data_node = DCAST(DataNode, child_node);
84 // If it's a DataNode-type child, we need to pass it the data. Maybe it
85 // has only one parent, and can accept the data immediately.
86 int num_parents = data_node->get_num_parents(_current_thread);
87 if (num_parents == 1) {
88 // The easy, common case: only one parent. We make our output into a
89 // one-element array of inputs by turning it into a pointer.
90 r_transmit(data_node, &output);
91 } else {
92 // A more difficult case: multiple parents. We must collect instances
93 // together, meaning we must hold onto this node until we have reached
94 // it through all paths.
95 CollectedData &collected_data = _multipass_data[data_node];
96 int parent_index = data_node->find_parent(node, _current_thread);
97 nassertv(parent_index != -1);
98
99 collected_data.set_data(parent_index, output);
100 collected_data._num_parents++;
101 nassertv(collected_data._num_parents <= num_parents);
102 if (collected_data._num_parents == num_parents) {
103 // Now we've got all the data; go into the child.
104 r_transmit(data_node, &collected_data._data[0]);
105 _multipass_data.erase(data_node);
106 }
107 }
108 } else {
109 // The child node is not a DataNode-type child. We continue the
110 // traversal, but data does not pass through this node, and instances
111 // are not collected together. (Although we appear to be passing the
112 // data through here, it doesn't do any good anyway, since the child
113 // nodes of this node will not know how to interpret the data from a
114 // non-DataNode parent.)
115 traverse_below(child_node, output);
116 }
117 }
118}
119
120/**
121 * Pick up any nodes that didn't get completely traversed. These must be
122 * nodes that have multiple parents, with at least one parent completely
123 * outside of the data graph.
124 */
127 while (!_multipass_data.empty()) {
128 MultipassData::iterator mi = _multipass_data.begin();
129 DataNode *data_node = (*mi).first;
130 const CollectedData &collected_data = (*mi).second;
131
132 dgraph_cat.warning()
133 << *data_node << " improperly parented partly outside of data graph.\n";
134
135 r_transmit(data_node, &collected_data._data[0]);
136 _multipass_data.erase(mi);
137 }
138}
139
140/**
141 * Part of the recursive implementation of traverse(). This transmits the
142 * given data into the indicated DataNode, and then sends the output data to
143 * each of the node's children.
144 */
145void DataGraphTraverser::
146r_transmit(DataNode *data_node, const DataNodeTransmit inputs[]) {
147 DataNodeTransmit output;
148 output.reserve(data_node->get_num_outputs());
149 data_node->transmit_data(this, inputs, output);
150
151 traverse_below(data_node, output);
152}
void traverse_below(PandaNode *node, const DataNodeTransmit &output)
Continues the traversal to all the children of the indicated node, passing in the given data,...
void traverse(PandaNode *node)
Starts the traversal of the data graph at the indicated root node.
void collect_leftovers()
Pick up any nodes that didn't get completely traversed.
Encapsulates the data generated from (or sent into) any particular DataNode.
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
int get_num_outputs() const
Returns the number of different outputs that have been defined for this node using define_output().
Definition dataNode.I:49
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
PandaNode * get_child(size_t n) const
Returns the nth child of the node.
Definition pandaNode.I:962
size_t get_num_children() const
Returns the number of children of the node.
Definition pandaNode.I:953
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
int find_parent(PandaNode *node, Thread *current_thread=Thread::get_current_thread()) const
Returns the index of the indicated parent node, if it is a parent, or -1 if it is not.
Definition pandaNode.I:44
get_children
Returns an object that can be used to walk through the list of children of the node.
Definition pandaNode.h:782
A thread; that is, a lightweight process.
Definition thread.h:46
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.