The Battle for Wesnoth  1.19.5+dev
animated.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2004 - 2024
3  by Philippe Plantier <ayin@anathas.org>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 /**
17  * @file
18  * Animate units.
19  */
20 
21 #pragma once
22 
23 #include <chrono>
24 #include <vector>
25 
26 void new_animation_frame();
27 std::chrono::steady_clock::time_point get_current_animation_tick();
28 
29 template<typename T>
30 class animated
31 {
32 public:
33  typedef std::pair<std::chrono::milliseconds, T> frame_description;
34  typedef std::vector<frame_description> anim_description;
35 
36  animated(const std::chrono::milliseconds& start_time = std::chrono::milliseconds{0});
37  explicit animated(const anim_description& cfg, const std::chrono::milliseconds& start_time = std::chrono::milliseconds{0}, bool force_change = false);
38 
39  virtual ~animated() = default;
40 
41  /** Adds a frame to an animation. */
42  void add_frame(const std::chrono::milliseconds& duration, const T& value, bool force_change = false);
43 
44  bool not_started() const;
45 
46  /**
47  * Starts an animation cycle.
48  *
49  * The first frame of the animation to start may be set to any value by
50  * using a start_time different to 0.
51  */
52  void start_animation(const std::chrono::milliseconds& start_time, bool cycles = false);
54  {
55  started_ = false;
56  }
57 
59  {
60  if(start_tick_ != std::chrono::steady_clock::time_point{}) {
61  started_ = true;
62  }
63  }
64 
65  std::chrono::milliseconds get_begin_time() const;
66  std::chrono::milliseconds get_end_time() const;
67  void set_begin_time(const std::chrono::milliseconds& new_begin_time);
68 
69  std::chrono::steady_clock::time_point time_to_tick(const std::chrono::milliseconds& animation_time) const;
70  std::chrono::milliseconds tick_to_time(const std::chrono::steady_clock::time_point& animation_tick) const;
71 
72  void update_last_draw_time(double acceleration = 0);
73  bool need_update() const;
74 
75  bool cycles() const
76  {
77  return cycles_;
78  }
79 
80  /** Returns true if the current animation was finished. */
81  bool animation_finished() const;
83  std::chrono::milliseconds get_animation_time() const;
84  std::chrono::milliseconds get_animation_time_potential() const;
85  void set_animation_time(const std::chrono::milliseconds& time);
86  void set_max_animation_time(const std::chrono::milliseconds& time);
87 
88  std::chrono::milliseconds get_animation_duration() const;
89  const T& get_current_frame() const;
90  std::chrono::milliseconds get_current_frame_begin_time() const;
91  std::chrono::milliseconds get_current_frame_end_time() const;
92  std::chrono::milliseconds get_current_frame_duration() const;
93  std::chrono::milliseconds get_current_frame_time() const;
94  const T& get_first_frame() const;
95  const T& get_frame(std::size_t n) const;
96  const T& get_last_frame() const;
97  std::size_t get_frames_count() const;
98 
99  void force_change()
100  {
101  does_not_change_ = false;
102  }
103 
104  bool does_not_change() const
105  {
106  return does_not_change_;
107  }
108 
109  static const T void_value_; // MSVC: the frame constructor below requires this to be public
110 
111 protected:
112  friend class unit_animation;
113 
114  void remove_frames_until(const std::chrono::milliseconds& starting_time);
115  void set_end_time(const std::chrono::milliseconds& ending_time);
116 
117  std::chrono::milliseconds starting_frame_time_;
118 
119 private:
120  struct frame
121  {
122  // Represents the timestamp of the frame start
123  std::chrono::milliseconds duration_;
125  std::chrono::milliseconds start_time_;
126  };
127 
128  bool does_not_change_; // Optimization for 1-frame permanent animations
129  bool started_;
131  std::vector<frame> frames_;
132 
133  // Can set a maximum animation time so that movement in particular does not exceed potential time
134  // Ignored if has a value of 0
135  std::chrono::milliseconds max_animation_time_;
136 
137  // These are only valid when anim is started
138  std::chrono::steady_clock::time_point start_tick_; // time at which we started
139  bool cycles_;
141  std::chrono::steady_clock::time_point last_update_tick_;
143 };
144 
145 // NOTE: this needs to be down here or the templates won't build.
146 #include "animated.tpp"
std::chrono::steady_clock::time_point get_current_animation_tick()
Definition: animated.cpp:34
void new_animation_frame()
Definition: animated.cpp:29
std::chrono::milliseconds get_animation_time_potential() const
const T & get_first_frame() const
std::chrono::milliseconds tick_to_time(const std::chrono::steady_clock::time_point &animation_tick) const
const T & get_frame(std::size_t n) const
std::chrono::steady_clock::time_point start_tick_
Definition: animated.hpp:138
animated(const anim_description &cfg, const std::chrono::milliseconds &start_time=std::chrono::milliseconds{0}, bool force_change=false)
std::vector< frame > frames_
Definition: animated.hpp:131
std::chrono::milliseconds get_begin_time() const
void start_animation(const std::chrono::milliseconds &start_time, bool cycles=false)
Starts an animation cycle.
std::chrono::milliseconds get_current_frame_begin_time() const
bool force_next_update_
Definition: animated.hpp:130
virtual ~animated()=default
std::chrono::milliseconds get_animation_time() const
std::chrono::steady_clock::time_point last_update_tick_
Definition: animated.hpp:141
std::chrono::milliseconds max_animation_time_
Definition: animated.hpp:135
std::pair< std::chrono::milliseconds, T > frame_description
Definition: animated.hpp:33
bool started_
Definition: animated.hpp:129
void set_max_animation_time(const std::chrono::milliseconds &time)
bool animation_finished_potential() const
void add_frame(const std::chrono::milliseconds &duration, const T &value, bool force_change=false)
Adds a frame to an animation.
std::chrono::milliseconds get_current_frame_duration() const
void pause_animation()
Definition: animated.hpp:53
void update_last_draw_time(double acceleration=0)
std::vector< frame_description > anim_description
Definition: animated.hpp:34
void set_end_time(const std::chrono::milliseconds &ending_time)
const T & get_last_frame() const
void force_change()
Definition: animated.hpp:99
int current_frame_key_
Definition: animated.hpp:142
bool does_not_change() const
Definition: animated.hpp:104
bool need_update() const
bool not_started() const
bool animation_finished() const
Returns true if the current animation was finished.
double acceleration_
Definition: animated.hpp:140
std::chrono::milliseconds starting_frame_time_
Definition: animated.hpp:117
void remove_frames_until(const std::chrono::milliseconds &starting_time)
bool cycles_
Definition: animated.hpp:139
std::chrono::steady_clock::time_point time_to_tick(const std::chrono::milliseconds &animation_time) const
const T & get_current_frame() const
void restart_animation()
Definition: animated.hpp:58
std::size_t get_frames_count() const
void set_begin_time(const std::chrono::milliseconds &new_begin_time)
std::chrono::milliseconds get_animation_duration() const
bool does_not_change_
Definition: animated.hpp:128
static const T void_value_
Definition: animated.hpp:109
std::chrono::milliseconds get_end_time() const
std::chrono::milliseconds get_current_frame_time() const
std::chrono::milliseconds get_current_frame_end_time() const
animated(const std::chrono::milliseconds &start_time=std::chrono::milliseconds{0})
void set_animation_time(const std::chrono::milliseconds &time)
bool cycles() const
Definition: animated.hpp:75
std::chrono::milliseconds duration_
Definition: animated.hpp:123
std::chrono::milliseconds start_time_
Definition: animated.hpp:125
static map_location::direction n