Panda3D
|
00001 // Filename: animInterface.cxx 00002 // Created by: drose (20Sep05) 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 "animInterface.h" 00016 #include "clockObject.h" 00017 #include "bamReader.h" 00018 #include "bamWriter.h" 00019 #include "datagram.h" 00020 #include "datagramIterator.h" 00021 00022 TypeHandle AnimInterface::_type_handle; 00023 00024 //////////////////////////////////////////////////////////////////// 00025 // Function: AnimInterface::Constructor 00026 // Access: Published 00027 // Description: 00028 //////////////////////////////////////////////////////////////////// 00029 AnimInterface:: 00030 AnimInterface() : 00031 _num_frames(0) 00032 { 00033 } 00034 00035 //////////////////////////////////////////////////////////////////// 00036 // Function: AnimInterface::Copy Constructor 00037 // Access: Published 00038 // Description: 00039 //////////////////////////////////////////////////////////////////// 00040 AnimInterface:: 00041 AnimInterface(const AnimInterface ©) : 00042 _num_frames(copy._num_frames), 00043 _cycler(copy._cycler) 00044 { 00045 } 00046 00047 //////////////////////////////////////////////////////////////////// 00048 // Function: AnimInterface::Destructor 00049 // Access: Published, Virtual 00050 // Description: 00051 //////////////////////////////////////////////////////////////////// 00052 AnimInterface:: 00053 ~AnimInterface() { 00054 } 00055 00056 //////////////////////////////////////////////////////////////////// 00057 // Function: AnimInterface::get_num_frames 00058 // Access: Published, Virtual 00059 // Description: Returns the number of frames in the animation. This 00060 // is a property of the animation and may not be 00061 // directly adjusted by the user (although it may change 00062 // without warning with certain kinds of animations, 00063 // since this is a virtual method that may be 00064 // overridden). 00065 //////////////////////////////////////////////////////////////////// 00066 int AnimInterface:: 00067 get_num_frames() const { 00068 return _num_frames; 00069 } 00070 00071 //////////////////////////////////////////////////////////////////// 00072 // Function: AnimInterface::output 00073 // Access: Published, Virtual 00074 // Description: 00075 //////////////////////////////////////////////////////////////////// 00076 void AnimInterface:: 00077 output(ostream &out) const { 00078 CDReader cdata(_cycler); 00079 cdata->output(out); 00080 } 00081 00082 //////////////////////////////////////////////////////////////////// 00083 // Function: AnimInterface::animation_activated 00084 // Access: Protected, Virtual 00085 // Description: This is provided as a callback method for when the 00086 // user calls one of the play/loop/pose type methods to 00087 // start the animation playing. 00088 //////////////////////////////////////////////////////////////////// 00089 void AnimInterface:: 00090 animation_activated() { 00091 } 00092 00093 //////////////////////////////////////////////////////////////////// 00094 // Function: AnimInterface::write_datagram 00095 // Access: Public, Virtual 00096 // Description: Writes the contents of this object to the datagram 00097 // for shipping out to a Bam file. 00098 //////////////////////////////////////////////////////////////////// 00099 void AnimInterface:: 00100 write_datagram(BamWriter *manager, Datagram &dg) { 00101 dg.add_int32(_num_frames); 00102 manager->write_cdata(dg, _cycler); 00103 } 00104 00105 //////////////////////////////////////////////////////////////////// 00106 // Function: AnimInterface::fillin 00107 // Access: Protected 00108 // Description: This internal function is called by make_from_bam to 00109 // read in all of the relevant data from the BamFile for 00110 // the new AnimInterface. 00111 //////////////////////////////////////////////////////////////////// 00112 void AnimInterface:: 00113 fillin(DatagramIterator &scan, BamReader *manager) { 00114 _num_frames = scan.get_int32(); 00115 manager->read_cdata(scan, _cycler); 00116 } 00117 00118 //////////////////////////////////////////////////////////////////// 00119 // Function: AnimInterface::CData::Constructor 00120 // Access: Published 00121 // Description: 00122 //////////////////////////////////////////////////////////////////// 00123 AnimInterface::CData:: 00124 CData() : 00125 _frame_rate(0.0), 00126 _play_mode(PM_pose), 00127 _start_time(0.0), 00128 _start_frame(0.0), 00129 _play_frames(0.0), 00130 _from_frame(0), 00131 _to_frame(0), 00132 _play_rate(1.0), 00133 _effective_frame_rate(0.0), 00134 _paused(true), 00135 _paused_f(0.0) 00136 { 00137 } 00138 00139 //////////////////////////////////////////////////////////////////// 00140 // Function: AnimInterface::CData::Copy Constructor 00141 // Access: Published 00142 // Description: 00143 //////////////////////////////////////////////////////////////////// 00144 AnimInterface::CData:: 00145 CData(const AnimInterface::CData ©) : 00146 _frame_rate(copy._frame_rate), 00147 _play_mode(copy._play_mode), 00148 _start_time(copy._start_time), 00149 _start_frame(copy._start_frame), 00150 _play_frames(copy._play_frames), 00151 _from_frame(copy._from_frame), 00152 _to_frame(copy._to_frame), 00153 _play_rate(copy._play_rate), 00154 _effective_frame_rate(copy._effective_frame_rate), 00155 _paused(copy._paused), 00156 _paused_f(copy._paused_f) 00157 { 00158 } 00159 00160 //////////////////////////////////////////////////////////////////// 00161 // Function: AnimInterface::CData::make_copy 00162 // Access: Public, Virtual 00163 // Description: 00164 //////////////////////////////////////////////////////////////////// 00165 CycleData *AnimInterface::CData:: 00166 make_copy() const { 00167 return new CData(*this); 00168 } 00169 00170 //////////////////////////////////////////////////////////////////// 00171 // Function: AnimInterface::CData::write_datagram 00172 // Access: Public, Virtual 00173 // Description: Writes the contents of this object to the datagram 00174 // for shipping out to a Bam file. 00175 //////////////////////////////////////////////////////////////////// 00176 void AnimInterface::CData:: 00177 write_datagram(BamWriter *, Datagram &dg) const { 00178 dg.add_stdfloat(_frame_rate); 00179 dg.add_uint8(_play_mode); 00180 dg.add_stdfloat(_start_time); 00181 dg.add_stdfloat(_start_frame); 00182 dg.add_stdfloat(_play_frames); 00183 dg.add_int32(_from_frame); 00184 dg.add_int32(_to_frame); 00185 dg.add_stdfloat(_play_rate); 00186 dg.add_bool(_paused); 00187 dg.add_stdfloat(_paused_f); 00188 } 00189 00190 //////////////////////////////////////////////////////////////////// 00191 // Function: AnimInterface::CData::fillin 00192 // Access: Public, Virtual 00193 // Description: This internal function is called by make_from_bam to 00194 // read in all of the relevant data from the BamFile for 00195 // the new AnimInterface. 00196 //////////////////////////////////////////////////////////////////// 00197 void AnimInterface::CData:: 00198 fillin(DatagramIterator &scan, BamReader *) { 00199 _frame_rate = scan.get_stdfloat(); 00200 _play_mode = (PlayMode)scan.get_uint8(); 00201 _start_time = scan.get_stdfloat(); 00202 _start_frame = scan.get_stdfloat(); 00203 _play_frames = scan.get_stdfloat(); 00204 _from_frame = scan.get_int32(); 00205 _to_frame = scan.get_int32(); 00206 _play_rate = scan.get_stdfloat(); 00207 _effective_frame_rate = _frame_rate * _play_rate; 00208 _paused = scan.get_bool(); 00209 _paused_f = scan.get_stdfloat(); 00210 } 00211 00212 //////////////////////////////////////////////////////////////////// 00213 // Function: AnimInterface::CData::play 00214 // Access: Public 00215 // Description: Runs the animation from the frame "from" to and 00216 // including the frame "to", at which point the 00217 // animation is stopped. Both "from" and "to" frame 00218 // numbers may be outside the range (0, 00219 // get_num_frames()) and the animation will follow the 00220 // range correctly, reporting numbers modulo 00221 // get_num_frames(). For instance, play(0, 00222 // get_num_frames() * 2) will play the animation twice 00223 // and then stop. 00224 //////////////////////////////////////////////////////////////////// 00225 void AnimInterface::CData:: 00226 play(double from, double to) { 00227 if (from >= to) { 00228 pose(from); 00229 return; 00230 } 00231 00232 _play_mode = PM_play; 00233 _start_time = ClockObject::get_global_clock()->get_frame_time(); 00234 _start_frame = from; 00235 _play_frames = to - from + 1.0; 00236 _from_frame = (int)floor(from); 00237 _to_frame = (int)floor(to); 00238 _paused_f = 0.0; 00239 00240 if (_effective_frame_rate < 0.0) { 00241 // If we'll be playing backward, start at the end. 00242 _start_time -= _play_frames / _effective_frame_rate; 00243 } 00244 } 00245 00246 //////////////////////////////////////////////////////////////////// 00247 // Function: AnimInterface::CData::loop 00248 // Access: Public 00249 // Description: Loops the animation from the frame "from" to and 00250 // including the frame "to", indefinitely. If restart 00251 // is true, the animation is restarted from the 00252 // beginning; otherwise, it continues from the current 00253 // frame. 00254 //////////////////////////////////////////////////////////////////// 00255 void AnimInterface::CData:: 00256 loop(bool restart, double from, double to) { 00257 if (from >= to) { 00258 pose(from); 00259 return; 00260 } 00261 00262 double fframe = get_full_fframe(); 00263 00264 _play_mode = PM_loop; 00265 _start_time = ClockObject::get_global_clock()->get_frame_time(); 00266 _start_frame = from; 00267 _play_frames = to - from + 1.0; 00268 _from_frame = (int)floor(from); 00269 _to_frame = (int)floor(to); 00270 _paused_f = 0.0; 00271 00272 if (!restart) { 00273 fframe = min(max(fframe, from), to); 00274 if (_paused) { 00275 _paused_f = fframe - _start_frame; 00276 } else { 00277 _start_time -= (fframe - _start_frame) / _effective_frame_rate; 00278 } 00279 } 00280 } 00281 00282 //////////////////////////////////////////////////////////////////// 00283 // Function: AnimInterface::CData::pingpong 00284 // Access: Public 00285 // Description: Loops the animation from the frame "from" to and 00286 // including the frame "to", and then back in the 00287 // opposite direction, indefinitely. 00288 //////////////////////////////////////////////////////////////////// 00289 void AnimInterface::CData:: 00290 pingpong(bool restart, double from, double to) { 00291 if (from >= to) { 00292 pose(from); 00293 return; 00294 } 00295 00296 double fframe = get_full_fframe(); 00297 00298 _play_mode = PM_pingpong; 00299 _start_time = ClockObject::get_global_clock()->get_frame_time(); 00300 _start_frame = from; 00301 _play_frames = to - from + 1.0; 00302 _from_frame = (int)floor(from); 00303 _to_frame = (int)floor(to); 00304 _paused_f = 0.0; 00305 00306 if (!restart) { 00307 fframe = min(max(fframe, from), to); 00308 if (_paused) { 00309 _paused_f = fframe - _start_frame; 00310 } else { 00311 _start_time -= (fframe - _start_frame) / _effective_frame_rate; 00312 } 00313 } 00314 } 00315 00316 //////////////////////////////////////////////////////////////////// 00317 // Function: AnimInterface::CData::pose 00318 // Access: Public 00319 // Description: Sets the animation to the indicated frame and holds 00320 // it there. 00321 //////////////////////////////////////////////////////////////////// 00322 void AnimInterface::CData:: 00323 pose(double frame) { 00324 _play_mode = PM_pose; 00325 _start_time = ClockObject::get_global_clock()->get_frame_time(); 00326 _start_frame = frame; 00327 _play_frames = 0.0; 00328 _from_frame = (int)floor(frame); 00329 _to_frame = (int)floor(frame); 00330 _paused_f = 0.0; 00331 } 00332 00333 //////////////////////////////////////////////////////////////////// 00334 // Function: AnimInterface::CData::get_full_frame 00335 // Access: Public 00336 // Description: Returns the current integer frame number, plus the 00337 // indicated increment. 00338 // 00339 // Unlike the value returned by get_frame(), this frame 00340 // number may extend beyond the range of 00341 // get_num_frames() if the frame range passed to play(), 00342 // loop(), etc. did. 00343 // 00344 // Unlike the value returned by get_full_fframe(), this 00345 // return value will never exceed the value passed to 00346 // to_frame in the play() method. 00347 //////////////////////////////////////////////////////////////////// 00348 int AnimInterface::CData:: 00349 get_full_frame(int increment) const { 00350 int frame = (int)floor(get_full_fframe()) + increment; 00351 if (_play_mode == PM_play) { 00352 // In play mode, we never let the return value exceed 00353 // (_from_frame, _to_frame). 00354 frame = min(max(frame, _from_frame), _to_frame); 00355 } 00356 return frame; 00357 } 00358 00359 //////////////////////////////////////////////////////////////////// 00360 // Function: AnimInterface::CData::get_full_fframe 00361 // Access: Public 00362 // Description: Returns the current floating-point frame number. 00363 // 00364 // Unlike the value returned by get_frame(), this frame 00365 // number may extend beyond the range of 00366 // get_num_frames() if the frame range passed to play(), 00367 // loop(), etc. did. 00368 // 00369 // Unlike the value returned by get_full_frame(), this 00370 // return value may equal (to_frame + 1.0), when the 00371 // animation has played to its natural end. However, in 00372 // this case the return value of get_full_frame() will 00373 // be to_frame, not (to_frame + 1). 00374 //////////////////////////////////////////////////////////////////// 00375 double AnimInterface::CData:: 00376 get_full_fframe() const { 00377 switch (_play_mode) { 00378 case PM_pose: 00379 return _start_frame; 00380 00381 case PM_play: 00382 return min(max(get_f(), 0.0), _play_frames) + _start_frame; 00383 00384 case PM_loop: 00385 nassertr(_play_frames >= 0.0, 0.0); 00386 return cmod(get_f(), _play_frames) + _start_frame; 00387 00388 case PM_pingpong: 00389 { 00390 nassertr(_play_frames >= 0.0, 0.0); 00391 double f = cmod(get_f(), _play_frames * 2.0); 00392 if (f > _play_frames) { 00393 return (_play_frames * 2.0 - f) + _start_frame; 00394 } else { 00395 return f + _start_frame; 00396 } 00397 } 00398 } 00399 00400 return _start_frame; 00401 } 00402 00403 //////////////////////////////////////////////////////////////////// 00404 // Function: AnimInterface::CData::is_playing 00405 // Access: Public 00406 // Description: Returns true if the animation is currently playing, 00407 // false if it is stopped (e.g. because stop() or pose() 00408 // was called, or because it reached the end of the 00409 // animation after play() was called). 00410 //////////////////////////////////////////////////////////////////// 00411 bool AnimInterface::CData:: 00412 is_playing() const { 00413 switch (_play_mode) { 00414 case PM_pose: 00415 return false; 00416 00417 case PM_play: 00418 return get_f() < _play_frames; 00419 00420 case PM_loop: 00421 case PM_pingpong: 00422 return true; 00423 } 00424 00425 return false; 00426 } 00427 00428 //////////////////////////////////////////////////////////////////// 00429 // Function: AnimInterface::CData::output 00430 // Access: Public 00431 // Description: 00432 //////////////////////////////////////////////////////////////////// 00433 void AnimInterface::CData:: 00434 output(ostream &out) const { 00435 switch (_play_mode) { 00436 case PM_pose: 00437 out << "pose, frame " << get_full_fframe(); 00438 return; 00439 00440 case PM_play: 00441 out << "play, frame " << get_full_fframe(); 00442 return; 00443 00444 case PM_loop: 00445 out << "loop, frame " << get_full_fframe(); 00446 return; 00447 00448 case PM_pingpong: 00449 out << "pingpong, frame " << get_full_fframe(); 00450 return; 00451 } 00452 } 00453 00454 //////////////////////////////////////////////////////////////////// 00455 // Function: AnimInterface::CData::internal_set_rate 00456 // Access: Public 00457 // Description: Called internally to adjust either or both of the 00458 // frame_rate or play_rate without changing the current 00459 // frame number if the animation is already playing. 00460 //////////////////////////////////////////////////////////////////// 00461 void AnimInterface::CData:: 00462 internal_set_rate(double frame_rate, double play_rate) { 00463 double f = get_f(); 00464 00465 _frame_rate = frame_rate; 00466 _play_rate = play_rate; 00467 _effective_frame_rate = frame_rate * play_rate; 00468 00469 if (_effective_frame_rate == 0.0) { 00470 _paused_f = f; 00471 _paused = true; 00472 00473 } else { 00474 // Compute a new _start_time that will keep f the same value with 00475 // the new play_rate. 00476 double new_elapsed = f / _effective_frame_rate; 00477 double now = ClockObject::get_global_clock()->get_frame_time(); 00478 _start_time = now - new_elapsed; 00479 _paused = false; 00480 } 00481 } 00482 00483 //////////////////////////////////////////////////////////////////// 00484 // Function: AnimInterface::CData::get_f 00485 // Access: Public 00486 // Description: Returns the current floating-point frame number, 00487 // elapsed since _start_frame. 00488 //////////////////////////////////////////////////////////////////// 00489 double AnimInterface::CData:: 00490 get_f() const { 00491 if (_paused) { 00492 return _paused_f; 00493 00494 } else { 00495 double now = ClockObject::get_global_clock()->get_frame_time(); 00496 double elapsed = now - _start_time; 00497 return (elapsed * _effective_frame_rate); 00498 } 00499 }