Panda3D

pandaNode.I

00001 // Filename: pandaNode.I
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 
00016 ////////////////////////////////////////////////////////////////////
00017 //     Function: PandaNode::get_num_parents
00018 //       Access: Published
00019 //  Description: Returns the number of parent nodes this node has.  If
00020 //               this number is greater than 1, the node has been
00021 //               multiply instanced.  The order of the parent nodes is
00022 //               not meaningful and is not related to the order in
00023 //               which the node was instanced to them.
00024 ////////////////////////////////////////////////////////////////////
00025 INLINE int PandaNode::
00026 get_num_parents(Thread *current_thread) const {
00027   CDReader cdata(_cycler, current_thread);
00028   return cdata->get_up()->size();
00029 }
00030 
00031 ////////////////////////////////////////////////////////////////////
00032 //     Function: PandaNode::get_parent
00033 //       Access: Published
00034 //  Description: Returns the nth parent node of this node.  See
00035 //               get_num_parents().  Also see get_parents(), if your
00036 //               intention is to iterate through the complete list of
00037 //               parents; get_parents() is preferable in this case.
00038 ////////////////////////////////////////////////////////////////////
00039 INLINE PandaNode *PandaNode::
00040 get_parent(int n, Thread *current_thread) const {
00041   CDReader cdata(_cycler, current_thread);
00042   CPT(Up) up = cdata->get_up();
00043   nassertr(n >= 0 && n < (int)up->size(), NULL);
00044   return (*up)[n].get_parent();
00045 }
00046 
00047 ////////////////////////////////////////////////////////////////////
00048 //     Function: PandaNode::find_parent
00049 //       Access: Published
00050 //  Description: Returns the index of the indicated parent node, if it
00051 //               is a parent, or -1 if it is not.
00052 ////////////////////////////////////////////////////////////////////
00053 INLINE int PandaNode::
00054 find_parent(PandaNode *node, Thread *current_thread) const {
00055   CDReader cdata(_cycler, current_thread);
00056   return do_find_parent(node, cdata);
00057 }
00058 
00059 ////////////////////////////////////////////////////////////////////
00060 //     Function: PandaNode::get_num_children
00061 //       Access: Published
00062 //  Description: Returns the number of child nodes this node has.  The
00063 //               order of the child nodes *is* meaningful and is based
00064 //               on the sort number that was passed to add_child(),
00065 //               and also on the order in which the nodes were added.
00066 ////////////////////////////////////////////////////////////////////
00067 INLINE int PandaNode::
00068 get_num_children(Thread *current_thread) const {
00069   CDReader cdata(_cycler, current_thread);
00070   return cdata->get_down()->size();
00071 }
00072 
00073 ////////////////////////////////////////////////////////////////////
00074 //     Function: PandaNode::get_child
00075 //       Access: Published
00076 //  Description: Returns the nth child node of this node.  See
00077 //               get_num_children().  Also see get_children(), if your
00078 //               intention is to iterate through the complete list of
00079 //               children; get_children() is preferable in this case.
00080 ////////////////////////////////////////////////////////////////////
00081 INLINE PandaNode *PandaNode::
00082 get_child(int n, Thread *current_thread) const {
00083   CDReader cdata(_cycler, current_thread);
00084   CPT(Down) down = cdata->get_down();
00085   nassertr(n >= 0 && n < (int)down->size(), NULL);
00086   return (*down)[n].get_child();
00087 }
00088 
00089 ////////////////////////////////////////////////////////////////////
00090 //     Function: PandaNode::get_child_sort
00091 //       Access: Published
00092 //  Description: Returns the sort index of the nth child node of this
00093 //               node (that is, the number that was passed to
00094 //               add_child()).  See get_num_children().
00095 ////////////////////////////////////////////////////////////////////
00096 INLINE int PandaNode::
00097 get_child_sort(int n, Thread *current_thread) const {
00098   CDReader cdata(_cycler, current_thread);
00099   CPT(Down) down = cdata->get_down();
00100   nassertr(n >= 0 && n < (int)down->size(), -1);
00101   return (*down)[n].get_sort();
00102 }
00103 
00104 ////////////////////////////////////////////////////////////////////
00105 //     Function: PandaNode::find_child
00106 //       Access: Published
00107 //  Description: Returns the index of the indicated child node, if it
00108 //               is a child, or -1 if it is not.
00109 ////////////////////////////////////////////////////////////////////
00110 INLINE int PandaNode::
00111 find_child(PandaNode *node, Thread *current_thread) const {
00112   CDReader cdata(_cycler, current_thread);
00113   return do_find_child(node, cdata->get_down());
00114 }
00115 
00116 ////////////////////////////////////////////////////////////////////
00117 //     Function: PandaNode::stash_child
00118 //       Access: Published
00119 //  Description: Stashes the indicated child node.  This removes the
00120 //               child from the list of active children and puts it on
00121 //               a special list of stashed children.  This child node
00122 //               no longer contributes to the bounding volume of the
00123 //               PandaNode, and is not visited in normal traversals.
00124 //               It is invisible and uncollidable.  The child may
00125 //               later be restored by calling unstash_child().
00126 //
00127 //               This function returns true if the child node was
00128 //               successfully stashed, or false if it was not a child
00129 //               of the node in the first place (e.g. it was
00130 //               previously stashed).
00131 ////////////////////////////////////////////////////////////////////
00132 INLINE bool PandaNode::
00133 stash_child(PandaNode *child_node, Thread *current_thread) {
00134   int child_index = find_child(child_node, current_thread);
00135   if (child_index < 0) {
00136     return false;
00137   }
00138   stash_child(child_index, current_thread);
00139   return true;
00140 }
00141 
00142 ////////////////////////////////////////////////////////////////////
00143 //     Function: PandaNode::unstash_child
00144 //       Access: Published
00145 //  Description: Returns the indicated stashed node to normal child
00146 //               status.  This removes the child from the list of
00147 //               stashed children and puts it on the normal list of
00148 //               active children.  This child node once again
00149 //               contributes to the bounding volume of the PandaNode,
00150 //               and will be visited in normal traversals.  It is
00151 //               visible and collidable.
00152 //
00153 //               This function returns true if the child node was
00154 //               successfully stashed, or false if it was not a child
00155 //               of the node in the first place (e.g. it was
00156 //               previously stashed).
00157 ////////////////////////////////////////////////////////////////////
00158 INLINE bool PandaNode::
00159 unstash_child(PandaNode *child_node, Thread *current_thread) {
00160   int stashed_index = find_stashed(child_node, current_thread);
00161   if (stashed_index < 0) {
00162     return false;
00163   }
00164   unstash_child(stashed_index, current_thread);
00165   return true;
00166 }
00167 
00168 ////////////////////////////////////////////////////////////////////
00169 //     Function: PandaNode::get_num_stashed
00170 //       Access: Published
00171 //  Description: Returns the number of stashed nodes this node has.
00172 //               These are former children of the node that have been
00173 //               moved to the special stashed list via stash_child().
00174 ////////////////////////////////////////////////////////////////////
00175 INLINE int PandaNode::
00176 get_num_stashed(Thread *current_thread) const {
00177   CDReader cdata(_cycler, current_thread);
00178   return cdata->get_stashed()->size();
00179 }
00180 
00181 ////////////////////////////////////////////////////////////////////
00182 //     Function: PandaNode::get_stashed
00183 //       Access: Published
00184 //  Description: Returns the nth stashed child of this node.  See
00185 //               get_num_stashed().  Also see get_stashed(), if your
00186 //               intention is to iterate through the complete list of
00187 //               stashed children; get_stashed() is preferable in this
00188 //               case.
00189 ////////////////////////////////////////////////////////////////////
00190 INLINE PandaNode *PandaNode::
00191 get_stashed(int n, Thread *current_thread) const {
00192   CDReader cdata(_cycler, current_thread);
00193   CPT(Down) stashed = cdata->get_stashed();
00194   nassertr(n >= 0 && n < (int)stashed->size(), NULL);
00195   return (*stashed)[n].get_child();
00196 }
00197 
00198 ////////////////////////////////////////////////////////////////////
00199 //     Function: PandaNode::get_stashed_sort
00200 //       Access: Published
00201 //  Description: Returns the sort index of the nth stashed node of this
00202 //               node (that is, the number that was passed to
00203 //               add_child()).  See get_num_stashed().
00204 ////////////////////////////////////////////////////////////////////
00205 INLINE int PandaNode::
00206 get_stashed_sort(int n, Thread *current_thread) const {
00207   CDReader cdata(_cycler, current_thread);
00208   CPT(Down) stashed = cdata->get_stashed();
00209   nassertr(n >= 0 && n < (int)stashed->size(), -1);
00210   return (*stashed)[n].get_sort();
00211 }
00212 
00213 ////////////////////////////////////////////////////////////////////
00214 //     Function: PandaNode::find_stashed
00215 //       Access: Published
00216 //  Description: Returns the index of the indicated stashed node, if
00217 //               it is a stashed child, or -1 if it is not.
00218 ////////////////////////////////////////////////////////////////////
00219 INLINE int PandaNode::
00220 find_stashed(PandaNode *node, Thread *current_thread) const {
00221   CDReader cdata(_cycler, current_thread);
00222   return do_find_child(node, cdata->get_stashed());
00223 }
00224 
00225 ////////////////////////////////////////////////////////////////////
00226 //     Function: PandaNode::get_attrib
00227 //       Access: Published
00228 //  Description: Returns the render attribute of the indicated type,
00229 //               if it is defined on the node, or NULL if it is not.
00230 //               This checks only what is set on this particular node
00231 //               level, and has nothing to do with what render
00232 //               attributes may be inherited from parent nodes.
00233 ////////////////////////////////////////////////////////////////////
00234 INLINE const RenderAttrib *PandaNode::
00235 get_attrib(TypeHandle type) const {
00236   CDReader cdata(_cycler);
00237   return cdata->_state->get_attrib(type);
00238 }
00239 
00240 ////////////////////////////////////////////////////////////////////
00241 //     Function: PandaNode::get_attrib
00242 //       Access: Published
00243 //  Description: Returns the render attribute of the indicated type,
00244 //               if it is defined on the node, or NULL if it is not.
00245 //               This checks only what is set on this particular node
00246 //               level, and has nothing to do with what render
00247 //               attributes may be inherited from parent nodes.
00248 ////////////////////////////////////////////////////////////////////
00249 INLINE const RenderAttrib *PandaNode::
00250 get_attrib(int slot) const {
00251   CDReader cdata(_cycler);
00252   return cdata->_state->get_attrib(slot);
00253 }
00254 
00255 ////////////////////////////////////////////////////////////////////
00256 //     Function: PandaNode::has_attrib
00257 //       Access: Published
00258 //  Description: Returns true if there is a render attribute of the
00259 //               indicated type defined on this node, or false if
00260 //               there is not.
00261 ////////////////////////////////////////////////////////////////////
00262 INLINE bool PandaNode::
00263 has_attrib(TypeHandle type) const {
00264   CDReader cdata(_cycler);
00265   return cdata->_state->has_attrib(type);
00266 }
00267 
00268 ////////////////////////////////////////////////////////////////////
00269 //     Function: PandaNode::has_attrib
00270 //       Access: Published
00271 //  Description: Returns true if there is a render attribute of the
00272 //               indicated type defined on this node, or false if
00273 //               there is not.
00274 ////////////////////////////////////////////////////////////////////
00275 INLINE bool PandaNode::
00276 has_attrib(int slot) const {
00277   CDReader cdata(_cycler);
00278   return cdata->_state->has_attrib(slot);
00279 }
00280 
00281 ////////////////////////////////////////////////////////////////////
00282 //     Function: PandaNode::clear_attrib
00283 //       Access: Published
00284 //  Description: Removes the render attribute of the given type from
00285 //               this node.  This node, and the subgraph below, will
00286 //               now inherit the indicated render attribute from the
00287 //               nodes above this one.
00288 ////////////////////////////////////////////////////////////////////
00289 INLINE void PandaNode::
00290 clear_attrib(TypeHandle type) {
00291   RenderAttribRegistry *reg = RenderAttribRegistry::quick_get_global_ptr();
00292   int slot = reg->get_slot(type);
00293   clear_attrib(slot);
00294 }
00295 
00296 ////////////////////////////////////////////////////////////////////
00297 //     Function: PandaNode::get_effect
00298 //       Access: Published
00299 //  Description: Returns the render effect of the indicated type,
00300 //               if it is defined on the node, or NULL if it is not.
00301 ////////////////////////////////////////////////////////////////////
00302 INLINE const RenderEffect *PandaNode::
00303 get_effect(TypeHandle type) const {
00304   CDReader cdata(_cycler);
00305   int index = cdata->_effects->find_effect(type);
00306   if (index >= 0) {
00307     return cdata->_effects->get_effect(index);
00308   }
00309   return NULL;
00310 }
00311 
00312 ////////////////////////////////////////////////////////////////////
00313 //     Function: PandaNode::has_effect
00314 //       Access: Published
00315 //  Description: Returns true if there is a render effect of the
00316 //               indicated type defined on this node, or false if
00317 //               there is not.
00318 ////////////////////////////////////////////////////////////////////
00319 INLINE bool PandaNode::
00320 has_effect(TypeHandle type) const {
00321   CDReader cdata(_cycler);
00322   int index = cdata->_effects->find_effect(type);
00323   return (index >= 0);
00324 }
00325 
00326 ////////////////////////////////////////////////////////////////////
00327 //     Function: PandaNode::get_state
00328 //       Access: Published
00329 //  Description: Returns the complete RenderState that will be applied
00330 //               to all nodes at this level and below, as set on this
00331 //               node.  This returns only the RenderState set on this
00332 //               particular node, and has nothing to do with state
00333 //               that might be inherited from above.
00334 ////////////////////////////////////////////////////////////////////
00335 INLINE const RenderState *PandaNode::
00336 get_state(Thread *current_thread) const {
00337   CDReader cdata(_cycler, current_thread);
00338   return cdata->_state;
00339 }
00340 
00341 ////////////////////////////////////////////////////////////////////
00342 //     Function: PandaNode::clear_state
00343 //       Access: Published
00344 //  Description: Resets this node to leave the render state alone.
00345 //               Nodes at this level and below will once again inherit
00346 //               their render state unchanged from the nodes above
00347 //               this level.
00348 ////////////////////////////////////////////////////////////////////
00349 INLINE void PandaNode::
00350 clear_state(Thread *current_thread) {
00351   set_state(RenderState::make_empty(), current_thread);
00352 }
00353 
00354 ////////////////////////////////////////////////////////////////////
00355 //     Function: PandaNode::get_effects
00356 //       Access: Published
00357 //  Description: Returns the complete RenderEffects that will be
00358 //               applied to this node.
00359 ////////////////////////////////////////////////////////////////////
00360 INLINE const RenderEffects *PandaNode::
00361 get_effects(Thread *current_thread) const {
00362   CDReader cdata(_cycler, current_thread);
00363   return cdata->_effects;
00364 }
00365 
00366 ////////////////////////////////////////////////////////////////////
00367 //     Function: PandaNode::clear_effects
00368 //       Access: Published
00369 //  Description: Resets this node to have no render effects.
00370 ////////////////////////////////////////////////////////////////////
00371 INLINE void PandaNode::
00372 clear_effects(Thread *current_thread) {
00373   set_effects(RenderEffects::make_empty(), current_thread);
00374 }
00375 
00376 ////////////////////////////////////////////////////////////////////
00377 //     Function: PandaNode::get_transform
00378 //       Access: Published
00379 //  Description: Returns the transform that has been set on this
00380 //               particular node.  This is not the net transform from
00381 //               the root, but simply the transform on this particular
00382 //               node.
00383 ////////////////////////////////////////////////////////////////////
00384 INLINE const TransformState *PandaNode::
00385 get_transform(Thread *current_thread) const {
00386   CDReader cdata(_cycler, current_thread);
00387   return cdata->_transform;
00388 }
00389 
00390 ////////////////////////////////////////////////////////////////////
00391 //     Function: PandaNode::clear_transform
00392 //       Access: Published
00393 //  Description: Resets the transform on this node to the identity
00394 //               transform.
00395 ////////////////////////////////////////////////////////////////////
00396 INLINE void PandaNode::
00397 clear_transform(Thread *current_thread) {
00398   set_transform(TransformState::make_identity(), current_thread);
00399 }
00400 
00401 ////////////////////////////////////////////////////////////////////
00402 //     Function: PandaNode::get_prev_transform
00403 //       Access: Published
00404 //  Description: Returns the transform that has been set as this
00405 //               node's "previous" position.  See
00406 //               set_prev_transform().
00407 ////////////////////////////////////////////////////////////////////
00408 const TransformState *PandaNode::
00409 get_prev_transform(Thread *current_thread) const {
00410   CDReader cdata(_cycler, current_thread);
00411   return cdata->_prev_transform;
00412 }
00413 
00414 ////////////////////////////////////////////////////////////////////
00415 //     Function: PandaNode::has_dirty_prev_transform
00416 //       Access: Published
00417 //  Description: Returns true if this node has the
00418 //               _dirty_prev_transform flag set, which indicates its
00419 //               _prev_transform is different from its _transform
00420 //               value (in pipeline stage 0).  In this case, the node
00421 //               will be visited by reset_prev_transform().
00422 ////////////////////////////////////////////////////////////////////
00423 INLINE bool PandaNode::
00424 has_dirty_prev_transform() const {
00425   return _dirty_prev_transform;
00426 }
00427 
00428 ////////////////////////////////////////////////////////////////////
00429 //     Function: PandaNode::get_tag
00430 //       Access: Published
00431 //  Description: Retrieves the user-defined value that was previously
00432 //               set on this node for the particular key, if any.  If
00433 //               no value has been previously set, returns the empty
00434 //               string.
00435 ////////////////////////////////////////////////////////////////////
00436 INLINE string PandaNode::
00437 get_tag(const string &key, Thread *current_thread) const {
00438   CDReader cdata(_cycler, current_thread);
00439   TagData::const_iterator ti;
00440   ti = cdata->_tag_data.find(key);
00441   if (ti != cdata->_tag_data.end()) {
00442     return (*ti).second;
00443   }
00444   return string();
00445 }
00446 
00447 ////////////////////////////////////////////////////////////////////
00448 //     Function: PandaNode::has_tag
00449 //       Access: Published
00450 //  Description: Returns true if a value has been defined on this node
00451 //               for the particular key (even if that value is the
00452 //               empty string), or false if no value has been set.
00453 ////////////////////////////////////////////////////////////////////
00454 INLINE bool PandaNode::
00455 has_tag(const string &key, Thread *current_thread) const {
00456   CDReader cdata(_cycler, current_thread);
00457   TagData::const_iterator ti;
00458   ti = cdata->_tag_data.find(key);
00459   return (ti != cdata->_tag_data.end());
00460 }
00461 
00462 ////////////////////////////////////////////////////////////////////
00463 //     Function: PandaNode::has_tags
00464 //       Access: Published
00465 //  Description: Returns true if the node has any tags (or any Python
00466 //               tags) at all, false if it has none.
00467 ////////////////////////////////////////////////////////////////////
00468 INLINE bool PandaNode::
00469 has_tags() const {
00470   CDReader cdata(_cycler);
00471   if (!cdata->_tag_data.empty()) {
00472     return true;
00473   }
00474 #ifdef HAVE_PYTHON
00475   if (!cdata->_python_tag_data.empty()) {
00476     return true;
00477   }
00478 #endif  // HAVE_PYTHON
00479   return false;
00480 }
00481 
00482 ////////////////////////////////////////////////////////////////////
00483 //     Function: PandaNode::ls
00484 //       Access: Published
00485 //  Description: Lists all the nodes at and below the current path
00486 //               hierarchically.
00487 ////////////////////////////////////////////////////////////////////
00488 INLINE void PandaNode::
00489 ls(ostream &out, int indent_level) const {
00490   r_list_descendants(out, indent_level);
00491 }
00492 
00493 ////////////////////////////////////////////////////////////////////
00494 //     Function: PandaNode::get_overall_bit
00495 //       Access: Published, Static
00496 //  Description: Returns the special bit that, when specifically
00497 //               cleared in the node's DrawMask, indicates that the
00498 //               node is hidden to all cameras, regardless of the
00499 //               remaining DrawMask bits.
00500 ////////////////////////////////////////////////////////////////////
00501 INLINE DrawMask PandaNode::
00502 get_overall_bit() {
00503   return _overall_bit;
00504 }
00505 
00506 ////////////////////////////////////////////////////////////////////
00507 //     Function: PandaNode::get_all_camera_mask
00508 //       Access: Published, Static
00509 //  Description: Returns a DrawMask that is appropriate for rendering
00510 //               to all cameras.
00511 ////////////////////////////////////////////////////////////////////
00512 INLINE DrawMask PandaNode::
00513 get_all_camera_mask() {
00514   return ~_overall_bit;
00515 }
00516 
00517 ////////////////////////////////////////////////////////////////////
00518 //     Function: PandaNode::is_overall_hidden
00519 //       Access: Published, Static
00520 //  Description: Returns true if the node has been hidden to all
00521 //               cameras by clearing its overall bit.
00522 ////////////////////////////////////////////////////////////////////
00523 INLINE bool PandaNode::
00524 is_overall_hidden() const {
00525   CDReader cdata(_cycler);
00526   return ((cdata->_draw_show_mask | ~cdata->_draw_control_mask) & _overall_bit).is_zero();
00527 }
00528 
00529 ////////////////////////////////////////////////////////////////////
00530 //     Function: PandaNode::set_overall_hidden
00531 //       Access: Published
00532 //  Description: Sets or clears the hidden flag.  When the hidden flag
00533 //               is true, the node and all of its children are
00534 //               invisible to all cameras, regardless of the setting
00535 //               of any draw masks.  Setting the hidden flag to false
00536 //               restores the previous visibility as established by
00537 //               the draw masks.
00538 //
00539 //               This actually works by twiddling the reserved
00540 //               _overall_bit in the node's draw mask, which has
00541 //               special meaning.
00542 ////////////////////////////////////////////////////////////////////
00543 INLINE void PandaNode::
00544 set_overall_hidden(bool hidden) {
00545   if (hidden) {
00546     adjust_draw_mask(DrawMask::all_off(), _overall_bit, DrawMask::all_off());
00547   } else {
00548     adjust_draw_mask(DrawMask::all_off(), DrawMask::all_off(), _overall_bit);
00549   }
00550 }
00551 
00552 ////////////////////////////////////////////////////////////////////
00553 //     Function: PandaNode::get_draw_control_mask
00554 //       Access: Published
00555 //  Description: Returns the set of bits in draw_show_mask that are
00556 //               considered meaningful.  See adjust_draw_mask().
00557 ////////////////////////////////////////////////////////////////////
00558 INLINE DrawMask PandaNode::
00559 get_draw_control_mask() const {
00560   CDReader cdata(_cycler);
00561   return cdata->_draw_control_mask;
00562 }
00563 
00564 ////////////////////////////////////////////////////////////////////
00565 //     Function: PandaNode::get_draw_show_mask
00566 //       Access: Published
00567 //  Description: Returns the hide/show bits of this particular node.
00568 //               See adjust_draw_mask().
00569 ////////////////////////////////////////////////////////////////////
00570 INLINE DrawMask PandaNode::
00571 get_draw_show_mask() const {
00572   CDReader cdata(_cycler);
00573   return cdata->_draw_show_mask;
00574 }
00575 
00576 ////////////////////////////////////////////////////////////////////
00577 //     Function: PandaNode::get_into_collide_mask
00578 //       Access: Published
00579 //  Description: Returns the "into" collide mask for this node.
00580 ////////////////////////////////////////////////////////////////////
00581 INLINE CollideMask PandaNode::
00582 get_into_collide_mask() const {
00583   CDReader cdata(_cycler);
00584   return cdata->_into_collide_mask;
00585 }
00586 
00587 ////////////////////////////////////////////////////////////////////
00588 //     Function: PandaNode::clear_bounds
00589 //       Access: Published
00590 //  Description: Reverses the effect of a previous call to
00591 //               set_bounds(), and allows the node's bounding volume
00592 //               to be automatically computed once more based on the
00593 //               contents of the node.
00594 ////////////////////////////////////////////////////////////////////
00595 INLINE void PandaNode::
00596 clear_bounds() {
00597   set_bounds((BoundingVolume *)NULL);
00598 }
00599 
00600 ////////////////////////////////////////////////////////////////////
00601 //     Function: PandaNode::get_internal_bounds
00602 //       Access: Published
00603 //  Description: Returns the node's internal bounding volume.  This is
00604 //               the bounding volume around the node alone, without
00605 //               including children.  If the user has called
00606 //               set_bounds(), it will be the specified bounding
00607 //               volume.
00608 ////////////////////////////////////////////////////////////////////
00609 INLINE CPT(BoundingVolume) PandaNode::
00610 get_internal_bounds(Thread *current_thread) const {
00611   return get_internal_bounds(current_thread->get_pipeline_stage(),
00612                              current_thread);
00613 }
00614 
00615 ////////////////////////////////////////////////////////////////////
00616 //     Function: PandaNode::get_internal_vertices
00617 //       Access: Published
00618 //  Description: Returns the total number of vertices that will be
00619 //               rendered by this particular node alone, not
00620 //               accounting for its children.
00621 //
00622 //               This may not include all vertices for certain dynamic
00623 //               effects.
00624 ////////////////////////////////////////////////////////////////////
00625 INLINE int PandaNode::
00626 get_internal_vertices(Thread *current_thread) const {
00627   return get_internal_vertices(current_thread->get_pipeline_stage(),
00628                                current_thread);
00629 }
00630 
00631 ////////////////////////////////////////////////////////////////////
00632 //     Function: PandaNode::is_bounds_stale
00633 //       Access: Published
00634 //  Description: Returns true if the bounding volume of this node is
00635 //                stale and will be implicitly recomputed at the next
00636 //                call to get_bounds(), or false if it is fresh and
00637 //                need not be recomputed.
00638 ////////////////////////////////////////////////////////////////////
00639 bool PandaNode::
00640 is_bounds_stale() const {
00641   CDReader cdata(_cycler);
00642   return (cdata->_last_update != cdata->_next_update);
00643 }
00644 
00645 ////////////////////////////////////////////////////////////////////
00646 //     Function: PandaNode::set_final
00647 //       Access: Published
00648 //  Description: Sets the "final" flag on this PandaNode.  If
00649 //               this is true, than no bounding volume need be tested
00650 //               below it; a positive intersection with this node's
00651 //               bounding volume is deemed to be a positive
00652 //               intersection with all geometry inside.
00653 //
00654 //               This is useful to quickly force a larger bounding
00655 //               volume around a node when the GeomNodes themselves
00656 //               are inaccurate for some reason, without forcing a
00657 //               recompute of every nested bounding volume.  It's also
00658 //               helpful when the bounding volume is tricked by some
00659 //               special properties, like billboards, that may move
00660 //               geometry out of its bounding volume otherwise.
00661 ////////////////////////////////////////////////////////////////////
00662 INLINE void PandaNode::
00663 set_final(bool flag) {
00664   CDWriter cdata(_cycler);
00665   cdata->_final_bounds = flag;
00666   mark_bam_modified();
00667 }
00668 
00669 ////////////////////////////////////////////////////////////////////
00670 //     Function: PandaNode::is_final
00671 //       Access: Published
00672 //  Description: Returns the current state of the "final" flag.
00673 //               Initially, this flag is off (false), but it may be
00674 //               changed by an explicit call to set_final().  See
00675 //               set_final().
00676 ////////////////////////////////////////////////////////////////////
00677 INLINE bool PandaNode::
00678 is_final(Thread *current_thread) const {
00679   CDReader cdata(_cycler, current_thread);
00680   return cdata->_final_bounds;
00681 }
00682 
00683 ////////////////////////////////////////////////////////////////////
00684 //     Function: PandaNode::get_fancy_bits
00685 //       Access: Published
00686 //  Description: Returns the union of all of the enum FancyBits values
00687 //               corresponding to the various "fancy" attributes that
00688 //               are set on the node.  If this returns 0, the node has
00689 //               nothing interesting about it.  This is intended to
00690 //               speed traversal by quickly skipping past nodes that
00691 //               don't particularly affect the render state.
00692 ////////////////////////////////////////////////////////////////////
00693 INLINE int PandaNode::
00694 get_fancy_bits(Thread *current_thread) const {
00695   CDReader cdata(_cycler, current_thread);
00696   return cdata->_fancy_bits;
00697 }
00698 
00699 ////////////////////////////////////////////////////////////////////
00700 //     Function: PandaNode::get_user_bounds
00701 //       Access: Protected
00702 //  Description: Returns the node's user bounding volume.  This is the
00703 //               bounding volume specified with get_bounds().  This
00704 //               will return NULL if the user bounding volume has
00705 //               never been set.
00706 ////////////////////////////////////////////////////////////////////
00707 INLINE CPT(BoundingVolume) PandaNode::
00708 get_user_bounds(int pipeline_stage, Thread *current_thread) const {
00709   CDStageReader cdata(_cycler, pipeline_stage, current_thread);
00710   return cdata->_user_bounds;
00711 }
00712 
00713 ////////////////////////////////////////////////////////////////////
00714 //     Function: PandaNode::mark_bounds_stale
00715 //       Access: Protected
00716 //  Description: Indicates that the bounding volume, or something that
00717 //               influences the bounding volume (or any of the other
00718 //               things stored in CData, like net_collide_mask),
00719 //               may have changed for this node, and that it must be
00720 //               recomputed.
00721 ////////////////////////////////////////////////////////////////////
00722 INLINE void PandaNode::
00723 mark_bounds_stale(int pipeline_stage, Thread *current_thread) const {
00724   // It's important that we don't hold the lock during the call to
00725   // force_bounds_stale().
00726   bool is_stale_bounds;
00727   {
00728     CDStageReader cdata(_cycler, pipeline_stage, current_thread);
00729     is_stale_bounds = (cdata->_last_update != cdata->_next_update);
00730   }
00731   if (!is_stale_bounds) {
00732     ((PandaNode *)this)->force_bounds_stale(pipeline_stage, current_thread);
00733   }
00734 }
00735 
00736 
00737 ////////////////////////////////////////////////////////////////////
00738 //     Function: PandaNode::mark_internal_bounds_stale
00739 //       Access: Protected
00740 //  Description: Should be called by a derived class to mark the
00741 //               internal bounding volume stale, so that
00742 //               recompute_internal_bounds() will be called when the
00743 //               bounding volume is next requested.
00744 ////////////////////////////////////////////////////////////////////
00745 INLINE void PandaNode::
00746 mark_internal_bounds_stale(int pipeline_stage, Thread *current_thread) {
00747   {
00748     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00749     ++cdata->_internal_bounds_mark;
00750   }
00751   mark_bounds_stale(pipeline_stage, current_thread);
00752 }
00753 
00754 ////////////////////////////////////////////////////////////////////
00755 //     Function: PandaNode::get_children
00756 //       Access: Public
00757 //  Description: Returns an object that can be used to walk through
00758 //               the list of children of the node.  When you intend to
00759 //               visit multiple children, using this is slightly
00760 //               faster than calling get_child() directly on the
00761 //               PandaNode, since this object avoids reopening the
00762 //               PipelineCycler each time.
00763 //
00764 //               This object also protects you from self-modifying
00765 //               loops (e.g. adding or removing children during
00766 //               traversal), since a virtual copy of the children is
00767 //               made ahead of time.  The virtual copy is fast--it is
00768 //               a form of copy-on-write, so the list is not actually
00769 //               copied unless it is modified during the traversal.
00770 ////////////////////////////////////////////////////////////////////
00771 INLINE PandaNode::Children PandaNode::
00772 get_children(Thread *current_thread) const {
00773   CDReader cdata(_cycler, current_thread);
00774   return Children(cdata);
00775 }
00776 
00777 ////////////////////////////////////////////////////////////////////
00778 //     Function: PandaNode::get_stashed
00779 //       Access: Public
00780 //  Description: Returns an object that can be used to walk through
00781 //               the list of children of the node.  When you intend to
00782 //               visit multiple children, using this is slightly
00783 //               faster than calling get_stashed() directly on the
00784 //               PandaNode, since this object avoids reopening the
00785 //               PipelineCycler each time.
00786 //
00787 //               This object also protects you from self-modifying
00788 //               loops (e.g. adding or removing children during
00789 //               traversal), since a virtual copy of the children is
00790 //               made ahead of time.  The virtual copy is fast--it is
00791 //               a form of copy-on-write, so the list is not actually
00792 //               copied unless it is modified during the traversal.
00793 ////////////////////////////////////////////////////////////////////
00794 INLINE PandaNode::Stashed PandaNode::
00795 get_stashed(Thread *current_thread) const {
00796   CDReader cdata(_cycler, current_thread);
00797   return Stashed(cdata);
00798 }
00799 
00800 ////////////////////////////////////////////////////////////////////
00801 //     Function: PandaNode::get_parents
00802 //       Access: Public
00803 //  Description: Returns an object that can be used to walk through
00804 //               the list of parents of the node, similar to
00805 //               get_children() and get_stashed().
00806 ////////////////////////////////////////////////////////////////////
00807 INLINE PandaNode::Parents PandaNode::
00808 get_parents(Thread *current_thread) const {
00809   CDReader cdata(_cycler, current_thread);
00810   return Parents(cdata);
00811 }
00812 
00813 ////////////////////////////////////////////////////////////////////
00814 //     Function: PandaNode::do_find_parent
00815 //       Access: Private
00816 //  Description: The private implementation of find_parent().
00817 ////////////////////////////////////////////////////////////////////
00818 INLINE int PandaNode::
00819 do_find_parent(PandaNode *node, const CData *cdata) const {
00820   CPT(Up) up = cdata->get_up();
00821   Up::const_iterator ui = up->find(UpConnection(node));
00822   if (ui == up->end()) {
00823     return -1;
00824   }
00825   return ui - up->begin();
00826 }
00827 
00828 ////////////////////////////////////////////////////////////////////
00829 //     Function: PandaNode::verify_child_no_cycles
00830 //       Access: Private
00831 //  Description: Ensures that attaching the indicated child node to
00832 //               this node would not introduce a cycle in the graph.
00833 //               Returns true if the attachment is valid, false
00834 //               otherwise.
00835 ////////////////////////////////////////////////////////////////////
00836 INLINE bool PandaNode::
00837 verify_child_no_cycles(PandaNode *child_node) {
00838 #ifndef NDEBUG
00839   if (detect_graph_cycles) {
00840     if (!find_node_above(child_node)) {
00841       return true;
00842     }
00843     report_cycle(child_node);
00844     return false;
00845   }
00846 #endif  // NDEBUG
00847   return true;
00848 }
00849 
00850 ////////////////////////////////////////////////////////////////////
00851 //     Function: PandaNode::set_dirty_prev_transform
00852 //       Access: Private
00853 //  Description: Sets the dirty_prev_transform flag, and adds the node
00854 //               to the _dirty_prev_transforms chain.
00855 ////////////////////////////////////////////////////////////////////
00856 INLINE void PandaNode::
00857 set_dirty_prev_transform() {
00858   if (!_dirty_prev_transform) {
00859     LightMutexHolder holder(_dirty_prev_transforms._lock);
00860     if (!_dirty_prev_transform) {
00861       LinkedListNode::insert_before(&_dirty_prev_transforms);
00862       _dirty_prev_transform = true;
00863     }
00864   }
00865 }
00866 
00867 ////////////////////////////////////////////////////////////////////
00868 //     Function: PandaNode::clear_dirty_prev_transform
00869 //       Access: Private
00870 //  Description: Clears the dirty_prev_transform flag, and removes the node
00871 //               from the _dirty_prev_transforms chain.
00872 ////////////////////////////////////////////////////////////////////
00873 INLINE void PandaNode::
00874 clear_dirty_prev_transform() {
00875   if (_dirty_prev_transform) {
00876     LightMutexHolder holder(_dirty_prev_transforms._lock);
00877     if (_dirty_prev_transform) {
00878       LinkedListNode::remove_from_list();
00879       _dirty_prev_transform = false;
00880     }
00881   }
00882 }
00883 
00884 ////////////////////////////////////////////////////////////////////
00885 //     Function: PandaNode::DownConnection::Constructor
00886 //       Access: Public
00887 //  Description:
00888 ////////////////////////////////////////////////////////////////////
00889 INLINE PandaNode::DownConnection::
00890 DownConnection(PandaNode *child, int sort) :
00891   _child(child),
00892   _sort(sort)
00893 {
00894 }
00895 
00896 ////////////////////////////////////////////////////////////////////
00897 //     Function: PandaNode::DownConnection::operator <
00898 //       Access: Public
00899 //  Description: Provides a partial ordering on the children of a node
00900 //               so that they are ranked first in sort order, and then
00901 //               (by virtue of the ordered_vector) in the order they
00902 //               were added.
00903 ////////////////////////////////////////////////////////////////////
00904 INLINE bool PandaNode::DownConnection::
00905 operator < (const DownConnection &other) const {
00906   return _sort < other._sort;
00907 }
00908 
00909 ////////////////////////////////////////////////////////////////////
00910 //     Function: PandaNode::DownConnection::get_child
00911 //       Access: Public
00912 //  Description: 
00913 ////////////////////////////////////////////////////////////////////
00914 INLINE PandaNode *PandaNode::DownConnection::
00915 get_child() const {
00916   return _child;
00917 }
00918 
00919 ////////////////////////////////////////////////////////////////////
00920 //     Function: PandaNode::DownConnection::set_child
00921 //       Access: Public
00922 //  Description: This is only called by PandaNode::replace_child().
00923 ////////////////////////////////////////////////////////////////////
00924 INLINE void PandaNode::DownConnection::
00925 set_child(PandaNode *child) {
00926   _child = child;
00927 }
00928 
00929 ////////////////////////////////////////////////////////////////////
00930 //     Function: PandaNode::DownConnection::get_sort
00931 //       Access: Public
00932 //  Description: 
00933 ////////////////////////////////////////////////////////////////////
00934 INLINE int PandaNode::DownConnection::
00935 get_sort() const {
00936   return _sort;
00937 }
00938 
00939 ////////////////////////////////////////////////////////////////////
00940 //     Function: PandaNode::UpConnection::Constructor
00941 //       Access: Public
00942 //  Description:
00943 ////////////////////////////////////////////////////////////////////
00944 INLINE PandaNode::UpConnection::
00945 UpConnection(PandaNode *parent) :
00946   _parent(parent)
00947 {
00948 }
00949 
00950 ////////////////////////////////////////////////////////////////////
00951 //     Function: PandaNode::UpConnection::operator <
00952 //       Access: Public
00953 //  Description: Sorts the up connections of a node by pointer.  This
00954 //               is different from the down connections of a node,
00955 //               which are sorted by the specified _sort number.  This
00956 //               makes it easy to locate a particular parent of a node
00957 //               by pointer, or to test for a parent-child
00958 //               relationship given two node pointers.
00959 ////////////////////////////////////////////////////////////////////
00960 INLINE bool PandaNode::UpConnection::
00961 operator < (const UpConnection &other) const {
00962   return _parent < other._parent;
00963 }
00964 
00965 ////////////////////////////////////////////////////////////////////
00966 //     Function: PandaNode::UpConnection::get_parent
00967 //       Access: Public
00968 //  Description: 
00969 ////////////////////////////////////////////////////////////////////
00970 INLINE PandaNode *PandaNode::UpConnection::
00971 get_parent() const {
00972   return _parent;
00973 }
00974 
00975 ////////////////////////////////////////////////////////////////////
00976 //     Function: PandaNode::BoundsData::Constructor
00977 //       Access: Protected
00978 //  Description:
00979 ////////////////////////////////////////////////////////////////////
00980 INLINE PandaNode::BoundsData::
00981 BoundsData() :
00982   _internal_bounds(NULL),
00983   _internal_vertices(0)
00984 {
00985   ++_internal_bounds_mark;
00986 }
00987 
00988 ////////////////////////////////////////////////////////////////////
00989 //     Function: PandaNode::BoundsData::Copy Constructor
00990 //       Access: Protected
00991 //  Description:
00992 ////////////////////////////////////////////////////////////////////
00993 INLINE PandaNode::BoundsData::
00994 BoundsData(const PandaNode::BoundsData &copy) :
00995   _internal_bounds(copy._internal_bounds),
00996   _internal_vertices(copy._internal_vertices),
00997   _internal_bounds_mark(copy._internal_bounds_mark),
00998   _internal_bounds_computed(copy._internal_bounds_computed)
00999 {
01000 }
01001 
01002 ////////////////////////////////////////////////////////////////////
01003 //     Function: PandaNode::BoundsData::copy_bounds
01004 //       Access: Protected
01005 //  Description: Copies just the BoundsData part of the structure.
01006 ////////////////////////////////////////////////////////////////////
01007 INLINE void PandaNode::BoundsData::
01008 copy_bounds(const PandaNode::BoundsData &copy) {
01009   _internal_bounds = copy._internal_bounds;
01010   _internal_vertices = copy._internal_vertices;
01011   _internal_bounds_mark = copy._internal_bounds_mark;
01012   _internal_bounds_computed = copy._internal_bounds_computed;
01013 }
01014 
01015 ////////////////////////////////////////////////////////////////////
01016 //     Function: PandaNode::CData::set_fancy_bit
01017 //       Access: Public
01018 //  Description: Internal function to set (if value is true) or clear
01019 //               (if value is false) the indicated bit(s) in the
01020 //               _fancy_bits member.
01021 ////////////////////////////////////////////////////////////////////
01022 INLINE void PandaNode::CData::
01023 set_fancy_bit(int bits, bool value) {
01024   if (value) {
01025     _fancy_bits |= bits;
01026   } else {
01027     _fancy_bits &= ~bits;
01028   }
01029 }
01030 
01031 ////////////////////////////////////////////////////////////////////
01032 //     Function: PandaNode::CData::get_down
01033 //       Access: Public
01034 //  Description: Returns a read-only pointer to the _down list.
01035 ////////////////////////////////////////////////////////////////////
01036 INLINE CPT(PandaNode::Down) PandaNode::CData::
01037 get_down() const {
01038   return _down.get_read_pointer();
01039 }
01040 
01041 ////////////////////////////////////////////////////////////////////
01042 //     Function: PandaNode::CData::modify_down
01043 //       Access: Public
01044 //  Description: Returns a modifiable, unique pointer to the _down
01045 //               list.
01046 ////////////////////////////////////////////////////////////////////
01047 INLINE PT(PandaNode::Down) PandaNode::CData::
01048 modify_down() {
01049   return _down.get_write_pointer();
01050 }
01051 
01052 ////////////////////////////////////////////////////////////////////
01053 //     Function: PandaNode::CData::get_stashed
01054 //       Access: Public
01055 //  Description: Returns a read-only pointer to the _stashed list.
01056 ////////////////////////////////////////////////////////////////////
01057 INLINE CPT(PandaNode::Down) PandaNode::CData::
01058 get_stashed() const {
01059   return _stashed.get_read_pointer();
01060 }
01061 
01062 ////////////////////////////////////////////////////////////////////
01063 //     Function: PandaNode::CData::modify_stashed
01064 //       Access: Public
01065 //  Description: Returns a modifiable, unique pointer to the _stashed
01066 //               list.
01067 ////////////////////////////////////////////////////////////////////
01068 INLINE PT(PandaNode::Down) PandaNode::CData::
01069 modify_stashed() {
01070   return _stashed.get_write_pointer();
01071 }
01072 
01073 ////////////////////////////////////////////////////////////////////
01074 //     Function: PandaNode::CData::get_up
01075 //       Access: Public
01076 //  Description: Returns a read-only pointer to the _up list.
01077 ////////////////////////////////////////////////////////////////////
01078 INLINE CPT(PandaNode::Up) PandaNode::CData::
01079 get_up() const {
01080   return _up.get_read_pointer();
01081 }
01082 
01083 ////////////////////////////////////////////////////////////////////
01084 //     Function: PandaNode::CData::modify_up
01085 //       Access: Public
01086 //  Description: Returns a modifiable, unique pointer to the _up
01087 //               list.
01088 ////////////////////////////////////////////////////////////////////
01089 INLINE PT(PandaNode::Up) PandaNode::CData::
01090 modify_up() {
01091   return _up.get_write_pointer();
01092 }
01093 
01094 ////////////////////////////////////////////////////////////////////
01095 //     Function: PandaNode::Children::Constructor
01096 //       Access: Public
01097 //  Description:
01098 ////////////////////////////////////////////////////////////////////
01099 INLINE PandaNode::Children::
01100 Children() {
01101 }
01102 
01103 ////////////////////////////////////////////////////////////////////
01104 //     Function: PandaNode::Children::Constructor
01105 //       Access: Public
01106 //  Description:
01107 ////////////////////////////////////////////////////////////////////
01108 INLINE PandaNode::Children::
01109 Children(const PandaNode::CData *cdata) :
01110   _down(cdata->get_down())
01111 {
01112 }
01113 
01114 ////////////////////////////////////////////////////////////////////
01115 //     Function: PandaNode::Children::Copy Constructor
01116 //       Access: Public
01117 //  Description:
01118 ////////////////////////////////////////////////////////////////////
01119 INLINE PandaNode::Children::
01120 Children(const PandaNode::Children &copy) :
01121   _down(copy._down)
01122 {
01123 }
01124 
01125 ////////////////////////////////////////////////////////////////////
01126 //     Function: PandaNode::Children::Copy Assignment Operator
01127 //       Access: Public
01128 //  Description:
01129 ////////////////////////////////////////////////////////////////////
01130 INLINE void PandaNode::Children::
01131 operator = (const PandaNode::Children &copy) {
01132   _down = copy._down;
01133 }
01134 
01135 ////////////////////////////////////////////////////////////////////
01136 //     Function: PandaNode::Children::get_num_children
01137 //       Access: Public
01138 //  Description: Returns the number of children of the node.
01139 ////////////////////////////////////////////////////////////////////
01140 INLINE int PandaNode::Children::
01141 get_num_children() const {
01142   nassertr(_down != (Down *)NULL, 0);
01143   return _down->size();
01144 }
01145 
01146 ////////////////////////////////////////////////////////////////////
01147 //     Function: PandaNode::Children::get_child
01148 //       Access: Public
01149 //  Description: Returns the nth child of the node.
01150 ////////////////////////////////////////////////////////////////////
01151 INLINE PandaNode *PandaNode::Children::
01152 get_child(int n) const {
01153   nassertr(_down != (Down *)NULL, NULL);
01154   nassertr(n >= 0 && n < (int)_down->size(), NULL);
01155   return (*_down)[n].get_child();
01156 }
01157 
01158 ////////////////////////////////////////////////////////////////////
01159 //     Function: PandaNode::Children::get_child_sort
01160 //       Access: Public
01161 //  Description: Returns the sort index of the nth child node of this
01162 //               node (that is, the number that was passed to
01163 //               add_child()).  See get_num_children().
01164 ////////////////////////////////////////////////////////////////////
01165 INLINE int PandaNode::Children::
01166 get_child_sort(int n) const {
01167   nassertr(_down != (Down *)NULL, -1);
01168   nassertr(n >= 0 && n < (int)_down->size(), -1);
01169   return (*_down)[n].get_sort();
01170 }
01171 
01172 ////////////////////////////////////////////////////////////////////
01173 //     Function: PandaNode::Stashed::Constructor
01174 //       Access: Public
01175 //  Description:
01176 ////////////////////////////////////////////////////////////////////
01177 INLINE PandaNode::Stashed::
01178 Stashed() {
01179 }
01180 
01181 ////////////////////////////////////////////////////////////////////
01182 //     Function: PandaNode::Stashed::Constructor
01183 //       Access: Public
01184 //  Description:
01185 ////////////////////////////////////////////////////////////////////
01186 INLINE PandaNode::Stashed::
01187 Stashed(const PandaNode::CData *cdata) :
01188   _stashed(cdata->get_stashed())
01189 {
01190 }
01191 
01192 ////////////////////////////////////////////////////////////////////
01193 //     Function: PandaNode::Stashed::Copy Constructor
01194 //       Access: Public
01195 //  Description:
01196 ////////////////////////////////////////////////////////////////////
01197 INLINE PandaNode::Stashed::
01198 Stashed(const PandaNode::Stashed &copy) :
01199   _stashed(copy._stashed)
01200 {
01201 }
01202 
01203 ////////////////////////////////////////////////////////////////////
01204 //     Function: PandaNode::Stashed::Copy Assignment Operator
01205 //       Access: Public
01206 //  Description:
01207 ////////////////////////////////////////////////////////////////////
01208 INLINE void PandaNode::Stashed::
01209 operator = (const PandaNode::Stashed &copy) {
01210   _stashed = copy._stashed;
01211 }
01212 
01213 ////////////////////////////////////////////////////////////////////
01214 //     Function: PandaNode::Stashed::get_num_stashed
01215 //       Access: Public
01216 //  Description: Returns the number of stashed children of the node.
01217 ////////////////////////////////////////////////////////////////////
01218 INLINE int PandaNode::Stashed::
01219 get_num_stashed() const {
01220   nassertr(_stashed != (Down *)NULL, 0);
01221   return _stashed->size();
01222 }
01223 
01224 ////////////////////////////////////////////////////////////////////
01225 //     Function: PandaNode::Stashed::get_stashed
01226 //       Access: Public
01227 //  Description: Returns the nth stashed child of the node.
01228 ////////////////////////////////////////////////////////////////////
01229 INLINE PandaNode *PandaNode::Stashed::
01230 get_stashed(int n) const {
01231   nassertr(_stashed != (Down *)NULL, NULL);
01232   nassertr(n >= 0 && n < (int)_stashed->size(), NULL);
01233   return (*_stashed)[n].get_child();
01234 }
01235 
01236 ////////////////////////////////////////////////////////////////////
01237 //     Function: PandaNode::Stashed::get_stashed_sort
01238 //       Access: Public
01239 //  Description: Returns the sort index of the nth child node of this
01240 //               node (that is, the number that was passed to
01241 //               add_child()).  See get_num_stashed().
01242 ////////////////////////////////////////////////////////////////////
01243 INLINE int PandaNode::Stashed::
01244 get_stashed_sort(int n) const {
01245   nassertr(_stashed != (Down *)NULL, -1);
01246   nassertr(n >= 0 && n < (int)_stashed->size(), -1);
01247   return (*_stashed)[n].get_sort();
01248 }
01249 
01250 ////////////////////////////////////////////////////////////////////
01251 //     Function: PandaNode::Parents::Constructor
01252 //       Access: Public
01253 //  Description:
01254 ////////////////////////////////////////////////////////////////////
01255 INLINE PandaNode::Parents::
01256 Parents() {
01257 }
01258 
01259 ////////////////////////////////////////////////////////////////////
01260 //     Function: PandaNode::Parents::Constructor
01261 //       Access: Public
01262 //  Description:
01263 ////////////////////////////////////////////////////////////////////
01264 INLINE PandaNode::Parents::
01265 Parents(const PandaNode::CData *cdata) :
01266   _up(cdata->get_up())
01267 {
01268 }
01269 
01270 ////////////////////////////////////////////////////////////////////
01271 //     Function: PandaNode::Parents::Copy Constructor
01272 //       Access: Public
01273 //  Description:
01274 ////////////////////////////////////////////////////////////////////
01275 INLINE PandaNode::Parents::
01276 Parents(const PandaNode::Parents &copy) :
01277   _up(copy._up)
01278 {
01279 }
01280 
01281 ////////////////////////////////////////////////////////////////////
01282 //     Function: PandaNode::Parents::Copy Assignment Operator
01283 //       Access: Public
01284 //  Description:
01285 ////////////////////////////////////////////////////////////////////
01286 INLINE void PandaNode::Parents::
01287 operator = (const PandaNode::Parents &copy) {
01288   _up = copy._up;
01289 }
01290 
01291 ////////////////////////////////////////////////////////////////////
01292 //     Function: PandaNode::Parents::get_num_parents
01293 //       Access: Public
01294 //  Description: Returns the number of parents of the node.
01295 ////////////////////////////////////////////////////////////////////
01296 INLINE int PandaNode::Parents::
01297 get_num_parents() const {
01298   nassertr(_up != (Up *)NULL, 0);
01299   return _up->size();
01300 }
01301 
01302 ////////////////////////////////////////////////////////////////////
01303 //     Function: PandaNode::Parents::get_parent
01304 //       Access: Public
01305 //  Description: Returns the nth parent of the node.
01306 ////////////////////////////////////////////////////////////////////
01307 INLINE PandaNode *PandaNode::Parents::
01308 get_parent(int n) const {
01309   nassertr(_up != (Up *)NULL, NULL);
01310   nassertr(n >= 0 && n < (int)_up->size(), NULL);
01311   return (*_up)[n].get_parent();
01312 }
01313 
01314 ////////////////////////////////////////////////////////////////////
01315 //     Function: PandaNodePipelineReader::Constructor
01316 //       Access: Public
01317 //  Description:
01318 ////////////////////////////////////////////////////////////////////
01319 INLINE PandaNodePipelineReader::
01320 PandaNodePipelineReader(const PandaNode *object, Thread *current_thread) :
01321   _object(object),
01322   _current_thread(current_thread),
01323   _cdata(object->_cycler.read_unlocked(current_thread))
01324 {
01325 #ifdef _DEBUG
01326   nassertv(_object->test_ref_count_nonzero());
01327 #endif // _DEBUG
01328 
01329 #ifdef DO_PIPELINING
01330   // We node_ref the CData pointer, so that if anyone makes changes to
01331   // the PandaNode while we hold this pointer, it will force a
01332   // copy--so that this object will remain unchanged (if out-of-date).
01333   _cdata->node_ref();
01334 #endif  // DO_PIPELINING
01335 }
01336 
01337 ////////////////////////////////////////////////////////////////////
01338 //     Function: PandaNodePipelineReader::Copy Constructor
01339 //       Access: Public
01340 //  Description: 
01341 ////////////////////////////////////////////////////////////////////
01342 INLINE PandaNodePipelineReader::
01343 PandaNodePipelineReader(const PandaNodePipelineReader &copy) :
01344   _object(copy._object),
01345   _current_thread(copy._current_thread),
01346   _cdata(copy._cdata)
01347 {
01348 #ifdef DO_PIPELINING
01349   _cdata->node_ref();
01350 #endif  // DO_PIPELINING
01351 
01352   /*
01353   if (_cdata != (PandaNode::CData *)NULL) {
01354     _object->_cycler.increment_read(_cdata);
01355   }
01356   */
01357 }
01358 
01359 ////////////////////////////////////////////////////////////////////
01360 //     Function: PandaNodePipelineReader::Copy Assignment Operator
01361 //       Access: Public
01362 //  Description: 
01363 ////////////////////////////////////////////////////////////////////
01364 INLINE void PandaNodePipelineReader::
01365 operator = (const PandaNodePipelineReader &copy) {
01366   nassertv(_current_thread == copy._current_thread);
01367 
01368   /*
01369   if (_cdata != (PandaNode::CData *)NULL) {
01370     _object->_cycler.release_read(_cdata);
01371   }
01372   */
01373 
01374 #ifdef DO_PIPELINING
01375   node_unref_delete((CycleData *)_cdata);
01376 #endif  // DO_PIPELINING
01377 
01378   _object = copy._object;
01379   _cdata = copy._cdata;
01380 
01381 #ifdef DO_PIPELINING
01382   _cdata->node_ref();
01383 #endif  // DO_PIPELINING
01384 
01385   /*
01386   if (_cdata != (PandaNode::CData *)NULL) {
01387     _object->_cycler.increment_read(_cdata);
01388   }
01389   */
01390 }
01391 
01392 ////////////////////////////////////////////////////////////////////
01393 //     Function: PandaNodePipelineReader::Destructor
01394 //       Access: Public
01395 //  Description:
01396 ////////////////////////////////////////////////////////////////////
01397 INLINE PandaNodePipelineReader::
01398 ~PandaNodePipelineReader() {
01399   /*
01400   if (_cdata != (PandaNode::CData *)NULL) {
01401     _object->_cycler.release_read(_cdata);
01402   }
01403   */
01404 
01405 #ifdef DO_PIPELINING
01406   node_unref_delete((CycleData *)_cdata);
01407 #endif  // DO_PIPELINING
01408 
01409 #ifdef _DEBUG
01410   _object = NULL;
01411   _cdata = NULL;
01412 #endif  // _DEBUG
01413 }
01414 
01415 ////////////////////////////////////////////////////////////////////
01416 //     Function: PandaNodePipelineReader::get_object
01417 //       Access: Public
01418 //  Description:
01419 ////////////////////////////////////////////////////////////////////
01420 INLINE const PandaNode *PandaNodePipelineReader::
01421 get_object() const {
01422   return _object;
01423 }
01424 
01425 ////////////////////////////////////////////////////////////////////
01426 //     Function: PandaNodePipelineReader::get_current_thread
01427 //       Access: Public
01428 //  Description:
01429 ////////////////////////////////////////////////////////////////////
01430 INLINE Thread *PandaNodePipelineReader::
01431 get_current_thread() const {
01432   return _current_thread;
01433 }
01434 
01435 ////////////////////////////////////////////////////////////////////
01436 //     Function: PandaNodePipelineReader::release
01437 //       Access: Public
01438 //  Description: Releases the lock on this object.  No future calls
01439 //               will be valid on this object.
01440 ////////////////////////////////////////////////////////////////////
01441 INLINE void PandaNodePipelineReader::
01442 release() {
01443   /*
01444   if (_cdata != (PandaNode::CData *)NULL) {
01445     _object->_cycler.release_read(_cdata);
01446     _cdata = NULL;
01447   }
01448   */
01449 }
01450 
01451 ////////////////////////////////////////////////////////////////////
01452 //     Function: PandaNodePipelineReader::compose_draw_mask
01453 //       Access: Public
01454 //  Description: Computes the result of applying this node's draw
01455 //               masks to a running draw mask, as during a traversal.
01456 ////////////////////////////////////////////////////////////////////
01457 INLINE void PandaNodePipelineReader::
01458 compose_draw_mask(DrawMask &running_draw_mask) const {
01459   nassertv(_cdata != (PandaNode::CData *)NULL);
01460   running_draw_mask = (running_draw_mask & ~_cdata->_draw_control_mask) |
01461     (_cdata->_draw_show_mask & _cdata->_draw_control_mask);
01462 }
01463 
01464 ////////////////////////////////////////////////////////////////////
01465 //     Function: PandaNodePipelineReader::compare_draw_mask
01466 //       Access: Public
01467 //  Description: Compares the running draw mask computed during a
01468 //               traversal with this node's net draw masks.  Returns
01469 //               true if the node should be traversed into, or false
01470 //               if there is nothing at this level or below that will
01471 //               be visible to the indicated camera_mask.
01472 ////////////////////////////////////////////////////////////////////
01473 INLINE bool PandaNodePipelineReader::
01474 compare_draw_mask(DrawMask running_draw_mask, DrawMask camera_mask) const {
01475   nassertr(_cdata != (PandaNode::CData *)NULL, false);
01476   nassertr(_cdata->_last_update == _cdata->_next_update, false);
01477 
01478   // As a special case, if net_draw_show_mask is all 0, it means
01479   // either that all nodes under this node are hidden to all cameras,
01480   // or that none of them are renderable nodes (or some combination).
01481   // In either case, we might as well short-circuit.
01482   if (_cdata->_net_draw_show_mask.is_zero()) {
01483     return false;
01484   }
01485 
01486   DrawMask net_draw_control_mask, net_draw_show_mask;
01487   net_draw_control_mask = _cdata->_net_draw_control_mask;
01488   net_draw_show_mask = _cdata->_net_draw_show_mask;
01489 
01490   // Now the bits that are not in net_draw_control_mask--that is,
01491   // those bits that are not changed by any of the nodes at this level
01492   // and below--are taken from running_draw_mask, which is inherited
01493   // from above.  On the other hand, the bits that *are* in
01494   // net_draw_control_mask--those bits that are changed by any of the
01495   // nodes at this level and below--are taken from net_draw_show_mask,
01496   // which is propagated upwards from below.
01497 
01498   // This way, we will traverse into this node if it has any children
01499   // which want to be visited by the traversal, but we will avoid
01500   // traversing into it if all of its children are hidden to this
01501   // camera.
01502   DrawMask compare_mask = (running_draw_mask & ~net_draw_control_mask) | (net_draw_show_mask & net_draw_control_mask);
01503 
01504   return !((compare_mask & PandaNode::_overall_bit).is_zero()) && !((compare_mask & camera_mask).is_zero());
01505 }
01506 
01507 ////////////////////////////////////////////////////////////////////
01508 //     Function: PandaNodePipelineReader::get_num_parents
01509 //       Access: Public
01510 //  Description: Returns the number of parent nodes this node has.  If
01511 //               this number is greater than 1, the node has been
01512 //               multiply instanced.  The order of the parent nodes is
01513 //               not meaningful and is not related to the order in
01514 //               which the node was instanced to them.
01515 ////////////////////////////////////////////////////////////////////
01516 INLINE int PandaNodePipelineReader::
01517 get_num_parents() const {
01518   return _cdata->get_up()->size();
01519 }
01520 
01521 ////////////////////////////////////////////////////////////////////
01522 //     Function: PandaNodePipelineReader::get_parent
01523 //       Access: Public
01524 //  Description: Returns the nth parent node of this node.  See
01525 //               get_num_parents().  Also see get_parents(), if your
01526 //               intention is to iterate through the complete list of
01527 //               parents; get_parents() is preferable in this case.
01528 ////////////////////////////////////////////////////////////////////
01529 INLINE PandaNode *PandaNodePipelineReader::
01530 get_parent(int n) const {
01531   CPT(PandaNode::Up) up = _cdata->get_up();
01532   nassertr(n >= 0 && n < (int)up->size(), NULL);
01533   return (*up)[n].get_parent();
01534 }
01535 
01536 ////////////////////////////////////////////////////////////////////
01537 //     Function: PandaNodePipelineReader::find_parent
01538 //       Access: Public
01539 //  Description: Returns the index of the indicated parent node, if it
01540 //               is a parent, or -1 if it is not.
01541 ////////////////////////////////////////////////////////////////////
01542 INLINE int PandaNodePipelineReader::
01543 find_parent(PandaNode *node) const {
01544   return _object->do_find_parent(node, _cdata);
01545 }
01546 
01547 ////////////////////////////////////////////////////////////////////
01548 //     Function: PandaNodePipelineReader::get_num_children
01549 //       Access: Public
01550 //  Description: Returns the number of child nodes this node has.  The
01551 //               order of the child nodes *is* meaningful and is based
01552 //               on the sort number that was passed to add_child(),
01553 //               and also on the order in which the nodes were added.
01554 ////////////////////////////////////////////////////////////////////
01555 INLINE int PandaNodePipelineReader::
01556 get_num_children() const {
01557   return _cdata->get_down()->size();
01558 }
01559 
01560 ////////////////////////////////////////////////////////////////////
01561 //     Function: PandaNodePipelineReader::get_child
01562 //       Access: Public
01563 //  Description: Returns the nth child node of this node.  See
01564 //               get_num_children().  Also see get_children(), if your
01565 //               intention is to iterate through the complete list of
01566 //               children; get_children() is preferable in this case.
01567 ////////////////////////////////////////////////////////////////////
01568 INLINE PandaNode *PandaNodePipelineReader::
01569 get_child(int n) const {
01570   CPT(PandaNode::Down) down = _cdata->get_down();
01571   nassertr(n >= 0 && n < (int)down->size(), NULL);
01572   return (*down)[n].get_child();
01573 }
01574 
01575 ////////////////////////////////////////////////////////////////////
01576 //     Function: PandaNodePipelineReader::get_child_sort
01577 //       Access: Public
01578 //  Description: Returns the sort index of the nth child node of this
01579 //               node (that is, the number that was passed to
01580 //               add_child()).  See get_num_children().
01581 ////////////////////////////////////////////////////////////////////
01582 INLINE int PandaNodePipelineReader::
01583 get_child_sort(int n) const {
01584   CPT(PandaNode::Down) down = _cdata->get_down();
01585   nassertr(n >= 0 && n < (int)down->size(), -1);
01586   return (*down)[n].get_sort();
01587 }
01588 
01589 ////////////////////////////////////////////////////////////////////
01590 //     Function: PandaNodePipelineReader::find_child
01591 //       Access: Public
01592 //  Description: Returns the index of the indicated child node, if it
01593 //               is a child, or -1 if it is not.
01594 ////////////////////////////////////////////////////////////////////
01595 INLINE int PandaNodePipelineReader::
01596 find_child(PandaNode *node) const {
01597   return _object->do_find_child(node, _cdata->get_down());
01598 }
01599 
01600 ////////////////////////////////////////////////////////////////////
01601 //     Function: PandaNodePipelineReader::get_num_stashed
01602 //       Access: Public
01603 //  Description: Returns the number of stashed nodes this node has.
01604 //               These are former children of the node that have been
01605 //               moved to the special stashed list via stash_child().
01606 ////////////////////////////////////////////////////////////////////
01607 INLINE int PandaNodePipelineReader::
01608 get_num_stashed() const {
01609   return _cdata->get_stashed()->size();
01610 }
01611 
01612 ////////////////////////////////////////////////////////////////////
01613 //     Function: PandaNodePipelineReader::get_stashed
01614 //       Access: Public
01615 //  Description: Returns the nth stashed child of this node.  See
01616 //               get_num_stashed().  Also see get_stashed(), if your
01617 //               intention is to iterate through the complete list of
01618 //               stashed children; get_stashed() is preferable in this
01619 //               case.
01620 ////////////////////////////////////////////////////////////////////
01621 INLINE PandaNode *PandaNodePipelineReader::
01622 get_stashed(int n) const {
01623   CPT(PandaNode::Down) stashed = _cdata->get_stashed();
01624   nassertr(n >= 0 && n < (int)stashed->size(), NULL);
01625   return (*stashed)[n].get_child();
01626 }
01627 
01628 ////////////////////////////////////////////////////////////////////
01629 //     Function: PandaNodePipelineReader::get_stashed_sort
01630 //       Access: Public
01631 //  Description: Returns the sort index of the nth stashed node of this
01632 //               node (that is, the number that was passed to
01633 //               add_child()).  See get_num_stashed().
01634 ////////////////////////////////////////////////////////////////////
01635 INLINE int PandaNodePipelineReader::
01636 get_stashed_sort(int n) const {
01637   CPT(PandaNode::Down) stashed = _cdata->get_stashed();
01638   nassertr(n >= 0 && n < (int)stashed->size(), -1);
01639   return (*stashed)[n].get_sort();
01640 }
01641 
01642 ////////////////////////////////////////////////////////////////////
01643 //     Function: PandaNodePipelineReader::find_stashed
01644 //       Access: Public
01645 //  Description: Returns the index of the indicated stashed node, if
01646 //               it is a stashed child, or -1 if it is not.
01647 ////////////////////////////////////////////////////////////////////
01648 INLINE int PandaNodePipelineReader::
01649 find_stashed(PandaNode *node) const {
01650   return _object->do_find_child(node, _cdata->get_stashed());
01651 }
01652 
01653 ////////////////////////////////////////////////////////////////////
01654 //     Function: PandaNodePipelineReader::get_state
01655 //       Access: Public
01656 //  Description: Returns the complete RenderState that will be applied
01657 //               to all nodes at this level and below, as set on this
01658 //               node.  This returns only the RenderState set on this
01659 //               particular node, and has nothing to do with state
01660 //               that might be inherited from above.
01661 ////////////////////////////////////////////////////////////////////
01662 INLINE const RenderState *PandaNodePipelineReader::
01663 get_state() const {
01664   return _cdata->_state;
01665 }
01666 
01667 ////////////////////////////////////////////////////////////////////
01668 //     Function: PandaNodePipelineReader::get_effects
01669 //       Access: Public
01670 //  Description: Returns the complete RenderEffects that will be
01671 //               applied to this node.
01672 ////////////////////////////////////////////////////////////////////
01673 INLINE const RenderEffects *PandaNodePipelineReader::
01674 get_effects() const {
01675   return _cdata->_effects;
01676 }
01677 
01678 ////////////////////////////////////////////////////////////////////
01679 //     Function: PandaNodePipelineReader::get_transform
01680 //       Access: Public
01681 //  Description: Returns the transform that has been set on this
01682 //               particular node.  This is not the net transform from
01683 //               the root, but simply the transform on this particular
01684 //               node.
01685 ////////////////////////////////////////////////////////////////////
01686 INLINE const TransformState *PandaNodePipelineReader::
01687 get_transform() const {
01688   return _cdata->_transform;
01689 }
01690 
01691 ////////////////////////////////////////////////////////////////////
01692 //     Function: PandaNodePipelineReader::get_prev_transform
01693 //       Access: Public
01694 //  Description: Returns the transform that has been set as this
01695 //               node's "previous" position.  See
01696 //               set_prev_transform().
01697 ////////////////////////////////////////////////////////////////////
01698 const TransformState *PandaNodePipelineReader::
01699 get_prev_transform() const {
01700   return _cdata->_prev_transform;
01701 }
01702 
01703 ////////////////////////////////////////////////////////////////////
01704 //     Function: PandaNodePipelineReader::get_tag
01705 //       Access: Public
01706 //  Description: Retrieves the user-defined value that was previously
01707 //               set on this node for the particular key, if any.  If
01708 //               no value has been previously set, returns the empty
01709 //               string.
01710 ////////////////////////////////////////////////////////////////////
01711 INLINE string PandaNodePipelineReader::
01712 get_tag(const string &key) const {
01713   PandaNode::TagData::const_iterator ti;
01714   ti = _cdata->_tag_data.find(key);
01715   if (ti != _cdata->_tag_data.end()) {
01716     return (*ti).second;
01717   }
01718   return string();
01719 }
01720 
01721 ////////////////////////////////////////////////////////////////////
01722 //     Function: PandaNodePipelineReader::has_tag
01723 //       Access: Public
01724 //  Description: Returns true if a value has been defined on this node
01725 //               for the particular key (even if that value is the
01726 //               empty string), or false if no value has been set.
01727 ////////////////////////////////////////////////////////////////////
01728 INLINE bool PandaNodePipelineReader::
01729 has_tag(const string &key) const {
01730   PandaNode::TagData::const_iterator ti;
01731   ti = _cdata->_tag_data.find(key);
01732   return (ti != _cdata->_tag_data.end());
01733 }
01734 
01735 ////////////////////////////////////////////////////////////////////
01736 //     Function: PandaNodePipelineReader::get_net_collide_mask
01737 //       Access: Public
01738 //  Description: Returns the union of all into_collide_mask() values
01739 //               set at CollisionNodes at this level and below.
01740 ////////////////////////////////////////////////////////////////////
01741 INLINE CollideMask PandaNodePipelineReader::
01742 get_net_collide_mask() const {
01743   nassertr(_cdata->_last_update == _cdata->_next_update, _cdata->_net_collide_mask);
01744   return _cdata->_net_collide_mask;
01745 }
01746 
01747 ////////////////////////////////////////////////////////////////////
01748 //     Function: PandaNodePipelineReader::get_off_clip_planes
01749 //       Access: Public
01750 //  Description: Returns a ClipPlaneAttrib which represents the union
01751 //               of all of the clip planes that have been turned *off*
01752 //               at this level and below.
01753 ////////////////////////////////////////////////////////////////////
01754 INLINE CPT(RenderAttrib) PandaNodePipelineReader::
01755 get_off_clip_planes() const {
01756   nassertr(_cdata->_last_update == _cdata->_next_update, _cdata->_off_clip_planes);
01757   return _cdata->_off_clip_planes;
01758 }
01759 
01760 ////////////////////////////////////////////////////////////////////
01761 //     Function: PandaNodePipelineReader::get_bounds
01762 //       Access: Public
01763 //  Description: Returns the external bounding volume of this node: a
01764 //               bounding volume that contains the user bounding
01765 //               volume, the internal bounding volume, and all of the
01766 //               children's bounding volumes.
01767 ////////////////////////////////////////////////////////////////////
01768 INLINE CPT(BoundingVolume) PandaNodePipelineReader::
01769 get_bounds() const {
01770   nassertr(_cdata->_last_update == _cdata->_next_update, _cdata->_external_bounds);
01771   return _cdata->_external_bounds;
01772 }
01773 
01774 ////////////////////////////////////////////////////////////////////
01775 //     Function: PandaNodePipelineReader::get_nested_vertices
01776 //       Access: Public
01777 //  Description: Returns the total number of vertices that will be
01778 //               rendered by this node and all of its descendents.
01779 //
01780 //               This is not necessarily an accurate count of vertices
01781 //               that will actually be rendered, since this will
01782 //               include all vertices of all LOD's, and it will also
01783 //               include hidden nodes.  It may also omit or only
01784 //               approximate certain kinds of dynamic geometry.
01785 //               However, it will not include stashed nodes.
01786 ////////////////////////////////////////////////////////////////////
01787 INLINE int PandaNodePipelineReader::
01788 get_nested_vertices() const {
01789   nassertr(_cdata->_last_update == _cdata->_next_update, _cdata->_nested_vertices);
01790   return _cdata->_nested_vertices;
01791 }
01792 
01793 ////////////////////////////////////////////////////////////////////
01794 //     Function: PandaNodePipelineReader::is_final
01795 //       Access: Public
01796 //  Description: Returns the current state of the "final" flag.
01797 //               Initially, this flag is off (false), but it may be
01798 //               changed by an explicit call to set_final().  See
01799 //               set_final().
01800 ////////////////////////////////////////////////////////////////////
01801 INLINE bool PandaNodePipelineReader::
01802 is_final() const {
01803   return _cdata->_final_bounds;
01804 }
01805 
01806 
01807 ////////////////////////////////////////////////////////////////////
01808 //     Function: PandaNodePipelineReader::get_fancy_bits
01809 //       Access: Public
01810 //  Description: Returns the union of all of the enum FancyBits values
01811 //               corresponding to the various "fancy" attributes that
01812 //               are set on the node.  If this returns 0, the node has
01813 //               nothing interesting about it.  This is intended to
01814 //               speed traversal by quickly skipping past nodes that
01815 //               don't particularly affect the render state.
01816 ////////////////////////////////////////////////////////////////////
01817 INLINE int PandaNodePipelineReader::
01818 get_fancy_bits() const {
01819   return _cdata->_fancy_bits;
01820 }
01821 
01822 ////////////////////////////////////////////////////////////////////
01823 //     Function: PandaNodePipelineReader::get_children
01824 //       Access: Public
01825 //  Description: Returns an object that can be used to walk through
01826 //               the list of children of the node.  When you intend to
01827 //               visit multiple children, using this is slightly
01828 //               faster than calling get_child() directly on the
01829 //               PandaNode, since this object avoids reopening the
01830 //               PipelineCycler each time.
01831 //
01832 //               This object also protects you from self-modifying
01833 //               loops (e.g. adding or removing children during
01834 //               traversal), since a virtual copy of the children is
01835 //               made ahead of time.  The virtual copy is fast--it is
01836 //               a form of copy-on-write, so the list is not actually
01837 //               copied unless it is modified during the traversal.
01838 ////////////////////////////////////////////////////////////////////
01839 INLINE PandaNode::Children PandaNodePipelineReader::
01840 get_children() const {
01841   return PandaNode::Children(_cdata);
01842 }
01843 
01844 ////////////////////////////////////////////////////////////////////
01845 //     Function: PandaNodePipelineReader::get_stashed
01846 //       Access: Public
01847 //  Description: Returns an object that can be used to walk through
01848 //               the list of children of the node.  When you intend to
01849 //               visit multiple children, using this is slightly
01850 //               faster than calling get_stashed() directly on the
01851 //               PandaNode, since this object avoids reopening the
01852 //               PipelineCycler each time.
01853 //
01854 //               This object also protects you from self-modifying
01855 //               loops (e.g. adding or removing children during
01856 //               traversal), since a virtual copy of the children is
01857 //               made ahead of time.  The virtual copy is fast--it is
01858 //               a form of copy-on-write, so the list is not actually
01859 //               copied unless it is modified during the traversal.
01860 ////////////////////////////////////////////////////////////////////
01861 INLINE PandaNode::Stashed PandaNodePipelineReader::
01862 get_stashed() const {
01863   return PandaNode::Stashed(_cdata);
01864 }
01865 
01866 ////////////////////////////////////////////////////////////////////
01867 //     Function: PandaNodePipelineReader::get_parents
01868 //       Access: Public
01869 //  Description: Returns an object that can be used to walk through
01870 //               the list of parents of the node, similar to
01871 //               get_children() and get_stashed().
01872 ////////////////////////////////////////////////////////////////////
01873 INLINE PandaNode::Parents PandaNodePipelineReader::
01874 get_parents() const {
01875   return PandaNode::Parents(_cdata);
01876 }
01877 
01878 ////////////////////////////////////////////////////////////////////
01879 //     Function: PandaNode::BamReaderAuxDataDown::Constructor
01880 //       Access: Public
01881 //  Description: 
01882 ////////////////////////////////////////////////////////////////////
01883 INLINE PandaNode::BamReaderAuxDataDown::
01884 BamReaderAuxDataDown() :
01885   _down_list(PandaNode::get_class_type())
01886 {
01887 }
 All Classes Functions Variables Enumerations