Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/chan/animControl.cxx

Go to the documentation of this file.
00001 // Filename: animControl.cxx
00002 // Created by:  drose (19Feb99)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 
00020 #include "animControl.h"
00021 #include "animChannelBase.h"
00022 #include "partBundle.h"
00023 #include "config_chan.h"
00024 
00025 #include <event.h>
00026 #include <throw_event.h>
00027 
00028 
00029 TypeHandle AnimControl::_type_handle;
00030 
00031 ////////////////////////////////////////////////////////////////////
00032 //     Function: AnimControl::Constructor
00033 //       Access: Public
00034 //  Description:
00035 ////////////////////////////////////////////////////////////////////
00036 AnimControl::
00037 AnimControl(PartBundle *part, AnimBundle *anim, int channel_index) {
00038 #ifdef DO_MEMORY_USAGE
00039   MemoryUsage::update_type(this, get_class_type());
00040 #endif
00041 
00042   _part = part;
00043   _anim = anim;
00044   _channel_index = channel_index;
00045 
00046   _play_rate = 1.0f;
00047   _frame = 0.0f;
00048   _as_of_time = 0.0f;
00049   _playing = false;
00050 
00051   _marked_frame = -1;
00052 }
00053 
00054 ////////////////////////////////////////////////////////////////////
00055 //     Function: AnimControl::Destructor
00056 //       Access: Published
00057 //  Description:
00058 ////////////////////////////////////////////////////////////////////
00059 AnimControl::
00060 ~AnimControl() {
00061   get_part()->set_control_effect(this, 0.0f);
00062 }
00063 
00064 
00065 ////////////////////////////////////////////////////////////////////
00066 //     Function: AnimControl::play
00067 //       Access: Published
00068 //  Description: Runs the entire animation from beginning to end and
00069 //               stops, throwing the stop event (if it is non-NULL).
00070 ////////////////////////////////////////////////////////////////////
00071 void AnimControl::
00072 play(const CPT_Event &stop_event) {
00073   nassertv(get_num_frames() > 0);
00074 
00075   if (get_play_rate() < 0.0f) {
00076     play(get_num_frames()-1, 0, stop_event);
00077   } else {
00078     play(0, get_num_frames()-1, stop_event);
00079   }
00080 }
00081 
00082 ////////////////////////////////////////////////////////////////////
00083 //     Function: AnimControl::play
00084 //       Access: Published
00085 //  Description: Runs the animation from the frame "from" to and
00086 //               including the frame "to", at which point the
00087 //               animation is stopped and the indicated stop event is
00088 //               thrown (if it is non-NULL).  If the to frame is less
00089 //               than the from frame (unless play_rate is negative),
00090 //               the animation will wrap around the end and begins
00091 //               again at the beginning before the animation stops.
00092 ////////////////////////////////////////////////////////////////////
00093 void AnimControl::
00094 play(int from, int to, const CPT_Event &stop_event) {
00095   nassertv(get_num_frames() > 0);
00096 
00097   nassertv(from >= 0 && from < get_num_frames());
00098   nassertv(to >= 0 && to < get_num_frames());
00099   _as_of_time = ClockObject::get_global_clock()->get_frame_time();
00100   _playing = true;
00101 
00102   _actions = _user_actions;
00103   if (stop_event != (Event*)0L) {
00104     insert_event_action(_actions, to, stop_event);
00105   }
00106   insert_stop_action(_actions, to);
00107 
00108   get_part()->control_activated(this);
00109   set_frame(from);
00110 }
00111 
00112 ////////////////////////////////////////////////////////////////////
00113 //     Function: AnimControl::loop
00114 //       Access: Published
00115 //  Description: Starts the entire animation looping.  If restart is
00116 //               true, the animation is restarted from the beginning;
00117 //               otherwise, it continues from the current frame.
00118 ////////////////////////////////////////////////////////////////////
00119 void AnimControl::
00120 loop(bool restart) {
00121   nassertv(get_num_frames() > 0);
00122 
00123   _as_of_time = ClockObject::get_global_clock()->get_frame_time();
00124   _playing = true;
00125 
00126   _actions = _user_actions;
00127   get_part()->control_activated(this);
00128 
00129   if (restart) {
00130     if (get_play_rate() < 0.0f) {
00131       set_frame(get_num_frames() - 1);
00132     } else {
00133       set_frame(0);
00134     }
00135   }
00136 }
00137 
00138 ////////////////////////////////////////////////////////////////////
00139 //     Function: AnimControl::loop
00140 //       Access: Published
00141 //  Description: Loops the animation from the frame "from" to and
00142 //               including the frame "to", indefinitely.  If restart
00143 //               is true, the animation is restarted from the
00144 //               beginning; otherwise, it continues from the current
00145 //               frame.
00146 ////////////////////////////////////////////////////////////////////
00147 void AnimControl::
00148 loop(bool restart, int from, int to) {
00149   nassertv(get_num_frames() > 0);
00150 
00151   nassertv(from >= 0 && from < get_num_frames());
00152   nassertv(to >= 0 && to < get_num_frames());
00153   _as_of_time = ClockObject::get_global_clock()->get_frame_time();
00154   _playing = true;
00155 
00156   _actions = _user_actions;
00157 
00158   if (get_play_rate() < 0.0f) {
00159     // If we're playing backward, we need to set up the loop a little
00160     // differently.
00161 
00162     if ((to == 0 && from == get_num_frames()-1) ||
00163         (to == from-1)) {
00164 
00165       // In this case, the user has specified to loop over the whole
00166       // range of animation.  We don't need a special jump action to
00167       // handle this.
00168 
00169     } else {
00170       // Otherwise, set up a jump action to effect the loop.  This isn't
00171       // completely accurate, since it will always jump exactly to the
00172       // first frame of the loop, no matter how many frames past the end
00173       // we'd gotten to, but it should be reasonably close, especially
00174       // if the number of frames in the loop is large enough and/or the
00175       // frame rate is high enough.
00176       insert_jump_action(_actions, (to-1+get_num_frames())%get_num_frames(),
00177                          from);
00178     }
00179   } else {
00180 
00181     if ((from == 0 && to == get_num_frames()-1) ||
00182         (from == to-1)) {
00183 
00184       // In this case, the user has specified to loop over the whole
00185       // range of animation.  We don't need a special jump action to
00186       // handle this.
00187 
00188     } else {
00189       // Otherwise, set up a jump action to effect the loop.  This isn't
00190       // completely accurate, since it will always jump exactly to the
00191       // first frame of the loop, no matter how many frames past the end
00192       // we'd gotten to, but it should be reasonably close, especially
00193       // if the number of frames in the loop is large enough and/or the
00194       // frame rate is high enough.
00195       insert_jump_action(_actions, (to+1)%get_num_frames(), from);
00196     }
00197   }
00198 
00199   get_part()->control_activated(this);
00200   if (restart) {
00201     set_frame(from);
00202   }
00203 }
00204 
00205 ////////////////////////////////////////////////////////////////////
00206 //     Function: AnimControl::pingpong
00207 //       Access: Published
00208 //  Description: Loops the animation from the frame "from" to and
00209 //               including the frame "to", and then back in the
00210 //               opposite direction, indefinitely.
00211 ////////////////////////////////////////////////////////////////////
00212 void AnimControl::
00213 pingpong(bool restart, int from, int to) {
00214   if (from == to) {
00215     pose(from);
00216     return;
00217   }
00218 
00219   nassertv(get_num_frames() > 0);
00220 
00221   nassertv(from >= 0 && from < get_num_frames());
00222   nassertv(to >= 0 && to < get_num_frames());
00223   _as_of_time = ClockObject::get_global_clock()->get_frame_time();
00224   _playing = true;
00225 
00226   _actions = _user_actions;
00227 
00228   insert_forward_action(_actions, from);
00229   insert_backward_action(_actions, to);
00230 
00231   get_part()->control_activated(this);
00232   if (restart) {
00233     set_frame(from);
00234   }
00235 }
00236 
00237 ////////////////////////////////////////////////////////////////////
00238 //     Function: AnimControl::stop
00239 //       Access: Published
00240 //  Description: Stops a currently playing or looping animation right
00241 //               where it is.  The animation remains posed at the
00242 //               current frame, and no event is thrown.
00243 ////////////////////////////////////////////////////////////////////
00244 void AnimControl::
00245 stop() {
00246   _playing = false;
00247 }
00248 
00249 ////////////////////////////////////////////////////////////////////
00250 //     Function: AnimControl::pose
00251 //       Access: Published
00252 //  Description: Sets the animation to the indicated frame and holds
00253 //               it there.
00254 ////////////////////////////////////////////////////////////////////
00255 void AnimControl::
00256 pose(int frame) {
00257   int num_frames = get_num_frames();
00258   nassertv(num_frames > 0);
00259 
00260   // Modulo the number of frames.
00261   frame = (int)(frame - cfloor(frame / num_frames) * num_frames);
00262   nassertv(frame >= 0 && frame < num_frames);
00263   _as_of_time = ClockObject::get_global_clock()->get_frame_time();
00264   _playing = false;
00265 
00266   _actions = _user_actions;
00267 
00268   get_part()->control_activated(this);
00269   set_frame(frame);
00270 }
00271 
00272 
00273 ////////////////////////////////////////////////////////////////////
00274 //     Function: AnimControl::add_event
00275 //       Access: Published
00276 //  Description: Adds the indicated event to the list of events that
00277 //               will be called whenever the animation reaches the
00278 //               indicated frame number.  Once added, the event will
00279 //               persist until it is removed via remove_event() or
00280 //               remove_all_events().
00281 ////////////////////////////////////////////////////////////////////
00282 void AnimControl::
00283 add_event(int frame, const CPT_Event &event) {
00284   insert_event_action(_user_actions, frame, event);
00285   if (_playing) {
00286     insert_event_action(_actions, frame, event);
00287   }
00288 }
00289 
00290 ////////////////////////////////////////////////////////////////////
00291 //     Function: AnimControl::remove_event
00292 //       Access: Published
00293 //  Description: Removes all events found that match the indicated
00294 //               event name, and returns the number of events
00295 //               removed.
00296 ////////////////////////////////////////////////////////////////////
00297 int AnimControl::
00298 remove_event(const string &event_name) {
00299   Actions new_actions;
00300 
00301   int removed = 0;
00302 
00303   Actions::const_iterator ai;
00304   for (ai = _user_actions.begin(); ai != _user_actions.end(); ++ai) {
00305     const Action &action = (*ai).second;
00306     if (action._type == AT_event &&
00307         action._event->get_name() == event_name) {
00308       // Remove this event by not copying it to new_actions.
00309       removed++;
00310     } else {
00311       // Preserve this event.
00312       new_actions.insert(*ai);
00313     }
00314   }
00315 
00316   if (removed != 0) {
00317     _user_actions.swap(new_actions);
00318 
00319     if (_playing) {
00320       new_actions.clear();
00321       int p_removed = 0;
00322       for (ai = _actions.begin(); ai != _actions.end(); ++ai) {
00323         const Action &action = (*ai).second;
00324         if (action._type == AT_event &&
00325             action._event->get_name() == event_name) {
00326           // Remove this event by not copying it to new_actions.
00327           p_removed++;
00328         } else {
00329           // Preserve this event.
00330           new_actions.insert(*ai);
00331         }
00332       }
00333       nassertr(p_removed == removed, removed);
00334       _actions.swap(new_actions);
00335     }
00336   }
00337 
00338   return removed;
00339 }
00340 
00341 ////////////////////////////////////////////////////////////////////
00342 //     Function: AnimControl::remove_all_events
00343 //       Access: Published
00344 //  Description: Removes all user-defined event messages.  However, if
00345 //               called while an animation is running, this will not
00346 //               take effect until the animation is stopped and
00347 //               restarted.
00348 ////////////////////////////////////////////////////////////////////
00349 void AnimControl::
00350 remove_all_events() {
00351   _user_actions.clear();
00352 }
00353 
00354 ////////////////////////////////////////////////////////////////////
00355 //     Function: AnimControl::get_part
00356 //       Access: Published
00357 //  Description: Returns the PartBundle bound in with this
00358 //               AnimControl.
00359 ////////////////////////////////////////////////////////////////////
00360 PartBundle *AnimControl::
00361 get_part() const {
00362   return DCAST(PartBundle, _part);
00363 }
00364 
00365 
00366 ////////////////////////////////////////////////////////////////////
00367 //     Function: AnimControl::advance_time
00368 //       Access: Public
00369 //  Description: Tells the AnimControl what time it is.  This
00370 //               recomputes the frame number according to the amount
00371 //               of time elapsed since last time.  Until this function
00372 //               is called, the frame number will not increment.  The
00373 //               time passed to this function must be nondecreasing;
00374 //               it is an error to call it with a value less than a
00375 //               previously-passed value.
00376 ////////////////////////////////////////////////////////////////////
00377 void AnimControl::
00378 advance_time(double time) {
00379   double elapsed_time = time - _as_of_time;
00380   double elapsed_frames = elapsed_time * get_frame_rate();
00381   _as_of_time = time;
00382 
00383   if (_playing && elapsed_frames != 0.0f) {
00384     int orig_frame = get_frame();
00385 
00386     _frame += elapsed_frames;
00387     double num_frames = (double)get_num_frames();
00388 
00389     int new_frame = get_frame();
00390 
00391     // Now call all the actions.
00392     if (elapsed_frames < 0.0f) {
00393       // If we're playing the animation backward, we have to check the
00394       // actions in reverse order.
00395 
00396       if (new_frame >= 0) {
00397         do_actions_backward(orig_frame-1, new_frame);
00398       } else {
00399         if (do_actions_backward(orig_frame-1, 0)) {
00400           // floor() is correct here, instead of simply an integer
00401           // cast, because we are using floating-point arithmetic
00402           // anyway (no need to convert to integer format and back
00403           // again), and because we need correct behavior when the
00404           // frame number is negative.
00405           _frame = _frame - cfloor(_frame / num_frames) * num_frames;
00406           new_frame = get_frame();
00407           do_actions_backward(get_num_frames(), new_frame);
00408         }
00409       }
00410     } else {
00411       // Normally, we'll be playing the animation forward.
00412 
00413       if (new_frame < get_num_frames()) {
00414         do_actions_forward(orig_frame+1, new_frame);
00415       } else {
00416         if (do_actions_forward(orig_frame+1, get_num_frames()-1)) {
00417           // floor() is correct here, instead of simply an integer
00418           // cast, because we are using floating-point arithmetic
00419           // anyway (no need to convert to integer format and back
00420           // again), and because we need correct behavior when the
00421           // frame number is negative.
00422           _frame = _frame - cfloor(_frame / num_frames) * num_frames;
00423           new_frame = get_frame();
00424           do_actions_forward(0, new_frame);
00425         }
00426       }
00427     }
00428   }
00429 }
00430 
00431 
00432 ////////////////////////////////////////////////////////////////////
00433 //     Function: AnimControl::channel_has_changed
00434 //       Access: Public
00435 //  Description: Returns true if the indicated channel value has
00436 //               changed since the last call to mark_channels().
00437 ////////////////////////////////////////////////////////////////////
00438 bool AnimControl::
00439 channel_has_changed(AnimChannelBase *channel) const {
00440   if (_marked_frame < 0) {
00441     return true;
00442   }
00443 
00444   int this_frame = get_frame();
00445 
00446   if (this_frame == _marked_frame) {
00447     return false;
00448   }
00449 
00450   return channel->has_changed(_marked_frame, this_frame);
00451 }
00452 
00453 
00454 ////////////////////////////////////////////////////////////////////
00455 //     Function: AnimControl::mark_channels
00456 //       Access: Public
00457 //  Description: Marks this point as the point of reference for the
00458 //               next call to channel_has_changed().
00459 ////////////////////////////////////////////////////////////////////
00460 void AnimControl::
00461 mark_channels() {
00462   _marked_frame = get_frame();
00463 }
00464 
00465 ////////////////////////////////////////////////////////////////////
00466 //     Function: AnimControl::output
00467 //       Access: Public
00468 //  Description:
00469 ////////////////////////////////////////////////////////////////////
00470 void AnimControl::
00471 output(ostream &out) const {
00472   out << "AnimControl(" << get_part()->get_name()
00473       << ", " << get_anim()->get_name() << ")";
00474 }
00475 
00476 
00477 
00478 ////////////////////////////////////////////////////////////////////
00479 //     Function: AnimControl::insert_event_action
00480 //       Access: Private, Static
00481 //  Description: Inserts an "event" action at the indicated frame
00482 //               number.  The event will be thrown as the animation
00483 //               reaches the indicated frame number.
00484 ////////////////////////////////////////////////////////////////////
00485 void AnimControl::
00486 insert_event_action(Actions &actions, int frame, const CPT_Event &event) {
00487   Action new_action;
00488   new_action._type = AT_event;
00489   new_action._event = event;
00490   actions.insert(pair<int, Action>(frame, new_action));
00491 }
00492 
00493 ////////////////////////////////////////////////////////////////////
00494 //     Function: AnimControl::insert_stop_action
00495 //       Access: Private, Static
00496 //  Description: Inserts a "stop" action at the indicated frame
00497 //               number.  The animation will stop as soon as it
00498 //               reaches the indicated frame number, traveling from
00499 //               either direction.
00500 ////////////////////////////////////////////////////////////////////
00501 void AnimControl::
00502 insert_stop_action(Actions &actions, int frame) {
00503   Action new_action;
00504   new_action._type = AT_stop;
00505   actions.insert(pair<int, Action>(frame, new_action));
00506 }
00507 
00508 
00509 ////////////////////////////////////////////////////////////////////
00510 //     Function: AnimControl::insert_jump_action
00511 //       Access: Private, Static
00512 //  Description: Inserts a "jump" action at the indicated frame
00513 //               number.  When the animation reaches the indicated
00514 //               frame number, it will jump to the indicated jump_to
00515 //               frame.  It will not seem to spend any time at the
00516 //               reached frame number.
00517 ////////////////////////////////////////////////////////////////////
00518 void AnimControl::
00519 insert_jump_action(Actions &actions, int frame, int jump_to) {
00520   Action new_action;
00521   new_action._type = AT_jump;
00522   new_action._jump_to = jump_to;
00523   actions.insert(pair<int, Action>(frame, new_action));
00524 }
00525 
00526 ////////////////////////////////////////////////////////////////////
00527 //     Function: AnimControl::insert_forward_action
00528 //       Access: Private, Static
00529 //  Description: Inserts a "forward" action at the indicated frame
00530 //               number.  When the animation hits this action while
00531 //               playing in a backward direction, it will stop and
00532 //               play in a forward direction instead.
00533 ////////////////////////////////////////////////////////////////////
00534 void AnimControl::
00535 insert_forward_action(Actions &actions, int frame) {
00536   Action new_action;
00537   new_action._type = AT_forward;
00538   actions.insert(pair<int, Action>(frame, new_action));
00539 }
00540 
00541 ////////////////////////////////////////////////////////////////////
00542 //     Function: AnimControl::insert_backward_action
00543 //       Access: Private, Static
00544 //  Description: Inserts a "backward" action at the indicated frame
00545 //               number.  When the animation hits this action while
00546 //               playing in a forward direction, it will stop and
00547 //               play in a backward direction instead.
00548 ////////////////////////////////////////////////////////////////////
00549 void AnimControl::
00550 insert_backward_action(Actions &actions, int frame) {
00551   Action new_action;
00552   new_action._type = AT_backward;
00553   actions.insert(pair<int, Action>(frame, new_action));
00554 }
00555 
00556 
00557 ////////////////////////////////////////////////////////////////////
00558 //     Function: AnimControl::set_frame
00559 //       Access: Private
00560 //  Description: Sets the current frame number to the indicated frame,
00561 //               and performs any actions on that frame.
00562 ////////////////////////////////////////////////////////////////////
00563 void AnimControl::
00564 set_frame(double frame) {
00565   _frame = frame;
00566   int iframe = get_frame();
00567   do_actions_forward(iframe, iframe);
00568 }
00569 
00570 ////////////////////////////////////////////////////////////////////
00571 //     Function: AnimControl::do_actions_forward
00572 //       Access: Private
00573 //  Description: Calls each of the actions, in turn, on the timeline
00574 //               between the indicated "from" frame and the indicated
00575 //               "to" frame, inclusive.  If any of the actions
00576 //               specifies to stop the animation, the animation is
00577 //               stopped, the current frame number is set to the point
00578 //               of stopping, no further actions are called, and false
00579 //               is returned.  Otherwise, true is returned.
00580 ////////////////////////////////////////////////////////////////////
00581 bool AnimControl::
00582 do_actions_forward(int from, int to) {
00583   if (to >= from) {
00584     Actions::const_iterator lower = _actions.lower_bound(from);
00585     Actions::const_iterator upper = _actions.lower_bound(to+1);
00586 
00587     int sequence_frame = -1;
00588     const Action *sequence_action;
00589 
00590     Actions::const_iterator ai;
00591     for (ai = lower; ai != upper; ++ai) {
00592       int frame = (*ai).first;
00593       const Action &action = (*ai).second;
00594 
00595       if (sequence_frame != -1 && frame > sequence_frame) {
00596         // We encountered an action that resequenced our frame numbers.
00597         // Now that we've finished evaluating all the other actions that
00598         // occurred in the same frame, evaluate this one action and
00599         // exit.
00600         do_sequence_action(sequence_frame, *sequence_action);
00601         return false;
00602       }
00603 
00604       do_action(frame, action, sequence_frame, sequence_action);
00605     }
00606 
00607     if (sequence_frame != -1) {
00608       do_sequence_action(sequence_frame, *sequence_action);
00609       return false;
00610     }
00611   }
00612 
00613   return true;
00614 }
00615 
00616 ////////////////////////////////////////////////////////////////////
00617 //     Function: AnimControl::do_actions_backward
00618 //       Access: Private
00619 //  Description: Calls each of the actions, in turn, on the timeline
00620 //               between the indicated "from" frame and the indicated
00621 //               "to" frame, in reverse order.  If any of the actions
00622 //               specifies to stop the animation, the animation is
00623 //               stopped, the current frame number is set to the point
00624 //               of stopping, no further actions are called, and false
00625 //               is returned.  Otherwise, true is returned.
00626 ////////////////////////////////////////////////////////////////////
00627 bool AnimControl::
00628 do_actions_backward(int from, int to) {
00629   if (from >= to) {
00630 #if defined(WIN32_VC) && !defined(NO_PCH)
00631     typedef Actions::const_reverse_iterator Action_reverse_iterator;
00632 #else
00633     typedef reverse_iterator<Actions::const_iterator> Action_reverse_iterator;
00634 #endif
00635     Action_reverse_iterator lower(_actions.upper_bound(from));
00636     Action_reverse_iterator upper(_actions.upper_bound(to-1));
00637 
00638     int sequence_frame = -1;
00639     const Action *sequence_action;
00640 
00641     Action_reverse_iterator ai;
00642     for (ai = lower; ai != upper; ++ai) {
00643       int frame = (*ai).first;
00644       const Action &action = (*ai).second;
00645 
00646       if (sequence_frame != -1 && frame < sequence_frame) {
00647         // We encountered an action that resequenced our frame numbers.
00648         // Now that we've finished evaluating all the other actions that
00649         // occurred in the same frame, evaluate this one action and
00650         // exit.
00651         do_sequence_action(sequence_frame, *sequence_action);
00652         return false;
00653       }
00654 
00655       do_action(frame, action, sequence_frame, sequence_action);
00656     }
00657 
00658     if (sequence_frame != -1) {
00659       do_sequence_action(sequence_frame, *sequence_action);
00660       return false;
00661     }
00662   }
00663 
00664   return true;
00665 }
00666 
00667 ////////////////////////////////////////////////////////////////////
00668 //     Function: AnimControl::do_action
00669 //       Access: Private
00670 //  Description: Performs a single action.  If the action involves
00671 //               some resequencing behavior--stopping, or jumping
00672 //               around to a new frame or something--does nothing
00673 //               immediately, but instead sets sequence_frame and
00674 //               sequence_action to the current frame number and
00675 //               action, so they may be executed later (after all the
00676 //               other actions this frame have been executed).
00677 ////////////////////////////////////////////////////////////////////
00678 void AnimControl::
00679 do_action(int frame, const Action &action,
00680           int &sequence_frame, const Action *&sequence_action) {
00681   switch (action._type) {
00682   case AT_stop:
00683   case AT_jump:
00684     sequence_frame = frame;
00685     sequence_action = &action;
00686     break;
00687 
00688   case AT_forward:
00689     // We only see "forward" actions if we're currently playing
00690     // backwards.
00691     if (_play_rate < 0.0f) {
00692       sequence_frame = frame;
00693       sequence_action = &action;
00694     }
00695     break;
00696 
00697   case AT_backward:
00698     // We only see "backward" actions if we're currently playing
00699     // forwards.
00700     if (_play_rate > 0.0f) {
00701       sequence_frame = frame;
00702       sequence_action = &action;
00703     }
00704     break;
00705 
00706   case AT_event:
00707     throw_event(action._event);
00708     break;
00709 
00710   default:
00711     chan_cat.error() << "Invalid action!\n";
00712     abort();
00713   }
00714 }
00715 
00716 ////////////////////////////////////////////////////////////////////
00717 //     Function: AnimControl::do_sequence_action
00718 //       Access: Private
00719 //  Description: Performs an action that was saved from do_action(),
00720 //               above.  This action presumably does some mucking
00721 //               around with the frame number or something, so we
00722 //               needed to do all the other actions associated with
00723 //               that frame first.
00724 ////////////////////////////////////////////////////////////////////
00725 void AnimControl::
00726 do_sequence_action(int frame, const Action &action) {
00727   switch (action._type) {
00728   case AT_stop:
00729     stop();
00730     break;
00731 
00732   case AT_jump:
00733     set_frame(action._jump_to);
00734     break;
00735 
00736   case AT_forward:
00737   case AT_backward:
00738     _play_rate = -_play_rate;
00739     set_frame(frame);
00740     break;
00741 
00742   case AT_event:
00743   default:
00744     chan_cat.error() << "Invalid sequence action!\n";
00745     abort();
00746   }
00747 }
00748 
00749 ////////////////////////////////////////////////////////////////////
00750 //     Function: AnimControl::Action::output
00751 //       Access: Public
00752 //  Description:
00753 ////////////////////////////////////////////////////////////////////
00754 void AnimControl::Action::
00755 output(ostream &out) const {
00756   switch (_type) {
00757   case AT_event:
00758     out << "event " << *_event;
00759     break;
00760 
00761   case AT_stop:
00762     out << "stop";
00763     break;
00764 
00765   case AT_jump:
00766     out << "jump to " << _jump_to;
00767     break;
00768 
00769   case AT_forward:
00770     out << "forward";
00771     break;
00772 
00773   case AT_backward:
00774     out << "backward";
00775     break;
00776 
00777   default:
00778     out << "**error**";
00779   }
00780 }

Generated on Fri May 2 00:35:02 2003 for Panda by doxygen1.3