Display: work on refactoring the main drawing system
Previously, every visible hex was iterated over and every element in that hex draw. This was inefficient for two reasons: First, it meant the performance footprint for many operations like unit drawing was O(n²), since the list of elements had to be checked for every single hex. Second, it meant the renderer had to switch active textures many more times than necessary. My new system involved drawing every element of a specific type at once - ie, all background terrains at once, all units, all items, etc. This reduces lookup time from O(n²) to O(n) and results in a noticeable performance increase. It also reduces the number of times the renderer needs to switch active textures, since bulk draws such as the map grid overlay are now done all at once while that specific texture is active. There are still some layering issues and missing elements that need to be sorted, especially in game_display.
This commit is contained in:
parent
0d69cbad69
commit
345fa27565
6 changed files with 384 additions and 189 deletions
310
src/display.cpp
310
src/display.cpp
|
@ -722,6 +722,14 @@ int display::get_location_y(const map_location& loc) const
|
|||
return static_cast<int>(map_area().y + (loc.y + theme_.border().size) * zoom_ - ypos_ + (is_odd(loc.x) ? zoom_/2 : 0));
|
||||
}
|
||||
|
||||
SDL_Point display::get_loc_drawing_origin(const map_location& loc) const
|
||||
{
|
||||
return {
|
||||
get_location_x(loc),
|
||||
get_location_y(loc)
|
||||
};
|
||||
}
|
||||
|
||||
map_location display::minimap_location_on(int x, int y)
|
||||
{
|
||||
//TODO: don't return location for this,
|
||||
|
@ -2564,40 +2572,102 @@ void display::redraw_everything()
|
|||
// NEW RENDERING CODE =========================================================================
|
||||
//
|
||||
|
||||
void display::draw_hex(const map_location& loc)
|
||||
void display::draw_hex(const map_location& /*loc*/)
|
||||
{
|
||||
const int xpos = get_location_x(loc);
|
||||
const int ypos = get_location_y(loc);
|
||||
// DO NOTHING
|
||||
}
|
||||
|
||||
image::TYPE image_type = get_image_type(loc);
|
||||
void display::draw_hex_overlays()
|
||||
{
|
||||
// DO NOTHING
|
||||
}
|
||||
|
||||
const bool on_map = get_map().on_board(loc);
|
||||
const time_of_day& tod = get_time_of_day(loc);
|
||||
|
||||
const bool is_shrouded = shrouded(loc);
|
||||
const bool is_fogged = fogged(loc);
|
||||
|
||||
std::vector<texture> images_fg = get_terrain_images(loc, tod.id, image_type, FOREGROUND);
|
||||
std::vector<texture> images_bg = get_terrain_images(loc, tod.id, image_type, BACKGROUND);
|
||||
|
||||
// Some debug output (TODO)
|
||||
//const int num_images_fg = images_fg.size();
|
||||
//const int num_images_bg = images_bg.size();
|
||||
|
||||
if(!is_shrouded) {
|
||||
//
|
||||
// Background terrains
|
||||
//
|
||||
for(const texture& t : images_bg) {
|
||||
render_scaled_to_zoom(t, xpos, ypos);
|
||||
void display::draw_visible_hexes(const rect_of_hexes& visible_hexes, TERRAIN_TYPE terrain_type)
|
||||
{
|
||||
for(const map_location& loc : visible_hexes) {
|
||||
if(shrouded(loc)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Village flags
|
||||
//
|
||||
const texture& flag = get_flag(loc);
|
||||
if(flag) {
|
||||
render_scaled_to_zoom(flag, xpos, ypos);
|
||||
image::TYPE image_type = get_image_type(loc);
|
||||
const time_of_day& tod = get_time_of_day(loc);
|
||||
|
||||
for(const texture& t : get_terrain_images(loc, tod.id, image_type, terrain_type)) {
|
||||
render_scaled_to_zoom(t, loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void display::draw_gamemap()
|
||||
{
|
||||
// Currenty visible hexes.
|
||||
const rect_of_hexes& visible_hexes = get_visible_hexes();
|
||||
|
||||
//
|
||||
// Background terrains
|
||||
//
|
||||
draw_visible_hexes(visible_hexes, BACKGROUND);
|
||||
|
||||
//
|
||||
// On-map overlays, such as [item]s.
|
||||
//
|
||||
for(const auto& overlay_record : *overlays_) {
|
||||
const map_location& o_loc = overlay_record.first;
|
||||
|
||||
if(shrouded(o_loc)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const overlay& item = overlay_record.second;
|
||||
const std::string& current_team_name = dc_->teams()[viewing_team()].team_name();
|
||||
|
||||
if((item.team_name.empty() || item.team_name.find(current_team_name) != std::string::npos) &&
|
||||
(!fogged(o_loc) || item.visible_in_fog))
|
||||
{
|
||||
const texture tex = item.image.find("~NO_TOD_SHIFT()") == std::string::npos
|
||||
? image::get_texture(item.image) // TODO
|
||||
: image::get_texture(item.image);
|
||||
|
||||
// was: SCALED_TO_HEX
|
||||
render_scaled_to_zoom(tex, o_loc);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Village flags
|
||||
//
|
||||
for(const team& t : dc_->teams()) {
|
||||
auto& flag = flags_[t.side() - 1];
|
||||
flag.update_last_draw_time();
|
||||
|
||||
for(const map_location& v_loc : t.villages()) {
|
||||
if(!fogged(v_loc) || !dc_->get_team(viewing_side()).is_enemy(t.side())) {
|
||||
|
||||
// TODO: move this if-animated check to a helper function.
|
||||
const image::locator& flag_image = animate_map_
|
||||
? flag.get_current_frame()
|
||||
: flag.get_first_frame();
|
||||
|
||||
render_scaled_to_zoom(image::get_texture(flag_image), v_loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The grid overlay, if that's been enabled
|
||||
//
|
||||
if(grid_) {
|
||||
for(const map_location& loc : visible_hexes) {
|
||||
if(shrouded(loc)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: split into drawing layers? If not, combine into one image or texture.
|
||||
static const texture grid_top = image::get_texture(game_config::images::grid_top);
|
||||
render_scaled_to_zoom(grid_top, loc);
|
||||
|
||||
static const texture grid_bottom = image::get_texture(game_config::images::grid_bottom);
|
||||
render_scaled_to_zoom(grid_bottom, loc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2605,47 +2675,88 @@ void display::draw_hex(const map_location& loc)
|
|||
// Units
|
||||
//
|
||||
if(!dc_->teams().empty()) {
|
||||
// TODO: why is this created every time?
|
||||
unit_drawer drawer = unit_drawer(*this);
|
||||
|
||||
auto u_it = dc_->units().find(loc);
|
||||
auto request = exclusive_unit_draw_requests_.find(loc);
|
||||
|
||||
// Real units
|
||||
if(u_it != dc_->units().end() && (request == exclusive_unit_draw_requests_.end() || request->second == u_it->id())) {
|
||||
drawer.redraw_unit(*u_it);
|
||||
for(const unit& real_unit : dc_->units()) {
|
||||
drawer.redraw_unit(real_unit);
|
||||
}
|
||||
|
||||
// Fake (moving) units
|
||||
for(const unit* temp_unit : *fake_unit_man_) {
|
||||
if(request == exclusive_unit_draw_requests_.end() || request->second == temp_unit->id()) {
|
||||
drawer.redraw_unit(*temp_unit);
|
||||
drawer.redraw_unit(*temp_unit);
|
||||
}
|
||||
|
||||
// TODO: re-add exclusionary checks for exclusive_unit_draw_requests_ later on, if necessary.
|
||||
#if 0
|
||||
auto request = exclusive_unit_draw_requests_.find(loc);
|
||||
if(request == exclusive_unit_draw_requests_.end() || request->second == u_it->id()) {};
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Foreground terrains. FIXME! sometimes cut off units...
|
||||
//
|
||||
draw_visible_hexes(visible_hexes, FOREGROUND);
|
||||
|
||||
//
|
||||
// Hex cursor (TODO: split into layers?)
|
||||
//
|
||||
draw_hex_cursor(mouseoverHex_);
|
||||
|
||||
//
|
||||
// Right now just handles halos - see game_display
|
||||
//
|
||||
post_commit();
|
||||
|
||||
draw_hex_overlays();
|
||||
|
||||
//
|
||||
// Shroud and fog
|
||||
//
|
||||
for(const map_location& loc : visible_hexes) {
|
||||
image::TYPE image_type = get_image_type(loc);
|
||||
|
||||
const bool is_shrouded = shrouded(loc);
|
||||
const bool is_fogged = fogged(loc);
|
||||
|
||||
// Main images.
|
||||
if(is_shrouded || is_fogged) {
|
||||
|
||||
// If is_shrouded is false, is_fogged is true
|
||||
const std::string& weather_image = is_shrouded
|
||||
? get_variant(shroud_images_, loc)
|
||||
: get_variant(fog_images_, loc);
|
||||
|
||||
// TODO: image type
|
||||
render_scaled_to_zoom(image::get_texture(weather_image), loc);
|
||||
}
|
||||
|
||||
// Transitions to main hexes.
|
||||
if(!is_shrouded) {
|
||||
for(const texture& t : get_fog_shroud_images(loc, image_type)) {
|
||||
render_scaled_to_zoom(t, loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Foreground terrains
|
||||
//
|
||||
if(!is_shrouded) {
|
||||
for(const texture& t : images_fg) {
|
||||
render_scaled_to_zoom(t, xpos, ypos);
|
||||
}
|
||||
}
|
||||
// ================================================================================
|
||||
// TODO: RE-ADD ALL THIS!
|
||||
// ================================================================================
|
||||
|
||||
#if 0
|
||||
|
||||
//
|
||||
// Mouseover overlays (TODO: delegate to editor)
|
||||
//
|
||||
#if 0
|
||||
if(loc == mouseoverHex_ && (on_map || (in_editor() && get_map().on_board_with_border(loc)))
|
||||
&& mouseover_hex_overlay_ != nullptr)
|
||||
{
|
||||
render_scaled_to_zoom(mouseover_hex_overlay_, xpos, ypos);
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Arrows (whiteboard?)
|
||||
// Arrows (whiteboard?) TODO:
|
||||
//
|
||||
auto arrows_in_hex = arrows_map_.find(loc);
|
||||
if(arrows_in_hex != arrows_map_.end()) {
|
||||
|
@ -2655,56 +2766,8 @@ void display::draw_hex(const map_location& loc)
|
|||
}
|
||||
|
||||
//
|
||||
// Draw the grid overlay, if that's been enabled
|
||||
// ToD Mask
|
||||
//
|
||||
if(!is_shrouded && grid_) {
|
||||
// TODO: split into drawing layers?
|
||||
static const texture grid_top = image::get_texture(game_config::images::grid_top);
|
||||
render_scaled_to_zoom(grid_top, xpos, ypos);
|
||||
|
||||
static const texture grid_bottom = image::get_texture(game_config::images::grid_bottom);
|
||||
render_scaled_to_zoom(grid_bottom, xpos, ypos);
|
||||
}
|
||||
|
||||
//
|
||||
// On-map overlays, such as [item]s.
|
||||
//
|
||||
if(!is_shrouded) {
|
||||
//typedef overlay_map::const_iterator Itor;
|
||||
auto overlays = overlays_->equal_range(loc);
|
||||
|
||||
//image::light_string lt;
|
||||
|
||||
const bool have_overlays = overlays.first != overlays.second;
|
||||
if(have_overlays) {
|
||||
// TODO:
|
||||
//tod_color tod_col = tod.color;
|
||||
|
||||
//if(tod_col != get_time_of_day().color) {
|
||||
// tod_col = tod_col + color_adjust_;
|
||||
//}
|
||||
|
||||
//lt = image::get_light_string(0, tod_col.r, tod_col.g, tod_col.b);
|
||||
|
||||
for(; overlays.first != overlays.second; ++overlays.first) {
|
||||
if((overlays.first->second.team_name == "" ||
|
||||
overlays.first->second.team_name.find(dc_->teams()[viewing_team()].team_name()) != std::string::npos)
|
||||
&& !(is_fogged && !overlays.first->second.visible_in_fog))
|
||||
{
|
||||
const std::string& image = overlays.first->second.image;
|
||||
|
||||
const texture tex = image.find("~NO_TOD_SHIFT()") == std::string::npos
|
||||
? image::get_texture(image) // TODO
|
||||
: image::get_texture(image);
|
||||
|
||||
// was: SCALED_TO_HEX
|
||||
render_scaled_to_zoom(tex, xpos, ypos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Draw the time-of-day mask on top of the terrain in the hex.
|
||||
// tod may differ from tod if hex is illuminated.
|
||||
const std::string& tod_hex_mask = tod.image_mask;
|
||||
|
@ -2715,16 +2778,7 @@ void display::draw_hex(const map_location& loc)
|
|||
drawing_queue_add(drawing_queue::LAYER_TERRAIN_FG, loc, xpos, ypos,
|
||||
image::get_image(tod_hex_mask,image::SCALED_TO_HEX));
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Hex cursor (TODO: split into layers)
|
||||
//
|
||||
if(on_map && loc == mouseoverHex_) {
|
||||
draw_hex_cursor(loc);
|
||||
}
|
||||
|
||||
#if 0
|
||||
//
|
||||
// Debugging output - coordinates, etc.
|
||||
//
|
||||
|
@ -2813,49 +2867,7 @@ void display::draw()
|
|||
SDL_Rect map_area_rect = map_area();
|
||||
render_clip_rect_setter setter(&map_area_rect);
|
||||
|
||||
const rect_of_hexes& visible_hexes = get_visible_hexes();
|
||||
|
||||
// First render pass.
|
||||
for(const map_location& loc : visible_hexes) {
|
||||
draw_hex(loc);
|
||||
}
|
||||
|
||||
// Right now just handles halos - see game_display.
|
||||
post_commit();
|
||||
|
||||
// Second render pass.
|
||||
for(const map_location& loc : visible_hexes) {
|
||||
const int xpos = get_location_x(loc);
|
||||
const int ypos = get_location_y(loc);
|
||||
|
||||
image::TYPE image_type = get_image_type(loc);
|
||||
|
||||
const bool is_shrouded = shrouded(loc);
|
||||
const bool is_fogged = fogged(loc);
|
||||
|
||||
//
|
||||
// Shroud and fog, main images.
|
||||
//
|
||||
if(is_shrouded || is_fogged) {
|
||||
|
||||
// If is_shrouded is false, is_fogged is true
|
||||
const std::string& weather_image = is_shrouded
|
||||
? get_variant(shroud_images_, loc)
|
||||
: get_variant(fog_images_, loc);
|
||||
|
||||
// TODO: image type
|
||||
render_scaled_to_zoom(image::get_texture(weather_image), xpos, ypos);
|
||||
}
|
||||
|
||||
//
|
||||
// Shroud and fog, transitions to main hexes.
|
||||
//
|
||||
if(!is_shrouded) {
|
||||
for(const texture& t : get_fog_shroud_images(loc, image_type)) {
|
||||
render_scaled_to_zoom(t, xpos, ypos);
|
||||
}
|
||||
}
|
||||
}
|
||||
draw_gamemap();
|
||||
}
|
||||
|
||||
// Draw map labels.
|
||||
|
|
|
@ -63,9 +63,11 @@ namespace wb {
|
|||
|
||||
#include "overlay.hpp"
|
||||
|
||||
#include <SDL_rect.h>
|
||||
#include <boost/circular_buffer.hpp>
|
||||
|
||||
#include "utils/functional.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
|
@ -285,6 +287,14 @@ public:
|
|||
int get_location_x(const map_location& loc) const;
|
||||
int get_location_y(const map_location& loc) const;
|
||||
|
||||
/**
|
||||
* Wrapper to return the drawing origin for the specified location in screen coordinates.
|
||||
* Combines @ref get_location_x and @ref get_location_y.
|
||||
*
|
||||
* @param loc The map location to look up.
|
||||
*/
|
||||
SDL_Point get_loc_drawing_origin(const map_location& loc) const;
|
||||
|
||||
/**
|
||||
* Rectangular area of hexes, allowing to decide how the top and bottom
|
||||
* edges handles the vertical shift for each parity of the x coordinate
|
||||
|
@ -326,7 +336,10 @@ public:
|
|||
const rect_of_hexes hexes_under_rect(const SDL_Rect& r) const;
|
||||
|
||||
/** Returns the rectangular area of visible hexes */
|
||||
const rect_of_hexes get_visible_hexes() const {return hexes_under_rect(map_area());}
|
||||
const rect_of_hexes get_visible_hexes() const
|
||||
{
|
||||
return hexes_under_rect(map_area());
|
||||
}
|
||||
|
||||
/** Returns true if location (x,y) is covered in shroud. */
|
||||
bool shrouded(const map_location& loc) const;
|
||||
|
@ -545,6 +558,14 @@ public:
|
|||
*/
|
||||
virtual void draw() override;
|
||||
|
||||
enum TERRAIN_TYPE { BACKGROUND, FOREGROUND};
|
||||
|
||||
private:
|
||||
void draw_visible_hexes(const rect_of_hexes& visible_hexes, TERRAIN_TYPE terrain_type);
|
||||
|
||||
void draw_gamemap();
|
||||
|
||||
public:
|
||||
map_labels& labels();
|
||||
const map_labels& labels() const;
|
||||
|
||||
|
@ -639,6 +660,23 @@ public:
|
|||
video_.render_copy(tex, nullptr, &dst, std::forward<T>(extra_args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a texture directly to the screen (or current rendering target) scaled to the
|
||||
* current zoom factor.
|
||||
*
|
||||
* @param tex The texture to render.
|
||||
* @param loc The map location to render at.
|
||||
* @param extra_args Any additional arguments to pass to @ref CVideo::render_copy.
|
||||
* This should not contain the texture or source/destination rects.
|
||||
*/
|
||||
template<typename... T>
|
||||
void render_scaled_to_zoom(const texture& tex, const map_location& loc, T&&... extra_args)
|
||||
{
|
||||
SDL_Point origin = get_loc_drawing_origin(loc);
|
||||
|
||||
render_scaled_to_zoom(tex, origin.x, origin.y, std::forward<T>(extra_args)...);
|
||||
}
|
||||
|
||||
private:
|
||||
void init_flags_for_side_internal(size_t side, const std::string& side_color);
|
||||
|
||||
|
@ -688,6 +726,8 @@ protected:
|
|||
|
||||
virtual void draw_hex_cursor(const map_location& loc);
|
||||
|
||||
virtual void draw_hex_overlays();
|
||||
|
||||
/**
|
||||
* @returns the image type to be used for the passed hex
|
||||
*/
|
||||
|
@ -701,8 +741,6 @@ protected:
|
|||
|
||||
void draw_minimap();
|
||||
|
||||
enum TERRAIN_TYPE { BACKGROUND, FOREGROUND};
|
||||
|
||||
void get_terrain_images(const map_location &loc,
|
||||
const std::string& timeid,
|
||||
TERRAIN_TYPE terrain_type);
|
||||
|
@ -721,6 +759,7 @@ protected:
|
|||
size_t currentTeam_;
|
||||
bool dont_show_all_; //const team *viewpoint_;
|
||||
int xpos_, ypos_;
|
||||
//camera_controller camera_controller_;
|
||||
bool view_locked_;
|
||||
theme theme_;
|
||||
static unsigned int zoom_;
|
||||
|
|
|
@ -76,22 +76,25 @@ image::TYPE editor_display::get_image_type(const map_location& loc)
|
|||
return image::TOD_COLORED;
|
||||
}
|
||||
|
||||
void editor_display::draw_hex(const map_location& loc)
|
||||
void editor_display::draw_hex_cursor(const map_location& loc)
|
||||
{
|
||||
//int xpos = get_location_x(loc);
|
||||
//int ypos = get_location_y(loc);
|
||||
display::draw_hex(loc);
|
||||
if (map().on_board_with_border(loc)) {
|
||||
if (map().in_selection(loc)) {
|
||||
//drawing_queue_add(drawing_queue::LAYER_FOG_SHROUD, loc, xpos, ypos,
|
||||
// image::get_texture("editor/selection-overlay.png"));
|
||||
}
|
||||
if(!map().on_board_with_border(loc)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (brush_locations_.find(loc) != brush_locations_.end()) {
|
||||
static const image::locator brush(game_config::images::editor_brush);
|
||||
//drawing_queue_add(drawing_queue::LAYER_SELECTED_HEX, loc, xpos, ypos,
|
||||
// image::get_texture(brush));
|
||||
}
|
||||
static texture brush(image::get_texture(game_config::images::editor_brush));
|
||||
|
||||
for(const map_location& b_loc : brush_locations_) {
|
||||
render_scaled_to_zoom(brush, b_loc); // LAYER_SELECTED_HEX
|
||||
}
|
||||
}
|
||||
|
||||
void editor_display::draw_hex_overlays()
|
||||
{
|
||||
static texture selection_overlay(image::get_texture("editor/selection-overlay.png"));
|
||||
|
||||
for(const map_location& s_loc : map().selection()) {
|
||||
render_scaled_to_zoom(selection_overlay, s_loc); // LAYER_FOG_SHROUD
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,8 @@ protected:
|
|||
*/
|
||||
image::TYPE get_image_type(const map_location& loc) override;
|
||||
|
||||
void draw_hex(const map_location& loc) override;
|
||||
virtual void draw_hex_cursor(const map_location& loc) override;
|
||||
virtual void draw_hex_overlays() override;
|
||||
|
||||
const SDL_Rect& get_clip_rect() override;
|
||||
void draw_sidebar() override;
|
||||
|
|
|
@ -235,45 +235,120 @@ void game_display::post_commit()
|
|||
|
||||
void game_display::draw_hex_cursor(const map_location& loc)
|
||||
{
|
||||
const int xpos = get_location_x(loc);
|
||||
const int ypos = get_location_y(loc);
|
||||
if(!get_map().on_board(loc) || cursor::get() == cursor::WAIT) {
|
||||
return;
|
||||
}
|
||||
|
||||
const unit* u = resources::gameboard->get_visible_unit(loc, dc_->teams()[viewing_team()]);
|
||||
|
||||
std::string bg_path;
|
||||
std::string fg_path;
|
||||
texture* cursor_bg = nullptr;
|
||||
texture* cursor_fg = nullptr;
|
||||
|
||||
// image::SCALED_TO_HEX
|
||||
|
||||
// TODO: should probably cache these results in this class.
|
||||
// TODO: either merge into one image or draw layered.
|
||||
|
||||
// Default
|
||||
static texture default_cursor_bg(image::get_texture("misc/hover-hex-top.png~RC(magenta>gold)"));
|
||||
static texture default_cursor_fg(image::get_texture("misc/hover-hex-bottom.png~RC(magenta>gold)"));
|
||||
|
||||
// Your troops
|
||||
static texture team_cursor_bg(image::get_texture("misc/hover-hex-top.png~RC(magenta>green)"));
|
||||
static texture team_cursor_fg(image::get_texture("misc/hover-hex-bottom.png~RC(magenta>green)"));
|
||||
|
||||
// Allies
|
||||
static texture ally_cursor_bg(image::get_texture("misc/hover-hex-top.png~RC(magenta>lightblue)"));
|
||||
static texture ally_cursor_fg(image::get_texture("misc/hover-hex-bottom.png~RC(magenta>lightblue)"));
|
||||
|
||||
// Enemies
|
||||
static texture enemy_cursor_bg(image::get_texture("misc/hover-hex-enemy-top.png~RC(magenta>red)"));
|
||||
static texture enemy_cursor_fg(image::get_texture("misc/hover-hex-enemy-bottom.png~RC(magenta>red)"));
|
||||
|
||||
const team& t = dc_->teams()[currentTeam_];
|
||||
|
||||
const unit* u = resources::gameboard->get_visible_unit(loc, dc_->teams()[viewing_team()]);
|
||||
|
||||
if(u == nullptr) {
|
||||
bg_path = "misc/hover-hex-top.png~RC(magenta>gold)";
|
||||
fg_path = "misc/hover-hex-bottom.png~RC(magenta>gold)";
|
||||
} else if(dc_->teams()[currentTeam_].is_enemy(u->side())) {
|
||||
bg_path = "misc/hover-hex-enemy-top.png~RC(magenta>red)";
|
||||
fg_path = "misc/hover-hex-enemy-bottom.png~RC(magenta>red)";
|
||||
} else if(dc_->teams()[currentTeam_].side() == u->side()) {
|
||||
bg_path = "misc/hover-hex-top.png~RC(magenta>green)";
|
||||
fg_path = "misc/hover-hex-bottom.png~RC(magenta>green)";
|
||||
cursor_bg = &default_cursor_bg;
|
||||
cursor_fg = &default_cursor_fg;
|
||||
} else if(t.is_enemy(u->side())) {
|
||||
cursor_bg = &enemy_cursor_bg;
|
||||
cursor_fg = &enemy_cursor_fg;
|
||||
} else if(t.side() == u->side()) {
|
||||
cursor_bg = &team_cursor_bg;
|
||||
cursor_fg = &team_cursor_fg;
|
||||
} else {
|
||||
bg_path = "misc/hover-hex-top.png~RC(magenta>lightblue)";
|
||||
fg_path = "misc/hover-hex-bottom.png~RC(magenta>lightblue)";
|
||||
cursor_bg = &ally_cursor_bg;
|
||||
cursor_fg = &ally_cursor_fg;
|
||||
}
|
||||
|
||||
texture cursor_bg = image::get_texture(bg_path);
|
||||
if(cursor_bg) {
|
||||
render_scaled_to_zoom(cursor_bg, xpos, ypos);
|
||||
render_scaled_to_zoom(*cursor_bg, loc);
|
||||
}
|
||||
|
||||
texture cursor_fg = image::get_texture(fg_path);
|
||||
if(cursor_fg) {
|
||||
render_scaled_to_zoom(cursor_fg, xpos, ypos);
|
||||
render_scaled_to_zoom(*cursor_fg, loc);
|
||||
}
|
||||
|
||||
//
|
||||
// Draw accompanying route markers, defence ratings, target status indicators
|
||||
//
|
||||
draw_movement_info(loc);
|
||||
}
|
||||
|
||||
void game_display::draw_hex_overlays()
|
||||
{
|
||||
//
|
||||
// Mask on unreachable locations
|
||||
//
|
||||
if(!reach_map_.empty()) {
|
||||
for(const map_location& loc : get_visible_hexes()) {
|
||||
if(shrouded(loc) || loc == attack_indicator_dst_ || reach_map_.find(loc) != reach_map_.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// was SCALED_TO_HEX
|
||||
static texture unreachable = image::get_texture(game_config::images::unreachable);
|
||||
|
||||
render_scaled_to_zoom(unreachable, loc);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Attack indicator - source
|
||||
//
|
||||
if(get_map().on_board(attack_indicator_src_)) {
|
||||
texture indicator = image::get_texture("misc/attack-indicator-src-" + attack_indicator_direction() + ".png");
|
||||
|
||||
// was SCALED_TO_HEX
|
||||
render_scaled_to_zoom(indicator, attack_indicator_src_);
|
||||
}
|
||||
|
||||
//
|
||||
// Attack indicator - target
|
||||
//
|
||||
if(get_map().on_board(attack_indicator_dst_)) {
|
||||
texture indicator = image::get_texture("misc/attack-indicator-dst-" + attack_indicator_direction() + ".png");
|
||||
|
||||
// was SCALED_TO_HEX
|
||||
render_scaled_to_zoom(indicator, attack_indicator_dst_);
|
||||
}
|
||||
|
||||
// Linger overlay unconditionally otherwise it might give glitches
|
||||
// so it's drawn over the shroud and fog.
|
||||
// FIXME: ^ split into seperate function so that happens.
|
||||
if(mode_ != RUNNING) {
|
||||
for(const map_location& loc : get_visible_hexes()) {
|
||||
static texture linger(image::get_texture(game_config::images::linger));
|
||||
|
||||
// was TOD_COLORED
|
||||
render_scaled_to_zoom(linger, loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void game_display::draw_hex(const map_location& loc)
|
||||
{
|
||||
return;
|
||||
|
||||
// Inherited.
|
||||
display::draw_hex(loc);
|
||||
|
||||
|
@ -438,8 +513,70 @@ void game_display::set_game_mode(const game_mode mode)
|
|||
}
|
||||
}
|
||||
|
||||
void game_display::draw_movement_info(const map_location& loc)
|
||||
void game_display::draw_movement_info(const map_location& /*loc*/)
|
||||
{
|
||||
if(route_.steps.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<wb::manager> wb = wb_.lock();
|
||||
|
||||
for(const auto& mark : route_.marks) {
|
||||
const map_location& m_loc = mark.first;
|
||||
|
||||
if(route_.steps.front() == m_loc || shrouded(m_loc) || !get_map().on_board(m_loc)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const unit_map::const_iterator un = (wb && wb->get_temp_move_unit().valid())
|
||||
? wb->get_temp_move_unit()
|
||||
: dc_->units().find(route_.steps.front());
|
||||
|
||||
if(un != dc_->units().end()) {
|
||||
#if 0
|
||||
// Display the def% of this terrain
|
||||
int def = 100 - un->defense_modifier(get_map().get_terrain(loc));
|
||||
|
||||
std::stringstream def_text;
|
||||
def_text << def << "%";
|
||||
|
||||
color_t color = game_config::red_to_green(def, false);
|
||||
|
||||
// simple mark (no turn point) use smaller font
|
||||
int def_font = w->second.turns > 0 ? 18 : 16;
|
||||
draw_text_in_hex(loc, drawing_queue::LAYER_MOVE_INFO, def_text.str(), def_font, color);
|
||||
#endif
|
||||
// TODO: do we want SCALED_TO_HEX?
|
||||
// LAYER_MOVE_INFO
|
||||
|
||||
if(mark.second.invisible) {
|
||||
static texture hidden(image::get_texture("misc/hidden.png"));
|
||||
render_scaled_to_zoom(hidden, m_loc);
|
||||
}
|
||||
|
||||
if(mark.second.zoc) {
|
||||
static texture zoc(image::get_texture("misc/zoc.png"));
|
||||
render_scaled_to_zoom(zoc, m_loc);
|
||||
}
|
||||
|
||||
if(mark.second.capture) {
|
||||
static texture capture(image::get_texture("misc/capture.png"));
|
||||
render_scaled_to_zoom(capture, m_loc);
|
||||
}
|
||||
#if 0
|
||||
// We display turn info only if different from a simple last "1"
|
||||
if(w->second.turns > 1 || (w->second.turns == 1 && loc != route_.steps.back())) {
|
||||
std::stringstream turns_text;
|
||||
turns_text << w->second.turns;
|
||||
draw_text_in_hex(loc, drawing_queue::LAYER_MOVE_INFO, turns_text.str(), 17, font::NORMAL_COLOR, 0.5,0.8);
|
||||
}
|
||||
#endif
|
||||
// The hex is full now, so skip the "show enemy moves"
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Search if there is a mark here
|
||||
pathfind::marked_route::mark_map::iterator w = route_.marks.find(loc);
|
||||
|
||||
|
@ -515,6 +652,7 @@ void game_display::draw_movement_info(const map_location& loc)
|
|||
}
|
||||
}
|
||||
|
||||
// Number of turns to reach
|
||||
if(!reach_map_.empty()) {
|
||||
reach_map::iterator reach = reach_map_.find(loc);
|
||||
if(reach != reach_map_.end() && reach->second > 1) {
|
||||
|
@ -522,6 +660,7 @@ void game_display::draw_movement_info(const map_location& loc)
|
|||
draw_text_in_hex(loc, drawing_queue::LAYER_MOVE_INFO, num, 16, font::YELLOW_COLOR);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<surface> footsteps_images(const map_location& loc, const pathfind::marked_route & route_, const display_context * dc_)
|
||||
|
|
|
@ -142,6 +142,7 @@ protected:
|
|||
|
||||
virtual void draw_hex_cursor(const map_location& loc) override;
|
||||
|
||||
virtual void draw_hex_overlays() override;
|
||||
public:
|
||||
/** Set the attack direction indicator. */
|
||||
void set_attack_indicator(const map_location& src, const map_location& dst);
|
||||
|
|
Loading…
Add table
Reference in a new issue