00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "global.hpp"
00018 #include "sound.hpp"
00019 #include "halo.hpp"
00020 #include <cassert>
00021
00022
00023 #include "display.hpp"
00024 #define UNIT_FRAME_H_PART2
00025 #include "unit_frame.hpp"
00026
00027
00028 progressive_string::progressive_string(const std::string & data,int duration)
00029 {
00030 const std::vector<std::string> first_pass = utils::split(data);
00031 input_ = data;
00032 const int time_chunk = maximum<int>(duration / (first_pass.size()?first_pass.size():1),1);
00033
00034 std::vector<std::string>::const_iterator tmp;
00035 for(tmp=first_pass.begin();tmp != first_pass.end() ; tmp++) {
00036 std::vector<std::string> second_pass = utils::split(*tmp,':');
00037 if(second_pass.size() > 1) {
00038 data_.push_back(std::pair<std::string,int>(second_pass[0],atoi(second_pass[1].c_str())));
00039 } else {
00040 data_.push_back(std::pair<std::string,int>(second_pass[0],time_chunk));
00041 }
00042 }
00043 }
00044 int progressive_string::duration() const
00045 {
00046 int total =0;
00047 std::vector<std::pair<std::string,int> >::const_iterator cur_halo;
00048 for(cur_halo = data_.begin() ; cur_halo != data_.end() ; cur_halo++) {
00049 total += cur_halo->second;
00050 }
00051 return total;
00052
00053 }
00054 static const std::string empty_string ="";
00055 const std::string& progressive_string::get_current_element(int current_time)const
00056 {
00057 int time = 0;
00058 unsigned int sub_halo = 0;
00059 if(data_.empty()) return empty_string;
00060 while(time < current_time&& sub_halo < data_.size()) {
00061 time += data_[sub_halo].second;
00062 sub_halo++;
00063
00064 }
00065 if(sub_halo) sub_halo--;
00066 if(sub_halo >= data_.size()) sub_halo = data_.size();
00067 return data_[sub_halo].first;
00068 }
00069
00070 template <class T>
00071 progressive_<T>::progressive_(const std::string &data, int duration)
00072 {
00073 input_ = data;
00074 const std::vector<std::string> first_split = utils::split(data);
00075 const int time_chunk = maximum<int>(duration / (first_split.size()?first_split.size():1),1);
00076
00077 std::vector<std::string>::const_iterator tmp;
00078 std::vector<std::pair<std::string,int> > first_pass;
00079 for(tmp=first_split.begin();tmp != first_split.end() ; tmp++) {
00080 std::vector<std::string> second_pass = utils::split(*tmp,':');
00081 if(second_pass.size() > 1) {
00082 first_pass.push_back(std::pair<std::string,int>(second_pass[0],atoi(second_pass[1].c_str())));
00083 } else {
00084 first_pass.push_back(std::pair<std::string,int>(second_pass[0],time_chunk));
00085 }
00086 }
00087 std::vector<std::pair<std::string,int> >::const_iterator tmp2;
00088 for(tmp2=first_pass.begin();tmp2 != first_pass.end() ; tmp2++) {
00089 std::vector<std::string> range = utils::split(tmp2->first,'~');
00090 data_.push_back(std::pair<std::pair<T, T>,int> (
00091 std::pair<T, T>(
00092 lexical_cast<T>(range[0].c_str()),
00093 lexical_cast<T>(range.size() > 1 ? range[1].c_str() : range[0].c_str())),
00094 tmp2->second));
00095 }
00096
00097 }
00098
00099 template <class T>
00100 const T progressive_<T>::get_current_element(int current_time, T default_val) const
00101 {
00102 int time = 0;
00103 unsigned int sub_halo = 0;
00104 int searched_time = current_time;
00105 if(searched_time < 0) searched_time = 0;
00106 if(searched_time > duration()) searched_time = duration();
00107 if(data_.empty()) return default_val;
00108 while(time < searched_time&& sub_halo < data_.size()) {
00109 time += data_[sub_halo].second;
00110 sub_halo++;
00111
00112 }
00113 if(sub_halo != 0) {
00114 sub_halo--;
00115 time -= data_[sub_halo].second;
00116 }
00117 if(sub_halo >= data_.size()) {
00118 sub_halo = data_.size();
00119 time = searched_time;
00120 }
00121
00122 const T first = data_[sub_halo].first.first;
00123 const T second = data_[sub_halo].first.second;
00124
00125 return T((static_cast<double>(searched_time - time) /
00126 static_cast<double>(data_[sub_halo].second)) *
00127 (second - first) + first);
00128 }
00129
00130 template<class T>
00131 int progressive_<T>::duration() const
00132 {
00133 int total = 0;
00134 typename std::vector<std::pair<std::pair<T, T>, int> >::const_iterator cur_halo;
00135 for(cur_halo = data_.begin() ; cur_halo != data_.end() ; cur_halo++) {
00136 total += cur_halo->second;
00137 }
00138 return total;
00139
00140 }
00141
00142 template <class T>
00143 bool progressive_<T>::does_not_change() const
00144 {
00145 return data_.empty() ||
00146 ( data_.size() == 1 && data_[0].first.first == data_[0].first.second);
00147 }
00148
00149
00150 template class progressive_<int>;
00151 template class progressive_<double>;
00152
00153 #undef UNIT_FRAME_H_PART2
00154 #include "unit_frame.hpp"
00155
00156
00157
00158 frame_builder::frame_builder(const config& cfg,const std::string& frame_string)
00159 {
00160 image(image::locator(cfg[frame_string+"image"]),cfg[frame_string+"image_mod"]);
00161 image_diagonal(image::locator(cfg[frame_string+"image_diagonal"]),cfg[frame_string+"image_mod"]);
00162 sound(cfg[frame_string+"sound"]);
00163 std::vector<std::string> tmp_string_vect=utils::split(cfg[frame_string+"text_color"]);
00164 if(tmp_string_vect.size() ==3) {
00165 text(cfg[frame_string+"text"],
00166 display::rgb(atoi(tmp_string_vect[0].c_str()),atoi(tmp_string_vect[1].c_str()),atoi(tmp_string_vect[2].c_str())));
00167 } else {
00168 text(cfg[frame_string+"text"],0);
00169 }
00170
00171 if(!cfg[frame_string+"duration"].empty()) {
00172 duration(atoi(cfg[frame_string+"duration"].c_str()));
00173 } else {
00174 duration(atoi(cfg[frame_string+"end"].c_str()) - atoi(cfg[frame_string+"begin"].c_str()));
00175 }
00176 halo(cfg[frame_string+"halo"],cfg[frame_string+"halo_x"],cfg[frame_string+"halo_y"]);
00177 tmp_string_vect=utils::split(cfg[frame_string+"blend_color"]);
00178 if(tmp_string_vect.size() ==3) {
00179 blend(cfg[frame_string+"blend_ratio"],display::rgb(atoi(tmp_string_vect[0].c_str()),atoi(tmp_string_vect[1].c_str()),atoi(tmp_string_vect[2].c_str())));
00180 } else {
00181 blend(cfg[frame_string+"blend_ratio"],0);
00182 }
00183 highlight(cfg[frame_string+"alpha"]);
00184 offset(cfg[frame_string+"offset"]);
00185 submerge(cfg[frame_string+"submerge"]);
00186 x(cfg[frame_string+"x"]);
00187 y(cfg[frame_string+"y"]);
00188
00189 }
00190
00191 const frame_parameters frame_builder::parameters(int current_time) const
00192 {
00193 frame_parameters result;
00194 result.duration = duration_;
00195 result.image = image_;
00196 result.image_diagonal = image_diagonal_;
00197 result.image_mod = image_mod_;
00198 result.halo = halo_.get_current_element(current_time);
00199 result.halo_x = halo_x_.get_current_element(current_time);
00200 result.halo_y = halo_y_.get_current_element(current_time);
00201 result.sound = sound_;
00202 result.text = text_;
00203 result.text_color = text_color_;
00204 result.blend_with = blend_with_;
00205 result.blend_ratio = blend_ratio_.get_current_element(current_time);
00206 result.highlight_ratio = highlight_ratio_.get_current_element(current_time,1.0);
00207 result.offset = offset_.get_current_element(current_time);
00208 result.submerge = submerge_.get_current_element(current_time);
00209 result.x = x_.get_current_element(current_time);
00210 result.y = y_.get_current_element(current_time);
00211 return result;
00212 }
00213 frame_builder & frame_builder::image(const image::locator image ,const std::string & image_mod)
00214 {
00215 image_ = image;
00216 image_mod_ = image_mod;
00217 return *this;
00218 }
00219 frame_builder & frame_builder::image_diagonal(const image::locator image_diagonal,const std::string& image_mod)
00220 {
00221 image_diagonal_ = image_diagonal;
00222 image_mod_ = image_mod;
00223 return *this;
00224 }
00225 frame_builder & frame_builder::sound(const std::string& sound)
00226 {
00227 sound_=sound;
00228 return *this;
00229 }
00230 frame_builder & frame_builder::text(const std::string& text,const Uint32 text_color)
00231 {
00232 text_=text;
00233 text_color_=text_color;
00234 return *this;
00235 }
00236 frame_builder & frame_builder::halo(const std::string &halo, const std::string &halo_x, const std::string& halo_y)
00237 {
00238 halo_ = progressive_string(halo,duration_);
00239 halo_x_ = progressive_int(halo_x,duration_);
00240 halo_y_ = progressive_int(halo_y,duration_);
00241 return *this;
00242 }
00243 frame_builder & frame_builder::duration(const int duration)
00244 {
00245 duration_= duration;
00246 recalculate_duration();
00247 return *this;
00248 }
00249 void frame_builder::recalculate_duration()
00250 {
00251 halo_ = progressive_string(halo_.get_original(),duration_);
00252 halo_x_ = progressive_int(halo_x_.get_original(),duration_);
00253 halo_y_ = progressive_int(halo_y_.get_original(),duration_);
00254 blend_ratio_=progressive_double(blend_ratio_.get_original(),duration_);
00255 highlight_ratio_=progressive_double(highlight_ratio_.get_original(),duration_);
00256 offset_=progressive_double(offset_.get_original(),duration_);
00257 submerge_=progressive_double(submerge_.get_original(),duration_);
00258 x_=progressive_int(x_.get_original(),duration_);
00259 y_=progressive_int(y_.get_original(),duration_);
00260 }
00261 frame_builder & frame_builder::blend(const std::string& blend_ratio,const Uint32 blend_color)
00262 {
00263 blend_with_=blend_color;
00264 blend_ratio_=progressive_double(blend_ratio,duration_);
00265 return *this;
00266 }
00267 frame_builder & frame_builder::highlight(const std::string& highlight)
00268 {
00269 highlight_ratio_=progressive_double(highlight,duration_);
00270 return *this;
00271 }
00272 frame_builder & frame_builder::offset(const std::string& offset)
00273 {
00274 offset_=progressive_double(offset,duration_);
00275 return *this;
00276 }
00277 frame_builder & frame_builder::submerge(const std::string& submerge)
00278 {
00279 submerge_=progressive_double(submerge,duration_);
00280 return *this;
00281 }
00282 frame_builder & frame_builder::x(const std::string& x)
00283 {
00284 x_=progressive_int(x,duration_);
00285 return *this;
00286 }
00287 frame_builder & frame_builder::y(const std::string& y)
00288 {
00289 y_=progressive_int(y,duration_);
00290 return *this;
00291 }
00292 bool frame_builder::does_not_change() const
00293 {
00294 return halo_.does_not_change() &&
00295 halo_x_.does_not_change() &&
00296 halo_y_.does_not_change() &&
00297 blend_ratio_.does_not_change() &&
00298 highlight_ratio_.does_not_change() &&
00299 offset_.does_not_change() &&
00300 submerge_.does_not_change() &&
00301 x_.does_not_change() &&
00302 y_.does_not_change();
00303 }
00304 bool frame_builder::need_update() const
00305 {
00306 if(!halo_.does_not_change() ||
00307 !halo_x_.does_not_change() ||
00308 !halo_y_.does_not_change() ||
00309 !blend_ratio_.does_not_change() ||
00310 !highlight_ratio_.does_not_change() ||
00311 !offset_.does_not_change() ||
00312 !submerge_.does_not_change() ||
00313 !x_.does_not_change() ||
00314 !y_.does_not_change() ) {
00315 return true;
00316 }
00317 return false;
00318 }
00319
00320 void unit_frame::redraw(const int frame_time,bool first_time,const gamemap::location & src,const gamemap::location & dst,int*halo_id,const frame_parameters & animation_val,const frame_parameters & engine_val)const
00321 {
00322 const int xsrc = game_display::get_singleton()->get_location_x(src);
00323 const int ysrc = game_display::get_singleton()->get_location_y(src);
00324 const int xdst = game_display::get_singleton()->get_location_x(dst);
00325 const int ydst = game_display::get_singleton()->get_location_y(dst);
00326 const gamemap::location::DIRECTION direction = src.get_relative_dir(dst);
00327
00328 const frame_parameters current_data = merge_parameters(frame_time,animation_val,engine_val);
00329 double tmp_offset = current_data.offset;
00330 int d2 = game_display::get_singleton()->hex_size() / 2;
00331
00332 if(first_time ) {
00333
00334 if(!current_data.sound.empty() ) {
00335 sound::play_sound(current_data.sound);
00336 }
00337 if(!current_data.text.empty() ) {
00338 game_display::get_singleton()->float_label(src,current_data.text,
00339 (current_data.text_color & 0x00FF0000) >> 16,
00340 (current_data.text_color & 0x0000FF00) >> 8,
00341 (current_data.text_color & 0x000000FF) >> 0);
00342 }
00343 }
00344 image::locator image_loc;
00345 if(direction != gamemap::location::NORTH && direction != gamemap::location::SOUTH) {
00346 image_loc = image::locator(current_data.image_diagonal,current_data.image_mod);
00347 }
00348 if(image_loc.is_void() || image_loc.get_filename() == "") {
00349 image_loc = image::locator(current_data.image,current_data.image_mod);
00350 }
00351
00352 surface image;
00353 if(!image_loc.is_void() && image_loc.get_filename() != "") {
00354 image=image::get_image(image_loc,
00355 image::SCALED_TO_ZOOM,
00356 false
00357 );
00358 }
00359 const int x = static_cast<int>(tmp_offset * xdst + (1.0-tmp_offset) * xsrc) + d2;
00360 const int y = static_cast<int>(tmp_offset * ydst + (1.0-tmp_offset) * ysrc) + d2;
00361 if (image != NULL) {
00362 bool facing_west = direction == gamemap::location::NORTH_WEST || direction == gamemap::location::SOUTH_WEST;
00363 bool facing_north = direction == gamemap::location::NORTH_WEST || direction == gamemap::location::NORTH || direction == gamemap::location::NORTH_EAST;
00364 game_display::get_singleton()->render_unit_image(x + current_data.x- image->w/2,
00365 y + current_data.y- image->h/2, false,
00366 gamemap::get_drawing_order(src), image, facing_west, false,
00367 ftofxp(current_data.highlight_ratio), current_data.blend_with,
00368 current_data.blend_ratio,current_data.submerge,!facing_north);
00369 }
00370 halo::remove(*halo_id);
00371 *halo_id = halo::NO_HALO;
00372 if(!current_data.halo.empty()) {
00373 halo::ORIENTATION orientation;
00374 switch(direction)
00375 {
00376 case gamemap::location::NORTH:
00377 case gamemap::location::NORTH_EAST:
00378 orientation = halo::NORMAL;
00379 break;
00380 case gamemap::location::SOUTH_EAST:
00381 case gamemap::location::SOUTH:
00382 orientation = halo::VREVERSE;
00383 break;
00384 case gamemap::location::SOUTH_WEST:
00385 orientation = halo::HVREVERSE;
00386 break;
00387 case gamemap::location::NORTH_WEST:
00388 orientation = halo::HREVERSE;
00389 break;
00390 case gamemap::location::NDIRECTIONS:
00391 default:
00392 orientation = halo::NORMAL;
00393 break;
00394 }
00395 if(direction != gamemap::location::SOUTH_WEST && direction != gamemap::location::NORTH_WEST) {
00396 *halo_id = halo::add(static_cast<int>(x+current_data.halo_x* game_display::get_singleton()->get_zoom_factor()),
00397 static_cast<int>(y+current_data.halo_y* game_display::get_singleton()->get_zoom_factor()),
00398 current_data.halo,
00399 gamemap::location(-1, -1),
00400 orientation);
00401 } else {
00402 *halo_id = halo::add(static_cast<int>(x-current_data.halo_x* game_display::get_singleton()->get_zoom_factor()),
00403 static_cast<int>(y+current_data.halo_y* game_display::get_singleton()->get_zoom_factor()),
00404 current_data.halo,
00405 gamemap::location(-1, -1),
00406 orientation);
00407 }
00408 }
00409 }
00410 void unit_frame::invalidate(const int frame_time,const gamemap::location & src,const gamemap::location & dst,const frame_parameters & animation_val,const frame_parameters & engine_val,const bool primary) const
00411 {
00412 const int xsrc = game_display::get_singleton()->get_location_x(src);
00413 const int ysrc = game_display::get_singleton()->get_location_y(src);
00414 const int xdst = game_display::get_singleton()->get_location_x(dst);
00415 const int ydst = game_display::get_singleton()->get_location_y(dst);
00416 const gamemap::location::DIRECTION direction = src.get_relative_dir(dst);
00417
00418 const frame_parameters current_data = merge_parameters(frame_time,animation_val,engine_val,primary);
00419 double tmp_offset = current_data.offset;
00420
00421
00422 image::locator image_loc;
00423 if(direction != gamemap::location::NORTH && direction != gamemap::location::SOUTH) {
00424 image_loc = current_data.image_diagonal;
00425 }
00426 if(image_loc.is_void() || image_loc.get_filename() == "") {
00427 image_loc = current_data.image;
00428 }
00429
00430 surface image;
00431 if(!image_loc.is_void() && image_loc.get_filename() != "") {
00432
00433
00434
00435
00436 image=image::get_image(image_loc,
00437 image::SCALED_TO_ZOOM,
00438 false
00439 );
00440 }
00441 const int x = static_cast<int>(tmp_offset * xdst + (1.0-tmp_offset) * xsrc)+current_data.x;
00442 const int y = static_cast<int>(tmp_offset * ydst + (1.0-tmp_offset) * ysrc)+current_data.y;
00443 if (image != NULL) {
00444
00445 if(x==xsrc && y == ysrc &&
00446 image->w == game_display::get_singleton()->hex_size() &&
00447 image->h == game_display::get_singleton()->hex_size()) {
00448
00449 game_display::get_singleton()->invalidate(src);
00450 } else {
00451 game_display::get_singleton()->invalidate_zone(x,y,x+image->w,y+image->h);
00452 }
00453
00454 }
00455 }
00456
00457
00458
00459 const frame_parameters unit_frame::merge_parameters(int current_time,const frame_parameters & animation_val,const frame_parameters & engine_val, bool primary) const
00460 {
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 frame_parameters result;
00471 const frame_parameters & current_val = builder_.parameters(current_time);
00472 assert(engine_val.image.is_void() || engine_val.image.get_filename() == "");
00473 result.image = current_val.image.is_void() || current_val.image.get_filename() == ""?animation_val.image:current_val.image;
00474
00475 assert(engine_val.image_diagonal.is_void() || engine_val.image_diagonal.get_filename() == "");
00476 result.image_diagonal = current_val.image_diagonal.is_void()|| current_val.image_diagonal.get_filename() == ""?animation_val.image_diagonal:current_val.image_diagonal;
00477
00478 result.image_mod = engine_val.image_mod + current_val.image_mod +animation_val.image_mod;
00479
00480 assert(engine_val.halo.empty());
00481 result.halo = current_val.halo.empty()?animation_val.halo:current_val.halo;
00482
00483 assert(engine_val.halo_x == 0);
00484 result.halo_x = current_val.halo_x?current_val.halo_x:animation_val.halo_x;
00485
00486 result.halo_y = current_val.halo_y?current_val.halo_y:animation_val.halo_y;
00487 result.halo_y += engine_val.halo_y;
00488
00489 assert(engine_val.duration == 0);
00490 result.duration = current_val.duration;
00491
00492 assert(engine_val.sound.empty());
00493 result.sound = current_val.sound.empty()?animation_val.sound:current_val.sound;
00494
00495 assert(engine_val.text.empty());
00496 result.text = current_val.text.empty()?animation_val.text:current_val.text;
00497
00498 assert(engine_val.text_color == 0);
00499 result.text_color = current_val.text_color?current_val.text_color:animation_val.text_color;
00500
00501 result.blend_with = current_val.blend_with?current_val.blend_with:animation_val.blend_with;
00502 if(primary&& engine_val.blend_with) result.blend_with = engine_val.blend_with;
00503
00504 result.blend_ratio = current_val.blend_ratio?current_val.blend_ratio:animation_val.blend_ratio;
00505 if(primary && engine_val.blend_ratio) result.blend_ratio += engine_val.blend_ratio;
00506
00507 result.highlight_ratio = current_val.highlight_ratio!=1.0?current_val.highlight_ratio:animation_val.highlight_ratio;
00508 if(primary && engine_val.highlight_ratio != 1.0) result.highlight_ratio = result.highlight_ratio +engine_val.highlight_ratio - 1.0;
00509
00510 assert(engine_val.offset == 0);
00511 result.offset = current_val.offset?current_val.offset:animation_val.offset;
00512
00513 result.submerge = current_val.submerge?current_val.submerge:animation_val.submerge;
00514 if(primary && engine_val.submerge) result.submerge = engine_val.submerge;
00515
00516 assert(engine_val.x == 0);
00517 result.x = current_val.x?current_val.x:animation_val.x;
00518
00519 result.y = current_val.y?current_val.y:animation_val.y;
00520 result.y += engine_val.y;
00521
00522 return result;
00523 }