00001 // Filename: pandaNode.cxx 00002 // Created by: drose (20Feb02) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "pandaNode.h" 00020 #include "config_pgraph.h" 00021 #include "nodePathComponent.h" 00022 #include "bamReader.h" 00023 #include "bamWriter.h" 00024 #include "indent.h" 00025 #include "geometricBoundingVolume.h" 00026 #include "sceneGraphReducer.h" 00027 #include "accumulatedAttribs.h" 00028 00029 00030 TypeHandle PandaNode::_type_handle; 00031 00032 // 00033 // We go through some considerable effort in this class to ensure that 00034 // NodePaths are kept consistent as we attach and detach nodes. We 00035 // must enforce the following rules: 00036 // 00037 // 1) Each NodePath (i.e. chain of NodePathComponents) represents a 00038 // complete unbroken chain from a PandaNode to the root of the 00039 // graph. 00040 // 00041 // 2) Each NodePathComponent chain is unique. There are no two 00042 // different NodePathComponents that reference the same path to the 00043 // root. 00044 // 00045 // The following rules all follow from rules (1) and (2): 00046 // 00047 // 3) If a PandaNode with no parents is attached to a new parent, 00048 // all NodePaths that previously indicated this node as the root of 00049 // graph must now be updated to include the complete chain to the 00050 // new root. 00051 // 00052 // 4) If a PandaNode with other parents is attached to a new parent, 00053 // any previously existing NodePaths are not affected. 00054 // 00055 // 5) If a PandaNode is disconnected from its parent, and it has no 00056 // other parents, all NodePaths that previously passed through this 00057 // node to the old parent must now be updated to indicate this node 00058 // is now the root. 00059 // 00060 // 6) If a PandaNode is disconnected from its parent, and it has at 00061 // least one other parent, all NodePaths that previously passed 00062 // through this node to the old parent must now be updated to pass 00063 // through one of the other parents instead. 00064 // 00065 // Rules (5) and (6) can especially complicate things because they 00066 // introduce the possibility that two formerly distinct NodePaths are 00067 // now equivalent, which violates rule (2). For example, if A is the 00068 // top of the graph with children B and C, and D is instanced to both 00069 // B and C, and E is a child of D, there might be two different 00070 // NodePaths to D: A/B/D/E and A/C/D/E. If you then break the 00071 // connection between D and E, both NodePaths must now become just the 00072 // singleton E. 00073 // 00074 // Unfortunately, we cannot simply remove one of the extra 00075 // NodePathComponents, because there may be any number of NodePath 00076 // objects that reference them. Instead, we define the concept of 00077 // "collapsed" NodePathComponents, which means one NodePathComponent 00078 // can be "collapsed" into a different one so that any attempt to 00079 // reference the first actually retrieves the second, rather like a 00080 // symbolic link in the file system. When the NodePath traverses its 00081 // component chain, it will pass right over the collapsed component in 00082 // favor of the one it has been collapsed into. 00083 // 00084 00085 00086 // 00087 // There are two different interfaces here for making and breaking 00088 // parent-child connections: the fundamental PandaNode interface, via 00089 // add_child() and remove_child() (and related functions), and the 00090 // NodePath support interface, via attach(), detach(), and reparent(). 00091 // They both do essentially the same thing, but with slightly 00092 // different inputs. Both are responsible for keeping all NodePaths 00093 // up-to-date according to the above rules. 00094 // 00095 // The NodePath support interface functions are strictly called from 00096 // within the NodePath class, and are used to implement 00097 // NodePath::reparent_to() and NodePath::remove_node(), etc. The 00098 // fundamental interface, on the other hand, is intended to be called 00099 // directly by the user. 00100 // 00101 // The fundamental interface has a slightly lower overhead because it 00102 // does not need to create a NodePathComponent chain where one does 00103 // not already exist; however, the NodePath support interface is more 00104 // useful when the NodePath already does exist, because it ensures 00105 // that the particular NodePath calling it is kept appropriately 00106 // up-to-date. 00107 // 00108 00109 00110 //////////////////////////////////////////////////////////////////// 00111 // Function: PandaNode::CData::make_copy 00112 // Access: Public, Virtual 00113 // Description: 00114 //////////////////////////////////////////////////////////////////// 00115 CycleData *PandaNode::CData:: 00116 make_copy() const { 00117 return new CData(*this); 00118 } 00119 00120 //////////////////////////////////////////////////////////////////// 00121 // Function: PandaNode::CData::write_datagram 00122 // Access: Public, Virtual 00123 // Description: Writes the contents of this object to the datagram 00124 // for shipping out to a Bam file. 00125 //////////////////////////////////////////////////////////////////// 00126 void PandaNode::CData:: 00127 write_datagram(BamWriter *manager, Datagram &dg) const { 00128 manager->write_pointer(dg, _state); 00129 manager->write_pointer(dg, _effects); 00130 manager->write_pointer(dg, _transform); 00131 00132 dg.add_uint32(_draw_mask.get_word()); 00133 00134 write_up_list(_up, manager, dg); 00135 write_down_list(_down, manager, dg); 00136 write_down_list(_stashed, manager, dg); 00137 } 00138 00139 //////////////////////////////////////////////////////////////////// 00140 // Function: PandaNode::CData::complete_pointers 00141 // Access: Public, Virtual 00142 // Description: Receives an array of pointers, one for each time 00143 // manager->read_pointer() was called in fillin(). 00144 // Returns the number of pointers processed. 00145 //////////////////////////////////////////////////////////////////// 00146 int PandaNode::CData:: 00147 complete_pointers(TypedWritable **p_list, BamReader *manager) { 00148 int pi = CycleData::complete_pointers(p_list, manager); 00149 00150 // Get the state, effects, and transform pointers. 00151 _state = DCAST(RenderState, p_list[pi++]); 00152 _effects = DCAST(RenderEffects, p_list[pi++]); 00153 _transform = DCAST(TransformState, p_list[pi++]); 00154 00155 // Finalize these pointers now to decrement their artificially-held 00156 // reference counts. We do this now, rather than later, in case 00157 // some other object reassigns them a little later on during 00158 // initialization, before they can finalize themselves normally (for 00159 // instance, the character may change the node's transform). If 00160 // that happens, the pointer may discover that no one else holds its 00161 // reference count when it finalizes, which will constitute a memory 00162 // leak (see the comments in TransformState::finalize(), etc.). 00163 manager->finalize_now((RenderState *)_state.p()); 00164 manager->finalize_now((RenderEffects *)_effects.p()); 00165 manager->finalize_now((TransformState *)_transform.p()); 00166 00167 // Get the parent and child pointers. 00168 pi += complete_up_list(_up, p_list + pi, manager); 00169 pi += complete_down_list(_down, p_list + pi, manager); 00170 pi += complete_down_list(_stashed, p_list + pi, manager); 00171 00172 return pi; 00173 } 00174 00175 //////////////////////////////////////////////////////////////////// 00176 // Function: PandaNode::CData::fillin 00177 // Access: Public, Virtual 00178 // Description: This internal function is called by make_from_bam to 00179 // read in all of the relevant data from the BamFile for 00180 // the new PandaNode. 00181 //////////////////////////////////////////////////////////////////// 00182 void PandaNode::CData:: 00183 fillin(DatagramIterator &scan, BamReader *manager) { 00184 // Read the state, effects, and transform pointers. 00185 manager->read_pointer(scan); 00186 manager->read_pointer(scan); 00187 manager->read_pointer(scan); 00188 00189 _draw_mask.set_word(scan.get_uint32()); 00190 00191 // Read the parent and child pointers. 00192 fillin_up_list(_up, scan, manager); 00193 fillin_down_list(_down, scan, manager); 00194 fillin_down_list(_stashed, scan, manager); 00195 } 00196 00197 //////////////////////////////////////////////////////////////////// 00198 // Function: PandaNode::CData::write_up_list 00199 // Access: Private 00200 // Description: Writes the indicated list of parent node pointers to 00201 // the datagram. 00202 //////////////////////////////////////////////////////////////////// 00203 void PandaNode::CData:: 00204 write_up_list(const PandaNode::Up &up_list, 00205 BamWriter *manager, Datagram &dg) const { 00206 // When we write a PandaNode, we write out its complete list of 00207 // child node pointers, but we only write out the parent node 00208 // pointers that have already been added to the bam file by a 00209 // previous write operation. This is a bit of trickery that allows 00210 // us to write out just a subgraph (instead of the complete graph) 00211 // when we write out an arbitrary node in the graph, yet also allows 00212 // us to keep nodes completely in sync when we use the bam format 00213 // for streaming scene graph operations over the network. 00214 00215 int num_parents = 0; 00216 Up::const_iterator ui; 00217 for (ui = up_list.begin(); ui != up_list.end(); ++ui) { 00218 PandaNode *parent_node = (*ui).get_parent(); 00219 if (manager->has_object(parent_node)) { 00220 num_parents++; 00221 } 00222 } 00223 nassertv(num_parents == (int)(PN_uint16)num_parents); 00224 dg.add_uint16(num_parents); 00225 for (ui = up_list.begin(); ui != up_list.end(); ++ui) { 00226 PandaNode *parent_node = (*ui).get_parent(); 00227 if (manager->has_object(parent_node)) { 00228 manager->write_pointer(dg, parent_node); 00229 } 00230 } 00231 } 00232 00233 //////////////////////////////////////////////////////////////////// 00234 // Function: PandaNode::CData::write_down_list 00235 // Access: Private 00236 // Description: Writes the indicated list of child node pointers to 00237 // the datagram. 00238 //////////////////////////////////////////////////////////////////// 00239 void PandaNode::CData:: 00240 write_down_list(const PandaNode::Down &down_list, 00241 BamWriter *manager, Datagram &dg) const { 00242 int num_children = down_list.size(); 00243 nassertv(num_children == (int)(PN_uint16)num_children); 00244 dg.add_uint16(num_children); 00245 00246 // Should we smarten up the writing of the sort number? Most of the 00247 // time these will all be zero. 00248 Down::const_iterator di; 00249 for (di = down_list.begin(); di != down_list.end(); ++di) { 00250 PandaNode *child_node = (*di).get_child(); 00251 int sort = (*di).get_sort(); 00252 manager->write_pointer(dg, child_node); 00253 dg.add_int32(sort); 00254 } 00255 } 00256 00257 //////////////////////////////////////////////////////////////////// 00258 // Function: PandaNode::CData::complete_up_list 00259 // Access: Private 00260 // Description: Calls complete_pointers() on the list of parent node 00261 // pointers. 00262 //////////////////////////////////////////////////////////////////// 00263 int PandaNode::CData:: 00264 complete_up_list(PandaNode::Up &up_list, 00265 TypedWritable **p_list, BamReader *manager) { 00266 int pi = 0; 00267 00268 // Get the parent pointers. 00269 Up::iterator ui; 00270 for (ui = up_list.begin(); ui != up_list.end(); ++ui) { 00271 PandaNode *parent_node = DCAST(PandaNode, p_list[pi++]); 00272 00273 // For some reason, VC++ won't accept UpConnection as an inline 00274 // temporary constructor here ("C2226: unexpected type 00275 // PandaNode::UpConnection"), so we must make this assignment 00276 // using an explicit temporary variable. 00277 UpConnection connection(parent_node); 00278 (*ui) = connection; 00279 } 00280 00281 // Now we should sort the list, since the sorting is based on 00282 // pointer order, which might be different from one session to the 00283 // next. 00284 up_list.sort(); 00285 00286 return pi; 00287 } 00288 00289 //////////////////////////////////////////////////////////////////// 00290 // Function: PandaNode::CData::complete_down_list 00291 // Access: Private 00292 // Description: Calls complete_pointers() on the list of child node 00293 // pointers. 00294 //////////////////////////////////////////////////////////////////// 00295 int PandaNode::CData:: 00296 complete_down_list(PandaNode::Down &down_list, 00297 TypedWritable **p_list, BamReader *manager) { 00298 int pi = 0; 00299 00300 Down::iterator di; 00301 for (di = down_list.begin(); di != down_list.end(); ++di) { 00302 int sort = (*di).get_sort(); 00303 PT(PandaNode) child_node = DCAST(PandaNode, p_list[pi++]); 00304 (*di) = DownConnection(child_node, sort); 00305 } 00306 00307 // Unlike the up list, we should *not* sort the down list. The down 00308 // list is stored in a specific order, not related to pointer order; 00309 // and this order should be preserved from one session to the next. 00310 00311 return pi; 00312 } 00313 00314 //////////////////////////////////////////////////////////////////// 00315 // Function: PandaNode::CData::fillin_up_list 00316 // Access: Private 00317 // Description: Reads the indicated list parent node pointers from 00318 // the datagram (or at least calls read_pointer() for 00319 // each one). 00320 //////////////////////////////////////////////////////////////////// 00321 void PandaNode::CData:: 00322 fillin_up_list(PandaNode::Up &up_list, 00323 DatagramIterator &scan, BamReader *manager) { 00324 int num_parents = scan.get_uint16(); 00325 // Read the list of parent nodes. Push back a NULL for each one. 00326 _up.reserve(num_parents); 00327 for (int i = 0; i < num_parents; i++) { 00328 manager->read_pointer(scan); 00329 _up.push_back(UpConnection(NULL)); 00330 } 00331 } 00332 00333 //////////////////////////////////////////////////////////////////// 00334 // Function: PandaNode::CData::fillin_down_list 00335 // Access: Private 00336 // Description: Reads the indicated list child node pointers from 00337 // the datagram (or at least calls read_pointer() for 00338 // each one). 00339 //////////////////////////////////////////////////////////////////// 00340 void PandaNode::CData:: 00341 fillin_down_list(PandaNode::Down &down_list, 00342 DatagramIterator &scan, BamReader *manager) { 00343 int num_children = scan.get_uint16(); 00344 // Read the list of child nodes. Push back a NULL for each one. 00345 down_list.reserve(num_children); 00346 for (int i = 0; i < num_children; i++) { 00347 manager->read_pointer(scan); 00348 int sort = scan.get_int32(); 00349 down_list.push_back(DownConnection(NULL, sort)); 00350 } 00351 } 00352 00353 //////////////////////////////////////////////////////////////////// 00354 // Function: PandaNode::ChildrenCopy::Constructor 00355 // Access: Public 00356 // Description: 00357 //////////////////////////////////////////////////////////////////// 00358 PandaNode::ChildrenCopy:: 00359 ChildrenCopy(const PandaNode::CDReader &cdata) { 00360 Children cr(cdata); 00361 int num_children = cr.get_num_children(); 00362 for (int i = 0; i < num_children; i++) { 00363 _list.push_back(cr.get_child(i)); 00364 } 00365 } 00366 00367 //////////////////////////////////////////////////////////////////// 00368 // Function: PandaNode::Constructor 00369 // Access: Published 00370 // Description: 00371 //////////////////////////////////////////////////////////////////// 00372 PandaNode:: 00373 PandaNode(const string &name) : 00374 Namable(name) 00375 { 00376 } 00377 00378 //////////////////////////////////////////////////////////////////// 00379 // Function: PandaNode::Destructor 00380 // Access: Published, Virtual 00381 // Description: 00382 //////////////////////////////////////////////////////////////////// 00383 PandaNode:: 00384 ~PandaNode() { 00385 // We shouldn't have any parents left by the time we destruct, or 00386 // there's a refcount fault somewhere. 00387 #ifndef NDEBUG 00388 { 00389 CDReader cdata(_cycler); 00390 nassertv(cdata->_up.empty()); 00391 } 00392 #endif // NDEBUG 00393 00394 remove_all_children(); 00395 } 00396 00397 //////////////////////////////////////////////////////////////////// 00398 // Function: PandaNode::Copy Constructor 00399 // Access: Protected 00400 // Description: Do not call the copy constructor directly; instead, 00401 // use make_copy() or copy_subgraph() to make a copy of 00402 // a node. 00403 //////////////////////////////////////////////////////////////////// 00404 PandaNode:: 00405 PandaNode(const PandaNode ©) : 00406 TypedWritable(copy), 00407 Namable(copy), 00408 ReferenceCount(copy) 00409 { 00410 // Copying a node does not copy its children. 00411 00412 // Copy the other node's state. 00413 CDReader copy_cdata(copy._cycler); 00414 CDWriter cdata(_cycler); 00415 cdata->_state = copy_cdata->_state; 00416 cdata->_effects = copy_cdata->_effects; 00417 cdata->_transform = copy_cdata->_transform; 00418 cdata->_draw_mask = copy_cdata->_draw_mask; 00419 } 00420 00421 //////////////////////////////////////////////////////////////////// 00422 // Function: PandaNode::Copy Assignment Operator 00423 // Access: Private 00424 // Description: Do not call the copy assignment operator at all. Use 00425 // make_copy() or copy_subgraph() to make a copy of a 00426 // node. 00427 //////////////////////////////////////////////////////////////////// 00428 void PandaNode:: 00429 operator = (const PandaNode ©) { 00430 nassertv(false); 00431 } 00432 00433 //////////////////////////////////////////////////////////////////// 00434 // Function: PandaNode::make_copy 00435 // Access: Public, Virtual 00436 // Description: Returns a newly-allocated PandaNode that is a shallow 00437 // copy of this one. It will be a different pointer, 00438 // but its internal data may or may not be shared with 00439 // that of the original PandaNode. No children will be 00440 // copied. 00441 //////////////////////////////////////////////////////////////////// 00442 PandaNode *PandaNode:: 00443 make_copy() const { 00444 return new PandaNode(*this); 00445 } 00446 00447 //////////////////////////////////////////////////////////////////// 00448 // Function: PandaNode::safe_to_flatten 00449 // Access: Public, Virtual 00450 // Description: Returns true if it is generally safe to flatten out 00451 // this particular kind of PandaNode by duplicating 00452 // instances, false otherwise (for instance, a Camera 00453 // cannot be safely flattened, because the Camera 00454 // pointer itself is meaningful). 00455 //////////////////////////////////////////////////////////////////// 00456 bool PandaNode:: 00457 safe_to_flatten() const { 00458 return true; 00459 } 00460 00461 //////////////////////////////////////////////////////////////////// 00462 // Function: PandaNode::safe_to_transform 00463 // Access: Public, Virtual 00464 // Description: Returns true if it is generally safe to transform 00465 // this particular kind of PandaNode by calling the 00466 // xform() method, false otherwise. For instance, it's 00467 // usually a bad idea to attempt to xform a Character. 00468 //////////////////////////////////////////////////////////////////// 00469 bool PandaNode:: 00470 safe_to_transform() const { 00471 return true; 00472 } 00473 00474 //////////////////////////////////////////////////////////////////// 00475 // Function: PandaNode::safe_to_modify_transform 00476 // Access: Public, Virtual 00477 // Description: Returns true if it is safe to automatically adjust 00478 // the transform on this kind of node. Usually, this is 00479 // only a bad idea if the user expects to find a 00480 // particular transform on the node. 00481 // 00482 // ModelNodes with the preserve_transform flag set are 00483 // presently the only kinds of nodes that should not 00484 // have their transform even adjusted. 00485 //////////////////////////////////////////////////////////////////// 00486 bool PandaNode:: 00487 safe_to_modify_transform() const { 00488 return true; 00489 } 00490 00491 //////////////////////////////////////////////////////////////////// 00492 // Function: PandaNode::safe_to_combine 00493 // Access: Public, Virtual 00494 // Description: Returns true if it is generally safe to combine this 00495 // particular kind of PandaNode with other kinds of 00496 // PandaNodes, adding children or whatever. For 00497 // instance, an LODNode should not be combined with any 00498 // other PandaNode, because its set of children is 00499 // meaningful. 00500 //////////////////////////////////////////////////////////////////// 00501 bool PandaNode:: 00502 safe_to_combine() const { 00503 return true; 00504 } 00505 00506 //////////////////////////////////////////////////////////////////// 00507 // Function: PandaNode::safe_to_flatten_below 00508 // Access: Public, Virtual 00509 // Description: Returns true if a flatten operation may safely 00510 // continue past this node, or false if it should drop 00511 // all attributes here and stop. 00512 //////////////////////////////////////////////////////////////////// 00513 bool PandaNode:: 00514 safe_to_flatten_below() const { 00515 return true; 00516 } 00517 00518 //////////////////////////////////////////////////////////////////// 00519 // Function: PandaNode::preserve_name 00520 // Access: Public, Virtual 00521 // Description: Returns true if the node's name has extrinsic meaning 00522 // and must be preserved across a flatten operation, 00523 // false otherwise. 00524 //////////////////////////////////////////////////////////////////// 00525 bool PandaNode:: 00526 preserve_name() const { 00527 return false; 00528 } 00529 00530 //////////////////////////////////////////////////////////////////// 00531 // Function: PandaNode::get_unsafe_to_apply_attribs 00532 // Access: Public, Virtual 00533 // Description: Returns the union of all attributes from 00534 // SceneGraphReducer::AttribTypes that may not safely be 00535 // applied to the vertices of this node. If this is 00536 // nonzero, these attributes must be dropped at this 00537 // node as a state change. 00538 // 00539 // This is a generalization of safe_to_transform(). 00540 //////////////////////////////////////////////////////////////////// 00541 int PandaNode:: 00542 get_unsafe_to_apply_attribs() const { 00543 return 0; 00544 } 00545 00546 //////////////////////////////////////////////////////////////////// 00547 // Function: PandaNode::apply_attribs_to_vertices 00548 // Access: Public, Virtual 00549 // Description: Applies whatever attributes are specified in the 00550 // AccumulatedAttribs object (and by the attrib_types 00551 // bitmask) to the vertices on this node, if 00552 // appropriate. If this node uses geom arrays like a 00553 // GeomNode, the supplied GeomTransformer may be used to 00554 // unify shared arrays across multiple different nodes. 00555 // 00556 // This is a generalization of xform(). 00557 //////////////////////////////////////////////////////////////////// 00558 void PandaNode:: 00559 apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types, 00560 GeomTransformer &transformer) { 00561 if ((attrib_types & SceneGraphReducer::TT_transform) != 0) { 00562 xform(attribs._transform->get_mat()); 00563 } 00564 } 00565 00566 //////////////////////////////////////////////////////////////////// 00567 // Function: PandaNode::xform 00568 // Access: Public, Virtual 00569 // Description: Transforms the contents of this PandaNode by the 00570 // indicated matrix, if it means anything to do so. For 00571 // most kinds of PandaNodes, this does nothing. 00572 //////////////////////////////////////////////////////////////////// 00573 void PandaNode:: 00574 xform(const LMatrix4f &) { 00575 } 00576 00577 //////////////////////////////////////////////////////////////////// 00578 // Function: PandaNode::combine_with 00579 // Access: Public, Virtual 00580 // Description: Collapses this PandaNode with the other PandaNode, if 00581 // possible, and returns a pointer to the combined 00582 // PandaNode, or NULL if the two PandaNodes cannot 00583 // safely be combined. 00584 // 00585 // The return value may be this, other, or a new 00586 // PandaNode altogether. 00587 // 00588 // This function is called from GraphReducer::flatten(), 00589 // and need not deal with children; its job is just to 00590 // decide whether to collapse the two PandaNodes and 00591 // what the collapsed PandaNode should look like. 00592 //////////////////////////////////////////////////////////////////// 00593 PandaNode *PandaNode:: 00594 combine_with(PandaNode *other) { 00595 // This is a little bit broken right now w.r.t. NodePaths, since any 00596 // NodePaths attached to the lost node will simply be disconnected. 00597 // This isn't the right thing to do; we should collapse those 00598 // NodePaths with these NodePaths instead. To do this properly, we 00599 // will need to combine this functionality with that of stealing the 00600 // other node's children into one method. Not too difficult, but 00601 // there are more pressing problems to work on right now. 00602 00603 00604 // An unadorned PandaNode always combines with any other PandaNodes by 00605 // yielding completely. However, if we are actually some fancy PandaNode 00606 // type that derives from PandaNode but didn't redefine this function, we 00607 // should refuse to combine. 00608 if (is_exact_type(get_class_type())) { 00609 // No, we're an ordinary PandaNode. 00610 return other; 00611 00612 } else if (other->is_exact_type(get_class_type())) { 00613 // We're not an ordinary PandaNode, but the other one is. 00614 return this; 00615 } 00616 00617 // We're something other than an ordinary PandaNode. Don't combine. 00618 return (PandaNode *)NULL; 00619 } 00620 00621 //////////////////////////////////////////////////////////////////// 00622 // Function: PandaNode::calc_tight_bounds 00623 // Access: Public, Virtual 00624 // Description: This is used to support 00625 // NodePath::calc_tight_bounds(). It is not intended to 00626 // be called directly, and it has nothing to do with the 00627 // normal Panda bounding-volume computation. 00628 // 00629 // If the node contains any geometry, this updates 00630 // min_point and max_point to enclose its bounding box. 00631 // found_any is to be set true if the node has any 00632 // geometry at all, or left alone if it has none. This 00633 // method may be called over several nodes, so it may 00634 // enter with min_point, max_point, and found_any 00635 // already set. 00636 // 00637 // This function is recursive, and the return value is 00638 // the transform after it has been modified by this 00639 // node's transform. 00640 //////////////////////////////////////////////////////////////////// 00641 CPT(TransformState) PandaNode:: 00642 calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any, 00643 const TransformState *transform) const { 00644 CPT(TransformState) next_transform = transform->compose(get_transform()); 00645 00646 Children cr = get_children(); 00647 int num_children = cr.get_num_children(); 00648 for (int i = 0; i < num_children; i++) { 00649 cr.get_child(i)->calc_tight_bounds(min_point, max_point, 00650 found_any, next_transform); 00651 } 00652 00653 return next_transform; 00654 } 00655 00656 //////////////////////////////////////////////////////////////////// 00657 // Function: PandaNode::has_cull_callback 00658 // Access: Public, Virtual 00659 // Description: Should be overridden by derived classes to return 00660 // true if cull_callback() has been defined. Otherwise, 00661 // returns false to indicate cull_callback() does not 00662 // need to be called for this node during the cull 00663 // traversal. 00664 //////////////////////////////////////////////////////////////////// 00665 bool PandaNode:: 00666 has_cull_callback() const { 00667 return false; 00668 } 00669 00670 //////////////////////////////////////////////////////////////////// 00671 // Function: PandaNode::cull_callback 00672 // Access: Public, Virtual 00673 // Description: If has_cull_callback() returns true, this function 00674 // will be called during the cull traversal to perform 00675 // any additional operations that should be performed at 00676 // cull time. This may include additional manipulation 00677 // of render state or additional visible/invisible 00678 // decisions, or any other arbitrary operation. 00679 // 00680 // By the time this function is called, the node has 00681 // already passed the bounding-volume test for the 00682 // viewing frustum, and the node's transform and state 00683 // have already been applied to the indicated 00684 // CullTraverserData object. 00685 // 00686 // The return value is true if this node should be 00687 // visible, or false if it should be culled. 00688 //////////////////////////////////////////////////////////////////// 00689 bool PandaNode:: 00690 cull_callback(CullTraverser *, CullTraverserData &) { 00691 return true; 00692 } 00693 00694 //////////////////////////////////////////////////////////////////// 00695 // Function: PandaNode::has_selective_visibility 00696 // Access: Public, Virtual 00697 // Description: Should be overridden by derived classes to return 00698 // true if this kind of node has some restrictions on 00699 // the set of children that should be rendered. Node 00700 // with this property include LODNodes, SwitchNodes, and 00701 // SequenceNodes. 00702 // 00703 // If this function returns true, 00704 // get_first_visible_child() and 00705 // get_next_visible_child() will be called to walk 00706 // through the list of children during cull, instead of 00707 // iterating through the entire list. This method is 00708 // called after cull_callback(), so cull_callback() may 00709 // be responsible for the decisions as to which children 00710 // are visible at the moment. 00711 //////////////////////////////////////////////////////////////////// 00712 bool PandaNode:: 00713 has_selective_visibility() const { 00714 return false; 00715 } 00716 00717 //////////////////////////////////////////////////////////////////// 00718 // Function: PandaNode::get_first_visible_child 00719 // Access: Public, Virtual 00720 // Description: Returns the index number of the first visible child 00721 // of this node, or a number >= get_num_children() if 00722 // there are no visible children of this node. This is 00723 // called during the cull traversal, but only if 00724 // has_selective_visibility() has already returned true. 00725 // See has_selective_visibility(). 00726 //////////////////////////////////////////////////////////////////// 00727 int PandaNode:: 00728 get_first_visible_child() const { 00729 return 0; 00730 } 00731 00732 //////////////////////////////////////////////////////////////////// 00733 // Function: PandaNode::get_next_visible_child 00734 // Access: Public, Virtual 00735 // Description: Returns the index number of the next visible child 00736 // of this node following the indicated child, or a 00737 // number >= get_num_children() if there are no more 00738 // visible children of this node. See 00739 // has_selective_visibility() and 00740 // get_first_visible_child(). 00741 //////////////////////////////////////////////////////////////////// 00742 int PandaNode:: 00743 get_next_visible_child(int n) const { 00744 return n + 1; 00745 } 00746 00747 //////////////////////////////////////////////////////////////////// 00748 // Function: PandaNode::has_single_child_visibility 00749 // Access: Public, Virtual 00750 // Description: Should be overridden by derived classes to return 00751 // true if this kind of node has the special property 00752 // that just one of its children is visible at any given 00753 // time, and furthermore that the particular visible 00754 // child can be determined without reference to any 00755 // external information (such as a camera). At present, 00756 // only SequenceNodes and SwitchNodes fall into this 00757 // category. 00758 // 00759 // If this function returns true, get_visible_child() 00760 // can be called to return the index of the 00761 // currently-visible child. 00762 //////////////////////////////////////////////////////////////////// 00763 bool PandaNode:: 00764 has_single_child_visibility() const { 00765 return false; 00766 } 00767 00768 //////////////////////////////////////////////////////////////////// 00769 // Function: PandaNode::get_visible_child 00770 // Access: Public, Virtual 00771 // Description: Returns the index number of the currently visible 00772 // child of this node. This is only meaningful if 00773 // has_single_child_visibility() has returned true. 00774 //////////////////////////////////////////////////////////////////// 00775 int PandaNode:: 00776 get_visible_child() const { 00777 return 0; 00778 } 00779 00780 //////////////////////////////////////////////////////////////////// 00781 // Function: PandaNode::copy_subgraph 00782 // Access: Published 00783 // Description: Allocates and returns a complete copy of this 00784 // PandaNode and the entire scene graph rooted at this 00785 // PandaNode. Some data may still be shared from the 00786 // original (e.g. vertex index tables), but nothing that 00787 // will impede normal use of the PandaNode. 00788 //////////////////////////////////////////////////////////////////// 00789 PT(PandaNode) PandaNode:: 00790 copy_subgraph() const { 00791 InstanceMap inst_map; 00792 return r_copy_subgraph(inst_map); 00793 } 00794 00795 //////////////////////////////////////////////////////////////////// 00796 // Function: PandaNode::find_child 00797 // Access: Published 00798 // Description: Returns the index of the indicated child node, if it 00799 // is a child, or -1 if it is not. 00800 //////////////////////////////////////////////////////////////////// 00801 int PandaNode:: 00802 find_child(PandaNode *node) const { 00803 nassertr(node != (PandaNode *)NULL, -1); 00804 CDReader cdata(_cycler); 00805 00806 // We have to search for the child by brute force, since we don't 00807 // know what sort index it was added as. 00808 Down::const_iterator di; 00809 for (di = cdata->_down.begin(); di != cdata->_down.end(); ++di) { 00810 if ((*di).get_child() == node) { 00811 return di - cdata->_down.begin(); 00812 } 00813 } 00814 00815 return -1; 00816 } 00817 00818 //////////////////////////////////////////////////////////////////// 00819 // Function: PandaNode::add_child 00820 // Access: Published 00821 // Description: Adds a new child to the node. The child is added in 00822 // the relative position indicated by sort; if all 00823 // children have the same sort index, the child is added 00824 // at the end. 00825 // 00826 // If the same child is added to a node more than once, 00827 // the previous instance is first removed. 00828 //////////////////////////////////////////////////////////////////// 00829 void PandaNode:: 00830 add_child(PandaNode *child_node, int sort) { 00831 nassertv(child_node != (PandaNode *)NULL); 00832 // Ensure the child_node is not deleted while we do this. 00833 PT(PandaNode) keep_child = child_node; 00834 remove_child(child_node); 00835 00836 CDWriter cdata(_cycler); 00837 CDWriter cdata_child(child_node->_cycler); 00838 00839 cdata->_down.insert(DownConnection(child_node, sort)); 00840 cdata_child->_up.insert(UpConnection(this)); 00841 00842 new_connection(this, child_node); 00843 00844 // Mark the bounding volumes stale. 00845 force_bound_stale(); 00846 00847 // Call callback hooks. 00848 children_changed(); 00849 child_node->parents_changed(); 00850 } 00851 00852 //////////////////////////////////////////////////////////////////// 00853 // Function: PandaNode::remove_child 00854 // Access: Published 00855 // Description: Removes the nth child from the node. 00856 //////////////////////////////////////////////////////////////////// 00857 void PandaNode:: 00858 remove_child(int n) { 00859 CDWriter cdata(_cycler); 00860 nassertv(n >= 0 && n < (int)cdata->_down.size()); 00861 00862 PT(PandaNode) child_node = cdata->_down[n].get_child(); 00863 CDWriter cdata_child(child_node->_cycler); 00864 00865 cdata->_down.erase(cdata->_down.begin() + n); 00866 int num_erased = cdata_child->_up.erase(UpConnection(this)); 00867 nassertv(num_erased == 1); 00868 00869 sever_connection(this, child_node); 00870 00871 // Mark the bounding volumes stale. 00872 force_bound_stale(); 00873 00874 // Call callback hooks. 00875 children_changed(); 00876 child_node->parents_changed(); 00877 } 00878 00879 //////////////////////////////////////////////////////////////////// 00880 // Function: PandaNode::remove_child 00881 // Access: Published 00882 // Description: Removes the indicated child from the node. Returns 00883 // true if the child was removed, false if it was not 00884 // already a child of the node. This will also 00885 // successfully remove the child if it had been stashed. 00886 //////////////////////////////////////////////////////////////////// 00887 bool PandaNode:: 00888 remove_child(PandaNode *child_node) { 00889 nassertr(child_node != (PandaNode *)NULL, false); 00890 // First, look for the parent in the child's up list, to ensure the 00891 // child is known. 00892 int parent_index = child_node->find_parent(this); 00893 if (parent_index < 0) { 00894 // Nope, no relation. 00895 return false; 00896 } 00897 00898 int child_index = find_child(child_node); 00899 if (child_index >= 0) { 00900 // The child exists; remove it. 00901 remove_child(child_index); 00902 return true; 00903 } 00904 00905 int stashed_index = find_stashed(child_node); 00906 if (stashed_index >= 0) { 00907 // The child has been stashed; remove it. 00908 remove_stashed(stashed_index); 00909 return true; 00910 } 00911 00912 // Never heard of this child. This shouldn't be possible, because 00913 // the parent was in the child's up list, above. Must be some 00914 // internal error. 00915 nassertr(false, false); 00916 return false; 00917 } 00918 00919 //////////////////////////////////////////////////////////////////// 00920 // Function: PandaNode::replace_child 00921 // Access: Published 00922 // Description: Searches for the orig_child node in the node's list 00923 // of children, and replaces it with the new_child 00924 // instead. Returns true if the replacement is made, or 00925 // false if the node is not a child. 00926 //////////////////////////////////////////////////////////////////// 00927 bool PandaNode:: 00928 replace_child(PandaNode *orig_child, PandaNode *new_child) { 00929 nassertr(orig_child != (PandaNode *)NULL, false); 00930 nassertr(new_child != (PandaNode *)NULL, false); 00931 // First, look for the parent in the child's up list, to ensure the 00932 // child is known. 00933 int parent_index = orig_child->find_parent(this); 00934 if (parent_index < 0) { 00935 // Nope, no relation. 00936 return false; 00937 } 00938 00939 if (orig_child == new_child) { 00940 // Trivial no-op. 00941 return true; 00942 } 00943 00944 // Don't let orig_child be destructed yet. 00945 PT(PandaNode) keep_orig_child = orig_child; 00946 00947 int child_index = find_child(orig_child); 00948 if (child_index >= 0) { 00949 // The child exists; replace it. 00950 CDWriter cdata(_cycler); 00951 DownConnection &down = cdata->_down[child_index]; 00952 nassertr(down.get_child() == orig_child, false); 00953 down.set_child(new_child); 00954 00955 } else { 00956 int stashed_index = find_stashed(orig_child); 00957 if (stashed_index >= 0) { 00958 // The child has been stashed; remove it. 00959 CDWriter cdata(_cycler); 00960 DownConnection &down = cdata->_stashed[stashed_index]; 00961 nassertr(down.get_child() == orig_child, false); 00962 down.set_child(new_child); 00963 00964 } else { 00965 // Never heard of this child. This shouldn't be possible, because 00966 // the parent was in the child's up list, above. Must be some 00967 // internal error. 00968 nassertr(false, false); 00969 return false; 00970 } 00971 } 00972 00973 // Now adjust the bookkeeping on both children. 00974 00975 CDWriter cdata_orig_child(orig_child->_cycler); 00976 CDWriter cdata_new_child(new_child->_cycler); 00977 00978 cdata_new_child->_up.insert(UpConnection(this)); 00979 int num_erased = cdata_orig_child->_up.erase(UpConnection(this)); 00980 nassertr(num_erased == 1, false); 00981 00982 sever_connection(this, orig_child); 00983 orig_child->parents_changed(); 00984 00985 new_connection(this, new_child); 00986 new_child->parents_changed(); 00987 00988 // Mark the bounding volumes stale. 00989 force_bound_stale(); 00990 children_changed(); 00991 00992 return true; 00993 } 00994 00995 00996 //////////////////////////////////////////////////////////////////// 00997 // Function: PandaNode::stash_child 00998 // Access: Published 00999 // Description: Stashes the indicated child node. This removes the 01000 // child from the list of active children and puts it on 01001 // a special list of stashed children. This child node 01002 // no longer contributes to the bounding volume of the 01003 // PandaNode, and is not visited in normal traversals. 01004 // It is invisible and uncollidable. The child may 01005 // later be restored by calling unstash_child(). 01006 //////////////////////////////////////////////////////////////////// 01007 void PandaNode:: 01008 stash_child(int child_index) { 01009 nassertv(child_index >= 0 && child_index < get_num_children()); 01010 PT(PandaNode) child_node = get_child(child_index); 01011 int sort = get_child_sort(child_index); 01012 01013 remove_child(child_index); 01014 01015 CDWriter cdata(_cycler); 01016 CDWriter cdata_child(child_node->_cycler); 01017 01018 cdata->_stashed.insert(DownConnection(child_node, sort)); 01019 cdata_child->_up.insert(UpConnection(this)); 01020 01021 new_connection(this, child_node); 01022 01023 // Mark the bounding volumes stale. 01024 force_bound_stale(); 01025 01026 // Call callback hooks. 01027 children_changed(); 01028 child_node->parents_changed(); 01029 } 01030 01031 //////////////////////////////////////////////////////////////////// 01032 // Function: PandaNode::unstash_child 01033 // Access: Published 01034 // Description: Returns the indicated stashed node to normal child 01035 // status. This removes the child from the list of 01036 // stashed children and puts it on the normal list of 01037 // active children. This child node once again 01038 // contributes to the bounding volume of the PandaNode, 01039 // and will be visited in normal traversals. It is 01040 // visible and collidable. 01041 //////////////////////////////////////////////////////////////////// 01042 void PandaNode:: 01043 unstash_child(int stashed_index) { 01044 nassertv(stashed_index >= 0 && stashed_index < get_num_stashed()); 01045 PT(PandaNode) child_node = get_stashed(stashed_index); 01046 int sort = get_stashed_sort(stashed_index); 01047 01048 remove_stashed(stashed_index); 01049 01050 CDWriter cdata(_cycler); 01051 CDWriter cdata_child(child_node->_cycler); 01052 01053 cdata->_down.insert(DownConnection(child_node, sort)); 01054 cdata_child->_up.insert(UpConnection(this)); 01055 01056 new_connection(this, child_node); 01057 01058 // Mark the bounding volumes stale. 01059 force_bound_stale(); 01060 01061 // Call callback hooks. 01062 children_changed(); 01063 child_node->parents_changed(); 01064 } 01065 01066 //////////////////////////////////////////////////////////////////// 01067 // Function: PandaNode::find_stashed 01068 // Access: Published 01069 // Description: Returns the index of the indicated stashed node, if 01070 // it is a stashed child, or -1 if it is not. 01071 //////////////////////////////////////////////////////////////////// 01072 int PandaNode:: 01073 find_stashed(PandaNode *node) const { 01074 CDReader cdata(_cycler); 01075 01076 // We have to search for the child by brute force, since we don't 01077 // know what sort index it was added as. 01078 Down::const_iterator di; 01079 for (di = cdata->_stashed.begin(); di != cdata->_stashed.end(); ++di) { 01080 if ((*di).get_child() == node) { 01081 return di - cdata->_stashed.begin(); 01082 } 01083 } 01084 01085 return -1; 01086 } 01087 01088 //////////////////////////////////////////////////////////////////// 01089 // Function: PandaNode::add_stashed 01090 // Access: Published 01091 // Description: Adds a new child to the node, directly as a stashed 01092 // child. The child is not added in the normal sense, 01093 // but will be revealed if unstash_child() is called on 01094 // it later. 01095 // 01096 // If the same child is added to a node more than once, 01097 // the previous instance is first removed. 01098 //////////////////////////////////////////////////////////////////// 01099 void PandaNode:: 01100 add_stashed(PandaNode *child_node, int sort) { 01101 // Ensure the child_node is not deleted while we do this. 01102 PT(PandaNode) keep_child = child_node; 01103 remove_child(child_node); 01104 01105 CDWriter cdata(_cycler); 01106 CDWriter cdata_child(child_node->_cycler); 01107 01108 cdata->_stashed.insert(DownConnection(child_node, sort)); 01109 cdata_child->_up.insert(UpConnection(this)); 01110 01111 new_connection(this, child_node); 01112 01113 // Call callback hooks. 01114 children_changed(); 01115 child_node->parents_changed(); 01116 } 01117 01118 //////////////////////////////////////////////////////////////////// 01119 // Function: PandaNode::remove_stashed 01120 // Access: Published 01121 // Description: Removes the nth stashed child from the node. 01122 //////////////////////////////////////////////////////////////////// 01123 void PandaNode:: 01124 remove_stashed(int n) { 01125 CDWriter cdata(_cycler); 01126 nassertv(n >= 0 && n < (int)cdata->_stashed.size()); 01127 01128 PT(PandaNode) child_node = cdata->_stashed[n].get_child(); 01129 CDWriter cdata_child(child_node->_cycler); 01130 01131 cdata->_stashed.erase(cdata->_stashed.begin() + n); 01132 int num_erased = cdata_child->_up.erase(UpConnection(this)); 01133 nassertv(num_erased == 1); 01134 01135 sever_connection(this, child_node); 01136 01137 // Mark the bounding volumes stale. 01138 force_bound_stale(); 01139 01140 // Call callback hooks. 01141 children_changed(); 01142 child_node->parents_changed(); 01143 } 01144 01145 //////////////////////////////////////////////////////////////////// 01146 // Function: PandaNode::remove_all_children 01147 // Access: Published 01148 // Description: Removes all the children from the node at once, 01149 // including stashed children. 01150 //////////////////////////////////////////////////////////////////// 01151 void PandaNode:: 01152 remove_all_children() { 01153 CDWriter cdata(_cycler); 01154 Down::iterator di; 01155 for (di = cdata->_down.begin(); di != cdata->_down.end(); ++di) { 01156 PT(PandaNode) child_node = (*di).get_child(); 01157 CDWriter cdata_child(child_node->_cycler); 01158 cdata_child->_up.erase(UpConnection(this)); 01159 01160 sever_connection(this, child_node); 01161 child_node->parents_changed(); 01162 } 01163 cdata->_down.clear(); 01164 01165 for (di = cdata->_stashed.begin(); di != cdata->_stashed.end(); ++di) { 01166 PT(PandaNode) child_node = (*di).get_child(); 01167 CDWriter cdata_child(child_node->_cycler); 01168 cdata_child->_up.erase(UpConnection(this)); 01169 01170 sever_connection(this, child_node); 01171 child_node->parents_changed(); 01172 } 01173 cdata->_stashed.clear(); 01174 01175 // Mark the bounding volumes stale. 01176 force_bound_stale(); 01177 children_changed(); 01178 } 01179 01180 //////////////////////////////////////////////////////////////////// 01181 // Function: PandaNode::steal_children 01182 // Access: Published 01183 // Description: Moves all the children from the other node onto this 01184 // node. 01185 //////////////////////////////////////////////////////////////////// 01186 void PandaNode:: 01187 steal_children(PandaNode *other) { 01188 if (other == this) { 01189 // Trivial. 01190 return; 01191 } 01192 01193 // We do this through the high-level interface for convenience. 01194 // This could begin to be a problem if we have a node with hundreds 01195 // of children to copy; this could break down the ov_set.insert() 01196 // method, which is an O(n^2) operation. If this happens, we should 01197 // rewrite this to do a simpler add_child() operation that involves 01198 // push_back() instead of insert(), and then sort the down list at 01199 // the end. 01200 01201 int num_children = other->get_num_children(); 01202 int i; 01203 for (i = 0; i < num_children; i++) { 01204 PandaNode *child_node = other->get_child(i); 01205 int sort = other->get_child_sort(i); 01206 add_child(child_node, sort); 01207 } 01208 int num_stashed = other->get_num_stashed(); 01209 for (i = 0; i < num_stashed; i++) { 01210 PandaNode *child_node = other->get_stashed(i); 01211 int sort = other->get_stashed_sort(i); 01212 add_stashed(child_node, sort); 01213 } 01214 01215 other->remove_all_children(); 01216 } 01217 01218 //////////////////////////////////////////////////////////////////// 01219 // Function: PandaNode::copy_children 01220 // Access: Published 01221 // Description: Makes another instance of all the children of the 01222 // other node, copying them to this node. 01223 //////////////////////////////////////////////////////////////////// 01224 void PandaNode:: 01225 copy_children(PandaNode *other) { 01226 if (other == this) { 01227 // Trivial. 01228 return; 01229 } 01230 int num_children = other->get_num_children(); 01231 int i; 01232 for (i = 0; i < num_children; i++) { 01233 PandaNode *child_node = other->get_child(i); 01234 int sort = other->get_child_sort(i); 01235 add_child(child_node, sort); 01236 } 01237 int num_stashed = other->get_num_stashed(); 01238 for (i = 0; i < num_stashed; i++) { 01239 PandaNode *child_node = other->get_stashed(i); 01240 int sort = other->get_stashed_sort(i); 01241 add_stashed(child_node, sort); 01242 } 01243 } 01244 01245 //////////////////////////////////////////////////////////////////// 01246 // Function: PandaNode::output 01247 // Access: Published, Virtual 01248 // Description: 01249 //////////////////////////////////////////////////////////////////// 01250 void PandaNode:: 01251 output(ostream &out) const { 01252 out << get_type() << " " << get_name(); 01253 } 01254 01255 //////////////////////////////////////////////////////////////////// 01256 // Function: PandaNode::write 01257 // Access: Published, Virtual 01258 // Description: 01259 //////////////////////////////////////////////////////////////////// 01260 void PandaNode:: 01261 write(ostream &out, int indent_level) const { 01262 indent(out, indent_level) << *this; 01263 CDReader cdata(_cycler); 01264 if (!cdata->_transform->is_identity()) { 01265 out << " " << *cdata->_transform; 01266 } 01267 if (!cdata->_state->is_empty()) { 01268 out << " " << *cdata->_state; 01269 } 01270 if (!cdata->_effects->is_empty()) { 01271 out << " " << *cdata->_effects; 01272 } 01273 out << "\n"; 01274 } 01275 01276 //////////////////////////////////////////////////////////////////// 01277 // Function: PandaNode::is_geom_node 01278 // Access: Public, Virtual 01279 // Description: A simple downcast check. Returns true if this kind 01280 // of node happens to inherit from GeomNode, false 01281 // otherwise. 01282 // 01283 // This is provided as a a faster alternative to calling 01284 // is_of_type(GeomNode::get_class_type()), since this 01285 // test is so important to rendering. 01286 //////////////////////////////////////////////////////////////////// 01287 bool PandaNode:: 01288 is_geom_node() const { 01289 return false; 01290 } 01291 01292 //////////////////////////////////////////////////////////////////// 01293 // Function: PandaNode::as_light 01294 // Access: Public, Virtual 01295 // Description: Cross-casts the node to a Light pointer, if it is one 01296 // of the four kinds of Light nodes, or returns NULL if 01297 // it is not. 01298 //////////////////////////////////////////////////////////////////// 01299 Light *PandaNode:: 01300 as_light() { 01301 return NULL; 01302 } 01303 01304 //////////////////////////////////////////////////////////////////// 01305 // Function: PandaNode::set_velocity 01306 // Access: Public, Virtual 01307 // Description: Indicates the instantaneous velocity of this node. 01308 // This function is meaningless to most kinds of nodes; 01309 // it is implemented only for CollisionNodes and is 01310 // intended to inform the collision system of velocity. 01311 // 01312 // It is defined at this level only as an abstract 01313 // interface to allow setting the velocity of a 01314 // collision node without having to link with, or know 01315 // anything about, the collision system. 01316 // 01317 // See CollisionNode::set_velocity(). 01318 //////////////////////////////////////////////////////////////////// 01319 void PandaNode:: 01320 set_velocity(const LVector3f &) { 01321 } 01322 01323 //////////////////////////////////////////////////////////////////// 01324 // Function: PandaNode::propagate_stale_bound 01325 // Access: Protected, Virtual 01326 // Description: Called by BoundedObject::mark_bound_stale(), this 01327 // should make sure that all bounding volumes that 01328 // depend on this one are marked stale also. 01329 //////////////////////////////////////////////////////////////////// 01330 void PandaNode:: 01331 propagate_stale_bound() { 01332 // Mark all of our parent nodes stale as well. 01333 CDWriter cdata(_cycler); 01334 Up::const_iterator ui; 01335 for (ui = cdata->_up.begin(); ui != cdata->_up.end(); ++ui) { 01336 PandaNode *parent_node = (*ui).get_parent(); 01337 parent_node->mark_bound_stale(); 01338 } 01339 } 01340 01341 //////////////////////////////////////////////////////////////////// 01342 // Function: PandaNode::recompute_bound 01343 // Access: Protected, Virtual 01344 // Description: Recomputes the dynamic bounding volume for this 01345 // object. The default behavior is the compute an empty 01346 // bounding volume; this may be overridden to extend it 01347 // to create a nonempty bounding volume. However, after 01348 // calling this function, it is guaranteed that the 01349 // _bound pointer will not be shared with any other 01350 // stage of the pipeline, and this new pointer is 01351 // returned. 01352 //////////////////////////////////////////////////////////////////// 01353 BoundingVolume *PandaNode:: 01354 recompute_bound() { 01355 // Get the internal bound before we do anything else, since the 01356 // is_bound_stale() flag may also apply to this. 01357 const BoundingVolume *internal_bound = &get_internal_bound(); 01358 01359 // Now, get ourselves a fresh, empty bounding volume. This will 01360 // reset the is_bound_stale() flag if it was set. 01361 BoundingVolume *bound = BoundedObject::recompute_bound(); 01362 nassertr(bound != (BoundingVolume*)NULL, bound); 01363 01364 // Also, recompute the net_collide_mask bits while we do this. 01365 CDWriter cdata(_cycler); 01366 cdata->_net_collide_mask = CollideMask::all_off(); 01367 01368 // Now actually compute the bounding volume by putting it around all 01369 // of our child bounding volumes. 01370 pvector<const BoundingVolume *> child_volumes; 01371 01372 // It goes around this node's internal bounding volume . . . 01373 child_volumes.push_back(internal_bound); 01374 01375 Down::const_iterator di; 01376 for (di = cdata->_down.begin(); di != cdata->_down.end(); ++di) { 01377 // . . . plus each node's external bounding volume. 01378 PandaNode *child = (*di).get_child(); 01379 const BoundingVolume &child_bound = child->get_bound(); 01380 child_volumes.push_back(&child_bound); 01381 cdata->_net_collide_mask |= child->get_net_collide_mask(); 01382 } 01383 01384 const BoundingVolume **child_begin = &child_volumes[0]; 01385 const BoundingVolume **child_end = child_begin + child_volumes.size(); 01386 01387 bool success = 01388 bound->around(child_begin, child_end); 01389 01390 #ifndef NDEBUG 01391 if (!success) { 01392 pgraph_cat.error() 01393 << "Unable to recompute bounding volume for " << *this << ":\n" 01394 << "Cannot put " << bound->get_type() << " around:\n"; 01395 for (int i = 0; i < (int)child_volumes.size(); i++) { 01396 pgraph_cat.error(false) 01397 << " " << *child_volumes[i] << "\n"; 01398 } 01399 } 01400 #endif 01401 01402 // Now, if we have a transform, apply it to the bounding volume we 01403 // just computed. 01404 const TransformState *transform = get_transform(); 01405 if (!transform->is_identity()) { 01406 GeometricBoundingVolume *gbv; 01407 DCAST_INTO_R(gbv, bound, bound); 01408 gbv->xform(transform->get_mat()); 01409 } 01410 01411 return bound; 01412 } 01413 01414 //////////////////////////////////////////////////////////////////// 01415 // Function: PandaNode::recompute_internal_bound 01416 // Access: Protected, Virtual 01417 // Description: Called when needed to recompute the node's 01418 // _internal_bound object. Nodes that contain anything 01419 // of substance should redefine this to do the right 01420 // thing. 01421 //////////////////////////////////////////////////////////////////// 01422 BoundingVolume *PandaNode:: 01423 recompute_internal_bound() { 01424 BoundingVolume *result = _internal_bound.recompute_bound(); 01425 return result; 01426 } 01427 01428 //////////////////////////////////////////////////////////////////// 01429 // Function: PandaNode::parents_changed 01430 // Access: Protected, Virtual 01431 // Description: Called after a scene graph update that either adds or 01432 // remove parents from this node, this just provides a 01433 // hook for derived PandaNode objects that need to 01434 // update themselves based on the set of parents the 01435 // node has. 01436 //////////////////////////////////////////////////////////////////// 01437 void PandaNode:: 01438 parents_changed() { 01439 } 01440 01441 //////////////////////////////////////////////////////////////////// 01442 // Function: PandaNode::children_changed 01443 // Access: Protected, Virtual 01444 // Description: Called after a scene graph update that either adds or 01445 // remove children from this node, this just provides a 01446 // hook for derived PandaNode objects that need to 01447 // update themselves based on the set of children the 01448 // node has. 01449 //////////////////////////////////////////////////////////////////// 01450 void PandaNode:: 01451 children_changed() { 01452 } 01453 01454 //////////////////////////////////////////////////////////////////// 01455 // Function: PandaNode::transform_changed 01456 // Access: Protected, Virtual 01457 // Description: Called after the node's transform has been changed 01458 // for any reason, this just provides a hook so derived 01459 // classes can do something special in this case. 01460 //////////////////////////////////////////////////////////////////// 01461 void PandaNode:: 01462 transform_changed() { 01463 } 01464 01465 //////////////////////////////////////////////////////////////////// 01466 // Function: PandaNode::r_copy_subgraph 01467 // Access: Protected, Virtual 01468 // Description: This is the recursive implementation of copy_subgraph(). 01469 // It returns a copy of the entire subgraph rooted at 01470 // this node. 01471 // 01472 // Note that it includes the parameter inst_map, which 01473 // is a map type, and is not (and cannot be) exported 01474 // from PANDA.DLL. Thus, any derivative of PandaNode 01475 // that is not also a member of PANDA.DLL *cannot* 01476 // access this map. 01477 //////////////////////////////////////////////////////////////////// 01478 PT(PandaNode) PandaNode:: 01479 r_copy_subgraph(PandaNode::InstanceMap &inst_map) const { 01480 PT(PandaNode) copy = make_copy(); 01481 nassertr(copy != (PandaNode *)NULL, NULL); 01482 if (copy->get_type() != get_type()) { 01483 pgraph_cat.warning() 01484 << "Don't know how to copy nodes of type " << get_type() << "\n"; 01485 } 01486 01487 copy->r_copy_children(this, inst_map); 01488 return copy; 01489 } 01490 01491 //////////////////////////////////////////////////////////////////// 01492 // Function: PandaNode::r_copy_children 01493 // Access: Protected, Virtual 01494 // Description: This is called by r_copy_subgraph(); the copy has 01495 // already been made of this particular node (and this 01496 // is the copy); this function's job is to copy all of 01497 // the children from the original. 01498 // 01499 // Note that it includes the parameter inst_map, which 01500 // is a map type, and is not (and cannot be) exported 01501 // from PANDA.DLL. Thus, any derivative of PandaNode 01502 // that is not also a member of PANDA.DLL *cannot* 01503 // access this map, and probably should not even 01504 // override this function. 01505 //////////////////////////////////////////////////////////////////// 01506 void PandaNode:: 01507 r_copy_children(const PandaNode *from, PandaNode::InstanceMap &inst_map) { 01508 CDReader from_cdata(from->_cycler); 01509 Down::const_iterator di; 01510 for (di = from_cdata->_down.begin(); di != from_cdata->_down.end(); ++di) { 01511 int sort = (*di).get_sort(); 01512 PandaNode *source_child = (*di).get_child(); 01513 PT(PandaNode) dest_child; 01514 01515 // Check to see if we have already copied this child. If we 01516 // have, use the copy. In this way, a subgraph that contains 01517 // instances will be correctly duplicated into another subgraph 01518 // that also contains its own instances. 01519 InstanceMap::const_iterator ci; 01520 ci = inst_map.find(source_child); 01521 if (ci != inst_map.end()) { 01522 dest_child = (*ci).second; 01523 } else { 01524 dest_child = source_child->r_copy_subgraph(inst_map); 01525 inst_map[source_child] = dest_child; 01526 } 01527 01528 add_child(dest_child, sort); 01529 } 01530 } 01531 01532 //////////////////////////////////////////////////////////////////// 01533 // Function: PandaNode::attach 01534 // Access: Private, Static 01535 // Description: Creates a new parent-child relationship, and returns 01536 // the new NodePathComponent. If the child was already 01537 // attached to the indicated parent, repositions it and 01538 // returns the original NodePathComponent. 01539 //////////////////////////////////////////////////////////////////// 01540 PT(NodePathComponent) PandaNode:: 01541 attach(NodePathComponent *parent, PandaNode *child_node, int sort) { 01542 nassertr(parent != (NodePathComponent *)NULL, (NodePathComponent *)NULL); 01543 01544 // See if the child was already attached to the parent. If it was, 01545 // we'll use that same NodePathComponent. 01546 PT(NodePathComponent) child = get_component(parent, child_node); 01547 01548 if (child == (NodePathComponent *)NULL) { 01549 // The child was not already attached to the parent, so get a new 01550 // component. 01551 child = get_top_component(child_node, true); 01552 } 01553 01554 reparent(parent, child, sort); 01555 return child; 01556 } 01557 01558 //////////////////////////////////////////////////////////////////// 01559 // Function: PandaNode::detach 01560 // Access: Private, Static 01561 // Description: Breaks a parent-child relationship. 01562 //////////////////////////////////////////////////////////////////// 01563 void PandaNode:: 01564 detach(NodePathComponent *child) { 01565 nassertv(child != (NodePathComponent *)NULL); 01566 nassertv(!child->is_top_node()); 01567 01568 PT(PandaNode) child_node = child->get_node(); 01569 PT(PandaNode) parent_node = child->get_next()->get_node(); 01570 01571 // We should actually have a parent-child relationship, since this 01572 // came from a NodePathComponent that ought to know about this 01573 // sort of thing. 01574 nassertv(child_node->find_parent(parent_node) >= 0); 01575 01576 CDWriter cdata_child(child_node->_cycler); 01577 CDWriter cdata_parent(parent_node->_cycler); 01578 01579 // Now look for the child and break the actual connection. 01580 01581 // First, look for and remove the parent node from the child's up 01582 // list. 01583 int num_erased = cdata_child->_up.erase(UpConnection(parent_node)); 01584 nassertv(num_erased == 1); 01585 01586 // Now, look for and remove the child node from the parent's down 01587 // list. We also check in the stashed list, in case the child node 01588 // has been stashed. 01589 Down::iterator di; 01590 bool found = false; 01591 for (di = cdata_parent->_down.begin(); 01592 di != cdata_parent->_down.end() && !found; 01593 ++di) { 01594 if ((*di).get_child() == child_node) { 01595 cdata_parent->_down.erase(di); 01596 found = true; 01597 } 01598 } 01599 for (di = cdata_parent->_stashed.begin(); 01600 di != cdata_parent->_stashed.end() && !found; 01601 ++di) { 01602 if ((*di).get_child() == child_node) { 01603 cdata_parent->_stashed.erase(di); 01604 found = true; 01605 } 01606 } 01607 nassertv(found); 01608 01609 // Finally, break the NodePathComponent connection. 01610 sever_connection(parent_node, child_node); 01611 01612 // Mark the bounding volumes stale. 01613 parent_node->force_bound_stale(); 01614 01615 // Call callback hooks. 01616 parent_node->children_changed(); 01617 child_node->parents_changed(); 01618 } 01619 01620 //////////////////////////////////////////////////////////////////// 01621 // Function: PandaNode::reparent 01622 // Access: Private, Static 01623 // Description: Switches a node from one parent to another. 01624 //////////////////////////////////////////////////////////////////// 01625 void PandaNode:: 01626 reparent(NodePathComponent *new_parent, NodePathComponent *child, int sort) { 01627 nassertv(new_parent != (NodePathComponent *)NULL); 01628 nassertv(child != (NodePathComponent *)NULL); 01629 01630 if (!child->is_top_node()) { 01631 detach(child); 01632 } 01633 01634 // Adjust the NodePathComponents. 01635 child->set_next(new_parent); 01636 01637 PandaNode *child_node = child->get_node(); 01638 PandaNode *parent_node = new_parent->get_node(); 01639 01640 // Now reattach at the indicated sort position. 01641 CDWriter cdata_parent(parent_node->_cycler); 01642 CDWriter cdata_child(child_node->_cycler); 01643 01644 cdata_parent->_down.insert(DownConnection(child_node, sort)); 01645 cdata_child->_up.insert(UpConnection(parent_node)); 01646 01647 cdata_child->_paths.insert(child); 01648 child_node->fix_path_lengths(cdata_child); 01649 01650 // Mark the bounding volumes stale. 01651 parent_node->force_bound_stale(); 01652 01653 // Call callback hooks. 01654 parent_node->children_changed(); 01655 child_node->parents_changed(); 01656 } 01657 01658 //////////////////////////////////////////////////////////////////// 01659 // Function: PandaNode::get_component 01660 // Access: Private, Static 01661 // Description: Returns the NodePathComponent based on the indicated 01662 // child of the given parent, or NULL if there is no 01663 // such parent-child relationship. 01664 //////////////////////////////////////////////////////////////////// 01665 PT(NodePathComponent) PandaNode:: 01666 get_component(NodePathComponent *parent, PandaNode *child_node) { 01667 nassertr(parent != (NodePathComponent *)NULL, (NodePathComponent *)NULL); 01668 PandaNode *parent_node = parent->get_node(); 01669 01670 { 01671 CDReader cdata_child(child_node->_cycler); 01672 01673 // First, walk through the list of NodePathComponents we already 01674 // have on the child, looking for one that already exists, 01675 // referencing the indicated parent component. 01676 Paths::const_iterator pi; 01677 for (pi = cdata_child->_paths.begin(); 01678 pi != cdata_child->_paths.end(); 01679 ++pi) { 01680 if ((*pi)->get_next() == parent) { 01681 // If we already have such a component, just return it. 01682 return (*pi); 01683 } 01684 } 01685 } 01686 01687 // We don't already have a NodePathComponent referring to this 01688 // parent-child relationship. Are they actually related? 01689 int child_index = child_node->find_parent(parent_node); 01690 if (child_index >= 0) { 01691 // They are. Create and return a new one. 01692 PT(NodePathComponent) child = 01693 new NodePathComponent(child_node, parent); 01694 CDWriter cdata_child(child_node->_cycler); 01695 cdata_child->_paths.insert(child); 01696 return child; 01697 } else { 01698 // They aren't related. Return NULL. 01699 return NULL; 01700 } 01701 } 01702 01703 //////////////////////////////////////////////////////////////////// 01704 // Function: PandaNode::get_top_component 01705 // Access: Private, Static 01706 // Description: Returns a NodePathComponent referencing the 01707 // indicated node as a singleton. It is invalid to call 01708 // this for a node that has parents, unless you are 01709 // about to create a new instance (and immediately 01710 // reconnect the NodePathComponent elsewhere). 01711 // 01712 // If force is true, this will always return something, 01713 // even if it needs to create a new top component; 01714 // otherwise, if force is false, it will return NULL if 01715 // there is not already a top component available. 01716 //////////////////////////////////////////////////////////////////// 01717 PT(NodePathComponent) PandaNode:: 01718 get_top_component(PandaNode *child_node, bool force) { 01719 { 01720 CDReader cdata_child(child_node->_cycler); 01721 01722 // Walk through the list of NodePathComponents we already have on 01723 // the child, looking for one that already exists as a top node. 01724 Paths::const_iterator pi; 01725 for (pi = cdata_child->_paths.begin(); 01726 pi != cdata_child->_paths.end(); 01727 ++pi) { 01728 if ((*pi)->is_top_node()) { 01729 // If we already have such a component, just return it. 01730 return (*pi); 01731 } 01732 } 01733 } 01734 01735 if (!force) { 01736 // If we don't care to force the point, return NULL to indicate 01737 // there's not already a top component. 01738 return NULL; 01739 } 01740 01741 // We don't already have such a NodePathComponent; create and 01742 // return a new one. 01743 PT(NodePathComponent) child = 01744 new NodePathComponent(child_node, (NodePathComponent *)NULL); 01745 CDWriter cdata_child(child_node->_cycler); 01746 cdata_child->_paths.insert(child); 01747 01748 return child; 01749 } 01750 01751 //////////////////////////////////////////////////////////////////// 01752 // Function: PandaNode::get_generic_component 01753 // Access: Private 01754 // Description: Returns a NodePathComponent referencing this node as 01755 // a path from the root. 01756 // 01757 // Unless accept_ambiguity is true, it is only valid to 01758 // call this if there is an unambiguous path from the 01759 // root; otherwise, a warning will be issued and one 01760 // path will be chosen arbitrarily. 01761 //////////////////////////////////////////////////////////////////// 01762 PT(NodePathComponent) PandaNode:: 01763 get_generic_component(bool accept_ambiguity) { 01764 bool ambiguity_detected = false; 01765 PT(NodePathComponent) result = 01766 r_get_generic_component(accept_ambiguity, ambiguity_detected); 01767 01768 if (!accept_ambiguity && ambiguity_detected) { 01769 pgraph_cat.warning() 01770 << "Chose: " << *result << "\n"; 01771 nassertr(!unambiguous_graph, result); 01772 } 01773 01774 return result; 01775 } 01776 01777 //////////////////////////////////////////////////////////////////// 01778 // Function: PandaNode::r_get_generic_component 01779 // Access: Private 01780 // Description: The recursive implementation of 01781 // get_generic_component, this simply sets the flag when 01782 // the ambiguity is detected (so we can report the 01783 // bottom node that started the ambiguous search). 01784 //////////////////////////////////////////////////////////////////// 01785 PT(NodePathComponent) PandaNode:: 01786 r_get_generic_component(bool accept_ambiguity, bool &ambiguity_detected) { 01787 int num_parents = get_num_parents(); 01788 if (num_parents == 0) { 01789 // No parents; no ambiguity. This is the root. 01790 return get_top_component(this, true); 01791 } 01792 01793 PT(NodePathComponent) result; 01794 if (num_parents == 1) { 01795 // Only one parent; no ambiguity. 01796 PT(NodePathComponent) parent = 01797 get_parent(0)->r_get_generic_component(accept_ambiguity, ambiguity_detected); 01798 result = get_component(parent, this); 01799 01800 } else { 01801 // Oops, multiple parents; the NodePath is ambiguous. 01802 if (!accept_ambiguity) { 01803 pgraph_cat.warning() 01804 << *this << " has " << num_parents 01805 << " parents; choosing arbitrary path to root.\n"; 01806 } 01807 ambiguity_detected = true; 01808 PT(NodePathComponent) parent = 01809 get_parent(0)->r_get_generic_component(accept_ambiguity, ambiguity_detected); 01810 result = get_component(parent, this); 01811 } 01812 01813 return result; 01814 } 01815 01816 //////////////////////////////////////////////////////////////////// 01817 // Function: PandaNode::delete_component 01818 // Access: Private 01819 // Description: Removes a NodePathComponent from the set prior to 01820 // its deletion. This should only be called by the 01821 // NodePathComponent destructor. 01822 //////////////////////////////////////////////////////////////////// 01823 void PandaNode:: 01824 delete_component(NodePathComponent *component) { 01825 // We have to remove the component from all of the pipeline stages, 01826 // not just the current one. 01827 int max_num_erased = 0; 01828 01829 int num_stages = _cycler.get_num_stages(); 01830 for (int i = 0; i < num_stages; i++) { 01831 if (_cycler.is_stage_unique(i)) { 01832 CData *cdata = _cycler.write_stage(i); 01833 int num_erased = cdata->_paths.erase(component); 01834 max_num_erased = max(max_num_erased, num_erased); 01835 _cycler.release_write_stage(i, cdata); 01836 } 01837 } 01838 01839 // This may legitimately be zero if we are deleting a collapsed NodePath. 01840 // nassertv(max_num_erased == 1); 01841 } 01842 01843 //////////////////////////////////////////////////////////////////// 01844 // Function: PandaNode::sever_connection 01845 // Access: Private, Static 01846 // Description: This is called internally when a parent-child 01847 // connection is broken to update the NodePathComponents 01848 // that reflected this connection. 01849 // 01850 // It severs any NodePathComponents on the child node 01851 // that reference the indicated parent node. If the 01852 // child node has additional parents, chooses one of 01853 // them arbitrarily instead. Collapses together 01854 // instances below this node that used to differentiate 01855 // on some instance above the old parent. 01856 //////////////////////////////////////////////////////////////////// 01857 void PandaNode:: 01858 sever_connection(PandaNode *parent_node, PandaNode *child_node) { 01859 CDWriter cdata_child(child_node->_cycler); 01860 PT(NodePathComponent) collapsed = (NodePathComponent *)NULL; 01861 01862 Paths::iterator pi; 01863 pi = cdata_child->_paths.begin(); 01864 while (pi != cdata_child->_paths.end()) { 01865 Paths::iterator pnext = pi; 01866 ++pnext; 01867 if (!(*pi)->is_top_node() && 01868 (*pi)->get_next()->get_node() == parent_node) { 01869 if (collapsed == (NodePathComponent *)NULL) { 01870 01871 // This is the first component we've found that references 01872 // this node. Should we sever it or reattach it? 01873 if (child_node->get_num_parents() == 0) { 01874 // If the node no longer has any parents, all of its paths will be 01875 // severed here. Collapse them all with the existing top 01876 // component if there is one. 01877 collapsed = get_top_component(child_node, false); 01878 01879 } else { 01880 // If the node still has one parent, all of its paths that 01881 // referenced the old parent will be combined with the 01882 // remaining parent. If there are multiple parents, choose 01883 // the first parent arbitrarily to combine with, and don't 01884 // complain if there's ambiguity. 01885 collapsed = child_node->get_generic_component(true); 01886 } 01887 01888 if (collapsed == (NodePathComponent *)NULL) { 01889 // Sever the component here; there's nothing to attach it 01890 // to. 01891 (*pi)->set_top_node(); 01892 collapsed = (*pi); 01893 01894 } else { 01895 // Collapse the new component with the pre-existing 01896 // component. 01897 (*pi)->collapse_with(collapsed); 01898 cdata_child->_paths.erase(pi); 01899 } 01900 01901 } else { 01902 // This is the second (or later) component we've found that 01903 // references this node. We should collapse it with the first 01904 // one. 01905 (*pi)->collapse_with(collapsed); 01906 cdata_child->_paths.erase(pi); 01907 } 01908 } 01909 pi = pnext; 01910 } 01911 child_node->fix_path_lengths(cdata_child); 01912 } 01913 01914 //////////////////////////////////////////////////////////////////// 01915 // Function: PandaNode::new_connection 01916 // Access: Private, Static 01917 // Description: This is called internally when a parent-child 01918 // connection is establshed to update the 01919 // NodePathComponents that might be involved. 01920 // 01921 // It adjusts any NodePathComponents the child has that 01922 // reference the child as a top node. Any other 01923 // components we can leave alone, because we are making 01924 // a new instance of the child. 01925 //////////////////////////////////////////////////////////////////// 01926 void PandaNode:: 01927 new_connection(PandaNode *parent_node, PandaNode *child_node) { 01928 CDWriter cdata_child(child_node->_cycler); 01929 01930 Paths::iterator pi; 01931 for (pi = cdata_child->_paths.begin(); 01932 pi != cdata_child->_paths.end(); 01933 ++pi) { 01934 if ((*pi)->is_top_node()) { 01935 (*pi)->set_next(parent_node->get_generic_component(false)); 01936 } 01937 } 01938 child_node->fix_path_lengths(cdata_child); 01939 } 01940 01941 //////////////////////////////////////////////////////////////////// 01942 // Function: PandaNode::fix_path_lengths 01943 // Access: Private 01944 // Description: Recursively fixes the _length member of each 01945 // NodePathComponent at this level and below, after an 01946 // add or delete child operation that might have messed 01947 // these up. 01948 //////////////////////////////////////////////////////////////////// 01949 void PandaNode:: 01950 fix_path_lengths(const CData *cdata) { 01951 bool any_wrong = false; 01952 01953 Paths::const_iterator pi; 01954 for (pi = cdata->_paths.begin(); pi != cdata->_paths.end(); ++pi) { 01955 if ((*pi)->fix_length()) { 01956 any_wrong = true; 01957 } 01958 } 01959 01960 // If any paths were updated, we have to recurse on all of our 01961 // children, since any one of those paths might be shared by any of 01962 // our child nodes. 01963 if (any_wrong) { 01964 Down::const_iterator di; 01965 for (di = cdata->_down.begin(); di != cdata->_down.end(); ++di) { 01966 PandaNode *child_node = (*di).get_child(); 01967 CDReader cdata_child(child_node->_cycler); 01968 child_node->fix_path_lengths(cdata_child); 01969 } 01970 for (di = cdata->_stashed.begin(); di != cdata->_stashed.end(); ++di) { 01971 PandaNode *child_node = (*di).get_child(); 01972 CDReader cdata_child(child_node->_cycler); 01973 child_node->fix_path_lengths(cdata_child); 01974 } 01975 } 01976 } 01977 01978 //////////////////////////////////////////////////////////////////// 01979 // Function: PandaNode::r_list_descendants 01980 // Access: Private 01981 // Description: The recursive implementation of ls(). 01982 //////////////////////////////////////////////////////////////////// 01983 void PandaNode:: 01984 r_list_descendants(ostream &out, int indent_level) const { 01985 CDReader cdata(_cycler); 01986 indent(out, indent_level) << *this; 01987 if (!cdata->_transform->is_identity()) { 01988 out << " " << *cdata->_transform; 01989 } 01990 if (!cdata->_state->is_empty()) { 01991 out << " " << *cdata->_state; 01992 } 01993 if (!cdata->_effects->is_empty()) { 01994 out << " " << *cdata->_effects; 01995 } 01996 out << "\n"; 01997 01998 Down::const_iterator di; 01999 for (di = cdata->_down.begin(); di != cdata->_down.end(); ++di) { 02000 (*di).get_child()->r_list_descendants(out, indent_level + 2); 02001 } 02002 02003 // Also report the number of stashed nodes at this level. 02004 int num_stashed = get_num_stashed(); 02005 if (num_stashed != 0) { 02006 indent(out, indent_level) << "(" << num_stashed << " stashed)\n"; 02007 } 02008 } 02009 02010 //////////////////////////////////////////////////////////////////// 02011 // Function: PandaNode::register_with_read_factory 02012 // Access: Public, Static 02013 // Description: Tells the BamReader how to create objects of type 02014 // PandaNode. 02015 //////////////////////////////////////////////////////////////////// 02016 void PandaNode:: 02017 register_with_read_factory() { 02018 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 02019 } 02020 02021 //////////////////////////////////////////////////////////////////// 02022 // Function: PandaNode::write_datagram 02023 // Access: Public, Virtual 02024 // Description: Writes the contents of this object to the datagram 02025 // for shipping out to a Bam file. 02026 //////////////////////////////////////////////////////////////////// 02027 void PandaNode:: 02028 write_datagram(BamWriter *manager, Datagram &dg) { 02029 TypedWritable::write_datagram(manager, dg); 02030 dg.add_string(get_name()); 02031 02032 manager->write_cdata(dg, _cycler); 02033 } 02034 02035 //////////////////////////////////////////////////////////////////// 02036 // Function: PandaNode::make_from_bam 02037 // Access: Protected, Static 02038 // Description: This function is called by the BamReader's factory 02039 // when a new object of type PandaNode is encountered 02040 // in the Bam file. It should create the PandaNode 02041 // and extract its information from the file. 02042 //////////////////////////////////////////////////////////////////// 02043 TypedWritable *PandaNode:: 02044 make_from_bam(const FactoryParams ¶ms) { 02045 PandaNode *node = new PandaNode(""); 02046 DatagramIterator scan; 02047 BamReader *manager; 02048 02049 parse_params(params, scan, manager); 02050 node->fillin(scan, manager); 02051 02052 return node; 02053 } 02054 02055 //////////////////////////////////////////////////////////////////// 02056 // Function: PandaNode::fillin 02057 // Access: Protected 02058 // Description: This internal function is called by make_from_bam to 02059 // read in all of the relevant data from the BamFile for 02060 // the new PandaNode. 02061 //////////////////////////////////////////////////////////////////// 02062 void PandaNode:: 02063 fillin(DatagramIterator &scan, BamReader *manager) { 02064 TypedWritable::fillin(scan, manager); 02065 02066 string name = scan.get_string(); 02067 set_name(name); 02068 02069 manager->read_cdata(scan, _cycler); 02070 }