Panda3D
pandaNode.I
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 pandaNode.I
10  * @author drose
11  * @date 2002-02-20
12  */
13 
14 /**
15  * Returns the number of parent nodes this node has. If this number is
16  * greater than 1, the node has been multiply instanced. The order of the
17  * parent nodes is not meaningful and is not related to the order in which the
18  * node was instanced to them.
19  */
20 INLINE int PandaNode::
21 get_num_parents(Thread *current_thread) const {
22  CDReader cdata(_cycler, current_thread);
23  return cdata->get_up()->size();
24 }
25 
26 /**
27  * Returns the nth parent node of this node. See get_num_parents(). Also see
28  * get_parents(), if your intention is to iterate through the complete list of
29  * parents; get_parents() is preferable in this case.
30  */
31 INLINE PandaNode *PandaNode::
32 get_parent(int n, Thread *current_thread) const {
33  CDReader cdata(_cycler, current_thread);
34  CPT(Up) up = cdata->get_up();
35  nassertr(n >= 0 && n < (int)up->size(), nullptr);
36  return (*up)[n].get_parent();
37 }
38 
39 /**
40  * Returns the index of the indicated parent node, if it is a parent, or -1 if
41  * it is not.
42  */
43 INLINE int PandaNode::
44 find_parent(PandaNode *node, Thread *current_thread) const {
45  CDReader cdata(_cycler, current_thread);
46  return do_find_parent(node, cdata);
47 }
48 
49 /**
50  * Returns the number of child nodes this node has. The order of the child
51  * nodes *is* meaningful and is based on the sort number that was passed to
52  * add_child(), and also on the order in which the nodes were added.
53  */
54 INLINE int PandaNode::
55 get_num_children(Thread *current_thread) const {
56  CDReader cdata(_cycler, current_thread);
57  return cdata->get_down()->size();
58 }
59 
60 /**
61  * Returns the nth child node of this node. See get_num_children(). Also see
62  * get_children(), if your intention is to iterate through the complete list
63  * of children; get_children() is preferable in this case.
64  */
65 INLINE PandaNode *PandaNode::
66 get_child(int n, Thread *current_thread) const {
67  CDReader cdata(_cycler, current_thread);
68  CPT(Down) down = cdata->get_down();
69  nassertr(n >= 0 && n < (int)down->size(), nullptr);
70  return (*down)[n].get_child();
71 }
72 
73 /**
74  * Returns the sort index of the nth child node of this node (that is, the
75  * number that was passed to add_child()). See get_num_children().
76  */
77 INLINE int PandaNode::
78 get_child_sort(int n, Thread *current_thread) const {
79  CDReader cdata(_cycler, current_thread);
80  CPT(Down) down = cdata->get_down();
81  nassertr(n >= 0 && n < (int)down->size(), -1);
82  return (*down)[n].get_sort();
83 }
84 
85 /**
86  * Returns the index of the indicated child node, if it is a child, or -1 if
87  * it is not.
88  */
89 INLINE int PandaNode::
90 find_child(PandaNode *node, Thread *current_thread) const {
91  CDReader cdata(_cycler, current_thread);
92  return do_find_child(node, cdata->get_down());
93 }
94 
95 /**
96  * Stashes the indicated child node. This removes the child from the list of
97  * active children and puts it on a special list of stashed children. This
98  * child node no longer contributes to the bounding volume of the PandaNode,
99  * and is not visited in normal traversals. It is invisible and uncollidable.
100  * The child may later be restored by calling unstash_child().
101  *
102  * This function returns true if the child node was successfully stashed, or
103  * false if it was not a child of the node in the first place (e.g. it was
104  * previously stashed).
105  */
106 INLINE bool PandaNode::
107 stash_child(PandaNode *child_node, Thread *current_thread) {
108  int child_index = find_child(child_node, current_thread);
109  if (child_index < 0) {
110  return false;
111  }
112  stash_child(child_index, current_thread);
113  return true;
114 }
115 
116 /**
117  * Returns the indicated stashed node to normal child status. This removes
118  * the child from the list of stashed children and puts it on the normal list
119  * of active children. This child node once again contributes to the bounding
120  * volume of the PandaNode, and will be visited in normal traversals. It is
121  * visible and collidable.
122  *
123  * This function returns true if the child node was successfully stashed, or
124  * false if it was not a child of the node in the first place (e.g. it was
125  * previously stashed).
126  */
127 INLINE bool PandaNode::
128 unstash_child(PandaNode *child_node, Thread *current_thread) {
129  int stashed_index = find_stashed(child_node, current_thread);
130  if (stashed_index < 0) {
131  return false;
132  }
133  unstash_child(stashed_index, current_thread);
134  return true;
135 }
136 
137 /**
138  * Returns the number of stashed nodes this node has. These are former
139  * children of the node that have been moved to the special stashed list via
140  * stash_child().
141  */
142 INLINE int PandaNode::
143 get_num_stashed(Thread *current_thread) const {
144  CDReader cdata(_cycler, current_thread);
145  return cdata->get_stashed()->size();
146 }
147 
148 /**
149  * Returns the nth stashed child of this node. See get_num_stashed(). Also
150  * see get_stashed(), if your intention is to iterate through the complete
151  * list of stashed children; get_stashed() is preferable in this case.
152  */
153 INLINE PandaNode *PandaNode::
154 get_stashed(int n, Thread *current_thread) const {
155  CDReader cdata(_cycler, current_thread);
156  CPT(Down) stashed = cdata->get_stashed();
157  nassertr(n >= 0 && n < (int)stashed->size(), nullptr);
158  return (*stashed)[n].get_child();
159 }
160 
161 /**
162  * Returns the sort index of the nth stashed node of this node (that is, the
163  * number that was passed to add_child()). See get_num_stashed().
164  */
165 INLINE int PandaNode::
166 get_stashed_sort(int n, Thread *current_thread) const {
167  CDReader cdata(_cycler, current_thread);
168  CPT(Down) stashed = cdata->get_stashed();
169  nassertr(n >= 0 && n < (int)stashed->size(), -1);
170  return (*stashed)[n].get_sort();
171 }
172 
173 /**
174  * Returns the index of the indicated stashed node, if it is a stashed child,
175  * or -1 if it is not.
176  */
177 INLINE int PandaNode::
178 find_stashed(PandaNode *node, Thread *current_thread) const {
179  CDReader cdata(_cycler, current_thread);
180  return do_find_child(node, cdata->get_stashed());
181 }
182 
183 /**
184  * Returns the render attribute of the indicated type, if it is defined on the
185  * node, or NULL if it is not. This checks only what is set on this
186  * particular node level, and has nothing to do with what render attributes
187  * may be inherited from parent nodes.
188  */
189 INLINE CPT(RenderAttrib) PandaNode::
190 get_attrib(TypeHandle type) const {
191  CDReader cdata(_cycler);
192  return cdata->_state->get_attrib(type);
193 }
194 
195 /**
196  * Returns the render attribute of the indicated type, if it is defined on the
197  * node, or NULL if it is not. This checks only what is set on this
198  * particular node level, and has nothing to do with what render attributes
199  * may be inherited from parent nodes.
200  */
201 INLINE CPT(RenderAttrib) PandaNode::
202 get_attrib(int slot) const {
203  CDReader cdata(_cycler);
204  return cdata->_state->get_attrib(slot);
205 }
206 
207 /**
208  * Returns true if there is a render attribute of the indicated type defined
209  * on this node, or false if there is not.
210  */
211 INLINE bool PandaNode::
212 has_attrib(TypeHandle type) const {
213  CDReader cdata(_cycler);
214  return cdata->_state->has_attrib(type);
215 }
216 
217 /**
218  * Returns true if there is a render attribute of the indicated type defined
219  * on this node, or false if there is not.
220  */
221 INLINE bool PandaNode::
222 has_attrib(int slot) const {
223  CDReader cdata(_cycler);
224  return cdata->_state->has_attrib(slot);
225 }
226 
227 /**
228  * Removes the render attribute of the given type from this node. This node,
229  * and the subgraph below, will now inherit the indicated render attribute
230  * from the nodes above this one.
231  */
232 INLINE void PandaNode::
233 clear_attrib(TypeHandle type) {
235  int slot = reg->get_slot(type);
236  clear_attrib(slot);
237 }
238 
239 /**
240  * Returns the render effect of the indicated type, if it is defined on the
241  * node, or NULL if it is not.
242  */
243 INLINE CPT(RenderEffect) PandaNode::
244 get_effect(TypeHandle type) const {
245  CDReader cdata(_cycler);
246  int index = cdata->_effects->find_effect(type);
247  if (index >= 0) {
248  return cdata->_effects->get_effect(index);
249  }
250  return nullptr;
251 }
252 
253 /**
254  * Returns true if there is a render effect of the indicated type defined on
255  * this node, or false if there is not.
256  */
257 INLINE bool PandaNode::
258 has_effect(TypeHandle type) const {
259  CDReader cdata(_cycler);
260  int index = cdata->_effects->find_effect(type);
261  return (index >= 0);
262 }
263 
264 /**
265  * Returns the complete RenderState that will be applied to all nodes at this
266  * level and below, as set on this node. This returns only the RenderState
267  * set on this particular node, and has nothing to do with state that might be
268  * inherited from above.
269  */
270 INLINE CPT(RenderState) PandaNode::
271 get_state(Thread *current_thread) const {
272  CDReader cdata(_cycler, current_thread);
273  return cdata->_state.p();
274 }
275 
276 /**
277  * Resets this node to leave the render state alone. Nodes at this level and
278  * below will once again inherit their render state unchanged from the nodes
279  * above this level.
280  */
281 INLINE void PandaNode::
282 clear_state(Thread *current_thread) {
283  set_state(RenderState::make_empty(), current_thread);
284 }
285 
286 /**
287  * Returns the complete RenderEffects that will be applied to this node.
288  */
289 INLINE CPT(RenderEffects) PandaNode::
290 get_effects(Thread *current_thread) const {
291  CDReader cdata(_cycler, current_thread);
292  return cdata->_effects;
293 }
294 
295 /**
296  * Resets this node to have no render effects.
297  */
298 INLINE void PandaNode::
299 clear_effects(Thread *current_thread) {
300  set_effects(RenderEffects::make_empty(), current_thread);
301 }
302 
303 /**
304  * Returns the transform that has been set on this particular node. This is
305  * not the net transform from the root, but simply the transform on this
306  * particular node.
307  */
308 INLINE CPT(TransformState) PandaNode::
309 get_transform(Thread *current_thread) const {
310  CDReader cdata(_cycler, current_thread);
311  return cdata->_transform.p();
312 }
313 
314 /**
315  * Resets the transform on this node to the identity transform.
316  */
317 INLINE void PandaNode::
318 clear_transform(Thread *current_thread) {
319  set_transform(TransformState::make_identity(), current_thread);
320 }
321 
322 /**
323  * Returns the transform that has been set as this node's "previous" position.
324  * See set_prev_transform().
325  */
326 INLINE CPT(TransformState) PandaNode::
327 get_prev_transform(Thread *current_thread) const {
328  CDReader cdata(_cycler, current_thread);
329  return cdata->_prev_transform.p();
330 }
331 
332 /**
333  * Returns true if this node has the _dirty_prev_transform flag set, which
334  * indicates its _prev_transform is different from its _transform value (in
335  * pipeline stage 0). In this case, the node will be visited by
336  * reset_prev_transform().
337  */
338 INLINE bool PandaNode::
339 has_dirty_prev_transform() const {
340  return _dirty_prev_transform;
341 }
342 
343 /**
344  * Retrieves the user-defined value that was previously set on this node for
345  * the particular key, if any. If no value has been previously set, returns
346  * the empty string.
347  */
348 INLINE std::string PandaNode::
349 get_tag(const std::string &key, Thread *current_thread) const {
350  CDReader cdata(_cycler, current_thread);
351  int index = cdata->_tag_data.find(key);
352  if (index >= 0) {
353  return cdata->_tag_data.get_data((size_t)index);
354  } else {
355  return std::string();
356  }
357 }
358 
359 /**
360  * Returns true if a value has been defined on this node for the particular
361  * key (even if that value is the empty string), or false if no value has been
362  * set.
363  */
364 INLINE bool PandaNode::
365 has_tag(const std::string &key, Thread *current_thread) const {
366  CDReader cdata(_cycler, current_thread);
367  return cdata->_tag_data.find(key) >= 0;
368 }
369 
370 /**
371  * Returns the number of tags applied to this node.
372  */
373 INLINE size_t PandaNode::
374 get_num_tags() const {
375  CDReader cdata(_cycler);
376  return cdata->_tag_data.size();
377 }
378 
379 /**
380  * Returns the key of the nth tag applied to this node.
381  */
382 INLINE std::string PandaNode::
383 get_tag_key(size_t i) const {
384  CDReader cdata(_cycler);
385  return cdata->_tag_data.get_key(i);
386 }
387 
388 /**
389  * Returns true if the node has any tags (or any Python tags) at all, false if
390  * it has none.
391  */
392 INLINE bool PandaNode::
393 has_tags() const {
394  CDReader cdata(_cycler);
395  if (!cdata->_tag_data.is_empty()) {
396  return true;
397  }
398 #ifdef HAVE_PYTHON
399  // This is a bit awkward, since it doesn't catch cases where the Python tags
400  // are cleared. Maybe we should make this behavior deprecated, so that
401  // has_tags will not consider the Python tags.
402  if (!_python_tag_data.is_null()) {
403  return true;
404  }
405 #endif // HAVE_PYTHON
406  return false;
407 }
408 
409 /**
410  * Lists all the nodes at and below the current path hierarchically.
411  */
412 INLINE void PandaNode::
413 ls(std::ostream &out, int indent_level) const {
414  r_list_descendants(out, indent_level);
415 }
416 
417 /**
418  * Returns the special bit that, when specifically cleared in the node's
419  * DrawMask, indicates that the node is hidden to all cameras, regardless of
420  * the remaining DrawMask bits.
421  */
422 INLINE DrawMask PandaNode::
423 get_overall_bit() {
424  return _overall_bit;
425 }
426 
427 /**
428  * Returns a DrawMask that is appropriate for rendering to all cameras.
429  */
430 INLINE DrawMask PandaNode::
432  return ~_overall_bit;
433 }
434 
435 /**
436  * Returns true if the node has been hidden to all cameras by clearing its
437  * overall bit.
438  */
439 INLINE bool PandaNode::
440 is_overall_hidden() const {
441  CDReader cdata(_cycler);
442  return ((cdata->_draw_show_mask | ~cdata->_draw_control_mask) & _overall_bit).is_zero();
443 }
444 
445 /**
446  * Sets or clears the hidden flag. When the hidden flag is true, the node and
447  * all of its children are invisible to all cameras, regardless of the setting
448  * of any draw masks. Setting the hidden flag to false restores the previous
449  * visibility as established by the draw masks.
450  *
451  * This actually works by twiddling the reserved _overall_bit in the node's
452  * draw mask, which has special meaning.
453  */
454 INLINE void PandaNode::
455 set_overall_hidden(bool hidden) {
456  if (hidden) {
458  } else {
460  }
461 }
462 
463 /**
464  * Returns the set of bits in draw_show_mask that are considered meaningful.
465  * See adjust_draw_mask().
466  */
467 INLINE DrawMask PandaNode::
468 get_draw_control_mask() const {
469  CDReader cdata(_cycler);
470  return cdata->_draw_control_mask;
471 }
472 
473 /**
474  * Returns the hide/show bits of this particular node. See
475  * adjust_draw_mask().
476  */
477 INLINE DrawMask PandaNode::
478 get_draw_show_mask() const {
479  CDReader cdata(_cycler);
480  return cdata->_draw_show_mask;
481 }
482 
483 /**
484  * Returns the "into" collide mask for this node.
485  */
487 get_into_collide_mask() const {
488  CDReader cdata(_cycler);
489  return cdata->_into_collide_mask;
490 }
491 
492 /**
493  * Reverses the effect of a previous call to set_bounds(), and allows the
494  * node's bounding volume to be automatically computed once more based on the
495  * contents of the node.
496  */
497 INLINE void PandaNode::
499  set_bounds(nullptr);
500 }
501 
502 /**
503  * Returns the node's internal bounding volume. This is the bounding volume
504  * around the node alone, without including children. If the user has called
505  * set_bounds(), it will be the specified bounding volume.
506  */
507 INLINE CPT(BoundingVolume) PandaNode::
508 get_internal_bounds(Thread *current_thread) const {
509  return get_internal_bounds(current_thread->get_pipeline_stage(),
510  current_thread);
511 }
512 
513 /**
514  * Returns the total number of vertices that will be rendered by this
515  * particular node alone, not accounting for its children.
516  *
517  * This may not include all vertices for certain dynamic effects.
518  */
519 INLINE int PandaNode::
520 get_internal_vertices(Thread *current_thread) const {
521  return get_internal_vertices(current_thread->get_pipeline_stage(),
522  current_thread);
523 }
524 
525 /**
526  * Returns true if the bounding volume of this node is stale and will be
527  * implicitly recomputed at the next call to get_bounds(), or false if it is
528  * fresh and need not be recomputed.
529  */
530 bool PandaNode::
531 is_bounds_stale() const {
532  CDReader cdata(_cycler);
533  return (cdata->_last_bounds_update != cdata->_next_update);
534 }
535 
536 /**
537  * Sets the "final" flag on this PandaNode. If this is true, than no bounding
538  * volume need be tested below it; a positive intersection with this node's
539  * bounding volume is deemed to be a positive intersection with all geometry
540  * inside.
541  *
542  * This is useful to quickly force a larger bounding volume around a node when
543  * the GeomNodes themselves are inaccurate for some reason, without forcing a
544  * recompute of every nested bounding volume. It's also helpful when the
545  * bounding volume is tricked by some special properties, like billboards,
546  * that may move geometry out of its bounding volume otherwise.
547  */
548 INLINE void PandaNode::
549 set_final(bool flag) {
550  CDWriter cdata(_cycler);
551  cdata->_final_bounds = flag;
553 }
554 
555 /**
556  * Returns the current state of the "final" flag. Initially, this flag is off
557  * (false), but it may be changed by an explicit call to set_final(). See
558  * set_final().
559  */
560 INLINE bool PandaNode::
561 is_final(Thread *current_thread) const {
562  CDReader cdata(_cycler, current_thread);
563  return cdata->_final_bounds;
564 }
565 
566 /**
567  * Returns the union of all of the enum FancyBits values corresponding to the
568  * various "fancy" attributes that are set on the node. If this returns 0,
569  * the node has nothing interesting about it. This is intended to speed
570  * traversal by quickly skipping past nodes that don't particularly affect the
571  * render state.
572  */
573 INLINE int PandaNode::
574 get_fancy_bits(Thread *current_thread) const {
575  CDReader cdata(_cycler, current_thread);
576  return cdata->_fancy_bits;
577 }
578 
579 /**
580  * Returns the node's user bounding volume. This is the bounding volume
581  * specified with get_bounds(). This will return NULL if the user bounding
582  * volume has never been set.
583  */
584 INLINE CPT(BoundingVolume) PandaNode::
585 get_user_bounds(int pipeline_stage, Thread *current_thread) const {
586  CDStageReader cdata(_cycler, pipeline_stage, current_thread);
587  return cdata->_user_bounds;
588 }
589 
590 /**
591  * Indicates that the bounding volume, or something that influences the
592  * bounding volume (or any of the other things stored in CData, like
593  * net_collide_mask), may have changed for this node, and that it must be
594  * recomputed.
595  */
596 INLINE void PandaNode::
597 mark_bounds_stale(int pipeline_stage, Thread *current_thread) const {
598  // We check whether it is already marked stale. If so, we don't have to
599  // make the call to force_bounds_stale().
600  bool is_stale_bounds;
601  {
602  CDStageReader cdata(_cycler, pipeline_stage, current_thread);
603  is_stale_bounds = (cdata->_last_update != cdata->_next_update);
604  }
605  // It's important that we don't hold the lock during the call to
606  // force_bounds_stale().
607  if (!is_stale_bounds) {
608  ((PandaNode *)this)->force_bounds_stale(pipeline_stage, current_thread);
609  }
610 }
611 
612 /**
613  * Should be called by a derived class to mark the internal bounding volume
614  * stale, so that recompute_internal_bounds() will be called when the bounding
615  * volume is next requested.
616  */
617 INLINE void PandaNode::
618 mark_internal_bounds_stale(int pipeline_stage, Thread *current_thread) {
619  {
620  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
621  ++cdata->_internal_bounds_mark;
622  }
623  mark_bounds_stale(pipeline_stage, current_thread);
624 }
625 
626 /**
627  * Returns an object that can be used to walk through the list of children of
628  * the node. When you intend to visit multiple children, using this is
629  * slightly faster than calling get_child() directly on the PandaNode, since
630  * this object avoids reopening the PipelineCycler each time.
631  *
632  * This object also protects you from self-modifying loops (e.g. adding or
633  * removing children during traversal), since a virtual copy of the children
634  * is made ahead of time. The virtual copy is fast--it is a form of copy-on-
635  * write, so the list is not actually copied unless it is modified during the
636  * traversal.
637  */
639 get_children(Thread *current_thread) const {
640  CDReader cdata(_cycler, current_thread);
641  return Children(cdata);
642 }
643 
644 /**
645  * Returns an object that can be used to walk through the list of children of
646  * the node. When you intend to visit multiple children, using this is
647  * slightly faster than calling get_stashed() directly on the PandaNode, since
648  * this object avoids reopening the PipelineCycler each time.
649  *
650  * This object also protects you from self-modifying loops (e.g. adding or
651  * removing children during traversal), since a virtual copy of the children
652  * is made ahead of time. The virtual copy is fast--it is a form of copy-on-
653  * write, so the list is not actually copied unless it is modified during the
654  * traversal.
655  */
657 get_stashed(Thread *current_thread) const {
658  CDReader cdata(_cycler, current_thread);
659  return Stashed(cdata);
660 }
661 
662 /**
663  * Returns an object that can be used to walk through the list of parents of
664  * the node, similar to get_children() and get_stashed().
665  */
667 get_parents(Thread *current_thread) const {
668  CDReader cdata(_cycler, current_thread);
669  return Parents(cdata);
670 }
671 
672 /**
673  * The private implementation of find_parent().
674  */
675 INLINE int PandaNode::
676 do_find_parent(PandaNode *node, const CData *cdata) const {
677  CPT(Up) up = cdata->get_up();
678  Up::const_iterator ui = up->find(UpConnection(node));
679  if (ui == up->end()) {
680  return -1;
681  }
682  return ui - up->begin();
683 }
684 
685 /**
686  * Ensures that attaching the indicated child node to this node would not
687  * introduce a cycle in the graph. Returns true if the attachment is valid,
688  * false otherwise.
689  */
690 INLINE bool PandaNode::
691 verify_child_no_cycles(PandaNode *child_node) {
692 #ifndef NDEBUG
693  if (detect_graph_cycles) {
694  if (!find_node_above(child_node)) {
695  return true;
696  }
697  report_cycle(child_node);
698  return false;
699  }
700 #endif // NDEBUG
701  return true;
702 }
703 
704 /**
705  * Sets the dirty_prev_transform flag, and adds the node to the
706  * _dirty_prev_transforms chain. Assumes _dirty_prev_transforms._lock is
707  * already held.
708  */
709 INLINE void PandaNode::
710 do_set_dirty_prev_transform() {
711  nassertv(_dirty_prev_transforms._lock.debug_is_locked());
712  if (!_dirty_prev_transform) {
713  LinkedListNode::insert_before(&_dirty_prev_transforms);
714  _dirty_prev_transform = true;
715  }
716 }
717 
718 /**
719  * Clears the dirty_prev_transform flag, and removes the node from the
720  * _dirty_prev_transforms chain. Assumes _dirty_prev_transforms._lock is
721  * already held.
722  */
723 INLINE void PandaNode::
724 do_clear_dirty_prev_transform() {
725  nassertv(_dirty_prev_transforms._lock.debug_is_locked());
726  if (_dirty_prev_transform) {
727  LinkedListNode::remove_from_list();
728  _dirty_prev_transform = false;
729  }
730 }
731 
732 /**
733  *
734  */
735 INLINE PandaNode::DownConnection::
736 DownConnection(PandaNode *child, int sort) :
737  _child(child),
738  _sort(sort)
739 {
740 }
741 
742 /**
743  * Provides a partial ordering on the children of a node so that they are
744  * ranked first in sort order, and then (by virtue of the ordered_vector) in
745  * the order they were added.
746  */
747 INLINE bool PandaNode::DownConnection::
748 operator < (const DownConnection &other) const {
749  return _sort < other._sort;
750 }
751 
752 /**
753  *
754  */
755 INLINE PandaNode *PandaNode::DownConnection::
756 get_child() const {
757  return _child;
758 }
759 
760 /**
761  * This is only called by PandaNode::replace_child().
762  */
763 INLINE void PandaNode::DownConnection::
765  _child = child;
766 }
767 
768 /**
769  *
770  */
771 INLINE int PandaNode::DownConnection::
772 get_sort() const {
773  return _sort;
774 }
775 
776 /**
777  *
778  */
779 INLINE PandaNode::UpConnection::
780 UpConnection(PandaNode *parent) :
781  _parent(parent)
782 {
783 }
784 
785 /**
786  * Sorts the up connections of a node by pointer. This is different from the
787  * down connections of a node, which are sorted by the specified _sort number.
788  * This makes it easy to locate a particular parent of a node by pointer, or
789  * to test for a parent-child relationship given two node pointers.
790  */
791 INLINE bool PandaNode::UpConnection::
792 operator < (const UpConnection &other) const {
793  return _parent < other._parent;
794 }
795 
796 /**
797  *
798  */
799 INLINE PandaNode *PandaNode::UpConnection::
800 get_parent() const {
801  return _parent;
802 }
803 
804 /**
805  *
806  */
807 INLINE PandaNode::BoundsData::
808 BoundsData() :
809  _internal_bounds(nullptr),
810  _internal_vertices(0)
811 {
812  ++_internal_bounds_mark;
813 }
814 
815 /**
816  *
817  */
818 INLINE PandaNode::BoundsData::
819 BoundsData(const PandaNode::BoundsData &copy) :
820  _internal_bounds(copy._internal_bounds),
821  _internal_vertices(copy._internal_vertices),
822  _internal_bounds_mark(copy._internal_bounds_mark),
823  _internal_bounds_computed(copy._internal_bounds_computed)
824 {
825 }
826 
827 /**
828  * Copies just the BoundsData part of the structure.
829  */
830 INLINE void PandaNode::BoundsData::
831 copy_bounds(const PandaNode::BoundsData &copy) {
832  _internal_bounds = copy._internal_bounds;
833  _internal_vertices = copy._internal_vertices;
834  _internal_bounds_mark = copy._internal_bounds_mark;
835  _internal_bounds_computed = copy._internal_bounds_computed;
836 }
837 
838 /**
839  * Internal function to set (if value is true) or clear (if value is false)
840  * the indicated bit(s) in the _fancy_bits member.
841  */
842 INLINE void PandaNode::CData::
843 set_fancy_bit(int bits, bool value) {
844  if (value) {
845  _fancy_bits |= bits;
846  } else {
847  _fancy_bits &= ~bits;
848  }
849 }
850 
851 /**
852  * Returns a read-only pointer to the _down list.
853  */
854 INLINE CPT(PandaNode::Down) PandaNode::CData::
855 get_down() const {
856  return _down.get_read_pointer();
857 }
858 
859 /**
860  * Returns a modifiable, unique pointer to the _down list.
861  */
862 INLINE PT(PandaNode::Down) PandaNode::CData::
863 modify_down() {
864  return _down.get_write_pointer();
865 }
866 
867 /**
868  * Returns a read-only pointer to the _stashed list.
869  */
870 INLINE CPT(PandaNode::Down) PandaNode::CData::
871 get_stashed() const {
872  return _stashed.get_read_pointer();
873 }
874 
875 /**
876  * Returns a modifiable, unique pointer to the _stashed list.
877  */
878 INLINE PT(PandaNode::Down) PandaNode::CData::
879 modify_stashed() {
880  return _stashed.get_write_pointer();
881 }
882 
883 /**
884  * Returns a read-only pointer to the _up list.
885  */
886 INLINE CPT(PandaNode::Up) PandaNode::CData::
887 get_up() const {
888  return _up.get_read_pointer();
889 }
890 
891 /**
892  * Returns a modifiable, unique pointer to the _up list.
893  */
894 INLINE PT(PandaNode::Up) PandaNode::CData::
895 modify_up() {
896  return _up.get_write_pointer();
897 }
898 
899 /**
900  *
901  */
902 INLINE PandaNode::Children::
903 Children() {
904 }
905 
906 /**
907  *
908  */
909 INLINE PandaNode::Children::
910 Children(const PandaNode::CData *cdata) :
911  _down(cdata->get_down())
912 {
913 }
914 
915 /**
916  *
917  */
918 INLINE PandaNode::Children::
919 Children(const PandaNode::Children &copy) :
920  _down(copy._down)
921 {
922 }
923 
924 /**
925  *
926  */
927 INLINE void PandaNode::Children::
928 operator = (const PandaNode::Children &copy) {
929  _down = copy._down;
930 }
931 
932 /**
933  *
934  */
935 INLINE PandaNode::Children::
936 Children(PandaNode::Children &&from) noexcept :
937  _down(std::move(from._down))
938 {
939 }
940 
941 /**
942  *
943  */
944 INLINE void PandaNode::Children::
945 operator = (PandaNode::Children &&from) noexcept {
946  _down = std::move(from._down);
947 }
948 
949 /**
950  * Returns the number of children of the node.
951  */
952 INLINE size_t PandaNode::Children::
954  nassertr(_down != nullptr, 0);
955  return _down->size();
956 }
957 
958 /**
959  * Returns the nth child of the node.
960  */
962 get_child(size_t n) const {
963  nassertr(_down != nullptr, nullptr);
964  nassertr(n < (size_t)_down->size(), nullptr);
965  return (*_down)[n].get_child();
966 }
967 
968 /**
969  * Returns the sort index of the nth child node of this node (that is, the
970  * number that was passed to add_child()). See get_num_children().
971  */
972 INLINE int PandaNode::Children::
973 get_child_sort(size_t n) const {
974  nassertr(_down != nullptr, -1);
975  nassertr(n < _down->size(), -1);
976  return (*_down)[n].get_sort();
977 }
978 
979 /**
980  *
981  */
982 INLINE PandaNode::Stashed::
983 Stashed() {
984 }
985 
986 /**
987  *
988  */
989 INLINE PandaNode::Stashed::
990 Stashed(const PandaNode::CData *cdata) :
991  _stashed(cdata->get_stashed())
992 {
993 }
994 
995 /**
996  *
997  */
998 INLINE PandaNode::Stashed::
999 Stashed(const PandaNode::Stashed &copy) :
1000  _stashed(copy._stashed)
1001 {
1002 }
1003 
1004 /**
1005  *
1006  */
1007 INLINE void PandaNode::Stashed::
1008 operator = (const PandaNode::Stashed &copy) {
1009  _stashed = copy._stashed;
1010 }
1011 
1012 /**
1013  *
1014  */
1015 INLINE PandaNode::Stashed::
1016 Stashed(PandaNode::Stashed &&from) noexcept :
1017  _stashed(std::move(from._stashed))
1018 {
1019 }
1020 
1021 /**
1022  *
1023  */
1024 INLINE void PandaNode::Stashed::
1025 operator = (PandaNode::Stashed &&from) noexcept {
1026  _stashed = std::move(from._stashed);
1027 }
1028 
1029 /**
1030  * Returns the number of stashed children of the node.
1031  */
1032 INLINE size_t PandaNode::Stashed::
1034  nassertr(_stashed != nullptr, 0);
1035  return _stashed->size();
1036 }
1037 
1038 /**
1039  * Returns the nth stashed child of the node.
1040  */
1042 get_stashed(size_t n) const {
1043  nassertr(_stashed != nullptr, nullptr);
1044  nassertr(n < _stashed->size(), nullptr);
1045  return (*_stashed)[n].get_child();
1046 }
1047 
1048 /**
1049  * Returns the sort index of the nth child node of this node (that is, the
1050  * number that was passed to add_child()). See get_num_stashed().
1051  */
1052 INLINE int PandaNode::Stashed::
1053 get_stashed_sort(size_t n) const {
1054  nassertr(_stashed != nullptr, -1);
1055  nassertr(n < _stashed->size(), -1);
1056  return (*_stashed)[n].get_sort();
1057 }
1058 
1059 /**
1060  *
1061  */
1062 INLINE PandaNode::Parents::
1063 Parents() {
1064 }
1065 
1066 /**
1067  *
1068  */
1069 INLINE PandaNode::Parents::
1070 Parents(const PandaNode::CData *cdata) :
1071  _up(cdata->get_up())
1072 {
1073 }
1074 
1075 /**
1076  *
1077  */
1078 INLINE PandaNode::Parents::
1079 Parents(const PandaNode::Parents &copy) :
1080  _up(copy._up)
1081 {
1082 }
1083 
1084 /**
1085  *
1086  */
1087 INLINE void PandaNode::Parents::
1088 operator = (const PandaNode::Parents &copy) {
1089  _up = copy._up;
1090 }
1091 
1092 /**
1093  *
1094  */
1095 INLINE PandaNode::Parents::
1096 Parents(PandaNode::Parents &&from) noexcept :
1097  _up(std::move(from._up))
1098 {
1099 }
1100 
1101 /**
1102  *
1103  */
1104 INLINE void PandaNode::Parents::
1105 operator = (PandaNode::Parents &&from) noexcept {
1106  _up = std::move(from._up);
1107 }
1108 
1109 /**
1110  * Returns the number of parents of the node.
1111  */
1112 INLINE size_t PandaNode::Parents::
1114  nassertr(_up != nullptr, 0);
1115  return _up->size();
1116 }
1117 
1118 /**
1119  * Returns the nth parent of the node.
1120  */
1122 get_parent(size_t n) const {
1123  nassertr(_up != nullptr, nullptr);
1124  nassertr(n < _up->size(), nullptr);
1125  return (*_up)[n].get_parent();
1126 }
1127 
1128 /**
1129  *
1130  */
1131 INLINE PandaNodePipelineReader::
1132 PandaNodePipelineReader(const PandaNode *node, Thread *current_thread) :
1133  _node(node),
1134  _current_thread(current_thread),
1135  _cdata(node->_cycler.read_unlocked(current_thread))
1136 {
1137 #ifdef _DEBUG
1138  nassertv(_node->test_ref_count_nonzero());
1139 #endif // _DEBUG
1140 
1141 #ifdef DO_PIPELINING
1142  // We node_ref the CData pointer, so that if anyone makes changes to the
1143  // PandaNode while we hold this pointer, it will force a copy--so that this
1144  // object will remain unchanged (if out-of-date).
1145  _cdata->node_ref();
1146 #endif // DO_PIPELINING
1147 }
1148 
1149 /**
1150  *
1151  */
1152 INLINE PandaNodePipelineReader::
1153 PandaNodePipelineReader(const PandaNodePipelineReader &copy) :
1154  _node(copy._node),
1155  _current_thread(copy._current_thread),
1156  _cdata(copy._cdata)
1157 {
1158 #ifdef DO_PIPELINING
1159  _cdata->node_ref();
1160 #endif // DO_PIPELINING
1161 
1162  /*
1163  if (_cdata != (PandaNode::CData *)NULL) {
1164  _node->_cycler.increment_read(_cdata);
1165  }
1166  */
1167 }
1168 
1169 /**
1170  *
1171  */
1172 INLINE void PandaNodePipelineReader::
1173 operator = (const PandaNodePipelineReader &copy) {
1174  nassertv(_current_thread == copy._current_thread);
1175 
1176  /*
1177  if (_cdata != (PandaNode::CData *)NULL) {
1178  _node->_cycler.release_read(_cdata);
1179  }
1180  */
1181 
1182 #ifdef DO_PIPELINING
1183  node_unref_delete((CycleData *)_cdata);
1184 #endif // DO_PIPELINING
1185 
1186  _node = copy._node;
1187  _cdata = copy._cdata;
1188 
1189 #ifdef DO_PIPELINING
1190  _cdata->node_ref();
1191 #endif // DO_PIPELINING
1192 
1193  /*
1194  if (_cdata != (PandaNode::CData *)NULL) {
1195  _node->_cycler.increment_read(_cdata);
1196  }
1197  */
1198 }
1199 
1200 /**
1201  *
1202  */
1203 INLINE PandaNodePipelineReader::
1204 ~PandaNodePipelineReader() {
1205  /*
1206  if (_cdata != (PandaNode::CData *)NULL) {
1207  _node->_cycler.release_read(_cdata);
1208  }
1209  */
1210 
1211 #ifdef DO_PIPELINING
1212  node_unref_delete((CycleData *)_cdata);
1213 #endif // DO_PIPELINING
1214 
1215 #ifdef _DEBUG
1216  _node = nullptr;
1217  _cdata = nullptr;
1218 #endif // _DEBUG
1219 }
1220 
1221 /**
1222  *
1223  */
1224 INLINE const PandaNode *PandaNodePipelineReader::
1225 get_node() const {
1226  return _node;
1227 }
1228 
1229 /**
1230  *
1231  */
1232 INLINE Thread *PandaNodePipelineReader::
1233 get_current_thread() const {
1234  return _current_thread;
1235 }
1236 
1237 /**
1238  * Releases the lock on this object. No future calls will be valid on this
1239  * object.
1240  */
1241 INLINE void PandaNodePipelineReader::
1243  /*
1244  if (_cdata != (PandaNode::CData *)NULL) {
1245  _node->_cycler.release_read(_cdata);
1246  _cdata = NULL;
1247  }
1248  */
1249 }
1250 
1251 /**
1252  * Computes the result of applying this node's draw masks to a running draw
1253  * mask, as during a traversal.
1254  */
1255 INLINE void PandaNodePipelineReader::
1256 compose_draw_mask(DrawMask &running_draw_mask) const {
1257  nassertv(_cdata != nullptr);
1258  running_draw_mask = (running_draw_mask & ~_cdata->_draw_control_mask) |
1259  (_cdata->_draw_show_mask & _cdata->_draw_control_mask);
1260 }
1261 
1262 /**
1263  * Compares the running draw mask computed during a traversal with this node's
1264  * net draw masks. Returns true if the node should be traversed into, or
1265  * false if there is nothing at this level or below that will be visible to
1266  * the indicated camera_mask.
1267  */
1268 INLINE bool PandaNodePipelineReader::
1269 compare_draw_mask(DrawMask running_draw_mask, DrawMask camera_mask) const {
1270  nassertr(_cdata != nullptr, false);
1271  nassertr(_cdata->_last_update == _cdata->_next_update, false);
1272 
1273  // As a special case, if net_draw_show_mask is all 0, it means either that
1274  // all nodes under this node are hidden to all cameras, or that none of them
1275  // are renderable nodes (or some combination). In either case, we might as
1276  // well short-circuit.
1277  if (_cdata->_net_draw_show_mask.is_zero()) {
1278  return false;
1279  }
1280 
1281  DrawMask net_draw_control_mask, net_draw_show_mask;
1282  net_draw_control_mask = _cdata->_net_draw_control_mask;
1283  net_draw_show_mask = _cdata->_net_draw_show_mask;
1284 
1285  // Now the bits that are not in net_draw_control_mask--that is, those bits
1286  // that are not changed by any of the nodes at this level and below--are
1287  // taken from running_draw_mask, which is inherited from above. On the
1288  // other hand, the bits that *are* in net_draw_control_mask--those bits that
1289  // are changed by any of the nodes at this level and below--are taken from
1290  // net_draw_show_mask, which is propagated upwards from below.
1291 
1292  // This way, we will traverse into this node if it has any children which
1293  // want to be visited by the traversal, but we will avoid traversing into it
1294  // if all of its children are hidden to this camera.
1295  DrawMask compare_mask = (running_draw_mask & ~net_draw_control_mask) | (net_draw_show_mask & net_draw_control_mask);
1296 
1297  return !((compare_mask & PandaNode::_overall_bit).is_zero()) && !((compare_mask & camera_mask).is_zero());
1298 }
1299 
1300 /**
1301  * Returns the number of parent nodes this node has. If this number is
1302  * greater than 1, the node has been multiply instanced. The order of the
1303  * parent nodes is not meaningful and is not related to the order in which the
1304  * node was instanced to them.
1305  */
1306 INLINE int PandaNodePipelineReader::
1308  return _cdata->get_up()->size();
1309 }
1310 
1311 /**
1312  * Returns the nth parent node of this node. See get_num_parents(). Also see
1313  * get_parents(), if your intention is to iterate through the complete list of
1314  * parents; get_parents() is preferable in this case.
1315  */
1317 get_parent(int n) const {
1318  CPT(PandaNode::Up) up = _cdata->get_up();
1319  nassertr(n >= 0 && n < (int)up->size(), nullptr);
1320  return (*up)[n].get_parent();
1321 }
1322 
1323 /**
1324  * Returns the index of the indicated parent node, if it is a parent, or -1 if
1325  * it is not.
1326  */
1327 INLINE int PandaNodePipelineReader::
1328 find_parent(PandaNode *node) const {
1329  return _node->do_find_parent(node, _cdata);
1330 }
1331 
1332 /**
1333  * Returns the number of child nodes this node has. The order of the child
1334  * nodes *is* meaningful and is based on the sort number that was passed to
1335  * add_child(), and also on the order in which the nodes were added.
1336  */
1337 INLINE int PandaNodePipelineReader::
1339  return _cdata->get_down()->size();
1340 }
1341 
1342 /**
1343  * Returns the nth child node of this node. See get_num_children(). Also see
1344  * get_children(), if your intention is to iterate through the complete list
1345  * of children; get_children() is preferable in this case.
1346  */
1348 get_child(int n) const {
1349  CPT(PandaNode::Down) down = _cdata->get_down();
1350  nassertr(n >= 0 && n < (int)down->size(), nullptr);
1351  return (*down)[n].get_child();
1352 }
1353 
1354 /**
1355  * Returns the sort index of the nth child node of this node (that is, the
1356  * number that was passed to add_child()). See get_num_children().
1357  */
1358 INLINE int PandaNodePipelineReader::
1359 get_child_sort(int n) const {
1360  CPT(PandaNode::Down) down = _cdata->get_down();
1361  nassertr(n >= 0 && n < (int)down->size(), -1);
1362  return (*down)[n].get_sort();
1363 }
1364 
1365 /**
1366  * Returns the index of the indicated child node, if it is a child, or -1 if
1367  * it is not.
1368  */
1369 INLINE int PandaNodePipelineReader::
1370 find_child(PandaNode *node) const {
1371  return _node->do_find_child(node, _cdata->get_down());
1372 }
1373 
1374 /**
1375  * Returns the number of stashed nodes this node has. These are former
1376  * children of the node that have been moved to the special stashed list via
1377  * stash_child().
1378  */
1379 INLINE int PandaNodePipelineReader::
1381  return _cdata->get_stashed()->size();
1382 }
1383 
1384 /**
1385  * Returns the nth stashed child of this node. See get_num_stashed(). Also
1386  * see get_stashed(), if your intention is to iterate through the complete
1387  * list of stashed children; get_stashed() is preferable in this case.
1388  */
1390 get_stashed(int n) const {
1391  CPT(PandaNode::Down) stashed = _cdata->get_stashed();
1392  nassertr(n >= 0 && n < (int)stashed->size(), nullptr);
1393  return (*stashed)[n].get_child();
1394 }
1395 
1396 /**
1397  * Returns the sort index of the nth stashed node of this node (that is, the
1398  * number that was passed to add_child()). See get_num_stashed().
1399  */
1400 INLINE int PandaNodePipelineReader::
1401 get_stashed_sort(int n) const {
1402  CPT(PandaNode::Down) stashed = _cdata->get_stashed();
1403  nassertr(n >= 0 && n < (int)stashed->size(), -1);
1404  return (*stashed)[n].get_sort();
1405 }
1406 
1407 /**
1408  * Returns the index of the indicated stashed node, if it is a stashed child,
1409  * or -1 if it is not.
1410  */
1411 INLINE int PandaNodePipelineReader::
1412 find_stashed(PandaNode *node) const {
1413  return _node->do_find_child(node, _cdata->get_stashed());
1414 }
1415 
1416 /**
1417  * Returns the complete RenderState that will be applied to all nodes at this
1418  * level and below, as set on this node. This returns only the RenderState
1419  * set on this particular node, and has nothing to do with state that might be
1420  * inherited from above.
1421  */
1423 get_state() const {
1424  return _cdata->_state;
1425 }
1426 
1427 /**
1428  * Returns the complete RenderEffects that will be applied to this node.
1429  */
1431 get_effects() const {
1432  return _cdata->_effects;
1433 }
1434 
1435 /**
1436  * Returns the transform that has been set on this particular node. This is
1437  * not the net transform from the root, but simply the transform on this
1438  * particular node.
1439  */
1441 get_transform() const {
1442  return _cdata->_transform;
1443 }
1444 
1445 /**
1446  * Returns the transform that has been set as this node's "previous" position.
1447  * See set_prev_transform().
1448  */
1451  return _cdata->_prev_transform;
1452 }
1453 
1454 /**
1455  * Retrieves the user-defined value that was previously set on this node for
1456  * the particular key, if any. If no value has been previously set, returns
1457  * the empty string.
1458  */
1459 INLINE std::string PandaNodePipelineReader::
1460 get_tag(const std::string &key) const {
1461  int index = _cdata->_tag_data.find(key);
1462  if (index >= 0) {
1463  return _cdata->_tag_data.get_data((size_t)index);
1464  } else {
1465  return std::string();
1466  }
1467 }
1468 
1469 /**
1470  * Returns true if a value has been defined on this node for the particular
1471  * key (even if that value is the empty string), or false if no value has been
1472  * set.
1473  */
1474 INLINE bool PandaNodePipelineReader::
1475 has_tag(const std::string &key) const {
1476  return _cdata->_tag_data.find(key) >= 0;
1477 }
1478 
1479 /**
1480  * Returns the union of all into_collide_mask() values set at CollisionNodes
1481  * at this level and below.
1482  */
1485  nassertr(_cdata->_last_update == _cdata->_next_update, _cdata->_net_collide_mask);
1486  return _cdata->_net_collide_mask;
1487 }
1488 
1489 /**
1490  * Returns a ClipPlaneAttrib which represents the union of all of the clip
1491  * planes that have been turned *off* at this level and below.
1492  */
1495  nassertr(_cdata->_last_update == _cdata->_next_update, _cdata->_off_clip_planes);
1496  return _cdata->_off_clip_planes;
1497 }
1498 
1499 /**
1500  * Returns the external bounding volume of this node: a bounding volume that
1501  * contains the user bounding volume, the internal bounding volume, and all of
1502  * the children's bounding volumes.
1503  */
1505 get_bounds() const {
1506  nassertr(_cdata->_last_bounds_update == _cdata->_next_update, _cdata->_external_bounds);
1507  return _cdata->_external_bounds;
1508 }
1509 
1510 /**
1511  * Returns the total number of vertices that will be rendered by this node and
1512  * all of its descendents.
1513  *
1514  * This is not necessarily an accurate count of vertices that will actually be
1515  * rendered, since this will include all vertices of all LOD's, and it will
1516  * also include hidden nodes. It may also omit or only approximate certain
1517  * kinds of dynamic geometry. However, it will not include stashed nodes.
1518  */
1519 INLINE int PandaNodePipelineReader::
1521  nassertr(_cdata->_last_bounds_update == _cdata->_next_update, _cdata->_nested_vertices);
1522  return _cdata->_nested_vertices;
1523 }
1524 
1525 /**
1526  * Returns the current state of the "final" flag. Initially, this flag is off
1527  * (false), but it may be changed by an explicit call to set_final(). See
1528  * set_final().
1529  */
1530 INLINE bool PandaNodePipelineReader::
1531 is_final() const {
1532  return _cdata->_final_bounds;
1533 }
1534 
1535 
1536 /**
1537  * Returns the union of all of the enum FancyBits values corresponding to the
1538  * various "fancy" attributes that are set on the node. If this returns 0,
1539  * the node has nothing interesting about it. This is intended to speed
1540  * traversal by quickly skipping past nodes that don't particularly affect the
1541  * render state.
1542  */
1543 INLINE int PandaNodePipelineReader::
1545  return _cdata->_fancy_bits;
1546 }
1547 
1548 /**
1549  * Returns an object that can be used to walk through the list of children of
1550  * the node. When you intend to visit multiple children, using this is
1551  * slightly faster than calling get_child() directly on the PandaNode, since
1552  * this object avoids reopening the PipelineCycler each time.
1553  *
1554  * This object also protects you from self-modifying loops (e.g. adding or
1555  * removing children during traversal), since a virtual copy of the children
1556  * is made ahead of time. The virtual copy is fast--it is a form of copy-on-
1557  * write, so the list is not actually copied unless it is modified during the
1558  * traversal.
1559  */
1561 get_children() const {
1562  return PandaNode::Children(_cdata);
1563 }
1564 
1565 /**
1566  * Returns an object that can be used to walk through the list of children of
1567  * the node. When you intend to visit multiple children, using this is
1568  * slightly faster than calling get_stashed() directly on the PandaNode, since
1569  * this object avoids reopening the PipelineCycler each time.
1570  *
1571  * This object also protects you from self-modifying loops (e.g. adding or
1572  * removing children during traversal), since a virtual copy of the children
1573  * is made ahead of time. The virtual copy is fast--it is a form of copy-on-
1574  * write, so the list is not actually copied unless it is modified during the
1575  * traversal.
1576  */
1578 get_stashed() const {
1579  return PandaNode::Stashed(_cdata);
1580 }
1581 
1582 /**
1583  * Returns an object that can be used to walk through the list of parents of
1584  * the node, similar to get_children() and get_stashed().
1585  */
1587 get_parents() const {
1588  return PandaNode::Parents(_cdata);
1589 }
1590 
1591 /**
1592  *
1593  */
1594 INLINE PandaNode::BamReaderAuxDataDown::
1595 BamReaderAuxDataDown() :
1596  _down_list(PandaNode::get_class_type())
1597 {
1598 }
PandaNode::set_effects
set_effects
Sets the complete RenderEffects that will be applied this node.
Definition: pandaNode.h:178
PandaNode::get_parent
get_parent
Returns the nth parent node of this node.
Definition: pandaNode.h:118
PandaNode::find_parent
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
PandaNode::adjust_draw_mask
void adjust_draw_mask(DrawMask show_mask, DrawMask hide_mask, DrawMask clear_mask)
Adjusts the hide/show bits of this particular node.
Definition: pandaNode.cxx:1585
RenderEffects
This represents a unique collection of RenderEffect objects that correspond to a particular renderabl...
Definition: renderEffects.h:41
CycleData
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:47
PandaNode::set_bounds
void set_bounds(const BoundingVolume *volume)
Resets the bounding volume so that it is the indicated volume.
Definition: pandaNode.cxx:1907
PandaNodePipelineReader::is_final
bool is_final() const
Returns the current state of the "final" flag.
Definition: pandaNode.I:1531
PandaNodePipelineReader::get_child_sort
int get_child_sort(int n) const
Returns the sort index of the nth child node of this node (that is, the number that was passed to add...
Definition: pandaNode.I:1359
PandaNode::Stashed::get_stashed
PandaNode * get_stashed(size_t n) const
Returns the nth stashed child of the node.
Definition: pandaNode.I:1042
PandaNode::get_stashed_sort
int get_stashed_sort(int n, Thread *current_thread=Thread::get_current_thread()) const
Returns the sort index of the nth stashed node of this node (that is, the number that was passed to a...
Definition: pandaNode.I:166
RenderEffect
This is the base class for a number of special render effects that may be set on scene graph nodes to...
Definition: renderEffect.h:48
PandaNodePipelineReader::get_prev_transform
const TransformState * get_prev_transform() const
Returns the transform that has been set as this node's "previous" position.
Definition: pandaNode.I:1450
PandaNodePipelineReader::get_nested_vertices
int get_nested_vertices() const
Returns the total number of vertices that will be rendered by this node and all of its descendents.
Definition: pandaNode.I:1520
PandaNodePipelineReader::compare_draw_mask
bool compare_draw_mask(DrawMask running_draw_mask, DrawMask camera_mask) const
Compares the running draw mask computed during a traversal with this node's net draw masks.
Definition: pandaNode.I:1269
PandaNodePipelineReader::get_children
PandaNode::Children get_children() const
Returns an object that can be used to walk through the list of children of the node.
Definition: pandaNode.I:1561
PandaNodePipelineReader::get_parents
PandaNode::Parents get_parents() const
Returns an object that can be used to walk through the list of parents of the node,...
Definition: pandaNode.I:1587
CPT
CPT(RenderAttrib) PandaNode
Returns the render attribute of the indicated type, if it is defined on the node, or NULL if it is no...
Definition: pandaNode.I:189
PandaNodePipelineReader::find_child
int find_child(PandaNode *node) const
Returns the index of the indicated child node, if it is a child, or -1 if it is not.
Definition: pandaNode.I:1370
PandaNodePipelineReader::get_effects
const RenderEffects * get_effects() const
Returns the complete RenderEffects that will be applied to this node.
Definition: pandaNode.I:1431
PandaNode::find_child
int find_child(PandaNode *node, Thread *current_thread=Thread::get_current_thread()) const
Returns the index of the indicated child node, if it is a child, or -1 if it is not.
Definition: pandaNode.I:90
PandaNodePipelineReader::get_stashed_sort
int get_stashed_sort(int n) const
Returns the sort index of the nth stashed node of this node (that is, the number that was passed to a...
Definition: pandaNode.I:1401
PandaNode::Parents
Definition: pandaNode.h:752
RenderAttrib
This is the base class for a number of render attributes (other than transform) that may be set on sc...
Definition: renderAttrib.h:51
PandaNode::Parents::get_parent
PandaNode * get_parent(size_t n) const
Returns the nth parent of the node.
Definition: pandaNode.I:1122
PandaNodePipelineReader
Encapsulates the data from a PandaNode, pre-fetched for one stage of the pipeline.
Definition: pandaNode.h:840
PandaNode::Children::get_child
PandaNode * get_child(size_t n) const
Returns the nth child of the node.
Definition: pandaNode.I:962
PandaNode::set_state
set_state
Sets the complete RenderState that will be applied to all nodes at this level and below.
Definition: pandaNode.h:173
PandaNode::get_child_sort
int get_child_sort(int n, Thread *current_thread=Thread::get_current_thread()) const
Returns the sort index of the nth child node of this node (that is, the number that was passed to add...
Definition: pandaNode.I:78
BitMask< uint32_t, 32 >
PandaNode::unstash_child
bool unstash_child(PandaNode *child_node, Thread *current_thread=Thread::get_current_thread())
Returns the indicated stashed node to normal child status.
Definition: pandaNode.I:128
PandaNodePipelineReader::get_state
const RenderState * get_state() const
Returns the complete RenderState that will be applied to all nodes at this level and below,...
Definition: pandaNode.I:1423
PandaNode::set_overall_hidden
set_overall_hidden
Sets or clears the hidden flag.
Definition: pandaNode.h:248
PandaNodePipelineReader::find_parent
int find_parent(PandaNode *node) const
Returns the index of the indicated parent node, if it is a parent, or -1 if it is not.
Definition: pandaNode.I:1328
PandaNodePipelineReader::has_tag
bool has_tag(const std::string &key) const
Returns true if a value has been defined on this node for the particular key (even if that value is t...
Definition: pandaNode.I:1475
PandaNodePipelineReader::get_parent
PandaNode * get_parent(int n) const
Returns the nth parent node of this node.
Definition: pandaNode.I:1317
CopyOnWriteObj1< DownList, TypeHandle >
PandaNode::get_all_camera_mask
get_all_camera_mask
Returns a DrawMask that is appropriate for rendering to all cameras.
Definition: pandaNode.h:247
PandaNode::get_children
get_children
Returns an object that can be used to walk through the list of children of the node.
Definition: pandaNode.h:782
PandaNode::get_draw_show_mask
get_draw_show_mask
Returns the hide/show bits of this particular node.
Definition: pandaNode.h:256
PandaNodePipelineReader::compose_draw_mask
void compose_draw_mask(DrawMask &running_draw_mask) const
Computes the result of applying this node's draw masks to a running draw mask, as during a traversal.
Definition: pandaNode.I:1256
RenderState
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
PandaNode::find_stashed
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
PandaNode::DownConnection
Definition: pandaNode.h:448
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
PandaNodePipelineReader::release
void release()
Releases the lock on this object.
Definition: pandaNode.I:1242
PandaNodePipelineReader::get_off_clip_planes
const RenderAttrib * get_off_clip_planes() const
Returns a ClipPlaneAttrib which represents the union of all of the clip planes that have been turned ...
Definition: pandaNode.I:1494
PandaNode::Children
Definition: pandaNode.h:706
TypedWritable::mark_bam_modified
void mark_bam_modified()
Increments the bam_modified counter, so that this object will be invalidated and retransmitted on any...
Definition: typedWritable.I:43
TransformState
Indicates a coordinate-system transform on vertices.
Definition: transformState.h:54
CycleDataReader
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
Definition: cycleDataReader.h:35
LightMutexDirect::debug_is_locked
bool debug_is_locked() const
Returns true if the current thread has locked the LightMutex, false otherwise.
Definition: lightMutexDirect.I:81
PandaNodePipelineReader::get_tag
std::string get_tag(const std::string &key) const
Retrieves the user-defined value that was previously set on this node for the particular key,...
Definition: pandaNode.I:1460
PandaNode::Children::get_num_children
size_t get_num_children() const
Returns the number of children of the node.
Definition: pandaNode.I:953
PandaNode::get_child
get_child
Returns the nth child node of this node.
Definition: pandaNode.h:124
PandaNodePipelineReader::get_bounds
const BoundingVolume * get_bounds() const
Returns the external bounding volume of this node: a bounding volume that contains the user bounding ...
Definition: pandaNode.I:1505
PandaNodePipelineReader::find_stashed
int find_stashed(PandaNode *node) const
Returns the index of the indicated stashed node, if it is a stashed child, or -1 if it is not.
Definition: pandaNode.I:1412
PandaNode::get_parents
get_parents
Returns an object that can be used to walk through the list of parents of the node,...
Definition: pandaNode.h:784
PandaNode::is_final
is_final
Returns the current state of the "final" flag.
Definition: pandaNode.h:314
PandaNodePipelineReader::get_num_stashed
int get_num_stashed() const
Returns the number of stashed nodes this node has.
Definition: pandaNode.I:1380
RenderAttribRegistry::get_slot
int get_slot(TypeHandle type_handle) const
Returns the slot number assigned to the indicated TypeHandle, or 0 if no slot number has been assigne...
Definition: renderAttribRegistry.I:19
PandaNode::clear_bounds
void clear_bounds()
Reverses the effect of a previous call to set_bounds(), and allows the node's bounding volume to be a...
Definition: pandaNode.I:498
PandaNode::get_stashed
get_stashed
Returns the nth stashed child of this node.
Definition: pandaNode.h:148
PandaNode::DownConnection::set_child
void set_child(PandaNode *child)
This is only called by PandaNode::replace_child().
Definition: pandaNode.I:764
PandaNode::stash_child
bool stash_child(PandaNode *child_node, Thread *current_thread=Thread::get_current_thread())
Stashes the indicated child node.
Definition: pandaNode.I:107
BitMask< uint32_t, 32 >::all_off
static BitMask< uint32_t, nbits > all_off()
Returns a BitMask whose bits are all off.
Definition: bitMask.I:43
PandaNode::set_transform
set_transform
Sets the transform that will be applied to this node and below.
Definition: pandaNode.h:183
PandaNodePipelineReader::get_net_collide_mask
CollideMask get_net_collide_mask() const
Returns the union of all into_collide_mask() values set at CollisionNodes at this level and below.
Definition: pandaNode.I:1484
PandaNodePipelineReader::get_num_children
int get_num_children() const
Returns the number of child nodes this node has.
Definition: pandaNode.I:1338
node_unref_delete
void node_unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
Definition: nodeReferenceCount.I:185
PandaNode::Parents::get_num_parents
size_t get_num_parents() const
Returns the number of parents of the node.
Definition: pandaNode.I:1113
PandaNodePipelineReader::get_num_parents
int get_num_parents() const
Returns the number of parent nodes this node has.
Definition: pandaNode.I:1307
PandaNode::Stashed::get_stashed_sort
int get_stashed_sort(size_t n) const
Returns the sort index of the nth child node of this node (that is, the number that was passed to add...
Definition: pandaNode.I:1053
PandaNode::get_into_collide_mask
get_into_collide_mask
Returns the "into" collide mask for this node.
Definition: pandaNode.h:264
Thread::get_pipeline_stage
get_pipeline_stage
Returns the Pipeline stage number associated with this thread.
Definition: thread.h:105
PandaNodePipelineReader::get_fancy_bits
int get_fancy_bits() const
Returns the union of all of the enum FancyBits values corresponding to the various "fancy" attributes...
Definition: pandaNode.I:1544
BoundingVolume
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
Definition: boundingVolume.h:41
PandaNode::get_num_parents
get_num_parents
Returns the number of parent nodes this node has.
Definition: pandaNode.h:118
PandaNode::get_num_children
get_num_children
Returns the number of child nodes this node has.
Definition: pandaNode.h:124
PandaNode
A basic node of the scene graph or data graph.
Definition: pandaNode.h:64
PandaNode::DownConnection::operator<
bool operator<(const DownConnection &other) const
Provides a partial ordering on the children of a node so that they are ranked first in sort order,...
Definition: pandaNode.I:748
PandaNodePipelineReader::get_child
PandaNode * get_child(int n) const
Returns the nth child node of this node.
Definition: pandaNode.I:1348
PandaNode::Stashed
Definition: pandaNode.h:729
PandaNode::get_num_stashed
get_num_stashed
Returns the number of stashed nodes this node has.
Definition: pandaNode.h:148
PandaNodePipelineReader::get_stashed
PandaNode::Stashed get_stashed() const
Returns an object that can be used to walk through the list of children of the node.
Definition: pandaNode.I:1578
PandaNode::is_overall_hidden
is_overall_hidden
Returns true if the node has been hidden to all cameras by clearing its overall bit.
Definition: pandaNode.h:248
Thread
A thread; that is, a lightweight process.
Definition: thread.h:46
PandaNode::get_draw_control_mask
get_draw_control_mask
Returns the set of bits in draw_show_mask that are considered meaningful.
Definition: pandaNode.h:255
RenderAttribRegistry::quick_get_global_ptr
static RenderAttribRegistry * quick_get_global_ptr()
Returns the global_ptr without first ensuring it has been initialized.
Definition: renderAttribRegistry.I:100
PandaNode::Stashed::get_num_stashed
size_t get_num_stashed() const
Returns the number of stashed children of the node.
Definition: pandaNode.I:1033
PandaNodePipelineReader::get_transform
const TransformState * get_transform() const
Returns the transform that has been set on this particular node.
Definition: pandaNode.I:1441
PandaNode::Children::get_child_sort
int get_child_sort(size_t n) const
Returns the sort index of the nth child node of this node (that is, the number that was passed to add...
Definition: pandaNode.I:973
PandaNode::get_fancy_bits
int get_fancy_bits(Thread *current_thread=Thread::get_current_thread()) const
Returns the union of all of the enum FancyBits values corresponding to the various "fancy" attributes...
Definition: pandaNode.I:574
RenderAttribRegistry
This class is used to associate each RenderAttrib with a different slot index at runtime,...
Definition: renderAttribRegistry.h:31