void unit::redraw_unit() { if (!loc_.valid()) { return; } if (refreshing_) { return; } trefreshing_lock lock(*this); redraw_counter_ ++; const int xsrc = disp_.get_location_x(loc_); const int ysrc = disp_.get_location_y(loc_); int zoom = disp_.hex_width(); surface surf = create_neutral_surface(zoom, zoom); if (surf) { disp_.drawing_buffer_add(display::LAYER_UNIT_DEFAULT, loc_, xsrc, ysrc, surf); } int ellipse_floating = 0; if (loc_ == controller_.selected_hex()) { disp_.drawing_buffer_add(display::LAYER_UNIT_BG, loc_, xsrc, ysrc - ellipse_floating, image::get_image("misc/ellipse-top.png", image::SCALED_TO_ZOOM)); disp_.drawing_buffer_add(display::LAYER_UNIT_FIRST, loc_, xsrc, ysrc - ellipse_floating, image::get_image("misc/ellipse-bottom.png", image::SCALED_TO_ZOOM)); } }
sdl::timage draw_text_to_texture(const SDL_Rect &area, int size, const SDL_Color &color, const std::string &text, bool use_tooltips, int style) { SDL_Rect rect = text_area(text, size, style); surface surf = create_neutral_surface(rect.w, rect.h); draw_text(surf, area, size, color, text, 0, 0, use_tooltips, style); return sdl::timage(surf); }
surface mask_modification::operator()(const surface& src) const { if(src->w == mask_->w && src->h == mask_->h && x_ == 0 && y_ == 0) return mask_surface(src, mask_); SDL_Rect r = create_rect(x_, y_, 0, 0); surface new_mask = create_neutral_surface(src->w, src->h); blit_surface(mask_, NULL, new_mask, &r); return mask_surface(src, new_mask); }
void mouse_action::set_terrain_mouse_overlay(editor_display& disp, const t_translation::t_terrain & fg, const t_translation::t_terrain & bg) { surface image_fg(image::get_image(disp.get_map().get_terrain_info(fg).editor_image())); surface image_bg(image::get_image(disp.get_map().get_terrain_info(bg).editor_image())); if (image_fg == nullptr || image_bg == nullptr) { ERR_ED << "Missing terrain icon" << std::endl; disp.set_mouseover_hex_overlay(nullptr); return; } // Create a transparent surface of the right size. surface image = create_neutral_surface(image_fg->w, image_fg->h); // For efficiency the size of the tile is cached. // We assume all tiles are of the same size. // The zoom factor can change, so it's not cached. // NOTE: when zooming and not moving the mouse, there are glitches. // Since the optimal alpha factor is unknown, it has to be calculated // on the fly, and caching the surfaces makes no sense yet. static const fixed_t alpha = 196; static const int size = image_fg->w; static const int half_size = size / 2; static const int quarter_size = size / 4; static const int offset = 2; static const int new_size = half_size - 2; // Blit left side image_fg = scale_surface(image_fg, new_size, new_size); SDL_Rect rcDestLeft = sdl::create_rect(offset, quarter_size, 0, 0); blit_surface ( image_fg, nullptr, image, &rcDestLeft ); // Blit right side image_bg = scale_surface(image_bg, new_size, new_size); SDL_Rect rcDestRight = sdl::create_rect(half_size, quarter_size, 0, 0); blit_surface ( image_bg, nullptr, image, &rcDestRight ); //apply mask so the overlay is contained within the mouseover hex image = mask_surface(image, image::get_hexmask()); // Add the alpha factor image = adjust_surface_alpha(image, alpha); // scale the image const int zoom = disp.hex_size(); if (zoom != game_config::tile_size) { image = scale_surface(image, zoom, zoom); } // Set as mouseover disp.set_mouseover_hex_overlay(image); }
void mouse_action_village::set_mouse_overlay(editor_display& disp) { surface image60 = image::get_image("icons/action/editor-tool-village_60.png"); //TODO avoid hardcoded hex field size surface image = create_neutral_surface(72,72); SDL_Rect r = sdl::create_rect(6, 6, 0, 0); blit_surface(image60, NULL, image, &r); Uint8 alpha = 196; int size = image->w; int zoom = static_cast<int>(size * disp.get_zoom_factor()); // Add the alpha factor and scale the image image = scale_surface(adjust_surface_alpha(image, alpha), zoom, zoom); disp.set_mouseover_hex_overlay(image); }
void part_ui::prepare_background() { // Build background surface if(p_.background().empty() != true) { background_.assign( image::get_image(p_.background()) ); } has_background_ = !background_.null(); if(background_.null() || background_->w * background_-> h == 0) { background_.assign( create_neutral_surface(video_.getx(), video_.gety()) ); } const double xscale = 1.0 * video_.getx() / background_->w; const double yscale = 1.0 * video_.gety() / background_->h; scale_factor_ = p_.scale_background() ? std::min<double>(xscale,yscale) : 1.0; background_ = scale_surface(background_, static_cast<int>(background_->w*scale_factor_), static_cast<int>(background_->h*scale_factor_)); ASSERT_LOG(background_.null() == false, "Oops: storyscreen part background got NULL"); }
surface getMinimap(int w, int h, const gamemap &map, const team *vw) { const int scale = 8; DBG_DP << "creating minimap " << int(map.w()*scale*0.75) << "," << map.h()*scale << "\n"; const size_t map_width = map.w()*scale*3/4; const size_t map_height = map.h()*scale; if(map_width == 0 || map_height == 0) { return surface(NULL); } surface minimap(create_neutral_surface(map_width, map_height)); if(minimap == NULL) return surface(NULL); typedef mini_terrain_cache_map cache_map; cache_map *normal_cache = &mini_terrain_cache; cache_map *fog_cache = &mini_fogged_terrain_cache; for(int y = 0; y != map.total_height(); ++y) { for(int x = 0; x != map.total_width(); ++x) { surface surf(NULL); const map_location loc(x,y); if(map.on_board(loc)) { const bool shrouded = (vw != NULL && vw->shrouded(loc)); // shrouded hex are not considered fogged (no need to fog a black image) const bool fogged = (vw != NULL && !shrouded && vw->fogged(loc)); const t_translation::t_terrain terrain = shrouded ? t_translation::VOID_TERRAIN : map[loc]; const terrain_type& terrain_info = map.get_terrain_info(terrain); bool need_fogging = false; cache_map* cache = fogged ? fog_cache : normal_cache; cache_map::iterator i = cache->find(terrain); if (fogged && i == cache->end()) { // we don't have the fogged version in cache // try the normal cache and ask fogging the image cache = normal_cache; i = cache->find(terrain); need_fogging = true; } if(i == cache->end()) { std::string base_file = "terrain/" + terrain_info.minimap_image() + ".png"; surface tile = get_image(base_file,image::HEXED); //Compose images of base and overlay if necessary // NOTE we also skip overlay when base is missing (to avoid hiding the error) if(tile != NULL && map.get_terrain_info(terrain).is_combined()) { std::string overlay_file = "terrain/" + terrain_info.minimap_image_overlay() + ".png"; surface overlay = get_image(overlay_file,image::HEXED); if(overlay != NULL && overlay != tile) { surface combined = create_neutral_surface(tile->w, tile->h); SDL_Rect r = create_rect(0,0,0,0); sdl_blit(tile, NULL, combined, &r); r.x = std::max(0, (tile->w - overlay->w)/2); r.y = std::max(0, (tile->h - overlay->h)/2); //blit_surface needs neutral surface surface overlay_neutral = make_neutral_surface(overlay); blit_surface(overlay_neutral, NULL, combined, &r); tile = combined; } } surf = scale_surface_sharp(tile, scale, scale); i = normal_cache->insert(cache_map::value_type(terrain,surf)).first; } surf = i->second; if (need_fogging) { surf = adjust_surface_color(surf,-50,-50,-50); fog_cache->insert(cache_map::value_type(terrain,surf)); } // we need a balanced shift up and down of the hexes. // if not, only the bottom half-hexes are clipped // and it looks asymmetrical. // also do 1-pixel shift because the scaling // function seems to do it with its rounding SDL_Rect maprect = create_rect( x * scale * 3 / 4 - 1 , y * scale + scale / 4 * (is_odd(x) ? 1 : -1) - 1 , 0 , 0); if(surf != NULL) sdl_blit(surf, NULL, minimap, &maprect); } } } double wratio = w*1.0 / minimap->w; double hratio = h*1.0 / minimap->h; double ratio = std::min<double>(wratio, hratio); minimap = scale_surface_sharp(minimap, static_cast<int>(minimap->w * ratio), static_cast<int>(minimap->h * ratio)); DBG_DP << "done generating minimap\n"; return minimap; }
void battle_prediction_pane::get_hp_distrib_surface(const std::vector<std::pair<int, double> >& hp_prob_vector, const battle_context_unit_stats& stats, const battle_context_unit_stats& opp_stats, surface& surf, int& width, int& height) { // Font size. If you change this, you must update the separator space. int fs = font::SIZE_SMALL; // Space before HP separator. int hp_sep = 24 + 6; // Bar space between both separators. int bar_space = 150; // Space after percentage separator. int percent_sep = 43 + 6; // Surface width and height. width = 30 + 2 + bar_space + 2 + percent_sep; height = 5 + (fs + 2) * hp_prob_vector.size(); // Create the surface. surf = create_neutral_surface(width, height); // Disable alpha channel to avoid problem with sdl_blit SDL_SetAlpha(surf, 0, SDL_ALPHA_OPAQUE); SDL_Rect clip_rect = sdl::create_rect(0, 0, width, height); Uint32 grey_color = SDL_MapRGBA(surf->format, 0xb7, 0xc1, 0xc1, 255); Uint32 background_color = SDL_MapRGBA(surf->format, 25, 25, 25, 255); sdl::fill_rect(surf, &clip_rect, background_color); // Draw the surrounding borders and separators. SDL_Rect top_border_rect = sdl::create_rect(0, 0, width, 2); sdl::fill_rect(surf, &top_border_rect, grey_color); SDL_Rect bottom_border_rect = sdl::create_rect(0, height - 2, width, 2); sdl::fill_rect(surf, &bottom_border_rect, grey_color); SDL_Rect left_border_rect = sdl::create_rect(0, 0, 2, height); sdl::fill_rect(surf, &left_border_rect, grey_color); SDL_Rect right_border_rect = sdl::create_rect(width - 2, 0, 2, height); sdl::fill_rect(surf, &right_border_rect, grey_color); SDL_Rect hp_sep_rect = sdl::create_rect(hp_sep, 0, 2, height); sdl::fill_rect(surf, &hp_sep_rect, grey_color); SDL_Rect percent_sep_rect = sdl::create_rect(width - percent_sep - 2, 0, 2, height); sdl::fill_rect(surf, &percent_sep_rect, grey_color); // Draw the rows (lower HP values are at the bottom). for(int i = 0; i < static_cast<int>(hp_prob_vector.size()); i++) { char str_buf[10]; // Get the HP and probability. int hp = hp_prob_vector[hp_prob_vector.size() - i - 1].first; double prob = hp_prob_vector[hp_prob_vector.size() - i - 1].second; SDL_Color row_color; // Death line is red. if(hp == 0) { SDL_Color color = {0xe5, 0, 0, 0}; row_color = color; } // Below current hitpoints value is orange. else if(hp < static_cast<int>(stats.hp)) { // Stone is grey. if(opp_stats.petrifies) { SDL_Color color = {0x9a, 0x9a, 0x9a, 0}; row_color = color; } else { SDL_Color color = {0xf4, 0xc9, 0, 0}; row_color = color; } } // Current hitpoints value and above is green. else { SDL_Color color = {0x08, 0xca, 0, 0}; row_color = color; } // Print HP, aligned right. snprintf(str_buf, 10, "%d", hp); str_buf[9] = '\0'; //prevents _snprintf error int hp_width = font::line_width(str_buf, fs); // Draw bars. font::draw_text_line(surf, clip_rect, fs, font::NORMAL_COLOR, str_buf, hp_sep - hp_width - 2, 2 + (fs + 2) * i, 0, TTF_STYLE_NORMAL); int bar_len = std::max<int>(static_cast<int>((prob * (bar_space - 4)) + 0.5), 2); SDL_Rect bar_rect_1 = sdl::create_rect(hp_sep + 4, 6 + (fs + 2) * i, bar_len, 8); sdl::fill_rect(surf, &bar_rect_1, blend_rgb(surf, row_color.r, row_color.g, row_color.b, 100)); SDL_Rect bar_rect_2 = sdl::create_rect(hp_sep + 4, 7 + (fs + 2) * i, bar_len, 6); sdl::fill_rect(surf, &bar_rect_2, blend_rgb(surf, row_color.r, row_color.g, row_color.b, 66)); SDL_Rect bar_rect_3 = sdl::create_rect(hp_sep + 4, 8 + (fs + 2) * i, bar_len, 4); sdl::fill_rect(surf, &bar_rect_3, blend_rgb(surf, row_color.r, row_color.g, row_color.b, 33)); SDL_Rect bar_rect_4 = sdl::create_rect(hp_sep + 4, 9 + (fs + 2) * i, bar_len, 2); sdl::fill_rect(surf, &bar_rect_4, blend_rgb(surf, row_color.r, row_color.g, row_color.b, 0)); // Draw probability percentage, aligned right. format_prob(str_buf, prob); int prob_width = font::line_width(str_buf, fs); font::draw_text_line(surf, clip_rect, fs, font::NORMAL_COLOR, str_buf, width - prob_width - 4, 2 + (fs + 2) * i, 0, TTF_STYLE_NORMAL); } }
void timage::draw(surface& canvas , const game_logic::map_formula_callable& variables) { DBG_GUI_D << "Image: draw.\n"; /** * @todo formulas are now recalculated every draw cycle which is a bit * silly unless there has been a resize. So to optimize we should use an * extra flag or do the calculation in a separate routine. */ const std::string& name = image_name_(variables); if(name.empty()) { DBG_GUI_D << "Image: formula returned no value, will not be drawn.\n"; return; } /* * The locator might return a different surface for every call so we can't * cache the output, also not if no formula is used. */ surface tmp(image::get_image(image::locator(name))); if(!tmp) { ERR_GUI_D << "Image: '" << name << "' not found and won't be drawn.\n"; return; } image_.assign(make_neutral_surface(tmp)); assert(image_); src_clip_ = ::create_rect(0, 0, image_->w, image_->h); game_logic::map_formula_callable local_variables(variables); local_variables.add("image_original_width", variant(image_->w)); local_variables.add("image_original_height", variant(image_->h)); unsigned w = w_(local_variables); VALIDATE_WITH_DEV_MESSAGE( static_cast<int>(w) >= 0 , _("Image doesn't fit on canvas.") , (formatter() << "Image '" << name << "', w = " << static_cast<int>(w) << ".").str()); unsigned h = h_(local_variables); VALIDATE_WITH_DEV_MESSAGE( static_cast<int>(h) >= 0 , _("Image doesn't fit on canvas.") , (formatter() << "Image '" << name << "', h = " << static_cast<int>(h) << ".").str()); local_variables.add("image_width", variant(w ? w : image_->w)); local_variables.add("image_height", variant(h ? h : image_->h)); const unsigned x = x_(local_variables); VALIDATE_WITH_DEV_MESSAGE( static_cast<int>(x) >= 0 , _("Image doesn't fit on canvas.") , (formatter() << "Image '" << name << "', x = " << static_cast<int>(x) << ".").str()); const unsigned y = y_(local_variables); VALIDATE_WITH_DEV_MESSAGE( static_cast<int>(y) >= 0 , _("Image doesn't fit on canvas.") , (formatter() << "Image '" << name << "', y = " << static_cast<int>(y) << ".").str()); // Copy the data to local variables to avoid overwriting the originals. SDL_Rect src_clip = src_clip_; SDL_Rect dst_clip = ::create_rect(x, y, 0, 0); surface surf; // Test whether we need to scale and do the scaling if needed. if(w || h) { bool done = false; bool stretch_image = (resize_mode_ == stretch) && (!!w ^ !!h); if(!w) { if(stretch_image) { DBG_GUI_D << "Image: vertical stretch from " << image_->w << ',' << image_->h << " to a height of " << h << ".\n"; surf = stretch_surface_vertical(image_, h, false); done = true; } w = image_->w; } if(!h) { if(stretch_image) { DBG_GUI_D << "Image: horizontal stretch from " << image_->w << ',' << image_->h << " to a width of " << w << ".\n"; surf = stretch_surface_horizontal(image_, w, false); done = true; } h = image_->h; } if(!done) { if(resize_mode_ == tile) { DBG_GUI_D << "Image: tiling from " << image_->w << ',' << image_->h << " to " << w << ',' << h << ".\n"; const int columns = (w + image_->w - 1) / image_->w; const int rows = (h + image_->h - 1) / image_->h; surf = create_neutral_surface(w, h); for(int x = 0; x < columns; ++x) { for(int y = 0; y < rows; ++y) { const SDL_Rect dest = ::create_rect( x * image_->w , y * image_->h , 0 , 0); blit_surface(image_, NULL, surf, &dest); } } } else { if(resize_mode_ == stretch) { ERR_GUI_D << "Image: failed to stretch image, " "fall back to scaling.\n"; } DBG_GUI_D << "Image: scaling from " << image_->w << ',' << image_->h << " to " << w << ',' << h << ".\n"; surf = scale_surface(image_, w, h, false); } } src_clip.w = w; src_clip.h = h; } else { surf = image_; } if(vertical_mirror_(local_variables)) { surf = flip_surface(surf, false); } blit_surface(surf, &src_clip, canvas, &dst_clip); }
void part_ui::prepare_background() { #ifdef SDL_GPU base_rect_.w = video_.getx(); base_rect_.h = video_.gety(); has_background_ = false; bool no_base_yet = true; BOOST_FOREACH(const background_layer& bl, p_.get_background_layers()) { sdl::timage layer; if (!bl.file().empty()) { layer = image::get_texture(bl.file()); } has_background_ = has_background_ || !layer.null(); if(layer.null() || layer.width() * layer.height() == 0) { continue; } const double xscale = 1.0 * video_.getx() / layer.base_width(); const double yscale = 1.0 * video_.gety() / layer.base_height(); const bool scalev = bl.scale_vertically(); const bool scaleh = bl.scale_horizontally(); const bool keep_ratio = bl.keep_aspect_ratio(); const bool tileh = bl.tile_horizontally(); const bool tilev = bl.tile_vertically(); double x_scale_factor = scaleh ? xscale : 1.0; double y_scale_factor = scalev ? yscale : 1.0; if (scalev && scaleh && keep_ratio) { x_scale_factor = y_scale_factor = std::min<double>(xscale, yscale); } else if (keep_ratio && scaleh) { x_scale_factor = y_scale_factor = xscale; } else if (keep_ratio && scalev) { x_scale_factor = y_scale_factor = yscale; } layer.set_smooth_scaling(true); SDL_Rect clip = sdl::create_rect(0, 0, layer.base_width(), layer.base_height()); if (tileh) { clip.x = (layer.base_width() - video_.getx())/2; clip.w = video_.getx(); layer.set_hwrap(GPU_WRAP_REPEAT); } if (tilev) { clip.y = (layer.base_height() - video_.gety())/2; clip.h = video_.gety(); layer.set_vwrap(GPU_WRAP_REPEAT); } layer.set_clip(clip); layer.set_scale(x_scale_factor, y_scale_factor); SDL_Rect base_rect = sdl::create_rect( (video_.getx() - layer.width()) / 2 , (video_.gety() - layer.height()) / 2 , layer.width() , layer.height()); background_images_.push_back(layer); background_positions_.push_back(std::pair<int, int>(base_rect.x, base_rect.y)); if (bl.is_base_layer() || no_base_yet) { x_scale_factor_ = x_scale_factor; y_scale_factor_ = y_scale_factor; base_rect_ = base_rect; no_base_yet = false; } } #else background_.assign( create_neutral_surface(video_.getx(), video_.gety()) ); base_rect_.w = video_.getx(); base_rect_.h = video_.gety(); has_background_ = false; bool no_base_yet = true; // Build background surface BOOST_FOREACH(const background_layer& bl, p_.get_background_layers()) { surface layer; if(bl.file().empty() != true) { layer.assign( image::get_image(bl.file()) ); } has_background_ = has_background_ || !layer.null(); if(layer.null() || layer->w * layer->h == 0) { continue; } layer = make_neutral_surface(layer); const double xscale = 1.0 * video_.getx() / layer->w; const double yscale = 1.0 * video_.gety() / layer->h; const bool scalev = bl.scale_vertically(); const bool scaleh = bl.scale_horizontally(); const bool keep_ratio = bl.keep_aspect_ratio(); double x_scale_factor = scaleh ? xscale : 1.0; double y_scale_factor = scalev ? yscale : 1.0; if (scalev && scaleh && keep_ratio) { x_scale_factor = y_scale_factor = std::min<double>(xscale, yscale); } else if (keep_ratio && scaleh) { x_scale_factor = y_scale_factor = xscale; } else if (keep_ratio && scalev) { x_scale_factor = y_scale_factor = yscale; } layer = scale_surface(layer, static_cast<int>(layer->w*x_scale_factor), static_cast<int>(layer->h*y_scale_factor), false); const int tilew = bl.tile_horizontally() ? video_.getx() : layer->w; const int tileh = bl.tile_vertically() ? video_.gety() : layer->h; layer = tile_surface(layer, tilew, tileh, false); SDL_Rect drect = sdl::create_rect( (background_->w - layer->w) / 2 , (background_->h - layer->h) / 2 , layer->w , layer->h); SDL_Rect srect = sdl::create_rect( 0 , 0 , layer->w , layer->h); SDL_Rect base_rect = drect; // If we can't see the whole image anyways, we'll want to display the // top-middle area. if (drect.y < 0) { drect.y = 0; base_rect.y = 0; } if (drect.x < 0) { srect.x -= drect.x; drect.x = 0; } blit_surface(layer, &srect, background_, &drect); ASSERT_LOG(layer.null() == false, "Oops: a storyscreen part background layer got NULL"); if (bl.is_base_layer() || no_base_yet) { x_scale_factor_ = x_scale_factor; y_scale_factor_ = y_scale_factor; base_rect_ = base_rect; no_base_yet = false; } } #endif }
surface floating_label::create_surface() { if(surf_.null()) { font::pango_text text; text.set_foreground_color(color_); text.set_font_size(font_size_); text.set_maximum_width(width_ < 0 ? clip_rect_.w : width_); text.set_maximum_height(height_ < 0 ? clip_rect_.h : height_, true); // ignore last '\n' if(!text_.empty() && *(text_.rbegin()) == '\n') { text.set_text(std::string(text_.begin(), text_.end() - 1), use_markup_); } else { text.set_text(text_, use_markup_); } surface foreground = text.render(); if(foreground == nullptr) { ERR_FT << "could not create floating label's text" << std::endl; return nullptr; } // combine foreground text with its background if(bgalpha_ != 0) { // background is a dark tooltip box surface background = create_neutral_surface(foreground->w + border_ * 2, foreground->h + border_ * 2); if(background == nullptr) { ERR_FT << "could not create tooltip box" << std::endl; return surf_ = foreground; } uint32_t color = SDL_MapRGBA(foreground->format, bgcolor_.r, bgcolor_.g, bgcolor_.b, bgalpha_); sdl::fill_surface_rect(background, nullptr, color); // we make the text less transparent, because the blitting on the // dark background will darken the anti-aliased part. // This 1.13 value seems to restore the brightness of version 1.4 // (where the text was blitted directly on screen) adjust_surface_alpha(foreground, ftofxp(1.13)); SDL_Rect r{border_, border_, 0, 0}; adjust_surface_alpha(foreground, SDL_ALPHA_OPAQUE); sdl_blit(foreground, nullptr, background, &r); surf_ = background; } else { // background is blurred shadow of the text surface background = create_neutral_surface(foreground->w + 4, foreground->h + 4); sdl::fill_surface_rect(background, nullptr, 0); SDL_Rect r{2, 2, 0, 0}; sdl_blit(foreground, nullptr, background, &r); background = shadow_image(background); if(background == nullptr) { ERR_FT << "could not create floating label's shadow" << std::endl; return surf_ = foreground; } sdl_blit(foreground, nullptr, background, &r); surf_ = background; } } return surf_; }
/** * Show credits with list of contributors. * * Names of people are shown scrolling up like in movie-credits.\n * Uses map from wesnoth or campaign as background. */ void show_about(display &disp, std::string campaign) { cursor::set(cursor::WAIT); CVideo &video = disp.video(); // surface screen = video.getSurface(); // if (screen == NULL) return; std::vector<std::string> text = about::get_text(campaign); // SDL_Rect screen_rect = {0, 0, video.getx(), video.gety()}; // const surface_restorer restorer(&video, screen_rect); cursor::set(cursor::NORMAL); std::vector<shared_string> image_list; if(campaign.size() && !images[campaign].empty()){ image_list=utils::split_shared(images[campaign]); }else{ image_list=utils::split_shared(images_default,',',utils::STRIP_SPACES); } surface map_image(scale_surface(image::get_image(image_list[0]), video.getx(), video.gety())); if(! map_image){ image_list[0]=game_config::game_title; map_image=surface(scale_surface(image::get_image(image_list[0]), video.getx(), video.gety())); } gui::button close(video,_("Close")); close.set_location((video.getx()/2)-(close.width()/2), video.gety() - 30); close.set_volatile(true); const int def_size = font::SIZE_XLARGE; const SDL_Color def_color = font::NORMAL_COLOUR; //substitute in the correct control characters for '+' and '-' std::string before_header(2, ' '); before_header[0] = font::LARGE_TEXT; for(unsigned i = 0; i < text.size(); ++i) { std::string &s = text[i]; if (s.empty()) continue; char &first = s[0]; if (first == '-') first = font::SMALL_TEXT; else if (first == '+') { first = font::LARGE_TEXT; text.insert(text.begin() + i, before_header); ++i; } } text.insert(text.begin(), 10, before_header); int startline = 0; //TODO: use values proportionnal to screen ? // distance from top of map image to top of scrolling text const int top_margin = 60; // distance from bottom of scrolling text to bottom of map image const int bottom_margin = 40; // distance from left of scrolling text to the frame border const int text_left_padding = video.getx()/32; int offset = 0; bool is_new_line = true; int first_line_height = 0; SDL_Rect frame_area = { video.getx() * 3/32, top_margin, video.getx() * 13 / 16, video.gety() - top_margin - bottom_margin }; // we use a dialog to contains the text. Strange idea but at least the style // will be consistent with the titlescreen gui::dialog_frame f(video, "", gui::dialog_frame::titlescreen_style, false); // set the layout and get the interior rectangle SDL_Rect text_rect = f.layout(frame_area).interior; text_rect.x += text_left_padding; text_rect.w -= text_left_padding; // make a copy to prevent SDL_blit to change its w and h SDL_Rect text_rect_blit = text_rect; CKey key; bool last_escape; surface text_surf = create_neutral_surface(text_rect.w, text_rect.h); //create_compatible_surface(screen, text_rect.w, text_rect.h); SDL_SetAlpha(text_surf, SDL_RLEACCEL, SDL_ALPHA_OPAQUE); int image_count = 0; int scroll_speed = 4; // scroll_speed*50 = speed of scroll in pixel per second // initialy redraw all bool redraw_mapimage = true; int max_text_width = text_rect.w; do { last_escape = key[SDLK_ESCAPE] != 0; // check to see if background image has changed if(text.size() && (image_count < ((startline * static_cast<int>(image_list.size())) / static_cast<int>(text.size())))){ image_count++; surface temp=surface(scale_surface(image::get_image(image_list[image_count]), video.getx(), video.gety())); map_image=temp?temp:map_image; redraw_mapimage = true; } // if (redraw_mapimage) { // draw map to screen, thus erasing all text //SDL_BlitSurface(map_image, NULL, screen, NULL); blit_surface(0, 0, map_image); // update_rect(screen_rect); // redraw the dialog f.draw_background(); f.draw_border(); // cache the dialog background (alpha blending + blurred map) //SDL_BlitSurface(screen, &text_rect, text_surf, NULL); redraw_mapimage = false; } /* else { // redraw the saved part of the dialog where text scrolled // thus erasing all text SDL_Rect modified = {0,0, max_text_width, text_rect.h}; SDL_BlitSurface(text_surf, &modified, screen, &text_rect_blit); //update_rect(text_rect); } */ const int line_spacing = 5; int y = text_rect.y - offset; int line = startline; int cur_line = 0; max_text_width = 0; { // clip to keep text into the frame (thus the new code block) clip_rect_setter set_clip_rect(/*screen,*/ text_rect); do { // draw the text (with ellipsis if needed) // update the max_text_width for future cleaning int w = font::draw_text(&video, text_rect, def_size, def_color, text[line], text_rect.x, y).w; max_text_width = std::max<int>(max_text_width, w); // since the real drawing on screen is clipped, // we do a dummy one to get the height of the not clipped line. // (each time because special format characters may change it) const int line_height = font::draw_text(NULL, text_rect, def_size, def_color, text[line], 0,0).h; if(is_new_line) { is_new_line = false; first_line_height = line_height + line_spacing; } line++; if(size_t(line) > text.size()-1) line = 0; y += line_height + line_spacing; cur_line++; } while(y < text_rect.y + text_rect.h); } // performs the actual scrolling offset += scroll_speed; if (offset>=first_line_height) { offset -= first_line_height; is_new_line = true; startline++; if(size_t(startline) == text.size()){ startline = 0; image_count = -1; } } // handle events if (key[SDLK_UP] && scroll_speed < 20) { ++scroll_speed; } if (key[SDLK_DOWN] && scroll_speed > 0) { --scroll_speed; } events::pump(); events::raise_process_event(); events::raise_draw_event(); // flip screen and wait, so the text does not scroll too fast disp.flip(); disp.delay(20); } while(!close.pressed() && (last_escape || !key[SDLK_ESCAPE])); }
surface getMinimap(int w, int h, const gamemap &map, const team *vw) { const int scale = 8; DBG_DP << "creating minimap " << int(map.w()*scale*0.75) << "," << int(map.h()*scale) << "\n"; const size_t map_width = map.w()*scale*3/4; const size_t map_height = map.h()*scale; if(map_width == 0 || map_height == 0) { return surface(NULL); } surface minimap(create_neutral_surface(map_width, map_height)); if(minimap == NULL) return surface(NULL); typedef mini_terrain_cache_map cache_map; cache_map *normal_cache = &mini_terrain_cache; cache_map *fog_cache = &mini_fogged_terrain_cache; for(int y = 0; y != map.total_height(); ++y) { for(int x = 0; x != map.total_width(); ++x) { surface surf(NULL); const map_location loc(x,y); if(map.on_board(loc)) { const bool shrouded = vw != NULL && vw->shrouded(loc); // shrouded hex are not considered fogged (no need to fog a black image) const bool fogged = vw != NULL && !shrouded && vw->fogged(loc); const t_translation::t_terrain terrain = shrouded ? t_translation::VOID_TERRAIN : map[loc]; bool need_fogging = false; cache_map* cache = fogged ? fog_cache : normal_cache; cache_map::iterator i = cache->find(terrain); if (fogged && i == cache->end()) { // we don't have the fogged version in cache // try the normal cache and ask fogging the image cache = normal_cache; i = cache->find(terrain); need_fogging = true; } if(i == cache->end()) { surface tile(get_image("terrain/" + map.get_terrain_info(terrain).minimap_image() + ".png",image::HEXED)); if(tile == 0) { utils::string_map symbols; symbols["terrain"] = t_translation::write_terrain_code(terrain); const std::string msg = vgettext("Could not get image for terrain: $terrain.", symbols); VALIDATE(false, msg); } //Compose images of base and overlay if neccessary if(map.get_terrain_info(terrain).is_combined()) { surface overlay(get_image("terrain/" + map.get_terrain_info(terrain).minimap_image_overlay() + ".png", image::HEXED)); if(overlay != 0 && overlay != tile) { surface combined = create_compatible_surface(tile, tile->w, tile->h); SDL_Rect r; r.x = 0; r.y = 0; SDL_BlitSurface(tile, NULL, combined, &r); r.x = std::max(0, (tile->w - overlay->w)/2); r.y = std::max(0, (tile->h - overlay->h)/2); if ((overlay->flags & SDL_RLEACCEL) == 0) { blit_surface(overlay, NULL, combined, &r); } else { WRN_DP << map.get_terrain_info(terrain).minimap_image_overlay() << ".png overlay is RLE-encoded, creating a neutral surface\n"; surface overlay_neutral = make_neutral_surface(overlay); blit_surface(overlay_neutral, NULL, combined, &r); } tile = combined; } } surf = surface(scale_surface_blended(tile,scale,scale)); VALIDATE(surf != NULL, _("Error creating or aquiring an image.")); i = normal_cache->insert(cache_map::value_type(terrain,surf)).first; } surf = i->second; if (need_fogging) { surf = surface(adjust_surface_colour(surf,-50,-50,-50)); fog_cache->insert(cache_map::value_type(terrain,surf)); } VALIDATE(surf != NULL, _("Error creating or aquiring an image.")); // we need a balanced shift up and down of the hexes. // if not, only the bottom half-hexes are clipped // and it looks asymmetrical. // also do 1-pixel shift because the scaling // function seems to do it with its rounding SDL_Rect maprect = {x * scale*3/4 - 1, y*scale + scale/4 * (is_odd(x) ? 1 : -1) - 1, 0, 0}; SDL_BlitSurface(surf, NULL, minimap, &maprect); } } } double wratio = w*1.0 / minimap->w; double hratio = h*1.0 / minimap->h; double ratio = std::min<double>(wratio, hratio); minimap = scale_surface(minimap, static_cast<int>(minimap->w * ratio), static_cast<int>(minimap->h * ratio)); DBG_DP << "done generating minimap\n"; return minimap; }
void unit2::redraw_unit() { if (!loc_.valid()) { return; } if (refreshing_) { return; } trefreshing_lock lock(*this); const int xsrc = disp_.map_area().x + disp_.get_scroll_pixel_x(rect_.x); const int ysrc = disp_.map_area().y + disp_.get_scroll_pixel_y(rect_.y); surface surf = create_neutral_surface(rect_.w, rect_.h); if (type_ == WIDGET) { redraw_widget(xsrc, ysrc, rect_.w, rect_.h); } else if (type_ == WINDOW) { disp_.drawing_buffer_add(display::LAYER_UNIT_DEFAULT, loc_, xsrc, ysrc, image::get_image(image(), image::SCALED_TO_ZOOM)); if (!cell_.id.empty()) { surface text_surf = font::get_rendered_text2(cell_.id, -1, 10, font::BLACK_COLOR); disp_.drawing_buffer_add(display::LAYER_UNIT_DEFAULT, loc_, xsrc, ysrc + rect_.w / 2, text_surf); } } else if (type_ == COLUMN) { int x = (loc_.x - 1) * image::tile_size; blit_integer_surface(x, surf, 0, 0); } else if (type_ == ROW) { int y = (loc_.y - 1) * image::tile_size; blit_integer_surface(y, surf, 0, 0); } blit_integer_surface(map_index_, surf, 0, 12); if (type_ == WINDOW || type_ == WIDGET) { // // draw rectangle // Uint32 border_color = 0x00ff00ff; if (loc_ == controller_.selected_hex()) { border_color = 0x0000ffff; } else if (this == controller_.last_unit()) { border_color = 0xff0000ff; } surface_lock locker(surf); // draw the border for (unsigned i = 0; i < 2; i ++) { const unsigned left = 0 + i; const unsigned right = left + rect_.w - (i * 2) - 1; const unsigned top = 0 + i; const unsigned bottom = top + rect_.h - (i * 2) - 1; // top horizontal (left -> right) draw_line(surf, border_color, left, top, right, top, true); // right vertical (top -> bottom) draw_line(surf, border_color, right, top, right, bottom, true); // bottom horizontal (left -> right) draw_line(surf, border_color, left, bottom, right, bottom, true); // left vertical (top -> bottom) draw_line(surf, border_color, left, top, left, bottom, true); } } disp_.drawing_buffer_add(display::LAYER_UNIT_DEFAULT, loc_, xsrc, ysrc, surf); }