The Battle for Wesnoth  1.15.2+dev
animation_component.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2018 by Chris Beck <render787@gmail.com>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
16 
17 #include "config.hpp"
18 #include "display.hpp"
19 #include "map/map.hpp"
20 #include "preferences/display.hpp"
21 #include "random.hpp"
22 #include "units/unit.hpp"
23 #include "units/types.hpp"
24 
25 #include <set>
26 
27 const unit_animation* unit_animation_component::choose_animation(const display& disp, const map_location& loc,const std::string& event,
28  const map_location& second_loc,const int value,const unit_animation::hit_type hit,
29  const_attack_ptr attack, const_attack_ptr second_attack, int swing_num)
30 {
31  // Select one of the matching animations at random
32  std::vector<const unit_animation*> options;
33  int max_val = unit_animation::MATCH_FAIL;
34  for(const unit_animation& anim : animations_) {
35  int matching = anim.matches(disp,loc,second_loc,&u_,event,value,hit,attack,second_attack,swing_num);
36  if(matching > unit_animation::MATCH_FAIL && matching == max_val) {
37  options.push_back(&anim);
38  } else if(matching > max_val) {
39  max_val = matching;
40  options.clear();
41  options.push_back(&anim);
42  }
43  }
44 
45  if(max_val == unit_animation::MATCH_FAIL) {
46  return nullptr;
47  }
48  return options[randomness::rng::default_instance().get_random_int(0, options.size()-1)];
49 }
50 
52 {
54  if(disp == nullptr) return;
56  start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "standing"),
57  with_bars, "", {0,0,0}, STATE_STANDING);
58  } else {
59  start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "_disabled_"),
60  with_bars, "", {0,0,0}, STATE_STANDING);
61  }
62 }
63 
65 {
67  start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "_ghosted_"),
68  with_bars);
69  anim_->pause_animation();
70 }
71 
73 {
75  start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "_disabled_ghosted_"),
76  with_bars);
77 }
78 
80 {
82  start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "idling"),
83  true, "", {0,0,0}, STATE_FORGET);
84 }
85 
87 {
88  const display *disp = display::get_singleton();
90  start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "selected"),
91  true, "", {0,0,0}, STATE_FORGET);
92  } else {
93  start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "_disabled_selected_"),
94  true, "", {0,0,0}, STATE_FORGET);
95  }
96 }
97 
98 void unit_animation_component::start_animation (int start_time, const unit_animation *animation,
99  bool with_bars, const std::string &text, color_t text_color, STATE state)
100 {
101  const display * disp = display::get_singleton();
102  if (!animation) {
103  if (state == STATE_STANDING)
104  state_ = state;
105  if (!anim_ && state_ != STATE_STANDING)
106  set_standing(with_bars);
107  return ;
108  }
109  state_ = state;
110  // everything except standing select and idle
111  bool accelerate = (state != STATE_FORGET && state != STATE_STANDING);
112  draw_bars_ = with_bars;
113  anim_.reset(new unit_animation(*animation));
114  const int real_start_time = start_time == INT_MAX ? anim_->get_begin_time() : start_time;
115  anim_->start_animation(real_start_time, u_.loc_, u_.loc_.get_direction(u_.facing_),
116  text, text_color, accelerate);
117  frame_begin_time_ = anim_->get_begin_time() -1;
118  if (disp->idle_anim()) {
120  + static_cast<int>(randomness::rng::default_instance().get_random_int(20000, 39999) * disp->idle_anim_rate());
121  } else {
122  next_idling_ = INT_MAX;
123  }
124 }
125 
127 {
128  if (state_ == STATE_FORGET && anim_ && anim_->animation_finished_potential())
129  {
130  set_standing();
131  return;
132  }
133  display &disp = *display::get_singleton();
136  {
137  return;
138  }
140  {
141  // prevent all units animating at the same time
142  if (disp.idle_anim()) {
144  + static_cast<int>(randomness::rng::default_instance().get_random_int(20000, 39999) * disp.idle_anim_rate());
145  } else {
146  next_idling_ = INT_MAX;
147  }
148  } else {
149  set_idling();
150  }
151 }
152 
154 {
155  unit_halo_.reset();
156  if(anim_ ) anim_->clear_haloes();
157 }
158 
160 {
161  bool result = false;
162 
163  // Very early calls, anim not initialized yet
164  if(get_animation()) {
165  frame_parameters params;
166  const gamemap & map = disp.get_map();
168  const terrain_type& terrain_info = map.get_terrain_info(terrain);
169 
170  int height_adjust = static_cast<int>(terrain_info.unit_height_adjust() * disp.get_zoom_factor());
171  if (u_.is_flying() && height_adjust < 0) {
172  height_adjust = 0;
173  }
174  params.y -= height_adjust;
175  params.halo_y -= height_adjust;
176  params.image_mod = u_.image_mods();
177  params.halo_mod = u_.TC_image_mods();
178  params.image= u_.default_anim_image();
179 
180  result |= get_animation()->invalidate(params);
181  }
182 
183  return result;
184 
185 }
186 
188 {
189  if (newtype) {
190  animations_ = newtype->animations();
191  }
192 
193  refreshing_ = false;
194  anim_.reset();
195 }
196 
198  if(effect["id"].empty()) {
199  unit_animation::add_anims(animations_, effect);
200  } else {
201  static std::map< std::string, std::vector<unit_animation>> animation_cache;
202  std::vector<unit_animation> &built = animation_cache[effect["id"]];
203  if(built.empty()) {
204  unit_animation::add_anims(built, effect);
205  }
206  animations_.insert(animations_.end(),built.begin(),built.end());
207  }
208 }
209 
210 std::vector<std::string> unit_animation_component::get_flags() {
211  std::set<std::string> result;
212  for(const auto& anim : animations_) {
213  const std::vector<std::string>& flags = anim.get_flags();
214  std::copy_if(flags.begin(), flags.end(), std::inserter(result, result.begin()), [](const std::string flag) {
215  return !(flag.empty() || (flag.front() == '_' && flag.back() == '_'));
216  });
217  }
218  return std::vector<std::string>(result.begin(), result.end());
219 }
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. flag used for drawing / animation
All parameters from a frame at a given instant.
Definition: frame.hpp:34
image::locator image
Definition: frame.hpp:40
static display * get_singleton()
Returns the display object if a display object exists.
Definition: display.hpp:88
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:1422
static double get_zoom_factor()
Returns the current zoom factor.
Definition: display.hpp:258
std::unique_ptr< unit_animation > anim_
The current animation.
int get_current_animation_tick()
Definition: animated.cpp:35
void set_selecting()
Sets the animation state to that when the unit is selected.
map_location::DIRECTION facing_
Definition: unit.hpp:1839
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:97
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:42
t_translation::terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:309
map_location get_direction(DIRECTION dir, unsigned int n=1u) const
Definition: location.cpp:359
const config & options()
Definition: game.cpp:593
void clear_haloes()
Clear the haloes associated to the unit.
int unit_height_adjust() const
Definition: terrain.hpp:116
std::string halo_mod
Definition: frame.hpp:49
const std::vector< unit_animation > & animations() const
Definition: types.cpp:500
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:492
Encapsulates the map of the game.
Definition: map.hpp:36
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:2417
bool show_standing_animations()
Definition: display.cpp:102
static const ::config * terrain
The terrain used to create the cache.
Definition: minimap.cpp:130
STATE
States for animation.
Encapsulates the map of the game.
Definition: location.hpp:42
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:494
std::string image_mod
Definition: frame.hpp:43
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:2093
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:51
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:92
bool incapacitated() const
Check if the unit has been petrified.
Definition: unit.hpp:874
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:68
map_location loc_
Definition: unit.hpp:1761
std::shared_ptr< const attack_type > const_attack_ptr
Definition: ptr.hpp:37
std::string TC_image_mods() const
Constructs a recolor (RC) IPF string for this unit&#39;s team color.
Definition: unit.cpp:2591
static rng & default_instance()
Definition: random.cpp:73
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:2596
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:1104