Freeciv21
Develop your civilization from humble roots to a global empire
mapctrl_common.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 1996-2023 Freeciv21 and Freeciv contributors. This file is
3  part of Freeciv21. Freeciv21 is free software: you can redistribute it
4  and/or modify it under the terms of the GNU General Public License as
5  published by the Free Software Foundation, either version 3 of the
6  License, or (at your option) any later version. You should have received
7  a copy of the GNU General Public License along with Freeciv21. If not,
8  see https://www.gnu.org/licenses/.
9  */
10 
11 // utility
12 #include "fcintl.h"
13 #include "log.h"
14 #include "support.h"
15 
16 // common
17 #include "combat.h"
18 #include "game.h"
19 #include "unitlist.h"
20 
21 // client
22 #include "chatline_common.h"
23 #include "client_main.h"
24 #include "climisc.h"
25 #include "control.h"
26 #include "goto.h"
27 #include "governor.h"
28 #include "mapctrl_common.h"
29 #include "mapview_g.h"
30 #include "minimap_panel.h"
31 #include "options.h"
32 #include "page_game.h"
33 #include "views/view_map.h"
34 #include "views/view_map_common.h"
35 
36 static int rec_corner_x, rec_corner_y; // corner to iterate from
37 static int rec_w, rec_h; // width, heigth in pixels
38 
39 bool rectangle_active = false;
40 
41 /* This changes the behaviour of left mouse
42  button in Area Selection mode. */
43 bool tiles_hilited_cities = false;
44 
45 // The mapcanvas clipboard
46 struct universal clipboard = {.value = {.building = nullptr},
47  .kind = VUT_NONE};
48 
49 // Goto with drag and drop.
53 
54 // Update the workers for a city on the map, when the update is received
55 struct city *city_workers_display = nullptr;
56 
57 /*************************************************************************/
58 
59 static void clipboard_send_production_packet(struct city *pcity);
60 
65 {
66  if (rectangle_active) {
67  rectangle_active = false;
68 
69  // Erase the previously drawn selection rectangle.
71  }
72 }
73 
78 void key_city_overlay(int canvas_x, int canvas_y)
79 {
80  struct tile *ptile = canvas_pos_to_tile(canvas_x, canvas_y);
81 
82  if (can_client_change_view() && ptile) {
83  struct unit *punit;
84  struct city *pcity = find_city_or_settler_near_tile(ptile, &punit);
85 
86  if (pcity) {
87  toggle_city_color(pcity);
88  } else if (punit) {
89  toggle_unit_color(punit);
90  }
91  }
92 }
93 
98 bool clipboard_copy_production(struct tile *ptile)
99 {
100  char buffer[256];
101  struct city *pcity = tile_city(ptile);
102 
103  if (!can_client_issue_orders()) {
104  return false;
105  }
106 
107  if (pcity) {
108  if (city_owner(pcity) != client.conn.playing) {
109  return false;
110  }
111  clipboard = pcity->production;
112  } else {
113  struct unit *punit = find_visible_unit(ptile);
114  if (!punit) {
115  return false;
116  }
118  unit_type_get(punit))) {
119  create_event(ptile, E_BAD_COMMAND, ftc_client,
120  _("You don't know how to build %s!"),
121  unit_name_translation(punit));
122  return true;
123  }
124  clipboard.kind = VUT_UTYPE;
126  }
128 
129  create_event(
130  ptile, E_CITY_PRODUCTION_CHANGED, // ?
131  ftc_client, _("Copy %s to clipboard."),
132  universal_name_translation(&clipboard, buffer, sizeof(buffer)));
133  return true;
134 }
135 
140 void clipboard_paste_production(struct city *pcity)
141 {
142  if (!can_client_issue_orders()) {
143  return;
144  }
145  if (nullptr == clipboard.value.building) {
146  create_event(city_tile(pcity), E_BAD_COMMAND, ftc_client,
147  _("Clipboard is empty."));
148  return;
149  }
150  if (!tiles_hilited_cities) {
151  if (nullptr != pcity && city_owner(pcity) == client.conn.playing) {
153  }
154  return;
155  }
156 }
157 
161 static void clipboard_send_production_packet(struct city *pcity)
162 {
164  || !can_city_build_now(pcity, &clipboard)) {
165  return;
166  }
167 
168  dsend_packet_city_change(&client.conn, pcity->id, clipboard.kind,
170 }
171 
177 {
178  if (!can_client_issue_orders()) {
179  return;
180  }
181  if (VUT_UTYPE == clipboard.kind) {
182  const struct unit_type *u =
184 
185  if (u) {
186  clipboard.value.utype = u;
187  }
188  }
189 }
190 
194 void release_goto_button(int canvas_x, int canvas_y)
195 {
196  struct tile *ptile = canvas_pos_to_tile(canvas_x, canvas_y);
197 
200  && ptile) {
201  do_unit_goto(ptile);
204  }
205  keyboardless_goto_active = false;
208 }
209 
214 void maybe_activate_keyboardless_goto(int canvas_x, int canvas_y)
215 {
216  struct tile *ptile = canvas_pos_to_tile(canvas_x, canvas_y);
217 
218  if (ptile && get_num_units_in_focus() > 0
223  }
224 }
225 
230 {
231  return can_end_turn()
234 }
235 
240 {
241  struct option *opt;
242 
243  opt = optset_option_by_name(server_optset, "fixedlength");
244  if (opt != nullptr && option_bool_get(opt)) {
245  return false;
246  }
247 
251  && governor::i()->hot());
252 }
253 
259 void action_button_pressed(int canvas_x, int canvas_y,
260  enum quickselect_type qtype)
261 {
262  struct tile *ptile = canvas_pos_to_tile(canvas_x, canvas_y);
263 
264  if (can_client_change_view() && ptile) {
265  /* FIXME: Some actions here will need to check can_client_issue_orders.
266  * But all we can check is the lowest common requirement. */
267  do_map_click(ptile, qtype);
268  }
269 }
270 
274 void wakeup_button_pressed(int canvas_x, int canvas_y)
275 {
276  struct tile *ptile = canvas_pos_to_tile(canvas_x, canvas_y);
277 
278  if (can_client_issue_orders() && ptile) {
279  wakeup_sentried_units(ptile);
280  }
281 }
282 
286 void adjust_workers_button_pressed(int canvas_x, int canvas_y)
287 {
288  struct tile *ptile = canvas_pos_to_tile(canvas_x, canvas_y);
289 
290  if (nullptr != ptile && can_client_issue_orders()) {
291  struct city *pcity = find_city_or_settler_near_tile(ptile, nullptr);
292 
293  if (pcity && !cma_is_city_under_agent(pcity, nullptr)) {
294  int city_x, city_y;
295 
296  fc_assert_ret(city_base_to_city_map(&city_x, &city_y, pcity, ptile));
297 
298  if (nullptr != tile_worked(ptile) && tile_worked(ptile) == pcity) {
299  dsend_packet_city_make_specialist(&client.conn, pcity->id,
300  ptile->index);
301  } else if (city_can_work_tile(pcity, ptile)) {
302  dsend_packet_city_make_worker(&client.conn, pcity->id, ptile->index);
303  } else {
304  return;
305  }
306 
307  /* When the city info packet is received, update the workers on the
308  * map. This is a bad hack used to selectively update the mapview
309  * when we receive the corresponding city packet. */
310  city_workers_display = pcity;
311  }
312  }
313 }
314 
319 void recenter_button_pressed(int canvas_x, int canvas_y)
320 {
321  // We use the "nearest" tile here so off-map clicks will still work.
322  struct tile *ptile = canvas_pos_to_nearest_tile(canvas_x, canvas_y);
323 
324  if (can_client_change_view() && ptile) {
325  queen()->mapview_wdg->center_on_tile(ptile);
326  }
327 }
328 
333 {
334  queen()->minimap_panel->turn_done()->setEnabled(
336 
337  if (can_end_turn()) {
338  if (waiting_for_end_turn) {
339  send_turn_done();
340  } else {
342  }
343  }
344 }
345 
349 void update_line(int canvas_x, int canvas_y)
350 {
351  struct tile *ptile;
352 
353  switch (hover_state) {
354  case HOVER_GOTO:
355  case HOVER_PATROL:
356  case HOVER_CONNECT:
357  ptile = canvas_pos_to_tile(canvas_x, canvas_y);
358 
360  break;
361  case HOVER_GOTO_SEL_TGT:
362  ptile = canvas_pos_to_tile(canvas_x, canvas_y);
363  fc_assert_ret(ptile);
367  break;
368  case HOVER_NONE:
369  case HOVER_PARADROP:
370  case HOVER_ACT_SEL_TGT:
371  case HOVER_DEBUG_TILE:
372  break;
373  };
374 }
#define ACTION_NONE
Definition: actions.h:220
bool can_city_build_now(const struct city *pcity, const struct universal *target)
Returns whether city can immediately build given target, unit or improvement.
Definition: city.cpp:953
struct player * city_owner(const struct city *pcity)
Return the owner of the city.
Definition: city.cpp:1083
struct tile * city_tile(const struct city *pcity)
Return the tile location of the city.
Definition: city.cpp:1095
bool city_base_to_city_map(int *city_map_x, int *city_map_y, const struct city *const pcity, const struct tile *map_tile)
Finds the city map coordinate for a given map position and a city.
Definition: city.cpp:274
bool city_can_work_tile(const struct city *pcity, const struct tile *ptile)
Returns TRUE when a tile is available to be worked, or the city itself is currently working the tile ...
Definition: city.cpp:1392
static governor * i()
Definition: governor.cpp:107
bool hot()
Definition: governor.h:22
void center_on_tile(tile *tile, bool animate=true)
Centers the view on a tile.
Definition: view_map.cpp:197
auto turn_done()
Retrieves the Turn Done button.
Definition: minimap_panel.h:39
::minimap_panel * minimap_panel
Definition: page_game.h:82
map_view * mapview_wdg
Definition: page_game.h:81
bool waiting_for_end_turn
bool is_server_busy()
Returns if server is considered busy at the moment.
struct civclient client
bool can_client_issue_orders()
Returns TRUE iff the client can issue orders (such as giving unit commands).
void send_turn_done()
Send information about player having finished his/her turn to server.
bool can_client_change_view()
Return TRUE if the client can change the view; i.e.
void create_event(struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Creates a struct packet_generic_message packet and injects it via handle_chat_msg.
Definition: climisc.cpp:952
std::vector< unit * > & get_units_in_focus()
Returns list of units currently in focus.
Definition: control.cpp:169
enum unit_orders goto_last_order
Definition: control.cpp:89
unit * find_visible_unit(const ::tile *ptile)
Return a pointer to a visible unit, if there is one.
Definition: control.cpp:749
void do_map_click(struct tile *ptile, enum quickselect_type qtype)
Handles everything when the user clicked a tile.
Definition: control.cpp:2410
void request_unit_goto(enum unit_orders last_order, action_id act_id, int sub_tgt_id)
Do a goto with an order at the end (or ORDER_LAST).
Definition: control.cpp:995
struct extra_type * connect_tgt
Definition: control.cpp:84
enum unit_activity connect_activity
Definition: control.cpp:83
int get_num_units_in_focus()
Return the number of units currently in focus (0 or more).
Definition: control.cpp:174
enum cursor_hover_state hover_state
Definition: control.cpp:82
int goto_last_sub_tgt
Definition: control.cpp:88
void set_hover_state(const std::vector< unit * > &units, enum cursor_hover_state state, enum unit_activity activity, struct extra_type *tgt, int last_tgt, int last_sub_tgt, action_id action, enum unit_orders order)
Enter the given hover state.
Definition: control.cpp:272
void clear_hover_state()
Clear current hover state (go to HOVER_NONE).
Definition: control.cpp:308
void wakeup_sentried_units(struct tile *ptile)
Wakes all owned sentried units on tile.
Definition: control.cpp:1458
action_id goto_last_action
Definition: control.cpp:86
void do_unit_goto(struct tile *ptile)
Finish the goto mode and let the units stored in goto_map_list move to a given location.
Definition: control.cpp:2647
quickselect_type
Definition: control.h:30
@ HOVER_GOTO
Definition: control.h:20
@ HOVER_PARADROP
Definition: control.h:21
@ HOVER_ACT_SEL_TGT
Definition: control.h:24
@ HOVER_NONE
Definition: control.h:19
@ HOVER_CONNECT
Definition: control.h:22
@ HOVER_DEBUG_TILE
Definition: control.h:26
@ HOVER_PATROL
Definition: control.h:23
@ HOVER_GOTO_SEL_TGT
Definition: control.h:25
#define _(String)
Definition: fcintl.h:50
const struct ft_color ftc_client
struct civ_game game
Definition: game.cpp:47
bool is_player_phase(const struct player *pplayer, int phase)
Return TRUE if it is this player's phase.
Definition: game.cpp:672
bool is_valid_goto_draw_line(struct tile *dest_tile)
Puts a line to dest_tile on the map according to the current goto_map.
Definition: goto.cpp:383
bool cma_is_city_under_agent(const struct city *pcity, struct cm_parameter *parameter)
Check whether city is under governor control, and fill parameter if it is.
Definition: governor.cpp:632
#define fc_assert_ret(condition)
Definition: log.h:112
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Are (x1,y1) and (x2,y2) really the same when adjusted? This function might be necessary ALOT of place...
Definition: map.cpp:887
void update_line(int canvas_x, int canvas_y)
Update the goto/patrol line to the given map canvas location.
void maybe_activate_keyboardless_goto(int canvas_x, int canvas_y)
The goto hover state is only activated when the mouse pointer moves beyond the tile where the button ...
void adjust_workers_button_pressed(int canvas_x, int canvas_y)
Adjust the position of city workers from the mapview.
static int rec_corner_y
bool rectangle_active
void release_goto_button(int canvas_x, int canvas_y)
Goto button has been released.
bool get_turn_done_button_state()
Return TRUE iff the turn done button should be enabled.
static int rec_h
bool tiles_hilited_cities
struct universal clipboard
void recenter_button_pressed(int canvas_x, int canvas_y)
Recenter the map on the canvas location, on user request.
void update_turn_done_button_state()
Update the turn done button state.
void action_button_pressed(int canvas_x, int canvas_y, enum quickselect_type qtype)
Do some appropriate action when the "main" mouse button (usually left-click) is pressed.
void wakeup_button_pressed(int canvas_x, int canvas_y)
Wakeup sentried units on the tile of the specified location.
struct city * city_workers_display
bool keyboardless_goto_button_down
static int rec_corner_x
void key_city_overlay(int canvas_x, int canvas_y)
The user pressed the overlay-city button (t) while the mouse was at the given canvas position.
bool can_end_turn()
Return TRUE iff client can end turn.
void cancel_selection_rectangle()
Redraws the selection rectangle after a map flush.
void upgrade_canvas_clipboard()
A newer technology may be available for units.
bool keyboardless_goto_active
void clipboard_paste_production(struct city *pcity)
If City tiles are hilited, paste into all those cities.
static void clipboard_send_production_packet(struct city *pcity)
Send request to build production in clipboard to server.
bool clipboard_copy_production(struct tile *ptile)
Shift-Left-Click on owned city or any visible unit to copy.
static int rec_w
struct tile * keyboardless_goto_start_tile
void update_turn_done_button(bool do_restore)
If do_restore is false it should change the turn button style (to draw the user's attention to it).
Definition: view_map.cpp:468
void draw_selection_rectangle(int canvas_x, int canvas_y, int w, int h)
Area Selection.
Definition: view_map.cpp:546
void update_unit_info_label(const std::vector< unit * > &unit_list)
Update the information label which gives info on the current unit and the tile under the current unit...
Definition: view_map.cpp:446
const struct option_set * server_optset
Definition: options.cpp:2430
client_options * gui_options
Definition: options.cpp:74
struct option * optset_option_by_name(const struct option_set *poptset, const char *name)
Returns the option corresponding of the name in this option set.
Definition: options.cpp:110
bool option_bool_get(const struct option *poption)
Returns the current value of this boolean option.
Definition: options.cpp:457
pageGame * queen()
Return game instandce.
Definition: page_game.cpp:557
#define is_human(plr)
Definition: player.h:226
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
Make user-friendly text for the source.
bool are_universals_equal(const struct universal *psource1, const struct universal *psource2)
Return TRUE iff the two sources are equivalent.
int universal_number(const struct universal *source)
Return the universal number of the constituent.
Definition: city.h:291
int id
Definition: city.h:296
struct universal production
Definition: city.h:368
struct packet_game_info info
Definition: game.h:80
struct connection conn
Definition: client_main.h:89
bool ai_manual_turn_done
Definition: options.h:84
struct player * playing
Definition: connection.h:142
The base class for options.
Definition: options.cpp:209
bool is_alive
Definition: player.h:250
bool phase_done
Definition: player.h:245
Definition: tile.h:42
int index
Definition: tile.h:43
Definition: unit.h:134
enum universals_n kind
Definition: fc_types.h:740
universals_u value
Definition: fc_types.h:739
struct city * tile_city(const struct tile *ptile)
Return the city on this tile (or nullptr), checking for city center.
Definition: tile.cpp:72
#define tile_worked(_tile)
Definition: tile.h:97
const struct unit_type * utype
Definition: fc_types.h:585
const struct impr_type * building
Definition: fc_types.h:579
@ ORDER_LAST
Definition: unit.h:43
const struct unit_type * unit_type_get(const struct unit *punit)
Return the unit type for this unit.
Definition: unittype.cpp:114
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Return whether this player can upgrade this unit type (to any other unit type).
Definition: unittype.cpp:1379
bool can_player_build_unit_direct(const struct player *p, const struct unit_type *punittype)
Whether player can build given unit somewhere, ignoring whether unit is obsolete and assuming the pla...
Definition: unittype.cpp:1628
const char * unit_name_translation(const struct unit *punit)
Return the (translated) name of the unit.
Definition: unittype.cpp:1265
struct tile * canvas_pos_to_tile(float canvas_x, float canvas_y)
Finds the tile corresponding to pixel coordinates.
struct city * find_city_or_settler_near_tile(const struct tile *ptile, struct unit **punit)
Find the "best" city/settlers to associate with the selected tile.
void toggle_city_color(struct city *pcity)
Toggle the city color.
void toggle_unit_color(struct unit *punit)
Toggle the unit color.
struct tile * canvas_pos_to_nearest_tile(float canvas_x, float canvas_y)
Finds the tile corresponding to pixel coordinates.