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 dialog_frame::draw_background() { if(auto_restore_) { clear_background(); // restorer_ = new surface_restorer(&video_, dim_.exterior); } if (dialog_style_.blur_radius) { //surface surf = ::get_surface_portion(video_.getSurface(), dim_.exterior); //surf = blur_surface(surf, dialog_style_.blur_radius, false); //SDL_BlitSurface(surf, NULL, video_.getSurface(), &dim_.exterior); // KP: fade instead of blur... SDL_SetRenderDrawColor(0, 0, 0, 0x80); SDL_RenderFill(&dim_.exterior); } if(bg_ == NULL) { ERR_DP << "could not find dialog background '" << dialog_style_.panel << "'\n"; return; } for(int i = 0; i < dim_.interior.w; i += bg_->w) { for(int j = 0; j < dim_.interior.h; j += bg_->h) { SDL_Rect src = {0,0,0,0}; src.w = std::min(dim_.interior.w - i, bg_->w); src.h = std::min(dim_.interior.h - j, bg_->h); SDL_Rect dst = src; dst.x = dim_.interior.x + i; dst.y = dim_.interior.y + j; //SDL_BlitSurface(bg_, &src, video_.getSurface(), &dst); blit_surface(dst.x, dst.y, bg_, &src); } } }
void dialog_frame::draw_border() { if(have_border_ == false) { return; } // surface top_image(scale_surface(top_, dim_.interior.w, top_->h)); // if(top_image != NULL) { //video_.blit_surface(dim_.interior.x, dim_.exterior.y, top_image); blit_surface_scaled(dim_.interior.x, dim_.exterior.y, dim_.interior.w, top_->h, top_); } // surface bot_image(scale_surface(bot_, dim_.interior.w, bot_->h)); // if(bot_image != NULL) { blit_surface_scaled(dim_.interior.x, dim_.interior.y + dim_.interior.h, dim_.interior.w, bot_->h, bot_); } // surface left_image(scale_surface(left_, left_->w, dim_.interior.h)); // if(left_image != NULL) { blit_surface_scaled(dim_.exterior.x, dim_.interior.y, left_->w, dim_.interior.h, left_); } // surface right_image(scale_surface(right_, right_->w, dim_.interior.h)); // if(right_image != NULL) { blit_surface_scaled(dim_.interior.x + dim_.interior.w, dim_.interior.y, right_->w, dim_.interior.h, right_); } // update_rect(dim_.exterior); if(top_left_ == NULL || bot_left_ == NULL || top_right_ == NULL || bot_right_ == NULL) { return; } blit_surface(dim_.interior.x - left_->w, dim_.interior.y - top_->h, top_left_); blit_surface(dim_.interior.x - left_->w, dim_.interior.y + dim_.interior.h + bot_->h - bot_left_->h, bot_left_); blit_surface(dim_.interior.x + dim_.interior.w + right_->w - top_right_->w, dim_.interior.y - top_->h, top_right_); blit_surface(dim_.interior.x + dim_.interior.w + right_->w - bot_right_->w, dim_.interior.y + dim_.interior.h + bot_->h - bot_right_->h, bot_right_); }
surface darken_modification::operator()(const surface &src) const { surface ret = make_neutral_surface(src); surface tod_dark(image::get_image(game_config::images::tod_dark)); if (tod_dark) blit_surface(tod_dark, NULL, ret, NULL); return ret; }
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 WorldObjRenderer::render_sprite(const ResDescriptor& desc, const Vector3f& pos) { Surface surface = Resource::load_surface(desc); // FIXME: hack, should take that info from the resource file blit_surface(surface, static_cast<int>(pos.x) - surface.get_width()/2, static_cast<int>(pos.y) - surface.get_height()); }
void multimenu::draw_row(const size_t row_index, const SDL_Rect &rect, menu::ROW_TYPE type) { surface img = image::get_image(active_items_[row_index] ? "buttons/checkbox-pressed.png" : "buttons/checkbox.png"); blit_surface(img, NULL, video().getSurface(), &rect); SDL_Rect newrect = { Sint16 (rect.x + img->w + 2), rect.y, Uint16 (rect.w - img->w - 2), rect.h }; menu::draw_row(row_index, newrect, type); }
void WorldObjRenderer::render_surface(const ResDescriptor& desc, const Vector3f& pos, int repeat) { Surface surface = Resource::load_surface(desc); for(int i = 0; i < repeat; ++i) { blit_surface(surface, static_cast<int>(pos.x) + surface.get_width()*i, static_cast<int>(pos.y)); } }
surface background_modification::operator()(const surface &src) const { surface ret = make_neutral_surface(src); #if SDL_VERSION_ATLEAST(2,0,0) SDL_FillRect(ret, NULL, SDL_MapRGBA(ret->format, color_.r, color_.g, color_.b, color_.a)); #else SDL_FillRect(ret, NULL, SDL_MapRGBA(ret->format, color_.r, color_.g, color_.b, color_.unused)); #endif SDL_SetAlpha(src, SDL_SRCALPHA, SDL_ALPHA_OPAQUE); blit_surface(src, NULL, ret, NULL); return ret; }
surface blit_modification::operator()(const surface& src) const { if(x_ >= src->w) { std::stringstream sstr; sstr << "~BLIT(): x-coordinate '" << x_ << "' larger than destination image's width '" << src->w << "' no blitting performed.\n"; throw texception(sstr); } if(y_ >= src->h) { std::stringstream sstr; sstr << "~BLIT(): y-coordinate '" << y_ << "' larger than destination image's height '" << src->h << "' no blitting performed.\n"; throw texception(sstr); } if(surf_->w + x_ > src->w) { std::stringstream sstr; sstr << "~BLIT(): offset and width '" << x_ + surf_->w << "' larger than destination image's width '" << src->w << "' no blitting performed.\n"; throw texception(sstr); } if(surf_->h + y_ > src->h) { std::stringstream sstr; sstr << "~BLIT(): offset and height '" << y_ + surf_->h << "' larger than destination image's height '" << src->h << "' no blitting performed.\n"; throw texception(sstr); } //blit_surface want neutral surfaces surface nsrc = make_neutral_surface(src); surface nsurf = make_neutral_surface(surf_); SDL_Rect r = create_rect(x_, y_, 0, 0); blit_surface(nsurf, NULL, nsrc, &r); return nsrc; }
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 menu::imgsel_style::draw_row_bg(menu& menu_ref, const size_t row_index, const SDL_Rect& rect, ROW_TYPE type) { if(type == SELECTED_ROW && has_background_ && !load_failed_) { if(bg_cache_.width != rect.w || bg_cache_.height != rect.h) { //draw scaled background image //scale image each time (to prevent loss of quality) bg_cache_.surf = scale_surface(img_map_["background"], rect.w, rect.h); bg_cache_.width = rect.w; bg_cache_.height = rect.h; } SDL_Rect clip = rect; blit_surface(rect.x,rect.y,bg_cache_.surf,NULL,&clip); } else { style::draw_row_bg(menu_ref, row_index, rect, type); } }
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 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 ttext::draw(surface& canvas , const game_logic::map_formula_callable& variables) { assert(variables.has_key("text")); // We first need to determine the size of the text which need the rendered // text. So resolve and render the text first and then start to resolve // the other formulas. const t_string text = text_(variables); if(text.empty()) { DBG_GUI_D << "Text: no text to render, leave.\n"; return; } static font::ttext text_renderer; text_renderer.set_text(text, text_markup_(variables)); text_renderer.set_font_size(font_size_) .set_font_style(font_style_) .set_alignment(text_alignment_(variables)) .set_foreground_color(color_) .set_maximum_width(maximum_width_(variables)) .set_maximum_height(maximum_height_(variables)) .set_ellipse_mode(variables.has_key("text_wrap_mode") ? static_cast<PangoEllipsizeMode> (variables.query_value("text_wrap_mode").as_int()) : PANGO_ELLIPSIZE_END); surface surf = text_renderer.render(); if(surf->w == 0) { DBG_GUI_D << "Text: Rendering '" << text << "' resulted in an empty canvas, leave.\n"; return; } game_logic::map_formula_callable local_variables(variables); local_variables.add("text_width", variant(surf->w)); local_variables.add("text_height", variant(surf->h)); /* std::cerr << "Text: drawing text '" << text << " maximum width " << maximum_width_(variables) << " maximum height " << maximum_height_(variables) << " text width " << surf->w << " text height " << surf->h; */ ///@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 unsigned x = x_(local_variables); const unsigned y = y_(local_variables); const unsigned w = w_(local_variables); const unsigned h = h_(local_variables); DBG_GUI_D << "Text: drawing text '" << text << "' drawn from " << x << ',' << y << " width " << w << " height " << h << " canvas size " << canvas->w << ',' << canvas->h << ".\n"; VALIDATE(static_cast<int>(x) < canvas->w && static_cast<int>(y) < canvas->h , _("Text doesn't start on canvas.")); // A text might be to long and will be clipped. if(surf->w > static_cast<int>(w)) { WRN_GUI_D << "Text: text is too wide for the " "canvas and will be clipped.\n"; } if(surf->h > static_cast<int>(h)) { WRN_GUI_D << "Text: text is too high for the " "canvas and will be clipped.\n"; } SDL_Rect dst = ::create_rect(x, y, canvas->w, canvas->h); blit_surface(surf, 0, canvas, &dst); }
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 menu::draw_row(const size_t row_index, const SDL_Rect& rect, ROW_TYPE type) { //called from style, draws one row's contents in a generic and adaptable way const std::vector<std::string>& row = (type == HEADING_ROW) ? heading_ : items_[row_index].fields; SDL_Rect const &area = screen_area(); SDL_Rect const &loc = inner_location(); const std::vector<int>& widths = column_widths(); bool lang_rtl = current_language_rtl(); int dir = (lang_rtl) ? -1 : 1; SDL_Rect column = loc; int xpos = rect.x; if(lang_rtl) xpos += rect.w; for(size_t i = 0; i != row.size(); ++i) { if(lang_rtl) xpos -= widths[i]; if(type == HEADING_ROW && highlight_heading_ == int(i)) { //draw_solid_tinted_rectangle(xpos,rect.y,widths[i],rect.h,255,255,255,0.3); //,video().getSurface()); } const int last_x = xpos; column.w = widths[i]; std::string str = row[i]; std::vector<std::string> img_text_items = utils::split(str, IMG_TEXT_SEPARATOR); for (std::vector<std::string>::const_iterator it = img_text_items.begin(); it != img_text_items.end(); it++) { str = *it; if (!str.empty() && str[0] == IMAGE_PREFIX) { const std::string image_name(str.begin()+1,str.end()); const surface img = style_->get_item_image(image_name); const int remaining_width = max_width_ < 0 ? area.w : std::min<int>(max_width_, ((lang_rtl)? xpos - rect.x : rect.x + rect.w - xpos)); if(img != NULL && img->w <= remaining_width && rect.y + img->h < area.h) { const size_t y = rect.y + (rect.h - img->h)/2; const size_t w = img->w + 5; const size_t x = xpos + ((lang_rtl) ? widths[i] - w : 0); blit_surface(x,y,img); if(!lang_rtl) xpos += w; column.w -= w; } } else { column.x = xpos; const bool has_wrap = (str.find_first_of("\r\n") != std::string::npos); //prevent ellipsis calculation if there is any line wrapping const std::string to_show = (use_ellipsis_ && !has_wrap) ? font::make_text_ellipsis(str, style_->get_font_size(), loc.w - (xpos - rect.x) - 2*style_->get_thickness(), false, true).get() : str; const SDL_Rect& text_size = font::text_area(str,style_->get_font_size()); const size_t y = rect.y + (rect.h - text_size.h)/2; font::draw_text(&video(),column,style_->get_font_size(),font::NORMAL_COLOUR,to_show,xpos,y); if(type == HEADING_ROW && sortby_ == int(i)) { const surface sort_img = image::get_image(sortreversed_ ? "misc/sort-arrow.png" : "misc/sort-arrow-reverse.png"); if(sort_img != NULL && sort_img->w <= widths[i] && sort_img->h <= rect.h) { const size_t sort_x = xpos + widths[i] - sort_img->w; const size_t sort_y = rect.y + rect.h/2 - sort_img->h/2; blit_surface(sort_x,sort_y,sort_img); } } xpos += dir * (text_size.w + 5); } } if(lang_rtl) xpos = last_x; else xpos = last_x + widths[i]; } }
/** * 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])); }
/* renders a window struct to the screen */ void gui_show_window(gui_window *window) { SDL_Rect src, rect; int i, j, hor_pixels_needed, hor_iterations_needed, ver_pixels_needed, ver_iterations_needed; assert(window); if (!window->visible) return; /* render background */ src.x = 0; src.y = 0; src.w = background->w; src.h = background->h; hor_pixels_needed = window->w - b1->w - b3->w; hor_iterations_needed = hor_pixels_needed / background->w; hor_pixels_needed -= (hor_iterations_needed * background->w); ver_pixels_needed = window->h - b1->h - b6->h; ver_iterations_needed = ver_pixels_needed / background->h; ver_pixels_needed -= (ver_iterations_needed * background->h); for (j = 0; j < ver_iterations_needed; j++) { for (i = 0; i < hor_iterations_needed; i++) { rect.x = window->x + b1->w; rect.y = window->y + b1->h; rect.w = window->w - b1->w - b3->w; rect.h = window->h - b6->h - b1->h; rect.x += (i * background->w); rect.y += (j * background->h); blit_surface(background, &src, &rect, 0); } } /* draw any left over background (the extra pixels_needed) */ for (j = 0; j < ver_iterations_needed; j++) { src.w = hor_pixels_needed; rect.x = window->x + b1->w; rect.y = window->y + b1->h; rect.w = hor_pixels_needed; rect.h = background->h; rect.x += (hor_iterations_needed * background->w); rect.y += (j * background->h); blit_surface(background, &src, &rect, 0); } for (i = 0; i < hor_iterations_needed; i++) { src.w = background->w; src.h = ver_pixels_needed; rect.x = window->x + b1->w; rect.y = window->y + b1->h; rect.w = background->w; rect.h = ver_pixels_needed; rect.x += (i * background->w); rect.y += (ver_iterations_needed * background->h); blit_surface(background, &src, &rect, 0); } /* finish that last square */ src.w = hor_pixels_needed; src.h = ver_pixels_needed; rect.x = window->x + b1->w; rect.y = window->y + b1->h; rect.w = hor_pixels_needed; rect.h = ver_pixels_needed; rect.x += (hor_iterations_needed * background->w); rect.y += (ver_iterations_needed * background->h); blit_surface(background, &src, &rect, 0); /* render upper left corner */ rect.x = window->x; rect.y = window->y; rect.w = b1->w; rect.h = b1->h; blit_surface(b1, NULL, &rect, 0); /* render upper border, repeating if necessary */ { int pixels_needed, iterations_needed; int i; pixels_needed = window->w - b1->w - b3->w; iterations_needed = pixels_needed / b2->w; pixels_needed -= (iterations_needed * b2->w); src.x = 0; src.y = 0; src.w = b2->w; src.h = b2->h; for (i = 0; i < iterations_needed; i++) { rect.x = window->x + b1->w; rect.y = window->y; rect.w = b2->w; rect.h = b2->h; rect.x += (i * b2->w); blit_surface(b2, &src, &rect, 0); } /* do left over pixels here */ if (pixels_needed) { src.w = pixels_needed; rect.x = window->x + b1->w; rect.y = window->y; rect.w = pixels_needed; rect.h = b2->h; rect.x += (i * b2->w); blit_surface(b2, &src, &rect, 0); } } /* render upper right corner */ rect.x = window->x + window->w - b3->w; rect.y = window->y; rect.w = b3->w; rect.h = b3->h; blit_surface(b3, NULL, &rect, 0); /* render left border, repeating if necessary */ { int pixels_needed, iterations_needed; int i; pixels_needed = window->h - b1->h - b6->h; iterations_needed = pixels_needed / b4->h; pixels_needed -= (iterations_needed * b4->h); src.x = 0; src.y = 0; src.w = b4->w; src.h = b4->h; for (i = 0; i < iterations_needed; i++) { rect.x = window->x; rect.y = window->y + b1->h; rect.w = b4->w; rect.h = b4->h; rect.y += (i * b4->h); blit_surface(b4, &src, &rect, 0); } /* do left over pixels here */ if (pixels_needed) { src.h = pixels_needed; rect.x = window->x; rect.y = window->y + b1->h; rect.w = b4->w; rect.h = pixels_needed; rect.y += (i * b4->h); blit_surface(b4, &src, &rect, 0); } } /* render right border, repeating if necessary */ { int pixels_needed, iterations_needed; int i; pixels_needed = window->h - b3->h - b8->h; iterations_needed = pixels_needed / b5->h; pixels_needed -= (iterations_needed * b5->h); src.x = 0; src.y = 0; src.w = b5->w; src.h = b5->h; for (i = 0; i < iterations_needed; i++) { rect.x = window->x + window->w - b5->w; rect.y = window->y + b3->h; rect.w = b5->w; rect.h = b5->h; rect.y += (i * b5->h); blit_surface(b5, &src, &rect, 0); } /* do left over pixels here */ if (pixels_needed) { src.h = pixels_needed; rect.x = window->x + window->w - b5->w; rect.y = window->y + b1->h; rect.w = b5->w; rect.h = pixels_needed; rect.y += (i * b5->h); blit_surface(b5, &src, &rect, 0); } } /* render lower left corner */ rect.x = window->x; rect.y = window->y + window->h - b6->h; rect.w = b6->w; rect.h = b6->h; blit_surface(b6, NULL, &rect, 0); /* render lower border, repeating if necessary */ { int pixels_needed, iterations_needed; int i; pixels_needed = window->w - b6->w - b8->w; iterations_needed = pixels_needed / b7->w; pixels_needed -= (iterations_needed * b7->w); src.x = 0; src.y = 0; src.w = b7->w; src.h = b7->h; for (i = 0; i < iterations_needed; i++) { rect.x = window->x + b6->w; rect.y = window->y + window->h - b7->h; rect.w = b7->w; rect.h = b7->h; rect.x += (i * b7->w); blit_surface(b7, &src, &rect, 0); } /* do left over pixels here */ if (pixels_needed) { src.w = pixels_needed; rect.x = window->x + b1->w; rect.y = window->y + window->h - b7->h; rect.w = pixels_needed; rect.h = b7->h; rect.x += (i * b7->w); blit_surface(b7, &src, &rect, 0); } } /* render lower right corner */ rect.x = window->x + window->w - b8->w; rect.y = window->y + window->h - b8->h - 1; /* -1 ? it was off .... ? */ rect.w = b8->w; rect.h = b8->h; blit_surface(b8, NULL, &rect, 0); }
void loadscreen::set_progress(const int percentage, const std::string &text, const bool commit) { if (gRedraw) { gRedraw = false; logo_drawn_ = false; } // Saturate percentage. prcnt_ = percentage < MIN_PERCENTAGE ? MIN_PERCENTAGE: percentage > MAX_PERCENTAGE ? MAX_PERCENTAGE: percentage; // Set progress bar parameters: int fcr = 21, fcg = 53, fcb = 80; // RGB-values for finished piece. int lcr = 21, lcg = 22, lcb = 24; // Leftover piece. //int bcr = 188, bcg = 176, bcb = 136; // Border color. int bcr = 104, bcg = 74, bcb = 28; // Border color. int bw = 1; //< Border width. int bispw = 1; //< Border inner spacing width. bw = 2*(bw+bispw) > screen_.getx() ? 0: 2*(bw+bispw) > screen_.gety() ? 0: bw; int scrx = screen_.getx() - 2*(bw+bispw); //< Available width. int scry = screen_.gety() - 2*(bw+bispw); //< Available height. int pbw = scrx/2; //< Used width. int pbh = scry/16; //< Used heigth. int lightning_thickness = 2; // surface const gdis = screen_.getSurface(); SDL_Rect area; // Clear the last text and draw new if text is provided. // if(text.length() > 0 && commit) // { // logo_drawn_ = false; // } bool updateFull = false; // Draw logo if it was succesfully loaded. // if (logo_surface_ && !logo_drawn_) if (!logo_drawn_) { /* area.x = (screen_.getx () - logo_surface_->w) / 2; area.y = ((scry - logo_surface_->h) / 2) - pbh; area.w = logo_surface_->w; area.h = logo_surface_->h; // Check if we have enough pixels to display it. if (area.x > 0 && area.y > 0) { pby_offset_ = (pbh + area.h)/2; SDL_BlitSurface (logo_surface_, 0, gdis, &area); } else { ERR_DISP << "loadscreen: Logo image is too big." << std::endl; } */ area.x = 0; area.y = 0; //area.w = logo_surface_->w; //area.h = logo_surface_->h; //SDL_BlitSurface (logo_surface_, 0, gdis, &area); //screen_.blit_surface(0, 0, logo_surface_); GLshort vertices[12]; GLfloat texCoords[8]; #ifdef __IPAD__ int size = 1024; #else int size = 512; #endif vertices[0] = 0; vertices[1] = 0; vertices[2] = 0; vertices[3] = size; vertices[4] = 0; vertices[5] = 0; vertices[6] = 0; vertices[7] = size; vertices[8] = 0; vertices[9] = size; vertices[10] = size; vertices[11] = 0; texCoords[0] = 0; texCoords[1] = 0; texCoords[2] = 1; texCoords[3] = 0; texCoords[4] = 0; texCoords[5] = 1; texCoords[6] = 1; texCoords[7] = 1; renderQueueAddTexture(vertices, texCoords, logo_texture_, 0xFFFFFFFF, 1.0); // glVertexPointer(3, GL_SHORT, 0, vertices); // glTexCoordPointer(2, GL_FLOAT, 0, texCoords); // glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); //SDL_RenderCopy(logo_texture_, NULL, NULL,DRAW); //SDL_RenderPresent(); //SDL_UpdateRect(gdis, area.x, area.y, area.w, area.h); // draw logo over everything #ifdef __IPAD__ std::string path = game_config::path + "/data/core/images/misc/logo.png"; surface logo_surface = IMG_Load(path.c_str()); blit_surface((1024-logo_surface.get()->w)/2, -10, logo_surface); SDL_Rect tip_area = {690, 306, 225, 140}; draw_tip_of_day(screen_, tips_of_day, gui::dialog_frame::titlescreen_style,&tip_area); #else std::string path = game_config::path + "/data/core/images/misc/logo_small.png"; surface logo_surface = IMG_Load(path.c_str()); blit_surface((480-logo_surface.get()->w)/2, -10, logo_surface); SDL_Rect tip_area = {242, 100, 225, 140}; draw_tip_of_day(screen_, tips_of_day, gui::dialog_frame::titlescreen_style,&tip_area); #endif logo_drawn_ = true; updateFull = true; } int pbx = (scrx - pbw)/2; // Horizontal location. #ifdef __IPAD__ int pby = 693; #else int pby = 276; //(scry - pbh)/2 + pby_offset_; // Vertical location. #endif // Draw top border. area.x = pbx; area.y = pby; area.w = pbw + 2*(bw+bispw); area.h = bw; // SDL_FillRect(gdis,&area,SDL_MapRGB(gdis->format,bcr,bcg,bcb)); SDL_SetRenderDrawColor(bcr, bcg, bcb, 0xff); SDL_RenderFill(&area); // Draw bottom border. area.x = pbx; area.y = pby + pbh + bw + 2*bispw; area.w = pbw + 2*(bw+bispw); area.h = bw; //SDL_FillRect(gdis,&area,SDL_MapRGB(gdis->format,bcr,bcg,bcb)); SDL_RenderFill(&area); // Draw left border. area.x = pbx; area.y = pby + bw; area.w = bw; area.h = pbh + 2*bispw; //SDL_FillRect(gdis,&area,SDL_MapRGB(gdis->format,bcr,bcg,bcb)); SDL_RenderFill(&area); // Draw right border. area.x = pbx + pbw + bw + 2*bispw; area.y = pby + bw; area.w = bw; area.h = pbh + 2*bispw; //SDL_FillRect(gdis,&area,SDL_MapRGB(gdis->format,bcr,bcg,bcb)); SDL_RenderFill(&area); // Draw the finished bar area. area.x = pbx + bw + bispw; area.y = pby + bw + bispw; area.w = (prcnt_ * pbw) / (MAX_PERCENTAGE - MIN_PERCENTAGE); area.h = pbh; //SDL_FillRect(gdis,&area,SDL_MapRGB(gdis->format,fcr,fcg,fcb)); SDL_SetRenderDrawColor(fcr, fcg, fcb, 0xff); SDL_RenderFill(&area); SDL_Rect lightning = area; lightning.h = lightning_thickness; //we add 25% of white to the color of the bar to simulate a light effect //SDL_FillRect(gdis,&lightning,SDL_MapRGB(gdis->format,(fcr*3+255)/4,(fcg*3+255)/4,(fcb*3+255)/4)); SDL_SetRenderDrawColor((fcr*3+255)/4,(fcg*3+255)/4,(fcb*3+255)/4, 0xff); SDL_RenderFill(&lightning); lightning.y = area.y+area.h-lightning.h; //remove 50% of color to simulate a shadow effect //SDL_FillRect(gdis,&lightning,SDL_MapRGB(gdis->format,fcr/2,fcg/2,fcb/2)); SDL_SetRenderDrawColor(fcr/2,fcg/2,fcb/2, 0xff); SDL_RenderFill(&lightning); // Draw the leftover bar area. area.x = pbx + bw + bispw + (prcnt_ * pbw) / (MAX_PERCENTAGE - MIN_PERCENTAGE); area.y = pby + bw + bispw; area.w = ((MAX_PERCENTAGE - prcnt_) * pbw) / (MAX_PERCENTAGE - MIN_PERCENTAGE); area.h = pbh; //SDL_FillRect(gdis,&area,SDL_MapRGB(gdis->format,lcr,lcg,lcb)); SDL_SetRenderDrawColor(lcr, lcg, lcb, 0xff); SDL_RenderFill(&area); // Clear the last text and draw new if text is provided. /* if(text.length() > 0 && commit) { SDL_Rect oldarea = textarea_; // SDL_FillRect(gdis,&textarea_,SDL_MapRGB(gdis->format,0,0,0)); textarea_ = font::line_size(text, font::SIZE_NORMAL); textarea_.x = scrx/2 + bw + bispw - textarea_.w / 2; textarea_.y = pby + pbh + 4*(bw + bispw); //draw_solid_tinted_rectangle(textarea_.x-4, textarea_.y-2, textarea_.w + 8, textarea_.h + 4,0,0,0,0.50,gdis); SDL_Rect tintRect = {textarea_.x-4, textarea_.y-2, textarea_.w + 8, textarea_.h + 4}; SDL_SetRenderDrawColor(0, 0, 0, 0x80); SDL_RenderFill(&tintRect); textarea_ = font::draw_text(&screen_,textarea_,font::SIZE_NORMAL,font::NORMAL_COLOUR,text,textarea_.x,textarea_.y); oldarea.x = std::min<int>(textarea_.x, oldarea.x); oldarea.y = std::min<int>(textarea_.y, oldarea.y); oldarea.w = std::max<int>(textarea_.w, oldarea.w); oldarea.h = std::max<int>(textarea_.h, oldarea.h); // SDL_UpdateRect(gdis, oldarea.x, oldarea.y, oldarea.w, oldarea.h); } */ // Update the rectangle if needed if(commit) { // SDL_UpdateRect(gdis, pbx, pby, pbw + 2*(bw + bispw), pbh + 2*(bw + bispw)); } // if (updateFull) // { // SDL_UpdateRect(gdis, 0, 0, 480, 320); // } // else if (commit) // { // SDL_UpdateRect(gdis, 116, 274, 251, 47); // } SDL_RenderPresent(); }
//helper blit functions specifically for the Image class wrapping a surface // //blit this (tile) image into another image (or screen) void Image::blitTo(Surface* dest, int destX, int destY, int tileNum /*= -1*/) { //Image class objects default to clip = 0 unless explicitly set blit_surface(this->_surface, (tileNum<0)?NULL:&this->tile(tileNum), //source dest->surface(), destX, destY); //dest }
TITLE_RESULT show_title(game_display& screen, config& tips_of_day) { disableTerrainCache(); free_all_caches(); cursor::set(cursor::NORMAL); const preferences::display_manager disp_manager(&screen); const hotkey::basic_handler key_handler(&screen); const font::floating_label_context label_manager; screen.video().modeChanged(); // resets modeChanged value // if (background_is_dirty_) { draw_background(screen); } //- Texts for the menu-buttons. //- Members of this array must correspond to the enumeration TITLE_RESULT static const char* button_labels[] = { //N_("TitleScreen button^Tutorial"), N_("TitleScreen button^Campaign"), #ifndef FREE_VERSION N_("TitleScreen button^Skirmish"), N_("TitleScreen button^Multiplayer"), #endif N_("TitleScreen button^Load"), // N_("TitleScreen button^Add-ons"), //#ifndef DISABLE_EDITOR2 //N_("TitleScreen button^Map Editor"), //#endif //N_("TitleScreen button^Language"), N_("TitleScreen button^Preferences"), N_("Sync Saves"), #ifndef DISABLE_OPENFEINT N_("TitleScreen button^OpenFeint"), #endif N_("TitleScreen button^Help"), //N_("TitleScreen button^Quit"), // Only the above buttons go into the menu-frame // Next 2 buttons go into frame for the tip-of-the-day: N_("TitleScreen button^Previous"), N_("TitleScreen button^Next"), //N_("TitleScreen button^Help"), // Next entry is no button, but shown as a mail-icon instead: //N_("TitleScreen button^Help Wesnoth") }; //- Texts for the tooltips of the menu-buttons static const char* help_button_labels[] = { //N_("Start a tutorial to familiarize yourself with the game"), N_("Start a new single player campaign"), #ifndef FREE_VERSION N_("Play a single scenario against the AI"), N_("Play multiplayer (hotseat or Internet)"), #endif N_("Load a saved game"), // N_("Download usermade campaigns, eras, or map packs"), //#ifndef DISABLE_EDITOR2 //N_("Start the map editor"), //#endif //N_("Change the language"), N_("Configure the game's settings"), N_("Sync saved games"), #ifndef DISABLE_OPENFEINT N_("Launch the OpenFeint dashboard"), #endif N_("Show Battle for Wesnoth help"), //N_("Quit the game"), N_("Show next tip of the day"), //N_("Upload statistics") }; //static const size_t nbuttons = sizeof(button_labels)/sizeof(*button_labels); #ifdef FREE_VERSION int nbuttons = 10; #else int nbuttons = 8; #endif #ifdef DISABLE_OPENFEINT nbuttons--; #endif #ifndef __IPAD__ nbuttons--; // because help is off to the left now #endif int menu_xbase = CVideo::getx()-108-10; //380; //(game_config::title_buttons_x*screen.w())/1024; const int menu_xincr = 0; #ifdef USE_TINY_GUI //const int menu_ybase = 15; //(330*screen.h())/768 - 50; //15; const int menu_yincr = 36+5; //(35*3)/4;//15; const int menu_ybase = (screen.h() - (36+5)*nbuttons - 5) / 2 + 4; #else const int menu_ybase = (screen.h() - (36+5)*nbuttons - 5) / 2 + 4; const int menu_yincr = 36+5; #endif #ifdef __IPAD__ menu_xbase -= 10; #endif const int padding = 4; //game_config::title_buttons_padding; std::vector<button> buttons; size_t b, max_width = 0; size_t n_menubuttons = 0; for(b = 0; b != nbuttons; ++b) { //#ifdef __IPHONEOS__ // if (b + TUTORIAL == TUTORIAL || b + TUTORIAL == START_MAP_EDITOR || b+TUTORIAL == CHANGE_LANGUAGE) // continue; //#endif buttons.push_back(button(screen.video(),sgettext(button_labels[b]))); buttons.back().set_help_string(sgettext(help_button_labels[b])); max_width = std::max<size_t>(max_width,buttons.back().width()); n_menubuttons = b; #ifdef __IPAD__ if(b + NEW_CAMPAIGN == SHOW_HELP) break; #else if(b + NEW_CAMPAIGN == SHOW_OPENFEINT) break; #endif } SDL_Rect main_dialog_area = {menu_xbase-padding, menu_ybase-padding, max_width+padding*2, menu_yincr*(n_menubuttons)+buttons.back().height()+padding*2}; gui::dialog_frame main_frame(screen.video(), "", gui::dialog_frame::titlescreen_style, false); main_frame.layout(main_dialog_area); // we only redraw transparent parts when asked, // to prevent alpha growing if (background_is_dirty_) { main_frame.draw_background(); main_frame.draw_border(); } int i=0; for(b = 0; b != nbuttons; ++b) { //#ifdef __IPHONEOS__ // if (b + TUTORIAL == TUTORIAL || b + TUTORIAL == START_MAP_EDITOR || b+TUTORIAL == CHANGE_LANGUAGE) // continue; //#endif buttons[i].set_width(max_width); buttons[i].set_location(menu_xbase + i*menu_xincr, menu_ybase + i*menu_yincr); #ifdef __IPAD__ if(b + NEW_CAMPAIGN == SHOW_HELP) break; #else if(b + NEW_CAMPAIGN == SHOW_OPENFEINT) break; #endif i++; } #ifndef __IPAD__ buttons.push_back(button(screen.video(),sgettext(button_labels[i+1]))); buttons.back().set_help_string(sgettext(help_button_labels[i+1])); buttons[i+1].set_width(max_width); buttons[i+1].set_location(5, 320-menu_yincr); #endif // b = TIP_PREVIOUS - NEW_CAMPAIGN; // gui::button previous_tip_button(screen.video(),sgettext(button_labels[b]),button::TYPE_PRESS,"lite_small"); // previous_tip_button.set_help_string( sgettext(button_labels[b] )); // b = TIP_NEXT - NEW_CAMPAIGN; // gui::button next_tip_button(screen.video(),sgettext(button_labels[b]),button::TYPE_PRESS,"lite_small"); // next_tip_button.set_help_string( sgettext(button_labels[b] )); // b = SHOW_HELP - NEW_CAMPAIGN; // gui::button help_tip_button(screen.video(),sgettext(button_labels[b]),button::TYPE_PRESS,"lite_small"); // help_tip_button.set_help_string( sgettext(button_labels[b] )); // gui::button beg_button(screen.video(),_("Help Wesnoth"),button::TYPE_IMAGE,"menu-button",button::MINIMUM_SPACE); // beg_button.set_help_string(_("Help Wesnoth by sending us information")); // next_tip_of_day(tips_of_day); // surface_restorer tip_of_day_restorer; // draw_tip_of_day(screen, tips_of_day, gui::dialog_frame::titlescreen_style, // &previous_tip_button, &next_tip_button, NULL/*&help_tip_button*/, &main_dialog_area, tip_of_day_restorer); // const int pad = game_config::title_tip_padding; // beg_button.set_location(screen.w() - pad - beg_button.location().w, // screen.h() - pad - beg_button.location().h); events::raise_draw_event(); LOG_DP << "drew buttons dialog\n"; // draw logo over everything #ifdef __IPAD__ std::string path = game_config::path + "/data/core/images/misc/logo.png"; #else std::string path = game_config::path + "/data/core/images/misc/logo_small.png"; #endif surface logo_surface = IMG_Load(path.c_str()); //blit_surface(480-logo_surface.get()->w, 0, logo_surface); CKey key; size_t keyboard_button = nbuttons; bool key_processed = false; // update_whole_screen(); background_is_dirty_ = false; titlescreen_handler ts_handler(key[SDLK_ESCAPE] != 0); //!= 0 to avoid a MSVC warning C4800 LOG_DP << "entering interactive loop...\n"; memory_stats("At titlescreen"); // Initialize OpenFeint now of_init(); for(;;) { events::pump(); for(size_t b = 0; b != buttons.size(); ++b) { if(buttons[b].pressed()) { free_title(); return static_cast<TITLE_RESULT>(b + NEW_CAMPAIGN); } } /* if(previous_tip_button.pressed()) { next_tip_of_day(tips_of_day, true); draw_tip_of_day(screen, tips_of_day, gui::dialog_frame::titlescreen_style, &previous_tip_button, &next_tip_button, &help_tip_button, &main_dialog_area, tip_of_day_restorer); } if(next_tip_button.pressed()) { next_tip_of_day(tips_of_day, false); draw_tip_of_day(screen, tips_of_day, gui::dialog_frame::titlescreen_style, &previous_tip_button, &next_tip_button, &help_tip_button, &main_dialog_area, tip_of_day_restorer); } */ // if(help_tip_button.pressed()) { // return SHOW_HELP; // } // if(beg_button.pressed()) { // return BEG_FOR_UPLOAD; // } if (key[SDLK_UP]) { if (!key_processed) { buttons[keyboard_button].set_active(false); if (keyboard_button == 0) { keyboard_button = nbuttons - 1; } else { keyboard_button--; } key_processed = true; buttons[keyboard_button].set_active(true); } } else if (key[SDLK_DOWN]) { if (!key_processed) { buttons[keyboard_button].set_active(false); if (keyboard_button > nbuttons - 1) { keyboard_button = 0; } else { keyboard_button++; } key_processed = true; buttons[keyboard_button].set_active(true); } } else { key_processed = false; } events::raise_process_event(); // KP: redraw draw_background(screen); main_frame.draw_background(); main_frame.draw_border(); events::raise_draw_event(); //blit_surface(480-logo_surface.get()->w, 0, logo_surface); #ifdef __IPAD__ blit_surface(-10, 0, logo_surface); #else blit_surface(-15, -10, logo_surface); #endif screen.flip(); // if (key[SDLK_ESCAPE] && !ts_handler.get_esc_ignore()) // return QUIT_GAME; if (key[SDLK_F5]) return RELOAD_GAME_DATA; if (key[SDLK_RETURN] && keyboard_button < nbuttons) { return static_cast<TITLE_RESULT>(keyboard_button + NEW_CAMPAIGN); } // If the resolution has changed due to the user resizing the screen, // or from changing between windowed and fullscreen: if(screen.video().modeChanged()) { return REDRAW_BACKGROUND; } screen.delay(10); } free_title(); return REDRAW_BACKGROUND; }
void tristate_button::draw_contents() { surface image(NULL); surface overlay(NULL); surface base = baseImage_; int offset = 0; switch (state_) { case UNINIT: return; case NORMAL: break; case TOUCHED_LEFT: overlay = touchedUpImage_; base = touchedBaseImage_; break; case TOUCHED_RIGHT: overlay = touchedDownImage_; base = touchedBaseImage_; break; case TOUCHED_BOTH_LEFT: case TOUCHED_BOTH_RIGHT: overlay = touchedBothImage_; base = touchedBaseImage_; break; case ACTIVE: // overlay = activeImage_; base = activeBaseImage_; break; case PRESSED_LEFT: base = activeBaseImage_; overlay = pressedUpImage_; break; case PRESSED_RIGHT: base = activeBaseImage_; overlay = pressedDownImage_; break; case PRESSED_BOTH: base = activeBaseImage_; overlay = pressedBothImage_; break; case PRESSED_ACTIVE_LEFT: overlay = pressedUpActiveImage_; base = activeBaseImage_; break; case PRESSED_ACTIVE_BOTH: overlay = pressedBothActiveImage_; base = activeBaseImage_; break; case PRESSED_ACTIVE_RIGHT: overlay = pressedDownActiveImage_; base = activeBaseImage_; break; } image = base; const int image_w = image->w; SDL_Rect const &loc = location(); SDL_Rect clipArea = loc; const int texty = loc.y + loc.h / 2 - textRect_.h / 2 + offset; int textx; clipArea.w += image_w + checkbox_horizontal_padding; textx = loc.x + image_w + checkbox_horizontal_padding / 2; SDL_Color button_color = font::BUTTON_COLOR; surface scalled_item; scalled_item.assign(scale_surface(itemImage_, 36, 36)); // blit_surface want neutral surfaces surface nitem = make_neutral_surface(scalled_item); surface nbase = make_neutral_surface(base); //TODO avoid magic numbers SDL_Rect r = sdl::create_rect(1, 1, 0, 0); blit_surface(nitem, NULL, nbase, &r); if (!overlay.null()) { surface noverlay = make_neutral_surface(overlay); blit_surface(noverlay, NULL, nbase, NULL); } // TODO for later reference // SDL_SetAlpha(nbase, SDL_SRCALPHA, SDL_ALPHA_OPAQUE); // SDL_SetAlpha(image, 0, 0); // // TODO might be needed. bg_restore(); image = nbase; video().blit_surface(loc.x, loc.y, image); clipArea.x += offset; clipArea.y += offset; clipArea.w -= 2 * offset; clipArea.h -= 2 * offset; font::draw_text(&video(), clipArea, font_size, button_color, label_, textx, texty); update_rect(loc); }
void menu::imgsel_style::draw_row(menu& menu_ref, const size_t row_index, const SDL_Rect& rect, ROW_TYPE type) { if(!load_failed_) { //draw item inside style::draw_row(menu_ref, row_index, rect, type); if(type == SELECTED_ROW) { // draw border surface image; SDL_Rect area; SDL_Rect clip = rect; area.x = rect.x; area.y = rect.y; image = img_map_["border-top"]; area.x = rect.x; area.y = rect.y; do { blit_surface(area.x,area.y,image,NULL,&clip); area.x += image->w; } while( area.x < rect.x + rect.w ); image = img_map_["border-left"]; area.x = rect.x; area.y = rect.y; do { blit_surface(area.x,area.y,image,NULL,&clip); area.y += image->h; } while( area.y < rect.y + rect.h ); image = img_map_["border-right"]; area.x = rect.x + rect.w - thickness_; area.y = rect.y; do { blit_surface(area.x,area.y,image,NULL,&clip); area.y += image->h; } while( area.y < rect.y + rect.h ); image = img_map_["border-bottom"]; area.x = rect.x; area.y = rect.y + rect.h - thickness_; do { blit_surface(area.x,area.y,image,NULL,&clip); area.x += image->w; } while( area.x < rect.x + rect.w ); image = img_map_["border-topleft"]; area.x = rect.x; area.y = rect.y; blit_surface(area.x,area.y,image); image = img_map_["border-topright"]; area.x = rect.x + rect.w - image->w; area.y = rect.y; blit_surface(area.x,area.y,image); image = img_map_["border-botleft"]; area.x = rect.x; area.y = rect.y + rect.h - image->h; blit_surface(area.x,area.y,image); image = img_map_["border-botright"]; area.x = rect.x + rect.w - image->w; area.y = rect.y + rect.h - image->h; blit_surface(area.x,area.y,image); } } else { //default drawing style::draw_row(menu_ref, row_index, rect, type); } }
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 button::draw_contents() { surface image = image_; const int image_w = image_->w; int offset = 0; switch(state_) { case ACTIVE: image = activeImage_; break; case PRESSED: image = pressedImage_; if (type_ == TYPE_PRESS) offset = 1; break; case PRESSED_ACTIVE: image = pressedActiveImage_; break; case TOUCHED_NORMAL: case TOUCHED_PRESSED: image = touchedImage_; break; default: break; } SDL_Rect const &loc = location(); SDL_Rect clipArea = loc; const int texty = loc.y + loc.h / 2 - textRect_.h / 2 + offset; int textx; if (type_ != TYPE_CHECK && type_ != TYPE_RADIO && type_ != TYPE_IMAGE) textx = loc.x + image->w / 2 - textRect_.w / 2 + offset; else { clipArea.w += image_w + checkbox_horizontal_padding; textx = loc.x + image_w + checkbox_horizontal_padding / 2; } SDL_Color button_color = font::BUTTON_COLOR; if (!enabled()) { if (state_ == PRESSED || state_ == PRESSED_ACTIVE) image = pressedDisabledImage_; else image = disabledImage_; button_color = font::GRAY_COLOR; } if (!overlayImage_.null()) { surface noverlay = make_neutral_surface( enabled() ? overlayImage_ : overlayDisabledImage_); if (!overlayPressedImage_.null()) { switch (state_) { case ACTIVE: if (!overlayActiveImage_.null()) noverlay = make_neutral_surface(overlayActiveImage_); break; case PRESSED: case PRESSED_ACTIVE: case TOUCHED_NORMAL: case TOUCHED_PRESSED: noverlay = make_neutral_surface( enabled() ? overlayPressedImage_ : overlayPressedDisabledImage_); break; default: break; } } surface nimage = make_neutral_surface(image); blit_surface(noverlay, NULL, nimage, NULL); image = nimage; } video().blit_surface(loc.x, loc.y, image); if (type_ != TYPE_IMAGE){ clipArea.x += offset; clipArea.y += offset; clipArea.w -= 2*offset; clipArea.h -= 2*offset; font::draw_text(&video(), clipArea, font_size, button_color, label_, textx, texty); } update_rect(loc); }
//blit a (tile) image into this image void Image::blitFrom(Image* source, int tileNum /*= -1*/, int destX, int destY ) { //Image class objects default to clip = 0 unless explicitly set blit_surface(source->surface(), (tileNum<0)?NULL:&source->tile(tileNum), //source this->_surface, destX, destY); //dest }
void gui_show_listbox(gui_listbox *lb) { int i, item; SDL_Rect rect; if (lb == NULL) return; if (!lb->visible) return; /* draw the under area first */ if (lb->trans_area == NULL) { SDL_Surface *area; SDL_Rect src, dest; area = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, lb->w - 17, lb->h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask); assert(area); rect.x = 0; rect.y = 0; rect.w = area->w; rect.h = area->h; SDL_FillRect(area, &rect, SDL_MapRGB(area->format, 0, 0, 0)); SDL_SetAlpha(area, SDL_SRCALPHA, 93); rect.x = lb->x; rect.y = lb->y; rect.w = area->w; rect.h = area->h; blit_surface(area, NULL, &rect, 0); SDL_FreeSurface(area); /* now that the trans area is drawn, back up that area there */ lb->trans_area = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, lb->w - 17, lb->h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask); src.x = lb->x; src.y = lb->y; src.w = lb->trans_area->w; src.h = lb->trans_area->h; dest.x = 0; dest.y = 0; dest.w = src.w; dest.h = src.h; SDL_BlitSurface(screen, &src, lb->trans_area, &dest); } else { rect.x = lb->x; rect.y = lb->y; rect.w = lb->trans_area->w; rect.h = lb->trans_area->h; blit_surface(lb->trans_area, NULL, &rect, 0); } if (lb->num_items == 0) return; /* now draw the items */ /* set "item" to the first item for the top, as dedicated by the progress bar */ item = (int)((float)lb->sb->progress * (float)(lb->num_items - 1)); lb->top_scrolled = item; /* draw the top bar */ rect.x = lb->x; rect.y = lb->y; rect.w = lb->w - 17; rect.h = 2; fill_rect(&rect, map_rgb(0, 93, 92)); /* draw all the item borders and call the callback (if one exists) to draw what's inside each element */ for (i = 0; (item < lb->num_items) && ((i * lb->item_h) < lb->h); i++) { if ((i + lb->top_scrolled) == lb->selected) { /* draw the selected bg */ rect.x = lb->x; rect.y = lb->y + (i * lb->item_h) + 2; rect.w = lb->w - 17; rect.h = lb->item_h - 2; if ((rect.y + rect.h) > (lb->y + lb->h)) rect.h = (lb->y + lb->h) - rect.y; fill_rect(&rect, map_rgb(0, 64, 65)); } /* draw the bottom item bar */ rect.x = lb->x; rect.y = lb->y + (i * lb->item_h) + lb->item_h; rect.w = lb->w - 17; rect.h = 2; if (rect.y < (lb->y + lb->h)) fill_rect(&rect, map_rgb(0, 93, 92)); if (lb->callback) (*lb->callback) (lb, rect.x, rect.y - lb->item_h, rect.w, lb->item_h, item); item++; } }