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) {
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 */
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::
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 */
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) {
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 */
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 */
486 INLINE 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 */
497 INLINE 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 */
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;
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 */
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 */
638 INLINE 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 */
656 INLINE 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 */
666 INLINE 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 */
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::
764 set_child(PandaNode *child) {
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::
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 */
961 INLINE 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 */
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::
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 */
1041 INLINE 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 */
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::
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 */
1121 INLINE 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 */
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::
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 */
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::
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 */
1316 INLINE 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 */
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::
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 */
1347 INLINE 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 */
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::
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 */
1389 INLINE 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 */
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 */
1422 INLINE 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 */
1430 INLINE 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 */
1440 INLINE 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 */
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 */
1483 INLINE CollideMask PandaNodePipelineReader::
1484 get_net_collide_mask() const {
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 */
1493 INLINE const RenderAttrib *PandaNodePipelineReader::
1494 get_off_clip_planes() const {
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 */
1504 INLINE const BoundingVolume *PandaNodePipelineReader::
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::
1520 get_nested_vertices() const {
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::
1544 get_fancy_bits() const {
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 */
1560 INLINE PandaNode::Children PandaNodePipelineReader::
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 */
1577 INLINE PandaNode::Stashed PandaNodePipelineReader::
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 */
1586 INLINE PandaNode::Parents PandaNodePipelineReader::
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 }
BitMask< uint32_t, 32 >
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
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
CopyOnWriteObj1< DownList, TypeHandle >
CycleDataReader
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
Definition: cycleDataReader.h:35
CycleData
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
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
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:1505
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:1578
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:1587
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:1561
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_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::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
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
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:1531
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
Definition: pandaNode.h:448
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::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::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::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
This class is used to associate each RenderAttrib with a different slot index at runtime,...
Definition: renderAttribRegistry.h:31
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
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
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