Panda3D
 All Classes Functions Variables Enumerations
pandaNode.cxx
1 // Filename: pandaNode.cxx
2 // Created by: drose (20Feb02)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "pandaNode.h"
16 #include "config_pgraph.h"
17 #include "nodePathComponent.h"
18 #include "bamReader.h"
19 #include "bamWriter.h"
20 #include "indent.h"
21 #include "geometricBoundingVolume.h"
22 #include "sceneGraphReducer.h"
23 #include "accumulatedAttribs.h"
24 #include "clipPlaneAttrib.h"
25 #include "boundingSphere.h"
26 #include "boundingBox.h"
27 #include "pStatTimer.h"
28 #include "config_mathutil.h"
29 #include "lightReMutexHolder.h"
30 #include "graphicsStateGuardianBase.h"
31 #include "py_panda.h"
32 
33 // This category is just temporary for debugging convenience.
34 NotifyCategoryDecl(drawmask, EXPCL_PANDA_PGRAPH, EXPTP_PANDA_PGRAPH);
35 NotifyCategoryDef(drawmask, "");
36 
37 TypeHandle PandaNode::BamReaderAuxDataDown::_type_handle;
38 
39 PandaNode::SceneRootFunc *PandaNode::_scene_root_func;
40 
41 PandaNodeChain PandaNode::_dirty_prev_transforms("_dirty_prev_transforms");
42 DrawMask PandaNode::_overall_bit = DrawMask::bit(31);
43 
44 PStatCollector PandaNode::_reset_prev_pcollector("App:Collisions:Reset");
45 PStatCollector PandaNode::_update_bounds_pcollector("*:Bounds");
46 
47 TypeHandle PandaNode::_type_handle;
48 TypeHandle PandaNode::CData::_type_handle;
49 TypeHandle PandaNodePipelineReader::_type_handle;
50 
51 //
52 // There are two different interfaces here for making and breaking
53 // parent-child connections: the fundamental PandaNode interface, via
54 // add_child() and remove_child() (and related functions), and the
55 // NodePath support interface, via attach(), detach(), and reparent().
56 // They both do essentially the same thing, but with slightly
57 // different inputs. The PandaNode interfaces try to guess which
58 // NodePaths should be updated as a result of the scene graph change,
59 // while the NodePath interfaces already know.
60 //
61 // The NodePath support interface functions are strictly called from
62 // within the NodePath class, and are used to implement
63 // NodePath::reparent_to() and NodePath::remove_node(), etc. The
64 // fundamental interface, on the other hand, is intended to be called
65 // directly by the user.
66 //
67 // The fundamental interface has a slightly lower overhead because it
68 // does not need to create a NodePathComponent chain where one does
69 // not already exist; however, the NodePath support interface is more
70 // useful when the NodePath already does exist, because it ensures
71 // that the particular NodePath calling it is kept appropriately
72 // up-to-date.
73 //
74 
75 
76 ////////////////////////////////////////////////////////////////////
77 // Function: PandaNode::Constructor
78 // Access: Published
79 // Description:
80 ////////////////////////////////////////////////////////////////////
81 PandaNode::
82 PandaNode(const string &name) :
83  Namable(name),
84  _paths_lock("PandaNode::_paths_lock"),
85  _dirty_prev_transform(false)
86 {
87  if (pgraph_cat.is_debug()) {
88  pgraph_cat.debug()
89  << "Constructing " << (void *)this << ", " << get_name() << "\n";
90  }
91 #ifndef NDEBUG
92  _unexpected_change_flags = 0;
93 #endif // !NDEBUG
94 
95 #ifdef DO_MEMORY_USAGE
96  MemoryUsage::update_type(this, this);
97 #endif
98 }
99 
100 ////////////////////////////////////////////////////////////////////
101 // Function: PandaNode::Destructor
102 // Access: Published, Virtual
103 // Description:
104 ////////////////////////////////////////////////////////////////////
105 PandaNode::
106 ~PandaNode() {
107  if (pgraph_cat.is_debug()) {
108  pgraph_cat.debug()
109  << "Destructing " << (void *)this << ", " << get_name() << "\n";
110  }
111 
112  if (_dirty_prev_transform) {
113  // Need to have this held before we grab any other locks.
114  LightMutexHolder holder(_dirty_prev_transforms._lock);
115  do_clear_dirty_prev_transform();
116  }
117 
118  // We shouldn't have any parents left by the time we destruct, or
119  // there's a refcount fault somewhere.
120 
121  // Actually, that's not necessarily true anymore, since we might be
122  // updating a node dynamically via the bam reader, which doesn't
123  // necessarily keep related pairs of nodes in sync with each other.
124  /*
125 #ifndef NDEBUG
126  {
127  CDReader cdata(_cycler);
128  nassertv(cdata->get_up()->empty());
129  }
130 #endif // NDEBUG
131  */
132 
134 }
135 
136 ////////////////////////////////////////////////////////////////////
137 // Function: PandaNode::Copy Constructor
138 // Access: Protected
139 // Description: Do not call the copy constructor directly; instead,
140 // use make_copy() or copy_subgraph() to make a copy of
141 // a node.
142 ////////////////////////////////////////////////////////////////////
143 PandaNode::
144 PandaNode(const PandaNode &copy) :
146  Namable(copy),
147  _paths_lock("PandaNode::_paths_lock"),
148  _dirty_prev_transform(false)
149 {
150  if (pgraph_cat.is_debug()) {
151  pgraph_cat.debug()
152  << "Copying " << (void *)this << ", " << get_name() << "\n";
153  }
154 #ifdef DO_MEMORY_USAGE
155  MemoryUsage::update_type(this, this);
156 #endif
157  // Copying a node does not copy its children.
158 #ifndef NDEBUG
159  _unexpected_change_flags = 0;
160 #endif // !NDEBUG
161 
162  // Need to have this held before we grab any other locks.
163  LightMutexHolder holder(_dirty_prev_transforms._lock);
164 
165  // Copy the other node's state.
166  {
167  CDReader copy_cdata(copy._cycler);
168  CDWriter cdata(_cycler, true);
169  cdata->_state = copy_cdata->_state;
170  cdata->_transform = copy_cdata->_transform;
171  cdata->_prev_transform = copy_cdata->_prev_transform;
172  if (cdata->_transform != cdata->_prev_transform) {
173  do_set_dirty_prev_transform();
174  }
175 
176  cdata->_effects = copy_cdata->_effects;
177  cdata->_tag_data = copy_cdata->_tag_data;
178  cdata->_draw_control_mask = copy_cdata->_draw_control_mask;
179  cdata->_draw_show_mask = copy_cdata->_draw_show_mask;
180  cdata->_into_collide_mask = copy_cdata->_into_collide_mask;
181  cdata->_bounds_type = copy_cdata->_bounds_type;
182  cdata->_user_bounds = copy_cdata->_user_bounds;
183  cdata->_internal_bounds = NULL;
184  cdata->_internal_bounds_computed = UpdateSeq::initial();
185  cdata->_internal_bounds_mark = UpdateSeq::initial();
186  ++cdata->_internal_bounds_mark;
187  cdata->_final_bounds = copy_cdata->_final_bounds;
188  cdata->_fancy_bits = copy_cdata->_fancy_bits;
189 
190 #ifdef HAVE_PYTHON
191  // Copy and increment all of the Python objects held by the other
192  // node.
193  cdata->_python_tag_data = copy_cdata->_python_tag_data;
194  cdata->inc_py_refs();
195 #endif // HAVE_PYTHON
196  }
197 }
198 
199 ////////////////////////////////////////////////////////////////////
200 // Function: PandaNode::Copy Assignment Operator
201 // Access: Private
202 // Description: Do not call the copy assignment operator at all. Use
203 // make_copy() or copy_subgraph() to make a copy of a
204 // node.
205 ////////////////////////////////////////////////////////////////////
206 void PandaNode::
207 operator = (const PandaNode &copy) {
208  nassertv(false);
209 }
210 
211 ////////////////////////////////////////////////////////////////////
212 // Function: PandaNode::dupe_for_flatten
213 // Access: Public, Virtual
214 // Description: This is similar to make_copy(), but it makes a copy
215 // for the specific purpose of flatten. Typically, this
216 // will be a new PandaNode with a new pointer, but all
217 // of the internal data will always be shared with the
218 // original; whereas the new node returned by
219 // make_copy() might not share the internal data.
220 ////////////////////////////////////////////////////////////////////
223  return make_copy();
224 }
225 
226 ////////////////////////////////////////////////////////////////////
227 // Function: PandaNode::safe_to_flatten
228 // Access: Public, Virtual
229 // Description: Returns true if it is generally safe to flatten out
230 // this particular kind of PandaNode by duplicating
231 // instances (by calling dupe_for_flatten()), false
232 // otherwise (for instance, a Camera cannot be safely
233 // flattened, because the Camera pointer itself is
234 // meaningful).
235 ////////////////////////////////////////////////////////////////////
236 bool PandaNode::
238  return true;
239 }
240 
241 ////////////////////////////////////////////////////////////////////
242 // Function: PandaNode::safe_to_transform
243 // Access: Public, Virtual
244 // Description: Returns true if it is generally safe to transform
245 // this particular kind of PandaNode by calling the
246 // xform() method, false otherwise.
247 ////////////////////////////////////////////////////////////////////
248 bool PandaNode::
250  return true;
251 }
252 
253 ////////////////////////////////////////////////////////////////////
254 // Function: PandaNode::safe_to_modify_transform
255 // Access: Public, Virtual
256 // Description: Returns true if it is safe to automatically adjust
257 // the transform on this kind of node. Usually, this is
258 // only a bad idea if the user expects to find a
259 // particular transform on the node.
260 //
261 // ModelNodes with the preserve_transform flag set are
262 // presently the only kinds of nodes that should not
263 // have their transform even adjusted.
264 ////////////////////////////////////////////////////////////////////
265 bool PandaNode::
267  return true;
268 }
269 
270 ////////////////////////////////////////////////////////////////////
271 // Function: PandaNode::safe_to_combine
272 // Access: Public, Virtual
273 // Description: Returns true if it is generally safe to combine this
274 // particular kind of PandaNode with other kinds of
275 // PandaNodes of compatible type, adding children or
276 // whatever. For instance, an LODNode should not be
277 // combined with any other PandaNode, because its set of
278 // children is meaningful.
279 ////////////////////////////////////////////////////////////////////
280 bool PandaNode::
282  return true;
283 }
284 
285 ////////////////////////////////////////////////////////////////////
286 // Function: PandaNode::safe_to_combine_children
287 // Access: Public, Virtual
288 // Description: Returns true if it is generally safe to combine the
289 // children of this PandaNode with each other. For
290 // instance, an LODNode's children should not be
291 // combined with each other, because the set of children
292 // is meaningful.
293 ////////////////////////////////////////////////////////////////////
294 bool PandaNode::
296  return true;
297 }
298 
299 ////////////////////////////////////////////////////////////////////
300 // Function: PandaNode::safe_to_flatten_below
301 // Access: Public, Virtual
302 // Description: Returns true if a flatten operation may safely
303 // continue past this node, or false if nodes below this
304 // node may not be molested.
305 ////////////////////////////////////////////////////////////////////
306 bool PandaNode::
308  return true;
309 }
310 
311 ////////////////////////////////////////////////////////////////////
312 // Function: PandaNode::preserve_name
313 // Access: Public, Virtual
314 // Description: Returns true if the node's name has extrinsic meaning
315 // and must be preserved across a flatten operation,
316 // false otherwise.
317 ////////////////////////////////////////////////////////////////////
318 bool PandaNode::
319 preserve_name() const {
320  return false;
321 }
322 
323 ////////////////////////////////////////////////////////////////////
324 // Function: PandaNode::get_unsafe_to_apply_attribs
325 // Access: Public, Virtual
326 // Description: Returns the union of all attributes from
327 // SceneGraphReducer::AttribTypes that may not safely be
328 // applied to the vertices of this node. If this is
329 // nonzero, these attributes must be dropped at this
330 // node as a state change.
331 //
332 // This is a generalization of safe_to_transform().
333 ////////////////////////////////////////////////////////////////////
334 int PandaNode::
336  return 0;
337 }
338 
339 ////////////////////////////////////////////////////////////////////
340 // Function: PandaNode::apply_attribs_to_vertices
341 // Access: Public, Virtual
342 // Description: Applies whatever attributes are specified in the
343 // AccumulatedAttribs object (and by the attrib_types
344 // bitmask) to the vertices on this node, if
345 // appropriate. If this node uses geom arrays like a
346 // GeomNode, the supplied GeomTransformer may be used to
347 // unify shared arrays across multiple different nodes.
348 //
349 // This is a generalization of xform().
350 ////////////////////////////////////////////////////////////////////
351 void PandaNode::
352 apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
353  GeomTransformer &transformer) {
354  if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
355  const LMatrix4 &mat = attribs._transform->get_mat();
356  xform(mat);
357 
358  Thread *current_thread = Thread::get_current_thread();
359  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
360  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
361  cdata->_effects = cdata->_effects->xform(mat);
362  cdata->set_fancy_bit(FB_effects, !cdata->_effects->is_empty());
363  }
364  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
365  }
367 }
368 
369 ////////////////////////////////////////////////////////////////////
370 // Function: PandaNode::xform
371 // Access: Public, Virtual
372 // Description: Transforms the contents of this PandaNode by the
373 // indicated matrix, if it means anything to do so. For
374 // most kinds of PandaNodes, this does nothing.
375 ////////////////////////////////////////////////////////////////////
376 void PandaNode::
377 xform(const LMatrix4 &) {
378 }
379 
380 ////////////////////////////////////////////////////////////////////
381 // Function: PandaNode::combine_with
382 // Access: Public, Virtual
383 // Description: Collapses this PandaNode with the other PandaNode, if
384 // possible, and returns a pointer to the combined
385 // PandaNode, or NULL if the two PandaNodes cannot
386 // safely be combined.
387 //
388 // The return value may be this, other, or a new
389 // PandaNode altogether.
390 //
391 // This function is called from GraphReducer::flatten(),
392 // and need not deal with children; its job is just to
393 // decide whether to collapse the two PandaNodes and
394 // what the collapsed PandaNode should look like.
395 ////////////////////////////////////////////////////////////////////
398  // An unadorned PandaNode always combines with any other PandaNodes by
399  // yielding completely. However, if we are actually some fancy PandaNode
400  // type that derives from PandaNode but didn't redefine this function, we
401  // should refuse to combine.
402  if (is_exact_type(get_class_type())) {
403  // No, we're an ordinary PandaNode.
404  return other;
405 
406  } else if (other->is_exact_type(get_class_type())) {
407  // We're not an ordinary PandaNode, but the other one is.
408  return this;
409  }
410 
411  // We're something other than an ordinary PandaNode. Don't combine.
412  return (PandaNode *)NULL;
413 }
414 
415 ////////////////////////////////////////////////////////////////////
416 // Function: PandaNode::calc_tight_bounds
417 // Access: Public, Virtual
418 // Description: This is used to support
419 // NodePath::calc_tight_bounds(). It is not intended to
420 // be called directly, and it has nothing to do with the
421 // normal Panda bounding-volume computation.
422 //
423 // If the node contains any geometry, this updates
424 // min_point and max_point to enclose its bounding box.
425 // found_any is to be set true if the node has any
426 // geometry at all, or left alone if it has none. This
427 // method may be called over several nodes, so it may
428 // enter with min_point, max_point, and found_any
429 // already set.
430 //
431 // This function is recursive, and the return value is
432 // the transform after it has been modified by this
433 // node's transform.
434 ////////////////////////////////////////////////////////////////////
435 CPT(TransformState) PandaNode::
436 calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any,
437  const TransformState *transform, Thread *current_thread) const {
438  CPT(TransformState) next_transform = transform->compose(get_transform());
439 
440  Children cr = get_children(current_thread);
441  int num_children = cr.get_num_children();
442  for (int i = 0; i < num_children; i++) {
443  cr.get_child(i)->calc_tight_bounds(min_point, max_point,
444  found_any, next_transform,
445  current_thread);
446  }
447 
448  return next_transform;
449 }
450 
451 ////////////////////////////////////////////////////////////////////
452 // Function: PandaNode::cull_callback
453 // Access: Public, Virtual
454 // Description: This function will be called during the cull
455 // traversal to perform any additional operations that
456 // should be performed at cull time. This may include
457 // additional manipulation of render state or additional
458 // visible/invisible decisions, or any other arbitrary
459 // operation.
460 //
461 // Note that this function will *not* be called unless
462 // set_cull_callback() is called in the constructor of
463 // the derived class. It is necessary to call
464 // set_cull_callback() to indicated that we require
465 // cull_callback() to be called.
466 //
467 // By the time this function is called, the node has
468 // already passed the bounding-volume test for the
469 // viewing frustum, and the node's transform and state
470 // have already been applied to the indicated
471 // CullTraverserData object.
472 //
473 // The return value is true if this node should be
474 // visible, or false if it should be culled.
475 ////////////////////////////////////////////////////////////////////
476 bool PandaNode::
478  return true;
479 }
480 
481 ////////////////////////////////////////////////////////////////////
482 // Function: PandaNode::has_selective_visibility
483 // Access: Public, Virtual
484 // Description: Should be overridden by derived classes to return
485 // true if this kind of node has some restrictions on
486 // the set of children that should be rendered. Node
487 // with this property include LODNodes, SwitchNodes, and
488 // SequenceNodes.
489 //
490 // If this function returns true,
491 // get_first_visible_child() and
492 // get_next_visible_child() will be called to walk
493 // through the list of children during cull, instead of
494 // iterating through the entire list. This method is
495 // called after cull_callback(), so cull_callback() may
496 // be responsible for the decisions as to which children
497 // are visible at the moment.
498 ////////////////////////////////////////////////////////////////////
499 bool PandaNode::
501  return false;
502 }
503 
504 ////////////////////////////////////////////////////////////////////
505 // Function: PandaNode::get_first_visible_child
506 // Access: Public, Virtual
507 // Description: Returns the index number of the first visible child
508 // of this node, or a number >= get_num_children() if
509 // there are no visible children of this node. This is
510 // called during the cull traversal, but only if
511 // has_selective_visibility() has already returned true.
512 // See has_selective_visibility().
513 ////////////////////////////////////////////////////////////////////
514 int PandaNode::
516  return 0;
517 }
518 
519 ////////////////////////////////////////////////////////////////////
520 // Function: PandaNode::get_next_visible_child
521 // Access: Public, Virtual
522 // Description: Returns the index number of the next visible child
523 // of this node following the indicated child, or a
524 // number >= get_num_children() if there are no more
525 // visible children of this node. See
526 // has_selective_visibility() and
527 // get_first_visible_child().
528 ////////////////////////////////////////////////////////////////////
529 int PandaNode::
531  return n + 1;
532 }
533 
534 ////////////////////////////////////////////////////////////////////
535 // Function: PandaNode::has_single_child_visibility
536 // Access: Public, Virtual
537 // Description: Should be overridden by derived classes to return
538 // true if this kind of node has the special property
539 // that just one of its children is visible at any given
540 // time, and furthermore that the particular visible
541 // child can be determined without reference to any
542 // external information (such as a camera). At present,
543 // only SequenceNodes and SwitchNodes fall into this
544 // category.
545 //
546 // If this function returns true, get_visible_child()
547 // can be called to return the index of the
548 // currently-visible child.
549 ////////////////////////////////////////////////////////////////////
550 bool PandaNode::
552  return false;
553 }
554 
555 ////////////////////////////////////////////////////////////////////
556 // Function: PandaNode::get_visible_child
557 // Access: Public, Virtual
558 // Description: Returns the index number of the currently visible
559 // child of this node. This is only meaningful if
560 // has_single_child_visibility() has returned true.
561 ////////////////////////////////////////////////////////////////////
562 int PandaNode::
564  return 0;
565 }
566 
567 ////////////////////////////////////////////////////////////////////
568 // Function: PandaNode::is_renderable
569 // Access: Public, Virtual
570 // Description: Returns true if there is some value to visiting this
571 // particular node during the cull traversal for any
572 // camera, false otherwise. This will be used to
573 // optimize the result of get_net_draw_show_mask(), so
574 // that any subtrees that contain only nodes for which
575 // is_renderable() is false need not be visited.
576 ////////////////////////////////////////////////////////////////////
577 bool PandaNode::
578 is_renderable() const {
579  return false;
580 }
581 
582 ////////////////////////////////////////////////////////////////////
583 // Function: PandaNode::add_for_draw
584 // Access: Public, Virtual
585 // Description: Adds the node's contents to the CullResult we are
586 // building up during the cull traversal, so that it
587 // will be drawn at render time. For most nodes other
588 // than GeomNodes, this is a do-nothing operation.
589 ////////////////////////////////////////////////////////////////////
590 void PandaNode::
592 }
593 
594 ////////////////////////////////////////////////////////////////////
595 // Function: PandaNode::make_copy
596 // Access: Published, Virtual
597 // Description: Returns a newly-allocated PandaNode that is a shallow
598 // copy of this one. It will be a different pointer,
599 // but its internal data may or may not be shared with
600 // that of the original PandaNode. No children will be
601 // copied.
602 ////////////////////////////////////////////////////////////////////
604 make_copy() const {
605  return new PandaNode(*this);
606 }
607 
608 ////////////////////////////////////////////////////////////////////
609 // Function: PandaNode::copy_subgraph
610 // Access: Published
611 // Description: Allocates and returns a complete copy of this
612 // PandaNode and the entire scene graph rooted at this
613 // PandaNode. Some data may still be shared from the
614 // original (e.g. vertex index tables), but nothing that
615 // will impede normal use of the PandaNode.
616 ////////////////////////////////////////////////////////////////////
617 PT(PandaNode) PandaNode::
618 copy_subgraph(Thread *current_thread) const {
619  InstanceMap inst_map;
620  return r_copy_subgraph(inst_map, current_thread);
621 }
622 
623 ////////////////////////////////////////////////////////////////////
624 // Function: PandaNode::count_num_descendants
625 // Access: Published
626 // Description: Returns the number of nodes at and below this level.
627 ////////////////////////////////////////////////////////////////////
628 int PandaNode::
630  int count = 1;
631  Children children = get_children();
632  int num_children = children.get_num_children();
633 
634  for (int i = 0; i < num_children; ++i) {
635  PandaNode *child = children.get_child(i);
636  count += child->count_num_descendants();
637  }
638 
639  return count;
640 }
641 
642 ////////////////////////////////////////////////////////////////////
643 // Function: PandaNode::add_child
644 // Access: Published
645 // Description: Adds a new child to the node. The child is added in
646 // the relative position indicated by sort; if all
647 // children have the same sort index, the child is added
648 // at the end.
649 //
650 // If the same child is added to a node more than once,
651 // the previous instance is first removed.
652 ////////////////////////////////////////////////////////////////////
653 void PandaNode::
654 add_child(PandaNode *child_node, int sort, Thread *current_thread) {
655  nassertv(child_node != (PandaNode *)NULL);
656 
657  if (!verify_child_no_cycles(child_node)) {
658  // Whoops, adding this child node would introduce a cycle in the
659  // scene graph.
660  return;
661  }
662 
663  // Ensure the child_node is not deleted while we do this.
664  PT(PandaNode) keep_child = child_node;
665  remove_child(child_node);
666 
667  // Apply this operation to the current stage as well as to all
668  // upstream stages.
669  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
670  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
671  CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
672 
673  cdata->modify_down()->insert(DownConnection(child_node, sort));
674  cdata_child->modify_up()->insert(UpConnection(this));
675  }
676  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
677 
678  OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
679  new_connection(this, child_node, pipeline_stage, current_thread);
680  }
681  CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
682 
683  force_bounds_stale();
684 
685  children_changed();
686  child_node->parents_changed();
688  child_node->mark_bam_modified();
689 }
690 
691 ////////////////////////////////////////////////////////////////////
692 // Function: PandaNode::remove_child
693 // Access: Published
694 // Description: Removes the nth child from the node.
695 ////////////////////////////////////////////////////////////////////
696 void PandaNode::
697 remove_child(int child_index, Thread *current_thread) {
698  int pipeline_stage = current_thread->get_pipeline_stage();
699  nassertv(pipeline_stage == 0);
700 
701  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
702  PT(Down) down = cdata->modify_down();
703  nassertv(child_index >= 0 && child_index < (int)down->size());
704 
705  PT(PandaNode) child_node = (*down)[child_index].get_child();
706  CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
707  current_thread);
708  PT(Up) up = cdata_child->modify_up();
709 
710  down->erase(down->begin() + child_index);
711  int num_erased = up->erase(UpConnection(this));
712  nassertv(num_erased == 1);
713 
714  sever_connection(this, child_node, pipeline_stage, current_thread);
715  force_bounds_stale(pipeline_stage, current_thread);
716 
717  children_changed();
718  child_node->parents_changed();
720  child_node->mark_bam_modified();
721 }
722 
723 ////////////////////////////////////////////////////////////////////
724 // Function: PandaNode::remove_child
725 // Access: Published
726 // Description: Removes the indicated child from the node. Returns
727 // true if the child was removed, false if it was not
728 // already a child of the node. This will also
729 // successfully remove the child if it had been stashed.
730 ////////////////////////////////////////////////////////////////////
731 bool PandaNode::
732 remove_child(PandaNode *child_node, Thread *current_thread) {
733  nassertr(child_node != (PandaNode *)NULL, false);
734 
735  // Make sure the child node is not destructed during the execution
736  // of this method.
737  PT(PandaNode) keep_child = child_node;
738 
739  // We have to do this for each upstream pipeline stage.
740  bool any_removed = false;
741 
742  OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
743  if (stage_remove_child(child_node, pipeline_stage, current_thread)) {
744  any_removed = true;
745 
746  sever_connection(this, child_node, pipeline_stage, current_thread);
747  force_bounds_stale(pipeline_stage, current_thread);
748  }
749  }
750  CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
751 
752  if (any_removed) {
753  // Call callback hooks.
754  children_changed();
755  child_node->parents_changed();
756  }
757 
758  return any_removed;
759 }
760 
761 ////////////////////////////////////////////////////////////////////
762 // Function: PandaNode::replace_child
763 // Access: Published
764 // Description: Searches for the orig_child node in the node's list
765 // of children, and replaces it with the new_child
766 // instead. Returns true if the replacement is made, or
767 // false if the node is not a child or if there is some
768 // other problem.
769 ////////////////////////////////////////////////////////////////////
770 bool PandaNode::
771 replace_child(PandaNode *orig_child, PandaNode *new_child,
772  Thread *current_thread) {
773  nassertr(orig_child != (PandaNode *)NULL, false);
774  nassertr(new_child != (PandaNode *)NULL, false);
775 
776  if (orig_child == new_child) {
777  // Trivial no-op.
778  return true;
779  }
780 
781  if (!verify_child_no_cycles(new_child)) {
782  // Whoops, adding this child node would introduce a cycle in the
783  // scene graph.
784  return false;
785  }
786 
787  // Make sure the orig_child node is not destructed during the
788  // execution of this method.
789  PT(PandaNode) keep_orig_child = orig_child;
790 
791  // We have to do this for each upstream pipeline stage.
792  bool any_replaced = false;
793 
794  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
795  if (stage_replace_child(orig_child, new_child, pipeline_stage, current_thread)) {
796  any_replaced = true;
797  }
798  }
799  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
800 
801  if (any_replaced) {
802  children_changed();
803  orig_child->parents_changed();
804  new_child->parents_changed();
805  }
806 
807  return any_replaced;
808 }
809 
810 
811 ////////////////////////////////////////////////////////////////////
812 // Function: PandaNode::stash_child
813 // Access: Published
814 // Description: Stashes the indicated child node. This removes the
815 // child from the list of active children and puts it on
816 // a special list of stashed children. This child node
817 // no longer contributes to the bounding volume of the
818 // PandaNode, and is not visited in normal traversals.
819 // It is invisible and uncollidable. The child may
820 // later be restored by calling unstash_child().
821 //
822 // This can only be called from the top pipeline stage
823 // (i.e. from App).
824 ////////////////////////////////////////////////////////////////////
825 void PandaNode::
826 stash_child(int child_index, Thread *current_thread) {
827  int pipeline_stage = current_thread->get_pipeline_stage();
828  nassertv(pipeline_stage == 0);
829  nassertv(child_index >= 0 && child_index < get_num_children());
830 
831  // Save a reference count for ourselves.
832  PT(PandaNode) self = this;
833 
834  PT(PandaNode) child_node = get_child(child_index);
835  int sort = get_child_sort(child_index);
836 
837  remove_child(child_index);
838 
839  {
840  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
841  CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
842 
843  cdata->modify_stashed()->insert(DownConnection(child_node, sort));
844  cdata_child->modify_up()->insert(UpConnection(this));
845  }
846 
847  new_connection(this, child_node, pipeline_stage, current_thread);
848  force_bounds_stale(pipeline_stage, current_thread);
849 
850  children_changed();
851  child_node->parents_changed();
853  child_node->mark_bam_modified();
854 }
855 
856 ////////////////////////////////////////////////////////////////////
857 // Function: PandaNode::unstash_child
858 // Access: Published
859 // Description: Returns the indicated stashed node to normal child
860 // status. This removes the child from the list of
861 // stashed children and puts it on the normal list of
862 // active children. This child node once again
863 // contributes to the bounding volume of the PandaNode,
864 // and will be visited in normal traversals. It is
865 // visible and collidable.
866 //
867 // This can only be called from the top pipeline stage
868 // (i.e. from App).
869 ////////////////////////////////////////////////////////////////////
870 void PandaNode::
871 unstash_child(int stashed_index, Thread *current_thread) {
872  int pipeline_stage = current_thread->get_pipeline_stage();
873  nassertv(pipeline_stage == 0);
874  nassertv(stashed_index >= 0 && stashed_index < get_num_stashed());
875 
876  // Save a reference count for ourselves. I don't think this should
877  // be necessary, but there are occasional crashes in stash() during
878  // furniture moving mode. Perhaps this will eliminate those
879  // crashes.
880  PT(PandaNode) self = this;
881 
882  PT(PandaNode) child_node = get_stashed(stashed_index);
883  int sort = get_stashed_sort(stashed_index);
884 
885  remove_stashed(stashed_index);
886 
887  {
888  CDWriter cdata(_cycler);
889  CDWriter cdata_child(child_node->_cycler);
890 
891  cdata->modify_down()->insert(DownConnection(child_node, sort));
892  cdata_child->modify_up()->insert(UpConnection(this));
893  }
894 
895  new_connection(this, child_node, pipeline_stage, current_thread);
896 
897  force_bounds_stale();
898  children_changed();
899  child_node->parents_changed();
901  child_node->mark_bam_modified();
902 }
903 
904 ////////////////////////////////////////////////////////////////////
905 // Function: PandaNode::add_stashed
906 // Access: Published
907 // Description: Adds a new child to the node, directly as a stashed
908 // child. The child is not added in the normal sense,
909 // but will be revealed if unstash_child() is called on
910 // it later.
911 //
912 // If the same child is added to a node more than once,
913 // the previous instance is first removed.
914 //
915 // This can only be called from the top pipeline stage
916 // (i.e. from App).
917 ////////////////////////////////////////////////////////////////////
918 void PandaNode::
919 add_stashed(PandaNode *child_node, int sort, Thread *current_thread) {
920  int pipeline_stage = current_thread->get_pipeline_stage();
921  nassertv(pipeline_stage == 0);
922 
923  if (!verify_child_no_cycles(child_node)) {
924  // Whoops, adding this child node would introduce a cycle in the
925  // scene graph.
926  return;
927  }
928 
929  // Ensure the child_node is not deleted while we do this.
930  PT(PandaNode) keep_child = child_node;
931  remove_child(child_node);
932 
933  {
934  CDWriter cdata(_cycler);
935  CDWriter cdata_child(child_node->_cycler);
936 
937  cdata->modify_stashed()->insert(DownConnection(child_node, sort));
938  cdata_child->modify_up()->insert(UpConnection(this));
939  }
940 
941  new_connection(this, child_node, pipeline_stage, current_thread);
942 
943  // Call callback hooks.
944  children_changed();
945  child_node->parents_changed();
947  child_node->mark_bam_modified();
948 }
949 
950 ////////////////////////////////////////////////////////////////////
951 // Function: PandaNode::remove_stashed
952 // Access: Published
953 // Description: Removes the nth stashed child from the node.
954 ////////////////////////////////////////////////////////////////////
955 void PandaNode::
956 remove_stashed(int child_index, Thread *current_thread) {
957  int pipeline_stage = current_thread->get_pipeline_stage();
958  nassertv(pipeline_stage == 0);
959 
960  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
961  Down &stashed = *cdata->modify_stashed();
962  nassertv(child_index >= 0 && child_index < (int)stashed.size());
963 
964  PT(PandaNode) child_node = stashed[child_index].get_child();
965  CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
966 
967  stashed.erase(stashed.begin() + child_index);
968  int num_erased = cdata_child->modify_up()->erase(UpConnection(this));
969  nassertv(num_erased == 1);
970 
971  sever_connection(this, child_node, pipeline_stage, current_thread);
972  force_bounds_stale(pipeline_stage, current_thread);
973 
974  children_changed();
975  child_node->parents_changed();
977  child_node->mark_bam_modified();
978 }
979 
980 ////////////////////////////////////////////////////////////////////
981 // Function: PandaNode::remove_all_children
982 // Access: Published
983 // Description: Removes all the children from the node at once,
984 // including stashed children.
985 //
986 // This can only be called from the top pipeline stage
987 // (i.e. from App).
988 ////////////////////////////////////////////////////////////////////
989 void PandaNode::
990 remove_all_children(Thread *current_thread) {
991  // We have to do this for each upstream pipeline stage.
992  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
993  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
994  PT(Down) down = cdata->modify_down();
995  Down::iterator di;
996  for (di = down->begin(); di != down->end(); ++di) {
997  PT(PandaNode) child_node = (*di).get_child();
998  CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
999  current_thread);
1000  cdata_child->modify_up()->erase(UpConnection(this));
1001 
1002  sever_connection(this, child_node, pipeline_stage, current_thread);
1003  child_node->parents_changed();
1004  child_node->mark_bam_modified();
1005  }
1006  down->clear();
1007 
1008  Down &stashed = *cdata->modify_stashed();
1009  for (di = stashed.begin(); di != stashed.end(); ++di) {
1010  PT(PandaNode) child_node = (*di).get_child();
1011  CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
1012  current_thread);
1013  cdata_child->modify_up()->erase(UpConnection(this));
1014 
1015  sever_connection(this, child_node, pipeline_stage, current_thread);
1016  child_node->parents_changed();
1017  child_node->mark_bam_modified();
1018  }
1019  stashed.clear();
1020  }
1021  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1022 
1023  force_bounds_stale();
1024  children_changed();
1026 }
1027 
1028 ////////////////////////////////////////////////////////////////////
1029 // Function: PandaNode::steal_children
1030 // Access: Published
1031 // Description: Moves all the children from the other node onto this
1032 // node.
1033 //
1034 // Any NodePaths to child nodes of the other node are
1035 // truncated, rather than moved to the new parent.
1036 ////////////////////////////////////////////////////////////////////
1037 void PandaNode::
1038 steal_children(PandaNode *other, Thread *current_thread) {
1039  if (other == this) {
1040  // Trivial.
1041  return;
1042  }
1043 
1044  // We do this through the high-level interface for convenience.
1045  // This could begin to be a problem if we have a node with hundreds
1046  // of children to copy; this could break down the ov_set.insert()
1047  // method, which is an O(n^2) operation. If this happens, we should
1048  // rewrite this to do a simpler add_child() operation that involves
1049  // push_back() instead of insert(), and then sort the down list at
1050  // the end.
1051 
1052  int num_children = other->get_num_children();
1053  int i;
1054  for (i = 0; i < num_children; i++) {
1055  PandaNode *child_node = other->get_child(i);
1056  int sort = other->get_child_sort(i);
1057  add_child(child_node, sort, current_thread);
1058  }
1059  int num_stashed = other->get_num_stashed();
1060  for (i = 0; i < num_stashed; i++) {
1061  PandaNode *child_node = other->get_stashed(i);
1062  int sort = other->get_stashed_sort(i);
1063  add_stashed(child_node, sort, current_thread);
1064  }
1065 
1066  other->remove_all_children(current_thread);
1067 }
1068 
1069 ////////////////////////////////////////////////////////////////////
1070 // Function: PandaNode::copy_children
1071 // Access: Published
1072 // Description: Makes another instance of all the children of the
1073 // other node, copying them to this node.
1074 ////////////////////////////////////////////////////////////////////
1075 void PandaNode::
1076 copy_children(PandaNode *other, Thread *current_thread) {
1077  if (other == this) {
1078  // Trivial.
1079  return;
1080  }
1081  Children children = other->get_children(current_thread);
1082  Stashed stashed = other->get_stashed(current_thread);
1083  int num_children = children.get_num_children();
1084  int i;
1085  for (i = 0; i < num_children; i++) {
1086  PandaNode *child_node = children.get_child(i);
1087  int sort = children.get_child_sort(i);
1088  add_child(child_node, sort, current_thread);
1089  }
1090  int num_stashed = stashed.get_num_stashed();
1091  for (i = 0; i < num_stashed; i++) {
1092  PandaNode *child_node = stashed.get_stashed(i);
1093  int sort = stashed.get_stashed_sort(i);
1094  add_stashed(child_node, sort, current_thread);
1095  }
1096 }
1097 
1098 ////////////////////////////////////////////////////////////////////
1099 // Function: PandaNode::set_attrib
1100 // Access: Published
1101 // Description: Adds the indicated render attribute to the scene
1102 // graph on this node. This attribute will now apply to
1103 // this node and everything below. If there was already
1104 // an attribute of the same type, it is replaced.
1105 ////////////////////////////////////////////////////////////////////
1106 void PandaNode::
1107 set_attrib(const RenderAttrib *attrib, int override) {
1108  // Apply this operation to the current stage as well as to all
1109  // upstream stages.
1110  bool any_changed = false;
1111  Thread *current_thread = Thread::get_current_thread();
1112  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1113  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1114 
1115  CPT(RenderState) new_state = cdata->_state->set_attrib(attrib, override);
1116  if (cdata->_state != new_state) {
1117  cdata->_state = new_state;
1118  cdata->set_fancy_bit(FB_state, true);
1119  any_changed = true;
1120  }
1121  }
1122  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1123 
1124  // Maybe we changed a ClipPlaneAttrib.
1125  if (any_changed) {
1126  mark_bounds_stale(current_thread);
1127  state_changed();
1129  }
1130 }
1131 
1132 ////////////////////////////////////////////////////////////////////
1133 // Function: PandaNode::clear_attrib
1134 // Access: Published
1135 // Description: Removes the render attribute of the given type from
1136 // this node. This node, and the subgraph below, will
1137 // now inherit the indicated render attribute from the
1138 // nodes above this one.
1139 ////////////////////////////////////////////////////////////////////
1140 void PandaNode::
1141 clear_attrib(int slot) {
1142  bool any_changed = false;
1143 
1144  Thread *current_thread = Thread::get_current_thread();
1145  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1146  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1147 
1148  CPT(RenderState) new_state = cdata->_state->remove_attrib(slot);
1149  if (cdata->_state != new_state) {
1150  cdata->_state = new_state;
1151  cdata->set_fancy_bit(FB_state, !new_state->is_empty());
1152  any_changed = true;
1153  }
1154  }
1155  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1156 
1157  // We mark the bounds stale when the state changes, in case
1158  // we have changed a ClipPlaneAttrib.
1159  if (any_changed) {
1160  mark_bounds_stale(current_thread);
1161  state_changed();
1163  }
1164 }
1165 
1166 ////////////////////////////////////////////////////////////////////
1167 // Function: PandaNode::set_effect
1168 // Access: Published
1169 // Description: Adds the indicated render effect to the scene
1170 // graph on this node. If there was already an effect
1171 // of the same type, it is replaced.
1172 ////////////////////////////////////////////////////////////////////
1173 void PandaNode::
1174 set_effect(const RenderEffect *effect) {
1175  // Apply this operation to the current stage as well as to all
1176  // upstream stages.
1177  Thread *current_thread = Thread::get_current_thread();
1178  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1179  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1180  cdata->_effects = cdata->_effects->add_effect(effect);
1181  cdata->set_fancy_bit(FB_effects, true);
1182  }
1183  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1185 }
1186 
1187 ////////////////////////////////////////////////////////////////////
1188 // Function: PandaNode::clear_effect
1189 // Access: Published
1190 // Description: Removes the render effect of the given type from
1191 // this node.
1192 ////////////////////////////////////////////////////////////////////
1193 void PandaNode::
1195  Thread *current_thread = Thread::get_current_thread();
1196  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1197  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1198  cdata->_effects = cdata->_effects->remove_effect(type);
1199  cdata->set_fancy_bit(FB_effects, !cdata->_effects->is_empty());
1200  }
1201  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1203 }
1204 
1205 ////////////////////////////////////////////////////////////////////
1206 // Function: PandaNode::set_state
1207 // Access: Published
1208 // Description: Sets the complete RenderState that will be applied to
1209 // all nodes at this level and below. (The actual state
1210 // that will be applied to lower nodes is based on the
1211 // composition of RenderStates from above this node as
1212 // well). This completely replaces whatever has been
1213 // set on this node via repeated calls to set_attrib().
1214 ////////////////////////////////////////////////////////////////////
1215 void PandaNode::
1216 set_state(const RenderState *state, Thread *current_thread) {
1217  // Apply this operation to the current stage as well as to all
1218  // upstream stages.
1219  bool any_changed = false;
1220  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1221  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1222  if (cdata->_state != state) {
1223  cdata->_state = state;
1224  cdata->set_fancy_bit(FB_state, !state->is_empty());
1225  any_changed = true;
1226  }
1227  }
1228  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1229 
1230  // Maybe we have changed a ClipPlaneAttrib.
1231  if (any_changed) {
1232  mark_bounds_stale(current_thread);
1233  state_changed();
1235  }
1236 }
1237 
1238 ////////////////////////////////////////////////////////////////////
1239 // Function: PandaNode::set_effects
1240 // Access: Published
1241 // Description: Sets the complete RenderEffects that will be applied
1242 // this node. This completely replaces whatever has
1243 // been set on this node via repeated calls to
1244 // set_attrib().
1245 ////////////////////////////////////////////////////////////////////
1246 void PandaNode::
1247 set_effects(const RenderEffects *effects, Thread *current_thread) {
1248  // Apply this operation to the current stage as well as to all
1249  // upstream stages.
1250  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1251  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1252  cdata->_effects = effects;
1253  cdata->set_fancy_bit(FB_effects, !effects->is_empty());
1254  }
1255  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1257 }
1258 
1259 ////////////////////////////////////////////////////////////////////
1260 // Function: PandaNode::set_transform
1261 // Access: Published
1262 // Description: Sets the transform that will be applied to this node
1263 // and below. This defines a new coordinate space at
1264 // this point in the scene graph and below.
1265 ////////////////////////////////////////////////////////////////////
1266 void PandaNode::
1267 set_transform(const TransformState *transform, Thread *current_thread) {
1268  // Need to have this held before we grab any other locks.
1269  LightMutexHolder holder(_dirty_prev_transforms._lock);
1270 
1271  // Apply this operation to the current stage as well as to all
1272  // upstream stages.
1273  bool any_changed = false;
1274  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1275  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1276  if (cdata->_transform != transform) {
1277  cdata->_transform = transform;
1278  cdata->set_fancy_bit(FB_transform, !transform->is_identity());
1279  any_changed = true;
1280 
1281  if (pipeline_stage == 0) {
1282  if (cdata->_transform != cdata->_prev_transform) {
1283  do_set_dirty_prev_transform();
1284  }
1285  }
1286  }
1287  }
1288  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1289 
1290  if (any_changed) {
1291  mark_bounds_stale(current_thread);
1292  transform_changed();
1294  }
1295 }
1296 
1297 ////////////////////////////////////////////////////////////////////
1298 // Function: PandaNode::set_prev_transform
1299 // Access: Published
1300 // Description: Sets the transform that represents this node's
1301 // "previous" position, one frame ago, for the purposes
1302 // of detecting motion for accurate collision
1303 // calculations.
1304 ////////////////////////////////////////////////////////////////////
1305 void PandaNode::
1306 set_prev_transform(const TransformState *transform, Thread *current_thread) {
1307  // Need to have this held before we grab any other locks.
1308  LightMutexHolder holder(_dirty_prev_transforms._lock);
1309 
1310  // Apply this operation to the current stage as well as to all
1311  // upstream stages.
1312  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1313  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1314  cdata->_prev_transform = transform;
1315  if (pipeline_stage == 0) {
1316  if (cdata->_transform != cdata->_prev_transform) {
1317  do_set_dirty_prev_transform();
1318  } else {
1319  do_clear_dirty_prev_transform();
1320  }
1321  }
1322  }
1323  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1325 }
1326 
1327 ////////////////////////////////////////////////////////////////////
1328 // Function: PandaNode::reset_prev_transform
1329 // Access: Published
1330 // Description: Resets the transform that represents this node's
1331 // "previous" position to the same as the current
1332 // transform. This is not the same thing as clearing it
1333 // to identity.
1334 ////////////////////////////////////////////////////////////////////
1335 void PandaNode::
1336 reset_prev_transform(Thread *current_thread) {
1337  // Need to have this held before we grab any other locks.
1338  LightMutexHolder holder(_dirty_prev_transforms._lock);
1339  do_clear_dirty_prev_transform();
1340 
1341  // Apply this operation to the current stage as well as to all
1342  // upstream stages.
1343 
1344  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1345  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1346  cdata->_prev_transform = cdata->_transform;
1347  }
1348  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1350 }
1351 
1352 ////////////////////////////////////////////////////////////////////
1353 // Function: PandaNode::reset_all_prev_transform
1354 // Access: Published, Static
1355 // Description: Visits all nodes in the world with the
1356 // _dirty_prev_transform flag--that is, all nodes whose
1357 // _prev_transform is different from the _transform in
1358 // pipeline stage 0--and resets the _prev_transform to
1359 // be the same as _transform.
1360 ////////////////////////////////////////////////////////////////////
1361 void PandaNode::
1363  nassertv(current_thread->get_pipeline_stage() == 0);
1364 
1365  PStatTimer timer(_reset_prev_pcollector, current_thread);
1366  LightMutexHolder holder(_dirty_prev_transforms._lock);
1367 
1368  LinkedListNode *list_node = _dirty_prev_transforms._next;
1369  while (list_node != &_dirty_prev_transforms) {
1370  PandaNode *panda_node = (PandaNode *)list_node;
1371  nassertv(panda_node->_dirty_prev_transform);
1372  panda_node->_dirty_prev_transform = false;
1373 
1374  CDStageWriter cdata(panda_node->_cycler, 0, current_thread);
1375  cdata->_prev_transform = cdata->_transform;
1376 
1377  list_node = panda_node->_next;
1378 #ifndef NDEBUG
1379  panda_node->_prev = NULL;
1380  panda_node->_next = NULL;
1381 #endif // NDEBUG
1382  panda_node->mark_bam_modified();
1383  }
1384 
1385  _dirty_prev_transforms._prev = &_dirty_prev_transforms;
1386  _dirty_prev_transforms._next = &_dirty_prev_transforms;
1387 }
1388 
1389 ////////////////////////////////////////////////////////////////////
1390 // Function: PandaNode::set_tag
1391 // Access: Published
1392 // Description: Associates a user-defined value with a user-defined
1393 // key which is stored on the node. This value has no
1394 // meaning to Panda; but it is stored indefinitely on
1395 // the node until it is requested again.
1396 //
1397 // Each unique key stores a different string value.
1398 // There is no effective limit on the number of
1399 // different keys that may be stored or on the length of
1400 // any one key's value.
1401 ////////////////////////////////////////////////////////////////////
1402 void PandaNode::
1403 set_tag(const string &key, const string &value, Thread *current_thread) {
1404  // Apply this operation to the current stage as well as to all
1405  // upstream stages.
1406  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1407  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1408  cdata->_tag_data[key] = value;
1409  cdata->set_fancy_bit(FB_tag, true);
1410  }
1411  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1413 }
1414 
1415 ////////////////////////////////////////////////////////////////////
1416 // Function: PandaNode::clear_tag
1417 // Access: Published
1418 // Description: Removes the value defined for this key on this
1419 // particular node. After a call to clear_tag(),
1420 // has_tag() will return false for the indicated key.
1421 ////////////////////////////////////////////////////////////////////
1422 void PandaNode::
1423 clear_tag(const string &key, Thread *current_thread) {
1424  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1425  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1426  cdata->_tag_data.erase(key);
1427  cdata->set_fancy_bit(FB_tag, !cdata->_tag_data.empty());
1428  }
1429  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1431 }
1432 
1433 ////////////////////////////////////////////////////////////////////
1434 // Function: PandaNode::copy_tags
1435 // Access: Published
1436 // Description: Copies all of the tags stored on the other node onto
1437 // this node. If a particular tag exists on both nodes,
1438 // the contents of this node's value is replaced by that
1439 // of the other.
1440 ////////////////////////////////////////////////////////////////////
1441 void PandaNode::
1443  if (other == this) {
1444  // Trivial.
1445  return;
1446  }
1447 
1448  // Apply this operation to the current stage as well as to all
1449  // upstream stages.
1450  Thread *current_thread = Thread::get_current_thread();
1451  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1452  CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
1453  CDStageReader cdatar(other->_cycler, pipeline_stage, current_thread);
1454 
1455  TagData::const_iterator ti;
1456  for (ti = cdatar->_tag_data.begin();
1457  ti != cdatar->_tag_data.end();
1458  ++ti) {
1459  cdataw->_tag_data[(*ti).first] = (*ti).second;
1460  }
1461  cdataw->set_fancy_bit(FB_tag, !cdataw->_tag_data.empty());
1462 
1463 #ifdef HAVE_PYTHON
1464  PythonTagData::const_iterator pti;
1465  for (pti = cdatar->_python_tag_data.begin();
1466  pti != cdatar->_python_tag_data.end();
1467  ++pti) {
1468  const string &key = (*pti).first;
1469  PyObject *value = (*pti).second;
1470  Py_XINCREF(value);
1471 
1472  pair<PythonTagData::iterator, bool> result;
1473  result = cdataw->_python_tag_data.insert(PythonTagData::value_type(key, value));
1474 
1475  if (!result.second) {
1476  // The insert was unsuccessful; that means the key was already
1477  // present in the map. In this case, we should decrement the
1478  // original value's reference count and replace it with the new
1479  // object.
1480  PythonTagData::iterator wpti = result.first;
1481  PyObject *old_value = (*wpti).second;
1482  Py_XDECREF(old_value);
1483  (*wpti).second = value;
1484  }
1485  }
1486 #endif // HAVE_PYTHON
1487  }
1488  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1490 }
1491 
1492 ////////////////////////////////////////////////////////////////////
1493 // Function: PandaNode::list_tags
1494 // Access: Published
1495 // Description: Writes a list of all the tag keys assigned to the
1496 // node to the indicated stream. Writes one instance of
1497 // the separator following each key (but does not write
1498 // a terminal separator). The value associated with
1499 // each key is not written.
1500 //
1501 // This is mainly for the benefit of the realtime user,
1502 // to see the list of all of the associated tag keys.
1503 ////////////////////////////////////////////////////////////////////
1504 void PandaNode::
1505 list_tags(ostream &out, const string &separator) const {
1506  CDReader cdata(_cycler);
1507  if (!cdata->_tag_data.empty()) {
1508  TagData::const_iterator ti = cdata->_tag_data.begin();
1509  out << (*ti).first;
1510  ++ti;
1511  while (ti != cdata->_tag_data.end()) {
1512  out << separator << (*ti).first;
1513  ++ti;
1514  }
1515  }
1516 
1517 #ifdef HAVE_PYTHON
1518  if (!cdata->_python_tag_data.empty()) {
1519  if (!cdata->_tag_data.empty()) {
1520  out << separator;
1521  }
1522  PythonTagData::const_iterator ti = cdata->_python_tag_data.begin();
1523  out << (*ti).first;
1524  ++ti;
1525  while (ti != cdata->_python_tag_data.end()) {
1526  out << separator << (*ti).first;
1527  ++ti;
1528  }
1529  }
1530 #endif // HAVE_PYTHON
1531 }
1532 
1533 ////////////////////////////////////////////////////////////////////
1534 // Function: Filename::get_tag_keys
1535 // Access: Published
1536 // Description: Fills the given vector up with the
1537 // list of tags on this PandaNode.
1538 //
1539 // It is the user's responsibility to ensure that the
1540 // keys vector is empty before making this call;
1541 // otherwise, the new keys will be appended to it.
1542 ////////////////////////////////////////////////////////////////////
1543 void PandaNode::
1544 get_tag_keys(vector_string &keys) const {
1545  CDReader cdata(_cycler);
1546  if (!cdata->_tag_data.empty()) {
1547  TagData::const_iterator ti = cdata->_tag_data.begin();
1548  while (ti != cdata->_tag_data.end()) {
1549  keys.push_back((*ti).first);
1550  ++ti;
1551  }
1552  }
1553 }
1554 
1555 ////////////////////////////////////////////////////////////////////
1556 // Function: PandaNode::compare_tags
1557 // Access: Published
1558 // Description: Returns a number less than 0, 0, or greater than 0,
1559 // to indicate the similarity of tags between this node
1560 // and the other one. If this returns 0, the tags are
1561 // identical. If it returns other than 0, then the tags
1562 // are different; and the nodes may be sorted into a
1563 // consistent (but arbitrary) ordering based on this
1564 // number.
1565 ////////////////////////////////////////////////////////////////////
1566 int PandaNode::
1567 compare_tags(const PandaNode *other) const {
1568  CDReader cdata(_cycler);
1569  CDReader cdata_other(other->_cycler);
1570 
1571  TagData::const_iterator ati = cdata->_tag_data.begin();
1572  TagData::const_iterator bti = cdata_other->_tag_data.begin();
1573  while (ati != cdata->_tag_data.end() &&
1574  bti != cdata_other->_tag_data.end()) {
1575  int cmp = strcmp((*ati).first.c_str(), (*bti).first.c_str());
1576  if (cmp != 0) {
1577  return cmp;
1578  }
1579 
1580  cmp = strcmp((*ati).second.c_str(), (*bti).second.c_str());
1581  if (cmp != 0) {
1582  return cmp;
1583  }
1584 
1585  ++ati;
1586  ++bti;
1587  }
1588  if (ati != cdata->_tag_data.end()) {
1589  // list A is longer.
1590  return 1;
1591  }
1592  if (bti != cdata_other->_tag_data.end()) {
1593  // list B is longer.
1594  return -1;
1595  }
1596 
1597 #ifdef HAVE_PYTHON
1598  PythonTagData::const_iterator api = cdata->_python_tag_data.begin();
1599  PythonTagData::const_iterator bpi = cdata_other->_python_tag_data.begin();
1600  while (api != cdata->_python_tag_data.end() &&
1601  bpi != cdata_other->_python_tag_data.end()) {
1602  int cmp = strcmp((*api).first.c_str(), (*bpi).first.c_str());
1603  if (cmp != 0) {
1604  return cmp;
1605  }
1606 
1607 #if PY_MAJOR_VERSION >= 3
1608  if (PyObject_RichCompareBool((*api).second, (*bpi).second, Py_LT) == 1) {
1609  return -1;
1610  } else if (PyObject_RichCompareBool((*api).second, (*bpi).second, Py_GT) == 1) {
1611  return 1;
1612  } else if (PyObject_RichCompareBool((*api).second, (*bpi).second, Py_EQ) == 1) {
1613  cmp = 0;
1614  } else {
1615 #else
1616  if (PyObject_Cmp((*api).second, (*bpi).second, &cmp) == -1) {
1617 #endif
1618  // Unable to compare objects; just compare pointers.
1619  if ((*api).second != (*bpi).second) {
1620  cmp = (*api).second < (*bpi).second ? -1 : 1;
1621  } else {
1622  cmp = 0;
1623  }
1624  }
1625  if (cmp != 0) {
1626  return cmp;
1627  }
1628 
1629  ++api;
1630  ++bpi;
1631  }
1632  if (api != cdata->_python_tag_data.end()) {
1633  // list A is longer.
1634  return 1;
1635  }
1636  if (bpi != cdata_other->_python_tag_data.end()) {
1637  // list B is longer.
1638  return -1;
1639  }
1640 #endif // HAVE_PYTHON
1641 
1642  return 0;
1643 }
1644 
1645 ////////////////////////////////////////////////////////////////////
1646 // Function: PandaNode::copy_all_properties
1647 // Access: Published
1648 // Description: Copies the TransformState, RenderState,
1649 // RenderEffects, tags, Python tags, and the show/hide
1650 // state from the other node onto this one. Typically
1651 // this is used to prepare a node to replace another
1652 // node in the scene graph (also see replace_node()).
1653 ////////////////////////////////////////////////////////////////////
1654 void PandaNode::
1656  if (other == this) {
1657  // Trivial.
1658  return;
1659  }
1660 
1661  // Need to have this held before we grab any other locks.
1662  LightMutexHolder holder(_dirty_prev_transforms._lock);
1663 
1664  bool any_transform_changed = false;
1665  bool any_state_changed = false;
1666  bool any_draw_mask_changed = false;
1667  Thread *current_thread = Thread::get_current_thread();
1668  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1669  CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
1670  CDStageReader cdatar(other->_cycler, pipeline_stage, current_thread);
1671 
1672  if (cdataw->_transform != cdatar->_transform) {
1673  any_transform_changed = true;
1674  }
1675  if (cdataw->_state != cdatar->_state) {
1676  any_state_changed = true;
1677  }
1678  if (cdataw->_draw_control_mask != cdatar->_draw_control_mask ||
1679  cdataw->_draw_show_mask != cdatar->_draw_show_mask) {
1680  any_draw_mask_changed = true;
1681  }
1682 
1683  cdataw->_transform = cdatar->_transform;
1684  cdataw->_prev_transform = cdatar->_prev_transform;
1685  cdataw->_state = cdatar->_state;
1686  cdataw->_effects = cdatar->_effects;
1687  cdataw->_draw_control_mask = cdatar->_draw_control_mask;
1688  cdataw->_draw_show_mask = cdatar->_draw_show_mask;
1689 
1690  // The collide mask becomes the union of the two masks. This is
1691  // important to preserve properties such as the default GeomNode
1692  // bitmask.
1693  cdataw->_into_collide_mask |= cdatar->_into_collide_mask;
1694 
1695  TagData::const_iterator ti;
1696  for (ti = cdatar->_tag_data.begin();
1697  ti != cdatar->_tag_data.end();
1698  ++ti) {
1699  cdataw->_tag_data[(*ti).first] = (*ti).second;
1700  }
1701 
1702 #ifdef HAVE_PYTHON
1703  PythonTagData::const_iterator pti;
1704  for (pti = cdatar->_python_tag_data.begin();
1705  pti != cdatar->_python_tag_data.end();
1706  ++pti) {
1707  const string &key = (*pti).first;
1708  PyObject *value = (*pti).second;
1709  Py_XINCREF(value);
1710 
1711  pair<PythonTagData::iterator, bool> result;
1712  result = cdataw->_python_tag_data.insert(PythonTagData::value_type(key, value));
1713 
1714  if (!result.second) {
1715  // The insert was unsuccessful; that means the key was already
1716  // present in the map. In this case, we should decrement the
1717  // original value's reference count and replace it with the new
1718  // object.
1719  PythonTagData::iterator wpti = result.first;
1720  PyObject *old_value = (*wpti).second;
1721  Py_XDECREF(old_value);
1722  (*wpti).second = value;
1723  }
1724  }
1725 #endif // HAVE_PYTHON
1726 
1727  static const int change_bits = (FB_transform | FB_state | FB_effects |
1728  FB_tag | FB_draw_mask);
1729  cdataw->_fancy_bits =
1730  (cdataw->_fancy_bits & ~change_bits) |
1731  (cdatar->_fancy_bits & change_bits);
1732 
1733  if (pipeline_stage == 0) {
1734  if (cdataw->_transform != cdataw->_prev_transform) {
1735  do_set_dirty_prev_transform();
1736  }
1737  }
1738  }
1739  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1740 
1741  if (any_transform_changed || any_state_changed || any_draw_mask_changed) {
1742  mark_bounds_stale(current_thread);
1743 
1744  if (any_transform_changed) {
1745  transform_changed();
1746  }
1747  if (any_state_changed) {
1748  state_changed();
1749  }
1750  if (any_draw_mask_changed) {
1751  draw_mask_changed();
1752  }
1754  }
1755 }
1756 
1757 ////////////////////////////////////////////////////////////////////
1758 // Function: PandaNode::replace_node
1759 // Access: Published
1760 // Description: Inserts this node into the scene graph in place of
1761 // the other one, and removes the other node. All scene
1762 // graph attributes (TransformState, RenderState, etc.)
1763 // are copied to this node.
1764 //
1765 // All children are moved to this node, and removed from
1766 // the old node. The new node is left in the same place
1767 // in the old node's parent's list of children.
1768 //
1769 // Even NodePaths that reference the old node are
1770 // updated in-place to reference the new node instead.
1771 //
1772 // This method is intended to be used to replace a node
1773 // of a given type in the scene graph with a node of a
1774 // different type.
1775 ////////////////////////////////////////////////////////////////////
1776 void PandaNode::
1778  // nassertv(Thread::get_current_pipeline_stage() == 0);
1779 
1780  if (other == this) {
1781  // Trivial.
1782  return;
1783  }
1784 
1785  // Make sure the other node is not destructed during the
1786  // execution of this method.
1787  PT(PandaNode) keep_other = other;
1788 
1789  // Get all the important scene graph properties.
1790  copy_all_properties(other);
1791 
1792  // Fix up the NodePaths.
1793  {
1794  LightReMutexHolder holder1(other->_paths_lock);
1795  LightReMutexHolder holder2(_paths_lock);
1796  Paths::iterator pi;
1797  for (pi = other->_paths.begin(); pi != other->_paths.end(); ++pi) {
1798  (*pi)->_node = this;
1799  _paths.insert(*pi);
1800  }
1801  other->_paths.clear();
1802  }
1803 
1804  // Get the children.
1805  steal_children(other);
1806 
1807  // Switch the parents.
1808  Thread *current_thread = Thread::get_current_thread();
1809  Parents other_parents = other->get_parents();
1810  for (int i = 0; i < other_parents.get_num_parents(); ++i) {
1811  PandaNode *parent = other_parents.get_parent(i);
1812  if (find_parent(parent) != -1) {
1813  // This node was already a child of this parent; don't change
1814  // it.
1815  parent->remove_child(other);
1816  } else {
1817  // This node was not yet a child of this parent; now it is.
1818  parent->replace_child(other, this, current_thread);
1819  }
1820  }
1821 }
1822 
1823 ////////////////////////////////////////////////////////////////////
1824 // Function: PandaNode::set_unexpected_change
1825 // Access: Published
1826 // Description: Sets one or more of the PandaNode::UnexpectedChange
1827 // bits on, indicating that the corresponding property
1828 // should not change again on this node. Once one of
1829 // these bits has been set, if the property changes, an
1830 // assertion failure will be raised, which is designed
1831 // to assist the developer in identifying the
1832 // troublesome code that modified the property
1833 // unexpectedly.
1834 //
1835 // The input parameter is the union of bits that are to
1836 // be set. To clear these bits later, use
1837 // clear_unexpected_change().
1838 //
1839 // Since this is a developer debugging tool only, this
1840 // function does nothing in a production (NDEBUG) build.
1841 ////////////////////////////////////////////////////////////////////
1842 void PandaNode::
1843 set_unexpected_change(unsigned int flags) {
1844 #ifndef NDEBUG
1845  _unexpected_change_flags |= flags;
1846 #endif // !NDEBUG
1847 }
1848 
1849 ////////////////////////////////////////////////////////////////////
1850 // Function: PandaNode::get_unexpected_change
1851 // Access: Published
1852 // Description: Returns nonzero if any of the bits in the input
1853 // parameter are set on this node, or zero if none of
1854 // them are set. More specifically, this returns the
1855 // particular set of bits (masked by the input
1856 // parameter) that have been set on this node. See
1857 // set_unexpected_change().
1858 //
1859 // Since this is a developer debugging tool only, this
1860 // function always returns zero in a production (NDEBUG)
1861 // build.
1862 ////////////////////////////////////////////////////////////////////
1863 unsigned int PandaNode::
1864 get_unexpected_change(unsigned int flags) const {
1865 #ifndef NDEBUG
1866  return _unexpected_change_flags & flags;
1867 #else
1868  return 0;
1869 #endif // !NDEBUG
1870 }
1871 
1872 ////////////////////////////////////////////////////////////////////
1873 // Function: PandaNode::clear_unexpected_change
1874 // Access: Published
1875 // Description: Sets one or more of the PandaNode::UnexpectedChange
1876 // bits off, indicating that the corresponding property
1877 // may once again change on this node. See
1878 // set_unexpected_change().
1879 //
1880 // The input parameter is the union of bits that are to
1881 // be cleared.
1882 //
1883 // Since this is a developer debugging tool only, this
1884 // function does nothing in a production (NDEBUG) build.
1885 ////////////////////////////////////////////////////////////////////
1886 void PandaNode::
1887 clear_unexpected_change(unsigned int flags) {
1888 #ifndef NDEBUG
1889  _unexpected_change_flags &= ~flags;
1890 #endif // !NDEBUG
1891 }
1892 
1893 ////////////////////////////////////////////////////////////////////
1894 // Function: PandaNode::adjust_draw_mask
1895 // Access: Published
1896 // Description: Adjusts the hide/show bits of this particular node.
1897 //
1898 // These three parameters can be used to adjust the
1899 // _draw_control_mask and _draw_show_mask independently,
1900 // which work together to provide per-camera visibility
1901 // for the node and its descendents.
1902 //
1903 // _draw_control_mask indicates the bits in
1904 // _draw_show_mask that are significant. Each different
1905 // bit corresponds to a different camera (and these bits
1906 // are assigned via Camera::set_camera_mask()).
1907 //
1908 // Where _draw_control_mask has a 1 bit, a 1 bit in
1909 // _draw_show_mask indicates the node is visible to that
1910 // camera, and a 0 bit indicates the node is hidden to
1911 // that camera. Where _draw_control_mask is 0, the node
1912 // is hidden only if a parent node is hidden.
1913 //
1914 // The meaning of the three parameters is as follows:
1915 //
1916 // * Wherever show_mask is 1, _draw_show_mask and
1917 // _draw_control_mask will be set 1. Thus, show_mask
1918 // indicates the set of cameras to which the node should
1919 // be shown.
1920 //
1921 // * Wherever hide_mask is 1, _draw_show_mask will be
1922 // set 0 and _draw_control_mask will be set 1. Thus,
1923 // hide_mask indicates the set of cameras from which the
1924 // node should be hidden.
1925 //
1926 // * Wherever clear_mask is 1, _draw_control_mask will
1927 // be set 0. Thus, clear_mask indicates the set of
1928 // cameras from which the hidden state should be
1929 // inherited from a parent.
1930 ////////////////////////////////////////////////////////////////////
1931 void PandaNode::
1932 adjust_draw_mask(DrawMask show_mask, DrawMask hide_mask, DrawMask clear_mask) {
1933  bool any_changed = false;
1934 
1935  Thread *current_thread = Thread::get_current_thread();
1936  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1937  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1938 
1939  DrawMask draw_control_mask = (cdata->_draw_control_mask | show_mask | hide_mask) & ~clear_mask;
1940  DrawMask draw_show_mask = (cdata->_draw_show_mask | show_mask) & ~hide_mask;
1941  // The uncontrolled bits are implicitly on.
1942  draw_show_mask |= ~draw_control_mask;
1943 
1944  if (cdata->_draw_control_mask != draw_control_mask ||
1945  cdata->_draw_show_mask != draw_show_mask) {
1946  cdata->_draw_control_mask = draw_control_mask;
1947  cdata->_draw_show_mask = draw_show_mask;
1948  any_changed = true;
1949  }
1950  cdata->set_fancy_bit(FB_draw_mask, !draw_control_mask.is_zero());
1951  }
1952  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1953 
1954  if (any_changed) {
1955  mark_bounds_stale(current_thread);
1956  draw_mask_changed();
1958  }
1959 }
1960 
1961 ////////////////////////////////////////////////////////////////////
1962 // Function: PandaNode::get_net_draw_control_mask
1963 // Access: Published
1964 // Description: Returns the set of bits in get_net_draw_show_mask()
1965 // that have been explicitly set via adjust_draw_mask(),
1966 // rather than implicitly inherited.
1967 //
1968 // A 1 bit in any position of this mask indicates that
1969 // (a) this node has renderable children, and (b) some
1970 // child of this node has made an explicit hide() or
1971 // show_through() call for the corresponding bit.
1972 ////////////////////////////////////////////////////////////////////
1975  Thread *current_thread = Thread::get_current_thread();
1976  int pipeline_stage = current_thread->get_pipeline_stage();
1977  CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
1978  if (cdata->_last_update != cdata->_next_update) {
1979  // The cache is stale; it needs to be rebuilt.
1980  PStatTimer timer(_update_bounds_pcollector);
1981  CDStageWriter cdataw =
1982  ((PandaNode *)this)->update_cached(false, pipeline_stage, cdata);
1983  return cdataw->_net_draw_control_mask;
1984  }
1985  return cdata->_net_draw_control_mask;
1986 }
1987 
1988 ////////////////////////////////////////////////////////////////////
1989 // Function: PandaNode::get_net_draw_show_mask
1990 // Access: Published
1991 // Description: Returns the union of all draw_show_mask values--of
1992 // renderable nodes only--at this level and below. If
1993 // any bit in this mask is 0, there is no reason to
1994 // traverse below this node for a camera with the
1995 // corresponding camera_mask.
1996 //
1997 // The bits in this mask that do not correspond to a 1
1998 // bit in the net_draw_control_mask are meaningless (and
1999 // will be set to 1). For bits that *do* correspond to
2000 // a 1 bit in the net_draw_control_mask, a 1 bit
2001 // indicates that at least one child should be visible,
2002 // while a 0 bit indicates that all children are hidden.
2003 ////////////////////////////////////////////////////////////////////
2006  Thread *current_thread = Thread::get_current_thread();
2007  int pipeline_stage = current_thread->get_pipeline_stage();
2008  CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
2009  if (cdata->_last_update != cdata->_next_update) {
2010  // The cache is stale; it needs to be rebuilt.
2011  PStatTimer timer(_update_bounds_pcollector);
2012  CDStageWriter cdataw =
2013  ((PandaNode *)this)->update_cached(false, pipeline_stage, cdata);
2014  return cdataw->_net_draw_show_mask;
2015  }
2016  return cdata->_net_draw_show_mask;
2017 }
2018 
2019 ////////////////////////////////////////////////////////////////////
2020 // Function: PandaNode::set_into_collide_mask
2021 // Access: Published
2022 // Description: Sets the "into" CollideMask.
2023 //
2024 // This specifies the set of bits that must be shared
2025 // with a CollisionNode's "from" CollideMask in order
2026 // for the CollisionNode to detect a collision with this
2027 // particular node.
2028 //
2029 // The actual CollideMask that will be set is masked by
2030 // the return value from get_legal_collide_mask().
2031 // Thus, the into_collide_mask cannot be set to anything
2032 // other than nonzero except for those types of nodes
2033 // that can be collided into, such as CollisionNodes and
2034 // GeomNodes.
2035 ////////////////////////////////////////////////////////////////////
2036 void PandaNode::
2038  mask &= get_legal_collide_mask();
2039 
2040  bool any_changed = false;
2041  Thread *current_thread = Thread::get_current_thread();
2042  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
2043  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
2044  if (cdata->_into_collide_mask != mask) {
2045  cdata->_into_collide_mask = mask;
2046  any_changed = true;
2047  }
2048  }
2049  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
2050 
2051  if (any_changed) {
2052  mark_bounds_stale(current_thread);
2054  }
2055 }
2056 
2057 ////////////////////////////////////////////////////////////////////
2058 // Function: PandaNode::get_legal_collide_mask
2059 // Access: Published, Virtual
2060 // Description: Returns the subset of CollideMask bits that may be
2061 // set for this particular type of PandaNode. For most
2062 // nodes, this is 0; it doesn't make sense to set a
2063 // CollideMask for most kinds of nodes.
2064 //
2065 // For nodes that can be collided with, such as GeomNode
2066 // and CollisionNode, this returns all bits on.
2067 ////////////////////////////////////////////////////////////////////
2070  return CollideMask::all_off();
2071 }
2072 
2073 ////////////////////////////////////////////////////////////////////
2074 // Function: PandaNode::get_net_collide_mask
2075 // Access: Published
2076 // Description: Returns the union of all into_collide_mask() values
2077 // set at CollisionNodes at this level and below.
2078 ////////////////////////////////////////////////////////////////////
2080 get_net_collide_mask(Thread *current_thread) const {
2081  int pipeline_stage = current_thread->get_pipeline_stage();
2082  CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
2083  if (cdata->_last_update != cdata->_next_update) {
2084  // The cache is stale; it needs to be rebuilt.
2085  PStatTimer timer(_update_bounds_pcollector);
2086  CDStageWriter cdataw =
2087  ((PandaNode *)this)->update_cached(false, pipeline_stage, cdata);
2088  return cdataw->_net_collide_mask;
2089  }
2090  return cdata->_net_collide_mask;
2091 }
2092 
2093 ////////////////////////////////////////////////////////////////////
2094 // Function: PandaNode::get_off_clip_planes
2095 // Access: Published
2096 // Description: Returns a ClipPlaneAttrib which represents the union
2097 // of all of the clip planes that have been turned *off*
2098 // at this level and below.
2099 ////////////////////////////////////////////////////////////////////
2100 CPT(RenderAttrib) PandaNode::
2101 get_off_clip_planes(Thread *current_thread) const {
2102  int pipeline_stage = current_thread->get_pipeline_stage();
2103  CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
2104  if (cdata->_last_update != cdata->_next_update) {
2105  // The cache is stale; it needs to be rebuilt.
2106  PStatTimer timer(_update_bounds_pcollector);
2107  CDStageWriter cdataw =
2108  ((PandaNode *)this)->update_cached(false, pipeline_stage, cdata);
2109  return cdataw->_off_clip_planes;
2110  }
2111  return cdata->_off_clip_planes;
2112 }
2113 
2114 ////////////////////////////////////////////////////////////////////
2115 // Function: PandaNode::prepare_scene
2116 // Access: Published
2117 // Description: Walks through the scene graph beginning at this node,
2118 // and does whatever initialization is required to
2119 // render the scene properly with the indicated GSG. It
2120 // is not strictly necessary to call this, since the GSG
2121 // will initialize itself when the scene is rendered,
2122 // but this may take some of the overhead away from that
2123 // process.
2124 //
2125 // In particular, this will ensure that textures and
2126 // vertex buffers within the scene are loaded into
2127 // graphics memory.
2128 ////////////////////////////////////////////////////////////////////
2129 void PandaNode::
2131  GeomTransformer transformer;
2132  Thread *current_thread = Thread::get_current_thread();
2133  r_prepare_scene(gsg, node_state, transformer, current_thread);
2134 }
2135 
2136 ////////////////////////////////////////////////////////////////////
2137 // Function: PandaNode::is_scene_root
2138 // Access: Published
2139 // Description: Returns true if this particular node is known to be
2140 // the render root of some active DisplayRegion
2141 // associated with the global GraphicsEngine, false
2142 // otherwise.
2143 ////////////////////////////////////////////////////////////////////
2144 bool PandaNode::
2145 is_scene_root() const {
2146  // This function pointer has to be filled in when the global
2147  // GraphicsEngine is created, because we can't link with the
2148  // GraphicsEngine functions directly.
2149  if (_scene_root_func != (SceneRootFunc *)NULL) {
2150  return (*_scene_root_func)(this);
2151  }
2152  return false;
2153 }
2154 
2155 ////////////////////////////////////////////////////////////////////
2156 // Function: PandaNode::is_under_scene_root
2157 // Access: Published
2158 // Description: Returns true if this particular node is in a live
2159 // scene graph: that is, it is a child or descendent of
2160 // a node that is itself a scene root. If this is true,
2161 // this node may potentially be traversed by the render
2162 // traverser. Stashed nodes don't count for this
2163 // purpose, but hidden nodes do.
2164 ////////////////////////////////////////////////////////////////////
2165 bool PandaNode::
2167  if (is_scene_root()) {
2168  return true;
2169  }
2170 
2171  Parents parents = get_parents();
2172  for (int i = 0; i < parents.get_num_parents(); ++i) {
2173  PandaNode *parent = parents.get_parent(i);
2174  if (parent->find_stashed((PandaNode *)this) == -1) {
2175  if (parent->is_under_scene_root()) {
2176  return true;
2177  }
2178  }
2179  }
2180  return false;
2181 }
2182 
2183 ////////////////////////////////////////////////////////////////////
2184 // Function: PandaNode::output
2185 // Access: Published, Virtual
2186 // Description:
2187 ////////////////////////////////////////////////////////////////////
2188 void PandaNode::
2189 output(ostream &out) const {
2190  out << get_type() << " " << get_name();
2191 }
2192 
2193 ////////////////////////////////////////////////////////////////////
2194 // Function: PandaNode::write
2195 // Access: Published, Virtual
2196 // Description:
2197 ////////////////////////////////////////////////////////////////////
2198 void PandaNode::
2199 write(ostream &out, int indent_level) const {
2200  indent(out, indent_level) << *this;
2201  if (has_tags()) {
2202  out << " [";
2203  list_tags(out, " ");
2204  out << "]";
2205  }
2206  CPT(TransformState) transform = get_transform();
2207  if (!transform->is_identity()) {
2208  out << " " << *transform;
2209  }
2210  CPT(RenderState) state = get_state();
2211  if (!state->is_empty()) {
2212  out << " " << *state;
2213  }
2214  CPT(RenderEffects) effects = get_effects();
2215  if (!effects->is_empty()) {
2216  out << " " << *effects;
2217  }
2218  DrawMask draw_control_mask = get_draw_control_mask();
2219  if (!draw_control_mask.is_zero()) {
2220  DrawMask draw_show_mask = get_draw_show_mask();
2221  if (!(draw_control_mask & _overall_bit).is_zero()) {
2222  if (!(draw_show_mask & _overall_bit).is_zero()) {
2223  out << " (show_through)";
2224  } else {
2225  out << " (hidden)";
2226  }
2227  }
2228  if (!(draw_control_mask & ~_overall_bit).is_zero()) {
2229  draw_control_mask &= ~_overall_bit;
2230  if (!(draw_show_mask & draw_control_mask).is_zero()) {
2231  out << " (per-camera show_through)";
2232  }
2233  if (!(~draw_show_mask & draw_control_mask).is_zero()) {
2234  out << " (per-camera hidden)";
2235  }
2236  }
2237  }
2238  out << "\n";
2239 }
2240 
2241 ////////////////////////////////////////////////////////////////////
2242 // Function: PandaNode::set_bounds_type
2243 // Access: Published
2244 // Description: Specifies the desired type of bounding volume that
2245 // will be created for this node. This is normally
2246 // BoundingVolume::BT_default, which means to set the
2247 // type according to the config variable "bounds-type".
2248 //
2249 // If this is BT_sphere or BT_box, a BoundingSphere or
2250 // BoundingBox is explicitly created. If it is BT_best,
2251 // the appropriate type to best enclose the node's
2252 // children is created.
2253 //
2254 // This affects the bounding volume returned by
2255 // get_bounds(), which is not exactly the same bounding
2256 // volume modified by set_bounds(), because a new
2257 // bounding volume has to be created that includes this
2258 // node and all of its children.
2259 ////////////////////////////////////////////////////////////////////
2260 void PandaNode::
2261 set_bounds_type(BoundingVolume::BoundsType bounds_type) {
2262  Thread *current_thread = Thread::get_current_thread();
2263  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
2264  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
2265  cdata->_bounds_type = bounds_type;
2266  mark_bounds_stale(pipeline_stage, current_thread);
2267 
2268  // GeomNodes, CollisionNodes, and PGItems all have an internal
2269  // bounds that may need to be updated when the bounds_type
2270  // changes.
2271  mark_internal_bounds_stale(pipeline_stage, current_thread);
2273  }
2274  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
2275 }
2276 
2277 ////////////////////////////////////////////////////////////////////
2278 // Function: PandaNode::get_bounds_type
2279 // Access: Published
2280 // Description: Returns the bounding volume type set with
2281 // set_bounds_type().
2282 ////////////////////////////////////////////////////////////////////
2283 BoundingVolume::BoundsType PandaNode::
2285  CDReader cdata(_cycler);
2286  return cdata->_bounds_type;
2287 }
2288 
2289 ////////////////////////////////////////////////////////////////////
2290 // Function: PandaNode::set_bounds
2291 // Access: Published
2292 // Description: Resets the bounding volume so that it is the
2293 // indicated volume. When it is explicitly set, the
2294 // bounding volume will no longer be automatically
2295 // computed according to the contents of the node
2296 // itself, for nodes like GeomNodes and TextNodes that
2297 // contain substance (but the bounding volume will still
2298 // be automatically expanded to include its children).
2299 //
2300 // Call clear_bounds() if you would like to return the
2301 // bounding volume to its default behavior later.
2302 ////////////////////////////////////////////////////////////////////
2303 void PandaNode::
2304 set_bounds(const BoundingVolume *volume) {
2305  Thread *current_thread = Thread::get_current_thread();
2306  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
2307  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
2308  if (volume == NULL) {
2309  cdata->_user_bounds = NULL;
2310  } else {
2311  cdata->_user_bounds = volume->make_copy();
2312  }
2313  mark_bounds_stale(pipeline_stage, current_thread);
2315  }
2316  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
2317 }
2318 
2319 ////////////////////////////////////////////////////////////////////
2320 // Function: PandaNode::set_bound
2321 // Access: Published
2322 // Description: Deprecated. Use set_bounds() instead.
2323 ////////////////////////////////////////////////////////////////////
2324 void PandaNode::
2325 set_bound(const BoundingVolume *volume) {
2326  pgraph_cat.warning()
2327  << "Deprecated PandaNode::set_bound() called. Use set_bounds() instead.\n";
2328  set_bounds(volume);
2329 }
2330 
2331 ////////////////////////////////////////////////////////////////////
2332 // Function: PandaNode::get_bounds
2333 // Access: Published
2334 // Description: Returns the external bounding volume of this node: a
2335 // bounding volume that contains the user bounding
2336 // volume, the internal bounding volume, and all of the
2337 // children's bounding volumes.
2338 ////////////////////////////////////////////////////////////////////
2340 get_bounds(Thread *current_thread) const {
2341  int pipeline_stage = current_thread->get_pipeline_stage();
2342  CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
2343  if (cdata->_last_bounds_update != cdata->_next_update) {
2344  // The cache is stale; it needs to be rebuilt.
2345  CPT(BoundingVolume) result;
2346  {
2347  PStatTimer timer(_update_bounds_pcollector);
2348  CDStageWriter cdataw =
2349  ((PandaNode *)this)->update_cached(true, pipeline_stage, cdata);
2350  result = cdataw->_external_bounds;
2351  }
2352  return result;
2353  }
2354  return cdata->_external_bounds;
2355 }
2356 
2357 ////////////////////////////////////////////////////////////////////
2358 // Function: PandaNode::get_bounds
2359 // Access: Published
2360 // Description: This flavor of get_bounds() return the external
2361 // bounding volume, and also fills in seq with the
2362 // bounding volume's current sequence number. When this
2363 // sequence number changes, it indicates that the
2364 // bounding volume might have changed, e.g. because some
2365 // nested child's bounding volume has changed.
2366 //
2367 // Although this might occasionally increment without
2368 // changing the bounding volume, the bounding volume
2369 // will never change without incrementing this counter,
2370 // so as long as this counter remains unchanged you can
2371 // be confident the bounding volume is also unchanged.
2372 ////////////////////////////////////////////////////////////////////
2374 get_bounds(UpdateSeq &seq, Thread *current_thread) const {
2375  int pipeline_stage = current_thread->get_pipeline_stage();
2376  CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
2377  if (cdata->_last_bounds_update != cdata->_next_update) {
2378  // The cache is stale; it needs to be rebuilt.
2379  CPT(BoundingVolume) result;
2380  {
2381  PStatTimer timer(_update_bounds_pcollector);
2382  CDStageWriter cdataw =
2383  ((PandaNode *)this)->update_cached(true, pipeline_stage, cdata);
2384  result = cdataw->_external_bounds;
2385  seq = cdataw->_last_bounds_update;
2386  }
2387  return result;
2388  }
2389  seq = cdata->_last_bounds_update;
2390  return cdata->_external_bounds;
2391 }
2392 
2393 ////////////////////////////////////////////////////////////////////
2394 // Function: PandaNode::get_nested_vertices
2395 // Access: Published
2396 // Description: Returns the total number of vertices that will be
2397 // rendered by this node and all of its descendents.
2398 //
2399 // This is not necessarily an accurate count of vertices
2400 // that will actually be rendered, since this will
2401 // include all vertices of all LOD's, and it will also
2402 // include hidden nodes. It may also omit or only
2403 // approximate certain kinds of dynamic geometry.
2404 // However, it will not include stashed nodes.
2405 ////////////////////////////////////////////////////////////////////
2406 int PandaNode::
2407 get_nested_vertices(Thread *current_thread) const {
2408  int pipeline_stage = current_thread->get_pipeline_stage();
2409  CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
2410  if (cdata->_last_bounds_update != cdata->_next_update) {
2411  // The cache is stale; it needs to be rebuilt.
2412  int result;
2413  {
2414  PStatTimer timer(_update_bounds_pcollector);
2415  CDStageWriter cdataw =
2416  ((PandaNode *)this)->update_cached(true, pipeline_stage, cdata);
2417  result = cdataw->_nested_vertices;
2418  }
2419  return result;
2420  }
2421  return cdata->_nested_vertices;
2422 }
2423 
2424 ////////////////////////////////////////////////////////////////////
2425 // Function: PandaNode::mark_bounds_stale
2426 // Access: Published
2427 // Description: Indicates that the bounding volume, or something that
2428 // influences the bounding volume (or any of the other
2429 // things stored in CData, like net_collide_mask),
2430 // may have changed for this node, and that it must be
2431 // recomputed.
2432 //
2433 // With no parameters, this means to iterate through all
2434 // stages including and upstream of the current pipeline
2435 // stage.
2436 //
2437 // This method is intended for internal use; usually it
2438 // is not necessary for a user to call this directly.
2439 // It will be called automatically by derived classes
2440 // when appropriate.
2441 ////////////////////////////////////////////////////////////////////
2442 void PandaNode::
2443 mark_bounds_stale(Thread *current_thread) const {
2444  OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
2445  mark_bounds_stale(pipeline_stage, current_thread);
2446  }
2447  CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
2448 }
2449 
2450 ////////////////////////////////////////////////////////////////////
2451 // Function: PandaNode::mark_internal_bounds_stale
2452 // Access: Published
2453 // Description: Should be called by a derived class to mark the
2454 // internal bounding volume stale, so that
2455 // compute_internal_bounds() will be called when the
2456 // bounding volume is next requested.
2457 //
2458 // With no parameters, this means to iterate through all
2459 // stages including and upstream of the current pipeline
2460 // stage.
2461 //
2462 // It is normally not necessary to call this method
2463 // directly; each node should be responsible for calling
2464 // it when its internals have changed.
2465 ////////////////////////////////////////////////////////////////////
2466 void PandaNode::
2468  OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
2469  mark_internal_bounds_stale(pipeline_stage, current_thread);
2470  }
2471  CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
2472 }
2473 
2474 ////////////////////////////////////////////////////////////////////
2475 // Function: PandaNode::is_geom_node
2476 // Access: Published, Virtual
2477 // Description: A simple downcast check. Returns true if this kind
2478 // of node happens to inherit from GeomNode, false
2479 // otherwise.
2480 //
2481 // This is provided as a a faster alternative to calling
2482 // is_of_type(GeomNode::get_class_type()), since this
2483 // test is so important to rendering.
2484 ////////////////////////////////////////////////////////////////////
2485 bool PandaNode::
2486 is_geom_node() const {
2487  return false;
2488 }
2489 
2490 ////////////////////////////////////////////////////////////////////
2491 // Function: PandaNode::is_lod_node
2492 // Access: Published, Virtual
2493 // Description: A simple downcast check. Returns true if this kind
2494 // of node happens to inherit from LODNode, false
2495 // otherwise.
2496 //
2497 // This is provided as a a faster alternative to calling
2498 // is_of_type(LODNode::get_class_type()).
2499 ////////////////////////////////////////////////////////////////////
2500 bool PandaNode::
2501 is_lod_node() const {
2502  return false;
2503 }
2504 
2505 ////////////////////////////////////////////////////////////////////
2506 // Function: PandaNode::is_collision_node
2507 // Access: Published, Virtual
2508 // Description: A simple downcast check. Returns true if this kind
2509 // of node happens to inherit from CollisionNode, false
2510 // otherwise.
2511 //
2512 // This is provided as a a faster alternative to calling
2513 // is_of_type(CollisionNode::get_class_type()).
2514 ////////////////////////////////////////////////////////////////////
2515 bool PandaNode::
2517  return false;
2518 }
2519 
2520 ////////////////////////////////////////////////////////////////////
2521 // Function: PandaNode::as_light
2522 // Access: Published, Virtual
2523 // Description: Cross-casts the node to a Light pointer, if it is one
2524 // of the four kinds of Light nodes, or returns NULL if
2525 // it is not.
2526 ////////////////////////////////////////////////////////////////////
2529  return NULL;
2530 }
2531 
2532 ////////////////////////////////////////////////////////////////////
2533 // Function: PandaNode::is_ambient_light
2534 // Access: Published, Virtual
2535 // Description: Returns true if this is an AmbientLight, false if it
2536 // is not a light, or it is some other kind of light.
2537 ////////////////////////////////////////////////////////////////////
2538 bool PandaNode::
2540  return false;
2541 }
2542 
2543 ////////////////////////////////////////////////////////////////////
2544 // Function: PandaNode::decode_from_bam_stream
2545 // Access: Published, Static
2546 // Description: Reads the string created by a previous call to
2547 // encode_to_bam_stream(), and extracts and returns the
2548 // single object on that string. Returns NULL on error.
2549 //
2550 // This method is intended to replace
2551 // decode_raw_from_bam_stream() when you know the stream
2552 // in question returns an object of type PandaNode,
2553 // allowing for easier reference count management. Note
2554 // that the caller is still responsible for maintaining
2555 // the reference count on the return value.
2556 ////////////////////////////////////////////////////////////////////
2557 PT(PandaNode) PandaNode::
2558 decode_from_bam_stream(const string &data, BamReader *reader) {
2559  TypedWritable *object;
2560  ReferenceCount *ref_ptr;
2561 
2562  if (!TypedWritable::decode_raw_from_bam_stream(object, ref_ptr, data, reader)) {
2563  return NULL;
2564  }
2565 
2566  return DCAST(PandaNode, object);
2567 }
2568 
2569 ////////////////////////////////////////////////////////////////////
2570 // Function: PandaNode::get_internal_bounds
2571 // Access: Protected
2572 // Description: Returns the node's internal bounding volume. This is
2573 // the bounding volume around the node alone, without
2574 // including children.
2575 ////////////////////////////////////////////////////////////////////
2577 get_internal_bounds(int pipeline_stage, Thread *current_thread) const {
2578  while (true) {
2579  UpdateSeq mark;
2580  {
2581  CDStageReader cdata(_cycler, pipeline_stage, current_thread);
2582  if (cdata->_user_bounds != (BoundingVolume *)NULL) {
2583  return cdata->_user_bounds;
2584  }
2585 
2586  if (cdata->_internal_bounds_mark == cdata->_internal_bounds_computed) {
2587  return cdata->_internal_bounds;
2588  }
2589 
2590  mark = cdata->_internal_bounds_mark;
2591  }
2592 
2593  // First, call compute_internal_bounds without acquiring the lock.
2594  // This avoids a deadlock condition.
2595  CPT(BoundingVolume) internal_bounds;
2596  int internal_vertices;
2597  compute_internal_bounds(internal_bounds, internal_vertices,
2598  pipeline_stage, current_thread);
2599  nassertr(!internal_bounds.is_null(), NULL);
2600 
2601  // Now, acquire the lock, and apply the above-computed bounds.
2602  CDStageWriter cdataw(((PandaNode *)this)->_cycler, pipeline_stage);
2603  if (cdataw->_internal_bounds_mark == mark) {
2604  cdataw->_internal_bounds_computed = mark;
2605  cdataw->_internal_bounds = internal_bounds;
2606  cdataw->_internal_vertices = internal_vertices;
2607  ((PandaNode *)this)->mark_bam_modified();
2608  return cdataw->_internal_bounds;
2609  }
2610 
2611  // Dang, someone in another thread incremented
2612  // _internal_bounds_mark while we weren't holding the lock. That
2613  // means we need to go back and do it again.
2614  }
2615 }
2616 
2617 ////////////////////////////////////////////////////////////////////
2618 // Function: PandaNode::get_internal_vertices
2619 // Access: Protected
2620 // Description: Returns the total number of vertices that will be
2621 // rendered by this particular node alone, not
2622 // accounting for its children.
2623 //
2624 // This may not include all vertices for certain dynamic
2625 // effects.
2626 ////////////////////////////////////////////////////////////////////
2627 int PandaNode::
2628 get_internal_vertices(int pipeline_stage, Thread *current_thread) const {
2629  while (true) {
2630  UpdateSeq mark;
2631  {
2632  CDStageReader cdata(_cycler, pipeline_stage, current_thread);
2633  if (cdata->_internal_bounds_mark == cdata->_internal_bounds_computed) {
2634  return cdata->_internal_vertices;
2635  }
2636 
2637  mark = cdata->_internal_bounds_mark;
2638  }
2639 
2640  // First, call compute_internal_bounds without acquiring the lock.
2641  // This avoids a deadlock condition.
2642  CPT(BoundingVolume) internal_bounds;
2643  int internal_vertices;
2644  compute_internal_bounds(internal_bounds, internal_vertices,
2645  pipeline_stage, current_thread);
2646  nassertr(!internal_bounds.is_null(), 0);
2647 
2648  // Now, acquire the lock, and apply the above-computed bounds.
2649  CDStageWriter cdataw(((PandaNode *)this)->_cycler, pipeline_stage);
2650  if (cdataw->_internal_bounds_mark == mark) {
2651  cdataw->_internal_bounds_computed = mark;
2652  cdataw->_internal_bounds = internal_bounds;
2653  cdataw->_internal_vertices = internal_vertices;
2654  ((PandaNode *)this)->mark_bam_modified();
2655  return cdataw->_internal_vertices;
2656  }
2657 
2658  // Dang, someone in another thread incremented
2659  // _internal_bounds_mark while we weren't holding the lock. That
2660  // means we need to go back and do it again.
2661  }
2662 }
2663 
2664 ////////////////////////////////////////////////////////////////////
2665 // Function: PandaNode::set_internal_bounds
2666 // Access: Protected
2667 // Description: This is provided as an alternate way for a node to
2668 // set its own internal bounds, rather than overloading
2669 // compute_internal_bounds(). If this method is called,
2670 // the internal bounding volume will immediately be set
2671 // to the indicated pointer.
2672 ////////////////////////////////////////////////////////////////////
2673 void PandaNode::
2674 set_internal_bounds(const BoundingVolume *volume) {
2675  Thread *current_thread = Thread::get_current_thread();
2676  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
2677  CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
2678  cdataw->_internal_bounds = volume;
2679  cdataw->_internal_bounds_computed = cdataw->_internal_bounds_mark;
2680  }
2681  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
2682  mark_bounds_stale(current_thread);
2684 }
2685 
2686 ////////////////////////////////////////////////////////////////////
2687 // Function: PandaNode::force_bounds_stale
2688 // Access: Protected
2689 // Description: Similar to mark_bounds_stale(), except that the
2690 // parents of this node marked stale even if this node
2691 // was already considered stale.
2692 //
2693 // With no parameters, this means to iterate through all
2694 // stages including and upstream of the current pipeline
2695 // stage.
2696 ////////////////////////////////////////////////////////////////////
2697 void PandaNode::
2698 force_bounds_stale(Thread *current_thread) {
2699  OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
2700  force_bounds_stale(pipeline_stage, current_thread);
2701  }
2702  CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
2703 }
2704 
2705 ////////////////////////////////////////////////////////////////////
2706 // Function: PandaNode::force_bounds_stale
2707 // Access: Protected
2708 // Description: Similar to mark_bounds_stale(), except that the
2709 // parents of this node marked stale even if this node
2710 // was already considered stale.
2711 ////////////////////////////////////////////////////////////////////
2712 void PandaNode::
2713 force_bounds_stale(int pipeline_stage, Thread *current_thread) {
2714  {
2715  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
2716  ++cdata->_next_update;
2718 
2719  // It is important that we allow this lock to be dropped before we
2720  // continue up the graph; otherwise, we risk deadlock from another
2721  // thread walking down the graph.
2722  }
2723 
2724  // It is similarly important that we use get_parents() here to copy
2725  // the parents list, instead of keeping the lock open while we walk
2726  // through the parents list directly on the node.
2727  Parents parents;
2728  {
2729  CDStageReader cdata(_cycler, pipeline_stage, current_thread);
2730  parents = Parents(cdata);
2731  }
2732  int num_parents = parents.get_num_parents();
2733  for (int i = 0; i < num_parents; ++i) {
2734  PandaNode *parent = parents.get_parent(i);
2735  parent->mark_bounds_stale(pipeline_stage, current_thread);
2736  }
2737 }
2738 
2739 ////////////////////////////////////////////////////////////////////
2740 // Function: PandaNode::r_mark_geom_bounds_stale
2741 // Access: Protected, Virtual
2742 // Description: Recursively calls Geom::mark_bounds_stale() on every
2743 // Geom at this node and below.
2744 ////////////////////////////////////////////////////////////////////
2745 void PandaNode::
2746 r_mark_geom_bounds_stale(Thread *current_thread) {
2747  Children children = get_children(current_thread);
2748 
2749  int i;
2750  for (i = 0; i < children.get_num_children(); i++) {
2751  PandaNode *child = children.get_child(i);
2752  child->r_mark_geom_bounds_stale(current_thread);
2753  }
2754 
2755  Stashed stashed = get_stashed(current_thread);
2756  for (i = 0; i < stashed.get_num_stashed(); i++) {
2757  PandaNode *child = stashed.get_stashed(i);
2758  child->r_mark_geom_bounds_stale(current_thread);
2759  }
2760 }
2761 
2762 ////////////////////////////////////////////////////////////////////
2763 // Function: PandaNode::compute_internal_bounds
2764 // Access: Protected, Virtual
2765 // Description: Returns a newly-allocated BoundingVolume that
2766 // represents the internal contents of the node. Should
2767 // be overridden by PandaNode classes that contain
2768 // something internally.
2769 ////////////////////////////////////////////////////////////////////
2770 void PandaNode::
2771 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
2772  int &internal_vertices,
2773  int pipeline_stage,
2774  Thread *current_thread) const {
2775  internal_bounds = new BoundingSphere;
2776  internal_vertices = 0;
2777 }
2778 
2779 ////////////////////////////////////////////////////////////////////
2780 // Function: PandaNode::parents_changed
2781 // Access: Protected, Virtual
2782 // Description: Called after a scene graph update that either adds or
2783 // remove parents from this node, this just provides a
2784 // hook for derived PandaNode objects that need to
2785 // update themselves based on the set of parents the
2786 // node has.
2787 ////////////////////////////////////////////////////////////////////
2788 void PandaNode::
2789 parents_changed() {
2790  nassertv((_unexpected_change_flags & UC_parents) == 0);
2791 }
2792 
2793 ////////////////////////////////////////////////////////////////////
2794 // Function: PandaNode::children_changed
2795 // Access: Protected, Virtual
2796 // Description: Called after a scene graph update that either adds or
2797 // remove children from this node, this just provides a
2798 // hook for derived PandaNode objects that need to
2799 // update themselves based on the set of children the
2800 // node has.
2801 ////////////////////////////////////////////////////////////////////
2802 void PandaNode::
2803 children_changed() {
2804  nassertv((_unexpected_change_flags & UC_children) == 0);
2805 }
2806 
2807 ////////////////////////////////////////////////////////////////////
2808 // Function: PandaNode::transform_changed
2809 // Access: Protected, Virtual
2810 // Description: Called after the node's transform has been changed
2811 // for any reason, this just provides a hook so derived
2812 // classes can do something special in this case.
2813 ////////////////////////////////////////////////////////////////////
2814 void PandaNode::
2815 transform_changed() {
2816  nassertv((_unexpected_change_flags & UC_transform) == 0);
2817 }
2818 
2819 ////////////////////////////////////////////////////////////////////
2820 // Function: PandaNode::state_changed
2821 // Access: Protected, Virtual
2822 // Description: Called after the node's RenderState has been changed
2823 // for any reason, this just provides a hook so derived
2824 // classes can do something special in this case.
2825 ////////////////////////////////////////////////////////////////////
2826 void PandaNode::
2827 state_changed() {
2828  nassertv((_unexpected_change_flags & UC_state) == 0);
2829 }
2830 
2831 ////////////////////////////////////////////////////////////////////
2832 // Function: PandaNode::draw_mask_changed
2833 // Access: Protected, Virtual
2834 // Description: Called after the node's DrawMask has been changed
2835 // for any reason, this just provides a hook so derived
2836 // classes can do something special in this case.
2837 ////////////////////////////////////////////////////////////////////
2838 void PandaNode::
2839 draw_mask_changed() {
2840  nassertv((_unexpected_change_flags & UC_draw_mask) == 0);
2841 }
2842 
2843 ////////////////////////////////////////////////////////////////////
2844 // Function: PandaNode::r_copy_subgraph
2845 // Access: Protected, Virtual
2846 // Description: This is the recursive implementation of copy_subgraph().
2847 // It returns a copy of the entire subgraph rooted at
2848 // this node.
2849 //
2850 // Note that it includes the parameter inst_map, which
2851 // is a map type, and is not (and cannot be) exported
2852 // from PANDA.DLL. Thus, any derivative of PandaNode
2853 // that is not also a member of PANDA.DLL *cannot*
2854 // access this map.
2855 ////////////////////////////////////////////////////////////////////
2856 PT(PandaNode) PandaNode::
2857 r_copy_subgraph(PandaNode::InstanceMap &inst_map, Thread *current_thread) const {
2858  PT(PandaNode) copy = make_copy();
2859  nassertr(copy != (PandaNode *)NULL, NULL);
2860  if (copy->get_type() != get_type()) {
2861  pgraph_cat.warning()
2862  << "Don't know how to copy nodes of type " << get_type() << "\n";
2863 
2864  if (no_unsupported_copy) {
2865  nassertr(false, NULL);
2866  }
2867  }
2868 
2869  copy->r_copy_children(this, inst_map, current_thread);
2870  return copy;
2871 }
2872 
2873 ////////////////////////////////////////////////////////////////////
2874 // Function: PandaNode::r_copy_children
2875 // Access: Protected, Virtual
2876 // Description: This is called by r_copy_subgraph(); the copy has
2877 // already been made of this particular node (and this
2878 // is the copy); this function's job is to copy all of
2879 // the children from the original.
2880 //
2881 // Note that it includes the parameter inst_map, which
2882 // is a map type, and is not (and cannot be) exported
2883 // from PANDA.DLL. Thus, any derivative of PandaNode
2884 // that is not also a member of PANDA.DLL *cannot*
2885 // access this map, and probably should not even
2886 // override this function.
2887 ////////////////////////////////////////////////////////////////////
2888 void PandaNode::
2889 r_copy_children(const PandaNode *from, PandaNode::InstanceMap &inst_map,
2890  Thread *current_thread) {
2891  CDReader from_cdata(from->_cycler, current_thread);
2892  CPT(Down) from_down = from_cdata->get_down();
2893  Down::const_iterator di;
2894  for (di = from_down->begin(); di != from_down->end(); ++di) {
2895  int sort = (*di).get_sort();
2896  PandaNode *source_child = (*di).get_child();
2897  PT(PandaNode) dest_child;
2898 
2899  // Check to see if we have already copied this child. If we
2900  // have, use the copy. In this way, a subgraph that contains
2901  // instances will be correctly duplicated into another subgraph
2902  // that also contains its own instances.
2903  InstanceMap::const_iterator ci;
2904  ci = inst_map.find(source_child);
2905  if (ci != inst_map.end()) {
2906  dest_child = (*ci).second;
2907  } else {
2908  dest_child = source_child->r_copy_subgraph(inst_map, current_thread);
2909  inst_map[source_child] = dest_child;
2910  }
2911 
2912  quick_add_new_child(dest_child, sort, current_thread);
2913  }
2914 }
2915 
2916 ////////////////////////////////////////////////////////////////////
2917 // Function: PandaNode::r_prepare_scene
2918 // Access: Public, Virtual
2919 // Description: The recursive implementation of prepare_scene().
2920 // Don't call this directly; call
2921 // PandaNode::prepare_scene() or
2922 // NodePath::prepare_scene() instead.
2923 ////////////////////////////////////////////////////////////////////
2924 void PandaNode::
2926  GeomTransformer &transformer, Thread *current_thread) {
2927  Children children = get_children(current_thread);
2928  // We must call get_num_children() each time through the loop, in
2929  // case we're running SIMPLE_THREADS and we get interrupted.
2930  int i;
2931  for (i = 0; i < children.get_num_children(); i++) {
2932  PandaNode *child = children.get_child(i);
2933  CPT(RenderState) child_state = node_state->compose(child->get_state());
2934  child->r_prepare_scene(gsg, child_state, transformer, current_thread);
2935  }
2936 
2937  Stashed stashed = get_stashed(current_thread);
2938  for (i = 0; i < stashed.get_num_stashed(); i++) {
2939  PandaNode *child = stashed.get_stashed(i);
2940  CPT(RenderState) child_state = node_state->compose(child->get_state());
2941  child->r_prepare_scene(gsg, child_state, transformer, current_thread);
2942  }
2943 }
2944 
2945 ////////////////////////////////////////////////////////////////////
2946 // Function: PandaNode::set_cull_callback
2947 // Access: Protected
2948 // Description: Intended to be called in the constructor by any
2949 // subclass that defines cull_callback(), this sets up
2950 // the flags to indicate that the cullback needs to be
2951 // called.
2952 ////////////////////////////////////////////////////////////////////
2953 void PandaNode::
2954 set_cull_callback() {
2955  Thread *current_thread = Thread::get_current_thread();
2956  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
2957  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
2958  cdata->set_fancy_bit(FB_cull_callback, true);
2959  }
2960  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
2962 }
2963 
2964 ////////////////////////////////////////////////////////////////////
2965 // Function: PandaNode::disable_cull_callback
2966 // Access: Protected
2967 // Description: disables the call back
2968 ////////////////////////////////////////////////////////////////////
2969 void PandaNode::
2970 disable_cull_callback() {
2971  Thread *current_thread = Thread::get_current_thread();
2972  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
2973  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
2974  cdata->set_fancy_bit(FB_cull_callback, false);
2975  }
2976  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
2978 }
2979 
2980 ////////////////////////////////////////////////////////////////////
2981 // Function: PandaNode::stage_remove_child
2982 // Access: Private
2983 // Description: The private implementation of remove_child(), for a
2984 // particular pipeline stage.
2985 ////////////////////////////////////////////////////////////////////
2986 bool PandaNode::
2987 stage_remove_child(PandaNode *child_node, int pipeline_stage,
2988  Thread *current_thread) {
2989  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
2990 
2991  // First, look for the parent in the child's up list, to ensure the
2992  // child is known.
2993  CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
2994  current_thread);
2995  int parent_index = child_node->do_find_parent(this, cdata_child);
2996  if (parent_index < 0) {
2997  // Nope, no relation.
2998  return false;
2999  }
3000 
3001  PT(Down) down = cdata->modify_down();
3002  int child_index = do_find_child(child_node, down);
3003  if (child_index >= 0) {
3004  // The child exists; remove it.
3005  down->erase(down->begin() + child_index);
3006  int num_erased = cdata_child->modify_up()->erase(UpConnection(this));
3007  nassertr(num_erased == 1, false);
3008  return true;
3009  }
3010 
3011  PT(Down) stashed = cdata->modify_stashed();
3012  int stashed_index = do_find_child(child_node, stashed);
3013  if (stashed_index >= 0) {
3014  // The child has been stashed; remove it.
3015  stashed->erase(stashed->begin() + stashed_index);
3016  int num_erased = cdata_child->modify_up()->erase(UpConnection(this));
3017  nassertr(num_erased == 1, false);
3018  return true;
3019  }
3020 
3021  // Never heard of this child. This shouldn't be possible, because
3022  // the parent was in the child's up list, above. Must be some
3023  // internal error.
3024  nassertr(false, false);
3025  return false;
3026 }
3027 
3028 ////////////////////////////////////////////////////////////////////
3029 // Function: PandaNode::stage_replace_child
3030 // Access: Private
3031 // Description: The private implementation of replace_child(), for a
3032 // particular pipeline stage.
3033 ////////////////////////////////////////////////////////////////////
3034 bool PandaNode::
3035 stage_replace_child(PandaNode *orig_child, PandaNode *new_child,
3036  int pipeline_stage, Thread *current_thread) {
3037  {
3038  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
3039  CDStageWriter cdata_orig_child(orig_child->_cycler, pipeline_stage, current_thread);
3040  CDStageWriter cdata_new_child(new_child->_cycler, pipeline_stage, current_thread);
3041 
3042  // First, look for the parent in the child's up list, to ensure the
3043  // child is known.
3044  int parent_index = orig_child->do_find_parent(this, cdata_orig_child);
3045  if (parent_index < 0) {
3046  // Nope, no relation.
3047  return false;
3048  }
3049 
3050  if (orig_child == new_child) {
3051  // Trivial no-op.
3052  return true;
3053  }
3054 
3055  // Don't let orig_child be destructed yet.
3056  PT(PandaNode) keep_orig_child = orig_child;
3057 
3058  // If we already have new_child as a child, remove it first.
3059  if (stage_remove_child(new_child, pipeline_stage, current_thread)) {
3060  sever_connection(this, new_child, pipeline_stage, current_thread);
3061  }
3062 
3063  PT(Down) down = cdata->modify_down();
3064  int child_index = do_find_child(orig_child, down);
3065  if (child_index >= 0) {
3066  // The child exists; replace it.
3067  DownConnection &dc = (*down)[child_index];
3068  nassertr(dc.get_child() == orig_child, false);
3069  dc.set_child(new_child);
3070 
3071  } else {
3072  PT(Down) stashed = cdata->modify_stashed();
3073  int stashed_index = do_find_child(orig_child, stashed);
3074  if (stashed_index >= 0) {
3075  // The child has been stashed; remove it.
3076  DownConnection &dc = (*stashed)[stashed_index];
3077  nassertr(dc.get_child() == orig_child, false);
3078  dc.set_child(new_child);
3079 
3080  } else {
3081  // Never heard of this child. This shouldn't be possible, because
3082  // the parent was in the child's up list, above. Must be some
3083  // internal error.
3084  nassertr(false, false);
3085  return false;
3086  }
3087  }
3088 
3089  // Now adjust the bookkeeping on both children.
3090  cdata_new_child->modify_up()->insert(UpConnection(this));
3091  int num_erased = cdata_orig_child->modify_up()->erase(UpConnection(this));
3092  nassertr(num_erased == 1, false);
3093  }
3094 
3095  sever_connection(this, orig_child, pipeline_stage, current_thread);
3096  new_connection(this, new_child, pipeline_stage, current_thread);
3097 
3098  force_bounds_stale(pipeline_stage, current_thread);
3099  orig_child->parents_changed();
3100  new_child->parents_changed();
3102  orig_child->mark_bam_modified();
3103  new_child->mark_bam_modified();
3104 
3105  return true;
3106 }
3107 
3108 ////////////////////////////////////////////////////////////////////
3109 // Function: PandaNode::quick_add_new_child
3110 // Access: Private
3111 // Description: Similar to add_child(), but performs fewer checks.
3112 // The purpose of this method is to add a child node
3113 // that was newly constructed, to a parent node that was
3114 // newly constructed, so we know we have to make fewer
3115 // sanity checks. This is a private method; do not call
3116 // it directly.
3117 ////////////////////////////////////////////////////////////////////
3118 void PandaNode::
3119 quick_add_new_child(PandaNode *child_node, int sort, Thread *current_thread) {
3120  // Apply this operation to the current stage as well as to all
3121  // upstream stages.
3122  OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
3123  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
3124  CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
3125 
3126  cdata->modify_down()->insert(DownConnection(child_node, sort));
3127  cdata_child->modify_up()->insert(UpConnection(this));
3128  }
3129  CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
3130 }
3131 
3132 ////////////////////////////////////////////////////////////////////
3133 // Function: PandaNode::report_cycle
3134 // Access: Private
3135 // Description: Raises an assertion when a graph cycle attempt is
3136 // detected (and aborted).
3137 ////////////////////////////////////////////////////////////////////
3138 void PandaNode::
3139 report_cycle(PandaNode *child_node) {
3140  ostringstream strm;
3141  strm << "Detected attempt to create a cycle in the scene graph: "
3142  << NodePath::any_path(this) << " : " << *child_node;
3143  nassert_raise(strm.str());
3144 }
3145 
3146 ////////////////////////////////////////////////////////////////////
3147 // Function: PandaNode::find_node_above
3148 // Access: Private
3149 // Description: Returns true if the indicated node is this node, or
3150 // any ancestor of this node; or false if it is not in
3151 // this node's ancestry.
3152 ////////////////////////////////////////////////////////////////////
3153 bool PandaNode::
3154 find_node_above(PandaNode *node) {
3155  if (node == this) {
3156  return true;
3157  }
3158 
3159  Parents parents = get_parents();
3160  for (int i = 0; i < parents.get_num_parents(); ++i) {
3161  PandaNode *parent = parents.get_parent(i);
3162  if (parent->find_node_above(node)) {
3163  return true;
3164  }
3165  }
3166 
3167  return false;
3168 }
3169 
3170 ////////////////////////////////////////////////////////////////////
3171 // Function: PandaNode::attach
3172 // Access: Private, Static
3173 // Description: Creates a new parent-child relationship, and returns
3174 // the new NodePathComponent. If the child was already
3175 // attached to the indicated parent, repositions it and
3176 // returns the original NodePathComponent.
3177 //
3178 // This operation is automatically propagated back up to
3179 // pipeline 0, from the specified pipeline stage.
3180 ////////////////////////////////////////////////////////////////////
3182 attach(NodePathComponent *parent, PandaNode *child_node, int sort,
3183  int pipeline_stage, Thread *current_thread) {
3184  if (parent == (NodePathComponent *)NULL) {
3185  // Attaching to NULL means to create a new "instance" with no
3186  // attachments, and no questions asked.
3187  PT(NodePathComponent) child =
3188  new NodePathComponent(child_node, (NodePathComponent *)NULL,
3189  pipeline_stage, current_thread);
3190  LightReMutexHolder holder(child_node->_paths_lock);
3191  child_node->_paths.insert(child);
3192  return child;
3193  }
3194 
3195  // See if the child was already attached to the parent. If it was,
3196  // we'll use that same NodePathComponent.
3197  PT(NodePathComponent) child = get_component(parent, child_node, pipeline_stage, current_thread);
3198 
3199  if (child == (NodePathComponent *)NULL) {
3200  // The child was not already attached to the parent, so get a new
3201  // component.
3202  child = get_top_component(child_node, true, pipeline_stage, current_thread);
3203  }
3204 
3205  reparent(parent, child, sort, false, pipeline_stage, current_thread);
3206 
3207  return child;
3208 }
3209 
3210 ////////////////////////////////////////////////////////////////////
3211 // Function: PandaNode::detach
3212 // Access: Private, Static
3213 // Description: Breaks a parent-child relationship.
3214 //
3215 // This operation is automatically propagated back up to
3216 // pipeline 0, from the specified pipeline stage.
3217 ////////////////////////////////////////////////////////////////////
3218 void PandaNode::
3219 detach(NodePathComponent *child, int pipeline_stage, Thread *current_thread) {
3220  nassertv(child != (NodePathComponent *)NULL);
3221 
3222  for (int pipeline_stage_i = pipeline_stage;
3223  pipeline_stage_i >= 0;
3224  --pipeline_stage_i) {
3225  detach_one_stage(child, pipeline_stage_i, current_thread);
3226  }
3227 
3228  child->get_node()->parents_changed();
3229 }
3230 
3231 ////////////////////////////////////////////////////////////////////
3232 // Function: PandaNode::detach_one_stage
3233 // Access: Private, Static
3234 // Description: Breaks a parent-child relationship.
3235 //
3236 // This operation is not automatically propagated
3237 // upstream. It is applied to the indicated pipeline
3238 // stage only.
3239 ////////////////////////////////////////////////////////////////////
3240 void PandaNode::
3241 detach_one_stage(NodePathComponent *child, int pipeline_stage,
3242  Thread *current_thread) {
3243  nassertv(child != (NodePathComponent *)NULL);
3244  if (child->is_top_node(pipeline_stage, current_thread)) {
3245  return;
3246  }
3247 
3248  PT(PandaNode) child_node = child->get_node();
3249  PT(PandaNode) parent_node = child->get_next(pipeline_stage, current_thread)->get_node();
3250 
3251  CDStageWriter cdata_parent(parent_node->_cycler, pipeline_stage, current_thread);
3252  CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
3253  int parent_index = child_node->do_find_parent(parent_node, cdata_child);
3254  if (parent_index >= 0) {
3255  // Now look for the child and break the actual connection.
3256 
3257  // First, look for and remove the parent node from the child's up
3258  // list.
3259  int num_erased = cdata_child->modify_up()->erase(UpConnection(parent_node));
3260  nassertv(num_erased == 1);
3261 
3262  // Now, look for and remove the child node from the parent's down
3263  // list. We also check in the stashed list, in case the child node
3264  // has been stashed.
3265  Down::iterator di;
3266  bool found = false;
3267  PT(Down) down = cdata_parent->modify_down();
3268  for (di = down->begin(); di != down->end(); ++di) {
3269  if ((*di).get_child() == child_node) {
3270  down->erase(di);
3271  found = true;
3272  break;
3273  }
3274  }
3275  if (!found) {
3276  PT(Down) stashed = cdata_parent->modify_stashed();
3277  for (di = stashed->begin(); di != stashed->end(); ++di) {
3278  if ((*di).get_child() == child_node) {
3279  stashed->erase(di);
3280  found = true;
3281  break;
3282  }
3283  }
3284  }
3285  nassertv(found);
3286  }
3287 
3288  // Finally, break the NodePathComponent connection.
3289  sever_connection(parent_node, child_node, pipeline_stage, current_thread);
3290 
3291  parent_node->force_bounds_stale(pipeline_stage, current_thread);
3292  parent_node->children_changed();
3293  parent_node->mark_bam_modified();
3294 }
3295 
3296 ////////////////////////////////////////////////////////////////////
3297 // Function: PandaNode::reparent
3298 // Access: Private, Static
3299 // Description: Switches a node from one parent to another. Returns
3300 // true if the new connection is allowed, or false if it
3301 // conflicts with another instance (that is, another
3302 // instance of the child is already attached to the
3303 // indicated parent).
3304 //
3305 // This operation is automatically propagated back up to
3306 // pipeline 0, from the specified pipeline stage.
3307 ////////////////////////////////////////////////////////////////////
3308 bool PandaNode::
3309 reparent(NodePathComponent *new_parent, NodePathComponent *child, int sort,
3310  bool as_stashed, int pipeline_stage, Thread *current_thread) {
3311  bool any_ok = false;
3312 
3313  if (new_parent != (NodePathComponent *)NULL &&
3314  !new_parent->get_node()->verify_child_no_cycles(child->get_node())) {
3315  // Whoops, adding this child node would introduce a cycle in the
3316  // scene graph.
3317  return false;
3318  }
3319 
3320  for (int pipeline_stage_i = pipeline_stage;
3321  pipeline_stage_i >= 0;
3322  --pipeline_stage_i) {
3323  if (reparent_one_stage(new_parent, child, sort, as_stashed,
3324  pipeline_stage_i, current_thread)) {
3325  any_ok = true;
3326  }
3327  }
3328 
3329  if (new_parent != (NodePathComponent *)NULL) {
3330  new_parent->get_node()->children_changed();
3331  new_parent->get_node()->mark_bam_modified();
3332  }
3333  child->get_node()->parents_changed();
3334  child->get_node()->mark_bam_modified();
3335 
3336  return any_ok;
3337 }
3338 
3339 ////////////////////////////////////////////////////////////////////
3340 // Function: PandaNode::reparent_one_stage
3341 // Access: Private, Static
3342 // Description: Switches a node from one parent to another. Returns
3343 // true if the new connection is allowed, or false if it
3344 // conflicts with another instance (that is, another
3345 // instance of the child is already attached to the
3346 // indicated parent).
3347 //
3348 // This operation is not automatically propagated
3349 // upstream. It is applied to the indicated pipeline
3350 // stage only.
3351 ////////////////////////////////////////////////////////////////////
3352 bool PandaNode::
3353 reparent_one_stage(NodePathComponent *new_parent, NodePathComponent *child,
3354  int sort, bool as_stashed, int pipeline_stage,
3355  Thread *current_thread) {
3356  nassertr(child != (NodePathComponent *)NULL, false);
3357 
3358  // Keep a reference count to the new parent, since detaching the
3359  // child might lose the count.
3360  PT(NodePathComponent) keep_parent = new_parent;
3361 
3362  if (!child->is_top_node(pipeline_stage, current_thread)) {
3363  detach(child, pipeline_stage, current_thread);
3364  }
3365 
3366  if (new_parent != (NodePathComponent *)NULL) {
3367  PandaNode *child_node = child->get_node();
3368  PandaNode *parent_node = new_parent->get_node();
3369 
3370  {
3371  CDStageReader cdata_child(child_node->_cycler, pipeline_stage, current_thread);
3372  int parent_index = child_node->do_find_parent(parent_node, cdata_child);
3373 
3374  if (parent_index >= 0) {
3375  // Whoops, there's already another instance of the child there.
3376  return false;
3377  }
3378  }
3379 
3380  // Redirect the connection to the indicated new parent.
3381  child->set_next(new_parent, pipeline_stage, current_thread);
3382 
3383  // Now reattach the child node at the indicated sort position.
3384  {
3385  CDStageWriter cdata_parent(parent_node->_cycler, pipeline_stage, current_thread);
3386  CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
3387 
3388  if (as_stashed) {
3389  cdata_parent->modify_stashed()->insert(DownConnection(child_node, sort));
3390  } else {
3391  cdata_parent->modify_down()->insert(DownConnection(child_node, sort));
3392  }
3393  cdata_child->modify_up()->insert(UpConnection(parent_node));
3394 
3395 #ifndef NDEBUG
3396  // The NodePathComponent should already be in the set.
3397  {
3398  LightReMutexHolder holder(child_node->_paths_lock);
3399  nassertr(child_node->_paths.find(child) != child_node->_paths.end(), false);
3400  }
3401 #endif // NDEBUG
3402  }
3403 
3404  child_node->fix_path_lengths(pipeline_stage, current_thread);
3405  parent_node->force_bounds_stale(pipeline_stage, current_thread);
3406  }
3407 
3408  return true;
3409 }
3410 
3411 ////////////////////////////////////////////////////////////////////
3412 // Function: PandaNode::get_component
3413 // Access: Private, Static
3414 // Description: Returns the NodePathComponent based on the indicated
3415 // child of the given parent, or NULL if there is no
3416 // such parent-child relationship.
3417 ////////////////////////////////////////////////////////////////////
3419 get_component(NodePathComponent *parent, PandaNode *child_node,
3420  int pipeline_stage, Thread *current_thread) {
3421  nassertr(parent != (NodePathComponent *)NULL, (NodePathComponent *)NULL);
3422  PandaNode *parent_node = parent->get_node();
3423 
3424  LightReMutexHolder holder(child_node->_paths_lock);
3425 
3426  // First, walk through the list of NodePathComponents we already
3427  // have on the child, looking for one that already exists,
3428  // referencing the indicated parent component.
3429  Paths::const_iterator pi;
3430  for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
3431  if ((*pi)->get_next(pipeline_stage, current_thread) == parent) {
3432  // If we already have such a component, just return it.
3433  return (*pi);
3434  }
3435  }
3436 
3437  // We don't already have a NodePathComponent referring to this
3438  // parent-child relationship. Are they actually related?
3439  CDStageReader cdata_child(child_node->_cycler, pipeline_stage, current_thread);
3440  int parent_index = child_node->do_find_parent(parent_node, cdata_child);
3441 
3442  if (parent_index >= 0) {
3443  // They are. Create and return a new one.
3444  PT(NodePathComponent) child =
3445  new NodePathComponent(child_node, parent, pipeline_stage, current_thread);
3446  child_node->_paths.insert(child);
3447  return child;
3448  } else {
3449  // They aren't related. Return NULL.
3450  return NULL;
3451  }
3452 }
3453 
3454 ////////////////////////////////////////////////////////////////////
3455 // Function: PandaNode::get_top_component
3456 // Access: Private, Static
3457 // Description: Returns a NodePathComponent referencing the
3458 // indicated node as a singleton. It is invalid to call
3459 // this for a node that has parents, unless you are
3460 // about to create a new instance (and immediately
3461 // reconnect the NodePathComponent elsewhere).
3462 //
3463 // If force is true, this will always return something,
3464 // even if it needs to create a new top component;
3465 // otherwise, if force is false, it will return NULL if
3466 // there is not already a top component available.
3467 ////////////////////////////////////////////////////////////////////
3469 get_top_component(PandaNode *child_node, bool force, int pipeline_stage,
3470  Thread *current_thread) {
3471  LightReMutexHolder holder(child_node->_paths_lock);
3472 
3473  // Walk through the list of NodePathComponents we already have on
3474  // the child, looking for one that already exists as a top node.
3475  Paths::const_iterator pi;
3476  for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
3477  if ((*pi)->is_top_node(pipeline_stage, current_thread)) {
3478  // If we already have such a component, just return it.
3479  return (*pi);
3480  }
3481  }
3482 
3483  if (!force) {
3484  // If we don't care to force the point, return NULL to indicate
3485  // there's not already a top component.
3486  return NULL;
3487  }
3488 
3489  // We don't already have such a NodePathComponent; create and
3490  // return a new one.
3491  PT(NodePathComponent) child =
3492  new NodePathComponent(child_node, (NodePathComponent *)NULL,
3493  pipeline_stage, current_thread);
3494  child_node->_paths.insert(child);
3495 
3496  return child;
3497 }
3498 
3499 ////////////////////////////////////////////////////////////////////
3500 // Function: PandaNode::get_generic_component
3501 // Access: Private
3502 // Description: Returns a NodePathComponent referencing this node as
3503 // a path from the root.
3504 //
3505 // Unless accept_ambiguity is true, it is only valid to
3506 // call this if there is an unambiguous path from the
3507 // root; otherwise, a warning will be issued and one
3508 // path will be chosen arbitrarily.
3509 ////////////////////////////////////////////////////////////////////
3511 get_generic_component(bool accept_ambiguity, int pipeline_stage,
3512  Thread *current_thread) {
3513  bool ambiguity_detected = false;
3514  PT(NodePathComponent) result =
3515  r_get_generic_component(accept_ambiguity, ambiguity_detected,
3516  pipeline_stage, current_thread);
3517 
3518  if (!accept_ambiguity && ambiguity_detected) {
3519  pgraph_cat.warning()
3520  << "Chose: " << *result << "\n";
3521  nassertr(!unambiguous_graph, result);
3522  }
3523 
3524  return result;
3525 }
3526 
3527 ////////////////////////////////////////////////////////////////////
3528 // Function: PandaNode::r_get_generic_component
3529 // Access: Private
3530 // Description: The recursive implementation of
3531 // get_generic_component, this simply sets the flag when
3532 // the ambiguity is detected (so we can report the
3533 // bottom node that started the ambiguous search).
3534 ////////////////////////////////////////////////////////////////////
3536 r_get_generic_component(bool accept_ambiguity, bool &ambiguity_detected,
3537  int pipeline_stage, Thread *current_thread) {
3538  PT(PandaNode) parent_node;
3539 
3540  {
3541  CDStageReader cdata(_cycler, pipeline_stage, current_thread);
3542 
3543  int num_parents = cdata->get_up()->size();
3544  if (num_parents == 0) {
3545  // No parents; no ambiguity. This is the root.
3546  return get_top_component(this, true, pipeline_stage, current_thread);
3547  }
3548 
3549  PT(NodePathComponent) result;
3550  if (num_parents == 1) {
3551  // Only one parent; no ambiguity.
3552  PT(NodePathComponent) parent =
3553  get_parent(0)->r_get_generic_component(accept_ambiguity, ambiguity_detected, pipeline_stage, current_thread);
3554  return get_component(parent, this, pipeline_stage, current_thread);
3555  }
3556 
3557  // Oops, multiple parents; the NodePath is ambiguous.
3558  if (!accept_ambiguity) {
3559  pgraph_cat.warning()
3560  << *this << " has " << num_parents
3561  << " parents; choosing arbitrary path to root.\n";
3562  }
3563  ambiguity_detected = true;
3564  CPT(Up) up = cdata->get_up();
3565  parent_node = (*up)[0].get_parent();
3566  }
3567 
3568  // Now that the lock is released, it's safe to recurse.
3569  PT(NodePathComponent) parent =
3570  parent_node->r_get_generic_component(accept_ambiguity, ambiguity_detected, pipeline_stage, current_thread);
3571  return get_component(parent, this, pipeline_stage, current_thread);
3572 }
3573 
3574 ////////////////////////////////////////////////////////////////////
3575 // Function: PandaNode::delete_component
3576 // Access: Private
3577 // Description: Removes a NodePathComponent from the set prior to
3578 // its deletion. This should only be called by the
3579 // NodePathComponent destructor.
3580 ////////////////////////////////////////////////////////////////////
3581 void PandaNode::
3582 delete_component(NodePathComponent *component) {
3583  LightReMutexHolder holder(_paths_lock);
3584  int num_erased = _paths.erase(component);
3585  nassertv(num_erased == 1);
3586 }
3587 
3588 ////////////////////////////////////////////////////////////////////
3589 // Function: PandaNode::sever_connection
3590 // Access: Private, Static
3591 // Description: This is called internally when a parent-child
3592 // connection is broken to update the NodePathComponents
3593 // that reflected this connection.
3594 //
3595 // It severs any NodePathComponents on the child node
3596 // that reference the indicated parent node. These
3597 // components remain unattached; there may therefore be
3598 // multiple "instances" of a node that all have no
3599 // parent, even while there are other instances that do
3600 // have parents.
3601 //
3602 // This operation is not automatically propagated
3603 // upstream. It is applied to the indicated pipeline
3604 // stage only.
3605 ////////////////////////////////////////////////////////////////////
3606 void PandaNode::
3607 sever_connection(PandaNode *parent_node, PandaNode *child_node,
3608  int pipeline_stage, Thread *current_thread) {
3609  {
3610  LightReMutexHolder holder(child_node->_paths_lock);
3611  Paths::iterator pi;
3612  for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
3613  if (!(*pi)->is_top_node(pipeline_stage, current_thread) &&
3614  (*pi)->get_next(pipeline_stage, current_thread)->get_node() == parent_node) {
3615  // Sever the component here.
3616  (*pi)->set_top_node(pipeline_stage, current_thread);
3617  }
3618  }
3619  }
3620  child_node->fix_path_lengths(pipeline_stage, current_thread);
3621 }
3622 
3623 ////////////////////////////////////////////////////////////////////
3624 // Function: PandaNode::new_connection
3625 // Access: Private, Static
3626 // Description: This is called internally when a parent-child
3627 // connection is established to update the
3628 // NodePathComponents that might be involved.
3629 //
3630 // It adjusts any NodePathComponents the child has that
3631 // reference the child as a top node. Any other
3632 // components we can leave alone, because we are making
3633 // a new instance of the child.
3634 //
3635 // This operation is not automatically propagated
3636 // upstream. It is applied to the indicated pipeline
3637 // stage only.
3638 ////////////////////////////////////////////////////////////////////
3639 void PandaNode::
3640 new_connection(PandaNode *parent_node, PandaNode *child_node,
3641  int pipeline_stage, Thread *current_thread) {
3642  {
3643  LightReMutexHolder holder(child_node->_paths_lock);
3644  Paths::iterator pi;
3645  for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
3646  if ((*pi)->is_top_node(pipeline_stage, current_thread)) {
3647  (*pi)->set_next(parent_node->get_generic_component(false, pipeline_stage, current_thread), pipeline_stage, current_thread);
3648  }
3649  }
3650  }
3651  child_node->fix_path_lengths(pipeline_stage, current_thread);
3652 }
3653 
3654 ////////////////////////////////////////////////////////////////////
3655 // Function: PandaNode::fix_path_lengths
3656 // Access: Private
3657 // Description: Recursively fixes the _length member of each
3658 // NodePathComponent at this level and below, after an
3659 // add or delete child operation that might have messed
3660 // these up.
3661 //
3662 // This operation is not automatically propagated
3663 // upstream. It is applied to the indicated pipeline
3664 // stage only.
3665 ////////////////////////////////////////////////////////////////////
3666 void PandaNode::
3667 fix_path_lengths(int pipeline_stage, Thread *current_thread) {
3668  LightReMutexHolder holder(_paths_lock);
3669 
3670  bool any_wrong = false;
3671 
3672  Paths::const_iterator pi;
3673  for (pi = _paths.begin(); pi != _paths.end(); ++pi) {
3674  if ((*pi)->fix_length(pipeline_stage, current_thread)) {
3675  any_wrong = true;
3676  }
3677  }
3678 
3679  // If any paths were updated, we have to recurse on all of our
3680  // children, since any one of those paths might be shared by any of
3681  // our child nodes. Don't hold any locks while we recurse.
3682  if (any_wrong) {
3683  Children children;
3684  Stashed stashed;
3685  {
3686  CDStageReader cdata(_cycler, pipeline_stage, current_thread);
3687  children = Children(cdata);
3688  stashed = Stashed(cdata);
3689  }
3690 
3691  int num_children = children.get_num_children();
3692  int i;
3693  for (i = 0; i < num_children; ++i) {
3694  PandaNode *child_node = children.get_child(i);
3695  child_node->fix_path_lengths(pipeline_stage, current_thread);
3696  }
3697  int num_stashed = stashed.get_num_stashed();
3698  for (i = 0; i < num_stashed; ++i) {
3699  PandaNode *child_node = stashed.get_stashed(i);
3700  child_node->fix_path_lengths(pipeline_stage, current_thread);
3701  }
3702  }
3703 }
3704 
3705 ////////////////////////////////////////////////////////////////////
3706 // Function: PandaNode::r_list_descendants
3707 // Access: Private
3708 // Description: The recursive implementation of ls().
3709 ////////////////////////////////////////////////////////////////////
3710 void PandaNode::
3711 r_list_descendants(ostream &out, int indent_level) const {
3712  write(out, indent_level);
3713 
3714  Children children = get_children();
3715  int num_children = children.get_num_children();
3716 
3717  for (int i = 0; i < num_children; ++i) {
3718  PandaNode *child = children.get_child(i);
3719  child->r_list_descendants(out, indent_level + 2);
3720  }
3721 
3722  // Also report the number of stashed nodes at this level.
3723  int num_stashed = get_num_stashed();
3724  if (num_stashed != 0) {
3725  indent(out, indent_level) << "(" << num_stashed << " stashed)\n";
3726  }
3727 }
3728 
3729 ////////////////////////////////////////////////////////////////////
3730 // Function: PandaNode::do_find_child
3731 // Access: Private
3732 // Description: The private implementation of find_child().
3733 ////////////////////////////////////////////////////////////////////
3734 int PandaNode::
3735 do_find_child(PandaNode *node, const PandaNode::Down *down) const {
3736  nassertr(node != (PandaNode *)NULL, -1);
3737 
3738  // We have to search for the child by brute force, since we don't
3739  // know what sort index it was added as.
3740  Down::const_iterator di;
3741  for (di = down->begin(); di != down->end(); ++di) {
3742  if ((*di).get_child() == node) {
3743  return di - down->begin();
3744  }
3745  }
3746 
3747  return -1;
3748 }
3749 
3750 ////////////////////////////////////////////////////////////////////
3751 // Function: PandaNode::update_cached
3752 // Access: Private
3753 // Description: Updates the cached values of the node that are
3754 // dependent on its children, such as the
3755 // external bounding volume, the _net_collide_mask,
3756 // and the _off_clip_planes.
3757 //
3758 // If update_bounds is false, it will not update the
3759 // bounding volume or vertex count.
3760 //
3761 // The old value should be passed in; it will be
3762 // released. The new value is returned.
3763 ////////////////////////////////////////////////////////////////////
3764 PandaNode::CDStageWriter PandaNode::
3765 update_cached(bool update_bounds, int pipeline_stage, PandaNode::CDLockedStageReader &cdata) {
3766  // We might need to try this a couple of times, in case someone else
3767  // steps on our result.
3768  if (drawmask_cat.is_debug()) {
3769  drawmask_cat.debug(false)
3770  << *this << "::update_cached() {\n";
3771  }
3772  Thread *current_thread = cdata.get_current_thread();
3773 
3774  do {
3775  // Grab the last_update counter.
3776  UpdateSeq last_update = cdata->_last_update;
3777  UpdateSeq next_update = cdata->_next_update;
3778  UpdateSeq last_bounds_update = cdata->_last_bounds_update;
3779  nassertr(last_update != next_update ||
3780  (update_bounds && last_bounds_update != next_update),
3781  CDStageWriter(_cycler, pipeline_stage, cdata));
3782 
3783  // Start with a clean slate.
3784  CollideMask net_collide_mask = cdata->_into_collide_mask;
3785  DrawMask net_draw_control_mask, net_draw_show_mask;
3786  bool renderable = is_renderable();
3787 
3788  if (renderable) {
3789  // If this node is itself renderable, it contributes to the net
3790  // draw mask.
3791  net_draw_control_mask = cdata->_draw_control_mask;
3792  net_draw_show_mask = cdata->_draw_show_mask;
3793  }
3794 
3795  if (drawmask_cat.is_debug()) {
3796  drawmask_cat.debug(false)
3797  << "net_draw_control_mask = " << net_draw_control_mask
3798  << "\nnet_draw_show_mask = " << net_draw_show_mask
3799  << "\n";
3800  }
3801  CPT(RenderAttrib) off_clip_planes = cdata->_state->get_attrib(ClipPlaneAttrib::get_class_slot());
3802  if (off_clip_planes == (RenderAttrib *)NULL) {
3803  off_clip_planes = ClipPlaneAttrib::make();
3804  }
3805 
3806  // Also get the list of the node's children.
3807  Children children(cdata);
3808 
3809  int num_vertices = cdata->_internal_vertices;
3810 
3811  // Now that we've got all the data we need from the node, we can
3812  // release the lock.
3813  _cycler.release_read_stage(pipeline_stage, cdata.take_pointer());
3814 
3815  int num_children = children.get_num_children();
3816 
3817  // We need to keep references to the bounding volumes, since in a
3818  // threaded environment the pointers might go away while we're
3819  // working (since we're not holding a lock on our set of children
3820  // right now). But we also need the regular pointers, to pass to
3821  // BoundingVolume::around().
3822  const BoundingVolume **child_volumes;
3823 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
3824  pvector<CPT(BoundingVolume) > child_volumes_ref;
3825  if (update_bounds) {
3826  child_volumes_ref.reserve(num_children + 1);
3827  }
3828 #endif
3829  int child_volumes_i = 0;
3830 
3831  bool all_box = true;
3832  CPT(BoundingVolume) internal_bounds = NULL;
3833 
3834  if (update_bounds) {
3835  child_volumes = (const BoundingVolume **)alloca(sizeof(BoundingVolume *) * (num_children + 1));
3836  internal_bounds = get_internal_bounds(pipeline_stage, current_thread);
3837 
3838  if (!internal_bounds->is_empty()) {
3839 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
3840  child_volumes_ref.push_back(internal_bounds);
3841 #endif
3842  nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
3843  child_volumes[child_volumes_i++] = internal_bounds;
3844  if (internal_bounds->as_bounding_box() == NULL) {
3845  all_box = false;
3846  }
3847  }
3848  }
3849 
3850  // Now expand those contents to include all of our children.
3851 
3852  for (int i = 0; i < num_children; ++i) {
3853  PandaNode *child = children.get_child(i);
3854 
3855  const ClipPlaneAttrib *orig_cp = DCAST(ClipPlaneAttrib, off_clip_planes);
3856 
3857  CDLockedStageReader child_cdata(child->_cycler, pipeline_stage, current_thread);
3858 
3859  UpdateSeq last_child_update = update_bounds
3860  ? child_cdata->_last_bounds_update
3861  : child_cdata->_last_update;
3862 
3863  if (last_child_update != child_cdata->_next_update) {
3864  // Child needs update.
3865  CDStageWriter child_cdataw = child->update_cached(update_bounds, pipeline_stage, child_cdata);
3866 
3867  net_collide_mask |= child_cdataw->_net_collide_mask;
3868 
3869  if (drawmask_cat.is_debug()) {
3870  drawmask_cat.debug(false)
3871  << "\nchild update " << *child << ":\n";
3872  }
3873 
3874  DrawMask child_control_mask = child_cdataw->_net_draw_control_mask;
3875  DrawMask child_show_mask = child_cdataw->_net_draw_show_mask;
3876  if (!(child_control_mask | child_show_mask).is_zero()) {
3877  // This child includes a renderable node or subtree. Thus,
3878  // we should propagate its draw masks.
3879  renderable = true;
3880 
3881  // For each bit position in the masks, we have assigned the
3882  // following semantic meaning. The number on the left
3883  // represents the pairing of the corresponding bit from the
3884  // control mask and from the show mask:
3885 
3886  // 00 : not a renderable node (control 0, show 0)
3887  // 01 : a normally visible node (control 0, show 1)
3888  // 10 : a hidden node (control 1, show 0)
3889  // 11 : a show-through node (control 1, show 1)
3890 
3891  // Now, when we accumulate these masks, we want to do so
3892  // according to the following table, for each bit position:
3893 
3894  // 00 01 10 11 (child)
3895  // ---------------------
3896  // 00 | 00 01 10 11
3897  // 01 | 01 01 01* 11
3898  // 10 | 10 01* 10 11
3899  // 11 | 11 11 11 11
3900  // (parent)
3901 
3902  // This table is almost the same as the union of both masks,
3903  // with one exception, marked with a * in the above table:
3904  // if one is 10 and the other is 01--that is, one is hidden
3905  // and the other is normally visible--then the result should
3906  // be 01, normally visible. This is because we only want to
3907  // propagate the hidden bit upwards if *all* renderable
3908  // nodes are hidden.
3909 
3910  // Get the set of exception bits for which the above rule
3911  // applies. These are the bits for which both bits have
3912  // flipped, but which were not the same in the original.
3913  DrawMask exception_mask = (net_draw_control_mask ^ child_control_mask) & (net_draw_show_mask ^ child_show_mask);
3914  exception_mask &= (net_draw_control_mask ^ net_draw_show_mask);
3915 
3916  if (drawmask_cat.is_debug()) {
3917  drawmask_cat.debug(false)
3918  << "exception_mask = " << exception_mask << "\n";
3919  }
3920 
3921  // Now compute the union, applying the above exception.
3922  net_draw_control_mask |= child_control_mask;
3923  net_draw_show_mask |= child_show_mask;
3924 
3925  net_draw_control_mask &= ~exception_mask;
3926  net_draw_show_mask |= exception_mask;
3927  }
3928 
3929  if (drawmask_cat.is_debug()) {
3930  drawmask_cat.debug(false)
3931  << "child_control_mask = " << child_control_mask
3932  << "\nchild_show_mask = " << child_show_mask
3933  << "\nnet_draw_control_mask = " << net_draw_control_mask
3934  << "\nnet_draw_show_mask = " << net_draw_show_mask
3935  << "\n";
3936  }
3937 
3938  off_clip_planes = orig_cp->compose_off(child_cdataw->_off_clip_planes);
3939 
3940  if (update_bounds) {
3941  if (!child_cdataw->_external_bounds->is_empty()) {
3942 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
3943  child_volumes_ref.push_back(child_cdataw->_external_bounds);
3944 #endif
3945  nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
3946  child_volumes[child_volumes_i++] = child_cdataw->_external_bounds;
3947  if (child_cdataw->_external_bounds->as_bounding_box() == NULL) {
3948  all_box = false;
3949  }
3950  }
3951  num_vertices += child_cdataw->_nested_vertices;
3952  }
3953 
3954  } else {
3955  // Child is good.
3956  net_collide_mask |= child_cdata->_net_collide_mask;
3957 
3958  // See comments in similar block above.
3959  if (drawmask_cat.is_debug()) {
3960  drawmask_cat.debug(false)
3961  << "\nchild fresh " << *child << ":\n";
3962  }
3963  DrawMask child_control_mask = child_cdata->_net_draw_control_mask;
3964  DrawMask child_show_mask = child_cdata->_net_draw_show_mask;
3965  if (!(child_control_mask | child_show_mask).is_zero()) {
3966  renderable = true;
3967 
3968  DrawMask exception_mask = (net_draw_control_mask ^ child_control_mask) & (net_draw_show_mask ^ child_show_mask);
3969  exception_mask &= (net_draw_control_mask ^ net_draw_show_mask);
3970 
3971  if (drawmask_cat.is_debug()) {
3972  drawmask_cat.debug(false)
3973  << "exception_mask = " << exception_mask << "\n";
3974  }
3975 
3976  // Now compute the union, applying the above exception.
3977  net_draw_control_mask |= child_control_mask;
3978  net_draw_show_mask |= child_show_mask;
3979 
3980  net_draw_control_mask &= ~exception_mask;
3981  net_draw_show_mask |= exception_mask;
3982  }
3983 
3984  if (drawmask_cat.is_debug()) {
3985  drawmask_cat.debug(false)
3986  << "child_control_mask = " << child_control_mask
3987  << "\nchild_show_mask = " << child_show_mask
3988  << "\nnet_draw_control_mask = " << net_draw_control_mask
3989  << "\nnet_draw_show_mask = " << net_draw_show_mask
3990  << "\n";
3991  }
3992 
3993  off_clip_planes = orig_cp->compose_off(child_cdata->_off_clip_planes);
3994 
3995  if (update_bounds) {
3996  if (!child_cdata->_external_bounds->is_empty()) {
3997 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
3998  child_volumes_ref.push_back(child_cdata->_external_bounds);
3999 #endif
4000  nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
4001  child_volumes[child_volumes_i++] = child_cdata->_external_bounds;
4002  if (child_cdata->_external_bounds->as_bounding_box() == NULL) {
4003  all_box = false;
4004  }
4005  }
4006  num_vertices += child_cdata->_nested_vertices;
4007  }
4008  }
4009  }
4010 
4011  {
4012  // Now grab the write lock on this node.
4013  CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
4014  if (last_update == cdataw->_last_update &&
4015  next_update == cdataw->_next_update) {
4016  // Great, no one has monkeyed with these while we were computing
4017  // the cache. Safe to store the computed values and return.
4018  cdataw->_net_collide_mask = net_collide_mask;
4019 
4020  if (renderable) {
4021  // Any explicit draw control mask on this node trumps anything
4022  // inherited from below, except a show-through.
4023  DrawMask draw_control_mask = cdataw->_draw_control_mask;
4024  DrawMask draw_show_mask = cdataw->_draw_show_mask;
4025 
4026  DrawMask show_through_mask = net_draw_control_mask & net_draw_show_mask;
4027 
4028  net_draw_control_mask |= draw_control_mask;
4029  net_draw_show_mask = (net_draw_show_mask & ~draw_control_mask) | (draw_show_mask & draw_control_mask);
4030 
4031  net_draw_show_mask |= show_through_mask;
4032 
4033  // There are renderable nodes below, so the implicit draw
4034  // bits are all on.
4035  cdataw->_net_draw_control_mask = net_draw_control_mask;
4036  cdataw->_net_draw_show_mask = net_draw_show_mask | ~net_draw_control_mask;
4037  if (drawmask_cat.is_debug()) {
4038  drawmask_cat.debug(false)
4039  << "renderable, set mask " << cdataw->_net_draw_show_mask << "\n";
4040  }
4041  } else {
4042  // There are no renderable nodes below, so the implicit draw
4043  // bits are all off. Also, we don't care about the draw
4044  // mask on this particular node (since nothing below it is
4045  // renderable anyway).
4046  cdataw->_net_draw_control_mask = net_draw_control_mask;
4047  cdataw->_net_draw_show_mask = net_draw_show_mask;
4048  if (drawmask_cat.is_debug()) {
4049  drawmask_cat.debug(false)
4050  << "not renderable, set mask " << cdataw->_net_draw_show_mask << "\n";
4051  }
4052  }
4053 
4054  cdataw->_off_clip_planes = off_clip_planes;
4055 
4056  if (update_bounds) {
4057  cdataw->_nested_vertices = num_vertices;
4058 
4059  CPT(TransformState) transform = get_transform(current_thread);
4060  PT(GeometricBoundingVolume) gbv;
4061 
4062  BoundingVolume::BoundsType btype = cdataw->_bounds_type;
4063  if (btype == BoundingVolume::BT_default) {
4064  btype = bounds_type;
4065  }
4066 
4067  if (btype == BoundingVolume::BT_box ||
4068  (btype != BoundingVolume::BT_sphere && all_box && transform->is_identity())) {
4069  // If all of the child volumes are a BoundingBox, and we
4070  // have no transform, then our volume is also a
4071  // BoundingBox.
4072 
4073  gbv = new BoundingBox;
4074  } else {
4075  // Otherwise, it's a sphere.
4076  gbv = new BoundingSphere;
4077  }
4078 
4079  if (child_volumes_i > 0) {
4080  const BoundingVolume **child_begin = &child_volumes[0];
4081  const BoundingVolume **child_end = child_begin + child_volumes_i;
4082  ((BoundingVolume *)gbv)->around(child_begin, child_end);
4083  }
4084 
4085  // If we have a transform, apply it to the bounding volume we
4086  // just computed.
4087  if (!transform->is_identity()) {
4088  gbv->xform(transform->get_mat());
4089  }
4090 
4091  cdataw->_external_bounds = gbv;
4092  cdataw->_last_bounds_update = next_update;
4093  }
4094 
4095  cdataw->_last_update = next_update;
4096 
4097  if (drawmask_cat.is_debug()) {
4098  drawmask_cat.debug(false)
4099  << "} " << *this << "::update_cached();\n";
4100  }
4101 
4102  nassertr(cdataw->_last_update == cdataw->_next_update, cdataw);
4103 
4104  // Even though implicit bounding volume is not (yet?) part of
4105  // the bam stream.
4107  return cdataw;
4108  }
4109 
4110  if (cdataw->_last_update == cdataw->_next_update &&
4111  (!update_bounds || cdataw->_last_bounds_update == cdataw->_next_update)) {
4112  // Someone else has computed the cache for us. OK.
4113  return cdataw;
4114  }
4115  }
4116 
4117  // We need to go around again. Release the write lock, and grab
4118  // the read lock back.
4119  cdata = CDLockedStageReader(_cycler, pipeline_stage, current_thread);
4120 
4121  if (cdata->_last_update == cdata->_next_update &&
4122  (!update_bounds || cdata->_last_bounds_update == cdata->_next_update)) {
4123  // Someone else has computed the cache for us while we were
4124  // diddling with the locks. OK.
4125  return CDStageWriter(_cycler, pipeline_stage, cdata);
4126  }
4127 
4128  } while (true);
4129 }
4130 
4131 ////////////////////////////////////////////////////////////////////
4132 // Function: PandaNode::set_scene_root_func
4133 // Access: Public, Static
4134 // Description: This is used by the GraphicsEngine to hook in a
4135 // pointer to the scene_root_func(), the function to
4136 // determine whether the node is an active scene root.
4137 // This back-pointer is necessary because we can't make
4138 // calls directly into GraphicsEngine, which is in the
4139 // display module.
4140 ////////////////////////////////////////////////////////////////////
4141 void PandaNode::
4142 set_scene_root_func(SceneRootFunc *func) {
4143  _scene_root_func = func;
4144 }
4145 
4146 ////////////////////////////////////////////////////////////////////
4147 // Function: PandaNode::register_with_read_factory
4148 // Access: Public, Static
4149 // Description: Tells the BamReader how to create objects of type
4150 // PandaNode.
4151 ////////////////////////////////////////////////////////////////////
4152 void PandaNode::
4154  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
4155 }
4156 
4157 ////////////////////////////////////////////////////////////////////
4158 // Function: PandaNode::write_datagram
4159 // Access: Public, Virtual
4160 // Description: Writes the contents of this object to the datagram
4161 // for shipping out to a Bam file.
4162 ////////////////////////////////////////////////////////////////////
4163 void PandaNode::
4165  TypedWritable::write_datagram(manager, dg);
4166  dg.add_string(get_name());
4167 
4168  manager->write_cdata(dg, _cycler);
4169 }
4170 
4171 ////////////////////////////////////////////////////////////////////
4172 // Function: PandaNode::update_bam_nested
4173 // Access: Public, Virtual
4174 // Description: Called by the BamWriter when this object has not
4175 // itself been modified recently, but it should check
4176 // its nested objects for updates.
4177 ////////////////////////////////////////////////////////////////////
4178 void PandaNode::
4180  CDReader cdata(_cycler);
4181  cdata->update_bam_nested(manager);
4182 }
4183 
4184 ////////////////////////////////////////////////////////////////////
4185 // Function: PandaNode::write_recorder
4186 // Access: Public
4187 // Description: This method is provided for the benefit of classes
4188 // (like MouseRecorder) that inherit from PandaMode and
4189 // also RecorderBase. It's not virtual at this level
4190 // since it doesn't need to be (it's called up from the
4191 // derived class).
4192 //
4193 // This method acts very like write_datagram, but it
4194 // writes the node as appropriate for writing a
4195 // RecorderBase object as described in the beginning of
4196 // a session file, meaning it doesn't need to write
4197 // things such as children. It balances with
4198 // fillin_recorder().
4199 ////////////////////////////////////////////////////////////////////
4200 void PandaNode::
4202  dg.add_string(get_name());
4203 }
4204 
4205 ////////////////////////////////////////////////////////////////////
4206 // Function: PandaNode::make_from_bam
4207 // Access: Protected, Static
4208 // Description: This function is called by the BamReader's factory
4209 // when a new object of type PandaNode is encountered
4210 // in the Bam file. It should create the PandaNode
4211 // and extract its information from the file.
4212 ////////////////////////////////////////////////////////////////////
4213 TypedWritable *PandaNode::
4214 make_from_bam(const FactoryParams &params) {
4215  PandaNode *node = new PandaNode("");
4216  DatagramIterator scan;
4217  BamReader *manager;
4218 
4219  parse_params(params, scan, manager);
4220  node->fillin(scan, manager);
4221 
4222  return node;
4223 }
4224 
4225 ////////////////////////////////////////////////////////////////////
4226 // Function: PandaNode::fillin
4227 // Access: Protected
4228 // Description: This internal function is called by make_from_bam to
4229 // read in all of the relevant data from the BamFile for
4230 // the new PandaNode.
4231 ////////////////////////////////////////////////////////////////////
4232 void PandaNode::
4233 fillin(DatagramIterator &scan, BamReader *manager) {
4234  TypedWritable::fillin(scan, manager);
4235 
4236  string name = scan.get_string();
4237  set_name(name);
4238 
4239  manager->read_cdata(scan, _cycler);
4240 }
4241 
4242 ////////////////////////////////////////////////////////////////////
4243 // Function: PandaNode::fillin_recorder
4244 // Access: Protected
4245 // Description: This internal function is called by make_recorder (in
4246 // classes derived from RecorderBase, such as
4247 // MouseRecorder) to read in all of the relevant data
4248 // from the session file. It balances with
4249 // write_recorder().
4250 ////////////////////////////////////////////////////////////////////
4251 void PandaNode::
4252 fillin_recorder(DatagramIterator &scan, BamReader *) {
4253  string name = scan.get_string();
4254  set_name(name);
4255 }
4256 
4257 ////////////////////////////////////////////////////////////////////
4258 // Function: PandaNode::CData::Constructor
4259 // Access: Public
4260 // Description:
4261 ////////////////////////////////////////////////////////////////////
4262 PandaNode::CData::
4263 CData() :
4264  _state(RenderState::make_empty()),
4265  _transform(TransformState::make_identity()),
4266  _prev_transform(TransformState::make_identity()),
4267 
4268  _effects(RenderEffects::make_empty()),
4269  _draw_control_mask(DrawMask::all_off()),
4270  _draw_show_mask(DrawMask::all_on()),
4271  _into_collide_mask(CollideMask::all_off()),
4272  _bounds_type(BoundingVolume::BT_default),
4273  _user_bounds(NULL),
4274  _final_bounds(false),
4275  _fancy_bits(0),
4276 
4277  _net_collide_mask(CollideMask::all_off()),
4278  _net_draw_control_mask(DrawMask::all_off()),
4279  _net_draw_show_mask(DrawMask::all_off()),
4280 
4281  _down(new PandaNode::Down(PandaNode::get_class_type())),
4282  _stashed(new PandaNode::Down(PandaNode::get_class_type())),
4283  _up(new PandaNode::Up(PandaNode::get_class_type()))
4284 {
4285  ++_next_update;
4286 }
4287 
4288 ////////////////////////////////////////////////////////////////////
4289 // Function: PandaNode::CData::Copy Constructor
4290 // Access: Public
4291 // Description:
4292 ////////////////////////////////////////////////////////////////////
4293 PandaNode::CData::
4294 CData(const PandaNode::CData &copy) :
4295  BoundsData(copy),
4296  _state(copy._state),
4297  _transform(copy._transform),
4298  _prev_transform(copy._prev_transform),
4299 
4300  _effects(copy._effects),
4301  _tag_data(copy._tag_data),
4302  // _python_tag_data appears below.
4303  _draw_control_mask(copy._draw_control_mask),
4304  _draw_show_mask(copy._draw_show_mask),
4305  _into_collide_mask(copy._into_collide_mask),
4306  _bounds_type(copy._bounds_type),
4307  _user_bounds(copy._user_bounds),
4308  _final_bounds(copy._final_bounds),
4309  _fancy_bits(copy._fancy_bits),
4310 
4311  _net_collide_mask(copy._net_collide_mask),
4312  _net_draw_control_mask(copy._net_draw_control_mask),
4313  _net_draw_show_mask(copy._net_draw_show_mask),
4314  _off_clip_planes(copy._off_clip_planes),
4315  _nested_vertices(copy._nested_vertices),
4316  _external_bounds(copy._external_bounds),
4317  _last_update(copy._last_update),
4318  _next_update(copy._next_update),
4319  _last_bounds_update(copy._last_bounds_update),
4320 
4321  _down(copy._down),
4322  _stashed(copy._stashed),
4323  _up(copy._up)
4324 {
4325  // Note that this copy constructor is not used by the PandaNode copy
4326  // constructor! Any elements that must be copied between nodes
4327  // should also be explicitly copied there.
4328 
4329 #ifdef HAVE_PYTHON
4330  // Copy and increment all of the Python objects held by the other
4331  // node.
4332  _python_tag_data = copy._python_tag_data;
4333  inc_py_refs();
4334 #endif // HAVE_PYTHON
4335 }
4336 
4337 ////////////////////////////////////////////////////////////////////
4338 // Function: PandaNode::CData::Destructor
4339 // Access: Public, Virtual
4340 // Description:
4341 ////////////////////////////////////////////////////////////////////
4342 PandaNode::CData::
4343 ~CData() {
4344 #ifdef HAVE_PYTHON
4345  // Free all of the Python objects held by this node.
4346  dec_py_refs();
4347 #endif // HAVE_PYTHON
4348 }
4349 
4350 ////////////////////////////////////////////////////////////////////
4351 // Function: PandaNode::CData::make_copy
4352 // Access: Public, Virtual
4353 // Description:
4354 ////////////////////////////////////////////////////////////////////
4355 CycleData *PandaNode::CData::
4356 make_copy() const {
4357  return new CData(*this);
4358 }
4359 
4360 ////////////////////////////////////////////////////////////////////
4361 // Function: PandaNode::CData::write_datagram
4362 // Access: Public, Virtual
4363 // Description: Writes the contents of this object to the datagram
4364 // for shipping out to a Bam file.
4365 ////////////////////////////////////////////////////////////////////
4366 void PandaNode::CData::
4367 write_datagram(BamWriter *manager, Datagram &dg) const {
4368  manager->write_pointer(dg, _state);
4369  manager->write_pointer(dg, _transform);
4370 
4371  //
4372  manager->write_pointer(dg, _effects);
4373 
4374  dg.add_uint32(_draw_control_mask.get_word());
4375  dg.add_uint32(_draw_show_mask.get_word());
4376  dg.add_uint32(_into_collide_mask.get_word());
4377  dg.add_uint8(_bounds_type);
4378 
4379  dg.add_uint32(_tag_data.size());
4380  TagData::const_iterator ti;
4381  for (ti = _tag_data.begin(); ti != _tag_data.end(); ++ti) {
4382  dg.add_string((*ti).first);
4383  dg.add_string((*ti).second);
4384  }
4385 
4386  //
4387  write_up_list(*get_up(), manager, dg);
4388  write_down_list(*get_down(), manager, dg);
4389  write_down_list(*get_stashed(), manager, dg);
4390 }
4391 
4392 ////////////////////////////////////////////////////////////////////
4393 // Function: PandaNode::CData::update_bam_nested
4394 // Access: Public
4395 // Description: Called by the BamWriter when this object has not
4396 // itself been modified recently, but it should check
4397 // its nested objects for updates.
4398 ////////////////////////////////////////////////////////////////////
4399 void PandaNode::CData::
4400 update_bam_nested(BamWriter *manager) const {
4401  // No need to check the state pointers for updates, since they're
4402  // all immutable objects.
4403  //manager->consider_update(_state);
4404  //manager->consider_update(_transform);
4405  //manager->consider_update(_effects);
4406 
4407  update_up_list(*get_up(), manager);
4408  update_down_list(*get_down(), manager);
4409  update_down_list(*get_stashed(), manager);
4410 }
4411 
4412 ////////////////////////////////////////////////////////////////////
4413 // Function: PandaNode::CData::complete_pointers
4414 // Access: Public, Virtual
4415 // Description: Receives an array of pointers, one for each time
4416 // manager->read_pointer() was called in fillin().
4417 // Returns the number of pointers processed.
4418 ////////////////////////////////////////////////////////////////////
4419 int PandaNode::CData::
4420 complete_pointers(TypedWritable **p_list, BamReader *manager) {
4421  int pi = CycleData::complete_pointers(p_list, manager);
4422 
4423  // Get the state and transform pointers.
4424  _state = DCAST(RenderState, p_list[pi++]);
4425  _transform = DCAST(TransformState, p_list[pi++]);
4426  _prev_transform = _transform;
4427 
4428  // Finalize these pointers now to decrement their artificially-held
4429  // reference counts. We do this now, rather than later, in case
4430  // some other object reassigns them a little later on during
4431  // initialization, before they can finalize themselves normally (for
4432  // instance, the character may change the node's transform). If
4433  // that happens, the pointer may discover that no one else holds its
4434  // reference count when it finalizes, which will constitute a memory
4435  // leak (see the comments in TransformState::finalize(), etc.).
4436  manager->finalize_now((RenderState *)_state.p());
4437  manager->finalize_now((TransformState *)_transform.p());
4438 
4439  //
4440 
4441  // Get the effects pointer.
4442  _effects = DCAST(RenderEffects, p_list[pi++]);
4443 
4444  // Finalize these pointers now to decrement their artificially-held
4445  // reference counts. We do this now, rather than later, in case
4446  // some other object reassigns them a little later on during
4447  // initialization, before they can finalize themselves normally (for
4448  // instance, the character may change the node's transform). If
4449  // that happens, the pointer may discover that no one else holds its
4450  // reference count when it finalizes, which will constitute a memory
4451  // leak (see the comments in TransformState::finalize(), etc.).
4452  manager->finalize_now((RenderEffects *)_effects.p());
4453 
4454  //
4455 
4456  // Get the parent and child pointers.
4457  pi += complete_up_list(*modify_up(), "up", p_list + pi, manager);
4458  pi += complete_down_list(*modify_down(), "down", p_list + pi, manager);
4459  pi += complete_down_list(*modify_stashed(), "stashed", p_list + pi, manager);
4460 
4461  // Since the _effects and _states members have been finalized by
4462  // now, this should be safe.
4463  set_fancy_bit(FB_transform, !_transform->is_identity());
4464  set_fancy_bit(FB_state, !_state->is_empty());
4465  set_fancy_bit(FB_effects, !_effects->is_empty());
4466  set_fancy_bit(FB_tag, !_tag_data.empty());
4467 
4468  return pi;
4469 }
4470 
4471 ////////////////////////////////////////////////////////////////////
4472 // Function: PandaNode::CData::fillin
4473 // Access: Public, Virtual
4474 // Description: This internal function is called by make_from_bam to
4475 // read in all of the relevant data from the BamFile for
4476 // the new PandaNode.
4477 ////////////////////////////////////////////////////////////////////
4478 void PandaNode::CData::
4479 fillin(DatagramIterator &scan, BamReader *manager) {
4480  // Read the state and transform pointers.
4481  manager->read_pointer(scan);
4482  manager->read_pointer(scan);
4483 
4484  //
4485  // Read the effects pointer.
4486  manager->read_pointer(scan);
4487 
4488  if (manager->get_file_minor_ver() < 2) {
4489  DrawMask draw_mask;
4490  draw_mask.set_word(scan.get_uint32());
4491 
4492  if (draw_mask == DrawMask::all_off()) {
4493  // Hidden.
4494  _draw_control_mask = _overall_bit;
4495  _draw_show_mask = ~_overall_bit;
4496 
4497  } else if (draw_mask == DrawMask::all_on()) {
4498  // Normally visible.
4499  _draw_control_mask = DrawMask::all_off();
4500  _draw_show_mask = DrawMask::all_on();
4501 
4502  } else {
4503  // Some per-camera combination.
4504  draw_mask &= ~_overall_bit;
4505  _draw_control_mask = ~draw_mask;
4506  _draw_show_mask = draw_mask;
4507  }
4508 
4509  } else {
4510  _draw_control_mask.set_word(scan.get_uint32());
4511  _draw_show_mask.set_word(scan.get_uint32());
4512  }
4513 
4514  _into_collide_mask.set_word(scan.get_uint32());
4515 
4516  _bounds_type = BoundingVolume::BT_default;
4517  if (manager->get_file_minor_ver() >= 19) {
4518  _bounds_type = (BoundingVolume::BoundsType)scan.get_uint8();
4519  }
4520 
4521  // Read in the tag list.
4522  int num_tags = scan.get_uint32();
4523  for (int i = 0; i < num_tags; i++) {
4524  string key = scan.get_string();
4525  string value = scan.get_string();
4526  _tag_data[key] = value;
4527  }
4528 
4529  //
4530  fillin_up_list(*modify_up(), "up", scan, manager);
4531  fillin_down_list(*modify_down(), "down", scan, manager);
4532  fillin_down_list(*modify_stashed(), "stashed", scan, manager);
4533 }
4534 
4535 #ifdef HAVE_PYTHON
4536 ////////////////////////////////////////////////////////////////////
4537 // Function: PandaNode::CData::inc_py_refs
4538 // Access: Public
4539 // Description: Increments the reference counts on all held Python
4540 // objects.
4541 ////////////////////////////////////////////////////////////////////
4542 void PandaNode::CData::
4543 inc_py_refs() {
4544  if (!_python_tag_data.empty()) {
4545 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
4546  // This might happen at any time, so be sure the Python state is
4547  // ready for it.
4548  PyGILState_STATE gstate;
4549  gstate = PyGILState_Ensure();
4550 #endif
4551  PythonTagData::const_iterator ti;
4552  for (ti = _python_tag_data.begin();
4553  ti != _python_tag_data.end();
4554  ++ti) {
4555  PyObject *value = (*ti).second;
4556  Py_XINCREF(value);
4557  }
4558 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
4559  PyGILState_Release(gstate);
4560 #endif
4561  }
4562 }
4563 #endif // HAVE_PYTHON
4564 
4565 #ifdef HAVE_PYTHON
4566 ////////////////////////////////////////////////////////////////////
4567 // Function: PandaNode::CData::dec_py_refs
4568 // Access: Public
4569 // Description: Decrements the reference counts on all held Python
4570 // objects.
4571 ////////////////////////////////////////////////////////////////////
4572 void PandaNode::CData::
4573 dec_py_refs() {
4574  if (!_python_tag_data.empty()) {
4575 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
4576  // This might happen at any time, so be sure the Python state is
4577  // ready for it.
4578  PyGILState_STATE gstate;
4579  gstate = PyGILState_Ensure();
4580 #endif
4581 
4582  PythonTagData::const_iterator ti;
4583  for (ti = _python_tag_data.begin();
4584  ti != _python_tag_data.end();
4585  ++ti) {
4586  PyObject *value = (*ti).second;
4587  Py_XDECREF(value);
4588  }
4589 
4590 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
4591  PyGILState_Release(gstate);
4592 #endif
4593  }
4594 }
4595 #endif // HAVE_PYTHON
4596 
4597 ////////////////////////////////////////////////////////////////////
4598 // Function: PandaNode::CData::write_up_list
4599 // Access: Public
4600 // Description: Writes the indicated list of parent node pointers to
4601 // the datagram.
4602 ////////////////////////////////////////////////////////////////////
4603 void PandaNode::CData::
4604 write_up_list(const PandaNode::Up &up_list,
4605  BamWriter *manager, Datagram &dg) const {
4606  // When we write a PandaNode, we write out its complete list of
4607  // child node pointers, but we only write out the parent node
4608  // pointers that have already been added to the bam file by a
4609  // previous write operation. This is a bit of trickery that allows
4610  // us to write out just a subgraph (instead of the complete graph)
4611  // when we write out an arbitrary node in the graph, yet also allows
4612  // us to keep nodes completely in sync when we use the bam format
4613  // for streaming scene graph operations over the network.
4614 
4615  int num_parents = 0;
4616  Up::const_iterator ui;
4617  for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
4618  PandaNode *parent_node = (*ui).get_parent();
4619  if (manager->has_object(parent_node)) {
4620  num_parents++;
4621  }
4622  }
4623  nassertv(num_parents == (int)(PN_uint16)num_parents);
4624  dg.add_uint16(num_parents);
4625  for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
4626  PandaNode *parent_node = (*ui).get_parent();
4627  if (manager->has_object(parent_node)) {
4628  manager->write_pointer(dg, parent_node);
4629  }
4630  }
4631 }
4632 
4633 ////////////////////////////////////////////////////////////////////
4634 // Function: PandaNode::CData::write_down_list
4635 // Access: Public
4636 // Description: Writes the indicated list of child node pointers to
4637 // the datagram.
4638 ////////////////////////////////////////////////////////////////////
4639 void PandaNode::CData::
4640 write_down_list(const PandaNode::Down &down_list,
4641  BamWriter *manager, Datagram &dg) const {
4642  int num_children = down_list.size();
4643  nassertv(num_children == (int)(PN_uint16)num_children);
4644  dg.add_uint16(num_children);
4645 
4646  // Should we smarten up the writing of the sort number? Most of the
4647  // time these will all be zero.
4648  Down::const_iterator di;
4649  for (di = down_list.begin(); di != down_list.end(); ++di) {
4650  PandaNode *child_node = (*di).get_child();
4651  int sort = (*di).get_sort();
4652  manager->write_pointer(dg, child_node);
4653  dg.add_int32(sort);
4654  }
4655 }
4656 
4657 ////////////////////////////////////////////////////////////////////
4658 // Function: PandaNode::CData::update_up_list
4659 // Access: Public
4660 // Description: Calls consider_update on each node of the indicated
4661 // up list.
4662 ////////////////////////////////////////////////////////////////////
4663 void PandaNode::CData::
4664 update_up_list(const PandaNode::Up &up_list, BamWriter *manager) const {
4665  Up::const_iterator ui;
4666  for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
4667  PandaNode *parent_node = (*ui).get_parent();
4668  if (manager->has_object(parent_node)) {
4669  manager->consider_update(parent_node);
4670  }
4671  }
4672 }
4673 
4674 ////////////////////////////////////////////////////////////////////
4675 // Function: PandaNode::CData::update_down_list
4676 // Access: Public
4677 // Description: Calls consider_update on each node of the indicated
4678 // up list.
4679 ////////////////////////////////////////////////////////////////////
4680 void PandaNode::CData::
4681 update_down_list(const PandaNode::Down &down_list, BamWriter *manager) const {
4682  Down::const_iterator di;
4683  for (di = down_list.begin(); di != down_list.end(); ++di) {
4684  PandaNode *child_node = (*di).get_child();
4685  manager->consider_update(child_node);
4686  }
4687 }
4688 
4689 ////////////////////////////////////////////////////////////////////
4690 // Function: PandaNode::CData::complete_up_list
4691 // Access: Public
4692 // Description: Calls complete_pointers() on the list of parent node
4693 // pointers.
4694 ////////////////////////////////////////////////////////////////////
4695 int PandaNode::CData::
4696 complete_up_list(PandaNode::Up &up_list, const string &tag,
4697  TypedWritable **p_list, BamReader *manager) {
4698  int pi = 0;
4699 
4700  int num_parents = manager->get_int_tag(tag);
4701  Up new_up_list(PandaNode::get_class_type());
4702  new_up_list.reserve(num_parents);
4703  for (int i = 0; i < num_parents; i++) {
4704  PandaNode *parent_node = DCAST(PandaNode, p_list[pi++]);
4705  UpConnection connection(parent_node);
4706  new_up_list.push_back(connection);
4707  }
4708 
4709  // Now we should sort the list, since the sorting is based on
4710  // pointer order, which might be different from one session to the
4711  // next.
4712  new_up_list.sort();
4713 
4714  // Make it permanent.
4715  up_list.swap(new_up_list);
4716  new_up_list.clear();
4717 
4718  return pi;
4719 }
4720 
4721 ////////////////////////////////////////////////////////////////////
4722 // Function: PandaNode::CData::complete_down_list
4723 // Access: Public
4724 // Description: Calls complete_pointers() on the list of child node
4725 // pointers.
4726 ////////////////////////////////////////////////////////////////////
4727 int PandaNode::CData::
4728 complete_down_list(PandaNode::Down &down_list, const string &tag,
4729  TypedWritable **p_list, BamReader *manager) {
4730  int pi = 0;
4731 
4732  BamReaderAuxDataDown *aux;
4733  DCAST_INTO_R(aux, manager->get_aux_tag(tag), pi);
4734 
4735  Down &new_down_list = aux->_down_list;
4736  for (Down::iterator di = new_down_list.begin();
4737  di != new_down_list.end();
4738  ++di) {
4739  PandaNode *child_node = DCAST(PandaNode, p_list[pi++]);
4740  (*di).set_child(child_node);
4741  }
4742 
4743  // Unlike the up list, we should *not* sort the down list. The down
4744  // list is stored in a specific order, not related to pointer order;
4745  // and this order should be preserved from one session to the next.
4746 
4747  // Make it permanent.
4748  down_list.swap(new_down_list);
4749  new_down_list.clear();
4750 
4751  return pi;
4752 }
4753 
4754 ////////////////////////////////////////////////////////////////////
4755 // Function: PandaNode::CData::fillin_up_list
4756 // Access: Public
4757 // Description: Reads the indicated list parent node pointers from
4758 // the datagram (or at least calls read_pointer() for
4759 // each one).
4760 ////////////////////////////////////////////////////////////////////
4761 void PandaNode::CData::
4762 fillin_up_list(PandaNode::Up &up_list, const string &tag,
4763  DatagramIterator &scan, BamReader *manager) {
4764  int num_parents = scan.get_uint16();
4765  manager->set_int_tag(tag, num_parents);
4766  manager->read_pointers(scan, num_parents);
4767 }
4768 
4769 ////////////////////////////////////////////////////////////////////
4770 // Function: PandaNode::CData::fillin_down_list
4771 // Access: Public
4772 // Description: Reads the indicated list child node pointers from
4773 // the datagram (or at least calls read_pointer() for
4774 // each one).
4775 ////////////////////////////////////////////////////////////////////
4776 void PandaNode::CData::
4777 fillin_down_list(PandaNode::Down &down_list, const string &tag,
4778  DatagramIterator &scan, BamReader *manager) {
4779  int num_children = scan.get_uint16();
4780 
4781  // Create a temporary down_list, with the right number of elements,
4782  // but a NULL value for each pointer (we'll fill in the pointers
4783  // later). We need to do this to associate the sort values with
4784  // their pointers.
4785  Down new_down_list(PandaNode::get_class_type());
4786  new_down_list.reserve(num_children);
4787  for (int i = 0; i < num_children; i++) {
4788  manager->read_pointer(scan);
4789  int sort = scan.get_int32();
4790  DownConnection connection(NULL, sort);
4791  new_down_list.push_back(connection);
4792  }
4793 
4794  // Now store the temporary down_list in the BamReader, so we can get
4795  // it during the call to complete_down_list().
4796  PT(BamReaderAuxDataDown) aux = new BamReaderAuxDataDown;
4797  aux->_down_list.swap(new_down_list);
4798  manager->set_aux_tag(tag, aux);
4799 }
4800 
4801 ////////////////////////////////////////////////////////////////////
4802 // Function: PandaNodePipelineReader::check_cached
4803 // Access: Public
4804 // Description: Ensures that the draw masks etc. are properly
4805 // computed on this node. If update_bounds is true,
4806 // also checks the bounding volume.
4807 ////////////////////////////////////////////////////////////////////
4809 check_cached(bool update_bounds) const {
4810  UpdateSeq last_update = update_bounds
4811  ? _cdata->_last_bounds_update
4812  : _cdata->_last_update;
4813 
4814  if (last_update != _cdata->_next_update) {
4815  // The cache is stale; it needs to be rebuilt.
4816 
4817  // We'll need to get a fresh read pointer, since another thread
4818  // might already have modified the pointer on the object since we
4819  // queried it.
4820 #ifdef DO_PIPELINING
4821  node_unref_delete((CycleData *)_cdata);
4822 #endif // DO_PIPELINING
4823  ((PandaNodePipelineReader *)this)->_cdata = NULL;
4824  int pipeline_stage = _current_thread->get_pipeline_stage();
4825  PandaNode::CDLockedStageReader fresh_cdata(_node->_cycler, pipeline_stage, _current_thread);
4826  if (fresh_cdata->_last_update == fresh_cdata->_next_update &&
4827  (!update_bounds || fresh_cdata->_last_bounds_update == fresh_cdata->_next_update)) {
4828  // What luck, some other thread has already freshened the
4829  // cache for us. Save the new pointer, and let the lock
4830  // release itself.
4831  if (_cdata != (const PandaNode::CData *)fresh_cdata) {
4832  ((PandaNodePipelineReader *)this)->_cdata = fresh_cdata;
4833 #ifdef DO_PIPELINING
4834  _cdata->node_ref();
4835 #endif // DO_PIPELINING
4836  }
4837 
4838  } else {
4839  // No, the cache is still stale. We have to do the work of
4840  // freshening it.
4841  PStatTimer timer(PandaNode::_update_bounds_pcollector);
4842  PandaNode::CDStageWriter cdataw = ((PandaNode *)_node)->update_cached(update_bounds, pipeline_stage, fresh_cdata);
4843  nassertv(cdataw->_last_update == cdataw->_next_update);
4844  // As above, we save the new pointer, and then let the lock
4845  // release itself.
4846  if (_cdata != (const PandaNode::CData *)cdataw) {
4847  ((PandaNodePipelineReader *)this)->_cdata = cdataw;
4848 #ifdef DO_PIPELINING
4849  _cdata->node_ref();
4850 #endif // DO_PIPELINING
4851  }
4852  }
4853  }
4854 
4855  nassertv(_cdata->_last_update == _cdata->_next_update);
4856  nassertv(!update_bounds || _cdata->_last_bounds_update == _cdata->_next_update);
4857 }
static BitMask< PN_uint32, nbits > bit(int index)
void set_tag(const string &key, const string &value, Thread *current_thread=Thread::get_current_thread())
Associates a user-defined value with a user-defined key which is stored on the node.
Definition: pandaNode.cxx:1403
void clear_unexpected_change(unsigned int flags)
Sets one or more of the PandaNode::UnexpectedChange bits off, indicating that the corresponding prope...
Definition: pandaNode.cxx:1887
virtual Light * as_light()
Cross-casts the node to a Light pointer, if it is one of the four kinds of Light nodes, or returns NULL if it is not.
Definition: pandaNode.cxx:2528
A basic node of the scene graph or data graph.
Definition: pandaNode.h:72
virtual int get_visible_child() const
Returns the index number of the currently visible child of this node.
Definition: pandaNode.cxx:563
The abstract interface to all kinds of lights.
Definition: light.h:42
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
Definition: boundingBox.h:31
void add_uint8(PN_uint8 value)
Adds an unsigned 8-bit integer to the datagram.
Definition: datagram.I:138
void remove_child(int child_index, Thread *current_thread=Thread::get_current_thread())
Removes the nth child from the node.
Definition: pandaNode.cxx:697
This is our own Panda specialization on the default STL map.
Definition: pmap.h:52
DrawMask get_net_draw_control_mask() const
Returns the set of bits in get_net_draw_show_mask() that have been explicitly set via adjust_draw_mas...
Definition: pandaNode.cxx:1974
void list_tags(ostream &out, const string &separator="\n") const
Writes a list of all the tag keys assigned to the node to the indicated stream.
Definition: pandaNode.cxx:1505
void add_string(const string &str)
Adds a variable-length string to the datagram.
Definition: datagram.I:351
This is the base class for a number of render attributes (other than transform) that may be set on sc...
Definition: renderAttrib.h:60
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: pandaNode.cxx:4164
PandaNode * get_parent(int n, Thread *current_thread=Thread::get_current_thread()) const
Returns the nth parent node of this node.
Definition: pandaNode.I:40
bool replace_child(PandaNode *orig_child, PandaNode *new_child, Thread *current_thread=Thread::get_current_thread())
Searches for the orig_child node in the node&#39;s list of children, and replaces it with the new_child i...
Definition: pandaNode.cxx:771
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:1188
virtual void apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types, GeomTransformer &transformer)
Applies whatever attributes are specified in the AccumulatedAttribs object (and by the attrib_types b...
Definition: pandaNode.cxx:352
virtual bool has_single_child_visibility() const
Should be overridden by derived classes to return true if this kind of node has the special property ...
Definition: pandaNode.cxx:551
virtual bool is_collision_node() const
A simple downcast check.
Definition: pandaNode.cxx:2516
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
int get_num_stashed() const
Returns the number of stashed children of the node.
Definition: pandaNode.I:1264
PandaNode * get_parent(int n) const
Returns the nth parent of the node.
Definition: pandaNode.I:1376
virtual PandaNode * combine_with(PandaNode *other)
Collapses this PandaNode with the other PandaNode, if possible, and returns a pointer to the combined...
Definition: pandaNode.cxx:397
static void reset_all_prev_transform(Thread *current_thread=Thread::get_current_thread())
Visits all nodes in the world with the _dirty_prev_transform flag–that is, all nodes whose _prev_tran...
Definition: pandaNode.cxx:1362
void write_recorder(BamWriter *manager, Datagram &dg)
This method is provided for the benefit of classes (like MouseRecorder) that inherit from PandaMode a...
Definition: pandaNode.cxx:4201
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
Definition: bamReader.cxx:747
Parents get_parents(Thread *current_thread=Thread::get_current_thread()) const
Returns an object that can be used to walk through the list of parents of the node, similar to get_children() and get_stashed().
Definition: pandaNode.I:809
void set_effects(const RenderEffects *effects, Thread *current_thread=Thread::get_current_thread())
Sets the complete RenderEffects that will be applied this node.
Definition: pandaNode.cxx:1247
void get_tag_keys(vector_string &keys) const
Fills the given vector up with the list of tags on this PandaNode.
Definition: pandaNode.cxx:1544
void set_bounds(const BoundingVolume *volume)
Resets the bounding volume so that it is the indicated volume.
Definition: pandaNode.cxx:2304
PandaNode * get_child(int n) const
Returns the nth child of the node.
Definition: pandaNode.I:1174
static BitMask< PN_uint32, nbits > all_on()
bool stash_child(PandaNode *child_node, Thread *current_thread=Thread::get_current_thread())
Stashes the indicated child node.
Definition: pandaNode.I:133
void clear_tag(const string &key, Thread *current_thread=Thread::get_current_thread())
Removes the value defined for this key on this particular node.
Definition: pandaNode.cxx:1423
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:159
This defines a bounding sphere, consisting of a center and a radius.
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:37
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
Definition: bamWriter.cxx:398
int compare_tags(const PandaNode *other) const
Returns a number less than 0, 0, or greater than 0, to indicate the similarity of tags between this n...
Definition: pandaNode.cxx:1567
int get_nested_vertices(Thread *current_thread=Thread::get_current_thread()) const
Returns the total number of vertices that will be rendered by this node and all of its descendents...
Definition: pandaNode.cxx:2407
This collects together the pieces of data that are accumulated for each node while walking the scene ...
virtual PandaNode * make_copy() const
Returns a newly-allocated PandaNode that is a shallow copy of this one.
Definition: pandaNode.cxx:604
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
Definition: typedObject.I:74
BamReaderAuxData * get_aux_tag(const string &tag) const
Returns the value previously set via set_aux_tag().
Definition: bamReader.cxx:853
static bool decode_raw_from_bam_stream(TypedWritable *&ptr, ReferenceCount *&ref_ptr, const string &data, BamReader *reader=NULL)
Reads the string created by a previous call to encode_to_bam_stream(), and extracts the single object...
const CycleDataType * take_pointer()
This is intended to be called only from CycleDataStageWriter when it elevates the pointer from read t...
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:1932
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:34
This functions similarly to a LightAttrib.
static BitMask< WType, nbits > all_off()
Returns a BitMask whose bits are all off.
Definition: bitMask.I:86
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Definition: lpoint3.h:99
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
This is the base class for a number of special render effects that may be set on scene graph nodes to...
Definition: renderEffect.h:56
PN_int32 get_int32()
Extracts a signed 32-bit integer.
PN_uint8 get_uint8()
Extracts an unsigned 8-bit integer.
int get_stashed_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:1289
PN_uint32 get_uint32()
Extracts an unsigned 32-bit integer.
static void register_with_read_factory()
Tells the BamReader how to create objects of type PandaNode.
Definition: pandaNode.cxx:4153
virtual bool is_lod_node() const
A simple downcast check.
Definition: pandaNode.cxx:2501
virtual int get_next_visible_child(int n) const
Returns the index number of the next visible child of this node following the indicated child...
Definition: pandaNode.cxx:530
virtual bool has_selective_visibility() const
Should be overridden by derived classes to return true if this kind of node has some restrictions on ...
Definition: pandaNode.cxx:500
virtual bool preserve_name() const
Returns true if the node&#39;s name has extrinsic meaning and must be preserved across a flatten operatio...
Definition: pandaNode.cxx:319
void set_word(WordType value)
Sets the entire BitMask to the value indicated by the given word.
Definition: bitMask.I:395
void copy_tags(PandaNode *other)
Copies all of the tags stored on the other node onto this node.
Definition: pandaNode.cxx:1442
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:2443
string get_string()
Extracts a variable-length string.
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class&#39;s make_from_bam() method to read in all...
PN_uint16 get_uint16()
Extracts an unsigned 16-bit integer.
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
Definition: thread.I:145
virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state, GeomTransformer &transformer, Thread *current_thread)
The recursive implementation of prepare_scene().
Definition: pandaNode.cxx:2925
void clear_attrib(TypeHandle type)
Removes the render attribute of the given type from this node.
Definition: pandaNode.I:290
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
This just stores the pointers to implement a doubly-linked list of some kind of object.
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
PandaNode * get_stashed(int n) const
Returns the nth stashed child of the node.
Definition: pandaNode.I:1275
static NodePath any_path(PandaNode *node, Thread *current_thread=Thread::get_current_thread())
Returns a new NodePath that represents any arbitrary path from the root to the indicated node...
Definition: nodePath.I:77
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:39
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
BoundingVolume::BoundsType get_bounds_type() const
Returns the bounding volume type set with set_bounds_type().
Definition: pandaNode.cxx:2284
bool has_tags() const
Returns true if the node has any tags (or any Python tags) at all, false if it has none...
Definition: pandaNode.I:469
bool is_top_node(int pipeline_stage, Thread *current_thread) const
Returns true if this component represents the top node in the path.
void reset_prev_transform(Thread *current_thread=Thread::get_current_thread())
Resets the transform that represents this node&#39;s &quot;previous&quot; position to the same as the current trans...
Definition: pandaNode.cxx:1336
bool has_object(const TypedWritable *obj) const
Returns true if the object has previously been written (or at least requested to be written) to the b...
Definition: bamWriter.cxx:208
virtual void xform(const LMatrix4 &mat)
Transforms the contents of this PandaNode by the indicated matrix, if it means anything to do so...
Definition: pandaNode.cxx:377
A lightweight class that represents a single element that may be timed and/or counted via stats...
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
virtual bool safe_to_modify_transform() const
Returns true if it is safe to automatically adjust the transform on this kind of node.
Definition: pandaNode.cxx:266
int find_stashed(PandaNode *node, Thread *current_thread=Thread::get_current_thread()) const
Returns the index of the indicated stashed node, if it is a stashed child, or -1 if it is not...
Definition: pandaNode.I:220
PandaNode * get_stashed(int n, Thread *current_thread=Thread::get_current_thread()) const
Returns the nth stashed child of this node.
Definition: pandaNode.I:191
A base class for all things which can have a name.
Definition: namable.h:29
unsigned int get_unexpected_change(unsigned int flags) const
Returns nonzero if any of the bits in the input parameter are set on this node, or zero if none of th...
Definition: pandaNode.cxx:1864
virtual bool safe_to_combine_children() const
Returns true if it is generally safe to combine the children of this PandaNode with each other...
Definition: pandaNode.cxx:295
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:2467
PandaNode * get_node() const
Returns the node referenced by this component.
virtual bool safe_to_combine() const
Returns true if it is generally safe to combine this particular kind of PandaNode with other kinds of...
Definition: pandaNode.cxx:281
CollideMask get_net_collide_mask(Thread *current_thread=Thread::get_current_thread()) const
Returns the union of all into_collide_mask() values set at CollisionNodes at this level and below...
Definition: pandaNode.cxx:2080
virtual CollideMask get_legal_collide_mask() const
Returns the subset of CollideMask bits that may be set for this particular type of PandaNode...
Definition: pandaNode.cxx:2069
This class is used by the SceneGraphReducer to maintain and accumulate the set of attributes we have ...
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:97
int get_num_children() const
Returns the number of children of the node.
Definition: pandaNode.I:1163
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:451
void remove_all_children(Thread *current_thread=Thread::get_current_thread())
Removes all the children from the node at once, including stashed children.
Definition: pandaNode.cxx:990
DrawMask get_draw_show_mask() const
Returns the hide/show bits of this particular node.
Definition: pandaNode.I:571
void set_bounds_type(BoundingVolume::BoundsType bounds_type)
Specifies the desired type of bounding volume that will be created for this node. ...
Definition: pandaNode.cxx:2261
Similar to MutexHolder, but for a light mutex.
virtual bool is_ambient_light() const
Returns true if this is an AmbientLight, false if it is not a light, or it is some other kind of ligh...
Definition: pandaNode.cxx:2539
virtual bool safe_to_transform() const
Returns true if it is generally safe to transform this particular kind of PandaNode by calling the xf...
Definition: pandaNode.cxx:249
void read_pointers(DatagramIterator &scan, int count)
A convenience function to read a contiguous list of pointers.
Definition: bamReader.cxx:694
int get_num_children(Thread *current_thread=Thread::get_current_thread()) const
Returns the number of child nodes this node has.
Definition: pandaNode.I:68
void remove_stashed(int child_index, Thread *current_thread=Thread::get_current_thread())
Removes the nth stashed child from the node.
Definition: pandaNode.cxx:956
int get_int_tag(const string &tag) const
Returns the value previously set via set_int_tag().
Definition: bamReader.cxx:804
void set_state(const RenderState *state, Thread *current_thread=Thread::get_current_thread())
Sets the complete RenderState that will be applied to all nodes at this level and below...
Definition: pandaNode.cxx:1216
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:40
void copy_all_properties(PandaNode *other)
Copies the TransformState, RenderState, RenderEffects, tags, Python tags, and the show/hide state fro...
Definition: pandaNode.cxx:1655
virtual void add_for_draw(CullTraverser *trav, CullTraverserData &data)
Adds the node&#39;s contents to the CullResult we are building up during the cull traversal, so that it will be drawn at render time.
Definition: pandaNode.cxx:591
void steal_children(PandaNode *other, Thread *current_thread=Thread::get_current_thread())
Moves all the children from the other node onto this node.
Definition: pandaNode.cxx:1038
int get_num_parents() const
Returns the number of parents of the node.
Definition: pandaNode.I:1365
Children get_children(Thread *current_thread=Thread::get_current_thread()) const
Returns an object that can be used to walk through the list of children of the node.
Definition: pandaNode.I:773
DrawMask get_draw_control_mask() const
Returns the set of bits in draw_show_mask that are considered meaningful.
Definition: pandaNode.I:559
virtual void update_bam_nested(BamWriter *manager)
Called by the BamWriter when this object has not itself been modified recently, but it should check i...
Definition: pandaNode.cxx:4179
void set_effect(const RenderEffect *effect)
Adds the indicated render effect to the scene graph on this node.
Definition: pandaNode.cxx:1174
void set_into_collide_mask(CollideMask mask)
Sets the &quot;into&quot; CollideMask.
Definition: pandaNode.cxx:2037
DrawMask get_net_draw_show_mask() const
Returns the union of all draw_show_mask values–of renderable nodes only–at this level and below...
Definition: pandaNode.cxx:2005
void set_unexpected_change(unsigned int flags)
Sets one or more of the PandaNode::UnexpectedChange bits on, indicating that the corresponding proper...
Definition: pandaNode.cxx:1843
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager-&gt;read_pointer() was called in fillin()...
Definition: cycleData.cxx:55
bool is_empty() const
Returns true if the state is empty, false otherwise.
Definition: renderState.I:33
virtual bool is_renderable() const
Returns true if there is some value to visiting this particular node during the cull traversal for an...
Definition: pandaNode.cxx:578
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
static void set_scene_root_func(SceneRootFunc *func)
This is used by the GraphicsEngine to hook in a pointer to the scene_root_func(), the function to det...
Definition: pandaNode.cxx:4142
void add_stashed(PandaNode *child_node, int sort=0, Thread *current_thread=Thread::get_current_thread())
Adds a new child to the node, directly as a stashed child.
Definition: pandaNode.cxx:919
A base class for things which need to inherit from both TypedWritable and from ReferenceCount.
This class is similar to CycleDataLockedReader, except it allows reading from a particular stage of t...
Similar to MutexHolder, but for a light reentrant mutex.
void finalize_now(TypedWritable *whom)
Forces the finalization of a particular object.
Definition: bamReader.cxx:980
void set_attrib(const RenderAttrib *attrib, int override=0)
Adds the indicated render attribute to the scene graph on this node.
Definition: pandaNode.cxx:1107
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:53
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:90
int get_num_stashed(Thread *current_thread=Thread::get_current_thread()) const
Returns the number of stashed nodes this node has.
Definition: pandaNode.I:176
void add_uint16(PN_uint16 value)
Adds an unsigned 16-bit integer to the datagram.
Definition: datagram.I:181
This class is similar to CycleDataReader, except it allows reading from a particular stage of the pip...
A base class for all things that want to be reference-counted.
int find_parent(PandaNode *node, Thread *current_thread=Thread::get_current_thread()) const
Returns the index of the indicated parent node, if it is a parent, or -1 if it is not...
Definition: pandaNode.I:54
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
PandaNode * get_child(int n, Thread *current_thread=Thread::get_current_thread()) const
Returns the nth child node of this node.
Definition: pandaNode.I:82
void set_bound(const BoundingVolume *volume)
Deprecated.
Definition: pandaNode.cxx:2325
void replace_node(PandaNode *other)
Inserts this node into the scene graph in place of the other one, and removes the other node...
Definition: pandaNode.cxx:1777
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:213
bool around(const BoundingVolume **first, const BoundingVolume **last)
Resets the volume to enclose only the volumes indicated.
A thread; that is, a lightweight process.
Definition: thread.h:51
void add_uint32(PN_uint32 value)
Adds an unsigned 32-bit integer to the datagram.
Definition: datagram.I:192
virtual bool safe_to_flatten_below() const
Returns true if a flatten operation may safely continue past this node, or false if nodes below this ...
Definition: pandaNode.cxx:307
Encapsulates the data from a PandaNode, pre-fetched for one stage of the pipeline.
Definition: pandaNode.h:815
bool is_empty() const
Returns true if the state is empty, false otherwise.
void set_int_tag(const string &tag, int value)
Allows the creating object to store a temporary data value on the BamReader.
Definition: bamReader.cxx:789
virtual int get_first_visible_child() const
Returns the index number of the first visible child of this node, or a number &gt;= get_num_children() i...
Definition: pandaNode.cxx:515
virtual int get_unsafe_to_apply_attribs() const
Returns the union of all attributes from SceneGraphReducer::AttribTypes that may not safely be applie...
Definition: pandaNode.cxx:335
void add_int32(PN_int32 value)
Adds a signed 32-bit integer to the datagram.
Definition: datagram.I:159
A class to retrieve the individual data elements previously stored in a Datagram. ...
void clear_effect(TypeHandle type)
Removes the render effect of the given type from this node.
Definition: pandaNode.cxx:1194
void set_prev_transform(const TransformState *transform, Thread *current_thread=Thread::get_current_thread())
Sets the transform that represents this node&#39;s &quot;previous&quot; position, one frame ago, for the purposes of detecting motion for accurate collision calculations.
Definition: pandaNode.cxx:1306
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
Definition: bamReader.I:105
virtual bool is_geom_node() const
A simple downcast check.
Definition: pandaNode.cxx:2486
void consider_update(const TypedWritable *obj)
Should be called from TypedWritable::update_bam_nested() to recursively check the entire hiererachy o...
Definition: bamWriter.cxx:237
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
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:206
virtual PandaNode * dupe_for_flatten() const
This is similar to make_copy(), but it makes a copy for the specific purpose of flatten.
Definition: pandaNode.cxx:222
bool is_under_scene_root() const
Returns true if this particular node is in a live scene graph: that is, it is a child or descendent o...
Definition: pandaNode.cxx:2166
This is a sequence number that increments monotonically.
Definition: updateSeq.h:43
void add_child(PandaNode *child_node, int sort=0, Thread *current_thread=Thread::get_current_thread())
Adds a new child to the node.
Definition: pandaNode.cxx:654
void copy_children(PandaNode *other, Thread *current_thread=Thread::get_current_thread())
Makes another instance of all the children of the other node, copying them to this node...
Definition: pandaNode.cxx:1076
void prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state)
Walks through the scene graph beginning at this node, and does whatever initialization is required to...
Definition: pandaNode.cxx:2130
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
bool is_zero() const
Returns true if the entire bitmask is zero, false otherwise.
Definition: bitMask.I:268
Thread * get_current_thread() const
Returns the Thread pointer of the currently-executing thread, as passed to the constructor of this ob...
This represents a unique collection of RenderEffect objects that correspond to a particular renderabl...
Definition: renderEffects.h:46
void set_transform(const TransformState *transform, Thread *current_thread=Thread::get_current_thread())
Sets the transform that will be applied to this node and below.
Definition: pandaNode.cxx:1267
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
Definition: cullTraverser.h:48
virtual bool safe_to_flatten() const
Returns true if it is generally safe to flatten out this particular kind of PandaNode by duplicating ...
Definition: pandaNode.cxx:237
bool is_scene_root() const
Returns true if this particular node is known to be the render root of some active DisplayRegion asso...
Definition: pandaNode.cxx:2145
void mark_bam_modified()
Increments the bam_modified counter, so that this object will be invalidated and retransmitted on any...
Definition: typedWritable.I:54
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data)
This function will be called during the cull traversal to perform any additional operations that shou...
Definition: pandaNode.cxx:477
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
Definition: bamWriter.cxx:279
int get_pipeline_stage() const
Returns the Pipeline stage number associated with this thread.
Definition: thread.I:84
int count_num_descendants() const
Returns the number of nodes at and below this level.
Definition: pandaNode.cxx:629
void read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:652
This class maintains a linked list of PandaNodes.
This is one component of a NodePath.
static UpdateSeq initial()
Returns an UpdateSeq in the &#39;initial&#39; state.
Definition: updateSeq.I:32
An object specifically designed to transform the vertices of a Geom without disturbing indexing or af...