optimize the drawing loop, apply patch #1952 by VIR
This commit is contained in:
parent
02c1e610c4
commit
29fe502d8a
8 changed files with 239 additions and 202 deletions
|
@ -115,6 +115,8 @@ Version 1.9.0+svn:
|
|||
the objectives are viewed several times.
|
||||
* Replace "working peasant" (indicating missing images in debug mode) by
|
||||
half-transparent "Image not found"
|
||||
* Improved rendering algorithm: reduced memory requirements and a much faster
|
||||
render loop; very noticable on big maps
|
||||
|
||||
Version 1.9.0:
|
||||
* AI:
|
||||
|
|
|
@ -162,6 +162,10 @@
|
|||
name = "Martin Renold (maxy/martinxyz)"
|
||||
comment = "performance and gui bug fixes"
|
||||
[/entry]
|
||||
[entry]
|
||||
name = "Matthias Kretz"
|
||||
comment = "optimizations"
|
||||
[/entry]
|
||||
[entry]
|
||||
name = "Moritz Göbelbecker (mog)"
|
||||
comment = "Work on the terrain engine"
|
||||
|
|
199
src/display.cpp
199
src/display.cpp
|
@ -804,28 +804,41 @@ std::vector<surface> display::get_terrain_images(const map_location &loc,
|
|||
}
|
||||
|
||||
void display::drawing_buffer_add(const tdrawing_layer layer,
|
||||
const map_location& loc, const tblit& blit)
|
||||
const map_location& loc, int x, int y, const surface surf,
|
||||
const SDL_Rect &clip)
|
||||
{
|
||||
tdrawing_layergroup group;
|
||||
|
||||
// find in which group the layer belongs
|
||||
// FIXME: temporary method. Group splitting should be made
|
||||
// public into the definition of tdrawing_layer
|
||||
if(layer < LAYER_UNIT_FIRST) {
|
||||
group = LAYERGROUP_TERRAIN_BG;
|
||||
} else if(layer < LAYER_UNIT_MOVE_DEFAULT) {
|
||||
group = LAYERGROUP_UNIT;
|
||||
} else if(layer < LAYER_REACHMAP) {
|
||||
group = LAYERGROUP_UNIT_MOVE;
|
||||
} else {
|
||||
group = LAYERGROUP_UI;
|
||||
}
|
||||
|
||||
drawing_buffer_[group][loc][layer].push_back(blit);
|
||||
drawing_buffer_.push_back(tblit(layer, loc, x, y, surf, clip));
|
||||
}
|
||||
|
||||
void display::drawing_buffer_add(const tdrawing_layer layer,
|
||||
const map_location& loc, int x, int y,
|
||||
const std::vector<surface> &surf,
|
||||
const SDL_Rect &clip)
|
||||
{
|
||||
drawing_buffer_.push_back(tblit(layer, loc, x, y, surf, clip));
|
||||
}
|
||||
|
||||
// FIXME: temporary method. Group splitting should be made
|
||||
// public into the definition of tdrawing_layer
|
||||
//
|
||||
// The drawing is done per layer_group, the range per group is [low, high).
|
||||
const display::tdrawing_layer display::drawing_buffer_key::layer_groups[] = {
|
||||
LAYER_TERRAIN_BG,
|
||||
LAYER_UNIT_FIRST,
|
||||
LAYER_UNIT_MOVE_DEFAULT,
|
||||
// Make sure the movement doesn't show above fog and reachmap.
|
||||
LAYER_REACHMAP,
|
||||
LAYER_LAST_LAYER
|
||||
};
|
||||
|
||||
// no need to change this if layer_groups above is changed
|
||||
const unsigned int display::drawing_buffer_key::max_layer_group = sizeof(display::drawing_buffer_key::layer_groups) / sizeof(display::tdrawing_layer) - 2;
|
||||
|
||||
void display::drawing_buffer_commit()
|
||||
{
|
||||
// std::list::sort() is a stable sort
|
||||
drawing_buffer_.sort();
|
||||
|
||||
SDL_Rect clip_rect = map_area();
|
||||
const surface screen = get_screen_surface();
|
||||
clip_rect_setter set_clip_rect(screen, &clip_rect);
|
||||
|
@ -841,35 +854,21 @@ void display::drawing_buffer_commit()
|
|||
*
|
||||
* This ended in the following priority order:
|
||||
* layergroup > location > layer > 'tblit' > surface
|
||||
*/
|
||||
|
||||
foreach(const tgroup_map::value_type& group, drawing_buffer_) {
|
||||
foreach(const tlocation_map::value_type& loc, group.second) {
|
||||
foreach(const tlayer_map::value_type& layer, loc.second) {
|
||||
foreach(const tblit& blit, layer.second) {
|
||||
foreach(const surface& surf, blit.surf) {
|
||||
// Note that dstrect can be changed by SDL_BlitSurface
|
||||
// and so a new instance should be initialized
|
||||
// to pass to each call to SDL_BlitSurface.
|
||||
SDL_Rect dstrect = create_rect(blit.x, blit.y, 0, 0);
|
||||
|
||||
if(blit.clip.x || blit.clip.y
|
||||
||blit.clip.w ||blit.clip.h) {
|
||||
|
||||
SDL_Rect srcrect = blit.clip;
|
||||
SDL_BlitSurface(surf,
|
||||
&srcrect, screen, &dstrect);
|
||||
} else {
|
||||
SDL_BlitSurface(surf,
|
||||
NULL, screen, &dstrect);
|
||||
}
|
||||
} //for surf
|
||||
update_rect(blit.x, blit.y, zoom_, zoom_);
|
||||
} // for blit
|
||||
} //for layer
|
||||
} //for loc
|
||||
} //for group
|
||||
*/
|
||||
|
||||
foreach(const tblit &blit, drawing_buffer_) {
|
||||
foreach(const surface& surf, blit.surf()) {
|
||||
// Note that dstrect can be changed by SDL_BlitSurface
|
||||
// and so a new instance should be initialized
|
||||
// to pass to each call to SDL_BlitSurface.
|
||||
SDL_Rect dstrect = create_rect(blit.x(), blit.y(), 0, 0);
|
||||
SDL_Rect srcrect = blit.clip();
|
||||
SDL_Rect *srcrectArg = (srcrect.x | srcrect.y | srcrect.w | srcrect.h)
|
||||
? &srcrect : NULL;
|
||||
SDL_BlitSurface(surf, srcrectArg, screen, &dstrect);
|
||||
}
|
||||
update_rect(blit.x(), blit.y(), zoom_, zoom_);
|
||||
}
|
||||
drawing_buffer_clear();
|
||||
}
|
||||
|
||||
|
@ -1118,11 +1117,11 @@ void display::draw_text_in_hex(const map_location& loc,
|
|||
for (int dy=-1; dy <= 1; ++dy) {
|
||||
for (int dx=-1; dx <= 1; ++dx) {
|
||||
if (dx!=0 || dy!=0) {
|
||||
drawing_buffer_add(layer, loc, tblit(x + dx, y + dy, back_surf));
|
||||
drawing_buffer_add(layer, loc, x + dx, y + dy, back_surf);
|
||||
}
|
||||
}
|
||||
}
|
||||
drawing_buffer_add(layer, loc, tblit(x, y, text_surf));
|
||||
drawing_buffer_add(layer, loc, x, y, text_surf);
|
||||
}
|
||||
|
||||
void display::render_image(int x, int y, const display::tdrawing_layer drawing_layer,
|
||||
|
@ -1172,7 +1171,7 @@ void display::render_image(int x, int y, const display::tdrawing_layer drawing_l
|
|||
// divide the surface into 2 parts
|
||||
const int submerge_height = std::max<int>(0, surf->h*(1.0-submerged));
|
||||
SDL_Rect srcrect = create_rect(0, 0, surf->w, submerge_height);
|
||||
drawing_buffer_add(drawing_layer, loc, tblit(x, y, surf, srcrect));
|
||||
drawing_buffer_add(drawing_layer, loc, x, y, surf, srcrect);
|
||||
|
||||
if(submerge_height != surf->h) {
|
||||
//the lower part will be transparent
|
||||
|
@ -1182,11 +1181,11 @@ void display::render_image(int x, int y, const display::tdrawing_layer drawing_l
|
|||
srcrect.h = surf->h-submerge_height;
|
||||
y += submerge_height;
|
||||
|
||||
drawing_buffer_add(drawing_layer, loc, tblit(x, y, surf, srcrect));
|
||||
drawing_buffer_add(drawing_layer, loc, x, y, surf, srcrect);
|
||||
}
|
||||
} else {
|
||||
// simple blit
|
||||
drawing_buffer_add(drawing_layer, loc, tblit(x, y, surf));
|
||||
drawing_buffer_add(drawing_layer, loc, x, y, surf);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1366,55 +1365,55 @@ void display::draw_border(const map_location& loc, const int xpos, const int ypo
|
|||
|
||||
// First handle the corners :
|
||||
if(loc.x == -1 && loc.y == -1) { // top left corner
|
||||
drawing_buffer_add(LAYER_BORDER, loc, tblit(xpos + zoom_/4, ypos,
|
||||
image::get_image(theme_.border().corner_image_top_left, image::SCALED_TO_ZOOM)));
|
||||
drawing_buffer_add(LAYER_BORDER, loc, xpos + zoom_/4, ypos,
|
||||
image::get_image(theme_.border().corner_image_top_left, image::SCALED_TO_ZOOM));
|
||||
} else if(loc.x == get_map().w() && loc.y == -1) { // top right corner
|
||||
// We use the map idea of odd and even, and map coords are internal coords + 1
|
||||
if(loc.x%2 == 0) {
|
||||
drawing_buffer_add(LAYER_BORDER, loc, tblit(xpos, ypos + zoom_/2,
|
||||
image::get_image(theme_.border().corner_image_top_right_odd, image::SCALED_TO_ZOOM)));
|
||||
drawing_buffer_add(LAYER_BORDER, loc, xpos, ypos + zoom_/2,
|
||||
image::get_image(theme_.border().corner_image_top_right_odd, image::SCALED_TO_ZOOM));
|
||||
} else {
|
||||
drawing_buffer_add(LAYER_BORDER, loc, tblit(xpos, ypos,
|
||||
image::get_image(theme_.border().corner_image_top_right_even, image::SCALED_TO_ZOOM)));
|
||||
drawing_buffer_add(LAYER_BORDER, loc, xpos, ypos,
|
||||
image::get_image(theme_.border().corner_image_top_right_even, image::SCALED_TO_ZOOM));
|
||||
}
|
||||
} else if(loc.x == -1 && loc.y == get_map().h()) { // bottom left corner
|
||||
drawing_buffer_add(LAYER_BORDER, loc, tblit(xpos + zoom_/4, ypos,
|
||||
image::get_image(theme_.border().corner_image_bottom_left, image::SCALED_TO_ZOOM)));
|
||||
drawing_buffer_add(LAYER_BORDER, loc, xpos + zoom_/4, ypos,
|
||||
image::get_image(theme_.border().corner_image_bottom_left, image::SCALED_TO_ZOOM));
|
||||
|
||||
} else if(loc.x == get_map().w() && loc.y == get_map().h()) { // bottom right corner
|
||||
// We use the map idea of odd and even, and map coords are internal coords + 1
|
||||
if(loc.x%2 == 1) {
|
||||
drawing_buffer_add(LAYER_BORDER, loc, tblit(xpos, ypos,
|
||||
image::get_image(theme_.border().corner_image_bottom_right_even, image::SCALED_TO_ZOOM)));
|
||||
drawing_buffer_add(LAYER_BORDER, loc, xpos, ypos,
|
||||
image::get_image(theme_.border().corner_image_bottom_right_even, image::SCALED_TO_ZOOM));
|
||||
} else {
|
||||
drawing_buffer_add(LAYER_BORDER, loc, tblit(xpos, ypos,
|
||||
image::get_image(theme_.border().corner_image_bottom_right_odd, image::SCALED_TO_ZOOM)));
|
||||
drawing_buffer_add(LAYER_BORDER, loc, xpos, ypos,
|
||||
image::get_image(theme_.border().corner_image_bottom_right_odd, image::SCALED_TO_ZOOM));
|
||||
}
|
||||
|
||||
// Now handle the sides:
|
||||
} else if(loc.x == -1) { // left side
|
||||
drawing_buffer_add(LAYER_BORDER, loc, tblit(xpos + zoom_/4, ypos,
|
||||
image::get_image(theme_.border().border_image_left, image::SCALED_TO_ZOOM)));
|
||||
drawing_buffer_add(LAYER_BORDER, loc, xpos + zoom_/4, ypos,
|
||||
image::get_image(theme_.border().border_image_left, image::SCALED_TO_ZOOM));
|
||||
} else if(loc.x == get_map().w()) { // right side
|
||||
drawing_buffer_add(LAYER_BORDER, loc, tblit(xpos + zoom_/4, ypos,
|
||||
image::get_image(theme_.border().border_image_right, image::SCALED_TO_ZOOM)));
|
||||
drawing_buffer_add(LAYER_BORDER, loc, xpos + zoom_/4, ypos,
|
||||
image::get_image(theme_.border().border_image_right, image::SCALED_TO_ZOOM));
|
||||
} else if(loc.y == -1) { // top side
|
||||
// We use the map idea of odd and even, and map coords are internal coords + 1
|
||||
if(loc.x%2 == 1) {
|
||||
drawing_buffer_add(LAYER_BORDER, loc, tblit(xpos, ypos,
|
||||
image::get_image(theme_.border().border_image_top_even, image::SCALED_TO_ZOOM)));
|
||||
drawing_buffer_add(LAYER_BORDER, loc, xpos, ypos,
|
||||
image::get_image(theme_.border().border_image_top_even, image::SCALED_TO_ZOOM));
|
||||
} else {
|
||||
drawing_buffer_add(LAYER_BORDER, loc, tblit(xpos, ypos + zoom_/2,
|
||||
image::get_image(theme_.border().border_image_top_odd, image::SCALED_TO_ZOOM)));
|
||||
drawing_buffer_add(LAYER_BORDER, loc, xpos, ypos + zoom_/2,
|
||||
image::get_image(theme_.border().border_image_top_odd, image::SCALED_TO_ZOOM));
|
||||
}
|
||||
} else if(loc.y == get_map().h()) { // bottom side
|
||||
// We use the map idea of odd and even, and map coords are internal coords + 1
|
||||
if(loc.x%2 == 1) {
|
||||
drawing_buffer_add(LAYER_BORDER, loc, tblit(xpos, ypos,
|
||||
image::get_image(theme_.border().border_image_bottom_even, image::SCALED_TO_ZOOM)));
|
||||
drawing_buffer_add(LAYER_BORDER, loc, xpos, ypos,
|
||||
image::get_image(theme_.border().border_image_bottom_even, image::SCALED_TO_ZOOM));
|
||||
} else {
|
||||
drawing_buffer_add(LAYER_BORDER, loc, tblit(xpos, ypos + zoom_/2,
|
||||
image::get_image(theme_.border().border_image_bottom_odd, image::SCALED_TO_ZOOM)));
|
||||
drawing_buffer_add(LAYER_BORDER, loc, xpos, ypos + zoom_/2,
|
||||
image::get_image(theme_.border().border_image_bottom_odd, image::SCALED_TO_ZOOM));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2039,20 +2038,20 @@ void display::draw_hex(const map_location& loc) {
|
|||
const time_of_day& tod = get_time_of_day(loc);
|
||||
if(!shrouded(loc)) {
|
||||
// unshrouded terrain (the normal case)
|
||||
drawing_buffer_add(LAYER_TERRAIN_BG, loc, tblit(xpos, ypos,
|
||||
get_terrain_images(loc,tod.id, image_type, BACKGROUND)));
|
||||
drawing_buffer_add(LAYER_TERRAIN_BG, loc, xpos, ypos,
|
||||
get_terrain_images(loc,tod.id, image_type, BACKGROUND));
|
||||
|
||||
drawing_buffer_add(LAYER_TERRAIN_FG, loc, tblit(xpos, ypos,
|
||||
get_terrain_images(loc,tod.id,image_type, FOREGROUND)));
|
||||
drawing_buffer_add(LAYER_TERRAIN_FG, loc, xpos, ypos,
|
||||
get_terrain_images(loc,tod.id,image_type, FOREGROUND));
|
||||
|
||||
// Draw the grid, if that's been enabled
|
||||
if(grid_ && on_map && !off_map_tile) {
|
||||
static const image::locator grid_top(game_config::images::grid_top);
|
||||
drawing_buffer_add(LAYER_GRID_TOP, loc, tblit(xpos, ypos,
|
||||
image::get_image(grid_top, image::TOD_COLORED)));
|
||||
drawing_buffer_add(LAYER_GRID_TOP, loc, xpos, ypos,
|
||||
image::get_image(grid_top, image::TOD_COLORED));
|
||||
static const image::locator grid_bottom(game_config::images::grid_bottom);
|
||||
drawing_buffer_add(LAYER_GRID_BOTTOM, loc, tblit(xpos, ypos,
|
||||
image::get_image(grid_bottom, image::TOD_COLORED)));
|
||||
drawing_buffer_add(LAYER_GRID_BOTTOM, loc, xpos, ypos,
|
||||
image::get_image(grid_bottom, image::TOD_COLORED));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2060,16 +2059,16 @@ void display::draw_hex(const map_location& loc) {
|
|||
// tod may differ from tod if hex is illuminated.
|
||||
const std::string& tod_hex_mask = tod.image_mask;
|
||||
if(tod_hex_mask1 != NULL || tod_hex_mask2 != NULL) {
|
||||
drawing_buffer_add(LAYER_TERRAIN_FG, loc, tblit(xpos, ypos, tod_hex_mask1));
|
||||
drawing_buffer_add(LAYER_TERRAIN_FG, loc, tblit(xpos, ypos, tod_hex_mask2));
|
||||
drawing_buffer_add(LAYER_TERRAIN_FG, loc, xpos, ypos, tod_hex_mask1);
|
||||
drawing_buffer_add(LAYER_TERRAIN_FG, loc, xpos, ypos, tod_hex_mask2);
|
||||
} else if(!tod_hex_mask.empty()) {
|
||||
drawing_buffer_add(LAYER_TERRAIN_FG, loc, tblit(xpos, ypos,
|
||||
image::get_image(tod_hex_mask,image::SCALED_TO_HEX)));
|
||||
drawing_buffer_add(LAYER_TERRAIN_FG, loc, xpos, ypos,
|
||||
image::get_image(tod_hex_mask,image::SCALED_TO_HEX));
|
||||
}
|
||||
|
||||
// Paint mouseover overlays
|
||||
if(loc == mouseoverHex_ && (on_map || (in_editor() && get_map().on_board_with_border(loc))) && mouseover_hex_overlay_ != NULL) {
|
||||
drawing_buffer_add(LAYER_MOUSEOVER_OVERLAY, loc, tblit(xpos, ypos, mouseover_hex_overlay_));
|
||||
drawing_buffer_add(LAYER_MOUSEOVER_OVERLAY, loc, xpos, ypos, mouseover_hex_overlay_);
|
||||
}
|
||||
|
||||
// Paint arrows
|
||||
|
@ -2085,23 +2084,23 @@ void display::draw_hex(const map_location& loc) {
|
|||
// We apply void also on off-map tiles
|
||||
// to shroud the half-hexes too
|
||||
const std::string& shroud_image = get_variant(shroud_images_, loc);
|
||||
drawing_buffer_add(LAYER_FOG_SHROUD, loc, tblit(xpos, ypos,
|
||||
image::get_image(shroud_image, image_type)));
|
||||
drawing_buffer_add(LAYER_FOG_SHROUD, loc, xpos, ypos,
|
||||
image::get_image(shroud_image, image_type));
|
||||
} else if(fogged(loc)) {
|
||||
const std::string& fog_image = get_variant(fog_images_, loc);
|
||||
drawing_buffer_add(LAYER_FOG_SHROUD, loc, tblit(xpos, ypos,
|
||||
image::get_image(fog_image, image_type)));
|
||||
drawing_buffer_add(LAYER_FOG_SHROUD, loc, xpos, ypos,
|
||||
image::get_image(fog_image, image_type));
|
||||
}
|
||||
|
||||
if(!shrouded(loc)) {
|
||||
drawing_buffer_add(LAYER_FOG_SHROUD, loc, tblit(xpos, ypos, get_fog_shroud_images(loc, image_type)));
|
||||
drawing_buffer_add(LAYER_FOG_SHROUD, loc, xpos, ypos, get_fog_shroud_images(loc, image_type));
|
||||
}
|
||||
|
||||
if(on_map && loc == mouseoverHex_) {
|
||||
drawing_buffer_add(LAYER_MOUSEOVER_TOP,
|
||||
loc, tblit(xpos, ypos, image::get_image("misc/hover-hex-top.png", image::SCALED_TO_HEX)));
|
||||
loc, xpos, ypos, image::get_image("misc/hover-hex-top.png", image::SCALED_TO_HEX));
|
||||
drawing_buffer_add(LAYER_MOUSEOVER_BOTTOM,
|
||||
loc, tblit(xpos, ypos, image::get_image("misc/hover-hex-bottom.png", image::SCALED_TO_HEX)));
|
||||
loc, xpos, ypos, image::get_image("misc/hover-hex-bottom.png", image::SCALED_TO_HEX));
|
||||
}
|
||||
|
||||
if (on_map) {
|
||||
|
@ -2118,8 +2117,8 @@ void display::draw_hex(const map_location& loc) {
|
|||
} else {
|
||||
off_y -= text->h / 2;
|
||||
}
|
||||
drawing_buffer_add(LAYER_FOG_SHROUD, loc, tblit(off_x, off_y, bg));
|
||||
drawing_buffer_add(LAYER_FOG_SHROUD, loc, tblit(off_x, off_y, text));
|
||||
drawing_buffer_add(LAYER_FOG_SHROUD, loc, off_x, off_y, bg);
|
||||
drawing_buffer_add(LAYER_FOG_SHROUD, loc, off_x, off_y, text);
|
||||
}
|
||||
if (draw_terrain_codes_ && (game_config::debug || !shrouded(loc))) {
|
||||
int off_x = xpos + hex_size()/2;
|
||||
|
@ -2132,14 +2131,14 @@ void display::draw_hex(const map_location& loc) {
|
|||
if (!draw_coordinates_) {
|
||||
off_y -= text->h / 2;
|
||||
}
|
||||
drawing_buffer_add(LAYER_FOG_SHROUD, loc, tblit(off_x, off_y, bg));
|
||||
drawing_buffer_add(LAYER_FOG_SHROUD, loc, tblit(off_x, off_y, text));
|
||||
drawing_buffer_add(LAYER_FOG_SHROUD, loc, off_x, off_y, bg);
|
||||
drawing_buffer_add(LAYER_FOG_SHROUD, loc, off_x, off_y, text);
|
||||
}
|
||||
}
|
||||
|
||||
if(debug_foreground) {
|
||||
drawing_buffer_add(LAYER_UNIT_DEFAULT, loc, tblit(xpos, ypos,
|
||||
image::get_image("terrain/foreground.png", image_type)));
|
||||
drawing_buffer_add(LAYER_UNIT_DEFAULT, loc, xpos, ypos,
|
||||
image::get_image("terrain/foreground.png", image_type));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
153
src/display.hpp
153
src/display.hpp
|
@ -608,41 +608,6 @@ protected:
|
|||
bool local_tod_light_;
|
||||
|
||||
public:
|
||||
/** Helper structure for rendering the terrains. */
|
||||
struct tblit{
|
||||
tblit(const int x, const int y) :
|
||||
x(x),
|
||||
y(y),
|
||||
surf(),
|
||||
clip()
|
||||
{}
|
||||
|
||||
tblit(const int x, const int y, const surface& surf,
|
||||
const SDL_Rect& clip = SDL_Rect()) :
|
||||
x(x),
|
||||
y(y),
|
||||
surf(1, surf),
|
||||
clip(clip)
|
||||
{}
|
||||
|
||||
tblit(const int x, const int y, const std::vector<surface>& surf,
|
||||
const SDL_Rect& clip = SDL_Rect()) :
|
||||
x(x),
|
||||
y(y),
|
||||
surf(surf),
|
||||
clip(clip)
|
||||
{}
|
||||
|
||||
|
||||
int x; /**< x screen coordinate to render at. */
|
||||
int y; /**< y screen coordinate to render at. */
|
||||
std::vector<surface> surf; /**< surface(s) to render. */
|
||||
SDL_Rect clip; /**<
|
||||
* The clipping area of the source if
|
||||
* ommitted the entire source is used.
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* The layers to render something on. This value should never be stored
|
||||
* it's the internal drawing order and adding removing and reordering
|
||||
|
@ -725,38 +690,102 @@ public:
|
|||
|
||||
protected:
|
||||
/**
|
||||
* Compare functor for the blitting.
|
||||
* In order to render a hex properly it needs to be rendered per row. On
|
||||
* this row several layers need to be drawn at the same time. Mainly the
|
||||
* unit and the background terrain. This is needed since both can spill
|
||||
* in the next hex. The foreground terrain needs to be drawn before to
|
||||
* avoid decapitation a unit.
|
||||
*
|
||||
* The blitting order must be sorted on y value first instead of x so added
|
||||
* another functor since map_location::operator< sorts on x value.
|
||||
* In other words:
|
||||
* for every layer
|
||||
* for every row (starting from the top)
|
||||
* for every hex in the row
|
||||
* ...
|
||||
*
|
||||
* this is modified to:
|
||||
* for every layer group
|
||||
* for every row (starting from the top)
|
||||
* for every layer in the group
|
||||
* for every hex in the row
|
||||
* ...
|
||||
*
|
||||
* * Surfaces are rendered per level in a map.
|
||||
* * Per level the items are rendered per location these locations are
|
||||
* stored in the drawing order required for units.
|
||||
* * every location has a vector with surfaces, each with its own screen
|
||||
* coordinate to render at.
|
||||
* * every vector element has a vector with surfaces to render.
|
||||
*/
|
||||
struct draw_order
|
||||
class drawing_buffer_key
|
||||
{
|
||||
bool operator()(const map_location& lhs, const map_location& rhs) const
|
||||
private:
|
||||
// store x, y, and layer in one 32 bit integer
|
||||
// 4 most significant bits == layer group => 16
|
||||
// 10 second most significant bits == y => 1024
|
||||
// 8 third most significant bits == layer => 256
|
||||
// 10 least significant bits == x => 1024
|
||||
unsigned int key_;
|
||||
|
||||
static const tdrawing_layer layer_groups[];
|
||||
static const unsigned int max_layer_group;
|
||||
|
||||
enum {
|
||||
MaxBorder = 3
|
||||
};
|
||||
public:
|
||||
drawing_buffer_key(const map_location &loc, tdrawing_layer layer)
|
||||
{
|
||||
// use similar y transformation as for on-screen coordinates
|
||||
int ly = lhs.y*2 + lhs.x%2;
|
||||
int ry = rhs.y*2 + rhs.x%2;
|
||||
return ly < ry || (ly == ry && lhs.x < rhs.x);
|
||||
// max_layer_group + 1 is the last valid entry in layer_groups, but it is always > layer
|
||||
// thus the first --g is a given => start with max_layer_groups right away
|
||||
unsigned int g = max_layer_group;
|
||||
while (layer < layer_groups[g]) {
|
||||
--g;
|
||||
}
|
||||
key_ = (g << 28) | (static_cast<unsigned int>(loc.y + MaxBorder) << 18);
|
||||
key_ |= (static_cast<unsigned int>(layer) << 10) | static_cast<unsigned int>(loc.x + MaxBorder);
|
||||
}
|
||||
|
||||
bool operator<(const drawing_buffer_key &rhs) const { return key_ < rhs.key_; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Group of layers:
|
||||
* layers of a group will always be rendered under layers of the next group
|
||||
* regardless of the location
|
||||
*/
|
||||
enum tdrawing_layergroup{
|
||||
LAYERGROUP_TERRAIN_BG,
|
||||
LAYERGROUP_UNIT,
|
||||
LAYERGROUP_UNIT_MOVE,
|
||||
LAYERGROUP_UI
|
||||
/** Helper structure for rendering the terrains. */
|
||||
class tblit
|
||||
{
|
||||
public:
|
||||
tblit(const tdrawing_layer layer, const map_location& loc,
|
||||
const int x, const int y, const surface surf,
|
||||
const SDL_Rect& clip)
|
||||
: x_(x), y_(y), surf_(1, surf), clip_(clip),
|
||||
key_(loc, layer)
|
||||
{}
|
||||
|
||||
tblit(const tdrawing_layer layer, const map_location& loc,
|
||||
const int x, const int y, const std::vector<surface>& surf,
|
||||
const SDL_Rect& clip)
|
||||
: x_(x), y_(y), surf_(surf), clip_(clip),
|
||||
key_(loc, layer)
|
||||
{}
|
||||
|
||||
int x() const { return x_; }
|
||||
int y() const { return y_; }
|
||||
const std::vector<surface> &surf() const { return surf_; }
|
||||
const SDL_Rect &clip() const { return clip_; }
|
||||
|
||||
bool operator<(const tblit &rhs) const { return key_ < rhs.key_; }
|
||||
|
||||
private:
|
||||
int x_; /**< x screen coordinate to render at. */
|
||||
int y_; /**< y screen coordinate to render at. */
|
||||
std::vector<surface> surf_; /**< surface(s) to render. */
|
||||
SDL_Rect clip_; /**<
|
||||
* The clipping area of the source if
|
||||
* ommitted the entire source is used.
|
||||
*/
|
||||
drawing_buffer_key key_;
|
||||
};
|
||||
|
||||
typedef std::map<tdrawing_layer, std::vector<tblit> > tlayer_map;
|
||||
typedef std::map<map_location, tlayer_map, draw_order > tlocation_map;
|
||||
typedef std::map<tdrawing_layergroup, tlocation_map> tgroup_map;
|
||||
tgroup_map drawing_buffer_;
|
||||
typedef std::list<tblit> tdrawing_buffer;
|
||||
tdrawing_buffer drawing_buffer_;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -769,7 +798,13 @@ public:
|
|||
* @param blit The structure to blit.
|
||||
*/
|
||||
void drawing_buffer_add(const tdrawing_layer layer,
|
||||
const map_location& loc, const tblit& blit);
|
||||
const map_location& loc, int x, int y, const surface surf,
|
||||
const SDL_Rect &clip = SDL_Rect());
|
||||
|
||||
void drawing_buffer_add(const tdrawing_layer layer,
|
||||
const map_location& loc, int x, int y,
|
||||
const std::vector<surface> &surf,
|
||||
const SDL_Rect &clip = SDL_Rect());
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -75,18 +75,17 @@ void editor_display::draw_hex(const map_location& loc)
|
|||
{
|
||||
int xpos = get_location_x(loc);
|
||||
int ypos = get_location_y(loc);
|
||||
tblit blit(xpos, ypos);
|
||||
display::draw_hex(loc);
|
||||
if (map().on_board_with_border(loc)) {
|
||||
if (map().in_selection(loc)) {
|
||||
drawing_buffer_add(LAYER_FOG_SHROUD, loc, tblit(xpos, ypos,
|
||||
image::get_image("editor/selection-overlay.png", image::TOD_COLORED)));
|
||||
drawing_buffer_add(LAYER_FOG_SHROUD, loc, xpos, ypos,
|
||||
image::get_image("editor/selection-overlay.png", image::TOD_COLORED));
|
||||
}
|
||||
|
||||
if (brush_locations_.find(loc) != brush_locations_.end()) {
|
||||
static const image::locator brush(game_config::images::editor_brush);
|
||||
drawing_buffer_add(LAYER_MOUSEOVER_OVERLAY, loc, tblit(xpos, ypos,
|
||||
image::get_image(brush, image::SCALED_TO_HEX)));
|
||||
drawing_buffer_add(LAYER_MOUSEOVER_OVERLAY, loc, xpos, ypos,
|
||||
image::get_image(brush, image::SCALED_TO_HEX));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -335,9 +335,8 @@ void game_display::draw_hex(const map_location& loc)
|
|||
const bool on_map = get_map().on_board(loc);
|
||||
const bool is_shrouded = shrouded(loc);
|
||||
const bool is_fogged = fogged(loc);
|
||||
int xpos = get_location_x(loc);
|
||||
int ypos = get_location_y(loc);
|
||||
tblit blit(xpos, ypos);
|
||||
const int xpos = get_location_x(loc);
|
||||
const int ypos = get_location_y(loc);
|
||||
|
||||
image::TYPE image_type = get_image_type(loc);
|
||||
|
||||
|
@ -351,12 +350,12 @@ void game_display::draw_hex(const map_location& loc)
|
|||
overlays.first->second.team_name.find(teams_[playing_team()].team_name()) != std::string::npos)
|
||||
&& !(is_fogged && !overlays.first->second.visible_in_fog))
|
||||
{
|
||||
drawing_buffer_add(LAYER_TERRAIN_BG, loc, tblit(xpos, ypos,
|
||||
image::get_image(overlays.first->second.image,image_type)));
|
||||
drawing_buffer_add(LAYER_TERRAIN_BG, loc, xpos, ypos,
|
||||
image::get_image(overlays.first->second.image,image_type));
|
||||
}
|
||||
}
|
||||
// village-control flags.
|
||||
drawing_buffer_add(LAYER_TERRAIN_BG, loc, tblit(xpos, ypos, get_flag(loc)));
|
||||
drawing_buffer_add(LAYER_TERRAIN_BG, loc, xpos, ypos, get_flag(loc));
|
||||
}
|
||||
|
||||
// Draw reach_map information.
|
||||
|
@ -365,8 +364,8 @@ void game_display::draw_hex(const map_location& loc)
|
|||
if (!is_shrouded && !reach_map_.empty()
|
||||
&& reach_map_.find(loc) == reach_map_.end() && loc != attack_indicator_dst_) {
|
||||
static const image::locator unreachable(game_config::images::unreachable);
|
||||
drawing_buffer_add(LAYER_REACHMAP, loc, tblit(xpos, ypos,
|
||||
image::get_image(unreachable,image::SCALED_TO_HEX)));
|
||||
drawing_buffer_add(LAYER_REACHMAP, loc, xpos, ypos,
|
||||
image::get_image(unreachable,image::SCALED_TO_HEX));
|
||||
}
|
||||
|
||||
resources::whiteboard->draw_hex(loc);
|
||||
|
@ -376,31 +375,30 @@ void game_display::draw_hex(const map_location& loc)
|
|||
// Footsteps indicating a movement path
|
||||
const std::vector<surface>& footstepImages = footsteps_images(loc);
|
||||
if (footstepImages.size() != 0) {
|
||||
drawing_buffer_add(LAYER_FOOTSTEPS, loc, tblit(xpos, ypos, footstepImages));
|
||||
drawing_buffer_add(LAYER_FOOTSTEPS, loc, xpos, ypos, footstepImages);
|
||||
}
|
||||
}
|
||||
// Draw the attack direction indicator
|
||||
if(on_map && loc == attack_indicator_src_) {
|
||||
drawing_buffer_add(LAYER_ATTACK_INDICATOR, loc, tblit(xpos, ypos,
|
||||
image::get_image("misc/attack-indicator-src-" + attack_indicator_direction() + ".png", image::SCALED_TO_HEX)));
|
||||
drawing_buffer_add(LAYER_ATTACK_INDICATOR, loc, xpos, ypos,
|
||||
image::get_image("misc/attack-indicator-src-" + attack_indicator_direction() + ".png", image::SCALED_TO_HEX));
|
||||
} else if (on_map && loc == attack_indicator_dst_) {
|
||||
drawing_buffer_add(LAYER_ATTACK_INDICATOR, loc, tblit(xpos, ypos,
|
||||
image::get_image("misc/attack-indicator-dst-" + attack_indicator_direction() + ".png", image::SCALED_TO_HEX)));
|
||||
drawing_buffer_add(LAYER_ATTACK_INDICATOR, loc, xpos, ypos,
|
||||
image::get_image("misc/attack-indicator-dst-" + attack_indicator_direction() + ".png", image::SCALED_TO_HEX));
|
||||
}
|
||||
|
||||
// Linger overlay unconditionally otherwise it might give glitches
|
||||
// so it's drawn over the shroud and fog.
|
||||
if(game_mode_ != RUNNING) {
|
||||
static const image::locator linger(game_config::images::linger);
|
||||
blit.surf.push_back(image::get_image(linger, image::TOD_COLORED));
|
||||
drawing_buffer_add(LAYER_LINGER_OVERLAY, loc, blit);
|
||||
blit.surf.clear();
|
||||
drawing_buffer_add(LAYER_LINGER_OVERLAY, loc, xpos, ypos,
|
||||
image::get_image(linger, image::TOD_COLORED));
|
||||
}
|
||||
|
||||
if(on_map && loc == selectedHex_ && !game_config::images::selected.empty()) {
|
||||
static const image::locator selected(game_config::images::selected);
|
||||
drawing_buffer_add(LAYER_SELECTED_HEX, loc, tblit(xpos, ypos,
|
||||
image::get_image(selected, image::SCALED_TO_HEX)));
|
||||
drawing_buffer_add(LAYER_SELECTED_HEX, loc, xpos, ypos,
|
||||
image::get_image(selected, image::SCALED_TO_HEX));
|
||||
}
|
||||
|
||||
// Show def% and turn to reach infos
|
||||
|
@ -567,8 +565,8 @@ void game_display::draw_bar(const std::string& image, int xpos, int ypos,
|
|||
SDL_Rect bot = create_rect(0, bar_loc.y + skip_rows, surf->w, 0);
|
||||
bot.h = surf->w - bot.y;
|
||||
|
||||
drawing_buffer_add(LAYER_UNIT_BAR, loc, tblit(xpos, ypos, surf, top));
|
||||
drawing_buffer_add(LAYER_UNIT_BAR, loc, tblit(xpos, ypos + top.h, surf, bot));
|
||||
drawing_buffer_add(LAYER_UNIT_BAR, loc, xpos, ypos, surf, top);
|
||||
drawing_buffer_add(LAYER_UNIT_BAR, loc, xpos, ypos + top.h, surf, bot);
|
||||
|
||||
size_t unfilled = static_cast<size_t>(height * (1.0 - filled));
|
||||
|
||||
|
@ -577,7 +575,7 @@ void game_display::draw_bar(const std::string& image, int xpos, int ypos,
|
|||
surface filled_surf = create_compatible_surface(bar_surf, bar_loc.w, height - unfilled);
|
||||
SDL_Rect filled_area = create_rect(0, 0, bar_loc.w, height-unfilled);
|
||||
SDL_FillRect(filled_surf,&filled_area,SDL_MapRGBA(bar_surf->format,col.r,col.g,col.b, r_alpha));
|
||||
drawing_buffer_add(LAYER_UNIT_BAR, loc, tblit(xpos + bar_loc.x, ypos + bar_loc.y + unfilled, filled_surf));
|
||||
drawing_buffer_add(LAYER_UNIT_BAR, loc, xpos + bar_loc.x, ypos + bar_loc.y + unfilled, filled_surf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -614,23 +612,23 @@ void game_display::draw_movement_info(const map_location& loc)
|
|||
int ypos = get_location_y(loc);
|
||||
|
||||
if (w->second.invisible) {
|
||||
drawing_buffer_add(LAYER_MOVE_INFO, loc, tblit(xpos, ypos,
|
||||
image::get_image("misc/hidden.png", image::SCALED_TO_HEX)));
|
||||
drawing_buffer_add(LAYER_MOVE_INFO, loc, xpos, ypos,
|
||||
image::get_image("misc/hidden.png", image::SCALED_TO_HEX));
|
||||
}
|
||||
|
||||
if (w->second.zoc) {
|
||||
drawing_buffer_add(LAYER_MOVE_INFO, loc, tblit(xpos, ypos,
|
||||
image::get_image("misc/zoc.png", image::SCALED_TO_HEX)));
|
||||
drawing_buffer_add(LAYER_MOVE_INFO, loc, xpos, ypos,
|
||||
image::get_image("misc/zoc.png", image::SCALED_TO_HEX));
|
||||
}
|
||||
|
||||
if (w->second.capture) {
|
||||
drawing_buffer_add(LAYER_MOVE_INFO, loc, tblit(xpos, ypos,
|
||||
image::get_image("misc/capture.png", image::SCALED_TO_HEX)));
|
||||
drawing_buffer_add(LAYER_MOVE_INFO, loc, xpos, ypos,
|
||||
image::get_image("misc/capture.png", image::SCALED_TO_HEX));
|
||||
}
|
||||
|
||||
if (w->second.pass_here) {
|
||||
drawing_buffer_add(LAYER_MOVE_INFO, loc, tblit(xpos, ypos,
|
||||
image::get_image("misc/waypoint.png", image::SCALED_TO_HEX)));
|
||||
drawing_buffer_add(LAYER_MOVE_INFO, loc, xpos, ypos,
|
||||
image::get_image("misc/waypoint.png", image::SCALED_TO_HEX));
|
||||
}
|
||||
|
||||
//we display turn info only if different from a simple last "1"
|
||||
|
|
10
src/unit.cpp
10
src/unit.cpp
|
@ -1891,13 +1891,13 @@ void unit::redraw_unit()
|
|||
if (ellipse_back != NULL) {
|
||||
//disp.drawing_buffer_add(display::LAYER_UNIT_BG, loc,
|
||||
disp.drawing_buffer_add(display::LAYER_UNIT_FIRST, loc_,
|
||||
display::tblit(xsrc, ysrc +adjusted_params.y-ellipse_floating, ellipse_back));
|
||||
xsrc, ysrc +adjusted_params.y-ellipse_floating, ellipse_back);
|
||||
}
|
||||
|
||||
if (ellipse_front != NULL) {
|
||||
//disp.drawing_buffer_add(display::LAYER_UNIT_FG, loc,
|
||||
disp.drawing_buffer_add(display::LAYER_UNIT_FIRST, loc_,
|
||||
display::tblit(xsrc, ysrc +adjusted_params.y-ellipse_floating, ellipse_front));
|
||||
xsrc, ysrc +adjusted_params.y-ellipse_floating, ellipse_front);
|
||||
}
|
||||
if(draw_bars) {
|
||||
const image::locator* orb_img = NULL;
|
||||
|
@ -1930,7 +1930,7 @@ void unit::redraw_unit()
|
|||
surface orb(image::get_image(*orb_img,image::SCALED_TO_ZOOM));
|
||||
if (orb != NULL) {
|
||||
disp.drawing_buffer_add(display::LAYER_UNIT_BAR,
|
||||
loc_, display::tblit(xsrc, ysrc +adjusted_params.y, orb));
|
||||
loc_, xsrc, ysrc +adjusted_params.y, orb);
|
||||
}
|
||||
|
||||
double unit_energy = 0.0;
|
||||
|
@ -1966,7 +1966,7 @@ void unit::redraw_unit()
|
|||
// crown = adjust_surface_alpha(crown, bar_alpha);
|
||||
//}
|
||||
disp.drawing_buffer_add(display::LAYER_UNIT_BAR,
|
||||
loc_, display::tblit(xsrc, ysrc +adjusted_params.y, crown));
|
||||
loc_, xsrc, ysrc +adjusted_params.y, crown);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1974,7 +1974,7 @@ void unit::redraw_unit()
|
|||
const surface ov_img(image::get_image(*ov, image::SCALED_TO_ZOOM));
|
||||
if(ov_img != NULL) {
|
||||
disp.drawing_buffer_add(display::LAYER_UNIT_BAR,
|
||||
loc_, display::tblit(xsrc, ysrc +adjusted_params.y, ov_img));
|
||||
loc_, xsrc, ysrc +adjusted_params.y, ov_img);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -160,16 +160,16 @@ void attack::draw_hex(const map_location& hex)
|
|||
int xpos = resources::screen->get_location_x(get_dest_hex());
|
||||
int ypos = resources::screen->get_location_y(get_dest_hex());
|
||||
|
||||
resources::screen->drawing_buffer_add(layer, get_dest_hex(), display::tblit(xpos, ypos,
|
||||
image::get_image("whiteboard/attack-indicator-src-" + direction_text + ".png", image::SCALED_TO_HEX)));
|
||||
resources::screen->drawing_buffer_add(layer, get_dest_hex(), xpos, ypos,
|
||||
image::get_image("whiteboard/attack-indicator-src-" + direction_text + ".png", image::SCALED_TO_HEX));
|
||||
}
|
||||
else if (hex == target_hex_) //add symbol to defender hex
|
||||
{
|
||||
int xpos = resources::screen->get_location_x(target_hex_);
|
||||
int ypos = resources::screen->get_location_y(target_hex_);
|
||||
|
||||
resources::screen->drawing_buffer_add(layer, target_hex_, display::tblit(xpos, ypos,
|
||||
image::get_image("whiteboard/attack-indicator-dst-" + direction_text + ".png", image::SCALED_TO_HEX)));
|
||||
resources::screen->drawing_buffer_add(layer, target_hex_, xpos, ypos,
|
||||
image::get_image("whiteboard/attack-indicator-dst-" + direction_text + ".png", image::SCALED_TO_HEX));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue