Brainstormed with alink about a new drawing framework and added that.

Upon zookeeper's request make the linger overlay on top of units
(not on top of halos since that gives glitches).
This commit is contained in:
Mark de Wever 2007-11-30 05:17:32 +00:00
parent 44f9238c1e
commit 9856f2cceb
5 changed files with 130 additions and 3 deletions

View file

@ -58,6 +58,9 @@ Version 1.3.11+svn:
* fix bug #8991: Load a second savegame crash when using --test option
* map editor and terrains:
* added village count to editor
* miscellaneous and bug fixes:
* added a new drawing framework only used for linger overlays at the
moment, other stuff can be converted later
Version 1.3.11:
* campaigns

View file

@ -77,7 +77,9 @@ display::display(CVideo& video, const gamemap& map, const config& theme_cfg, con
invalidateGameStatus_(true),
map_labels_(*this,map, 0),
_scroll_event("scrolled"),
nextDraw_(0), fps_handle_(0),
nextDraw_(0),
drawing_buffer_(LAYER_LAST_LAYER),
fps_handle_(0),
idle_anim_(preferences::idle_anim()),
idle_anim_rate_(1.0)
{
@ -602,6 +604,59 @@ void display::tile_stack_render(int x, int y)
update_rect(x, y, zoom_, zoom_);
}
void display::drawing_buffer_commit()
{
SDL_Rect clip_rect = map_area();
surface const dst(screen_.getSurface());
clip_rect_setter set_clip_rect(dst, clip_rect);
// Simply go down all levels in the drawing_buffer_ and render them.
for(tdrawing_buffer::const_iterator
layer_itor = drawing_buffer_.begin(),
layer_itor_end = drawing_buffer_.end();
layer_itor != layer_itor_end; ++layer_itor) {
for(std::map<int, std::vector<tblit> >::const_iterator
drawing_iterator = layer_itor->begin(),
drawing_iterator_end = layer_itor->end();
drawing_iterator != drawing_iterator_end; ++drawing_iterator) {
for(std::vector<tblit>::const_iterator
blit_itor = drawing_iterator->second.begin(),
blit_itor_end = drawing_iterator->second.end();
blit_itor != blit_itor_end; ++blit_itor) {
for(std::vector<surface>::const_iterator
surface_itor = blit_itor->surf.begin(),
surface_itor_end = blit_itor->surf.end();
surface_itor != surface_itor_end; ++surface_itor) {
// 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 = { blit_itor->x, blit_itor->y, 0, 0 };
SDL_BlitSurface(*surface_itor, NULL, dst, &dstrect);
}
}
}
}
drawing_buffer_clear();
}
void display::drawing_buffer_clear()
{
// Note clear the items, the vector should remain the same size.
surface const dst(screen_.getSurface());
for(tdrawing_buffer::iterator layer_itor =
drawing_buffer_.begin(),
layer_itor_end = drawing_buffer_.end();
layer_itor != layer_itor_end; ++layer_itor) {
layer_itor->clear();
}
}
void display::sunset(const size_t delay)
{
// This allow both parametric and toggle use

View file

@ -414,6 +414,60 @@ protected:
void tile_stack_render(int x, int y);
void tile_stack_clear() {tile_stack_.clear();};
//! Helper structure for rendering the terrains.
struct tblit{
tblit(const int x, const int y, const surface& surf) :
x(x),
y(y),
surf()
{}
int x; //!< x screen coordinate to render at
int y; //!< y screen coordinate to render at
std::vector<surface> surf; //!< surface(s) to render
};
//! The layers to render something on. This value should never be stored
//! it's the internal drawing order and adding removing and reordering
//! the layers should be save.
//! If needed in WML use the name and map that to the enum value.
enum tdrawing_layer{
//LAYER_TERRAIN_BG, //! Sample for terrain drawn behind a unit.
//LAYER_UNIT, //! Sample for the layer to draw a unit on.
//LAYER_TERRAIN_FG, //! Sample for terrain to draw in front of a unit.
LAYER_LINGER_OVERLAY, //! The overlay used for the linger mode.
LAYER_LAST_LAYER //! Don't draw to this layer it's a dummy
//! to size the vector.
};
//! * Surfaces are rendered per level in a vector.
//! * 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.
typedef std::vector<std::map<int /*drawing_order*/, std::vector<tblit> > > tdrawing_buffer;
tdrawing_buffer drawing_buffer_;
public:
//! Add an item to the drawing buffer.
//!
//! @param layer The layer to draw on.
//! @param drawing_order The order in which to draw, needed for units.
//! @param blit The structure to blit.
void drawing_buffer_add(const tdrawing_layer layer, const int drawing_order, const tblit& blit)
{ drawing_buffer_[layer][drawing_order].push_back(blit); }
protected:
//! Draws the drawing_buffer_ and clears it.
void drawing_buffer_commit();
//! Clears the drawing buffer.
void drawing_buffer_clear();
//! redraw all panels associated with the map display
void draw_all_panels();

View file

@ -229,7 +229,6 @@ void game_display::scroll_to_leader(unit_map& units, int side)
}
}
void game_display::draw(bool update,bool force)
{
if (screen_.update_locked()) {
@ -276,6 +275,9 @@ void game_display::draw(bool update,bool force)
int xpos = get_location_x(*it);
int ypos = get_location_y(*it);
tblit blit(xpos, ypos, 0);
int drawing_order = gamemap::get_drawing_order(*it);
// Store invalidated units
if ((temp_unit_ && temp_unit_loc_==*it) || units_.find(*it) != units_.end()) {
unit_invals.insert(*it);
@ -401,7 +403,9 @@ void game_display::draw(bool update,bool force)
} else if(fogged(*it)) {
tile_stack_append(image::get_image(fog_image, image::SCALED_TO_HEX));
} else if(game_mode_ != RUNNING) {
tile_stack_append(image::get_image(game_config::linger_image, image::SCALED_TO_HEX));
blit.surf.push_back(image::get_image(game_config::linger_image, image::SCALED_TO_HEX));
drawing_buffer_add(LAYER_LINGER_OVERLAY, drawing_order, blit);
blit.surf.clear();
}
if(!is_shrouded) {
@ -441,6 +445,9 @@ void game_display::draw(bool update,bool force)
invalidated_.clear();
}
drawing_buffer_commit();
halo::render();
draw_sidebar();

View file

@ -105,6 +105,14 @@ public:
static const location null_location;
};
//! Drawing order, copied from ordered_draw in display.hpp.
//!
//! This returns the order in which the units should be drawn so they overlap
//! propererly.
static int get_drawing_order (const gamemap::location& loc )
{ return (loc.y * 2 + loc.x % 2) * 1024; }
const t_translation::t_list& underlying_mvt_terrain(const location& loc) const
{ return underlying_mvt_terrain(get_terrain(loc)); }
const t_translation::t_list& underlying_def_terrain(const location& loc) const