Panda3D

pandaNode.cxx

00001 // Filename: pandaNode.cxx
00002 // Created by:  drose (20Feb02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "pandaNode.h"
00016 #include "config_pgraph.h"
00017 #include "nodePathComponent.h"
00018 #include "bamReader.h"
00019 #include "bamWriter.h"
00020 #include "indent.h"
00021 #include "geometricBoundingVolume.h"
00022 #include "sceneGraphReducer.h"
00023 #include "accumulatedAttribs.h"
00024 #include "clipPlaneAttrib.h"
00025 #include "boundingSphere.h"
00026 #include "boundingBox.h"
00027 #include "pStatTimer.h"
00028 #include "config_mathutil.h"
00029 #include "lightReMutexHolder.h"
00030 #include "graphicsStateGuardianBase.h"
00031 #include "py_panda.h"
00032 
00033 // This category is just temporary for debugging convenience.
00034 NotifyCategoryDecl(drawmask, EXPCL_PANDA_PGRAPH, EXPTP_PANDA_PGRAPH);
00035 NotifyCategoryDef(drawmask, "");
00036 
00037 TypeHandle PandaNode::BamReaderAuxDataDown::_type_handle;
00038 
00039 PandaNode::SceneRootFunc *PandaNode::_scene_root_func;
00040 
00041 PandaNodeChain PandaNode::_dirty_prev_transforms;
00042 DrawMask PandaNode::_overall_bit = DrawMask::bit(31);
00043 
00044 PStatCollector PandaNode::_reset_prev_pcollector("App:Collisions:Reset");
00045 PStatCollector PandaNode::_update_bounds_pcollector("*:Bounds");
00046 
00047 TypeHandle PandaNode::_type_handle;
00048 TypeHandle PandaNode::CData::_type_handle;
00049 TypeHandle PandaNodePipelineReader::_type_handle;
00050 
00051 //
00052 // There are two different interfaces here for making and breaking
00053 // parent-child connections: the fundamental PandaNode interface, via
00054 // add_child() and remove_child() (and related functions), and the
00055 // NodePath support interface, via attach(), detach(), and reparent().
00056 // They both do essentially the same thing, but with slightly
00057 // different inputs.  The PandaNode interfaces try to guess which
00058 // NodePaths should be updated as a result of the scene graph change,
00059 // while the NodePath interfaces already know.
00060 //
00061 // The NodePath support interface functions are strictly called from
00062 // within the NodePath class, and are used to implement
00063 // NodePath::reparent_to() and NodePath::remove_node(), etc.  The
00064 // fundamental interface, on the other hand, is intended to be called
00065 // directly by the user.
00066 //
00067 // The fundamental interface has a slightly lower overhead because it
00068 // does not need to create a NodePathComponent chain where one does
00069 // not already exist; however, the NodePath support interface is more
00070 // useful when the NodePath already does exist, because it ensures
00071 // that the particular NodePath calling it is kept appropriately
00072 // up-to-date.
00073 //
00074 
00075 
00076 ////////////////////////////////////////////////////////////////////
00077 //     Function: PandaNode::Constructor
00078 //       Access: Published
00079 //  Description:
00080 ////////////////////////////////////////////////////////////////////
00081 PandaNode::
00082 PandaNode(const string &name) :
00083   Namable(name),
00084   _paths_lock("PandaNode::_paths_lock"),
00085   _dirty_prev_transform(false)
00086 {
00087   if (pgraph_cat.is_debug()) {
00088     pgraph_cat.debug()
00089       << "Constructing " << (void *)this << ", " << get_name() << "\n";
00090   }
00091 #ifndef NDEBUG
00092   _unexpected_change_flags = 0;
00093 #endif // !NDEBUG
00094 
00095 #ifdef DO_MEMORY_USAGE
00096   MemoryUsage::update_type(this, this);
00097 #endif
00098 }
00099 
00100 ////////////////////////////////////////////////////////////////////
00101 //     Function: PandaNode::Destructor
00102 //       Access: Published, Virtual
00103 //  Description:
00104 ////////////////////////////////////////////////////////////////////
00105 PandaNode::
00106 ~PandaNode() {
00107   if (pgraph_cat.is_debug()) {
00108     pgraph_cat.debug()
00109       << "Destructing " << (void *)this << ", " << get_name() << "\n";
00110   }
00111   clear_dirty_prev_transform();
00112 
00113   // We shouldn't have any parents left by the time we destruct, or
00114   // there's a refcount fault somewhere.
00115 
00116   // Actually, that's not necessarily true anymore, since we might be
00117   // updating a node dynamically via the bam reader, which doesn't
00118   // necessarily keep related pairs of nodes in sync with each other.
00119   /*
00120 #ifndef NDEBUG
00121   {
00122     CDReader cdata(_cycler);
00123     nassertv(cdata->get_up()->empty());
00124   }
00125 #endif  // NDEBUG
00126   */
00127 
00128   remove_all_children();
00129 }
00130 
00131 ////////////////////////////////////////////////////////////////////
00132 //     Function: PandaNode::Copy Constructor
00133 //       Access: Protected
00134 //  Description: Do not call the copy constructor directly; instead,
00135 //               use make_copy() or copy_subgraph() to make a copy of
00136 //               a node.
00137 ////////////////////////////////////////////////////////////////////
00138 PandaNode::
00139 PandaNode(const PandaNode &copy) :
00140   ReferenceCount(copy),
00141   TypedWritable(copy),
00142   Namable(copy),
00143   _paths_lock("PandaNode::_paths_lock"),
00144   _dirty_prev_transform(false)
00145 {
00146   if (pgraph_cat.is_debug()) {
00147     pgraph_cat.debug()
00148       << "Copying " << (void *)this << ", " << get_name() << "\n";
00149   }
00150 #ifdef DO_MEMORY_USAGE
00151   MemoryUsage::update_type(this, this);
00152 #endif
00153   // Copying a node does not copy its children.
00154 #ifndef NDEBUG
00155   _unexpected_change_flags = 0;
00156 #endif // !NDEBUG
00157 
00158   // Copy the other node's state.
00159   {
00160     CDReader copy_cdata(copy._cycler);
00161     CDWriter cdata(_cycler, true);
00162     cdata->_state = copy_cdata->_state;
00163     cdata->_transform = copy_cdata->_transform;
00164     cdata->_prev_transform = copy_cdata->_prev_transform;
00165     if (cdata->_transform != cdata->_prev_transform) {
00166       set_dirty_prev_transform();
00167     }
00168 
00169     cdata->_effects = copy_cdata->_effects;
00170     cdata->_tag_data = copy_cdata->_tag_data;
00171     cdata->_draw_control_mask = copy_cdata->_draw_control_mask;
00172     cdata->_draw_show_mask = copy_cdata->_draw_show_mask;
00173     cdata->_into_collide_mask = copy_cdata->_into_collide_mask;
00174     cdata->_bounds_type = copy_cdata->_bounds_type;
00175     cdata->_user_bounds = copy_cdata->_user_bounds;
00176     cdata->_internal_bounds = NULL;
00177     cdata->_internal_bounds_computed = UpdateSeq::initial();
00178     cdata->_internal_bounds_mark = UpdateSeq::initial();
00179     ++cdata->_internal_bounds_mark;
00180     cdata->_final_bounds = copy_cdata->_final_bounds;
00181     cdata->_fancy_bits = copy_cdata->_fancy_bits;
00182     
00183 #ifdef HAVE_PYTHON
00184     // Copy and increment all of the Python objects held by the other
00185     // node.
00186     cdata->_python_tag_data = copy_cdata->_python_tag_data;
00187     cdata->inc_py_refs();
00188 #endif  // HAVE_PYTHON
00189   }
00190 }
00191 
00192 ////////////////////////////////////////////////////////////////////
00193 //     Function: PandaNode::Copy Assignment Operator
00194 //       Access: Private
00195 //  Description: Do not call the copy assignment operator at all.  Use
00196 //               make_copy() or copy_subgraph() to make a copy of a
00197 //               node.
00198 ////////////////////////////////////////////////////////////////////
00199 void PandaNode::
00200 operator = (const PandaNode &copy) {
00201   nassertv(false);
00202 }
00203 
00204 ////////////////////////////////////////////////////////////////////
00205 //     Function: PandaNode::as_reference_count
00206 //       Access: Public, Virtual
00207 //  Description: Returns the pointer cast to a ReferenceCount pointer,
00208 //               if it is in fact of that type.
00209 ////////////////////////////////////////////////////////////////////
00210 ReferenceCount *PandaNode::
00211 as_reference_count() {
00212   return this;
00213 }
00214 
00215 ////////////////////////////////////////////////////////////////////
00216 //     Function: PandaNode::dupe_for_flatten
00217 //       Access: Public, Virtual
00218 //  Description: This is similar to make_copy(), but it makes a copy
00219 //               for the specific purpose of flatten.  Typically, this
00220 //               will be a new PandaNode with a new pointer, but all
00221 //               of the internal data will always be shared with the
00222 //               original; whereas the new node returned by
00223 //               make_copy() might not share the internal data.
00224 ////////////////////////////////////////////////////////////////////
00225 PandaNode *PandaNode::
00226 dupe_for_flatten() const {
00227   return make_copy();
00228 }
00229 
00230 ////////////////////////////////////////////////////////////////////
00231 //     Function: PandaNode::safe_to_flatten
00232 //       Access: Public, Virtual
00233 //  Description: Returns true if it is generally safe to flatten out
00234 //               this particular kind of PandaNode by duplicating
00235 //               instances (by calling dupe_for_flatten()), false
00236 //               otherwise (for instance, a Camera cannot be safely
00237 //               flattened, because the Camera pointer itself is
00238 //               meaningful).
00239 ////////////////////////////////////////////////////////////////////
00240 bool PandaNode::
00241 safe_to_flatten() const {
00242   return true;
00243 }
00244 
00245 ////////////////////////////////////////////////////////////////////
00246 //     Function: PandaNode::safe_to_transform
00247 //       Access: Public, Virtual
00248 //  Description: Returns true if it is generally safe to transform
00249 //               this particular kind of PandaNode by calling the
00250 //               xform() method, false otherwise.
00251 ////////////////////////////////////////////////////////////////////
00252 bool PandaNode::
00253 safe_to_transform() const {
00254   return true;
00255 }
00256 
00257 ////////////////////////////////////////////////////////////////////
00258 //     Function: PandaNode::safe_to_modify_transform
00259 //       Access: Public, Virtual
00260 //  Description: Returns true if it is safe to automatically adjust
00261 //               the transform on this kind of node.  Usually, this is
00262 //               only a bad idea if the user expects to find a
00263 //               particular transform on the node.
00264 //
00265 //               ModelNodes with the preserve_transform flag set are
00266 //               presently the only kinds of nodes that should not
00267 //               have their transform even adjusted.
00268 ////////////////////////////////////////////////////////////////////
00269 bool PandaNode::
00270 safe_to_modify_transform() const {
00271   return true;
00272 }
00273 
00274 ////////////////////////////////////////////////////////////////////
00275 //     Function: PandaNode::safe_to_combine
00276 //       Access: Public, Virtual
00277 //  Description: Returns true if it is generally safe to combine this
00278 //               particular kind of PandaNode with other kinds of
00279 //               PandaNodes of compatible type, adding children or
00280 //               whatever.  For instance, an LODNode should not be
00281 //               combined with any other PandaNode, because its set of
00282 //               children is meaningful.
00283 ////////////////////////////////////////////////////////////////////
00284 bool PandaNode::
00285 safe_to_combine() const {
00286   return true;
00287 }
00288 
00289 ////////////////////////////////////////////////////////////////////
00290 //     Function: PandaNode::safe_to_combine_children
00291 //       Access: Public, Virtual
00292 //  Description: Returns true if it is generally safe to combine the
00293 //               children of this PandaNode with each other.  For
00294 //               instance, an LODNode's children should not be
00295 //               combined with each other, because the set of children
00296 //               is meaningful.
00297 ////////////////////////////////////////////////////////////////////
00298 bool PandaNode::
00299 safe_to_combine_children() const {
00300   return true;
00301 }
00302 
00303 ////////////////////////////////////////////////////////////////////
00304 //     Function: PandaNode::safe_to_flatten_below
00305 //       Access: Public, Virtual
00306 //  Description: Returns true if a flatten operation may safely
00307 //               continue past this node, or false if nodes below this
00308 //               node may not be molested.
00309 ////////////////////////////////////////////////////////////////////
00310 bool PandaNode::
00311 safe_to_flatten_below() const {
00312   return true;
00313 }
00314 
00315 ////////////////////////////////////////////////////////////////////
00316 //     Function: PandaNode::preserve_name
00317 //       Access: Public, Virtual
00318 //  Description: Returns true if the node's name has extrinsic meaning
00319 //               and must be preserved across a flatten operation,
00320 //               false otherwise.
00321 ////////////////////////////////////////////////////////////////////
00322 bool PandaNode::
00323 preserve_name() const {
00324   return false;
00325 }
00326 
00327 ////////////////////////////////////////////////////////////////////
00328 //     Function: PandaNode::get_unsafe_to_apply_attribs
00329 //       Access: Public, Virtual
00330 //  Description: Returns the union of all attributes from
00331 //               SceneGraphReducer::AttribTypes that may not safely be
00332 //               applied to the vertices of this node.  If this is
00333 //               nonzero, these attributes must be dropped at this
00334 //               node as a state change.
00335 //
00336 //               This is a generalization of safe_to_transform().
00337 ////////////////////////////////////////////////////////////////////
00338 int PandaNode::
00339 get_unsafe_to_apply_attribs() const {
00340   return 0;
00341 }
00342 
00343 ////////////////////////////////////////////////////////////////////
00344 //     Function: PandaNode::apply_attribs_to_vertices
00345 //       Access: Public, Virtual
00346 //  Description: Applies whatever attributes are specified in the
00347 //               AccumulatedAttribs object (and by the attrib_types
00348 //               bitmask) to the vertices on this node, if
00349 //               appropriate.  If this node uses geom arrays like a
00350 //               GeomNode, the supplied GeomTransformer may be used to
00351 //               unify shared arrays across multiple different nodes.
00352 //
00353 //               This is a generalization of xform().
00354 ////////////////////////////////////////////////////////////////////
00355 void PandaNode::
00356 apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
00357                           GeomTransformer &transformer) {
00358   if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
00359     const LMatrix4f &mat = attribs._transform->get_mat();
00360     xform(mat);
00361 
00362     Thread *current_thread = Thread::get_current_thread();
00363     OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00364       CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00365       cdata->_effects = cdata->_effects->xform(mat);
00366       cdata->set_fancy_bit(FB_effects, !cdata->_effects->is_empty());
00367     }
00368     CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00369   }
00370   mark_bam_modified();
00371 }
00372 
00373 ////////////////////////////////////////////////////////////////////
00374 //     Function: PandaNode::xform
00375 //       Access: Public, Virtual
00376 //  Description: Transforms the contents of this PandaNode by the
00377 //               indicated matrix, if it means anything to do so.  For
00378 //               most kinds of PandaNodes, this does nothing.
00379 ////////////////////////////////////////////////////////////////////
00380 void PandaNode::
00381 xform(const LMatrix4f &) {
00382 }
00383 
00384 ////////////////////////////////////////////////////////////////////
00385 //     Function: PandaNode::combine_with
00386 //       Access: Public, Virtual
00387 //  Description: Collapses this PandaNode with the other PandaNode, if
00388 //               possible, and returns a pointer to the combined
00389 //               PandaNode, or NULL if the two PandaNodes cannot
00390 //               safely be combined.
00391 //
00392 //               The return value may be this, other, or a new
00393 //               PandaNode altogether.
00394 //
00395 //               This function is called from GraphReducer::flatten(),
00396 //               and need not deal with children; its job is just to
00397 //               decide whether to collapse the two PandaNodes and
00398 //               what the collapsed PandaNode should look like.
00399 ////////////////////////////////////////////////////////////////////
00400 PandaNode *PandaNode::
00401 combine_with(PandaNode *other) {
00402   // An unadorned PandaNode always combines with any other PandaNodes by
00403   // yielding completely.  However, if we are actually some fancy PandaNode
00404   // type that derives from PandaNode but didn't redefine this function, we
00405   // should refuse to combine.
00406   if (is_exact_type(get_class_type())) {
00407     // No, we're an ordinary PandaNode.
00408     return other;
00409 
00410   } else if (other->is_exact_type(get_class_type())) {
00411     // We're not an ordinary PandaNode, but the other one is.
00412     return this;
00413   }
00414 
00415   // We're something other than an ordinary PandaNode.  Don't combine.
00416   return (PandaNode *)NULL;
00417 }
00418 
00419 ////////////////////////////////////////////////////////////////////
00420 //     Function: PandaNode::calc_tight_bounds
00421 //       Access: Public, Virtual
00422 //  Description: This is used to support
00423 //               NodePath::calc_tight_bounds().  It is not intended to
00424 //               be called directly, and it has nothing to do with the
00425 //               normal Panda bounding-volume computation.
00426 //
00427 //               If the node contains any geometry, this updates
00428 //               min_point and max_point to enclose its bounding box.
00429 //               found_any is to be set true if the node has any
00430 //               geometry at all, or left alone if it has none.  This
00431 //               method may be called over several nodes, so it may
00432 //               enter with min_point, max_point, and found_any
00433 //               already set.
00434 //
00435 //               This function is recursive, and the return value is
00436 //               the transform after it has been modified by this
00437 //               node's transform.
00438 ////////////////////////////////////////////////////////////////////
00439 CPT(TransformState) PandaNode::
00440 calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any,
00441                   const TransformState *transform, Thread *current_thread) const {
00442   CPT(TransformState) next_transform = transform->compose(get_transform());
00443 
00444   Children cr = get_children(current_thread);
00445   int num_children = cr.get_num_children();
00446   for (int i = 0; i < num_children; i++) {
00447     cr.get_child(i)->calc_tight_bounds(min_point, max_point,
00448                                        found_any, next_transform,
00449                                        current_thread);
00450   }
00451 
00452   return next_transform;
00453 }
00454 
00455 ////////////////////////////////////////////////////////////////////
00456 //     Function: PandaNode::cull_callback
00457 //       Access: Public, Virtual
00458 //  Description: This function will be called during the cull
00459 //               traversal to perform any additional operations that
00460 //               should be performed at cull time.  This may include
00461 //               additional manipulation of render state or additional
00462 //               visible/invisible decisions, or any other arbitrary
00463 //               operation.
00464 //
00465 //               Note that this function will *not* be called unless
00466 //               set_cull_callback() is called in the constructor of
00467 //               the derived class.  It is necessary to call
00468 //               set_cull_callback() to indicated that we require
00469 //               cull_callback() to be called.
00470 //
00471 //               By the time this function is called, the node has
00472 //               already passed the bounding-volume test for the
00473 //               viewing frustum, and the node's transform and state
00474 //               have already been applied to the indicated
00475 //               CullTraverserData object.
00476 //
00477 //               The return value is true if this node should be
00478 //               visible, or false if it should be culled.
00479 ////////////////////////////////////////////////////////////////////
00480 bool PandaNode::
00481 cull_callback(CullTraverser *, CullTraverserData &) {
00482   return true;
00483 }
00484 
00485 ////////////////////////////////////////////////////////////////////
00486 //     Function: PandaNode::has_selective_visibility
00487 //       Access: Public, Virtual
00488 //  Description: Should be overridden by derived classes to return
00489 //               true if this kind of node has some restrictions on
00490 //               the set of children that should be rendered.  Node
00491 //               with this property include LODNodes, SwitchNodes, and
00492 //               SequenceNodes.
00493 //
00494 //               If this function returns true,
00495 //               get_first_visible_child() and
00496 //               get_next_visible_child() will be called to walk
00497 //               through the list of children during cull, instead of
00498 //               iterating through the entire list.  This method is
00499 //               called after cull_callback(), so cull_callback() may
00500 //               be responsible for the decisions as to which children
00501 //               are visible at the moment.
00502 ////////////////////////////////////////////////////////////////////
00503 bool PandaNode::
00504 has_selective_visibility() const {
00505   return false;
00506 }
00507 
00508 ////////////////////////////////////////////////////////////////////
00509 //     Function: PandaNode::get_first_visible_child
00510 //       Access: Public, Virtual
00511 //  Description: Returns the index number of the first visible child
00512 //               of this node, or a number >= get_num_children() if
00513 //               there are no visible children of this node.  This is
00514 //               called during the cull traversal, but only if
00515 //               has_selective_visibility() has already returned true.
00516 //               See has_selective_visibility().
00517 ////////////////////////////////////////////////////////////////////
00518 int PandaNode::
00519 get_first_visible_child() const {
00520   return 0;
00521 }
00522 
00523 ////////////////////////////////////////////////////////////////////
00524 //     Function: PandaNode::get_next_visible_child
00525 //       Access: Public, Virtual
00526 //  Description: Returns the index number of the next visible child
00527 //               of this node following the indicated child, or a
00528 //               number >= get_num_children() if there are no more
00529 //               visible children of this node.  See
00530 //               has_selective_visibility() and
00531 //               get_first_visible_child().
00532 ////////////////////////////////////////////////////////////////////
00533 int PandaNode::
00534 get_next_visible_child(int n) const {
00535   return n + 1;
00536 }
00537 
00538 ////////////////////////////////////////////////////////////////////
00539 //     Function: PandaNode::has_single_child_visibility
00540 //       Access: Public, Virtual
00541 //  Description: Should be overridden by derived classes to return
00542 //               true if this kind of node has the special property
00543 //               that just one of its children is visible at any given
00544 //               time, and furthermore that the particular visible
00545 //               child can be determined without reference to any
00546 //               external information (such as a camera).  At present,
00547 //               only SequenceNodes and SwitchNodes fall into this
00548 //               category.
00549 //
00550 //               If this function returns true, get_visible_child()
00551 //               can be called to return the index of the
00552 //               currently-visible child.
00553 ////////////////////////////////////////////////////////////////////
00554 bool PandaNode::
00555 has_single_child_visibility() const {
00556   return false;
00557 }
00558 
00559 ////////////////////////////////////////////////////////////////////
00560 //     Function: PandaNode::get_visible_child
00561 //       Access: Public, Virtual
00562 //  Description: Returns the index number of the currently visible
00563 //               child of this node.  This is only meaningful if
00564 //               has_single_child_visibility() has returned true.
00565 ////////////////////////////////////////////////////////////////////
00566 int PandaNode::
00567 get_visible_child() const {
00568   return 0;
00569 }
00570 
00571 ////////////////////////////////////////////////////////////////////
00572 //     Function: PandaNode::is_renderable
00573 //       Access: Public, Virtual
00574 //  Description: Returns true if there is some value to visiting this
00575 //               particular node during the cull traversal for any
00576 //               camera, false otherwise.  This will be used to
00577 //               optimize the result of get_net_draw_show_mask(), so
00578 //               that any subtrees that contain only nodes for which
00579 //               is_renderable() is false need not be visited.
00580 ////////////////////////////////////////////////////////////////////
00581 bool PandaNode::
00582 is_renderable() const {
00583   return false;
00584 }
00585 
00586 ////////////////////////////////////////////////////////////////////
00587 //     Function: PandaNode::add_for_draw
00588 //       Access: Public, Virtual
00589 //  Description: Adds the node's contents to the CullResult we are
00590 //               building up during the cull traversal, so that it
00591 //               will be drawn at render time.  For most nodes other
00592 //               than GeomNodes, this is a do-nothing operation.
00593 ////////////////////////////////////////////////////////////////////
00594 void PandaNode::
00595 add_for_draw(CullTraverser *, CullTraverserData &) {
00596 }
00597 
00598 ////////////////////////////////////////////////////////////////////
00599 //     Function: PandaNode::make_copy
00600 //       Access: Published, Virtual
00601 //  Description: Returns a newly-allocated PandaNode that is a shallow
00602 //               copy of this one.  It will be a different pointer,
00603 //               but its internal data may or may not be shared with
00604 //               that of the original PandaNode.  No children will be
00605 //               copied.
00606 ////////////////////////////////////////////////////////////////////
00607 PandaNode *PandaNode::
00608 make_copy() const {
00609   return new PandaNode(*this);
00610 }
00611 
00612 ////////////////////////////////////////////////////////////////////
00613 //     Function: PandaNode::copy_subgraph
00614 //       Access: Published
00615 //  Description: Allocates and returns a complete copy of this
00616 //               PandaNode and the entire scene graph rooted at this
00617 //               PandaNode.  Some data may still be shared from the
00618 //               original (e.g. vertex index tables), but nothing that
00619 //               will impede normal use of the PandaNode.
00620 ////////////////////////////////////////////////////////////////////
00621 PT(PandaNode) PandaNode::
00622 copy_subgraph(Thread *current_thread) const {
00623   InstanceMap inst_map;
00624   return r_copy_subgraph(inst_map, current_thread);
00625 }
00626 
00627 #ifdef HAVE_PYTHON
00628 ////////////////////////////////////////////////////////////////////
00629 //     Function: PandaNode::__copy__
00630 //       Access: Published
00631 //  Description: A special Python method that is invoked by
00632 //               copy.copy(node).  Unlike the PandaNode copy
00633 //               constructor, which creates a new node without
00634 //               children, this shares child pointers (essentially
00635 //               making every child an instance).  This is intended to
00636 //               simulate the behavior of copy.copy() for other
00637 //               objects.
00638 ////////////////////////////////////////////////////////////////////
00639 PT(PandaNode) PandaNode::
00640 __copy__() const {
00641   Thread *current_thread = Thread::get_current_thread();
00642 
00643   PT(PandaNode) node_dupe = make_copy();
00644 
00645   Children children = get_children(current_thread);
00646   int num_children = children.get_num_children();
00647 
00648   for (int i = 0; i < num_children; ++i) {
00649     PandaNode *child = children.get_child(i);
00650     node_dupe->add_child(children.get_child(i), children.get_child_sort(i));
00651   }
00652 
00653   return node_dupe;
00654 }
00655 #endif  // HAVE_PYTHON
00656 
00657 #ifdef HAVE_PYTHON
00658 ////////////////////////////////////////////////////////////////////
00659 //     Function: PandaNode::__deepcopy__
00660 //       Access: Published
00661 //  Description: A special Python method that is invoked by
00662 //               copy.deepcopy(node).  This calls copy_subgraph()
00663 //               unless the node is already present in the provided
00664 //               dictionary.
00665 ////////////////////////////////////////////////////////////////////
00666 PyObject *PandaNode::
00667 __deepcopy__(PyObject *self, PyObject *memo) const {
00668   IMPORT_THIS struct Dtool_PyTypedObject Dtool_PandaNode;
00669 
00670   // Borrowed reference.
00671   PyObject *dupe = PyDict_GetItem(memo, self);
00672   if (dupe != NULL) {
00673     // Already in the memo dictionary.
00674     Py_INCREF(dupe);
00675     return dupe;
00676   }
00677 
00678   PT(PandaNode) node_dupe = copy_subgraph();
00679 
00680   // DTool_CreatePyInstanceTyped() steals a C++ reference.
00681   node_dupe->ref();
00682   dupe = DTool_CreatePyInstanceTyped
00683     ((void *)node_dupe.p(), Dtool_PandaNode, true, false, 
00684      node_dupe->get_type_index());
00685 
00686   if (PyDict_SetItem(memo, self, dupe) != 0) {
00687     Py_DECREF(dupe);
00688     return NULL;
00689   }
00690 
00691   return dupe;
00692 }
00693 #endif  // HAVE_PYTHON
00694 
00695 ////////////////////////////////////////////////////////////////////
00696 //     Function: PandaNode::count_num_descendants
00697 //       Access: Published
00698 //  Description: Returns the number of nodes at and below this level.
00699 ////////////////////////////////////////////////////////////////////
00700 int PandaNode::
00701 count_num_descendants() const {
00702   int count = 1;
00703   Children children = get_children();
00704   int num_children = children.get_num_children();
00705 
00706   for (int i = 0; i < num_children; ++i) {
00707     PandaNode *child = children.get_child(i);
00708     count += child->count_num_descendants();
00709   }
00710 
00711   return count;
00712 }
00713 
00714 ////////////////////////////////////////////////////////////////////
00715 //     Function: PandaNode::add_child
00716 //       Access: Published
00717 //  Description: Adds a new child to the node.  The child is added in
00718 //               the relative position indicated by sort; if all
00719 //               children have the same sort index, the child is added
00720 //               at the end.
00721 //
00722 //               If the same child is added to a node more than once,
00723 //               the previous instance is first removed.
00724 ////////////////////////////////////////////////////////////////////
00725 void PandaNode::
00726 add_child(PandaNode *child_node, int sort, Thread *current_thread) {
00727   nassertv(child_node != (PandaNode *)NULL);
00728 
00729   if (!verify_child_no_cycles(child_node)) {
00730     // Whoops, adding this child node would introduce a cycle in the
00731     // scene graph.
00732     return;
00733   }
00734 
00735   // Ensure the child_node is not deleted while we do this.
00736   PT(PandaNode) keep_child = child_node;
00737   remove_child(child_node);
00738 
00739   // Apply this operation to the current stage as well as to all
00740   // upstream stages.
00741   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00742     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00743     CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
00744     
00745     cdata->modify_down()->insert(DownConnection(child_node, sort));
00746     cdata_child->modify_up()->insert(UpConnection(this));
00747   }
00748   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00749 
00750   OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
00751     new_connection(this, child_node, pipeline_stage, current_thread);
00752   }
00753   CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
00754 
00755   force_bounds_stale();
00756 
00757   children_changed();
00758   child_node->parents_changed();
00759   mark_bam_modified();
00760   child_node->mark_bam_modified();
00761 }
00762 
00763 ////////////////////////////////////////////////////////////////////
00764 //     Function: PandaNode::remove_child
00765 //       Access: Published
00766 //  Description: Removes the nth child from the node.
00767 ////////////////////////////////////////////////////////////////////
00768 void PandaNode::
00769 remove_child(int child_index, Thread *current_thread) {
00770   int pipeline_stage = current_thread->get_pipeline_stage();
00771   nassertv(pipeline_stage == 0);
00772 
00773   CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00774   PT(Down) down = cdata->modify_down();
00775   nassertv(child_index >= 0 && child_index < (int)down->size());
00776   
00777   PT(PandaNode) child_node = (*down)[child_index].get_child();
00778   CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, 
00779                                  current_thread);
00780   PT(Up) up = cdata_child->modify_up();
00781 
00782   down->erase(down->begin() + child_index);
00783   int num_erased = up->erase(UpConnection(this));
00784   nassertv(num_erased == 1);
00785 
00786   sever_connection(this, child_node, pipeline_stage, current_thread);
00787   force_bounds_stale(pipeline_stage, current_thread);
00788 
00789   children_changed();
00790   child_node->parents_changed();
00791   mark_bam_modified();
00792   child_node->mark_bam_modified();
00793 }
00794 
00795 ////////////////////////////////////////////////////////////////////
00796 //     Function: PandaNode::remove_child
00797 //       Access: Published
00798 //  Description: Removes the indicated child from the node.  Returns
00799 //               true if the child was removed, false if it was not
00800 //               already a child of the node.  This will also
00801 //               successfully remove the child if it had been stashed.
00802 ////////////////////////////////////////////////////////////////////
00803 bool PandaNode::
00804 remove_child(PandaNode *child_node, Thread *current_thread) {
00805   nassertr(child_node != (PandaNode *)NULL, false);
00806   
00807   // Make sure the child node is not destructed during the execution
00808   // of this method.
00809   PT(PandaNode) keep_child = child_node;
00810 
00811   // We have to do this for each upstream pipeline stage.
00812   bool any_removed = false;
00813 
00814   OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
00815     if (stage_remove_child(child_node, pipeline_stage, current_thread)) {
00816       any_removed = true;
00817 
00818       sever_connection(this, child_node, pipeline_stage, current_thread);
00819       force_bounds_stale(pipeline_stage, current_thread);
00820     }
00821   }
00822   CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
00823 
00824   if (any_removed) {
00825     // Call callback hooks.
00826     children_changed();
00827     child_node->parents_changed();
00828   }
00829 
00830   return any_removed;
00831 }
00832 
00833 ////////////////////////////////////////////////////////////////////
00834 //     Function: PandaNode::replace_child
00835 //       Access: Published
00836 //  Description: Searches for the orig_child node in the node's list
00837 //               of children, and replaces it with the new_child
00838 //               instead.  Returns true if the replacement is made, or
00839 //               false if the node is not a child or if there is some
00840 //               other problem.
00841 ////////////////////////////////////////////////////////////////////
00842 bool PandaNode::
00843 replace_child(PandaNode *orig_child, PandaNode *new_child,
00844               Thread *current_thread) {
00845   nassertr(orig_child != (PandaNode *)NULL, false);
00846   nassertr(new_child != (PandaNode *)NULL, false);
00847 
00848   if (orig_child == new_child) {
00849     // Trivial no-op.
00850     return true;
00851   }
00852 
00853   if (!verify_child_no_cycles(new_child)) {
00854     // Whoops, adding this child node would introduce a cycle in the
00855     // scene graph.
00856     return false;
00857   }
00858   
00859   // Make sure the orig_child node is not destructed during the
00860   // execution of this method.
00861   PT(PandaNode) keep_orig_child = orig_child;
00862 
00863   // We have to do this for each upstream pipeline stage.
00864   bool any_replaced = false;
00865 
00866   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00867     if (stage_replace_child(orig_child, new_child, pipeline_stage, current_thread)) {
00868       any_replaced = true;
00869     }
00870   }
00871   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00872 
00873   if (any_replaced) {
00874     children_changed();
00875     orig_child->parents_changed();
00876     new_child->parents_changed();
00877   }
00878 
00879   return any_replaced;
00880 }
00881 
00882 
00883 ////////////////////////////////////////////////////////////////////
00884 //     Function: PandaNode::stash_child
00885 //       Access: Published
00886 //  Description: Stashes the indicated child node.  This removes the
00887 //               child from the list of active children and puts it on
00888 //               a special list of stashed children.  This child node
00889 //               no longer contributes to the bounding volume of the
00890 //               PandaNode, and is not visited in normal traversals.
00891 //               It is invisible and uncollidable.  The child may
00892 //               later be restored by calling unstash_child().
00893 //
00894 //               This can only be called from the top pipeline stage
00895 //               (i.e. from App).
00896 ////////////////////////////////////////////////////////////////////
00897 void PandaNode::
00898 stash_child(int child_index, Thread *current_thread) {
00899   int pipeline_stage = current_thread->get_pipeline_stage();
00900   nassertv(pipeline_stage == 0);
00901   nassertv(child_index >= 0 && child_index < get_num_children());
00902 
00903   // Save a reference count for ourselves.
00904   PT(PandaNode) self = this;
00905 
00906   PT(PandaNode) child_node = get_child(child_index);
00907   int sort = get_child_sort(child_index);
00908   
00909   remove_child(child_index);
00910 
00911   {
00912     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00913     CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
00914     
00915     cdata->modify_stashed()->insert(DownConnection(child_node, sort));
00916     cdata_child->modify_up()->insert(UpConnection(this));
00917   }
00918 
00919   new_connection(this, child_node, pipeline_stage, current_thread);
00920   force_bounds_stale(pipeline_stage, current_thread);
00921 
00922   children_changed();
00923   child_node->parents_changed();
00924   mark_bam_modified();
00925   child_node->mark_bam_modified();
00926 }
00927 
00928 ////////////////////////////////////////////////////////////////////
00929 //     Function: PandaNode::unstash_child
00930 //       Access: Published
00931 //  Description: Returns the indicated stashed node to normal child
00932 //               status.  This removes the child from the list of
00933 //               stashed children and puts it on the normal list of
00934 //               active children.  This child node once again
00935 //               contributes to the bounding volume of the PandaNode,
00936 //               and will be visited in normal traversals.  It is
00937 //               visible and collidable.
00938 //
00939 //               This can only be called from the top pipeline stage
00940 //               (i.e. from App).
00941 ////////////////////////////////////////////////////////////////////
00942 void PandaNode::
00943 unstash_child(int stashed_index, Thread *current_thread) { 
00944   int pipeline_stage = current_thread->get_pipeline_stage();
00945   nassertv(pipeline_stage == 0);
00946   nassertv(stashed_index >= 0 && stashed_index < get_num_stashed());
00947 
00948   // Save a reference count for ourselves.  I don't think this should
00949   // be necessary, but there are occasional crashes in stash() during
00950   // furniture moving mode.  Perhaps this will eliminate those
00951   // crashes.
00952   PT(PandaNode) self = this;
00953 
00954   PT(PandaNode) child_node = get_stashed(stashed_index);
00955   int sort = get_stashed_sort(stashed_index);
00956   
00957   remove_stashed(stashed_index);
00958   
00959   {
00960     CDWriter cdata(_cycler);
00961     CDWriter cdata_child(child_node->_cycler);
00962 
00963     cdata->modify_down()->insert(DownConnection(child_node, sort));
00964     cdata_child->modify_up()->insert(UpConnection(this));
00965   }
00966 
00967   new_connection(this, child_node, pipeline_stage, current_thread);
00968 
00969   force_bounds_stale();
00970   children_changed();
00971   child_node->parents_changed();
00972   mark_bam_modified();
00973   child_node->mark_bam_modified();
00974 }
00975 
00976 ////////////////////////////////////////////////////////////////////
00977 //     Function: PandaNode::add_stashed
00978 //       Access: Published
00979 //  Description: Adds a new child to the node, directly as a stashed
00980 //               child.  The child is not added in the normal sense,
00981 //               but will be revealed if unstash_child() is called on
00982 //               it later.
00983 //
00984 //               If the same child is added to a node more than once,
00985 //               the previous instance is first removed.
00986 //
00987 //               This can only be called from the top pipeline stage
00988 //               (i.e. from App).
00989 ////////////////////////////////////////////////////////////////////
00990 void PandaNode::
00991 add_stashed(PandaNode *child_node, int sort, Thread *current_thread) {
00992   int pipeline_stage = current_thread->get_pipeline_stage();
00993   nassertv(pipeline_stage == 0);
00994 
00995   if (!verify_child_no_cycles(child_node)) {
00996     // Whoops, adding this child node would introduce a cycle in the
00997     // scene graph.
00998     return;
00999   }
01000 
01001   // Ensure the child_node is not deleted while we do this.
01002   PT(PandaNode) keep_child = child_node;
01003   remove_child(child_node);
01004 
01005   {
01006     CDWriter cdata(_cycler);
01007     CDWriter cdata_child(child_node->_cycler);
01008     
01009     cdata->modify_stashed()->insert(DownConnection(child_node, sort));
01010     cdata_child->modify_up()->insert(UpConnection(this));
01011   }
01012     
01013   new_connection(this, child_node, pipeline_stage, current_thread);
01014 
01015   // Call callback hooks.
01016   children_changed();
01017   child_node->parents_changed();
01018   mark_bam_modified();
01019   child_node->mark_bam_modified();
01020 }
01021 
01022 ////////////////////////////////////////////////////////////////////
01023 //     Function: PandaNode::remove_stashed
01024 //       Access: Published
01025 //  Description: Removes the nth stashed child from the node.
01026 ////////////////////////////////////////////////////////////////////
01027 void PandaNode::
01028 remove_stashed(int child_index, Thread *current_thread) {
01029   int pipeline_stage = current_thread->get_pipeline_stage();
01030   nassertv(pipeline_stage == 0);
01031 
01032   CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01033   Down &stashed = *cdata->modify_stashed();
01034   nassertv(child_index >= 0 && child_index < (int)stashed.size());
01035   
01036   PT(PandaNode) child_node = stashed[child_index].get_child();
01037   CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
01038 
01039   stashed.erase(stashed.begin() + child_index);
01040   int num_erased = cdata_child->modify_up()->erase(UpConnection(this));
01041   nassertv(num_erased == 1);
01042 
01043   sever_connection(this, child_node, pipeline_stage, current_thread);
01044   force_bounds_stale(pipeline_stage, current_thread);
01045 
01046   children_changed();
01047   child_node->parents_changed();
01048   mark_bam_modified();
01049   child_node->mark_bam_modified();
01050 }
01051 
01052 ////////////////////////////////////////////////////////////////////
01053 //     Function: PandaNode::remove_all_children
01054 //       Access: Published
01055 //  Description: Removes all the children from the node at once,
01056 //               including stashed children.
01057 //
01058 //               This can only be called from the top pipeline stage
01059 //               (i.e. from App).
01060 ////////////////////////////////////////////////////////////////////
01061 void PandaNode::
01062 remove_all_children(Thread *current_thread) {
01063   // We have to do this for each upstream pipeline stage.
01064   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01065     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01066     PT(Down) down = cdata->modify_down();
01067     Down::iterator di;
01068     for (di = down->begin(); di != down->end(); ++di) {
01069       PT(PandaNode) child_node = (*di).get_child();
01070       CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
01071                                      current_thread);
01072       cdata_child->modify_up()->erase(UpConnection(this));
01073       
01074       sever_connection(this, child_node, pipeline_stage, current_thread);
01075       child_node->parents_changed();
01076       child_node->mark_bam_modified();
01077     }
01078     down->clear();
01079     
01080     Down &stashed = *cdata->modify_stashed();
01081     for (di = stashed.begin(); di != stashed.end(); ++di) {
01082       PT(PandaNode) child_node = (*di).get_child();
01083       CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
01084                                      current_thread);
01085       cdata_child->modify_up()->erase(UpConnection(this));
01086       
01087       sever_connection(this, child_node, pipeline_stage, current_thread);
01088       child_node->parents_changed();
01089       child_node->mark_bam_modified();
01090     }
01091     stashed.clear();
01092   }
01093   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01094 
01095   force_bounds_stale();
01096   children_changed();
01097   mark_bam_modified();
01098 }
01099 
01100 ////////////////////////////////////////////////////////////////////
01101 //     Function: PandaNode::steal_children
01102 //       Access: Published
01103 //  Description: Moves all the children from the other node onto this
01104 //               node.
01105 //
01106 //               Any NodePaths to child nodes of the other node are
01107 //               truncated, rather than moved to the new parent.
01108 ////////////////////////////////////////////////////////////////////
01109 void PandaNode::
01110 steal_children(PandaNode *other, Thread *current_thread) {
01111   if (other == this) {
01112     // Trivial.
01113     return;
01114   }
01115 
01116   // We do this through the high-level interface for convenience.
01117   // This could begin to be a problem if we have a node with hundreds
01118   // of children to copy; this could break down the ov_set.insert()
01119   // method, which is an O(n^2) operation.  If this happens, we should
01120   // rewrite this to do a simpler add_child() operation that involves
01121   // push_back() instead of insert(), and then sort the down list at
01122   // the end.
01123 
01124   int num_children = other->get_num_children();
01125   int i;
01126   for (i = 0; i < num_children; i++) {
01127     PandaNode *child_node = other->get_child(i);
01128     int sort = other->get_child_sort(i);
01129     add_child(child_node, sort, current_thread);
01130   }
01131   int num_stashed = other->get_num_stashed();
01132   for (i = 0; i < num_stashed; i++) {
01133     PandaNode *child_node = other->get_stashed(i);
01134     int sort = other->get_stashed_sort(i);
01135     add_stashed(child_node, sort, current_thread);
01136   }
01137 
01138   other->remove_all_children(current_thread);
01139 }
01140 
01141 ////////////////////////////////////////////////////////////////////
01142 //     Function: PandaNode::copy_children
01143 //       Access: Published
01144 //  Description: Makes another instance of all the children of the
01145 //               other node, copying them to this node.
01146 ////////////////////////////////////////////////////////////////////
01147 void PandaNode::
01148 copy_children(PandaNode *other, Thread *current_thread) {
01149   if (other == this) {
01150     // Trivial.
01151     return;
01152   }
01153   Children children = other->get_children(current_thread);
01154   Stashed stashed = other->get_stashed(current_thread);
01155   int num_children = children.get_num_children();
01156   int i;
01157   for (i = 0; i < num_children; i++) {
01158     PandaNode *child_node = children.get_child(i);
01159     int sort = children.get_child_sort(i);
01160     add_child(child_node, sort, current_thread);
01161   }
01162   int num_stashed = stashed.get_num_stashed();
01163   for (i = 0; i < num_stashed; i++) {
01164     PandaNode *child_node = stashed.get_stashed(i);
01165     int sort = stashed.get_stashed_sort(i);
01166     add_stashed(child_node, sort, current_thread);
01167   }
01168 }
01169 
01170 ////////////////////////////////////////////////////////////////////
01171 //     Function: PandaNode::set_attrib
01172 //       Access: Published
01173 //  Description: Adds the indicated render attribute to the scene
01174 //               graph on this node.  This attribute will now apply to
01175 //               this node and everything below.  If there was already
01176 //               an attribute of the same type, it is replaced.
01177 ////////////////////////////////////////////////////////////////////
01178 void PandaNode::
01179 set_attrib(const RenderAttrib *attrib, int override) {
01180   // Apply this operation to the current stage as well as to all
01181   // upstream stages.
01182   bool any_changed = false;
01183   Thread *current_thread = Thread::get_current_thread();
01184   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01185     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01186     
01187     CPT(RenderState) new_state = cdata->_state->set_attrib(attrib, override);
01188     if (cdata->_state != new_state) {
01189       cdata->_state = new_state;
01190       cdata->set_fancy_bit(FB_state, true);
01191       any_changed = true;
01192     }
01193   }
01194   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01195 
01196   // Maybe we changed a ClipPlaneAttrib.
01197   if (any_changed) {
01198     mark_bounds_stale(current_thread);
01199     state_changed();
01200     mark_bam_modified();
01201   }
01202 }
01203 
01204 ////////////////////////////////////////////////////////////////////
01205 //     Function: PandaNode::clear_attrib
01206 //       Access: Published
01207 //  Description: Removes the render attribute of the given type from
01208 //               this node.  This node, and the subgraph below, will
01209 //               now inherit the indicated render attribute from the
01210 //               nodes above this one.
01211 ////////////////////////////////////////////////////////////////////
01212 void PandaNode::
01213 clear_attrib(int slot) {
01214   bool any_changed = false;
01215 
01216   Thread *current_thread = Thread::get_current_thread();
01217   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01218     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01219     
01220     CPT(RenderState) new_state = cdata->_state->remove_attrib(slot);
01221     if (cdata->_state != new_state) {
01222       cdata->_state = new_state;
01223       cdata->set_fancy_bit(FB_state, !new_state->is_empty());
01224       any_changed = true;
01225     }
01226   }
01227   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01228 
01229   // We mark the bounds stale when the state changes, in case
01230   // we have changed a ClipPlaneAttrib.
01231   if (any_changed) {
01232     mark_bounds_stale(current_thread);
01233     state_changed();
01234     mark_bam_modified();
01235   }
01236 }
01237 
01238 ////////////////////////////////////////////////////////////////////
01239 //     Function: PandaNode::set_effect
01240 //       Access: Published
01241 //  Description: Adds the indicated render effect to the scene
01242 //               graph on this node.  If there was already an effect
01243 //               of the same type, it is replaced.
01244 ////////////////////////////////////////////////////////////////////
01245 void PandaNode::
01246 set_effect(const RenderEffect *effect) {
01247   // Apply this operation to the current stage as well as to all
01248   // upstream stages.
01249   Thread *current_thread = Thread::get_current_thread();
01250   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01251     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01252     cdata->_effects = cdata->_effects->add_effect(effect);
01253     cdata->set_fancy_bit(FB_effects, true);
01254   }
01255   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01256   mark_bam_modified();
01257 }
01258 
01259 ////////////////////////////////////////////////////////////////////
01260 //     Function: PandaNode::clear_effect
01261 //       Access: Published
01262 //  Description: Removes the render effect of the given type from
01263 //               this node.
01264 ////////////////////////////////////////////////////////////////////
01265 void PandaNode::
01266 clear_effect(TypeHandle type) {
01267   Thread *current_thread = Thread::get_current_thread();
01268   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01269     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01270     cdata->_effects = cdata->_effects->remove_effect(type);
01271     cdata->set_fancy_bit(FB_effects, !cdata->_effects->is_empty());
01272   }
01273   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01274   mark_bam_modified();
01275 }
01276 
01277 ////////////////////////////////////////////////////////////////////
01278 //     Function: PandaNode::set_state
01279 //       Access: Published
01280 //  Description: Sets the complete RenderState that will be applied to
01281 //               all nodes at this level and below.  (The actual state
01282 //               that will be applied to lower nodes is based on the
01283 //               composition of RenderStates from above this node as
01284 //               well).  This completely replaces whatever has been
01285 //               set on this node via repeated calls to set_attrib().
01286 ////////////////////////////////////////////////////////////////////
01287 void PandaNode::
01288 set_state(const RenderState *state, Thread *current_thread) {
01289   // Apply this operation to the current stage as well as to all
01290   // upstream stages.
01291   bool any_changed = false;
01292   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01293     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01294     if (cdata->_state != state) {
01295       cdata->_state = state;
01296       cdata->set_fancy_bit(FB_state, !state->is_empty());
01297       any_changed = true;
01298     }
01299   }
01300   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01301 
01302   // Maybe we have changed a ClipPlaneAttrib.
01303   if (any_changed) {
01304     mark_bounds_stale(current_thread);
01305     state_changed();
01306     mark_bam_modified();
01307   }
01308 }
01309 
01310 ////////////////////////////////////////////////////////////////////
01311 //     Function: PandaNode::set_effects
01312 //       Access: Published
01313 //  Description: Sets the complete RenderEffects that will be applied
01314 //               this node.  This completely replaces whatever has
01315 //               been set on this node via repeated calls to
01316 //               set_attrib().
01317 ////////////////////////////////////////////////////////////////////
01318 void PandaNode::
01319 set_effects(const RenderEffects *effects, Thread *current_thread) {
01320   // Apply this operation to the current stage as well as to all
01321   // upstream stages.
01322   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01323     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01324     cdata->_effects = effects;
01325     cdata->set_fancy_bit(FB_effects, !effects->is_empty());
01326   }
01327   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01328   mark_bam_modified();
01329 }
01330 
01331 ////////////////////////////////////////////////////////////////////
01332 //     Function: PandaNode::set_transform
01333 //       Access: Published
01334 //  Description: Sets the transform that will be applied to this node
01335 //               and below.  This defines a new coordinate space at
01336 //               this point in the scene graph and below.
01337 ////////////////////////////////////////////////////////////////////
01338 void PandaNode::
01339 set_transform(const TransformState *transform, Thread *current_thread) {
01340   // Apply this operation to the current stage as well as to all
01341   // upstream stages.
01342   bool any_changed = false;
01343   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01344     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01345     if (cdata->_transform != transform) {
01346       cdata->_transform = transform;
01347       cdata->set_fancy_bit(FB_transform, !transform->is_identity());
01348       any_changed = true;
01349 
01350       if (pipeline_stage == 0) {
01351         if (cdata->_transform != cdata->_prev_transform) {
01352           set_dirty_prev_transform();
01353         }
01354       }
01355     }
01356   }
01357   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01358 
01359   if (any_changed) {
01360     mark_bounds_stale(current_thread);
01361     transform_changed();
01362     mark_bam_modified();
01363   }
01364 }
01365 
01366 ////////////////////////////////////////////////////////////////////
01367 //     Function: PandaNode::set_prev_transform
01368 //       Access: Published
01369 //  Description: Sets the transform that represents this node's
01370 //               "previous" position, one frame ago, for the purposes
01371 //               of detecting motion for accurate collision
01372 //               calculations.
01373 ////////////////////////////////////////////////////////////////////
01374 void PandaNode::
01375 set_prev_transform(const TransformState *transform, Thread *current_thread) {
01376   // Apply this operation to the current stage as well as to all
01377   // upstream stages.
01378   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01379     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01380     cdata->_prev_transform = transform;
01381     if (pipeline_stage == 0) {
01382       if (cdata->_transform != cdata->_prev_transform) {
01383         set_dirty_prev_transform();
01384       } else {
01385         clear_dirty_prev_transform();
01386       }
01387     }
01388   }
01389   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01390   mark_bam_modified();
01391 }
01392 
01393 ////////////////////////////////////////////////////////////////////
01394 //     Function: PandaNode::reset_prev_transform
01395 //       Access: Published
01396 //  Description: Resets the transform that represents this node's
01397 //               "previous" position to the same as the current
01398 //               transform.  This is not the same thing as clearing it
01399 //               to identity.
01400 ////////////////////////////////////////////////////////////////////
01401 void PandaNode::
01402 reset_prev_transform(Thread *current_thread) {
01403   // Apply this operation to the current stage as well as to all
01404   // upstream stages.
01405   clear_dirty_prev_transform();
01406 
01407   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01408     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01409     cdata->_prev_transform = cdata->_transform;
01410   }
01411   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01412   mark_bam_modified();
01413 }
01414 
01415 ////////////////////////////////////////////////////////////////////
01416 //     Function: PandaNode::reset_all_prev_transform
01417 //       Access: Published, Static
01418 //  Description: Visits all nodes in the world with the
01419 //               _dirty_prev_transform flag--that is, all nodes whose
01420 //               _prev_transform is different from the _transform in
01421 //               pipeline stage 0--and resets the _prev_transform to
01422 //               be the same as _transform.
01423 ////////////////////////////////////////////////////////////////////
01424 void PandaNode::
01425 reset_all_prev_transform(Thread *current_thread) {
01426   nassertv(current_thread->get_pipeline_stage() == 0);
01427 
01428   PStatTimer timer(_reset_prev_pcollector, current_thread);
01429   LightMutexHolder holder(_dirty_prev_transforms._lock);
01430 
01431   LinkedListNode *list_node = _dirty_prev_transforms._next;
01432   while (list_node != &_dirty_prev_transforms) {
01433     PandaNode *panda_node = (PandaNode *)list_node;
01434     nassertv(panda_node->_dirty_prev_transform);
01435     panda_node->_dirty_prev_transform = false;
01436     
01437     CDStageWriter cdata(panda_node->_cycler, 0, current_thread);
01438     cdata->_prev_transform = cdata->_transform;
01439 
01440     list_node = panda_node->_next;
01441 #ifndef NDEBUG
01442     panda_node->_prev = NULL;
01443     panda_node->_next = NULL;
01444 #endif  // NDEBUG
01445     panda_node->mark_bam_modified();
01446   }
01447 
01448   _dirty_prev_transforms._prev = &_dirty_prev_transforms;
01449   _dirty_prev_transforms._next = &_dirty_prev_transforms;
01450 }
01451 
01452 ////////////////////////////////////////////////////////////////////
01453 //     Function: PandaNode::set_tag
01454 //       Access: Published
01455 //  Description: Associates a user-defined value with a user-defined
01456 //               key which is stored on the node.  This value has no
01457 //               meaning to Panda; but it is stored indefinitely on
01458 //               the node until it is requested again.
01459 //
01460 //               Each unique key stores a different string value.
01461 //               There is no effective limit on the number of
01462 //               different keys that may be stored or on the length of
01463 //               any one key's value.
01464 ////////////////////////////////////////////////////////////////////
01465 void PandaNode::
01466 set_tag(const string &key, const string &value, Thread *current_thread) {
01467   // Apply this operation to the current stage as well as to all
01468   // upstream stages.
01469   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01470     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01471     cdata->_tag_data[key] = value;
01472     cdata->set_fancy_bit(FB_tag, true);
01473   }
01474   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01475   mark_bam_modified();
01476 }
01477 
01478 ////////////////////////////////////////////////////////////////////
01479 //     Function: PandaNode::clear_tag
01480 //       Access: Published
01481 //  Description: Removes the value defined for this key on this
01482 //               particular node.  After a call to clear_tag(),
01483 //               has_tag() will return false for the indicated key.
01484 ////////////////////////////////////////////////////////////////////
01485 void PandaNode::
01486 clear_tag(const string &key, Thread *current_thread) {
01487   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01488     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01489     cdata->_tag_data.erase(key);
01490     cdata->set_fancy_bit(FB_tag, !cdata->_tag_data.empty());
01491   }
01492   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01493   mark_bam_modified();
01494 }
01495 
01496 #ifdef HAVE_PYTHON
01497 ////////////////////////////////////////////////////////////////////
01498 //     Function: PandaNode::set_python_tag
01499 //       Access: Published
01500 //  Description: Associates an arbitrary Python object with a
01501 //               user-defined key which is stored on the node.  This
01502 //               is similar to set_tag(), except it can store any
01503 //               Python object instead of just a string.  However, the
01504 //               Python object is not recorded to a bam file.
01505 //
01506 //               Each unique key stores a different string value.
01507 //               There is no effective limit on the number of
01508 //               different keys that may be stored or on the length of
01509 //               any one key's value.
01510 ////////////////////////////////////////////////////////////////////
01511 void PandaNode::
01512 set_python_tag(const string &key, PyObject *value) {
01513   Thread *current_thread = Thread::get_current_thread();
01514   int pipeline_stage = current_thread->get_pipeline_stage();
01515   nassertv(pipeline_stage == 0);
01516 
01517   CDWriter cdata(_cycler);
01518   Py_XINCREF(value);
01519 
01520   pair<PythonTagData::iterator, bool> result;
01521   result = cdata->_python_tag_data.insert(PythonTagData::value_type(key, value));
01522 
01523   if (!result.second) {
01524     // The insert was unsuccessful; that means the key was already
01525     // present in the map.  In this case, we should decrement the
01526     // original value's reference count and replace it with the new
01527     // object.
01528     PythonTagData::iterator ti = result.first;
01529     PyObject *old_value = (*ti).second;
01530     Py_XDECREF(old_value);
01531     (*ti).second = value;
01532   }
01533 
01534   // Even though the python tag isn't recorded in the bam stream?
01535   mark_bam_modified();
01536 }
01537 #endif  // HAVE_PYTHON
01538 
01539 #ifdef HAVE_PYTHON
01540 ////////////////////////////////////////////////////////////////////
01541 //     Function: PandaNode::get_python_tag
01542 //       Access: Published
01543 //  Description: Retrieves the Python object that was previously
01544 //               set on this node for the particular key, if any.  If
01545 //               no value has been previously set, returns None.
01546 ////////////////////////////////////////////////////////////////////
01547 PyObject *PandaNode::
01548 get_python_tag(const string &key) const {
01549   CDReader cdata(_cycler);
01550   PythonTagData::const_iterator ti;
01551   ti = cdata->_python_tag_data.find(key);
01552   if (ti != cdata->_python_tag_data.end()) {
01553     PyObject *result = (*ti).second;
01554     Py_XINCREF(result);
01555     return result;
01556   }
01557   Py_INCREF(Py_None);
01558   return Py_None;
01559 }
01560 #endif  // HAVE_PYTHON
01561 
01562 #ifdef HAVE_PYTHON
01563 ////////////////////////////////////////////////////////////////////
01564 //     Function: PandaNode::has_python_tag
01565 //       Access: Published
01566 //  Description: Returns true if a Python object has been defined on
01567 //               this node for the particular key (even if that object
01568 //               is None), or false if no object has been set.
01569 ////////////////////////////////////////////////////////////////////
01570 bool PandaNode::
01571 has_python_tag(const string &key) const {
01572   CDReader cdata(_cycler);
01573   PythonTagData::const_iterator ti;
01574   ti = cdata->_python_tag_data.find(key);
01575   return (ti != cdata->_python_tag_data.end());
01576 }
01577 #endif  // HAVE_PYTHON
01578 
01579 #ifdef HAVE_PYTHON
01580 ////////////////////////////////////////////////////////////////////
01581 //     Function: PandaNode::clear_python_tag
01582 //       Access: Published
01583 //  Description: Removes the Python object defined for this key on
01584 //               this particular node.  After a call to
01585 //               clear_python_tag(), has_python_tag() will return
01586 //               false for the indicated key.
01587 ////////////////////////////////////////////////////////////////////
01588 void PandaNode::
01589 clear_python_tag(const string &key) {
01590   Thread *current_thread = Thread::get_current_thread();
01591   int pipeline_stage = current_thread->get_pipeline_stage();
01592   nassertv(pipeline_stage == 0);
01593 
01594   CDWriter cdata(_cycler, current_thread);
01595   PythonTagData::iterator ti;
01596   ti = cdata->_python_tag_data.find(key);
01597   if (ti != cdata->_python_tag_data.end()) {
01598     PyObject *value = (*ti).second;
01599     Py_XDECREF(value);
01600     cdata->_python_tag_data.erase(ti);
01601   }
01602 
01603   // Even though the python tag isn't recorded in the bam stream?
01604   mark_bam_modified();
01605 }
01606 #endif  // HAVE_PYTHON
01607 
01608 ////////////////////////////////////////////////////////////////////
01609 //     Function: PandaNode::copy_tags
01610 //       Access: Published
01611 //  Description: Copies all of the tags stored on the other node onto
01612 //               this node.  If a particular tag exists on both nodes,
01613 //               the contents of this node's value is replaced by that
01614 //               of the other.
01615 ////////////////////////////////////////////////////////////////////
01616 void PandaNode::
01617 copy_tags(PandaNode *other) {
01618   if (other == this) {
01619     // Trivial.
01620     return;
01621   }
01622 
01623   // Apply this operation to the current stage as well as to all
01624   // upstream stages.
01625   Thread *current_thread = Thread::get_current_thread();
01626   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01627     CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
01628     CDStageReader cdatar(other->_cycler, pipeline_stage, current_thread);
01629       
01630     TagData::const_iterator ti;
01631     for (ti = cdatar->_tag_data.begin();
01632          ti != cdatar->_tag_data.end();
01633          ++ti) {
01634       cdataw->_tag_data[(*ti).first] = (*ti).second;
01635     }
01636     cdataw->set_fancy_bit(FB_tag, !cdataw->_tag_data.empty());
01637     
01638 #ifdef HAVE_PYTHON
01639     PythonTagData::const_iterator pti;
01640     for (pti = cdatar->_python_tag_data.begin();
01641          pti != cdatar->_python_tag_data.end();
01642          ++pti) {
01643       const string &key = (*pti).first;
01644       PyObject *value = (*pti).second;
01645       Py_XINCREF(value);
01646       
01647       pair<PythonTagData::iterator, bool> result;
01648       result = cdataw->_python_tag_data.insert(PythonTagData::value_type(key, value));
01649       
01650       if (!result.second) {
01651         // The insert was unsuccessful; that means the key was already
01652         // present in the map.  In this case, we should decrement the
01653         // original value's reference count and replace it with the new
01654         // object.
01655         PythonTagData::iterator wpti = result.first;
01656         PyObject *old_value = (*wpti).second;
01657         Py_XDECREF(old_value);
01658         (*wpti).second = value;
01659       }
01660     }
01661 #endif // HAVE_PYTHON
01662   }
01663   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01664   mark_bam_modified();
01665 }
01666 
01667 ////////////////////////////////////////////////////////////////////
01668 //     Function: PandaNode::list_tags
01669 //       Access: Published
01670 //  Description: Writes a list of all the tag keys assigned to the
01671 //               node to the indicated stream.  Writes one instance of
01672 //               the separator following each key (but does not write
01673 //               a terminal separator).  The value associated with
01674 //               each key is not written.
01675 //
01676 //               This is mainly for the benefit of the realtime user,
01677 //               to see the list of all of the associated tag keys.
01678 ////////////////////////////////////////////////////////////////////
01679 void PandaNode::
01680 list_tags(ostream &out, const string &separator) const {
01681   CDReader cdata(_cycler);
01682   if (!cdata->_tag_data.empty()) {
01683     TagData::const_iterator ti = cdata->_tag_data.begin();
01684     out << (*ti).first;
01685     ++ti;
01686     while (ti != cdata->_tag_data.end()) {
01687       out << separator << (*ti).first;
01688       ++ti;
01689     }
01690   }
01691 
01692 #ifdef HAVE_PYTHON
01693   if (!cdata->_python_tag_data.empty()) {
01694     if (!cdata->_tag_data.empty()) {
01695       out << separator;
01696     }
01697     PythonTagData::const_iterator ti = cdata->_python_tag_data.begin();
01698     out << (*ti).first;
01699     ++ti;
01700     while (ti != cdata->_python_tag_data.end()) {
01701       out << separator << (*ti).first;
01702       ++ti;
01703     }
01704   }
01705 #endif  // HAVE_PYTHON
01706 }
01707 
01708 ////////////////////////////////////////////////////////////////////
01709 //     Function: PandaNode::compare_tags
01710 //       Access: Published
01711 //  Description: Returns a number less than 0, 0, or greater than 0,
01712 //               to indicate the similarity of tags between this node
01713 //               and the other one.  If this returns 0, the tags are
01714 //               identical.  If it returns other than 0, then the tags
01715 //               are different; and the nodes may be sorted into a
01716 //               consistent (but arbitrary) ordering based on this
01717 //               number.
01718 ////////////////////////////////////////////////////////////////////
01719 int PandaNode::
01720 compare_tags(const PandaNode *other) const {
01721   CDReader cdata(_cycler);
01722   CDReader cdata_other(other->_cycler);
01723 
01724   TagData::const_iterator ati = cdata->_tag_data.begin();
01725   TagData::const_iterator bti = cdata_other->_tag_data.begin();
01726   while (ati != cdata->_tag_data.end() &&
01727          bti != cdata_other->_tag_data.end()) {
01728     int cmp = strcmp((*ati).first.c_str(), (*bti).first.c_str());
01729     if (cmp != 0) {
01730       return cmp;
01731     }
01732 
01733     cmp = strcmp((*ati).second.c_str(), (*bti).second.c_str());
01734     if (cmp != 0) {
01735       return cmp;
01736     }
01737 
01738     ++ati;
01739     ++bti;
01740   }
01741   if (ati != cdata->_tag_data.end()) {
01742     // list A is longer.
01743     return 1;
01744   }
01745   if (bti != cdata_other->_tag_data.end()) {
01746     // list B is longer.
01747     return -1;
01748   }
01749 
01750 #ifdef HAVE_PYTHON
01751   PythonTagData::const_iterator api = cdata->_python_tag_data.begin();
01752   PythonTagData::const_iterator bpi = cdata_other->_python_tag_data.begin();
01753   while (api != cdata->_python_tag_data.end() &&
01754          bpi != cdata_other->_python_tag_data.end()) {
01755     int cmp = strcmp((*api).first.c_str(), (*bpi).first.c_str());
01756     if (cmp != 0) {
01757       return cmp;
01758     }
01759 
01760     if (PyObject_Cmp((*api).second, (*bpi).second, &cmp) == -1) {
01761       // Unable to compare objects; just compare pointers.
01762       if ((*api).second != (*bpi).second) {
01763         cmp = (*api).second < (*bpi).second ? -1 : 1;
01764       } else {
01765         cmp = 0;
01766       }
01767     }
01768     if (cmp != 0) {
01769       return cmp;
01770     }
01771 
01772     ++api;
01773     ++bpi;
01774   }
01775   if (api != cdata->_python_tag_data.end()) {
01776     // list A is longer.
01777     return 1;
01778   }
01779   if (bpi != cdata_other->_python_tag_data.end()) {
01780     // list B is longer.
01781     return -1;
01782   }
01783 #endif  // HAVE_PYTHON
01784 
01785   return 0;
01786 }
01787 
01788 ////////////////////////////////////////////////////////////////////
01789 //     Function: PandaNode::copy_all_properties
01790 //       Access: Published
01791 //  Description: Copies the TransformState, RenderState,
01792 //               RenderEffects, tags, Python tags, and the show/hide
01793 //               state from the other node onto this one.  Typically
01794 //               this is used to prepare a node to replace another
01795 //               node in the scene graph (also see replace_node()).
01796 ////////////////////////////////////////////////////////////////////
01797 void PandaNode::
01798 copy_all_properties(PandaNode *other) {
01799   if (other == this) {
01800     // Trivial.
01801     return;
01802   }
01803 
01804   bool any_transform_changed = false;
01805   bool any_state_changed = false;
01806   bool any_draw_mask_changed = false;
01807   Thread *current_thread = Thread::get_current_thread();
01808   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01809     CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
01810     CDStageReader cdatar(other->_cycler, pipeline_stage, current_thread);
01811 
01812     if (cdataw->_transform != cdatar->_transform) {
01813       any_transform_changed = true;
01814     }
01815     if (cdataw->_state != cdatar->_state) {
01816       any_state_changed = true;
01817     }
01818     if (cdataw->_draw_control_mask != cdatar->_draw_control_mask ||
01819         cdataw->_draw_show_mask != cdatar->_draw_show_mask) {
01820       any_draw_mask_changed = true;
01821     }
01822 
01823     cdataw->_transform = cdatar->_transform;
01824     cdataw->_prev_transform = cdatar->_prev_transform;
01825     cdataw->_state = cdatar->_state;
01826     cdataw->_effects = cdatar->_effects;
01827     cdataw->_draw_control_mask = cdatar->_draw_control_mask;
01828     cdataw->_draw_show_mask = cdatar->_draw_show_mask;
01829 
01830     // The collide mask becomes the union of the two masks.  This is
01831     // important to preserve properties such as the default GeomNode
01832     // bitmask.
01833     cdataw->_into_collide_mask |= cdatar->_into_collide_mask;
01834       
01835     TagData::const_iterator ti;
01836     for (ti = cdatar->_tag_data.begin();
01837          ti != cdatar->_tag_data.end();
01838          ++ti) {
01839       cdataw->_tag_data[(*ti).first] = (*ti).second;
01840     }
01841     
01842 #ifdef HAVE_PYTHON
01843     PythonTagData::const_iterator pti;
01844     for (pti = cdatar->_python_tag_data.begin();
01845          pti != cdatar->_python_tag_data.end();
01846          ++pti) {
01847       const string &key = (*pti).first;
01848       PyObject *value = (*pti).second;
01849       Py_XINCREF(value);
01850       
01851       pair<PythonTagData::iterator, bool> result;
01852       result = cdataw->_python_tag_data.insert(PythonTagData::value_type(key, value));
01853       
01854       if (!result.second) {
01855         // The insert was unsuccessful; that means the key was already
01856         // present in the map.  In this case, we should decrement the
01857         // original value's reference count and replace it with the new
01858         // object.
01859         PythonTagData::iterator wpti = result.first;
01860         PyObject *old_value = (*wpti).second;
01861         Py_XDECREF(old_value);
01862         (*wpti).second = value;
01863       }
01864     }
01865 #endif // HAVE_PYTHON
01866 
01867     static const int change_bits = (FB_transform | FB_state | FB_effects |
01868                                     FB_tag | FB_draw_mask);
01869     cdataw->_fancy_bits =
01870       (cdataw->_fancy_bits & ~change_bits) |
01871       (cdatar->_fancy_bits & change_bits);
01872 
01873     if (pipeline_stage == 0) {
01874       if (cdataw->_transform != cdataw->_prev_transform) {
01875         set_dirty_prev_transform();
01876       }
01877     }
01878   }
01879   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01880 
01881   if (any_transform_changed || any_state_changed || any_draw_mask_changed) {
01882     mark_bounds_stale(current_thread);
01883 
01884     if (any_transform_changed) {
01885       transform_changed();
01886     }
01887     if (any_state_changed) {
01888       state_changed();
01889     }
01890     if (any_draw_mask_changed) {
01891       draw_mask_changed();
01892     }
01893     mark_bam_modified();
01894   }
01895 }
01896 
01897 ////////////////////////////////////////////////////////////////////
01898 //     Function: PandaNode::replace_node
01899 //       Access: Published
01900 //  Description: Inserts this node into the scene graph in place of
01901 //               the other one, and removes the other node.  All scene
01902 //               graph attributes (TransformState, RenderState, etc.)
01903 //               are copied to this node.  
01904 //
01905 //               All children are moved to this node, and removed from
01906 //               the old node.  The new node is left in the same place
01907 //               in the old node's parent's list of children.
01908 //
01909 //               Even NodePaths that reference the old node are
01910 //               updated in-place to reference the new node instead.
01911 //
01912 //               This method is intended to be used to replace a node
01913 //               of a given type in the scene graph with a node of a
01914 //               different type.
01915 ////////////////////////////////////////////////////////////////////
01916 void PandaNode::
01917 replace_node(PandaNode *other) {
01918   //  nassertv(Thread::get_current_pipeline_stage() == 0);
01919 
01920   if (other == this) {
01921     // Trivial.
01922     return;
01923   }
01924 
01925   // Make sure the other node is not destructed during the
01926   // execution of this method.
01927   PT(PandaNode) keep_other = other;
01928 
01929   // Get all the important scene graph properties.
01930   copy_all_properties(other);
01931 
01932   // Fix up the NodePaths.
01933   {
01934     LightReMutexHolder holder1(other->_paths_lock);
01935     LightReMutexHolder holder2(_paths_lock);
01936     Paths::iterator pi;
01937     for (pi = other->_paths.begin(); pi != other->_paths.end(); ++pi) {
01938       (*pi)->_node = this;
01939       _paths.insert(*pi);
01940     }
01941     other->_paths.clear();
01942   }
01943 
01944   // Get the children.
01945   steal_children(other);
01946 
01947   // Switch the parents.
01948   Thread *current_thread = Thread::get_current_thread();
01949   Parents other_parents = other->get_parents();
01950   for (int i = 0; i < other_parents.get_num_parents(); ++i) {
01951     PandaNode *parent = other_parents.get_parent(i);
01952     if (find_parent(parent) != -1) {
01953       // This node was already a child of this parent; don't change
01954       // it.
01955       parent->remove_child(other);
01956     } else {
01957       // This node was not yet a child of this parent; now it is.
01958       parent->replace_child(other, this, current_thread);
01959     }
01960   }
01961 }
01962 
01963 ////////////////////////////////////////////////////////////////////
01964 //     Function: PandaNode::set_unexpected_change
01965 //       Access: Published
01966 //  Description: Sets one or more of the PandaNode::UnexpectedChange
01967 //               bits on, indicating that the corresponding property
01968 //               should not change again on this node.  Once one of
01969 //               these bits has been set, if the property changes, an
01970 //               assertion failure will be raised, which is designed
01971 //               to assist the developer in identifying the
01972 //               troublesome code that modified the property
01973 //               unexpectedly.
01974 //
01975 //               The input parameter is the union of bits that are to
01976 //               be set.  To clear these bits later, use
01977 //               clear_unexpected_change().
01978 //
01979 //               Since this is a developer debugging tool only, this
01980 //               function does nothing in a production (NDEBUG) build.
01981 ////////////////////////////////////////////////////////////////////
01982 void PandaNode::
01983 set_unexpected_change(unsigned int flags) {
01984 #ifndef NDEBUG
01985   _unexpected_change_flags |= flags;
01986 #endif // !NDEBUG
01987 }
01988 
01989 ////////////////////////////////////////////////////////////////////
01990 //     Function: PandaNode::get_unexpected_change
01991 //       Access: Published
01992 //  Description: Returns nonzero if any of the bits in the input
01993 //               parameter are set on this node, or zero if none of
01994 //               them are set.  More specifically, this returns the
01995 //               particular set of bits (masked by the input
01996 //               parameter) that have been set on this node.  See
01997 //               set_unexpected_change().
01998 //
01999 //               Since this is a developer debugging tool only, this
02000 //               function always returns zero in a production (NDEBUG)
02001 //               build.
02002 ////////////////////////////////////////////////////////////////////
02003 unsigned int PandaNode::
02004 get_unexpected_change(unsigned int flags) const {
02005 #ifndef NDEBUG
02006   return _unexpected_change_flags & flags;
02007 #else
02008   return 0;
02009 #endif // !NDEBUG
02010 }
02011 
02012 ////////////////////////////////////////////////////////////////////
02013 //     Function: PandaNode::clear_unexpected_change
02014 //       Access: Published
02015 //  Description: Sets one or more of the PandaNode::UnexpectedChange
02016 //               bits off, indicating that the corresponding property
02017 //               may once again change on this node.  See
02018 //               set_unexpected_change().
02019 //
02020 //               The input parameter is the union of bits that are to
02021 //               be cleared.
02022 //
02023 //               Since this is a developer debugging tool only, this
02024 //               function does nothing in a production (NDEBUG) build.
02025 ////////////////////////////////////////////////////////////////////
02026 void PandaNode::
02027 clear_unexpected_change(unsigned int flags) {
02028 #ifndef NDEBUG
02029   _unexpected_change_flags &= ~flags;
02030 #endif // !NDEBUG
02031 }
02032 
02033 ////////////////////////////////////////////////////////////////////
02034 //     Function: PandaNode::adjust_draw_mask
02035 //       Access: Published
02036 //  Description: Adjusts the hide/show bits of this particular node.
02037 //
02038 //               These three parameters can be used to adjust the
02039 //               _draw_control_mask and _draw_show_mask independently,
02040 //               which work together to provide per-camera visibility
02041 //               for the node and its descendents.
02042 //
02043 //               _draw_control_mask indicates the bits in
02044 //               _draw_show_mask that are significant.  Each different
02045 //               bit corresponds to a different camera (and these bits
02046 //               are assigned via Camera::set_camera_mask()).
02047 //
02048 //               Where _draw_control_mask has a 1 bit, a 1 bit in
02049 //               _draw_show_mask indicates the node is visible to that
02050 //               camera, and a 0 bit indicates the node is hidden to
02051 //               that camera.  Where _draw_control_mask is 0, the node
02052 //               is hidden only if a parent node is hidden.
02053 //
02054 //               The meaning of the three parameters is as follows:
02055 //
02056 //               * Wherever show_mask is 1, _draw_show_mask and
02057 //               _draw_control_mask will be set 1.  Thus, show_mask
02058 //               indicates the set of cameras to which the node should
02059 //               be shown.
02060 //
02061 //               * Wherever hide_mask is 1, _draw_show_mask will be
02062 //               set 0 and _draw_control_mask will be set 1.  Thus,
02063 //               hide_mask indicates the set of cameras from which the
02064 //               node should be hidden.
02065 //
02066 //               * Wherever clear_mask is 1, _draw_control_mask will
02067 //               be set 0.  Thus, clear_mask indicates the set of
02068 //               cameras from which the hidden state should be
02069 //               inherited from a parent.
02070 ////////////////////////////////////////////////////////////////////
02071 void PandaNode::
02072 adjust_draw_mask(DrawMask show_mask, DrawMask hide_mask, DrawMask clear_mask) {
02073   bool any_changed = false;
02074 
02075   Thread *current_thread = Thread::get_current_thread();
02076   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02077     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02078     
02079     DrawMask draw_control_mask = (cdata->_draw_control_mask | show_mask | hide_mask) & ~clear_mask;
02080     DrawMask draw_show_mask = (cdata->_draw_show_mask | show_mask) & ~hide_mask;
02081     // The uncontrolled bits are implicitly on.
02082     draw_show_mask |= ~draw_control_mask;
02083 
02084     if (cdata->_draw_control_mask != draw_control_mask ||
02085         cdata->_draw_show_mask != draw_show_mask) {
02086       cdata->_draw_control_mask = draw_control_mask;
02087       cdata->_draw_show_mask = draw_show_mask;
02088       any_changed = true;
02089     }
02090     cdata->set_fancy_bit(FB_draw_mask, !draw_control_mask.is_zero());
02091   }
02092   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02093 
02094   if (any_changed) {
02095     mark_bounds_stale(current_thread);
02096     draw_mask_changed();
02097     mark_bam_modified();
02098   }
02099 }
02100 
02101 ////////////////////////////////////////////////////////////////////
02102 //     Function: PandaNode::get_net_draw_control_mask
02103 //       Access: Published
02104 //  Description: Returns the set of bits in get_net_draw_show_mask()
02105 //               that have been explicitly set via adjust_draw_mask(),
02106 //               rather than implicitly inherited.
02107 //
02108 //               A 1 bit in any position of this mask indicates that
02109 //               (a) this node has renderable children, and (b) some
02110 //               child of this node has made an explicit hide() or
02111 //               show_through() call for the corresponding bit.
02112 ////////////////////////////////////////////////////////////////////
02113 DrawMask PandaNode::
02114 get_net_draw_control_mask() const {
02115   Thread *current_thread = Thread::get_current_thread();
02116   int pipeline_stage = current_thread->get_pipeline_stage();
02117   CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02118   if (cdata->_last_update != cdata->_next_update) {
02119     // The cache is stale; it needs to be rebuilt.
02120     PStatTimer timer(_update_bounds_pcollector);
02121     CDStageWriter cdataw = 
02122       ((PandaNode *)this)->update_bounds(pipeline_stage, cdata); 
02123     return cdataw->_net_draw_control_mask;
02124   }
02125   return cdata->_net_draw_control_mask;
02126 }
02127 
02128 ////////////////////////////////////////////////////////////////////
02129 //     Function: PandaNode::get_net_draw_show_mask
02130 //       Access: Published
02131 //  Description: Returns the union of all draw_show_mask values--of
02132 //               renderable nodes only--at this level and below.  If
02133 //               any bit in this mask is 0, there is no reason to
02134 //               traverse below this node for a camera with the
02135 //               corresponding camera_mask.
02136 //
02137 //               The bits in this mask that do not correspond to a 1
02138 //               bit in the net_draw_control_mask are meaningless (and
02139 //               will be set to 1).  For bits that *do* correspond to
02140 //               a 1 bit in the net_draw_control_mask, a 1 bit
02141 //               indicates that at least one child should be visible,
02142 //               while a 0 bit indicates that all children are hidden.
02143 ////////////////////////////////////////////////////////////////////
02144 DrawMask PandaNode::
02145 get_net_draw_show_mask() const {
02146   Thread *current_thread = Thread::get_current_thread();
02147   int pipeline_stage = current_thread->get_pipeline_stage();
02148   CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02149   if (cdata->_last_update != cdata->_next_update) {
02150     // The cache is stale; it needs to be rebuilt.
02151     PStatTimer timer(_update_bounds_pcollector);
02152     CDStageWriter cdataw = 
02153       ((PandaNode *)this)->update_bounds(pipeline_stage, cdata); 
02154     return cdataw->_net_draw_show_mask;
02155   }
02156   return cdata->_net_draw_show_mask;
02157 }
02158 
02159 ////////////////////////////////////////////////////////////////////
02160 //     Function: PandaNode::set_into_collide_mask
02161 //       Access: Published
02162 //  Description: Sets the "into" CollideMask.  
02163 //
02164 //               This specifies the set of bits that must be shared
02165 //               with a CollisionNode's "from" CollideMask in order
02166 //               for the CollisionNode to detect a collision with this
02167 //               particular node.
02168 //
02169 //               The actual CollideMask that will be set is masked by
02170 //               the return value from get_legal_collide_mask().
02171 //               Thus, the into_collide_mask cannot be set to anything
02172 //               other than nonzero except for those types of nodes
02173 //               that can be collided into, such as CollisionNodes and
02174 //               GeomNodes.
02175 ////////////////////////////////////////////////////////////////////
02176 void PandaNode::
02177 set_into_collide_mask(CollideMask mask) {
02178   mask &= get_legal_collide_mask();
02179 
02180   bool any_changed = false;
02181   Thread *current_thread = Thread::get_current_thread();
02182   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02183     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02184     if (cdata->_into_collide_mask != mask) {
02185       cdata->_into_collide_mask = mask;
02186       any_changed = true;
02187     }
02188   }
02189   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02190 
02191   if (any_changed) {
02192     mark_bounds_stale(current_thread);
02193     mark_bam_modified();
02194   }
02195 }
02196 
02197 ////////////////////////////////////////////////////////////////////
02198 //     Function: PandaNode::get_legal_collide_mask
02199 //       Access: Published, Virtual
02200 //  Description: Returns the subset of CollideMask bits that may be
02201 //               set for this particular type of PandaNode.  For most
02202 //               nodes, this is 0; it doesn't make sense to set a
02203 //               CollideMask for most kinds of nodes.
02204 //
02205 //               For nodes that can be collided with, such as GeomNode
02206 //               and CollisionNode, this returns all bits on.
02207 ////////////////////////////////////////////////////////////////////
02208 CollideMask PandaNode::
02209 get_legal_collide_mask() const {
02210   return CollideMask::all_off();
02211 }
02212 
02213 ////////////////////////////////////////////////////////////////////
02214 //     Function: PandaNode::get_net_collide_mask
02215 //       Access: Published
02216 //  Description: Returns the union of all into_collide_mask() values
02217 //               set at CollisionNodes at this level and below.
02218 ////////////////////////////////////////////////////////////////////
02219 CollideMask PandaNode::
02220 get_net_collide_mask(Thread *current_thread) const {
02221   int pipeline_stage = current_thread->get_pipeline_stage();
02222   CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02223   if (cdata->_last_update != cdata->_next_update) {
02224     // The cache is stale; it needs to be rebuilt.
02225     PStatTimer timer(_update_bounds_pcollector);
02226     CDStageWriter cdataw = 
02227       ((PandaNode *)this)->update_bounds(pipeline_stage, cdata); 
02228     return cdataw->_net_collide_mask;
02229   }
02230   return cdata->_net_collide_mask;
02231 }
02232 
02233 ////////////////////////////////////////////////////////////////////
02234 //     Function: PandaNode::get_off_clip_planes
02235 //       Access: Published
02236 //  Description: Returns a ClipPlaneAttrib which represents the union
02237 //               of all of the clip planes that have been turned *off*
02238 //               at this level and below.
02239 ////////////////////////////////////////////////////////////////////
02240 CPT(RenderAttrib) PandaNode::
02241 get_off_clip_planes(Thread *current_thread) const {
02242   int pipeline_stage = current_thread->get_pipeline_stage();
02243   CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02244   if (cdata->_last_update != cdata->_next_update) {
02245     // The cache is stale; it needs to be rebuilt.
02246     PStatTimer timer(_update_bounds_pcollector);
02247     CDStageWriter cdataw = 
02248       ((PandaNode *)this)->update_bounds(pipeline_stage, cdata); 
02249     return cdataw->_off_clip_planes;
02250   }
02251   return cdata->_off_clip_planes;
02252 }
02253 
02254 ////////////////////////////////////////////////////////////////////
02255 //     Function: PandaNode::prepare_scene
02256 //       Access: Published
02257 //  Description: Walks through the scene graph beginning at this node,
02258 //               and does whatever initialization is required to
02259 //               render the scene properly with the indicated GSG.  It
02260 //               is not strictly necessary to call this, since the GSG
02261 //               will initialize itself when the scene is rendered,
02262 //               but this may take some of the overhead away from that
02263 //               process.
02264 //
02265 //               In particular, this will ensure that textures within
02266 //               the scene are loaded in texture memory, and display
02267 //               lists are built up from static geometry.
02268 ////////////////////////////////////////////////////////////////////
02269 void PandaNode::
02270 prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *net_state) {
02271   Thread *current_thread = Thread::get_current_thread();
02272   PreparedGraphicsObjects *prepared_objects = gsg->get_prepared_objects();
02273   r_prepare_scene(net_state, prepared_objects, current_thread);
02274 }
02275 
02276 ////////////////////////////////////////////////////////////////////
02277 //     Function: PandaNode::is_scene_root
02278 //       Access: Published
02279 //  Description: Returns true if this particular node is known to be
02280 //               the render root of some active DisplayRegion
02281 //               associated with the global GraphicsEngine, false
02282 //               otherwise.
02283 ////////////////////////////////////////////////////////////////////
02284 bool PandaNode::
02285 is_scene_root() const {
02286   // This function pointer has to be filled in when the global
02287   // GraphicsEngine is created, because we can't link with the
02288   // GraphicsEngine functions directly.
02289   if (_scene_root_func != (SceneRootFunc *)NULL) {
02290     return (*_scene_root_func)(this);
02291   }
02292   return false;
02293 }
02294 
02295 ////////////////////////////////////////////////////////////////////
02296 //     Function: PandaNode::is_under_scene_root
02297 //       Access: Published
02298 //  Description: Returns true if this particular node is in a live
02299 //               scene graph: that is, it is a child or descendent of
02300 //               a node that is itself a scene root.  If this is true,
02301 //               this node may potentially be traversed by the render
02302 //               traverser.  Stashed nodes don't count for this
02303 //               purpose, but hidden nodes do.
02304 ////////////////////////////////////////////////////////////////////
02305 bool PandaNode::
02306 is_under_scene_root() const {
02307   if (is_scene_root()) {
02308     return true;
02309   }
02310 
02311   Parents parents = get_parents();
02312   for (int i = 0; i < parents.get_num_parents(); ++i) {
02313     PandaNode *parent = parents.get_parent(i);
02314     if (parent->find_stashed((PandaNode *)this) == -1) {
02315       if (parent->is_under_scene_root()) {
02316         return true;
02317       }
02318     }
02319   }
02320   return false;
02321 }
02322 
02323 ////////////////////////////////////////////////////////////////////
02324 //     Function: PandaNode::output
02325 //       Access: Published, Virtual
02326 //  Description: 
02327 ////////////////////////////////////////////////////////////////////
02328 void PandaNode::
02329 output(ostream &out) const {
02330   out << get_type() << " " << get_name();
02331 }
02332 
02333 ////////////////////////////////////////////////////////////////////
02334 //     Function: PandaNode::write
02335 //       Access: Published, Virtual
02336 //  Description: 
02337 ////////////////////////////////////////////////////////////////////
02338 void PandaNode::
02339 write(ostream &out, int indent_level) const {
02340   indent(out, indent_level) << *this;
02341   if (has_tags()) {
02342     out << " [";
02343     list_tags(out, " ");
02344     out << "]";
02345   }
02346   CPT(TransformState) transform = get_transform();
02347   if (!transform->is_identity()) {
02348     out << " " << *transform;
02349   }
02350   CPT(RenderState) state = get_state();
02351   if (!state->is_empty()) {
02352     out << " " << *state;
02353   }
02354   CPT(RenderEffects) effects = get_effects();
02355   if (!effects->is_empty()) {
02356     out << " " << *effects;
02357   }
02358   DrawMask draw_control_mask = get_draw_control_mask();
02359   if (!draw_control_mask.is_zero()) {
02360     DrawMask draw_show_mask = get_draw_show_mask();
02361     if (!(draw_control_mask & _overall_bit).is_zero()) {
02362       if (!(draw_show_mask & _overall_bit).is_zero()) {
02363         out << " (show_through)";
02364       } else {
02365         out << " (hidden)";
02366       }
02367     }
02368     if (!(draw_control_mask & ~_overall_bit).is_zero()) {
02369       draw_control_mask &= ~_overall_bit;
02370       if (!(draw_show_mask & draw_control_mask).is_zero()) {
02371         out << " (per-camera show_through)";
02372       }
02373       if (!(~draw_show_mask & draw_control_mask).is_zero()) {
02374         out << " (per-camera hidden)";
02375       }
02376     }
02377   }
02378   out << "\n";
02379 }
02380 
02381 ////////////////////////////////////////////////////////////////////
02382 //     Function: PandaNode::set_bounds_type
02383 //       Access: Published
02384 //  Description: Specifies the desired type of bounding volume that
02385 //               will be created for this node.  This is normally
02386 //               BoundingVolume::BT_default, which means to set the
02387 //               type according to the config variable "bounds-type".
02388 //
02389 //               If this is BT_sphere or BT_box, a BoundingSphere or
02390 //               BoundingBox is explicitly created.  If it is BT_best,
02391 //               the appropriate type to best enclose the node's
02392 //               children is created.
02393 //
02394 //               This affects the bounding volume returned by
02395 //               get_bounds(), which is not exactly the same bounding
02396 //               volume modified by set_bounds(), because a new
02397 //               bounding volume has to be created that includes this
02398 //               node and all of its children.
02399 ////////////////////////////////////////////////////////////////////
02400 void PandaNode::
02401 set_bounds_type(BoundingVolume::BoundsType bounds_type) {
02402   Thread *current_thread = Thread::get_current_thread();
02403   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02404     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02405     cdata->_bounds_type = bounds_type;
02406     mark_bounds_stale(pipeline_stage, current_thread);
02407 
02408     // GeomNodes, CollisionNodes, and PGItems all have an internal
02409     // bounds that may need to be updated when the bounds_type
02410     // changes.
02411     mark_internal_bounds_stale(pipeline_stage, current_thread);
02412     mark_bam_modified();
02413   }
02414   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02415 }
02416 
02417 ////////////////////////////////////////////////////////////////////
02418 //     Function: PandaNode::get_bounds_type
02419 //       Access: Published
02420 //  Description: Returns the bounding volume type set with
02421 //               set_bounds_type().
02422 ////////////////////////////////////////////////////////////////////
02423 BoundingVolume::BoundsType PandaNode::
02424 get_bounds_type() const {
02425   CDReader cdata(_cycler);
02426   return cdata->_bounds_type;
02427 }
02428 
02429 ////////////////////////////////////////////////////////////////////
02430 //     Function: PandaNode::set_bounds
02431 //       Access: Published
02432 //  Description: Resets the bounding volume so that it is the
02433 //               indicated volume.  When it is explicitly set, the
02434 //               bounding volume will no longer be automatically
02435 //               computed according to the contents of the node
02436 //               itself, for nodes like GeomNodes and TextNodes that
02437 //               contain substance (but the bounding volume will still
02438 //               be automatically expanded to include its children).
02439 //
02440 //               Call clear_bounds() if you would like to return the
02441 //               bounding volume to its default behavior later.
02442 ////////////////////////////////////////////////////////////////////
02443 void PandaNode::
02444 set_bounds(const BoundingVolume *volume) {
02445   Thread *current_thread = Thread::get_current_thread();
02446   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02447     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02448     if (volume == NULL) {
02449       cdata->_user_bounds = NULL;
02450     } else {
02451       cdata->_user_bounds = volume->make_copy();
02452     }
02453     mark_bounds_stale(pipeline_stage, current_thread);
02454     mark_bam_modified();
02455   }
02456   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02457 }
02458 
02459 ////////////////////////////////////////////////////////////////////
02460 //     Function: PandaNode::set_bound
02461 //       Access: Published
02462 //  Description: Deprecated.  Use set_bounds() instead.
02463 ////////////////////////////////////////////////////////////////////
02464 void PandaNode::
02465 set_bound(const BoundingVolume *volume) {
02466   pgraph_cat.warning()
02467     << "Deprecated PandaNode::set_bound() called.  Use set_bounds() instead.\n";
02468   set_bounds(volume);
02469 }
02470 
02471 ////////////////////////////////////////////////////////////////////
02472 //     Function: PandaNode::get_bounds
02473 //       Access: Published
02474 //  Description: Returns the external bounding volume of this node: a
02475 //               bounding volume that contains the user bounding
02476 //               volume, the internal bounding volume, and all of the
02477 //               children's bounding volumes.
02478 ////////////////////////////////////////////////////////////////////
02479 CPT(BoundingVolume) PandaNode::
02480 get_bounds(Thread *current_thread) const {
02481   int pipeline_stage = current_thread->get_pipeline_stage();
02482   CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02483   if (cdata->_last_update != cdata->_next_update) {
02484     // The cache is stale; it needs to be rebuilt.
02485     CPT(BoundingVolume) result;
02486     {
02487       PStatTimer timer(_update_bounds_pcollector);
02488       CDStageWriter cdataw = 
02489         ((PandaNode *)this)->update_bounds(pipeline_stage, cdata); 
02490       result = cdataw->_external_bounds;
02491     }
02492     return result;
02493   }
02494   return cdata->_external_bounds;
02495 }
02496 
02497 ////////////////////////////////////////////////////////////////////
02498 //     Function: PandaNode::get_bounds
02499 //       Access: Published
02500 //  Description: This flavor of get_bounds() return the external
02501 //               bounding volume, and also fills in seq with the
02502 //               bounding volume's current sequence number.  When this
02503 //               sequence number changes, it indicates that the
02504 //               bounding volume might have changed, e.g. because some
02505 //               nested child's bounding volume has changed.
02506 //
02507 //               Although this might occasionally increment without
02508 //               changing the bounding volume, the bounding volume
02509 //               will never change without incrementing this counter,
02510 //               so as long as this counter remains unchanged you can
02511 //               be confident the bounding volume is also unchanged.
02512 ////////////////////////////////////////////////////////////////////
02513 CPT(BoundingVolume) PandaNode::
02514 get_bounds(UpdateSeq &seq, Thread *current_thread) const {
02515   int pipeline_stage = current_thread->get_pipeline_stage();
02516   CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02517   if (cdata->_last_update != cdata->_next_update) {
02518     // The cache is stale; it needs to be rebuilt.
02519     CPT(BoundingVolume) result;
02520     {
02521       PStatTimer timer(_update_bounds_pcollector);
02522       CDStageWriter cdataw = 
02523         ((PandaNode *)this)->update_bounds(pipeline_stage, cdata); 
02524       result = cdataw->_external_bounds;
02525       seq = cdataw->_last_update;
02526     }
02527     return result;
02528   }
02529   seq = cdata->_last_update;
02530   return cdata->_external_bounds;
02531 }
02532 
02533 ////////////////////////////////////////////////////////////////////
02534 //     Function: PandaNode::get_nested_vertices
02535 //       Access: Published
02536 //  Description: Returns the total number of vertices that will be
02537 //               rendered by this node and all of its descendents.
02538 //
02539 //               This is not necessarily an accurate count of vertices
02540 //               that will actually be rendered, since this will
02541 //               include all vertices of all LOD's, and it will also
02542 //               include hidden nodes.  It may also omit or only
02543 //               approximate certain kinds of dynamic geometry.
02544 //               However, it will not include stashed nodes.
02545 ////////////////////////////////////////////////////////////////////
02546 int PandaNode::
02547 get_nested_vertices(Thread *current_thread) const {
02548   int pipeline_stage = current_thread->get_pipeline_stage();
02549   CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02550   if (cdata->_last_update != cdata->_next_update) {
02551     // The cache is stale; it needs to be rebuilt.
02552     int result;
02553     {
02554       PStatTimer timer(_update_bounds_pcollector);
02555       CDStageWriter cdataw = 
02556         ((PandaNode *)this)->update_bounds(pipeline_stage, cdata); 
02557       result = cdataw->_nested_vertices;
02558     }
02559     return result;
02560   }
02561   return cdata->_nested_vertices;
02562 }
02563 
02564 ////////////////////////////////////////////////////////////////////
02565 //     Function: PandaNode::mark_bounds_stale
02566 //       Access: Published
02567 //  Description: Indicates that the bounding volume, or something that
02568 //               influences the bounding volume (or any of the other
02569 //               things stored in CData, like net_collide_mask),
02570 //               may have changed for this node, and that it must be
02571 //               recomputed.
02572 //
02573 //               With no parameters, this means to iterate through all
02574 //               stages including and upstream of the current pipeline
02575 //               stage.
02576 //
02577 //               This method is intended for internal use; usually it
02578 //               is not necessary for a user to call this directly.
02579 //               It will be called automatically by derived classes
02580 //               when appropriate.
02581 ////////////////////////////////////////////////////////////////////
02582 void PandaNode::
02583 mark_bounds_stale(Thread *current_thread) const {
02584   OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
02585     mark_bounds_stale(pipeline_stage, current_thread);
02586   }
02587   CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
02588 }
02589 
02590 ////////////////////////////////////////////////////////////////////
02591 //     Function: PandaNode::mark_internal_bounds_stale
02592 //       Access: Published
02593 //  Description: Should be called by a derived class to mark the
02594 //               internal bounding volume stale, so that
02595 //               compute_internal_bounds() will be called when the
02596 //               bounding volume is next requested.
02597 //
02598 //               With no parameters, this means to iterate through all
02599 //               stages including and upstream of the current pipeline
02600 //               stage.
02601 //
02602 //               It is normally not necessary to call this method
02603 //               directly; each node should be responsible for calling
02604 //               it when its internals have changed.
02605 ////////////////////////////////////////////////////////////////////
02606 void PandaNode::
02607 mark_internal_bounds_stale(Thread *current_thread) {
02608   OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
02609     mark_internal_bounds_stale(pipeline_stage, current_thread);
02610   }
02611   CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
02612 }
02613 
02614 ////////////////////////////////////////////////////////////////////
02615 //     Function: PandaNode::is_geom_node
02616 //       Access: Published, Virtual
02617 //  Description: A simple downcast check.  Returns true if this kind
02618 //               of node happens to inherit from GeomNode, false
02619 //               otherwise.
02620 //
02621 //               This is provided as a a faster alternative to calling
02622 //               is_of_type(GeomNode::get_class_type()), since this
02623 //               test is so important to rendering.
02624 ////////////////////////////////////////////////////////////////////
02625 bool PandaNode::
02626 is_geom_node() const {
02627   return false;
02628 }
02629 
02630 ////////////////////////////////////////////////////////////////////
02631 //     Function: PandaNode::is_lod_node
02632 //       Access: Published, Virtual
02633 //  Description: A simple downcast check.  Returns true if this kind
02634 //               of node happens to inherit from LODNode, false
02635 //               otherwise.
02636 //
02637 //               This is provided as a a faster alternative to calling
02638 //               is_of_type(LODNode::get_class_type()).
02639 ////////////////////////////////////////////////////////////////////
02640 bool PandaNode::
02641 is_lod_node() const {
02642   return false;
02643 }
02644 
02645 ////////////////////////////////////////////////////////////////////
02646 //     Function: PandaNode::as_light
02647 //       Access: Published, Virtual
02648 //  Description: Cross-casts the node to a Light pointer, if it is one
02649 //               of the four kinds of Light nodes, or returns NULL if
02650 //               it is not.
02651 ////////////////////////////////////////////////////////////////////
02652 Light *PandaNode::
02653 as_light() {
02654   return NULL;
02655 }
02656 
02657 ////////////////////////////////////////////////////////////////////
02658 //     Function: PandaNode::is_ambient_light
02659 //       Access: Published, Virtual
02660 //  Description: Returns true if this is an AmbientLight, false if it
02661 //               is not a light, or it is some other kind of light.
02662 ////////////////////////////////////////////////////////////////////
02663 bool PandaNode::
02664 is_ambient_light() const {
02665   return false;
02666 }
02667 
02668 ////////////////////////////////////////////////////////////////////
02669 //     Function: PandaNode::decode_from_bam_stream
02670 //       Access: Published, Static
02671 //  Description: Reads the string created by a previous call to
02672 //               encode_to_bam_stream(), and extracts and returns the
02673 //               single object on that string.  Returns NULL on error.
02674 //
02675 //               This method is intended to replace
02676 //               decode_raw_from_bam_stream() when you know the stream
02677 //               in question returns an object of type PandaNode,
02678 //               allowing for easier reference count management.  Note
02679 //               that the caller is still responsible for maintaining
02680 //               the reference count on the return value.
02681 ////////////////////////////////////////////////////////////////////
02682 PT(PandaNode) PandaNode::
02683 decode_from_bam_stream(const string &data, BamReader *reader) {
02684   TypedWritable *object;
02685   ReferenceCount *ref_ptr;
02686 
02687   if (!TypedWritable::decode_raw_from_bam_stream(object, ref_ptr, data, reader)) {
02688     return NULL;
02689   }
02690 
02691   return DCAST(PandaNode, object);
02692 }
02693 
02694 ////////////////////////////////////////////////////////////////////
02695 //     Function: PandaNode::get_internal_bounds
02696 //       Access: Protected
02697 //  Description: Returns the node's internal bounding volume.  This is
02698 //               the bounding volume around the node alone, without
02699 //               including children.
02700 ////////////////////////////////////////////////////////////////////
02701 CPT(BoundingVolume) PandaNode::
02702 get_internal_bounds(int pipeline_stage, Thread *current_thread) const {
02703   while (true) {
02704     UpdateSeq mark;
02705     {
02706       CDStageReader cdata(_cycler, pipeline_stage, current_thread);
02707       if (cdata->_user_bounds != (BoundingVolume *)NULL) {
02708         return cdata->_user_bounds;
02709       }
02710       
02711       if (cdata->_internal_bounds_mark == cdata->_internal_bounds_computed) {
02712         return cdata->_internal_bounds;
02713       }
02714 
02715       mark = cdata->_internal_bounds_mark;
02716     }
02717 
02718     // First, call compute_internal_bounds without acquiring the lock.
02719     // This avoids a deadlock condition.
02720     CPT(BoundingVolume) internal_bounds;
02721     int internal_vertices;
02722     compute_internal_bounds(internal_bounds, internal_vertices,
02723                             pipeline_stage, current_thread);
02724     nassertr(!internal_bounds.is_null(), NULL);
02725     
02726     // Now, acquire the lock, and apply the above-computed bounds.
02727     CDStageWriter cdataw(((PandaNode *)this)->_cycler, pipeline_stage);
02728     if (cdataw->_internal_bounds_mark == mark) {
02729       cdataw->_internal_bounds_computed = mark;
02730       cdataw->_internal_bounds = internal_bounds;
02731       cdataw->_internal_vertices = internal_vertices;
02732       ((PandaNode *)this)->mark_bam_modified();
02733       return cdataw->_internal_bounds;
02734     }
02735 
02736     // Dang, someone in another thread incremented
02737     // _internal_bounds_mark while we weren't holding the lock.  That
02738     // means we need to go back and do it again.
02739   }
02740 }
02741 
02742 ////////////////////////////////////////////////////////////////////
02743 //     Function: PandaNode::get_internal_vertices
02744 //       Access: Protected
02745 //  Description: Returns the total number of vertices that will be
02746 //               rendered by this particular node alone, not
02747 //               accounting for its children.
02748 //
02749 //               This may not include all vertices for certain dynamic
02750 //               effects.
02751 ////////////////////////////////////////////////////////////////////
02752 int PandaNode::
02753 get_internal_vertices(int pipeline_stage, Thread *current_thread) const {
02754   while (true) {
02755     UpdateSeq mark;
02756     {
02757       CDStageReader cdata(_cycler, pipeline_stage, current_thread);
02758       if (cdata->_internal_bounds_mark == cdata->_internal_bounds_computed) {
02759         return cdata->_internal_vertices;
02760       }
02761 
02762       mark = cdata->_internal_bounds_mark;
02763     }
02764 
02765     // First, call compute_internal_bounds without acquiring the lock.
02766     // This avoids a deadlock condition.
02767     CPT(BoundingVolume) internal_bounds;
02768     int internal_vertices;
02769     compute_internal_bounds(internal_bounds, internal_vertices,
02770                             pipeline_stage, current_thread);
02771     nassertr(!internal_bounds.is_null(), 0);
02772     
02773     // Now, acquire the lock, and apply the above-computed bounds.
02774     CDStageWriter cdataw(((PandaNode *)this)->_cycler, pipeline_stage);
02775     if (cdataw->_internal_bounds_mark == mark) {
02776       cdataw->_internal_bounds_computed = mark;
02777       cdataw->_internal_bounds = internal_bounds;
02778       cdataw->_internal_vertices = internal_vertices;
02779       ((PandaNode *)this)->mark_bam_modified();
02780       return cdataw->_internal_vertices;
02781     }
02782 
02783     // Dang, someone in another thread incremented
02784     // _internal_bounds_mark while we weren't holding the lock.  That
02785     // means we need to go back and do it again.
02786   }
02787 }
02788 
02789 ////////////////////////////////////////////////////////////////////
02790 //     Function: PandaNode::set_internal_bounds
02791 //       Access: Protected
02792 //  Description: This is provided as an alternate way for a node to
02793 //               set its own internal bounds, rather than overloading
02794 //               compute_internal_bounds().  If this method is called,
02795 //               the internal bounding volume will immediately be set
02796 //               to the indicated pointer.
02797 ////////////////////////////////////////////////////////////////////
02798 void PandaNode::
02799 set_internal_bounds(const BoundingVolume *volume) {
02800   Thread *current_thread = Thread::get_current_thread();
02801   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02802     CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
02803     cdataw->_internal_bounds = volume;
02804     cdataw->_internal_bounds_computed = cdataw->_internal_bounds_mark;
02805   }
02806   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02807   mark_bounds_stale(current_thread);
02808   mark_bam_modified();
02809 }
02810 
02811 ////////////////////////////////////////////////////////////////////
02812 //     Function: PandaNode::force_bounds_stale
02813 //       Access: Protected
02814 //  Description: Similar to mark_bounds_stale(), except that the
02815 //               parents of this node marked stale even if this node
02816 //               was already considered stale.
02817 //
02818 //               With no parameters, this means to iterate through all
02819 //               stages including and upstream of the current pipeline
02820 //               stage.
02821 ////////////////////////////////////////////////////////////////////
02822 void PandaNode::
02823 force_bounds_stale(Thread *current_thread) {
02824   OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
02825     force_bounds_stale(pipeline_stage, current_thread);
02826   }
02827   CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
02828 }
02829 
02830 ////////////////////////////////////////////////////////////////////
02831 //     Function: PandaNode::force_bounds_stale
02832 //       Access: Protected
02833 //  Description: Similar to mark_bounds_stale(), except that the
02834 //               parents of this node marked stale even if this node
02835 //               was already considered stale.
02836 ////////////////////////////////////////////////////////////////////
02837 void PandaNode::
02838 force_bounds_stale(int pipeline_stage, Thread *current_thread) {
02839   {
02840     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02841     ++cdata->_next_update;
02842     mark_bam_modified();
02843 
02844     // It is important that we allow this lock to be dropped before we
02845     // continue up the graph; otherwise, we risk deadlock from another
02846     // thread walking down the graph.
02847   }
02848 
02849   // It is similarly important that we use get_parents() here to copy
02850   // the parents list, instead of keeping the lock open while we walk
02851   // through the parents list directly on the node.
02852   Parents parents;
02853   {
02854     CDStageReader cdata(_cycler, pipeline_stage, current_thread);
02855     parents = Parents(cdata);
02856   }
02857   int num_parents = parents.get_num_parents();
02858   for (int i = 0; i < num_parents; ++i) {
02859     PandaNode *parent = parents.get_parent(i);
02860     parent->mark_bounds_stale(pipeline_stage, current_thread);
02861   }
02862 }
02863 
02864 ////////////////////////////////////////////////////////////////////
02865 //     Function: PandaNode::r_mark_geom_bounds_stale
02866 //       Access: Protected, Virtual
02867 //  Description: Recursively calls Geom::mark_bounds_stale() on every
02868 //               Geom at this node and below.
02869 ////////////////////////////////////////////////////////////////////
02870 void PandaNode::
02871 r_mark_geom_bounds_stale(Thread *current_thread) {
02872   Children children = get_children(current_thread);
02873 
02874   int i;
02875   for (i = 0; i < children.get_num_children(); i++) {
02876     PandaNode *child = children.get_child(i);
02877     child->r_mark_geom_bounds_stale(current_thread);
02878   }
02879 
02880   Stashed stashed = get_stashed(current_thread);
02881   for (i = 0; i < stashed.get_num_stashed(); i++) {
02882     PandaNode *child = stashed.get_stashed(i);
02883     child->r_mark_geom_bounds_stale(current_thread);
02884   }
02885 }
02886 
02887 ////////////////////////////////////////////////////////////////////
02888 //     Function: PandaNode::compute_internal_bounds
02889 //       Access: Protected, Virtual
02890 //  Description: Returns a newly-allocated BoundingVolume that
02891 //               represents the internal contents of the node.  Should
02892 //               be overridden by PandaNode classes that contain
02893 //               something internally.
02894 ////////////////////////////////////////////////////////////////////
02895 void PandaNode::
02896 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
02897                         int &internal_vertices,
02898                         int pipeline_stage,
02899                         Thread *current_thread) const {
02900   internal_bounds = new BoundingSphere;
02901   internal_vertices = 0;
02902 }
02903 
02904 ////////////////////////////////////////////////////////////////////
02905 //     Function: PandaNode::parents_changed
02906 //       Access: Protected, Virtual
02907 //  Description: Called after a scene graph update that either adds or
02908 //               remove parents from this node, this just provides a
02909 //               hook for derived PandaNode objects that need to
02910 //               update themselves based on the set of parents the
02911 //               node has.
02912 ////////////////////////////////////////////////////////////////////
02913 void PandaNode::
02914 parents_changed() {
02915   nassertv((_unexpected_change_flags & UC_parents) == 0);
02916 }
02917 
02918 ////////////////////////////////////////////////////////////////////
02919 //     Function: PandaNode::children_changed
02920 //       Access: Protected, Virtual
02921 //  Description: Called after a scene graph update that either adds or
02922 //               remove children from this node, this just provides a
02923 //               hook for derived PandaNode objects that need to
02924 //               update themselves based on the set of children the
02925 //               node has.
02926 ////////////////////////////////////////////////////////////////////
02927 void PandaNode::
02928 children_changed() {
02929   nassertv((_unexpected_change_flags & UC_children) == 0);
02930 }
02931 
02932 ////////////////////////////////////////////////////////////////////
02933 //     Function: PandaNode::transform_changed
02934 //       Access: Protected, Virtual
02935 //  Description: Called after the node's transform has been changed
02936 //               for any reason, this just provides a hook so derived
02937 //               classes can do something special in this case.
02938 ////////////////////////////////////////////////////////////////////
02939 void PandaNode::
02940 transform_changed() {
02941   nassertv((_unexpected_change_flags & UC_transform) == 0);
02942 }
02943 
02944 ////////////////////////////////////////////////////////////////////
02945 //     Function: PandaNode::state_changed
02946 //       Access: Protected, Virtual
02947 //  Description: Called after the node's RenderState has been changed
02948 //               for any reason, this just provides a hook so derived
02949 //               classes can do something special in this case.
02950 ////////////////////////////////////////////////////////////////////
02951 void PandaNode::
02952 state_changed() {
02953   nassertv((_unexpected_change_flags & UC_state) == 0);
02954 }
02955 
02956 ////////////////////////////////////////////////////////////////////
02957 //     Function: PandaNode::draw_mask_changed
02958 //       Access: Protected, Virtual
02959 //  Description: Called after the node's DrawMask has been changed
02960 //               for any reason, this just provides a hook so derived
02961 //               classes can do something special in this case.
02962 ////////////////////////////////////////////////////////////////////
02963 void PandaNode::
02964 draw_mask_changed() {
02965   nassertv((_unexpected_change_flags & UC_draw_mask) == 0);
02966 }
02967 
02968 ////////////////////////////////////////////////////////////////////
02969 //     Function: PandaNode::r_copy_subgraph
02970 //       Access: Protected, Virtual
02971 //  Description: This is the recursive implementation of copy_subgraph().
02972 //               It returns a copy of the entire subgraph rooted at
02973 //               this node.
02974 //
02975 //               Note that it includes the parameter inst_map, which
02976 //               is a map type, and is not (and cannot be) exported
02977 //               from PANDA.DLL.  Thus, any derivative of PandaNode
02978 //               that is not also a member of PANDA.DLL *cannot*
02979 //               access this map.
02980 ////////////////////////////////////////////////////////////////////
02981 PT(PandaNode) PandaNode::
02982 r_copy_subgraph(PandaNode::InstanceMap &inst_map, Thread *current_thread) const {
02983   PT(PandaNode) copy = make_copy();
02984   nassertr(copy != (PandaNode *)NULL, NULL);
02985   if (copy->get_type() != get_type()) {
02986     pgraph_cat.warning()
02987       << "Don't know how to copy nodes of type " << get_type() << "\n";
02988 
02989     if (no_unsupported_copy) {
02990       nassertr(false, NULL);
02991     }
02992   }
02993 
02994   copy->r_copy_children(this, inst_map, current_thread);
02995   return copy;
02996 }
02997 
02998 ////////////////////////////////////////////////////////////////////
02999 //     Function: PandaNode::r_copy_children
03000 //       Access: Protected, Virtual
03001 //  Description: This is called by r_copy_subgraph(); the copy has
03002 //               already been made of this particular node (and this
03003 //               is the copy); this function's job is to copy all of
03004 //               the children from the original.
03005 //
03006 //               Note that it includes the parameter inst_map, which
03007 //               is a map type, and is not (and cannot be) exported
03008 //               from PANDA.DLL.  Thus, any derivative of PandaNode
03009 //               that is not also a member of PANDA.DLL *cannot*
03010 //               access this map, and probably should not even
03011 //               override this function.
03012 ////////////////////////////////////////////////////////////////////
03013 void PandaNode::
03014 r_copy_children(const PandaNode *from, PandaNode::InstanceMap &inst_map,
03015                 Thread *current_thread) {
03016   CDReader from_cdata(from->_cycler, current_thread);
03017   CPT(Down) from_down = from_cdata->get_down();
03018   Down::const_iterator di;
03019   for (di = from_down->begin(); di != from_down->end(); ++di) {
03020     int sort = (*di).get_sort();
03021     PandaNode *source_child = (*di).get_child();
03022     PT(PandaNode) dest_child;
03023 
03024     // Check to see if we have already copied this child.  If we
03025     // have, use the copy.  In this way, a subgraph that contains
03026     // instances will be correctly duplicated into another subgraph
03027     // that also contains its own instances.
03028     InstanceMap::const_iterator ci;
03029     ci = inst_map.find(source_child);
03030     if (ci != inst_map.end()) {
03031       dest_child = (*ci).second;
03032     } else {
03033       dest_child = source_child->r_copy_subgraph(inst_map, current_thread);
03034       inst_map[source_child] = dest_child;
03035     }
03036 
03037     quick_add_new_child(dest_child, sort, current_thread);
03038   }
03039 }
03040 
03041 ////////////////////////////////////////////////////////////////////
03042 //     Function: PandaNode::r_prepare_scene
03043 //       Access: Public, Virtual
03044 //  Description: The recursive implementation of prepare_scene().
03045 //               Don't call this directly; call
03046 //               PandaNode::prepare_scene() or
03047 //               NodePath::prepare_scene() instead.
03048 ////////////////////////////////////////////////////////////////////
03049 void PandaNode::
03050 r_prepare_scene(const RenderState *state,
03051                 PreparedGraphicsObjects *prepared_objects,
03052                 Thread *current_thread) {
03053   Children children = get_children(current_thread);
03054   // We must call get_num_children() each time through the loop, in
03055   // case we're running SIMPLE_THREADS and we get interrupted.
03056   int i;
03057   for (i = 0; i < children.get_num_children(); i++) {
03058     PandaNode *child = children.get_child(i);
03059     CPT(RenderState) child_state = state->compose(child->get_state());
03060     child->r_prepare_scene(child_state, prepared_objects, current_thread);
03061   }
03062 
03063   Stashed stashed = get_stashed(current_thread);
03064   for (i = 0; i < stashed.get_num_stashed(); i++) {
03065     PandaNode *child = stashed.get_stashed(i);
03066     CPT(RenderState) child_state = state->compose(child->get_state());
03067     child->r_prepare_scene(child_state, prepared_objects, current_thread);
03068   }
03069 }
03070 
03071 ////////////////////////////////////////////////////////////////////
03072 //     Function: PandaNode::set_cull_callback
03073 //       Access: Protected
03074 //  Description: Intended to be called in the constructor by any
03075 //               subclass that defines cull_callback(), this sets up
03076 //               the flags to indicate that the cullback needs to be
03077 //               called.
03078 ////////////////////////////////////////////////////////////////////
03079 void PandaNode::
03080 set_cull_callback() {
03081   Thread *current_thread = Thread::get_current_thread();
03082   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
03083     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03084     cdata->set_fancy_bit(FB_cull_callback, true);
03085   }
03086   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
03087   mark_bam_modified();
03088 }
03089 
03090 ////////////////////////////////////////////////////////////////////
03091 //     Function: PandaNode::disable_cull_callback
03092 //       Access: Protected
03093 //  Description: disables the call back
03094 ////////////////////////////////////////////////////////////////////
03095 void PandaNode::
03096 disable_cull_callback() {
03097   Thread *current_thread = Thread::get_current_thread();
03098   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
03099     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03100     cdata->set_fancy_bit(FB_cull_callback, false);
03101   }
03102   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
03103   mark_bam_modified();
03104 }
03105 
03106 ////////////////////////////////////////////////////////////////////
03107 //     Function: PandaNode::stage_remove_child
03108 //       Access: Private
03109 //  Description: The private implementation of remove_child(), for a
03110 //               particular pipeline stage.
03111 ////////////////////////////////////////////////////////////////////
03112 bool PandaNode::
03113 stage_remove_child(PandaNode *child_node, int pipeline_stage,
03114                    Thread *current_thread) {
03115   CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03116       
03117   // First, look for the parent in the child's up list, to ensure the
03118   // child is known.
03119   CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
03120                             current_thread);
03121   int parent_index = child_node->do_find_parent(this, cdata_child);
03122   if (parent_index < 0) {
03123     // Nope, no relation.
03124     return false;
03125   }
03126 
03127   PT(Down) down = cdata->modify_down();
03128   int child_index = do_find_child(child_node, down);
03129   if (child_index >= 0) {
03130     // The child exists; remove it.
03131     down->erase(down->begin() + child_index);
03132     int num_erased = cdata_child->modify_up()->erase(UpConnection(this));
03133     nassertr(num_erased == 1, false);
03134     return true;
03135   }
03136 
03137   PT(Down) stashed = cdata->modify_stashed();
03138   int stashed_index = do_find_child(child_node, stashed);
03139   if (stashed_index >= 0) {
03140     // The child has been stashed; remove it.
03141     stashed->erase(stashed->begin() + stashed_index);
03142     int num_erased = cdata_child->modify_up()->erase(UpConnection(this));
03143     nassertr(num_erased == 1, false);
03144     return true;
03145   }
03146 
03147   // Never heard of this child.  This shouldn't be possible, because
03148   // the parent was in the child's up list, above.  Must be some
03149   // internal error.
03150   nassertr(false, false);
03151   return false;
03152 }
03153 
03154 ////////////////////////////////////////////////////////////////////
03155 //     Function: PandaNode::stage_replace_child
03156 //       Access: Private
03157 //  Description: The private implementation of replace_child(), for a
03158 //               particular pipeline stage.
03159 ////////////////////////////////////////////////////////////////////
03160 bool PandaNode::
03161 stage_replace_child(PandaNode *orig_child, PandaNode *new_child,
03162                     int pipeline_stage, Thread *current_thread) {
03163   {
03164     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03165     CDStageWriter cdata_orig_child(orig_child->_cycler, pipeline_stage, current_thread);
03166     CDStageWriter cdata_new_child(new_child->_cycler, pipeline_stage, current_thread);
03167     
03168     // First, look for the parent in the child's up list, to ensure the
03169     // child is known.
03170     int parent_index = orig_child->do_find_parent(this, cdata_orig_child);
03171     if (parent_index < 0) {
03172       // Nope, no relation.
03173       return false;
03174     }
03175     
03176     if (orig_child == new_child) {
03177       // Trivial no-op.
03178       return true;
03179     }
03180     
03181     // Don't let orig_child be destructed yet.
03182     PT(PandaNode) keep_orig_child = orig_child;
03183 
03184     // If we already have new_child as a child, remove it first.
03185     if (stage_remove_child(new_child, pipeline_stage, current_thread)) {
03186       sever_connection(this, new_child, pipeline_stage, current_thread);
03187     }
03188     
03189     PT(Down) down = cdata->modify_down();
03190     int child_index = do_find_child(orig_child, down);
03191     if (child_index >= 0) {
03192       // The child exists; replace it.
03193       DownConnection &dc = (*down)[child_index];
03194       nassertr(dc.get_child() == orig_child, false);
03195       dc.set_child(new_child);
03196       
03197     } else {
03198       PT(Down) stashed = cdata->modify_stashed();
03199       int stashed_index = do_find_child(orig_child, stashed);
03200       if (stashed_index >= 0) {
03201         // The child has been stashed; remove it.
03202         DownConnection &dc = (*stashed)[stashed_index];
03203         nassertr(dc.get_child() == orig_child, false);
03204         dc.set_child(new_child);
03205         
03206       } else {
03207         // Never heard of this child.  This shouldn't be possible, because
03208         // the parent was in the child's up list, above.  Must be some
03209         // internal error.
03210         nassertr(false, false);
03211         return false;
03212       }
03213     }
03214     
03215     // Now adjust the bookkeeping on both children.
03216     cdata_new_child->modify_up()->insert(UpConnection(this));
03217     int num_erased = cdata_orig_child->modify_up()->erase(UpConnection(this));
03218     nassertr(num_erased == 1, false);
03219   }
03220 
03221   sever_connection(this, orig_child, pipeline_stage, current_thread);
03222   new_connection(this, new_child, pipeline_stage, current_thread);
03223 
03224   force_bounds_stale(pipeline_stage, current_thread);
03225   orig_child->parents_changed();
03226   new_child->parents_changed();
03227   mark_bam_modified();
03228   orig_child->mark_bam_modified();
03229   new_child->mark_bam_modified();
03230 
03231   return true;
03232 }
03233 
03234 ////////////////////////////////////////////////////////////////////
03235 //     Function: PandaNode::quick_add_new_child
03236 //       Access: Private
03237 //  Description: Similar to add_child(), but performs fewer checks.
03238 //               The purpose of this method is to add a child node
03239 //               that was newly constructed, to a parent node that was
03240 //               newly constructed, so we know we have to make fewer
03241 //               sanity checks.  This is a private method; do not call
03242 //               it directly.
03243 ////////////////////////////////////////////////////////////////////
03244 void PandaNode::
03245 quick_add_new_child(PandaNode *child_node, int sort, Thread *current_thread) {
03246   // Apply this operation to the current stage as well as to all
03247   // upstream stages.
03248   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
03249     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03250     CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03251     
03252     cdata->modify_down()->insert(DownConnection(child_node, sort));
03253     cdata_child->modify_up()->insert(UpConnection(this));
03254   }
03255   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
03256 }
03257 
03258 ////////////////////////////////////////////////////////////////////
03259 //     Function: PandaNode::report_cycle
03260 //       Access: Private
03261 //  Description: Raises an assertion when a graph cycle attempt is
03262 //               detected (and aborted).
03263 ////////////////////////////////////////////////////////////////////
03264 void PandaNode::
03265 report_cycle(PandaNode *child_node) {
03266   ostringstream strm;
03267   strm << "Detected attempt to create a cycle in the scene graph: " 
03268        << NodePath::any_path(this) << " : " << *child_node;
03269   nassert_raise(strm.str());
03270 }
03271 
03272 ////////////////////////////////////////////////////////////////////
03273 //     Function: PandaNode::find_node_above
03274 //       Access: Private
03275 //  Description: Returns true if the indicated node is this node, or
03276 //               any ancestor of this node; or false if it is not in
03277 //               this node's ancestry.
03278 ////////////////////////////////////////////////////////////////////
03279 bool PandaNode::
03280 find_node_above(PandaNode *node) {
03281   if (node == this) {
03282     return true;
03283   }
03284 
03285   Parents parents = get_parents();
03286   for (int i = 0; i < parents.get_num_parents(); ++i) {
03287     PandaNode *parent = parents.get_parent(i);
03288     if (parent->find_node_above(node)) {
03289       return true;
03290     }
03291   }
03292 
03293   return false;
03294 }
03295 
03296 ////////////////////////////////////////////////////////////////////
03297 //     Function: PandaNode::attach
03298 //       Access: Private, Static
03299 //  Description: Creates a new parent-child relationship, and returns
03300 //               the new NodePathComponent.  If the child was already
03301 //               attached to the indicated parent, repositions it and
03302 //               returns the original NodePathComponent.
03303 //
03304 //               This operation is automatically propagated back up to
03305 //               pipeline 0, from the specified pipeline stage.
03306 ////////////////////////////////////////////////////////////////////
03307 PT(NodePathComponent) PandaNode::
03308 attach(NodePathComponent *parent, PandaNode *child_node, int sort,
03309        int pipeline_stage, Thread *current_thread) {
03310   if (parent == (NodePathComponent *)NULL) {
03311     // Attaching to NULL means to create a new "instance" with no
03312     // attachments, and no questions asked.
03313     PT(NodePathComponent) child = 
03314       new NodePathComponent(child_node, (NodePathComponent *)NULL,
03315                             pipeline_stage, current_thread);
03316     LightReMutexHolder holder(child_node->_paths_lock);
03317     child_node->_paths.insert(child);
03318     return child;
03319   }
03320 
03321   // See if the child was already attached to the parent.  If it was,
03322   // we'll use that same NodePathComponent.
03323   PT(NodePathComponent) child = get_component(parent, child_node, pipeline_stage, current_thread);
03324 
03325   if (child == (NodePathComponent *)NULL) {
03326     // The child was not already attached to the parent, so get a new
03327     // component.
03328     child = get_top_component(child_node, true, pipeline_stage, current_thread);
03329   }
03330 
03331   reparent(parent, child, sort, false, pipeline_stage, current_thread);
03332 
03333   return child;
03334 }
03335 
03336 ////////////////////////////////////////////////////////////////////
03337 //     Function: PandaNode::detach
03338 //       Access: Private, Static
03339 //  Description: Breaks a parent-child relationship.
03340 //
03341 //               This operation is automatically propagated back up to
03342 //               pipeline 0, from the specified pipeline stage.
03343 ////////////////////////////////////////////////////////////////////
03344 void PandaNode::
03345 detach(NodePathComponent *child, int pipeline_stage, Thread *current_thread) {
03346   nassertv(child != (NodePathComponent *)NULL);
03347 
03348   for (int pipeline_stage_i = pipeline_stage;
03349        pipeline_stage_i >= 0; 
03350        --pipeline_stage_i) {
03351     detach_one_stage(child, pipeline_stage_i, current_thread);
03352   }
03353 
03354   child->get_node()->parents_changed();
03355 }
03356 
03357 ////////////////////////////////////////////////////////////////////
03358 //     Function: PandaNode::detach_one_stage
03359 //       Access: Private, Static
03360 //  Description: Breaks a parent-child relationship.
03361 //
03362 //               This operation is not automatically propagated
03363 //               upstream.  It is applied to the indicated pipeline
03364 //               stage only.
03365 ////////////////////////////////////////////////////////////////////
03366 void PandaNode::
03367 detach_one_stage(NodePathComponent *child, int pipeline_stage, 
03368                  Thread *current_thread) {
03369   nassertv(child != (NodePathComponent *)NULL);
03370   if (child->is_top_node(pipeline_stage, current_thread)) {
03371     return;
03372   }
03373 
03374   PT(PandaNode) child_node = child->get_node();
03375   PT(PandaNode) parent_node = child->get_next(pipeline_stage, current_thread)->get_node();
03376     
03377   CDStageWriter cdata_parent(parent_node->_cycler, pipeline_stage, current_thread);
03378   CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03379   int parent_index = child_node->do_find_parent(parent_node, cdata_child);
03380   if (parent_index >= 0) {
03381     // Now look for the child and break the actual connection.
03382     
03383     // First, look for and remove the parent node from the child's up
03384     // list.
03385     int num_erased = cdata_child->modify_up()->erase(UpConnection(parent_node));
03386     nassertv(num_erased == 1);
03387     
03388     // Now, look for and remove the child node from the parent's down
03389     // list.  We also check in the stashed list, in case the child node
03390     // has been stashed.
03391     Down::iterator di;
03392     bool found = false;
03393     PT(Down) down = cdata_parent->modify_down();
03394     for (di = down->begin(); di != down->end(); ++di) {
03395       if ((*di).get_child() == child_node) {
03396         down->erase(di);
03397         found = true;
03398         break;
03399       }
03400     }
03401     if (!found) {
03402       PT(Down) stashed = cdata_parent->modify_stashed();
03403       for (di = stashed->begin(); di != stashed->end(); ++di) {
03404         if ((*di).get_child() == child_node) {
03405           stashed->erase(di);
03406           found = true;
03407           break;
03408         }
03409       }
03410     }
03411     nassertv(found);
03412   }
03413     
03414   // Finally, break the NodePathComponent connection.
03415   sever_connection(parent_node, child_node, pipeline_stage, current_thread);
03416 
03417   parent_node->force_bounds_stale(pipeline_stage, current_thread);
03418   parent_node->children_changed();
03419   parent_node->mark_bam_modified();
03420 }
03421 
03422 ////////////////////////////////////////////////////////////////////
03423 //     Function: PandaNode::reparent
03424 //       Access: Private, Static
03425 //  Description: Switches a node from one parent to another.  Returns
03426 //               true if the new connection is allowed, or false if it
03427 //               conflicts with another instance (that is, another
03428 //               instance of the child is already attached to the
03429 //               indicated parent).
03430 //
03431 //               This operation is automatically propagated back up to
03432 //               pipeline 0, from the specified pipeline stage.
03433 ////////////////////////////////////////////////////////////////////
03434 bool PandaNode::
03435 reparent(NodePathComponent *new_parent, NodePathComponent *child, int sort,
03436          bool as_stashed, int pipeline_stage, Thread *current_thread) {
03437   bool any_ok = false;
03438 
03439   if (new_parent != (NodePathComponent *)NULL &&
03440       !new_parent->get_node()->verify_child_no_cycles(child->get_node())) {
03441     // Whoops, adding this child node would introduce a cycle in the
03442     // scene graph.
03443     return false;
03444   }
03445 
03446   for (int pipeline_stage_i = pipeline_stage;
03447        pipeline_stage_i >= 0; 
03448        --pipeline_stage_i) {
03449     if (reparent_one_stage(new_parent, child, sort, as_stashed, 
03450                            pipeline_stage_i, current_thread)) {
03451       any_ok = true;
03452     }
03453   }
03454 
03455   if (new_parent != (NodePathComponent *)NULL) {
03456     new_parent->get_node()->children_changed();
03457     new_parent->get_node()->mark_bam_modified();
03458   }
03459   child->get_node()->parents_changed();
03460   child->get_node()->mark_bam_modified();
03461 
03462   return any_ok;
03463 }
03464 
03465 ////////////////////////////////////////////////////////////////////
03466 //     Function: PandaNode::reparent_one_stage
03467 //       Access: Private, Static
03468 //  Description: Switches a node from one parent to another.  Returns
03469 //               true if the new connection is allowed, or false if it
03470 //               conflicts with another instance (that is, another
03471 //               instance of the child is already attached to the
03472 //               indicated parent).
03473 //
03474 //               This operation is not automatically propagated
03475 //               upstream.  It is applied to the indicated pipeline
03476 //               stage only.
03477 ////////////////////////////////////////////////////////////////////
03478 bool PandaNode::
03479 reparent_one_stage(NodePathComponent *new_parent, NodePathComponent *child, 
03480                    int sort, bool as_stashed, int pipeline_stage, 
03481                    Thread *current_thread) {
03482   nassertr(child != (NodePathComponent *)NULL, false);
03483 
03484   // Keep a reference count to the new parent, since detaching the
03485   // child might lose the count.
03486   PT(NodePathComponent) keep_parent = new_parent;
03487 
03488   if (!child->is_top_node(pipeline_stage, current_thread)) {
03489     detach(child, pipeline_stage, current_thread);
03490   }
03491 
03492   if (new_parent != (NodePathComponent *)NULL) {
03493     PandaNode *child_node = child->get_node();
03494     PandaNode *parent_node = new_parent->get_node();
03495 
03496     {
03497       CDStageReader cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03498       int parent_index = child_node->do_find_parent(parent_node, cdata_child);
03499 
03500       if (parent_index >= 0) {
03501         // Whoops, there's already another instance of the child there.
03502         return false;
03503       }
03504     }
03505 
03506     // Redirect the connection to the indicated new parent.
03507     child->set_next(new_parent, pipeline_stage, current_thread);
03508     
03509     // Now reattach the child node at the indicated sort position.
03510     {
03511       CDStageWriter cdata_parent(parent_node->_cycler, pipeline_stage, current_thread);
03512       CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03513 
03514       if (as_stashed) {
03515         cdata_parent->modify_stashed()->insert(DownConnection(child_node, sort));
03516       } else {
03517         cdata_parent->modify_down()->insert(DownConnection(child_node, sort));
03518       }
03519       cdata_child->modify_up()->insert(UpConnection(parent_node));
03520 
03521 #ifndef NDEBUG
03522       // The NodePathComponent should already be in the set.
03523       {
03524         LightReMutexHolder holder(child_node->_paths_lock);
03525         nassertr(child_node->_paths.find(child) != child_node->_paths.end(), false);
03526       }
03527 #endif // NDEBUG
03528     }
03529 
03530     child_node->fix_path_lengths(pipeline_stage, current_thread);
03531     parent_node->force_bounds_stale(pipeline_stage, current_thread);
03532   }
03533 
03534   return true;
03535 }
03536 
03537 ////////////////////////////////////////////////////////////////////
03538 //     Function: PandaNode::get_component
03539 //       Access: Private, Static
03540 //  Description: Returns the NodePathComponent based on the indicated
03541 //               child of the given parent, or NULL if there is no
03542 //               such parent-child relationship.
03543 ////////////////////////////////////////////////////////////////////
03544 PT(NodePathComponent) PandaNode::
03545 get_component(NodePathComponent *parent, PandaNode *child_node,
03546               int pipeline_stage, Thread *current_thread) {
03547   nassertr(parent != (NodePathComponent *)NULL, (NodePathComponent *)NULL);
03548   PandaNode *parent_node = parent->get_node();
03549 
03550   LightReMutexHolder holder(child_node->_paths_lock);
03551 
03552   // First, walk through the list of NodePathComponents we already
03553   // have on the child, looking for one that already exists,
03554   // referencing the indicated parent component.
03555   Paths::const_iterator pi;
03556   for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
03557     if ((*pi)->get_next(pipeline_stage, current_thread) == parent) {
03558       // If we already have such a component, just return it.
03559       return (*pi);
03560     }
03561   }
03562     
03563   // We don't already have a NodePathComponent referring to this
03564   // parent-child relationship.  Are they actually related?
03565   CDStageReader cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03566   int parent_index = child_node->do_find_parent(parent_node, cdata_child);
03567   
03568   if (parent_index >= 0) {
03569     // They are.  Create and return a new one.
03570     PT(NodePathComponent) child = 
03571       new NodePathComponent(child_node, parent, pipeline_stage, current_thread);
03572     child_node->_paths.insert(child);
03573     return child;
03574   } else {
03575     // They aren't related.  Return NULL.
03576     return NULL;
03577   }
03578 }
03579 
03580 ////////////////////////////////////////////////////////////////////
03581 //     Function: PandaNode::get_top_component
03582 //       Access: Private, Static
03583 //  Description: Returns a NodePathComponent referencing the
03584 //               indicated node as a singleton.  It is invalid to call
03585 //               this for a node that has parents, unless you are
03586 //               about to create a new instance (and immediately
03587 //               reconnect the NodePathComponent elsewhere).
03588 //
03589 //               If force is true, this will always return something,
03590 //               even if it needs to create a new top component;
03591 //               otherwise, if force is false, it will return NULL if
03592 //               there is not already a top component available.
03593 ////////////////////////////////////////////////////////////////////
03594 PT(NodePathComponent) PandaNode::
03595 get_top_component(PandaNode *child_node, bool force, int pipeline_stage, 
03596                   Thread *current_thread) {
03597   LightReMutexHolder holder(child_node->_paths_lock);
03598 
03599   // Walk through the list of NodePathComponents we already have on
03600   // the child, looking for one that already exists as a top node.
03601   Paths::const_iterator pi;
03602   for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
03603     if ((*pi)->is_top_node(pipeline_stage, current_thread)) {
03604       // If we already have such a component, just return it.
03605       return (*pi);
03606     }
03607   }
03608 
03609   if (!force) {
03610     // If we don't care to force the point, return NULL to indicate
03611     // there's not already a top component.
03612     return NULL;
03613   }
03614 
03615   // We don't already have such a NodePathComponent; create and
03616   // return a new one.
03617   PT(NodePathComponent) child = 
03618     new NodePathComponent(child_node, (NodePathComponent *)NULL,
03619                           pipeline_stage, current_thread);
03620   child_node->_paths.insert(child);
03621 
03622   return child;
03623 }
03624 
03625 ////////////////////////////////////////////////////////////////////
03626 //     Function: PandaNode::get_generic_component
03627 //       Access: Private
03628 //  Description: Returns a NodePathComponent referencing this node as
03629 //               a path from the root.  
03630 //
03631 //               Unless accept_ambiguity is true, it is only valid to
03632 //               call this if there is an unambiguous path from the
03633 //               root; otherwise, a warning will be issued and one
03634 //               path will be chosen arbitrarily.
03635 ////////////////////////////////////////////////////////////////////
03636 PT(NodePathComponent) PandaNode::
03637 get_generic_component(bool accept_ambiguity, int pipeline_stage, 
03638                       Thread *current_thread) {
03639   bool ambiguity_detected = false;
03640   PT(NodePathComponent) result = 
03641     r_get_generic_component(accept_ambiguity, ambiguity_detected,
03642                             pipeline_stage, current_thread);
03643 
03644   if (!accept_ambiguity && ambiguity_detected) {
03645     pgraph_cat.warning()
03646       << "Chose: " << *result << "\n";
03647     nassertr(!unambiguous_graph, result);
03648   }
03649 
03650   return result;
03651 }
03652 
03653 ////////////////////////////////////////////////////////////////////
03654 //     Function: PandaNode::r_get_generic_component
03655 //       Access: Private
03656 //  Description: The recursive implementation of
03657 //               get_generic_component, this simply sets the flag when
03658 //               the ambiguity is detected (so we can report the
03659 //               bottom node that started the ambiguous search).
03660 ////////////////////////////////////////////////////////////////////
03661 PT(NodePathComponent) PandaNode::
03662 r_get_generic_component(bool accept_ambiguity, bool &ambiguity_detected,
03663                         int pipeline_stage, Thread *current_thread) {
03664   PT(PandaNode) parent_node;
03665 
03666   {
03667     CDStageReader cdata(_cycler, pipeline_stage, current_thread);
03668     
03669     int num_parents = cdata->get_up()->size();
03670     if (num_parents == 0) {
03671       // No parents; no ambiguity.  This is the root.
03672       return get_top_component(this, true, pipeline_stage, current_thread);
03673     } 
03674 
03675     PT(NodePathComponent) result;
03676     if (num_parents == 1) {
03677       // Only one parent; no ambiguity.
03678       PT(NodePathComponent) parent = 
03679         get_parent(0)->r_get_generic_component(accept_ambiguity, ambiguity_detected, pipeline_stage, current_thread);
03680       return get_component(parent, this, pipeline_stage, current_thread);
03681     }
03682 
03683     // Oops, multiple parents; the NodePath is ambiguous.
03684     if (!accept_ambiguity) {
03685       pgraph_cat.warning()
03686         << *this << " has " << num_parents
03687         << " parents; choosing arbitrary path to root.\n";
03688     }
03689     ambiguity_detected = true;
03690     CPT(Up) up = cdata->get_up();
03691     parent_node = (*up)[0].get_parent();
03692   }
03693 
03694   // Now that the lock is released, it's safe to recurse.
03695   PT(NodePathComponent) parent = 
03696     parent_node->r_get_generic_component(accept_ambiguity, ambiguity_detected, pipeline_stage, current_thread);
03697   return get_component(parent, this, pipeline_stage, current_thread);
03698 }
03699 
03700 ////////////////////////////////////////////////////////////////////
03701 //     Function: PandaNode::delete_component
03702 //       Access: Private
03703 //  Description: Removes a NodePathComponent from the set prior to
03704 //               its deletion.  This should only be called by the
03705 //               NodePathComponent destructor.
03706 ////////////////////////////////////////////////////////////////////
03707 void PandaNode::
03708 delete_component(NodePathComponent *component) {
03709   LightReMutexHolder holder(_paths_lock);
03710   int num_erased = _paths.erase(component);
03711   nassertv(num_erased == 1);
03712 }
03713 
03714 ////////////////////////////////////////////////////////////////////
03715 //     Function: PandaNode::sever_connection
03716 //       Access: Private, Static
03717 //  Description: This is called internally when a parent-child
03718 //               connection is broken to update the NodePathComponents
03719 //               that reflected this connection.
03720 //
03721 //               It severs any NodePathComponents on the child node
03722 //               that reference the indicated parent node.  These
03723 //               components remain unattached; there may therefore be
03724 //               multiple "instances" of a node that all have no
03725 //               parent, even while there are other instances that do
03726 //               have parents.
03727 //
03728 //               This operation is not automatically propagated
03729 //               upstream.  It is applied to the indicated pipeline
03730 //               stage only.
03731 ////////////////////////////////////////////////////////////////////
03732 void PandaNode::
03733 sever_connection(PandaNode *parent_node, PandaNode *child_node,
03734                  int pipeline_stage, Thread *current_thread) {
03735   {
03736     LightReMutexHolder holder(child_node->_paths_lock);
03737     Paths::iterator pi;
03738     for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
03739       if (!(*pi)->is_top_node(pipeline_stage, current_thread) && 
03740           (*pi)->get_next(pipeline_stage, current_thread)->get_node() == parent_node) {
03741         // Sever the component here.
03742         (*pi)->set_top_node(pipeline_stage, current_thread);
03743       }
03744     }
03745   }
03746   child_node->fix_path_lengths(pipeline_stage, current_thread);
03747 }
03748 
03749 ////////////////////////////////////////////////////////////////////
03750 //     Function: PandaNode::new_connection
03751 //       Access: Private, Static
03752 //  Description: This is called internally when a parent-child
03753 //               connection is established to update the
03754 //               NodePathComponents that might be involved.
03755 //
03756 //               It adjusts any NodePathComponents the child has that
03757 //               reference the child as a top node.  Any other
03758 //               components we can leave alone, because we are making
03759 //               a new instance of the child.
03760 //
03761 //               This operation is not automatically propagated
03762 //               upstream.  It is applied to the indicated pipeline
03763 //               stage only.
03764 ////////////////////////////////////////////////////////////////////
03765 void PandaNode::
03766 new_connection(PandaNode *parent_node, PandaNode *child_node,
03767                int pipeline_stage, Thread *current_thread) {
03768   {
03769     LightReMutexHolder holder(child_node->_paths_lock);
03770     Paths::iterator pi;
03771     for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
03772       if ((*pi)->is_top_node(pipeline_stage, current_thread)) {
03773         (*pi)->set_next(parent_node->get_generic_component(false, pipeline_stage, current_thread), pipeline_stage, current_thread);
03774       }
03775     }
03776   }
03777   child_node->fix_path_lengths(pipeline_stage, current_thread);
03778 }
03779 
03780 ////////////////////////////////////////////////////////////////////
03781 //     Function: PandaNode::fix_path_lengths
03782 //       Access: Private
03783 //  Description: Recursively fixes the _length member of each
03784 //               NodePathComponent at this level and below, after an
03785 //               add or delete child operation that might have messed
03786 //               these up.
03787 //
03788 //               This operation is not automatically propagated
03789 //               upstream.  It is applied to the indicated pipeline
03790 //               stage only.
03791 ////////////////////////////////////////////////////////////////////
03792 void PandaNode::
03793 fix_path_lengths(int pipeline_stage, Thread *current_thread) {
03794   LightReMutexHolder holder(_paths_lock);
03795 
03796   bool any_wrong = false;
03797 
03798   Paths::const_iterator pi;
03799   for (pi = _paths.begin(); pi != _paths.end(); ++pi) {
03800     if ((*pi)->fix_length(pipeline_stage, current_thread)) {
03801       any_wrong = true;
03802     }
03803   }
03804   
03805   // If any paths were updated, we have to recurse on all of our
03806   // children, since any one of those paths might be shared by any of
03807   // our child nodes.  Don't hold any locks while we recurse.
03808   if (any_wrong) {
03809     Children children;
03810     Stashed stashed;
03811     {
03812       CDStageReader cdata(_cycler, pipeline_stage, current_thread);
03813       children = Children(cdata);
03814       stashed = Stashed(cdata);
03815     }
03816 
03817     int num_children = children.get_num_children();
03818     int i;
03819     for (i = 0; i < num_children; ++i) {
03820       PandaNode *child_node = children.get_child(i);
03821       child_node->fix_path_lengths(pipeline_stage, current_thread);
03822     }
03823     int num_stashed = stashed.get_num_stashed();
03824     for (i = 0; i < num_stashed; ++i) {
03825       PandaNode *child_node = stashed.get_stashed(i);
03826       child_node->fix_path_lengths(pipeline_stage, current_thread);
03827     }
03828   }
03829 }
03830 
03831 ////////////////////////////////////////////////////////////////////
03832 //     Function: PandaNode::r_list_descendants
03833 //       Access: Private
03834 //  Description: The recursive implementation of ls().
03835 ////////////////////////////////////////////////////////////////////
03836 void PandaNode::
03837 r_list_descendants(ostream &out, int indent_level) const {
03838   write(out, indent_level);
03839 
03840   Children children = get_children();
03841   int num_children = children.get_num_children();
03842 
03843   for (int i = 0; i < num_children; ++i) {
03844     PandaNode *child = children.get_child(i);
03845     child->r_list_descendants(out, indent_level + 2);
03846   }
03847 
03848   // Also report the number of stashed nodes at this level.
03849   int num_stashed = get_num_stashed();
03850   if (num_stashed != 0) {
03851     indent(out, indent_level) << "(" << num_stashed << " stashed)\n";
03852   }
03853 }
03854 
03855 ////////////////////////////////////////////////////////////////////
03856 //     Function: PandaNode::do_find_child
03857 //       Access: Private
03858 //  Description: The private implementation of find_child().
03859 ////////////////////////////////////////////////////////////////////
03860 int PandaNode::
03861 do_find_child(PandaNode *node, const PandaNode::Down *down) const {
03862   nassertr(node != (PandaNode *)NULL, -1);
03863 
03864   // We have to search for the child by brute force, since we don't
03865   // know what sort index it was added as.
03866   Down::const_iterator di;
03867   for (di = down->begin(); di != down->end(); ++di) {
03868     if ((*di).get_child() == node) {
03869       return di - down->begin();
03870     }
03871   }
03872 
03873   return -1;
03874 }
03875 
03876 ////////////////////////////////////////////////////////////////////
03877 //     Function: PandaNode::update_bounds
03878 //       Access: Private
03879 //  Description: Updates the cached values of the node that are
03880 //               dependent on its children, such as the
03881 //               external bounding volume, the _net_collide_mask, and
03882 //               the _off_clip_planes.
03883 //
03884 //               The old value should be passed in; it will be
03885 //               released.  The new value is returned.
03886 ////////////////////////////////////////////////////////////////////
03887 PandaNode::CDStageWriter PandaNode::
03888 update_bounds(int pipeline_stage, PandaNode::CDLockedStageReader &cdata) {
03889   // We might need to try this a couple of times, in case someone else
03890   // steps on our result.
03891   if (drawmask_cat.is_debug()) {
03892     drawmask_cat.debug(false) 
03893       << *this << "::update_bounds() {\n";
03894   }
03895   Thread *current_thread = cdata.get_current_thread();
03896 
03897   do {
03898     // Grab the last_update counter.
03899     UpdateSeq last_update = cdata->_last_update;
03900     UpdateSeq next_update = cdata->_next_update;
03901     nassertr(last_update != next_update, CDStageWriter(_cycler, pipeline_stage, cdata));
03902 
03903     // Start with a clean slate.
03904     CollideMask net_collide_mask = cdata->_into_collide_mask;
03905     DrawMask net_draw_control_mask, net_draw_show_mask;
03906     bool renderable = is_renderable();
03907 
03908     if (renderable) {
03909       // If this node is itself renderable, it contributes to the net
03910       // draw mask.
03911       net_draw_control_mask = cdata->_draw_control_mask;
03912       net_draw_show_mask = cdata->_draw_show_mask;
03913     }
03914 
03915     if (drawmask_cat.is_debug()) {
03916       drawmask_cat.debug(false)
03917         << "net_draw_control_mask = " << net_draw_control_mask
03918         << "\nnet_draw_show_mask = " << net_draw_show_mask
03919         << "\n";
03920     }
03921     CPT(RenderAttrib) off_clip_planes = cdata->_state->get_attrib(ClipPlaneAttrib::get_class_slot());
03922     if (off_clip_planes == (RenderAttrib *)NULL) {
03923       off_clip_planes = ClipPlaneAttrib::make();
03924     }
03925 
03926     // Also get the list of the node's children.
03927     Children children(cdata);
03928 
03929     int num_vertices = cdata->_internal_vertices;
03930 
03931     // Now that we've got all the data we need from the node, we can
03932     // release the lock.
03933     _cycler.release_read_stage(pipeline_stage, cdata.take_pointer());
03934 
03935     int num_children = children.get_num_children();
03936 
03937     // We need to keep references to the bounding volumes, since in a
03938     // threaded environment the pointers might go away while we're
03939     // working (since we're not holding a lock on our set of children
03940     // right now).  But we also need the regular pointers, to pass to
03941     // BoundingVolume::around().
03942 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
03943     pvector<CPT(BoundingVolume) > child_volumes_ref;
03944     child_volumes_ref.reserve(num_children + 1);
03945 #endif
03946     const BoundingVolume **child_volumes = (const BoundingVolume **)alloca(sizeof(BoundingVolume *) * (num_children + 1));
03947     int child_volumes_i = 0;
03948   
03949     bool all_box = true;
03950     CPT(BoundingVolume) internal_bounds = 
03951       get_internal_bounds(pipeline_stage, current_thread);
03952 
03953     if (!internal_bounds->is_empty()) {
03954 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
03955       child_volumes_ref.push_back(internal_bounds);
03956 #endif
03957       nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
03958       child_volumes[child_volumes_i++] = internal_bounds;
03959       if (internal_bounds->as_bounding_box() == NULL) {
03960         all_box = false;
03961       }
03962     }
03963 
03964     // Now expand those contents to include all of our children.
03965 
03966     for (int i = 0; i < num_children; ++i) {
03967       PandaNode *child = children.get_child(i);
03968 
03969       const ClipPlaneAttrib *orig_cp = DCAST(ClipPlaneAttrib, off_clip_planes);
03970       
03971       CDLockedStageReader child_cdata(child->_cycler, pipeline_stage, current_thread);
03972       if (child_cdata->_last_update != child_cdata->_next_update) {
03973         // Child needs update.
03974         CDStageWriter child_cdataw = child->update_bounds(pipeline_stage, child_cdata);
03975       
03976         net_collide_mask |= child_cdataw->_net_collide_mask;
03977 
03978         if (drawmask_cat.is_debug()) {
03979           drawmask_cat.debug(false)
03980             << "\nchild update " << *child << ":\n";
03981         }
03982 
03983         DrawMask child_control_mask = child_cdataw->_net_draw_control_mask;
03984         DrawMask child_show_mask = child_cdataw->_net_draw_show_mask;
03985         if (!(child_control_mask | child_show_mask).is_zero()) {
03986           // This child includes a renderable node or subtree.  Thus,
03987           // we should propagate its draw masks.
03988           renderable = true;
03989 
03990           // For each bit position in the masks, we have assigned the
03991           // following semantic meaning.  The number on the left
03992           // represents the pairing of the corresponding bit from the
03993           // control mask and from the show mask:
03994           
03995           //   00 : not a renderable node   (control 0, show 0)
03996           //   01 : a normally visible node (control 0, show 1)
03997           //   10 : a hidden node           (control 1, show 0)
03998           //   11 : a show-through node     (control 1, show 1)
03999 
04000           // Now, when we accumulate these masks, we want to do so
04001           // according to the following table, for each bit position:
04002 
04003           //          00   01   10   11     (child)
04004           //        ---------------------
04005           //     00 | 00   01   10   11
04006           //     01 | 01   01   01*  11
04007           //     10 | 10   01*  10   11
04008           //     11 | 11   11   11   11
04009           // (parent)
04010 
04011           // This table is almost the same as the union of both masks,
04012           // with one exception, marked with a * in the above table:
04013           // if one is 10 and the other is 01--that is, one is hidden
04014           // and the other is normally visible--then the result should
04015           // be 01, normally visible.  This is because we only want to
04016           // propagate the hidden bit upwards if *all* renderable
04017           // nodes are hidden.
04018 
04019           // Get the set of exception bits for which the above rule
04020           // applies.  These are the bits for which both bits have
04021           // flipped, but which were not the same in the original.
04022           DrawMask exception_mask = (net_draw_control_mask ^ child_control_mask) & (net_draw_show_mask ^ child_show_mask);
04023           exception_mask &= (net_draw_control_mask ^ net_draw_show_mask);
04024 
04025           if (drawmask_cat.is_debug()) {
04026             drawmask_cat.debug(false)
04027               << "exception_mask = " << exception_mask << "\n";
04028           }
04029 
04030           // Now compute the union, applying the above exception.
04031           net_draw_control_mask |= child_control_mask;
04032           net_draw_show_mask |= child_show_mask;
04033           
04034           net_draw_control_mask &= ~exception_mask;
04035           net_draw_show_mask |= exception_mask;
04036         }
04037 
04038         if (drawmask_cat.is_debug()) {
04039           drawmask_cat.debug(false)
04040             << "child_control_mask = " << child_control_mask
04041             << "\nchild_show_mask = " << child_show_mask
04042             << "\nnet_draw_control_mask = " << net_draw_control_mask
04043             << "\nnet_draw_show_mask = " << net_draw_show_mask
04044             << "\n";
04045         }
04046             
04047         off_clip_planes = orig_cp->compose_off(child_cdataw->_off_clip_planes);
04048         if (!child_cdataw->_external_bounds->is_empty()) {
04049 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04050           child_volumes_ref.push_back(child_cdataw->_external_bounds);
04051 #endif
04052           nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
04053           child_volumes[child_volumes_i++] = child_cdataw->_external_bounds;
04054           if (child_cdataw->_external_bounds->as_bounding_box() == NULL) {
04055             all_box = false;
04056           }
04057         }
04058         num_vertices += child_cdataw->_nested_vertices;
04059 
04060       } else {
04061         // Child is good.
04062         net_collide_mask |= child_cdata->_net_collide_mask;
04063 
04064         // See comments in similar block above.
04065         if (drawmask_cat.is_debug()) {
04066           drawmask_cat.debug(false)
04067             << "\nchild fresh " << *child << ":\n";
04068         }
04069         DrawMask child_control_mask = child_cdata->_net_draw_control_mask;
04070         DrawMask child_show_mask = child_cdata->_net_draw_show_mask;
04071         if (!(child_control_mask | child_show_mask).is_zero()) {
04072           renderable = true;
04073 
04074           DrawMask exception_mask = (net_draw_control_mask ^ child_control_mask) & (net_draw_show_mask ^ child_show_mask);
04075           exception_mask &= (net_draw_control_mask ^ net_draw_show_mask);
04076 
04077           if (drawmask_cat.is_debug()) {
04078             drawmask_cat.debug(false)
04079               << "exception_mask = " << exception_mask << "\n";
04080           }
04081 
04082           // Now compute the union, applying the above exception.
04083           net_draw_control_mask |= child_control_mask;
04084           net_draw_show_mask |= child_show_mask;
04085           
04086           net_draw_control_mask &= ~exception_mask;
04087           net_draw_show_mask |= exception_mask;
04088         }
04089 
04090         if (drawmask_cat.is_debug()) {
04091           drawmask_cat.debug(false)
04092             << "child_control_mask = " << child_control_mask
04093             << "\nchild_show_mask = " << child_show_mask
04094             << "\nnet_draw_control_mask = " << net_draw_control_mask
04095             << "\nnet_draw_show_mask = " << net_draw_show_mask
04096             << "\n";
04097         }
04098 
04099         off_clip_planes = orig_cp->compose_off(child_cdata->_off_clip_planes);
04100         if (!child_cdata->_external_bounds->is_empty()) {
04101 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04102           child_volumes_ref.push_back(child_cdata->_external_bounds);
04103 #endif
04104           nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
04105           child_volumes[child_volumes_i++] = child_cdata->_external_bounds;
04106           if (child_cdata->_external_bounds->as_bounding_box() == NULL) {
04107             all_box = false;
04108           }
04109         }
04110         num_vertices += child_cdata->_nested_vertices;
04111       }
04112     }
04113 
04114     {
04115       // Now grab the write lock on this node.
04116       CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
04117       if (last_update == cdataw->_last_update && 
04118           next_update == cdataw->_next_update) {
04119         // Great, no one has monkeyed with these while we were computing
04120         // the cache.  Safe to store the computed values and return.
04121         cdataw->_net_collide_mask = net_collide_mask;
04122 
04123         if (renderable) {
04124           // Any explicit draw control mask on this node trumps anything
04125           // inherited from below, except a show-through.
04126           DrawMask draw_control_mask = cdataw->_draw_control_mask;
04127           DrawMask draw_show_mask = cdataw->_draw_show_mask;
04128 
04129           DrawMask show_through_mask = net_draw_control_mask & net_draw_show_mask;
04130           
04131           net_draw_control_mask |= draw_control_mask;
04132           net_draw_show_mask = (net_draw_show_mask & ~draw_control_mask) | (draw_show_mask & draw_control_mask);
04133 
04134           net_draw_show_mask |= show_through_mask;
04135           
04136           // There are renderable nodes below, so the implicit draw
04137           // bits are all on.
04138           cdataw->_net_draw_control_mask = net_draw_control_mask;
04139           cdataw->_net_draw_show_mask = net_draw_show_mask | ~net_draw_control_mask;
04140           if (drawmask_cat.is_debug()) {
04141             drawmask_cat.debug(false)
04142               << "renderable, set mask " << cdataw->_net_draw_show_mask << "\n";
04143           }
04144         } else {
04145           // There are no renderable nodes below, so the implicit draw
04146           // bits are all off.  Also, we don't care about the draw
04147           // mask on this particular node (since nothing below it is
04148           // renderable anyway).
04149           cdataw->_net_draw_control_mask = net_draw_control_mask;
04150           cdataw->_net_draw_show_mask = net_draw_show_mask;
04151           if (drawmask_cat.is_debug()) {
04152             drawmask_cat.debug(false)
04153               << "not renderable, set mask " << cdataw->_net_draw_show_mask << "\n";
04154           }
04155         }
04156 
04157         cdataw->_off_clip_planes = off_clip_planes;
04158         cdataw->_nested_vertices = num_vertices;
04159 
04160         CPT(TransformState) transform = get_transform(current_thread);
04161         PT(GeometricBoundingVolume) gbv;
04162 
04163         BoundingVolume::BoundsType btype = cdataw->_bounds_type;
04164         if (btype == BoundingVolume::BT_default) {
04165           btype = bounds_type;
04166         }
04167 
04168         if (btype == BoundingVolume::BT_box ||
04169             (btype != BoundingVolume::BT_sphere && all_box && transform->is_identity())) {
04170           // If all of the child volumes are a BoundingBox, and we
04171           // have no transform, then our volume is also a
04172           // BoundingBox.
04173           
04174           gbv = new BoundingBox;
04175         } else {
04176           // Otherwise, it's a sphere.
04177           gbv = new BoundingSphere;
04178         }
04179         
04180         if (child_volumes_i > 0) {
04181           const BoundingVolume **child_begin = &child_volumes[0];
04182           const BoundingVolume **child_end = child_begin + child_volumes_i;
04183           ((BoundingVolume *)gbv)->around(child_begin, child_end);
04184         }
04185         
04186         // If we have a transform, apply it to the bounding volume we
04187         // just computed.
04188         if (!transform->is_identity()) {
04189           gbv->xform(transform->get_mat());
04190         }
04191 
04192         cdataw->_external_bounds = gbv;
04193         cdataw->_last_update = next_update;
04194 
04195         if (drawmask_cat.is_debug()) {
04196           drawmask_cat.debug(false)
04197             << "} " << *this << "::update_bounds();\n";
04198         }
04199 
04200         nassertr(cdataw->_last_update == cdataw->_next_update, cdataw);
04201     
04202         // Even though implicit bounding volume is not (yet?) part of
04203         // the bam stream.
04204         mark_bam_modified();
04205         return cdataw;
04206       }
04207       
04208       if (cdataw->_last_update == cdataw->_next_update) {
04209         // Someone else has computed the cache for us.  OK.
04210         return cdataw;
04211       }
04212     }
04213 
04214     // We need to go around again.  Release the write lock, and grab
04215     // the read lock back.
04216     cdata = CDLockedStageReader(_cycler, pipeline_stage, current_thread);
04217 
04218     if (cdata->_last_update == cdata->_next_update) {
04219       // Someone else has computed the cache for us while we were
04220       // diddling with the locks.  OK.
04221       return CDStageWriter(_cycler, pipeline_stage, cdata);
04222     }
04223 
04224   } while (true);
04225 }
04226 
04227 ////////////////////////////////////////////////////////////////////
04228 //     Function: PandaNode::set_scene_root_func
04229 //       Access: Public, Static
04230 //  Description: This is used by the GraphicsEngine to hook in a
04231 //               pointer to the scene_root_func(), the function to
04232 //               determine whether the node is an active scene root.
04233 //               This back-pointer is necessary because we can't make
04234 //               calls directly into GraphicsEngine, which is in the
04235 //               display module.
04236 ////////////////////////////////////////////////////////////////////
04237 void PandaNode::
04238 set_scene_root_func(SceneRootFunc *func) {
04239   _scene_root_func = func;
04240 }
04241 
04242 ////////////////////////////////////////////////////////////////////
04243 //     Function: PandaNode::register_with_read_factory
04244 //       Access: Public, Static
04245 //  Description: Tells the BamReader how to create objects of type
04246 //               PandaNode.
04247 ////////////////////////////////////////////////////////////////////
04248 void PandaNode::
04249 register_with_read_factory() {
04250   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
04251 }
04252 
04253 ////////////////////////////////////////////////////////////////////
04254 //     Function: PandaNode::write_datagram
04255 //       Access: Public, Virtual
04256 //  Description: Writes the contents of this object to the datagram
04257 //               for shipping out to a Bam file.
04258 ////////////////////////////////////////////////////////////////////
04259 void PandaNode::
04260 write_datagram(BamWriter *manager, Datagram &dg) {
04261   TypedWritable::write_datagram(manager, dg);
04262   dg.add_string(get_name());
04263 
04264   manager->write_cdata(dg, _cycler);
04265 }
04266 
04267 ////////////////////////////////////////////////////////////////////
04268 //     Function: PandaNode::update_bam_nested
04269 //       Access: Public, Virtual
04270 //  Description: Called by the BamWriter when this object has not
04271 //               itself been modified recently, but it should check
04272 //               its nested objects for updates.
04273 ////////////////////////////////////////////////////////////////////
04274 void PandaNode::
04275 update_bam_nested(BamWriter *manager) {
04276   CDReader cdata(_cycler);
04277   cdata->update_bam_nested(manager);
04278 }
04279 
04280 ////////////////////////////////////////////////////////////////////
04281 //     Function: PandaNode::write_recorder
04282 //       Access: Public
04283 //  Description: This method is provided for the benefit of classes
04284 //               (like MouseRecorder) that inherit from PandaMode and
04285 //               also RecorderBase.  It's not virtual at this level
04286 //               since it doesn't need to be (it's called up from the
04287 //               derived class).
04288 //
04289 //               This method acts very like write_datagram, but it
04290 //               writes the node as appropriate for writing a
04291 //               RecorderBase object as described in the beginning of
04292 //               a session file, meaning it doesn't need to write
04293 //               things such as children.  It balances with
04294 //               fillin_recorder().
04295 ////////////////////////////////////////////////////////////////////
04296 void PandaNode::
04297 write_recorder(BamWriter *, Datagram &dg) {
04298   dg.add_string(get_name());
04299 }
04300 
04301 ////////////////////////////////////////////////////////////////////
04302 //     Function: PandaNode::make_from_bam
04303 //       Access: Protected, Static
04304 //  Description: This function is called by the BamReader's factory
04305 //               when a new object of type PandaNode is encountered
04306 //               in the Bam file.  It should create the PandaNode
04307 //               and extract its information from the file.
04308 ////////////////////////////////////////////////////////////////////
04309 TypedWritable *PandaNode::
04310 make_from_bam(const FactoryParams &params) {
04311   PandaNode *node = new PandaNode("");
04312   DatagramIterator scan;
04313   BamReader *manager;
04314 
04315   parse_params(params, scan, manager);
04316   node->fillin(scan, manager);
04317 
04318   return node;
04319 }
04320 
04321 ////////////////////////////////////////////////////////////////////
04322 //     Function: PandaNode::fillin
04323 //       Access: Protected
04324 //  Description: This internal function is called by make_from_bam to
04325 //               read in all of the relevant data from the BamFile for
04326 //               the new PandaNode.
04327 ////////////////////////////////////////////////////////////////////
04328 void PandaNode::
04329 fillin(DatagramIterator &scan, BamReader *manager) {
04330   TypedWritable::fillin(scan, manager);
04331 
04332   string name = scan.get_string();
04333   set_name(name);
04334 
04335   manager->read_cdata(scan, _cycler);
04336 }
04337 
04338 ////////////////////////////////////////////////////////////////////
04339 //     Function: PandaNode::fillin_recorder
04340 //       Access: Protected
04341 //  Description: This internal function is called by make_recorder (in
04342 //               classes derived from RecorderBase, such as
04343 //               MouseRecorder) to read in all of the relevant data
04344 //               from the session file.  It balances with
04345 //               write_recorder().
04346 ////////////////////////////////////////////////////////////////////
04347 void PandaNode::
04348 fillin_recorder(DatagramIterator &scan, BamReader *) {
04349   string name = scan.get_string();
04350   set_name(name);
04351 }
04352 
04353 ////////////////////////////////////////////////////////////////////
04354 //     Function: PandaNode::CData::Constructor
04355 //       Access: Public
04356 //  Description:
04357 ////////////////////////////////////////////////////////////////////
04358 PandaNode::CData::
04359 CData() :
04360   _state(RenderState::make_empty()),
04361   _transform(TransformState::make_identity()),
04362   _prev_transform(TransformState::make_identity()),
04363 
04364   _effects(RenderEffects::make_empty()),
04365   _draw_control_mask(DrawMask::all_off()),
04366   _draw_show_mask(DrawMask::all_on()),
04367   _into_collide_mask(CollideMask::all_off()),
04368   _bounds_type(BoundingVolume::BT_default),
04369   _user_bounds(NULL),
04370   _final_bounds(false),
04371   _fancy_bits(0),
04372 
04373   _net_collide_mask(CollideMask::all_off()),
04374   _net_draw_control_mask(DrawMask::all_off()),
04375   _net_draw_show_mask(DrawMask::all_off()),
04376 
04377   _down(new PandaNode::Down(PandaNode::get_class_type())),
04378   _stashed(new PandaNode::Down(PandaNode::get_class_type())),
04379   _up(new PandaNode::Up(PandaNode::get_class_type()))
04380 {
04381   ++_next_update;
04382 }
04383 
04384 ////////////////////////////////////////////////////////////////////
04385 //     Function: PandaNode::CData::Copy Constructor
04386 //       Access: Public
04387 //  Description:
04388 ////////////////////////////////////////////////////////////////////
04389 PandaNode::CData::
04390 CData(const PandaNode::CData &copy) :
04391   BoundsData(copy),
04392   _state(copy._state),
04393   _transform(copy._transform),
04394   _prev_transform(copy._prev_transform),
04395 
04396   _effects(copy._effects),
04397   _tag_data(copy._tag_data),
04398   _draw_control_mask(copy._draw_control_mask),
04399   _draw_show_mask(copy._draw_show_mask),
04400   _into_collide_mask(copy._into_collide_mask),
04401   _bounds_type(copy._bounds_type),
04402   _user_bounds(copy._user_bounds),
04403   _final_bounds(copy._final_bounds),
04404   _fancy_bits(copy._fancy_bits),
04405 
04406   _net_collide_mask(copy._net_collide_mask),
04407   _net_draw_control_mask(copy._net_draw_control_mask),
04408   _net_draw_show_mask(copy._net_draw_show_mask),
04409   _off_clip_planes(copy._off_clip_planes),
04410   _nested_vertices(copy._nested_vertices),
04411   _external_bounds(copy._external_bounds),
04412   _last_update(copy._last_update),
04413   _next_update(copy._next_update),
04414 
04415   _down(copy._down),
04416   _stashed(copy._stashed),
04417   _up(copy._up)
04418 {
04419   // Note that this copy constructor is not used by the PandaNode copy
04420   // constructor!  Any elements that must be copied between nodes
04421   // should also be explicitly copied there.
04422 
04423 #ifdef HAVE_PYTHON
04424   // Copy and increment all of the Python objects held by the other
04425   // node.
04426   _python_tag_data = _python_tag_data;
04427   inc_py_refs();
04428 #endif  // HAVE_PYTHON
04429 }
04430 
04431 ////////////////////////////////////////////////////////////////////
04432 //     Function: PandaNode::CData::Destructor
04433 //       Access: Public, Virtual
04434 //  Description:
04435 ////////////////////////////////////////////////////////////////////
04436 PandaNode::CData::
04437 ~CData() {
04438 #ifdef HAVE_PYTHON
04439   // Free all of the Python objects held by this node.
04440   dec_py_refs();
04441 #endif  // HAVE_PYTHON
04442 }
04443 
04444 ////////////////////////////////////////////////////////////////////
04445 //     Function: PandaNode::CData::make_copy
04446 //       Access: Public, Virtual
04447 //  Description:
04448 ////////////////////////////////////////////////////////////////////
04449 CycleData *PandaNode::CData::
04450 make_copy() const {
04451   return new CData(*this);
04452 }
04453 
04454 ////////////////////////////////////////////////////////////////////
04455 //     Function: PandaNode::CData::write_datagram
04456 //       Access: Public, Virtual
04457 //  Description: Writes the contents of this object to the datagram
04458 //               for shipping out to a Bam file.
04459 ////////////////////////////////////////////////////////////////////
04460 void PandaNode::CData::
04461 write_datagram(BamWriter *manager, Datagram &dg) const {
04462   manager->write_pointer(dg, _state);
04463   manager->write_pointer(dg, _transform);
04464 
04465   //
04466   manager->write_pointer(dg, _effects);
04467 
04468   dg.add_uint32(_draw_control_mask.get_word());
04469   dg.add_uint32(_draw_show_mask.get_word());
04470   dg.add_uint32(_into_collide_mask.get_word());
04471   dg.add_uint8(_bounds_type);
04472 
04473   dg.add_uint32(_tag_data.size());
04474   TagData::const_iterator ti;
04475   for (ti = _tag_data.begin(); ti != _tag_data.end(); ++ti) {
04476     dg.add_string((*ti).first);
04477     dg.add_string((*ti).second);
04478   }
04479 
04480   //
04481   write_up_list(*get_up(), manager, dg);
04482   write_down_list(*get_down(), manager, dg);
04483   write_down_list(*get_stashed(), manager, dg);
04484 }
04485 
04486 ////////////////////////////////////////////////////////////////////
04487 //     Function: PandaNode::CData::update_bam_nested
04488 //       Access: Public
04489 //  Description: Called by the BamWriter when this object has not
04490 //               itself been modified recently, but it should check
04491 //               its nested objects for updates.
04492 ////////////////////////////////////////////////////////////////////
04493 void PandaNode::CData::
04494 update_bam_nested(BamWriter *manager) const {
04495   // No need to check the state pointers for updates, since they're
04496   // all immutable objects.
04497   //manager->consider_update(_state);
04498   //manager->consider_update(_transform);
04499   //manager->consider_update(_effects);
04500 
04501   update_up_list(*get_up(), manager);
04502   update_down_list(*get_down(), manager);
04503   update_down_list(*get_stashed(), manager);
04504 }
04505 
04506 ////////////////////////////////////////////////////////////////////
04507 //     Function: PandaNode::CData::complete_pointers
04508 //       Access: Public, Virtual
04509 //  Description: Receives an array of pointers, one for each time
04510 //               manager->read_pointer() was called in fillin().
04511 //               Returns the number of pointers processed.
04512 ////////////////////////////////////////////////////////////////////
04513 int PandaNode::CData::
04514 complete_pointers(TypedWritable **p_list, BamReader *manager) {
04515   int pi = CycleData::complete_pointers(p_list, manager);
04516 
04517   // Get the state and transform pointers.
04518   _state = DCAST(RenderState, p_list[pi++]);
04519   _transform = DCAST(TransformState, p_list[pi++]);
04520   _prev_transform = _transform;
04521 
04522   // Finalize these pointers now to decrement their artificially-held
04523   // reference counts.  We do this now, rather than later, in case
04524   // some other object reassigns them a little later on during
04525   // initialization, before they can finalize themselves normally (for
04526   // instance, the character may change the node's transform).  If
04527   // that happens, the pointer may discover that no one else holds its
04528   // reference count when it finalizes, which will constitute a memory
04529   // leak (see the comments in TransformState::finalize(), etc.).
04530   manager->finalize_now((RenderState *)_state.p());
04531   manager->finalize_now((TransformState *)_transform.p());
04532 
04533   //
04534 
04535   // Get the effects pointer.
04536   _effects = DCAST(RenderEffects, p_list[pi++]);
04537 
04538   // Finalize these pointers now to decrement their artificially-held
04539   // reference counts.  We do this now, rather than later, in case
04540   // some other object reassigns them a little later on during
04541   // initialization, before they can finalize themselves normally (for
04542   // instance, the character may change the node's transform).  If
04543   // that happens, the pointer may discover that no one else holds its
04544   // reference count when it finalizes, which will constitute a memory
04545   // leak (see the comments in TransformState::finalize(), etc.).
04546   manager->finalize_now((RenderEffects *)_effects.p());
04547 
04548   //
04549 
04550   // Get the parent and child pointers.
04551   pi += complete_up_list(*modify_up(), "up", p_list + pi, manager);
04552   pi += complete_down_list(*modify_down(), "down", p_list + pi, manager);
04553   pi += complete_down_list(*modify_stashed(), "stashed", p_list + pi, manager);
04554 
04555   // Since the _effects and _states members have been finalized by
04556   // now, this should be safe.
04557   set_fancy_bit(FB_transform, !_transform->is_identity());
04558   set_fancy_bit(FB_state, !_state->is_empty());
04559   set_fancy_bit(FB_effects, !_effects->is_empty());
04560   set_fancy_bit(FB_tag, !_tag_data.empty());
04561 
04562   return pi;
04563 }
04564 
04565 ////////////////////////////////////////////////////////////////////
04566 //     Function: PandaNode::CData::fillin
04567 //       Access: Public, Virtual
04568 //  Description: This internal function is called by make_from_bam to
04569 //               read in all of the relevant data from the BamFile for
04570 //               the new PandaNode.
04571 ////////////////////////////////////////////////////////////////////
04572 void PandaNode::CData::
04573 fillin(DatagramIterator &scan, BamReader *manager) {
04574   // Read the state and transform pointers.
04575   manager->read_pointer(scan);
04576   manager->read_pointer(scan);
04577 
04578   //
04579   // Read the effects pointer.
04580   manager->read_pointer(scan);
04581 
04582   if (manager->get_file_minor_ver() < 2) {
04583     DrawMask draw_mask;
04584     draw_mask.set_word(scan.get_uint32());
04585 
04586     if (draw_mask == DrawMask::all_off()) {
04587       // Hidden.
04588       _draw_control_mask = _overall_bit;
04589       _draw_show_mask = ~_overall_bit;
04590 
04591     } else if (draw_mask == DrawMask::all_on()) {
04592       // Normally visible.
04593       _draw_control_mask = DrawMask::all_off();
04594       _draw_show_mask = DrawMask::all_on();
04595 
04596     } else {
04597       // Some per-camera combination.
04598       draw_mask &= ~_overall_bit;
04599       _draw_control_mask = ~draw_mask;
04600       _draw_show_mask = draw_mask;
04601     }
04602 
04603   } else {
04604     _draw_control_mask.set_word(scan.get_uint32());
04605     _draw_show_mask.set_word(scan.get_uint32());
04606   }
04607 
04608   _into_collide_mask.set_word(scan.get_uint32());
04609 
04610   _bounds_type = BoundingVolume::BT_default;
04611   if (manager->get_file_minor_ver() >= 19) {
04612     _bounds_type = (BoundingVolume::BoundsType)scan.get_uint8();
04613   }
04614 
04615   // Read in the tag list.
04616   int num_tags = scan.get_uint32();
04617   for (int i = 0; i < num_tags; i++) {
04618     string key = scan.get_string();
04619     string value = scan.get_string();
04620     _tag_data[key] = value;
04621   }
04622 
04623   //
04624   fillin_up_list(*modify_up(), "up", scan, manager);
04625   fillin_down_list(*modify_down(), "down", scan, manager);
04626   fillin_down_list(*modify_stashed(), "stashed", scan, manager);
04627 }
04628 
04629 #ifdef HAVE_PYTHON
04630 ////////////////////////////////////////////////////////////////////
04631 //     Function: PandaNode::CData::inc_py_refs
04632 //       Access: Public
04633 //  Description: Increments the reference counts on all held Python
04634 //               objects.
04635 ////////////////////////////////////////////////////////////////////
04636 void PandaNode::CData::
04637 inc_py_refs() {
04638   PythonTagData::const_iterator ti;
04639   for (ti = _python_tag_data.begin();
04640        ti != _python_tag_data.end();
04641        ++ti) {
04642     PyObject *value = (*ti).second;
04643     Py_XINCREF(value);
04644   }
04645 }
04646 #endif  // HAVE_PYTHON
04647 
04648 #ifdef HAVE_PYTHON
04649 ////////////////////////////////////////////////////////////////////
04650 //     Function: PandaNode::CData::dec_py_refs
04651 //       Access: Public
04652 //  Description: Decrements the reference counts on all held Python
04653 //               objects.
04654 ////////////////////////////////////////////////////////////////////
04655 void PandaNode::CData::
04656 dec_py_refs() {
04657   PythonTagData::const_iterator ti;
04658   for (ti = _python_tag_data.begin();
04659        ti != _python_tag_data.end();
04660        ++ti) {
04661     PyObject *value = (*ti).second;
04662     Py_XDECREF(value);
04663   }
04664 }
04665 #endif  // HAVE_PYTHON
04666 
04667 ////////////////////////////////////////////////////////////////////
04668 //     Function: PandaNode::CData::write_up_list
04669 //       Access: Public
04670 //  Description: Writes the indicated list of parent node pointers to
04671 //               the datagram.
04672 ////////////////////////////////////////////////////////////////////
04673 void PandaNode::CData::
04674 write_up_list(const PandaNode::Up &up_list,
04675               BamWriter *manager, Datagram &dg) const {
04676   // When we write a PandaNode, we write out its complete list of
04677   // child node pointers, but we only write out the parent node
04678   // pointers that have already been added to the bam file by a
04679   // previous write operation.  This is a bit of trickery that allows
04680   // us to write out just a subgraph (instead of the complete graph)
04681   // when we write out an arbitrary node in the graph, yet also allows
04682   // us to keep nodes completely in sync when we use the bam format
04683   // for streaming scene graph operations over the network.
04684 
04685   int num_parents = 0;
04686   Up::const_iterator ui;
04687   for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
04688     PandaNode *parent_node = (*ui).get_parent();
04689     if (manager->has_object(parent_node)) {
04690       num_parents++;
04691     }
04692   }
04693   nassertv(num_parents == (int)(PN_uint16)num_parents);
04694   dg.add_uint16(num_parents);
04695   for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
04696     PandaNode *parent_node = (*ui).get_parent();
04697     if (manager->has_object(parent_node)) {
04698       manager->write_pointer(dg, parent_node);
04699     }
04700   }
04701 }
04702 
04703 ////////////////////////////////////////////////////////////////////
04704 //     Function: PandaNode::CData::write_down_list
04705 //       Access: Public
04706 //  Description: Writes the indicated list of child node pointers to
04707 //               the datagram.
04708 ////////////////////////////////////////////////////////////////////
04709 void PandaNode::CData::
04710 write_down_list(const PandaNode::Down &down_list,
04711                 BamWriter *manager, Datagram &dg) const {
04712   int num_children = down_list.size();
04713   nassertv(num_children == (int)(PN_uint16)num_children);
04714   dg.add_uint16(num_children);
04715 
04716   // Should we smarten up the writing of the sort number?  Most of the
04717   // time these will all be zero.
04718   Down::const_iterator di;
04719   for (di = down_list.begin(); di != down_list.end(); ++di) {
04720     PandaNode *child_node = (*di).get_child();
04721     int sort = (*di).get_sort();
04722     manager->write_pointer(dg, child_node);
04723     dg.add_int32(sort);
04724   }
04725 }
04726 
04727 ////////////////////////////////////////////////////////////////////
04728 //     Function: PandaNode::CData::update_up_list
04729 //       Access: Public
04730 //  Description: Calls consider_update on each node of the indicated
04731 //               up list.
04732 ////////////////////////////////////////////////////////////////////
04733 void PandaNode::CData::
04734 update_up_list(const PandaNode::Up &up_list, BamWriter *manager) const {
04735   Up::const_iterator ui;
04736   for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
04737     PandaNode *parent_node = (*ui).get_parent();
04738     if (manager->has_object(parent_node)) {
04739       manager->consider_update(parent_node);
04740     }
04741   }
04742 }
04743 
04744 ////////////////////////////////////////////////////////////////////
04745 //     Function: PandaNode::CData::update_down_list
04746 //       Access: Public
04747 //  Description: Calls consider_update on each node of the indicated
04748 //               up list.
04749 ////////////////////////////////////////////////////////////////////
04750 void PandaNode::CData::
04751 update_down_list(const PandaNode::Down &down_list, BamWriter *manager) const {
04752   Down::const_iterator di;
04753   for (di = down_list.begin(); di != down_list.end(); ++di) {
04754     PandaNode *child_node = (*di).get_child();
04755     manager->consider_update(child_node);
04756   }
04757 }
04758 
04759 ////////////////////////////////////////////////////////////////////
04760 //     Function: PandaNode::CData::complete_up_list
04761 //       Access: Public
04762 //  Description: Calls complete_pointers() on the list of parent node
04763 //               pointers.
04764 ////////////////////////////////////////////////////////////////////
04765 int PandaNode::CData::
04766 complete_up_list(PandaNode::Up &up_list, const string &tag,
04767                  TypedWritable **p_list, BamReader *manager) {
04768   int pi = 0;
04769 
04770   int num_parents = manager->get_int_tag(tag);
04771   Up new_up_list(PandaNode::get_class_type());
04772   new_up_list.reserve(num_parents);
04773   for (int i = 0; i < num_parents; i++) {
04774     PandaNode *parent_node = DCAST(PandaNode, p_list[pi++]);
04775     UpConnection connection(parent_node);
04776     new_up_list.push_back(connection);
04777   }
04778 
04779   // Now we should sort the list, since the sorting is based on
04780   // pointer order, which might be different from one session to the
04781   // next.
04782   new_up_list.sort();
04783 
04784   // Make it permanent.
04785   up_list.swap(new_up_list);
04786   new_up_list.clear();
04787 
04788   return pi;
04789 }
04790 
04791 ////////////////////////////////////////////////////////////////////
04792 //     Function: PandaNode::CData::complete_down_list
04793 //       Access: Public
04794 //  Description: Calls complete_pointers() on the list of child node
04795 //               pointers.
04796 ////////////////////////////////////////////////////////////////////
04797 int PandaNode::CData::
04798 complete_down_list(PandaNode::Down &down_list, const string &tag,
04799                    TypedWritable **p_list, BamReader *manager) {
04800   int pi = 0;
04801 
04802   BamReaderAuxDataDown *aux;
04803   DCAST_INTO_R(aux, manager->get_aux_tag(tag), pi);
04804 
04805   Down &new_down_list = aux->_down_list;
04806   for (Down::iterator di = new_down_list.begin();
04807        di != new_down_list.end(); 
04808        ++di) {
04809     PandaNode *child_node = DCAST(PandaNode, p_list[pi++]);
04810     (*di).set_child(child_node);
04811   }
04812 
04813   // Unlike the up list, we should *not* sort the down list.  The down
04814   // list is stored in a specific order, not related to pointer order;
04815   // and this order should be preserved from one session to the next.
04816 
04817   // Make it permanent.
04818   down_list.swap(new_down_list);
04819   new_down_list.clear();
04820 
04821   return pi;
04822 }
04823 
04824 ////////////////////////////////////////////////////////////////////
04825 //     Function: PandaNode::CData::fillin_up_list
04826 //       Access: Public
04827 //  Description: Reads the indicated list parent node pointers from
04828 //               the datagram (or at least calls read_pointer() for
04829 //               each one).
04830 ////////////////////////////////////////////////////////////////////
04831 void PandaNode::CData::
04832 fillin_up_list(PandaNode::Up &up_list, const string &tag,
04833                DatagramIterator &scan, BamReader *manager) {
04834   int num_parents = scan.get_uint16();
04835   manager->set_int_tag(tag, num_parents);
04836   manager->read_pointers(scan, num_parents);
04837 }
04838 
04839 ////////////////////////////////////////////////////////////////////
04840 //     Function: PandaNode::CData::fillin_down_list
04841 //       Access: Public
04842 //  Description: Reads the indicated list child node pointers from
04843 //               the datagram (or at least calls read_pointer() for
04844 //               each one).
04845 ////////////////////////////////////////////////////////////////////
04846 void PandaNode::CData::
04847 fillin_down_list(PandaNode::Down &down_list, const string &tag,
04848                  DatagramIterator &scan, BamReader *manager) {
04849   int num_children = scan.get_uint16();
04850 
04851   // Create a temporary down_list, with the right number of elements,
04852   // but a NULL value for each pointer (we'll fill in the pointers
04853   // later).  We need to do this to associate the sort values with
04854   // their pointers.
04855   Down new_down_list(PandaNode::get_class_type());
04856   new_down_list.reserve(num_children);
04857   for (int i = 0; i < num_children; i++) {
04858     manager->read_pointer(scan);
04859     int sort = scan.get_int32();
04860     DownConnection connection(NULL, sort);
04861     new_down_list.push_back(connection);
04862   }
04863 
04864   // Now store the temporary down_list in the BamReader, so we can get
04865   // it during the call to complete_down_list().
04866   PT(BamReaderAuxDataDown) aux = new BamReaderAuxDataDown;
04867   aux->_down_list.swap(new_down_list);
04868   manager->set_aux_tag(tag, aux);
04869 }
04870 
04871 ////////////////////////////////////////////////////////////////////
04872 //     Function: PandaNodePipelineReader::check_bounds
04873 //       Access: Public
04874 //  Description: Ensures that the bounding volume is properly computed
04875 //               on this node.
04876 ////////////////////////////////////////////////////////////////////
04877 void PandaNodePipelineReader::
04878 check_bounds() const {
04879   if (_cdata->_last_update != _cdata->_next_update) {
04880     // The cache is stale; it needs to be rebuilt.
04881 
04882     // We'll need to get a fresh read pointer, since another thread
04883     // might already have modified the pointer on the object since we
04884     // queried it.
04885 #ifdef DO_PIPELINING
04886     node_unref_delete((CycleData *)_cdata);
04887 #endif  // DO_PIPELINING
04888     ((PandaNodePipelineReader *)this)->_cdata = NULL;
04889     int pipeline_stage = _current_thread->get_pipeline_stage();
04890     PandaNode::CDLockedStageReader fresh_cdata(_object->_cycler, pipeline_stage, _current_thread);
04891     if (fresh_cdata->_last_update == fresh_cdata->_next_update) {
04892       // What luck, some other thread has already freshened the
04893       // cache for us.  Save the new pointer, and let the lock
04894       // release itself.
04895       if (_cdata != (const PandaNode::CData *)fresh_cdata) {
04896         ((PandaNodePipelineReader *)this)->_cdata = fresh_cdata;
04897 #ifdef DO_PIPELINING
04898         _cdata->node_ref();
04899 #endif  // DO_PIPELINING
04900       }
04901       
04902     } else {
04903       // No, the cache is still stale.  We have to do the work of
04904       // freshening it.
04905       PStatTimer timer(PandaNode::_update_bounds_pcollector);
04906       PandaNode::CDStageWriter cdataw = ((PandaNode *)_object)->update_bounds(pipeline_stage, fresh_cdata);
04907       nassertv(cdataw->_last_update == cdataw->_next_update);
04908       // As above, we save the new pointer, and then let the lock
04909       // release itself.
04910       if (_cdata != (const PandaNode::CData *)cdataw) {
04911         ((PandaNodePipelineReader *)this)->_cdata = cdataw;
04912 #ifdef DO_PIPELINING
04913         _cdata->node_ref();
04914 #endif  // DO_PIPELINING
04915       }
04916     }
04917   }
04918 
04919   nassertv(_cdata->_last_update == _cdata->_next_update);
04920 }
 All Classes Functions Variables Enumerations