1 /***********************************************************************
2 Freeciv - Copyright (C) 2005 - 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)
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 ***********************************************************************/
15 #include <fc_config.h>
22 #include "bitvector.h"
34 #include "client_main.h"
38 #include "mapctrl_common.h"
43 #include "editgui_g.h"
44 #include "mapview_g.h"
47 enum selection_modes
{
48 SELECTION_MODE_NEW
= 0,
53 enum editor_tool_flags
{
58 ETF_HAS_APPLIED_PLAYER
= 1<<3,
59 ETF_HAS_VALUE_ERASE
= 1<<4
64 struct tile_list
*vtiles
;
65 const struct tile
*origin
;
70 enum editor_tool_mode mode
;
73 int applied_player_no
;
80 enum editor_tool_type tool
;
81 struct editor_tool tools
[NUM_EDITOR_TOOL_TYPES
];
83 const struct tile
*current_tile
;
94 enum selection_modes selection_mode
;
96 struct tile_hash
*selected_tile_table
;
97 struct edit_buffer
*copybuf
;
100 static struct editor_state
*editor
= NULL
;
102 /****************************************************************************
103 Set tool to some value legal under current ruleset.
104 ****************************************************************************/
105 static void tool_set_init_value(enum editor_tool_type ett
)
107 struct editor_tool
*tool
= editor
->tools
+ ett
;
109 if (ett
== ETT_TERRAIN_SPECIAL
111 || ett
== ETT_MILITARY_BASE
) {
112 struct extra_type
*first
= NULL
;
114 extra_type_iterate(pextra
) {
115 if (ett
== ETT_ROAD
) {
116 if (is_extra_caused_by(pextra
, EC_ROAD
)) {
120 } else if (ett
== ETT_MILITARY_BASE
) {
121 if (is_extra_caused_by(pextra
, EC_BASE
)) {
126 /* Considers extras that are neither bases or roads, specials */
130 } extra_type_iterate_end
;
133 tool
->value
= extra_index(first
);
142 /****************************************************************************
143 Initialize editor tool data.
144 ****************************************************************************/
145 static void tool_init(enum editor_tool_type ett
, const char *name
,
146 int flags
, const char *tooltip
)
148 struct editor_tool
*tool
;
150 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
154 tool
= editor
->tools
+ ett
;
156 if (ett
== ETT_COPYPASTE
) {
157 tool
->mode
= ETM_COPY
;
159 tool
->mode
= ETM_PAINT
;
163 tool
->tooltip
= tooltip
;
166 tool
->applied_player_no
= 0;
168 tool_set_init_value(ett
);
171 /****************************************************************************
172 Adjust editor for changed ruleset.
173 ****************************************************************************/
174 void editor_ruleset_changed(void)
178 for (t
= 0; t
< NUM_EDITOR_TOOL_TYPES
; t
++) {
179 tool_set_init_value(t
);
183 /****************************************************************************
184 Initialize the client's editor state information to some suitable default
185 values. This only needs to be done once at client start.
186 ****************************************************************************/
187 void editor_init(void)
189 fc_assert(editor
== NULL
);
191 editor
= fc_calloc(1, sizeof(struct editor_state
));
193 tool_init(ETT_TERRAIN
, _("Terrain"),
194 ETF_HAS_VALUE
| ETF_HAS_SIZE
,
195 _("Change tile terrain.\nShortcut: t\n"
196 "Select terrain type: shift+t or right-click here."));
197 tool_init(ETT_TERRAIN_RESOURCE
, _("Terrain Resource"),
198 ETF_HAS_VALUE
| ETF_HAS_SIZE
,
199 _("Change tile terrain resources.\nShortcut: r\n"
200 "Select resource type: shift+r or right-click here."));
201 tool_init(ETT_TERRAIN_SPECIAL
, _("Terrain Special"), ETF_HAS_VALUE
202 | ETF_HAS_SIZE
| ETF_HAS_VALUE_ERASE
,
203 _("Modify tile specials.\nShortcut: s\n"
204 "Select special type: shift+s or right-click here."));
205 tool_init(ETT_ROAD
, _("Road"), ETF_HAS_VALUE
206 | ETF_HAS_SIZE
| ETF_HAS_VALUE_ERASE
,
207 _("Modify roads on tile.\nShortcut: p\n"
208 "Select road type: shift+p or right-click here."));
209 tool_init(ETT_MILITARY_BASE
, _("Military Base"), ETF_HAS_VALUE
210 | ETF_HAS_SIZE
| ETF_HAS_VALUE_ERASE
,
211 _("Create a military base.\nShortcut: m\n"
212 "Select base type: shift+m or right-click here."));
213 tool_init(ETT_UNIT
, _("Unit"), ETF_HAS_VALUE
| ETF_HAS_COUNT
214 | ETF_HAS_APPLIED_PLAYER
| ETF_HAS_VALUE_ERASE
,
215 _("Create unit.\nShortcut: u\nSelect unit "
216 "type: shift+u or right-click here."));
217 tool_init(ETT_CITY
, _("City"), ETF_HAS_SIZE
| ETF_HAS_APPLIED_PLAYER
,
218 _("Create city.\nShortcut: c"));
219 tool_init(ETT_VISION
, _("Vision"), ETF_HAS_SIZE
,
220 _("Modify player's tile knowledge.\nShortcut: v"));
221 tool_init(ETT_STARTPOS
, _("Start Position"), ETF_NO_FLAGS
,
222 _("Place a start position which allows any nation to "
223 "start at the tile. To allow only certain nations to "
224 "start there, middle click on the start position on "
225 "the map and use the property editor.\nShortcut: b"));
227 tool_init(ETT_COPYPASTE
, _("Copy/Paste"), ETF_HAS_SIZE
,
228 _("Copy and paste tiles.\n"
229 "Shortcut for copy mode: shift-c\n"
230 "Shoftcut for paste mode: shift-v"));
231 editor
->copybuf
= edit_buffer_new(EBT_ALL
);
233 editor
->selected_tile_table
= tile_hash_new();
234 tile_hash_set_no_shrink(editor
->selected_tile_table
, TRUE
);
237 /****************************************************************************
238 Clear the editor data which is game dependent.
239 ****************************************************************************/
240 void editor_clear(void)
242 fc_assert_ret(editor
!= NULL
);
244 edit_buffer_clear(editor
->copybuf
);
245 tile_hash_clear(editor
->selected_tile_table
);
248 /****************************************************************************
249 Free the client's editor.
250 ****************************************************************************/
251 void editor_free(void)
253 fc_assert_ret(editor
!= NULL
);
255 edit_buffer_free(editor
->copybuf
);
256 tile_hash_destroy(editor
->selected_tile_table
);
261 /****************************************************************************
262 Set the current tool to be used by the editor.
263 ****************************************************************************/
264 void editor_set_tool(enum editor_tool_type ett
)
266 if (editor
== NULL
) {
270 if (!(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
277 /****************************************************************************
278 Get the current tool used by the editor.
279 ****************************************************************************/
280 enum editor_tool_type
editor_get_tool(void)
282 if (editor
== NULL
) {
283 return NUM_EDITOR_TOOL_TYPES
;
289 /****************************************************************************
290 Set the mode for the editor tool.
291 ****************************************************************************/
292 void editor_tool_set_mode(enum editor_tool_type ett
,
293 enum editor_tool_mode etm
)
295 if (editor
== NULL
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)
296 || !(0 <= etm
&& etm
< NUM_EDITOR_TOOL_MODES
)
297 || !editor_tool_has_mode(ett
, etm
)) {
301 editor
->tools
[ett
].mode
= etm
;
304 /****************************************************************************
305 Return TRUE if the given tool supports the given mode.
306 ****************************************************************************/
307 bool editor_tool_has_mode(enum editor_tool_type ett
,
308 enum editor_tool_mode etm
)
310 if (editor
== NULL
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)
311 || !(0 <= etm
&& etm
< NUM_EDITOR_TOOL_MODES
)) {
315 if (etm
== ETM_COPY
|| etm
== ETM_PASTE
) {
316 return ett
== ETT_COPYPASTE
;
319 if (ett
== ETT_COPYPASTE
) {
320 return etm
== ETM_COPY
|| etm
== ETM_PASTE
;
326 /****************************************************************************
327 Get the mode for the tool.
328 ****************************************************************************/
329 enum editor_tool_mode
editor_tool_get_mode(enum editor_tool_type ett
)
331 if (editor
== NULL
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
332 return NUM_EDITOR_TOOL_MODES
;
334 return editor
->tools
[ett
].mode
;
337 /****************************************************************************
338 Returns TRUE if the *client* is in edit mode.
339 ****************************************************************************/
340 bool editor_is_active(void)
342 return can_conn_edit(&client
.conn
);
345 /****************************************************************************
346 Returns TRUE if the given tool should be made available to the user via
347 the editor GUI. For example, this will return FALSE for ETT_MILITARY_BASE
348 if there are no bases defined in the ruleset.
350 NB: This depends on the ruleset information received from the server, so
351 it will return FALSE if the client does not have it yet.
352 ****************************************************************************/
353 bool editor_tool_is_usable(enum editor_tool_type ett
)
355 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
360 case ETT_MILITARY_BASE
:
361 return base_count() > 0;
363 return road_count() > 0;
364 case ETT_TERRAIN_RESOURCE
:
365 return resource_count() > 0;
367 return utype_count() > 0;
374 /****************************************************************************
375 Returns TRUE if the given tool type has sub-values (e.g. the terrain
376 tool has values corresponding to the terrain types).
377 ****************************************************************************/
378 bool editor_tool_has_value(enum editor_tool_type ett
)
380 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
383 return editor
->tools
[ett
].flags
& ETF_HAS_VALUE
;
386 /****************************************************************************
387 Set the value ID for the given tool. How the value is interpreted depends
389 ****************************************************************************/
390 void editor_tool_set_value(enum editor_tool_type ett
, int value
)
392 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)
393 || !editor_tool_has_value(ett
)) {
396 editor
->tools
[ett
].value
= value
;
399 /****************************************************************************
400 Get the current tool sub-value.
401 ****************************************************************************/
402 int editor_tool_get_value(enum editor_tool_type ett
)
404 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)
405 || !editor_tool_has_value(ett
)) {
409 return editor
->tools
[ett
].value
;
412 /****************************************************************************
413 Record the start of the selection rectangle.
414 ****************************************************************************/
415 static void editor_start_selection_rectangle(int canvas_x
, int canvas_y
)
421 if (editor
->selection_mode
== SELECTION_MODE_NEW
422 && editor_selection_count() > 0) {
423 editor_selection_clear();
424 update_map_canvas_visible();
427 editor
->selrect_start_x
= canvas_x
;
428 editor
->selrect_start_y
= canvas_y
;
429 editor
->selrect_width
= 0;
430 editor
->selrect_height
= 0;
431 editor
->selrect_active
= TRUE
;
434 /****************************************************************************
435 Temporary convenience function to work-around the fact that certain
436 special values (S_RESOURCE_VALID) do not in fact
437 correspond to drawable special types.
438 ****************************************************************************/
439 static inline bool tile_really_has_any_specials(const struct tile
*ptile
)
445 extra_type_by_cause_iterate(EC_SPECIAL
, pextra
) {
446 if (tile_has_extra(ptile
, pextra
)) {
449 } extra_type_by_cause_iterate_end
;
454 /****************************************************************************
455 Set the editor's current applied player number according to what exists
457 ****************************************************************************/
458 static void editor_grab_applied_player(const struct tile
*ptile
)
462 if (!editor
|| !ptile
) {
466 if (client_has_player()
467 && tile_get_known(ptile
, client_player()) == TILE_UNKNOWN
) {
471 if (tile_city(ptile
) != NULL
) {
472 apno
= player_number(city_owner(tile_city(ptile
)));
473 } else if (unit_list_size(ptile
->units
) > 0) {
474 struct unit
*punit
= unit_list_get(ptile
->units
, 0);
475 apno
= player_number(unit_owner(punit
));
476 } else if (tile_owner(ptile
) != NULL
) {
477 apno
= player_number(tile_owner(ptile
));
480 if (player_by_number(apno
) != NULL
) {
481 editor_tool_set_applied_player(editor_get_tool(), apno
);
486 /****************************************************************************
487 Set the editor's current tool according to what exists at the given tile.
488 ****************************************************************************/
489 static void editor_grab_tool(const struct tile
*ptile
)
491 int ett
= -1, value
= 0;
492 struct extra_type
*first_base
= NULL
;
493 struct extra_type
*first_road
= NULL
;
503 extra_type_by_cause_iterate(EC_BASE
, pextra
) {
504 if (tile_has_extra(ptile
, pextra
)) {
508 } extra_type_by_cause_iterate_end
;
510 extra_type_by_cause_iterate(EC_ROAD
, pextra
) {
511 if (tile_has_extra(ptile
, pextra
)) {
515 } extra_type_by_cause_iterate_end
;
517 if (client_has_player()
518 && tile_get_known(ptile
, client_player()) == TILE_UNKNOWN
) {
521 } else if (tile_city(ptile
)) {
524 } else if (unit_list_size(ptile
->units
) > 0) {
525 int max_score
= 0, score
;
526 struct unit
*grabbed_punit
= NULL
;
528 unit_list_iterate(ptile
->units
, punit
) {
530 if (uclass_has_flag(unit_class_get(punit
), UCF_UNREACHABLE
)) {
532 } else if (utype_move_type(unit_type_get(punit
)) == UMT_LAND
) {
534 } else if (utype_move_type(unit_type_get(punit
)) == UMT_SEA
) {
539 if (unit_transported(punit
)) {
543 if (score
> max_score
) {
545 grabbed_punit
= punit
;
547 } unit_list_iterate_end
;
551 value
= utype_number(unit_type_get(grabbed_punit
));
553 } else if (first_base
!= NULL
) {
554 ett
= ETT_MILITARY_BASE
;
555 value
= extra_index(first_base
);
557 } else if (first_road
!= NULL
) {
559 value
= extra_index(first_road
);
561 } else if (tile_really_has_any_specials(ptile
)) {
562 struct extra_type
*specials_array
[MAX_EXTRA_TYPES
];
564 struct extra_type
*special
= NULL
;
566 extra_type_by_cause_iterate(EC_SPECIAL
, s
) {
567 specials_array
[count
++] = s
;
568 } extra_type_by_cause_iterate_end
;
570 /* Grab specials in reverse order of enum tile_special_type. */
572 for (i
= count
- 1; i
>= 0; i
--) {
573 if (tile_has_extra(ptile
, specials_array
[i
])) {
574 special
= specials_array
[i
];
579 if (special
!= NULL
) {
580 ett
= ETT_TERRAIN_SPECIAL
;
581 value
= extra_index(special
);
583 } else if (tile_resource(ptile
) != NULL
) {
584 ett
= ETT_TERRAIN_RESOURCE
;
585 value
= resource_number(tile_resource(ptile
));
587 } else if (tile_terrain(ptile
) != NULL
) {
589 value
= terrain_number(tile_terrain(ptile
));
596 editor_set_tool(ett
);
597 if (editor_tool_has_value(ett
)) {
598 editor_tool_set_value(ett
, value
);
603 /****************************************************************************
604 Returns TRUE if the given tile has some objects with editable properties.
605 ****************************************************************************/
606 static inline bool can_edit_tile_properties(struct tile
*ptile
)
608 return ptile
!= NULL
;
611 /****************************************************************************
612 Handle a request to edit the properties for the given tile. If the tile
613 is part of a selection, then all selected tiles are passed to the
615 ****************************************************************************/
616 static void popup_properties(struct tile
*ptile
)
618 struct tile_list
*tiles
;
624 tiles
= tile_list_new();
626 if (editor_tile_is_selected(ptile
)) {
627 tile_hash_iterate(editor
->selected_tile_table
, sel_tile
) {
628 if (can_edit_tile_properties(sel_tile
)) {
629 tile_list_append(tiles
, sel_tile
);
631 } tile_hash_iterate_end
;
633 if (can_edit_tile_properties(ptile
)) {
634 tile_list_append(tiles
, ptile
);
638 editgui_popup_properties(tiles
, NUM_OBJTYPES
);
640 tile_list_destroy(tiles
);
643 /****************************************************************************
644 Handle a user's mouse button press at the given point on the map canvas.
645 ****************************************************************************/
646 void editor_mouse_button_press(int canvas_x
, int canvas_y
,
647 int button
, int modifiers
)
651 if (editor
== NULL
) {
655 ptile
= canvas_pos_to_tile(canvas_x
, canvas_y
);
662 case MOUSE_BUTTON_LEFT
:
663 if (modifiers
== EKM_SHIFT
) {
664 editor_grab_tool(ptile
);
665 } else if (modifiers
== EKM_CTRL
) {
666 editor_grab_applied_player(ptile
);
667 } else if (modifiers
== EKM_NONE
) {
668 editor
->tool_active
= TRUE
;
669 editor_apply_tool(ptile
, FALSE
);
670 editor_notify_edit_finished();
671 editor_set_current_tile(ptile
);
675 case MOUSE_BUTTON_RIGHT
:
676 if (modifiers
== (EKM_ALT
| EKM_CTRL
)) {
677 popup_properties(ptile
);
681 if (modifiers
== EKM_SHIFT
) {
682 editor
->selection_mode
= SELECTION_MODE_ADD
;
683 } else if (modifiers
== EKM_ALT
) {
684 editor
->selection_mode
= SELECTION_MODE_REMOVE
;
685 } else if (modifiers
== EKM_NONE
) {
686 editor
->selection_mode
= SELECTION_MODE_NEW
;
690 editor_start_selection_rectangle(canvas_x
, canvas_y
);
693 case MOUSE_BUTTON_MIDDLE
:
694 if (modifiers
== EKM_NONE
) {
695 popup_properties(ptile
);
704 /****************************************************************************
705 Record and handle the end of the selection rectangle.
706 ****************************************************************************/
707 static void editor_end_selection_rectangle(int canvas_x
, int canvas_y
)
715 editor
->selrect_active
= FALSE
;
717 if (editor
->selrect_width
<= 0 || editor
->selrect_height
<= 0) {
720 ptile
= canvas_pos_to_tile(canvas_x
, canvas_y
);
721 if (ptile
&& editor
->selection_mode
== SELECTION_MODE_ADD
) {
722 editor_selection_add(ptile
);
723 } else if (ptile
&& editor
->selection_mode
== SELECTION_MODE_REMOVE
) {
724 editor_selection_remove(ptile
);
726 recenter_button_pressed(canvas_x
, canvas_y
);
731 refresh_tile_mapcanvas(ptile
, TRUE
, TRUE
);
737 gui_rect_iterate(mapview
.gui_x0
+ editor
->selrect_x
,
738 mapview
.gui_y0
+ editor
->selrect_y
,
739 editor
->selrect_width
, editor
->selrect_height
,
740 ptile
, pedge
, pcorner
, map_zoom
) {
744 if (editor
->selection_mode
== SELECTION_MODE_NEW
745 || editor
->selection_mode
== SELECTION_MODE_ADD
) {
746 editor_selection_add(ptile
);
747 } else if (editor
->selection_mode
== SELECTION_MODE_REMOVE
) {
748 editor_selection_remove(ptile
);
750 } gui_rect_iterate_end
;
752 w
= tileset_tile_width(tileset
);
753 h
= tileset_tile_height(tileset
);
755 update_map_canvas(editor
->selrect_x
- w
,
756 editor
->selrect_y
- h
,
757 editor
->selrect_width
+ 2 * w
,
758 editor
->selrect_height
+ 2 * h
);
762 /****************************************************************************
763 Draws the editor selection rectangle using draw_selection_rectangle().
764 ****************************************************************************/
765 static void editor_draw_selrect(void)
771 if (editor
->selrect_active
&& editor
->selrect_width
> 0
772 && editor
->selrect_height
> 0) {
773 draw_selection_rectangle(editor
->selrect_x
,
775 editor
->selrect_width
,
776 editor
->selrect_height
);
780 /****************************************************************************
781 Handle the release of a mouse button click.
782 ****************************************************************************/
783 void editor_mouse_button_release(int canvas_x
, int canvas_y
,
784 int button
, int modifiers
)
788 case MOUSE_BUTTON_LEFT
:
789 editor_set_current_tile(NULL
);
790 editor
->tool_active
= FALSE
;
793 case MOUSE_BUTTON_RIGHT
:
794 if (editor
->selrect_active
) {
795 editor_end_selection_rectangle(canvas_x
, canvas_y
);
799 case MOUSE_BUTTON_MIDDLE
:
807 /****************************************************************************
808 Handle a change in the size of the selection rectangle. The given point
809 is the new extremity of the rectangle.
810 ****************************************************************************/
811 static void editor_resize_selection_rectangle(int canvas_x
, int canvas_y
)
815 if (editor
->selrect_start_x
<= canvas_x
) {
816 xl
= editor
->selrect_start_x
;
820 xr
= editor
->selrect_start_x
;
823 if (editor
->selrect_start_y
<= canvas_y
) {
824 yt
= editor
->selrect_start_y
;
828 yb
= editor
->selrect_start_y
;
831 /* Erase the previously drawn rectangle. */
832 editor_draw_selrect();
834 if (xl
== xr
|| yt
== yb
) {
835 editor
->selrect_width
= 0;
836 editor
->selrect_height
= 0;
840 editor
->selrect_x
= xl
;
841 editor
->selrect_y
= yt
;
842 editor
->selrect_width
= xr
- xl
;
843 editor
->selrect_height
= yb
- yt
;
845 editor_draw_selrect();
848 /****************************************************************************
849 Handle the mouse moving over the map canvas.
850 ****************************************************************************/
851 void editor_mouse_move(int canvas_x
, int canvas_y
, int modifiers
)
853 const struct tile
*ptile
, *old
;
859 old
= editor_get_current_tile();
860 ptile
= canvas_pos_to_tile(canvas_x
, canvas_y
);
866 if (editor
->tool_active
&& old
!= NULL
&& old
!= ptile
) {
867 editor_apply_tool(ptile
, FALSE
);
868 editor_notify_edit_finished();
869 editor_set_current_tile(ptile
);
872 if (editor
->selrect_active
) {
873 editor_resize_selection_rectangle(canvas_x
, canvas_y
);
877 /****************************************************************************
878 Notify the server that a batch of edits has completed. This is used as
879 a hint for the server to now do any checks it has saved while the batch
881 ****************************************************************************/
882 void editor_notify_edit_finished(void)
884 send_packet_edit_check_tiles(&client
.conn
);
887 /****************************************************************************
888 Apply the current editor tool to the given tile. This function is
889 suitable to called over multiple tiles at once. Once the batch of
890 operations is finished you should call editor_notify_edit_finished.
891 The 'part_of_selection' parameter should be TRUE if the tool is
892 being applied to a tile from a selection.
893 ****************************************************************************/
894 void editor_apply_tool(const struct tile
*ptile
,
895 bool part_of_selection
)
897 enum editor_tool_type ett
;
898 enum editor_tool_mode etm
;
899 int value
, size
, count
, apno
, tile
, id
;
901 struct connection
*my_conn
= &client
.conn
;
903 if (editor
== NULL
|| ptile
== NULL
) {
907 ett
= editor_get_tool();
908 etm
= editor_tool_get_mode(ett
);
909 size
= editor_tool_get_size(ett
);
910 count
= editor_tool_get_count(ett
);
911 value
= editor_tool_get_value(ett
);
912 apno
= editor_tool_get_applied_player(ett
);
914 if (ett
!= ETT_VISION
&& !client_is_global_observer()
915 && client_has_player()
916 && tile_get_known(ptile
, client_player()) == TILE_UNKNOWN
) {
920 if (editor_tool_has_applied_player(ett
)
921 && player_by_number(apno
) == NULL
) {
925 if (ett
== ETT_COPYPASTE
) {
926 struct edit_buffer
*ebuf
;
927 ebuf
= editor_get_copy_buffer();
928 if (etm
== ETM_COPY
) {
929 if (part_of_selection
) {
930 edit_buffer_copy(ebuf
, ptile
);
932 edit_buffer_clear(ebuf
);
933 edit_buffer_copy_square(ebuf
, ptile
, size
);
936 } else if (etm
== ETM_PAINT
|| etm
== ETM_PASTE
) {
937 edit_buffer_paste(ebuf
, ptile
);
942 if (part_of_selection
&& ett
!= ETT_CITY
) {
946 erase
= (etm
== ETM_ERASE
);
947 tile
= tile_index(ptile
);
952 dsend_packet_edit_tile_terrain(my_conn
, tile
, erase
? 0 : value
, size
);
955 case ETT_TERRAIN_RESOURCE
:
956 dsend_packet_edit_tile_resource(my_conn
, tile
,
957 erase
? resource_count() : value
,
961 case ETT_TERRAIN_SPECIAL
:
963 case ETT_MILITARY_BASE
:
964 dsend_packet_edit_tile_extra(my_conn
, tile
, value
, erase
, size
);
969 dsend_packet_edit_unit_remove(my_conn
, apno
, tile
, value
, count
);
971 dsend_packet_edit_unit_create(my_conn
, apno
, tile
, value
, count
, 0);
977 struct city
*pcity
= tile_city(ptile
);
980 dsend_packet_edit_city_remove(my_conn
, id
);
983 dsend_packet_edit_city_create(my_conn
, apno
, tile
, size
, 0);
988 if (client_has_player()) {
989 id
= client_player_number();
990 dsend_packet_edit_player_vision(my_conn
, id
, tile
, !erase
, size
);
995 dsend_packet_edit_startpos(my_conn
, tile
, erase
, 0);
1003 /****************************************************************************
1004 Sets the tile currently assumed to be under the user's mouse pointer.
1005 ****************************************************************************/
1006 void editor_set_current_tile(const struct tile
*ptile
)
1008 if (editor
== NULL
) {
1012 editor
->current_tile
= ptile
;
1015 /****************************************************************************
1016 Get the tile that the user's mouse pointer is currently over.
1017 ****************************************************************************/
1018 const struct tile
*editor_get_current_tile(void)
1020 if (editor
== NULL
) {
1024 return editor
->current_tile
;
1027 /****************************************************************************
1028 Toggle the current tool mode between the given mode and ETM_PAINT (or
1029 ETM_COPY for the copy & paste tool).
1030 ****************************************************************************/
1031 void editor_tool_toggle_mode(enum editor_tool_type ett
,
1032 enum editor_tool_mode etm
)
1034 if (!editor_tool_has_mode(ett
, etm
)) {
1037 if (editor_tool_get_mode(ett
) == etm
) {
1038 editor_tool_set_mode(ett
, ett
== ETT_COPYPASTE
1039 ? ETM_COPY
: ETM_PAINT
);
1041 editor_tool_set_mode(ett
, etm
);
1045 /****************************************************************************
1046 Set the editor tool mode to the next available mode.
1047 ****************************************************************************/
1048 void editor_tool_cycle_mode(enum editor_tool_type ett
)
1053 mode
= editor_tool_get_mode(ett
);
1054 if (!(0 <= mode
&& mode
< NUM_EDITOR_TOOL_MODES
)) {
1058 for (count
= 0; count
< NUM_EDITOR_TOOL_MODES
; count
++) {
1059 mode
= (mode
+ 1) % NUM_EDITOR_TOOL_MODES
;
1060 if (editor_tool_has_mode(ett
, mode
)) {
1067 editor_tool_set_mode(ett
, mode
);
1071 /****************************************************************************
1072 Unselect all selected tiles.
1073 ****************************************************************************/
1074 void editor_selection_clear(void)
1079 tile_hash_clear(editor
->selected_tile_table
);
1082 /****************************************************************************
1083 Add the given tile to the current selection.
1084 ****************************************************************************/
1085 void editor_selection_add(const struct tile
*ptile
)
1087 if (!editor
|| !ptile
) {
1090 tile_hash_insert(editor
->selected_tile_table
, ptile
, NULL
);
1093 /****************************************************************************
1094 Remove the given tile from the current selection.
1095 ****************************************************************************/
1096 void editor_selection_remove(const struct tile
*ptile
)
1098 if (!editor
|| !ptile
) {
1101 tile_hash_remove(editor
->selected_tile_table
, ptile
);
1104 /****************************************************************************
1105 Returns TRUE if the given tile is selected.
1106 ****************************************************************************/
1107 bool editor_tile_is_selected(const struct tile
*ptile
)
1109 if (!editor
|| !ptile
) {
1112 return tile_hash_lookup(editor
->selected_tile_table
, ptile
, NULL
);
1115 /****************************************************************************
1116 Apply the current editor tool to all tiles in the current selection.
1117 ****************************************************************************/
1118 void editor_apply_tool_to_selection(void)
1120 enum editor_tool_type ett
;
1122 if (!editor
|| editor_selection_count() <= 0) {
1126 ett
= editor_get_tool();
1127 if (editor_tool_get_mode(ett
) == ETM_COPY
) {
1128 struct edit_buffer
*ebuf
;
1129 ebuf
= editor_get_copy_buffer();
1130 edit_buffer_clear(ebuf
);
1131 edit_buffer_set_origin(ebuf
, editor_get_selection_center());
1134 connection_do_buffer(&client
.conn
);
1135 tile_hash_iterate(editor
->selected_tile_table
, ptile
) {
1136 editor_apply_tool(ptile
, TRUE
);
1137 } tile_hash_iterate_end
;
1138 editor_notify_edit_finished();
1139 connection_do_unbuffer(&client
.conn
);
1141 if (editor_tool_get_mode(ett
) == ETM_COPY
) {
1146 /****************************************************************************
1147 Get the translated name of the given tool type.
1148 ****************************************************************************/
1149 const char *editor_tool_get_name(enum editor_tool_type ett
)
1151 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
1155 return editor
->tools
[ett
].name
;
1158 /****************************************************************************
1159 Get the translated name of the given tool value. If no such name exists,
1160 returns an empty string.
1161 ****************************************************************************/
1162 const char *editor_tool_get_value_name(enum editor_tool_type emt
, int value
)
1164 struct terrain
*pterrain
;
1165 struct resource
*presource
;
1166 struct unit_type
*putype
;
1167 struct extra_type
*pextra
;
1175 pterrain
= terrain_by_number(value
);
1176 return pterrain
? terrain_name_translation(pterrain
) : "";
1178 case ETT_TERRAIN_RESOURCE
:
1179 presource
= resource_by_number(value
);
1180 return presource
? resource_name_translation(presource
) : "";
1182 case ETT_TERRAIN_SPECIAL
:
1184 case ETT_MILITARY_BASE
:
1185 pextra
= extra_by_number(value
);
1186 return pextra
!= NULL
? extra_name_translation(pextra
) : "";
1189 putype
= utype_by_number(value
);
1190 return putype
? utype_name_translation(putype
) : "";
1198 /****************************************************************************
1199 Return TRUE if the given editor tool uses the 'size' parameter.
1200 ****************************************************************************/
1201 bool editor_tool_has_size(enum editor_tool_type ett
)
1203 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
1206 return editor
->tools
[ett
].flags
& ETF_HAS_SIZE
;
1209 /****************************************************************************
1210 Returns the current size parameter for the given editor tools.
1211 ****************************************************************************/
1212 int editor_tool_get_size(enum editor_tool_type ett
)
1214 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
1217 return editor
->tools
[ett
].size
;
1220 /****************************************************************************
1221 Sets the size parameter for the given tool.
1222 ****************************************************************************/
1223 void editor_tool_set_size(enum editor_tool_type ett
, int size
)
1225 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
1228 editor
->tools
[ett
].size
= MAX(1, size
);
1231 /****************************************************************************
1232 Return TRUE if it is meaningful for the given tool to use the 'count'
1234 ****************************************************************************/
1235 bool editor_tool_has_count(enum editor_tool_type ett
)
1237 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
1240 return editor
->tools
[ett
].flags
& ETF_HAS_COUNT
;
1243 /****************************************************************************
1244 Returns the 'count' parameter for the editor tool.
1245 ****************************************************************************/
1246 int editor_tool_get_count(enum editor_tool_type ett
)
1248 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
1251 return editor
->tools
[ett
].count
;
1254 /****************************************************************************
1255 Sets the 'count' parameter of the tool to the given value.
1256 ****************************************************************************/
1257 void editor_tool_set_count(enum editor_tool_type ett
, int count
)
1259 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
1262 editor
->tools
[ett
].count
= MAX(1, count
);
1265 /****************************************************************************
1266 Returns a sprite containing an icon for the given tool type. Returns
1267 NULL if no such sprite exists.
1268 ****************************************************************************/
1269 struct sprite
*editor_tool_get_sprite(enum editor_tool_type ett
)
1271 const struct editor_sprites
*sprites
;
1273 if (!tileset
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
1277 sprites
= get_editor_sprites(tileset
);
1284 return sprites
->copypaste
;
1287 return sprites
->terrain
;
1289 case ETT_TERRAIN_RESOURCE
:
1290 return sprites
->terrain_resource
;
1292 case ETT_TERRAIN_SPECIAL
:
1293 return sprites
->terrain_special
;
1296 return sprites
->road
;
1297 case ETT_MILITARY_BASE
:
1298 return sprites
->military_base
;
1300 return sprites
->unit
;
1303 return sprites
->city
;
1306 return sprites
->vision
;
1309 return sprites
->startpos
;
1318 /****************************************************************************
1319 Returns a translated "tooltip" description for the given tool type.
1320 ****************************************************************************/
1321 const char *editor_tool_get_tooltip(enum editor_tool_type ett
)
1323 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)
1324 || !editor
->tools
[ett
].tooltip
) {
1327 return editor
->tools
[ett
].tooltip
;
1330 /****************************************************************************
1331 Returns the current applied player number for the editor tool.
1333 May return a player number for which player_by_number returns NULL.
1334 ****************************************************************************/
1335 int editor_tool_get_applied_player(enum editor_tool_type ett
)
1337 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
1340 return editor
->tools
[ett
].applied_player_no
;
1343 /****************************************************************************
1344 Sets the editor tool's applied player number to the given value.
1345 ****************************************************************************/
1346 void editor_tool_set_applied_player(enum editor_tool_type ett
,
1349 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
1352 editor
->tools
[ett
].applied_player_no
= player_no
;
1355 /****************************************************************************
1356 Returns TRUE if the given tool makes use of the editor's applied player
1358 ****************************************************************************/
1359 bool editor_tool_has_applied_player(enum editor_tool_type ett
)
1361 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
1364 return editor
->tools
[ett
].flags
& ETF_HAS_APPLIED_PLAYER
;
1367 /****************************************************************************
1368 Returns TRUE if erase mode for the given tool erases by sub-value instead
1369 of any object corresponding to the tool type.
1370 ****************************************************************************/
1371 bool editor_tool_has_value_erase(enum editor_tool_type ett
)
1373 if (!editor
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
1376 return editor
->tools
[ett
].flags
& ETF_HAS_VALUE_ERASE
;
1379 /****************************************************************************
1380 Returns the number of currently selected tiles.
1381 ****************************************************************************/
1382 int editor_selection_count(void)
1387 return tile_hash_size(editor
->selected_tile_table
);
1390 /****************************************************************************
1391 Creates a virtual unit (like unit_virtual_create) based on the current
1392 editor state. You should free() the unit when it is no longer needed.
1393 If creation is not possible, then NULL is returned.
1395 The virtual unit has no homecity or tile. It is owned by the player
1396 corresponding to the current 'applied player' parameter and has unit type
1397 given by the sub-value of the unit tool (ETT_UNIT).
1398 ****************************************************************************/
1399 struct unit
*editor_unit_virtual_create(void)
1402 struct player
*pplayer
;
1403 struct unit_type
*putype
;
1406 value
= editor_tool_get_value(ETT_UNIT
);
1407 putype
= utype_by_number(value
);
1413 apno
= editor_tool_get_applied_player(ETT_UNIT
);
1414 pplayer
= player_by_number(apno
);
1419 vunit
= unit_virtual_create(pplayer
, NULL
, putype
, 0);
1424 /****************************************************************************
1425 Create a new edit buffer corresponding to all types set in 'type_flags'.
1426 ****************************************************************************/
1427 struct edit_buffer
*edit_buffer_new(int type_flags
)
1429 struct edit_buffer
*ebuf
;
1431 if (!(0 <= type_flags
&& type_flags
<= EBT_ALL
)) {
1435 ebuf
= fc_calloc(1, sizeof(*ebuf
));
1436 ebuf
->type_flags
= type_flags
;
1437 ebuf
->vtiles
= tile_list_new();
1442 /****************************************************************************
1443 Free all memory allocated for the edit buffer.
1444 ****************************************************************************/
1445 void edit_buffer_free(struct edit_buffer
*ebuf
)
1452 tile_list_iterate(ebuf
->vtiles
, vtile
) {
1453 tile_virtual_destroy(vtile
);
1454 } tile_list_iterate_end
;
1455 tile_list_destroy(ebuf
->vtiles
);
1456 ebuf
->vtiles
= NULL
;
1461 /****************************************************************************
1462 Remove all copy data stored in the edit buffer.
1463 ****************************************************************************/
1464 void edit_buffer_clear(struct edit_buffer
*ebuf
)
1466 if (!ebuf
|| !ebuf
->vtiles
) {
1470 tile_list_iterate(ebuf
->vtiles
, vtile
) {
1471 tile_virtual_destroy(vtile
);
1472 } tile_list_iterate_end
;
1473 tile_list_clear(ebuf
->vtiles
);
1475 edit_buffer_set_origin(ebuf
, NULL
);
1478 /****************************************************************************
1479 Copy from a square region of half-width 'radius' centered around 'center'
1481 ****************************************************************************/
1482 void edit_buffer_copy_square(struct edit_buffer
*ebuf
,
1483 const struct tile
*center
,
1486 if (!ebuf
|| !center
|| radius
< 1) {
1490 edit_buffer_set_origin(ebuf
, center
);
1491 square_iterate(center
, radius
- 1, ptile
) {
1492 edit_buffer_copy(ebuf
, ptile
);
1493 } square_iterate_end
;
1496 /****************************************************************************
1497 Append a single tile to the copy buffer.
1498 ****************************************************************************/
1499 void edit_buffer_copy(struct edit_buffer
*ebuf
, const struct tile
*ptile
)
1503 bool copied
= FALSE
;
1505 if (!ebuf
|| !ptile
) {
1509 vtile
= tile_virtual_new(NULL
);
1510 vtile
->index
= tile_index(ptile
);
1512 edit_buffer_type_iterate(ebuf
, type
) {
1515 if (tile_terrain(ptile
)) {
1516 tile_set_terrain(vtile
, tile_terrain(ptile
));
1521 if (tile_resource(ptile
)) {
1522 tile_set_resource(vtile
, tile_resource(ptile
));
1527 extra_type_by_cause_iterate(EC_SPECIAL
, pextra
) {
1528 if (tile_has_extra(ptile
, pextra
)) {
1529 tile_add_extra(vtile
, pextra
);
1532 } extra_type_by_cause_iterate_end
;
1535 extra_type_iterate(pextra
) {
1536 if (tile_has_extra(ptile
, pextra
)
1537 && is_extra_caused_by(pextra
, EC_BASE
)) {
1538 tile_add_extra(vtile
, pextra
);
1541 } extra_type_iterate_end
;
1543 extra_type_iterate(pextra
) {
1544 if (tile_has_extra(ptile
, pextra
)
1545 && is_extra_caused_by(pextra
, EC_ROAD
)) {
1546 tile_add_extra(vtile
, pextra
);
1549 } extra_type_iterate_end
;
1551 unit_list_iterate(ptile
->units
, punit
) {
1555 vunit
= unit_virtual_create(unit_owner(punit
), NULL
,
1556 unit_type_get(punit
), punit
->veteran
);
1557 vunit
->homecity
= punit
->homecity
;
1558 vunit
->hp
= punit
->hp
;
1559 unit_list_append(vtile
->units
, vunit
);
1561 } unit_list_iterate_end
;
1564 if (tile_city(ptile
)) {
1565 struct city
*pcity
, *vcity
;
1566 char name
[MAX_LEN_NAME
];
1568 pcity
= tile_city(ptile
);
1569 fc_snprintf(name
, sizeof(name
), "Copy of %s",
1570 city_name_get(pcity
));
1571 vcity
= create_city_virtual(city_owner(pcity
), NULL
, name
);
1572 city_size_set(vcity
, city_size_get(pcity
));
1573 improvement_iterate(pimprove
) {
1574 if (!is_improvement(pimprove
)
1575 || !city_has_building(pcity
, pimprove
)) {
1578 city_add_improvement(vcity
, pimprove
);
1579 } improvement_iterate_end
;
1580 tile_set_worked(vtile
, vcity
);
1587 } edit_buffer_type_iterate_end
;
1590 tile_list_append(ebuf
->vtiles
, vtile
);
1592 tile_virtual_destroy(vtile
);
1596 /****************************************************************************
1597 Helper function to fill in an edit packet with the tile's current values.
1598 ****************************************************************************/
1599 static void fill_tile_edit_packet(struct packet_edit_tile
*packet
,
1600 const struct tile
*ptile
)
1602 const struct resource
*presource
;
1603 const struct terrain
*pterrain
;
1605 if (!packet
|| !ptile
) {
1608 packet
->tile
= tile_index(ptile
);
1609 packet
->extras
= *tile_extras(ptile
);
1611 presource
= tile_resource(ptile
);
1612 packet
->resource
= presource
1613 ? resource_number(presource
)
1616 pterrain
= tile_terrain(ptile
);
1617 packet
->terrain
= pterrain
1618 ? terrain_number(pterrain
)
1621 if (ptile
->label
== NULL
) {
1622 packet
->label
[0] = '\0';
1624 strncpy(packet
->label
, ptile
->label
, sizeof(packet
->label
));
1628 /****************************************************************************
1629 Helper function for edit_buffer_paste(). Do a single paste of the stuff set
1630 in the buffer on the virtual tile to the destination tile 'ptile_dest'.
1631 ****************************************************************************/
1632 static void paste_tile(struct edit_buffer
*ebuf
,
1633 const struct tile
*vtile
,
1634 const struct tile
*ptile_dest
)
1636 struct connection
*my_conn
= &client
.conn
;
1637 struct packet_edit_tile tile_packet
;
1639 int value
, owner
, tile
;
1640 bool send_edit_tile
= FALSE
;
1642 if (!ebuf
|| !vtile
|| !ptile_dest
) {
1646 tile
= tile_index(ptile_dest
);
1648 fill_tile_edit_packet(&tile_packet
, ptile_dest
);
1650 edit_buffer_type_iterate(ebuf
, type
) {
1653 if (!tile_terrain(vtile
)) {
1656 value
= terrain_number(tile_terrain(vtile
));
1657 dsend_packet_edit_tile_terrain(my_conn
, tile
, value
, 1);
1660 if (!tile_resource(vtile
)) {
1663 value
= resource_number(tile_resource(vtile
));
1664 dsend_packet_edit_tile_resource(my_conn
, tile
, value
, 1);
1667 extra_type_by_cause_iterate(EC_SPECIAL
, pextra
) {
1668 if (tile_has_extra(vtile
, pextra
)) {
1669 BV_SET(tile_packet
.extras
, extra_index(pextra
));
1670 send_edit_tile
= TRUE
;
1672 } extra_type_by_cause_iterate_end
;
1675 extra_type_iterate(pextra
) {
1676 if (tile_has_extra(vtile
, pextra
)
1677 && is_extra_caused_by(pextra
, EC_BASE
)) {
1678 BV_SET(tile_packet
.extras
, extra_index(pextra
));
1679 send_edit_tile
= TRUE
;
1681 } extra_type_iterate_end
;
1684 extra_type_iterate(pextra
) {
1685 if (tile_has_extra(vtile
, pextra
)
1686 && is_extra_caused_by(pextra
, EC_ROAD
)) {
1687 BV_SET(tile_packet
.extras
, extra_index(pextra
));
1688 send_edit_tile
= TRUE
;
1690 } extra_type_iterate_end
;
1693 unit_list_iterate(vtile
->units
, vunit
) {
1694 value
= utype_number(unit_type_get(vunit
));
1695 owner
= player_number(unit_owner(vunit
));
1696 dsend_packet_edit_unit_create(my_conn
, owner
, tile
, value
, 1, 0);
1697 } unit_list_iterate_end
;
1700 vcity
= tile_city(vtile
);
1704 owner
= player_number(city_owner(vcity
));
1705 value
= city_size_get(vcity
);
1706 dsend_packet_edit_city_create(my_conn
, owner
, tile
, value
, 0);
1711 } edit_buffer_type_iterate_end
;
1713 if (send_edit_tile
) {
1714 send_packet_edit_tile(my_conn
, &tile_packet
);
1718 /****************************************************************************
1719 Paste the entire contents of the edit buffer using 'dest' as the origin.
1720 ****************************************************************************/
1721 void edit_buffer_paste(struct edit_buffer
*ebuf
, const struct tile
*dest
)
1723 struct connection
*my_conn
= &client
.conn
;
1724 const struct tile
*origin
, *ptile
;
1727 if (!ebuf
|| !dest
) {
1731 /* Calculate vector. */
1732 origin
= edit_buffer_get_origin(ebuf
);
1733 fc_assert_ret(origin
!= NULL
);
1734 map_distance_vector(&dx
, &dy
, origin
, dest
);
1736 connection_do_buffer(my_conn
);
1737 tile_list_iterate(ebuf
->vtiles
, vtile
) {
1740 index_to_map_pos(&virt_x
, &virt_y
, tile_index(vtile
));
1741 ptile
= map_pos_to_tile(virt_x
+ dx
, virt_y
+ dy
);
1745 paste_tile(ebuf
, vtile
, ptile
);
1746 } tile_list_iterate_end
;
1747 connection_do_unbuffer(my_conn
);
1750 /****************************************************************************
1751 Returns the copy buffer for the given tool.
1752 ****************************************************************************/
1753 struct edit_buffer
*editor_get_copy_buffer(void)
1758 return editor
->copybuf
;
1761 /****************************************************************************
1762 Returns the translated string name for the given mode.
1763 ****************************************************************************/
1764 const char *editor_tool_get_mode_name(enum editor_tool_type ett
,
1765 enum editor_tool_mode etm
)
1769 value_erase
= editor_tool_has_value_erase(ett
);
1777 return _("Erase Value");
1789 log_error("Unrecognized editor tool mode %d "
1790 "in editor_tool_get_mode_name().", etm
);
1797 /****************************************************************************
1798 Returns a translated tooltip string assumed to be used for the toggle
1799 button for this tool mode in the editor gui.
1800 ****************************************************************************/
1801 const char *editor_get_mode_tooltip(enum editor_tool_mode etm
)
1805 return _("Toggle erase mode.\nShortcut: shift-d");
1808 return _("Toggle copy mode.\nShortcut: shift-c");
1811 return _("Toggle paste mode.\nShortcut: shift-v");
1820 /****************************************************************************
1821 Returns the editor sprite corresponding to the tool mode.
1822 ****************************************************************************/
1823 struct sprite
*editor_get_mode_sprite(enum editor_tool_mode etm
)
1825 const struct editor_sprites
*sprites
;
1827 sprites
= get_editor_sprites(tileset
);
1834 return sprites
->brush
;
1837 return sprites
->erase
;
1840 return sprites
->copy
;
1843 return sprites
->paste
;
1852 /****************************************************************************
1853 Fill the supplied buffer with a translated string describing the edit
1854 buffer's current state. Returns the number of bytes used.
1855 ****************************************************************************/
1856 int edit_buffer_get_status_string(const struct edit_buffer
*ebuf
,
1857 char *buf
, int buflen
)
1862 if (!buf
|| buflen
< 1) {
1866 ret
= fc_strlcpy(buf
, _("Buffer empty."), buflen
);
1867 if (!ebuf
|| !ebuf
->vtiles
) {
1871 total
= tile_list_size(ebuf
->vtiles
);
1873 fmt
= PL_("%d tile copied.", "%d tiles copied.", total
);
1874 ret
= fc_snprintf(buf
, buflen
, fmt
, total
);
1880 /****************************************************************************
1881 Set the "origin" for subsequent copy operations. This controls the x and
1882 y offset of newly created virtual tiles in the buffer.
1883 ****************************************************************************/
1884 void edit_buffer_set_origin(struct edit_buffer
*ebuf
,
1885 const struct tile
*ptile
)
1890 ebuf
->origin
= ptile
;
1893 /****************************************************************************
1894 Return the previously set origin, or NULL if none.
1895 ****************************************************************************/
1896 const struct tile
*edit_buffer_get_origin(const struct edit_buffer
*ebuf
)
1901 return ebuf
->origin
;
1904 /****************************************************************************
1905 Returns TRUE if the edit buffer was created with the given type flag.
1906 ****************************************************************************/
1907 bool edit_buffer_has_type(const struct edit_buffer
*ebuf
, int type
)
1912 return ebuf
->type_flags
& type
;
1915 /****************************************************************************
1916 Returns the "center" tile of a group of selected tiles, or NULL.
1917 The center is calculated as the vector sum divided by the number of tiles,
1918 i.e. the average of the map distance vectors of the selected tiles.
1919 ****************************************************************************/
1920 const struct tile
*editor_get_selection_center(void)
1923 const struct tile
*origin
, *center
;
1925 int xsum
= 0, ysum
= 0;
1927 if (!editor
|| !editor
->selected_tile_table
) {
1931 count
= tile_hash_size(editor
->selected_tile_table
);
1936 origin
= map_pos_to_tile(0, 0);
1937 tile_hash_iterate(editor
->selected_tile_table
, ptile
) {
1938 map_distance_vector(&dx
, &dy
, origin
, ptile
);
1941 } tile_hash_iterate_end
;
1945 center
= map_pos_to_tile(cx
, cy
);