Panda3D
 All Classes Functions Variables Enumerations
nodePathComponent.cxx
1 // Filename: nodePathComponent.cxx
2 // Created by: drose (25Feb02)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "nodePathComponent.h"
16 #include "lightMutexHolder.h"
17 
18 // We start the key counters off at 1, since 0 is reserved for an
19 // empty NodePath (and also for an unassigned key).
20 int NodePathComponent::_next_key = 1;
21 LightMutex NodePathComponent::_key_lock("NodePathComponent::_key_lock");
22 TypeHandle NodePathComponent::_type_handle;
23 TypeHandle NodePathComponent::CData::_type_handle;
24 
25 
26 ////////////////////////////////////////////////////////////////////
27 // Function: NodePathComponent::CData::make_copy
28 // Access: Public, Virtual
29 // Description:
30 ////////////////////////////////////////////////////////////////////
31 CycleData *NodePathComponent::CData::
32 make_copy() const {
33  return new CData(*this);
34 }
35 
36 ////////////////////////////////////////////////////////////////////
37 // Function: NodePathComponent::Constructor
38 // Access: Private
39 // Description: Constructs a new NodePathComponent from the
40 // indicated node. Don't try to call this directly; ask
41 // the PandaNode to do it for you.
42 ////////////////////////////////////////////////////////////////////
43 NodePathComponent::
44 NodePathComponent(PandaNode *node, NodePathComponent *next,
45  int pipeline_stage, Thread *current_thread) :
46  _node(node),
47  _key(0)
48 {
49 #ifdef DO_MEMORY_USAGE
50  MemoryUsage::update_type(this, get_class_type());
51 #endif
52 
53  for (int pipeline_stage_i = pipeline_stage;
54  pipeline_stage_i >= 0;
55  --pipeline_stage_i) {
56  CDStageWriter cdata(_cycler, pipeline_stage_i, current_thread);
57  cdata->_next = next;
58 
59  if (next != (NodePathComponent *)NULL) {
60  cdata->_length = next->get_length(pipeline_stage_i, current_thread) + 1;
61  }
62  }
63 }
64 
65 ////////////////////////////////////////////////////////////////////
66 // Function: NodePathComponent::get_key
67 // Access: Public
68 // Description: Returns an index number that is guaranteed to be
69 // unique for this particular NodePathComponent, and not
70 // to be reused for the lifetime of the application
71 // (barring integer overflow).
72 ////////////////////////////////////////////////////////////////////
74 get_key() const {
75  LightMutexHolder holder(_key_lock);
76  if (_key == 0) {
77  // The first time someone asks for a particular component's key,
78  // we make it up on the spot. This helps keep us from wasting
79  // index numbers generating a unique number for *every* component
80  // in the world (we only have 4.2 billion 32-bit integers, after
81  // all)
82  ((NodePathComponent *)this)->_key = _next_key++;
83  }
84  return _key;
85 }
86 
87 ////////////////////////////////////////////////////////////////////
88 // Function: NodePathComponent::is_top_node
89 // Access: Public
90 // Description: Returns true if this component represents the top
91 // node in the path.
92 ////////////////////////////////////////////////////////////////////
94 is_top_node(int pipeline_stage, Thread *current_thread) const {
95  CDStageReader cdata(_cycler, pipeline_stage, current_thread);
96  return (cdata->_next == (NodePathComponent *)NULL);
97 }
98 
99 ////////////////////////////////////////////////////////////////////
100 // Function: NodePathComponent::get_length
101 // Access: Public
102 // Description: Returns the length of the path to this node.
103 ////////////////////////////////////////////////////////////////////
105 get_length(int pipeline_stage, Thread *current_thread) const {
106  CDStageReader cdata(_cycler, pipeline_stage, current_thread);
107  return cdata->_length;
108 }
109 
110 ////////////////////////////////////////////////////////////////////
111 // Function: NodePathComponent::get_next
112 // Access: Public
113 // Description: Returns the next component in the path.
114 ////////////////////////////////////////////////////////////////////
116 get_next(int pipeline_stage, Thread *current_thread) const {
117  CDStageReader cdata(_cycler, pipeline_stage, current_thread);
118  NodePathComponent *next = cdata->_next;
119 
120  return next;
121 }
122 
123 ////////////////////////////////////////////////////////////////////
124 // Function: NodePathComponent::fix_length
125 // Access: Public
126 // Description: Checks that the length indicated by the component is
127 // one more than the length of its predecessor. If this
128 // is broken, fixes it and returns true indicating the
129 // component has been changed; otherwise, returns false.
130 ////////////////////////////////////////////////////////////////////
132 fix_length(int pipeline_stage, Thread *current_thread) {
133  CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
134 
135  int length_should_be = 1;
136  if (cdata->_next != (NodePathComponent *)NULL) {
137  length_should_be = cdata->_next->get_length(pipeline_stage, current_thread) + 1;
138  }
139 
140  if (cdata->_length == length_should_be) {
141  return false;
142  }
143 
144  CDStageWriter cdataw(_cycler, pipeline_stage, cdata);
145  cdataw->_length = length_should_be;
146  return true;
147 }
148 
149 ////////////////////////////////////////////////////////////////////
150 // Function: NodePathComponent::output
151 // Access: Public
152 // Description: The recursive implementation of NodePath::output(),
153 // this writes the names of each node component in order
154 // from beginning to end, by first walking to the end of
155 // the linked list and then outputting from there.
156 ////////////////////////////////////////////////////////////////////
158 output(ostream &out) const {
159  Thread *current_thread = Thread::get_current_thread();
160  int pipeline_stage = current_thread->get_pipeline_stage();
161 
162  PandaNode *node = get_node();
163  NodePathComponent *next = get_next(pipeline_stage, current_thread);
164  if (next != (NodePathComponent *)NULL) {
165  // This is not the head of the list; keep going up.
166  next->output(out);
167  out << "/";
168 
169  PandaNode *parent_node = next->get_node();
170  if (parent_node->find_stashed(node) >= 0) {
171  // The node is stashed.
172  out << "@@";
173 
174  } else if (node->find_parent(parent_node) < 0) {
175  // Oops, there's an error. This shouldn't happen.
176  out << ".../";
177  }
178  }
179 
180  // Now output this component.
181  if (node->has_name()) {
182  out << node->get_name();
183  } else {
184  out << "-" << node->get_type();
185  }
186  // out << "[" << this->get_length() << "]";
187 }
188 
189 ////////////////////////////////////////////////////////////////////
190 // Function: NodePathComponent::set_next
191 // Access: Private
192 // Description: Sets the next pointer in the path.
193 ////////////////////////////////////////////////////////////////////
194 void NodePathComponent::
195 set_next(NodePathComponent *next, int pipeline_stage, Thread *current_thread) {
196  nassertv(next != (NodePathComponent *)NULL);
197  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
198  cdata->_next = next;
199 }
200 
201 ////////////////////////////////////////////////////////////////////
202 // Function: NodePathComponent::set_top_node
203 // Access: Private
204 // Description: Severs any connection to the next pointer in the
205 // path and makes this component a top node.
206 ////////////////////////////////////////////////////////////////////
207 void NodePathComponent::
208 set_top_node(int pipeline_stage, Thread *current_thread) {
209  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
210  cdata->_next = (NodePathComponent *)NULL;
211 }
bool fix_length(int pipeline_stage, Thread *current_thread)
Checks that the length indicated by the component is one more than the length of its predecessor...
A basic node of the scene graph or data graph.
Definition: pandaNode.h:72
int get_key() const
Returns an index number that is guaranteed to be unique for this particular NodePathComponent, and not to be reused for the lifetime of the application (barring integer overflow).
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
int get_length(int pipeline_stage, Thread *current_thread) const
Returns the length of the path to this node.
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
Definition: namable.I:75
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
Definition: thread.I:145
bool is_top_node(int pipeline_stage, Thread *current_thread) const
Returns true if this component represents the top node in the path.
int find_stashed(PandaNode *node, Thread *current_thread=Thread::get_current_thread()) const
Returns the index of the indicated stashed node, if it is a stashed child, or -1 if it is not...
Definition: pandaNode.I:220
PandaNode * get_node() const
Returns the node referenced by this component.
Similar to MutexHolder, but for a light mutex.
This class is similar to CycleDataLockedReader, except it allows reading from a particular stage of t...
This class is similar to CycleDataReader, except it allows reading from a particular stage of the pip...
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:54
A thread; that is, a lightweight process.
Definition: thread.h:51
void output(ostream &out) const
The recursive implementation of NodePath::output(), this writes the names of each node component in o...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
This is a standard, non-reentrant mutex, similar to the Mutex class.
Definition: lightMutex.h:45
NodePathComponent * get_next(int pipeline_stage, Thread *current_thread) const
Returns the next component in the path.
int get_pipeline_stage() const
Returns the Pipeline stage number associated with this thread.
Definition: thread.I:84
This is one component of a NodePath.