Panda3D
 All Classes Functions Variables Enumerations
animInterface.cxx
1 // Filename: animInterface.cxx
2 // Created by: drose (20Sep05)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "animInterface.h"
16 #include "clockObject.h"
17 #include "bamReader.h"
18 #include "bamWriter.h"
19 #include "datagram.h"
20 #include "datagramIterator.h"
21 
22 TypeHandle AnimInterface::_type_handle;
23 
24 ////////////////////////////////////////////////////////////////////
25 // Function: AnimInterface::Constructor
26 // Access: Published
27 // Description:
28 ////////////////////////////////////////////////////////////////////
29 AnimInterface::
30 AnimInterface() :
31  _num_frames(0)
32 {
33 }
34 
35 ////////////////////////////////////////////////////////////////////
36 // Function: AnimInterface::Copy Constructor
37 // Access: Published
38 // Description:
39 ////////////////////////////////////////////////////////////////////
40 AnimInterface::
41 AnimInterface(const AnimInterface &copy) :
42  _num_frames(copy._num_frames),
43  _cycler(copy._cycler)
44 {
45 }
46 
47 ////////////////////////////////////////////////////////////////////
48 // Function: AnimInterface::Destructor
49 // Access: Published, Virtual
50 // Description:
51 ////////////////////////////////////////////////////////////////////
52 AnimInterface::
53 ~AnimInterface() {
54 }
55 
56 ////////////////////////////////////////////////////////////////////
57 // Function: AnimInterface::get_num_frames
58 // Access: Published, Virtual
59 // Description: Returns the number of frames in the animation. This
60 // is a property of the animation and may not be
61 // directly adjusted by the user (although it may change
62 // without warning with certain kinds of animations,
63 // since this is a virtual method that may be
64 // overridden).
65 ////////////////////////////////////////////////////////////////////
67 get_num_frames() const {
68  return _num_frames;
69 }
70 
71 ////////////////////////////////////////////////////////////////////
72 // Function: AnimInterface::output
73 // Access: Published, Virtual
74 // Description:
75 ////////////////////////////////////////////////////////////////////
76 void AnimInterface::
77 output(ostream &out) const {
78  CDReader cdata(_cycler);
79  cdata->output(out);
80 }
81 
82 ////////////////////////////////////////////////////////////////////
83 // Function: AnimInterface::animation_activated
84 // Access: Protected, Virtual
85 // Description: This is provided as a callback method for when the
86 // user calls one of the play/loop/pose type methods to
87 // start the animation playing.
88 ////////////////////////////////////////////////////////////////////
89 void AnimInterface::
90 animation_activated() {
91 }
92 
93 ////////////////////////////////////////////////////////////////////
94 // Function: AnimInterface::write_datagram
95 // Access: Public, Virtual
96 // Description: Writes the contents of this object to the datagram
97 // for shipping out to a Bam file.
98 ////////////////////////////////////////////////////////////////////
99 void AnimInterface::
100 write_datagram(BamWriter *manager, Datagram &dg) {
101  dg.add_int32(_num_frames);
102  manager->write_cdata(dg, _cycler);
103 }
104 
105 ////////////////////////////////////////////////////////////////////
106 // Function: AnimInterface::fillin
107 // Access: Protected
108 // Description: This internal function is called by make_from_bam to
109 // read in all of the relevant data from the BamFile for
110 // the new AnimInterface.
111 ////////////////////////////////////////////////////////////////////
112 void AnimInterface::
113 fillin(DatagramIterator &scan, BamReader *manager) {
114  _num_frames = scan.get_int32();
115  manager->read_cdata(scan, _cycler);
116 }
117 
118 ////////////////////////////////////////////////////////////////////
119 // Function: AnimInterface::CData::Constructor
120 // Access: Published
121 // Description:
122 ////////////////////////////////////////////////////////////////////
123 AnimInterface::CData::
124 CData() :
125  _frame_rate(0.0),
126  _play_mode(PM_pose),
127  _start_time(0.0),
128  _start_frame(0.0),
129  _play_frames(0.0),
130  _from_frame(0),
131  _to_frame(0),
132  _play_rate(1.0),
133  _effective_frame_rate(0.0),
134  _paused(true),
135  _paused_f(0.0)
136 {
137 }
138 
139 ////////////////////////////////////////////////////////////////////
140 // Function: AnimInterface::CData::Copy Constructor
141 // Access: Published
142 // Description:
143 ////////////////////////////////////////////////////////////////////
144 AnimInterface::CData::
145 CData(const AnimInterface::CData &copy) :
146  _frame_rate(copy._frame_rate),
147  _play_mode(copy._play_mode),
148  _start_time(copy._start_time),
149  _start_frame(copy._start_frame),
150  _play_frames(copy._play_frames),
151  _from_frame(copy._from_frame),
152  _to_frame(copy._to_frame),
153  _play_rate(copy._play_rate),
154  _effective_frame_rate(copy._effective_frame_rate),
155  _paused(copy._paused),
156  _paused_f(copy._paused_f)
157 {
158 }
159 
160 ////////////////////////////////////////////////////////////////////
161 // Function: AnimInterface::CData::make_copy
162 // Access: Public, Virtual
163 // Description:
164 ////////////////////////////////////////////////////////////////////
165 CycleData *AnimInterface::CData::
166 make_copy() const {
167  return new CData(*this);
168 }
169 
170 ////////////////////////////////////////////////////////////////////
171 // Function: AnimInterface::CData::write_datagram
172 // Access: Public, Virtual
173 // Description: Writes the contents of this object to the datagram
174 // for shipping out to a Bam file.
175 ////////////////////////////////////////////////////////////////////
176 void AnimInterface::CData::
177 write_datagram(BamWriter *, Datagram &dg) const {
178  dg.add_stdfloat(_frame_rate);
179  dg.add_uint8(_play_mode);
180  dg.add_stdfloat(_start_time);
181  dg.add_stdfloat(_start_frame);
182  dg.add_stdfloat(_play_frames);
183  dg.add_int32(_from_frame);
184  dg.add_int32(_to_frame);
185  dg.add_stdfloat(_play_rate);
186  dg.add_bool(_paused);
187  dg.add_stdfloat(_paused_f);
188 }
189 
190 ////////////////////////////////////////////////////////////////////
191 // Function: AnimInterface::CData::fillin
192 // Access: Public, Virtual
193 // Description: This internal function is called by make_from_bam to
194 // read in all of the relevant data from the BamFile for
195 // the new AnimInterface.
196 ////////////////////////////////////////////////////////////////////
197 void AnimInterface::CData::
198 fillin(DatagramIterator &scan, BamReader *) {
199  _frame_rate = scan.get_stdfloat();
200  _play_mode = (PlayMode)scan.get_uint8();
201  _start_time = scan.get_stdfloat();
202  _start_frame = scan.get_stdfloat();
203  _play_frames = scan.get_stdfloat();
204  _from_frame = scan.get_int32();
205  _to_frame = scan.get_int32();
206  _play_rate = scan.get_stdfloat();
207  _effective_frame_rate = _frame_rate * _play_rate;
208  _paused = scan.get_bool();
209  _paused_f = scan.get_stdfloat();
210 }
211 
212 ////////////////////////////////////////////////////////////////////
213 // Function: AnimInterface::CData::play
214 // Access: Public
215 // Description: Runs the animation from the frame "from" to and
216 // including the frame "to", at which point the
217 // animation is stopped. Both "from" and "to" frame
218 // numbers may be outside the range (0,
219 // get_num_frames()) and the animation will follow the
220 // range correctly, reporting numbers modulo
221 // get_num_frames(). For instance, play(0,
222 // get_num_frames() * 2) will play the animation twice
223 // and then stop.
224 ////////////////////////////////////////////////////////////////////
225 void AnimInterface::CData::
226 play(double from, double to) {
227  if (from >= to) {
228  pose(from);
229  return;
230  }
231 
232  _play_mode = PM_play;
234  _start_frame = from;
235  _play_frames = to - from + 1.0;
236  _from_frame = (int)floor(from);
237  _to_frame = (int)floor(to);
238  _paused_f = 0.0;
239 
240  if (_effective_frame_rate < 0.0) {
241  // If we'll be playing backward, start at the end.
242  _start_time -= _play_frames / _effective_frame_rate;
243  }
244 }
245 
246 ////////////////////////////////////////////////////////////////////
247 // Function: AnimInterface::CData::loop
248 // Access: Public
249 // Description: Loops the animation from the frame "from" to and
250 // including the frame "to", indefinitely. If restart
251 // is true, the animation is restarted from the
252 // beginning; otherwise, it continues from the current
253 // frame.
254 ////////////////////////////////////////////////////////////////////
255 void AnimInterface::CData::
256 loop(bool restart, double from, double to) {
257  if (from >= to) {
258  pose(from);
259  return;
260  }
261 
262  double fframe = get_full_fframe();
263 
264  _play_mode = PM_loop;
266  _start_frame = from;
267  _play_frames = to - from + 1.0;
268  _from_frame = (int)floor(from);
269  _to_frame = (int)floor(to);
270  _paused_f = 0.0;
271 
272  if (!restart) {
273  fframe = min(max(fframe, from), to);
274  if (_paused) {
275  _paused_f = fframe - _start_frame;
276  } else {
277  _start_time -= (fframe - _start_frame) / _effective_frame_rate;
278  }
279  }
280 }
281 
282 ////////////////////////////////////////////////////////////////////
283 // Function: AnimInterface::CData::pingpong
284 // Access: Public
285 // Description: Loops the animation from the frame "from" to and
286 // including the frame "to", and then back in the
287 // opposite direction, indefinitely.
288 ////////////////////////////////////////////////////////////////////
289 void AnimInterface::CData::
290 pingpong(bool restart, double from, double to) {
291  if (from >= to) {
292  pose(from);
293  return;
294  }
295 
296  double fframe = get_full_fframe();
297 
298  _play_mode = PM_pingpong;
300  _start_frame = from;
301  _play_frames = to - from + 1.0;
302  _from_frame = (int)floor(from);
303  _to_frame = (int)floor(to);
304  _paused_f = 0.0;
305 
306  if (!restart) {
307  fframe = min(max(fframe, from), to);
308  if (_paused) {
309  _paused_f = fframe - _start_frame;
310  } else {
311  _start_time -= (fframe - _start_frame) / _effective_frame_rate;
312  }
313  }
314 }
315 
316 ////////////////////////////////////////////////////////////////////
317 // Function: AnimInterface::CData::pose
318 // Access: Public
319 // Description: Sets the animation to the indicated frame and holds
320 // it there.
321 ////////////////////////////////////////////////////////////////////
322 void AnimInterface::CData::
323 pose(double frame) {
324  _play_mode = PM_pose;
326  _start_frame = frame;
327  _play_frames = 0.0;
328  _from_frame = (int)floor(frame);
329  _to_frame = (int)floor(frame);
330  _paused_f = 0.0;
331 }
332 
333 ////////////////////////////////////////////////////////////////////
334 // Function: AnimInterface::CData::get_full_frame
335 // Access: Public
336 // Description: Returns the current integer frame number, plus the
337 // indicated increment.
338 //
339 // Unlike the value returned by get_frame(), this frame
340 // number may extend beyond the range of
341 // get_num_frames() if the frame range passed to play(),
342 // loop(), etc. did.
343 //
344 // Unlike the value returned by get_full_fframe(), this
345 // return value will never exceed the value passed to
346 // to_frame in the play() method.
347 ////////////////////////////////////////////////////////////////////
348 int AnimInterface::CData::
349 get_full_frame(int increment) const {
350  int frame = (int)floor(get_full_fframe()) + increment;
351  if (_play_mode == PM_play) {
352  // In play mode, we never let the return value exceed
353  // (_from_frame, _to_frame).
354  frame = min(max(frame, _from_frame), _to_frame);
355  }
356  return frame;
357 }
358 
359 ////////////////////////////////////////////////////////////////////
360 // Function: AnimInterface::CData::get_full_fframe
361 // Access: Public
362 // Description: Returns the current floating-point frame number.
363 //
364 // Unlike the value returned by get_frame(), this frame
365 // number may extend beyond the range of
366 // get_num_frames() if the frame range passed to play(),
367 // loop(), etc. did.
368 //
369 // Unlike the value returned by get_full_frame(), this
370 // return value may equal (to_frame + 1.0), when the
371 // animation has played to its natural end. However, in
372 // this case the return value of get_full_frame() will
373 // be to_frame, not (to_frame + 1).
374 ////////////////////////////////////////////////////////////////////
375 double AnimInterface::CData::
376 get_full_fframe() const {
377  switch (_play_mode) {
378  case PM_pose:
379  return _start_frame;
380 
381  case PM_play:
382  return min(max(get_f(), 0.0), _play_frames) + _start_frame;
383 
384  case PM_loop:
385  nassertr(_play_frames >= 0.0, 0.0);
386  return cmod(get_f(), _play_frames) + _start_frame;
387 
388  case PM_pingpong:
389  {
390  nassertr(_play_frames >= 0.0, 0.0);
391  double f = cmod(get_f(), _play_frames * 2.0);
392  if (f > _play_frames) {
393  return (_play_frames * 2.0 - f) + _start_frame;
394  } else {
395  return f + _start_frame;
396  }
397  }
398  }
399 
400  return _start_frame;
401 }
402 
403 ////////////////////////////////////////////////////////////////////
404 // Function: AnimInterface::CData::is_playing
405 // Access: Public
406 // Description: Returns true if the animation is currently playing,
407 // false if it is stopped (e.g. because stop() or pose()
408 // was called, or because it reached the end of the
409 // animation after play() was called).
410 ////////////////////////////////////////////////////////////////////
411 bool AnimInterface::CData::
412 is_playing() const {
413  switch (_play_mode) {
414  case PM_pose:
415  return false;
416 
417  case PM_play:
418  return get_f() < _play_frames;
419 
420  case PM_loop:
421  case PM_pingpong:
422  return true;
423  }
424 
425  return false;
426 }
427 
428 ////////////////////////////////////////////////////////////////////
429 // Function: AnimInterface::CData::output
430 // Access: Public
431 // Description:
432 ////////////////////////////////////////////////////////////////////
433 void AnimInterface::CData::
434 output(ostream &out) const {
435  switch (_play_mode) {
436  case PM_pose:
437  out << "pose, frame " << get_full_fframe();
438  return;
439 
440  case PM_play:
441  out << "play, frame " << get_full_fframe();
442  return;
443 
444  case PM_loop:
445  out << "loop, frame " << get_full_fframe();
446  return;
447 
448  case PM_pingpong:
449  out << "pingpong, frame " << get_full_fframe();
450  return;
451  }
452 }
453 
454 ////////////////////////////////////////////////////////////////////
455 // Function: AnimInterface::CData::internal_set_rate
456 // Access: Public
457 // Description: Called internally to adjust either or both of the
458 // frame_rate or play_rate without changing the current
459 // frame number if the animation is already playing.
460 ////////////////////////////////////////////////////////////////////
461 void AnimInterface::CData::
462 internal_set_rate(double frame_rate, double play_rate) {
463  double f = get_f();
464 
465  _frame_rate = frame_rate;
466  _play_rate = play_rate;
467  _effective_frame_rate = frame_rate * play_rate;
468 
469  if (_effective_frame_rate == 0.0) {
470  _paused_f = f;
471  _paused = true;
472 
473  } else {
474  // Compute a new _start_time that will keep f the same value with
475  // the new play_rate.
476  double new_elapsed = f / _effective_frame_rate;
478  _start_time = now - new_elapsed;
479  _paused = false;
480  }
481 }
482 
483 ////////////////////////////////////////////////////////////////////
484 // Function: AnimInterface::CData::get_f
485 // Access: Public
486 // Description: Returns the current floating-point frame number,
487 // elapsed since _start_frame.
488 ////////////////////////////////////////////////////////////////////
489 double AnimInterface::CData::
490 get_f() const {
491  if (_paused) {
492  return _paused_f;
493 
494  } else {
496  double elapsed = now - _start_time;
497  return (elapsed * _effective_frame_rate);
498  }
499 }
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:271
void add_uint8(PN_uint8 value)
Adds an unsigned 8-bit integer to the datagram.
Definition: datagram.I:138
bool get_bool()
Extracts a boolean value.
PN_stdfloat get_stdfloat()
Extracts either a 32-bit or a 64-bit floating-point number, according to Datagram::set_stdfloat_doubl...
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
Definition: bamReader.cxx:747
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
Definition: bamWriter.cxx:398
virtual int get_num_frames() const
Returns the number of frames in the animation.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
PN_int32 get_int32()
Extracts a signed 32-bit integer.
PN_uint8 get_uint8()
Extracts an unsigned 8-bit integer.
This is the fundamental interface for things that have a play/loop/stop type interface for frame-base...
Definition: animInterface.h:39
void add_stdfloat(PN_stdfloat value)
Adds either a 32-bit or a 64-bit floating-point number, according to set_stdfloat_double().
Definition: datagram.I:240
void add_bool(bool value)
Adds a boolean value to the datagram.
Definition: datagram.I:118
double get_frame_time(Thread *current_thread=Thread::get_current_thread()) const
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
Definition: clockObject.I:48
void add_int32(PN_int32 value)
Adds a signed 32-bit integer to the datagram.
Definition: datagram.I:159
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43