-
-
Notifications
You must be signed in to change notification settings - Fork 988
/
editor_controller.cpp
1412 lines (1273 loc) · 45 KB
/
editor_controller.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
Copyright (C) 2008 - 2017 by Tomasz Sniatowski <kailoran@gmail.com>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#define GETTEXT_DOMAIN "wesnoth-editor"
#include "editor/map/context_manager.hpp"
#include "editor/action/action.hpp"
#include "editor/action/action_unit.hpp"
#include "editor/action/action_select.hpp"
#include "editor/controller/editor_controller.hpp"
#include "editor/palette/terrain_palettes.hpp"
#include "editor/palette/location_palette.hpp"
#include "editor/action/mouse/mouse_action.hpp"
#include "editor/editor_preferences.hpp"
#include "gui/dialogs/edit_text.hpp"
#include "gui/dialogs/editor/custom_tod.hpp"
#include "gui/dialogs/message.hpp"
#include "gui/dialogs/preferences_dialog.hpp"
#include "gui/dialogs/transient_message.hpp"
#include "gui/dialogs/unit_list.hpp"
#include "gui/widgets/window.hpp"
#include "wml_exception.hpp"
#include "resources.hpp"
#include "reports.hpp"
#include "config_assign.hpp"
#include "desktop/clipboard.hpp"
#include "floating_label.hpp"
#include "game_board.hpp"
#include "game_preferences.hpp"
#include "gettext.hpp"
#include "preferences_display.hpp"
#include "sound.hpp"
#include "units/unit.hpp"
#include "units/animation_component.hpp"
#include "quit_confirmation.hpp"
#include "utils/functional.hpp"
namespace {
static std::vector<std::string> saved_windows_;
}
namespace editor {
editor_controller::editor_controller(const config &game_config, CVideo& video)
: controller_base(game_config, video)
, mouse_handler_base()
, quit_confirmation(std::bind(&editor_controller::quit_confirm, this))
, active_menu_(editor::MAP)
, reports_(new reports())
, gui_(new editor_display(*this, editor::get_dummy_display_context(), video, *reports_, controller_base::get_theme(game_config, "editor"), config()))
, tods_()
, context_manager_(new context_manager(*gui_.get(), game_config_))
, toolkit_(nullptr)
, tooltip_manager_(video)
, floating_label_manager_(nullptr)
, help_manager_(nullptr)
, do_quit_(false)
, quit_mode_(EXIT_ERROR)
, music_tracks_()
{
init_gui();
toolkit_.reset(new editor_toolkit(*gui_.get(), key_, game_config_, *context_manager_.get()));
help_manager_.reset(new help::help_manager(&game_config));
context_manager_->switch_context(0, true);
init_tods(game_config);
init_music(game_config);
get_current_map_context().set_starting_position_labels(gui());
cursor::set(cursor::NORMAL);
gui().create_buttons();
gui().redraw_everything();
events::raise_draw_event();
}
void editor_controller::init_gui()
{
gui_->change_display_context(&get_current_map_context());
preferences::set_preference_display_settings();
gui_->add_redraw_observer(std::bind(&editor_controller::display_redraw_callback, this, _1));
floating_label_manager_.reset(new font::floating_label_context());
gui().set_draw_coordinates(preferences::editor::draw_hex_coordinates());
gui().set_draw_terrain_codes(preferences::editor::draw_terrain_codes());
gui().set_draw_num_of_bitmaps(preferences::editor::draw_num_of_bitmaps());
// halo_manager_.reset(new halo::manager(*gui_));
// resources::halo = halo_manager_.get();
// ^ These lines no longer necessary, the gui owns its halo manager.
// TODO: Should the editor map contexts actually own the halo manager and swap them in and out from the gui?
// Note that if that is what happens it might not actually be a good idea for the gui to own the halo manager, so that it can be swapped out
// without deleting it.
}
void editor_controller::init_tods(const config& game_config)
{
for (const config &schedule : game_config.child_range("editor_times")) {
const std::string& schedule_id = schedule["id"];
const std::string& schedule_name = schedule["name"];
if (schedule_id.empty()) {
ERR_ED << "Missing ID attribute in a TOD Schedule." << std::endl;
continue;
}
tods_map::iterator times = tods_.find(schedule_id);
if (times == tods_.end()) {
std::pair<tods_map::iterator, bool> new_times =
tods_.insert( std::pair<std::string, std::pair<std::string, std::vector<time_of_day> > >
(schedule_id, std::pair<std::string, std::vector<time_of_day> >(schedule_name, std::vector<time_of_day>())) );
times = new_times.first;
} else {
ERR_ED << "Duplicate TOD Schedule identifiers." << std::endl;
continue;
}
for (const config &time : schedule.child_range("time")) {
times->second.second.push_back(time_of_day(time));
}
}
if (tods_.empty()) {
ERR_ED << "No editor time-of-day defined" << std::endl;
}
}
void editor_controller::init_music(const config& game_config)
{
const std::string tag_name = "editor_music";
if (!game_config.has_child(tag_name))
ERR_ED << "No editor music defined" << std::endl;
else {
for (const config& editor_music : game_config.child_range(tag_name)) {
for (const config& music : editor_music.child_range("music")) {
sound::music_track track(music);
if (track.file_path().empty())
WRN_ED << "Music track " << track.id() << " not found." << std::endl;
else
music_tracks_.push_back(sound::music_track(music));
}
}
}
}
editor_controller::~editor_controller()
{
resources::units = nullptr;
resources::tod_manager = nullptr;
resources::filter_con = nullptr;
resources::classification = nullptr;
}
EXIT_STATUS editor_controller::main_loop()
{
try {
while (!do_quit_) {
play_slice();
}
} catch (editor_exception& e) {
gui2::show_transient_message(gui().video(), _("Fatal error"), e.what());
return EXIT_ERROR;
} catch (wml_exception& e) {
e.show(gui().video());
}
return quit_mode_;
}
void editor_controller::status_table() {
}
void editor_controller::do_screenshot(const std::string& screenshot_filename /* = "map_screenshot.bmp" */)
{
try {
if (!gui().screenshot(screenshot_filename,true)) {
ERR_ED << "Screenshot creation failed!\n";
}
} catch (wml_exception& e) {
e.show(gui().video());
}
}
bool editor_controller::quit_confirm()
{
std::string modified;
size_t amount = context_manager_->modified_maps(modified);
std::string message;
if (amount == 0) {
message = _("Do you really want to quit?");
} else if (amount == 1) {
message = _("Do you really want to quit? Changes to this map since the last save will be lost.");
} else {
message = _("Do you really want to quit? The following maps were modified and all changes since the last save will be lost:");
message += "\n" + modified;
}
return quit_confirmation::show_prompt(message);
}
void editor_controller::custom_tods_dialog()
{
if (tods_.empty()) {
gui2::show_error_message(gui().video(),
_("No editor time-of-day found."));
return;
}
image::color_adjustment_resetter adjust_resetter;
tod_manager& manager = *get_current_map_context().get_time_manager();
if(gui2::dialogs::custom_tod::execute(manager.times(), manager.get_current_time(), gui().video())) {
// TODO save the new tod here
}
// TODO: when saving the ToD is actually possible, deal with actually registering the choice of
// ToD or changes in the ToD values with the manager. In that case this should be conditional again.
adjust_resetter.reset();
context_manager_->refresh_all();
}
bool editor_controller::can_execute_command(const hotkey::hotkey_command& cmd, int index) const
{
using namespace hotkey; //reduce hotkey:: clutter
switch (cmd.id) {
case HOTKEY_NULL:
if (index >= 0) {
unsigned i = static_cast<unsigned>(index);
switch (active_menu_) {
case editor::MAP:
if (i < context_manager_->open_maps()) {
return true;
}
return false;
case editor::LOAD_MRU:
case editor::PALETTE:
case editor::AREA:
case editor::SIDE:
case editor::TIME:
case editor::SCHEDULE:
case editor::LOCAL_SCHEDULE:
case editor::MUSIC:
case editor::LOCAL_TIME:
case editor::UNIT_FACING:
return true;
}
}
return false;
case HOTKEY_EDITOR_PALETTE_GROUPS:
return true;
case HOTKEY_EDITOR_PALETTE_UPSCROLL:
return toolkit_->get_palette_manager()->can_scroll_up();
case HOTKEY_EDITOR_PALETTE_DOWNSCROLL:
return toolkit_->get_palette_manager()->can_scroll_down();
case HOTKEY_ZOOM_IN:
return !gui_->zoom_at_max();
case HOTKEY_ZOOM_OUT:
return !gui_->zoom_at_min();
case HOTKEY_ZOOM_DEFAULT:
case HOTKEY_FULLSCREEN:
case HOTKEY_SCREENSHOT:
case HOTKEY_MAP_SCREENSHOT:
case HOTKEY_TOGGLE_GRID:
case HOTKEY_MOUSE_SCROLL:
case HOTKEY_ANIMATE_MAP:
case HOTKEY_MUTE:
case HOTKEY_PREFERENCES:
case HOTKEY_HELP:
case HOTKEY_QUIT_GAME:
case HOTKEY_SCROLL_UP:
case HOTKEY_SCROLL_DOWN:
case HOTKEY_SCROLL_LEFT:
case HOTKEY_SCROLL_RIGHT:
return true; //general hotkeys we can always do
case hotkey::HOTKEY_UNIT_LIST:
return get_current_map_context().get_units().size() != 0;
case HOTKEY_STATUS_TABLE:
return !get_current_map_context().get_teams().empty();
case HOTKEY_TERRAIN_DESCRIPTION:
return gui().mouseover_hex().valid();
// unit tool related
case HOTKEY_DELETE_UNIT:
case HOTKEY_RENAME_UNIT:
case HOTKEY_EDITOR_UNIT_CHANGE_ID:
case HOTKEY_EDITOR_UNIT_TOGGLE_CANRECRUIT:
case HOTKEY_EDITOR_UNIT_TOGGLE_RENAMEABLE:
case HOTKEY_EDITOR_UNIT_TOGGLE_LOYAL:
case HOTKEY_EDITOR_UNIT_RECRUIT_ASSIGN:
case HOTKEY_EDITOR_UNIT_FACING:
case HOTKEY_UNIT_DESCRIPTION:
{
map_location loc = gui_->mouseover_hex();
const unit_map& units = get_current_map_context().get_units();
return (toolkit_->is_mouse_action_set(HOTKEY_EDITOR_TOOL_UNIT) &&
units.find(loc) != units.end());
}
case HOTKEY_UNDO:
return get_current_map_context().can_undo();
case HOTKEY_REDO:
return get_current_map_context().can_redo();
case HOTKEY_EDITOR_PARTIAL_UNDO:
return get_current_map_context().can_undo();
case TITLE_SCREEN__RELOAD_WML:
case HOTKEY_QUIT_TO_DESKTOP:
case HOTKEY_EDITOR_CUSTOM_TODS:
case HOTKEY_EDITOR_MAP_NEW:
case HOTKEY_EDITOR_SCENARIO_NEW:
case HOTKEY_EDITOR_MAP_LOAD:
case HOTKEY_EDITOR_MAP_SAVE_AS:
case HOTKEY_EDITOR_SCENARIO_SAVE_AS:
return true;
case HOTKEY_EDITOR_AREA_ADD:
case HOTKEY_EDITOR_SIDE_NEW:
return !get_current_map_context().is_pure_map();
case HOTKEY_EDITOR_SIDE_EDIT:
case HOTKEY_EDITOR_SIDE_REMOVE:
return !get_current_map_context().get_teams().empty();
// brushes
case HOTKEY_EDITOR_BRUSH_NEXT:
case HOTKEY_EDITOR_BRUSH_1:
case HOTKEY_EDITOR_BRUSH_2:
case HOTKEY_EDITOR_BRUSH_3:
case HOTKEY_EDITOR_BRUSH_NW_SE:
case HOTKEY_EDITOR_BRUSH_SW_NE:
return get_mouse_action().supports_brushes();
case HOTKEY_EDITOR_TOOL_NEXT:
return true;
case HOTKEY_EDITOR_PALETTE_ITEM_SWAP:
return toolkit_->get_palette_manager()->active_palette().supports_swap();
case HOTKEY_EDITOR_MAP_SAVE:
return get_current_map_context().modified();
case HOTKEY_EDITOR_MAP_SAVE_ALL:
{
std::string dummy;
return context_manager_->modified_maps(dummy) > 1;
}
case HOTKEY_EDITOR_PLAYLIST:
case HOTKEY_EDITOR_SCHEDULE:
return !get_current_map_context().is_pure_map();
case HOTKEY_EDITOR_MAP_SWITCH:
case HOTKEY_EDITOR_MAP_CLOSE:
return true;
case HOTKEY_EDITOR_MAP_REVERT:
return !get_current_map_context().get_filename().empty()
&& get_current_map_context().modified();
// Tools
// Pure map editing tools this can be used all the time.
case HOTKEY_EDITOR_TOOL_PAINT:
case HOTKEY_EDITOR_TOOL_FILL:
case HOTKEY_EDITOR_TOOL_SELECT:
case HOTKEY_EDITOR_TOOL_STARTING_POSITION:
return true;
// WWL dependent tools which don't rely on defined sides.
case HOTKEY_EDITOR_SCENARIO_EDIT:
case HOTKEY_EDITOR_TOOL_LABEL:
case HOTKEY_EDITOR_TOOL_ITEM:
return !get_current_map_context().is_pure_map();
case HOTKEY_EDITOR_TOOL_UNIT:
case HOTKEY_EDITOR_TOOL_VILLAGE:
return !get_current_map_context().get_teams().empty();
case HOTKEY_EDITOR_AREA_REMOVE:
case HOTKEY_EDITOR_AREA_RENAME:
case HOTKEY_EDITOR_LOCAL_TIME:
return !get_current_map_context().is_pure_map() &&
!get_current_map_context().get_time_manager()->get_area_ids().empty();
case HOTKEY_EDITOR_AREA_SAVE:
return !get_current_map_context().is_pure_map() &&
!get_current_map_context().get_time_manager()->get_area_ids().empty()
&& !context_manager_->get_map().selection().empty();
case HOTKEY_EDITOR_SELECTION_EXPORT:
case HOTKEY_EDITOR_SELECTION_CUT:
case HOTKEY_EDITOR_SELECTION_COPY:
case HOTKEY_EDITOR_SELECTION_FILL:
return !context_manager_->get_map().selection().empty()
&& !toolkit_->is_mouse_action_set(HOTKEY_EDITOR_CLIPBOARD_PASTE);
case HOTKEY_EDITOR_SELECTION_RANDOMIZE:
return (context_manager_->get_map().selection().size() > 1
&& !toolkit_->is_mouse_action_set(HOTKEY_EDITOR_CLIPBOARD_PASTE));
case HOTKEY_EDITOR_SELECTION_ROTATE:
case HOTKEY_EDITOR_SELECTION_FLIP:
case HOTKEY_EDITOR_SELECTION_GENERATE:
return false; //not implemented
case HOTKEY_EDITOR_CLIPBOARD_PASTE:
return !context_manager_->clipboard_empty();
case HOTKEY_EDITOR_CLIPBOARD_ROTATE_CW:
case HOTKEY_EDITOR_CLIPBOARD_ROTATE_CCW:
case HOTKEY_EDITOR_CLIPBOARD_FLIP_HORIZONTAL:
case HOTKEY_EDITOR_CLIPBOARD_FLIP_VERTICAL:
return !context_manager_->clipboard_empty()
&& toolkit_->is_mouse_action_set(HOTKEY_EDITOR_CLIPBOARD_PASTE);
case HOTKEY_EDITOR_SELECT_ALL:
case HOTKEY_EDITOR_SELECT_NONE:
return !toolkit_->is_mouse_action_set(HOTKEY_EDITOR_CLIPBOARD_PASTE);
case HOTKEY_EDITOR_SELECT_INVERSE:
return !get_current_map_context().get_map().selection().empty()
&& !get_current_map_context().get_map().everything_selected()
&& !toolkit_->is_mouse_action_set(HOTKEY_EDITOR_CLIPBOARD_PASTE);
case HOTKEY_EDITOR_MAP_RESIZE:
case HOTKEY_EDITOR_MAP_GENERATE:
case HOTKEY_EDITOR_MAP_APPLY_MASK:
case HOTKEY_EDITOR_MAP_CREATE_MASK_TO:
case HOTKEY_EDITOR_REFRESH:
case HOTKEY_EDITOR_UPDATE_TRANSITIONS:
case HOTKEY_EDITOR_AUTO_UPDATE_TRANSITIONS:
case HOTKEY_EDITOR_PARTIAL_UPDATE_TRANSITIONS:
case HOTKEY_EDITOR_NO_UPDATE_TRANSITIONS:
case HOTKEY_EDITOR_REFRESH_IMAGE_CACHE:
case HOTKEY_MINIMAP_CODING_TERRAIN:
case HOTKEY_MINIMAP_CODING_UNIT:
case HOTKEY_MINIMAP_DRAW_UNITS:
case HOTKEY_MINIMAP_DRAW_TERRAIN:
case HOTKEY_MINIMAP_DRAW_VILLAGES:
case HOTKEY_EDITOR_REMOVE_LOCATION:
return true;
case HOTKEY_EDITOR_MAP_ROTATE:
return false; //not implemented
case HOTKEY_EDITOR_DRAW_COORDINATES:
case HOTKEY_EDITOR_DRAW_TERRAIN_CODES:
case HOTKEY_EDITOR_DRAW_NUM_OF_BITMAPS:
return true;
default:
return false;
}
}
hotkey::ACTION_STATE editor_controller::get_action_state(hotkey::HOTKEY_COMMAND command, int index) const {
using namespace hotkey;
switch (command) {
case HOTKEY_EDITOR_UNIT_TOGGLE_LOYAL:
{
unit_map::const_unit_iterator un =
get_current_map_context().get_units().find(gui_->mouseover_hex());
return un->loyal() ? ACTION_ON : ACTION_OFF;
}
case HOTKEY_EDITOR_UNIT_TOGGLE_CANRECRUIT:
{
unit_map::const_unit_iterator un =
get_current_map_context().get_units().find(gui_->mouseover_hex());
return un->can_recruit() ? ACTION_ON : ACTION_OFF;
}
case HOTKEY_EDITOR_UNIT_TOGGLE_RENAMEABLE:
{
unit_map::const_unit_iterator un =
get_current_map_context().get_units().find(gui_->mouseover_hex());
return (!un->unrenamable()) ? ACTION_ON : ACTION_OFF;
}
//TODO remove hardcoded hotkey names
case HOTKEY_EDITOR_AUTO_UPDATE_TRANSITIONS:
return context_manager_->is_active_transitions_hotkey("editor-auto-update-transitions")
? ACTION_SELECTED : ACTION_DESELECTED;
case HOTKEY_EDITOR_PARTIAL_UPDATE_TRANSITIONS:
return context_manager_->is_active_transitions_hotkey("editor-partial-update-transitions")
? ACTION_SELECTED : ACTION_DESELECTED;
case HOTKEY_EDITOR_NO_UPDATE_TRANSITIONS:
return context_manager_->is_active_transitions_hotkey("editor-no-update-transitions")
? ACTION_SELECTED : ACTION_DESELECTED;
case HOTKEY_EDITOR_BRUSH_1:
return toolkit_->is_active_brush("brush-1") ? ACTION_ON : ACTION_OFF;
case HOTKEY_EDITOR_BRUSH_2:
return toolkit_->is_active_brush("brush-2") ? ACTION_ON : ACTION_OFF;
case HOTKEY_EDITOR_BRUSH_3:
return toolkit_->is_active_brush("brush-3") ? ACTION_ON : ACTION_OFF;
case HOTKEY_EDITOR_BRUSH_NW_SE:
return toolkit_->is_active_brush("brush-nw-se") ? ACTION_ON : ACTION_OFF;
case HOTKEY_EDITOR_BRUSH_SW_NE:
return toolkit_->is_active_brush("brush-sw-ne") ? ACTION_ON : ACTION_OFF;
case HOTKEY_TOGGLE_GRID:
return preferences::grid() ? ACTION_ON : ACTION_OFF;
case HOTKEY_EDITOR_SELECT_ALL:
return get_current_map_context().get_map().everything_selected() ?
ACTION_SELECTED : ACTION_DESELECTED;
case HOTKEY_EDITOR_SELECT_NONE:
return get_current_map_context().get_map().selection().empty() ?
ACTION_SELECTED : ACTION_DESELECTED;
case HOTKEY_EDITOR_TOOL_FILL:
case HOTKEY_EDITOR_TOOL_LABEL:
case HOTKEY_EDITOR_TOOL_PAINT:
case HOTKEY_EDITOR_TOOL_SELECT:
case HOTKEY_EDITOR_CLIPBOARD_PASTE:
case HOTKEY_EDITOR_TOOL_STARTING_POSITION:
case HOTKEY_EDITOR_TOOL_UNIT:
case HOTKEY_EDITOR_TOOL_VILLAGE:
case HOTKEY_EDITOR_TOOL_ITEM:
return toolkit_->is_mouse_action_set(command) ? ACTION_ON : ACTION_OFF;
case HOTKEY_EDITOR_DRAW_COORDINATES:
return gui_->get_draw_coordinates() ? ACTION_ON : ACTION_OFF;
case HOTKEY_EDITOR_DRAW_TERRAIN_CODES:
return gui_->get_draw_terrain_codes() ? ACTION_ON : ACTION_OFF;
case HOTKEY_EDITOR_DRAW_NUM_OF_BITMAPS:
return gui_->get_draw_num_of_bitmaps() ? ACTION_ON : ACTION_OFF;
case HOTKEY_MINIMAP_DRAW_VILLAGES:
return (preferences::minimap_draw_villages()) ? hotkey::ACTION_ON : hotkey::ACTION_OFF;
case HOTKEY_MINIMAP_CODING_UNIT:
return (preferences::minimap_movement_coding()) ? hotkey::ACTION_ON : hotkey::ACTION_OFF;
case HOTKEY_MINIMAP_CODING_TERRAIN:
return (preferences::minimap_terrain_coding()) ? hotkey::ACTION_ON : hotkey::ACTION_OFF;
case HOTKEY_MINIMAP_DRAW_UNITS:
return (preferences::minimap_draw_units()) ? hotkey::ACTION_ON : hotkey::ACTION_OFF;
case HOTKEY_MINIMAP_DRAW_TERRAIN:
return (preferences::minimap_draw_terrain()) ? hotkey::ACTION_ON : hotkey::ACTION_OFF;
case HOTKEY_ZOOM_DEFAULT:
return (gui_->get_zoom_factor() == 1.0) ? hotkey::ACTION_ON : hotkey::ACTION_OFF;
case HOTKEY_NULL:
switch (active_menu_) {
case editor::MAP:
return index == context_manager_->current_context_index()
? ACTION_SELECTED : ACTION_DESELECTED;
case editor::LOAD_MRU:
return ACTION_STATELESS;
case editor::PALETTE:
return ACTION_STATELESS;
case editor::AREA:
return index == get_current_map_context().get_active_area()
? ACTION_SELECTED : ACTION_DESELECTED;
case editor::SIDE:
return static_cast<size_t>(index) == gui_->playing_team()
? ACTION_SELECTED : ACTION_DESELECTED;
case editor::TIME:
return index == get_current_map_context().get_time_manager()->get_current_time()
? ACTION_SELECTED : ACTION_DESELECTED;
case editor::LOCAL_TIME:
return index == get_current_map_context().get_time_manager()->get_current_area_time(
get_current_map_context().get_active_area())
? ACTION_SELECTED : ACTION_DESELECTED;
case editor::MUSIC:
return get_current_map_context().is_in_playlist(music_tracks_[index].id())
? ACTION_ON : ACTION_OFF;
case editor::SCHEDULE:
{
tods_map::const_iterator it = tods_.begin();
std::advance(it, index);
const std::vector<time_of_day>& times1 = it->second.second;
const std::vector<time_of_day>& times2 = get_current_map_context().get_time_manager()->times();
return (times1 == times2) ? ACTION_SELECTED : ACTION_DESELECTED;
}
case editor::LOCAL_SCHEDULE:
{
tods_map::const_iterator it = tods_.begin();
std::advance(it, index);
const std::vector<time_of_day>& times1 = it->second.second;
int active_area = get_current_map_context().get_active_area();
const std::vector<time_of_day>& times2 = get_current_map_context().get_time_manager()->times(active_area);
return (times1 == times2) ? ACTION_SELECTED : ACTION_DESELECTED;
}
case editor::UNIT_FACING:
{
unit_map::const_unit_iterator un = get_current_map_context().get_units().find(gui_->mouseover_hex());
assert(un != get_current_map_context().get_units().end());
return un->facing() == index ? ACTION_SELECTED : ACTION_DESELECTED;
}
}
return ACTION_ON;
default:
return command_executor::get_action_state(command, index);
}
}
bool editor_controller::execute_command(const hotkey::hotkey_command& cmd, int index, bool press)
{
hotkey::HOTKEY_COMMAND command = cmd.id;
SCOPE_ED;
using namespace hotkey;
// nothing here handles release; fall through to base implementation
if (!press) {
return hotkey::command_executor::execute_command(cmd, index, press);
}
switch (command) {
case HOTKEY_NULL:
switch (active_menu_) {
case MAP:
if (index >= 0) {
unsigned i = static_cast<unsigned>(index);
if (i < context_manager_->size()) {
context_manager_->switch_context(index);
toolkit_->hotkey_set_mouse_action(HOTKEY_EDITOR_TOOL_PAINT);
return true;
}
}
return false;
case LOAD_MRU:
if (index >= 0) {
context_manager_->load_mru_item(static_cast<unsigned>(index));
}
return true;
case PALETTE:
toolkit_->get_palette_manager()->set_group(index);
return true;
case SIDE:
gui_->set_team(index, true);
gui_->set_playing_team(index);
toolkit_->get_palette_manager()->draw_contents();
return true;
case AREA:
{
get_current_map_context().set_active_area(index);
const std::set<map_location>& area =
get_current_map_context().get_time_manager()->get_area_by_index(index);
std::vector<map_location> locs(area.begin(), area.end());
get_current_map_context().select_area(index);
gui_->scroll_to_tiles(locs.begin(), locs.end());
return true;
}
case TIME:
{
get_current_map_context().set_starting_time(index);
const tod_manager* tod = context_manager_->get_map_context().get_time_manager();
tod_color col = tod->times()[index].color;
gui_->adjust_color_overlay(col.r, col.g, col.b);
return true;
}
case LOCAL_TIME:
{
get_current_map_context().set_local_starting_time(index);
return true;
}
case MUSIC:
{
//TODO mark the map as changed
sound::play_music_once(music_tracks_[index].id());
get_current_map_context().add_to_playlist(music_tracks_[index]);
std::vector<std::string> items;
items.emplace_back("editor-playlist");
std::shared_ptr<gui::button> b = gui_->find_menu_button("menu-playlist");
show_menu(items, b->location().x +1, b->location().y + b->height() +1, false, *gui_);
return true;
}
case SCHEDULE:
{
tods_map::iterator iter = tods_.begin();
std::advance(iter, index);
get_current_map_context().replace_schedule(iter->second.second);
const tod_manager* tod = get_current_map_context().get_time_manager();
tod_color col = tod->times()[0].color;
gui_->adjust_color_overlay(col.r, col.g, col.b);
return true;
}
case LOCAL_SCHEDULE:
{
tods_map::iterator iter = tods_.begin();
std::advance(iter, index);
get_current_map_context().replace_local_schedule(iter->second.second);
return true;
}
case UNIT_FACING:
{
unit_map::unit_iterator un = get_current_map_context().get_units().find(gui_->mouseover_hex());
assert(un != get_current_map_context().get_units().end());
un->set_facing(map_location::DIRECTION(index));
un->anim_comp().set_standing();
return true;
}
}
return true;
//Zoom
case HOTKEY_ZOOM_IN:
gui_->set_zoom(true);
get_current_map_context().get_labels().recalculate_labels();
toolkit_->set_mouseover_overlay(*gui_);
return true;
case HOTKEY_ZOOM_OUT:
gui_->set_zoom(false);
get_current_map_context().get_labels().recalculate_labels();
toolkit_->set_mouseover_overlay(*gui_);
return true;
case HOTKEY_ZOOM_DEFAULT:
gui_->set_default_zoom();
get_current_map_context().get_labels().recalculate_labels();
toolkit_->set_mouseover_overlay(*gui_);
return true;
//Palette
case HOTKEY_EDITOR_PALETTE_GROUPS:
{
//TODO this code waits for the gui2 dialog to get ready
// std::vector< std::pair< std::string, std::string > > blah_items;
// toolkit_->get_palette_manager()->active_palette().expand_palette_groups_menu(blah_items);
// int selected = 1; //toolkit_->get_palette_manager()->active_palette().get_selected;
// gui2::teditor_select_palette_group::execute(selected, blah_items, gui_->video());
}
return true;
case HOTKEY_EDITOR_PALETTE_UPSCROLL:
toolkit_->get_palette_manager()->scroll_up();
gui_->draw(true,false);
return true;
case HOTKEY_EDITOR_PALETTE_DOWNSCROLL:
toolkit_->get_palette_manager()->scroll_down();
gui_->draw(true,false);
return true;
case HOTKEY_QUIT_GAME:
if(quit_confirmation::quit()) {
do_quit_ = true;
quit_mode_ = EXIT_NORMAL;
}
return true;
case HOTKEY_QUIT_TO_DESKTOP:
quit_confirmation::quit_to_desktop();
return true;
case TITLE_SCREEN__RELOAD_WML:
context_manager_->save_all_maps(true);
do_quit_ = true;
quit_mode_ = EXIT_RELOAD_DATA;
return true;
case HOTKEY_EDITOR_CUSTOM_TODS:
custom_tods_dialog();
return true;
case HOTKEY_EDITOR_PALETTE_ITEM_SWAP:
toolkit_->get_palette_manager()->active_palette().swap();
return true;
case HOTKEY_EDITOR_PARTIAL_UNDO:
if (dynamic_cast<const editor_action_chain*>(get_current_map_context().last_undo_action()) != nullptr) {
get_current_map_context().partial_undo();
context_manager_->refresh_after_action();
} else {
undo();
}
return true;
//Tool Selection
case HOTKEY_EDITOR_TOOL_PAINT:
case HOTKEY_EDITOR_TOOL_FILL:
case HOTKEY_EDITOR_TOOL_SELECT:
case HOTKEY_EDITOR_TOOL_STARTING_POSITION:
case HOTKEY_EDITOR_TOOL_LABEL:
case HOTKEY_EDITOR_TOOL_UNIT:
case HOTKEY_EDITOR_TOOL_VILLAGE:
case HOTKEY_EDITOR_TOOL_ITEM:
toolkit_->hotkey_set_mouse_action(command);
return true;
case HOTKEY_EDITOR_AREA_ADD:
add_area();
return true;
case HOTKEY_EDITOR_UNIT_CHANGE_ID:
change_unit_id();
return true;
case HOTKEY_EDITOR_UNIT_RECRUIT_ASSIGN:
{
map_location loc = gui_->mouseover_hex();
const unit_map::unit_iterator un = get_current_map_context().get_units().find(loc);
const std::set<std::string>& recruit_set = toolkit_->get_palette_manager()->unit_palette_->get_selected_bg_items();
std::vector<std::string> recruits(recruit_set.begin(), recruit_set.end());
un->set_recruits(recruits);
}
return true;
case HOTKEY_EDITOR_UNIT_TOGGLE_RENAMEABLE:
{
map_location loc = gui_->mouseover_hex();
const unit_map::unit_iterator un = get_current_map_context().get_units().find(loc);
bool unrenamable = un->unrenamable();
un->set_unrenamable(!unrenamable);
}
return true;
case HOTKEY_EDITOR_UNIT_TOGGLE_CANRECRUIT:
{
map_location loc = gui_->mouseover_hex();
const unit_map::unit_iterator un = get_current_map_context().get_units().find(loc);
bool canrecruit = un->can_recruit();
un->set_can_recruit(!canrecruit);
un->anim_comp().set_standing();
}
return true;
case HOTKEY_DELETE_UNIT:
{
map_location loc = gui_->mouseover_hex();
perform_delete(new editor_action_unit_delete(loc));
}
return true;
case HOTKEY_EDITOR_CLIPBOARD_PASTE: //paste is somewhat different as it might be "one action then revert to previous mode"
toolkit_->hotkey_set_mouse_action(command);
return true;
//Clipboard
case HOTKEY_EDITOR_CLIPBOARD_ROTATE_CW:
context_manager_->get_clipboard().rotate_60_cw();
toolkit_->update_mouse_action_highlights();
return true;
case HOTKEY_EDITOR_CLIPBOARD_ROTATE_CCW:
context_manager_->get_clipboard().rotate_60_ccw();
toolkit_->update_mouse_action_highlights();
return true;
case HOTKEY_EDITOR_CLIPBOARD_FLIP_HORIZONTAL:
context_manager_->get_clipboard().flip_horizontal();
toolkit_->update_mouse_action_highlights();
return true;
case HOTKEY_EDITOR_CLIPBOARD_FLIP_VERTICAL:
context_manager_->get_clipboard().flip_vertical();
toolkit_->update_mouse_action_highlights();
return true;
//Brushes
case HOTKEY_EDITOR_BRUSH_NEXT:
toolkit_->cycle_brush();
return true;
case HOTKEY_EDITOR_BRUSH_1:
toolkit_->set_brush("brush-1");
return true;
case HOTKEY_EDITOR_BRUSH_2:
toolkit_->set_brush("brush-2");
return true;
case HOTKEY_EDITOR_BRUSH_3:
toolkit_->set_brush("brush-3");
return true;
case HOTKEY_EDITOR_BRUSH_NW_SE:
toolkit_->set_brush("brush-nw-se");
return true;
case HOTKEY_EDITOR_BRUSH_SW_NE:
toolkit_->set_brush("brush-sw-ne");
return true;
case HOTKEY_EDITOR_SELECTION_COPY:
copy_selection();
return true;
case HOTKEY_EDITOR_SELECTION_CUT:
cut_selection();
return true;
case HOTKEY_EDITOR_AREA_RENAME:
context_manager_->rename_area_dialog();
return true;
case HOTKEY_EDITOR_AREA_SAVE:
save_area();
return true;
case HOTKEY_EDITOR_SELECTION_EXPORT:
export_selection_coords();
return true;
case HOTKEY_EDITOR_SELECT_ALL:
if(!context_manager_->get_map().everything_selected()) {
context_manager_->perform_refresh(editor_action_select_all());
return true;
}
FALLTHROUGH;
case HOTKEY_EDITOR_SELECT_INVERSE:
context_manager_->perform_refresh(editor_action_select_inverse());
return true;
case HOTKEY_EDITOR_SELECT_NONE:
context_manager_->perform_refresh(editor_action_select_none());
return true;
case HOTKEY_EDITOR_SELECTION_FILL:
context_manager_->fill_selection();
return true;
case HOTKEY_EDITOR_SELECTION_RANDOMIZE:
context_manager_->perform_refresh(editor_action_shuffle_area(
context_manager_->get_map().selection()));
return true;
case HOTKEY_EDITOR_SCENARIO_EDIT:
context_manager_->edit_scenario_dialog();
return true;
case HOTKEY_EDITOR_AREA_REMOVE:
get_current_map_context().remove_area(
get_current_map_context().get_active_area());
return true;
// map specific
case HOTKEY_EDITOR_MAP_CLOSE:
context_manager_->close_current_context();
return true;
case HOTKEY_EDITOR_MAP_LOAD:
context_manager_->load_map_dialog();
return true;
case HOTKEY_EDITOR_MAP_REVERT:
context_manager_->revert_map();
return true;
case HOTKEY_EDITOR_MAP_NEW:
context_manager_->new_map_dialog();
return true;
case HOTKEY_EDITOR_SCENARIO_NEW:
context_manager_->new_scenario_dialog();
return true;
case HOTKEY_EDITOR_MAP_SAVE:
save_map();
return true;
case HOTKEY_EDITOR_MAP_SAVE_ALL:
context_manager_->save_all_maps();
return true;
case HOTKEY_EDITOR_MAP_SAVE_AS:
context_manager_->save_map_as_dialog();
return true;
case HOTKEY_EDITOR_SCENARIO_SAVE_AS:
context_manager_->save_scenario_as_dialog();
return true;
case HOTKEY_EDITOR_MAP_GENERATE:
context_manager_->generate_map_dialog();
return true;
case HOTKEY_EDITOR_MAP_APPLY_MASK:
context_manager_->apply_mask_dialog();
return true;
case HOTKEY_EDITOR_MAP_CREATE_MASK_TO:
context_manager_->create_mask_to_dialog();
return true;
case HOTKEY_EDITOR_MAP_RESIZE:
context_manager_->resize_map_dialog();
return true;
// Side specific ones
case HOTKEY_EDITOR_SIDE_NEW:
get_current_map_context().new_side();
gui_->init_flags();
return true;
case HOTKEY_EDITOR_SIDE_REMOVE:
gui_->set_team(0, true);
gui_->set_playing_team(0);
get_current_map_context().remove_side();
return true;
case HOTKEY_EDITOR_SIDE_EDIT:
context_manager_->edit_side_dialog(gui_->viewing_team());
return true;
// Transitions
case HOTKEY_EDITOR_PARTIAL_UPDATE_TRANSITIONS:
context_manager_->set_update_transitions_mode(2);
return true;
case HOTKEY_EDITOR_AUTO_UPDATE_TRANSITIONS:
context_manager_->set_update_transitions_mode(1);
return true;
case HOTKEY_EDITOR_NO_UPDATE_TRANSITIONS:
context_manager_->set_update_transitions_mode(0);
return true;
case HOTKEY_EDITOR_TOGGLE_TRANSITIONS:
if(context_manager_->toggle_update_transitions()) {
return true;
}
FALLTHROUGH;
case HOTKEY_EDITOR_UPDATE_TRANSITIONS:
context_manager_->refresh_all();
return true;
// Refresh
case HOTKEY_EDITOR_REFRESH:
context_manager_->reload_map();
return true;
case HOTKEY_EDITOR_REFRESH_IMAGE_CACHE:
refresh_image_cache();
return true;
case HOTKEY_EDITOR_DRAW_COORDINATES:
gui().set_draw_coordinates(!gui().get_draw_coordinates());
preferences::editor::set_draw_hex_coordinates(gui().get_draw_coordinates());
gui().invalidate_all();
return true;
case HOTKEY_EDITOR_DRAW_TERRAIN_CODES:
gui().set_draw_terrain_codes(!gui().get_draw_terrain_codes());
preferences::editor::set_draw_terrain_codes(gui().get_draw_terrain_codes());
gui().invalidate_all();
return true;
case HOTKEY_EDITOR_DRAW_NUM_OF_BITMAPS:
gui().set_draw_num_of_bitmaps(!gui().get_draw_num_of_bitmaps());
preferences::editor::set_draw_num_of_bitmaps(gui().get_draw_num_of_bitmaps());
gui().invalidate_all();
return true;
case HOTKEY_EDITOR_REMOVE_LOCATION: {
location_palette* lp = dynamic_cast<location_palette*>(&toolkit_->get_palette_manager()->active_palette());
if (lp) {
perform_delete(new editor_action_starting_position(map_location(), lp->selected_item()));
}
return true;
}
default:
return hotkey::command_executor::execute_command(cmd, index, press);