Freeciv-3.3
Loading...
Searching...
No Matches
mapctrl_common.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 2002 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdlib.h> /* qsort */
19
20/* utility */
21#include "fcintl.h"
22#include "log.h"
23#include "support.h"
24
25/* common */
26#include "combat.h"
27#include "game.h"
28#include "unitlist.h"
29
30/* client */
31#include "agents.h"
32#include "chatline_common.h"
33#include "cityrep_g.h"
34#include "client_main.h"
35#include "climisc.h"
36#include "cma_core.h"
37#include "control.h"
38#include "editor.h"
39#include "fcintl.h"
40#include "goto.h"
41#include "mapctrl_common.h"
42#include "mapctrl_g.h"
43#include "mapview_g.h"
44#include "options.h"
45#include "overview_common.h"
46#include "tilespec.h"
47#include "zoom.h"
48
49/* Selection Rectangle */
50static float rec_anchor_x, rec_anchor_y; /* canvas coordinates for anchor */
52static int rec_corner_x, rec_corner_y; /* corner to iterate from */
53static int rec_w, rec_h; /* width, heigth in pixels */
54
57
58/* This changes the behaviour of left mouse
59 button in Area Selection mode. */
61
62/* The mapcanvas clipboard */
64{ .kind = VUT_NONE,
65 .value = {.building = NULL}
66};
67
68/* Goto with drag and drop. */
72
73/* Update the workers for a city on the map, when the update is received */
75
76/*************************************************************************/
77
79static void define_tiles_within_rectangle(bool append);
80
81/**********************************************************************/
99
100/**********************************************************************/
114static void define_tiles_within_rectangle(bool append)
115{
116 const int W = tileset_tile_width(tileset), half_W = W / 2;
117 const int H = tileset_tile_height(tileset), half_H = H / 2;
118 const int segments_x = abs(rec_w / half_W);
119 const int segments_y = abs(rec_h / half_H);
120
121 /* Iteration direction */
122 const int inc_x = (rec_w > 0 ? half_W : -half_W);
123 const int inc_y = (rec_h > 0 ? half_H : -half_H);
124 int x, y, xx, yy;
125 float x2, y2;
126 struct unit_list *units = unit_list_new();
127 const struct city *pcity;
128 bool found_any_cities = FALSE;
129
130 if (!append) {
132 }
133
134 y = rec_corner_y;
135 for (yy = 0; yy <= segments_y; yy++, y += inc_y) {
136 x = rec_corner_x;
137 for (xx = 0; xx <= segments_x; xx++, x += inc_x) {
138 struct tile *ptile;
139
140 /* For diamond shaped tiles, every other row is indented.
141 */
142 if ((yy % 2 ^ xx % 2) != 0) {
143 continue;
144 }
145
146 ptile = canvas_pos_to_tile(x, y, map_zoom);
147 if (!ptile) {
148 continue;
149 }
150
151 /* "Half-tile" indentation must match, or we'll process
152 * some tiles twice in the case of rectangular shape tiles.
153 */
154 tile_to_canvas_pos(&x2, &y2, map_zoom, ptile);
155
156 if ((yy % 2) != 0 && ((rec_corner_x % W) ^ abs((int)x2 % W)) != 0) {
157 continue;
158 }
159
160 /* Tile passed all tests; process it.
161 */
162 pcity = tile_city(ptile);
163 if (pcity != NULL && city_owner(pcity) == client_player()) {
166 }
167 unit_list_iterate(ptile->units, punit) {
170 }
172 }
173 }
174
176 && unit_list_size(units) > 0) {
177 if (!append) {
178 struct unit *punit = unit_list_get(units, 0);
179
181 unit_list_remove(units, punit);
182 }
183 unit_list_iterate(units, punit) {
186 }
187 unit_list_destroy(units);
188
189 /* Clear previous rectangle. */
191
192 /* Hilite in City List Window */
194 hilite_cities_from_canvas(); /* cityrep.c */
195 }
196}
197
198/**********************************************************************/
202{
203 const int W = tileset_tile_width(tileset), half_W = W / 2;
204 const int H = tileset_tile_height(tileset), half_H = H / 2;
205 static struct tile *rec_tile = NULL;
206 int diff_x, diff_y;
207 struct tile *center_tile;
208 struct tile *ptile;
209
211
212 /* Did mouse pointer move beyond the current tile's
213 * boundaries? Avoid macros; tile may be unreal!
214 */
215 if (ptile == rec_tile) {
216 return;
217 }
218 rec_tile = ptile;
219
220 /* Clear previous rectangle. */
222
223 /* Fix canvas coords to the center of the tile. */
225 canvas_x += half_W;
226 canvas_y += half_H;
227
228 rec_w = rec_anchor_x - canvas_x; /* Width */
229 rec_h = rec_anchor_y - canvas_y; /* Height */
230
231 /* FIXME: This may be off-by-one. */
234
235 /* Adjust width, height if mapview has recentered. */
236 if (diff_x != 0 || diff_y != 0) {
237
239 rec_w += (diff_x - diff_y) * half_W;
240 rec_h += (diff_x + diff_y) * half_H;
241
242 /* Iso wrapping */
243 if (abs(rec_w) > MAP_NATIVE_WIDTH * half_W / 2) {
245
246 rec_w > 0 ? (rec_w -= wx, rec_h -= wy) : (rec_w += wx, rec_h += wy);
247 }
248
249 } else {
250 rec_w += diff_x * W;
251 rec_h += diff_y * H;
252
253 /* X wrapping */
254 if (abs(rec_w) > MAP_NATIVE_WIDTH * half_W) {
255 int wx = MAP_NATIVE_WIDTH * W;
256
257 rec_w > 0 ? (rec_w -= wx) : (rec_w += wx);
258 }
259 }
260 }
261
262 if (rec_w == 0 && rec_h == 0) {
264 return;
265 }
266
267 /* It is currently drawn only to the screen, not backing store */
272}
273
274/**********************************************************************/
283
284/**********************************************************************/
288{
289 if (rectangle_active) {
292
293 /* Erase the previously drawn selection rectangle. */
295 }
296}
297
298/**********************************************************************/
302{
304}
305
306/**********************************************************************/
316
317/**********************************************************************/
332
333/**********************************************************************/
336void toggle_tile_hilite(struct tile *ptile)
337{
338 struct city *pcity = tile_city(ptile);
339
340 if (mapdeco_is_highlight_set(ptile)) {
342 if (pcity) {
343 toggle_city_hilite(pcity, FALSE); /* cityrep.c */
344 }
345 }
346 else if (NULL != pcity && city_owner(pcity) == client.conn.playing) {
350 } else {
351 return;
352 }
353}
354
355/**********************************************************************/
360{
362
363 if (can_client_change_view() && ptile) {
364 struct unit *punit;
366
367 if (pcity) {
369 } else if (punit) {
371 }
372 }
373}
374
375/**********************************************************************/
380{
381 char buffer[256];
382 struct city *pcity = tile_city(ptile);
383
385 return FALSE;
386 }
387
388 if (pcity) {
390 return FALSE;
391 }
392 clipboard = pcity->production;
393 } else {
394 struct unit *punit = find_visible_unit(ptile);
395
396 if (!punit) {
397 return FALSE;
398 }
399
402 FALSE)) {
404 _("You don't know how to build %s!"),
406 return TRUE;
407 }
408
411 }
413
415 ftc_client, _("Copy %s to clipboard."),
416 universal_name_translation(&clipboard, buffer, sizeof(buffer)));
417 return TRUE;
418}
419
420/**********************************************************************/
425{
427 return;
428 }
429 if (NULL == clipboard.value.building) {
431 _("Clipboard is empty."));
432 return;
433 }
435 if (NULL != pcity && city_owner(pcity) == client.conn.playing) {
437 }
438 return;
439 } else {
444 }
447 }
448}
449
450/**********************************************************************/
454{
455 if (are_universals_equal(&pcity->production, &clipboard)
457 return;
458 }
459
463}
464
465/**********************************************************************/
470{
472 return;
473 }
474 if (VUT_UTYPE == clipboard.kind) {
475 const struct unit_type *u =
477
478 if (u) {
480 }
481 }
482}
483
484/**********************************************************************/
502
503/**********************************************************************/
518
519/**********************************************************************/
527
528/**********************************************************************/
531bool can_end_turn(void)
532{
533 struct option *opt;
534
535 opt = optset_option_by_name(server_optset, "fixedlength");
536 if (opt != NULL && option_bool_get(opt)) {
537 return FALSE;
538 }
539
543 && !is_server_busy()
545 && !agents_busy());
546}
547
548/**********************************************************************/
553{
555
556 if (!can_client_change_view()) {
557 return;
558 }
559
560 gui_x += DIR_DX[gui_dir] * mapview.width / 2;
563}
564
565/**********************************************************************/
572{
574
575 if (can_client_change_view() && ptile) {
576 /* FIXME: Some actions here will need to check can_client_issue_orders.
577 * But all we can check is the lowest common requirement. */
578 do_map_click(ptile, qtype);
579 }
580}
581
582/**********************************************************************/
586{
588
589 if (can_client_issue_orders() && ptile) {
591 }
592}
593
594/**********************************************************************/
598{
600
601 if (NULL != ptile && can_client_issue_orders()) {
602 struct city *pcity = find_city_near_tile(ptile);
603
605#ifndef FREECIV_NDEBUG
606 int city_x, city_y;
607#endif
608
610
611 if (NULL != tile_worked(ptile) && tile_worked(ptile) == pcity) {
613 pcity->id, ptile->index);
614 } else if (city_can_work_tile(pcity, ptile)) {
616 pcity->id, ptile->index);
617 } else {
618 return;
619 }
620
621 /* When the city info packet is received, update the workers on the
622 * map. This is a bad hack used to selectively update the mapview
623 * when we receive the corresponding city packet. */
625 }
626 }
627}
628
629/**********************************************************************/
634{
635 /* We use the "nearest" tile here so off-map clicks will still work. */
637 mouse_zoom);
638
639 if (can_client_change_view() && ptile) {
641 }
642}
643
644/**********************************************************************/
661
662/**********************************************************************/
666{
667 struct tile *ptile;
668 struct unit_list *punits;
669
670 switch (hover_state) {
671 case HOVER_GOTO:
672 case HOVER_PATROL:
673 case HOVER_CONNECT:
675
677 break;
681
683 ptile->index, goto_last_sub_tgt,
685 break;
686 case HOVER_NONE:
687 case HOVER_TELEPORT:
688 case HOVER_PARADROP:
690 break;
691 };
692}
693
694/**********************************************************************/
698{
699 struct tile *ptile;
700 struct unit_list *punits;
701 int x, y;
702
703 switch (hover_state) {
704 case HOVER_GOTO:
705 case HOVER_PATROL:
706 case HOVER_CONNECT:
708 ptile = map_pos_to_tile(&(wld.map), x, y);
709
711 break;
714 ptile = map_pos_to_tile(&(wld.map), x, y);
716
718 ptile->index, goto_last_sub_tgt,
720 break;
721 case HOVER_NONE:
722 case HOVER_TELEPORT:
723 case HOVER_PARADROP:
725 break;
726 };
727}
728
729/**********************************************************************/
736static int unit_list_compare(const void *a, const void *b)
737{
738 const struct unit *punit1 = *(struct unit **)a;
739 const struct unit *punit2 = *(struct unit **)b;
740
742 /* For units with the same transporter or no transporter: sort by id. */
743 /* Perhaps we should sort by name instead? */
744 return punit1->id - punit2->id;
745 } else if (unit_transport_get(punit1) == punit2) {
746 return 1;
747 } else if (unit_transport_get(punit2) == punit1) {
748 return -1;
749 } else {
750 /* If the transporters aren't the same, put in order by the
751 * transporters. */
752 const struct unit *ptrans1 = unit_transport_get(punit1);
753 const struct unit *ptrans2 = unit_transport_get(punit2);
754
755 if (!ptrans1) {
756 ptrans1 = punit1;
757 }
758 if (!ptrans2) {
759 ptrans2 = punit2;
760 }
761
763 }
764}
765
766/**********************************************************************/
769void fill_tile_unit_list(const struct tile *ptile, struct unit **unit_list)
770{
771 int i = 0;
772
773 /* First populate the unit list. */
774 unit_list_iterate(ptile->units, punit) {
775 unit_list[i] = punit;
776 i++;
778
779 /* Then sort it. */
780 qsort(unit_list, i, sizeof(*unit_list), unit_list_compare);
781}
#define ACTION_NONE
Definition actions.h:55
bool agents_busy(void)
Definition agents.c:804
struct canvas int int canvas_y
Definition canvas_g.h:43
struct canvas int canvas_x
Definition canvas_g.h:43
bool city_base_to_city_map(int *city_map_x, int *city_map_y, const struct city *const pcity, const struct tile *map_tile)
Definition city.c:281
bool can_city_build_now(const struct civ_map *nmap, const struct city *pcity, const struct universal *target)
Definition city.c:1013
bool city_can_work_tile(const struct city *pcity, const struct tile *ptile)
Definition city.c:1456
#define city_list_iterate(citylist, pcity)
Definition city.h:505
#define city_tile(_pcity_)
Definition city.h:561
#define city_owner(_pcity_)
Definition city.h:560
#define city_list_iterate_end
Definition city.h:507
bool waiting_for_end_turn
void send_turn_done(void)
struct civclient client
bool can_client_issue_orders(void)
bool is_server_busy(void)
bool can_client_change_view(void)
#define client_player()
void create_event(struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition climisc.c:1093
bool cma_is_city_under_agent(const struct city *pcity, struct cm_parameter *parameter)
Definition cma_core.c:552
char * incite_cost
Definition comments.c:76
void connection_do_buffer(struct connection *pc)
Definition connection.c:324
void connection_do_unbuffer(struct connection *pc)
Definition connection.c:336
enum unit_orders goto_last_order
Definition control.c:96
void clear_hover_state(void)
Definition control.c:328
void do_map_click(struct tile *ptile, enum quickselect_type qtype)
Definition control.c:2909
void unit_focus_add(struct unit *punit)
Definition control.c:561
void unit_focus_set(struct unit *punit)
Definition control.c:506
void request_unit_goto(enum unit_orders last_order, action_id act_id, int sub_tgt_id)
Definition control.c:1130
struct extra_type * connect_tgt
Definition control.c:91
struct unit_list * get_units_in_focus(void)
Definition control.c:177
enum unit_activity connect_activity
Definition control.c:90
void set_hover_state(struct unit_list *punits, 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)
Definition control.c:290
enum cursor_hover_state hover_state
Definition control.c:89
int goto_last_sub_tgt
Definition control.c:95
struct unit * find_visible_unit(struct tile *ptile)
Definition control.c:822
int get_num_units_in_focus(void)
Definition control.c:185
void wakeup_sentried_units(struct tile *ptile)
Definition control.c:1583
action_id goto_last_action
Definition control.c:93
void do_unit_goto(struct tile *ptile)
Definition control.c:3124
quickselect_type
Definition control.h:37
@ HOVER_GOTO
Definition control.h:27
@ HOVER_PARADROP
Definition control.h:29
@ HOVER_TELEPORT
Definition control.h:28
@ HOVER_ACT_SEL_TGT
Definition control.h:32
@ HOVER_NONE
Definition control.h:26
@ HOVER_CONNECT
Definition control.h:30
@ HOVER_PATROL
Definition control.h:31
@ HOVER_GOTO_SEL_TGT
Definition control.h:33
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
#define _(String)
Definition fcintl.h:67
const struct ft_color ftc_client
struct civ_game game
Definition game.c:61
bool is_player_phase(const struct player *pplayer, int phase)
Definition game.c:712
struct world wld
Definition game.c:62
bool is_valid_goto_draw_line(struct tile *dest_tile)
Definition goto.c:1350
void toggle_city_hilite(struct city *pcity, bool on_off)
Definition cityrep.c:2093
void hilite_cities_from_canvas(void)
Definition cityrep.c:2070
void set_turn_done_button_state(bool state)
Definition mapctrl.c:210
void update_turn_done_button(bool do_restore)
Definition mapview.c:76
void draw_selection_rectangle(int canvas_x, int canvas_y, int w, int h)
Definition mapview.c:749
void update_unit_info_label(struct unit_list *punits)
Definition mapview.c:275
#define fc_assert_ret(condition)
Definition log.h:192
const int DIR_DY[8]
Definition map.c:86
const int DIR_DX[8]
Definition map.c:85
struct tile * map_pos_to_tile(const struct civ_map *nmap, int map_x, int map_y)
Definition map.c:434
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:1076
void map_distance_vector(int *dx, int *dy, const struct tile *tile0, const struct tile *tile1)
Definition map.c:1213
void cancel_selection_rectangle(void)
void update_line(int canvas_x, int canvas_y)
void maybe_activate_keyboardless_goto(int canvas_x, int canvas_y)
void adjust_workers_button_pressed(int canvas_x, int canvas_y)
bool rbutton_down
static int rec_corner_y
bool rectangle_active
void release_goto_button(int canvas_x, int canvas_y)
static int rec_h
bool tiles_hilited_cities
struct universal clipboard
void redraw_selection_rectangle(void)
void recenter_button_pressed(int canvas_x, int canvas_y)
void upgrade_canvas_clipboard(void)
void update_turn_done_button_state(void)
void action_button_pressed(int canvas_x, int canvas_y, enum quickselect_type qtype)
void wakeup_button_pressed(int canvas_x, int canvas_y)
struct city * city_workers_display
static float rec_anchor_y
bool get_turn_done_button_state(void)
void scroll_mapview(enum direction8 gui_dir)
void release_right_button(int canvas_x, int canvas_y, bool shift)
bool keyboardless_goto_button_down
static int rec_corner_x
void key_city_overlay(int canvas_x, int canvas_y)
static float rec_anchor_x
void update_selection_rectangle(float canvas_x, float canvas_y)
bool can_end_turn(void)
void overview_update_line(int overview_x, int overview_y)
void anchor_selection_rectangle(int canvas_x, int canvas_y)
void cancel_tile_hiliting(void)
bool keyboardless_goto_active
void clipboard_paste_production(struct city *pcity)
static struct tile * rec_canvas_center_tile
void fill_tile_unit_list(const struct tile *ptile, struct unit **unit_list)
static void define_tiles_within_rectangle(bool append)
static void clipboard_send_production_packet(struct city *pcity)
bool clipboard_copy_production(struct tile *ptile)
static int rec_w
bool is_city_hilited(struct city *pcity)
static int unit_list_compare(const void *a, const void *b)
struct tile * keyboardless_goto_start_tile
void toggle_tile_hilite(struct tile *ptile)
void mapdeco_set_highlight(const struct tile *ptile, bool highlight)
struct city * find_city_or_settler_near_tile(const struct tile *ptile, struct unit **punit)
void set_mapview_origin(float gui_x0, float gui_y0, float zoom)
struct view mapview
struct tile * get_center_tile_mapcanvas(void)
struct tile * canvas_pos_to_tile(float canvas_x, float canvas_y, float zoom)
struct city * find_city_near_tile(const struct tile *ptile)
bool mapdeco_is_highlight_set(const struct tile *ptile)
void center_tile_mapcanvas(const struct tile *ptile)
void toggle_city_color(struct city *pcity)
struct tile * canvas_pos_to_nearest_tile(float canvas_x, float canvas_y, float zoom)
const struct tile * center_tile
void mapdeco_clear_highlights(void)
void toggle_unit_color(struct unit *punit)
bool tile_to_canvas_pos(float *canvas_x, float *canvas_y, float zoom, const struct tile *ptile)
#define H(x, y, z)
Definition md5.c:92
const struct option_set * server_optset
Definition options.c:4278
bool option_bool_get(const struct option *poption)
Definition options.c:833
struct client_options gui_options
Definition options.c:71
struct option * optset_option_by_name(const struct option_set *poptset, const char *name)
Definition options.c:467
void overview_to_map_pos(int *map_x, int *map_y, int overview_x, int overview_y)
int dsend_packet_city_make_specialist(struct connection *pc, int city_id, int tile_id)
int dsend_packet_city_change(struct connection *pc, int city_id, int production_kind, int production_value)
int dsend_packet_city_make_worker(struct connection *pc, int city_id, int tile_id)
#define is_human(plr)
Definition player.h:231
bool are_universals_equal(const struct universal *psource1, const struct universal *psource2)
int universal_number(const struct universal *source)
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
Definition city.h:317
struct packet_game_info info
Definition game.h:89
struct connection conn
Definition client_main.h:96
bool ai_manual_turn_done
Definition options.h:155
bool separate_unit_selection
Definition options.h:175
struct player * playing
Definition connection.h:151
struct city_list * cities
Definition player.h:281
bool is_alive
Definition player.h:268
bool phase_done
Definition player.h:263
Definition tile.h:50
int index
Definition tile.h:51
struct unit_list * units
Definition tile.h:58
Definition unit.h:140
int id
Definition unit.h:147
enum universals_n kind
Definition fc_types.h:608
universals_u value
Definition fc_types.h:607
int height
float gui_x0
float gui_y0
int width
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_worked(_tile)
Definition tile.h:115
bool tileset_is_isometric(const struct tileset *t)
Definition tilespec.c:738
int tileset_tile_height(const struct tileset *t)
Definition tilespec.c:791
int tileset_tile_width(const struct tileset *t)
Definition tilespec.c:779
const struct unit_type * utype
Definition fc_types.h:553
const struct impr_type * building
Definition fc_types.h:546
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2518
@ ORDER_LAST
Definition unit.h:50
#define unit_owner(_pu)
Definition unit.h:403
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
const char * unit_name_translation(const struct unit *punit)
Definition unittype.c:1575
bool can_player_build_unit_direct(const struct player *p, const struct unit_type *punittype, bool consider_reg_impr_req)
Definition unittype.c:1974
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1709
#define MAP_NATIVE_WIDTH
float mouse_zoom
Definition zoom.c:28
float map_zoom
Definition zoom.c:25