The Battle for Wesnoth  1.19.6+dev
arrow.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010 - 2024
3  by Gabriel Morin <gabrielmorin (at) gmail (dot) com>
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  * Method bodies for the arrow class.
19  */
20 
21 #include "arrow.hpp"
22 
23 #include "draw.hpp"
24 #include "log.hpp"
25 
26 static lg::log_domain log_arrows("arrows");
27 #define ERR_ARR LOG_STREAM(err, log_arrows)
28 #define WRN_ARR LOG_STREAM(warn, log_arrows)
29 #define LOG_ARR LOG_STREAM(info, log_arrows)
30 #define DBG_ARR LOG_STREAM(debug, log_arrows)
31 
32 arrow::arrow(bool hidden)
33  : color_("red")
34  , style_(STYLE_STANDARD)
35  , path_()
36  , previous_path_()
37  , symbols_map_()
38  , hidden_(true)
39 {
40  if(!hidden)
41  show();
42 }
43 
45 {
46  hide();
47 }
48 
50 {
51  if(hidden_)
52  return;
53 
54  hidden_ = true;
55 
56  if(display* disp = display::get_singleton()) {
58  disp->remove_arrow(*this);
59  }
60 }
61 
63 {
64  if(!hidden_)
65  return;
66 
67  hidden_ = false;
68 
69  if(display* disp = display::get_singleton()) {
70  disp->add_arrow(*this);
71  }
72 }
73 
75 {
76  if (valid_path(path))
77  {
79  path_ = path;
81  if(!hidden_)
82  {
85  }
86  }
87 }
88 
90 {
93  previous_path_.clear();
94  path_.clear();
95  symbols_map_.clear();
97 }
98 
99 void arrow::set_color(const std::string& color)
100 {
101  color_ = color;
102  if (valid_path(path_))
103  {
104  update_symbols();
105  }
106 }
107 
108 const std::string arrow::STYLE_STANDARD = "standard";
109 const std::string arrow::STYLE_HIGHLIGHTED = "highlighted";
110 const std::string arrow::STYLE_FOCUS = "focus";
111 const std::string arrow::STYLE_FOCUS_INVALID = "focus_invalid";
112 
113 void arrow::set_style(const std::string& style)
114 {
115  style_ = style;
116  if (valid_path(path_))
117  {
118  update_symbols();
119  }
120 }
121 
123 {
124  return path_;
125 }
126 
128 {
129  return previous_path_;
130 }
131 
132 bool arrow::path_contains(const map_location& hex) const
133 {
134  bool contains = symbols_map_.find(hex) != symbols_map_.end();
135  return contains;
136 }
137 
139 {
140  if(auto iter = symbols_map_.find(hex); iter != symbols_map_.end()) {
141  return iter->second;
142  } else {
143  return {}; // TODO: optional<locator>? Practically I don't think this path gets hit
144  }
145 }
146 
148 {
149  return (path.size() >= 2);
150 }
151 
153 {
154  if (!valid_path(path_))
155  {
156  WRN_ARR << "arrow::update_symbols called with invalid path";
157  return;
158  }
159 
160  symbols_map_.clear();
162 
163  const std::string mods = "~RC(FF00FF>"+ color_ + ")"; //magenta to current color
164 
165  const std::string dirname = "arrows/";
166  std::string prefix = "";
167  std::string suffix = "";
168  std::string image_filename = "";
169  arrow_path_t::const_iterator const arrow_start_hex = path_.begin();
170  arrow_path_t::const_iterator const arrow_pre_end_hex = path_.end() - 2;
171  arrow_path_t::const_iterator const arrow_end_hex = path_.end() - 1;
172  bool teleport_out = false;
173 
175  for (hex = path_.begin(); hex != path_.end(); ++hex)
176  {
177  prefix = "";
178  suffix = "";
179  image_filename = "";
180  bool start = false;
181  bool pre_end = false;
182  bool end = false;
183 
184  // teleport in if we teleported out last hex
185  bool teleport_in = teleport_out;
186  teleport_out = false;
187 
188  // Determine some special cases
189  if (hex == arrow_start_hex)
190  start = true;
191  if (hex == arrow_pre_end_hex)
192  pre_end = true;
193  else if (hex == arrow_end_hex)
194  end = true;
195  if (hex != arrow_end_hex && !tiles_adjacent(*hex, *(hex + 1)))
196  teleport_out = true;
197 
198  // calculate enter and exit directions, if available
200  if (!start && !teleport_in)
201  {
202  enter_dir = hex->get_relative_dir(*(hex-1));
203  }
205  if (!end && !teleport_out)
206  {
207  exit_dir = hex->get_relative_dir(*(hex+1));
208  }
209 
210  // Now figure out the actual images
211  if (teleport_out)
212  {
213  prefix = "teleport-out";
215  {
216  suffix = map_location::write_direction(enter_dir);
217  }
218  }
219  else if (teleport_in)
220  {
221  prefix = "teleport-in";
223  {
224  suffix = map_location::write_direction(exit_dir);
225  }
226  }
227  else if (start)
228  {
229  prefix = "start";
230  suffix = map_location::write_direction(exit_dir);
231  if (pre_end)
232  {
233  suffix = suffix + "_ending";
234  }
235  }
236  else if (end)
237  {
238  prefix = "end";
239  suffix = map_location::write_direction(enter_dir);
240  }
241  else
242  {
243  std::string enter, exit;
244  enter = map_location::write_direction(enter_dir);
245  exit = map_location::write_direction(exit_dir);
246  if (pre_end)
247  {
248  exit = exit + "_ending";
249  }
250 
251  //assert(std::abs(enter_dir - exit_dir) > 1); //impossible turn?
252  if (enter_dir < exit_dir)
253  {
254  prefix = enter;
255  suffix = exit;
256  }
257  else //(enter_dir > exit_dir)
258  {
259  prefix = exit;
260  suffix = enter;
261  }
262  }
263 
264  image_filename = dirname + style_ + "/" + prefix;
265  if (!suffix.empty())
266  {
267  image_filename += ("-" + suffix);
268  }
269  image_filename += ".png";
270  assert(!image_filename.empty());
271 
272  image::locator image = image::locator(image_filename, mods);
273  if (!image::exists(image))
274  {
275  ERR_ARR << "Image " << image_filename << " not found.";
277  }
278  symbols_map_[*hex] = image;
279  }
280 }
281 
283 {
284  if(display* disp = display::get_singleton()) {
285  for(const map_location& loc : path) {
286  disp->invalidate(loc);
287  }
288  }
289 }
290 
292 {
293  if(display* disp = display::get_singleton()) {
294  disp->update_arrow(*this);
295  }
296 }
map_location loc
Definition: move.cpp:172
static lg::log_domain log_arrows("arrows")
#define WRN_ARR
Definition: arrow.cpp:28
#define ERR_ARR
Definition: arrow.cpp:27
Arrows destined to be drawn on the map.
std::vector< map_location > arrow_path_t
Definition: arrow.hpp:25
bool hidden_
Definition: arrow.hpp:104
static void invalidate_arrow_path(const arrow_path_t &path)
Invalidates every hex along the given path.
Definition: arrow.cpp:282
void show()
Definition: arrow.cpp:62
static const std::string STYLE_FOCUS_INVALID
Definition: arrow.hpp:70
void hide()
Sets the arrow's visibility.
Definition: arrow.cpp:49
void set_style(const std::string &style)
Definition: arrow.cpp:113
arrow_path_t path_
Definition: arrow.hpp:98
arrow_path_t previous_path_
Definition: arrow.hpp:99
static const std::string STYLE_FOCUS
Definition: arrow.hpp:69
bool path_contains(const map_location &hex) const
Definition: arrow.cpp:132
void reset()
invalidates and clears the present path, forgets the previous path, clears the symbols map
Definition: arrow.cpp:89
static const std::string STYLE_STANDARD
If you add more styles, you should look at move::update_arrow_style()
Definition: arrow.hpp:67
static const std::string STYLE_HIGHLIGHTED
Definition: arrow.hpp:68
std::string style_
represents the subdirectory that holds images for this arrow style
Definition: arrow.hpp:96
void update_symbols()
Calculate the symbols to place along the arrow path.
Definition: arrow.cpp:152
const arrow_path_t & get_previous_path() const
Definition: arrow.cpp:127
void notify_arrow_changed()
Definition: arrow.cpp:291
~arrow()
Definition: arrow.cpp:44
arrow(const arrow &)=delete
const arrow_path_t & get_path() const
Definition: arrow.cpp:122
void set_path(const arrow_path_t &path)
Definition: arrow.cpp:74
arrow_symbols_map_t symbols_map_
Definition: arrow.hpp:102
std::string color_
Definition: arrow.hpp:94
image::locator get_image_for_loc(const map_location &hex) const
Definition: arrow.cpp:138
void set_color(const std::string &color)
The string color parameter is in the same format expected by the image::locator modifiers parameter.
Definition: arrow.cpp:99
static bool valid_path(const arrow_path_t &path)
Checks that the path is not of length 0 or 1.
Definition: arrow.cpp:147
Sort-of-Singleton that many classes, both GUI and non-GUI, use to access the game data.
Definition: display.hpp:97
static display * get_singleton()
Returns the display object if a display object exists.
Definition: display.hpp:111
Generic locator abstracting the location of an image.
Definition: picture.hpp:59
Drawing functions, for drawing things on the screen.
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).
EXIT_STATUS start(bool clear_id, const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
std::string path
Definition: filesystem.cpp:91
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:818
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
Definition: general.hpp:86
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
Encapsulates the map of the game.
Definition: location.hpp:45
static std::string write_direction(direction dir)
Definition: location.cpp:154
direction
Valid directions which can be moved in our hexagonal world.
Definition: location.hpp:47