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