Exemple #1
0
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));
	}
}
Exemple #2
0
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);
}
Exemple #4
0
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");
}
Exemple #7
0
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);
}
Exemple #10
0
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_;
}
Exemple #12
0
/**
 * 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;
}
Exemple #14
0
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);
}