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

panda/src/chan/partBundle.cxx

Go to the documentation of this file.
00001 // Filename: partBundle.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 "partBundle.h"
00021 #include "animBundle.h"
00022 #include "animControl.h"
00023 #include "config_chan.h"
00024 
00025 #include "indent.h"
00026 #include "datagram.h"
00027 #include "datagramIterator.h"
00028 #include "bamReader.h"
00029 #include "bamWriter.h"
00030 
00031 TypeHandle PartBundle::_type_handle;
00032 
00033 
00034 
00035 ////////////////////////////////////////////////////////////////////
00036 //     Function: PartBundle::Copy Constructor
00037 //       Access: Protected
00038 //  Description: Normally, you'd use make_copy() or copy_subgraph() to
00039 //               make a copy of this.
00040 ////////////////////////////////////////////////////////////////////
00041 PartBundle::
00042 PartBundle(const PartBundle &copy) :
00043   PartGroup(copy),
00044   _blend_type(copy._blend_type)
00045 {
00046   // We don't invoke the AnimControlCollection's copy, or any of the
00047   // bound animations.
00048   _last_control_set = NULL;
00049   _net_blend = 0.0f;
00050   _anim_changed = false;
00051 }
00052 
00053 ////////////////////////////////////////////////////////////////////
00054 //     Function: PartBundle::Constructor
00055 //       Access: Public
00056 //  Description: Normally, a PartBundle constructor should not be
00057 //               called directly--it will get created when a
00058 //               PartBundleNode is created.
00059 ////////////////////////////////////////////////////////////////////
00060 PartBundle::
00061 PartBundle(const string &name) : PartGroup(name) {
00062   _blend_type = BT_single;
00063 
00064   _last_control_set = NULL;
00065   _net_blend = 0.0f;
00066   _anim_changed = false;
00067 }
00068 
00069 ////////////////////////////////////////////////////////////////////
00070 //     Function: PartBundle::make_copy
00071 //       Access: Public, Virtual
00072 //  Description: Allocates and returns a new copy of the node.
00073 //               Children are not copied, but see copy_subgraph().
00074 ////////////////////////////////////////////////////////////////////
00075 PartGroup *PartBundle::
00076 make_copy() const {
00077   return new PartBundle(*this);
00078 }
00079 
00080 
00081 ////////////////////////////////////////////////////////////////////
00082 //     Function: PartBundle::set_blend_type
00083 //       Access: Published
00084 //  Description: Defines the way the character responds to multiple
00085 //               set_control_effect()).  By default, the blend_type is
00086 //               BT_single, which disallows multiple animations.  In
00087 //               BT_single mode, it is not necessary to explicitly set
00088 //               the control_effect when starting an animation;
00089 //               starting the animation will implicitly remove the
00090 //               control_effect from the previous animation and set it
00091 //               on the current one.
00092 //
00093 //               However, if the blend_type is set to any other value,
00094 //               the control_effect must be explicitly set via
00095 //               set_control_effect() whenever an animation is to
00096 //               affect the character.
00097 //
00098 //               See partBundle.h for a description of the meaning of
00099 //               each of the BlendType values.
00100 ////////////////////////////////////////////////////////////////////
00101 void PartBundle::
00102 set_blend_type(BlendType bt) {
00103   if (_blend_type != bt) {
00104     _blend_type = bt;
00105 
00106     if (_blend_type == BT_single && control_size() > 1) {
00107       // If we just changed to a single blend type, i.e. no blending,
00108       // we should eliminate all the AnimControls other than the
00109       // most-recently-added one.
00110 
00111       nassertv(_last_control_set != NULL);
00112       clear_and_stop_except(_last_control_set);
00113     }
00114 
00115     _anim_changed = true;
00116   }
00117 }
00118 
00119 ////////////////////////////////////////////////////////////////////
00120 //     Function: PartBundle::clear_control_effects
00121 //       Access: Published
00122 //  Description: Sets the control effect of all AnimControls to zero
00123 //               (but does not "stop" the AnimControls).  The
00124 //               character will no longer be affected by any
00125 //               animation, and will return to its original Jesus
00126 //               pose.
00127 //
00128 //               The AnimControls which are no longer associated will
00129 //               not be using any CPU cycles, but they may still be in
00130 //               the "playing" state; if they are later reassociated
00131 //               with the PartBundle they will resume at their current
00132 //               frame as if they'd been running all along.
00133 ////////////////////////////////////////////////////////////////////
00134 void PartBundle::
00135 clear_control_effects() {
00136   if (!_blend.empty()) {
00137     _blend.clear();
00138     _net_blend = 0.0f;
00139     _anim_changed = true;
00140   }
00141 }
00142 
00143 
00144 ////////////////////////////////////////////////////////////////////
00145 //     Function: PartBundle::set_control_effect
00146 //       Access: Published
00147 //  Description: Sets the amount by which the character is affected by
00148 //               the indicated AnimControl (and its associated
00149 //               animation).  Normally, this will only be zero or one.
00150 //               Zero indicates the animation does not affect the
00151 //               character, and one means it does.
00152 //
00153 //               If the blend_type is not BT_single (see
00154 //               set_blend_type()), it is possible to have multiple
00155 //               AnimControls in effect simultaneously.  In this case,
00156 //               the effect is a weight that indicates the relative
00157 //               importance of each AnimControl to the final
00158 //               animation.
00159 ////////////////////////////////////////////////////////////////////
00160 void PartBundle::
00161 set_control_effect(AnimControl *control, float effect) {
00162   nassertv(control->get_part() == this);
00163 
00164   if (effect == 0.0f) {
00165     // An effect of zero means to eliminate the control.
00166     ChannelBlend::iterator cbi = _blend.find(control);
00167     if (cbi != _blend.end()) {
00168       _blend.erase(cbi);
00169       _anim_changed = true;
00170     }
00171 
00172   } else {
00173     // Otherwise we define it.
00174 
00175     // If we currently have BT_single, we only allow one AnimControl
00176     // at a time.  Stop all of the other AnimControls.
00177     if (get_blend_type() == BT_single) {
00178       clear_and_stop_except(control);
00179     }
00180 
00181     if (get_control_effect(control) != effect) {
00182       _blend[control] = effect;
00183       _anim_changed = true;
00184     }
00185     _last_control_set = control;
00186   }
00187 
00188   recompute_net_blend();
00189 }
00190 
00191 
00192 ////////////////////////////////////////////////////////////////////
00193 //     Function: PartBundle::get_control_effect
00194 //       Access: Published
00195 //  Description: Returns the amount by which the character is affected
00196 //               by the indicated AnimControl and its associated
00197 //               animation.  See set_control_effect().
00198 ////////////////////////////////////////////////////////////////////
00199 float PartBundle::
00200 get_control_effect(AnimControl *control) {
00201   nassertr(control->get_part() == this, 0.0f);
00202 
00203   ChannelBlend::iterator cbi = _blend.find(control);
00204   if (cbi == _blend.end()) {
00205     // The control is not in effect.
00206     return 0.0f;
00207   } else {
00208     return (*cbi).second;
00209   }
00210 }
00211 
00212 
00213 
00214 ////////////////////////////////////////////////////////////////////
00215 //     Function: PartBundle::output
00216 //       Access: Published, Virtual
00217 //  Description: Writes a one-line description of the bundle.
00218 ////////////////////////////////////////////////////////////////////
00219 void PartBundle::
00220 output(ostream &out) const {
00221   out << get_type() << " " << get_name();
00222 }
00223 
00224 ////////////////////////////////////////////////////////////////////
00225 //     Function: PartBundle::write
00226 //       Access: Published, Virtual
00227 //  Description: Writes a brief description of the bundle and all of
00228 //               its descendants.
00229 ////////////////////////////////////////////////////////////////////
00230 void PartBundle::
00231 write(ostream &out, int indent_level) const {
00232   indent(out, indent_level)
00233     << get_type() << " " << get_name() << " {\n";
00234   write_descendants(out, indent_level + 2);
00235   indent(out, indent_level) << "}\n";
00236 }
00237 
00238 
00239 ////////////////////////////////////////////////////////////////////
00240 //     Function: PartBundle::bind_anim
00241 //       Access: Published
00242 //  Description: Binds the animation to the bundle, if possible, and
00243 //               returns a new AnimControl that can be used to start
00244 //               and stop the animation.  If the anim hierarchy does
00245 //               not match the part hierarchy, returns NULL.
00246 //
00247 //               If hierarchy_match_flags is 0, only an exact match is
00248 //               accepted; otherwise, it may contain a union of
00249 //               PartGroup::HierarchyMatchFlags values indicating
00250 //               conditions that will be tolerated (but warnings will
00251 //               still be issued).
00252 //
00253 //               This flavor of bind_anim() does not associate a name
00254 //               with the channel, and the AnimControl is not stored
00255 //               within the PartBundle; it is the user's
00256 //               responsibility to maintain the pointer.  The
00257 //               animation will automatically unbind itself when the
00258 //               AnimControl destructs (i.e. its reference count goes
00259 //               to zero).
00260 ////////////////////////////////////////////////////////////////////
00261 PT(AnimControl) PartBundle::
00262 bind_anim(AnimBundle *anim, int hierarchy_match_flags) {
00263   if ((hierarchy_match_flags & HMF_ok_wrong_root_name) == 0) {
00264     // Make sure the root names match.
00265     if (get_name() != anim->get_name()) {
00266       if (chan_cat.is_error()) {
00267         chan_cat.error()
00268           << "Root name of part (" << get_name()
00269           << ") does not match that of anim (" << anim->get_name()
00270           << ")\n";
00271       }
00272       return NULL;
00273     }
00274   }
00275 
00276   if (!check_hierarchy(anim, NULL, hierarchy_match_flags)) {
00277     return NULL;
00278   }
00279 
00280   plist<int> holes;
00281   int channel_index = 0;
00282   pick_channel_index(holes, channel_index);
00283 
00284   if (!holes.empty()) {
00285     channel_index = holes.front();
00286   }
00287 
00288   bind_hierarchy(anim, channel_index);
00289   return new AnimControl(this, anim, channel_index);
00290 }
00291 
00292 ////////////////////////////////////////////////////////////////////
00293 //     Function: PartBundle::bind_anim
00294 //       Access: Published
00295 //  Description: Binds the animation to the bundle, if possible, and
00296 //               returns a new AnimControl that can be used to start
00297 //               and stop the animation.  If the anim hierarchy does
00298 //               not match the part hierarchy, returns NULL.
00299 //
00300 //               If hierarchy_match_flags is 0, only an exact match is
00301 //               accepted; otherwise, it may contain a union of
00302 //               PartGroup::HierarchyMatchFlags values indicating
00303 //               conditions that will be tolerated (but warnings will
00304 //               still be issued).
00305 //
00306 //               This flavor of bind_anim() automatically stores the
00307 //               bound AnimControl in the PartBundle with the
00308 //               indicated name, so that it may later be referenced by
00309 //               name.  This means that the animation will not be
00310 //               unbound until another animation with the same name is
00311 //               bound, or it is explicitly unbound with
00312 //               unbind_anim().
00313 //
00314 //               The return value is true if the animation was
00315 //               successfully bound, false if there was some error.
00316 ////////////////////////////////////////////////////////////////////
00317 bool PartBundle::
00318 bind_anim(AnimBundle *anim, const string &name,
00319           int hierarchy_match_flags) {
00320   PT(AnimControl) control = bind_anim(anim, hierarchy_match_flags);
00321   if (control == (AnimControl *)NULL) {
00322     return false;
00323   }
00324 
00325   store_anim(control, name);
00326   return true;
00327 }
00328 
00329 ////////////////////////////////////////////////////////////////////
00330 //     Function: PartBundle::advance_time
00331 //       Access: Public
00332 //  Description: Calls advance_time() on all AnimControls currently
00333 //               in effect.
00334 ////////////////////////////////////////////////////////////////////
00335 void PartBundle::
00336 advance_time(double time) {
00337   ChannelBlend::const_iterator cbi;
00338   for (cbi = _blend.begin(); cbi != _blend.end(); ++cbi) {
00339     AnimControl *control = (*cbi).first;
00340     control->advance_time(time);
00341   }
00342 }
00343 
00344 ////////////////////////////////////////////////////////////////////
00345 //     Function: PartBundle::update
00346 //       Access: Public
00347 //  Description: Updates all the parts in the bundle to reflect the
00348 //               data for the current frame (as set in each of the
00349 //               AnimControls).
00350 //
00351 //               Returns true if any part has changed as a result of
00352 //               this, or false otherwise.
00353 ////////////////////////////////////////////////////////////////////
00354 bool PartBundle::
00355 update() {
00356   bool any_changed = do_update(this, NULL, false, _anim_changed);
00357 
00358   // Now update all the controls for next time.
00359   ChannelBlend::const_iterator cbi;
00360   for (cbi = _blend.begin(); cbi != _blend.end(); ++cbi) {
00361     AnimControl *control = (*cbi).first;
00362     control->mark_channels();
00363   }
00364   _anim_changed = false;
00365 
00366   return any_changed;
00367 }
00368 
00369 ////////////////////////////////////////////////////////////////////
00370 //     Function: PartBundle::force_update
00371 //       Access: Public
00372 //  Description: Updates all the parts in the bundle to reflect the
00373 //               data for the current frame, whether we believe it
00374 //               needs it or not.
00375 ////////////////////////////////////////////////////////////////////
00376 bool PartBundle::
00377 force_update() {
00378   bool any_changed = do_update(this, NULL, true, true);
00379 
00380   // Now update all the controls for next time.
00381   ChannelBlend::const_iterator cbi;
00382   for (cbi = _blend.begin(); cbi != _blend.end(); ++cbi) {
00383     AnimControl *control = (*cbi).first;
00384     control->mark_channels();
00385   }
00386   _anim_changed = false;
00387 
00388   return any_changed;
00389 }
00390 
00391 
00392 ////////////////////////////////////////////////////////////////////
00393 //     Function: PartBundle::control_activated
00394 //       Access: Public, Virtual
00395 //  Description: Called by the AnimControl whenever it starts an
00396 //               animation.  This is just a hook so the bundle can do
00397 //               something, if necessary, before the animation starts.
00398 ////////////////////////////////////////////////////////////////////
00399 void PartBundle::
00400 control_activated(AnimControl *control) {
00401   nassertv(control->get_part() == this);
00402 
00403   // If (and only if) our blend type is BT_single, which means no
00404   // blending, then starting an animation implicitly enables it.
00405   if (get_blend_type() == BT_single) {
00406     set_control_effect(control, 1.0f);
00407   }
00408 }
00409 
00410 
00411 
00412 ////////////////////////////////////////////////////////////////////
00413 //     Function: PartBundle::recompute_net_blend
00414 //       Access: Protected
00415 //  Description: Recomputes the total blending amount after a control
00416 //               effect has been adjusted.  This value must be kept
00417 //               up-to-date so we can normalize the blending amounts.
00418 ////////////////////////////////////////////////////////////////////
00419 void PartBundle::
00420 recompute_net_blend() {
00421   _net_blend = 0.0f;
00422 
00423   ChannelBlend::const_iterator bti;
00424   for (bti = _blend.begin(); bti != _blend.end(); ++bti) {
00425     _net_blend += (*bti).second;
00426   }
00427 }
00428 
00429 ////////////////////////////////////////////////////////////////////
00430 //     Function: PartBundle::finalize
00431 //       Access: Public
00432 //  Description: Method to ensure that any necessary clean up tasks
00433 //               that have to be performed by this object are performed
00434 ////////////////////////////////////////////////////////////////////
00435 void PartBundle::
00436 finalize(void)
00437 {
00438   do_update(this, NULL, true, true);
00439 }
00440 
00441 ////////////////////////////////////////////////////////////////////
00442 //     Function: PartBundle::make_PartBundle
00443 //       Access: Protected
00444 //  Description: Factory method to generate a PartBundle object
00445 ////////////////////////////////////////////////////////////////////
00446 TypedWritable* PartBundle::
00447 make_PartBundle(const FactoryParams &params)
00448 {
00449   PartBundle *me = new PartBundle;
00450   DatagramIterator scan;
00451   BamReader *manager;
00452 
00453   parse_params(params, scan, manager);
00454   me->fillin(scan, manager);
00455   manager->register_finalize(me);
00456   return me;
00457 }
00458 
00459 ////////////////////////////////////////////////////////////////////
00460 //     Function: PartBundle::register_with_factory
00461 //       Access: Public, Static
00462 //  Description: Factory method to generate a PartBundle object
00463 ////////////////////////////////////////////////////////////////////
00464 void PartBundle::
00465 register_with_read_factory(void)
00466 {
00467   BamReader::get_factory()->register_factory(get_class_type(), make_PartBundle);
00468 }
00469 
00470 ////////////////////////////////////////////////////////////////////
00471 //     Function: PartBundle::clear_and_stop_except
00472 //       Access: Protected
00473 //  Description: Removes and stops all the currently activated
00474 //               AnimControls, except for the indicated one.  This is
00475 //               a special internal function that's only called when
00476 //               _blend_type is BT_single, to automatically stop all
00477 //               the other currently-executing animations.
00478 ////////////////////////////////////////////////////////////////////
00479 void PartBundle::
00480 clear_and_stop_except(AnimControl *control) {
00481   double new_net_blend = 0.0f;
00482   ChannelBlend new_blend;
00483   bool any_changed = false;
00484 
00485   ChannelBlend::iterator cbi;
00486   for (cbi = _blend.begin(); cbi != _blend.end(); ++cbi) {
00487     AnimControl *ac = (*cbi).first;
00488     if (ac == control) {
00489       // Save this control, but only this one.
00490       new_blend.insert(new_blend.end(), (*cbi));
00491       new_net_blend += (*cbi).second;
00492     } else {
00493       // Remove and stop this control.
00494       ac->stop();
00495       any_changed = true;
00496     }
00497   }
00498 
00499   if (any_changed) {
00500     _net_blend = new_net_blend;
00501     _blend.swap(new_blend);
00502     _anim_changed = true;
00503   }
00504 }

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