1 /*
2    Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
3    Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY.
11 
12    See the COPYING file for more details.
13 */
14 
15 /** @file */
16 
17 #pragma once
18 
19 class config;
20 class team;
21 class game_board;
22 
23 #include "chat_events.hpp"
24 #include "display.hpp"
25 #include "display_chat_manager.hpp"
26 #include "pathfind/pathfind.hpp"
27 
28 #include <deque>
29 
30 // This needs to be separate from display.h because of the static
31 // singleton member, which will otherwise trigger link failure
32 // when building the editor.
33 
34 class game_display : public display
35 {
36 public:
37 	game_display(game_board& board,
38 			std::weak_ptr<wb::manager> wb,
39 			reports & reports_object,
40 			const config& theme_cfg,
41 			const config& level,
42 			bool dummy=false);
43 
44 	~game_display();
get_singleton()45 	static game_display* get_singleton()
46 	{
47 		return static_cast<game_display*>(singleton_);
48 	}
49 
50 	/**
51 	 * Update lighting settings.
52 	 *
53 	 * Should be called on every new turn.
54 	 */
55 	void new_turn();
56 
observers() const57 	virtual const std::set<std::string>& observers() const override { return chat_man_->observers(); }
58 	/**
59 	 * Scrolls to the leader of a certain side.
60 	 *
61 	 * This will normally be the playing team.
62 	 */
63 	void scroll_to_leader(int side, SCROLL_TYPE scroll_type = ONSCREEN,bool force = true);
64 
65 	/**
66 	 * Function to display a location as selected.
67 	 *
68 	 * If a unit is in the location, and there is no unit in the currently
69 	 * highlighted hex, the unit will be displayed in the sidebar.
70 	 */
71 	virtual void select_hex(map_location hex) override;
72 
73 	/**
74 	 * Function to highlight a location.
75 	 *
76 	 * If a unit is in the location, it will be displayed in the sidebar.
77 	 * Selection is used when a unit has been clicked on, while highlighting is
78 	 * used when a location has been moused over.
79 	 */
80 	virtual void highlight_hex(map_location hex) override;
81 
82 	/**
83 	 * Change the unit to be displayed in the sidebar.
84 	 *
85 	 * This is used when selecting or highlighting is not wanted.
86 	 */
87 	void display_unit_hex(map_location hex);
88 
89 	/**
90 	 * Sets the paths that are currently displayed as available
91 	 * for the unit to move along.
92 	 * All other paths will be grayed out.
93 	 */
94 	void highlight_reach(const pathfind::paths &paths_list);
95 
96 	/**
97 	 * Add more paths to highlight.  Print numbers where they overlap.
98 	 * Used by Show Enemy Moves.  If @a goal is not @c null_location, highlight
99 	 * enemy units that can reach @a goal.
100 	 */
101 	void highlight_another_reach(const pathfind::paths &paths_list,
102 			const map_location& goal = map_location::null_location());
103 	/**
104 	 * Return the locations of units that can reach @a goal (@see highlight_another_reach()).
105 	 */
units_that_can_reach_goal() const106 	const std::set<map_location>& units_that_can_reach_goal() const { return units_that_can_reach_goal_; }
107 
108 	/** Reset highlighting of paths. */
109 	bool unhighlight_reach();
110 
111 	/**
112 	 * Sets the route along which footsteps are drawn to show movement of a
113 	 * unit. If nullptr, no route is displayed. @a route does not have to remain
114 	 * valid after being set.
115 	 */
116 	void set_route(const pathfind::marked_route *route);
117 
118 	/** Function to float a label above a tile */
119 	void float_label(const map_location& loc, const std::string& text, const color_t& color);
120 
121 	/** Draws the movement info (turns available) for a given location. */
122 	void draw_movement_info(const map_location& loc);
123 
124 	/** Function to invalidate that unit status displayed on the sidebar. */
invalidate_unit()125 	void invalidate_unit() { invalidateGameStatus_ = true; }
126 
127 	/** Same as invalidate_unit() if moving the displayed unit. */
128 	void invalidate_unit_after_move(const map_location& src, const map_location& dst);
129 
130 	virtual const time_of_day& get_time_of_day(const map_location& loc) const override;
131 
132 	virtual bool has_time_area() const override;
133 
134 protected:
135 	/**
136 	 * game_display pre_draw does specific things related e.g. to unit rendering
137 	 * and calls the whiteboard pre-draw method.
138 	 */
139 	virtual void pre_draw() override;
140 	/**
141 	 * Calls the whiteboard's post-draw method.
142 	 */
143 	virtual void post_draw() override;
144 
145 	virtual void draw_invalidated() override;
146 
147 	virtual void post_commit() override;
148 
149 	virtual void draw_hex(const map_location& loc) override;
150 
151 	std::set<map_location> units_that_can_reach_goal_;
152 
153 public:
154 	/** Set the attack direction indicator. */
155 	void set_attack_indicator(const map_location& src, const map_location& dst);
156 	void clear_attack_indicator();
157 	// TODO: compare reports::context::mhb()->current_unit_attacks_from()
get_attack_indicator_src()158 	const map_location& get_attack_indicator_src() { return attack_indicator_src_; }
159 
160 	/** Function to get attack direction suffix. */
attack_indicator_direction() const161 	std::string attack_indicator_direction() const {
162 		return map_location::write_direction(
163 			attack_indicator_src_.get_relative_dir(attack_indicator_dst_));
164 	}
165 
166 	// Functions used in the editor:
167 
168 	//void draw_terrain_palette(int x, int y, terrain_type::TERRAIN selected);
169 	t_translation::terrain_code get_terrain_on(int palx, int paly, int x, int y);
170 
displayed_unit_hex() const171 	virtual const map_location &displayed_unit_hex() const override { return displayedUnitHex_; }
172 
173 	/**
174 	 * annotate hex with number, useful for debugging or UI prototype
175 	 */
176 	static int& debug_highlight(const map_location& loc);
clear_debug_highlights()177 	static void clear_debug_highlights() { debugHighlights_.clear(); }
178 
179 
180 	/** The playing team is the team whose turn it is. */
playing_side() const181 	virtual int playing_side() const override { return activeTeam_ + 1; }
182 
183 
184 	std::string current_team_name() const;
185 
get_chat_manager()186 	display_chat_manager & get_chat_manager() { return *chat_man_; }
187 
188 	void begin_game();
189 
in_game() const190 	virtual bool in_game() const override { return in_game_; }
191 
192 	/**
193 	 * Sets the linger mode for the display.
194 	 * There have been some discussions on what to do with fog and shroud
195 	 * the extra variables make it easier to modify the behavior. There
196 	 * might even be a split between victory and defeat.
197 	 *
198 	 * @todo if the current implementation is wanted we can change
199 	 * the stuff back to a boolean
200 	 */
201 	enum game_mode {
202 		RUNNING,         /**< no linger overlay, show fog and shroud. */
203 		LINGER };     /**< linger overlay, show fog and shroud. */
204 
205 	void set_game_mode(const game_mode mode);
206 
207 	/// Sets whether the screen (map visuals) needs to be rebuilt. This is typically after the map has been changed by wml.
208 	void needs_rebuild(bool b);
209 
210 	/// Rebuilds the screen if needs_rebuild(true) was previously called, and resets the flag.
211 	bool maybe_rebuild();
212 
213 private:
214 	game_display(const game_display&);
215 	void operator=(const game_display&);
216 
217 	virtual void draw_sidebar() override;
218 
219 	overlay_map overlay_map_;
220 
221 	// Locations of the attack direction indicator's parts
222 	map_location attack_indicator_src_;
223 	map_location attack_indicator_dst_;
224 
225 	pathfind::marked_route route_;
226 
227 	void invalidate_route();
228 
229 	map_location displayedUnitHex_;
230 
231 	double sidebarScaling_;
232 
233 	bool first_turn_, in_game_;
234 
235 	const std::unique_ptr<display_chat_manager> chat_man_;
236 
237 	game_mode mode_;
238 
239 	// For debug mode
240 	static std::map<map_location, int> debugHighlights_;
241 
242 	bool needs_rebuild_;
243 
244 };
245