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: Filename::get_tag_keys
01726 //       Access: Published
01727 //  Description: Fills the given vector up with the
01728 //               list of tags on this PandaNode.
01729 //
01730 //               It is the user's responsibility to ensure that the
01731 //               keys vector is empty before making this call;
01732 //               otherwise, the new keys will be appended to it.
01733 ////////////////////////////////////////////////////////////////////
01734 void PandaNode::
01735 get_tag_keys(vector_string &keys) const {
01736   CDReader cdata(_cycler);
01737   if (!cdata->_tag_data.empty()) {
01738     TagData::const_iterator ti = cdata->_tag_data.begin();
01739     while (ti != cdata->_tag_data.end()) {
01740       keys.push_back((*ti).first);
01741       ++ti;
01742     }
01743   }
01744 }
01745 
01746 #ifdef HAVE_PYTHON
01747 ////////////////////////////////////////////////////////////////////
01748 //     Function: Filename::get_python_tag_keys
01749 //       Access: Published
01750 //  Description: Fills the given vector up with the
01751 //               list of Python tags on this PandaNode.
01752 //
01753 //               It is the user's responsibility to ensure that the
01754 //               keys vector is empty before making this call;
01755 //               otherwise, the new files will be appended to it.
01756 ////////////////////////////////////////////////////////////////////
01757 void PandaNode::
01758 get_python_tag_keys(vector_string &keys) const {
01759   CDReader cdata(_cycler);
01760   if (!cdata->_python_tag_data.empty()) {
01761     PythonTagData::const_iterator ti = cdata->_python_tag_data.begin();
01762     while (ti != cdata->_python_tag_data.end()) {
01763       keys.push_back((*ti).first);
01764       ++ti;
01765     }
01766   }
01767 }
01768 
01769 ////////////////////////////////////////////////////////////////////
01770 //     Function: Filename::get_tag_keys
01771 //       Access: Published
01772 //  Description: This variant on get_tag_keys returns
01773 //               a Python list of strings.
01774 ////////////////////////////////////////////////////////////////////
01775 PyObject *PandaNode::
01776 get_tag_keys() const {
01777   vector_string keys;
01778   get_tag_keys(keys);
01779 
01780   PyObject *result = PyList_New(keys.size());
01781   for (size_t i = 0; i < keys.size(); ++i) {
01782     const string &tag_name = keys[i];
01783 #if PY_MAJOR_VERSION >= 3
01784     PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size());
01785 #else
01786     PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size());
01787 #endif
01788     PyList_SET_ITEM(result, i, str);
01789   }
01790 
01791   return result;
01792 }
01793 
01794 ////////////////////////////////////////////////////////////////////
01795 //     Function: Filename::get_python_tag_keys
01796 //       Access: Published
01797 //  Description: This variant on get_python_tag_keys returns
01798 //               a Python list of strings.
01799 ////////////////////////////////////////////////////////////////////
01800 PyObject *PandaNode::
01801 get_python_tag_keys() const {
01802   vector_string keys;
01803   get_python_tag_keys(keys);
01804 
01805   PyObject *result = PyList_New(keys.size());
01806   for (size_t i = 0; i < keys.size(); ++i) {
01807     const string &tag_name = keys[i];
01808 #if PY_MAJOR_VERSION >= 3
01809     PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size());
01810 #else
01811     PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size());
01812 #endif
01813     PyList_SET_ITEM(result, i, str);
01814   }
01815 
01816   return result;
01817 }
01818 #endif  // HAVE_PYTHON
01819 
01820 ////////////////////////////////////////////////////////////////////
01821 //     Function: PandaNode::compare_tags
01822 //       Access: Published
01823 //  Description: Returns a number less than 0, 0, or greater than 0,
01824 //               to indicate the similarity of tags between this node
01825 //               and the other one.  If this returns 0, the tags are
01826 //               identical.  If it returns other than 0, then the tags
01827 //               are different; and the nodes may be sorted into a
01828 //               consistent (but arbitrary) ordering based on this
01829 //               number.
01830 ////////////////////////////////////////////////////////////////////
01831 int PandaNode::
01832 compare_tags(const PandaNode *other) const {
01833   CDReader cdata(_cycler);
01834   CDReader cdata_other(other->_cycler);
01835 
01836   TagData::const_iterator ati = cdata->_tag_data.begin();
01837   TagData::const_iterator bti = cdata_other->_tag_data.begin();
01838   while (ati != cdata->_tag_data.end() &&
01839          bti != cdata_other->_tag_data.end()) {
01840     int cmp = strcmp((*ati).first.c_str(), (*bti).first.c_str());
01841     if (cmp != 0) {
01842       return cmp;
01843     }
01844 
01845     cmp = strcmp((*ati).second.c_str(), (*bti).second.c_str());
01846     if (cmp != 0) {
01847       return cmp;
01848     }
01849 
01850     ++ati;
01851     ++bti;
01852   }
01853   if (ati != cdata->_tag_data.end()) {
01854     // list A is longer.
01855     return 1;
01856   }
01857   if (bti != cdata_other->_tag_data.end()) {
01858     // list B is longer.
01859     return -1;
01860   }
01861 
01862 #ifdef HAVE_PYTHON
01863   PythonTagData::const_iterator api = cdata->_python_tag_data.begin();
01864   PythonTagData::const_iterator bpi = cdata_other->_python_tag_data.begin();
01865   while (api != cdata->_python_tag_data.end() &&
01866          bpi != cdata_other->_python_tag_data.end()) {
01867     int cmp = strcmp((*api).first.c_str(), (*bpi).first.c_str());
01868     if (cmp != 0) {
01869       return cmp;
01870     }
01871 
01872 #if PY_MAJOR_VERSION >= 3
01873     if (PyObject_RichCompareBool((*api).second, (*bpi).second, Py_LT) == 1) {
01874       return -1;
01875     } else if (PyObject_RichCompareBool((*api).second, (*bpi).second, Py_GT) == 1) {
01876       return 1;
01877     } else if (PyObject_RichCompareBool((*api).second, (*bpi).second, Py_EQ) == 1) {
01878       cmp = 0;
01879     } else {
01880 #else
01881     if (PyObject_Cmp((*api).second, (*bpi).second, &cmp) == -1) {
01882 #endif
01883       // Unable to compare objects; just compare pointers.
01884       if ((*api).second != (*bpi).second) {
01885         cmp = (*api).second < (*bpi).second ? -1 : 1;
01886       } else {
01887         cmp = 0;
01888       }
01889     }
01890     if (cmp != 0) {
01891       return cmp;
01892     }
01893 
01894     ++api;
01895     ++bpi;
01896   }
01897   if (api != cdata->_python_tag_data.end()) {
01898     // list A is longer.
01899     return 1;
01900   }
01901   if (bpi != cdata_other->_python_tag_data.end()) {
01902     // list B is longer.
01903     return -1;
01904   }
01905 #endif  // HAVE_PYTHON
01906 
01907   return 0;
01908 }
01909 
01910 ////////////////////////////////////////////////////////////////////
01911 //     Function: PandaNode::copy_all_properties
01912 //       Access: Published
01913 //  Description: Copies the TransformState, RenderState,
01914 //               RenderEffects, tags, Python tags, and the show/hide
01915 //               state from the other node onto this one.  Typically
01916 //               this is used to prepare a node to replace another
01917 //               node in the scene graph (also see replace_node()).
01918 ////////////////////////////////////////////////////////////////////
01919 void PandaNode::
01920 copy_all_properties(PandaNode *other) {
01921   if (other == this) {
01922     // Trivial.
01923     return;
01924   }
01925 
01926   // Need to have this held before we grab any other locks.
01927   LightMutexHolder holder(_dirty_prev_transforms._lock);
01928 
01929   bool any_transform_changed = false;
01930   bool any_state_changed = false;
01931   bool any_draw_mask_changed = false;
01932   Thread *current_thread = Thread::get_current_thread();
01933   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01934     CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
01935     CDStageReader cdatar(other->_cycler, pipeline_stage, current_thread);
01936 
01937     if (cdataw->_transform != cdatar->_transform) {
01938       any_transform_changed = true;
01939     }
01940     if (cdataw->_state != cdatar->_state) {
01941       any_state_changed = true;
01942     }
01943     if (cdataw->_draw_control_mask != cdatar->_draw_control_mask ||
01944         cdataw->_draw_show_mask != cdatar->_draw_show_mask) {
01945       any_draw_mask_changed = true;
01946     }
01947 
01948     cdataw->_transform = cdatar->_transform;
01949     cdataw->_prev_transform = cdatar->_prev_transform;
01950     cdataw->_state = cdatar->_state;
01951     cdataw->_effects = cdatar->_effects;
01952     cdataw->_draw_control_mask = cdatar->_draw_control_mask;
01953     cdataw->_draw_show_mask = cdatar->_draw_show_mask;
01954 
01955     // The collide mask becomes the union of the two masks.  This is
01956     // important to preserve properties such as the default GeomNode
01957     // bitmask.
01958     cdataw->_into_collide_mask |= cdatar->_into_collide_mask;
01959       
01960     TagData::const_iterator ti;
01961     for (ti = cdatar->_tag_data.begin();
01962          ti != cdatar->_tag_data.end();
01963          ++ti) {
01964       cdataw->_tag_data[(*ti).first] = (*ti).second;
01965     }
01966     
01967 #ifdef HAVE_PYTHON
01968     PythonTagData::const_iterator pti;
01969     for (pti = cdatar->_python_tag_data.begin();
01970          pti != cdatar->_python_tag_data.end();
01971          ++pti) {
01972       const string &key = (*pti).first;
01973       PyObject *value = (*pti).second;
01974       Py_XINCREF(value);
01975       
01976       pair<PythonTagData::iterator, bool> result;
01977       result = cdataw->_python_tag_data.insert(PythonTagData::value_type(key, value));
01978       
01979       if (!result.second) {
01980         // The insert was unsuccessful; that means the key was already
01981         // present in the map.  In this case, we should decrement the
01982         // original value's reference count and replace it with the new
01983         // object.
01984         PythonTagData::iterator wpti = result.first;
01985         PyObject *old_value = (*wpti).second;
01986         Py_XDECREF(old_value);
01987         (*wpti).second = value;
01988       }
01989     }
01990 #endif // HAVE_PYTHON
01991 
01992     static const int change_bits = (FB_transform | FB_state | FB_effects |
01993                                     FB_tag | FB_draw_mask);
01994     cdataw->_fancy_bits =
01995       (cdataw->_fancy_bits & ~change_bits) |
01996       (cdatar->_fancy_bits & change_bits);
01997 
01998     if (pipeline_stage == 0) {
01999       if (cdataw->_transform != cdataw->_prev_transform) {
02000         do_set_dirty_prev_transform();
02001       }
02002     }
02003   }
02004   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02005 
02006   if (any_transform_changed || any_state_changed || any_draw_mask_changed) {
02007     mark_bounds_stale(current_thread);
02008 
02009     if (any_transform_changed) {
02010       transform_changed();
02011     }
02012     if (any_state_changed) {
02013       state_changed();
02014     }
02015     if (any_draw_mask_changed) {
02016       draw_mask_changed();
02017     }
02018     mark_bam_modified();
02019   }
02020 }
02021 
02022 ////////////////////////////////////////////////////////////////////
02023 //     Function: PandaNode::replace_node
02024 //       Access: Published
02025 //  Description: Inserts this node into the scene graph in place of
02026 //               the other one, and removes the other node.  All scene
02027 //               graph attributes (TransformState, RenderState, etc.)
02028 //               are copied to this node.  
02029 //
02030 //               All children are moved to this node, and removed from
02031 //               the old node.  The new node is left in the same place
02032 //               in the old node's parent's list of children.
02033 //
02034 //               Even NodePaths that reference the old node are
02035 //               updated in-place to reference the new node instead.
02036 //
02037 //               This method is intended to be used to replace a node
02038 //               of a given type in the scene graph with a node of a
02039 //               different type.
02040 ////////////////////////////////////////////////////////////////////
02041 void PandaNode::
02042 replace_node(PandaNode *other) {
02043   //  nassertv(Thread::get_current_pipeline_stage() == 0);
02044 
02045   if (other == this) {
02046     // Trivial.
02047     return;
02048   }
02049 
02050   // Make sure the other node is not destructed during the
02051   // execution of this method.
02052   PT(PandaNode) keep_other = other;
02053 
02054   // Get all the important scene graph properties.
02055   copy_all_properties(other);
02056 
02057   // Fix up the NodePaths.
02058   {
02059     LightReMutexHolder holder1(other->_paths_lock);
02060     LightReMutexHolder holder2(_paths_lock);
02061     Paths::iterator pi;
02062     for (pi = other->_paths.begin(); pi != other->_paths.end(); ++pi) {
02063       (*pi)->_node = this;
02064       _paths.insert(*pi);
02065     }
02066     other->_paths.clear();
02067   }
02068 
02069   // Get the children.
02070   steal_children(other);
02071 
02072   // Switch the parents.
02073   Thread *current_thread = Thread::get_current_thread();
02074   Parents other_parents = other->get_parents();
02075   for (int i = 0; i < other_parents.get_num_parents(); ++i) {
02076     PandaNode *parent = other_parents.get_parent(i);
02077     if (find_parent(parent) != -1) {
02078       // This node was already a child of this parent; don't change
02079       // it.
02080       parent->remove_child(other);
02081     } else {
02082       // This node was not yet a child of this parent; now it is.
02083       parent->replace_child(other, this, current_thread);
02084     }
02085   }
02086 }
02087 
02088 ////////////////////////////////////////////////////////////////////
02089 //     Function: PandaNode::set_unexpected_change
02090 //       Access: Published
02091 //  Description: Sets one or more of the PandaNode::UnexpectedChange
02092 //               bits on, indicating that the corresponding property
02093 //               should not change again on this node.  Once one of
02094 //               these bits has been set, if the property changes, an
02095 //               assertion failure will be raised, which is designed
02096 //               to assist the developer in identifying the
02097 //               troublesome code that modified the property
02098 //               unexpectedly.
02099 //
02100 //               The input parameter is the union of bits that are to
02101 //               be set.  To clear these bits later, use
02102 //               clear_unexpected_change().
02103 //
02104 //               Since this is a developer debugging tool only, this
02105 //               function does nothing in a production (NDEBUG) build.
02106 ////////////////////////////////////////////////////////////////////
02107 void PandaNode::
02108 set_unexpected_change(unsigned int flags) {
02109 #ifndef NDEBUG
02110   _unexpected_change_flags |= flags;
02111 #endif // !NDEBUG
02112 }
02113 
02114 ////////////////////////////////////////////////////////////////////
02115 //     Function: PandaNode::get_unexpected_change
02116 //       Access: Published
02117 //  Description: Returns nonzero if any of the bits in the input
02118 //               parameter are set on this node, or zero if none of
02119 //               them are set.  More specifically, this returns the
02120 //               particular set of bits (masked by the input
02121 //               parameter) that have been set on this node.  See
02122 //               set_unexpected_change().
02123 //
02124 //               Since this is a developer debugging tool only, this
02125 //               function always returns zero in a production (NDEBUG)
02126 //               build.
02127 ////////////////////////////////////////////////////////////////////
02128 unsigned int PandaNode::
02129 get_unexpected_change(unsigned int flags) const {
02130 #ifndef NDEBUG
02131   return _unexpected_change_flags & flags;
02132 #else
02133   return 0;
02134 #endif // !NDEBUG
02135 }
02136 
02137 ////////////////////////////////////////////////////////////////////
02138 //     Function: PandaNode::clear_unexpected_change
02139 //       Access: Published
02140 //  Description: Sets one or more of the PandaNode::UnexpectedChange
02141 //               bits off, indicating that the corresponding property
02142 //               may once again change on this node.  See
02143 //               set_unexpected_change().
02144 //
02145 //               The input parameter is the union of bits that are to
02146 //               be cleared.
02147 //
02148 //               Since this is a developer debugging tool only, this
02149 //               function does nothing in a production (NDEBUG) build.
02150 ////////////////////////////////////////////////////////////////////
02151 void PandaNode::
02152 clear_unexpected_change(unsigned int flags) {
02153 #ifndef NDEBUG
02154   _unexpected_change_flags &= ~flags;
02155 #endif // !NDEBUG
02156 }
02157 
02158 ////////////////////////////////////////////////////////////////////
02159 //     Function: PandaNode::adjust_draw_mask
02160 //       Access: Published
02161 //  Description: Adjusts the hide/show bits of this particular node.
02162 //
02163 //               These three parameters can be used to adjust the
02164 //               _draw_control_mask and _draw_show_mask independently,
02165 //               which work together to provide per-camera visibility
02166 //               for the node and its descendents.
02167 //
02168 //               _draw_control_mask indicates the bits in
02169 //               _draw_show_mask that are significant.  Each different
02170 //               bit corresponds to a different camera (and these bits
02171 //               are assigned via Camera::set_camera_mask()).
02172 //
02173 //               Where _draw_control_mask has a 1 bit, a 1 bit in
02174 //               _draw_show_mask indicates the node is visible to that
02175 //               camera, and a 0 bit indicates the node is hidden to
02176 //               that camera.  Where _draw_control_mask is 0, the node
02177 //               is hidden only if a parent node is hidden.
02178 //
02179 //               The meaning of the three parameters is as follows:
02180 //
02181 //               * Wherever show_mask is 1, _draw_show_mask and
02182 //               _draw_control_mask will be set 1.  Thus, show_mask
02183 //               indicates the set of cameras to which the node should
02184 //               be shown.
02185 //
02186 //               * Wherever hide_mask is 1, _draw_show_mask will be
02187 //               set 0 and _draw_control_mask will be set 1.  Thus,
02188 //               hide_mask indicates the set of cameras from which the
02189 //               node should be hidden.
02190 //
02191 //               * Wherever clear_mask is 1, _draw_control_mask will
02192 //               be set 0.  Thus, clear_mask indicates the set of
02193 //               cameras from which the hidden state should be
02194 //               inherited from a parent.
02195 ////////////////////////////////////////////////////////////////////
02196 void PandaNode::
02197 adjust_draw_mask(DrawMask show_mask, DrawMask hide_mask, DrawMask clear_mask) {
02198   bool any_changed = false;
02199 
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     
02204     DrawMask draw_control_mask = (cdata->_draw_control_mask | show_mask | hide_mask) & ~clear_mask;
02205     DrawMask draw_show_mask = (cdata->_draw_show_mask | show_mask) & ~hide_mask;
02206     // The uncontrolled bits are implicitly on.
02207     draw_show_mask |= ~draw_control_mask;
02208 
02209     if (cdata->_draw_control_mask != draw_control_mask ||
02210         cdata->_draw_show_mask != draw_show_mask) {
02211       cdata->_draw_control_mask = draw_control_mask;
02212       cdata->_draw_show_mask = draw_show_mask;
02213       any_changed = true;
02214     }
02215     cdata->set_fancy_bit(FB_draw_mask, !draw_control_mask.is_zero());
02216   }
02217   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02218 
02219   if (any_changed) {
02220     mark_bounds_stale(current_thread);
02221     draw_mask_changed();
02222     mark_bam_modified();
02223   }
02224 }
02225 
02226 ////////////////////////////////////////////////////////////////////
02227 //     Function: PandaNode::get_net_draw_control_mask
02228 //       Access: Published
02229 //  Description: Returns the set of bits in get_net_draw_show_mask()
02230 //               that have been explicitly set via adjust_draw_mask(),
02231 //               rather than implicitly inherited.
02232 //
02233 //               A 1 bit in any position of this mask indicates that
02234 //               (a) this node has renderable children, and (b) some
02235 //               child of this node has made an explicit hide() or
02236 //               show_through() call for the corresponding bit.
02237 ////////////////////////////////////////////////////////////////////
02238 DrawMask PandaNode::
02239 get_net_draw_control_mask() const {
02240   Thread *current_thread = Thread::get_current_thread();
02241   int pipeline_stage = current_thread->get_pipeline_stage();
02242   CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02243   if (cdata->_last_update != cdata->_next_update) {
02244     // The cache is stale; it needs to be rebuilt.
02245     PStatTimer timer(_update_bounds_pcollector);
02246     CDStageWriter cdataw = 
02247       ((PandaNode *)this)->update_bounds(pipeline_stage, cdata); 
02248     return cdataw->_net_draw_control_mask;
02249   }
02250   return cdata->_net_draw_control_mask;
02251 }
02252 
02253 ////////////////////////////////////////////////////////////////////
02254 //     Function: PandaNode::get_net_draw_show_mask
02255 //       Access: Published
02256 //  Description: Returns the union of all draw_show_mask values--of
02257 //               renderable nodes only--at this level and below.  If
02258 //               any bit in this mask is 0, there is no reason to
02259 //               traverse below this node for a camera with the
02260 //               corresponding camera_mask.
02261 //
02262 //               The bits in this mask that do not correspond to a 1
02263 //               bit in the net_draw_control_mask are meaningless (and
02264 //               will be set to 1).  For bits that *do* correspond to
02265 //               a 1 bit in the net_draw_control_mask, a 1 bit
02266 //               indicates that at least one child should be visible,
02267 //               while a 0 bit indicates that all children are hidden.
02268 ////////////////////////////////////////////////////////////////////
02269 DrawMask PandaNode::
02270 get_net_draw_show_mask() const {
02271   Thread *current_thread = Thread::get_current_thread();
02272   int pipeline_stage = current_thread->get_pipeline_stage();
02273   CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02274   if (cdata->_last_update != cdata->_next_update) {
02275     // The cache is stale; it needs to be rebuilt.
02276     PStatTimer timer(_update_bounds_pcollector);
02277     CDStageWriter cdataw = 
02278       ((PandaNode *)this)->update_bounds(pipeline_stage, cdata); 
02279     return cdataw->_net_draw_show_mask;
02280   }
02281   return cdata->_net_draw_show_mask;
02282 }
02283 
02284 ////////////////////////////////////////////////////////////////////
02285 //     Function: PandaNode::set_into_collide_mask
02286 //       Access: Published
02287 //  Description: Sets the "into" CollideMask.  
02288 //
02289 //               This specifies the set of bits that must be shared
02290 //               with a CollisionNode's "from" CollideMask in order
02291 //               for the CollisionNode to detect a collision with this
02292 //               particular node.
02293 //
02294 //               The actual CollideMask that will be set is masked by
02295 //               the return value from get_legal_collide_mask().
02296 //               Thus, the into_collide_mask cannot be set to anything
02297 //               other than nonzero except for those types of nodes
02298 //               that can be collided into, such as CollisionNodes and
02299 //               GeomNodes.
02300 ////////////////////////////////////////////////////////////////////
02301 void PandaNode::
02302 set_into_collide_mask(CollideMask mask) {
02303   mask &= get_legal_collide_mask();
02304 
02305   bool any_changed = false;
02306   Thread *current_thread = Thread::get_current_thread();
02307   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02308     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02309     if (cdata->_into_collide_mask != mask) {
02310       cdata->_into_collide_mask = mask;
02311       any_changed = true;
02312     }
02313   }
02314   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02315 
02316   if (any_changed) {
02317     mark_bounds_stale(current_thread);
02318     mark_bam_modified();
02319   }
02320 }
02321 
02322 ////////////////////////////////////////////////////////////////////
02323 //     Function: PandaNode::get_legal_collide_mask
02324 //       Access: Published, Virtual
02325 //  Description: Returns the subset of CollideMask bits that may be
02326 //               set for this particular type of PandaNode.  For most
02327 //               nodes, this is 0; it doesn't make sense to set a
02328 //               CollideMask for most kinds of nodes.
02329 //
02330 //               For nodes that can be collided with, such as GeomNode
02331 //               and CollisionNode, this returns all bits on.
02332 ////////////////////////////////////////////////////////////////////
02333 CollideMask PandaNode::
02334 get_legal_collide_mask() const {
02335   return CollideMask::all_off();
02336 }
02337 
02338 ////////////////////////////////////////////////////////////////////
02339 //     Function: PandaNode::get_net_collide_mask
02340 //       Access: Published
02341 //  Description: Returns the union of all into_collide_mask() values
02342 //               set at CollisionNodes at this level and below.
02343 ////////////////////////////////////////////////////////////////////
02344 CollideMask PandaNode::
02345 get_net_collide_mask(Thread *current_thread) const {
02346   int pipeline_stage = current_thread->get_pipeline_stage();
02347   CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02348   if (cdata->_last_update != cdata->_next_update) {
02349     // The cache is stale; it needs to be rebuilt.
02350     PStatTimer timer(_update_bounds_pcollector);
02351     CDStageWriter cdataw = 
02352       ((PandaNode *)this)->update_bounds(pipeline_stage, cdata); 
02353     return cdataw->_net_collide_mask;
02354   }
02355   return cdata->_net_collide_mask;
02356 }
02357 
02358 ////////////////////////////////////////////////////////////////////
02359 //     Function: PandaNode::get_off_clip_planes
02360 //       Access: Published
02361 //  Description: Returns a ClipPlaneAttrib which represents the union
02362 //               of all of the clip planes that have been turned *off*
02363 //               at this level and below.
02364 ////////////////////////////////////////////////////////////////////
02365 CPT(RenderAttrib) PandaNode::
02366 get_off_clip_planes(Thread *current_thread) const {
02367   int pipeline_stage = current_thread->get_pipeline_stage();
02368   CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02369   if (cdata->_last_update != cdata->_next_update) {
02370     // The cache is stale; it needs to be rebuilt.
02371     PStatTimer timer(_update_bounds_pcollector);
02372     CDStageWriter cdataw = 
02373       ((PandaNode *)this)->update_bounds(pipeline_stage, cdata); 
02374     return cdataw->_off_clip_planes;
02375   }
02376   return cdata->_off_clip_planes;
02377 }
02378 
02379 ////////////////////////////////////////////////////////////////////
02380 //     Function: PandaNode::prepare_scene
02381 //       Access: Published
02382 //  Description: Walks through the scene graph beginning at this node,
02383 //               and does whatever initialization is required to
02384 //               render the scene properly with the indicated GSG.  It
02385 //               is not strictly necessary to call this, since the GSG
02386 //               will initialize itself when the scene is rendered,
02387 //               but this may take some of the overhead away from that
02388 //               process.
02389 //
02390 //               In particular, this will ensure that textures and
02391 //               vertex buffers within the scene are loaded into
02392 //               graphics memory.
02393 ////////////////////////////////////////////////////////////////////
02394 void PandaNode::
02395 prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state) {
02396   GeomTransformer transformer;
02397   Thread *current_thread = Thread::get_current_thread();
02398   r_prepare_scene(gsg, node_state, transformer, current_thread);
02399 }
02400 
02401 ////////////////////////////////////////////////////////////////////
02402 //     Function: PandaNode::is_scene_root
02403 //       Access: Published
02404 //  Description: Returns true if this particular node is known to be
02405 //               the render root of some active DisplayRegion
02406 //               associated with the global GraphicsEngine, false
02407 //               otherwise.
02408 ////////////////////////////////////////////////////////////////////
02409 bool PandaNode::
02410 is_scene_root() const {
02411   // This function pointer has to be filled in when the global
02412   // GraphicsEngine is created, because we can't link with the
02413   // GraphicsEngine functions directly.
02414   if (_scene_root_func != (SceneRootFunc *)NULL) {
02415     return (*_scene_root_func)(this);
02416   }
02417   return false;
02418 }
02419 
02420 ////////////////////////////////////////////////////////////////////
02421 //     Function: PandaNode::is_under_scene_root
02422 //       Access: Published
02423 //  Description: Returns true if this particular node is in a live
02424 //               scene graph: that is, it is a child or descendent of
02425 //               a node that is itself a scene root.  If this is true,
02426 //               this node may potentially be traversed by the render
02427 //               traverser.  Stashed nodes don't count for this
02428 //               purpose, but hidden nodes do.
02429 ////////////////////////////////////////////////////////////////////
02430 bool PandaNode::
02431 is_under_scene_root() const {
02432   if (is_scene_root()) {
02433     return true;
02434   }
02435 
02436   Parents parents = get_parents();
02437   for (int i = 0; i < parents.get_num_parents(); ++i) {
02438     PandaNode *parent = parents.get_parent(i);
02439     if (parent->find_stashed((PandaNode *)this) == -1) {
02440       if (parent->is_under_scene_root()) {
02441         return true;
02442       }
02443     }
02444   }
02445   return false;
02446 }
02447 
02448 ////////////////////////////////////////////////////////////////////
02449 //     Function: PandaNode::output
02450 //       Access: Published, Virtual
02451 //  Description: 
02452 ////////////////////////////////////////////////////////////////////
02453 void PandaNode::
02454 output(ostream &out) const {
02455   out << get_type() << " " << get_name();
02456 }
02457 
02458 ////////////////////////////////////////////////////////////////////
02459 //     Function: PandaNode::write
02460 //       Access: Published, Virtual
02461 //  Description: 
02462 ////////////////////////////////////////////////////////////////////
02463 void PandaNode::
02464 write(ostream &out, int indent_level) const {
02465   indent(out, indent_level) << *this;
02466   if (has_tags()) {
02467     out << " [";
02468     list_tags(out, " ");
02469     out << "]";
02470   }
02471   CPT(TransformState) transform = get_transform();
02472   if (!transform->is_identity()) {
02473     out << " " << *transform;
02474   }
02475   CPT(RenderState) state = get_state();
02476   if (!state->is_empty()) {
02477     out << " " << *state;
02478   }
02479   CPT(RenderEffects) effects = get_effects();
02480   if (!effects->is_empty()) {
02481     out << " " << *effects;
02482   }
02483   DrawMask draw_control_mask = get_draw_control_mask();
02484   if (!draw_control_mask.is_zero()) {
02485     DrawMask draw_show_mask = get_draw_show_mask();
02486     if (!(draw_control_mask & _overall_bit).is_zero()) {
02487       if (!(draw_show_mask & _overall_bit).is_zero()) {
02488         out << " (show_through)";
02489       } else {
02490         out << " (hidden)";
02491       }
02492     }
02493     if (!(draw_control_mask & ~_overall_bit).is_zero()) {
02494       draw_control_mask &= ~_overall_bit;
02495       if (!(draw_show_mask & draw_control_mask).is_zero()) {
02496         out << " (per-camera show_through)";
02497       }
02498       if (!(~draw_show_mask & draw_control_mask).is_zero()) {
02499         out << " (per-camera hidden)";
02500       }
02501     }
02502   }
02503   out << "\n";
02504 }
02505 
02506 ////////////////////////////////////////////////////////////////////
02507 //     Function: PandaNode::set_bounds_type
02508 //       Access: Published
02509 //  Description: Specifies the desired type of bounding volume that
02510 //               will be created for this node.  This is normally
02511 //               BoundingVolume::BT_default, which means to set the
02512 //               type according to the config variable "bounds-type".
02513 //
02514 //               If this is BT_sphere or BT_box, a BoundingSphere or
02515 //               BoundingBox is explicitly created.  If it is BT_best,
02516 //               the appropriate type to best enclose the node's
02517 //               children is created.
02518 //
02519 //               This affects the bounding volume returned by
02520 //               get_bounds(), which is not exactly the same bounding
02521 //               volume modified by set_bounds(), because a new
02522 //               bounding volume has to be created that includes this
02523 //               node and all of its children.
02524 ////////////////////////////////////////////////////////////////////
02525 void PandaNode::
02526 set_bounds_type(BoundingVolume::BoundsType bounds_type) {
02527   Thread *current_thread = Thread::get_current_thread();
02528   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02529     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02530     cdata->_bounds_type = bounds_type;
02531     mark_bounds_stale(pipeline_stage, current_thread);
02532 
02533     // GeomNodes, CollisionNodes, and PGItems all have an internal
02534     // bounds that may need to be updated when the bounds_type
02535     // changes.
02536     mark_internal_bounds_stale(pipeline_stage, current_thread);
02537     mark_bam_modified();
02538   }
02539   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02540 }
02541 
02542 ////////////////////////////////////////////////////////////////////
02543 //     Function: PandaNode::get_bounds_type
02544 //       Access: Published
02545 //  Description: Returns the bounding volume type set with
02546 //               set_bounds_type().
02547 ////////////////////////////////////////////////////////////////////
02548 BoundingVolume::BoundsType PandaNode::
02549 get_bounds_type() const {
02550   CDReader cdata(_cycler);
02551   return cdata->_bounds_type;
02552 }
02553 
02554 ////////////////////////////////////////////////////////////////////
02555 //     Function: PandaNode::set_bounds
02556 //       Access: Published
02557 //  Description: Resets the bounding volume so that it is the
02558 //               indicated volume.  When it is explicitly set, the
02559 //               bounding volume will no longer be automatically
02560 //               computed according to the contents of the node
02561 //               itself, for nodes like GeomNodes and TextNodes that
02562 //               contain substance (but the bounding volume will still
02563 //               be automatically expanded to include its children).
02564 //
02565 //               Call clear_bounds() if you would like to return the
02566 //               bounding volume to its default behavior later.
02567 ////////////////////////////////////////////////////////////////////
02568 void PandaNode::
02569 set_bounds(const BoundingVolume *volume) {
02570   Thread *current_thread = Thread::get_current_thread();
02571   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02572     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02573     if (volume == NULL) {
02574       cdata->_user_bounds = NULL;
02575     } else {
02576       cdata->_user_bounds = volume->make_copy();
02577     }
02578     mark_bounds_stale(pipeline_stage, current_thread);
02579     mark_bam_modified();
02580   }
02581   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02582 }
02583 
02584 ////////////////////////////////////////////////////////////////////
02585 //     Function: PandaNode::set_bound
02586 //       Access: Published
02587 //  Description: Deprecated.  Use set_bounds() instead.
02588 ////////////////////////////////////////////////////////////////////
02589 void PandaNode::
02590 set_bound(const BoundingVolume *volume) {
02591   pgraph_cat.warning()
02592     << "Deprecated PandaNode::set_bound() called.  Use set_bounds() instead.\n";
02593   set_bounds(volume);
02594 }
02595 
02596 ////////////////////////////////////////////////////////////////////
02597 //     Function: PandaNode::get_bounds
02598 //       Access: Published
02599 //  Description: Returns the external bounding volume of this node: a
02600 //               bounding volume that contains the user bounding
02601 //               volume, the internal bounding volume, and all of the
02602 //               children's bounding volumes.
02603 ////////////////////////////////////////////////////////////////////
02604 CPT(BoundingVolume) PandaNode::
02605 get_bounds(Thread *current_thread) const {
02606   int pipeline_stage = current_thread->get_pipeline_stage();
02607   CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02608   if (cdata->_last_update != cdata->_next_update) {
02609     // The cache is stale; it needs to be rebuilt.
02610     CPT(BoundingVolume) result;
02611     {
02612       PStatTimer timer(_update_bounds_pcollector);
02613       CDStageWriter cdataw = 
02614         ((PandaNode *)this)->update_bounds(pipeline_stage, cdata); 
02615       result = cdataw->_external_bounds;
02616     }
02617     return result;
02618   }
02619   return cdata->_external_bounds;
02620 }
02621 
02622 ////////////////////////////////////////////////////////////////////
02623 //     Function: PandaNode::get_bounds
02624 //       Access: Published
02625 //  Description: This flavor of get_bounds() return the external
02626 //               bounding volume, and also fills in seq with the
02627 //               bounding volume's current sequence number.  When this
02628 //               sequence number changes, it indicates that the
02629 //               bounding volume might have changed, e.g. because some
02630 //               nested child's bounding volume has changed.
02631 //
02632 //               Although this might occasionally increment without
02633 //               changing the bounding volume, the bounding volume
02634 //               will never change without incrementing this counter,
02635 //               so as long as this counter remains unchanged you can
02636 //               be confident the bounding volume is also unchanged.
02637 ////////////////////////////////////////////////////////////////////
02638 CPT(BoundingVolume) PandaNode::
02639 get_bounds(UpdateSeq &seq, Thread *current_thread) const {
02640   int pipeline_stage = current_thread->get_pipeline_stage();
02641   CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02642   if (cdata->_last_update != cdata->_next_update) {
02643     // The cache is stale; it needs to be rebuilt.
02644     CPT(BoundingVolume) result;
02645     {
02646       PStatTimer timer(_update_bounds_pcollector);
02647       CDStageWriter cdataw = 
02648         ((PandaNode *)this)->update_bounds(pipeline_stage, cdata); 
02649       result = cdataw->_external_bounds;
02650       seq = cdataw->_last_update;
02651     }
02652     return result;
02653   }
02654   seq = cdata->_last_update;
02655   return cdata->_external_bounds;
02656 }
02657 
02658 ////////////////////////////////////////////////////////////////////
02659 //     Function: PandaNode::get_nested_vertices
02660 //       Access: Published
02661 //  Description: Returns the total number of vertices that will be
02662 //               rendered by this node and all of its descendents.
02663 //
02664 //               This is not necessarily an accurate count of vertices
02665 //               that will actually be rendered, since this will
02666 //               include all vertices of all LOD's, and it will also
02667 //               include hidden nodes.  It may also omit or only
02668 //               approximate certain kinds of dynamic geometry.
02669 //               However, it will not include stashed nodes.
02670 ////////////////////////////////////////////////////////////////////
02671 int PandaNode::
02672 get_nested_vertices(Thread *current_thread) const {
02673   int pipeline_stage = current_thread->get_pipeline_stage();
02674   CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
02675   if (cdata->_last_update != cdata->_next_update) {
02676     // The cache is stale; it needs to be rebuilt.
02677     int result;
02678     {
02679       PStatTimer timer(_update_bounds_pcollector);
02680       CDStageWriter cdataw = 
02681         ((PandaNode *)this)->update_bounds(pipeline_stage, cdata); 
02682       result = cdataw->_nested_vertices;
02683     }
02684     return result;
02685   }
02686   return cdata->_nested_vertices;
02687 }
02688 
02689 ////////////////////////////////////////////////////////////////////
02690 //     Function: PandaNode::mark_bounds_stale
02691 //       Access: Published
02692 //  Description: Indicates that the bounding volume, or something that
02693 //               influences the bounding volume (or any of the other
02694 //               things stored in CData, like net_collide_mask),
02695 //               may have changed for this node, and that it must be
02696 //               recomputed.
02697 //
02698 //               With no parameters, this means to iterate through all
02699 //               stages including and upstream of the current pipeline
02700 //               stage.
02701 //
02702 //               This method is intended for internal use; usually it
02703 //               is not necessary for a user to call this directly.
02704 //               It will be called automatically by derived classes
02705 //               when appropriate.
02706 ////////////////////////////////////////////////////////////////////
02707 void PandaNode::
02708 mark_bounds_stale(Thread *current_thread) const {
02709   OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
02710     mark_bounds_stale(pipeline_stage, current_thread);
02711   }
02712   CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
02713 }
02714 
02715 ////////////////////////////////////////////////////////////////////
02716 //     Function: PandaNode::mark_internal_bounds_stale
02717 //       Access: Published
02718 //  Description: Should be called by a derived class to mark the
02719 //               internal bounding volume stale, so that
02720 //               compute_internal_bounds() will be called when the
02721 //               bounding volume is next requested.
02722 //
02723 //               With no parameters, this means to iterate through all
02724 //               stages including and upstream of the current pipeline
02725 //               stage.
02726 //
02727 //               It is normally not necessary to call this method
02728 //               directly; each node should be responsible for calling
02729 //               it when its internals have changed.
02730 ////////////////////////////////////////////////////////////////////
02731 void PandaNode::
02732 mark_internal_bounds_stale(Thread *current_thread) {
02733   OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
02734     mark_internal_bounds_stale(pipeline_stage, current_thread);
02735   }
02736   CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
02737 }
02738 
02739 ////////////////////////////////////////////////////////////////////
02740 //     Function: PandaNode::is_geom_node
02741 //       Access: Published, Virtual
02742 //  Description: A simple downcast check.  Returns true if this kind
02743 //               of node happens to inherit from GeomNode, false
02744 //               otherwise.
02745 //
02746 //               This is provided as a a faster alternative to calling
02747 //               is_of_type(GeomNode::get_class_type()), since this
02748 //               test is so important to rendering.
02749 ////////////////////////////////////////////////////////////////////
02750 bool PandaNode::
02751 is_geom_node() const {
02752   return false;
02753 }
02754 
02755 ////////////////////////////////////////////////////////////////////
02756 //     Function: PandaNode::is_lod_node
02757 //       Access: Published, Virtual
02758 //  Description: A simple downcast check.  Returns true if this kind
02759 //               of node happens to inherit from LODNode, false
02760 //               otherwise.
02761 //
02762 //               This is provided as a a faster alternative to calling
02763 //               is_of_type(LODNode::get_class_type()).
02764 ////////////////////////////////////////////////////////////////////
02765 bool PandaNode::
02766 is_lod_node() const {
02767   return false;
02768 }
02769 
02770 ////////////////////////////////////////////////////////////////////
02771 //     Function: PandaNode::is_collision_node
02772 //       Access: Published, Virtual
02773 //  Description: A simple downcast check.  Returns true if this kind
02774 //               of node happens to inherit from CollisionNode, false
02775 //               otherwise.
02776 //
02777 //               This is provided as a a faster alternative to calling
02778 //               is_of_type(CollisionNode::get_class_type()).
02779 ////////////////////////////////////////////////////////////////////
02780 bool PandaNode::
02781 is_collision_node() const {
02782   return false;
02783 }
02784 
02785 ////////////////////////////////////////////////////////////////////
02786 //     Function: PandaNode::as_light
02787 //       Access: Published, Virtual
02788 //  Description: Cross-casts the node to a Light pointer, if it is one
02789 //               of the four kinds of Light nodes, or returns NULL if
02790 //               it is not.
02791 ////////////////////////////////////////////////////////////////////
02792 Light *PandaNode::
02793 as_light() {
02794   return NULL;
02795 }
02796 
02797 ////////////////////////////////////////////////////////////////////
02798 //     Function: PandaNode::is_ambient_light
02799 //       Access: Published, Virtual
02800 //  Description: Returns true if this is an AmbientLight, false if it
02801 //               is not a light, or it is some other kind of light.
02802 ////////////////////////////////////////////////////////////////////
02803 bool PandaNode::
02804 is_ambient_light() const {
02805   return false;
02806 }
02807 
02808 ////////////////////////////////////////////////////////////////////
02809 //     Function: PandaNode::decode_from_bam_stream
02810 //       Access: Published, Static
02811 //  Description: Reads the string created by a previous call to
02812 //               encode_to_bam_stream(), and extracts and returns the
02813 //               single object on that string.  Returns NULL on error.
02814 //
02815 //               This method is intended to replace
02816 //               decode_raw_from_bam_stream() when you know the stream
02817 //               in question returns an object of type PandaNode,
02818 //               allowing for easier reference count management.  Note
02819 //               that the caller is still responsible for maintaining
02820 //               the reference count on the return value.
02821 ////////////////////////////////////////////////////////////////////
02822 PT(PandaNode) PandaNode::
02823 decode_from_bam_stream(const string &data, BamReader *reader) {
02824   TypedWritable *object;
02825   ReferenceCount *ref_ptr;
02826 
02827   if (!TypedWritable::decode_raw_from_bam_stream(object, ref_ptr, data, reader)) {
02828     return NULL;
02829   }
02830 
02831   return DCAST(PandaNode, object);
02832 }
02833 
02834 ////////////////////////////////////////////////////////////////////
02835 //     Function: PandaNode::get_internal_bounds
02836 //       Access: Protected
02837 //  Description: Returns the node's internal bounding volume.  This is
02838 //               the bounding volume around the node alone, without
02839 //               including children.
02840 ////////////////////////////////////////////////////////////////////
02841 CPT(BoundingVolume) PandaNode::
02842 get_internal_bounds(int pipeline_stage, Thread *current_thread) const {
02843   while (true) {
02844     UpdateSeq mark;
02845     {
02846       CDStageReader cdata(_cycler, pipeline_stage, current_thread);
02847       if (cdata->_user_bounds != (BoundingVolume *)NULL) {
02848         return cdata->_user_bounds;
02849       }
02850       
02851       if (cdata->_internal_bounds_mark == cdata->_internal_bounds_computed) {
02852         return cdata->_internal_bounds;
02853       }
02854 
02855       mark = cdata->_internal_bounds_mark;
02856     }
02857 
02858     // First, call compute_internal_bounds without acquiring the lock.
02859     // This avoids a deadlock condition.
02860     CPT(BoundingVolume) internal_bounds;
02861     int internal_vertices;
02862     compute_internal_bounds(internal_bounds, internal_vertices,
02863                             pipeline_stage, current_thread);
02864     nassertr(!internal_bounds.is_null(), NULL);
02865     
02866     // Now, acquire the lock, and apply the above-computed bounds.
02867     CDStageWriter cdataw(((PandaNode *)this)->_cycler, pipeline_stage);
02868     if (cdataw->_internal_bounds_mark == mark) {
02869       cdataw->_internal_bounds_computed = mark;
02870       cdataw->_internal_bounds = internal_bounds;
02871       cdataw->_internal_vertices = internal_vertices;
02872       ((PandaNode *)this)->mark_bam_modified();
02873       return cdataw->_internal_bounds;
02874     }
02875 
02876     // Dang, someone in another thread incremented
02877     // _internal_bounds_mark while we weren't holding the lock.  That
02878     // means we need to go back and do it again.
02879   }
02880 }
02881 
02882 ////////////////////////////////////////////////////////////////////
02883 //     Function: PandaNode::get_internal_vertices
02884 //       Access: Protected
02885 //  Description: Returns the total number of vertices that will be
02886 //               rendered by this particular node alone, not
02887 //               accounting for its children.
02888 //
02889 //               This may not include all vertices for certain dynamic
02890 //               effects.
02891 ////////////////////////////////////////////////////////////////////
02892 int PandaNode::
02893 get_internal_vertices(int pipeline_stage, Thread *current_thread) const {
02894   while (true) {
02895     UpdateSeq mark;
02896     {
02897       CDStageReader cdata(_cycler, pipeline_stage, current_thread);
02898       if (cdata->_internal_bounds_mark == cdata->_internal_bounds_computed) {
02899         return cdata->_internal_vertices;
02900       }
02901 
02902       mark = cdata->_internal_bounds_mark;
02903     }
02904 
02905     // First, call compute_internal_bounds without acquiring the lock.
02906     // This avoids a deadlock condition.
02907     CPT(BoundingVolume) internal_bounds;
02908     int internal_vertices;
02909     compute_internal_bounds(internal_bounds, internal_vertices,
02910                             pipeline_stage, current_thread);
02911     nassertr(!internal_bounds.is_null(), 0);
02912     
02913     // Now, acquire the lock, and apply the above-computed bounds.
02914     CDStageWriter cdataw(((PandaNode *)this)->_cycler, pipeline_stage);
02915     if (cdataw->_internal_bounds_mark == mark) {
02916       cdataw->_internal_bounds_computed = mark;
02917       cdataw->_internal_bounds = internal_bounds;
02918       cdataw->_internal_vertices = internal_vertices;
02919       ((PandaNode *)this)->mark_bam_modified();
02920       return cdataw->_internal_vertices;
02921     }
02922 
02923     // Dang, someone in another thread incremented
02924     // _internal_bounds_mark while we weren't holding the lock.  That
02925     // means we need to go back and do it again.
02926   }
02927 }
02928 
02929 ////////////////////////////////////////////////////////////////////
02930 //     Function: PandaNode::set_internal_bounds
02931 //       Access: Protected
02932 //  Description: This is provided as an alternate way for a node to
02933 //               set its own internal bounds, rather than overloading
02934 //               compute_internal_bounds().  If this method is called,
02935 //               the internal bounding volume will immediately be set
02936 //               to the indicated pointer.
02937 ////////////////////////////////////////////////////////////////////
02938 void PandaNode::
02939 set_internal_bounds(const BoundingVolume *volume) {
02940   Thread *current_thread = Thread::get_current_thread();
02941   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
02942     CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
02943     cdataw->_internal_bounds = volume;
02944     cdataw->_internal_bounds_computed = cdataw->_internal_bounds_mark;
02945   }
02946   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
02947   mark_bounds_stale(current_thread);
02948   mark_bam_modified();
02949 }
02950 
02951 ////////////////////////////////////////////////////////////////////
02952 //     Function: PandaNode::force_bounds_stale
02953 //       Access: Protected
02954 //  Description: Similar to mark_bounds_stale(), except that the
02955 //               parents of this node marked stale even if this node
02956 //               was already considered stale.
02957 //
02958 //               With no parameters, this means to iterate through all
02959 //               stages including and upstream of the current pipeline
02960 //               stage.
02961 ////////////////////////////////////////////////////////////////////
02962 void PandaNode::
02963 force_bounds_stale(Thread *current_thread) {
02964   OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler, current_thread) {
02965     force_bounds_stale(pipeline_stage, current_thread);
02966   }
02967   CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(_cycler);
02968 }
02969 
02970 ////////////////////////////////////////////////////////////////////
02971 //     Function: PandaNode::force_bounds_stale
02972 //       Access: Protected
02973 //  Description: Similar to mark_bounds_stale(), except that the
02974 //               parents of this node marked stale even if this node
02975 //               was already considered stale.
02976 ////////////////////////////////////////////////////////////////////
02977 void PandaNode::
02978 force_bounds_stale(int pipeline_stage, Thread *current_thread) {
02979   {
02980     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
02981     ++cdata->_next_update;
02982     mark_bam_modified();
02983 
02984     // It is important that we allow this lock to be dropped before we
02985     // continue up the graph; otherwise, we risk deadlock from another
02986     // thread walking down the graph.
02987   }
02988 
02989   // It is similarly important that we use get_parents() here to copy
02990   // the parents list, instead of keeping the lock open while we walk
02991   // through the parents list directly on the node.
02992   Parents parents;
02993   {
02994     CDStageReader cdata(_cycler, pipeline_stage, current_thread);
02995     parents = Parents(cdata);
02996   }
02997   int num_parents = parents.get_num_parents();
02998   for (int i = 0; i < num_parents; ++i) {
02999     PandaNode *parent = parents.get_parent(i);
03000     parent->mark_bounds_stale(pipeline_stage, current_thread);
03001   }
03002 }
03003 
03004 ////////////////////////////////////////////////////////////////////
03005 //     Function: PandaNode::r_mark_geom_bounds_stale
03006 //       Access: Protected, Virtual
03007 //  Description: Recursively calls Geom::mark_bounds_stale() on every
03008 //               Geom at this node and below.
03009 ////////////////////////////////////////////////////////////////////
03010 void PandaNode::
03011 r_mark_geom_bounds_stale(Thread *current_thread) {
03012   Children children = get_children(current_thread);
03013 
03014   int i;
03015   for (i = 0; i < children.get_num_children(); i++) {
03016     PandaNode *child = children.get_child(i);
03017     child->r_mark_geom_bounds_stale(current_thread);
03018   }
03019 
03020   Stashed stashed = get_stashed(current_thread);
03021   for (i = 0; i < stashed.get_num_stashed(); i++) {
03022     PandaNode *child = stashed.get_stashed(i);
03023     child->r_mark_geom_bounds_stale(current_thread);
03024   }
03025 }
03026 
03027 ////////////////////////////////////////////////////////////////////
03028 //     Function: PandaNode::compute_internal_bounds
03029 //       Access: Protected, Virtual
03030 //  Description: Returns a newly-allocated BoundingVolume that
03031 //               represents the internal contents of the node.  Should
03032 //               be overridden by PandaNode classes that contain
03033 //               something internally.
03034 ////////////////////////////////////////////////////////////////////
03035 void PandaNode::
03036 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
03037                         int &internal_vertices,
03038                         int pipeline_stage,
03039                         Thread *current_thread) const {
03040   internal_bounds = new BoundingSphere;
03041   internal_vertices = 0;
03042 }
03043 
03044 ////////////////////////////////////////////////////////////////////
03045 //     Function: PandaNode::parents_changed
03046 //       Access: Protected, Virtual
03047 //  Description: Called after a scene graph update that either adds or
03048 //               remove parents from this node, this just provides a
03049 //               hook for derived PandaNode objects that need to
03050 //               update themselves based on the set of parents the
03051 //               node has.
03052 ////////////////////////////////////////////////////////////////////
03053 void PandaNode::
03054 parents_changed() {
03055   nassertv((_unexpected_change_flags & UC_parents) == 0);
03056 }
03057 
03058 ////////////////////////////////////////////////////////////////////
03059 //     Function: PandaNode::children_changed
03060 //       Access: Protected, Virtual
03061 //  Description: Called after a scene graph update that either adds or
03062 //               remove children from this node, this just provides a
03063 //               hook for derived PandaNode objects that need to
03064 //               update themselves based on the set of children the
03065 //               node has.
03066 ////////////////////////////////////////////////////////////////////
03067 void PandaNode::
03068 children_changed() {
03069   nassertv((_unexpected_change_flags & UC_children) == 0);
03070 }
03071 
03072 ////////////////////////////////////////////////////////////////////
03073 //     Function: PandaNode::transform_changed
03074 //       Access: Protected, Virtual
03075 //  Description: Called after the node's transform has been changed
03076 //               for any reason, this just provides a hook so derived
03077 //               classes can do something special in this case.
03078 ////////////////////////////////////////////////////////////////////
03079 void PandaNode::
03080 transform_changed() {
03081   nassertv((_unexpected_change_flags & UC_transform) == 0);
03082 }
03083 
03084 ////////////////////////////////////////////////////////////////////
03085 //     Function: PandaNode::state_changed
03086 //       Access: Protected, Virtual
03087 //  Description: Called after the node's RenderState has been changed
03088 //               for any reason, this just provides a hook so derived
03089 //               classes can do something special in this case.
03090 ////////////////////////////////////////////////////////////////////
03091 void PandaNode::
03092 state_changed() {
03093   nassertv((_unexpected_change_flags & UC_state) == 0);
03094 }
03095 
03096 ////////////////////////////////////////////////////////////////////
03097 //     Function: PandaNode::draw_mask_changed
03098 //       Access: Protected, Virtual
03099 //  Description: Called after the node's DrawMask has been changed
03100 //               for any reason, this just provides a hook so derived
03101 //               classes can do something special in this case.
03102 ////////////////////////////////////////////////////////////////////
03103 void PandaNode::
03104 draw_mask_changed() {
03105   nassertv((_unexpected_change_flags & UC_draw_mask) == 0);
03106 }
03107 
03108 ////////////////////////////////////////////////////////////////////
03109 //     Function: PandaNode::r_copy_subgraph
03110 //       Access: Protected, Virtual
03111 //  Description: This is the recursive implementation of copy_subgraph().
03112 //               It returns a copy of the entire subgraph rooted at
03113 //               this node.
03114 //
03115 //               Note that it includes the parameter inst_map, which
03116 //               is a map type, and is not (and cannot be) exported
03117 //               from PANDA.DLL.  Thus, any derivative of PandaNode
03118 //               that is not also a member of PANDA.DLL *cannot*
03119 //               access this map.
03120 ////////////////////////////////////////////////////////////////////
03121 PT(PandaNode) PandaNode::
03122 r_copy_subgraph(PandaNode::InstanceMap &inst_map, Thread *current_thread) const {
03123   PT(PandaNode) copy = make_copy();
03124   nassertr(copy != (PandaNode *)NULL, NULL);
03125   if (copy->get_type() != get_type()) {
03126     pgraph_cat.warning()
03127       << "Don't know how to copy nodes of type " << get_type() << "\n";
03128 
03129     if (no_unsupported_copy) {
03130       nassertr(false, NULL);
03131     }
03132   }
03133 
03134   copy->r_copy_children(this, inst_map, current_thread);
03135   return copy;
03136 }
03137 
03138 ////////////////////////////////////////////////////////////////////
03139 //     Function: PandaNode::r_copy_children
03140 //       Access: Protected, Virtual
03141 //  Description: This is called by r_copy_subgraph(); the copy has
03142 //               already been made of this particular node (and this
03143 //               is the copy); this function's job is to copy all of
03144 //               the children from the original.
03145 //
03146 //               Note that it includes the parameter inst_map, which
03147 //               is a map type, and is not (and cannot be) exported
03148 //               from PANDA.DLL.  Thus, any derivative of PandaNode
03149 //               that is not also a member of PANDA.DLL *cannot*
03150 //               access this map, and probably should not even
03151 //               override this function.
03152 ////////////////////////////////////////////////////////////////////
03153 void PandaNode::
03154 r_copy_children(const PandaNode *from, PandaNode::InstanceMap &inst_map,
03155                 Thread *current_thread) {
03156   CDReader from_cdata(from->_cycler, current_thread);
03157   CPT(Down) from_down = from_cdata->get_down();
03158   Down::const_iterator di;
03159   for (di = from_down->begin(); di != from_down->end(); ++di) {
03160     int sort = (*di).get_sort();
03161     PandaNode *source_child = (*di).get_child();
03162     PT(PandaNode) dest_child;
03163 
03164     // Check to see if we have already copied this child.  If we
03165     // have, use the copy.  In this way, a subgraph that contains
03166     // instances will be correctly duplicated into another subgraph
03167     // that also contains its own instances.
03168     InstanceMap::const_iterator ci;
03169     ci = inst_map.find(source_child);
03170     if (ci != inst_map.end()) {
03171       dest_child = (*ci).second;
03172     } else {
03173       dest_child = source_child->r_copy_subgraph(inst_map, current_thread);
03174       inst_map[source_child] = dest_child;
03175     }
03176 
03177     quick_add_new_child(dest_child, sort, current_thread);
03178   }
03179 }
03180 
03181 ////////////////////////////////////////////////////////////////////
03182 //     Function: PandaNode::r_prepare_scene
03183 //       Access: Public, Virtual
03184 //  Description: The recursive implementation of prepare_scene().
03185 //               Don't call this directly; call
03186 //               PandaNode::prepare_scene() or
03187 //               NodePath::prepare_scene() instead.
03188 ////////////////////////////////////////////////////////////////////
03189 void PandaNode::
03190 r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state,
03191                 GeomTransformer &transformer, Thread *current_thread) {
03192   Children children = get_children(current_thread);
03193   // We must call get_num_children() each time through the loop, in
03194   // case we're running SIMPLE_THREADS and we get interrupted.
03195   int i;
03196   for (i = 0; i < children.get_num_children(); i++) {
03197     PandaNode *child = children.get_child(i);
03198     CPT(RenderState) child_state = node_state->compose(child->get_state());
03199     child->r_prepare_scene(gsg, child_state, transformer, current_thread);
03200   }
03201 
03202   Stashed stashed = get_stashed(current_thread);
03203   for (i = 0; i < stashed.get_num_stashed(); i++) {
03204     PandaNode *child = stashed.get_stashed(i);
03205     CPT(RenderState) child_state = node_state->compose(child->get_state());
03206     child->r_prepare_scene(gsg, child_state, transformer, current_thread);
03207   }
03208 }
03209 
03210 ////////////////////////////////////////////////////////////////////
03211 //     Function: PandaNode::set_cull_callback
03212 //       Access: Protected
03213 //  Description: Intended to be called in the constructor by any
03214 //               subclass that defines cull_callback(), this sets up
03215 //               the flags to indicate that the cullback needs to be
03216 //               called.
03217 ////////////////////////////////////////////////////////////////////
03218 void PandaNode::
03219 set_cull_callback() {
03220   Thread *current_thread = Thread::get_current_thread();
03221   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
03222     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03223     cdata->set_fancy_bit(FB_cull_callback, true);
03224   }
03225   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
03226   mark_bam_modified();
03227 }
03228 
03229 ////////////////////////////////////////////////////////////////////
03230 //     Function: PandaNode::disable_cull_callback
03231 //       Access: Protected
03232 //  Description: disables the call back
03233 ////////////////////////////////////////////////////////////////////
03234 void PandaNode::
03235 disable_cull_callback() {
03236   Thread *current_thread = Thread::get_current_thread();
03237   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
03238     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03239     cdata->set_fancy_bit(FB_cull_callback, false);
03240   }
03241   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
03242   mark_bam_modified();
03243 }
03244 
03245 ////////////////////////////////////////////////////////////////////
03246 //     Function: PandaNode::stage_remove_child
03247 //       Access: Private
03248 //  Description: The private implementation of remove_child(), for a
03249 //               particular pipeline stage.
03250 ////////////////////////////////////////////////////////////////////
03251 bool PandaNode::
03252 stage_remove_child(PandaNode *child_node, int pipeline_stage,
03253                    Thread *current_thread) {
03254   CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03255       
03256   // First, look for the parent in the child's up list, to ensure the
03257   // child is known.
03258   CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
03259                             current_thread);
03260   int parent_index = child_node->do_find_parent(this, cdata_child);
03261   if (parent_index < 0) {
03262     // Nope, no relation.
03263     return false;
03264   }
03265 
03266   PT(Down) down = cdata->modify_down();
03267   int child_index = do_find_child(child_node, down);
03268   if (child_index >= 0) {
03269     // The child exists; remove it.
03270     down->erase(down->begin() + child_index);
03271     int num_erased = cdata_child->modify_up()->erase(UpConnection(this));
03272     nassertr(num_erased == 1, false);
03273     return true;
03274   }
03275 
03276   PT(Down) stashed = cdata->modify_stashed();
03277   int stashed_index = do_find_child(child_node, stashed);
03278   if (stashed_index >= 0) {
03279     // The child has been stashed; remove it.
03280     stashed->erase(stashed->begin() + stashed_index);
03281     int num_erased = cdata_child->modify_up()->erase(UpConnection(this));
03282     nassertr(num_erased == 1, false);
03283     return true;
03284   }
03285 
03286   // Never heard of this child.  This shouldn't be possible, because
03287   // the parent was in the child's up list, above.  Must be some
03288   // internal error.
03289   nassertr(false, false);
03290   return false;
03291 }
03292 
03293 ////////////////////////////////////////////////////////////////////
03294 //     Function: PandaNode::stage_replace_child
03295 //       Access: Private
03296 //  Description: The private implementation of replace_child(), for a
03297 //               particular pipeline stage.
03298 ////////////////////////////////////////////////////////////////////
03299 bool PandaNode::
03300 stage_replace_child(PandaNode *orig_child, PandaNode *new_child,
03301                     int pipeline_stage, Thread *current_thread) {
03302   {
03303     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03304     CDStageWriter cdata_orig_child(orig_child->_cycler, pipeline_stage, current_thread);
03305     CDStageWriter cdata_new_child(new_child->_cycler, pipeline_stage, current_thread);
03306     
03307     // First, look for the parent in the child's up list, to ensure the
03308     // child is known.
03309     int parent_index = orig_child->do_find_parent(this, cdata_orig_child);
03310     if (parent_index < 0) {
03311       // Nope, no relation.
03312       return false;
03313     }
03314     
03315     if (orig_child == new_child) {
03316       // Trivial no-op.
03317       return true;
03318     }
03319     
03320     // Don't let orig_child be destructed yet.
03321     PT(PandaNode) keep_orig_child = orig_child;
03322 
03323     // If we already have new_child as a child, remove it first.
03324     if (stage_remove_child(new_child, pipeline_stage, current_thread)) {
03325       sever_connection(this, new_child, pipeline_stage, current_thread);
03326     }
03327     
03328     PT(Down) down = cdata->modify_down();
03329     int child_index = do_find_child(orig_child, down);
03330     if (child_index >= 0) {
03331       // The child exists; replace it.
03332       DownConnection &dc = (*down)[child_index];
03333       nassertr(dc.get_child() == orig_child, false);
03334       dc.set_child(new_child);
03335       
03336     } else {
03337       PT(Down) stashed = cdata->modify_stashed();
03338       int stashed_index = do_find_child(orig_child, stashed);
03339       if (stashed_index >= 0) {
03340         // The child has been stashed; remove it.
03341         DownConnection &dc = (*stashed)[stashed_index];
03342         nassertr(dc.get_child() == orig_child, false);
03343         dc.set_child(new_child);
03344         
03345       } else {
03346         // Never heard of this child.  This shouldn't be possible, because
03347         // the parent was in the child's up list, above.  Must be some
03348         // internal error.
03349         nassertr(false, false);
03350         return false;
03351       }
03352     }
03353     
03354     // Now adjust the bookkeeping on both children.
03355     cdata_new_child->modify_up()->insert(UpConnection(this));
03356     int num_erased = cdata_orig_child->modify_up()->erase(UpConnection(this));
03357     nassertr(num_erased == 1, false);
03358   }
03359 
03360   sever_connection(this, orig_child, pipeline_stage, current_thread);
03361   new_connection(this, new_child, pipeline_stage, current_thread);
03362 
03363   force_bounds_stale(pipeline_stage, current_thread);
03364   orig_child->parents_changed();
03365   new_child->parents_changed();
03366   mark_bam_modified();
03367   orig_child->mark_bam_modified();
03368   new_child->mark_bam_modified();
03369 
03370   return true;
03371 }
03372 
03373 ////////////////////////////////////////////////////////////////////
03374 //     Function: PandaNode::quick_add_new_child
03375 //       Access: Private
03376 //  Description: Similar to add_child(), but performs fewer checks.
03377 //               The purpose of this method is to add a child node
03378 //               that was newly constructed, to a parent node that was
03379 //               newly constructed, so we know we have to make fewer
03380 //               sanity checks.  This is a private method; do not call
03381 //               it directly.
03382 ////////////////////////////////////////////////////////////////////
03383 void PandaNode::
03384 quick_add_new_child(PandaNode *child_node, int sort, Thread *current_thread) {
03385   // Apply this operation to the current stage as well as to all
03386   // upstream stages.
03387   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
03388     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
03389     CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03390     
03391     cdata->modify_down()->insert(DownConnection(child_node, sort));
03392     cdata_child->modify_up()->insert(UpConnection(this));
03393   }
03394   CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
03395 }
03396 
03397 ////////////////////////////////////////////////////////////////////
03398 //     Function: PandaNode::report_cycle
03399 //       Access: Private
03400 //  Description: Raises an assertion when a graph cycle attempt is
03401 //               detected (and aborted).
03402 ////////////////////////////////////////////////////////////////////
03403 void PandaNode::
03404 report_cycle(PandaNode *child_node) {
03405   ostringstream strm;
03406   strm << "Detected attempt to create a cycle in the scene graph: " 
03407        << NodePath::any_path(this) << " : " << *child_node;
03408   nassert_raise(strm.str());
03409 }
03410 
03411 ////////////////////////////////////////////////////////////////////
03412 //     Function: PandaNode::find_node_above
03413 //       Access: Private
03414 //  Description: Returns true if the indicated node is this node, or
03415 //               any ancestor of this node; or false if it is not in
03416 //               this node's ancestry.
03417 ////////////////////////////////////////////////////////////////////
03418 bool PandaNode::
03419 find_node_above(PandaNode *node) {
03420   if (node == this) {
03421     return true;
03422   }
03423 
03424   Parents parents = get_parents();
03425   for (int i = 0; i < parents.get_num_parents(); ++i) {
03426     PandaNode *parent = parents.get_parent(i);
03427     if (parent->find_node_above(node)) {
03428       return true;
03429     }
03430   }
03431 
03432   return false;
03433 }
03434 
03435 ////////////////////////////////////////////////////////////////////
03436 //     Function: PandaNode::attach
03437 //       Access: Private, Static
03438 //  Description: Creates a new parent-child relationship, and returns
03439 //               the new NodePathComponent.  If the child was already
03440 //               attached to the indicated parent, repositions it and
03441 //               returns the original NodePathComponent.
03442 //
03443 //               This operation is automatically propagated back up to
03444 //               pipeline 0, from the specified pipeline stage.
03445 ////////////////////////////////////////////////////////////////////
03446 PT(NodePathComponent) PandaNode::
03447 attach(NodePathComponent *parent, PandaNode *child_node, int sort,
03448        int pipeline_stage, Thread *current_thread) {
03449   if (parent == (NodePathComponent *)NULL) {
03450     // Attaching to NULL means to create a new "instance" with no
03451     // attachments, and no questions asked.
03452     PT(NodePathComponent) child = 
03453       new NodePathComponent(child_node, (NodePathComponent *)NULL,
03454                             pipeline_stage, current_thread);
03455     LightReMutexHolder holder(child_node->_paths_lock);
03456     child_node->_paths.insert(child);
03457     return child;
03458   }
03459 
03460   // See if the child was already attached to the parent.  If it was,
03461   // we'll use that same NodePathComponent.
03462   PT(NodePathComponent) child = get_component(parent, child_node, pipeline_stage, current_thread);
03463 
03464   if (child == (NodePathComponent *)NULL) {
03465     // The child was not already attached to the parent, so get a new
03466     // component.
03467     child = get_top_component(child_node, true, pipeline_stage, current_thread);
03468   }
03469 
03470   reparent(parent, child, sort, false, pipeline_stage, current_thread);
03471 
03472   return child;
03473 }
03474 
03475 ////////////////////////////////////////////////////////////////////
03476 //     Function: PandaNode::detach
03477 //       Access: Private, Static
03478 //  Description: Breaks a parent-child relationship.
03479 //
03480 //               This operation is automatically propagated back up to
03481 //               pipeline 0, from the specified pipeline stage.
03482 ////////////////////////////////////////////////////////////////////
03483 void PandaNode::
03484 detach(NodePathComponent *child, int pipeline_stage, Thread *current_thread) {
03485   nassertv(child != (NodePathComponent *)NULL);
03486 
03487   for (int pipeline_stage_i = pipeline_stage;
03488        pipeline_stage_i >= 0; 
03489        --pipeline_stage_i) {
03490     detach_one_stage(child, pipeline_stage_i, current_thread);
03491   }
03492 
03493   child->get_node()->parents_changed();
03494 }
03495 
03496 ////////////////////////////////////////////////////////////////////
03497 //     Function: PandaNode::detach_one_stage
03498 //       Access: Private, Static
03499 //  Description: Breaks a parent-child relationship.
03500 //
03501 //               This operation is not automatically propagated
03502 //               upstream.  It is applied to the indicated pipeline
03503 //               stage only.
03504 ////////////////////////////////////////////////////////////////////
03505 void PandaNode::
03506 detach_one_stage(NodePathComponent *child, int pipeline_stage, 
03507                  Thread *current_thread) {
03508   nassertv(child != (NodePathComponent *)NULL);
03509   if (child->is_top_node(pipeline_stage, current_thread)) {
03510     return;
03511   }
03512 
03513   PT(PandaNode) child_node = child->get_node();
03514   PT(PandaNode) parent_node = child->get_next(pipeline_stage, current_thread)->get_node();
03515     
03516   CDStageWriter cdata_parent(parent_node->_cycler, pipeline_stage, current_thread);
03517   CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03518   int parent_index = child_node->do_find_parent(parent_node, cdata_child);
03519   if (parent_index >= 0) {
03520     // Now look for the child and break the actual connection.
03521     
03522     // First, look for and remove the parent node from the child's up
03523     // list.
03524     int num_erased = cdata_child->modify_up()->erase(UpConnection(parent_node));
03525     nassertv(num_erased == 1);
03526     
03527     // Now, look for and remove the child node from the parent's down
03528     // list.  We also check in the stashed list, in case the child node
03529     // has been stashed.
03530     Down::iterator di;
03531     bool found = false;
03532     PT(Down) down = cdata_parent->modify_down();
03533     for (di = down->begin(); di != down->end(); ++di) {
03534       if ((*di).get_child() == child_node) {
03535         down->erase(di);
03536         found = true;
03537         break;
03538       }
03539     }
03540     if (!found) {
03541       PT(Down) stashed = cdata_parent->modify_stashed();
03542       for (di = stashed->begin(); di != stashed->end(); ++di) {
03543         if ((*di).get_child() == child_node) {
03544           stashed->erase(di);
03545           found = true;
03546           break;
03547         }
03548       }
03549     }
03550     nassertv(found);
03551   }
03552     
03553   // Finally, break the NodePathComponent connection.
03554   sever_connection(parent_node, child_node, pipeline_stage, current_thread);
03555 
03556   parent_node->force_bounds_stale(pipeline_stage, current_thread);
03557   parent_node->children_changed();
03558   parent_node->mark_bam_modified();
03559 }
03560 
03561 ////////////////////////////////////////////////////////////////////
03562 //     Function: PandaNode::reparent
03563 //       Access: Private, Static
03564 //  Description: Switches a node from one parent to another.  Returns
03565 //               true if the new connection is allowed, or false if it
03566 //               conflicts with another instance (that is, another
03567 //               instance of the child is already attached to the
03568 //               indicated parent).
03569 //
03570 //               This operation is automatically propagated back up to
03571 //               pipeline 0, from the specified pipeline stage.
03572 ////////////////////////////////////////////////////////////////////
03573 bool PandaNode::
03574 reparent(NodePathComponent *new_parent, NodePathComponent *child, int sort,
03575          bool as_stashed, int pipeline_stage, Thread *current_thread) {
03576   bool any_ok = false;
03577 
03578   if (new_parent != (NodePathComponent *)NULL &&
03579       !new_parent->get_node()->verify_child_no_cycles(child->get_node())) {
03580     // Whoops, adding this child node would introduce a cycle in the
03581     // scene graph.
03582     return false;
03583   }
03584 
03585   for (int pipeline_stage_i = pipeline_stage;
03586        pipeline_stage_i >= 0; 
03587        --pipeline_stage_i) {
03588     if (reparent_one_stage(new_parent, child, sort, as_stashed, 
03589                            pipeline_stage_i, current_thread)) {
03590       any_ok = true;
03591     }
03592   }
03593 
03594   if (new_parent != (NodePathComponent *)NULL) {
03595     new_parent->get_node()->children_changed();
03596     new_parent->get_node()->mark_bam_modified();
03597   }
03598   child->get_node()->parents_changed();
03599   child->get_node()->mark_bam_modified();
03600 
03601   return any_ok;
03602 }
03603 
03604 ////////////////////////////////////////////////////////////////////
03605 //     Function: PandaNode::reparent_one_stage
03606 //       Access: Private, Static
03607 //  Description: Switches a node from one parent to another.  Returns
03608 //               true if the new connection is allowed, or false if it
03609 //               conflicts with another instance (that is, another
03610 //               instance of the child is already attached to the
03611 //               indicated parent).
03612 //
03613 //               This operation is not automatically propagated
03614 //               upstream.  It is applied to the indicated pipeline
03615 //               stage only.
03616 ////////////////////////////////////////////////////////////////////
03617 bool PandaNode::
03618 reparent_one_stage(NodePathComponent *new_parent, NodePathComponent *child, 
03619                    int sort, bool as_stashed, int pipeline_stage, 
03620                    Thread *current_thread) {
03621   nassertr(child != (NodePathComponent *)NULL, false);
03622 
03623   // Keep a reference count to the new parent, since detaching the
03624   // child might lose the count.
03625   PT(NodePathComponent) keep_parent = new_parent;
03626 
03627   if (!child->is_top_node(pipeline_stage, current_thread)) {
03628     detach(child, pipeline_stage, current_thread);
03629   }
03630 
03631   if (new_parent != (NodePathComponent *)NULL) {
03632     PandaNode *child_node = child->get_node();
03633     PandaNode *parent_node = new_parent->get_node();
03634 
03635     {
03636       CDStageReader cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03637       int parent_index = child_node->do_find_parent(parent_node, cdata_child);
03638 
03639       if (parent_index >= 0) {
03640         // Whoops, there's already another instance of the child there.
03641         return false;
03642       }
03643     }
03644 
03645     // Redirect the connection to the indicated new parent.
03646     child->set_next(new_parent, pipeline_stage, current_thread);
03647     
03648     // Now reattach the child node at the indicated sort position.
03649     {
03650       CDStageWriter cdata_parent(parent_node->_cycler, pipeline_stage, current_thread);
03651       CDStageWriter cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03652 
03653       if (as_stashed) {
03654         cdata_parent->modify_stashed()->insert(DownConnection(child_node, sort));
03655       } else {
03656         cdata_parent->modify_down()->insert(DownConnection(child_node, sort));
03657       }
03658       cdata_child->modify_up()->insert(UpConnection(parent_node));
03659 
03660 #ifndef NDEBUG
03661       // The NodePathComponent should already be in the set.
03662       {
03663         LightReMutexHolder holder(child_node->_paths_lock);
03664         nassertr(child_node->_paths.find(child) != child_node->_paths.end(), false);
03665       }
03666 #endif // NDEBUG
03667     }
03668 
03669     child_node->fix_path_lengths(pipeline_stage, current_thread);
03670     parent_node->force_bounds_stale(pipeline_stage, current_thread);
03671   }
03672 
03673   return true;
03674 }
03675 
03676 ////////////////////////////////////////////////////////////////////
03677 //     Function: PandaNode::get_component
03678 //       Access: Private, Static
03679 //  Description: Returns the NodePathComponent based on the indicated
03680 //               child of the given parent, or NULL if there is no
03681 //               such parent-child relationship.
03682 ////////////////////////////////////////////////////////////////////
03683 PT(NodePathComponent) PandaNode::
03684 get_component(NodePathComponent *parent, PandaNode *child_node,
03685               int pipeline_stage, Thread *current_thread) {
03686   nassertr(parent != (NodePathComponent *)NULL, (NodePathComponent *)NULL);
03687   PandaNode *parent_node = parent->get_node();
03688 
03689   LightReMutexHolder holder(child_node->_paths_lock);
03690 
03691   // First, walk through the list of NodePathComponents we already
03692   // have on the child, looking for one that already exists,
03693   // referencing the indicated parent component.
03694   Paths::const_iterator pi;
03695   for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
03696     if ((*pi)->get_next(pipeline_stage, current_thread) == parent) {
03697       // If we already have such a component, just return it.
03698       return (*pi);
03699     }
03700   }
03701     
03702   // We don't already have a NodePathComponent referring to this
03703   // parent-child relationship.  Are they actually related?
03704   CDStageReader cdata_child(child_node->_cycler, pipeline_stage, current_thread);
03705   int parent_index = child_node->do_find_parent(parent_node, cdata_child);
03706   
03707   if (parent_index >= 0) {
03708     // They are.  Create and return a new one.
03709     PT(NodePathComponent) child = 
03710       new NodePathComponent(child_node, parent, pipeline_stage, current_thread);
03711     child_node->_paths.insert(child);
03712     return child;
03713   } else {
03714     // They aren't related.  Return NULL.
03715     return NULL;
03716   }
03717 }
03718 
03719 ////////////////////////////////////////////////////////////////////
03720 //     Function: PandaNode::get_top_component
03721 //       Access: Private, Static
03722 //  Description: Returns a NodePathComponent referencing the
03723 //               indicated node as a singleton.  It is invalid to call
03724 //               this for a node that has parents, unless you are
03725 //               about to create a new instance (and immediately
03726 //               reconnect the NodePathComponent elsewhere).
03727 //
03728 //               If force is true, this will always return something,
03729 //               even if it needs to create a new top component;
03730 //               otherwise, if force is false, it will return NULL if
03731 //               there is not already a top component available.
03732 ////////////////////////////////////////////////////////////////////
03733 PT(NodePathComponent) PandaNode::
03734 get_top_component(PandaNode *child_node, bool force, int pipeline_stage, 
03735                   Thread *current_thread) {
03736   LightReMutexHolder holder(child_node->_paths_lock);
03737 
03738   // Walk through the list of NodePathComponents we already have on
03739   // the child, looking for one that already exists as a top node.
03740   Paths::const_iterator pi;
03741   for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
03742     if ((*pi)->is_top_node(pipeline_stage, current_thread)) {
03743       // If we already have such a component, just return it.
03744       return (*pi);
03745     }
03746   }
03747 
03748   if (!force) {
03749     // If we don't care to force the point, return NULL to indicate
03750     // there's not already a top component.
03751     return NULL;
03752   }
03753 
03754   // We don't already have such a NodePathComponent; create and
03755   // return a new one.
03756   PT(NodePathComponent) child = 
03757     new NodePathComponent(child_node, (NodePathComponent *)NULL,
03758                           pipeline_stage, current_thread);
03759   child_node->_paths.insert(child);
03760 
03761   return child;
03762 }
03763 
03764 ////////////////////////////////////////////////////////////////////
03765 //     Function: PandaNode::get_generic_component
03766 //       Access: Private
03767 //  Description: Returns a NodePathComponent referencing this node as
03768 //               a path from the root.  
03769 //
03770 //               Unless accept_ambiguity is true, it is only valid to
03771 //               call this if there is an unambiguous path from the
03772 //               root; otherwise, a warning will be issued and one
03773 //               path will be chosen arbitrarily.
03774 ////////////////////////////////////////////////////////////////////
03775 PT(NodePathComponent) PandaNode::
03776 get_generic_component(bool accept_ambiguity, int pipeline_stage, 
03777                       Thread *current_thread) {
03778   bool ambiguity_detected = false;
03779   PT(NodePathComponent) result = 
03780     r_get_generic_component(accept_ambiguity, ambiguity_detected,
03781                             pipeline_stage, current_thread);
03782 
03783   if (!accept_ambiguity && ambiguity_detected) {
03784     pgraph_cat.warning()
03785       << "Chose: " << *result << "\n";
03786     nassertr(!unambiguous_graph, result);
03787   }
03788 
03789   return result;
03790 }
03791 
03792 ////////////////////////////////////////////////////////////////////
03793 //     Function: PandaNode::r_get_generic_component
03794 //       Access: Private
03795 //  Description: The recursive implementation of
03796 //               get_generic_component, this simply sets the flag when
03797 //               the ambiguity is detected (so we can report the
03798 //               bottom node that started the ambiguous search).
03799 ////////////////////////////////////////////////////////////////////
03800 PT(NodePathComponent) PandaNode::
03801 r_get_generic_component(bool accept_ambiguity, bool &ambiguity_detected,
03802                         int pipeline_stage, Thread *current_thread) {
03803   PT(PandaNode) parent_node;
03804 
03805   {
03806     CDStageReader cdata(_cycler, pipeline_stage, current_thread);
03807     
03808     int num_parents = cdata->get_up()->size();
03809     if (num_parents == 0) {
03810       // No parents; no ambiguity.  This is the root.
03811       return get_top_component(this, true, pipeline_stage, current_thread);
03812     } 
03813 
03814     PT(NodePathComponent) result;
03815     if (num_parents == 1) {
03816       // Only one parent; no ambiguity.
03817       PT(NodePathComponent) parent = 
03818         get_parent(0)->r_get_generic_component(accept_ambiguity, ambiguity_detected, pipeline_stage, current_thread);
03819       return get_component(parent, this, pipeline_stage, current_thread);
03820     }
03821 
03822     // Oops, multiple parents; the NodePath is ambiguous.
03823     if (!accept_ambiguity) {
03824       pgraph_cat.warning()
03825         << *this << " has " << num_parents
03826         << " parents; choosing arbitrary path to root.\n";
03827     }
03828     ambiguity_detected = true;
03829     CPT(Up) up = cdata->get_up();
03830     parent_node = (*up)[0].get_parent();
03831   }
03832 
03833   // Now that the lock is released, it's safe to recurse.
03834   PT(NodePathComponent) parent = 
03835     parent_node->r_get_generic_component(accept_ambiguity, ambiguity_detected, pipeline_stage, current_thread);
03836   return get_component(parent, this, pipeline_stage, current_thread);
03837 }
03838 
03839 ////////////////////////////////////////////////////////////////////
03840 //     Function: PandaNode::delete_component
03841 //       Access: Private
03842 //  Description: Removes a NodePathComponent from the set prior to
03843 //               its deletion.  This should only be called by the
03844 //               NodePathComponent destructor.
03845 ////////////////////////////////////////////////////////////////////
03846 void PandaNode::
03847 delete_component(NodePathComponent *component) {
03848   LightReMutexHolder holder(_paths_lock);
03849   int num_erased = _paths.erase(component);
03850   nassertv(num_erased == 1);
03851 }
03852 
03853 ////////////////////////////////////////////////////////////////////
03854 //     Function: PandaNode::sever_connection
03855 //       Access: Private, Static
03856 //  Description: This is called internally when a parent-child
03857 //               connection is broken to update the NodePathComponents
03858 //               that reflected this connection.
03859 //
03860 //               It severs any NodePathComponents on the child node
03861 //               that reference the indicated parent node.  These
03862 //               components remain unattached; there may therefore be
03863 //               multiple "instances" of a node that all have no
03864 //               parent, even while there are other instances that do
03865 //               have parents.
03866 //
03867 //               This operation is not automatically propagated
03868 //               upstream.  It is applied to the indicated pipeline
03869 //               stage only.
03870 ////////////////////////////////////////////////////////////////////
03871 void PandaNode::
03872 sever_connection(PandaNode *parent_node, PandaNode *child_node,
03873                  int pipeline_stage, Thread *current_thread) {
03874   {
03875     LightReMutexHolder holder(child_node->_paths_lock);
03876     Paths::iterator pi;
03877     for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
03878       if (!(*pi)->is_top_node(pipeline_stage, current_thread) && 
03879           (*pi)->get_next(pipeline_stage, current_thread)->get_node() == parent_node) {
03880         // Sever the component here.
03881         (*pi)->set_top_node(pipeline_stage, current_thread);
03882       }
03883     }
03884   }
03885   child_node->fix_path_lengths(pipeline_stage, current_thread);
03886 }
03887 
03888 ////////////////////////////////////////////////////////////////////
03889 //     Function: PandaNode::new_connection
03890 //       Access: Private, Static
03891 //  Description: This is called internally when a parent-child
03892 //               connection is established to update the
03893 //               NodePathComponents that might be involved.
03894 //
03895 //               It adjusts any NodePathComponents the child has that
03896 //               reference the child as a top node.  Any other
03897 //               components we can leave alone, because we are making
03898 //               a new instance of the child.
03899 //
03900 //               This operation is not automatically propagated
03901 //               upstream.  It is applied to the indicated pipeline
03902 //               stage only.
03903 ////////////////////////////////////////////////////////////////////
03904 void PandaNode::
03905 new_connection(PandaNode *parent_node, PandaNode *child_node,
03906                int pipeline_stage, Thread *current_thread) {
03907   {
03908     LightReMutexHolder holder(child_node->_paths_lock);
03909     Paths::iterator pi;
03910     for (pi = child_node->_paths.begin(); pi != child_node->_paths.end(); ++pi) {
03911       if ((*pi)->is_top_node(pipeline_stage, current_thread)) {
03912         (*pi)->set_next(parent_node->get_generic_component(false, pipeline_stage, current_thread), pipeline_stage, current_thread);
03913       }
03914     }
03915   }
03916   child_node->fix_path_lengths(pipeline_stage, current_thread);
03917 }
03918 
03919 ////////////////////////////////////////////////////////////////////
03920 //     Function: PandaNode::fix_path_lengths
03921 //       Access: Private
03922 //  Description: Recursively fixes the _length member of each
03923 //               NodePathComponent at this level and below, after an
03924 //               add or delete child operation that might have messed
03925 //               these up.
03926 //
03927 //               This operation is not automatically propagated
03928 //               upstream.  It is applied to the indicated pipeline
03929 //               stage only.
03930 ////////////////////////////////////////////////////////////////////
03931 void PandaNode::
03932 fix_path_lengths(int pipeline_stage, Thread *current_thread) {
03933   LightReMutexHolder holder(_paths_lock);
03934 
03935   bool any_wrong = false;
03936 
03937   Paths::const_iterator pi;
03938   for (pi = _paths.begin(); pi != _paths.end(); ++pi) {
03939     if ((*pi)->fix_length(pipeline_stage, current_thread)) {
03940       any_wrong = true;
03941     }
03942   }
03943   
03944   // If any paths were updated, we have to recurse on all of our
03945   // children, since any one of those paths might be shared by any of
03946   // our child nodes.  Don't hold any locks while we recurse.
03947   if (any_wrong) {
03948     Children children;
03949     Stashed stashed;
03950     {
03951       CDStageReader cdata(_cycler, pipeline_stage, current_thread);
03952       children = Children(cdata);
03953       stashed = Stashed(cdata);
03954     }
03955 
03956     int num_children = children.get_num_children();
03957     int i;
03958     for (i = 0; i < num_children; ++i) {
03959       PandaNode *child_node = children.get_child(i);
03960       child_node->fix_path_lengths(pipeline_stage, current_thread);
03961     }
03962     int num_stashed = stashed.get_num_stashed();
03963     for (i = 0; i < num_stashed; ++i) {
03964       PandaNode *child_node = stashed.get_stashed(i);
03965       child_node->fix_path_lengths(pipeline_stage, current_thread);
03966     }
03967   }
03968 }
03969 
03970 ////////////////////////////////////////////////////////////////////
03971 //     Function: PandaNode::r_list_descendants
03972 //       Access: Private
03973 //  Description: The recursive implementation of ls().
03974 ////////////////////////////////////////////////////////////////////
03975 void PandaNode::
03976 r_list_descendants(ostream &out, int indent_level) const {
03977   write(out, indent_level);
03978 
03979   Children children = get_children();
03980   int num_children = children.get_num_children();
03981 
03982   for (int i = 0; i < num_children; ++i) {
03983     PandaNode *child = children.get_child(i);
03984     child->r_list_descendants(out, indent_level + 2);
03985   }
03986 
03987   // Also report the number of stashed nodes at this level.
03988   int num_stashed = get_num_stashed();
03989   if (num_stashed != 0) {
03990     indent(out, indent_level) << "(" << num_stashed << " stashed)\n";
03991   }
03992 }
03993 
03994 ////////////////////////////////////////////////////////////////////
03995 //     Function: PandaNode::do_find_child
03996 //       Access: Private
03997 //  Description: The private implementation of find_child().
03998 ////////////////////////////////////////////////////////////////////
03999 int PandaNode::
04000 do_find_child(PandaNode *node, const PandaNode::Down *down) const {
04001   nassertr(node != (PandaNode *)NULL, -1);
04002 
04003   // We have to search for the child by brute force, since we don't
04004   // know what sort index it was added as.
04005   Down::const_iterator di;
04006   for (di = down->begin(); di != down->end(); ++di) {
04007     if ((*di).get_child() == node) {
04008       return di - down->begin();
04009     }
04010   }
04011 
04012   return -1;
04013 }
04014 
04015 ////////////////////////////////////////////////////////////////////
04016 //     Function: PandaNode::update_bounds
04017 //       Access: Private
04018 //  Description: Updates the cached values of the node that are
04019 //               dependent on its children, such as the
04020 //               external bounding volume, the _net_collide_mask, and
04021 //               the _off_clip_planes.
04022 //
04023 //               The old value should be passed in; it will be
04024 //               released.  The new value is returned.
04025 ////////////////////////////////////////////////////////////////////
04026 PandaNode::CDStageWriter PandaNode::
04027 update_bounds(int pipeline_stage, PandaNode::CDLockedStageReader &cdata) {
04028   // We might need to try this a couple of times, in case someone else
04029   // steps on our result.
04030   if (drawmask_cat.is_debug()) {
04031     drawmask_cat.debug(false) 
04032       << *this << "::update_bounds() {\n";
04033   }
04034   Thread *current_thread = cdata.get_current_thread();
04035 
04036   do {
04037     // Grab the last_update counter.
04038     UpdateSeq last_update = cdata->_last_update;
04039     UpdateSeq next_update = cdata->_next_update;
04040     nassertr(last_update != next_update, CDStageWriter(_cycler, pipeline_stage, cdata));
04041 
04042     // Start with a clean slate.
04043     CollideMask net_collide_mask = cdata->_into_collide_mask;
04044     DrawMask net_draw_control_mask, net_draw_show_mask;
04045     bool renderable = is_renderable();
04046 
04047     if (renderable) {
04048       // If this node is itself renderable, it contributes to the net
04049       // draw mask.
04050       net_draw_control_mask = cdata->_draw_control_mask;
04051       net_draw_show_mask = cdata->_draw_show_mask;
04052     }
04053 
04054     if (drawmask_cat.is_debug()) {
04055       drawmask_cat.debug(false)
04056         << "net_draw_control_mask = " << net_draw_control_mask
04057         << "\nnet_draw_show_mask = " << net_draw_show_mask
04058         << "\n";
04059     }
04060     CPT(RenderAttrib) off_clip_planes = cdata->_state->get_attrib(ClipPlaneAttrib::get_class_slot());
04061     if (off_clip_planes == (RenderAttrib *)NULL) {
04062       off_clip_planes = ClipPlaneAttrib::make();
04063     }
04064 
04065     // Also get the list of the node's children.
04066     Children children(cdata);
04067 
04068     int num_vertices = cdata->_internal_vertices;
04069 
04070     // Now that we've got all the data we need from the node, we can
04071     // release the lock.
04072     _cycler.release_read_stage(pipeline_stage, cdata.take_pointer());
04073 
04074     int num_children = children.get_num_children();
04075 
04076     // We need to keep references to the bounding volumes, since in a
04077     // threaded environment the pointers might go away while we're
04078     // working (since we're not holding a lock on our set of children
04079     // right now).  But we also need the regular pointers, to pass to
04080     // BoundingVolume::around().
04081 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04082     pvector<CPT(BoundingVolume) > child_volumes_ref;
04083     child_volumes_ref.reserve(num_children + 1);
04084 #endif
04085     const BoundingVolume **child_volumes = (const BoundingVolume **)alloca(sizeof(BoundingVolume *) * (num_children + 1));
04086     int child_volumes_i = 0;
04087   
04088     bool all_box = true;
04089     CPT(BoundingVolume) internal_bounds = 
04090       get_internal_bounds(pipeline_stage, current_thread);
04091 
04092     if (!internal_bounds->is_empty()) {
04093 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04094       child_volumes_ref.push_back(internal_bounds);
04095 #endif
04096       nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
04097       child_volumes[child_volumes_i++] = internal_bounds;
04098       if (internal_bounds->as_bounding_box() == NULL) {
04099         all_box = false;
04100       }
04101     }
04102 
04103     // Now expand those contents to include all of our children.
04104 
04105     for (int i = 0; i < num_children; ++i) {
04106       PandaNode *child = children.get_child(i);
04107 
04108       const ClipPlaneAttrib *orig_cp = DCAST(ClipPlaneAttrib, off_clip_planes);
04109       
04110       CDLockedStageReader child_cdata(child->_cycler, pipeline_stage, current_thread);
04111       if (child_cdata->_last_update != child_cdata->_next_update) {
04112         // Child needs update.
04113         CDStageWriter child_cdataw = child->update_bounds(pipeline_stage, child_cdata);
04114       
04115         net_collide_mask |= child_cdataw->_net_collide_mask;
04116 
04117         if (drawmask_cat.is_debug()) {
04118           drawmask_cat.debug(false)
04119             << "\nchild update " << *child << ":\n";
04120         }
04121 
04122         DrawMask child_control_mask = child_cdataw->_net_draw_control_mask;
04123         DrawMask child_show_mask = child_cdataw->_net_draw_show_mask;
04124         if (!(child_control_mask | child_show_mask).is_zero()) {
04125           // This child includes a renderable node or subtree.  Thus,
04126           // we should propagate its draw masks.
04127           renderable = true;
04128 
04129           // For each bit position in the masks, we have assigned the
04130           // following semantic meaning.  The number on the left
04131           // represents the pairing of the corresponding bit from the
04132           // control mask and from the show mask:
04133           
04134           //   00 : not a renderable node   (control 0, show 0)
04135           //   01 : a normally visible node (control 0, show 1)
04136           //   10 : a hidden node           (control 1, show 0)
04137           //   11 : a show-through node     (control 1, show 1)
04138 
04139           // Now, when we accumulate these masks, we want to do so
04140           // according to the following table, for each bit position:
04141 
04142           //          00   01   10   11     (child)
04143           //        ---------------------
04144           //     00 | 00   01   10   11
04145           //     01 | 01   01   01*  11
04146           //     10 | 10   01*  10   11
04147           //     11 | 11   11   11   11
04148           // (parent)
04149 
04150           // This table is almost the same as the union of both masks,
04151           // with one exception, marked with a * in the above table:
04152           // if one is 10 and the other is 01--that is, one is hidden
04153           // and the other is normally visible--then the result should
04154           // be 01, normally visible.  This is because we only want to
04155           // propagate the hidden bit upwards if *all* renderable
04156           // nodes are hidden.
04157 
04158           // Get the set of exception bits for which the above rule
04159           // applies.  These are the bits for which both bits have
04160           // flipped, but which were not the same in the original.
04161           DrawMask exception_mask = (net_draw_control_mask ^ child_control_mask) & (net_draw_show_mask ^ child_show_mask);
04162           exception_mask &= (net_draw_control_mask ^ net_draw_show_mask);
04163 
04164           if (drawmask_cat.is_debug()) {
04165             drawmask_cat.debug(false)
04166               << "exception_mask = " << exception_mask << "\n";
04167           }
04168 
04169           // Now compute the union, applying the above exception.
04170           net_draw_control_mask |= child_control_mask;
04171           net_draw_show_mask |= child_show_mask;
04172           
04173           net_draw_control_mask &= ~exception_mask;
04174           net_draw_show_mask |= exception_mask;
04175         }
04176 
04177         if (drawmask_cat.is_debug()) {
04178           drawmask_cat.debug(false)
04179             << "child_control_mask = " << child_control_mask
04180             << "\nchild_show_mask = " << child_show_mask
04181             << "\nnet_draw_control_mask = " << net_draw_control_mask
04182             << "\nnet_draw_show_mask = " << net_draw_show_mask
04183             << "\n";
04184         }
04185             
04186         off_clip_planes = orig_cp->compose_off(child_cdataw->_off_clip_planes);
04187         if (!child_cdataw->_external_bounds->is_empty()) {
04188 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04189           child_volumes_ref.push_back(child_cdataw->_external_bounds);
04190 #endif
04191           nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
04192           child_volumes[child_volumes_i++] = child_cdataw->_external_bounds;
04193           if (child_cdataw->_external_bounds->as_bounding_box() == NULL) {
04194             all_box = false;
04195           }
04196         }
04197         num_vertices += child_cdataw->_nested_vertices;
04198 
04199       } else {
04200         // Child is good.
04201         net_collide_mask |= child_cdata->_net_collide_mask;
04202 
04203         // See comments in similar block above.
04204         if (drawmask_cat.is_debug()) {
04205           drawmask_cat.debug(false)
04206             << "\nchild fresh " << *child << ":\n";
04207         }
04208         DrawMask child_control_mask = child_cdata->_net_draw_control_mask;
04209         DrawMask child_show_mask = child_cdata->_net_draw_show_mask;
04210         if (!(child_control_mask | child_show_mask).is_zero()) {
04211           renderable = true;
04212 
04213           DrawMask exception_mask = (net_draw_control_mask ^ child_control_mask) & (net_draw_show_mask ^ child_show_mask);
04214           exception_mask &= (net_draw_control_mask ^ net_draw_show_mask);
04215 
04216           if (drawmask_cat.is_debug()) {
04217             drawmask_cat.debug(false)
04218               << "exception_mask = " << exception_mask << "\n";
04219           }
04220 
04221           // Now compute the union, applying the above exception.
04222           net_draw_control_mask |= child_control_mask;
04223           net_draw_show_mask |= child_show_mask;
04224           
04225           net_draw_control_mask &= ~exception_mask;
04226           net_draw_show_mask |= exception_mask;
04227         }
04228 
04229         if (drawmask_cat.is_debug()) {
04230           drawmask_cat.debug(false)
04231             << "child_control_mask = " << child_control_mask
04232             << "\nchild_show_mask = " << child_show_mask
04233             << "\nnet_draw_control_mask = " << net_draw_control_mask
04234             << "\nnet_draw_show_mask = " << net_draw_show_mask
04235             << "\n";
04236         }
04237 
04238         off_clip_planes = orig_cp->compose_off(child_cdata->_off_clip_planes);
04239         if (!child_cdata->_external_bounds->is_empty()) {
04240 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04241           child_volumes_ref.push_back(child_cdata->_external_bounds);
04242 #endif
04243           nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata));
04244           child_volumes[child_volumes_i++] = child_cdata->_external_bounds;
04245           if (child_cdata->_external_bounds->as_bounding_box() == NULL) {
04246             all_box = false;
04247           }
04248         }
04249         num_vertices += child_cdata->_nested_vertices;
04250       }
04251     }
04252 
04253     {
04254       // Now grab the write lock on this node.
04255       CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
04256       if (last_update == cdataw->_last_update && 
04257           next_update == cdataw->_next_update) {
04258         // Great, no one has monkeyed with these while we were computing
04259         // the cache.  Safe to store the computed values and return.
04260         cdataw->_net_collide_mask = net_collide_mask;
04261 
04262         if (renderable) {
04263           // Any explicit draw control mask on this node trumps anything
04264           // inherited from below, except a show-through.
04265           DrawMask draw_control_mask = cdataw->_draw_control_mask;
04266           DrawMask draw_show_mask = cdataw->_draw_show_mask;
04267 
04268           DrawMask show_through_mask = net_draw_control_mask & net_draw_show_mask;
04269           
04270           net_draw_control_mask |= draw_control_mask;
04271           net_draw_show_mask = (net_draw_show_mask & ~draw_control_mask) | (draw_show_mask & draw_control_mask);
04272 
04273           net_draw_show_mask |= show_through_mask;
04274           
04275           // There are renderable nodes below, so the implicit draw
04276           // bits are all on.
04277           cdataw->_net_draw_control_mask = net_draw_control_mask;
04278           cdataw->_net_draw_show_mask = net_draw_show_mask | ~net_draw_control_mask;
04279           if (drawmask_cat.is_debug()) {
04280             drawmask_cat.debug(false)
04281               << "renderable, set mask " << cdataw->_net_draw_show_mask << "\n";
04282           }
04283         } else {
04284           // There are no renderable nodes below, so the implicit draw
04285           // bits are all off.  Also, we don't care about the draw
04286           // mask on this particular node (since nothing below it is
04287           // renderable anyway).
04288           cdataw->_net_draw_control_mask = net_draw_control_mask;
04289           cdataw->_net_draw_show_mask = net_draw_show_mask;
04290           if (drawmask_cat.is_debug()) {
04291             drawmask_cat.debug(false)
04292               << "not renderable, set mask " << cdataw->_net_draw_show_mask << "\n";
04293           }
04294         }
04295 
04296         cdataw->_off_clip_planes = off_clip_planes;
04297         cdataw->_nested_vertices = num_vertices;
04298 
04299         CPT(TransformState) transform = get_transform(current_thread);
04300         PT(GeometricBoundingVolume) gbv;
04301 
04302         BoundingVolume::BoundsType btype = cdataw->_bounds_type;
04303         if (btype == BoundingVolume::BT_default) {
04304           btype = bounds_type;
04305         }
04306 
04307         if (btype == BoundingVolume::BT_box ||
04308             (btype != BoundingVolume::BT_sphere && all_box && transform->is_identity())) {
04309           // If all of the child volumes are a BoundingBox, and we
04310           // have no transform, then our volume is also a
04311           // BoundingBox.
04312           
04313           gbv = new BoundingBox;
04314         } else {
04315           // Otherwise, it's a sphere.
04316           gbv = new BoundingSphere;
04317         }
04318         
04319         if (child_volumes_i > 0) {
04320           const BoundingVolume **child_begin = &child_volumes[0];
04321           const BoundingVolume **child_end = child_begin + child_volumes_i;
04322           ((BoundingVolume *)gbv)->around(child_begin, child_end);
04323         }
04324         
04325         // If we have a transform, apply it to the bounding volume we
04326         // just computed.
04327         if (!transform->is_identity()) {
04328           gbv->xform(transform->get_mat());
04329         }
04330 
04331         cdataw->_external_bounds = gbv;
04332         cdataw->_last_update = next_update;
04333 
04334         if (drawmask_cat.is_debug()) {
04335           drawmask_cat.debug(false)
04336             << "} " << *this << "::update_bounds();\n";
04337         }
04338 
04339         nassertr(cdataw->_last_update == cdataw->_next_update, cdataw);
04340     
04341         // Even though implicit bounding volume is not (yet?) part of
04342         // the bam stream.
04343         mark_bam_modified();
04344         return cdataw;
04345       }
04346       
04347       if (cdataw->_last_update == cdataw->_next_update) {
04348         // Someone else has computed the cache for us.  OK.
04349         return cdataw;
04350       }
04351     }
04352 
04353     // We need to go around again.  Release the write lock, and grab
04354     // the read lock back.
04355     cdata = CDLockedStageReader(_cycler, pipeline_stage, current_thread);
04356 
04357     if (cdata->_last_update == cdata->_next_update) {
04358       // Someone else has computed the cache for us while we were
04359       // diddling with the locks.  OK.
04360       return CDStageWriter(_cycler, pipeline_stage, cdata);
04361     }
04362 
04363   } while (true);
04364 }
04365 
04366 ////////////////////////////////////////////////////////////////////
04367 //     Function: PandaNode::set_scene_root_func
04368 //       Access: Public, Static
04369 //  Description: This is used by the GraphicsEngine to hook in a
04370 //               pointer to the scene_root_func(), the function to
04371 //               determine whether the node is an active scene root.
04372 //               This back-pointer is necessary because we can't make
04373 //               calls directly into GraphicsEngine, which is in the
04374 //               display module.
04375 ////////////////////////////////////////////////////////////////////
04376 void PandaNode::
04377 set_scene_root_func(SceneRootFunc *func) {
04378   _scene_root_func = func;
04379 }
04380 
04381 ////////////////////////////////////////////////////////////////////
04382 //     Function: PandaNode::register_with_read_factory
04383 //       Access: Public, Static
04384 //  Description: Tells the BamReader how to create objects of type
04385 //               PandaNode.
04386 ////////////////////////////////////////////////////////////////////
04387 void PandaNode::
04388 register_with_read_factory() {
04389   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
04390 }
04391 
04392 ////////////////////////////////////////////////////////////////////
04393 //     Function: PandaNode::write_datagram
04394 //       Access: Public, Virtual
04395 //  Description: Writes the contents of this object to the datagram
04396 //               for shipping out to a Bam file.
04397 ////////////////////////////////////////////////////////////////////
04398 void PandaNode::
04399 write_datagram(BamWriter *manager, Datagram &dg) {
04400   TypedWritable::write_datagram(manager, dg);
04401   dg.add_string(get_name());
04402 
04403   manager->write_cdata(dg, _cycler);
04404 }
04405 
04406 ////////////////////////////////////////////////////////////////////
04407 //     Function: PandaNode::update_bam_nested
04408 //       Access: Public, Virtual
04409 //  Description: Called by the BamWriter when this object has not
04410 //               itself been modified recently, but it should check
04411 //               its nested objects for updates.
04412 ////////////////////////////////////////////////////////////////////
04413 void PandaNode::
04414 update_bam_nested(BamWriter *manager) {
04415   CDReader cdata(_cycler);
04416   cdata->update_bam_nested(manager);
04417 }
04418 
04419 ////////////////////////////////////////////////////////////////////
04420 //     Function: PandaNode::write_recorder
04421 //       Access: Public
04422 //  Description: This method is provided for the benefit of classes
04423 //               (like MouseRecorder) that inherit from PandaMode and
04424 //               also RecorderBase.  It's not virtual at this level
04425 //               since it doesn't need to be (it's called up from the
04426 //               derived class).
04427 //
04428 //               This method acts very like write_datagram, but it
04429 //               writes the node as appropriate for writing a
04430 //               RecorderBase object as described in the beginning of
04431 //               a session file, meaning it doesn't need to write
04432 //               things such as children.  It balances with
04433 //               fillin_recorder().
04434 ////////////////////////////////////////////////////////////////////
04435 void PandaNode::
04436 write_recorder(BamWriter *, Datagram &dg) {
04437   dg.add_string(get_name());
04438 }
04439 
04440 ////////////////////////////////////////////////////////////////////
04441 //     Function: PandaNode::make_from_bam
04442 //       Access: Protected, Static
04443 //  Description: This function is called by the BamReader's factory
04444 //               when a new object of type PandaNode is encountered
04445 //               in the Bam file.  It should create the PandaNode
04446 //               and extract its information from the file.
04447 ////////////////////////////////////////////////////////////////////
04448 TypedWritable *PandaNode::
04449 make_from_bam(const FactoryParams &params) {
04450   PandaNode *node = new PandaNode("");
04451   DatagramIterator scan;
04452   BamReader *manager;
04453 
04454   parse_params(params, scan, manager);
04455   node->fillin(scan, manager);
04456 
04457   return node;
04458 }
04459 
04460 ////////////////////////////////////////////////////////////////////
04461 //     Function: PandaNode::fillin
04462 //       Access: Protected
04463 //  Description: This internal function is called by make_from_bam to
04464 //               read in all of the relevant data from the BamFile for
04465 //               the new PandaNode.
04466 ////////////////////////////////////////////////////////////////////
04467 void PandaNode::
04468 fillin(DatagramIterator &scan, BamReader *manager) {
04469   TypedWritable::fillin(scan, manager);
04470 
04471   string name = scan.get_string();
04472   set_name(name);
04473 
04474   manager->read_cdata(scan, _cycler);
04475 }
04476 
04477 ////////////////////////////////////////////////////////////////////
04478 //     Function: PandaNode::fillin_recorder
04479 //       Access: Protected
04480 //  Description: This internal function is called by make_recorder (in
04481 //               classes derived from RecorderBase, such as
04482 //               MouseRecorder) to read in all of the relevant data
04483 //               from the session file.  It balances with
04484 //               write_recorder().
04485 ////////////////////////////////////////////////////////////////////
04486 void PandaNode::
04487 fillin_recorder(DatagramIterator &scan, BamReader *) {
04488   string name = scan.get_string();
04489   set_name(name);
04490 }
04491 
04492 ////////////////////////////////////////////////////////////////////
04493 //     Function: PandaNode::CData::Constructor
04494 //       Access: Public
04495 //  Description:
04496 ////////////////////////////////////////////////////////////////////
04497 PandaNode::CData::
04498 CData() :
04499   _state(RenderState::make_empty()),
04500   _transform(TransformState::make_identity()),
04501   _prev_transform(TransformState::make_identity()),
04502 
04503   _effects(RenderEffects::make_empty()),
04504   _draw_control_mask(DrawMask::all_off()),
04505   _draw_show_mask(DrawMask::all_on()),
04506   _into_collide_mask(CollideMask::all_off()),
04507   _bounds_type(BoundingVolume::BT_default),
04508   _user_bounds(NULL),
04509   _final_bounds(false),
04510   _fancy_bits(0),
04511 
04512   _net_collide_mask(CollideMask::all_off()),
04513   _net_draw_control_mask(DrawMask::all_off()),
04514   _net_draw_show_mask(DrawMask::all_off()),
04515 
04516   _down(new PandaNode::Down(PandaNode::get_class_type())),
04517   _stashed(new PandaNode::Down(PandaNode::get_class_type())),
04518   _up(new PandaNode::Up(PandaNode::get_class_type()))
04519 {
04520   ++_next_update;
04521 }
04522 
04523 ////////////////////////////////////////////////////////////////////
04524 //     Function: PandaNode::CData::Copy Constructor
04525 //       Access: Public
04526 //  Description:
04527 ////////////////////////////////////////////////////////////////////
04528 PandaNode::CData::
04529 CData(const PandaNode::CData &copy) :
04530   BoundsData(copy),
04531   _state(copy._state),
04532   _transform(copy._transform),
04533   _prev_transform(copy._prev_transform),
04534 
04535   _effects(copy._effects),
04536   _tag_data(copy._tag_data),
04537   // _python_tag_data appears below.
04538   _draw_control_mask(copy._draw_control_mask),
04539   _draw_show_mask(copy._draw_show_mask),
04540   _into_collide_mask(copy._into_collide_mask),
04541   _bounds_type(copy._bounds_type),
04542   _user_bounds(copy._user_bounds),
04543   _final_bounds(copy._final_bounds),
04544   _fancy_bits(copy._fancy_bits),
04545 
04546   _net_collide_mask(copy._net_collide_mask),
04547   _net_draw_control_mask(copy._net_draw_control_mask),
04548   _net_draw_show_mask(copy._net_draw_show_mask),
04549   _off_clip_planes(copy._off_clip_planes),
04550   _nested_vertices(copy._nested_vertices),
04551   _external_bounds(copy._external_bounds),
04552   _last_update(copy._last_update),
04553   _next_update(copy._next_update),
04554 
04555   _down(copy._down),
04556   _stashed(copy._stashed),
04557   _up(copy._up)
04558 {
04559   // Note that this copy constructor is not used by the PandaNode copy
04560   // constructor!  Any elements that must be copied between nodes
04561   // should also be explicitly copied there.
04562 
04563 #ifdef HAVE_PYTHON
04564   // Copy and increment all of the Python objects held by the other
04565   // node.
04566   _python_tag_data = copy._python_tag_data;
04567   inc_py_refs();
04568 #endif  // HAVE_PYTHON
04569 }
04570 
04571 ////////////////////////////////////////////////////////////////////
04572 //     Function: PandaNode::CData::Destructor
04573 //       Access: Public, Virtual
04574 //  Description:
04575 ////////////////////////////////////////////////////////////////////
04576 PandaNode::CData::
04577 ~CData() {
04578 #ifdef HAVE_PYTHON
04579   // Free all of the Python objects held by this node.
04580   dec_py_refs();
04581 #endif  // HAVE_PYTHON
04582 }
04583 
04584 ////////////////////////////////////////////////////////////////////
04585 //     Function: PandaNode::CData::make_copy
04586 //       Access: Public, Virtual
04587 //  Description:
04588 ////////////////////////////////////////////////////////////////////
04589 CycleData *PandaNode::CData::
04590 make_copy() const {
04591   return new CData(*this);
04592 }
04593 
04594 ////////////////////////////////////////////////////////////////////
04595 //     Function: PandaNode::CData::write_datagram
04596 //       Access: Public, Virtual
04597 //  Description: Writes the contents of this object to the datagram
04598 //               for shipping out to a Bam file.
04599 ////////////////////////////////////////////////////////////////////
04600 void PandaNode::CData::
04601 write_datagram(BamWriter *manager, Datagram &dg) const {
04602   manager->write_pointer(dg, _state);
04603   manager->write_pointer(dg, _transform);
04604 
04605   //
04606   manager->write_pointer(dg, _effects);
04607 
04608   dg.add_uint32(_draw_control_mask.get_word());
04609   dg.add_uint32(_draw_show_mask.get_word());
04610   dg.add_uint32(_into_collide_mask.get_word());
04611   dg.add_uint8(_bounds_type);
04612 
04613   dg.add_uint32(_tag_data.size());
04614   TagData::const_iterator ti;
04615   for (ti = _tag_data.begin(); ti != _tag_data.end(); ++ti) {
04616     dg.add_string((*ti).first);
04617     dg.add_string((*ti).second);
04618   }
04619 
04620   //
04621   write_up_list(*get_up(), manager, dg);
04622   write_down_list(*get_down(), manager, dg);
04623   write_down_list(*get_stashed(), manager, dg);
04624 }
04625 
04626 ////////////////////////////////////////////////////////////////////
04627 //     Function: PandaNode::CData::update_bam_nested
04628 //       Access: Public
04629 //  Description: Called by the BamWriter when this object has not
04630 //               itself been modified recently, but it should check
04631 //               its nested objects for updates.
04632 ////////////////////////////////////////////////////////////////////
04633 void PandaNode::CData::
04634 update_bam_nested(BamWriter *manager) const {
04635   // No need to check the state pointers for updates, since they're
04636   // all immutable objects.
04637   //manager->consider_update(_state);
04638   //manager->consider_update(_transform);
04639   //manager->consider_update(_effects);
04640 
04641   update_up_list(*get_up(), manager);
04642   update_down_list(*get_down(), manager);
04643   update_down_list(*get_stashed(), manager);
04644 }
04645 
04646 ////////////////////////////////////////////////////////////////////
04647 //     Function: PandaNode::CData::complete_pointers
04648 //       Access: Public, Virtual
04649 //  Description: Receives an array of pointers, one for each time
04650 //               manager->read_pointer() was called in fillin().
04651 //               Returns the number of pointers processed.
04652 ////////////////////////////////////////////////////////////////////
04653 int PandaNode::CData::
04654 complete_pointers(TypedWritable **p_list, BamReader *manager) {
04655   int pi = CycleData::complete_pointers(p_list, manager);
04656 
04657   // Get the state and transform pointers.
04658   _state = DCAST(RenderState, p_list[pi++]);
04659   _transform = DCAST(TransformState, p_list[pi++]);
04660   _prev_transform = _transform;
04661 
04662   // Finalize these pointers now to decrement their artificially-held
04663   // reference counts.  We do this now, rather than later, in case
04664   // some other object reassigns them a little later on during
04665   // initialization, before they can finalize themselves normally (for
04666   // instance, the character may change the node's transform).  If
04667   // that happens, the pointer may discover that no one else holds its
04668   // reference count when it finalizes, which will constitute a memory
04669   // leak (see the comments in TransformState::finalize(), etc.).
04670   manager->finalize_now((RenderState *)_state.p());
04671   manager->finalize_now((TransformState *)_transform.p());
04672 
04673   //
04674 
04675   // Get the effects pointer.
04676   _effects = DCAST(RenderEffects, p_list[pi++]);
04677 
04678   // Finalize these pointers now to decrement their artificially-held
04679   // reference counts.  We do this now, rather than later, in case
04680   // some other object reassigns them a little later on during
04681   // initialization, before they can finalize themselves normally (for
04682   // instance, the character may change the node's transform).  If
04683   // that happens, the pointer may discover that no one else holds its
04684   // reference count when it finalizes, which will constitute a memory
04685   // leak (see the comments in TransformState::finalize(), etc.).
04686   manager->finalize_now((RenderEffects *)_effects.p());
04687 
04688   //
04689 
04690   // Get the parent and child pointers.
04691   pi += complete_up_list(*modify_up(), "up", p_list + pi, manager);
04692   pi += complete_down_list(*modify_down(), "down", p_list + pi, manager);
04693   pi += complete_down_list(*modify_stashed(), "stashed", p_list + pi, manager);
04694 
04695   // Since the _effects and _states members have been finalized by
04696   // now, this should be safe.
04697   set_fancy_bit(FB_transform, !_transform->is_identity());
04698   set_fancy_bit(FB_state, !_state->is_empty());
04699   set_fancy_bit(FB_effects, !_effects->is_empty());
04700   set_fancy_bit(FB_tag, !_tag_data.empty());
04701 
04702   return pi;
04703 }
04704 
04705 ////////////////////////////////////////////////////////////////////
04706 //     Function: PandaNode::CData::fillin
04707 //       Access: Public, Virtual
04708 //  Description: This internal function is called by make_from_bam to
04709 //               read in all of the relevant data from the BamFile for
04710 //               the new PandaNode.
04711 ////////////////////////////////////////////////////////////////////
04712 void PandaNode::CData::
04713 fillin(DatagramIterator &scan, BamReader *manager) {
04714   // Read the state and transform pointers.
04715   manager->read_pointer(scan);
04716   manager->read_pointer(scan);
04717 
04718   //
04719   // Read the effects pointer.
04720   manager->read_pointer(scan);
04721 
04722   if (manager->get_file_minor_ver() < 2) {
04723     DrawMask draw_mask;
04724     draw_mask.set_word(scan.get_uint32());
04725 
04726     if (draw_mask == DrawMask::all_off()) {
04727       // Hidden.
04728       _draw_control_mask = _overall_bit;
04729       _draw_show_mask = ~_overall_bit;
04730 
04731     } else if (draw_mask == DrawMask::all_on()) {
04732       // Normally visible.
04733       _draw_control_mask = DrawMask::all_off();
04734       _draw_show_mask = DrawMask::all_on();
04735 
04736     } else {
04737       // Some per-camera combination.
04738       draw_mask &= ~_overall_bit;
04739       _draw_control_mask = ~draw_mask;
04740       _draw_show_mask = draw_mask;
04741     }
04742 
04743   } else {
04744     _draw_control_mask.set_word(scan.get_uint32());
04745     _draw_show_mask.set_word(scan.get_uint32());
04746   }
04747 
04748   _into_collide_mask.set_word(scan.get_uint32());
04749 
04750   _bounds_type = BoundingVolume::BT_default;
04751   if (manager->get_file_minor_ver() >= 19) {
04752     _bounds_type = (BoundingVolume::BoundsType)scan.get_uint8();
04753   }
04754 
04755   // Read in the tag list.
04756   int num_tags = scan.get_uint32();
04757   for (int i = 0; i < num_tags; i++) {
04758     string key = scan.get_string();
04759     string value = scan.get_string();
04760     _tag_data[key] = value;
04761   }
04762 
04763   //
04764   fillin_up_list(*modify_up(), "up", scan, manager);
04765   fillin_down_list(*modify_down(), "down", scan, manager);
04766   fillin_down_list(*modify_stashed(), "stashed", scan, manager);
04767 }
04768 
04769 #ifdef HAVE_PYTHON
04770 ////////////////////////////////////////////////////////////////////
04771 //     Function: PandaNode::CData::inc_py_refs
04772 //       Access: Public
04773 //  Description: Increments the reference counts on all held Python
04774 //               objects.
04775 ////////////////////////////////////////////////////////////////////
04776 void PandaNode::CData::
04777 inc_py_refs() {
04778   if (!_python_tag_data.empty()) {
04779 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04780     // This might happen at any time, so be sure the Python state is
04781     // ready for it.
04782     PyGILState_STATE gstate;
04783     gstate = PyGILState_Ensure();
04784 #endif
04785     PythonTagData::const_iterator ti;
04786     for (ti = _python_tag_data.begin();
04787          ti != _python_tag_data.end();
04788          ++ti) {
04789       PyObject *value = (*ti).second;
04790       Py_XINCREF(value);
04791     }
04792 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04793     PyGILState_Release(gstate);
04794 #endif
04795   }
04796 }
04797 #endif  // HAVE_PYTHON
04798 
04799 #ifdef HAVE_PYTHON
04800 ////////////////////////////////////////////////////////////////////
04801 //     Function: PandaNode::CData::dec_py_refs
04802 //       Access: Public
04803 //  Description: Decrements the reference counts on all held Python
04804 //               objects.
04805 ////////////////////////////////////////////////////////////////////
04806 void PandaNode::CData::
04807 dec_py_refs() {
04808   if (!_python_tag_data.empty()) {
04809 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04810     // This might happen at any time, so be sure the Python state is
04811     // ready for it.
04812     PyGILState_STATE gstate;
04813     gstate = PyGILState_Ensure();
04814 #endif
04815     
04816     PythonTagData::const_iterator ti;
04817     for (ti = _python_tag_data.begin();
04818          ti != _python_tag_data.end();
04819          ++ti) {
04820       PyObject *value = (*ti).second;
04821       Py_XDECREF(value);
04822     }
04823     
04824 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
04825     PyGILState_Release(gstate);
04826 #endif
04827   }
04828 }
04829 #endif  // HAVE_PYTHON
04830 
04831 ////////////////////////////////////////////////////////////////////
04832 //     Function: PandaNode::CData::write_up_list
04833 //       Access: Public
04834 //  Description: Writes the indicated list of parent node pointers to
04835 //               the datagram.
04836 ////////////////////////////////////////////////////////////////////
04837 void PandaNode::CData::
04838 write_up_list(const PandaNode::Up &up_list,
04839               BamWriter *manager, Datagram &dg) const {
04840   // When we write a PandaNode, we write out its complete list of
04841   // child node pointers, but we only write out the parent node
04842   // pointers that have already been added to the bam file by a
04843   // previous write operation.  This is a bit of trickery that allows
04844   // us to write out just a subgraph (instead of the complete graph)
04845   // when we write out an arbitrary node in the graph, yet also allows
04846   // us to keep nodes completely in sync when we use the bam format
04847   // for streaming scene graph operations over the network.
04848 
04849   int num_parents = 0;
04850   Up::const_iterator ui;
04851   for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
04852     PandaNode *parent_node = (*ui).get_parent();
04853     if (manager->has_object(parent_node)) {
04854       num_parents++;
04855     }
04856   }
04857   nassertv(num_parents == (int)(PN_uint16)num_parents);
04858   dg.add_uint16(num_parents);
04859   for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
04860     PandaNode *parent_node = (*ui).get_parent();
04861     if (manager->has_object(parent_node)) {
04862       manager->write_pointer(dg, parent_node);
04863     }
04864   }
04865 }
04866 
04867 ////////////////////////////////////////////////////////////////////
04868 //     Function: PandaNode::CData::write_down_list
04869 //       Access: Public
04870 //  Description: Writes the indicated list of child node pointers to
04871 //               the datagram.
04872 ////////////////////////////////////////////////////////////////////
04873 void PandaNode::CData::
04874 write_down_list(const PandaNode::Down &down_list,
04875                 BamWriter *manager, Datagram &dg) const {
04876   int num_children = down_list.size();
04877   nassertv(num_children == (int)(PN_uint16)num_children);
04878   dg.add_uint16(num_children);
04879 
04880   // Should we smarten up the writing of the sort number?  Most of the
04881   // time these will all be zero.
04882   Down::const_iterator di;
04883   for (di = down_list.begin(); di != down_list.end(); ++di) {
04884     PandaNode *child_node = (*di).get_child();
04885     int sort = (*di).get_sort();
04886     manager->write_pointer(dg, child_node);
04887     dg.add_int32(sort);
04888   }
04889 }
04890 
04891 ////////////////////////////////////////////////////////////////////
04892 //     Function: PandaNode::CData::update_up_list
04893 //       Access: Public
04894 //  Description: Calls consider_update on each node of the indicated
04895 //               up list.
04896 ////////////////////////////////////////////////////////////////////
04897 void PandaNode::CData::
04898 update_up_list(const PandaNode::Up &up_list, BamWriter *manager) const {
04899   Up::const_iterator ui;
04900   for (ui = up_list.begin(); ui != up_list.end(); ++ui) {
04901     PandaNode *parent_node = (*ui).get_parent();
04902     if (manager->has_object(parent_node)) {
04903       manager->consider_update(parent_node);
04904     }
04905   }
04906 }
04907 
04908 ////////////////////////////////////////////////////////////////////
04909 //     Function: PandaNode::CData::update_down_list
04910 //       Access: Public
04911 //  Description: Calls consider_update on each node of the indicated
04912 //               up list.
04913 ////////////////////////////////////////////////////////////////////
04914 void PandaNode::CData::
04915 update_down_list(const PandaNode::Down &down_list, BamWriter *manager) const {
04916   Down::const_iterator di;
04917   for (di = down_list.begin(); di != down_list.end(); ++di) {
04918     PandaNode *child_node = (*di).get_child();
04919     manager->consider_update(child_node);
04920   }
04921 }
04922 
04923 ////////////////////////////////////////////////////////////////////
04924 //     Function: PandaNode::CData::complete_up_list
04925 //       Access: Public
04926 //  Description: Calls complete_pointers() on the list of parent node
04927 //               pointers.
04928 ////////////////////////////////////////////////////////////////////
04929 int PandaNode::CData::
04930 complete_up_list(PandaNode::Up &up_list, const string &tag,
04931                  TypedWritable **p_list, BamReader *manager) {
04932   int pi = 0;
04933 
04934   int num_parents = manager->get_int_tag(tag);
04935   Up new_up_list(PandaNode::get_class_type());
04936   new_up_list.reserve(num_parents);
04937   for (int i = 0; i < num_parents; i++) {
04938     PandaNode *parent_node = DCAST(PandaNode, p_list[pi++]);
04939     UpConnection connection(parent_node);
04940     new_up_list.push_back(connection);
04941   }
04942 
04943   // Now we should sort the list, since the sorting is based on
04944   // pointer order, which might be different from one session to the
04945   // next.
04946   new_up_list.sort();
04947 
04948   // Make it permanent.
04949   up_list.swap(new_up_list);
04950   new_up_list.clear();
04951 
04952   return pi;
04953 }
04954 
04955 ////////////////////////////////////////////////////////////////////
04956 //     Function: PandaNode::CData::complete_down_list
04957 //       Access: Public
04958 //  Description: Calls complete_pointers() on the list of child node
04959 //               pointers.
04960 ////////////////////////////////////////////////////////////////////
04961 int PandaNode::CData::
04962 complete_down_list(PandaNode::Down &down_list, const string &tag,
04963                    TypedWritable **p_list, BamReader *manager) {
04964   int pi = 0;
04965 
04966   BamReaderAuxDataDown *aux;
04967   DCAST_INTO_R(aux, manager->get_aux_tag(tag), pi);
04968 
04969   Down &new_down_list = aux->_down_list;
04970   for (Down::iterator di = new_down_list.begin();
04971        di != new_down_list.end(); 
04972        ++di) {
04973     PandaNode *child_node = DCAST(PandaNode, p_list[pi++]);
04974     (*di).set_child(child_node);
04975   }
04976 
04977   // Unlike the up list, we should *not* sort the down list.  The down
04978   // list is stored in a specific order, not related to pointer order;
04979   // and this order should be preserved from one session to the next.
04980 
04981   // Make it permanent.
04982   down_list.swap(new_down_list);
04983   new_down_list.clear();
04984 
04985   return pi;
04986 }
04987 
04988 ////////////////////////////////////////////////////////////////////
04989 //     Function: PandaNode::CData::fillin_up_list
04990 //       Access: Public
04991 //  Description: Reads the indicated list parent node pointers from
04992 //               the datagram (or at least calls read_pointer() for
04993 //               each one).
04994 ////////////////////////////////////////////////////////////////////
04995 void PandaNode::CData::
04996 fillin_up_list(PandaNode::Up &up_list, const string &tag,
04997                DatagramIterator &scan, BamReader *manager) {
04998   int num_parents = scan.get_uint16();
04999   manager->set_int_tag(tag, num_parents);
05000   manager->read_pointers(scan, num_parents);
05001 }
05002 
05003 ////////////////////////////////////////////////////////////////////
05004 //     Function: PandaNode::CData::fillin_down_list
05005 //       Access: Public
05006 //  Description: Reads the indicated list child node pointers from
05007 //               the datagram (or at least calls read_pointer() for
05008 //               each one).
05009 ////////////////////////////////////////////////////////////////////
05010 void PandaNode::CData::
05011 fillin_down_list(PandaNode::Down &down_list, const string &tag,
05012                  DatagramIterator &scan, BamReader *manager) {
05013   int num_children = scan.get_uint16();
05014 
05015   // Create a temporary down_list, with the right number of elements,
05016   // but a NULL value for each pointer (we'll fill in the pointers
05017   // later).  We need to do this to associate the sort values with
05018   // their pointers.
05019   Down new_down_list(PandaNode::get_class_type());
05020   new_down_list.reserve(num_children);
05021   for (int i = 0; i < num_children; i++) {
05022     manager->read_pointer(scan);
05023     int sort = scan.get_int32();
05024     DownConnection connection(NULL, sort);
05025     new_down_list.push_back(connection);
05026   }
05027 
05028   // Now store the temporary down_list in the BamReader, so we can get
05029   // it during the call to complete_down_list().
05030   PT(BamReaderAuxDataDown) aux = new BamReaderAuxDataDown;
05031   aux->_down_list.swap(new_down_list);
05032   manager->set_aux_tag(tag, aux);
05033 }
05034 
05035 ////////////////////////////////////////////////////////////////////
05036 //     Function: PandaNodePipelineReader::check_bounds
05037 //       Access: Public
05038 //  Description: Ensures that the bounding volume is properly computed
05039 //               on this node.
05040 ////////////////////////////////////////////////////////////////////
05041 void PandaNodePipelineReader::
05042 check_bounds() const {
05043   if (_cdata->_last_update != _cdata->_next_update) {
05044     // The cache is stale; it needs to be rebuilt.
05045 
05046     // We'll need to get a fresh read pointer, since another thread
05047     // might already have modified the pointer on the object since we
05048     // queried it.
05049 #ifdef DO_PIPELINING
05050     node_unref_delete((CycleData *)_cdata);
05051 #endif  // DO_PIPELINING
05052     ((PandaNodePipelineReader *)this)->_cdata = NULL;
05053     int pipeline_stage = _current_thread->get_pipeline_stage();
05054     PandaNode::CDLockedStageReader fresh_cdata(_object->_cycler, pipeline_stage, _current_thread);
05055     if (fresh_cdata->_last_update == fresh_cdata->_next_update) {
05056       // What luck, some other thread has already freshened the
05057       // cache for us.  Save the new pointer, and let the lock
05058       // release itself.
05059       if (_cdata != (const PandaNode::CData *)fresh_cdata) {
05060         ((PandaNodePipelineReader *)this)->_cdata = fresh_cdata;
05061 #ifdef DO_PIPELINING
05062         _cdata->node_ref();
05063 #endif  // DO_PIPELINING
05064       }
05065       
05066     } else {
05067       // No, the cache is still stale.  We have to do the work of
05068       // freshening it.
05069       PStatTimer timer(PandaNode::_update_bounds_pcollector);
05070       PandaNode::CDStageWriter cdataw = ((PandaNode *)_object)->update_bounds(pipeline_stage, fresh_cdata);
05071       nassertv(cdataw->_last_update == cdataw->_next_update);
05072       // As above, we save the new pointer, and then let the lock
05073       // release itself.
05074       if (_cdata != (const PandaNode::CData *)cdataw) {
05075         ((PandaNodePipelineReader *)this)->_cdata = cdataw;
05076 #ifdef DO_PIPELINING
05077         _cdata->node_ref();
05078 #endif  // DO_PIPELINING
05079       }
05080     }
05081   }
05082 
05083   nassertv(_cdata->_last_update == _cdata->_next_update);
05084 }