Panda3D

animControl.cxx

00001 // Filename: animControl.cxx
00002 // Created by:  drose (19Feb99)
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 #include "animControl.h"
00016 #include "animChannelBase.h"
00017 #include "partBundle.h"
00018 #include "config_chan.h"
00019 #include "dcast.h"
00020 #include "mutexHolder.h"
00021 #include "throw_event.h"
00022 
00023 TypeHandle AnimControl::_type_handle;
00024 
00025 ////////////////////////////////////////////////////////////////////
00026 //     Function: AnimControl::Constructor
00027 //       Access: Public
00028 //  Description: This constructor is used to create a temporarily
00029 //               uninitialized AnimControl that will serve as a
00030 //               placeholder for an animation while the animation is
00031 //               being loaded during an asynchronous load-and-bind
00032 //               operation.
00033 ////////////////////////////////////////////////////////////////////
00034 AnimControl::
00035 AnimControl(const string &name, PartBundle *part, 
00036             double frame_rate, int num_frames) :
00037   Namable(name),
00038   _pending_lock(name),
00039   _pending_cvar(_pending_lock),
00040   _bound_joints(BitArray::all_on())
00041 {
00042 #ifdef DO_MEMORY_USAGE
00043   MemoryUsage::update_type(this, get_class_type());
00044 #endif
00045 
00046   _pending = true;
00047   _part = part;
00048   _anim = NULL;
00049   _channel_index = -1;
00050   set_frame_rate(frame_rate);
00051   set_num_frames(num_frames);
00052 
00053   _marked_frame = -1;
00054 }
00055 
00056 ////////////////////////////////////////////////////////////////////
00057 //     Function: AnimControl::setup_anim
00058 //       Access: Public
00059 //  Description: This can only be called once for a given AnimControl.
00060 //               It is used to supply the AnimBundle and related
00061 //               information.
00062 ////////////////////////////////////////////////////////////////////
00063 void AnimControl::
00064 setup_anim(PartBundle *part, AnimBundle *anim, int channel_index, 
00065            const BitArray &bound_joints) {
00066   MutexHolder holder(_pending_lock);
00067   nassertv(_pending && part == _part);
00068   nassertv(_anim == (AnimBundle *)NULL);
00069   _anim = anim;
00070   _channel_index = channel_index;
00071   _bound_joints = bound_joints;
00072   set_frame_rate(_anim->get_base_frame_rate());
00073   set_num_frames(_anim->get_num_frames());
00074 
00075   // Now the AnimControl is fully set up.
00076   _marked_frame = -1;
00077   _pending = false;
00078   _pending_cvar.notify_all();
00079   if (!_pending_done_event.empty()) {
00080     throw_event(_pending_done_event);
00081   }
00082 }
00083 
00084 ////////////////////////////////////////////////////////////////////
00085 //     Function: AnimControl::set_bound_joints
00086 //       Access: Public
00087 //  Description: Called to initialize the AnimControl with its array
00088 //               of bound_joints, before setup_anim() has completed.
00089 ////////////////////////////////////////////////////////////////////
00090 void AnimControl::
00091 set_bound_joints(const BitArray &bound_joints) {
00092   MutexHolder holder(_pending_lock);
00093   _bound_joints = bound_joints;
00094 }
00095 
00096 ////////////////////////////////////////////////////////////////////
00097 //     Function: AnimControl::fail_anim
00098 //       Access: Public
00099 //  Description: This can only be called once for a given AnimControl.
00100 //               It indicates the attempt to bind it asynchronously
00101 //               has failed.
00102 ////////////////////////////////////////////////////////////////////
00103 void AnimControl::
00104 fail_anim(PartBundle *part) {
00105   MutexHolder holder(_pending_lock);
00106   nassertv(_pending && part == _part);
00107   _pending = false;
00108   _pending_cvar.notify_all();
00109   if (!_pending_done_event.empty()) {
00110     throw_event(_pending_done_event);
00111   }
00112 }
00113 
00114 ////////////////////////////////////////////////////////////////////
00115 //     Function: AnimControl::Destructor
00116 //       Access: Published, Virtual
00117 //  Description:
00118 ////////////////////////////////////////////////////////////////////
00119 AnimControl::
00120 ~AnimControl() {
00121   get_part()->set_control_effect(this, 0.0f);
00122 }
00123 
00124 ////////////////////////////////////////////////////////////////////
00125 //     Function: AnimControl::wait_pending
00126 //       Access: Published
00127 //  Description: Blocks the current thread until the AnimControl has
00128 //               finished loading and is fully bound.
00129 ////////////////////////////////////////////////////////////////////
00130 void AnimControl::
00131 wait_pending() {
00132   MutexHolder holder(_pending_lock);
00133   if (_pending) {
00134     // TODO: we should elevate the priority of the associated
00135     // BindAnimRequest while we're waiting for it, so it will jump to
00136     // the front of the queue.
00137     chan_cat.info()
00138       << "Blocking " << *Thread::get_current_thread() 
00139       << " until " << get_name() << " is bound\n";
00140     while (_pending) {
00141       _pending_cvar.wait();
00142     }
00143   }
00144 }
00145 
00146 ////////////////////////////////////////////////////////////////////
00147 //     Function: AnimControl::set_pending_done_event
00148 //       Access: Published
00149 //  Description: Specifies an event name that will be thrown when the
00150 //               AnimControl is finished binding asynchronously.  If
00151 //               the AnimControl has already finished binding, the
00152 //               event will be thrown immediately.
00153 ////////////////////////////////////////////////////////////////////
00154 void AnimControl::
00155 set_pending_done_event(const string &done_event) {
00156   MutexHolder holder(_pending_lock);
00157   _pending_done_event = done_event;
00158   if (!_pending) {
00159     throw_event(_pending_done_event);
00160   }
00161 }
00162 
00163 ////////////////////////////////////////////////////////////////////
00164 //     Function: AnimControl::get_pending_done_event
00165 //       Access: Published
00166 //  Description: Returns the event name that will be thrown when the
00167 //               AnimControl is finished binding asynchronously.
00168 ////////////////////////////////////////////////////////////////////
00169 string AnimControl::
00170 get_pending_done_event() const {
00171   MutexHolder holder(_pending_lock);
00172   return _pending_done_event;
00173 }
00174 
00175 ////////////////////////////////////////////////////////////////////
00176 //     Function: AnimControl::get_part
00177 //       Access: Published
00178 //  Description: Returns the PartBundle bound in with this
00179 //               AnimControl.
00180 ////////////////////////////////////////////////////////////////////
00181 PartBundle *AnimControl::
00182 get_part() const {
00183   return DCAST(PartBundle, _part);
00184 }
00185 
00186 ////////////////////////////////////////////////////////////////////
00187 //     Function: AnimControl::output
00188 //       Access: Published
00189 //  Description:
00190 ////////////////////////////////////////////////////////////////////
00191 void AnimControl::
00192 output(ostream &out) const {
00193   out << "AnimControl(" << get_name() << ", " << get_part()->get_name()
00194       << ": ";
00195   AnimInterface::output(out);
00196   out << ")";
00197 
00198   if (is_pending()) {
00199     out << " (pending bind)";
00200   } else if (!has_anim()) {
00201     out << " (failed bind)";
00202   }
00203 }
00204 
00205 ////////////////////////////////////////////////////////////////////
00206 //     Function: AnimControl::channel_has_changed
00207 //       Access: Public
00208 //  Description: Returns true if the indicated channel value has
00209 //               changed since the last call to mark_channels().
00210 ////////////////////////////////////////////////////////////////////
00211 bool AnimControl::
00212 channel_has_changed(AnimChannelBase *channel, bool frame_blend_flag) const {
00213   if (_marked_frame < 0) {
00214     return true;
00215   }
00216 
00217   int this_frame = get_frame();
00218   double this_frac = 0.0;
00219   if (frame_blend_flag) {
00220     this_frac = get_frac();
00221   }
00222   return channel->has_changed(_marked_frame, _marked_frac, 
00223                               this_frame, this_frac);
00224 }
00225 
00226 ////////////////////////////////////////////////////////////////////
00227 //     Function: AnimControl::mark_channels
00228 //       Access: Public
00229 //  Description: Marks this point as the point of reference for the
00230 //               next call to channel_has_changed().
00231 ////////////////////////////////////////////////////////////////////
00232 void AnimControl::
00233 mark_channels(bool frame_blend_flag) {
00234   _marked_frame = get_frame();
00235   _marked_frac = 0.0;
00236   if (frame_blend_flag) {
00237     _marked_frac = get_frac();
00238   }
00239 }
00240 
00241 ////////////////////////////////////////////////////////////////////
00242 //     Function: AnimControl::animation_activated
00243 //       Access: Protected, Virtual
00244 //  Description: This is provided as a callback method for when the
00245 //               user calls one of the play/loop/pose type methods to
00246 //               start the animation playing.
00247 ////////////////////////////////////////////////////////////////////
00248 void AnimControl::
00249 animation_activated() {
00250   get_part()->control_activated(this);
00251 }
 All Classes Functions Variables Enumerations