From 643ebe221f6977864c95548691d5ecba4ee49980 Mon Sep 17 00:00:00 2001 From: Charles Dang Date: Wed, 14 Jun 2017 14:20:30 +1100 Subject: [PATCH] Got a bunch more components drawing Reachmaps, attack indicators, shroud/fog (incomplete). --- src/display.cpp | 325 ++++++++++++++++++------------------------- src/display.hpp | 4 +- src/game_display.cpp | 100 ++++++++----- src/units/drawer.cpp | 4 +- 4 files changed, 203 insertions(+), 230 deletions(-) diff --git a/src/display.cpp b/src/display.cpp index bbb20be2e49e..0fe0d7e379da 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -956,7 +956,7 @@ static const std::string& get_direction(size_t n) return dirs[n >= dirs.size() ? 0 : n]; } -std::vector display::get_fog_shroud_images(const map_location& loc, image::TYPE image_type) +std::vector display::get_fog_shroud_images(const map_location& loc, image::TYPE image_type) { std::vector names; @@ -1034,12 +1034,14 @@ std::vector display::get_fog_shroud_images(const map_location& loc, ima } // now get the surfaces - std::vector res; + std::vector res; + res.reserve(names.size()); - for (std::string& name : names) { - surface surf(image::get_image(name, image_type)); - if (surf) - res.push_back(std::move(surf)); + for(std::string& name : names) { + texture tex(image::get_texture(name)); // TODO: image_type + if(tex) { + res.push_back(std::move(tex)); + } } return res; @@ -1388,6 +1390,7 @@ void display::draw_text_in_hex(const map_location& loc, } } } + drawing_buffer_add(layer, loc, x, y, text_surf); } @@ -1555,6 +1558,7 @@ void display::announce(const std::string& message, const color_t& color, const a if(options.discard_previous) { font::remove_floating_label(prevLabel); } + font::floating_label flabel(message); flabel.set_font_size(font::SIZE_XLARGE); flabel.set_color(color); @@ -2888,50 +2892,135 @@ void display::draw_invalidated() { } } -void display::draw_hex(const map_location& /*loc*/) + +// +// NEW RENDERING CODE ========================================================================= +// + +void display::draw_hex(const map_location& loc) { - return; + const int xpos = get_location_x(loc); + const int ypos = get_location_y(loc); + + image::TYPE image_type = get_image_type(loc); - //int xpos = get_location_x(loc); - //int ypos = get_location_y(loc); + const bool on_map = get_map().on_board(loc); + const time_of_day& tod = get_time_of_day(loc); - //image::TYPE image_type = get_image_type(loc); + const bool is_shrouded = shrouded(loc); + const bool is_fogged = fogged(loc); - //const bool on_map = get_map().on_board(loc); - //const time_of_day& tod = get_time_of_day(loc); + // FIXME + if(dc_->teams().empty()) { + //return; + } - //int num_images_fg = 0; - //int num_images_bg = 0; + // TODO: why is this created every time? + unit_drawer drawer = unit_drawer(*this); - //if(!shrouded(loc)) { -#if 0 - std::vector images_fg = get_terrain_images(loc,tod.id, image_type, FOREGROUND); - std::vector images_bg = get_terrain_images(loc,tod.id, image_type, BACKGROUND); + std::vector images_fg = get_terrain_images(loc, tod.id, image_type, FOREGROUND); + std::vector images_bg = get_terrain_images(loc, tod.id, image_type, BACKGROUND); - if(images_fg.empty() && images_bg.empty()) { - return; + // Some debug output + 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); } - num_images_fg = images_fg.size(); - num_images_bg = images_bg.size(); - for(auto& t : images_bg) { - //assert(t); + // + // Village flags + // + const texture& flag = get_flag(loc); + if(flag) { + render_scaled_to_zoom(flag, xpos, ypos); } - for(auto& t : images_fg) { - //assert(t); + } + + // + // Units + // + 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); + } + + // 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); } - // unshrouded terrain (the normal case) - if(!images_bg.empty()) { - drawing_buffer_add(drawing_buffer::LAYER_TERRAIN_BG, loc, xpos, ypos, images_bg); - } else { - //std::cerr << "bg images empty" << std::endl; + } + + // + // Foreground terrains + // + if(!is_shrouded) { + for(const texture& t : images_fg) { + render_scaled_to_zoom(t, xpos, ypos); } + } - if(!images_fg.empty()) { - drawing_buffer_add(drawing_buffer::LAYER_TERRAIN_FG, loc, xpos, ypos, images_fg); - } else { - //std::cerr << "fg images empty" << std::endl; + // + // Shroud and fog + // + 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); + } + + if(!is_shrouded) { + // TODO: + // std::vector fog_shroud_images = get_fog_shroud_images(loc, image_type); + } + + // + // 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 + // + auto arrows_in_hex = arrows_map_.find(loc); + if(arrows_in_hex != arrows_map_.end()) { + for(arrow* const a : arrows_in_hex->second) { + a->draw_hex(loc); } + } + + // + // Hex cursor (TODO: split into layers) + // + if(on_map && loc == mouseoverHex_) { + draw_hex_cursor(loc); + } + + // + // TODO + // + //if(!shrouded(loc)) { +#if 0 // Draw the grid, if that's been enabled if(grid_) { @@ -2945,9 +3034,7 @@ void display::draw_hex(const map_location& /*loc*/) // village-control flags. //drawing_buffer_add(drawing_buffer::LAYER_TERRAIN_BG, loc, xpos, ypos, get_flag(loc)); //} -#endif -#if 0 if(!shrouded(loc)) { typedef overlay_map::const_iterator Itor; std::pair overlays = overlays_->equal_range(loc); @@ -2990,38 +3077,8 @@ void display::draw_hex(const map_location& /*loc*/) 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_ != nullptr) { - drawing_buffer_add(drawing_buffer::LAYER_MOUSEOVER_OVERLAY, loc, xpos, ypos, mouseover_hex_overlay_); - } - - // Paint arrows - arrows_map_t::const_iterator arrows_in_hex = arrows_map_.find(loc); - if(arrows_in_hex != arrows_map_.end()) { - for (arrow* const a : arrows_in_hex->second) { - a->draw_hex(loc); - } - } - // Apply shroud, fog and linger overlay - if(shrouded(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(drawing_buffer::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(drawing_buffer::LAYER_FOG_SHROUD, loc, xpos, ypos, - image::get_image(fog_image, image_type)); - } - - if(!shrouded(loc)) { - drawing_buffer_add(drawing_buffer::LAYER_FOG_SHROUD, loc, xpos, ypos, get_fog_shroud_images(loc, image_type)); - } - if (on_map) { if (draw_coordinates_) { int off_x = xpos + hex_size()/2; @@ -3085,138 +3142,31 @@ void display::draw_hex(const map_location& /*loc*/) #endif } - -// -// NEW RENDERING CODE ========================================================================= -// - -//template -////void display::render_scaled_to_zoom(const texture& tex, const int x_pos, const int y_pos, T&&... extra_args) - - -void display::draw_gamemap() -{ - SDL_Rect area = map_area(); - render_clip_rect_setter setter(&area); - - // TODO: ToD coloring of terrains. - - // The unit drawer can't function without teams. - // FIXME - if(dc_->teams().empty()) { - //return; - } - - // TODO: why is this created every time? - unit_drawer drawer = unit_drawer(*this); - - for(const map_location& loc : get_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 on_map = get_map().on_board(loc); - const time_of_day& tod = get_time_of_day(loc); - - // TODO: - //if(shrouded(loc))) { - // return; - //} - - - // - // Background terrains - // - get_terrain_images(loc, tod.id, image_type, FOREGROUND); - for(const texture& t : terrain_image_vector_) { - render_scaled_to_zoom(t, xpos, ypos); - } - - // - // Village flags - // - texture flag = get_flag(loc); - if(flag) { - render_scaled_to_zoom(flag, xpos, ypos); - } - - // - // Units - // - 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); - } - - // 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); - } - } - - // - // Foreground terrains - // - get_terrain_images(loc, tod.id, image_type, BACKGROUND); - for(const texture& t : terrain_image_vector_) { - render_scaled_to_zoom(t, xpos, ypos); - } - - // - // Mouseover overlays - // -#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 - // - auto arrows_in_hex = arrows_map_.find(loc); - if(arrows_in_hex != arrows_map_.end()) { - for(arrow* const a : arrows_in_hex->second) { - a->draw_hex(loc); - } - } - - // - // Hex cursor (TODO: split into layers) - // - if(on_map && loc == mouseoverHex_) { - draw_hex_cursor(loc); - } - } -} - void display::draw_new() { // Execute any pre-draw actions from derived classes. pre_draw(); // Draw theme background. - const SDL_Rect area = map_outside_area(); - draw_background(area, theme_.border().background_image); + const SDL_Rect outside_area = map_outside_area(); + draw_background(outside_area, theme_.border().background_image); // Progress animations. invalidate_animations(); + draw_all_panels(); + draw_minimap(); + + SDL_Rect map_area_rect = map_area(); + render_clip_rect_setter setter(&map_area_rect); + // Draw the gamemap and its contents (units, etc); - draw_gamemap(); + for(const map_location& loc : get_visible_hexes()) { + draw_hex(loc); + } post_commit(); - draw_all_panels(); - draw_minimap(); - // Draw map labels. font::draw_floating_labels(); @@ -3228,8 +3178,9 @@ void display::draw_new() draw_debugging_aids(); // Call any redraw observers. + // FIXME: makes the editor slow. for(std::function f : redraw_observers_) { - f(*this); + // f(*this); } // Execute any post-draw actions from derived classes. diff --git a/src/display.hpp b/src/display.hpp index b138c20bfbd1..937e4eb5a74a 100644 --- a/src/display.hpp +++ b/src/display.hpp @@ -745,8 +745,6 @@ class display : public video2::draw_layering */ virtual void draw_sidebar() {} - void draw_gamemap(); - void draw_minimap(); enum TERRAIN_TYPE { BACKGROUND, FOREGROUND}; @@ -755,7 +753,7 @@ class display : public video2::draw_layering const std::string& timeid, TERRAIN_TYPE terrain_type); - std::vector get_fog_shroud_images(const map_location& loc, image::TYPE image_type); + std::vector get_fog_shroud_images(const map_location& loc, image::TYPE image_type); void draw_image_for_report(surface& img, SDL_Rect& rect); diff --git a/src/game_display.cpp b/src/game_display.cpp index db13ed1b685c..c67e69405617 100644 --- a/src/game_display.cpp +++ b/src/game_display.cpp @@ -205,11 +205,14 @@ void game_display::scroll_to_leader(int side, SCROLL_TYPE scroll_type,bool force } } -void game_display::pre_draw() { - if (std::shared_ptr w = wb_.lock()) { +void game_display::pre_draw() +{ + if(std::shared_ptr w = wb_.lock()) { w->pre_draw(); } + process_reachmap_changes(); + /** * @todo FIXME: must modify changed, but best to do it at the * floating_label level @@ -217,8 +220,8 @@ void game_display::pre_draw() { chat_man_->prune_chat_messages(); } - -void game_display::post_draw() { +void game_display::post_draw() +{ if (std::shared_ptr w = wb_.lock()) { w->post_draw(); } @@ -226,6 +229,8 @@ void game_display::post_draw() { void game_display::draw_invalidated() { + return; // DONE + halo_man_->unrender(invalidated_); display::draw_invalidated(); if (fake_unit_man_->empty()) { @@ -275,12 +280,12 @@ void game_display::draw_hex_cursor(const map_location& loc) fg_path = "misc/hover-hex-bottom.png~RC(magenta>lightblue)"; } - texture cursor_bg = image::get_texture(image::locator(bg_path)); + texture cursor_bg = image::get_texture(bg_path); if(cursor_bg) { render_scaled_to_zoom(cursor_bg, xpos, ypos); } - texture cursor_fg = image::get_texture(image::locator(fg_path)); + texture cursor_fg = image::get_texture(fg_path); if(cursor_fg) { render_scaled_to_zoom(cursor_fg, xpos, ypos); } @@ -288,16 +293,17 @@ void game_display::draw_hex_cursor(const map_location& loc) void game_display::draw_hex(const map_location& loc) { - return; + // Inherited. + display::draw_hex(loc); + const bool on_map = get_map().on_board(loc); const bool is_shrouded = shrouded(loc); -// const bool is_fogged = fogged(loc); + //const bool is_fogged = fogged(loc); + const int xpos = get_location_x(loc); const int ypos = get_location_y(loc); -// image::TYPE image_type = get_image_type(loc); - - display::draw_hex(loc); + //image::TYPE image_type = get_image_type(loc); if(cursor::get() == cursor::WAIT) { // Interaction is disabled, so we don't need anything else @@ -335,17 +341,19 @@ void game_display::draw_hex(const map_location& loc) } #endif - // Draw reach_map information. - // We remove the reachability mask of the unit - // that we want to attack. - 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(drawing_buffer::LAYER_REACHMAP, loc, xpos, ypos, - image::get_image(unreachable,image::SCALED_TO_HEX)); + // We remove the reachability mask of the unit that we want to attack. + if(!is_shrouded && !reach_map_.empty() + && reach_map_.find(loc) == reach_map_.end() && loc != attack_indicator_dst_) + { + static texture unreachable = image::get_texture(game_config::images::unreachable); + static texture::info info = unreachable.get_info(); + + SDL_Rect dst {xpos, ypos, info.w, info.h}; + video().render_copy(unreachable, nullptr, &dst); // SCALED_TO_HEX } +#if 0 if (std::shared_ptr w = wb_.lock()) { w->draw_hex(loc); @@ -357,29 +365,43 @@ void game_display::draw_hex(const map_location& loc) } } } +#endif + // Draw the attack direction indicator + // TODO: SCALED_TO_HEX if(on_map && loc == attack_indicator_src_) { - drawing_buffer_add(drawing_buffer::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(drawing_buffer::LAYER_ATTACK_INDICATOR, loc, xpos, ypos, - image::get_image("misc/attack-indicator-dst-" + attack_indicator_direction() + ".png", image::SCALED_TO_HEX)); + texture indicator = image::get_texture("misc/attack-indicator-src-" + attack_indicator_direction() + ".png"); + texture::info info = indicator.get_info(); + + SDL_Rect dst {xpos, ypos, info.w, info.h}; + video().render_copy(indicator, nullptr, &dst); + } else if(on_map && loc == attack_indicator_dst_) { + texture indicator = image::get_texture("misc/attack-indicator-dst-" + attack_indicator_direction() + ".png"); + texture::info info = indicator.get_info(); + + SDL_Rect dst {xpos, ypos, info.w, info.h}; + video().render_copy(indicator, nullptr, &dst); } // Linger overlay unconditionally otherwise it might give glitches // so it's drawn over the shroud and fog. if(mode_ != RUNNING) { - static const image::locator linger(game_config::images::linger); - drawing_buffer_add(drawing_buffer::LAYER_LINGER_OVERLAY, loc, xpos, ypos, - image::get_image(linger, image::TOD_COLORED)); + static texture linger = image::get_texture(game_config::images::linger); + static texture::info info = linger.get_info(); + + SDL_Rect dst {xpos, ypos, info.w, info.h}; + video().render_copy(linger, nullptr, &dst); // TOD_COLORED } if(on_map && loc == selectedHex_ && !game_config::images::selected.empty()) { - static const image::locator selected(game_config::images::selected); - drawing_buffer_add(drawing_buffer::LAYER_SELECTED_HEX, loc, xpos, ypos, - image::get_image(selected, image::SCALED_TO_HEX)); + static texture selected = image::get_texture(game_config::images::selected); + static texture::info info = selected.get_info(); + + SDL_Rect dst {xpos, ypos, info.w, info.h}; + video().render_copy(selected, nullptr, &dst); // SCALED_TO_HEX } +#if 0 // Show def% and turn to reach info if(!is_shrouded && on_map) { draw_movement_info(loc); @@ -392,7 +414,9 @@ void game_display::draw_hex(const map_location& loc) draw_text_in_hex(loc, drawing_buffer::LAYER_MOVE_INFO, txt, 18, font::BAD_COLOR); } } + //simulate_delay += 1; +#endif } const time_of_day& game_display::get_time_of_day(const map_location& loc) const @@ -426,7 +450,6 @@ void game_display::draw_sidebar() } } - void game_display::set_game_mode(const game_mode mode) { if(mode != mode_) { @@ -443,11 +466,11 @@ void game_display::draw_movement_info(const map_location& loc) std::shared_ptr wb = wb_.lock(); // Don't use empty route or the first step (the unit will be there) - if(w != route_.marks.end() - && !route_.steps.empty() && route_.steps.front() != loc) { - 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(w != route_.marks.end() && !route_.steps.empty() && route_.steps.front() != loc) { + 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()) { // Display the def% of this terrain int move_cost = un->movement_cost(get_map().get_terrain(loc)); @@ -490,6 +513,7 @@ void game_display::draw_movement_info(const map_location& loc) return; } } + // When out-of-turn, it's still interesting to check out the terrain defs of the selected unit else if (selectedHex_.valid() && loc == mouseoverHex_) { @@ -511,9 +535,9 @@ void game_display::draw_movement_info(const map_location& loc) } } - if (!reach_map_.empty()) { + if(!reach_map_.empty()) { reach_map::iterator reach = reach_map_.find(loc); - if (reach != reach_map_.end() && reach->second > 1) { + if(reach != reach_map_.end() && reach->second > 1) { const std::string num = std::to_string(reach->second); draw_text_in_hex(loc, drawing_buffer::LAYER_MOVE_INFO, num, 16, font::YELLOW_COLOR); } diff --git a/src/units/drawer.cpp b/src/units/drawer.cpp index 22a0865965e9..a0144667902e 100644 --- a/src/units/drawer.cpp +++ b/src/units/drawer.cpp @@ -226,8 +226,8 @@ void unit_drawer::redraw_unit(const unit & u) const ellipse << "-" << leader << nozoc << selected << "bottom.png~RC(ellipse_red>" << tc << ")"; // Load the ellipse parts recolored to match team color - ellipse_back = image::get_texture(image::locator(ellipse_top) /*, image::SCALED_TO_ZOOM)*/); - ellipse_front = image::get_texture(image::locator(ellipse_bot) /*, image::SCALED_TO_ZOOM)*/); + ellipse_back = image::get_texture(ellipse_top /*, image::SCALED_TO_ZOOM)*/); + ellipse_front = image::get_texture(ellipse_bot /*, image::SCALED_TO_ZOOM)*/); } }