Upgraded unit_animation and unit_frame to use t_token and t_interned.

1. Changed std::strings to t_token when used as indices.

2. Made a frame_parsed_parameters token resulting in upto 25% memory
savings if unit animations are on for a large variety of units.
This commit is contained in:
Thonsew 2011-09-08 19:17:48 +00:00
parent 7e99017fa4
commit d56fbf14fe
12 changed files with 899 additions and 533 deletions

View file

@ -208,8 +208,9 @@ bool animate_unit_advancement(const map_location &loc, size_t choice, const bool
if (!resources::screen->video().update_locked()) {
unit_animator animator;
bool with_bars = true;
animator.add_animation(&*u,"levelout", u->get_location(), map_location(), 0, with_bars);
bool with_bars = true;
static const config::t_token z_levelout("levelout", false);
animator.add_animation(&*u, z_levelout, u->get_location(), map_location(), 0, with_bars);
animator.start_animations();
animator.wait_for_end();
}
@ -245,7 +246,8 @@ bool animate_unit_advancement(const map_location &loc, size_t choice, const bool
if (u != resources::units->end() && !resources::screen->video().update_locked()) {
unit_animator animator;
animator.add_animation(&*u, "levelin", u->get_location(), map_location(), 0, true);
static const config::t_token z_levelin("levelin", false);
animator.add_animation(&*u, z_levelin, u->get_location(), map_location(), 0, true);
animator.start_animations();
animator.wait_for_end();
animator.set_all_standing();

View file

@ -348,6 +348,11 @@ size_t hash_value(const locator::value& val) {
return hash;
}
size_t hash_value(const locator& a) {
size_t hash = hash_value(a.val_);
boost::hash_combine(hash, a.index_);
return hash;
}
// Check if localized file is uptodate according to l10n track index.
// Make sure only that the image is not explicitly recorded as fuzzy,
// in order to be able to use non-tracked images (e.g. from UMC).

View file

@ -67,6 +67,7 @@ namespace image {
};
friend size_t hash_value(const value&);
friend size_t hash_value(const locator&);
public:
@ -140,6 +141,7 @@ namespace image {
};
size_t hash_value(const locator::value&);
size_t hash_value(const locator& );
typedef cache_type<surface> image_cache;

View file

@ -77,6 +77,8 @@ public:
inline std::string operator+(const n_token::t_token &a, const std::string &b) { return static_cast<std::string const &>(a) + b; }
inline std::string operator+(const std::string &a, const n_token::t_token &b) { return a + static_cast<std::string const &>(b); }
inline std::string operator+(const n_token::t_token &a, const char *b) { return static_cast<std::string const &>(a) + b; }
inline std::string operator+(const char *a, const n_token::t_token &b) { return a + static_cast<std::string const &>(b); }
inline std::string operator+(const n_token::t_token &a, const n_token::t_token &b) {
return static_cast<std::string const &>(a) + static_cast<std::string const &>(b); }

View file

@ -1928,8 +1928,7 @@ void unit::set_selecting()
}
void unit::start_animation(int start_time, const unit_animation *animation,
bool with_bars, const std::string &text, Uint32 text_color, STATE state)
{
bool with_bars, const n_token::t_token &text, Uint32 text_color, STATE state) {
const game_display * disp = game_display::get_singleton();
state_ = state;
if (!animation) {
@ -2832,7 +2831,7 @@ void unit::add_trait_description(const config& trait, const t_string& descriptio
}
}
const unit_animation* unit::choose_animation(const game_display& disp, const map_location& loc,const std::string& event,
const unit_animation* unit::choose_animation(const game_display& disp, const map_location& loc,const n_token::t_token& 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
{

View file

@ -287,8 +287,8 @@ public:
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);
bool with_bars, const n_token::t_token &text = z_empty,
Uint32 text_color = 0, STATE state = STATE_ANIM);
/** The name of the file to game_display (used in menus). */
config::t_token const & absolute_image() const { return cfg_[z_image]; }
@ -304,7 +304,7 @@ public:
const unit_race* race() const { return race_; }
const unit_animation* choose_animation(const game_display& disp,
const map_location& loc, const std::string& event,
const map_location& loc, const n_token::t_token& event,
const map_location& second_loc = map_location::null_location,
const int damage=0,
const unit_animation::hit_type hit_type = unit_animation::INVALID,

File diff suppressed because it is too large Load diff

View file

@ -19,6 +19,12 @@
#include "config.hpp"
#include "unit_frame.hpp"
namespace {
//Static tokens are replacements for string literals in code
//They allow for fast comparison, copying and hashing operations.
static const config::t_token z_frame("frame", false);
}
class attack_type;
class game_display;
class unit;
@ -31,11 +37,11 @@ class unit_animation
typedef enum { MATCH_FAIL=-10 , DEFAULT_ANIM=-9} variation_type;
typedef enum { HIT, MISS, KILL, INVALID} hit_type;
static const std::vector<std::string>& all_tag_names();
static const std::vector<n_token::t_token>& all_tag_names();
static void fill_initial_animations( std::vector<unit_animation> & animations, const config & cfg);
static void add_anims( std::vector<unit_animation> & animations, const config & cfg);
int matches(const game_display &disp,const map_location& loc,const map_location& second_loc,const unit* my_unit,const std::string & event="",const int value=0,hit_type hit=INVALID,const attack_type* attack=NULL,const attack_type* second_attack = NULL, int value2 =0) const;
int matches(const game_display &disp,const map_location& loc,const map_location& second_loc,const unit* my_unit,const n_token::t_token & event=z_empty,const int value=0,hit_type hit=INVALID,const attack_type* attack=NULL,const attack_type* second_attack = NULL, int value2 =0) const;
const unit_frame& get_last_frame() const{ return unit_anim_.get_last_frame() ; };
@ -54,7 +60,7 @@ class unit_animation
void start_animation(int start_time
, const map_location &src = map_location::null_location
, const map_location &dst = map_location::null_location
, const std::string& text = ""
, const n_token::t_token& text = z_empty
, const Uint32 text_color = 0
, const bool accelerate = true);
void update_parameters(const map_location &src, const map_location &dst);
@ -67,7 +73,7 @@ class unit_animation
friend class unit;
explicit unit_animation(const config &cfg, const std::string &frame_string = "");
explicit unit_animation(const config &cfg, const n_token::t_token &frame_string = z_empty);
protected:
// reserved to class unit, for the special case of redrawing the unit base frame
@ -75,23 +81,22 @@ class unit_animation
private:
explicit unit_animation(int start_time
, const unit_frame &frame
, const std::string& event = ""
, const n_token::t_token& event = z_empty
, const int variation=DEFAULT_ANIM
, const frame_builder & builder = frame_builder());
class particule:public animated<unit_frame>
{
class particule:public animated<unit_frame> {
public:
explicit particule(int start_time=0,const frame_builder &builder = frame_builder()) :
animated<unit_frame>(start_time),
accelerate(true),
parameters_(builder),
parameters_(frame_parsed_parameters(builder)),
halo_id_(0),
last_frame_begin_time_(0),
cycles_(false)
{};
explicit particule(const config& cfg
, const std::string& frame_string ="frame");
, const n_token::t_token& frame_string = z_frame);
virtual ~particule();
bool need_update() const;
@ -100,22 +105,25 @@ class unit_animation
void override(int start_time
, int duration
, const cycle_state cycles
, const std::string& highlight = ""
, const std::string& blend_ratio =""
, const n_token::t_token& highlight = z_empty
, const n_token::t_token& blend_ratio =z_empty
, Uint32 blend_color = 0
, const std::string& offset = ""
, const std::string& layer = ""
, const std::string& modifiers = "");
, const n_token::t_token& offset = z_empty
, const n_token::t_token& layer = z_empty
, const n_token::t_token& modifiers = z_empty);
void redraw( const frame_parameters& value,const map_location &src, const map_location &dst);
std::set<map_location> get_overlaped_hex(const frame_parameters& value,const map_location &src, const map_location &dst);
void start_animation(int start_time);
const frame_parameters parameters(const frame_parameters & default_val) const { return get_current_frame().merge_parameters(get_current_frame_time(),parameters_.parameters(get_animation_time()-get_begin_time()),default_val); };
const frame_parameters parameters(const frame_parameters & default_val) const {
return get_current_frame().merge_parameters(get_current_frame_time(), (*parameters_).parameters(get_animation_time()-get_begin_time()),default_val); };
void clear_halo();
bool accelerate;
private:
typedef n_interned::t_interned_token<frame_parsed_parameters> t_frame_parameter_token;
//animation params that can be locally overridden by frames
frame_parsed_parameters parameters_;
t_frame_parameter_token parameters_;
int halo_id_;
int last_frame_begin_time_;
bool cycles_;
@ -127,13 +135,13 @@ class unit_animation
std::vector<map_location::DIRECTION> directions_;
int frequency_;
int base_score_;
std::vector<std::string> event_;
std::vector<n_token::t_token> event_;
std::vector<int> value_;
std::vector<config> primary_attack_filter_;
std::vector<config> secondary_attack_filter_;
std::vector<hit_type> hits_;
std::vector<int> value2_;
std::map<std::string,particule> sub_anims_;
std::map<n_token::t_token,particule> sub_anims_;
particule unit_anim_;
/* these are drawing parameters, but for efficiancy reason they are in the anim and not in the particle */
map_location src_;
@ -158,15 +166,15 @@ class unit_animator
, const unit_animation * animation
, const map_location &src = map_location::null_location
, bool with_bars = false
, const std::string& text = ""
, const n_token::t_token& text = z_empty
, const Uint32 text_color = 0);
void add_animation(unit* animated_unit
, const std::string& event
, const n_token::t_token& event
, const map_location &src = map_location::null_location
, const map_location &dst = map_location::null_location
, const int value = 0
, bool with_bars = false
, const std::string& text = ""
, const n_token::t_token& text = z_empty
, const Uint32 text_color = 0
, const unit_animation::hit_type hit_type =
unit_animation::INVALID
@ -174,12 +182,12 @@ class unit_animator
, const attack_type* second_attack = NULL
, int value2 = 0);
void replace_anim_if_invalid(unit* animated_unit
, const std::string& event
, const n_token::t_token& event
, const map_location &src = map_location::null_location
, const map_location &dst = map_location::null_location
, const int value = 0
, bool with_bars = false
, const std::string& text = ""
, const n_token::t_token& text = z_empty
, const Uint32 text_color = 0
, const unit_animation::hit_type hit_type =
unit_animation::INVALID
@ -213,7 +221,7 @@ class unit_animator
unit *my_unit;
const unit_animation * animation;
std::string text;
n_token::t_token text;
Uint32 text_color;
map_location src;
bool with_bars;

View file

@ -35,6 +35,42 @@ namespace {
static const config::t_token z_red("red", false);
static const config::t_token z_green("green", false);
static const config::t_token z_blue("blue", false);
static const config::t_token z_pre_teleport("pre_teleport", false);
static const config::t_token z_post_teleport("post_teleport", false);
static const config::t_token z_movement("movement", false);
static const config::t_token z_pre_movement("pre_movement", false);
static const config::t_token z_post_movement("post_movement", false);
static const config::t_token z_draw_weapon("draw_weapon", false);
static const config::t_token z_sheath_weapon("sheath_weapon", false);
static const config::t_token z_death("death", false);
static const config::t_token z_victory("victory", false);
static const config::t_token z_unit_attack("unit_attack", false);
static const config::t_token z_leadership("leadership", false);
static const config::t_token z_resistance("resistance", false);
static const config::t_token z_attack("attack", false);
static const config::t_token z_defend("defend", false);
static const config::t_token z_leading("leading", false);
static const config::t_token z_recruiting("recruiting", false);
static const config::t_token z_recruited("recruited", false);
static const config::t_token z_healing("healing", false);
static const config::t_token z_poisoned("poisoned", false);
static const config::t_token z_healed("healed", false);
static const config::t_token z_filter("filter", false);
static const config::t_token z_primary_attack("primary_attack", false);
static const config::t_token z_secondary_attack("secondary_attack", false);
static const config::t_token z_hits("hits", false);
static const config::t_token z_yes("yes", false);
static const config::t_token z_hit("hit", false);
static const config::t_token z_no("no", false);
static const config::t_token z_miss("miss", false);
static const config::t_token z_kill("kill", false);
static const config::t_token z_facing("facing", false);
static const config::t_token z_flag("flag", false);
static const config::t_token z_value("value", false);
static const config::t_token z_with_bars("with_bars", false);
static const config::t_token z_text("text", false);
static const config::t_token z_value_second("value_second", false);
static const config::t_token z_animate("animate", false);
}
@ -51,7 +87,7 @@ static void teleport_unit_between( const map_location& a, const map_location& b,
disp->invalidate(temp_unit.get_location());
temp_unit.set_facing(a.get_relative_dir(b));
unit_animator animator;
animator.add_animation(&temp_unit,"pre_teleport",a);
animator.add_animation(&temp_unit,z_pre_teleport,a);
animator.start_animations();
animator.wait_for_end();
}
@ -62,7 +98,7 @@ static void teleport_unit_between( const map_location& a, const map_location& b,
temp_unit.set_facing(a.get_relative_dir(b));
disp->scroll_to_tiles(b,a,game_display::ONSCREEN,true,0.0,false);
unit_animator animator;
animator.add_animation(&temp_unit,"post_teleport",b);
animator.add_animation(&temp_unit,z_post_teleport,b);
animator.start_animations();
animator.wait_for_end();
}
@ -83,8 +119,8 @@ static void move_unit_between(const map_location& a, const map_location& b, unit
disp->invalidate(temp_unit.get_location());
temp_unit.set_facing(a.get_relative_dir(b));
unit_animator animator;
animator.replace_anim_if_invalid(&temp_unit,"movement",a,b,step_num,
false,"",0,unit_animation::INVALID,NULL,NULL,step_left);
animator.replace_anim_if_invalid(&temp_unit,z_movement,a,b,step_num,
false,z_empty,0,unit_animation::INVALID,NULL,NULL,step_left);
animator.start_animations();
animator.pause_animation();
disp->scroll_to_tiles(a,b,game_display::ONSCREEN,true,0.0,false);
@ -180,7 +216,7 @@ void move_unit(const std::vector<map_location>& path, unit& u,
disp->invalidate(temp_unit.get_location());
temp_unit.set_facing(path[0].get_relative_dir(path[1]));
unit_animator animator;
animator.add_animation(&temp_unit,"pre_movement",path[0],path[1]);
animator.add_animation(&temp_unit,z_pre_movement,path[0],path[1]);
animator.start_animations();
animator.wait_for_end();
@ -218,7 +254,7 @@ void move_unit(const std::vector<map_location>& path, unit& u,
temp_unit.set_location(path[path.size() - 1]);
temp_unit.set_facing(path[path.size()-2].get_relative_dir(path[path.size()-1]));
animator.clear();
animator.add_animation(&temp_unit,"post_movement",path[path.size()-1],map_location::null_location);
animator.add_animation(&temp_unit,z_post_movement,path[path.size()-1],map_location::null_location);
animator.start_animations();
animator.wait_for_end();
temp_unit.remove_from_game_display();
@ -245,8 +281,8 @@ void unit_draw_weapon(const map_location& loc, unit& attacker,
return;
}
unit_animator animator;
animator.add_animation(&attacker,"draw_weapon",loc,defender_loc,0,false,"",0,unit_animation::HIT,attack,secondary_attack,0);
animator.add_animation(defender,"draw_weapon",defender_loc,loc,0,false,"",0,unit_animation::MISS,secondary_attack,attack,0);
animator.add_animation(&attacker,z_draw_weapon,loc,defender_loc,0,false,z_empty,0,unit_animation::HIT,attack,secondary_attack,0);
animator.add_animation(defender,z_draw_weapon,defender_loc,loc,0,false,z_empty,0,unit_animation::MISS,secondary_attack,attack,0);
animator.start_animations();
animator.wait_for_end();
@ -262,10 +298,10 @@ void unit_sheath_weapon(const map_location& primary_loc, unit* primary_unit,
}
unit_animator animator;
if(primary_unit) {
animator.add_animation(primary_unit,"sheath_weapon",primary_loc,secondary_loc,0,false,"",0,unit_animation::INVALID,primary_attack,secondary_attack,0);
animator.add_animation(primary_unit,z_sheath_weapon,primary_loc,secondary_loc,0,false,z_empty,0,unit_animation::INVALID,primary_attack,secondary_attack,0);
}
if(secondary_unit) {
animator.add_animation(secondary_unit,"sheath_weapon",secondary_loc,primary_loc,0,false,"",0,unit_animation::INVALID,secondary_attack,primary_attack,0);
animator.add_animation(secondary_unit,z_sheath_weapon,secondary_loc,primary_loc,0,false,z_empty,0,unit_animation::INVALID,secondary_attack,primary_attack,0);
}
if(primary_unit || secondary_unit) {
@ -292,9 +328,9 @@ void unit_die(const map_location& loc, unit& loser,
}
unit_animator animator;
// hide the hp/xp bars of the loser (useless and prevent bars around an erased unit)
animator.add_animation(&loser,"death",loc,winner_loc,0,false,"",0,unit_animation::KILL,attack,secondary_attack,0);
animator.add_animation(&loser,z_death,loc,winner_loc,0,false,z_empty,0,unit_animation::KILL,attack,secondary_attack,0);
// but show the bars of the winner (avoid blinking and show its xp gain)
animator.add_animation(winner,"victory",winner_loc,loc,0,true,"",0,
animator.add_animation(winner,z_victory,winner_loc,loc,0,true,z_empty,0,
unit_animation::KILL,secondary_attack,attack,0);
animator.start_animations();
animator.wait_for_end();
@ -323,7 +359,7 @@ void unit_attack(
// scroll such that there is at least half a hex spacing around fighters
disp->scroll_to_tiles(a,b,game_display::ONSCREEN,true,0.5,false);
log_scope("unit_attack");
log_scope(z_unit_attack);
const unit_map::iterator att = units.find(a);
assert(att != units.end());
@ -340,8 +376,8 @@ void unit_attack(
unit_animator animator;
unit_ability_list leaders = attacker.get_abilities("leadership");
unit_ability_list helpers = defender.get_abilities("resistance");
unit_ability_list leaders = attacker.get_abilities(z_leadership);
unit_ability_list helpers = defender.get_abilities(z_resistance);
std::string text ;
if(damage) text = lexical_cast<std::string>(damage);
@ -365,17 +401,17 @@ void unit_attack(
}else {
hit_type = unit_animation::MISS;
}
animator.add_animation(&attacker, "attack", att->get_location(),
def->get_location(), damage, true, text_2,
display::rgb(0, 255, 0), hit_type, &attack, secondary_attack,
swing);
animator.add_animation(&attacker, z_attack, att->get_location(),
def->get_location(), damage, true, n_token::t_token(text_2),
display::rgb(0, 255, 0), 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,
def->get_location(), "defend", att->get_location(), damage,
def->get_location(), z_defend, att->get_location(), damage,
hit_type, &attack, secondary_attack, swing);
animator.add_animation(&defender, defender_anim, def->get_location(),
true, text , display::rgb(255, 0, 0));
true, n_token::t_token(text) , display::rgb(255, 0, 0));
for (std::vector<std::pair<const config *, map_location> >::iterator itor = leaders.cfgs.begin(); itor != leaders.cfgs.end(); ++itor) {
if(itor->second == a) continue;
@ -383,8 +419,8 @@ void unit_attack(
unit_map::iterator leader = units.find(itor->second);
assert(leader != units.end());
leader->set_facing(itor->second.get_relative_dir(a));
animator.add_animation(&*leader, "leading", itor->second,
att->get_location(), damage, true, "", 0,
animator.add_animation(&*leader, z_leading, itor->second,
att->get_location(), damage, true, z_empty, 0,
hit_type, &attack, secondary_attack, swing);
}
for (std::vector<std::pair<const config *, map_location> >::iterator itor = helpers.cfgs.begin(); itor != helpers.cfgs.end(); ++itor) {
@ -393,8 +429,8 @@ void unit_attack(
unit_map::iterator helper = units.find(itor->second);
assert(helper != units.end());
helper->set_facing(itor->second.get_relative_dir(b));
animator.add_animation(&*helper, "resistance", itor->second,
def->get_location(), damage, true, "", 0,
animator.add_animation(&*helper, z_resistance, itor->second,
def->get_location(), damage, true, z_empty, 0,
hit_type, &attack, secondary_attack, swing);
}
@ -424,7 +460,7 @@ void reset_helpers(const unit *attacker,const unit *defender)
game_display* disp = game_display::get_singleton();
unit_map& units = disp->get_units();
if(attacker) {
unit_ability_list leaders = attacker->get_abilities("leadership");
unit_ability_list leaders = attacker->get_abilities(z_leadership);
for (std::vector<std::pair<const config *, map_location> >::iterator itor = leaders.cfgs.begin(); itor != leaders.cfgs.end(); ++itor) {
unit_map::iterator leader = units.find(itor->second);
assert(leader != units.end());
@ -433,7 +469,7 @@ void reset_helpers(const unit *attacker,const unit *defender)
}
if(defender) {
unit_ability_list helpers = defender->get_abilities("resistance");
unit_ability_list helpers = defender->get_abilities(z_resistance);
for (std::vector<std::pair<const config *, map_location> >::iterator itor = helpers.cfgs.begin(); itor != helpers.cfgs.end(); ++itor) {
unit_map::iterator helper = units.find(itor->second);
assert(helper != units.end());
@ -456,14 +492,14 @@ void unit_recruited(const map_location& loc,const map_location& leader_loc)
if(leader == disp->get_units().end()) return;
disp->scroll_to_tiles(loc,leader_loc,game_display::ONSCREEN,true,0.0,false);
leader->set_facing(leader_loc.get_relative_dir(loc));
animator.add_animation(&*leader, "recruiting", leader_loc, loc, 0, true);
animator.add_animation(&*leader, z_recruiting, leader_loc, loc, 0, true);
} else {
disp->scroll_to_tile(loc,game_display::ONSCREEN,true,false);
}
disp->draw();
u->set_hidden(false);
animator.add_animation(&*u, "recruited", loc, leader_loc);
animator.add_animation(&*u, z_recruited, loc, leader_loc);
animator.start_animations();
animator.wait_for_end();
animator.set_all_standing();
@ -483,13 +519,13 @@ void unit_healing(unit &healed, const map_location &healed_loc,
foreach (unit *h, healers) {
h->set_facing(h->get_location().get_relative_dir(healed_loc));
animator.add_animation(h, "healing", h->get_location(),
animator.add_animation(h, z_healing, h->get_location(),
healed_loc, healing);
}
if (healing < 0) {
animator.add_animation(&healed,"poisoned",healed_loc,map_location::null_location,-healing,false,lexical_cast<std::string>(-healing), display::rgb(255,0,0));
animator.add_animation(&healed,z_poisoned,healed_loc,map_location::null_location,-healing,false,n_token::t_token(lexical_cast<std::string>(-healing)), display::rgb(255,0,0));
} else {
animator.add_animation(&healed,"healed",healed_loc,map_location::null_location,healing,false,lexical_cast<std::string>(healing), display::rgb(0,255,0));
animator.add_animation(&healed,z_healed,healed_loc,map_location::null_location,healing,false, n_token::t_token(lexical_cast<std::string>(healing)), display::rgb(0,255,0));
}
animator.start_animations();
animator.wait_for_end();
@ -516,7 +552,7 @@ void wml_animation_internal(unit_animator &animator, const vconfig &cfg, const m
// Search for a valid unit filter,
// and if we have one, look for the matching unit
vconfig filter = cfg.child("filter");
vconfig filter = cfg.child(z_filter);
if(!filter.null()) {
for (u = resources::units->begin(); u != resources::units->end(); ++u) {
if (game_events::unit_matches_filter(*u, filter))
@ -534,7 +570,7 @@ void wml_animation_internal(unit_animator &animator, const vconfig &cfg, const m
std::vector<attack_type> attacks = u->attacks();
std::vector<attack_type>::iterator itor;
filter = cfg.child("primary_attack");
filter = cfg.child(z_primary_attack);
if(!filter.null()) {
for(itor = attacks.begin(); itor != attacks.end(); ++itor){
if(itor->matches_filter(filter.get_parsed_config())) {
@ -544,7 +580,7 @@ void wml_animation_internal(unit_animator &animator, const vconfig &cfg, const m
}
}
filter = cfg.child("secondary_attack");
filter = cfg.child(z_secondary_attack);
if(!filter.null()) {
for(itor = attacks.begin(); itor != attacks.end(); ++itor){
if(itor->matches_filter(filter.get_parsed_config())) {
@ -554,13 +590,13 @@ void wml_animation_internal(unit_animator &animator, const vconfig &cfg, const m
}
}
if(cfg["hits"] == "yes" || cfg["hits"] == "hit") {
if(cfg[z_hits] == z_yes || cfg[z_hits] == z_hit) {
hits = unit_animation::HIT;
}
if(cfg["hits"] == "no" || cfg["hits"] == "miss") {
if(cfg[z_hits] == z_no || cfg[z_hits] == z_miss) {
hits = unit_animation::MISS;
}
if( cfg["hits"] == "kill" ) {
if( cfg[z_hits] == z_kill ) {
hits = unit_animation::KILL;
}
if(cfg[z_red].empty() && cfg[z_green].empty() && cfg[z_blue].empty()) {
@ -569,7 +605,7 @@ void wml_animation_internal(unit_animator &animator, const vconfig &cfg, const m
text_color = display::rgb(cfg[z_red], cfg[z_green], cfg[z_blue]);
}
resources::screen->scroll_to_tile(u->get_location(), game_display::ONSCREEN, true, false);
vconfig t_filter = cfg.child("facing");
vconfig t_filter = cfg.child(z_facing);
map_location secondary_loc = map_location::null_location;
if(!t_filter.empty()) {
terrain_filter filter(t_filter, *resources::units);
@ -581,12 +617,12 @@ void wml_animation_internal(unit_animator &animator, const vconfig &cfg, const m
secondary_loc = u->get_location().get_direction(dir);
}
}
animator.add_animation(&*u, cfg["flag"], u->get_location(),
secondary_loc, cfg["value"], cfg["with_bars"].to_bool(),
cfg["text"], text_color, hits, primary, secondary,
cfg["value_second"]);
animator.add_animation(&*u, cfg[z_flag], u->get_location(),
secondary_loc, cfg[z_value], cfg[z_with_bars].to_bool(),
cfg[z_text], text_color, hits, primary, secondary,
cfg[z_value_second]);
}
const vconfig::child_list sub_anims = cfg.get_children("animate");
const vconfig::child_list sub_anims = cfg.get_children(z_animate);
vconfig::child_list::const_iterator anim_itor;
for(anim_itor = sub_anims.begin(); anim_itor != sub_anims.end();++anim_itor) {
wml_animation_internal(animator, *anim_itor);

View file

@ -23,75 +23,121 @@
#include "unit_frame.hpp"
progressive_string::progressive_string(const std::string & data,int duration) :
data_(),
input_(data)
{
const std::vector<std::string> first_pass = utils::split(data);
const int time_chunk = std::max<int>(duration / (first_pass.size()?first_pass.size():1),1);
namespace {
//Static tokens are replacements for string literals in code
//They allow for fast comparison, copying and hashing operations.
std::vector<std::string>::const_iterator tmp;
for(tmp=first_pass.begin();tmp != first_pass.end() ; ++tmp) {
std::vector<std::string> second_pass = utils::split(*tmp,':');
if(second_pass.size() > 1) {
data_.push_back(std::pair<std::string,int>(second_pass[0],atoi(second_pass[1].c_str())));
} else {
data_.push_back(std::pair<std::string,int>(second_pass[0],time_chunk));
}
static const config::t_token z_image_diagonal("image_diagonal", false);
static const config::t_token z_image_mod("image_mod", false);
static const config::t_token z_halo_x("halo_x", false);
static const config::t_token z_halo_y("halo_y", false);
static const config::t_token z_halo_mod("halo_mod", false);
static const config::t_token z_sound("sound", false);
static const config::t_token z_text("text", false);
static const config::t_token z_blend_ratio("blend_ratio", false);
static const config::t_token z_alpha("alpha", false);
static const config::t_token z_offset("offset", false);
static const config::t_token z_submerge("submerge", false);
static const config::t_token z_x("x", false);
static const config::t_token z_y("y", false);
static const config::t_token z_directional_x("directional_x", false);
static const config::t_token z_directional_y("directional_y", false);
static const config::t_token z_layer("layer", false);
static const config::t_token z_auto_vflip("auto_vflip", false);
static const config::t_token z_auto_hflip("auto_hflip", false);
static const config::t_token z_primary("primary", false);
static const config::t_token z_text_color("text_color", false);
static const config::t_token z_duration("duration", false);
static const config::t_token z_end("end", false);
static const config::t_token z_begin("begin", false);
static const config::t_token z_blend_color("blend_color", false);
}
template <class T>
void progressive_discrete<T>::progressive_discrete_core(n_token::t_token const & data, int duration) {
const std::vector<n_token::t_token> first_pass = utils::split_token(data);
const int time_chunk = std::max<int>(duration / (first_pass.size() ? first_pass.size() : 1), 1);
std::vector<n_token::t_token>::const_iterator tmp;
for(tmp=first_pass.begin(); tmp != first_pass.end() ; ++tmp) {
std::vector<n_token::t_token> second_pass = utils::split_token(*tmp,':');
if(second_pass.size() > 1) {
data_.push_back(std::pair<n_token::t_token, int>(second_pass[0],atoi(second_pass[1].c_str())));
} else {
data_.push_back(std::pair<n_token::t_token, int>(second_pass[0],time_chunk));
}
}
int progressive_string::duration() const
{
int total =0;
std::vector<std::pair<std::string,int> >::const_iterator cur_halo;
for(cur_halo = data_.begin() ; cur_halo != data_.end() ; ++cur_halo) {
total += cur_halo->second;
}
return total;
}
static const std::string empty_string;
template <class T>
progressive_discrete<T>::progressive_discrete(progressive_discrete<T> const & a) : data_(), input_(a.input_) {
typename t_data::const_iterator i=a.data_.begin(), iend=a.data_.end();
for(;i!= iend; ++i){ data_.push_back(*i); } }
const std::string& progressive_string::get_current_element(int current_time)const
{
template <class T>
int progressive_discrete<T>::duration() const {
int total =0;
std::vector<std::pair<n_token::t_token, int> >::const_iterator cur_halo;
for(cur_halo = data_.begin() ; cur_halo != data_.end() ; ++cur_halo) {
total += cur_halo->second; }
return total;
}
template <class T>
const T& progressive_discrete<T>::get_current_element(int current_time)const {
int time = 0;
unsigned int sub_halo = 0;
if(data_.empty()) return empty_string;
if(data_.empty()) return z_empty;
while(time < current_time&& sub_halo < data_.size()) {
time += data_[sub_halo].second;
++sub_halo;
}
++sub_halo; }
if(sub_halo) sub_halo--;
return data_[sub_halo].first;
}
template <class T>
progressive_<T>::progressive_(const std::string &data, int duration) :
data_(),
input_(data)
{
bool progressive_discrete<T>::operator==(progressive_discrete const & b) const {
if (data_.size() != b.data_.size() ){ return false; }
return std::equal(data_.begin(), data_.end(), b.data_.begin());
}
template <typename T>
size_t hash_value(progressive_discrete<T> const & a) {
return boost::hash_value(a.data_); }
template <class T>
T progressive_continuous<T>::default_default_value_ = T() ;
template <class T>
void progressive_continuous<T>::progressive_continuous_core(const config::t_token &data, int duration) {
int split_flag = utils::REMOVE_EMPTY; // useless to strip spaces
const std::vector<std::string> comma_split = utils::split(data,',',split_flag);
const std::vector<config::t_token> comma_split = utils::split_token(data,',',split_flag);
const int time_chunk = std::max<int>(1, duration / std::max<int>(comma_split.size(),1));
std::vector<std::string>::const_iterator com_it = comma_split.begin();
std::vector<config::t_token>::const_iterator com_it = comma_split.begin();
for(; com_it != comma_split.end(); ++com_it) {
std::vector<std::string> colon_split = utils::split(*com_it,':',split_flag);
std::vector<config::t_token> colon_split = utils::split_token(*com_it,':',split_flag);
int time = (colon_split.size() > 1) ? atoi(colon_split[1].c_str()) : time_chunk;
std::vector<std::string> range = utils::split(colon_split[0],'~',split_flag);
std::vector<config::t_token> range = utils::split_token(colon_split[0],'~',split_flag);
T range0 = lexical_cast<T>(range[0]);
T range1 = (range.size() > 1) ? lexical_cast<T>(range[1]) : range0;
typedef std::pair<T,T> range_pair;
data_.push_back(std::pair<range_pair,int>(range_pair(range0, range1), time));
data_.push_back(std::pair<range_pair, int>(range_pair(range0, range1), time));
}
}
template <class T>
const T progressive_<T>::get_current_element(int current_time, T default_val) const
{
progressive_continuous<T>::progressive_continuous(progressive_continuous<T> const & a) : data_(), input_(a.input_) {
typename t_data::const_iterator i=a.data_.begin(), iend=a.data_.end();
for(;i!= iend; ++i){ data_.push_back(*i); }
}
template <class T>
const T progressive_continuous<T>::get_current_element(int current_time, T const & default_val) const {
int time = 0;
unsigned int sub_halo = 0;
int searched_time = current_time;
@ -101,7 +147,6 @@ const T progressive_<T>::get_current_element(int current_time, T default_val) co
while(time < searched_time&& sub_halo < data_.size()) {
time += data_[sub_halo].second;
++sub_halo;
}
if(sub_halo != 0) {
sub_halo--;
@ -117,39 +162,48 @@ const T progressive_<T>::get_current_element(int current_time, T default_val) co
}
template<class T>
int progressive_<T>::duration() const
{
int progressive_continuous<T>::duration() const {
int total = 0;
typename std::vector<std::pair<std::pair<T, T>, int> >::const_iterator cur_halo;
for(cur_halo = data_.begin() ; cur_halo != data_.end() ; ++cur_halo) {
total += cur_halo->second;
}
return total;
}
template <class T>
bool progressive_<T>::does_not_change() const
{
return data_.empty() ||
( data_.size() == 1 && data_[0].first.first == data_[0].first.second);
bool progressive_continuous<T>::does_not_change() const {
return data_.empty() || ( data_.size() == 1 && data_[0].first.first == data_[0].first.second);
}
template <class T>
bool progressive_continuous<T>::operator==(progressive_continuous const & b) const {
if (data_.size() != b.data_.size()) { return false; }
return std::equal(data_.begin(), data_.end(), b.data_.begin());
}
template <typename T>
size_t hash_value(progressive_continuous<T> const & a) {
return boost::hash_value(a.data_); }
// Force compilation of the following template instantiations
template class progressive_<int>;
template class progressive_<double>;
template class progressive_discrete<n_token::t_token>;
template class progressive_discrete<std::string>;
template class progressive_continuous<int>;
template class progressive_continuous<double>;
frame_parameters::frame_parameters() :
duration(0),
image(),
image_diagonal(),
image_mod(""),
halo(""),
image_mod(z_empty),
halo(z_empty),
halo_x(0),
halo_y(0),
halo_mod(""),
sound(""),
text(""),
halo_mod(z_empty),
sound(z_empty),
text(z_empty),
text_color(0),
blend_with(0),
blend_ratio(0.0),
@ -170,119 +224,119 @@ frame_builder::frame_builder() :
duration_(1),
image_(),
image_diagonal_(),
image_mod_(""),
halo_(""),
halo_x_(""),
halo_y_(""),
halo_mod_(""),
sound_(""),
text_(""),
image_mod_(z_empty),
halo_(z_empty),
halo_x_(z_empty),
halo_y_(z_empty),
halo_mod_(z_empty),
sound_(z_empty),
text_(z_empty),
text_color_(0),
blend_with_(0),
blend_ratio_(""),
highlight_ratio_(""),
offset_(""),
submerge_(""),
x_(""),
y_(""),
directional_x_(""),
directional_y_(""),
blend_ratio_(z_empty),
highlight_ratio_(z_empty),
offset_(z_empty),
submerge_(z_empty),
x_(z_empty),
y_(z_empty),
directional_x_(z_empty),
directional_y_(z_empty),
auto_vflip_(t_unset),
auto_hflip_(t_unset),
primary_frame_(t_unset),
drawing_layer_(str_cast(display::LAYER_UNIT_DEFAULT - display::LAYER_UNIT_FIRST))
{}
frame_builder::frame_builder(const config& cfg,const std::string& frame_string) :
frame_builder::frame_builder(const config& cfg,const n_token::t_token& frame_string) :
duration_(1),
image_(cfg[frame_string + "image"].token()),
image_diagonal_(cfg[frame_string + "image_diagonal"].token()),
image_mod_(cfg[frame_string + "image_mod"]),
halo_(cfg[frame_string + "halo"]),
halo_x_(cfg[frame_string + "halo_x"]),
halo_y_(cfg[frame_string + "halo_y"]),
halo_mod_(cfg[frame_string + "halo_mod"]),
sound_(cfg[frame_string + "sound"]),
text_(cfg[frame_string + "text"]),
image_(cfg[frame_string + z_image].token()),
image_diagonal_(cfg[frame_string + z_image_diagonal].token()),
image_mod_(cfg[frame_string + z_image_mod].token()),
halo_(cfg[frame_string + z_halo].token()),
halo_x_(cfg[frame_string + z_halo_x].token()),
halo_y_(cfg[frame_string + z_halo_y].token()),
halo_mod_(cfg[frame_string + z_halo_mod].token()),
sound_(cfg[frame_string + z_sound].token()),
text_(cfg[frame_string + z_text].token()),
text_color_(0),
blend_with_(0),
blend_ratio_(cfg[frame_string + "blend_ratio"]),
highlight_ratio_(cfg[frame_string + "alpha"]),
offset_(cfg[frame_string + "offset"]),
submerge_(cfg[frame_string + "submerge"]),
x_(cfg[frame_string + "x"]),
y_(cfg[frame_string + "y"]),
directional_x_(cfg[frame_string + "directional_x"]),
directional_y_(cfg[frame_string + "directional_y"]),
blend_ratio_(cfg[frame_string + z_blend_ratio].token()),
highlight_ratio_(cfg[frame_string + z_alpha].token()),
offset_(cfg[frame_string + z_offset].token()),
submerge_(cfg[frame_string + z_submerge].token()),
x_(cfg[frame_string + z_x].token()),
y_(cfg[frame_string + z_y].token()),
directional_x_(cfg[frame_string + z_directional_x].token()),
directional_y_(cfg[frame_string + z_directional_y].token()),
auto_vflip_(t_unset),
auto_hflip_(t_unset),
primary_frame_(t_unset),
drawing_layer_(cfg[frame_string + "layer"])
drawing_layer_(cfg[frame_string + z_layer].token())
{
if(!cfg.has_attribute(frame_string + "auto_vflip")) {
if(!cfg.has_attribute(frame_string + z_auto_vflip)) {
auto_vflip_ = t_unset;
} else if(cfg[frame_string + "auto_vflip"].to_bool()) {
} else if(cfg[frame_string + z_auto_vflip].to_bool()) {
auto_vflip_ = t_true;
} else {
auto_vflip_ = t_false;
}
if(!cfg.has_attribute(frame_string + "auto_hflip")) {
if(!cfg.has_attribute(frame_string + z_auto_hflip)) {
auto_hflip_ = t_unset;
} else if(cfg[frame_string + "auto_hflip"].to_bool()) {
} else if(cfg[frame_string + z_auto_hflip].to_bool()) {
auto_hflip_ = t_true;
} else {
auto_hflip_ = t_false;
}
if(!cfg.has_attribute(frame_string + "primary")) {
if(!cfg.has_attribute(frame_string + z_primary)) {
primary_frame_ = t_unset;
} else if(cfg[frame_string + "primary"].to_bool()) {
} else if(cfg[frame_string + z_primary].to_bool()) {
primary_frame_ = t_true;
} else {
primary_frame_ = t_false;
}
std::vector<std::string> color = utils::split(cfg[frame_string + "text_color"]);
std::vector<n_token::t_token> color = utils::split_token(cfg[frame_string + z_text_color]);
if (color.size() == 3) {
text_color_ = display::rgb(atoi(color[0].c_str()),
atoi(color[1].c_str()), atoi(color[2].c_str()));
}
if (const config::attribute_value *v = cfg.get(frame_string + "duration")) {
if (const config::attribute_value *v = cfg.get(frame_string + z_duration)) {
duration(*v);
} else {
duration(cfg[frame_string + "end"].to_int() - cfg[frame_string + "begin"].to_int());
duration(cfg[frame_string + z_end].to_int() - cfg[frame_string + z_begin].to_int());
}
color = utils::split(cfg[frame_string + "blend_color"]);
color = utils::split_token(cfg[frame_string + z_blend_color]);
if (color.size() == 3) {
blend_with_ = display::rgb(atoi(color[0].c_str()),
atoi(color[1].c_str()), atoi(color[2].c_str()));
}
}
frame_builder & frame_builder::image(const image::locator& image ,const std::string & image_mod)
frame_builder & frame_builder::image(const image::locator& image ,const n_token::t_token & image_mod)
{
image_ = image;
image_mod_ = image_mod;
return *this;
}
frame_builder & frame_builder::image_diagonal(const image::locator& image_diagonal,const std::string& image_mod)
frame_builder & frame_builder::image_diagonal(const image::locator& image_diagonal,const n_token::t_token& image_mod)
{
image_diagonal_ = image_diagonal;
image_mod_ = image_mod;
return *this;
}
frame_builder & frame_builder::sound(const std::string& sound)
frame_builder & frame_builder::sound(const n_token::t_token& sound)
{
sound_=sound;
return *this;
}
frame_builder & frame_builder::text(const std::string& text,const Uint32 text_color)
frame_builder & frame_builder::text(const n_token::t_token& text,const Uint32 text_color)
{
text_=text;
text_color_=text_color;
return *this;
}
frame_builder & frame_builder::halo(const std::string &halo, const std::string &halo_x, const std::string& halo_y,const std::string & halo_mod)
frame_builder & frame_builder::halo(const n_token::t_token &halo, const n_token::t_token &halo_x, const n_token::t_token& halo_y,const n_token::t_token & halo_mod)
{
halo_ = halo;
halo_x_ = halo_x;
@ -295,43 +349,43 @@ frame_builder & frame_builder::duration(const int duration)
duration_= duration;
return *this;
}
frame_builder & frame_builder::blend(const std::string& blend_ratio,const Uint32 blend_color)
frame_builder & frame_builder::blend(const n_token::t_token& blend_ratio,const Uint32 blend_color)
{
blend_with_=blend_color;
blend_ratio_=blend_ratio;
return *this;
}
frame_builder & frame_builder::highlight(const std::string& highlight)
frame_builder & frame_builder::highlight(const n_token::t_token& highlight)
{
highlight_ratio_=highlight;
return *this;
}
frame_builder & frame_builder::offset(const std::string& offset)
frame_builder & frame_builder::offset(const n_token::t_token& offset)
{
offset_=offset;
return *this;
}
frame_builder & frame_builder::submerge(const std::string& submerge)
frame_builder & frame_builder::submerge(const n_token::t_token& submerge)
{
submerge_=submerge;
return *this;
}
frame_builder & frame_builder::x(const std::string& x)
frame_builder & frame_builder::x(const n_token::t_token& x)
{
x_=x;
return *this;
}
frame_builder & frame_builder::y(const std::string& y)
frame_builder & frame_builder::y(const n_token::t_token& y)
{
y_=y;
return *this;
}
frame_builder & frame_builder::directional_x(const std::string& directional_x)
frame_builder & frame_builder::directional_x(const n_token::t_token& directional_x)
{
directional_x_=directional_x;
return *this;
}
frame_builder & frame_builder::directional_y(const std::string& directional_y)
frame_builder & frame_builder::directional_y(const n_token::t_token& directional_y)
{
directional_y_=directional_y;
return *this;
@ -354,7 +408,7 @@ frame_builder & frame_builder::primary_frame(const bool primary_frame)
else primary_frame_ = t_false;
return *this;
}
frame_builder & frame_builder::drawing_layer(const std::string& drawing_layer)
frame_builder & frame_builder::drawing_layer(const n_token::t_token& drawing_layer)
{
drawing_layer_=drawing_layer;
return *this;
@ -386,7 +440,71 @@ frame_parsed_parameters::frame_parsed_parameters(const frame_builder & builder,
auto_hflip_(builder.auto_hflip_),
primary_frame_(builder.primary_frame_),
drawing_layer_(builder.drawing_layer_,duration_)
{}
{
}
bool frame_parsed_parameters::operator==(frame_parsed_parameters const & b) const {
return duration_ == b.duration_
&& image_ == b.image_
&& image_diagonal_ == b.image_diagonal_
&& image_mod_ == b.image_mod_
&& halo_ == b.halo_
&& halo_x_ == b.halo_x_
&& halo_y_ == b.halo_y_
&& halo_mod_ == b. halo_mod_
&& sound_ == b.sound_
&& text_ == b.text_
&& text_color_ == b.text_color_
&& blend_with_ == b.blend_with_
&& blend_ratio_ == b.blend_ratio_
&& highlight_ratio_ == b.highlight_ratio_
&& offset_ == b.offset_
&& submerge_ == b.submerge_
&& x_ == b.x_
&& y_ == b.y_
&& directional_x_ == b.directional_y_
&& directional_y_ == b.directional_x_
&& auto_vflip_ == b.auto_vflip_
&& auto_hflip_ == b.auto_hflip_
&& primary_frame_ == b.primary_frame_
&& drawing_layer_ == b.drawing_layer_
;
}
size_t hash_value(frame_parsed_parameters const & a) {
std::size_t hash = 0;
boost::hash_combine(hash, a.duration_);
boost::hash_combine(hash, a.image_);
boost::hash_combine(hash, a.image_diagonal_);
boost::hash_combine(hash, a.image_mod_);
boost::hash_combine(hash, a.halo_);
boost::hash_combine(hash, a.halo_mod_);
boost::hash_combine(hash, a.halo_x_);
boost::hash_combine(hash, a.halo_y_);
boost::hash_combine(hash, a.sound_);
boost::hash_combine(hash, a.text_);
boost::hash_combine(hash, a.text_color_);
boost::hash_combine(hash, a.blend_with_);
boost::hash_combine(hash, a.blend_ratio_);
boost::hash_combine(hash, a.highlight_ratio_);
boost::hash_combine(hash, a.offset_);
boost::hash_combine(hash, a.submerge_);
boost::hash_combine(hash, a.x_);
boost::hash_combine(hash, a.y_);
boost::hash_combine(hash, a.directional_x_);
boost::hash_combine(hash, a.directional_y_);
boost::hash_combine(hash, a.auto_vflip_);
boost::hash_combine(hash, a.auto_hflip_);
boost::hash_combine(hash, a.primary_frame_);
boost::hash_combine(hash, a.drawing_layer_);
return hash;
}
bool frame_parsed_parameters::does_not_change() const
@ -454,18 +572,18 @@ const frame_parameters frame_parsed_parameters::parameters(int current_time) con
}
void frame_parsed_parameters::override( int duration
, const std::string& highlight
, const std::string& blend_ratio
, const n_token::t_token& highlight
, const n_token::t_token& blend_ratio
, Uint32 blend_color
, const std::string& offset
, const std::string& layer
, const std::string& modifiers)
, const n_token::t_token& offset
, const n_token::t_token& layer
, const n_token::t_token& modifiers)
{
if(!highlight.empty()) {
highlight_ratio_ = progressive_double(highlight,duration);
} else if(duration != duration_){
highlight_ratio_=progressive_double(highlight_ratio_.get_original(),duration);
highlight_ratio_ = progressive_double(highlight_ratio_.get_original(),duration);
}
if(!offset.empty()) {
offset_= progressive_double(offset,duration);
@ -484,11 +602,11 @@ void frame_parsed_parameters::override( int duration
drawing_layer_=progressive_int(drawing_layer_.get_original(),duration);
}
if(!modifiers.empty()) {
image_mod_+=modifiers;
image_mod_ = n_token::t_token( image_mod_ + modifiers );
}
if(duration != duration_) {
halo_ = progressive_string(halo_.get_original(),duration);
halo_ = progressive_token(halo_.get_original(),duration);
halo_x_ = progressive_int(halo_x_.get_original(),duration);
halo_y_ = progressive_int(halo_y_.get_original(),duration);
submerge_=progressive_double(submerge_.get_original(),duration);
@ -533,12 +651,12 @@ void unit_frame::redraw(const int frame_time,bool first_time,const map_location
if(direction != map_location::NORTH && direction != map_location::SOUTH) {
image_loc = image::locator(current_data.image_diagonal, n_token::t_token(current_data.image_mod)); //todo remove
}
if(image_loc.is_void() || image_loc.get_filename() == "") { // invalid diag image, or not diagonal
if(image_loc.is_void() || image_loc.get_filename() == z_empty) { // invalid diag image, or not diagonal
image_loc = image::locator(current_data.image,n_token::t_token(current_data.image_mod)); //rmove extra contructor
}
surface image;
if(!image_loc.is_void() && image_loc.get_filename() != "") { // invalid diag image, or not diagonal
if(!image_loc.is_void() && image_loc.get_filename() != z_empty) { // invalid diag image, or not diagonal
image=image::get_image(image_loc, image::SCALED_TO_ZOOM);
}
const int x = static_cast<int>(tmp_offset * xdst + (1.0-tmp_offset) * xsrc) + d2;
@ -636,7 +754,7 @@ std::set<map_location> unit_frame::get_overlaped_hex(const int frame_time,const
if(direction != map_location::NORTH && direction != map_location::SOUTH) {
image_loc = image::locator(current_data.image_diagonal, n_token::t_token(current_data.image_mod));
}
if(image_loc.is_void() || image_loc.get_filename() == "") { // invalid diag image, or not diagonal
if(image_loc.is_void() || image_loc.get_filename() == z_empty) { // invalid diag image, or not diagonal
image_loc = image::locator(current_data.image, n_token::t_token(current_data.image_mod));
}
@ -670,7 +788,7 @@ std::set<map_location> unit_frame::get_overlaped_hex(const int frame_time,const
#endif //_OPENMP
{
surface image;
if(!image_loc.is_void() && image_loc.get_filename() != "") { // invalid diag image, or not diagonal
if(!image_loc.is_void() && image_loc.get_filename() != z_empty) { // invalid diag image, or not diagonal
image=image::get_image(image_loc,
image::SCALED_TO_ZOOM
);
@ -737,7 +855,7 @@ const frame_parameters unit_frame::merge_parameters(int current_time,const frame
*
*/
frame_parameters result;
const frame_parameters & current_val = builder_.parameters(current_time);
const frame_parameters & current_val = static_cast<frame_parsed_parameters const &>(builder_).parameters(current_time);
result.primary_frame = engine_val.primary_frame;
if(animation_val.primary_frame != t_unset) result.primary_frame = animation_val.primary_frame;
@ -745,13 +863,13 @@ const frame_parameters unit_frame::merge_parameters(int current_time,const frame
const bool primary = result.primary_frame;
/** engine provides a default image to use for the unit when none is available */
result.image = current_val.image.is_void() || current_val.image.get_filename() == ""?animation_val.image:current_val.image;
result.image = current_val.image.is_void() || current_val.image.get_filename() == z_empty ?animation_val.image:current_val.image;
if(primary && ( result.image.is_void() || result.image.get_filename().empty())) {
result.image = engine_val.image;
}
/** engine provides a default image to use for the unit when none is available */
result.image_diagonal = current_val.image_diagonal.is_void() || current_val.image_diagonal.get_filename() == ""?animation_val.image_diagonal:current_val.image_diagonal;
result.image_diagonal = current_val.image_diagonal.is_void() || current_val.image_diagonal.get_filename() == z_empty ?animation_val.image_diagonal:current_val.image_diagonal;
if(primary && ( result.image_diagonal.is_void() || result.image_diagonal.get_filename().empty())) {
result.image_diagonal = engine_val.image_diagonal;
}
@ -759,12 +877,12 @@ const frame_parameters unit_frame::merge_parameters(int current_time,const frame
/** engine provides a string for "petrified" and "team color" modifications
note that image_mod is the complete modification and halo_mod is only the TC part
see unit.cpp, we know that and use it*/
result.image_mod = current_val.image_mod +animation_val.image_mod;
result.image_mod = current_val.image_mod + animation_val.image_mod;
if(primary) {
result.image_mod += engine_val.image_mod;
} else {
result.image_mod += engine_val.halo_mod;
}
result.image_mod += engine_val.image_mod;
} else {
result.image_mod += engine_val.halo_mod;
}
assert(engine_val.halo.empty());
result.halo = current_val.halo.empty()?animation_val.halo:current_val.halo;

View file

@ -22,40 +22,67 @@
#define UNIT_FRAME_H_INCLUDED
#include "image.hpp"
#include "utils/interned.hpp"
class config;
class progressive_string {
public:
progressive_string(const std::string& data = "",int duration = 0);
int duration() const;
const std::string & get_current_element(int time) const;
bool does_not_change() const { return data_.size() <= 1; }
std::string get_original() const { return input_; }
private:
std::vector<std::pair<std::string,int> > data_;
std::string input_;
template <class T>
class progressive_discrete {
public:
progressive_discrete(const n_token::t_token& data = z_empty, int duration = 0) : data_(), input_(data) {
progressive_discrete_core(data, duration); }
// progressive_discrete(const std::string& data = z_empty, int duration = 0): data_(), input_(data) {
// progressive_discrete_core(n_token::t_token(data), duration); }
void progressive_discrete_core(const n_token::t_token& data = z_empty, int duration = 0);
progressive_discrete(progressive_discrete const & );
int duration() const;
const T & get_current_element(int time) const;
bool does_not_change() const { return data_.size() <= 1; }
n_token::t_token const & get_original() const { return input_; }
bool operator==(progressive_discrete const &) const;
template<typename X>
friend size_t hash_value(progressive_discrete<X> const &);
private:
typedef std::vector<std::pair<n_token::t_token, int> > t_data;
t_data data_;
n_token::t_token input_;
};
template <class T>
class progressive_
{
std::vector<std::pair<std::pair<T, T>, int> > data_;
std::string input_;
class progressive_continuous {
typedef std::pair<T,T> range_pair;
typedef std::vector<std::pair<range_pair, int> > t_data;
t_data data_;
n_token::t_token input_;
static T default_default_value_;
public:
progressive_(const std::string& data = "", int duration = 0);
progressive_continuous(const n_token::t_token& data = z_empty, int duration = 0) : data_(), input_(data) {
progressive_continuous_core(data, duration); }
// progressive_continuous(const std::string& data = z_empty, int duration = 0) : data_(), input_(data) {
// progressive_continuous_core(data, duration); }
void progressive_continuous_core(const n_token::t_token& data = z_empty, int duration = 0);
progressive_continuous(progressive_continuous const &);
static void set_default_default_value(T const & dv = T()) {default_default_value_ = dv;}
int duration() const;
const T get_current_element(int time,T default_val=0) const;
const T get_current_element(int time,T const & default_val=progressive_continuous<T>::default_default_value_) const;
bool does_not_change() const;
std::string get_original() const { return input_; }
n_token::t_token const & get_original() const { return input_; }
bool operator==(progressive_continuous const &) const;
template <typename X> friend size_t hash_value(progressive_continuous<X> const &);
};
typedef progressive_<int> progressive_int;
typedef progressive_<double> progressive_double;
typedef progressive_discrete<n_token::t_token> progressive_token;
typedef progressive_discrete<std::string> progressive_string;
typedef progressive_continuous<int> progressive_int;
typedef progressive_continuous<double> progressive_double;
typedef enum tristate {t_false,t_true,t_unset} tristate;
/** All parameters from a frame at a given instant */
class frame_parameters{
class frame_parameters {
public:
frame_parameters();
@ -63,12 +90,12 @@ class frame_parameters{
image::locator image;
image::locator image_diagonal;
std::string image_mod;
std::string halo;
n_token::t_token halo;
int halo_x;
int halo_y;
std::string halo_mod;
std::string sound;
std::string text;
n_token::t_token sound;
n_token::t_token text;
Uint32 text_color;
Uint32 blend_with;
double blend_ratio;
@ -91,53 +118,53 @@ class frame_parsed_parameters;
class frame_builder {
public:
frame_builder();
frame_builder(const config& cfg,const std::string &frame_string = "");
frame_builder(const config& cfg,const n_token::t_token &frame_string = z_empty);
/** allow easy chained modifications will raised assert if used after initialization */
frame_builder & duration(const int duration);
frame_builder & image(const image::locator& image ,const std::string & image_mod="");
frame_builder & image_diagonal(const image::locator& image_diagonal,const std::string & image_mod="");
frame_builder & sound(const std::string& sound);
frame_builder & text(const std::string& text,const Uint32 text_color);
frame_builder & halo(const std::string &halo, const std::string &halo_x, const std::string& halo_y,const std::string& halo_mod);
frame_builder & blend(const std::string& blend_ratio,const Uint32 blend_color);
frame_builder & highlight(const std::string& highlight);
frame_builder & offset(const std::string& offset);
frame_builder & submerge(const std::string& submerge);
frame_builder & x(const std::string& x);
frame_builder & y(const std::string& y);
frame_builder & directional_x(const std::string& directional_x);
frame_builder & directional_y(const std::string& directional_y);
frame_builder & image(const image::locator& image ,const n_token::t_token & image_mod=z_empty);
frame_builder & image_diagonal(const image::locator& image_diagonal,const n_token::t_token & image_mod=z_empty);
frame_builder & sound(const n_token::t_token& sound);
frame_builder & text(const n_token::t_token& text,const Uint32 text_color);
frame_builder & halo(const n_token::t_token &halo, const n_token::t_token &halo_x, const n_token::t_token& halo_y,const n_token::t_token& halo_mod);
frame_builder & blend(const n_token::t_token& blend_ratio,const Uint32 blend_color);
frame_builder & highlight(const n_token::t_token& highlight);
frame_builder & offset(const n_token::t_token& offset);
frame_builder & submerge(const n_token::t_token& submerge);
frame_builder & x(const n_token::t_token& x);
frame_builder & y(const n_token::t_token& y);
frame_builder & directional_x(const n_token::t_token& directional_x);
frame_builder & directional_y(const n_token::t_token& directional_y);
frame_builder & auto_vflip(const bool auto_vflip);
frame_builder & auto_hflip(const bool auto_hflip);
frame_builder & primary_frame(const bool primary_frame);
frame_builder & drawing_layer(const std::string& drawing_layer);
frame_builder & drawing_layer(const n_token::t_token& drawing_layer);
/** getters for the different parameters */
private:
friend class frame_parsed_parameters;
int duration_;
image::locator image_;
image::locator image_diagonal_;
std::string image_mod_;
std::string halo_;
std::string halo_x_;
std::string halo_y_;
std::string halo_mod_;
std::string sound_;
std::string text_;
n_token::t_token image_mod_;
n_token::t_token halo_;
n_token::t_token halo_x_;
n_token::t_token halo_y_;
n_token::t_token halo_mod_;
n_token::t_token sound_;
n_token::t_token text_;
Uint32 text_color_;
Uint32 blend_with_;
std::string blend_ratio_;
std::string highlight_ratio_;
std::string offset_;
std::string submerge_;
std::string x_;
std::string y_;
std::string directional_x_;
std::string directional_y_;
n_token::t_token blend_ratio_;
n_token::t_token highlight_ratio_;
n_token::t_token offset_;
n_token::t_token submerge_;
n_token::t_token x_;
n_token::t_token y_;
n_token::t_token directional_x_;
n_token::t_token directional_y_;
tristate auto_vflip_;
tristate auto_hflip_;
tristate primary_frame_;
std::string drawing_layer_;
n_token::t_token drawing_layer_;
};
/**
* keep most parameters in a separate class to simplify handling of large
@ -145,32 +172,39 @@ class frame_builder {
*/
class frame_parsed_parameters {
public:
frame_parsed_parameters(const frame_builder& builder=frame_builder(),int override_duration = 0);
/** allow easy chained modifications will raised assert if used after initialization */
void override( int duration
, const std::string& highlight = ""
, const std::string& blend_ratio =""
, const n_token::t_token& highlight = z_empty
, const n_token::t_token& blend_ratio =z_empty
, Uint32 blend_color = 0
, const std::string& offset = ""
, const std::string& layer = ""
, const std::string& modifiers = "");
, const n_token::t_token& offset = z_empty
, const n_token::t_token& layer = z_empty
, const n_token::t_token& modifiers = z_empty);
/** getters for the different parameters */
const frame_parameters parameters(int current_time) const ;
int duration() const{ return duration_;};
bool does_not_change() const;
bool need_update() const;
bool operator==(frame_parsed_parameters const & a) const;
friend size_t hash_value(frame_parsed_parameters const &);
friend std::ostream & operator<<(std::ostream &out, frame_parsed_parameters const & a){
return out << a.text_; }
private:
int duration_;
image::locator image_;
image::locator image_diagonal_;
std::string image_mod_;
progressive_string halo_;
n_token::t_token image_mod_;
progressive_token halo_;
progressive_int halo_x_;
progressive_int halo_y_;
std::string halo_mod_;
std::string sound_;
std::string text_;
n_token::t_token halo_mod_;
n_token::t_token sound_;
n_token::t_token text_;
Uint32 text_color_;
Uint32 blend_with_;
progressive_double blend_ratio_;
@ -186,22 +220,30 @@ class frame_parsed_parameters {
tristate primary_frame_;
progressive_int drawing_layer_;
};
/// A token to a frame builder which are 10:1 redundant
///todo a second index to the frame_parameter_token via the builder so that the toke can be
///created without constructing the frame parameters
typedef n_interned::t_interned_token<frame_parsed_parameters> t_frame_parameter_token;
/** Describe a unit's animation sequence. */
class unit_frame {
public:
// Constructors
unit_frame(const frame_builder builder=frame_builder()):builder_(builder){};
void redraw(const int frame_time,bool first_time,const map_location & src,const map_location & dst,int*halo_id,const frame_parameters & animation_val,const frame_parameters & engine_val)const;
const frame_parameters merge_parameters(int current_time,const frame_parameters & animation_val,const frame_parameters & engine_val=frame_parameters()) const;
const frame_parameters parameters(int current_time) const {return builder_.parameters(current_time);};
int duration() const { return builder_.duration();};
bool does_not_change() const{ return builder_.does_not_change();};
bool need_update() const{ return builder_.need_update();};
std::set<map_location> get_overlaped_hex(const int frame_time,const map_location & src,const map_location & dst,const frame_parameters & animation_val,const frame_parameters & engine_val) const;
private:
frame_parsed_parameters builder_;
public:
// Constructors
unit_frame(const frame_builder builder=frame_builder()) : builder_(frame_parsed_parameters(builder)){ }
void redraw(const int frame_time,bool first_time,const map_location & src,const map_location & dst,int*halo_id,const frame_parameters & animation_val,const frame_parameters & engine_val)const;
const frame_parameters merge_parameters(int current_time,const frame_parameters & animation_val,const frame_parameters & engine_val=frame_parameters()) const;
const frame_parameters parameters(int current_time) const {
return static_cast<frame_parsed_parameters const &>(builder_).parameters(current_time); }
int duration() const { return static_cast<frame_parsed_parameters const &>(builder_).duration();};
bool does_not_change() const{ return static_cast<frame_parsed_parameters const &>(builder_).does_not_change();};
bool need_update() const{ return static_cast<frame_parsed_parameters const &>(builder_).need_update();};
std::set<map_location> get_overlaped_hex(const int frame_time,const map_location & src,const map_location & dst,const frame_parameters & animation_val,const frame_parameters & engine_val) const;
private:
t_frame_parameter_token builder_;
};
#endif

View file

@ -54,13 +54,13 @@ template <typename T, typename T_hasher = boost::hash<T> > class t_interned_toke
*/
template <typename T, typename T_hasher >
class t_interned_token {
///Private default constructor. t_interned is always initialized to a T
t_interned_token(){};
public:
inline ~t_interned_token();
///default constructor.
t_interned_token();
///Create token
///@param[in] is_ref_counted determines if all tokens of this value will be ref counted.
///Static tokens should not be ref counted.
@ -74,8 +74,15 @@ public:
inline bool valid() const;
inline bool empty() const {return !valid();}
///Cast to the constant member
operator T const &() const { return iter_->first; }
///Access to the constant member
T const & operator*() const { return iter_->first; }
///Access constant members of T
T const * operator->() const { return &iter_->first; }
///Fast equality operators
friend inline bool operator==(t_interned_token const &a, t_interned_token const &b) { return (a.iter_==b.iter_); }
///Fast equality operators
@ -134,6 +141,9 @@ private:
///Do not inline.
static t_stash & the_stash();
///Initialize first default constructed value. The default value is only constructed once.
typename t_stash::value_type * first_default_constructed();
///Increment the reference count
inline void inc_ref();
///Decrement the reference count
@ -155,6 +165,23 @@ typename t_interned_token<T, T_hasher>::t_stash & t_interned_token<T, T_hasher>:
return *the_stash_;
}
template <typename T, typename T_hasher >
typename t_interned_token<T, T_hasher>::t_stash::value_type * t_interned_token<T, T_hasher>::first_default_constructed() {
t_stash & the_stash_ = the_stash();
t_interned default_value_(0);
T a = T();
std::pair<typename t_stash::iterator, bool> maybe_inserted = the_stash_.insert(std::make_pair(a, default_value_));
return &*(maybe_inserted.first);
}
template <typename T, typename T_hasher >
t_interned_token<T, T_hasher>::t_interned_token() : is_ref_counted_(false) {
static typename t_stash::value_type * default_iter = first_default_constructed();
iter_ = default_iter;
}
template <typename T, typename T_hasher >
t_interned_token<T, T_hasher>::t_interned_token(T const & a , bool is_ref_counted) : is_ref_counted_(is_ref_counted){