Panda3D
 All Classes Functions Variables Enumerations
partBundle.cxx
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 &copy) :
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 &params) {
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 &copy) :
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 }
 All Classes Functions Variables Enumerations