diff --git a/projectfiles/CodeBlocks-SCons/wesnoth.cbp b/projectfiles/CodeBlocks-SCons/wesnoth.cbp
index e3eb1844b5b..7db6a54a25c 100644
--- a/projectfiles/CodeBlocks-SCons/wesnoth.cbp
+++ b/projectfiles/CodeBlocks-SCons/wesnoth.cbp
@@ -986,6 +986,8 @@
+
+
diff --git a/projectfiles/CodeBlocks/wesnoth.cbp b/projectfiles/CodeBlocks/wesnoth.cbp
index 5d94e32a01e..ce111871bda 100644
--- a/projectfiles/CodeBlocks/wesnoth.cbp
+++ b/projectfiles/CodeBlocks/wesnoth.cbp
@@ -1021,6 +1021,8 @@
+
+
diff --git a/projectfiles/VC9/wesnoth.vcproj b/projectfiles/VC9/wesnoth.vcproj
index e773a6d56fd..f7cd58d536b 100644
--- a/projectfiles/VC9/wesnoth.vcproj
+++ b/projectfiles/VC9/wesnoth.vcproj
@@ -21068,6 +21068,14 @@
RelativePath="..\..\src\unit_animation.hpp"
>
+
+
+
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7e8819a8926..6cdb2893c84 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -890,6 +890,7 @@ set(wesnoth-main_SRC
unit.cpp
unit_abilities.cpp
unit_animation.cpp
+ unit_animation_component.cpp
unit_display.cpp
unit_formula_manager.cpp
unit_frame.cpp
diff --git a/src/SConscript b/src/SConscript
index 8d5c728f917..110015ecd80 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -523,6 +523,7 @@ wesnoth_sources = Split("""
unit.cpp
unit_abilities.cpp
unit_animation.cpp
+ unit_animation_component.cpp
unit_display.cpp
unit_formula_manager.cpp
unit_frame.cpp
diff --git a/src/actions/attack.cpp b/src/actions/attack.cpp
index 6e0a6d35cac..573511f6e62 100644
--- a/src/actions/attack.cpp
+++ b/src/actions/attack.cpp
@@ -44,6 +44,7 @@
#include "../tod_manager.hpp"
#include "../unit.hpp"
#include "../unit_abilities.hpp"
+#include "../unit_animation_component.hpp"
#include "../unit_display.hpp"
#include "../unit_helper.hpp"
#include "../unit_map.hpp"
@@ -1326,13 +1327,13 @@ namespace {
if (a_.valid()) {
unit &u = a_.get_unit();
- u.set_standing();
+ u.anim_comp().set_standing();
u.set_experience(u.experience() + a_.xp_);
}
if (d_.valid()) {
unit &u = d_.get_unit();
- u.set_standing();
+ u.anim_comp().set_standing();
u.set_experience(u.experience() + d_.xp_);
}
diff --git a/src/actions/move.cpp b/src/actions/move.cpp
index 4e403a51883..f3ab2bcb9d9 100644
--- a/src/actions/move.cpp
+++ b/src/actions/move.cpp
@@ -42,6 +42,7 @@
#include "../formula_string_utils.hpp"
#include "../team.hpp"
#include "../unit.hpp"
+#include "../unit_animation_component.hpp"
#include "../whiteboard/manager.hpp"
#include
@@ -494,7 +495,7 @@ namespace { // Private helpers for move_unit()
moves_left_.pop_front();
// Invalidate before moving so we invalidate neighbor hexes if needed.
- move_it_->invalidate(disp);
+ move_it_->anim_comp().invalidate(disp);
// Attempt actually moving.
// (Fails if *step_to is occupied).
@@ -505,7 +506,7 @@ namespace { // Private helpers for move_unit()
// Update the moving unit.
move_it_ = move_result.first;
move_it_->set_facing(step_from->get_relative_dir(*step_to));
- move_it_->set_standing(false);
+ move_it_->anim_comp().set_standing(false);
disp.invalidate_unit_after_move(*move_loc_, *step_to);
disp.invalidate(*step_to);
move_loc_ = step_to;
diff --git a/src/actions/undo.cpp b/src/actions/undo.cpp
index de4fbee213c..f9c297840fd 100644
--- a/src/actions/undo.cpp
+++ b/src/actions/undo.cpp
@@ -30,6 +30,7 @@
#include "../resources.hpp"
#include "../team.hpp"
#include "../unit.hpp"
+#include "../unit_animation_component.hpp"
#include "../unit_display.hpp"
#include "../unit_map.hpp"
#include "../whiteboard/manager.hpp"
@@ -746,7 +747,7 @@ bool undo_list::move_action::undo(int side, undo_list & /*undos*/)
u = units.find(rev_route.back());
u->set_goto(map_location());
u->set_movement(saved_moves, true);
- u->set_standing();
+ u->anim_comp().set_standing();
gui.invalidate_unit_after_move(rev_route.front(), rev_route.back());
return true;
@@ -964,7 +965,7 @@ bool undo_list::move_action::redo(int side)
// Set the unit's state.
u->set_goto(goto_hex);
u->set_movement(saved_moves, true);
- u->set_standing();
+ u->anim_comp().set_standing();
if ( resources::gameboard->map().is_village(route.back()) ) {
get_village(route.back(), u->side());
diff --git a/src/display.cpp b/src/display.cpp
index 89ad38d2d5b..972c2e655ec 100644
--- a/src/display.cpp
+++ b/src/display.cpp
@@ -17,6 +17,7 @@
* Routines to set up the display, scroll and zoom the map.
*/
+#include "arrow.hpp"
#include "cursor.hpp"
#include "drawable_unit.hpp"
#include "display.hpp"
@@ -30,19 +31,20 @@
#include "map.hpp"
#include "map_label.hpp"
#include "minimap.hpp"
+#include "overlay.hpp"
#include "play_controller.hpp" //note: this can probably be refactored out
#include "reports.hpp"
+#include "resources.hpp"
+#include "synced_context.hpp"
#include "team.hpp"
#include "terrain_builder.hpp"
#include "text.hpp"
#include "time_of_day.hpp"
#include "tooltips.hpp"
-#include "arrow.hpp"
#include "tod_manager.hpp"
-#include "resources.hpp"
+#include "unit.hpp"
+#include "unit_animation_component.hpp"
#include "whiteboard/manager.hpp"
-#include "overlay.hpp"
-#include "synced_context.hpp"
#include "SDL_image.h"
@@ -3056,10 +3058,10 @@ void display::invalidate_animations()
}
const std::deque & unit_list = fake_unit_man_->get_fake_unit_list_for_invalidation();
BOOST_FOREACH(const unit* u, unit_list) {
- u->refresh();
+ u->anim_comp().refresh();
}
BOOST_FOREACH(const unit & u, dc_->units()) {
- u.refresh();
+ u.anim_comp().refresh();
}
bool new_inval;
do {
@@ -3068,10 +3070,10 @@ void display::invalidate_animations()
#pragma omp parallel for reduction(|:new_inval) shared(unit_list) schedule(guided)
#endif //_OPENMP
BOOST_FOREACH(const unit* u, unit_list) {
- new_inval |= u->invalidate(*this);
+ new_inval |= u->anim_comp().invalidate(*this);
}
BOOST_FOREACH(const unit & u, dc_->units()) {
- new_inval |= u.invalidate(*this);
+ new_inval |= u.anim_comp().invalidate(*this);
}
}while(new_inval);
}
diff --git a/src/drawable_unit.cpp b/src/drawable_unit.cpp
index b5e3039f343..942d76c9de1 100644
--- a/src/drawable_unit.cpp
+++ b/src/drawable_unit.cpp
@@ -21,6 +21,7 @@
#include "map.hpp"
#include "team.hpp"
#include "unit_animation.hpp"
+#include "unit_animation_component.hpp"
#include "unit_frame.hpp"
#include
@@ -33,24 +34,26 @@ void drawable_unit::redraw_unit (display & disp) const
const team & viewing_team = teams[disp.viewing_team()];
+ unit_animation_component & ac = *anim_comp_;
+
if ( hidden_ || disp.is_blindfolded() || !is_visible_to_team(viewing_team,map, disp.show_everything()) )
{
- clear_haloes();
- if(anim_) {
- anim_->update_last_draw_time();
+ ac.clear_haloes();
+ if(ac.anim_) {
+ ac.anim_->update_last_draw_time();
}
return;
}
- if (!anim_) {
- set_standing();
- if (!anim_) return;
+ if (!ac.anim_) {
+ ac.set_standing();
+ if (!ac.anim_) return;
}
- if (refreshing_) return;
- refreshing_ = true;
+ if (ac.refreshing_) return;
+ ac.refreshing_ = true;
- anim_->update_last_draw_time();
+ ac.anim_->update_last_draw_time();
frame_parameters params;
const t_translation::t_terrain terrain = map.get_terrain(loc_);
const terrain_type& terrain_info = map.get_terrain_info(terrain);
@@ -106,7 +109,7 @@ void drawable_unit::redraw_unit (display & disp) const
params.primary_frame = t_true;
- const frame_parameters adjusted_params = anim_->get_current_params(params);
+ const frame_parameters adjusted_params = ac.anim_->get_current_params(params);
const map_location dst = loc_.get_direction(facing_);
const int xsrc = disp.get_location_x(loc_);
@@ -118,20 +121,20 @@ void drawable_unit::redraw_unit (display & disp) const
const int x = static_cast(adjusted_params.offset * xdst + (1.0-adjusted_params.offset) * xsrc) + d2;
const int y = static_cast(adjusted_params.offset * ydst + (1.0-adjusted_params.offset) * ysrc) + d2;
- if(unit_halo_ == halo::NO_HALO && !image_halo().empty()) {
- unit_halo_ = halo::add(0, 0, image_halo()+TC_image_mods(), map_location(-1, -1));
+ if(ac.unit_halo_ == halo::NO_HALO && !image_halo().empty()) {
+ ac.unit_halo_ = halo::add(0, 0, image_halo()+TC_image_mods(), map_location(-1, -1));
}
- if(unit_halo_ != halo::NO_HALO && image_halo().empty()) {
- halo::remove(unit_halo_);
- unit_halo_ = halo::NO_HALO;
- } else if(unit_halo_ != halo::NO_HALO) {
- halo::set_location(unit_halo_, x, y - height_adjust);
+ if(ac.unit_halo_ != halo::NO_HALO && image_halo().empty()) {
+ halo::remove(ac.unit_halo_);
+ ac.unit_halo_ = halo::NO_HALO;
+ } else if(ac.unit_halo_ != halo::NO_HALO) {
+ halo::set_location(ac.unit_halo_, x, y - height_adjust);
}
// We draw bars only if wanted, visible on the map view
- bool draw_bars = draw_bars_ ;
+ bool draw_bars = ac.draw_bars_ ;
if (draw_bars) {
const int d = disp.hex_size();
SDL_Rect unit_rect = sdl::create_rect(xsrc, ysrc +adjusted_params.y, d, d);
@@ -291,7 +294,7 @@ void drawable_unit::redraw_unit (display & disp) const
params.y -= height_adjust_unit - height_adjust;
params.halo_y -= height_adjust_unit - height_adjust;
- anim_->redraw(params);
- refreshing_ = false;
+ ac.anim_->redraw(params);
+ ac.refreshing_ = false;
}
diff --git a/src/editor/action/action_item.cpp b/src/editor/action/action_item.cpp
index 9cd50afeeda..dd3b6b91849 100644
--- a/src/editor/action/action_item.cpp
+++ b/src/editor/action/action_item.cpp
@@ -101,7 +101,7 @@ void editor_action_item_replace::perform_without_undo(map_context& /*mc*/) const
//
// item& u = *items.find(new_loc_);
// //TODO do we still need set_standing?
-// u.set_standing();
+// u.anim_comp().set_standing();
//
// mc.add_changed_location(loc_);
// mc.add_changed_location(new_loc_);
diff --git a/src/editor/action/action_unit.cpp b/src/editor/action/action_unit.cpp
index e3d69454c80..b65bff7598d 100644
--- a/src/editor/action/action_unit.cpp
+++ b/src/editor/action/action_unit.cpp
@@ -24,6 +24,9 @@
#include "editor/map/map_context.hpp"
+#include "../../unit.hpp"
+#include "../../unit_animation_component.hpp"
+
#include
namespace editor {
@@ -99,7 +102,7 @@ void editor_action_unit_replace::perform_without_undo(map_context& mc) const
unit& u = *units.find(new_loc_);
//TODO do we still need set_standing?
- u.set_standing();
+ u.anim_comp().set_standing();
mc.add_changed_location(loc_);
mc.add_changed_location(new_loc_);
@@ -135,7 +138,7 @@ void editor_action_unit_facing::perform_without_undo(map_context& mc) const
if (unit_it != units.end()) {
unit_it->set_facing(new_direction_);
- unit_it->set_standing();
+ unit_it->anim_comp().set_standing();
}
}
diff --git a/src/editor/editor_controller.cpp b/src/editor/editor_controller.cpp
index aa61ed81bb2..38d2f5ad2a0 100644
--- a/src/editor/editor_controller.cpp
+++ b/src/editor/editor_controller.cpp
@@ -42,9 +42,11 @@
#include "../clipboard.hpp"
#include "../game_preferences.hpp"
#include "../gettext.hpp"
+#include "../leader_scroll_dialog.hpp"
#include "../preferences_display.hpp"
#include "../sound.hpp"
-#include "../leader_scroll_dialog.hpp"
+#include "../unit.hpp"
+#include "../unit_animation_component.hpp"
#include "halo.hpp"
@@ -655,7 +657,7 @@ bool editor_controller::execute_command(const hotkey::hotkey_command& cmd, int i
resources::units->find(gui_->mouseover_hex());
assert(un != resources::units->end());
un->set_facing(map_location::DIRECTION(index));
- un->set_standing();
+ un->anim_comp().set_standing();
return true;
}
}
@@ -766,7 +768,7 @@ bool editor_controller::execute_command(const hotkey::hotkey_command& cmd, int i
const unit_map::unit_iterator un = context_manager_->get_map_context().get_units().find(loc);
bool canrecruit = un->can_recruit();
un->set_can_recurit(!canrecruit);
- un->set_standing();
+ un->anim_comp().set_standing();
}
return true;
case HOTKEY_DELETE_UNIT:
diff --git a/src/fake_unit_manager.cpp b/src/fake_unit_manager.cpp
index 9394dc1401e..cafae7b726d 100644
--- a/src/fake_unit_manager.cpp
+++ b/src/fake_unit_manager.cpp
@@ -18,6 +18,7 @@
#include "fake_unit.hpp"
#include "log.hpp"
#include "unit.hpp"
+#include "unit_animation_component.hpp"
static lg::log_domain log_engine("engine");
#define ERR_NG LOG_STREAM(err, log_engine)
@@ -43,7 +44,7 @@ int fake_unit_manager::remove_temporary_unit(unit *u)
fake_units_.erase(it, fake_units_.end());
my_display_.invalidate(u->get_location());
// Redraw with no location to get rid of haloes
- u->clear_haloes();
+ u->anim_comp().clear_haloes();
}
if (removed > 1) {
ERR_NG << "Error: duplicate temp unit found in fake_unit_manager::remove_temporary_unit" << std::endl;
diff --git a/src/game_events/action_wml.cpp b/src/game_events/action_wml.cpp
index b5a6209580b..fd602fc53e0 100644
--- a/src/game_events/action_wml.cpp
+++ b/src/game_events/action_wml.cpp
@@ -58,6 +58,8 @@
#include "../soundsource.hpp"
#include "../synced_context.hpp"
#include "../terrain_filter.hpp"
+#include "../unit.hpp"
+#include "../unit_animation_component.hpp"
#include "../unit_display.hpp"
#include "../unit_helper.hpp"
#include "../wml_exception.hpp"
@@ -857,7 +859,7 @@ WML_HANDLER_FUNCTION(heal_unit, event_info, cfg)
u->set_state(unit::STATE_SLOWED, false);
u->set_state(unit::STATE_PETRIFIED, false);
u->set_state(unit::STATE_UNHEALABLE, false);
- u->set_standing();
+ u->anim_comp().set_standing();
}
if (heal_amount_to_set)
@@ -948,7 +950,7 @@ WML_HANDLER_FUNCTION(kill, event_info, cfg)
resources::screen->invalidate(loc);
unit_map::iterator iun = resources::units->find(loc);
if ( iun != resources::units->end() && iun.valid() )
- iun->invalidate(*resources::screen);
+ iun->anim_comp().invalidate(*resources::screen);
}
resources::screen->redraw_minimap();
@@ -1422,7 +1424,7 @@ WML_HANDLER_FUNCTION(move_units_fake, /*event_info*/, cfg)
path_step[1] = paths[un][step];
unit_display::move_unit(path_step, *units[un]);
units[un]->set_location(path_step[1]);
- units[un]->set_standing();
+ units[un]->anim_comp().set_standing();
}
}
@@ -2359,7 +2361,7 @@ WML_HANDLER_FUNCTION(teleport, event_info, cfg)
unit::clear_status_caches();
u = resources::units->find(vacant_dst);
- u->set_standing();
+ u->anim_comp().set_standing();
if ( clear_shroud ) {
// Now that the unit is visibly in position, clear the shroud.
diff --git a/src/mouse_events.cpp b/src/mouse_events.cpp
index 7fce837152f..93f96be210f 100644
--- a/src/mouse_events.cpp
+++ b/src/mouse_events.cpp
@@ -40,6 +40,8 @@
#include "replay_helper.hpp"
#include "resources.hpp"
#include "synced_context.hpp"
+#include "unit.hpp"
+#include "unit_animation_component.hpp"
#include "wml_separators.hpp"
#include "whiteboard/manager.hpp"
@@ -725,7 +727,7 @@ void mouse_handler::select_hex(const map_location& hex, const bool browse, const
if (!(browse || resources::whiteboard->unit_has_actions(&*u)))
{
sound::play_UI_sound("select-unit.wav");
- u->set_selecting();
+ u->anim_comp().set_selecting();
if(fire_event) {
// ensure unit map is back to normal while event is fired
wb::real_map srum;
diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp
index 6a5c98fa84a..9f2e850a74e 100644
--- a/src/scripting/lua.cpp
+++ b/src/scripting/lua.cpp
@@ -65,6 +65,7 @@
#include "sound.hpp"
#include "synced_context.hpp"
#include "unit.hpp"
+#include "unit_animation_component.hpp"
#include "ai/lua/core.hpp"
#include "version.hpp"
#include "gui/widgets/clickable.hpp"
@@ -2193,7 +2194,7 @@ static int intf_put_unit(lua_State *L)
if (lu) {
lu->put_map(loc);
- lu->get()->set_standing();
+ lu->get()->anim_comp().set_standing();
} else {
u->set_location(loc);
resources::units->insert(u);
@@ -2268,7 +2269,7 @@ static int intf_extract_unit(lua_State *L)
if (lu->on_map()) {
u = resources::units->extract(u->get_location());
assert(u);
- u->clear_haloes();
+ u->anim_comp().clear_haloes();
} else if (int side = lu->on_recall_list()) {
team &t = (*resources::teams)[side - 1];
UnitPtr v = UnitPtr(new unit(*u));
diff --git a/src/unit.cpp b/src/unit.cpp
index 0e506b413b0..3b7bdc8515c 100644
--- a/src/unit.cpp
+++ b/src/unit.cpp
@@ -32,6 +32,7 @@
#include "resources.hpp"
#include "unit_id.hpp"
#include "unit_abilities.hpp"
+#include "unit_animation_component.hpp"
#include "unit_formula_manager.hpp"
#include "scripting/lua.hpp"
#include "side_filter.hpp"
@@ -184,7 +185,6 @@ unit::unit(const unit& o):
events_(o.events_),
filter_recall_(o.filter_recall_),
emit_zoc_(o.emit_zoc_),
- state_(o.state_),
overlays_(o.overlays_),
@@ -202,17 +202,12 @@ unit::unit(const unit& o):
modification_descriptions_(o.modification_descriptions_),
+ anim_comp_(new unit_animation_component(*this, *o.anim_comp_)),
+
animations_(o.animations_),
- anim_(NULL),
- next_idling_(0),
-
- frame_begin_time_(o.frame_begin_time_),
- unit_halo_(halo::NO_HALO),
getsHit_(o.getsHit_),
- refreshing_(o.refreshing_),
hidden_(o.hidden_),
- draw_bars_(o.draw_bars_),
hp_bar_scaling_(o.hp_bar_scaling_),
xp_bar_scaling_(o.xp_bar_scaling_),
@@ -265,7 +260,6 @@ unit::unit(const config &cfg, bool use_traits, const vconfig* vcfg) :
events_(),
filter_recall_(),
emit_zoc_(0),
- state_(STATE_STANDING),
overlays_(),
role_(cfg["role"]),
attacks_(),
@@ -278,15 +272,10 @@ unit::unit(const config &cfg, bool use_traits, const vconfig* vcfg) :
is_fearless_(false),
is_healthy_(false),
modification_descriptions_(),
+ anim_comp_(new unit_animation_component(*this)),
animations_(),
- anim_(NULL),
- next_idling_(0),
- frame_begin_time_(0),
- unit_halo_(halo::NO_HALO),
getsHit_(0),
- refreshing_(false),
hidden_(false),
- draw_bars_(false),
hp_bar_scaling_(cfg["hp_bar_scaling"].blank() ? type_->hp_bar_scaling() : cfg["hp_bar_scaling"]),
xp_bar_scaling_(cfg["xp_bar_scaling"].blank() ? type_->xp_bar_scaling() : cfg["xp_bar_scaling"]),
modifications_(),
@@ -370,7 +359,7 @@ unit::unit(const config &cfg, bool use_traits, const vconfig* vcfg) :
unit_value_ = *v;
}
if (const config::attribute_value *v = cfg.get("halo")) {
- clear_haloes();
+ anim_comp_->clear_haloes();
cfg_["halo"] = *v;
}
if (const config::attribute_value *v = cfg.get("profile")) {
@@ -570,7 +559,6 @@ unit::unit(const unit_type &u_type, int side, bool real_unit,
events_(),
filter_recall_(),
emit_zoc_(0),
- state_(STATE_STANDING),
overlays_(),
role_(),
attacks_(),
@@ -583,15 +571,10 @@ unit::unit(const unit_type &u_type, int side, bool real_unit,
is_fearless_(false),
is_healthy_(false),
modification_descriptions_(),
+ anim_comp_(new unit_animation_component(*this)),
animations_(),
- anim_(NULL),
- next_idling_(0),
- frame_begin_time_(0),
- unit_halo_(halo::NO_HALO),
getsHit_(0),
- refreshing_(false),
hidden_(false),
- draw_bars_(false),
modifications_(),
invisibility_cache_()
{
@@ -614,7 +597,7 @@ unit::unit(const unit_type &u_type, int side, bool real_unit,
unit::~unit()
{
try {
- clear_haloes();
+ anim_comp_->clear_haloes();
// Remove us from the status cache
std::vector::iterator itor =
@@ -623,6 +606,8 @@ unit::~unit()
if(itor != units_with_cache.end()) {
units_with_cache.erase(itor);
}
+ } catch (std::exception & e) {
+ ERR_UT << "Caught exception when destroying unit: " << e.what() << std::endl;
} catch (...) {}
}
@@ -864,8 +849,7 @@ void unit::advance_to(const config &old_cfg, const unit_type &u_type,
game_events::add_events(cfg_.child_range("event"), new_type.id());
cfg_.clear_children("event");
- refreshing_ = false;
- anim_.reset();
+ anim_comp_->reset_after_advance();
}
std::string unit::big_profile() const
@@ -1069,7 +1053,7 @@ void unit::expire_modifications(const std::string & duration)
}
if ( rebuild_from != NULL ) {
- clear_haloes();
+ anim_comp_->clear_haloes();
advance_to(*rebuild_from);
}
}
@@ -1759,80 +1743,6 @@ const surface unit::still_image(bool scaled) const
return unit_image;
}
-void unit::set_standing(bool with_bars) const
-{
- display *disp = display::get_singleton();
- if (preferences::show_standing_animations()&& !incapacitated()) {
- start_animation(INT_MAX, choose_animation(*disp, loc_, "standing"),
- with_bars, "", 0, STATE_STANDING);
- } else {
- start_animation(INT_MAX, choose_animation(*disp, loc_, "_disabled_"),
- with_bars, "", 0, STATE_STANDING);
- }
-}
-
-void unit::set_ghosted(bool with_bars) const
-{
- display *disp = display::get_singleton();
- start_animation(INT_MAX, choose_animation(*disp, loc_, "ghosted"),
- with_bars);
-}
-
-void unit::set_disabled_ghosted(bool with_bars) const
-{
- display *disp = display::get_singleton();
- start_animation(INT_MAX, choose_animation(*disp, loc_, "disabled_ghosted"),
- with_bars);
-}
-
-void unit::set_idling() const
-{
- display *disp = display::get_singleton();
- start_animation(INT_MAX, choose_animation(*disp, loc_, "idling"),
- true, "", 0, STATE_FORGET);
-}
-
-void unit::set_selecting() const
-{
- const display *disp = display::get_singleton();
- if (preferences::show_standing_animations() && !get_state(STATE_PETRIFIED)) {
- start_animation(INT_MAX, choose_animation(*disp, loc_, "selected"),
- true, "", 0, STATE_FORGET);
- } else {
- start_animation(INT_MAX, choose_animation(*disp, loc_, "_disabled_selected_"),
- true, "", 0, STATE_FORGET);
- }
-}
-
-void unit::start_animation (int start_time, const unit_animation *animation,
- bool with_bars, const std::string &text, Uint32 text_color, STATE state) const
-{
- const display * disp = display::get_singleton();
- if (!animation) {
- if (state == STATE_STANDING)
- state_ = state;
- if (!anim_ && state_ != STATE_STANDING)
- set_standing(with_bars);
- return ;
- }
- state_ = state;
- // everything except standing select and idle
- bool accelerate = (state != STATE_FORGET && state != STATE_STANDING);
- draw_bars_ = with_bars;
- anim_.reset(new unit_animation(*animation));
- const int real_start_time = start_time == INT_MAX ? anim_->get_begin_time() : start_time;
- anim_->start_animation(real_start_time, loc_, loc_.get_direction(facing_),
- text, text_color, accelerate);
- frame_begin_time_ = anim_->get_begin_time() -1;
- if (disp->idle_anim()) {
- next_idling_ = get_current_animation_tick()
- + static_cast((20000 + rand() % 20000) * disp->idle_anim_rate());
- } else {
- next_idling_ = INT_MAX;
- }
-}
-
-
void unit::set_facing(map_location::DIRECTION dir) const {
if(dir != map_location::NDIRECTIONS) {
facing_ = dir;
@@ -1840,42 +1750,6 @@ void unit::set_facing(map_location::DIRECTION dir) const {
// Else look at yourself (not available so continue to face the same direction)
}
-void unit::clear_haloes () const
-{
- if(unit_halo_ != halo::NO_HALO) {
- halo::remove(unit_halo_);
- unit_halo_ = halo::NO_HALO;
- }
- if(anim_ ) anim_->clear_haloes();
-}
-bool unit::invalidate (const display & disp) const
-{
- bool result = false;
-
- // Very early calls, anim not initialized yet
- if(get_animation()) {
- frame_parameters params;
- const gamemap & map = disp.get_map();
- const t_translation::t_terrain terrain = map.get_terrain(get_location());
- const terrain_type& terrain_info = map.get_terrain_info(terrain);
-
- int height_adjust = static_cast(terrain_info.unit_height_adjust() * disp.get_zoom_factor());
- if (is_flying() && height_adjust < 0) {
- height_adjust = 0;
- }
- params.y -= height_adjust;
- params.halo_y -= height_adjust;
- params.image_mod = image_mods();
- params.halo_mod = TC_image_mods();
- params.image= absolute_image();
-
- result |= get_animation()->invalidate(params);
- }
-
- return result;
-
-}
-
int unit::upkeep() const
{
// Leaders do not incur upkeep.
@@ -2333,7 +2207,7 @@ void unit::add_modification(const std::string& mod_type, const config& mod, bool
cfg_["ellipse"] = effect["ellipse"];
} else if (apply_to == "halo") {
- clear_haloes();
+ anim_comp_->clear_haloes();
cfg_["halo"] = effect["halo"];
} else if (apply_to == "overlay") {
@@ -2478,31 +2352,6 @@ std::string unit::absolute_image() const {
return cfg_["image_icon"].empty() ? cfg_["image"] : cfg_["image_icon"];
}
-const unit_animation* unit::choose_animation(const display& disp, const map_location& loc,const std::string& event,
- const map_location& second_loc,const int value,const unit_animation::hit_type hit,
- const attack_type* attack, const attack_type* second_attack, int swing_num) const
-{
- // Select one of the matching animations at random
- std::vector options;
- int max_val = unit_animation::MATCH_FAIL;
- for(std::vector::const_iterator i = animations_.begin(); i != animations_.end(); ++i) {
- int matching = i->matches(disp,loc,second_loc,this,event,value,hit,attack,second_attack,swing_num);
- if(matching > unit_animation::MATCH_FAIL && matching == max_val) {
- options.push_back(&*i);
- } else if(matching > max_val) {
- max_val = matching;
- options.clear();
- options.push_back(&*i);
- }
- }
-
- if(max_val == unit_animation::MATCH_FAIL) {
- return NULL;
- }
- return options[rand()%options.size()];
-}
-
-
void unit::apply_modifications()
{
log_scope("apply mods");
@@ -2720,33 +2569,6 @@ int side_upkeep(int side)
return res;
}
-void unit::refresh() const
-{
- if (state_ == STATE_FORGET && anim_ && anim_->animation_finished_potential())
- {
- set_standing();
- return;
- }
- display &disp = *display::get_singleton();
- if (state_ != STATE_STANDING || get_current_animation_tick() < next_idling_ ||
- !disp.tile_nearly_on_screen(loc_) || incapacitated())
- {
- return;
- }
- if (get_current_animation_tick() > next_idling_ + 1000)
- {
- // prevent all units animating at the same time
- if (disp.idle_anim()) {
- next_idling_ = get_current_animation_tick()
- + static_cast((20000 + rand() % 20000) * disp.idle_anim_rate());
- } else {
- next_idling_ = INT_MAX;
- }
- } else {
- set_idling();
- }
-}
-
team_data calculate_team_data(const team& tm, int side)
{
team_data res;
@@ -2802,7 +2624,7 @@ void unit::set_hidden(bool state) const {
hidden_ = state;
if(!state) return;
// We need to get rid of haloes immediately to avoid display glitches
- clear_haloes();
+ anim_comp_->clear_haloes();
}
// Filters unimportant stats from the unit config and returns a checksum of
diff --git a/src/unit.hpp b/src/unit.hpp
index 365bf389018..9975c331c01 100644
--- a/src/unit.hpp
+++ b/src/unit.hpp
@@ -28,6 +28,7 @@
class display;
class gamemap;
class team;
+class unit_animation_component;
class unit_formula_manager;
class vconfig;
@@ -204,7 +205,6 @@ public:
void end_turn();
void new_scenario();
/** Called on every draw */
- void refresh() const;
bool take_hit(int damage) { hit_points_ -= damage; return hit_points_ <= 0; }
void heal(int amount);
@@ -248,21 +248,10 @@ public:
/** A SDL surface, ready for display for place where we need a still-image of the unit. */
const surface still_image(bool scaled = false) const;
- /** Clear unit_halo_ */
- void clear_haloes() const;
-
- void set_standing(bool with_bars = true) const;
-
- void set_ghosted(bool with_bars = true) const;
- void set_disabled_ghosted(bool with_bars = true) const;
-
- void set_idling() const;
- void set_selecting() const;
- unit_animation* get_animation() const { return anim_.get();}
+ unit_animation_component & anim_comp() const { return *anim_comp_; }
void set_facing(map_location::DIRECTION dir) const;
map_location::DIRECTION facing() const { return facing_; }
- bool invalidate(const display & disp) const;
const std::vector& trait_names() const { return trait_names_; }
const std::vector& trait_descriptions() const { return trait_descriptions_; }
std::vector get_traits_list() const;
@@ -319,15 +308,6 @@ public:
const map_location& get_interrupted_move() const { return interrupted_move_; }
void set_interrupted_move(const map_location& interrupted_move) { interrupted_move_ = interrupted_move; }
- /** States for animation. */
- enum STATE {
- STATE_STANDING, /** anim must fit in a hex */
- STATE_FORGET, /** animation will be automatically replaced by a standing anim when finished */
- STATE_ANIM}; /** normal anims */
- void start_animation (int start_time, const unit_animation *animation,
- bool with_bars, const std::string &text = "",
- Uint32 text_color = 0, STATE state = STATE_ANIM) const;
-
/** The name of the file to game_display (used in menus). */
std::string absolute_image() const;
std::string image_halo() const { return cfg_["halo"]; }
@@ -342,13 +322,6 @@ public:
/// Never returns NULL, but may point to the null race.
const unit_race* race() const { return race_; }
- 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::INVALID,
- const attack_type* attack=NULL,const attack_type* second_attack = NULL,
- int swing_num =0) const;
/**
* Returns true if the unit is currently under effect by an ability with this given TAG NAME.
@@ -477,7 +450,6 @@ private:
protected:
bool emit_zoc_;
- mutable STATE state_; //animation state
private:
std::vector overlays_;
@@ -497,19 +469,14 @@ private:
utils::string_map modification_descriptions_;
// Animations:
+ friend class unit_animation_component;
+
protected:
+ boost::scoped_ptr anim_comp_;
std::vector animations_;
- mutable boost::scoped_ptr anim_;
- mutable int next_idling_; // used for animation
- mutable int frame_begin_time_; // used for animation
-
-
- mutable int unit_halo_; // flag used for drawing / animation
bool getsHit_;
- mutable bool refreshing_; // avoid infinite recursion. flag used for drawing / animation
mutable bool hidden_;
- mutable bool draw_bars_; // flag used for drawing / animation
double hp_bar_scaling_, xp_bar_scaling_;
private:
diff --git a/src/unit_animation.cpp b/src/unit_animation.cpp
index aaf27153f65..a48a7341f38 100644
--- a/src/unit_animation.cpp
+++ b/src/unit_animation.cpp
@@ -19,10 +19,11 @@
#include "game_display.hpp"
#include "halo.hpp"
#include "map.hpp"
-#include "unit.hpp"
-#include "variable.hpp"
-#include "resources.hpp"
#include "play_controller.hpp"
+#include "resources.hpp"
+#include "unit.hpp"
+#include "unit_animation_component.hpp"
+#include "variable.hpp"
#include
@@ -1283,7 +1284,7 @@ void unit_animator::add_animation(const unit* animated_unit
tmp.text_color = text_color;
tmp.src = src;
tmp.with_bars= with_bars;
- tmp.animation = animated_unit->choose_animation(*disp,src,event,dst,value,hit_type,attack,second_attack,value2);
+ tmp.animation = animated_unit->anim_comp().choose_animation(*disp,src,event,dst,value,hit_type,attack,second_attack,value2);
if(!tmp.animation) return;
start_time_ = std::max(start_time_,tmp.animation->get_begin_time());
@@ -1326,9 +1327,9 @@ void unit_animator::replace_anim_if_invalid(const unit* animated_unit
{
if(!animated_unit) return;
display*disp = display::get_singleton();
- if(animated_unit->get_animation() &&
- !animated_unit->get_animation()->animation_finished_potential() &&
- animated_unit->get_animation()->matches(*disp,src,dst,animated_unit,event,value,hit_type,attack,second_attack,value2) >unit_animation::MATCH_FAIL) {
+ if(animated_unit->anim_comp().get_animation() &&
+ !animated_unit->anim_comp().get_animation()->animation_finished_potential() &&
+ animated_unit->anim_comp().get_animation()->matches(*disp,src,dst,animated_unit,event,value,hit_type,attack,second_attack,value2) >unit_animation::MATCH_FAIL) {
anim_elem tmp;
tmp.my_unit = animated_unit;
tmp.text = text;
@@ -1347,21 +1348,21 @@ void unit_animator::start_animations()
int begin_time = INT_MAX;
std::vector::iterator anim;
for(anim = animated_units_.begin(); anim != animated_units_.end();++anim) {
- if(anim->my_unit->get_animation()) {
+ if(anim->my_unit->anim_comp().get_animation()) {
if(anim->animation) {
begin_time = std::min(begin_time,anim->animation->get_begin_time());
} else {
- begin_time = std::min(begin_time,anim->my_unit->get_animation()->get_begin_time());
+ begin_time = std::min(begin_time,anim->my_unit->anim_comp().get_animation()->get_begin_time());
}
}
}
for(anim = animated_units_.begin(); anim != animated_units_.end();++anim) {
if(anim->animation) {
- anim->my_unit->start_animation(begin_time, anim->animation,
+ anim->my_unit->anim_comp().start_animation(begin_time, anim->animation,
anim->with_bars, anim->text, anim->text_color);
anim->animation = NULL;
} else {
- anim->my_unit->get_animation()->update_parameters(anim->src,anim->src.get_direction(anim->my_unit->facing()));
+ anim->my_unit->anim_comp().get_animation()->update_parameters(anim->src,anim->src.get_direction(anim->my_unit->facing()));
}
}
@@ -1371,7 +1372,7 @@ bool unit_animator::would_end() const
{
bool finished = true;
for(std::vector::const_iterator anim = animated_units_.begin(); anim != animated_units_.end();++anim) {
- finished &= anim->my_unit->get_animation()->animation_finished_potential();
+ finished &= anim->my_unit->anim_comp().get_animation()->animation_finished_potential();
}
return finished;
}
@@ -1381,7 +1382,7 @@ void unit_animator::wait_until(int animation_time) const
display*disp = display::get_singleton();
double speed = disp->turbo_speed();
resources::controller->play_slice(false);
- int end_tick = animated_units_[0].my_unit->get_animation()->time_to_tick(animation_time);
+ int end_tick = animated_units_[0].my_unit->anim_comp().get_animation()->time_to_tick(animation_time);
while (SDL_GetTicks() < static_cast(end_tick)
- std::min(static_cast(20/speed),20)) {
@@ -1389,7 +1390,7 @@ void unit_animator::wait_until(int animation_time) const
std::min(10,
static_cast((animation_time - get_animation_time()) * speed))));
resources::controller->play_slice(false);
- end_tick = animated_units_[0].my_unit->get_animation()->time_to_tick(animation_time);
+ end_tick = animated_units_[0].my_unit->anim_comp().get_animation()->time_to_tick(animation_time);
}
disp->delay(std::max(0,end_tick - SDL_GetTicks() +5));
new_animation_frame();
@@ -1442,25 +1443,25 @@ void unit_animator::wait_for_end() const
disp->delay(10);
finished = true;
for(std::vector::const_iterator anim = animated_units_.begin(); anim != animated_units_.end();++anim) {
- finished &= anim->my_unit->get_animation()->animation_finished_potential();
+ finished &= anim->my_unit->anim_comp().get_animation()->animation_finished_potential();
}
}
}
int unit_animator::get_animation_time() const{
- return animated_units_[0].my_unit->get_animation()->get_animation_time() ;
+ return animated_units_[0].my_unit->anim_comp().get_animation()->get_animation_time() ;
}
int unit_animator::get_animation_time_potential() const{
- return animated_units_[0].my_unit->get_animation()->get_animation_time_potential() ;
+ return animated_units_[0].my_unit->anim_comp().get_animation()->get_animation_time_potential() ;
}
int unit_animator::get_end_time() const
{
int end_time = INT_MIN;
for(std::vector::const_iterator anim = animated_units_.begin(); anim != animated_units_.end();++anim) {
- if(anim->my_unit->get_animation()) {
- end_time = std::max(end_time,anim->my_unit->get_animation()->get_end_time());
+ if(anim->my_unit->anim_comp().get_animation()) {
+ end_time = std::max(end_time,anim->my_unit->anim_comp().get_animation()->get_end_time());
}
}
return end_time;
@@ -1469,8 +1470,8 @@ int unit_animator::get_end_time() const
void unit_animator::pause_animation()
{
for(std::vector::iterator anim = animated_units_.begin(); anim != animated_units_.end();++anim) {
- if(anim->my_unit->get_animation()) {
- anim->my_unit->get_animation()->pause_animation();
+ if(anim->my_unit->anim_comp().get_animation()) {
+ anim->my_unit->anim_comp().get_animation()->pause_animation();
}
}
}
@@ -1478,8 +1479,8 @@ void unit_animator::pause_animation()
void unit_animator::restart_animation()
{
for(std::vector::iterator anim = animated_units_.begin(); anim != animated_units_.end();++anim) {
- if(anim->my_unit->get_animation()) {
- anim->my_unit->get_animation()->restart_animation();
+ if(anim->my_unit->anim_comp().get_animation()) {
+ anim->my_unit->anim_comp().get_animation()->restart_animation();
}
}
}
@@ -1487,6 +1488,6 @@ void unit_animator::restart_animation()
void unit_animator::set_all_standing()
{
for(std::vector::iterator anim = animated_units_.begin(); anim != animated_units_.end();++anim) {
- anim->my_unit->set_standing();
+ anim->my_unit->anim_comp().set_standing();
}
}
diff --git a/src/unit_animation_component.cpp b/src/unit_animation_component.cpp
new file mode 100644
index 00000000000..36f45e175a0
--- /dev/null
+++ b/src/unit_animation_component.cpp
@@ -0,0 +1,188 @@
+/*
+ Copyright (C) 2014 by Chris Beck
+ Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY.
+
+ See the COPYING file for more details.
+*/
+
+#include "unit_animation_component.hpp"
+
+#include "display.hpp"
+#include "map.hpp"
+#include "preferences.hpp"
+#include "unit_animation.hpp"
+#include "unit.hpp"
+
+const unit_animation* unit_animation_component::choose_animation(const display& disp, const map_location& loc,const std::string& event,
+ const map_location& second_loc,const int value,const unit_animation::hit_type hit,
+ const attack_type* attack, const attack_type* second_attack, int swing_num)
+{
+ // Select one of the matching animations at random
+ std::vector options;
+ int max_val = unit_animation::MATCH_FAIL;
+ for(std::vector::const_iterator i = u_.animations_.begin(); i != u_.animations_.end(); ++i) {
+ int matching = i->matches(disp,loc,second_loc,&u_,event,value,hit,attack,second_attack,swing_num);
+ if(matching > unit_animation::MATCH_FAIL && matching == max_val) {
+ options.push_back(&*i);
+ } else if(matching > max_val) {
+ max_val = matching;
+ options.clear();
+ options.push_back(&*i);
+ }
+ }
+
+ if(max_val == unit_animation::MATCH_FAIL) {
+ return NULL;
+ }
+ return options[rand()%options.size()];
+}
+
+void unit_animation_component::set_standing(bool with_bars)
+{
+ display *disp = display::get_singleton();
+ if (preferences::show_standing_animations()&& !u_.incapacitated()) {
+ start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "standing"),
+ with_bars, "", 0, STATE_STANDING);
+ } else {
+ start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "_disabled_"),
+ with_bars, "", 0, STATE_STANDING);
+ }
+}
+
+void unit_animation_component::set_ghosted(bool with_bars)
+{
+ display *disp = display::get_singleton();
+ start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "ghosted"),
+ with_bars);
+}
+
+void unit_animation_component::set_disabled_ghosted(bool with_bars)
+{
+ display *disp = display::get_singleton();
+ start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "disabled_ghosted"),
+ with_bars);
+}
+
+void unit_animation_component::set_idling()
+{
+ display *disp = display::get_singleton();
+ start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "idling"),
+ true, "", 0, STATE_FORGET);
+}
+
+void unit_animation_component::set_selecting()
+{
+ const display *disp = display::get_singleton();
+ if (preferences::show_standing_animations() && !u_.incapacitated()) {
+ start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "selected"),
+ true, "", 0, STATE_FORGET);
+ } else {
+ start_animation(INT_MAX, choose_animation(*disp, u_.loc_, "_disabled_selected_"),
+ true, "", 0, STATE_FORGET);
+ }
+}
+
+void unit_animation_component::start_animation (int start_time, const unit_animation *animation,
+ bool with_bars, const std::string &text, Uint32 text_color, STATE state)
+{
+ const display * disp = display::get_singleton();
+ if (!animation) {
+ if (state == STATE_STANDING)
+ state_ = state;
+ if (!anim_ && state_ != STATE_STANDING)
+ set_standing(with_bars);
+ return ;
+ }
+ state_ = state;
+ // everything except standing select and idle
+ bool accelerate = (state != STATE_FORGET && state != STATE_STANDING);
+ draw_bars_ = with_bars;
+ anim_.reset(new unit_animation(*animation));
+ const int real_start_time = start_time == INT_MAX ? anim_->get_begin_time() : start_time;
+ anim_->start_animation(real_start_time, u_.loc_, u_.loc_.get_direction(u_.facing_),
+ text, text_color, accelerate);
+ frame_begin_time_ = anim_->get_begin_time() -1;
+ if (disp->idle_anim()) {
+ next_idling_ = get_current_animation_tick()
+ + static_cast((20000 + rand() % 20000) * disp->idle_anim_rate());
+ } else {
+ next_idling_ = INT_MAX;
+ }
+}
+
+void unit_animation_component::refresh()
+{
+ if (state_ == STATE_FORGET && anim_ && anim_->animation_finished_potential())
+ {
+ set_standing();
+ return;
+ }
+ display &disp = *display::get_singleton();
+ if (state_ != STATE_STANDING || get_current_animation_tick() < next_idling_ ||
+ !disp.tile_nearly_on_screen(u_.loc_) || u_.incapacitated())
+ {
+ return;
+ }
+ if (get_current_animation_tick() > next_idling_ + 1000)
+ {
+ // prevent all units animating at the same time
+ if (disp.idle_anim()) {
+ next_idling_ = get_current_animation_tick()
+ + static_cast((20000 + rand() % 20000) * disp.idle_anim_rate());
+ } else {
+ next_idling_ = INT_MAX;
+ }
+ } else {
+ set_idling();
+ }
+}
+
+void unit_animation_component::clear_haloes ()
+{
+ if(unit_halo_ != halo::NO_HALO) {
+ halo::remove(unit_halo_);
+ unit_halo_ = halo::NO_HALO;
+ }
+ if(anim_ ) anim_->clear_haloes();
+}
+
+bool unit_animation_component::invalidate (const display & disp)
+{
+ bool result = false;
+
+ // Very early calls, anim not initialized yet
+ if(get_animation()) {
+ frame_parameters params;
+ const gamemap & map = disp.get_map();
+ const t_translation::t_terrain terrain = map.get_terrain(u_.loc_);
+ const terrain_type& terrain_info = map.get_terrain_info(terrain);
+
+ int height_adjust = static_cast(terrain_info.unit_height_adjust() * disp.get_zoom_factor());
+ if (u_.is_flying() && height_adjust < 0) {
+ height_adjust = 0;
+ }
+ params.y -= height_adjust;
+ params.halo_y -= height_adjust;
+ params.image_mod = u_.image_mods();
+ params.halo_mod = u_.TC_image_mods();
+ params.image= u_.absolute_image();
+
+ result |= get_animation()->invalidate(params);
+ }
+
+ return result;
+
+}
+
+void unit_animation_component::reset_after_advance()
+{
+ refreshing_ = false;
+ anim_.reset();
+}
diff --git a/src/unit_animation_component.hpp b/src/unit_animation_component.hpp
new file mode 100644
index 00000000000..0748aa2acda
--- /dev/null
+++ b/src/unit_animation_component.hpp
@@ -0,0 +1,104 @@
+/*
+ Copyright (C) 2014 by Chris Beck
+ Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY.
+
+ See the COPYING file for more details.
+*/
+
+// This class encapsulates the animation functionality of unit.
+
+#ifndef UNIT_ANIM_COMP_HPP
+#define UNIT_ANIM_COMP_HPP
+
+#include "halo.hpp"
+#include "unit_animation.hpp" //Note: only needed for enum
+
+#include
+
+class unit;
+
+class unit_animation_component
+{
+public:
+ /** States for animation. */
+ enum STATE {
+ STATE_STANDING, /** anim must fit in a hex */
+ STATE_FORGET, /** animation will be automatically replaced by a standing anim when finished */
+ STATE_ANIM}; /** normal anims */
+
+ unit_animation_component(unit & my_unit) :
+ u_(my_unit),
+ anim_(NULL),
+ state_(STATE_STANDING),
+ next_idling_(0),
+ frame_begin_time_(0),
+ draw_bars_(false),
+ refreshing_(false),
+ unit_halo_(halo::NO_HALO) {}
+
+ unit_animation_component(unit & my_unit, const unit_animation_component & o) :
+ u_(my_unit),
+ anim_(NULL),
+ state_(o.state_),
+ next_idling_(0),
+ frame_begin_time_(o.frame_begin_time_),
+ draw_bars_(o.draw_bars_),
+ refreshing_(o.refreshing_),
+ unit_halo_(halo::NO_HALO) {}
+
+ 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::INVALID,
+ const attack_type* attack=NULL,const attack_type* second_attack = NULL,
+ int swing_num =0);
+
+ void set_standing(bool with_bars = true);
+
+ void set_ghosted(bool with_bars = true);
+ void set_disabled_ghosted(bool with_bars = true);
+
+ void set_idling();
+ void set_selecting();
+
+ void start_animation (int start_time, const unit_animation *animation,
+ bool with_bars, const std::string &text = "",
+ Uint32 text_color = 0, STATE state = STATE_ANIM);
+
+ bool invalidate(const display & disp);
+
+ void refresh();
+
+ void clear_haloes();
+
+ void reset_after_advance();
+
+ unit_animation* get_animation() const { return anim_.get(); }
+
+ friend class unit;
+ friend class drawable_unit;
+private:
+ const unit & u_;
+
+ boost::scoped_ptr anim_;
+
+ STATE state_; //animation state
+
+ int next_idling_; // used for animation
+ int frame_begin_time_; // used for animation
+
+ bool draw_bars_;
+ bool refreshing_; // avoid infinite recursion. flag used for drawing / animation
+
+ int unit_halo_; // flag used for drawing / animation
+};
+
+#endif
diff --git a/src/unit_display.cpp b/src/unit_display.cpp
index 5de5413942b..3ccbe3c4c7a 100644
--- a/src/unit_display.cpp
+++ b/src/unit_display.cpp
@@ -26,6 +26,8 @@
#include "mouse_events.hpp"
#include "resources.hpp"
#include "terrain_filter.hpp"
+#include "unit.hpp"
+#include "unit_animation_component.hpp"
#include "unit_map.hpp"
#include
@@ -92,7 +94,7 @@ static void teleport_unit_between(const map_location& a, const map_location& b,
animator.wait_for_end();
}
- temp_unit.set_standing();
+ temp_unit.anim_comp().set_standing();
disp.update_display();
events::pump();
}
@@ -267,7 +269,7 @@ void unit_mover::start(unit& u)
// Initialize our temporary unit for the move.
temp_unit_ptr_->set_location(path_[0]);
temp_unit_ptr_->set_facing(path_[0].get_relative_dir(path_[1]));
- temp_unit_ptr_->set_standing(false);
+ temp_unit_ptr_->anim_comp().set_standing(false);
disp_->invalidate(path_[0]);
// If the unit can be seen here by the viewing side:
@@ -299,7 +301,7 @@ void unit_mover::start(unit& u)
// Switch the display back to the real unit.
u.set_facing(temp_unit_ptr_->facing());
- u.set_standing(false); // Need to reset u's animation so the new facing takes effect.
+ u.anim_comp().set_standing(false); // Need to reset u's animation so the new facing takes effect.
u.set_hidden(was_hidden_);
temp_unit_ptr_->set_hidden(true);
}
@@ -353,13 +355,13 @@ void unit_mover::proceed_to(unit& u, size_t path_index, bool update, bool wait)
temp_unit_ptr_->set_location(path_[current_]);
disp_->invalidate(path_[current_]);
// scroll in as much of the remaining path as possible
- if ( temp_unit_ptr_->get_animation() )
- temp_unit_ptr_->get_animation()->pause_animation();
+ if ( temp_unit_ptr_->anim_comp().get_animation() )
+ temp_unit_ptr_->anim_comp().get_animation()->pause_animation();
disp_->scroll_to_tiles(path_.begin() + current_,
path_.end(), game_display::ONSCREEN,
true, false, 0.0, force_scroll_);
- if ( temp_unit_ptr_->get_animation() )
- temp_unit_ptr_->get_animation()->restart_animation();
+ if ( temp_unit_ptr_->anim_comp().get_animation() )
+ temp_unit_ptr_->anim_comp().get_animation()->restart_animation();
}
if ( tiles_adjacent(path_[current_], path_[current_+1]) )
@@ -375,7 +377,7 @@ void unit_mover::proceed_to(unit& u, size_t path_index, bool update, bool wait)
// Update the unit's facing.
u.set_facing(temp_unit_ptr_->facing());
- u.set_standing(false); // Need to reset u's animation so the new facing takes effect.
+ u.anim_comp().set_standing(false); // Need to reset u's animation so the new facing takes effect.
// Remember the unit to unhide when the animation finishes.
shown_unit_ = &u;
if ( wait )
@@ -458,7 +460,7 @@ void unit_mover::finish(unit &u, map_location::DIRECTION dir)
// Facing gets set even when not animating.
u.set_facing(dir == map_location::NDIRECTIONS ? final_dir : dir);
- u.set_standing(true); // Need to reset u's animation so the new facing takes effect.
+ u.anim_comp().set_standing(true); // Need to reset u's animation so the new facing takes effect.
// Redraw path ends (even if not animating).
disp_->invalidate(path_.front());
@@ -532,10 +534,10 @@ void unit_sheath_weapon(const map_location& primary_loc, unit* primary_unit,
animator.wait_for_end();
}
if(primary_unit) {
- primary_unit->set_standing();
+ primary_unit->anim_comp().set_standing();
}
if(secondary_unit) {
- secondary_unit->set_standing();
+ secondary_unit->anim_comp().set_standing();
}
reset_helpers(primary_unit,secondary_unit);
@@ -618,7 +620,7 @@ void unit_attack(display * disp, game_board & board,
hit_type, &attack, secondary_attack, swing);
// note that we take an anim from the real unit, we'll use it later
- const unit_animation *defender_anim = def->choose_animation(*disp,
+ const unit_animation *defender_anim = def->anim_comp().choose_animation(*disp,
def->get_location(), "defend", att->get_location(), damage,
hit_type, &attack, secondary_attack, swing);
animator.add_animation(&defender, defender_anim, def->get_location(),
@@ -660,7 +662,7 @@ void unit_attack(display * disp, game_board & board,
}
animator.wait_for_end();
// pass the animation back to the real unit
- def->start_animation(animator.get_end_time(), defender_anim, true);
+ def->anim_comp().start_animation(animator.get_end_time(), defender_anim, true);
reset_helpers(&*att, &*def);
def->set_hitpoints(def_hitpoints);
}
@@ -675,7 +677,7 @@ void reset_helpers(const unit *attacker,const unit *defender)
BOOST_FOREACH (const unit_ability & ability, leaders) {
unit_map::const_iterator leader = units.find(ability.second);
assert(leader != units.end());
- leader->set_standing();
+ leader->anim_comp().set_standing();
}
}
@@ -684,7 +686,7 @@ void reset_helpers(const unit *attacker,const unit *defender)
BOOST_FOREACH (const unit_ability & ability, helpers) {
unit_map::const_iterator helper = units.find(ability.second);
assert(helper != units.end());
- helper->set_standing();
+ helper->anim_comp().set_standing();
}
}
}
diff --git a/src/whiteboard/highlighter.cpp b/src/whiteboard/highlighter.cpp
index e6aadee3e7b..18516117e15 100644
--- a/src/whiteboard/highlighter.cpp
+++ b/src/whiteboard/highlighter.cpp
@@ -42,6 +42,7 @@
#include "play_controller.hpp"
#include "resources.hpp"
#include "unit.hpp"
+#include "unit_animation_component.hpp"
#include "unit_map.hpp"
#include
@@ -198,7 +199,7 @@ void highlighter::last_action_redraw(move_ptr move)
bool this_is_second_to_last_action = (second_to_last_action != sa.end() && move == *second_to_last_action);
if(this_is_last_action || (this_is_second_to_last_action && !last_action_has_fake_unit)) {
- move->get_fake_unit()->set_standing(true);
+ move->get_fake_unit()->anim_comp().set_standing(true);
}
}
}
@@ -276,7 +277,7 @@ void highlighter::highlight_main_visitor::visit(move_ptr move)
}
if(move->get_fake_unit()) {
///@todo find some highlight animation
- move->get_fake_unit()->set_ghosted(true);
+ move->get_fake_unit()->anim_comp().set_ghosted(true);
//Make sure the fake unit is the only one displayed in its hex
resources::screen->add_exclusive_draw(move->get_fake_unit()->get_location(), *move->get_fake_unit());
highlighter_.exclusive_display_hexes_.insert(move->get_fake_unit()->get_location());
@@ -308,7 +309,7 @@ void highlighter::highlight_secondary_visitor::visit(move_ptr move)
move->set_arrow_brightness(move::ARROW_BRIGHTNESS_HIGHLIGHTED);
}
if(move->get_fake_unit()) {
- move->get_fake_unit()->set_ghosted(true);
+ move->get_fake_unit()->anim_comp().set_ghosted(true);
//Make sure the fake unit is the only one displayed in its hex
resources::screen->add_exclusive_draw(move->get_fake_unit()->get_location(), *move->get_fake_unit());
highlighter_.exclusive_display_hexes_.insert(move->get_fake_unit()->get_location());
@@ -328,7 +329,7 @@ void highlighter::unhighlight_visitor::visit(move_ptr move)
move->set_arrow_brightness(move::ARROW_BRIGHTNESS_STANDARD);
}
if(move->get_fake_unit()) {
- move->get_fake_unit()->set_disabled_ghosted(false);
+ move->get_fake_unit()->anim_comp().set_disabled_ghosted(false);
highlighter_.last_action_redraw(move);
}
diff --git a/src/whiteboard/manager.cpp b/src/whiteboard/manager.cpp
index bdcca51c26d..ba2c0028439 100644
--- a/src/whiteboard/manager.cpp
+++ b/src/whiteboard/manager.cpp
@@ -45,6 +45,8 @@
#include "play_controller.hpp"
#include "resources.hpp"
#include "team.hpp"
+#include "unit.hpp"
+#include "unit_animation_component.hpp"
#include "unit_display.hpp"
#include
@@ -334,7 +336,7 @@ void manager::post_delete_action(action_ptr action)
if(action_it != side_actions->end()) {
move_ptr move = boost::dynamic_pointer_cast(*action_it);
if(move && move->get_fake_unit()) {
- move->get_fake_unit()->set_standing(true);
+ move->get_fake_unit()->anim_comp().set_standing(true);
}
}
}
@@ -714,13 +716,13 @@ void manager::create_temp_move()
// Create temp ghost unit
fake_unit.reset(new class fake_unit(*temp_moved_unit));
fake_unit->place_on_fake_unit_manager( resources::fake_units);
- fake_unit->set_ghosted(true);
+ fake_unit->anim_comp().set_ghosted(true);
}
unit_display::move_unit(path, *fake_unit, false); //get facing right
- fake_unit->invalidate(*game_display::get_singleton());
+ fake_unit->anim_comp().invalidate(*game_display::get_singleton());
fake_unit->set_location(*curr_itor);
- fake_unit->set_ghosted(true);
+ fake_unit->anim_comp().set_ghosted(true);
}
else //zero-hex path -- don't bother drawing a fake unit
fake_unit.reset();
@@ -730,7 +732,7 @@ void manager::create_temp_move()
}
//in case path shortens on next step and one ghosted unit has to be removed
int ind = fake_units_.size() - 1;
- fake_units_[ind]->invalidate(*game_display::get_singleton());
+ fake_units_[ind]->anim_comp().invalidate(*game_display::get_singleton());
//toss out old arrows and fake units
move_arrows_.resize(turn+1);
fake_units_.resize(turn+1);
@@ -741,7 +743,7 @@ void manager::erase_temp_move()
move_arrows_.clear();
BOOST_FOREACH(fake_unit_ptr const& tmp, fake_units_) {
if(tmp) {
- tmp->invalidate(*game_display::get_singleton());
+ tmp->anim_comp().invalidate(*game_display::get_singleton());
}
}
fake_units_.clear();
@@ -812,7 +814,7 @@ void manager::save_temp_attack(const map_location& attacker_loc, const map_locat
assert(route_->steps.back() == attacker_loc);
source_hex = route_->steps.front();
- fake_unit->set_disabled_ghosted(true);
+ fake_unit->anim_comp().set_disabled_ghosted(true);
}
else
{
diff --git a/src/whiteboard/move.cpp b/src/whiteboard/move.cpp
index 33bd61b36fe..e6ded93e559 100644
--- a/src/whiteboard/move.cpp
+++ b/src/whiteboard/move.cpp
@@ -35,6 +35,7 @@
#include "resources.hpp"
#include "team.hpp"
#include "unit.hpp"
+#include "unit_animation_component.hpp"
#include "unit_display.hpp"
#include "unit_map.hpp"
@@ -135,7 +136,7 @@ move::move(config const& cfg, bool hidden)
if(hidden)
fake_unit_->set_hidden(true);
fake_unit_->place_on_fake_unit_manager(resources::fake_units);
- fake_unit_->set_ghosted(true);
+ fake_unit_->anim_comp().set_ghosted(true);
unit_display::move_unit(route_->steps, *fake_unit_, false); //get facing right
fake_unit_->set_location(route_->steps.back());
@@ -151,7 +152,7 @@ void move::init()
//than previous actions' fake units
if (fake_unit_)
{
- fake_unit_->set_ghosted(true);
+ fake_unit_->anim_comp().set_ghosted(true);
}
side_actions_ptr side_actions = resources::teams->at(team_index()).get_side_actions();
side_actions::iterator action = side_actions->find_last_action_of(*(get_unit()));
@@ -160,7 +161,7 @@ void move::init()
if (move_ptr move = boost::dynamic_pointer_cast(*action))
{
if (move->fake_unit_)
- move->fake_unit_->set_disabled_ghosted(true);
+ move->fake_unit_->anim_comp().set_disabled_ghosted(true);
}
}
diff --git a/src/whiteboard/recall.cpp b/src/whiteboard/recall.cpp
index 0b1b96d9a1b..d2b00c67526 100644
--- a/src/whiteboard/recall.cpp
+++ b/src/whiteboard/recall.cpp
@@ -33,6 +33,7 @@
#include "synced_context.hpp"
#include "team.hpp"
#include "unit.hpp"
+#include "unit_animation_component.hpp"
#include
@@ -98,7 +99,7 @@ void recall::init()
fake_unit_->set_location(recall_hex_);
fake_unit_->set_movement(0, true);
fake_unit_->set_attacks(0);
- fake_unit_->set_ghosted(false);
+ fake_unit_->anim_comp().set_ghosted(false);
fake_unit_->place_on_fake_unit_manager( resources::fake_units);
}
diff --git a/src/whiteboard/recruit.cpp b/src/whiteboard/recruit.cpp
index 0ad53fd7953..2c1feaa6ec8 100644
--- a/src/whiteboard/recruit.cpp
+++ b/src/whiteboard/recruit.cpp
@@ -29,6 +29,7 @@
#include "play_controller.hpp"
#include "resources.hpp"
#include "unit.hpp"
+#include "unit_animation_component.hpp"
#include "unit_map.hpp"
#include "unit_types.hpp"
@@ -87,7 +88,7 @@ void recruit::init()
fake_unit_->set_location(recruit_hex_);
fake_unit_->set_movement(0, true);
fake_unit_->set_attacks(0);
- fake_unit_->set_ghosted(false);
+ fake_unit_->anim_comp().set_ghosted(false);
fake_unit_->place_on_fake_unit_manager(resources::fake_units);
cost_ = fake_unit_->type().cost();
diff --git a/src/whiteboard/utility.cpp b/src/whiteboard/utility.cpp
index d50f2859b09..36861f6a5d1 100644
--- a/src/whiteboard/utility.cpp
+++ b/src/whiteboard/utility.cpp
@@ -32,6 +32,7 @@
#include "resources.hpp"
#include "team.hpp"
#include "unit.hpp"
+#include "unit_animation_component.hpp"
#include
@@ -140,13 +141,13 @@ temporary_unit_hider::~temporary_unit_hider()
void ghost_owner_unit(unit* unit)
{
- unit->set_disabled_ghosted(false);
+ unit->anim_comp().set_disabled_ghosted(false);
resources::screen->invalidate(unit->get_location());
}
void unghost_owner_unit(unit* unit)
{
- unit->set_standing(true);
+ unit->anim_comp().set_standing(true);
resources::screen->invalidate(unit->get_location());
}