Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/pgraph/pandaNode.cxx

Go to the documentation of this file.
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 &copy) :
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 &copy) {
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 &params) {
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 }

Generated on Fri May 2 00:42:08 2003 for Panda by doxygen1.3