Panda3D

animInterface.cxx

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 &copy) :
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 &copy) :
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 }
 All Classes Functions Variables Enumerations