Panda3D
|
00001 // Filename: partBundle.cxx 00002 // Created by: drose (22Feb99) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 00016 #include "partBundle.h" 00017 #include "animBundle.h" 00018 #include "animBundleNode.h" 00019 #include "animControl.h" 00020 #include "loader.h" 00021 #include "animPreloadTable.h" 00022 #include "config_chan.h" 00023 #include "bitArray.h" 00024 #include "string_utils.h" 00025 #include "indent.h" 00026 #include "datagram.h" 00027 #include "datagramIterator.h" 00028 #include "bamReader.h" 00029 #include "bamWriter.h" 00030 #include "configVariableEnum.h" 00031 #include "loaderOptions.h" 00032 00033 #include <algorithm> 00034 00035 TypeHandle PartBundle::_type_handle; 00036 00037 00038 static ConfigVariableEnum<PartBundle::BlendType> anim_blend_type 00039 ("anim-blend-type", PartBundle::BT_normalized_linear, 00040 PRC_DESC("The default blend type to use for blending animations between " 00041 "frames, or between multiple animations. See interpolate-frames, " 00042 "and also PartBundle::set_anim_blend_flag() and " 00043 "PartBundle::set_frame_blend_flag().")); 00044 00045 00046 //////////////////////////////////////////////////////////////////// 00047 // Function: PartBundle::Copy Constructor 00048 // Access: Protected 00049 // Description: Normally, you'd use make_copy() or copy_subgraph() to 00050 // make a copy of this. 00051 //////////////////////////////////////////////////////////////////// 00052 PartBundle:: 00053 PartBundle(const PartBundle ©) : 00054 PartGroup(copy) 00055 { 00056 _anim_preload = copy._anim_preload; 00057 _update_delay = 0.0; 00058 00059 CDWriter cdata(_cycler, true); 00060 CDReader cdata_from(copy._cycler); 00061 cdata->_blend_type = cdata_from->_blend_type; 00062 cdata->_anim_blend_flag = cdata_from->_anim_blend_flag; 00063 cdata->_frame_blend_flag = cdata_from->_frame_blend_flag; 00064 cdata->_root_xform = cdata_from->_root_xform; 00065 } 00066 00067 //////////////////////////////////////////////////////////////////// 00068 // Function: PartBundle::Constructor 00069 // Access: Public 00070 // Description: Normally, a PartBundle constructor should not be 00071 // called directly--it will get created when a 00072 // PartBundleNode is created. 00073 //////////////////////////////////////////////////////////////////// 00074 PartBundle:: 00075 PartBundle(const string &name) : 00076 PartGroup(name) 00077 { 00078 _update_delay = 0.0; 00079 } 00080 00081 //////////////////////////////////////////////////////////////////// 00082 // Function: PartBundle::make_copy 00083 // Access: Public, Virtual 00084 // Description: Allocates and returns a new copy of the node. 00085 // Children are not copied, but see copy_subgraph(). 00086 //////////////////////////////////////////////////////////////////// 00087 PartGroup *PartBundle:: 00088 make_copy() const { 00089 return new PartBundle(*this); 00090 } 00091 00092 //////////////////////////////////////////////////////////////////// 00093 // Function: PartBundle::merge_anim_preloads 00094 // Access: Published 00095 // Description: Copies the contents of the other PartBundle's preload 00096 // table into this one. 00097 //////////////////////////////////////////////////////////////////// 00098 void PartBundle:: 00099 merge_anim_preloads(const PartBundle *other) { 00100 if (other->_anim_preload == (AnimPreloadTable *)NULL || 00101 _anim_preload == other->_anim_preload) { 00102 // No-op. 00103 return; 00104 } 00105 00106 if (_anim_preload == (AnimPreloadTable *)NULL) { 00107 // Trivial case. 00108 _anim_preload = other->_anim_preload; 00109 return; 00110 } 00111 00112 // Copy-on-write. 00113 PT(AnimPreloadTable) anim_preload = _anim_preload.get_write_pointer(); 00114 anim_preload->add_anims_from(other->_anim_preload.get_read_pointer()); 00115 } 00116 00117 //////////////////////////////////////////////////////////////////// 00118 // Function: PartBundle::set_anim_blend_flag 00119 // Access: Published 00120 // Description: Defines the way the character responds to multiple 00121 // calls to set_control_effect()). By default, this 00122 // flag is set false, which disallows multiple 00123 // animations. When this flag is false, it is not 00124 // necessary to explicitly set the control_effect when 00125 // starting an animation; starting the animation will 00126 // implicitly remove the control_effect from the 00127 // previous animation and set it on the current one. 00128 // 00129 // However, if this flag is set true, the control_effect 00130 // must be explicitly set via set_control_effect() 00131 // whenever an animation is to affect the character. 00132 //////////////////////////////////////////////////////////////////// 00133 void PartBundle:: 00134 set_anim_blend_flag(bool anim_blend_flag) { 00135 nassertv(Thread::get_current_pipeline_stage() == 0); 00136 00137 CDLockedReader cdata(_cycler); 00138 if (cdata->_anim_blend_flag != anim_blend_flag) { 00139 CDWriter cdataw(_cycler, cdata); 00140 cdataw->_anim_blend_flag = anim_blend_flag; 00141 00142 if (!anim_blend_flag && cdataw->_blend.size() > 1) { 00143 // If we just changed to disallow animation blending, we should 00144 // eliminate all the AnimControls other than the 00145 // most-recently-added one. 00146 00147 nassertv(cdataw->_last_control_set != NULL); 00148 clear_and_stop_intersecting(cdataw->_last_control_set, cdataw); 00149 } 00150 00151 cdataw->_anim_changed = true; 00152 } 00153 } 00154 00155 //////////////////////////////////////////////////////////////////// 00156 // Function: PartBundle::apply_transform 00157 // Access: Published 00158 // Description: Returns a PartBundle that is a duplicate of this one, 00159 // but with the indicated transform applied. If this is 00160 // called multiple times with the same TransformState 00161 // pointer, it returns the same PartBundle each time. 00162 //////////////////////////////////////////////////////////////////// 00163 PT(PartBundle) PartBundle:: 00164 apply_transform(const TransformState *transform) { 00165 if (transform->is_identity()) { 00166 // Trivial no-op. 00167 return this; 00168 } 00169 00170 AppliedTransforms::iterator ati = _applied_transforms.find(transform); 00171 if (ati != _applied_transforms.end()) { 00172 if ((*ati).first.is_valid_pointer() && 00173 (*ati).second.is_valid_pointer()) { 00174 // Here's our cached result. 00175 return (*ati).second.p(); 00176 } 00177 } 00178 00179 PT(PartBundle) new_bundle = DCAST(PartBundle, copy_subgraph()); 00180 new_bundle->xform(transform->get_mat()); 00181 00182 if (ati != _applied_transforms.end()) { 00183 // A stale pointer to a deleted result. Update it. 00184 (*ati).first.refresh(); 00185 (*ati).second = new_bundle; 00186 } else { 00187 // No such result yet. Store it. 00188 bool inserted = _applied_transforms.insert(AppliedTransforms::value_type(transform, new_bundle)).second; 00189 nassertr(inserted, new_bundle); 00190 } 00191 00192 // Make sure the new transform gets immediately applied to all of 00193 // the joints. 00194 new_bundle->force_update(); 00195 00196 return new_bundle; 00197 } 00198 00199 //////////////////////////////////////////////////////////////////// 00200 // Function: PartBundle::clear_control_effects 00201 // Access: Published 00202 // Description: Sets the control effect of all AnimControls to zero 00203 // (but does not "stop" the AnimControls). The 00204 // character will no longer be affected by any 00205 // animation, and will return to its default 00206 // pose (unless restore-initial-pose is false). 00207 // 00208 // The AnimControls which are no longer associated will 00209 // not be using any CPU cycles, but they may still be in 00210 // the "playing" state; if they are later reassociated 00211 // with the PartBundle they will resume at their current 00212 // frame as if they'd been running all along. 00213 //////////////////////////////////////////////////////////////////// 00214 void PartBundle:: 00215 clear_control_effects() { 00216 nassertv(Thread::get_current_pipeline_stage() == 0); 00217 00218 CDLockedReader cdata(_cycler); 00219 if (!cdata->_blend.empty()) { 00220 CDWriter cdataw(_cycler, cdata); 00221 cdataw->_blend.clear(); 00222 cdataw->_net_blend = 0.0f; 00223 cdataw->_anim_changed = true; 00224 determine_effective_channels(cdataw); 00225 } 00226 } 00227 00228 //////////////////////////////////////////////////////////////////// 00229 // Function: PartBundle::output 00230 // Access: Published, Virtual 00231 // Description: Writes a one-line description of the bundle. 00232 //////////////////////////////////////////////////////////////////// 00233 void PartBundle:: 00234 output(ostream &out) const { 00235 out << get_type() << " " << get_name(); 00236 } 00237 00238 //////////////////////////////////////////////////////////////////// 00239 // Function: PartBundle::write 00240 // Access: Published, Virtual 00241 // Description: Writes a brief description of the bundle and all of 00242 // its descendants. 00243 //////////////////////////////////////////////////////////////////// 00244 void PartBundle:: 00245 write(ostream &out, int indent_level) const { 00246 indent(out, indent_level) 00247 << get_type() << " " << get_name() << " {\n"; 00248 write_descendants(out, indent_level + 2); 00249 indent(out, indent_level) << "}\n"; 00250 } 00251 00252 00253 //////////////////////////////////////////////////////////////////// 00254 // Function: PartBundle::bind_anim 00255 // Access: Published 00256 // Description: Binds the animation to the bundle, if possible, and 00257 // returns a new AnimControl that can be used to start 00258 // and stop the animation. If the anim hierarchy does 00259 // not match the part hierarchy, returns NULL. 00260 // 00261 // If hierarchy_match_flags is 0, only an exact match is 00262 // accepted; otherwise, it may contain a union of 00263 // PartGroup::HierarchyMatchFlags values indicating 00264 // conditions that will be tolerated (but warnings will 00265 // still be issued). 00266 // 00267 // If subset is specified, it restricts the binding only 00268 // to the named subtree of joints. 00269 // 00270 // The AnimControl is not stored within the PartBundle; 00271 // it is the user's responsibility to maintain the 00272 // pointer. The animation will automatically unbind 00273 // itself when the AnimControl destructs (i.e. its 00274 // reference count goes to zero). 00275 //////////////////////////////////////////////////////////////////// 00276 PT(AnimControl) PartBundle:: 00277 bind_anim(AnimBundle *anim, int hierarchy_match_flags, 00278 const PartSubset &subset) { 00279 PT(AnimControl) control = new AnimControl(anim->get_name(), this, 1.0f, 0); 00280 if (do_bind_anim(control, anim, hierarchy_match_flags, subset)) { 00281 return control; 00282 } 00283 00284 return NULL; 00285 } 00286 00287 //////////////////////////////////////////////////////////////////// 00288 // Function: PartBundle::load_bind_anim 00289 // Access: Published 00290 // Description: Binds an animation to the bundle. The animation is 00291 // loaded from the disk via the indicated Loader object. 00292 // In other respects, this behaves similarly to 00293 // bind_anim(), with the addition of asynchronous 00294 // support. 00295 // 00296 // If allow_aysnc is true, the load will be asynchronous 00297 // if possible. This requires that the animation 00298 // basename can be found in the PartBundle's preload 00299 // table (see get_anim_preload()). 00300 // 00301 // In an asynchronous load, the animation file will be 00302 // loaded and bound in a sub-thread. This means that 00303 // the animation will not necessarily be available at 00304 // the time this method returns. You may still use the 00305 // returned AnimControl immediately, though, but no 00306 // visible effect will occur until the animation 00307 // eventually becomes available. 00308 // 00309 // You can test AnimControl::is_pending() to see if the 00310 // animation has been loaded yet, or wait for it to 00311 // finish with AnimControl::wait_pending() or even 00312 // PartBundle::wait_pending(). You can also set an 00313 // event to be triggered when the animation finishes 00314 // loading with AnimControl::set_pending_done_event(). 00315 //////////////////////////////////////////////////////////////////// 00316 PT(AnimControl) PartBundle:: 00317 load_bind_anim(Loader *loader, const Filename &filename, 00318 int hierarchy_match_flags, const PartSubset &subset, 00319 bool allow_async) { 00320 nassertr(loader != (Loader *)NULL, NULL); 00321 00322 LoaderOptions anim_options(LoaderOptions::LF_search | 00323 LoaderOptions::LF_report_errors | 00324 LoaderOptions::LF_convert_anim); 00325 string basename = filename.get_basename_wo_extension(); 00326 00327 int anim_index = -1; 00328 CPT(AnimPreloadTable) anim_preload = _anim_preload.get_read_pointer(); 00329 if (anim_preload != (AnimPreloadTable *)NULL) { 00330 anim_index = anim_preload->find_anim(basename); 00331 } 00332 00333 if (anim_index < 0 || !allow_async || !Thread::is_threading_supported()) { 00334 // The animation is not present in the table, or allow_async is 00335 // false. Therefore, perform an ordinary synchronous 00336 // load-and-bind. 00337 00338 PT(PandaNode) model = loader->load_sync(filename, anim_options); 00339 if (model == (PandaNode *)NULL) { 00340 // Couldn't load the file. 00341 return NULL; 00342 } 00343 AnimBundle *anim = AnimBundleNode::find_anim_bundle(model); 00344 if (anim == (AnimBundle *)NULL) { 00345 // No anim bundle. 00346 return NULL; 00347 } 00348 PT(AnimControl) control = bind_anim(anim, hierarchy_match_flags, subset); 00349 if (control == (AnimControl *)NULL) { 00350 // Couldn't bind. 00351 return NULL; 00352 } 00353 control->set_anim_model(model); 00354 return control; 00355 } 00356 00357 // The animation is present in the table, so we can perform an 00358 // asynchronous load-and-bind. 00359 PN_stdfloat frame_rate = anim_preload->get_base_frame_rate(anim_index); 00360 int num_frames = anim_preload->get_num_frames(anim_index); 00361 PT(AnimControl) control = 00362 new AnimControl(basename, this, frame_rate, num_frames); 00363 00364 if (!subset.is_include_empty()) { 00365 // Figure out the actual subset of joints to be bound. 00366 int joint_index = 0; 00367 BitArray bound_joints; 00368 find_bound_joints(joint_index, false, bound_joints, subset); 00369 control->set_bound_joints(bound_joints); 00370 } 00371 00372 PT(BindAnimRequest) request = 00373 new BindAnimRequest(string("bind:") + filename.get_basename(), 00374 filename, anim_options, loader, control, 00375 hierarchy_match_flags, subset); 00376 request->set_priority(async_bind_priority); 00377 loader->load_async(request); 00378 00379 return control; 00380 } 00381 00382 //////////////////////////////////////////////////////////////////// 00383 // Function: PartBundle::wait_pending 00384 // Access: Published 00385 // Description: Blocks the current thread until all currently-pending 00386 // AnimControls, with a nonzero control effect, have 00387 // been loaded and are properly bound. 00388 //////////////////////////////////////////////////////////////////// 00389 void PartBundle:: 00390 wait_pending() { 00391 CDReader cdata(_cycler); 00392 ChannelBlend::const_iterator cbi; 00393 for (cbi = cdata->_blend.begin(); 00394 cbi != cdata->_blend.end(); 00395 ++cbi) { 00396 AnimControl *control = (*cbi).first; 00397 PN_stdfloat effect = (*cbi).second; 00398 if (effect != 0.0f) { 00399 control->wait_pending(); 00400 } 00401 } 00402 } 00403 00404 //////////////////////////////////////////////////////////////////// 00405 // Function: PartBundle::freeze_joint 00406 // Access: Published 00407 // Description: Specifies that the joint with the indicated name 00408 // should be frozen with the specified transform. It 00409 // will henceforth always hold this fixed transform, 00410 // regardless of any animations that may subsequently be 00411 // bound to the joint. 00412 // 00413 // Returns true if the joint is successfully frozen, or 00414 // false if the named child is not a joint (or slider) 00415 // or does not exist. 00416 //////////////////////////////////////////////////////////////////// 00417 bool PartBundle:: 00418 freeze_joint(const string &joint_name, const TransformState *transform) { 00419 PartGroup *child = find_child(joint_name); 00420 if (child == (PartGroup *)NULL) { 00421 return false; 00422 } 00423 00424 CDWriter cdata(_cycler, false); 00425 cdata->_anim_changed = true; 00426 00427 return child->apply_freeze(transform); 00428 } 00429 00430 //////////////////////////////////////////////////////////////////// 00431 // Function: PartBundle::freeze_joint 00432 // Access: Published 00433 // Description: Specifies that the joint with the indicated name 00434 // should be frozen with the specified transform. It 00435 // will henceforth always hold this fixed transform, 00436 // regardless of any animations that may subsequently be 00437 // bound to the joint. 00438 // 00439 // Returns true if the joint is successfully frozen, or 00440 // false if the named child is not a joint (or slider) 00441 // or does not exist. 00442 //////////////////////////////////////////////////////////////////// 00443 bool PartBundle:: 00444 freeze_joint(const string &joint_name, const LVecBase3 &pos, const LVecBase3 &hpr, const LVecBase3 &scale) { 00445 PartGroup *child = find_child(joint_name); 00446 if (child == (PartGroup *)NULL) { 00447 return false; 00448 } 00449 00450 CDWriter cdata(_cycler, false); 00451 cdata->_anim_changed = true; 00452 00453 return child->apply_freeze_matrix(pos, hpr, scale); 00454 } 00455 00456 //////////////////////////////////////////////////////////////////// 00457 // Function: PartBundle::freeze_joint 00458 // Access: Published 00459 // Description: Specifies that the joint with the indicated name 00460 // should be frozen with the specified transform. It 00461 // will henceforth always hold this fixed transform, 00462 // regardless of any animations that may subsequently be 00463 // bound to the joint. 00464 // 00465 // Returns true if the joint is successfully frozen, or 00466 // false if the named child is not a joint (or slider) 00467 // or does not exist. 00468 //////////////////////////////////////////////////////////////////// 00469 bool PartBundle:: 00470 freeze_joint(const string &joint_name, PN_stdfloat value) { 00471 PartGroup *child = find_child(joint_name); 00472 if (child == (PartGroup *)NULL) { 00473 return false; 00474 } 00475 00476 CDWriter cdata(_cycler, false); 00477 cdata->_anim_changed = true; 00478 00479 return child->apply_freeze_scalar(value); 00480 } 00481 00482 //////////////////////////////////////////////////////////////////// 00483 // Function: PartBundle::control_joint 00484 // Access: Published 00485 // Description: Specifies that the joint with the indicated name 00486 // should be animated with the transform on the 00487 // indicated node. It will henceforth always follow the 00488 // node's transform, regardless of any animations that 00489 // may subsequently be bound to the joint. 00490 // 00491 // Returns true if the joint is successfully controlled, 00492 // or false if the named child is not a joint (or 00493 // slider) or does not exist. 00494 //////////////////////////////////////////////////////////////////// 00495 bool PartBundle:: 00496 control_joint(const string &joint_name, PandaNode *node) { 00497 PartGroup *child = find_child(joint_name); 00498 if (child == (PartGroup *)NULL) { 00499 return false; 00500 } 00501 00502 CDWriter cdata(_cycler, false); 00503 cdata->_anim_changed = true; 00504 00505 return child->apply_control(node); 00506 } 00507 00508 //////////////////////////////////////////////////////////////////// 00509 // Function: PartBundle::release_joint 00510 // Access: Published 00511 // Description: Releases the named joint from the effects of a 00512 // previous call to freeze_joint() or control_joint(). 00513 // It will henceforth once again follow whatever 00514 // transforms are dictated by the animation. 00515 // 00516 // Returns true if the joint is released, or false if 00517 // the named child was not previously controlled or 00518 // frozen, or it does not exist. 00519 //////////////////////////////////////////////////////////////////// 00520 bool PartBundle:: 00521 release_joint(const string &joint_name) { 00522 PartGroup *child = find_child(joint_name); 00523 if (child == (PartGroup *)NULL) { 00524 return false; 00525 } 00526 00527 CDWriter cdata(_cycler, false); 00528 cdata->_anim_changed = true; 00529 00530 return child->clear_forced_channel(); 00531 } 00532 00533 //////////////////////////////////////////////////////////////////// 00534 // Function: PartBundle::update 00535 // Access: Published 00536 // Description: Updates all the parts in the bundle to reflect the 00537 // data for the current frame (as set in each of the 00538 // AnimControls). 00539 // 00540 // Returns true if any part has changed as a result of 00541 // this, or false otherwise. 00542 //////////////////////////////////////////////////////////////////// 00543 bool PartBundle:: 00544 update() { 00545 Thread *current_thread = Thread::get_current_thread(); 00546 CDWriter cdata(_cycler, false, current_thread); 00547 bool any_changed = false; 00548 00549 double now = ClockObject::get_global_clock()->get_frame_time(current_thread); 00550 if (now > cdata->_last_update + _update_delay || cdata->_anim_changed) { 00551 bool anim_changed = cdata->_anim_changed; 00552 bool frame_blend_flag = cdata->_frame_blend_flag; 00553 00554 any_changed = do_update(this, cdata, NULL, false, anim_changed, 00555 current_thread); 00556 00557 // Now update all the controls for next time. 00558 ChannelBlend::const_iterator cbi; 00559 for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) { 00560 AnimControl *control = (*cbi).first; 00561 control->mark_channels(frame_blend_flag); 00562 } 00563 00564 cdata->_anim_changed = false; 00565 cdata->_last_update = now; 00566 } 00567 00568 return any_changed; 00569 } 00570 00571 //////////////////////////////////////////////////////////////////// 00572 // Function: PartBundle::force_update 00573 // Access: Published 00574 // Description: Updates all the parts in the bundle to reflect the 00575 // data for the current frame, whether we believe it 00576 // needs it or not. 00577 //////////////////////////////////////////////////////////////////// 00578 bool PartBundle:: 00579 force_update() { 00580 Thread *current_thread = Thread::get_current_thread(); 00581 CDWriter cdata(_cycler, false, current_thread); 00582 bool any_changed = do_update(this, cdata, NULL, true, true, current_thread); 00583 00584 // Now update all the controls for next time. 00585 ChannelBlend::const_iterator cbi; 00586 for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) { 00587 AnimControl *control = (*cbi).first; 00588 control->mark_channels(cdata->_frame_blend_flag); 00589 } 00590 00591 cdata->_anim_changed = false; 00592 00593 return any_changed; 00594 } 00595 00596 00597 //////////////////////////////////////////////////////////////////// 00598 // Function: PartBundle::control_activated 00599 // Access: Public, Virtual 00600 // Description: Called by the AnimControl whenever it starts an 00601 // animation. This is just a hook so the bundle can do 00602 // something, if necessary, before the animation starts. 00603 //////////////////////////////////////////////////////////////////// 00604 void PartBundle:: 00605 control_activated(AnimControl *control) { 00606 nassertv(Thread::get_current_pipeline_stage() == 0); 00607 nassertv(control->get_part() == this); 00608 00609 CDLockedReader cdata(_cycler); 00610 00611 // If (and only if) our anim_blend_flag is false, then starting an 00612 // animation implicitly enables it. 00613 if (!cdata->_anim_blend_flag) { 00614 CDWriter cdataw(_cycler, cdata); 00615 do_set_control_effect(control, 1.0f, cdataw); 00616 } 00617 } 00618 00619 //////////////////////////////////////////////////////////////////// 00620 // Function: PartBundle::do_bind_anim 00621 // Access: Public 00622 // Description: The internal implementation of bind_anim(), this 00623 // receives a pointer to an uninitialized AnimControl 00624 // and fills it in if the bind is successful. Returns 00625 // true if successful, false otherwise. 00626 //////////////////////////////////////////////////////////////////// 00627 bool PartBundle:: 00628 do_bind_anim(AnimControl *control, AnimBundle *anim, 00629 int hierarchy_match_flags, const PartSubset &subset) { 00630 nassertr(Thread::get_current_pipeline_stage() == 0, false); 00631 00632 // Make sure this pointer doesn't destruct during the lifetime of this 00633 // method. 00634 PT(AnimBundle) ptanim = anim; 00635 00636 if ((hierarchy_match_flags & HMF_ok_wrong_root_name) == 0) { 00637 // Make sure the root names match. 00638 if (get_name() != ptanim->get_name()) { 00639 if (chan_cat.is_error()) { 00640 chan_cat.error() 00641 << "Root name of part (" << get_name() 00642 << ") does not match that of anim (" << ptanim->get_name() 00643 << ")\n"; 00644 } 00645 return false; 00646 } 00647 } 00648 00649 if (!check_hierarchy(anim, NULL, hierarchy_match_flags)) { 00650 return false; 00651 } 00652 00653 plist<int> holes; 00654 int channel_index = 0; 00655 pick_channel_index(holes, channel_index); 00656 00657 if (!holes.empty()) { 00658 channel_index = holes.front(); 00659 } 00660 00661 int joint_index = 0; 00662 BitArray bound_joints; 00663 if (subset.is_include_empty()) { 00664 bound_joints = BitArray::all_on(); 00665 } 00666 bind_hierarchy(ptanim, channel_index, joint_index, 00667 subset.is_include_empty(), bound_joints, subset); 00668 control->setup_anim(this, anim, channel_index, bound_joints); 00669 00670 CDReader cdata(_cycler); 00671 determine_effective_channels(cdata); 00672 00673 return true; 00674 } 00675 00676 //////////////////////////////////////////////////////////////////// 00677 // Function: PartBundle::add_node 00678 // Access: Protected, Virtual 00679 // Description: Adds the PartBundleNode pointer to the set of nodes 00680 // associated with the PartBundle. Normally called only 00681 // by the PartBundleNode itself, for instance when the 00682 // bundle is flattened with another node. 00683 //////////////////////////////////////////////////////////////////// 00684 void PartBundle:: 00685 add_node(PartBundleNode *node) { 00686 nassertv(find(_nodes.begin(), _nodes.end(), node) == _nodes.end()); 00687 _nodes.push_back(node); 00688 } 00689 00690 //////////////////////////////////////////////////////////////////// 00691 // Function: PartBundle::remove_node 00692 // Access: Protected, Virtual 00693 // Description: Removes the PartBundleNode pointer from the set of 00694 // nodes associated with the PartBundle. Normally 00695 // called only by the PartBundleNode itself, for 00696 // instance when the bundle is flattened with another 00697 // node. 00698 //////////////////////////////////////////////////////////////////// 00699 void PartBundle:: 00700 remove_node(PartBundleNode *node) { 00701 Nodes::iterator ni = find(_nodes.begin(), _nodes.end(), node); 00702 nassertv(ni != _nodes.end()); 00703 _nodes.erase(ni); 00704 } 00705 00706 //////////////////////////////////////////////////////////////////// 00707 // Function: PartBundle::do_set_control_effect 00708 // Access: Private 00709 // Description: The private implementation of set_control_effect(). 00710 //////////////////////////////////////////////////////////////////// 00711 void PartBundle:: 00712 do_set_control_effect(AnimControl *control, PN_stdfloat effect, CData *cdata) { 00713 nassertv(control->get_part() == this); 00714 00715 if (effect == 0.0f) { 00716 // An effect of zero means to eliminate the control. 00717 ChannelBlend::iterator cbi = cdata->_blend.find(control); 00718 if (cbi != cdata->_blend.end()) { 00719 cdata->_blend.erase(cbi); 00720 cdata->_anim_changed = true; 00721 } 00722 00723 } else { 00724 // Otherwise we define it. 00725 00726 // If anim_blend_flag is false, we only allow one AnimControl at a 00727 // time. Stop all of the other AnimControls. 00728 if (!cdata->_anim_blend_flag) { 00729 clear_and_stop_intersecting(control, cdata); 00730 } 00731 00732 if (do_get_control_effect(control, cdata) != effect) { 00733 cdata->_blend[control] = effect; 00734 cdata->_anim_changed = true; 00735 } 00736 cdata->_last_control_set = control; 00737 } 00738 00739 recompute_net_blend(cdata); 00740 } 00741 00742 //////////////////////////////////////////////////////////////////// 00743 // Function: PartBundle::do_get_control_effect 00744 // Access: Private 00745 // Description: The private implementation of get_control_effect(). 00746 //////////////////////////////////////////////////////////////////// 00747 PN_stdfloat PartBundle:: 00748 do_get_control_effect(AnimControl *control, const CData *cdata) const { 00749 nassertr(control->get_part() == this, 0.0f); 00750 00751 ChannelBlend::const_iterator cbi = cdata->_blend.find(control); 00752 if (cbi == cdata->_blend.end()) { 00753 // The control is not in effect. 00754 return 0.0f; 00755 } else { 00756 return (*cbi).second; 00757 } 00758 } 00759 00760 00761 //////////////////////////////////////////////////////////////////// 00762 // Function: PartBundle::recompute_net_blend 00763 // Access: Private 00764 // Description: Recomputes the total blending amount after a control 00765 // effect has been adjusted. This value must be kept 00766 // up-to-date so we can normalize the blending amounts. 00767 //////////////////////////////////////////////////////////////////// 00768 void PartBundle:: 00769 recompute_net_blend(CData *cdata) { 00770 cdata->_net_blend = 0.0f; 00771 00772 ChannelBlend::const_iterator bti; 00773 for (bti = cdata->_blend.begin(); bti != cdata->_blend.end(); ++bti) { 00774 cdata->_net_blend += (*bti).second; 00775 } 00776 determine_effective_channels(cdata); 00777 } 00778 00779 //////////////////////////////////////////////////////////////////// 00780 // Function: PartBundle::clear_and_stop_intersecting 00781 // Access: Private 00782 // Description: Removes and stops all the currently activated 00783 // AnimControls that animate some joints also animated 00784 // by the indicated AnimControl. This is a special 00785 // internal function that's only called when 00786 // _anim_blend_flag is false, to automatically stop all 00787 // the other currently-executing animations. 00788 //////////////////////////////////////////////////////////////////// 00789 void PartBundle:: 00790 clear_and_stop_intersecting(AnimControl *control, CData *cdata) { 00791 double new_net_blend = 0.0f; 00792 ChannelBlend new_blend; 00793 bool any_changed = false; 00794 00795 ChannelBlend::iterator cbi; 00796 for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) { 00797 AnimControl *ac = (*cbi).first; 00798 if (ac == control || 00799 !ac->get_bound_joints().has_bits_in_common(control->get_bound_joints())) { 00800 // Save this control--it's either the target control, or it has 00801 // no joints in common with the target control. 00802 new_blend.insert(new_blend.end(), (*cbi)); 00803 new_net_blend += (*cbi).second; 00804 } else { 00805 // Remove and stop this control. 00806 ac->stop(); 00807 any_changed = true; 00808 } 00809 } 00810 00811 if (any_changed) { 00812 cdata->_net_blend = new_net_blend; 00813 cdata->_blend.swap(new_blend); 00814 cdata->_anim_changed = true; 00815 determine_effective_channels(cdata); 00816 } 00817 } 00818 00819 //////////////////////////////////////////////////////////////////// 00820 // Function: PartBundle::finalize 00821 // Access: Public, Virtual 00822 // Description: Called by the BamReader to perform any final actions 00823 // needed for setting up the object after all objects 00824 // have been read and all pointers have been completed. 00825 //////////////////////////////////////////////////////////////////// 00826 void PartBundle:: 00827 finalize(BamReader *) { 00828 Thread *current_thread = Thread::get_current_thread(); 00829 CDWriter cdata(_cycler, true); 00830 do_update(this, cdata, NULL, true, true, current_thread); 00831 } 00832 00833 //////////////////////////////////////////////////////////////////// 00834 // Function: PartBundle::write_datagram 00835 // Access: Public, Virtual 00836 // Description: Writes the contents of this object to the datagram 00837 // for shipping out to a Bam file. 00838 //////////////////////////////////////////////////////////////////// 00839 void PartBundle:: 00840 write_datagram(BamWriter *manager, Datagram &dg) { 00841 PartGroup::write_datagram(manager, dg); 00842 manager->write_pointer(dg, _anim_preload.get_read_pointer()); 00843 manager->write_cdata(dg, _cycler); 00844 } 00845 00846 //////////////////////////////////////////////////////////////////// 00847 // Function: PartBundle::complete_pointers 00848 // Access: Public 00849 // Description: Takes in a vector of pointers to TypedWritable 00850 // objects that correspond to all the requests for 00851 // pointers that this object made to BamReader. 00852 //////////////////////////////////////////////////////////////////// 00853 int PartBundle:: 00854 complete_pointers(TypedWritable **p_list, BamReader *manager) { 00855 int pi = PartGroup::complete_pointers(p_list, manager); 00856 00857 if (manager->get_file_minor_ver() >= 17) { 00858 _anim_preload = DCAST(AnimPreloadTable, p_list[pi++]); 00859 } 00860 00861 return pi; 00862 } 00863 00864 //////////////////////////////////////////////////////////////////// 00865 // Function: PartBundle::make_from_bam 00866 // Access: Protected 00867 // Description: Factory method to generate a PartBundle object 00868 //////////////////////////////////////////////////////////////////// 00869 TypedWritable* PartBundle:: 00870 make_from_bam(const FactoryParams ¶ms) { 00871 PartBundle *me = new PartBundle; 00872 DatagramIterator scan; 00873 BamReader *manager; 00874 00875 parse_params(params, scan, manager); 00876 me->fillin(scan, manager); 00877 manager->register_finalize(me); 00878 return me; 00879 } 00880 00881 //////////////////////////////////////////////////////////////////// 00882 // Function: PartBundle::fillin 00883 // Access: Protected 00884 // Description: This internal function is called by make_from_bam to 00885 // read in all of the relevant data from the BamFile for 00886 // the new PartBundle. 00887 //////////////////////////////////////////////////////////////////// 00888 void PartBundle:: 00889 fillin(DatagramIterator &scan, BamReader *manager) { 00890 PartGroup::fillin(scan, manager); 00891 if (manager->get_file_minor_ver() >= 17) { 00892 manager->read_pointer(scan); // _anim_preload 00893 } 00894 if (manager->get_file_minor_ver() >= 10) { 00895 manager->read_cdata(scan, _cycler); 00896 } 00897 if (manager->get_file_minor_ver() == 11) { 00898 // No longer need the _modifies_anim_bundles flag 00899 scan.get_bool(); 00900 } 00901 } 00902 00903 //////////////////////////////////////////////////////////////////// 00904 // Function: PartBundle::register_with_factory 00905 // Access: Public, Static 00906 // Description: Factory method to generate a PartBundle object 00907 //////////////////////////////////////////////////////////////////// 00908 void PartBundle:: 00909 register_with_read_factory() { 00910 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 00911 } 00912 00913 //////////////////////////////////////////////////////////////////// 00914 // Function: PartBundle::CData::Constructor 00915 // Access: Public 00916 // Description: 00917 //////////////////////////////////////////////////////////////////// 00918 PartBundle::CData:: 00919 CData() { 00920 _blend_type = anim_blend_type; 00921 _anim_blend_flag = false; 00922 _frame_blend_flag = interpolate_frames; 00923 _root_xform = LMatrix4::ident_mat(); 00924 _last_control_set = NULL; 00925 _net_blend = 0.0f; 00926 _anim_changed = false; 00927 _last_update = 0.0; 00928 } 00929 00930 //////////////////////////////////////////////////////////////////// 00931 // Function: PartBundle::CData::Copy Constructor 00932 // Access: Public 00933 // Description: 00934 //////////////////////////////////////////////////////////////////// 00935 PartBundle::CData:: 00936 CData(const PartBundle::CData ©) : 00937 _blend_type(copy._blend_type), 00938 _anim_blend_flag(copy._anim_blend_flag), 00939 _frame_blend_flag(copy._frame_blend_flag), 00940 _root_xform(copy._root_xform), 00941 _last_control_set(copy._last_control_set), 00942 _blend(copy._blend), 00943 _net_blend(copy._net_blend), 00944 _anim_changed(copy._anim_changed), 00945 _last_update(copy._last_update) 00946 { 00947 // Note that this copy constructor is not used by the PartBundle 00948 // copy constructor! Any elements that must be copied between 00949 // PartBundles should also be explicitly copied there. 00950 } 00951 00952 //////////////////////////////////////////////////////////////////// 00953 // Function: PartBundle::CData::make_copy 00954 // Access: Public, Virtual 00955 // Description: 00956 //////////////////////////////////////////////////////////////////// 00957 CycleData *PartBundle::CData:: 00958 make_copy() const { 00959 return new CData(*this); 00960 } 00961 00962 //////////////////////////////////////////////////////////////////// 00963 // Function: PartBundle::CData::write_datagram 00964 // Access: Public, Virtual 00965 // Description: Writes the contents of this object to the datagram 00966 // for shipping out to a Bam file. 00967 //////////////////////////////////////////////////////////////////// 00968 void PartBundle::CData:: 00969 write_datagram(BamWriter *manager, Datagram &dg) const { 00970 dg.add_uint8(_blend_type); 00971 dg.add_bool(_anim_blend_flag); 00972 dg.add_bool(_frame_blend_flag); 00973 _root_xform.write_datagram(dg); 00974 00975 // The remaining members are strictly dynamic. 00976 } 00977 00978 //////////////////////////////////////////////////////////////////// 00979 // Function: PartBundle::CData::fillin 00980 // Access: Public, Virtual 00981 // Description: This internal function is called by make_from_bam to 00982 // read in all of the relevant data from the BamFile for 00983 // the new PartBundle. 00984 //////////////////////////////////////////////////////////////////// 00985 void PartBundle::CData:: 00986 fillin(DatagramIterator &scan, BamReader *manager) { 00987 _blend_type = (BlendType)scan.get_uint8(); 00988 _anim_blend_flag = scan.get_bool(); 00989 _frame_blend_flag = scan.get_bool(); 00990 _root_xform.read_datagram(scan); 00991 } 00992 00993 //////////////////////////////////////////////////////////////////// 00994 // Function: PartBundle::BlendType output operator 00995 // Description: 00996 //////////////////////////////////////////////////////////////////// 00997 ostream & 00998 operator << (ostream &out, PartBundle::BlendType blend_type) { 00999 switch (blend_type) { 01000 case PartBundle::BT_linear: 01001 return out << "linear"; 01002 01003 case PartBundle::BT_normalized_linear: 01004 return out << "normalized_linear"; 01005 01006 case PartBundle::BT_componentwise: 01007 return out << "componentwise"; 01008 01009 case PartBundle::BT_componentwise_quat: 01010 return out << "componentwise_quat"; 01011 } 01012 01013 chan_cat->error() 01014 << "Invalid BlendType value: " << (int)blend_type << "\n"; 01015 nassertr(false, out); 01016 return out; 01017 } 01018 01019 //////////////////////////////////////////////////////////////////// 01020 // Function: PartBundle::BlendType input operator 01021 // Description: 01022 //////////////////////////////////////////////////////////////////// 01023 istream & 01024 operator >> (istream &in, PartBundle::BlendType &blend_type) { 01025 string word; 01026 in >> word; 01027 01028 if (cmp_nocase_uh(word, "linear") == 0) { 01029 blend_type = PartBundle::BT_linear; 01030 01031 } else if (cmp_nocase_uh(word, "normalized_linear") == 0) { 01032 blend_type = PartBundle::BT_normalized_linear; 01033 01034 } else if (cmp_nocase_uh(word, "componentwise") == 0) { 01035 blend_type = PartBundle::BT_componentwise; 01036 01037 } else if (cmp_nocase_uh(word, "componentwise_quat") == 0) { 01038 blend_type = PartBundle::BT_componentwise_quat; 01039 01040 } else { 01041 chan_cat->error() 01042 << "Invalid BlendType string: " << word << "\n"; 01043 blend_type = PartBundle::BT_linear; 01044 } 01045 return in; 01046 }