unit_frame.cpp

Go to the documentation of this file.
00001 /* $Id: unit_frame.cpp 53812 2012-04-06 15:24:59Z fendrin $ */
00002 /*
00003    Copyright (C) 2006 - 2012 by Jeremy Rosen <jeremy.rosen@enst-bretagne.fr>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 /** @file */
00017 
00018 #include "global.hpp"
00019 
00020 #include "game_display.hpp"
00021 #include "halo.hpp"
00022 #include "sound.hpp"
00023 #include "unit_frame.hpp"
00024 
00025 
00026 progressive_string::progressive_string(const std::string & data,int duration) :
00027     data_(),
00028     input_(data)
00029 {
00030         const std::vector<std::string> first_pass = utils::split(data);
00031         const int time_chunk = std::max<int>(duration / (first_pass.size()?first_pass.size():1),1);
00032 
00033         std::vector<std::string>::const_iterator tmp;
00034         for(tmp=first_pass.begin();tmp != first_pass.end() ; ++tmp) {
00035             std::vector<std::string> second_pass = utils::split(*tmp,':');
00036             if(second_pass.size() > 1) {
00037                 data_.push_back(std::pair<std::string,int>(second_pass[0],atoi(second_pass[1].c_str())));
00038             } else {
00039                 data_.push_back(std::pair<std::string,int>(second_pass[0],time_chunk));
00040             }
00041         }
00042 }
00043 int progressive_string::duration() const
00044 {
00045     int total =0;
00046     std::vector<std::pair<std::string,int> >::const_iterator cur_halo;
00047     for(cur_halo = data_.begin() ; cur_halo != data_.end() ; ++cur_halo) {
00048         total += cur_halo->second;
00049     }
00050     return total;
00051 
00052 }
00053 
00054 static const std::string empty_string;
00055 
00056 const std::string& progressive_string::get_current_element(int current_time)const
00057 {
00058     int time = 0;
00059     unsigned int sub_halo = 0;
00060     if(data_.empty()) return empty_string;
00061     while(time < current_time&& sub_halo < data_.size()) {
00062         time += data_[sub_halo].second;
00063         ++sub_halo;
00064 
00065     }
00066     if(sub_halo) sub_halo--;
00067     return data_[sub_halo].first;
00068 }
00069 
00070 template <class T>
00071 progressive_<T>::progressive_(const std::string &data, int duration) :
00072     data_(),
00073     input_(data)
00074 {
00075     int split_flag = utils::REMOVE_EMPTY; // useless to strip spaces
00076     const std::vector<std::string> comma_split = utils::split(data,',',split_flag);
00077     const int time_chunk = std::max<int>(1, duration / std::max<int>(comma_split.size(),1));
00078 
00079     std::vector<std::string>::const_iterator com_it = comma_split.begin();
00080     for(; com_it != comma_split.end(); ++com_it) {
00081         std::vector<std::string> colon_split = utils::split(*com_it,':',split_flag);
00082         int time = (colon_split.size() > 1) ? atoi(colon_split[1].c_str()) : time_chunk;
00083 
00084         std::vector<std::string> range = utils::split(colon_split[0],'~',split_flag);
00085         T range0 = lexical_cast<T>(range[0]);
00086         T range1 = (range.size() > 1) ? lexical_cast<T>(range[1]) : range0;
00087         typedef std::pair<T,T> range_pair;
00088         data_.push_back(std::pair<range_pair,int>(range_pair(range0, range1), time));
00089     }
00090 }
00091 
00092 template <class T>
00093 const T progressive_<T>::get_current_element(int current_time, T default_val) const
00094 {
00095     int time = 0;
00096     unsigned int sub_halo = 0;
00097     int searched_time = current_time;
00098     if(searched_time < 0) searched_time = 0;
00099     if(searched_time > duration()) searched_time = duration();
00100     if(data_.empty()) return default_val;
00101     while(time < searched_time&& sub_halo < data_.size()) {
00102         time += data_[sub_halo].second;
00103         ++sub_halo;
00104 
00105     }
00106     if(sub_halo != 0) {
00107         sub_halo--;
00108         time -= data_[sub_halo].second;
00109     }
00110 
00111     const T first =  data_[sub_halo].first.first;
00112     const T second =  data_[sub_halo].first.second;
00113 
00114     return T((static_cast<double>(searched_time - time) /
00115         static_cast<double>(data_[sub_halo].second)) *
00116         (second - first) + first);
00117 }
00118 
00119 template<class T>
00120 int progressive_<T>::duration() const
00121 {
00122     int total = 0;
00123     typename std::vector<std::pair<std::pair<T, T>, int> >::const_iterator cur_halo;
00124     for(cur_halo = data_.begin() ; cur_halo != data_.end() ; ++cur_halo) {
00125         total += cur_halo->second;
00126     }
00127     return total;
00128 
00129 }
00130 
00131 template <class T>
00132 bool progressive_<T>::does_not_change() const
00133 {
00134 return data_.empty() ||
00135     ( data_.size() == 1 && data_[0].first.first == data_[0].first.second);
00136 }
00137 
00138 // Force compilation of the following template instantiations
00139 template class progressive_<int>;
00140 template class progressive_<double>;
00141 
00142 frame_parameters::frame_parameters() :
00143     duration(0),
00144     image(),
00145     image_diagonal(),
00146     image_mod(""),
00147     halo(""),
00148     halo_x(0),
00149     halo_y(0),
00150     halo_mod(""),
00151     sound(""),
00152     text(""),
00153     text_color(0),
00154     blend_with(0),
00155     blend_ratio(0.0),
00156     highlight_ratio(1.0),
00157     offset(0),
00158     submerge(0.0),
00159     x(0),
00160     y(0),
00161     directional_x(0),
00162     directional_y(0),
00163     auto_vflip(t_unset),
00164     auto_hflip(t_unset),
00165     primary_frame(t_unset),
00166     drawing_layer(display::LAYER_UNIT_DEFAULT - display::LAYER_UNIT_FIRST)
00167 {}
00168 
00169 frame_builder::frame_builder() :
00170     duration_(1),
00171     image_(),
00172     image_diagonal_(),
00173     image_mod_(""),
00174     halo_(""),
00175     halo_x_(""),
00176     halo_y_(""),
00177     halo_mod_(""),
00178     sound_(""),
00179     text_(""),
00180     text_color_(0),
00181     blend_with_(0),
00182     blend_ratio_(""),
00183     highlight_ratio_(""),
00184     offset_(""),
00185     submerge_(""),
00186     x_(""),
00187     y_(""),
00188     directional_x_(""),
00189     directional_y_(""),
00190     auto_vflip_(t_unset),
00191     auto_hflip_(t_unset),
00192     primary_frame_(t_unset),
00193     drawing_layer_(str_cast(display::LAYER_UNIT_DEFAULT - display::LAYER_UNIT_FIRST))
00194 {}
00195 
00196 frame_builder::frame_builder(const config& cfg,const std::string& frame_string) :
00197     duration_(1),
00198     image_(cfg[frame_string + "image"]),
00199     image_diagonal_(cfg[frame_string + "image_diagonal"]),
00200     image_mod_(cfg[frame_string + "image_mod"]),
00201     halo_(cfg[frame_string + "halo"]),
00202     halo_x_(cfg[frame_string + "halo_x"]),
00203     halo_y_(cfg[frame_string + "halo_y"]),
00204     halo_mod_(cfg[frame_string + "halo_mod"]),
00205     sound_(cfg[frame_string + "sound"]),
00206     text_(cfg[frame_string + "text"]),
00207     text_color_(0),
00208     blend_with_(0),
00209     blend_ratio_(cfg[frame_string + "blend_ratio"]),
00210     highlight_ratio_(cfg[frame_string + "alpha"]),
00211     offset_(cfg[frame_string + "offset"]),
00212     submerge_(cfg[frame_string + "submerge"]),
00213     x_(cfg[frame_string + "x"]),
00214     y_(cfg[frame_string + "y"]),
00215     directional_x_(cfg[frame_string + "directional_x"]),
00216     directional_y_(cfg[frame_string + "directional_y"]),
00217     auto_vflip_(t_unset),
00218     auto_hflip_(t_unset),
00219     primary_frame_(t_unset),
00220     drawing_layer_(cfg[frame_string + "layer"])
00221 {
00222     if(!cfg.has_attribute(frame_string + "auto_vflip")) {
00223         auto_vflip_ = t_unset;
00224     } else if(cfg[frame_string + "auto_vflip"].to_bool()) {
00225         auto_vflip_ = t_true;
00226     } else {
00227         auto_vflip_ = t_false;
00228     }
00229     if(!cfg.has_attribute(frame_string + "auto_hflip")) {
00230         auto_hflip_ = t_unset;
00231     } else if(cfg[frame_string + "auto_hflip"].to_bool()) {
00232         auto_hflip_ = t_true;
00233     } else {
00234         auto_hflip_ = t_false;
00235     }
00236     if(!cfg.has_attribute(frame_string + "primary")) {
00237         primary_frame_ = t_unset;
00238     } else if(cfg[frame_string + "primary"].to_bool()) {
00239         primary_frame_ = t_true;
00240     } else {
00241         primary_frame_ = t_false;
00242     }
00243     std::vector<std::string> color = utils::split(cfg[frame_string + "text_color"]);
00244     if (color.size() == 3) {
00245         text_color_ = display::rgb(atoi(color[0].c_str()),
00246             atoi(color[1].c_str()), atoi(color[2].c_str()));
00247     }
00248 
00249     if (const config::attribute_value *v = cfg.get(frame_string + "duration")) {
00250         duration(*v);
00251     } else {
00252         duration(cfg[frame_string + "end"].to_int() - cfg[frame_string + "begin"].to_int());
00253     }
00254 
00255     color = utils::split(cfg[frame_string + "blend_color"]);
00256     if (color.size() == 3) {
00257         blend_with_ = display::rgb(atoi(color[0].c_str()),
00258             atoi(color[1].c_str()), atoi(color[2].c_str()));
00259     }
00260 }
00261 
00262 frame_builder & frame_builder::image(const image::locator& image ,const std::string & image_mod)
00263 {
00264     image_ = image;
00265     image_mod_ = image_mod;
00266     return *this;
00267 }
00268 frame_builder & frame_builder::image_diagonal(const image::locator& image_diagonal,const std::string& image_mod)
00269 {
00270     image_diagonal_ = image_diagonal;
00271     image_mod_ = image_mod;
00272     return *this;
00273 }
00274 frame_builder & frame_builder::sound(const std::string& sound)
00275 {
00276     sound_=sound;
00277     return *this;
00278 }
00279 frame_builder & frame_builder::text(const std::string& text,const  Uint32 text_color)
00280 {
00281     text_=text;
00282     text_color_=text_color;
00283     return *this;
00284 }
00285 frame_builder & frame_builder::halo(const std::string &halo, const std::string &halo_x, const std::string& halo_y,const std::string & halo_mod)
00286 {
00287     halo_ = halo;
00288     halo_x_ = halo_x;
00289     halo_y_ = halo_y;
00290     halo_mod_= halo_mod;
00291     return *this;
00292 }
00293 frame_builder & frame_builder::duration(const int duration)
00294 {
00295     duration_= duration;
00296     return *this;
00297 }
00298 frame_builder & frame_builder::blend(const std::string& blend_ratio,const Uint32 blend_color)
00299 {
00300     blend_with_=blend_color;
00301     blend_ratio_=blend_ratio;
00302     return *this;
00303 }
00304 frame_builder & frame_builder::highlight(const std::string& highlight)
00305 {
00306     highlight_ratio_=highlight;
00307     return *this;
00308 }
00309 frame_builder & frame_builder::offset(const std::string& offset)
00310 {
00311     offset_=offset;
00312     return *this;
00313 }
00314 frame_builder & frame_builder::submerge(const std::string& submerge)
00315 {
00316     submerge_=submerge;
00317     return *this;
00318 }
00319 frame_builder & frame_builder::x(const std::string& x)
00320 {
00321     x_=x;
00322     return *this;
00323 }
00324 frame_builder & frame_builder::y(const std::string& y)
00325 {
00326     y_=y;
00327     return *this;
00328 }
00329 frame_builder & frame_builder::directional_x(const std::string& directional_x)
00330 {
00331     directional_x_=directional_x;
00332     return *this;
00333 }
00334 frame_builder & frame_builder::directional_y(const std::string& directional_y)
00335 {
00336     directional_y_=directional_y;
00337     return *this;
00338 }
00339 frame_builder & frame_builder::auto_vflip(const bool auto_vflip)
00340 {
00341     if(auto_vflip) auto_vflip_ = t_true;
00342     else auto_vflip_ = t_false;
00343     return *this;
00344 }
00345 frame_builder & frame_builder::auto_hflip(const bool auto_hflip)
00346 {
00347     if(auto_hflip) auto_hflip_ = t_true;
00348     else auto_hflip_ = t_false;
00349     return *this;
00350 }
00351 frame_builder & frame_builder::primary_frame(const bool primary_frame)
00352 {
00353     if(primary_frame) primary_frame_ = t_true;
00354     else primary_frame_ = t_false;
00355     return *this;
00356 }
00357 frame_builder & frame_builder::drawing_layer(const std::string& drawing_layer)
00358 {
00359     drawing_layer_=drawing_layer;
00360     return *this;
00361 }
00362 
00363 
00364 frame_parsed_parameters::frame_parsed_parameters(const frame_builder & builder, int duration) :
00365     duration_(duration ? duration :builder.duration_),
00366     image_(builder.image_),
00367     image_diagonal_(builder.image_diagonal_),
00368     image_mod_(builder.image_mod_),
00369     halo_(builder.halo_,duration_),
00370     halo_x_(builder.halo_x_,duration_),
00371     halo_y_(builder.halo_y_,duration_),
00372     halo_mod_(builder.halo_mod_),
00373     sound_(builder.sound_),
00374     text_(builder.text_),
00375     text_color_(builder.text_color_),
00376     blend_with_(builder.blend_with_),
00377     blend_ratio_(builder.blend_ratio_,duration_),
00378     highlight_ratio_(builder.highlight_ratio_,duration_),
00379     offset_(builder.offset_,duration_),
00380     submerge_(builder.submerge_,duration_),
00381     x_(builder.x_,duration_),
00382     y_(builder.y_,duration_),
00383     directional_x_(builder.directional_x_,duration_),
00384     directional_y_(builder.directional_y_,duration_),
00385     auto_vflip_(builder.auto_vflip_),
00386     auto_hflip_(builder.auto_hflip_),
00387     primary_frame_(builder.primary_frame_),
00388     drawing_layer_(builder.drawing_layer_,duration_)
00389 {}
00390 
00391 
00392 bool frame_parsed_parameters::does_not_change() const
00393 {
00394     return halo_.does_not_change() &&
00395         halo_x_.does_not_change() &&
00396         halo_y_.does_not_change() &&
00397         blend_ratio_.does_not_change() &&
00398         highlight_ratio_.does_not_change() &&
00399         offset_.does_not_change() &&
00400         submerge_.does_not_change() &&
00401         x_.does_not_change() &&
00402         y_.does_not_change() &&
00403         directional_x_.does_not_change() &&
00404         directional_y_.does_not_change() &&
00405         drawing_layer_.does_not_change();
00406 }
00407 bool frame_parsed_parameters::need_update() const
00408 {
00409     if(!halo_.does_not_change() ||
00410             !halo_x_.does_not_change() ||
00411             !halo_y_.does_not_change() ||
00412             !blend_ratio_.does_not_change() ||
00413             !highlight_ratio_.does_not_change() ||
00414             !offset_.does_not_change() ||
00415             !submerge_.does_not_change() ||
00416             !x_.does_not_change() ||
00417             !y_.does_not_change() ||
00418             !directional_x_.does_not_change() ||
00419             !directional_y_.does_not_change() ||
00420             !drawing_layer_.does_not_change() ) {
00421             return true;
00422     }
00423     return false;
00424 }
00425 
00426 const frame_parameters frame_parsed_parameters::parameters(int current_time) const
00427 {
00428     frame_parameters result;
00429     result.duration = duration_;
00430     result.image = image_;
00431     result.image_diagonal = image_diagonal_;
00432     result.image_mod = image_mod_;
00433     result.halo = halo_.get_current_element(current_time);
00434     result.halo_x = halo_x_.get_current_element(current_time);
00435     result.halo_y = halo_y_.get_current_element(current_time);
00436     result.halo_mod = halo_mod_;
00437     result.sound = sound_;
00438     result.text = text_;
00439     result.text_color = text_color_;
00440     result.blend_with = blend_with_;
00441     result.blend_ratio = blend_ratio_.get_current_element(current_time);
00442     result.highlight_ratio = highlight_ratio_.get_current_element(current_time,1.0);
00443     result.offset = offset_.get_current_element(current_time,-1000);
00444     result.submerge = submerge_.get_current_element(current_time);
00445     result.x = x_.get_current_element(current_time);
00446     result.y = y_.get_current_element(current_time);
00447     result.directional_x = directional_x_.get_current_element(current_time);
00448     result.directional_y = directional_y_.get_current_element(current_time);
00449     result.auto_vflip = auto_vflip_;
00450     result.auto_hflip = auto_hflip_;
00451     result.primary_frame = primary_frame_;
00452     result.drawing_layer = drawing_layer_.get_current_element(current_time,display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
00453     return result;
00454 }
00455 
00456 void frame_parsed_parameters::override( int duration
00457         , const std::string& highlight
00458         , const std::string& blend_ratio
00459         , Uint32 blend_color
00460         , const std::string& offset
00461         , const std::string& layer
00462         , const std::string& modifiers)
00463 {
00464 
00465     if(!highlight.empty()) {
00466         highlight_ratio_ = progressive_double(highlight,duration);
00467     } else if(duration != duration_){
00468         highlight_ratio_=progressive_double(highlight_ratio_.get_original(),duration);
00469     }
00470     if(!offset.empty()) {
00471         offset_= progressive_double(offset,duration);
00472     } else  if(duration != duration_){
00473         offset_=progressive_double(offset_.get_original(),duration);
00474     }
00475     if(!blend_ratio.empty()) {
00476         blend_ratio_ = progressive_double(blend_ratio,duration);
00477         blend_with_  = blend_color;
00478     } else  if(duration != duration_){
00479         blend_ratio_=progressive_double(blend_ratio_.get_original(),duration);
00480     }
00481     if(!layer.empty()) {
00482         drawing_layer_ = progressive_int(layer,duration);
00483     } else  if(duration != duration_){
00484         drawing_layer_=progressive_int(drawing_layer_.get_original(),duration);
00485     }
00486     if(!modifiers.empty()) {
00487         image_mod_+=modifiers;
00488     }
00489 
00490     if(duration != duration_) {
00491         halo_ = progressive_string(halo_.get_original(),duration);
00492         halo_x_ = progressive_int(halo_x_.get_original(),duration);
00493         halo_y_ = progressive_int(halo_y_.get_original(),duration);
00494         submerge_=progressive_double(submerge_.get_original(),duration);
00495         x_=progressive_int(x_.get_original(),duration);
00496         y_=progressive_int(y_.get_original(),duration);
00497         directional_x_=progressive_int(directional_x_.get_original(),duration);
00498         directional_y_=progressive_int(directional_y_.get_original(),duration);
00499         duration_ = duration;
00500     }
00501 }
00502 
00503 
00504 void unit_frame::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
00505 {
00506     const int xsrc = game_display::get_singleton()->get_location_x(src);
00507     const int ysrc = game_display::get_singleton()->get_location_y(src);
00508     const int xdst = game_display::get_singleton()->get_location_x(dst);
00509     const int ydst = game_display::get_singleton()->get_location_y(dst);
00510     const map_location::DIRECTION direction = src.get_relative_dir(dst);
00511 
00512     const frame_parameters current_data = merge_parameters(frame_time,animation_val,engine_val);
00513     double tmp_offset = current_data.offset;
00514 
00515         // debug code allowing to see the number of frames and their position
00516         // you need to add a '/n'
00517         // if (tmp_offset) std::cout << (int)(tmp_offset*100) << ",";
00518 
00519     int d2 = display::get_singleton()->hex_size() / 2;
00520     if(first_time ) {
00521         // stuff sthat should be done only once per frame
00522         if(!current_data.sound.empty()  ) {
00523             sound::play_sound(current_data.sound);
00524         }
00525         if(!current_data.text.empty()  ) {
00526             game_display::get_singleton()->float_label(src,current_data.text,
00527             (current_data.text_color & 0x00FF0000) >> 16,
00528             (current_data.text_color & 0x0000FF00) >> 8,
00529             (current_data.text_color & 0x000000FF) >> 0);
00530         }
00531     }
00532     image::locator image_loc;
00533     if(direction != map_location::NORTH && direction != map_location::SOUTH) {
00534         image_loc = image::locator(current_data.image_diagonal,current_data.image_mod);
00535     }
00536     if(image_loc.is_void() || image_loc.get_filename() == "") { // invalid diag image, or not diagonal
00537         image_loc = image::locator(current_data.image,current_data.image_mod);
00538     }
00539 
00540     surface image;
00541     if(!image_loc.is_void() && image_loc.get_filename() != "") { // invalid diag image, or not diagonal
00542         image=image::get_image(image_loc, image::SCALED_TO_ZOOM);
00543     }
00544     const int x = static_cast<int>(tmp_offset * xdst + (1.0-tmp_offset) * xsrc) + d2;
00545     const int y = static_cast<int>(tmp_offset * ydst + (1.0-tmp_offset) * ysrc) + d2;
00546     if (image != NULL) {
00547 #ifdef LOW_MEM
00548         bool facing_west = false;
00549 #else
00550         bool facing_west = direction == map_location::NORTH_WEST || direction == map_location::SOUTH_WEST;
00551 #endif
00552         bool facing_north = direction == map_location::NORTH_WEST || direction == map_location::NORTH || direction == map_location::NORTH_EAST;
00553         if(!current_data.auto_hflip) facing_west = false;
00554         if(!current_data.auto_vflip) facing_north = true;
00555         int my_x = x + current_data.x- image->w/2;
00556         int my_y = y + current_data.y- image->h/2;
00557         if(facing_west) {
00558             my_x -= current_data.directional_x;
00559         } else {
00560             my_x += current_data.directional_x;
00561         }
00562         if(facing_north) {
00563             my_y += current_data.directional_y;
00564         } else {
00565             my_y -= current_data.directional_y;
00566         }
00567 
00568         game_display::get_singleton()->render_image( my_x,my_y,
00569                     static_cast<display::tdrawing_layer>(display::LAYER_UNIT_FIRST+current_data.drawing_layer),
00570                     src, image, facing_west, false,
00571                 ftofxp(current_data.highlight_ratio), current_data.blend_with,
00572                     current_data.blend_ratio,current_data.submerge,!facing_north);
00573     }
00574     halo::remove(*halo_id);
00575     *halo_id = halo::NO_HALO;
00576     if(!current_data.halo.empty()) {
00577         halo::ORIENTATION orientation;
00578         switch(direction)
00579         {
00580             case map_location::NORTH:
00581             case map_location::NORTH_EAST:
00582                 orientation = halo::NORMAL;
00583                 break;
00584             case map_location::SOUTH_EAST:
00585             case map_location::SOUTH:
00586                 if(!current_data.auto_vflip) {
00587                     orientation = halo::NORMAL;
00588                 } else {
00589                     orientation = halo::VREVERSE;
00590                 }
00591                 break;
00592             case map_location::SOUTH_WEST:
00593                 if(!current_data.auto_vflip) {
00594                     orientation = halo::HREVERSE;
00595                 } else {
00596                     orientation = halo::HVREVERSE;
00597                 }
00598                 break;
00599             case map_location::NORTH_WEST:
00600                 orientation = halo::HREVERSE;
00601                 break;
00602             case map_location::NDIRECTIONS:
00603             default:
00604                 orientation = halo::NORMAL;
00605                 break;
00606         }
00607         if(direction != map_location::SOUTH_WEST && direction != map_location::NORTH_WEST) {
00608             *halo_id = halo::add(static_cast<int>(x+current_data.halo_x* game_display::get_singleton()->get_zoom_factor()),
00609                     static_cast<int>(y+current_data.halo_y* game_display::get_singleton()->get_zoom_factor()),
00610                     current_data.halo + current_data.halo_mod,
00611                     map_location(-1, -1),
00612                     orientation);
00613         } else {
00614             *halo_id = halo::add(static_cast<int>(x-current_data.halo_x* game_display::get_singleton()->get_zoom_factor()),
00615                     static_cast<int>(y+current_data.halo_y* game_display::get_singleton()->get_zoom_factor()),
00616                     current_data.halo + current_data.halo_mod,
00617                     map_location(-1, -1),
00618                     orientation);
00619         }
00620     }
00621 }
00622 std::set<map_location> 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
00623 {
00624     display* disp = display::get_singleton();
00625     const int xsrc = disp->get_location_x(src);
00626     const int ysrc = disp->get_location_y(src);
00627     const int xdst = disp->get_location_x(dst);
00628     const int ydst = disp->get_location_y(dst);
00629     const map_location::DIRECTION direction = src.get_relative_dir(dst);
00630 
00631     const frame_parameters current_data = merge_parameters(frame_time,animation_val,engine_val);
00632     double tmp_offset = current_data.offset;
00633     int d2 = game_display::get_singleton()->hex_size() / 2;
00634 
00635     image::locator image_loc;
00636     if(direction != map_location::NORTH && direction != map_location::SOUTH) {
00637         image_loc = image::locator(current_data.image_diagonal,current_data.image_mod);
00638     }
00639     if(image_loc.is_void() || image_loc.get_filename() == "") { // invalid diag image, or not diagonal
00640         image_loc = image::locator(current_data.image,current_data.image_mod);
00641     }
00642 
00643     // we always invalidate our own hex because we need to be called at redraw time even
00644     // if we don't draw anything in the hex itself
00645     std::set<map_location> result;
00646     if(tmp_offset==0 && current_data.x == 0 && current_data.directional_x == 0 && image::is_in_hex(image_loc)) {
00647         result.insert(src);
00648         int my_y = current_data.y;
00649         bool facing_north = direction == map_location::NORTH_WEST || direction == map_location::NORTH || direction == map_location::NORTH_EAST;
00650         if(!current_data.auto_vflip) facing_north = true;
00651         if(facing_north) {
00652             my_y += current_data.directional_y;
00653         } else {
00654             my_y -= current_data.directional_y;
00655         }
00656         if(my_y < 0) {
00657             result.insert(src.get_direction(map_location::NORTH));
00658             result.insert(src.get_direction(map_location::NORTH_EAST));
00659             result.insert(src.get_direction(map_location::NORTH_WEST));
00660         } else if(my_y > 0) {
00661             result.insert(src.get_direction(map_location::SOUTH));
00662             result.insert(src.get_direction(map_location::SOUTH_EAST));
00663             result.insert(src.get_direction(map_location::SOUTH_WEST));
00664         }
00665     } else {
00666         int w=0;
00667         int h =0;
00668 #ifdef _OPENMP
00669 #pragma omp critical(frame_surface) // with the way surfaces work it's hard to lock the refcount within sdl_utils
00670 #endif //_OPENMP
00671         {
00672             surface image;
00673             if(!image_loc.is_void() && image_loc.get_filename() != "") { // invalid diag image, or not diagonal
00674                 image=image::get_image(image_loc,
00675                         image::SCALED_TO_ZOOM
00676                         );
00677             }
00678             if(image != NULL) {
00679                 w = image->w;
00680                 h = image->h;
00681             }
00682         }
00683         if (w != 0 || h != 0) {
00684             const int x = static_cast<int>(tmp_offset * xdst + (1.0-tmp_offset) * xsrc);
00685             const int y = static_cast<int>(tmp_offset * ydst + (1.0-tmp_offset) * ysrc);
00686 #ifdef LOW_MEM
00687             bool facing_west = false;
00688 #else
00689             bool facing_west = direction == map_location::NORTH_WEST || direction == map_location::SOUTH_WEST;
00690 #endif
00691             bool facing_north = direction == map_location::NORTH_WEST || direction == map_location::NORTH || direction == map_location::NORTH_EAST;
00692             if(!current_data.auto_vflip) facing_north = true;
00693             if(!current_data.auto_hflip) facing_west = false;
00694             int my_x = x +current_data.x+d2- w/2;
00695             int my_y = y +current_data.y+d2- h/2;
00696             if(facing_west) {
00697                 my_x += current_data.directional_x;
00698             } else {
00699                 my_x -= current_data.directional_x;
00700             }
00701             if(facing_north) {
00702                 my_y += current_data.directional_y;
00703             } else {
00704                 my_y -= current_data.directional_y;
00705             }
00706 
00707             const SDL_Rect r = create_rect(my_x, my_y, w, h);
00708             // check if our underlying hexes are invalidated
00709             // if we need to update ourselves because we changed, invalidate our hexes
00710             // and return whether or not our hexs was invalidated
00711             // invalidate ourself to be called at redraw time
00712             result.insert(src);
00713             display::rect_of_hexes underlying_hex = disp->hexes_under_rect(r);
00714             result.insert(underlying_hex.begin(),underlying_hex.end());
00715         } else {
00716             // we have no "redraw surface" but we still need to invalidate our own hex
00717             // in case we have a halo and/or sound that needs a redraw
00718             // invalidate ourself to be called at redraw time
00719             result.insert(src);
00720             result.insert(dst);
00721         }
00722     }
00723     return result;
00724 }
00725 
00726 
00727 
00728 const frame_parameters unit_frame::merge_parameters(int current_time,const frame_parameters & animation_val,const frame_parameters & engine_val) const
00729 {
00730     /**
00731      * this function merges the value provided by
00732      *  * the frame
00733      *  * the engine (poison, flying unit...)
00734      *  * the animation as a whole
00735      *  there is no absolute rule for merging, so creativity is the rule
00736      *  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)
00737      *
00738      */
00739     frame_parameters result;
00740     const frame_parameters & current_val = builder_.parameters(current_time);
00741 
00742     result.primary_frame = engine_val.primary_frame;
00743     if(animation_val.primary_frame != t_unset) result.primary_frame = animation_val.primary_frame;
00744     if(current_val.primary_frame != t_unset) result.primary_frame = current_val.primary_frame;
00745     const bool primary = result.primary_frame;
00746 
00747     /** engine provides a default image to use for the unit when none is available */
00748     result.image = current_val.image.is_void() || current_val.image.get_filename() == ""?animation_val.image:current_val.image;
00749     if(primary && ( result.image.is_void() || result.image.get_filename().empty())) {
00750         result.image = engine_val.image;
00751     }
00752 
00753     /** engine provides a default image to use for the unit when none is available */
00754     result.image_diagonal = current_val.image_diagonal.is_void() || current_val.image_diagonal.get_filename() == ""?animation_val.image_diagonal:current_val.image_diagonal;
00755     if(primary && ( result.image_diagonal.is_void() || result.image_diagonal.get_filename().empty())) {
00756         result.image_diagonal = engine_val.image_diagonal;
00757     }
00758 
00759     /** engine provides a string for "petrified" and "team color" modifications
00760           note that image_mod is the complete modification and halo_mod is only the TC part
00761           see unit.cpp, we know that and use it*/
00762         result.image_mod = current_val.image_mod +animation_val.image_mod;
00763     if(primary) {
00764                 result.image_mod += engine_val.image_mod;
00765         } else {
00766                 result.image_mod += engine_val.halo_mod;
00767         }
00768 
00769     assert(engine_val.halo.empty());
00770     result.halo = current_val.halo.empty()?animation_val.halo:current_val.halo;
00771 
00772     assert(engine_val.halo_x == 0);
00773     result.halo_x =  current_val.halo_x?current_val.halo_x:animation_val.halo_x;
00774 
00775     /** the engine provide y modification for terrain with height adjust and flying units */
00776     result.halo_y = current_val.halo_y?current_val.halo_y:animation_val.halo_y;
00777     result.halo_y += engine_val.halo_y;
00778 
00779     result.halo_mod = current_val.halo_mod +animation_val.halo_mod;
00780     result.halo_mod += engine_val.halo_mod;
00781 
00782     assert(engine_val.duration == 0);
00783     result.duration = current_val.duration;
00784 
00785     assert(engine_val.sound.empty());
00786     result.sound = current_val.sound.empty()?animation_val.sound:current_val.sound;
00787 
00788     assert(engine_val.text.empty());
00789     result.text = current_val.text.empty()?animation_val.text:current_val.text;
00790 
00791     assert(engine_val.text_color == 0);
00792     result.text_color = current_val.text_color?current_val.text_color:animation_val.text_color;
00793 
00794     /** engine provide a blend color for poisoned units */
00795     result.blend_with = current_val.blend_with?current_val.blend_with:animation_val.blend_with;
00796     if(primary&& engine_val.blend_with) result.blend_with = display::max_rgb(engine_val.blend_with,result.blend_with);
00797 
00798     /** engine provide a blend color for poisoned units */
00799     result.blend_ratio = current_val.blend_ratio?current_val.blend_ratio:animation_val.blend_ratio;
00800     if(primary && engine_val.blend_ratio) {
00801         result.blend_ratio = std::min(
00802                   result.blend_ratio + engine_val.blend_ratio
00803                 , 1.0);
00804     }
00805 
00806     /** engine provide a highlight ratio for selected units and visible "invisible" units */
00807     result.highlight_ratio = current_val.highlight_ratio!=1.0?current_val.highlight_ratio:animation_val.highlight_ratio;
00808     if(primary && engine_val.highlight_ratio != 1.0) result.highlight_ratio = result.highlight_ratio +engine_val.highlight_ratio - 1.0; // selected unit
00809 
00810     assert(engine_val.offset == 0);
00811     result.offset = (current_val.offset!=-1000)?current_val.offset:animation_val.offset;
00812     if(result.offset == -1000) result.offset = 0.0;
00813 
00814     /** engine provides a submerge for units in water */
00815     result.submerge = current_val.submerge?current_val.submerge:animation_val.submerge;
00816     if(primary && engine_val.submerge && !result.submerge ) result.submerge = engine_val.submerge;
00817 
00818     assert(engine_val.x == 0);
00819     result.x = current_val.x?current_val.x:animation_val.x;
00820 
00821     /** the engine provide y modification for terrain with height adjust and flying units */
00822     result.y = current_val.y?current_val.y:animation_val.y;
00823     result.y += engine_val.y;
00824 
00825     assert(engine_val.directional_x == 0);
00826     result.directional_x = current_val.directional_x?current_val.directional_x:animation_val.directional_x;
00827     assert(engine_val.directional_y == 0);
00828     result.directional_y = current_val.directional_y?current_val.directional_y:animation_val.directional_y;
00829 
00830     assert(engine_val.drawing_layer == display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST);
00831     result.drawing_layer = current_val.drawing_layer !=  display::LAYER_UNIT_DEFAULT-display::LAYER_UNIT_FIRST?
00832         current_val.drawing_layer:animation_val.drawing_layer;
00833 
00834     /** the engine provide us with default value to compare with, we update if different */
00835     result.auto_hflip = engine_val.auto_hflip;
00836     if(animation_val.auto_hflip != t_unset) result.auto_hflip = animation_val.auto_hflip;
00837     if(current_val.auto_hflip != t_unset) result.auto_hflip = current_val.auto_hflip;
00838     if(result.auto_hflip == t_unset) result.auto_hflip = t_true;
00839 
00840     result.auto_vflip = engine_val.auto_vflip;
00841     if(animation_val.auto_vflip != t_unset) result.auto_vflip = animation_val.auto_vflip;
00842     if(current_val.auto_vflip != t_unset) result.auto_vflip = current_val.auto_vflip;
00843     if(result.auto_vflip == t_unset) {
00844         if(primary) result.auto_vflip=t_false;
00845         else result.auto_vflip = t_true;
00846     }
00847 #ifdef LOW_MEM
00848     if(primary) {
00849         result.image= engine_val.image;
00850         result.image_diagonal= engine_val.image;
00851     }
00852 #endif
00853     return result;
00854 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:14 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs