Panda3D
|
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 }