Panda3D
nodePathComponent.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 nodePathComponent.cxx
10  * @author drose
11  * @date 2002-02-25
12  */
13 
14 #include "nodePathComponent.h"
15 #include "lightMutexHolder.h"
16 
17 // We start the key counters off at 1, since 0 is reserved for an empty
18 // NodePath (and also for an unassigned key).
19 int NodePathComponent::_next_key = 1;
20 LightMutex NodePathComponent::_key_lock("NodePathComponent::_key_lock");
21 TypeHandle NodePathComponent::_type_handle;
22 TypeHandle NodePathComponent::CData::_type_handle;
23 
24 
25 /**
26  *
27  */
28 CycleData *NodePathComponent::CData::
29 make_copy() const {
30  return new CData(*this);
31 }
32 
33 /**
34  * Constructs a new NodePathComponent from the indicated node. Don't try to
35  * call this directly; ask the PandaNode to do it for you.
36  */
37 NodePathComponent::
38 NodePathComponent(PandaNode *node, NodePathComponent *next,
39  int pipeline_stage, Thread *current_thread) :
40  _node(node),
41  _key(0)
42 {
43 #ifdef DO_MEMORY_USAGE
44  MemoryUsage::update_type(this, get_class_type());
45 #endif
46 
47  for (int pipeline_stage_i = pipeline_stage;
48  pipeline_stage_i >= 0;
49  --pipeline_stage_i) {
50  CDStageWriter cdata(_cycler, pipeline_stage_i, current_thread);
51  cdata->_next = next;
52 
53  if (next != nullptr) {
54  cdata->_length = next->get_length(pipeline_stage_i, current_thread) + 1;
55  }
56  }
57 }
58 
59 /**
60  * Returns an index number that is guaranteed to be unique for this particular
61  * NodePathComponent, and not to be reused for the lifetime of the application
62  * (barring integer overflow).
63  */
65 get_key() const {
66  LightMutexHolder holder(_key_lock);
67  if (_key == 0) {
68  // The first time someone asks for a particular component's key, we make
69  // it up on the spot. This helps keep us from wasting index numbers
70  // generating a unique number for *every* component in the world (we only
71  // have 4.2 billion 32-bit integers, after all)
72  ((NodePathComponent *)this)->_key = _next_key++;
73  }
74  return _key;
75 }
76 
77 /**
78  * Returns true if this component represents the top node in the path.
79  */
81 is_top_node(int pipeline_stage, Thread *current_thread) const {
82  CDStageReader cdata(_cycler, pipeline_stage, current_thread);
83  return (cdata->_next == nullptr);
84 }
85 
86 /**
87  * Returns the length of the path to this node.
88  */
90 get_length(int pipeline_stage, Thread *current_thread) const {
91  CDStageReader cdata(_cycler, pipeline_stage, current_thread);
92  return cdata->_length;
93 }
94 
95 /**
96  * Checks that the length indicated by the component is one more than the
97  * length of its predecessor. If this is broken, fixes it and returns true
98  * indicating the component has been changed; otherwise, returns false.
99  */
101 fix_length(int pipeline_stage, Thread *current_thread) {
102  CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
103 
104  int length_should_be = 1;
105  if (cdata->_next != nullptr) {
106  length_should_be = cdata->_next->get_length(pipeline_stage, current_thread) + 1;
107  }
108 
109  if (cdata->_length == length_should_be) {
110  return false;
111  }
112 
113  CDStageWriter cdataw(_cycler, pipeline_stage, cdata);
114  cdataw->_length = length_should_be;
115  return true;
116 }
117 
118 /**
119  * The recursive implementation of NodePath::output(), this writes the names
120  * of each node component in order from beginning to end, by first walking to
121  * the end of the linked list and then outputting from there.
122  */
124 output(std::ostream &out) const {
125  Thread *current_thread = Thread::get_current_thread();
126  int pipeline_stage = current_thread->get_pipeline_stage();
127 
128  PandaNode *node = get_node();
129  NodePathComponent *next = get_next(pipeline_stage, current_thread);
130  if (next != nullptr) {
131  // This is not the head of the list; keep going up.
132  next->output(out);
133  out << "/";
134 
135  PandaNode *parent_node = next->get_node();
136  if (parent_node->find_stashed(node) >= 0) {
137  // The node is stashed.
138  out << "@@";
139 
140  } else if (node->find_parent(parent_node) < 0) {
141  // Oops, there's an error. This shouldn't happen.
142  out << ".../";
143  }
144  }
145 
146  // Now output this component.
147  if (node->has_name()) {
148  out << node->get_name();
149  } else {
150  out << "-" << node->get_type();
151  }
152  // out << "[" << this->get_length() << "]";
153 }
154 
155 /**
156  * Sets the next pointer in the path.
157  */
158 void NodePathComponent::
159 set_next(NodePathComponent *next, int pipeline_stage, Thread *current_thread) {
160  nassertv(next != nullptr);
161  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
162  cdata->_next = next;
163 }
164 
165 /**
166  * Severs any connection to the next pointer in the path and makes this
167  * component a top node.
168  */
169 void NodePathComponent::
170 set_top_node(int pipeline_stage, Thread *current_thread) {
171  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
172  cdata->_next = nullptr;
173 }
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:64
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:47
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaNode * get_node() const
Returns the node referenced by this component.
get_pipeline_stage
Returns the Pipeline stage number associated with this thread.
Definition: thread.h:105
bool is_top_node(int pipeline_stage, Thread *current_thread) const
Returns true if this component represents the top node in the path.
Similar to MutexHolder, but for a light mutex.
void output(std::ostream &out) const
The recursive implementation of NodePath::output(), this writes the names of each node component in o...
NodePathComponent * get_next(int pipeline_stage, Thread *current_thread) const
Returns the next component in the path.
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
This class is similar to CycleDataLockedReader, except it allows reading from a particular stage of t...
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
Definition: memoryUsage.I:55
This class is similar to CycleDataReader, except it allows reading from a particular stage of the pip...
A thread; that is, a lightweight process.
Definition: thread.h:46
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:44
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
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:178
This is a standard, non-reentrant mutex, similar to the Mutex class.
Definition: lightMutex.h:39
This is one component of a NodePath.