1 /*
2    Copyright (C) 2006 - 2018 by Joerg Hinrichs <joerg.hinrichs@alice-dsl.de>
3    wesnoth playturn Copyright (C) 2003 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 #pragma once
17 
18 #include "game_display.hpp"             // for game_display -> display conversion.
19 #include "map/location.hpp"             // for map_location
20 #include "mouse_handler_base.hpp"       // for mouse_handler_base
21 #include "pathfind/pathfind.hpp"        // for marked_route, paths
22 #include "units/map.hpp"                 // for unit_map, etc
23 
24 #include <set>                          // for set
25 #include <vector>                       // for vector
26 #include <SDL2/SDL_events.h>                 // for SDL_MouseButtonEvent
27 
28 class game_display;
29 class battle_context;  // lines 23-23
30 class play_controller;
31 class team;
32 class unit;
33 
34 namespace events{
35 
36 class mouse_handler : public mouse_handler_base {
37 public:
38 	mouse_handler(game_display* gui, play_controller & pc);
39 	~mouse_handler();
get_singleton()40 	static mouse_handler* get_singleton() { return singleton_ ;}
41 	void set_side(int side_number);
42 	void mouse_press(const SDL_MouseButtonEvent& event, const bool browse);
43 	void cycle_units(const bool browse, const bool reverse = false);
cycle_back_units(const bool browse)44 	void cycle_back_units(const bool browse) { cycle_units(browse, true); }
45 
get_path_turns() const46 	int get_path_turns() const { return path_turns_; }
47 
48 	/**
49 	 * @param loc the location occupied by the enemy
50 	 * @returns the location from which the selected unit can attack the enemy
51 	 */
52 	map_location current_unit_attacks_from(const map_location& loc) const;
current_paths() const53 	const pathfind::paths& current_paths() const { return current_paths_; }
54 
get_last_hex() const55 	const map_location& get_last_hex() const { return last_hex_; }
get_selected_hex() const56 	map_location get_selected_hex() const { return selected_hex_; }
set_path_turns(const int path_turns)57 	void set_path_turns(const int path_turns) { path_turns_ = path_turns; }
58 	void set_current_paths(const pathfind::paths & new_paths);
59 	void deselect_hex();
invalidate_reachmap()60 	void invalidate_reachmap() { reachmap_invalid_ = true; }
61 
set_gui(game_display * gui)62 	void set_gui(game_display* gui) { gui_ = gui; }
63 
64 	unit_map::iterator selected_unit();
65 
66 	pathfind::marked_route get_route(const unit* un, map_location go_to, team &team) const;
67 
get_current_route() const68 	const pathfind::marked_route& get_current_route() const { return current_route_; }
69 
70 	//get visible adjacent enemies of 1-based side around location loc
71 	std::set<map_location> get_adj_enemies(const map_location& loc, int side) const;
72 
73 	// show the attack dialog and return the choice made
74 	// which can be invalid if 'cancel' was used
75 	int show_attack_dialog(const map_location& attacker_loc, const map_location& defender_loc);
76 	// wrapper to catch bad_alloc so this should be called
77 	void attack_enemy(const map_location& attacker_loc, const map_location& defender_loc, int choice);
78 
79 	/// Moves a unit across the board for a player.
80 	size_t move_unit_along_route(const std::vector<map_location> & steps, bool & interrupted);
81 
82 	void select_hex(const map_location& hex, const bool browse,
83 		const bool highlight = true,
84 		const bool fire_event = true);
85 
86 	void move_action(bool browse);
87 
88 	void touch_action(const map_location hex, bool browse);
89 
90 	void select_or_action(bool browse);
91 
92 	/**
93 	 * Uses SDL and @ref game_display::hex_clicked_on
94 	 * to fetch the hex the mouse is hovering, if applicable.
95 	 */
96 	const map_location hovered_hex() const;
97 
98 	/** Unit exists on the hex, no matter if friend or foe. */
99 	bool hex_hosts_unit(const map_location& hex) const;
100 
101 	/**
102 	 * Use this to disable hovering an unit from highlighting its movement
103 	 * range.
104 	 *
105 	 * @see enable_units_highlight()
106 	 */
107 	void disable_units_highlight();
108 
109 	/**
110 	 * When unit highlighting is disabled, call this when the mouse no
111 	 * longer hovers any unit to enable highlighting again.
112 	 *
113 	 * @see disable_units_highlight()
114 	 */
115 	void enable_units_highlight();
116 
117 protected:
118 	/**
119 	 * Due to the way this class is constructed we can assume that the
120 	 * display* gui_ member actually points to a game_display (derived class)
121 	 */
gui()122 	game_display& gui() { return *gui_; }
123 	/** Const version */
gui() const124 	const game_display& gui() const { return *gui_; }
125 
126 	int drag_threshold() const;
127 	/**
128 	 * Use update to force an update of the mouse state.
129 	 */
130 	void mouse_motion(int x, int y, const bool browse, bool update=false, map_location loc = map_location::null_location());
131 	bool right_click_show_menu(int x, int y, const bool browse);
132 //	bool left_click(int x, int y, const bool browse);
133 	bool move_unit_along_current_route();
134 
135 	void touch_motion(int x, int y, const bool browse, bool update=false, map_location loc = map_location::null_location());
136 
137 	void save_whiteboard_attack(const map_location& attacker_loc, const map_location& defender_loc, int weapon_choice);
138 
139 	// fill weapon choices into bc_vector
140 	// return the best weapon choice
141 	int fill_weapon_choices(std::vector<battle_context>& bc_vector, unit_map::iterator attacker, unit_map::iterator defender);
142 	// the real function but can throw bad_alloc
143 	// choice is the attack chosen in the attack dialog
144 	void attack_enemy_(const map_location& attacker_loc
145 			, const map_location& defender_loc
146 			, int choice);
147 
148 	void show_attack_options(const unit_map::const_iterator &u);
149 	unit_map::const_iterator find_unit(const map_location& hex) const;
150 	unit_map::iterator find_unit(const map_location& hex);
151 	/*
152 	 * These return raw pointers instead of smart pointers.
153 	 * Useful if you don't want to increase the unit reference count.
154 	 */
155 	unit* find_unit_nonowning(const map_location& hex);
156 	const unit* find_unit_nonowning(const map_location& hex) const;
157 	bool unit_in_cycle(unit_map::const_iterator it);
158 private:
159 	team& viewing_team();
160 	const team& viewing_team() const;
161 	team &current_team();
162 
163 	game_display* gui_;
164 	play_controller & pc_;
165 
166 	// previous highlighted hexes
167 	// the hex of the selected unit and empty hex are "free"
168 	map_location previous_hex_;
169 	map_location previous_free_hex_;
170 	map_location selected_hex_;
171 	map_location next_unit_;
172 	pathfind::marked_route current_route_;
173 	pathfind::paths current_paths_;
174 	bool unselected_paths_;
175 	bool unselected_reach_;
176 	int path_turns_;
177 	int side_num_;
178 
179 	bool over_route_;
180 	bool reachmap_invalid_;
181 	bool show_partial_move_;
182 
183 	static mouse_handler * singleton_;
184 
185 	bool preventing_units_highlight_;
186 };
187 
188 }
189