diff --git a/src/units/animation.cpp b/src/units/animation.cpp index f4284e5eabfd..ce3b21224a43 100644 --- a/src/units/animation.cpp +++ b/src/units/animation.cpp @@ -1084,10 +1084,10 @@ void unit_animation::redraw(frame_parameters& value, halo::manager& halo_man) invalidated_ = false; overlaped_hex_.clear(); - value.primary_frame = t_true; + value.primary_frame = true; unit_anim_.redraw(value,src_,dst_, halo_man); - value.primary_frame = t_false; + value.primary_frame = false; for(auto& anim : sub_anims_) { anim.second.redraw(value, src_, dst_, halo_man); } @@ -1111,9 +1111,9 @@ bool unit_animation::invalidate(frame_parameters& value) if(overlaped_hex_.empty()) { if(complete_redraw) { - value.primary_frame = t_true; + value.primary_frame = true; overlaped_hex_ = unit_anim_.get_overlaped_hex(value, src_, dst_); - value.primary_frame = t_false; + value.primary_frame = false; for(auto& anim : sub_anims_) { std::set tmp = anim.second.get_overlaped_hex(value, src_, dst_); diff --git a/src/units/drawer.cpp b/src/units/drawer.cpp index 44ff9167ba5b..6d08224ea3d4 100644 --- a/src/units/drawer.cpp +++ b/src/units/drawer.cpp @@ -147,7 +147,7 @@ void unit_drawer::redraw_unit (const unit & u) const if(u.incapacitated()) params.image_mod +="~GS()"; - params.primary_frame = t_true; + params.primary_frame = true; const frame_parameters adjusted_params = ac.anim_->get_current_params(params); diff --git a/src/units/frame.cpp b/src/units/frame.cpp index 21ab0c3fe318..bd30f046f4d8 100644 --- a/src/units/frame.cpp +++ b/src/units/frame.cpp @@ -12,108 +12,190 @@ See the COPYING file for more details. */ -/** @file */ +#include "units/frame.hpp" +#include "color.hpp" #include "game_display.hpp" #include "log.hpp" -#include "color.hpp" #include "sound.hpp" -#include "units/frame.hpp" static lg::log_domain log_engine("engine"); #define ERR_NG LOG_STREAM(err, log_engine) -progressive_string::progressive_string(const std::string & data,int duration) : - data_(), - input_(data) -{ - const std::vector first_pass = utils::square_parenthetical_split(data); - int time_chunk = std::max(duration, 1); - std::vector::const_iterator tmp; - - if (duration > 1 && first_pass.size() > 0) { - // If duration specified, divide evenly the time for items with unspecified times - int total_specified_time = 0; - for(tmp=first_pass.begin(); tmp != first_pass.end(); ++tmp) { - std::vector second_pass = utils::split(*tmp,':'); - if(second_pass.size() > 1) { - try { - total_specified_time += std::stoi(second_pass[1]); - } catch(std::invalid_argument) { - ERR_NG << "Invalid time in unit animation: " << second_pass[1] << "\n"; - } - } - } - time_chunk = std::max((duration - total_specified_time) / first_pass.size(), 1); +template +progressive_base::progressive_base(const std::string& data, int duration) + : data_() + , input_(data) +{ + int split_flag = utils::REMOVE_EMPTY; // useless to strip spaces + const std::vector comma_split = utils::split(data,',',split_flag); + const int time_chunk = std::max(1, duration / std::max(comma_split.size(),1)); + + for(const auto& entry : comma_split) { + std::vector colon_split = utils::split(entry, ':', split_flag); + int time = 0; + + try { + time = (colon_split.size() > 1) ? std::stoi(colon_split[1]) : time_chunk; + } catch(std::invalid_argument) { + ERR_NG << "Invalid time in unit animation: " << colon_split[1] << "\n"; } - for(tmp=first_pass.begin(); tmp != first_pass.end(); ++tmp) { - std::vector second_pass = utils::split(*tmp,':'); + try { + std::vector range = utils::split(colon_split[0],'~',split_flag); + T range0 = lexical_cast(range[0]); + T range1 = (range.size() > 1) ? lexical_cast(range[1]) : range0; + + data_.push_back({{range0, range1}, time}); + } catch(bad_lexical_cast) {} + } +} + +template +const T progressive_base::get_current_element(int current_time, T default_val) const +{ + if(data_.empty()) { + return default_val; + } + + int time = 0; + unsigned int sub_halo = 0; + int searched_time = current_time; + + if(searched_time < 0) searched_time = 0; + if(searched_time > duration()) searched_time = duration(); + + while(time < searched_time && sub_halo < data_.size()) { + time += data_[sub_halo].second; + ++sub_halo; + } + + if(sub_halo != 0) { + sub_halo--; + time -= data_[sub_halo].second; + } + + const T first = data_[sub_halo].first.first; + const T second = data_[sub_halo].first.second; + + return T(( + static_cast(searched_time - time) / + static_cast(data_[sub_halo].second) + ) * (second - first) + first); +} + +template +int progressive_base::duration() const +{ + int total = 0; + for(const auto& entry : data_) { + total += entry.second; + } + + return total; +} + +template +bool progressive_base::does_not_change() const +{ + return data_.empty() || (data_.size() == 1 && data_[0].first.first == data_[0].first.second); +} + +progressive_string::progressive_string(const std::string& data,int duration) + : data_() + , input_(data) +{ + const std::vector first_pass = utils::square_parenthetical_split(data); + int time_chunk = std::max(duration, 1); + + if(duration > 1 && !first_pass.empty()) { + // If duration specified, divide evenly the time for items with unspecified times + int total_specified_time = 0; + + for(const std::string& fp_string : first_pass) { + std::vector second_pass = utils::split(fp_string, ':'); if(second_pass.size() > 1) { try { - data_.push_back(std::pair(std::move(second_pass[0]),std::stoi(second_pass[1]))); + total_specified_time += std::stoi(second_pass[1]); } catch(std::invalid_argument) { ERR_NG << "Invalid time in unit animation: " << second_pass[1] << "\n"; } - } else { - data_.push_back(std::pair(std::move(second_pass[0]),time_chunk)); } } + + time_chunk = std::max((duration - total_specified_time) / first_pass.size(), 1); + } + + for(const std::string& fp_string : first_pass) { + std::vector second_pass = utils::split(fp_string, ':'); + if(second_pass.size() > 1) { + try { + data_.push_back({std::move(second_pass[0]), std::stoi(second_pass[1])}); + } catch(std::invalid_argument) { + ERR_NG << "Invalid time in unit animation: " << second_pass[1] << "\n"; + } + } else { + data_.push_back({std::move(second_pass[0]) ,time_chunk}); + } + } } + int progressive_string::duration() const { - int total =0; - std::vector >::const_iterator cur_halo; - for(cur_halo = data_.begin() ; cur_halo != data_.end() ; ++cur_halo) { - total += cur_halo->second; + int total = 0; + for(const auto& entry : data_) { + total += entry.second; } + return total; } -progressive_image::progressive_image(const std::string & data,int duration) : - data_(), - input_(data) -{ - const std::vector first_pass = utils::square_parenthetical_split(data); - int time_chunk = std::max(duration, 1); - std::vector::const_iterator tmp; - - if (duration > 1 && first_pass.size() > 0) { - // If duration specified, divide evenly the time for images with unspecified times - int total_specified_time = 0; - for(tmp=first_pass.begin(); tmp != first_pass.end(); ++tmp) { - std::vector second_pass = utils::split(*tmp,':'); - if(second_pass.size() > 1) { - try { - total_specified_time += std::stoi(second_pass[1]); - } catch(std::invalid_argument) { - ERR_NG << "Invalid time in unit animation: " << second_pass[1] << "\n"; - } - } - } - time_chunk = std::max((duration - total_specified_time) / first_pass.size(), 1); - } +progressive_image::progressive_image(const std::string& data,int duration) + : data_() + , input_(data) +{ + const std::vector first_pass = utils::square_parenthetical_split(data); + int time_chunk = std::max(duration, 1); - for(tmp=first_pass.begin(); tmp != first_pass.end(); ++tmp) { - std::vector second_pass = utils::split(*tmp,':'); + if(duration > 1 && !first_pass.empty() ) { + // If duration specified, divide evenly the time for images with unspecified times + int total_specified_time = 0; + + for(const std::string& fp_string : first_pass) { + std::vector second_pass = utils::split(fp_string, ':'); if(second_pass.size() > 1) { try { - data_.push_back(std::pair(std::move(second_pass[0]),std::stoi(second_pass[1]))); + total_specified_time += std::stoi(second_pass[1]); } catch(std::invalid_argument) { ERR_NG << "Invalid time in unit animation: " << second_pass[1] << "\n"; } - } else { - data_.push_back(std::pair(std::move(second_pass[0]),time_chunk)); } } + + time_chunk = std::max((duration - total_specified_time) / first_pass.size(), 1); + } + + for(const std::string& fp_string : first_pass) { + std::vector second_pass = utils::split(fp_string, ':'); + if(second_pass.size() > 1) { + try { + data_.push_back({std::move(second_pass[0]), std::stoi(second_pass[1])}); + } catch(std::invalid_argument) { + ERR_NG << "Invalid time in unit animation: " << second_pass[1] << "\n"; + } + } else { + data_.push_back({std::move(second_pass[0]), time_chunk}); + } + } } + int progressive_image::duration() const { - int total =0; - std::vector >::const_iterator cur_halo; - for(cur_halo = data_.begin() ; cur_halo != data_.end() ; ++cur_halo) { - total += cur_halo->second; + int total = 0; + for(const auto& entry : data_) { + total += entry.second; } + return total; } @@ -121,15 +203,22 @@ const image::locator empty_image; const image::locator& progressive_image::get_current_element(int current_time) const { + if(data_.empty()) { + return empty_image; + } + int time = 0; unsigned int sub_image = 0; - if(data_.empty()) return empty_image; - while(time < current_time&& sub_image < data_.size()) { + + while(time < current_time && sub_image < data_.size()) { time += data_[sub_image].second; ++sub_image; + } + if(sub_image) { + sub_image--; } - if(sub_image) sub_image--; + return data_[sub_image].first; } @@ -137,216 +226,135 @@ static const std::string empty_string; const std::string& progressive_string::get_current_element(int current_time) const { - int time = 0; - unsigned int sub_halo = 0; - if(data_.empty()) return empty_string; - while(time < current_time&& sub_halo < data_.size()) { - time += data_[sub_halo].second; - ++sub_halo; - + if(data_.empty()) { + return empty_string; } - if(sub_halo) sub_halo--; - return data_[sub_halo].first; -} - -template -progressive_::progressive_(const std::string &data, int duration) : - data_(), - input_(data) -{ - int split_flag = utils::REMOVE_EMPTY; // useless to strip spaces - const std::vector comma_split = utils::split(data,',',split_flag); - const int time_chunk = std::max(1, duration / std::max(comma_split.size(),1)); - std::vector::const_iterator com_it = comma_split.begin(); - for(; com_it != comma_split.end(); ++com_it) { - std::vector colon_split = utils::split(*com_it,':',split_flag); - int time = 0; - - try { - time = (colon_split.size() > 1) ? std::stoi(colon_split[1]) : time_chunk; - } catch(std::invalid_argument) { - ERR_NG << "Invalid time in unit animation: " << colon_split[1] << "\n"; - } - - try { - std::vector range = utils::split(colon_split[0],'~',split_flag); - T range0 = lexical_cast(range[0]); - T range1 = (range.size() > 1) ? lexical_cast(range[1]) : range0; - typedef std::pair range_pair; - data_.push_back(std::pair(range_pair(range0, range1), time)); - } catch(bad_lexical_cast) {} - } -} - -template -const T progressive_::get_current_element(int current_time, T default_val) const -{ int time = 0; unsigned int sub_halo = 0; - int searched_time = current_time; - if(searched_time < 0) searched_time = 0; - if(searched_time > duration()) searched_time = duration(); - if(data_.empty()) return default_val; - while(time < searched_time&& sub_halo < data_.size()) { + + while(time < current_time && sub_halo < data_.size()) { time += data_[sub_halo].second; ++sub_halo; - } - if(sub_halo != 0) { - sub_halo--; - time -= data_[sub_halo].second; - } - - const T first = data_[sub_halo].first.first; - const T second = data_[sub_halo].first.second; - return T((static_cast(searched_time - time) / - static_cast(data_[sub_halo].second)) * - (second - first) + first); -} - -template -int progressive_::duration() const -{ - int total = 0; - typename std::vector, int> >::const_iterator cur_halo; - for(cur_halo = data_.begin() ; cur_halo != data_.end() ; ++cur_halo) { - total += cur_halo->second; + if(sub_halo) { + sub_halo--; } - return total; -} - -template -bool progressive_::does_not_change() const -{ -return data_.empty() || - ( data_.size() == 1 && data_[0].first.first == data_[0].first.second); + return data_[sub_halo].first; } // Force compilation of the following template instantiations -template class progressive_; -template class progressive_; - -bool tristate_to_bool(tristate tri, bool def) -{ - switch(tri) - { - case(t_false): - return false; - case(t_true): - return true; - case(t_unset): - return def; - default: - throw "found unexpected tristate"; - } -} - -frame_parameters::frame_parameters() : - duration(0), - image(), - image_diagonal(), - image_mod(""), - halo(""), - halo_x(0), - halo_y(0), - halo_mod(""), - sound(""), - text(""), - text_color(), - blend_with(), - blend_ratio(0.0), - highlight_ratio(1.0), - offset(0), - submerge(0.0), - x(0), - y(0), - directional_x(0), - directional_y(0), - auto_vflip(t_unset), - auto_hflip(t_unset), - primary_frame(t_unset), - drawing_layer(display::LAYER_UNIT_DEFAULT - display::LAYER_UNIT_FIRST) +template class progressive_base; +template class progressive_base; + +frame_parameters::frame_parameters() + : duration(0) + , image() + , image_diagonal() + , image_mod("") + , halo("") + , halo_x(0) + , halo_y(0) + , halo_mod("") + , sound("") + , text("") + , text_color() + , blend_with() + , blend_ratio(0.0) + , highlight_ratio(1.0) + , offset(0) + , submerge(0.0) + , x(0) + , y(0) + , directional_x(0) + , directional_y(0) + , auto_vflip(boost::logic::indeterminate) + , auto_hflip(boost::logic::indeterminate) + , primary_frame(boost::logic::indeterminate) + , drawing_layer(display::LAYER_UNIT_DEFAULT - display::LAYER_UNIT_FIRST) {} -frame_builder::frame_builder() : - duration_(1), - image_(), - image_diagonal_(), - image_mod_(""), - halo_(""), - halo_x_(""), - halo_y_(""), - halo_mod_(""), - sound_(""), - text_(""), - text_color_(), - blend_with_(), - blend_ratio_(""), - highlight_ratio_(""), - offset_(""), - submerge_(""), - x_(""), - y_(""), - directional_x_(""), - directional_y_(""), - auto_vflip_(t_unset), - auto_hflip_(t_unset), - primary_frame_(t_unset), - drawing_layer_(std::to_string(display::LAYER_UNIT_DEFAULT - display::LAYER_UNIT_FIRST)) +frame_builder::frame_builder() + : duration_(1) + , image_() + , image_diagonal_() + , image_mod_("") + , halo_("") + , halo_x_("") + , halo_y_("") + , halo_mod_("") + , sound_("") + , text_("") + , text_color_() + , blend_with_() + , blend_ratio_("") + , highlight_ratio_("") + , offset_("") + , submerge_("") + , x_("") + , y_("") + , directional_x_("") + , directional_y_("") + , auto_vflip_(boost::logic::indeterminate) + , auto_hflip_(boost::logic::indeterminate) + , primary_frame_(boost::logic::indeterminate) + , drawing_layer_(std::to_string(display::LAYER_UNIT_DEFAULT - display::LAYER_UNIT_FIRST)) {} -frame_builder::frame_builder(const config& cfg,const std::string& frame_string) : - duration_(1), - image_(cfg[frame_string + "image"]), - image_diagonal_(cfg[frame_string + "image_diagonal"]), - 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"]), - text_color_(), - blend_with_(), - 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"]), - auto_vflip_(t_unset), - auto_hflip_(t_unset), - primary_frame_(t_unset), - drawing_layer_(cfg[frame_string + "layer"]) +frame_builder::frame_builder(const config& cfg,const std::string& frame_string) + : duration_(1) + , image_(cfg[frame_string + "image"]) + , image_diagonal_(cfg[frame_string + "image_diagonal"]) + , 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"]) + , text_color_() + , blend_with_() + , 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"]) + , auto_vflip_(boost::logic::indeterminate) + , auto_hflip_(boost::logic::indeterminate) + , primary_frame_(boost::logic::indeterminate) + , drawing_layer_(cfg[frame_string + "layer"]) { if(!cfg.has_attribute(frame_string + "auto_vflip")) { - auto_vflip_ = t_unset; + auto_vflip_ = boost::logic::indeterminate; } else if(cfg[frame_string + "auto_vflip"].to_bool()) { - auto_vflip_ = t_true; + auto_vflip_ = true; } else { - auto_vflip_ = t_false; + auto_vflip_ = false; } + if(!cfg.has_attribute(frame_string + "auto_hflip")) { - auto_hflip_ = t_unset; + auto_hflip_ = boost::logic::indeterminate; } else if(cfg[frame_string + "auto_hflip"].to_bool()) { - auto_hflip_ = t_true; + auto_hflip_ = true; } else { - auto_hflip_ = t_false; + auto_hflip_ = false; } + if(!cfg.has_attribute(frame_string + "primary")) { - primary_frame_ = t_unset; + primary_frame_ = boost::logic::indeterminate; } else if(cfg[frame_string + "primary"].to_bool()) { - primary_frame_ = t_true; + primary_frame_ = true; } else { - primary_frame_ = t_false; + primary_frame_ = false; } + std::vector color = utils::split(cfg[frame_string + "text_color"]); - if (color.size() == 3) { + if(color.size() == 3) { try { text_color_ = color_t(std::stoi(color[0]), std::stoi(color[1]), std::stoi(color[2])); } catch(std::invalid_argument) { @@ -354,21 +362,22 @@ frame_builder::frame_builder(const config& cfg,const std::string& frame_string) } } - if (const config::attribute_value *v = cfg.get(frame_string + "duration")) { + if(const config::attribute_value* v = cfg.get(frame_string + "duration")) { duration(*v); - } else if (!cfg.get(frame_string + "end")) { - int halo_duration = (progressive_string(halo_,1)).duration(); - int image_duration = (progressive_image(image_,1)).duration(); - int image_diagonal_duration = (progressive_image(image_diagonal_,1)).duration(); - duration(std::max(std::max(image_duration,image_diagonal_duration),halo_duration)); + } else if(!cfg.get(frame_string + "end")) { + int halo_duration = (progressive_string(halo_, 1)).duration(); + int image_duration = (progressive_image(image_, 1)).duration(); + int image_diagonal_duration = (progressive_image(image_diagonal_, 1)).duration(); + duration(std::max(std::max(image_duration, image_diagonal_duration), halo_duration)); } else { duration(cfg[frame_string + "end"].to_int() - cfg[frame_string + "begin"].to_int()); } - duration_ = std::max(duration_,1); + + duration_ = std::max(duration_, 1); color = utils::split(cfg[frame_string + "blend_color"]); - if (color.size() == 3) { + if(color.size() == 3) { try { blend_with_ = color_t(std::stoi(color[0]), std::stoi(color[1]), std::stoi(color[2])); } catch(std::invalid_argument) { @@ -377,30 +386,34 @@ frame_builder::frame_builder(const config& cfg,const std::string& frame_string) } } -frame_builder & frame_builder::image(const std::string& image ,const std::string & image_mod) +frame_builder& frame_builder::image(const std::string& image ,const std::string& image_mod) { image_ = image; image_mod_ = image_mod; return *this; } -frame_builder & frame_builder::image_diagonal(const std::string& image_diagonal,const std::string& image_mod) + +frame_builder& frame_builder::image_diagonal(const std::string& image_diagonal,const std::string& 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 std::string& sound) { - sound_=sound; + sound_ = sound; return *this; } -frame_builder & frame_builder::text(const std::string& text,const color_t text_color) + +frame_builder& frame_builder::text(const std::string& text,const color_t text_color) { - text_=text; - text_color_=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 std::string& halo, const std::string& halo_x, const std::string& halo_y,const std::string& halo_mod) { halo_ = halo; halo_x_ = halo_x; @@ -408,107 +421,117 @@ frame_builder & frame_builder::halo(const std::string &halo, const std::string & halo_mod_= halo_mod; return *this; } -frame_builder & frame_builder::duration(const int duration) + +frame_builder& frame_builder::duration(const int duration) { - duration_= duration; + duration_ = duration; return *this; } -frame_builder & frame_builder::blend(const std::string& blend_ratio,const color_t blend_color) + +frame_builder& frame_builder::blend(const std::string& blend_ratio,const color_t blend_color) { - blend_with_=blend_color; - blend_ratio_=blend_ratio; + 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 std::string& highlight) { - highlight_ratio_=highlight; + highlight_ratio_ = highlight; return *this; } -frame_builder & frame_builder::offset(const std::string& offset) + +frame_builder& frame_builder::offset(const std::string& offset) { - offset_=offset; + offset_ = offset; return *this; } -frame_builder & frame_builder::submerge(const std::string& submerge) + +frame_builder& frame_builder::submerge(const std::string& submerge) { - submerge_=submerge; + submerge_ = submerge; return *this; } -frame_builder & frame_builder::x(const std::string& x) + +frame_builder& frame_builder::x(const std::string& x) { - x_=x; + x_ = x; return *this; } -frame_builder & frame_builder::y(const std::string& y) + +frame_builder& frame_builder::y(const std::string& y) { - y_=y; + y_ = y; return *this; } -frame_builder & frame_builder::directional_x(const std::string& directional_x) + +frame_builder& frame_builder::directional_x(const std::string& directional_x) { - directional_x_=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 std::string& directional_y) { - directional_y_=directional_y; + directional_y_ = directional_y; return *this; } -frame_builder & frame_builder::auto_vflip(const bool auto_vflip) + +frame_builder& frame_builder::auto_vflip(const bool auto_vflip) { - if(auto_vflip) auto_vflip_ = t_true; - else auto_vflip_ = t_false; + auto_vflip_ = auto_vflip ? true : false; return *this; } -frame_builder & frame_builder::auto_hflip(const bool auto_hflip) + +frame_builder& frame_builder::auto_hflip(const bool auto_hflip) { - if(auto_hflip) auto_hflip_ = t_true; - else auto_hflip_ = t_false; + auto_hflip_ = auto_hflip ? true : false; return *this; } -frame_builder & frame_builder::primary_frame(const bool primary_frame) + +frame_builder& frame_builder::primary_frame(const bool primary_frame) { - if(primary_frame) primary_frame_ = t_true; - else primary_frame_ = t_false; + primary_frame_ = primary_frame ? true : false; return *this; } -frame_builder & frame_builder::drawing_layer(const std::string& drawing_layer) + +frame_builder& frame_builder::drawing_layer(const std::string& drawing_layer) { drawing_layer_=drawing_layer; return *this; } -frame_parsed_parameters::frame_parsed_parameters(const frame_builder & builder, int duration) : - duration_(duration ? duration :builder.duration_), - image_(builder.image_,duration_), - image_diagonal_(builder.image_diagonal_,duration_), - image_mod_(builder.image_mod_), - halo_(builder.halo_,duration_), - halo_x_(builder.halo_x_,duration_), - halo_y_(builder.halo_y_,duration_), - halo_mod_(builder.halo_mod_), - sound_(builder.sound_), - text_(builder.text_), - text_color_(builder.text_color_), - blend_with_(builder.blend_with_), - blend_ratio_(builder.blend_ratio_,duration_), - highlight_ratio_(builder.highlight_ratio_,duration_), - offset_(builder.offset_,duration_), - submerge_(builder.submerge_,duration_), - x_(builder.x_,duration_), - y_(builder.y_,duration_), - directional_x_(builder.directional_x_,duration_), - directional_y_(builder.directional_y_,duration_), - auto_vflip_(builder.auto_vflip_), - auto_hflip_(builder.auto_hflip_), - primary_frame_(builder.primary_frame_), - drawing_layer_(builder.drawing_layer_,duration_) +frame_parsed_parameters::frame_parsed_parameters(const frame_builder& builder, int duration) + : duration_(duration ? duration : builder.duration_) + , image_(builder.image_,duration_) + , image_diagonal_(builder.image_diagonal_,duration_) + , image_mod_(builder.image_mod_) + , halo_(builder.halo_,duration_) + , halo_x_(builder.halo_x_,duration_) + , halo_y_(builder.halo_y_,duration_) + , halo_mod_(builder.halo_mod_) + , sound_(builder.sound_) + , text_(builder.text_) + , text_color_(builder.text_color_) + , blend_with_(builder.blend_with_) + , blend_ratio_(builder.blend_ratio_,duration_) + , highlight_ratio_(builder.highlight_ratio_,duration_) + , offset_(builder.offset_,duration_) + , submerge_(builder.submerge_,duration_) + , x_(builder.x_,duration_) + , y_(builder.y_,duration_) + , directional_x_(builder.directional_x_,duration_) + , directional_y_(builder.directional_y_,duration_) + , auto_vflip_(builder.auto_vflip_) + , auto_hflip_(builder.auto_hflip_) + , primary_frame_(builder.primary_frame_) + , drawing_layer_(builder.drawing_layer_,duration_) {} - bool frame_parsed_parameters::does_not_change() const { - return image_.does_not_change() && + return + image_.does_not_change() && image_diagonal_.does_not_change() && halo_.does_not_change() && halo_x_.does_not_change() && @@ -523,25 +546,10 @@ bool frame_parsed_parameters::does_not_change() const directional_y_.does_not_change() && drawing_layer_.does_not_change(); } + bool frame_parsed_parameters::need_update() const { - if(!image_.does_not_change() || - !image_diagonal_.does_not_change() || - !halo_.does_not_change() || - !halo_x_.does_not_change() || - !halo_y_.does_not_change() || - !blend_ratio_.does_not_change() || - !highlight_ratio_.does_not_change() || - !offset_.does_not_change() || - !submerge_.does_not_change() || - !x_.does_not_change() || - !y_.does_not_change() || - !directional_x_.does_not_change() || - !directional_y_.does_not_change() || - !drawing_layer_.does_not_change() ) { - return true; - } - return false; + return !this->does_not_change(); } const frame_parameters frame_parsed_parameters::parameters(int current_time) const @@ -574,145 +582,246 @@ const frame_parameters frame_parsed_parameters::parameters(int current_time) con return result; } -void frame_parsed_parameters::override( int duration - , const std::string& highlight - , const std::string& blend_ratio - , color_t blend_color - , const std::string& offset - , const std::string& layer - , const std::string& modifiers) +void frame_parsed_parameters::override(int duration, + const std::string& highlight, + const std::string& blend_ratio, + color_t blend_color, + const std::string& offset, + const std::string& layer, + const std::string& 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); - } else if(duration != duration_){ - offset_=progressive_double(offset_.get_original(),duration); + offset_ = progressive_double(offset,duration); + } else if(duration != duration_){ + offset_ = progressive_double(offset_.get_original(),duration); } + if(!blend_ratio.empty()) { blend_ratio_ = progressive_double(blend_ratio,duration); blend_with_ = blend_color; - } else if(duration != duration_){ - blend_ratio_=progressive_double(blend_ratio_.get_original(),duration); + } else if(duration != duration_){ + blend_ratio_ = progressive_double(blend_ratio_.get_original(),duration); } + if(!layer.empty()) { drawing_layer_ = progressive_int(layer,duration); - } else if(duration != duration_){ - drawing_layer_=progressive_int(drawing_layer_.get_original(),duration); + } else if(duration != duration_){ + drawing_layer_ = progressive_int(drawing_layer_.get_original(),duration); } + if(!modifiers.empty()) { - image_mod_+=modifiers; + image_mod_ += modifiers; } if(duration != duration_) { - image_ = progressive_image(image_.get_original(),duration); - image_diagonal_ = progressive_image(image_diagonal_.get_original(),duration); - halo_ = progressive_string(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); - x_=progressive_int(x_.get_original(),duration); - y_=progressive_int(y_.get_original(),duration); - directional_x_=progressive_int(directional_x_.get_original(),duration); - directional_y_=progressive_int(directional_y_.get_original(),duration); + image_ = progressive_image(image_.get_original(), duration); + image_diagonal_ = progressive_image(image_diagonal_.get_original(), duration); + halo_ = progressive_string(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); + x_ = progressive_int(x_.get_original(), duration); + y_ = progressive_int(y_.get_original(), duration); + directional_x_ = progressive_int(directional_x_.get_original(), duration); + directional_y_ = progressive_int(directional_y_.get_original(), duration); duration_ = duration; } } -std::vector frame_parsed_parameters::debug_strings() const { + +std::vector frame_parsed_parameters::debug_strings() const +{ std::vector v; - if (duration_>0) v.push_back("duration="+utils::half_signed_value(duration_)); - if (!image_.get_original().empty()) v.push_back("image="+image_.get_original()); - if (!image_diagonal_.get_original().empty()) v.push_back("image_diagonal="+image_diagonal_.get_original()); - if (!image_mod_.empty()) v.push_back("image_mod="+image_mod_); - if (!halo_.get_original().empty()) v.push_back("halo="+halo_.get_original()); - if (!halo_x_.get_original().empty()) v.push_back("halo_x="+halo_x_.get_original()); - if (!halo_y_.get_original().empty()) v.push_back("halo_y="+halo_y_.get_original()); - if (!halo_mod_.empty()) v.push_back("halo_mod="+halo_mod_); - if (!sound_.empty()) v.push_back("sound="+sound_); - if (!text_.empty()) { - v.push_back("text="+text_); + + if(duration_ > 0) { + v.push_back("duration=" + utils::half_signed_value(duration_)); + } + + if(!image_.get_original().empty()) { + v.push_back("image=" + image_.get_original()); + } + + if(!image_diagonal_.get_original().empty()) { + v.push_back("image_diagonal=" + image_diagonal_.get_original()); + } + + if(!image_mod_.empty()) { + v.push_back("image_mod=" + image_mod_); + } + + if(!halo_.get_original().empty()) { + v.push_back("halo=" + halo_.get_original()); + } + + if(!halo_x_.get_original().empty()) { + v.push_back("halo_x=" + halo_x_.get_original()); + } + + if(!halo_y_.get_original().empty()) { + v.push_back("halo_y=" + halo_y_.get_original()); + } + + if(!halo_mod_.empty()) { + v.push_back("halo_mod=" + halo_mod_); + } + + if(!sound_.empty()) { + v.push_back("sound=" + sound_); + } + + if(!text_.empty()) { + v.push_back("text=" + text_); + if(text_color_) { v.push_back("text_color=" + text_color_.get().to_rgba_string()); } } - if (!blend_ratio_.get_original().empty()) { - v.push_back("blend_ratio="+blend_ratio_.get_original()); + + if(!blend_ratio_.get_original().empty()) { + v.push_back("blend_ratio=" + blend_ratio_.get_original()); + if(blend_with_) { v.push_back("blend_with=" + blend_with_.get().to_rgba_string()); } } - if (!highlight_ratio_.get_original().empty()) v.push_back("highlight_ratio="+highlight_ratio_.get_original()); - if (!offset_.get_original().empty()) v.push_back("offset="+offset_.get_original()); - if (!submerge_.get_original().empty()) v.push_back("submerge="+submerge_.get_original()); - if (!x_.get_original().empty()) v.push_back("x="+x_.get_original()); - if (!y_.get_original().empty()) v.push_back("y="+y_.get_original()); - if (!directional_x_.get_original().empty()) v.push_back("directional_x="+directional_x_.get_original()); - if (!directional_y_.get_original().empty()) v.push_back("directional_y="+directional_y_.get_original()); - if (auto_vflip_ == t_true) v.push_back("auto_vflip=true"); - if (auto_vflip_ == t_false) v.push_back("auto_vflip=false"); - if (auto_hflip_ == t_true) v.push_back("auto_hflip=true"); - if (auto_hflip_ == t_false) v.push_back("auto_hflip=false"); - if (primary_frame_ == t_true) v.push_back("primary_frame=true"); - if (primary_frame_ == t_false) v.push_back("primary_frame=false"); - if (!drawing_layer_.get_original().empty()) v.push_back("drawing_layer="+drawing_layer_.get_original()); + + if(!highlight_ratio_.get_original().empty()) { + v.push_back("highlight_ratio=" + highlight_ratio_.get_original()); + } + + if(!offset_.get_original().empty()) { + v.push_back("offset=" + offset_.get_original()); + } + + if(!submerge_.get_original().empty()) { + v.push_back("submerge=" + submerge_.get_original()); + } + + if(!x_.get_original().empty()) { + v.push_back("x=" + x_.get_original()); + } + + if(!y_.get_original().empty()) { + v.push_back("y=" + y_.get_original()); + } + + if(!directional_x_.get_original().empty()) { + v.push_back("directional_x=" + directional_x_.get_original()); + } + + if(!directional_y_.get_original().empty()) { + v.push_back("directional_y=" + directional_y_.get_original()); + } + + if(auto_vflip_ == true) { + v.push_back("auto_vflip=true"); + } + + if(auto_vflip_ == false) { + v.push_back("auto_vflip=false"); + } + + if(auto_hflip_ == true) { + v.push_back("auto_hflip=true"); + } + + if(auto_hflip_ == false) { + v.push_back("auto_hflip=false"); + } + + if(primary_frame_ == true) { + v.push_back("primary_frame=true"); + } + + if(primary_frame_ == false) { + v.push_back("primary_frame=false"); + } + + if(!drawing_layer_.get_original().empty()) { + v.push_back("drawing_layer=" + drawing_layer_.get_original()); + } + return v; } - -void unit_frame::redraw(const int frame_time,bool on_start_time,bool in_scope_of_frame,const map_location & src,const map_location & dst,halo::handle & halo_id,halo::manager & halo_man, const frame_parameters & animation_val,const frame_parameters & engine_val)const +void unit_frame::redraw(const int frame_time, bool on_start_time, bool in_scope_of_frame, + const map_location& src, const map_location& dst, + halo::handle& halo_id, halo::manager& halo_man, + const frame_parameters& animation_val, const frame_parameters& engine_val) const { - const int xsrc = game_display::get_singleton()->get_location_x(src); - const int ysrc = game_display::get_singleton()->get_location_y(src); - const int xdst = game_display::get_singleton()->get_location_x(dst); - const int ydst = game_display::get_singleton()->get_location_y(dst); + game_display* game_disp = game_display::get_singleton(); + + const int xsrc = game_disp->get_location_x(src); + const int ysrc = game_disp->get_location_y(src); + const int xdst = game_disp->get_location_x(dst); + const int ydst = game_disp->get_location_y(dst); const map_location::DIRECTION direction = src.get_relative_dir(dst); const frame_parameters current_data = merge_parameters(frame_time,animation_val,engine_val); double tmp_offset = current_data.offset; - // debug code allowing to see the number of frames and their position - // you need to add a '/n' - // if (tmp_offset) std::cout << (int)(tmp_offset*100) << ","; + // Debug code to see the number of frames and their position + //if(tmp_offset) { + // std::cout << static_cast(tmp_offset * 100) << "," << "\n"; + //} - int d2 = display::get_singleton()->hex_size() / 2; - if(on_start_time ) { - // stuff that should be done only once per frame + if(on_start_time) { + // Stuff that should be done only once per frame if(!current_data.sound.empty() ) { sound::play_sound(current_data.sound); } + if(!current_data.text.empty() && current_data.text_color) { - game_display::get_singleton()->float_label(src, current_data.text, current_data.text_color.get()); + game_disp->float_label(src, current_data.text, current_data.text_color.get()); } } + image::locator image_loc; if(direction != map_location::NORTH && direction != map_location::SOUTH) { - image_loc = image::locator(current_data.image_diagonal,current_data.image_mod); + image_loc = image::locator(current_data.image_diagonal, current_data.image_mod); } - if(image_loc.is_void() || image_loc.get_filename() == "") { // invalid diag image, or not diagonal - image_loc = image::locator(current_data.image,current_data.image_mod); + + if(image_loc.is_void() || image_loc.get_filename().empty()) { // invalid diag image, or not diagonal + image_loc = image::locator(current_data.image, current_data.image_mod); } 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().empty()) { // invalid diag image, or not diagonal image=image::get_image(image_loc, image::SCALED_TO_ZOOM); } - const int x = static_cast(tmp_offset * xdst + (1.0-tmp_offset) * xsrc) + d2; - const int y = static_cast(tmp_offset * ydst + (1.0-tmp_offset) * ysrc) + d2; - if (image != nullptr) { - bool facing_west = direction == map_location::NORTH_WEST || direction == map_location::SOUTH_WEST; - bool facing_north = direction == map_location::NORTH_WEST || direction == map_location::NORTH || direction == map_location::NORTH_EAST; - if(!current_data.auto_hflip) facing_west = false; - if(!current_data.auto_vflip) facing_north = true; - int my_x = x + current_data.x- image->w/2; - int my_y = y + current_data.y- image->h/2; + + const int d2 = display::get_singleton()->hex_size() / 2; + + const int x = static_cast(tmp_offset * xdst + (1.0 - tmp_offset) * xsrc) + d2; + const int y = static_cast(tmp_offset * ydst + (1.0 - tmp_offset) * ysrc) + d2; + + if(image != nullptr) { + bool facing_west = ( + direction == map_location::NORTH_WEST || + direction == map_location::SOUTH_WEST); + + bool facing_north = ( + direction == map_location::NORTH_WEST || + direction == map_location::NORTH || + direction == map_location::NORTH_EAST); + + if(!current_data.auto_hflip) { facing_west = false; } + if(!current_data.auto_vflip) { facing_north = true; } + + int my_x = x + current_data.x - image->w / 2; + int my_y = y + current_data.y - image->h / 2; + if(facing_west) { my_x -= current_data.directional_x; } else { my_x += current_data.directional_x; } + if(facing_north) { my_y += current_data.directional_y; } else { @@ -725,93 +834,113 @@ void unit_frame::redraw(const int frame_time,bool on_start_time,bool in_scope_of ftofxp(current_data.highlight_ratio), current_data.blend_with ? current_data.blend_with.get() : color_t(), current_data.blend_ratio, current_data.submerge, !facing_north); } + halo_id = halo::handle(); //halo::NO_HALO; - if (!in_scope_of_frame) { //check after frame as first/last frame image used in defense/attack anims + if(!in_scope_of_frame) { //check after frame as first/last frame image used in defense/attack anims return; } - if(!current_data.halo.empty()) { - halo::ORIENTATION orientation; - switch(direction) - { - case map_location::NORTH: - case map_location::NORTH_EAST: + // No halos, exit + if(current_data.halo.empty()) { + return; + } + + halo::ORIENTATION orientation; + switch(direction) + { + case map_location::NORTH: + case map_location::NORTH_EAST: + orientation = halo::NORMAL; + break; + case map_location::SOUTH_EAST: + case map_location::SOUTH: + if(!current_data.auto_vflip) { orientation = halo::NORMAL; - break; - case map_location::SOUTH_EAST: - case map_location::SOUTH: - if(!current_data.auto_vflip) { - orientation = halo::NORMAL; - } else { - orientation = halo::VREVERSE; - } - break; - case map_location::SOUTH_WEST: - if(!current_data.auto_vflip) { - orientation = halo::HREVERSE; - } else { - orientation = halo::HVREVERSE; - } - break; - case map_location::NORTH_WEST: + } else { + orientation = halo::VREVERSE; + } + break; + case map_location::SOUTH_WEST: + if(!current_data.auto_vflip) { orientation = halo::HREVERSE; - break; - case map_location::NDIRECTIONS: - default: - orientation = halo::NORMAL; - break; - } + } else { + orientation = halo::HVREVERSE; + } + break; + case map_location::NORTH_WEST: + orientation = halo::HREVERSE; + break; + case map_location::NDIRECTIONS: + default: + orientation = halo::NORMAL; + break; + } - if(direction != map_location::SOUTH_WEST && direction != map_location::NORTH_WEST) { - halo_id = halo_man.add(static_cast(x+current_data.halo_x* game_display::get_singleton()->get_zoom_factor()), - static_cast(y+current_data.halo_y* game_display::get_singleton()->get_zoom_factor()), - current_data.halo + current_data.halo_mod, - map_location(-1, -1), - orientation); - } else { - halo_id = halo_man.add(static_cast(x-current_data.halo_x* game_display::get_singleton()->get_zoom_factor()), - static_cast(y+current_data.halo_y* game_display::get_singleton()->get_zoom_factor()), - current_data.halo + current_data.halo_mod, - map_location(-1, -1), - orientation); - } + if(direction != map_location::SOUTH_WEST && direction != map_location::NORTH_WEST) { + halo_id = halo_man.add( + static_cast(x + current_data.halo_x * game_display::get_singleton()->get_zoom_factor()), + static_cast(y + current_data.halo_y * game_display::get_singleton()->get_zoom_factor()), + current_data.halo + current_data.halo_mod, + map_location(-1, -1), + orientation + ); + } else { + halo_id = halo_man.add( + static_cast(x - current_data.halo_x * game_display::get_singleton()->get_zoom_factor()), + static_cast(y + current_data.halo_y * game_display::get_singleton()->get_zoom_factor()), + current_data.halo + current_data.halo_mod, + map_location(-1, -1), + orientation + ); } } -std::set unit_frame::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 + +std::set unit_frame::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 { display* disp = display::get_singleton(); + const int xsrc = disp->get_location_x(src); const int ysrc = disp->get_location_y(src); const int xdst = disp->get_location_x(dst); const int ydst = disp->get_location_y(dst); const map_location::DIRECTION direction = src.get_relative_dir(dst); - const frame_parameters current_data = merge_parameters(frame_time,animation_val,engine_val); + const frame_parameters current_data = merge_parameters(frame_time, animation_val, engine_val); + double tmp_offset = current_data.offset; - int d2 = game_display::get_singleton()->hex_size() / 2; + const int d2 = game_display::get_singleton()->hex_size() / 2; image::locator image_loc; if(direction != map_location::NORTH && direction != map_location::SOUTH) { - image_loc = image::locator(current_data.image_diagonal,current_data.image_mod); + image_loc = image::locator(current_data.image_diagonal, current_data.image_mod); } - if(image_loc.is_void() || image_loc.get_filename() == "") { // invalid diag image, or not diagonal - image_loc = image::locator(current_data.image,current_data.image_mod); + + if(image_loc.is_void() || image_loc.get_filename().empty()) { // invalid diag image, or not diagonal + image_loc = image::locator(current_data.image, current_data.image_mod); } - // we always invalidate our own hex because we need to be called at redraw time even + // We always invalidate our own hex because we need to be called at redraw time even // if we don't draw anything in the hex itself std::set result; - if(tmp_offset==0 && current_data.x == 0 && current_data.directional_x == 0 && image::is_in_hex(image_loc)) { + if(tmp_offset == 0 && current_data.x == 0 && current_data.directional_x == 0 && image::is_in_hex(image_loc)) { result.insert(src); + + bool facing_north = ( + direction == map_location::NORTH_WEST || + direction == map_location::NORTH || + direction == map_location::NORTH_EAST); + + if(!current_data.auto_vflip) { facing_north = true; } + int my_y = current_data.y; - bool facing_north = direction == map_location::NORTH_WEST || direction == map_location::NORTH || direction == map_location::NORTH_EAST; - if(!current_data.auto_vflip) facing_north = true; if(facing_north) { my_y += current_data.directional_y; } else { my_y -= current_data.directional_y; } + if(my_y < 0) { result.insert(src.get_direction(map_location::NORTH)); result.insert(src.get_direction(map_location::NORTH_EAST)); @@ -822,99 +951,123 @@ std::set unit_frame::get_overlaped_hex(const int frame_time,const result.insert(src.get_direction(map_location::SOUTH_WEST)); } } else { - int w=0; - int h =0; + int w = 0, h = 0; + #ifdef _OPENMP #pragma omp critical(frame_surface) // with the way surfaces work it's hard to lock the refcount within sdl_utils #endif //_OPENMP + { surface image; - if(!image_loc.is_void() && image_loc.get_filename() != "") { // invalid diag image, or not diagonal - image=image::get_image(image_loc, - image::SCALED_TO_ZOOM - ); + if(!image_loc.is_void() && !image_loc.get_filename().empty()) { // invalid diag image, or not diagonal + image = image::get_image(image_loc, image::SCALED_TO_ZOOM); } + if(image != nullptr) { w = image->w; h = image->h; } } - if (w != 0 || h != 0) { - const int x = static_cast(tmp_offset * xdst + (1.0-tmp_offset) * xsrc); - const int y = static_cast(tmp_offset * ydst + (1.0-tmp_offset) * ysrc); - bool facing_west = direction == map_location::NORTH_WEST || direction == map_location::SOUTH_WEST; - bool facing_north = direction == map_location::NORTH_WEST || direction == map_location::NORTH || direction == map_location::NORTH_EAST; - if(!current_data.auto_vflip) facing_north = true; - if(!current_data.auto_hflip) facing_west = false; - int my_x = x +current_data.x+d2- w/2; - int my_y = y +current_data.y+d2- h/2; + + if(w != 0 || h != 0) { + const int x = static_cast(tmp_offset * xdst + (1.0 - tmp_offset) * xsrc); + const int y = static_cast(tmp_offset * ydst + (1.0 - tmp_offset) * ysrc); + + bool facing_west = ( + direction == map_location::NORTH_WEST || + direction == map_location::SOUTH_WEST); + + bool facing_north = ( + direction == map_location::NORTH_WEST || + direction == map_location::NORTH || + direction == map_location::NORTH_EAST); + + if(!current_data.auto_vflip) { facing_north = true; } + if(!current_data.auto_hflip) { facing_west = false; } + + int my_x = x + current_data.x + d2 - w / 2; + int my_y = y + current_data.y + d2 - h / 2; + if(facing_west) { my_x += current_data.directional_x; } else { my_x -= current_data.directional_x; } + if(facing_north) { my_y += current_data.directional_y; } else { my_y -= current_data.directional_y; } - const SDL_Rect r = sdl::create_rect(my_x, my_y, w, h); - // check if our underlying hexes are invalidated - // if we need to update ourselves because we changed, invalidate our hexes - // and return whether or not our hexes was invalidated - // invalidate ourself to be called at redraw time - result.insert(src); + // Check if our underlying hexes are invalidated. If we need to update ourselves because we changed, + // invalidate our hexes and return whether or not was sucessful. + const SDL_Rect r = {my_x, my_y, w, h}; display::rect_of_hexes underlying_hex = disp->hexes_under_rect(r); - result.insert(underlying_hex.begin(),underlying_hex.end()); + + result.insert(src); + result.insert(underlying_hex.begin(), underlying_hex.end()); } else { - // we have no "redraw surface" but we still need to invalidate our own hex - // in case we have a halo and/or sound that needs a redraw - // invalidate ourself to be called at redraw time + // We have no "redraw surface" but we still need to invalidate our own hex in case we have a halo + // and/or sound that needs a redraw. result.insert(src); result.insert(dst); } } + return result; } - - -const frame_parameters unit_frame::merge_parameters(int current_time,const frame_parameters & animation_val,const frame_parameters & engine_val) const +/** + * This function merges the value provided by: + * - the frame + * - the engine (poison, flying unit...) + * - the animation as a whole + * + * There is no absolute rule for merging, so creativity is the rule. If a value is never provided by the engine, assert. + * This way if it becomes used, people will easily find the right place to look. + */ +const frame_parameters unit_frame::merge_parameters(int current_time, const frame_parameters& animation_val, + const frame_parameters& engine_val) const { - /** - * this function merges the value provided by - * * the frame - * * the engine (poison, flying unit...) - * * the animation as a whole - * there is no absolute rule for merging, so creativity is the rule - * if a value is never provided by the engine, assert. (this way if it becomes used, people will easily find the right place to look) - * - */ frame_parameters result; - const frame_parameters & current_val = builder_.parameters(current_time); + const frame_parameters& current_val = 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; - if(current_val.primary_frame != t_unset) result.primary_frame = current_val.primary_frame; - const bool primary = tristate_to_bool(result.primary_frame, true); + if(!boost::logic::indeterminate(animation_val.primary_frame)) { + result.primary_frame = animation_val.primary_frame; + } + + if(!boost::logic::indeterminate(current_val.primary_frame)) { + result.primary_frame = current_val.primary_frame; + } + + // Convert the tribool to bool + const bool primary = result.primary_frame == true; + + /** The 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().empty() + ? animation_val.image + : current_val.image; - /** 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; - if(primary && ( result.image.is_void() || result.image.get_filename().empty())) { + 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; - if(primary && ( result.image_diagonal.is_void() || result.image_diagonal.get_filename().empty())) { + /** The 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().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; } - /** 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; + /** + * The 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. + */ + result.image_mod = current_val.image_mod + animation_val.image_mod; if(primary) { result.image_mod += engine_val.image_mod; } else { @@ -922,85 +1075,107 @@ const frame_parameters unit_frame::merge_parameters(int current_time,const frame } assert(engine_val.halo.empty()); - result.halo = current_val.halo.empty()?animation_val.halo:current_val.halo; + result.halo = current_val.halo.empty() ? animation_val.halo : current_val.halo; assert(engine_val.halo_x == 0); - result.halo_x = current_val.halo_x?current_val.halo_x:animation_val.halo_x; + result.halo_x = current_val.halo_x ? current_val.halo_x : animation_val.halo_x; - /** the engine provide y modification for terrain with height adjust and flying units */ - result.halo_y = current_val.halo_y?current_val.halo_y:animation_val.halo_y; + /** The engine provides a y modification for terrain with height adjust and flying units */ + result.halo_y = current_val.halo_y ? current_val.halo_y : animation_val.halo_y; result.halo_y += engine_val.halo_y; - result.halo_mod = current_val.halo_mod +animation_val.halo_mod; + result.halo_mod = current_val.halo_mod + animation_val.halo_mod; result.halo_mod += engine_val.halo_mod; assert(engine_val.duration == 0); result.duration = current_val.duration; assert(engine_val.sound.empty()); - result.sound = current_val.sound.empty()?animation_val.sound:current_val.sound; + result.sound = current_val.sound.empty() ? animation_val.sound : current_val.sound; assert(engine_val.text.empty()); - result.text = current_val.text.empty()?animation_val.text:current_val.text; + result.text = current_val.text.empty() ? animation_val.text : current_val.text; // TODO: how should this be handled now that we use color_t? assert(!engine_val.text_color); result.text_color = current_val.text_color && current_val.text_color ? current_val.text_color : animation_val.text_color; - /** engine provide a blend color for poisoned units */ + /** The engine provides a blend color for poisoned units */ result.blend_with = current_val.blend_with ? current_val.blend_with : animation_val.blend_with; if(primary && engine_val.blend_with && result.blend_with) { result.blend_with = engine_val.blend_with.get().blend_lighten(result.blend_with.get()); } - /** engine provide a blend color for poisoned units */ + /** The engine provides a blend color for poisoned units */ result.blend_ratio = current_val.blend_ratio?current_val.blend_ratio:animation_val.blend_ratio; if(primary && engine_val.blend_ratio) { - result.blend_ratio = std::min( - result.blend_ratio + engine_val.blend_ratio - , 1.0); + result.blend_ratio = std::min(result.blend_ratio + engine_val.blend_ratio, 1.0); } - /** engine provide a highlight ratio for selected units and visible "invisible" units */ - result.highlight_ratio = current_val.highlight_ratio!=1.0?current_val.highlight_ratio:animation_val.highlight_ratio; - if(primary && engine_val.highlight_ratio != 1.0) result.highlight_ratio = result.highlight_ratio +engine_val.highlight_ratio - 1.0; // selected unit + /** The engine provides a highlight ratio for selected units and visible "invisible" units */ + result.highlight_ratio = current_val.highlight_ratio != 1.0 ? current_val.highlight_ratio : animation_val.highlight_ratio; + if(primary && engine_val.highlight_ratio != 1.0) { + result.highlight_ratio = result.highlight_ratio + engine_val.highlight_ratio - 1.0; // selected unit + } assert(engine_val.offset == 0); - result.offset = (current_val.offset!=-1000)?current_val.offset:animation_val.offset; - if(result.offset == -1000) result.offset = 0.0; + result.offset = (current_val.offset != -1000) ? current_val.offset : animation_val.offset; + if(result.offset == -1000) { + result.offset = 0.0; + } - /** engine provides a submerge for units in water */ - result.submerge = current_val.submerge?current_val.submerge:animation_val.submerge; - if(primary && engine_val.submerge && !result.submerge ) result.submerge = engine_val.submerge; + /** The engine provides a submerge for units in water */ + result.submerge = current_val.submerge ? current_val.submerge : animation_val.submerge; + if(primary && engine_val.submerge && !result.submerge) { + result.submerge = engine_val.submerge; + } assert(engine_val.x == 0); - result.x = current_val.x?current_val.x:animation_val.x; + result.x = current_val.x ? current_val.x : animation_val.x; - /** the engine provide y modification for terrain with height adjust and flying units */ + /** The engine provides a y modification for terrain with height adjust and flying units */ result.y = current_val.y?current_val.y:animation_val.y; result.y += engine_val.y; assert(engine_val.directional_x == 0); - result.directional_x = current_val.directional_x?current_val.directional_x:animation_val.directional_x; + result.directional_x = current_val.directional_x ? current_val.directional_x : animation_val.directional_x; + assert(engine_val.directional_y == 0); - result.directional_y = current_val.directional_y?current_val.directional_y:animation_val.directional_y; + result.directional_y = current_val.directional_y ? current_val.directional_y : animation_val.directional_y; - assert(engine_val.drawing_layer == display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST); - result.drawing_layer = current_val.drawing_layer != display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST? - current_val.drawing_layer:animation_val.drawing_layer; + assert(engine_val.drawing_layer == display::LAYER_UNIT_DEFAULT - display::LAYER_UNIT_FIRST); + result.drawing_layer = current_val.drawing_layer != display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST + ? current_val.drawing_layer + : animation_val.drawing_layer; - /** the engine provide us with default value to compare with, we update if different */ + /** The engine provides us with a default value to compare to. Update if different */ result.auto_hflip = engine_val.auto_hflip; - if(animation_val.auto_hflip != t_unset) result.auto_hflip = animation_val.auto_hflip; - if(current_val.auto_hflip != t_unset) result.auto_hflip = current_val.auto_hflip; - if(result.auto_hflip == t_unset) result.auto_hflip = t_true; + + if(!boost::logic::indeterminate(animation_val.auto_hflip)) { + result.auto_hflip = animation_val.auto_hflip; + } + + if(!boost::logic::indeterminate(current_val.auto_hflip)) { + result.auto_hflip = current_val.auto_hflip; + } + + if(boost::logic::indeterminate(result.auto_hflip)) { + result.auto_hflip = true; + } result.auto_vflip = engine_val.auto_vflip; - if(animation_val.auto_vflip != t_unset) result.auto_vflip = animation_val.auto_vflip; - if(current_val.auto_vflip != t_unset) result.auto_vflip = current_val.auto_vflip; - if(result.auto_vflip == t_unset) { - if(primary) result.auto_vflip=t_false; - else result.auto_vflip = t_true; + + if(!boost::logic::indeterminate(animation_val.auto_vflip)) { + result.auto_vflip = animation_val.auto_vflip; } + + if(!boost::logic::indeterminate(current_val.auto_vflip)) { + result.auto_vflip = current_val.auto_vflip; + } + + if(boost::logic::indeterminate(result.auto_vflip)) { + result.auto_vflip = primary ? false : true; + } + return result; } diff --git a/src/units/frame.hpp b/src/units/frame.hpp index 720169496f4e..6afc788e12d6 100644 --- a/src/units/frame.hpp +++ b/src/units/frame.hpp @@ -23,203 +23,297 @@ #include "halo.hpp" #include "image.hpp" +#include #include 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 > data_; - std::string input_; -}; +/* FIXME: these 'progressive_' classes are all mostly equivalent except for the exact type of the + * data_ vector and the interactions with it. Need to figure how to reduce the code duplication - + * perhaps inherit from progressive_base? Though do note the string/image functions are only + * unique since they don't store a pair of pairs. + */ +template +class progressive_base +{ +public: + progressive_base(const std::string& data = "", int duration = 0); + int duration() const; + const T get_current_element(int time, T default_val = 0) const; + bool does_not_change() const; + + std::string get_original() const + { + return input_; + } -class progressive_image { - public: - progressive_image(const std::string& data = "",int duration = 0); - int duration() const; - const image::locator & 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 > data_; - std::string input_; +private: + std::vector, int>> data_; + std::string input_; }; -template -class progressive_ +class progressive_string { - std::vector, int> > data_; +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> data_; std::string input_; +}; + +class progressive_image +{ public: - progressive_(const std::string& data = "", int duration = 0); + progressive_image(const std::string& data = "", int duration = 0); int duration() const; - const T get_current_element(int time,T default_val=0) const; - bool does_not_change() const; - std::string get_original() const { return input_; } + const image::locator& 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> data_; + std::string input_; }; -typedef progressive_ progressive_int; -typedef progressive_ progressive_double; +typedef progressive_base progressive_int; +typedef progressive_base progressive_double; -enum tristate {t_false,t_true,t_unset}; -bool tristate_to_bool(tristate tri, bool def); /** All parameters from a frame at a given instant */ -class frame_parameters{ - public: +struct frame_parameters +{ frame_parameters(); int duration; + image::locator image; image::locator image_diagonal; + std::string image_mod; std::string halo; + int halo_x; int halo_y; + std::string halo_mod; std::string sound; std::string text; + boost::optional text_color; boost::optional blend_with; + double blend_ratio; double highlight_ratio; double offset; double submerge; + int x; int y; int directional_x; int directional_y; - tristate auto_vflip; - tristate auto_hflip; - tristate primary_frame; + + boost::tribool auto_vflip; + boost::tribool auto_hflip; + boost::tribool primary_frame; + int drawing_layer; -} ; +}; + /** - * easily build frame parameters with the serialized constructors + * Easily build frame parameters with the serialized constructors */ class frame_parsed_parameters; -class frame_builder { - public: - frame_builder(); - frame_builder(const config& cfg,const std::string &frame_string = ""); - /** allow easy chained modifications will raised assert if used after initialization */ - frame_builder & duration(const int duration); - frame_builder & image(const std::string& image ,const std::string & image_mod=""); - frame_builder & image_diagonal(const std::string& image_diagonal,const std::string & image_mod=""); - frame_builder & sound(const std::string& sound); - frame_builder & text(const std::string& text,const color_t 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 color_t 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 & 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); - /** getters for the different parameters */ - private: - friend class frame_parsed_parameters; - int duration_; - std::string image_; - std::string 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_; - boost::optional text_color_; - boost::optional 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_; - tristate auto_vflip_; - tristate auto_hflip_; - tristate primary_frame_; - std::string drawing_layer_; +class frame_builder +{ +public: + frame_builder(); + frame_builder(const config& cfg, const std::string& frame_string = ""); + + /** Allow easy chained modifications. Will raised assert if used after initialization */ + frame_builder& duration(const int duration); + frame_builder& image(const std::string& image, const std::string& image_mod = ""); + frame_builder& image_diagonal(const std::string& image_diagonal, const std::string& image_mod = ""); + frame_builder& sound(const std::string& sound); + frame_builder& text(const std::string& text, const color_t 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 color_t 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& 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); + +private: + friend class frame_parsed_parameters; + + int duration_; + + std::string image_; + std::string 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_; + + boost::optional text_color_; + boost::optional 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_; + + boost::tribool auto_vflip_; + boost::tribool auto_hflip_; + boost::tribool primary_frame_; + + std::string drawing_layer_; }; + /** - * keep most parameters in a separate class to simplify handling of large - * number of parameters handling is common for frame level and animation level + * Keep most parameters in a separate class to simplify the handling of the large + * number of parameters between the frame level and animation level. */ -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 ="" - , color_t blend_color = {0,0,0} - , const std::string& offset = "" - , const std::string& layer = "" - , const std::string& modifiers = ""); - /** 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; - std::vector debug_strings() const; //contents of frame in strings - private: - int duration_; - progressive_image image_; - progressive_image image_diagonal_; - std::string image_mod_; - progressive_string halo_; - progressive_int halo_x_; - progressive_int halo_y_; - std::string halo_mod_; - std::string sound_; - std::string text_; - boost::optional text_color_; - boost::optional blend_with_; - progressive_double blend_ratio_; - progressive_double highlight_ratio_; - progressive_double offset_; - progressive_double submerge_; - progressive_int x_; - progressive_int y_; - progressive_int directional_x_; - progressive_int directional_y_; - tristate auto_vflip_; - tristate auto_hflip_; - tristate primary_frame_; - progressive_int drawing_layer_; +class frame_parsed_parameters +{ +public: + frame_parsed_parameters(const frame_builder& builder = frame_builder(), int override_duration = 0); + + void override(int duration, + const std::string& highlight = "", + const std::string& blend_ratio = "", + color_t blend_color = {0,0,0}, + const std::string& offset = "", + const std::string& layer = "", + const std::string& modifiers = ""); + + /** 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; + + /** Contents of frame in strings */ + std::vector debug_strings() const; + +private: + int duration_; + + progressive_image image_; + progressive_image image_diagonal_; + + std::string image_mod_; + + progressive_string halo_; + progressive_int halo_x_; + progressive_int halo_y_; + + std::string halo_mod_; + std::string sound_; + std::string text_; + + boost::optional text_color_; + boost::optional blend_with_; + + progressive_double blend_ratio_; + progressive_double highlight_ratio_; + progressive_double offset_; + progressive_double submerge_; + progressive_int x_; + progressive_int y_; + progressive_int directional_x_; + progressive_int directional_y_; + + boost::tribool auto_vflip_; + boost::tribool auto_hflip_; + boost::tribool primary_frame_; + + progressive_int drawing_layer_; }; -/** 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 on_start_time,bool in_scope_of_frame,const map_location & src,const map_location & dst,halo::handle & halo_id, halo::manager & halo_man, 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);} - const frame_parameters end_parameters() const {return builder_.parameters(duration());} - - 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 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; - std::vector debug_strings() const { return builder_.debug_strings();} //contents of frame in strings - private: - frame_parsed_parameters builder_; +/** Describes 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 on_start_time, bool in_scope_of_frame, const map_location& src, const map_location& dst, + halo::handle& halo_id, halo::manager& halo_man, 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); + } + + const frame_parameters end_parameters() const + { + return builder_.parameters(duration()); + } + + 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::vector debug_strings() const + { + // Contents of frame in strings + return builder_.debug_strings(); + } + + std::set 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_; }; #endif