4 Part of the Battle for Wesnoth Project http://www.wesnoth.org/
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2
8 or at your option any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY.
12 See the COPYING file for more details.
17 * Templates related to animations.
25 #include "animated.hpp"
27 template<typename T, typename T_void_value>
28 const T animated<T,T_void_value>::void_value_ = T_void_value()();
30 template<typename T, typename T_void_value>
31 inline animated<T,T_void_value>::animated(int start_time) :
32 starting_frame_time_(start_time),
33 does_not_change_(true),
35 force_next_update_(false),
45 template<typename T, typename T_void_value>
46 inline animated<T,T_void_value>::animated(const std::vector<std::pair<int,T> > &cfg, int start_time, bool force_change ):
47 starting_frame_time_(start_time),
48 does_not_change_(true),
50 force_next_update_(false),
58 typename std::vector< std::pair<int,T> >::const_iterator itor = cfg.begin();
59 for (; itor != cfg.end(); ++itor) {
60 add_frame(itor->first,itor->second,force_change);
64 template<typename T, typename T_void_value>
65 inline void animated<T,T_void_value>::add_frame(int duration, const T& value,bool force_change)
67 if (frames_.empty() ) {
68 does_not_change_=!force_change;
69 frames_.push_back( frame(duration,value,starting_frame_time_));
71 does_not_change_=false;
72 frames_.push_back( frame(duration,value,frames_.back().start_time_+frames_.back().duration_));
76 template<typename T, typename T_void_value>
77 inline void animated<T,T_void_value>::start_animation(int start_time, bool cycles)
80 last_update_tick_ = get_current_animation_tick();
81 acceleration_ = 1.0; //assume acceleration is 1, this will be fixed at first update_last_draw_time
82 start_tick_ = last_update_tick_ +
83 static_cast<int>(( starting_frame_time_ - start_time)/acceleration_);
86 if (acceleration_ <= 0) {
89 current_frame_key_= 0;
90 force_next_update_ = !frames_.empty();
93 template<typename T, typename T_void_value>
94 inline void animated<T,T_void_value>::update_last_draw_time(double acceleration)
96 if (acceleration > 0 && acceleration_ != acceleration) {
97 int tmp = tick_to_time(last_update_tick_);
98 acceleration_ = acceleration;
99 start_tick_ = last_update_tick_ +
100 static_cast<int>(( starting_frame_time_ - tmp)/acceleration_);
102 if (!started_ && start_tick_ != 0) {
103 // animation is paused
104 start_tick_ += get_current_animation_tick() - last_update_tick_;
106 last_update_tick_ = get_current_animation_tick();
107 if (force_next_update_) {
108 force_next_update_ = false;
111 if (does_not_change_) {
115 // Always update last_update_tick_, for the animation_time functions to work.
120 if (frames_.empty()) {
121 does_not_change_ = true;
125 while(get_animation_time() > get_end_time()){ // cut extra time
126 start_tick_ += std::max<int>(static_cast<int>(get_animation_duration()/acceleration_),1);
127 current_frame_key_ = 0;
130 if (get_current_frame_end_time() < get_animation_time() && // catch up
131 get_current_frame_end_time() < get_end_time()) {// don't go after the end
132 current_frame_key_++;
136 template<typename T, typename T_void_value>
137 inline bool animated<T,T_void_value>::need_update() const
139 if (force_next_update_) {
142 if (does_not_change_) {
145 if (frames_.empty()) {
148 if (!started_ && start_tick_ == 0) {
151 if (get_current_animation_tick() >
152 static_cast<int>(get_current_frame_end_time() /
153 acceleration_ + start_tick_)) {
159 template<typename T, typename T_void_value>
160 inline bool animated<T,T_void_value>::animation_finished_potential() const
162 if (frames_.empty()) {
165 if (!started_ && start_tick_ == 0) {
171 if (tick_to_time(get_current_animation_tick()) > get_end_time()) {
178 template<typename T, typename T_void_value>
179 inline bool animated<T,T_void_value>::animation_finished() const
181 if (frames_.empty()) {
184 if (!started_ && start_tick_ == 0) {
190 if (get_animation_time() > get_end_time()) {
197 template<typename T, typename T_void_value>
198 inline int animated<T,T_void_value>::get_animation_time_potential() const
200 if (!started_ && start_tick_ == 0 ) {
201 return starting_frame_time_;
204 return tick_to_time(get_current_animation_tick());
207 template<typename T, typename T_void_value>
208 inline int animated<T,T_void_value>::get_animation_time() const
210 if (!started_ && start_tick_ == 0 ) {
211 return starting_frame_time_;
214 return tick_to_time(last_update_tick_);
217 template<typename T, typename T_void_value>
218 inline void animated<T,T_void_value>::set_animation_time(int time)
220 start_tick_ = last_update_tick_ +
221 static_cast<int>((starting_frame_time_ - time) / acceleration_);
223 current_frame_key_= 0;
224 force_next_update_ = true;
227 template<typename T, typename T_void_value>
228 inline int animated<T,T_void_value>::get_animation_duration() const
230 return get_end_time() - get_begin_time();
233 template<typename T, typename T_void_value>
234 inline const T& animated<T,T_void_value>::get_current_frame() const
236 if (frames_.empty()) {
239 return frames_[current_frame_key_].value_;
242 template<typename T, typename T_void_value>
243 inline int animated<T,T_void_value>::get_current_frame_begin_time() const
245 if (frames_.empty()) {
246 return starting_frame_time_;
248 return frames_[current_frame_key_].start_time_;
251 template<typename T, typename T_void_value>
252 inline int animated<T,T_void_value>::get_current_frame_end_time() const
254 if (frames_.empty()) {
255 return starting_frame_time_;
257 return get_current_frame_begin_time() +get_current_frame_duration();
260 template<typename T, typename T_void_value>
261 inline int animated<T,T_void_value>::get_current_frame_duration() const
263 if (frames_.empty()) {
266 return frames_[current_frame_key_].duration_;
269 template<typename T, typename T_void_value>
270 inline int animated<T,T_void_value>::get_current_frame_time() const
272 if (frames_.empty()) {
275 //FIXME: get_animation_time() use acceleration but get_current_frame_begin_time() doesn't ?
276 return std::max<int>(0,get_animation_time() - get_current_frame_begin_time());
279 template<typename T, typename T_void_value>
280 inline const T& animated<T,T_void_value>::get_first_frame() const
282 if (frames_.empty()) {
285 return frames_[0].value_;
288 template<typename T, typename T_void_value>
289 inline const T& animated<T,T_void_value>::get_frame(size_t n) const
291 if (n >= frames_.size()) {
294 return frames_[n].value_;
297 template<typename T, typename T_void_value>
298 inline const T& animated<T,T_void_value>::get_last_frame() const
300 if (frames_.empty()) {
303 return frames_.back().value_;
306 template<typename T, typename T_void_value>
307 inline size_t animated<T,T_void_value>::get_frames_count() const
309 return frames_.size();
312 template<typename T, typename T_void_value>
313 inline int animated<T,T_void_value>::get_begin_time() const
315 return starting_frame_time_;
318 template<typename T, typename T_void_value>
319 inline int animated<T,T_void_value>::time_to_tick(int animation_time) const
321 if (!started_ && start_tick_ == 0) {
324 return start_tick_ + static_cast<int>((animation_time-starting_frame_time_) / acceleration_);
327 template<typename T, typename T_void_value>
328 inline int animated<T,T_void_value>::tick_to_time(int animation_tick) const
330 if (!started_ && start_tick_ == 0) {
333 return static_cast<int>(
334 (static_cast<double>(animation_tick - start_tick_) *
335 acceleration_) + starting_frame_time_);
338 template<typename T, typename T_void_value>
339 inline int animated<T,T_void_value>::get_end_time() const
341 if (frames_.empty()) {
342 return starting_frame_time_;
344 return frames_.back().start_time_ + frames_.back().duration_;
347 template<typename T, typename T_void_value>
348 void animated<T,T_void_value>::remove_frames_until(int new_starting_time)
350 while (starting_frame_time_ < new_starting_time && !frames_.empty()) {
351 starting_frame_time_ += frames_[0].duration_;
352 frames_.erase(frames_.begin());
356 template<typename T, typename T_void_value>
357 inline void animated<T,T_void_value>::set_end_time(int new_ending_time)
359 int last_start_time = starting_frame_time_;
360 typename std::vector<frame>::iterator current_frame = frames_.begin();
361 while (last_start_time < new_ending_time && current_frame != frames_.end()) {
362 last_start_time += current_frame->duration_;
365 // at this point last_start_time is set to the beginning of the first frame past the end
366 // or set to frames_.end()
367 frames_.erase(current_frame,frames_.end());
368 frames_.back().duration_ += new_ending_time - last_start_time;
371 template<typename T, typename T_void_value>
372 inline void animated<T,T_void_value>::set_begin_time(int new_begin_time)
374 const int variation = new_begin_time - starting_frame_time_;
375 starting_frame_time_ += variation;
376 for (typename std::vector<frame>::iterator itor = frames_.begin(); itor != frames_.end() ; ++itor) {
377 itor->start_time_ += variation;