Panda3D

Loading...
Searching...
No Matches
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 */
20INLINE 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 */
31INLINE 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 */
43INLINE 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 */
54INLINE 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 */
65INLINE 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 */
77INLINE 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 */
89INLINE 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 */
106INLINE 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 */
127INLINE 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 */
142INLINE 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 */
153INLINE 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 */
165INLINE 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 */
177INLINE 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 */
189INLINE CPT(RenderAttrib) PandaNode::
190get_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 */
201INLINE CPT(RenderAttrib) PandaNode::
202get_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 */
211INLINE bool PandaNode::
212has_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 */
221INLINE bool PandaNode::
222has_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 */
232INLINE void PandaNode::
233clear_attrib(TypeHandle type) {
234 RenderAttribRegistry *reg = RenderAttribRegistry::quick_get_global_ptr();
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 */
243INLINE CPT(RenderEffect) PandaNode::
244get_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 */
257INLINE bool PandaNode::
258has_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 */
270INLINE CPT(RenderState) PandaNode::
271get_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 */
281INLINE void PandaNode::
282clear_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 */
289INLINE CPT(RenderEffects) PandaNode::
290get_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 */
298INLINE void PandaNode::
299clear_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 */
308INLINE CPT(TransformState) PandaNode::
309get_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 */
317INLINE void PandaNode::
318clear_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 */
326INLINE CPT(TransformState) PandaNode::
327get_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 */
338INLINE bool PandaNode::
339has_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 */
348INLINE std::string PandaNode::
349get_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 */
364INLINE bool PandaNode::
365has_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 */
373INLINE size_t PandaNode::
374get_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 */
382INLINE std::string PandaNode::
383get_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 */
392INLINE bool PandaNode::
393has_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 */
412INLINE void PandaNode::
413ls(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 */
422INLINE DrawMask PandaNode::
423get_overall_bit() {
424 return _overall_bit;
425}
426
427/**
428 * Returns a DrawMask that is appropriate for rendering to all cameras.
429 */
430INLINE DrawMask PandaNode::
431 get_all_camera_mask() {
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 */
439INLINE 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 */
454INLINE void PandaNode::
455 set_overall_hidden(bool hidden) {
456 if (hidden) {
457 adjust_draw_mask(DrawMask::all_off(), _overall_bit, DrawMask::all_off());
458 } else {
459 adjust_draw_mask(DrawMask::all_off(), DrawMask::all_off(), _overall_bit);
460 }
461}
462
463/**
464 * Returns the set of bits in draw_show_mask that are considered meaningful.
465 * See adjust_draw_mask().
466 */
467INLINE 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 */
477INLINE 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 */
486INLINE CollideMask PandaNode::
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 */
497INLINE void PandaNode::
498 clear_bounds() {
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 */
507INLINE 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 */
519INLINE 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::
531is_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 */
548INLINE void PandaNode::
549set_final(bool flag) {
550 CDWriter cdata(_cycler);
551 cdata->_final_bounds = flag;
552 mark_bam_modified();
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 */
560INLINE 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 */
573INLINE 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 */
584INLINE CPT(BoundingVolume) PandaNode::
585get_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 */
596INLINE 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 */
617INLINE 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 */
638INLINE PandaNode::Children PandaNode::
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 */
656INLINE PandaNode::Stashed PandaNode::
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 */
666INLINE PandaNode::Parents PandaNode::
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 */
675INLINE int PandaNode::
676do_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 */
690INLINE bool PandaNode::
691verify_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 */
709INLINE void PandaNode::
710do_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 */
723INLINE void PandaNode::
724do_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 */
735INLINE PandaNode::DownConnection::
736DownConnection(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 */
747INLINE bool PandaNode::DownConnection::
748 operator < (const DownConnection &other) const {
749 return _sort < other._sort;
750}
751
752/**
753 *
754 */
755INLINE PandaNode *PandaNode::DownConnection::
756get_child() const {
757 return _child;
758}
759
760/**
761 * This is only called by PandaNode::replace_child().
762 */
763INLINE void PandaNode::DownConnection::
764 set_child(PandaNode *child) {
765 _child = child;
766}
767
768/**
769 *
770 */
771INLINE int PandaNode::DownConnection::
772get_sort() const {
773 return _sort;
774}
775
776/**
777 *
778 */
779INLINE PandaNode::UpConnection::
780UpConnection(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 */
791INLINE bool PandaNode::UpConnection::
792operator < (const UpConnection &other) const {
793 return _parent < other._parent;
794}
795
796/**
797 *
798 */
799INLINE PandaNode *PandaNode::UpConnection::
800get_parent() const {
801 return _parent;
802}
803
804/**
805 *
806 */
807INLINE PandaNode::BoundsData::
808BoundsData() :
809 _internal_bounds(nullptr),
810 _internal_vertices(0)
811{
812 ++_internal_bounds_mark;
813}
814
815/**
816 *
817 */
818INLINE PandaNode::BoundsData::
819BoundsData(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 */
830INLINE void PandaNode::BoundsData::
831copy_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 */
842INLINE void PandaNode::CData::
843set_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 */
854INLINE CPT(PandaNode::Down) PandaNode::CData::
855get_down() const {
856 return _down.get_read_pointer();
857}
858
859/**
860 * Returns a modifiable, unique pointer to the _down list.
861 */
862INLINE PT(PandaNode::Down) PandaNode::CData::
863modify_down() {
864 return _down.get_write_pointer();
865}
866
867/**
868 * Returns a read-only pointer to the _stashed list.
869 */
870INLINE CPT(PandaNode::Down) PandaNode::CData::
871get_stashed() const {
872 return _stashed.get_read_pointer();
873}
874
875/**
876 * Returns a modifiable, unique pointer to the _stashed list.
877 */
878INLINE PT(PandaNode::Down) PandaNode::CData::
879modify_stashed() {
880 return _stashed.get_write_pointer();
881}
882
883/**
884 * Returns a read-only pointer to the _up list.
885 */
886INLINE CPT(PandaNode::Up) PandaNode::CData::
887get_up() const {
888 return _up.get_read_pointer();
889}
890
891/**
892 * Returns a modifiable, unique pointer to the _up list.
893 */
894INLINE PT(PandaNode::Up) PandaNode::CData::
895modify_up() {
896 return _up.get_write_pointer();
897}
898
899/**
900 *
901 */
902INLINE PandaNode::Children::
903Children() {
904}
905
906/**
907 *
908 */
909INLINE PandaNode::Children::
910Children(const PandaNode::CData *cdata) :
911 _down(cdata->get_down())
912{
913}
914
915/**
916 *
917 */
918INLINE PandaNode::Children::
919Children(const PandaNode::Children &copy) :
920 _down(copy._down)
921{
922}
923
924/**
925 *
926 */
927INLINE void PandaNode::Children::
928operator = (const PandaNode::Children &copy) {
929 _down = copy._down;
930}
931
932/**
933 *
934 */
935INLINE PandaNode::Children::
936Children(PandaNode::Children &&from) noexcept :
937 _down(std::move(from._down))
938{
939}
940
941/**
942 *
943 */
944INLINE void PandaNode::Children::
945operator = (PandaNode::Children &&from) noexcept {
946 _down = std::move(from._down);
947}
948
949/**
950 * Returns the number of children of the node.
951 */
952INLINE size_t PandaNode::Children::
953 get_num_children() const {
954 nassertr(_down != nullptr, 0);
955 return _down->size();
956}
957
958/**
959 * Returns the nth child of the node.
960 */
961INLINE PandaNode *PandaNode::Children::
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 */
972INLINE 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 */
982INLINE PandaNode::Stashed::
983Stashed() {
984}
985
986/**
987 *
988 */
989INLINE PandaNode::Stashed::
990Stashed(const PandaNode::CData *cdata) :
991 _stashed(cdata->get_stashed())
992{
993}
994
995/**
996 *
997 */
998INLINE PandaNode::Stashed::
999Stashed(const PandaNode::Stashed &copy) :
1000 _stashed(copy._stashed)
1001{
1002}
1003
1004/**
1005 *
1006 */
1007INLINE void PandaNode::Stashed::
1008operator = (const PandaNode::Stashed &copy) {
1009 _stashed = copy._stashed;
1010}
1011
1012/**
1013 *
1014 */
1015INLINE PandaNode::Stashed::
1016Stashed(PandaNode::Stashed &&from) noexcept :
1017 _stashed(std::move(from._stashed))
1018{
1019}
1020
1021/**
1022 *
1023 */
1024INLINE void PandaNode::Stashed::
1025operator = (PandaNode::Stashed &&from) noexcept {
1026 _stashed = std::move(from._stashed);
1027}
1028
1029/**
1030 * Returns the number of stashed children of the node.
1031 */
1032INLINE size_t PandaNode::Stashed::
1033 get_num_stashed() const {
1034 nassertr(_stashed != nullptr, 0);
1035 return _stashed->size();
1036}
1037
1038/**
1039 * Returns the nth stashed child of the node.
1040 */
1041INLINE PandaNode *PandaNode::Stashed::
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 */
1052INLINE 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 */
1062INLINE PandaNode::Parents::
1063Parents() {
1064}
1065
1066/**
1067 *
1068 */
1069INLINE PandaNode::Parents::
1070Parents(const PandaNode::CData *cdata) :
1071 _up(cdata->get_up())
1072{
1073}
1074
1075/**
1076 *
1077 */
1078INLINE PandaNode::Parents::
1079Parents(const PandaNode::Parents &copy) :
1080 _up(copy._up)
1081{
1082}
1083
1084/**
1085 *
1086 */
1087INLINE void PandaNode::Parents::
1088operator = (const PandaNode::Parents &copy) {
1089 _up = copy._up;
1090}
1091
1092/**
1093 *
1094 */
1095INLINE PandaNode::Parents::
1096Parents(PandaNode::Parents &&from) noexcept :
1097 _up(std::move(from._up))
1098{
1099}
1100
1101/**
1102 *
1103 */
1104INLINE void PandaNode::Parents::
1105operator = (PandaNode::Parents &&from) noexcept {
1106 _up = std::move(from._up);
1107}
1108
1109/**
1110 * Returns the number of parents of the node.
1111 */
1112INLINE size_t PandaNode::Parents::
1113 get_num_parents() const {
1114 nassertr(_up != nullptr, 0);
1115 return _up->size();
1116}
1117
1118/**
1119 * Returns the nth parent of the node.
1120 */
1121INLINE PandaNode *PandaNode::Parents::
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 */
1131INLINE PandaNodePipelineReader::
1132PandaNodePipelineReader(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 */
1152INLINE PandaNodePipelineReader::
1153PandaNodePipelineReader(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 */
1172INLINE void PandaNodePipelineReader::
1173operator = (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 */
1203INLINE 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 */
1224INLINE const PandaNode *PandaNodePipelineReader::
1225get_node() const {
1226 return _node;
1227}
1228
1229/**
1230 *
1231 */
1232INLINE Thread *PandaNodePipelineReader::
1233get_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 */
1241INLINE void PandaNodePipelineReader::
1242 release() {
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 */
1255INLINE 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 */
1268INLINE 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 */
1306INLINE int PandaNodePipelineReader::
1307 get_num_parents() const {
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 */
1316INLINE PandaNode *PandaNodePipelineReader::
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 */
1327INLINE 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 */
1337INLINE int PandaNodePipelineReader::
1338 get_num_children() const {
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 */
1347INLINE PandaNode *PandaNodePipelineReader::
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 */
1358INLINE 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 */
1369INLINE 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 */
1379INLINE int PandaNodePipelineReader::
1380 get_num_stashed() const {
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 */
1389INLINE PandaNode *PandaNodePipelineReader::
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 */
1400INLINE 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 */
1411INLINE 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 */
1422INLINE const RenderState *PandaNodePipelineReader::
1423 get_state() const {
1424 return _cdata->_state;
1425}
1426
1427/**
1428 * Returns the complete RenderEffects that will be applied to this node.
1429 */
1430INLINE const RenderEffects *PandaNodePipelineReader::
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 */
1440INLINE const TransformState *PandaNodePipelineReader::
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 */
1449 const TransformState *PandaNodePipelineReader::
1450 get_prev_transform() const {
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 */
1459INLINE 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 */
1474INLINE bool PandaNodePipelineReader::
1475 has_tag(const std::string &key) const {
1476 return _cdata->_tag_data.find(key) >= 0;
1477}
1478
1479/**
1480 * Returns the "into" collide mask for this node.
1481 */
1482INLINE CollideMask PandaNodePipelineReader::
1483 get_into_collide_mask() const {
1484 return _cdata->_into_collide_mask;
1485}
1486
1487/**
1488 * Returns the union of all into_collide_mask() values set at CollisionNodes
1489 * at this level and below.
1490 */
1491INLINE CollideMask PandaNodePipelineReader::
1492 get_net_collide_mask() const {
1493 nassertr(_cdata->_last_update == _cdata->_next_update, _cdata->_net_collide_mask);
1494 return _cdata->_net_collide_mask;
1495}
1496
1497/**
1498 * Returns a ClipPlaneAttrib which represents the union of all of the clip
1499 * planes that have been turned *off* at this level and below.
1500 */
1501INLINE const RenderAttrib *PandaNodePipelineReader::
1502 get_off_clip_planes() const {
1503 nassertr(_cdata->_last_update == _cdata->_next_update, _cdata->_off_clip_planes);
1504 return _cdata->_off_clip_planes;
1505}
1506
1507/**
1508 * Returns the external bounding volume of this node: a bounding volume that
1509 * contains the user bounding volume, the internal bounding volume, and all of
1510 * the children's bounding volumes.
1511 */
1512INLINE const BoundingVolume *PandaNodePipelineReader::
1513 get_bounds() const {
1514 nassertr(_cdata->_last_bounds_update == _cdata->_next_update, _cdata->_external_bounds);
1515 return _cdata->_external_bounds;
1516}
1517
1518/**
1519 * Returns the total number of vertices that will be rendered by this node and
1520 * all of its descendents.
1521 *
1522 * This is not necessarily an accurate count of vertices that will actually be
1523 * rendered, since this will include all vertices of all LOD's, and it will
1524 * also include hidden nodes. It may also omit or only approximate certain
1525 * kinds of dynamic geometry. However, it will not include stashed nodes.
1526 */
1527INLINE int PandaNodePipelineReader::
1528 get_nested_vertices() const {
1529 nassertr(_cdata->_last_bounds_update == _cdata->_next_update, _cdata->_nested_vertices);
1530 return _cdata->_nested_vertices;
1531}
1532
1533/**
1534 * Returns the current state of the "final" flag. Initially, this flag is off
1535 * (false), but it may be changed by an explicit call to set_final(). See
1536 * set_final().
1537 */
1538INLINE bool PandaNodePipelineReader::
1539 is_final() const {
1540 return _cdata->_final_bounds;
1541}
1542
1543
1544/**
1545 * Returns the union of all of the enum FancyBits values corresponding to the
1546 * various "fancy" attributes that are set on the node. If this returns 0,
1547 * the node has nothing interesting about it. This is intended to speed
1548 * traversal by quickly skipping past nodes that don't particularly affect the
1549 * render state.
1550 */
1551INLINE int PandaNodePipelineReader::
1552 get_fancy_bits() const {
1553 return _cdata->_fancy_bits;
1554}
1555
1556/**
1557 * Returns an object that can be used to walk through the list of children of
1558 * the node. When you intend to visit multiple children, using this is
1559 * slightly faster than calling get_child() directly on the PandaNode, since
1560 * this object avoids reopening the PipelineCycler each time.
1561 *
1562 * This object also protects you from self-modifying loops (e.g. adding or
1563 * removing children during traversal), since a virtual copy of the children
1564 * is made ahead of time. The virtual copy is fast--it is a form of copy-on-
1565 * write, so the list is not actually copied unless it is modified during the
1566 * traversal.
1567 */
1568INLINE PandaNode::Children PandaNodePipelineReader::
1569 get_children() const {
1570 return PandaNode::Children(_cdata);
1571}
1572
1573/**
1574 * Returns an object that can be used to walk through the list of children of
1575 * the node. When you intend to visit multiple children, using this is
1576 * slightly faster than calling get_stashed() directly on the PandaNode, since
1577 * this object avoids reopening the PipelineCycler each time.
1578 *
1579 * This object also protects you from self-modifying loops (e.g. adding or
1580 * removing children during traversal), since a virtual copy of the children
1581 * is made ahead of time. The virtual copy is fast--it is a form of copy-on-
1582 * write, so the list is not actually copied unless it is modified during the
1583 * traversal.
1584 */
1585INLINE PandaNode::Stashed PandaNodePipelineReader::
1586 get_stashed() const {
1587 return PandaNode::Stashed(_cdata);
1588}
1589
1590/**
1591 * Returns an object that can be used to walk through the list of parents of
1592 * the node, similar to get_children() and get_stashed().
1593 */
1594INLINE PandaNode::Parents PandaNodePipelineReader::
1595 get_parents() const {
1596 return PandaNode::Parents(_cdata);
1597}
1598
1599/**
1600 *
1601 */
1602INLINE PandaNode::BamReaderAuxDataDown::
1603BamReaderAuxDataDown() :
1604 _down_list(PandaNode::get_class_type())
1605{
1606}
BitMask< uint32_t, 32 >::all_off
static BitMask< uint32_t, nbits > all_off()
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
PandaNodePipelineReader
Encapsulates the data from a PandaNode, pre-fetched for one stage of the pipeline.
Definition pandaNode.h:840
PandaNodePipelineReader::get_transform
const TransformState * get_transform() const
Returns the transform that has been set on this particular node.
Definition pandaNode.I:1441
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
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
PandaNodePipelineReader::release
void release()
Releases the lock on this object.
Definition pandaNode.I:1242
PandaNodePipelineReader::get_effects
const RenderEffects * get_effects() const
Returns the complete RenderEffects that will be applied to this node.
Definition pandaNode.I:1431
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:1513
PandaNodePipelineReader::get_child
PandaNode * get_child(int n) const
Returns the nth child node of this node.
Definition pandaNode.I:1348
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
PandaNodePipelineReader::get_parent
PandaNode * get_parent(int n) const
Returns the nth parent node of this node.
Definition pandaNode.I:1317
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
PandaNodePipelineReader::get_num_children
int get_num_children() const
Returns the number of child nodes this node has.
Definition pandaNode.I:1338
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:1586
PandaNodePipelineReader::get_num_parents
int get_num_parents() const
Returns the number of parent nodes this node has.
Definition pandaNode.I:1307
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::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
PandaNodePipelineReader::get_num_stashed
int get_num_stashed() const
Returns the number of stashed nodes this node has.
Definition pandaNode.I:1380
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::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_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:1595
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
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:1569
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:1492
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:1528
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:1502
PandaNodePipelineReader::get_into_collide_mask
CollideMask get_into_collide_mask() const
Returns the "into" collide mask for this node.
Definition pandaNode.I:1483
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:1552
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::is_final
bool is_final() const
Returns the current state of the "final" flag.
Definition pandaNode.I:1539
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
PandaNode::Children
Definition pandaNode.h:706
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::Children::get_child
PandaNode * get_child(size_t n) const
Returns the nth child of the node.
Definition pandaNode.I:962
PandaNode::Children::get_num_children
size_t get_num_children() const
Returns the number of children of the node.
Definition pandaNode.I:953
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
PandaNode::DownConnection::set_child
void set_child(PandaNode *child)
This is only called by PandaNode::replace_child().
Definition pandaNode.I:764
PandaNode::Parents
Definition pandaNode.h:752
PandaNode::Parents::get_parent
PandaNode * get_parent(size_t n) const
Returns the nth parent of the node.
Definition pandaNode.I:1122
PandaNode::Parents::get_num_parents
size_t get_num_parents() const
Returns the number of parents of the node.
Definition pandaNode.I:1113
PandaNode::Stashed
Definition pandaNode.h:729
PandaNode::Stashed::get_stashed
PandaNode * get_stashed(size_t n) const
Returns the nth stashed child of the node.
Definition pandaNode.I:1042
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::Stashed::get_num_stashed
size_t get_num_stashed() const
Returns the number of stashed children of the node.
Definition pandaNode.I:1033
PandaNode
A basic node of the scene graph or data graph.
Definition pandaNode.h:65
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
PandaNode::is_final
is_final
Returns the current state of the "final" flag.
Definition pandaNode.h:314
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
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
PandaNode::set_overall_hidden
set_overall_hidden
Sets or clears the hidden flag.
Definition pandaNode.h:248
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::mark_internal_bounds_stale
void mark_internal_bounds_stale(Thread *current_thread=Thread::get_current_thread())
Should be called by a derived class to mark the internal bounding volume stale, so that compute_inter...
Definition pandaNode.cxx:2046
PandaNode::get_num_parents
get_num_parents
Returns the number of parent nodes this node has.
Definition pandaNode.h:118
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::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
PandaNode::set_bounds
void set_bounds(const BoundingVolume *volume)
Resets the bounding volume so that it is the indicated volume.
Definition pandaNode.cxx:1907
PandaNode::set_effects
set_effects
Sets the complete RenderEffects that will be applied this node.
Definition pandaNode.h:178
PandaNode::get_into_collide_mask
get_into_collide_mask
Returns the "into" collide mask for this node.
Definition pandaNode.h:264
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::get_num_stashed
get_num_stashed
Returns the number of stashed nodes this node has.
Definition pandaNode.h:148
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
PandaNode::get_draw_show_mask
get_draw_show_mask
Returns the hide/show bits of this particular node.
Definition pandaNode.h:256
PandaNode::get_child
get_child
Returns the nth child node of this node.
Definition pandaNode.h:124
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::set_transform
set_transform
Sets the transform that will be applied to this node and below.
Definition pandaNode.h:183
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
PandaNode::get_internal_vertices
get_internal_vertices
Returns the total number of vertices that will be rendered by this particular node alone,...
Definition pandaNode.h:305
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::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
PandaNode::get_stashed
get_stashed
Returns the nth stashed child of this node.
Definition pandaNode.h:148
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_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::mark_bounds_stale
void mark_bounds_stale(Thread *current_thread=Thread::get_current_thread()) const
Indicates that the bounding volume, or something that influences the bounding volume (or any of the o...
Definition pandaNode.cxx:2027
PandaNode::get_internal_bounds
get_internal_bounds
Returns the node's internal bounding volume.
Definition pandaNode.h:304
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
PandaNode::get_parent
get_parent
Returns the nth parent node of this node.
Definition pandaNode.h:118
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
PandaNode::get_num_children
get_num_children
Returns the number of child nodes this node has.
Definition pandaNode.h:124
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
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
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
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
RenderEffects
This represents a unique collection of RenderEffect objects that correspond to a particular renderabl...
Definition renderEffects.h:41
RenderEffects::make_empty
static ConstPointerTo< RenderEffects > make_empty()
Returns a RenderEffects with no effects set.
Definition renderEffects.cxx:176
RenderState
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition renderState.h:47
Thread
A thread; that is, a lightweight process.
Definition thread.h:46
Thread::get_pipeline_stage
get_pipeline_stage
Returns the Pipeline stage number associated with this thread.
Definition thread.h:105
TransformState
Indicates a coordinate-system transform on vertices.
Definition transformState.h:54
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
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
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