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

panda/src/chan/auto_bind.cxx

Go to the documentation of this file.
00001 // Filename: auto_bind.cxx
00002 // Created by:  drose (23Feb99)
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 "auto_bind.h"
00021 #include "animBundleNode.h"
00022 #include "partBundleNode.h"
00023 #include "config_chan.h"
00024 #include "string_utils.h"
00025 
00026 typedef pset<AnimBundleNode *> AnimNodes;
00027 typedef pmap<string, AnimNodes> Anims;
00028 
00029 typedef pset<PartBundleNode *> PartNodes;
00030 typedef pmap<string, PartNodes> Parts;
00031 
00032 
00033 ////////////////////////////////////////////////////////////////////
00034 //     Function: bind_anims
00035 //  Description: A support function for auto_bind(), below.  Given a
00036 //               set of AnimBundles and a set of PartBundles that all
00037 //               share the same name, perform whatever bindings make
00038 //               sense.
00039 ////////////////////////////////////////////////////////////////////
00040 static void
00041 bind_anims(const PartNodes &parts, const AnimNodes &anims,
00042            AnimControlCollection &controls,
00043            int hierarchy_match_flags) {
00044 
00045   PartNodes::const_iterator pni;
00046 
00047   for (pni = parts.begin(); pni != parts.end(); ++pni) {
00048     PartBundle *part = (*pni)->get_bundle();
00049 
00050     AnimNodes::const_iterator ani;
00051     for (ani = anims.begin(); ani != anims.end(); ++ani) {
00052       AnimBundle *anim = (*ani)->get_bundle();
00053 
00054       if (chan_cat.is_info()) {
00055         chan_cat.info()
00056           << "Attempting to bind " << *part << " to " << *anim << "\n";
00057       }
00058 
00059       PT(AnimControl) control =
00060         part->bind_anim(anim, hierarchy_match_flags);
00061       string name = anim->get_name();
00062       if (control != (AnimControl *)NULL) {
00063         if (controls.find_anim(name) != (AnimControl *)NULL) {
00064           // That name's already used; synthesize another one.
00065           int index = 0;
00066           string new_name;
00067           do {
00068             index++;
00069             new_name = name + '.' + format_string(index);
00070           } while (controls.find_anim(new_name) != (AnimControl *)NULL);
00071           name = new_name;
00072         }
00073 
00074         controls.store_anim(control, name);
00075       }
00076 
00077       if (chan_cat.is_info()) {
00078         if (control == (AnimControl *)NULL) {
00079           chan_cat.info()
00080             << "Bind failed.\n";
00081         } else {
00082           chan_cat.info()
00083             << "Bind succeeded, index "
00084             << control->get_channel_index() << "; accessible as "
00085             << name << "\n";
00086         }
00087       }
00088     }
00089   }
00090 }
00091 
00092 ////////////////////////////////////////////////////////////////////
00093 //     Function: r_find_bundles
00094 //  Description: A support function for auto_bind(), below.  Walks
00095 //               through the hierarchy and finds all of the
00096 //               PartBundles and AnimBundles.
00097 ////////////////////////////////////////////////////////////////////
00098 static void 
00099 r_find_bundles(PandaNode *node, Anims &anims, Parts &parts) {
00100   if (node->is_of_type(AnimBundleNode::get_class_type())) {
00101     AnimBundleNode *bn = DCAST(AnimBundleNode, node);
00102     anims[bn->get_bundle()->get_name()].insert(bn);
00103     
00104   } else if (node->is_of_type(PartBundleNode::get_class_type())) {
00105     PartBundleNode *bn = DCAST(PartBundleNode, node);
00106     parts[bn->get_bundle()->get_name()].insert(bn);
00107   }
00108 
00109   PandaNode::Children cr = node->get_children();
00110   int num_children = cr.get_num_children();
00111   for (int i = 0; i < num_children; i++) {
00112     r_find_bundles(cr.get_child(i), anims, parts);
00113   }
00114 }
00115 
00116 
00117 ////////////////////////////////////////////////////////////////////
00118 //     Function: auto_bind
00119 //  Description: Walks the scene graph or subgraph beginning at the
00120 //               indicated node, and attempts to bind any AnimBundles
00121 //               found to their matching PartBundles, when possible.
00122 //
00123 //               The list of all resulting AnimControls created is
00124 //               filled into controls.
00125 ////////////////////////////////////////////////////////////////////
00126 void
00127 auto_bind(PandaNode *root_node, AnimControlCollection &controls,
00128           int hierarchy_match_flags) {
00129   // First, locate all the bundles in the subgraph.
00130   Anims anims;
00131   Parts parts;
00132   r_find_bundles(root_node, anims, parts);
00133 
00134   if (chan_cat.is_debug()) {
00135     int anim_count = 0;
00136     Anims::const_iterator ai;
00137     for (ai = anims.begin(); ai != anims.end(); ++ai) {
00138       anim_count += (int)(*ai).second.size();
00139     }
00140     chan_cat.debug()
00141       << "Found " << anim_count << " anims:\n";
00142     for (ai = anims.begin(); ai != anims.end(); ++ai) {
00143       chan_cat.debug(false)
00144         << " " << (*ai).first;
00145       if ((*ai).second.size() != 1) {
00146         chan_cat.debug(false)
00147           << "*" << ((*ai).second.size());
00148       }
00149     }
00150     chan_cat.debug(false)
00151       << "\n";
00152 
00153     int part_count = 0;
00154     Parts::const_iterator pi;
00155     for (pi = parts.begin(); pi != parts.end(); ++pi) {
00156       part_count += (int)(*pi).second.size();
00157     }
00158     chan_cat.debug()
00159       << "Found " << part_count << " parts:\n";
00160     for (pi = parts.begin(); pi != parts.end(); ++pi) {
00161       chan_cat.debug(false)
00162         << " " << (*pi).first;
00163       if ((*pi).second.size() != 1) {
00164         chan_cat.debug(false)
00165           << "*" << ((*pi).second.size());
00166       }
00167     }
00168     chan_cat.debug(false)
00169       << "\n";
00170   }
00171 
00172   // Now, match up the bundles by name.
00173 
00174   Anims::const_iterator ai = anims.begin();
00175   Parts::const_iterator pi = parts.begin();
00176 
00177   while (ai != anims.end() && pi != parts.end()) {
00178     if ((*ai).first < (*pi).first) {
00179       // Here's an anim with no matching parts.
00180       ++ai;
00181 
00182     } else if ((*pi).first < (*ai).first) {
00183       // And here's a part with no matching anims.
00184       ++pi;
00185 
00186     } else {
00187       // But here we have (at least one) match!
00188       bind_anims((*pi).second, (*ai).second, controls,
00189                    hierarchy_match_flags);
00190       ++pi;
00191 
00192       // We don't increment the anim counter yet.  That way, the same
00193       // anim may bind to multiple parts, if they all share the same
00194       // name.
00195     }
00196   }
00197 }
00198 
00199 

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