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

panda/src/chan/partGroup.cxx

Go to the documentation of this file.
00001 // Filename: partGroup.cxx
00002 // Created by:  drose (22Feb99)
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 
00020 #include "partGroup.h"
00021 #include "animGroup.h"
00022 #include "config_chan.h"
00023 
00024 #include <indent.h>
00025 #include <datagram.h>
00026 #include <datagramIterator.h>
00027 #include <bamReader.h>
00028 #include <bamWriter.h>
00029 
00030 #include <algorithm>
00031 
00032 TypeHandle PartGroup::_type_handle;
00033 
00034 ////////////////////////////////////////////////////////////////////
00035 //     Function: PartGroup::Constructor
00036 //       Access: Public
00037 //  Description: Creates the PartGroup, and adds it to the indicated
00038 //               parent.  The only way to delete it subsequently is to
00039 //               delete the entire hierarchy.
00040 ////////////////////////////////////////////////////////////////////
00041 PartGroup::
00042 PartGroup(PartGroup *parent, const string &name) : Namable(name) {
00043   nassertv(parent != NULL);
00044 
00045   parent->_children.push_back(this);
00046 }
00047 
00048 ////////////////////////////////////////////////////////////////////
00049 //     Function: PartGroup::Destructor
00050 //       Access: Public
00051 //  Description:
00052 ////////////////////////////////////////////////////////////////////
00053 PartGroup::
00054 ~PartGroup() {
00055 }
00056 
00057 ////////////////////////////////////////////////////////////////////
00058 //     Function: PartGroup::make_copy
00059 //       Access: Public, Virtual
00060 //  Description: Allocates and returns a new copy of the node.
00061 //               Children are not copied, but see copy_subgraph().
00062 ////////////////////////////////////////////////////////////////////
00063 PartGroup *PartGroup::
00064 make_copy() const {
00065   return new PartGroup(*this);
00066 }
00067 
00068 ////////////////////////////////////////////////////////////////////
00069 //     Function: PartGroup::copy_subgraph
00070 //       Access: Public
00071 //  Description: Allocates and returns a new copy of this node and of
00072 //               all of its children.
00073 ////////////////////////////////////////////////////////////////////
00074 PartGroup *PartGroup::
00075 copy_subgraph() const {
00076   PartGroup *root = make_copy();
00077 
00078   if (root->get_type() != get_type()) {
00079     chan_cat.warning()
00080       << "Don't know how to copy " << get_type() << "\n";
00081   }
00082 
00083   Children::const_iterator ci;
00084   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00085     PartGroup *child = (*ci)->copy_subgraph();
00086     root->_children.push_back(child);
00087   }
00088 
00089   return root;
00090 }
00091 
00092 
00093 ////////////////////////////////////////////////////////////////////
00094 //     Function: PartGroup::get_num_children
00095 //       Access: Public
00096 //  Description: Returns the number of child nodes of the group.
00097 ////////////////////////////////////////////////////////////////////
00098 int PartGroup::
00099 get_num_children() const {
00100   return _children.size();
00101 }
00102 
00103 
00104 ////////////////////////////////////////////////////////////////////
00105 //     Function: PartGroup::get_child
00106 //       Access: Public
00107 //  Description: Returns the nth child of the group.
00108 ////////////////////////////////////////////////////////////////////
00109 PartGroup *PartGroup::
00110 get_child(int n) const {
00111   nassertr(n >= 0 && n < (int)_children.size(), NULL);
00112   return _children[n];
00113 }
00114 
00115 ////////////////////////////////////////////////////////////////////
00116 //     Function: PartGroup::find_child
00117 //       Access: Public
00118 //  Description: Returns the first descendant found with the indicated
00119 //               name, or NULL if no such descendant exists.
00120 ////////////////////////////////////////////////////////////////////
00121 PartGroup *PartGroup::
00122 find_child(const string &name) const {
00123   Children::const_iterator ci;
00124   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00125     PartGroup *child = (*ci);
00126     if (child->get_name() == name) {
00127       return child;
00128     }
00129     PartGroup *result = child->find_child(name);
00130     if (result != (PartGroup *)NULL) {
00131       return result;
00132     }
00133   }
00134 
00135   return (PartGroup *)NULL;
00136 }
00137 
00138 ////////////////////////////////////////////////////////////////////
00139 //     Function: PartGroup::get_value_type
00140 //       Access: Public, Virtual
00141 //  Description: Returns the TypeHandle associated with the ValueType
00142 //               we are concerned with.  This is provided to allow a
00143 //               bit of run-time checking that joints and channels are
00144 //               matching properly in type.
00145 ////////////////////////////////////////////////////////////////////
00146 TypeHandle PartGroup::
00147 get_value_type() const {
00148   return TypeHandle::none();
00149 }
00150 
00151 
00152 // An STL object to sort a list of children into alphabetical order.
00153 class PartGroupAlphabeticalOrder {
00154 public:
00155   bool operator()(const PT(PartGroup) &a, const PT(PartGroup) &b) const {
00156     return a->get_name() < b->get_name();
00157   }
00158 };
00159 
00160 ////////////////////////////////////////////////////////////////////
00161 //     Function: PartGroup::sort_descendants
00162 //       Access: Public
00163 //  Description: Sorts the children nodes at each level of the
00164 //               hierarchy into alphabetical order.  This should be
00165 //               done after creating the hierarchy, to guarantee that
00166 //               the correct names will match up together when the
00167 //               AnimBundle is later bound to a PlayerRoot.
00168 ////////////////////////////////////////////////////////////////////
00169 void PartGroup::
00170 sort_descendants() {
00171   sort(_children.begin(), _children.end(), PartGroupAlphabeticalOrder());
00172 
00173   Children::iterator ci;
00174   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00175     (*ci)->sort_descendants();
00176   }
00177 }
00178 
00179 ////////////////////////////////////////////////////////////////////
00180 //     Function: PartGroup::check_hierarchy
00181 //       Access: Public
00182 //  Description: Walks the part hierarchy in tandem with the indicated
00183 //               anim hierarchy, and returns true if the hierarchies
00184 //               match, false otherwise.
00185 //
00186 //               If hierarchy_match_flags is 0, only an exact match is
00187 //               accepted; otherwise, it may contain a union of
00188 //               PartGroup::HierarchyMatchFlags values indicating
00189 //               conditions that will be tolerated (but warnings will
00190 //               still be issued).
00191 //
00192 //               If there is a discrepancy, it is reported to the
00193 //               indicated output stream, if it is non-null.
00194 ////////////////////////////////////////////////////////////////////
00195 bool PartGroup::
00196 check_hierarchy(const AnimGroup *anim, const PartGroup *,
00197                 int hierarchy_match_flags) const {
00198   if (anim->get_value_type() != get_value_type()) {
00199     if (chan_cat.is_error()) {
00200       chan_cat.error()
00201         << "Part " << get_name() << " expects type " << get_value_type()
00202         << " while matching anim node has type " << anim->get_value_type()
00203         << ".\n";
00204     }
00205     return false;
00206   }
00207 
00208   if (chan_cat.is_info()) {
00209     // If we're issuing error messages, check ahead of time if the set
00210     // of children agrees.  If it does not, we'll write a one-line
00211     // warning, and then list the set of children that differ.
00212 
00213     bool match = true;
00214     if (anim->get_num_children() != get_num_children()) {
00215       chan_cat.info()
00216         << "Part " << get_name() << " has " << get_num_children()
00217         << " children, while matching anim node has "
00218         << anim->get_num_children() << ":\n";
00219       match = false;
00220 
00221     } else {
00222       for (int i = 0; match && i < get_num_children(); i++) {
00223         PartGroup *pc = get_child(i);
00224         AnimGroup *ac = anim->get_child(i);
00225 
00226         match = (pc->get_name() == ac->get_name());
00227       }
00228       if (!match) {
00229         chan_cat.info()
00230           << "Part " << get_name() << " has a different set of children "
00231           << " than matching anim node:\n";
00232       }
00233     }
00234     if (!match) {
00235       int i = 0, j = 0;
00236       while (i < get_num_children() &&
00237              j < anim->get_num_children()) {
00238         PartGroup *pc = get_child(i);
00239         AnimGroup *ac = anim->get_child(j);
00240 
00241         if (pc->get_name() < ac->get_name()) {
00242           chan_cat.info()
00243             << "  part has " << pc->get_name()
00244             << ", not in anim.\n";
00245           i++;
00246         } else if (ac->get_name() < pc->get_name()) {
00247           chan_cat.info()
00248             << "  anim has " << ac->get_name()
00249             << ", not in part.\n";
00250           j++;
00251         } else {
00252           //      chan_cat.info() << "  part and anim both have " << ac->get_name() << "\n";
00253           i++;
00254           j++;
00255         }
00256       }
00257 
00258       while (i < get_num_children()) {
00259         PartGroup *pc = get_child(i);
00260         chan_cat.info()
00261           << "  part has " << pc->get_name()
00262           << ", not in anim.\n";
00263         i++;
00264       }
00265 
00266       while (j < anim->get_num_children()) {
00267         AnimGroup *ac = anim->get_child(j);
00268         chan_cat.info()
00269           << "  anim has " << ac->get_name()
00270           << ", not in part.\n";
00271         j++;
00272       }
00273     }
00274   }
00275 
00276   // Now walk the list of children and check the matching
00277   // sub-hierarchies only.
00278 
00279   int i = 0, j = 0;
00280   while (i < get_num_children() &&
00281          j < anim->get_num_children()) {
00282     PartGroup *pc = get_child(i);
00283     AnimGroup *ac = anim->get_child(j);
00284 
00285     if (pc->get_name() < ac->get_name()) {
00286       if ((hierarchy_match_flags & HMF_ok_part_extra) == 0) {
00287         return false;
00288       }
00289       i++;
00290     } else if (ac->get_name() < pc->get_name()) {
00291       if ((hierarchy_match_flags & HMF_ok_anim_extra) == 0) {
00292         return false;
00293       }
00294       j++;
00295     } else {
00296       if (!pc->check_hierarchy(ac, this, hierarchy_match_flags)) {
00297         return false;
00298       }
00299       i++;
00300       j++;
00301     }
00302   }
00303 
00304   if (i < get_num_children()) {
00305     // There's at least one extra part.
00306     if ((hierarchy_match_flags & HMF_ok_part_extra) == 0) {
00307       return false;
00308     }
00309   }
00310 
00311   if (j < anim->get_num_children()) {
00312     // There's at least one extra anim channel.
00313     if ((hierarchy_match_flags & HMF_ok_anim_extra) == 0) {
00314       return false;
00315     }
00316   }
00317 
00318   return true;
00319 }
00320 
00321 ////////////////////////////////////////////////////////////////////
00322 //     Function: PartGroup::write
00323 //       Access: Public, Virtual
00324 //  Description: Writes a brief description of the group and all of
00325 //               its descendants.
00326 ////////////////////////////////////////////////////////////////////
00327 void PartGroup::
00328 write(ostream &out, int indent_level) const {
00329   indent(out, indent_level)
00330     << get_type() << " " << get_name() << " {\n";
00331   write_descendants(out, indent_level + 2);
00332   indent(out, indent_level) << "}\n";
00333 }
00334 
00335 ////////////////////////////////////////////////////////////////////
00336 //     Function: PartGroup::write_with_value
00337 //       Access: Public, Virtual
00338 //  Description: Writes a brief description of the group, showing its
00339 //               current value, and that of all of its descendants.
00340 ////////////////////////////////////////////////////////////////////
00341 void PartGroup::
00342 write_with_value(ostream &out, int indent_level) const {
00343   indent(out, indent_level)
00344     << get_type() << " " << get_name() << " {\n";
00345   write_descendants_with_value(out, indent_level + 2);
00346   indent(out, indent_level) << "}\n";
00347 }
00348 
00349 
00350 ////////////////////////////////////////////////////////////////////
00351 //     Function: PartGroup::do_update
00352 //       Access: Public, Virtual
00353 //  Description: Recursively update this particular part and all of
00354 //               its descendents for the current frame.  This is not
00355 //               really public and is not intended to be called
00356 //               directly; it is called from the top of the tree by
00357 //               PartBundle::update().
00358 //
00359 //               The return value is true if any part has changed,
00360 //               false otherwise.
00361 ////////////////////////////////////////////////////////////////////
00362 bool PartGroup::
00363 do_update(PartBundle *root, PartGroup *,
00364           bool parent_changed, bool anim_changed) {
00365   bool any_changed = false;
00366 
00367   Children::iterator ci;
00368   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00369     if ((*ci)->do_update(root, this, parent_changed, anim_changed)) {
00370       any_changed = true;
00371     }
00372   }
00373 
00374   return any_changed;
00375 }
00376 
00377 
00378 ////////////////////////////////////////////////////////////////////
00379 //     Function: PartGroup::write_descendants
00380 //       Access: Protected
00381 //  Description: Writes a brief description of all of the group's
00382 //               descendants.
00383 ////////////////////////////////////////////////////////////////////
00384 void PartGroup::
00385 write_descendants(ostream &out, int indent_level) const {
00386   Children::const_iterator ci;
00387 
00388   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00389     (*ci)->write(out, indent_level);
00390   }
00391 }
00392 
00393 ////////////////////////////////////////////////////////////////////
00394 //     Function: PartGroup::write_descendants_with_value
00395 //       Access: Protected
00396 //  Description: Writes a brief description of all of the group's
00397 //               descendants and their values.
00398 ////////////////////////////////////////////////////////////////////
00399 void PartGroup::
00400 write_descendants_with_value(ostream &out, int indent_level) const {
00401   Children::const_iterator ci;
00402 
00403   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00404     (*ci)->write_with_value(out, indent_level);
00405   }
00406 }
00407 
00408 
00409 
00410 
00411 ////////////////////////////////////////////////////////////////////
00412 //     Function: PartGroup::pick_channel_index
00413 //       Access: Protected, Virtual
00414 //  Description: Walks the part hierarchy, looking for a suitable
00415 //               channel index number to use.  Available index numbers
00416 //               are the elements of the holes set, as well as next to
00417 //               infinity.
00418 ////////////////////////////////////////////////////////////////////
00419 void PartGroup::
00420 pick_channel_index(plist<int> &holes, int &next) const {
00421   Children::const_iterator ci;
00422   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00423     (*ci)->pick_channel_index(holes, next);
00424   }
00425 }
00426 
00427 
00428 ////////////////////////////////////////////////////////////////////
00429 //     Function: PartGroup::bind_hierarchy
00430 //       Access: Protected, Virtual
00431 //  Description: Binds the indicated anim hierarchy to the part
00432 //               hierarchy, at the given channel index number.
00433 ////////////////////////////////////////////////////////////////////
00434 void PartGroup::
00435 bind_hierarchy(AnimGroup *anim, int channel_index) {
00436   int i = 0, j = 0;
00437   int part_num_children = get_num_children();
00438   int anim_num_children = (anim == NULL) ? 0 : anim->get_num_children();
00439 
00440   while (i < part_num_children && j < anim_num_children) {
00441     PartGroup *pc = get_child(i);
00442     AnimGroup *ac = anim->get_child(j);
00443 
00444     if (pc->get_name() < ac->get_name()) {
00445       // Here's a part, not in the anim.  Bind it to the special NULL
00446       // anim.
00447       pc->bind_hierarchy(NULL, channel_index);
00448       i++;
00449     } else if (ac->get_name() < pc->get_name()) {
00450       j++;
00451     } else {
00452       pc->bind_hierarchy(ac, channel_index);
00453       i++;
00454       j++;
00455     }
00456   }
00457 
00458   // Now pick up any more parts, not in the anim.
00459   while (i < part_num_children) {
00460     PartGroup *pc = get_child(i);
00461     pc->bind_hierarchy(NULL, channel_index);
00462     i++;
00463   }
00464 }
00465 
00466 ////////////////////////////////////////////////////////////////////
00467 //     Function: PartGroup::write_datagram
00468 //       Access: Public
00469 //  Description: Function to write the important information in
00470 //               the particular object to a Datagram
00471 ////////////////////////////////////////////////////////////////////
00472 void PartGroup::
00473 write_datagram(BamWriter *manager, Datagram &me)
00474 {
00475   int i;
00476   me.add_string(get_name());
00477   me.add_uint16(_children.size());
00478   for(i = 0; i < (int)_children.size(); i++)
00479   {
00480     manager->write_pointer(me, _children[i]);
00481   }
00482 }
00483 
00484 ////////////////////////////////////////////////////////////////////
00485 //     Function: PartGroup::fillin
00486 //       Access: Protected
00487 //  Description: Function that reads out of the datagram (or asks
00488 //               manager to read) all of the data that is needed to
00489 //               re-create this object and stores it in the appropiate
00490 //               place
00491 ////////////////////////////////////////////////////////////////////
00492 void PartGroup::
00493 fillin(DatagramIterator& scan, BamReader* manager)
00494 {
00495   int i;
00496   set_name(scan.get_string());
00497   _num_children = scan.get_uint16();
00498   for(i = 0; i < _num_children; i++)
00499   {
00500     manager->read_pointer(scan);
00501   }
00502 }
00503 
00504 ////////////////////////////////////////////////////////////////////
00505 //     Function: PartGroup::complete_pointers
00506 //       Access: Public
00507 //  Description: Takes in a vector of pointes to TypedWritable
00508 //               objects that correspond to all the requests for
00509 //               pointers that this object made to BamReader.
00510 ////////////////////////////////////////////////////////////////////
00511 int PartGroup::
00512 complete_pointers(TypedWritable **p_list, BamReader*)
00513 {
00514   int i;
00515   for(i = 0; i < _num_children; i++)
00516   {
00517     if (p_list[i] == TypedWritable::Null)
00518     {
00519       chan_cat->warning() << get_type().get_name()
00520                           << " Ignoring null PartGroup" << endl;
00521     }
00522     else
00523     {
00524       _children.push_back(DCAST(PartGroup, p_list[i]));
00525     }
00526   }
00527 
00528   return _num_children;
00529 }
00530 
00531 ////////////////////////////////////////////////////////////////////
00532 //     Function: PartGroup::make_PartGroup
00533 //       Access: Protected
00534 //  Description: Factory method to generate a PartGroup object
00535 ////////////////////////////////////////////////////////////////////
00536 TypedWritable* PartGroup::
00537 make_PartGroup(const FactoryParams &params)
00538 {
00539   PartGroup *me = new PartGroup;
00540   DatagramIterator scan;
00541   BamReader *manager;
00542 
00543   parse_params(params, scan, manager);
00544   me->fillin(scan, manager);
00545   return me;
00546 }
00547 
00548 ////////////////////////////////////////////////////////////////////
00549 //     Function: PartGroup::register_with_factory
00550 //       Access: Public, Static
00551 //  Description: Factory method to generate a PartGroup object
00552 ////////////////////////////////////////////////////////////////////
00553 void PartGroup::
00554 register_with_read_factory(void)
00555 {
00556   BamReader::get_factory()->register_factory(get_class_type(), make_PartGroup);
00557 }
00558 

Generated on Fri May 2 00:35:15 2003 for Panda by doxygen1.3