The Battle for Wesnoth  1.19.9+dev
game_display.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2025
3  by David White <dave@whitevine.net>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 /**
17  * @file
18  * During a game, show map & info-panels at top+right.
19  */
20 
21 #include "game_display.hpp"
22 
23 #include <utility>
24 
25 
26 #include "cursor.hpp"
27 #include "display_chat_manager.hpp"
28 #include "fake_unit_manager.hpp"
29 #include "floating_label.hpp"
30 #include "game_board.hpp"
32 #include "log.hpp"
33 #include "map/map.hpp"
34 #include "font/standard_colors.hpp"
35 #include "reports.hpp"
36 #include "resources.hpp"
37 #include "tod_manager.hpp"
38 #include "color.hpp"
39 #include "synced_context.hpp"
40 #include "units/unit.hpp"
41 #include "units/drawer.hpp"
42 #include "utils/general.hpp"
43 #include "whiteboard/manager.hpp"
44 #include "overlay.hpp"
45 #include "draw.hpp"
46 
47 static lg::log_domain log_display("display");
48 #define ERR_DP LOG_STREAM(err, log_display)
49 #define LOG_DP LOG_STREAM(info, log_display)
50 #define DBG_DP LOG_STREAM(debug, log_display)
51 
52 static lg::log_domain log_engine("engine");
53 #define ERR_NG LOG_STREAM(err, log_engine)
54 
55 /**
56  * Function to return 2 half-hex footsteps images for the given location.
57  * Only loc is on the current route set by set_route.
58  *
59  * This function is only used internally by game_display so I have moved it out of the header into the compilaton unit.
60  */
61 std::vector<texture> footsteps_images(const map_location& loc, const pathfind::marked_route & route_, const display_context * dc_);
62 
64  std::weak_ptr<wb::manager> wb,
65  reports& reports_object,
66  const std::string& theme_id,
67  const config& level)
68  : display(&board, std::move(wb), reports_object, theme_id, level)
69  , overlay_map_()
70  , attack_indicator_src_()
71  , attack_indicator_dst_()
72  , route_()
73  , displayedUnitHex_()
74  , first_turn_(true)
75  , in_game_(false)
76  , chat_man_(new display_chat_manager(*this))
77  , mode_(RUNNING)
78  , needs_rebuild_(false)
79 {
80 }
81 
83 {
84  try {
85  chat_man_->prune_chat_messages(true);
86  } catch(...) {
87  DBG_DP << "Caught exception in game_display destructor: " << utils::get_unknown_exception_type();
88  }
89 }
90 
92 {
93  if(!first_turn_) {
96 
97  if(old_tod.image_mask != tod.image_mask) {
98  fade_tod_mask(old_tod.image_mask, tod.image_mask);
99  }
100  }
101 
102  first_turn_ = false;
103 
104  update_tod();
105 }
106 
108 {
109  if(hex.valid() && fogged(hex)) {
110  return;
111  }
112  display::select_hex(hex);
113 
114  display_unit_hex(hex);
115 }
116 
118 {
119  wb::future_map_if future(!synced_context::is_synced()); /**< Lasts for whole method. */
120 
122  if (u) {
123  displayedUnitHex_ = hex;
124  invalidate_unit();
125  } else {
127  if (u) {
128  // mouse moved from unit hex to non-unit hex
129  if (context().units().count(selectedHex_)) {
131  invalidate_unit();
132  }
133  }
134  }
135 
138 }
139 
140 
142 {
143  if (!hex.valid())
144  return;
145 
146  wb::future_map_if future(!synced_context::is_synced()); /**< Lasts for whole method. */
147 
149  if (u) {
150  displayedUnitHex_ = hex;
151  invalidate_unit();
152  }
153 }
154 
156 {
157  if (src == displayedUnitHex_) {
159  invalidate_unit();
160  }
161 }
162 
163 void game_display::scroll_to_leader(int side, SCROLL_TYPE scroll_type,bool force)
164 {
166 
167  if(leader.valid() && leader->is_visible_to_team(viewing_team(), false)) {
168  scroll_to_tile(leader->get_location(), scroll_type, true, force);
169  }
170 }
171 
173 {
174  display::update();
175 
176  if (std::shared_ptr<wb::manager> w = wb_.lock()) {
177  w->pre_draw();
178  }
180  /**
181  * @todo FIXME: must modify changed, but best to do it at the
182  * floating_label level
183  */
184  chat_man_->prune_chat_messages();
185 }
186 
187 
189 {
190  display::render();
191 
192  if (std::shared_ptr<wb::manager> w = wb_.lock()) {
193  w->post_draw();
194  }
195 }
196 
198 {
200  if (fake_unit_man_->empty()) {
201  return;
202  }
203  unit_drawer drawer = unit_drawer(*this);
204 
205  for(const unit* temp_unit : *fake_unit_man_) {
206  const map_location& loc = temp_unit->get_location();
207  if(utils::contains(invalidated_, loc) && unit_can_draw_here(loc, *temp_unit)) {
208  drawer.redraw_unit(*temp_unit);
209  }
210  }
211 }
212 
213 namespace
214 {
215 const std::string mouseover_normal_top = "misc/hover-hex-top.png~RC(magenta>gold)";
216 const std::string mouseover_normal_bot = "misc/hover-hex-bottom.png~RC(magenta>gold)";
217 
218 const std::string mouseover_enemy_top = "misc/hover-hex-enemy-top.png~RC(magenta>red)";
219 const std::string mouseover_enemy_bot = "misc/hover-hex-enemy-bottom.png~RC(magenta>red)";
220 
221 const std::string mouseover_self_top = "misc/hover-hex-top.png~RC(magenta>green)";
222 const std::string mouseover_self_bot = "misc/hover-hex-bottom.png~RC(magenta>green)";
223 
224 const std::string mouseover_ally_top = "misc/hover-hex-top.png~RC(magenta>lightblue)";
225 const std::string mouseover_ally_bot = "misc/hover-hex-bottom.png~RC(magenta>lightblue)";
226 }
227 
229 {
230  const bool on_map = context().map().on_board(loc);
231  const bool is_shrouded = shrouded(loc);
232 
234 
235  if(cursor::get() == cursor::WAIT) {
236  // Interaction is disabled, so we don't need anything else
237  return;
238  }
239 
240  if(on_map && loc == mouseoverHex_ && !map_screenshot_) {
242  const unit* u = context().get_visible_unit(loc, viewing_team());
243  if(u != nullptr) {
244  hex_top_layer = drawing_layer::mouseover_top;
245  }
246 
247  const std::string* mo_top_path;
248  const std::string* mo_bot_path;
249 
250  if(u == nullptr) {
251  mo_top_path = &mouseover_normal_top;
252  mo_bot_path = &mouseover_normal_bot;
253  } else if(viewing_team().is_enemy(u->side())) {
254  mo_top_path = &mouseover_enemy_top;
255  mo_bot_path = &mouseover_enemy_bot;
256  } else if(viewing_team().side() == u->side()) {
257  mo_top_path = &mouseover_self_top;
258  mo_bot_path = &mouseover_self_bot;
259  } else {
260  mo_top_path = &mouseover_ally_top;
261  mo_bot_path = &mouseover_ally_bot;
262  }
263 
264  drawing_buffer_add(hex_top_layer, loc,
265  [tex = image::get_texture(*mo_top_path, image::HEXED)](const rect& dest) { draw::blit(tex, dest); });
266 
268  [tex = image::get_texture(*mo_bot_path, image::HEXED)](const rect& dest) { draw::blit(tex, dest); });
269  }
270 
271  // Draw reach_map information.
272  if(!is_shrouded && !reach_map_.empty() && reach_map_.find(loc) != reach_map_.end()) {
273  // draw the reachmap tint below units and high terrain graphics
274  std::string color = prefs::get().reach_map_color();
275  std::string tint_opacity = std::to_string(prefs::get().reach_map_tint_opacity());
276 
277  drawing_buffer_add(drawing_layer::reachmap_highlight, loc, [tex = image::get_texture(game_config::reach_map_prefix + ".png~RC(magenta>"+color+")~O("+tint_opacity+"%)", image::HEXED)](const rect& dest) {
278  draw::blit(tex, dest);
279  });
280  // We remove the reachmap border mask of the hovered hex to avoid weird interactions with other visual objects.
281  if(loc != mouseoverHex_) {
282  // draw the highlight borders on top of units and terrain
284  for(const texture& t : images) {
285  draw::blit(t, dest);
286  }
287  });
288  }
289  }
290 
291  if(std::shared_ptr<wb::manager> w = wb_.lock()) {
292  w->draw_hex(loc);
293 
294  if(!(w->is_active() && w->has_temp_move())) {
295  std::vector<texture> footstepImages = footsteps_images(loc, route_, dc_);
296  if(!footstepImages.empty()) {
297  drawing_buffer_add(drawing_layer::footsteps, loc, [images = std::move(footstepImages)](const rect& dest) {
298  for(const texture& t : images) {
299  draw::blit(t, dest);
300  }
301  });
302  }
303  }
304  }
305 
306  // Draw the attack direction indicator
307  if(on_map && loc == attack_indicator_src_) {
309  [tex = image::get_texture("misc/attack-indicator-src-" + attack_indicator_direction() + ".png", image::HEXED)](const rect& dest)
310  { draw::blit(tex, dest); }
311  );
312  } else if(on_map && loc == attack_indicator_dst_) {
314  [tex = image::get_texture("misc/attack-indicator-dst-" + attack_indicator_direction() + ".png", image::HEXED)](const rect& dest)
315  { draw::blit(tex, dest); }
316  );
317  }
318 
319  // Linger overlay unconditionally otherwise it might give glitches
320  // so it's drawn over the shroud and fog.
321  if(mode_ != RUNNING) {
324  [tex = image::get_texture(linger, image::TOD_COLORED)](const rect& dest) { draw::blit(tex, dest); });
325  }
326 
327  if(on_map && loc == selectedHex_ && !game_config::images::selected.empty()) {
330  [tex = image::get_texture(selected, image::HEXED)](const rect& dest) { draw::blit(tex, dest); });
331  }
332 
333  // Show def% and turn to reach info
334  if(!is_shrouded && on_map) {
336  }
337 }
338 
340 {
342 }
343 
345 {
347 }
348 
350 {
351  display::layout();
352 
353  // We need teams for the reports below
354  if(context().teams().empty()) {
355  return;
356  }
357 
358  refresh_report("report_clock");
359  refresh_report("report_battery");
360  refresh_report("report_countdown");
361 
363  {
364  wb::future_map future; // start planned unit map scope
365 
366  // We display the unit the mouse is over if it is over a unit,
367  // otherwise we display the unit that is selected.
368  for (const std::string &name : reports_object_->report_list()) {
369  refresh_report(name);
370  }
371  invalidateGameStatus_ = false;
372  }
373 }
374 
375 
377 {
378  if(mode != mode_) {
379  mode_ = mode;
380  invalidate_all();
381  }
382 }
383 
385 {
386  // Search if there is a mark here
388 
389  std::shared_ptr<wb::manager> wb = wb_.lock();
390 
391  // Don't use empty route or the first step (the unit will be there)
392  if(w != route_.marks.end()
393  && !route_.steps.empty() && route_.steps.front() != loc) {
394  const unit_map::const_iterator un =
395  (wb && wb->get_temp_move_unit().valid()) ?
396  wb->get_temp_move_unit() : context().units().find(route_.steps.front());
397  if(un != context().units().end()) {
398  // Display the def% of this terrain
399  int move_cost = un->movement_cost(context().map().get_terrain(loc));
400  int def = (move_cost == movetype::UNREACHABLE ?
401  0 : 100 - un->defense_modifier(context().map().get_terrain(loc)));
402  std::stringstream def_text;
403  def_text << def << "%";
404 
405  color_t color = game_config::red_to_green(def, false);
406 
407  // simple mark (no turn point) use smaller font
408  int def_font = w->second.turns > 0 ? 18 : 16;
409  draw_text_in_hex(loc, drawing_layer::move_info, def_text.str(), def_font, color);
410 
412  [inv = w->second.invisible, zoc = w->second.zoc, cap = w->second.capture](const rect& dest) {
413  if(inv) {
414  draw::blit(image::get_texture(image::locator{"misc/hidden.png"}, image::HEXED), dest);
415  }
416 
417  if(zoc) {
418  draw::blit(image::get_texture(image::locator{"misc/zoc.png"}, image::HEXED), dest);
419  }
420 
421  if(cap) {
422  draw::blit(image::get_texture(image::locator{"misc/capture.png"}, image::HEXED), dest);
423  }
424  });
425 
426  //we display turn info only if different from a simple last "1"
427  if (w->second.turns > 1 || (w->second.turns == 1 && loc != route_.steps.back())) {
428  std::stringstream turns_text;
429  turns_text << w->second.turns;
430  draw_text_in_hex(loc, drawing_layer::move_info, turns_text.str(), 17, font::NORMAL_COLOR, 0.5,0.8);
431  }
432 
433  // The hex is full now, so skip the "show enemy moves"
434  return;
435  }
436  }
437  // When out-of-turn, it's still interesting to check out the terrain defs of the selected unit
438  else if (selectedHex_.valid() && loc == mouseoverHex_)
439  {
440  const unit_map::const_iterator selectedUnit = resources::gameboard->find_visible_unit(selectedHex_,viewing_team());
441  const unit_map::const_iterator mouseoveredUnit = resources::gameboard->find_visible_unit(mouseoverHex_,viewing_team());
442  if(selectedUnit != context().units().end() && mouseoveredUnit == context().units().end()) {
443  // Display the def% of this terrain
444  int move_cost = selectedUnit->movement_cost(context().map().get_terrain(loc));
445  int def = (move_cost == movetype::UNREACHABLE ?
446  0 : 100 - selectedUnit->defense_modifier(context().map().get_terrain(loc)));
447  std::stringstream def_text;
448  def_text << def << "%";
449 
450  color_t color = game_config::red_to_green(def, false);
451 
452  // use small font
453  int def_font = 16;
454  draw_text_in_hex(loc, drawing_layer::move_info, def_text.str(), def_font, color);
455  }
456  }
457 
458  if (!reach_map_.empty()) {
459  reach_map::iterator reach = reach_map_.find(loc);
460  if (reach != reach_map_.end() && reach->second > 1) {
461  const std::string num = std::to_string(reach->second);
462  draw_text_in_hex(loc, drawing_layer::move_info, num, 16, font::YELLOW_COLOR);
463  }
464  }
465 }
466 
467 std::vector<texture> footsteps_images(const map_location& loc, const pathfind::marked_route & route_, const display_context * dc_)
468 {
469  std::vector<texture> res;
470 
471  if (route_.steps.size() < 2) {
472  return res; // no real "route"
473  }
474 
475  std::vector<map_location>::const_iterator i =
476  std::find(route_.steps.begin(),route_.steps.end(),loc);
477 
478  if( i == route_.steps.end()) {
479  return res; // not on the route
480  }
481 
482  // Check which footsteps images of game_config we will use
483  int move_cost = 1;
484  const unit_map::const_iterator u = dc_->units().find(route_.steps.front());
485  if(u != dc_->units().end()) {
486  move_cost = u->movement_cost(dc_->map().get_terrain(loc));
487  }
488  int image_number = std::min<int>(move_cost, game_config::foot_speed_prefix.size());
489  if (image_number < 1) {
490  return res; // Invalid movement cost or no images
491  }
492  const std::string foot_speed_prefix = game_config::foot_speed_prefix[image_number-1];
493 
494  texture teleport;
495 
496  // We draw 2 half-hex (with possibly different directions),
497  // but skip the first for the first step.
498  const int first_half = (i == route_.steps.begin()) ? 1 : 0;
499  // and the second for the last step
500  const int second_half = (i+1 == route_.steps.end()) ? 0 : 1;
501 
502  for (int h = first_half; h <= second_half; ++h) {
503  const std::string sense( h==0 ? "-in" : "-out" );
504 
505  if (!tiles_adjacent(*(i+(h-1)), *(i+h))) {
506  std::string teleport_image =
508  teleport = image::get_texture(teleport_image, image::HEXED);
509  continue;
510  }
511 
512  // In function of the half, use the incoming or outgoing direction
513  map_location::direction dir = (i+(h-1))->get_relative_dir(*(i+h));
514 
515  std::string rotate;
517  // No image, take the opposite direction and do a 180 rotation
518  dir = i->get_opposite_direction(dir);
519  rotate = "~FL(horiz)~FL(vert)";
520  }
521 
522  const std::string image = foot_speed_prefix
523  + sense + "-" + i->write_direction(dir)
524  + ".png" + rotate;
525 
526  res.push_back(image::get_texture(image, image::HEXED));
527  }
528 
529  // we draw teleport image (if any) in last
530  if (teleport != nullptr) res.push_back(teleport);
531 
532  return res;
533 }
534 
535 
536 
538 {
540  highlight_another_reach(paths_list);
541 }
542 
544  const map_location& goal)
545 {
546  // Fold endpoints of routes into reachability map.
547  for (const pathfind::paths::step &dest : paths_list.destinations) {
548  reach_map_[dest.curr]++;
549  }
550  reach_map_changed_ = true;
551 
552  if(goal != map_location::null_location() && paths_list.destinations.contains(goal)) {
553  const auto& path_to_goal = paths_list.destinations.get_path(paths_list.destinations.find(goal));
554  const map_location enemy_unit_location = path_to_goal[0];
555  units_that_can_reach_goal_.insert(enemy_unit_location);
556  }
557 }
558 
560 {
562  if(!reach_map_.empty()) {
563  reach_map_.clear();
564  reach_map_changed_ = true;
565  return true;
566  } else {
567  return false;
568  }
569 }
570 
572 {
573  for(std::vector<map_location>::const_iterator i = route_.steps.begin();
574  i != route_.steps.end(); ++i) {
575  invalidate(*i);
576  }
577 }
578 
580 {
582 
583  if(route != nullptr) {
584  route_ = *route;
585  } else {
586  route_.steps.clear();
587  route_.marks.clear();
588  }
589 
591 }
592 
593 void game_display::float_label(const map_location& loc, const std::string& text, const color_t& color)
594 {
595  if(prefs::get().floating_labels() == false || fogged(loc)) {
596  return;
597  }
598 
599  rect loc_rect = get_location_rect(loc);
600 
601  font::floating_label flabel(text);
603  flabel.set_color(color);
604  flabel.set_position(loc_rect.center().x, loc_rect.y); // middle of top edge
605  flabel.set_move(0, -0.1 * turbo_speed() * get_zoom_factor());
606  flabel.set_lifetime(std::chrono::milliseconds{static_cast<int>(1000 / turbo_speed())});
608 
609  font::add_floating_label(flabel);
610 }
611 
613 {
617 
620 
623  }
624 }
625 
627 {
629 }
630 
632 {
633  in_game_ = true;
634  create_buttons();
635  invalidate_all();
636 }
637 
639  if (b) {
640  needs_rebuild_ = true;
641  }
642 }
643 
645  if (needs_rebuild_) {
646  needs_rebuild_ = false;
648  invalidate_all();
649  rebuild_all();
650  return true;
651  }
652  return false;
653 }
654 
656 {
657  return overlay_map_;
658 }
659 
660 std::vector<texture> game_display::get_reachmap_images(const map_location& loc) const
661 {
662  // Use get_direction() from display.cpp namespace display_direction
663  using namespace display_direction;
664  std::vector<std::string> names;
665  const auto adjacent = get_adjacent_tiles(loc);
666 
667  enum visibility { REACH = 0, ENEMY = 1, CLEAR = 2 };
668  std::array<visibility, 6> tiles;
669 
670  const std::string* image_prefix_ = &game_config::reach_map_prefix;
671 
672  for(int i = 0; i < 6; ++i) {
673  // look for units adjacent to loc
674  std::string test_location = std::to_string(adjacent[i].x) + "," + std::to_string(adjacent[i].y);
675  const unit *u = context().get_visible_unit(adjacent[i], viewing_team());
676  if(reach_map_.find(adjacent[i]) != reach_map_.end()) {
677  DBG_DP << test_location << " is REACHABLE";
678  tiles[i] = REACH;
679  }
680  /**
681  * Make sure there is a unit selected or displayed when drawing the reachmap with enemy detection.
682  * Enemy detection needs to be "disabled" when the reach_map_team_index_ failsafes to viewing_team_index.
683  */
685  DBG_DP << test_location << " is NOT REACHABLE";
686  tiles[i] = CLEAR;
687  }
688  // Grab the reachmap-context team index updated in "display::process_reachmap_changes()" and test for adjacent enemy units
689  else if(u != nullptr && resources::gameboard->get_team(display::reach_map_team_index_).is_enemy(u->side())) {
690  DBG_DP << test_location << " has an ENEMY";
691  tiles[i] = ENEMY;
692  } else {
693  DBG_DP << test_location << " is NOT REACHABLE";
694  tiles[i] = CLEAR;
695  }
696  }
697 
698  // Find out if location is in the inner part of reachmap (surrounded by reach)
699  int s;
700  for(s = 0; s != 6; ++s) {
701  if(tiles[s] != REACH) {
702  break;
703  }
704  }
705 
706  if(s == 6) {
707  // Completely surrounded by reach. This may have a special graphic.
708  DBG_DP << "Tried completely surrounding";
709  std::string name = *image_prefix_ + "-all.png";
710  if(image::exists(name)) {
711  names.push_back(std::move(name));
712  }
713  }
714 
715  // Find all the directions overlap occurs from
716  for(int i = 0, cap1 = 0; cap1 != 6; ++cap1) {
717  if(tiles[i] != REACH) {
718  std::ostringstream stream;
719  std::string suffix;
720  std::string name;
721  stream << *image_prefix_;
722 
723  std::string color = prefs::get().reach_map_color();
724  std::string enemy_color = prefs::get().reach_map_enemy_color();
725  std::string border_opacity = std::to_string(prefs::get().reach_map_border_opacity());
726 
727  if(tiles[i] == ENEMY) {
728  suffix = ".png~RC(magenta>"+enemy_color+")~O("+border_opacity+"%)";
729  } else {
730  suffix = ".png~RC(magenta>"+color+")~O("+border_opacity+"%)";
731  }
732 
733  for(int cap2 = 0; tiles[i] != REACH && cap2 != 6; i = (i + 1) % 6, ++cap2) {
734  stream << get_direction(i);
735  if(!image::exists(stream.str() + ".png")) {
736  DBG_DP << "Image does not exist: " << stream.str() + ".png on " << loc;
737  // If we don't have any surface at all,
738  // then move onto the next overlapped area
739  if(name.empty()) {
740  i = (i + 1) % 6;
741  }
742  break;
743  } else {
744  name = stream.str();
745  }
746  }
747 
748  if(!name.empty()) {
749  names.push_back(name + suffix);
750  }
751  } else {
752  i = (i + 1) % 6;
753  }
754  }
755 
756  // now get the textures
757  std::vector<texture> res;
758 
759  for(const std::string& name : names) {
760  DBG_DP << "Pushing: " << name;
761  if(texture tex = image::get_texture(name, image::HEXED)) {
762  res.push_back(std::move(tex));
763  }
764  }
765 
766  return res;
767 }
map_location loc
Definition: move.cpp:172
const std::vector< map_location > & route_
Definition: move.cpp:386
double t
Definition: astarsearch.cpp:63
std::vector< std::string > names
Definition: build_info.cpp:67
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:158
Abstract class for exposing game data that doesn't depend on the GUI, however which for historical re...
const unit * get_visible_unit(const map_location &loc, const team &current_team, bool see_all=false) const
virtual const gamemap & map() const =0
virtual const unit_map & units() const =0
Sort-of-Singleton that many classes, both GUI and non-GUI, use to access the game data.
Definition: display.hpp:97
const team & viewing_team() const
Definition: display.cpp:344
bool map_screenshot_
Used to indicate to drawing functions that we are doing a map screenshot.
Definition: display.hpp:883
void draw_text_in_hex(const map_location &loc, const drawing_layer layer, const std::string &text, std::size_t font_size, color_t color, double x_in_hex=0.5, double y_in_hex=0.5)
Draw text on a hex.
Definition: display.cpp:1463
std::size_t viewing_team_index_
Definition: display.hpp:727
std::map< map_location, std::vector< overlay > > overlay_map
Definition: display.hpp:905
map_location selectedHex_
Definition: display.hpp:782
void recalculate_minimap()
Schedule the minimap for recalculation.
Definition: display.cpp:1586
bool unit_can_draw_here(const map_location &loc, const unit &unit) const
Returns true if there is no exclusive draw request for loc, or if there is, that it's for unit.
Definition: display.cpp:388
virtual void render() override
Update offscreen render buffers.
Definition: display.cpp:2422
void fade_tod_mask(const std::string &old, const std::string &new_)
ToD mask smooth fade.
Definition: display.cpp:2210
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
Definition: display.cpp:3095
double turbo_speed() const
Definition: display.cpp:2135
bool reach_map_changed_
Definition: display.hpp:900
static double get_zoom_factor()
Returns the current zoom factor.
Definition: display.hpp:270
void invalidate_game_status()
Function to invalidate the game status displayed on the sidebar.
Definition: display.hpp:316
void rebuild_all()
Rebuild all dynamic terrain.
Definition: display.cpp:435
virtual void layout() override
Finalize screen layout.
Definition: display.cpp:2391
virtual void highlight_hex(map_location hex)
Definition: display.cpp:1494
void update_tod(const time_of_day *tod_override=nullptr)
Applies r,g,b coloring to the map.
Definition: display.cpp:394
void process_reachmap_changes()
Definition: display.cpp:3267
void scroll_to_tile(const map_location &loc, SCROLL_TYPE scroll_type=ONSCREEN, bool check_fogged=true, bool force=true)
Scroll such that location loc is on-screen.
Definition: display.cpp:1985
map_location mouseoverHex_
Definition: display.hpp:783
bool fogged(const map_location &loc) const
Returns true if location (x,y) is covered in fog.
Definition: display.cpp:676
void invalidate_all()
Function to invalidate all tiles.
Definition: display.cpp:3088
void drawing_buffer_add(const drawing_layer layer, const map_location &loc, decltype(draw_helper::do_draw) draw_func)
Add an item to the drawing buffer.
Definition: display.cpp:1259
std::size_t reach_map_team_index_
Definition: display.hpp:902
const display_context & context() const
Definition: display.hpp:193
rect get_location_rect(const map_location &loc) const
Returns the on-screen rect corresponding to a loc.
Definition: display.cpp:689
std::set< map_location > invalidated_
Definition: display.hpp:772
void create_buttons()
Definition: display.cpp:847
bool invalidateGameStatus_
Definition: display.hpp:753
virtual void draw_invalidated()
Only called when there's actual redrawing to do.
Definition: display.cpp:2575
reports * reports_object_
Definition: display.hpp:755
virtual void update() override
Update animations and internal state.
Definition: display.cpp:2374
virtual void draw_hex(const map_location &loc)
Redraws a single gamemap location.
Definition: display.cpp:2611
const std::unique_ptr< fake_unit_manager > fake_unit_man_
Definition: display.hpp:746
const display_context * dc_
Definition: display.hpp:684
bool shrouded(const map_location &loc) const
Returns true if location (x,y) is covered in shroud.
Definition: display.cpp:671
bool dont_show_all_
Definition: display.hpp:728
void refresh_report(const std::string &report_name, const config *new_cfg=nullptr)
Update the given report.
Definition: display.cpp:2844
std::weak_ptr< wb::manager > wb_
Definition: display.hpp:686
virtual void select_hex(map_location hex)
Definition: display.cpp:1486
reach_map reach_map_
Definition: display.hpp:898
void set_move(double xmove, double ymove)
void set_position(double xpos, double ypos)
void set_lifetime(const std::chrono::milliseconds &lifetime, const std::chrono::milliseconds &fadeout=std::chrono::milliseconds{100})
void set_color(const color_t &color)
void set_scroll_mode(LABEL_SCROLL_MODE scroll)
void set_font_size(int font_size)
Game board class.
Definition: game_board.hpp:47
unit_map::iterator find_visible_unit(const map_location &loc, const team &current_team, bool see_all=false)
Definition: game_board.cpp:185
virtual void draw_invalidated() override
Only called when there's actual redrawing to do.
void draw_movement_info(const map_location &loc)
Draws the movement info (turns available) for a given location.
void display_unit_hex(map_location hex)
Change the unit to be displayed in the sidebar.
void invalidate_unit_after_move(const map_location &src, const map_location &dst)
Same as invalidate_unit() if moving the displayed unit.
std::string attack_indicator_direction() const
Function to get attack direction suffix.
game_mode mode_
virtual void highlight_hex(map_location hex) override
Function to highlight a location.
map_location displayedUnitHex_
void invalidate_route()
std::vector< texture > get_reachmap_images(const map_location &loc) const
void scroll_to_leader(int side, SCROLL_TYPE scroll_type=ONSCREEN, bool force=true)
Scrolls to the leader of a certain side.
void set_game_mode(const game_mode mode)
virtual void draw_hex(const map_location &loc) override
Redraws a single gamemap location.
void set_attack_indicator(const map_location &src, const map_location &dst)
Set the attack direction indicator.
const std::unique_ptr< display_chat_manager > chat_man_
pathfind::marked_route route_
virtual void render() override
TLD render() override.
void set_route(const pathfind::marked_route *route)
Sets the route along which footsteps are drawn to show movement of a unit.
virtual overlay_map & get_overlays() override
Inherited from display.
std::set< map_location > units_that_can_reach_goal_
void invalidate_unit()
Function to invalidate that unit status displayed on the sidebar.
virtual void select_hex(map_location hex) override
Function to display a location as selected.
void highlight_reach(const pathfind::paths &paths_list)
Sets the paths that are currently displayed as available for the unit to move along.
void new_turn()
Update lighting settings.
void clear_attack_indicator()
virtual const time_of_day & get_time_of_day(const map_location &loc) const override
void highlight_another_reach(const pathfind::paths &paths_list, const map_location &goal=map_location::null_location())
Add more paths to highlight.
map_location attack_indicator_dst_
game_mode
Sets the linger mode for the display.
@ RUNNING
no linger overlay, show fog and shroud.
bool unhighlight_reach()
Reset highlighting of paths.
void needs_rebuild(bool b)
Sets whether the screen (map visuals) needs to be rebuilt.
overlay_map overlay_map_
bool maybe_rebuild()
Rebuilds the screen if needs_rebuild(true) was previously called, and resets the flag.
virtual void layout() override
TLD layout() override.
virtual bool has_time_area() const override
game_display(game_board &board, std::weak_ptr< wb::manager > wb, reports &reports_object, const std::string &theme_id, const config &level)
virtual void update() override
TLD update() override.
map_location attack_indicator_src_
void float_label(const map_location &loc, const std::string &text, const color_t &color)
Function to float a label above a tile.
terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:302
bool on_board(const map_location &loc) const
Tell if a location is on the map.
Definition: map.cpp:385
Generic locator abstracting the location of an image.
Definition: picture.hpp:59
static const int UNREACHABLE
Magic value that signifies a hex is unreachable.
Definition: movetype.hpp:174
static prefs & get()
std::string reach_map_color()
std::string reach_map_enemy_color()
const std::set< std::string > & report_list()
Definition: reports.cpp:1844
static bool is_synced()
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition: texture.hpp:33
bool has_time_area() const
const time_of_day & get_time_of_day(int for_turn=0) const
Returns global time of day for the passed turn.
Definition: tod_manager.hpp:56
const time_of_day & get_previous_time_of_day() const
void redraw_unit(const unit &u) const
draw a unit.
Definition: drawer.cpp:202
unit_iterator end()
Definition: map.hpp:428
unit_iterator find(std::size_t id)
Definition: map.cpp:302
unit_iterator find_leader(int side)
Definition: map.cpp:320
This class represents a single unit of a specific type.
Definition: unit.hpp:133
Drawing functions, for drawing things on the screen.
drawing_layer
@ linger_overlay
The overlay used for the linger mode.
@ reachmap_highlight
Overlay on reachable hexes.
@ footsteps
Footsteps showing path from unit to mouse.
@ attack_indicator
Layer which holds the attack indicator.
@ reachmap_border
Overlay border of reachable hexes.
@ mouseover_top
Top half of image following the mouse.
@ mouseover_bottom
Bottom half of image following the mouse.
@ move_info
Movement info (defense%, etc...)
@ selected_hex
Image on the selected unit.
std::size_t i
Definition: function.cpp:1029
int w
static lg::log_domain log_engine("engine")
std::vector< texture > footsteps_images(const map_location &loc, const pathfind::marked_route &route_, const display_context *dc_)
Function to return 2 half-hex footsteps images for the given location.
static lg::log_domain log_display("display")
#define DBG_DP
int side() const
The side this unit belongs to.
Definition: unit.hpp:343
T end(const std::pair< T, T > &p)
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
Definition: location.cpp:479
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
Definition: location.cpp:507
Standard logging facilities (interface).
bool is_shrouded(const display *disp, const map_location &loc)
Our definition of map labels being obscured is if the tile is obscured, or the tile below is obscured...
Definition: label.cpp:32
CURSOR_TYPE get()
Definition: cursor.cpp:216
@ WAIT
Definition: cursor.hpp:28
const std::string & get_direction(std::size_t n)
Definition: display.cpp:839
void blit(const texture &tex, const SDL_Rect &dst)
Draws a texture, or part of a texture, at the given location.
Definition: draw.cpp:317
const int SIZE_FLOAT_LABEL
Definition: constants.cpp:32
const color_t YELLOW_COLOR
int add_floating_label(const floating_label &flabel)
add a label floating on the screen above everything else.
const color_t NORMAL_COLOR
@ ANCHOR_LABEL_MAP
std::string selected
std::string foot_teleport_enter
std::vector< std::string > foot_speed_prefix
std::string foot_teleport_exit
int reach_map_border_opacity
std::string reach_map_prefix
Definition: game_config.cpp:58
int reach_map_tint_opacity
color_t red_to_green(double val, bool for_text)
Return a color corresponding to the value val red for val=0.0 to green for val=100....
Functions to load and save images from/to disk.
bool exists(const image::locator &i_locator)
Returns true if the given image actually exists, without loading it.
Definition: picture.cpp:820
@ HEXED
Standard hexagonal tile mask applied, removing portions that don't fit.
Definition: picture.hpp:166
@ TOD_COLORED
Same as HEXED, but with Time of Day color tint applied.
Definition: picture.hpp:168
texture get_texture(const image::locator &i_locator, TYPE type, bool skip_cache)
Returns an image texture suitable for hardware-accelerated rendering.
Definition: picture.cpp:922
Unit and team statistics.
::tod_manager * tod_manager
Definition: resources.cpp:29
game_board * gameboard
Definition: resources.cpp:20
std::size_t size(std::string_view str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:85
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
Definition: general.hpp:86
std::string get_unknown_exception_type()
Utility function for finding the type of thing caught with catch(...).
Definition: general.cpp:23
auto * find(Container &container, const Value &value)
Convenience wrapper for using find on a container without needing to comare to end()
Definition: general.hpp:140
Definition: display.hpp:45
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
rect dst
Location on the final composed sheet.
rect src
Non-transparent portion of the surface to compose.
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:59
Encapsulates the map of the game.
Definition: location.hpp:45
bool valid() const
Definition: location.hpp:110
direction
Valid directions which can be moved in our hexagonal world.
Definition: location.hpp:47
static const map_location & null_location()
Definition: location.hpp:102
Structure which holds a single route and marks for special events.
Definition: pathfind.hpp:142
std::vector< map_location > & steps
Definition: pathfind.hpp:187
std::vector< map_location > get_path(const const_iterator &) const
Returns the path going from the source point (included) to the destination point j (excluded).
Definition: pathfind.cpp:497
bool contains(const map_location &) const
Definition: pathfind.cpp:514
const_iterator find(const map_location &) const
Definition: pathfind.cpp:478
map_location curr
Definition: pathfind.hpp:89
Object which contains all the possible locations a unit can move to, with associated best routes to t...
Definition: pathfind.hpp:73
dest_vect destinations
Definition: pathfind.hpp:101
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:49
constexpr point center() const
The center point of the rectangle, accounting for origin.
Definition: rect.hpp:106
Object which defines a time of day with associated bonuses, image, sounds etc.
Definition: time_of_day.hpp:57
std::string image_mask
The image that is to be laid over all images while this time of day lasts.
Definition: time_of_day.hpp:96
bool valid() const
Definition: map.hpp:273
Applies the planned unit map for the duration of the struct's life.
Definition: manager.hpp:253
static map_location::direction s
#define h
#define b