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 ©) : 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 ¶ms) 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 }