The Battle for Wesnoth  1.17.0-dev
animation_component.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2021
3  by Chris Beck <render787@gmail.com>
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 
17 
18 #include "config.hpp"
19 #include "display.hpp"
20 #include "map/map.hpp"
21 #include "preferences/display.hpp"
22 #include "random.hpp"
23 #include "units/unit.hpp"
24 #include "units/types.hpp"
25 
26 #include <set>
27 
28 const unit_animation* unit_animation_component::choose_animation(const display& disp, const map_location& loc,const std::string& event,
29  const map_location& second_loc,const int value,const unit_animation::hit_type hit,
30  const_attack_ptr attack, const_attack_ptr second_attack, int swing_num)
31 {
32  // Select one of the matching animations at random
33  std::vector<const unit_animation*> options;
34  int max_val = unit_animation::MATCH_FAIL;
35  for(const unit_animation& anim : animations_) {
36  int matching = anim.matches(disp,loc,second_loc,u_.shared_from_this(),event,value,hit,attack,second_attack,swing_num);
37  if(matching > unit_animation::MATCH_FAIL && matching == max_val) {
38  options.push_back(&anim);
39  } else if(matching > max_val) {
40  max_val = matching;
41  options.clear();
42  options.push_back(&anim);
43  }
44  }
45 
46  if(max_val == unit_animation::MATCH_FAIL) {
47  return nullptr;
48  }
49  return options[randomness::rng::default_instance().get_random_int(0, options.size()-1)];
50 }
51 
53 {
55  if(disp == nullptr) return;
57  start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "standing"),
58  with_bars, "", {0,0,0}, STATE_STANDING);
59  } else {
60  start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "_disabled_"),
61  with_bars, "", {0,0,0}, STATE_STANDING);
62  }
63 }
64 
66 {
68  start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "_ghosted_"),
69  with_bars);
70  anim_->pause_animation();
71 }
72 
74 {
76  start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "_disabled_ghosted_"),
77  with_bars);
78 }
79 
81 {
83  start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "idling"),
84  true, "", {0,0,0}, STATE_FORGET);
85 }
86 
88 {
89  const display *disp = display::get_singleton();
91  start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "selected"),
92  true, "", {0,0,0}, STATE_FORGET);
93  } else {
94  start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "_disabled_selected_"),
95  true, "", {0,0,0}, STATE_FORGET);
96  }
97 }
98 
99 void unit_animation_component::start_animation (int start_time, const unit_animation *animation,
100  bool with_bars, const std::string &text, color_t text_color, STATE state)
101 {
102  const display * disp = display::get_singleton();
103  if (!animation) {
104  if (state == STATE_STANDING)
105  state_ = state;
106  if (!anim_ && state_ != STATE_STANDING)
107  set_standing(with_bars);
108  return ;
109  }
110  state_ = state;
111  // everything except standing select and idle
112  bool accelerate = (state != STATE_FORGET && state != STATE_STANDING);
113  draw_bars_ = with_bars;
114  anim_.reset(new unit_animation(*animation));
115  const int real_start_time = start_time == INT_MAX ? anim_->get_begin_time() : start_time;
116  anim_->start_animation(real_start_time, u_.loc_, u_.loc_.get_direction(u_.facing_),
117  text, text_color, accelerate);
118  frame_begin_time_ = anim_->get_begin_time() -1;
119  if (disp->idle_anim()) {
121  + static_cast<int>(randomness::rng::default_instance().get_random_int(20000, 39999) * disp->idle_anim_rate());
122  } else {
123  next_idling_ = INT_MAX;
124  }
125 }
126 
128 {
129  if (state_ == STATE_FORGET && anim_ && anim_->animation_finished_potential())
130  {
131  set_standing();
132  return;
133  }
134  display &disp = *display::get_singleton();
137  {
138  return;
139  }
141  {
142  // prevent all units animating at the same time
143  if (disp.idle_anim()) {
145  + static_cast<int>(randomness::rng::default_instance().get_random_int(20000, 39999) * disp.idle_anim_rate());
146  } else {
147  next_idling_ = INT_MAX;
148  }
149  } else {
150  set_idling();
151  }
152 }
153 
155 {
156  unit_halo_.reset();
157  if(anim_ ) anim_->clear_haloes();
158 }
159 
161 {
162  bool result = false;
163 
164  // Very early calls, anim not initialized yet
165  if(get_animation()) {
166  frame_parameters params;
167  const gamemap & map = disp.get_map();
168  const t_translation::terrain_code terrain = map.get_terrain(u_.loc_);
169  const terrain_type& terrain_info = map.get_terrain_info(terrain);
170 
171  int height_adjust = static_cast<int>(terrain_info.unit_height_adjust() * disp.get_zoom_factor());
172  if (u_.is_flying() && height_adjust < 0) {
173  height_adjust = 0;
174  }
175  params.y -= height_adjust;
176  params.halo_y -= height_adjust;
177  params.image_mod = u_.image_mods();
178  params.halo_mod = u_.TC_image_mods();
179  params.image= u_.default_anim_image();
180 
181  result |= get_animation()->invalidate(params);
182  }
183 
184  return result;
185 
186 }
187 
189 {
190  if (newtype) {
191  animations_ = newtype->animations();
192  }
193 
194  refreshing_ = false;
195  anim_.reset();
196 }
197 
199  if(effect["id"].empty()) {
201  } else {
202  static std::map< std::string, std::vector<unit_animation>> animation_cache;
203  std::vector<unit_animation> &built = animation_cache[effect["id"]];
204  if(built.empty()) {
205  unit_animation::add_anims(built, effect);
206  }
207  animations_.insert(animations_.end(),built.begin(),built.end());
208  }
209 }
210 
211 std::vector<std::string> unit_animation_component::get_flags() {
212  std::set<std::string> result;
213  for(const auto& anim : animations_) {
214  const std::vector<std::string>& flags = anim.get_flags();
215  std::copy_if(flags.begin(), flags.end(), std::inserter(result, result.begin()), [](const std::string flag) {
216  return !(flag.empty() || (flag.front() == '_' && flag.back() == '_'));
217  });
218  }
219  return std::vector<std::string>(result.begin(), result.end());
220 }
void start_animation(int start_time, const unit_animation *animation, bool with_bars, const std::string &text="", color_t text_color={}, STATE state=STATE_ANIM)
Begin an animation.
bool refreshing_
avoid infinite recursion.
All parameters from a frame at a given instant.
Definition: frame.hpp:35
image::locator image
Definition: frame.hpp:41
static display * get_singleton()
Returns the display object if a display object exists.
Definition: display.hpp:92
const unit & u_
A reference to the unit that owns this object.
void set_disabled_ghosted(bool with_bars=true)
Whiteboard related somehow.
bool is_flying() const
Check if the unit is a flying unit.
Definition: unit.hpp:1455
static double get_zoom_factor()
Returns the current zoom factor.
Definition: display.hpp:263
std::unique_ptr< unit_animation > anim_
The current animation.
int get_current_animation_tick()
Definition: animated.cpp:36
static void add_anims(std::vector< unit_animation > &animations, const config &cfg)
Definition: animation.cpp:628
map_location loc_
Definition: unit.hpp:1839
void set_selecting()
Sets the animation state to that when the unit is selected.
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:50
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
Definition: map.cpp:98
bool draw_bars_
bool indicating whether to draw bars with the unit
Definitions for the interface to Wesnoth Markup Language (WML).
void refresh()
Intermittently activates the idling animations in place of the standing animations.
unit_animation * get_animation() const
Get a pointer to the current animation.
int frame_begin_time_
time for the frame to begin
A single unit type that the player may recruit.
Definition: types.hpp:45
map_location get_direction(DIRECTION dir, unsigned int n=1u) const
Definition: location.cpp:360
const config & options()
Definition: game.cpp:569
void clear_haloes()
Clear the haloes associated to the unit.
int unit_height_adjust() const
Definition: terrain.hpp:137
std::string halo_mod
Definition: frame.hpp:50
const std::vector< unit_animation > & animations() const
Definition: types.cpp:537
terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:302
const unit_animation * choose_animation(const display &disp, const map_location &loc, const std::string &event, const map_location &second_loc=map_location::null_location(), const int damage=0, const unit_animation::hit_type hit_type=unit_animation::hit_type::INVALID, const_attack_ptr attack=nullptr, const_attack_ptr second_attack=nullptr, int swing_num=0)
Chooses an appropriate animation from the list of known animations.
bool idle_anim() const
Definition: display.hpp:497
Encapsulates the map of the game.
Definition: map.hpp:171
STATE state_
animation state
bool invalidate(const display &disp)
Invalidates an animation with respect to a display object, preparing it for redraw.
map_display and display: classes which take care of displaying the map and game-data on the screen...
std::string default_anim_image() const
The default image to use for animation frames with no defined image.
Definition: unit.cpp:2388
bool show_standing_animations()
Definition: display.cpp:103
STATE
States for animation.
Encapsulates the map of the game.
Definition: location.hpp:38
void set_idling()
Sets the animation state to idling.
std::vector< std::string > get_flags()
Get the flags of all registered animations.
double idle_anim_rate() const
Definition: display.hpp:499
std::string image_mod
Definition: frame.hpp:44
bool tile_nearly_on_screen(const map_location &loc) const
Checks if location loc or one of the adjacent tiles is visible on screen.
Definition: display.cpp:2114
int get_random_int(int min, int max)
This helper method provides a random int from the underlying generator, using results of next_random...
Definition: random.hpp:52
void apply_new_animation_effect(const config &effect)
Adds an animation described by a config.
std::vector< unit_animation > animations_
List of registered animations for this unit.
const gamemap & get_map() const
Definition: display.hpp:96
bool incapacitated() const
Check if the unit has been petrified.
Definition: unit.hpp:894
halo::handle unit_halo_
handle to the halo of this unit
void set_standing(bool with_bars=true)
Sets the animation state to standing.
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:61
std::shared_ptr< const attack_type > const_attack_ptr
Definition: ptr.hpp:34
std::string TC_image_mods() const
Constructs a recolor (RC) IPF string for this unit&#39;s team color.
Definition: unit.cpp:2557
static rng & default_instance()
Definition: random.cpp:74
void set_ghosted(bool with_bars=true)
Sets the animation state to ghosted.
std::string image_mods() const
Gets an IPF string containing all IPF image mods.
Definition: unit.cpp:2562
void reset_after_advance(const unit_type *newtype=nullptr)
Resets the animations list after the unit is advanced.
int next_idling_
time for next idle animation
bool invalidate(frame_parameters &value)
Definition: animation.cpp:1106
map_location::DIRECTION facing_
Definition: unit.hpp:1917