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