-
-
Notifications
You must be signed in to change notification settings - Fork 991
/
map_context.hpp
500 lines (390 loc) · 13.6 KB
/
map_context.hpp
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
/*
Copyright (C) 2008 - 2014 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.
*/
#ifndef EDITOR_MAP_CONTEXT_HPP_INCLUDED
#define EDITOR_MAP_CONTEXT_HPP_INCLUDED
#include "editor_map.hpp"
#include "game_classification.hpp"
#include "map_label.hpp"
#include "mp_game_settings.hpp"
#include "sound_music_track.hpp"
#include "tod_manager.hpp"
#include "unit_map.hpp"
#include "overlay.hpp"
#include "../../display_context.hpp"
#include <boost/utility.hpp>
#include <boost/scoped_ptr.hpp>
namespace editor {
/**
* This class wraps around a map to provide a concise interface for the editor to work with.
* The actual map object can change rapidly (be assigned to), the map context persists
* data (like the undo stacks) in this case. The functionality is here, not in editor_controller
* as e.g. the undo stack is part of the map, not the editor as a whole. This might allow many
* maps to be open at the same time.
*/
class map_context : public display_context, private boost::noncopyable
{
public:
/**
* Create a map context from an existing map. The filename is set to be
* empty, indicating a new map.
* Marked "explicit" to avoid automatic conversions.
*/
explicit map_context(const editor_map& map, const display& disp, bool pure_map, const config& schedule);
/**
* Create map_context from a map file. If the map cannot be loaded, an
* exception will be thrown and the object will not be constructed. If the
* map file is a scenario, the map specified in its map_data key will be
* loaded, and the stored filename updated accordingly. Maps embedded
* inside scenarios do not change the filename, but set the "embedded" flag
* instead.
*/
map_context(const config& game_config, const std::string& filename, const display& disp);
/**
* Map context destructor
*/
virtual ~map_context();
/**
* Select the nth tod area.
* @param index of the tod area to select.
*/
bool select_area(int index);
/**
* Map accessor
*/
editor_map& get_map() { return map_; }
/**
* Map accessor - const version
*/
const editor_map& get_map() const { return map_; }
/** Adds a new side to the map */
void new_side() {
team t;
t.set_hidden(false);
teams_.push_back(t);
actions_since_save_++;
}
/** removes the last side from the scenario */
void remove_side() {
teams_.pop_back();
actions_since_save_++;
}
void save_area(const std::set<map_location>& area) {
tod_manager_->replace_area_locations(active_area_, area);
}
void new_area(const std::set<map_location>& area) {
tod_manager_->add_time_area("", area, config());
active_area_ = tod_manager_->get_area_ids().size() -1;
actions_since_save_++;
}
void remove_area(int index);
/** Get the team from the current map context object */
std::vector<team>& get_teams() {
return teams_;
}
map_labels& get_labels() {
return labels_;
}
/** Get the unit map from the current map context object */
unit_map& get_units() {
return units_;
}
const unit_map& get_units() const {
return units_;
}
void replace_schedule(const std::vector<time_of_day>& schedule);
/**
* Const accessor names needed to implement "display_context" interface
*/
virtual const unit_map & units() const {
return units_;
}
virtual const std::vector<team>& teams() const {
return teams_;
}
virtual const gamemap & map() const {
return map_;
}
/**
* Replace the [time]s of the currently active area.
*/
void replace_local_schedule(const std::vector<time_of_day>& schedule);
/**
* TODO
*/
void set_starting_time(int time);
/**
* TODO
*/
void set_local_starting_time(int time) {
tod_manager_->set_current_time(time, active_area_);
actions_since_save_++;
}
tod_manager* get_time_manager() {
return tod_manager_.get();
}
mp_game_settings & get_mp_settings() {
return mp_settings_;
}
game_classification& get_classification() {
return game_classification_;
}
/**
*
* @return the index of the currently active area.
*/
int get_active_area() const {
return active_area_;
}
void set_active_area(int index) {
active_area_ = index;
}
bool is_in_playlist(std::string track_id) {
return music_tracks_.find(track_id) != music_tracks_.end();
}
void add_to_playlist(const sound::music_track& track) {
if (music_tracks_.find(track.id()) == music_tracks_.end())
music_tracks_.insert(std::pair<std::string, sound::music_track>(track.id(), track));
else music_tracks_.erase(track.id());
}
/**
* Draw a terrain on a single location on the map.
* Sets the refresh flags accordingly.
*/
void draw_terrain(const t_translation::t_terrain & terrain, const map_location& loc,
bool one_layer_only = false);
/**
* Actual drawing function used by both overloaded variants of draw_terrain.
*/
void draw_terrain_actual(const t_translation::t_terrain & terrain, const map_location& loc,
bool one_layer_only = false);
/**
* Draw a terrain on a set of locations on the map.
* Sets the refresh flags accordingly.
*/
void draw_terrain(const t_translation::t_terrain & terrain, const std::set<map_location>& locs,
bool one_layer_only = false);
/**
* Getter for the reload flag. Reload is the highest level of required refreshing,
* set when the map size has changed or the map was reassigned.
*/
bool needs_reload() const { return needs_reload_; }
/**
* Setter for the reload flag
*/
void set_needs_reload(bool value=true) { needs_reload_ = value; }
/**
* Getter for the terrain rebuild flag. Set whenever any terrain has changed.
*/
bool needs_terrain_rebuild() const { return needs_terrain_rebuild_; }
/**
* Setter for the terrain rebuild flag
*/
void set_needs_terrain_rebuild(bool value=true) { needs_terrain_rebuild_ = value; }
/**
* TODO
*/
void set_scenario_setup(const std::string& id, const std::string& name, const std::string& description,
int turns, int xp_mod, bool victory_defeated, bool random_time);
/**
* TODO
*/
void set_side_setup(int side, const std::string& id, const std::string& name,
int gold, int income, int village_gold, int village_support,
bool fog, bool share_view, bool shroud, bool share_maps,
team::CONTROLLER controller, bool hidden, bool no_leader);
/**
* Getter for the labels reset flag. Set when the labels need to be refreshed.
*/
bool needs_labels_reset() const { return needs_labels_reset_; }
/**
* Setter for the labels reset flag
*/
void set_needs_labels_reset(bool value=true) { needs_labels_reset_ = value; }
const std::set<map_location> changed_locations() const { return changed_locations_; }
void clear_changed_locations();
void add_changed_location(const map_location& loc);
void add_changed_location(const std::set<map_location>& locs);
void set_everything_changed();
bool everything_changed() const;
void set_labels(display& disp);
void clear_starting_position_labels(display& disp);
void set_starting_position_labels(display& disp);
void reset_starting_position_labels(display& disp);
const std::string& get_filename() const { return filename_; }
void set_filename(const std::string& fn) { filename_ = fn; }
const std::string& get_map_data_key() const { return map_data_key_; }
const std::string& get_id() const { return scenario_id_; }
const std::string& get_description() const { return scenario_description_; }
const std::string& get_name() const { return scenario_name_; }
int get_xp_mod() const { return xp_mod_; }
bool random_start_time() const { return random_time_; }
bool victory_defeated() const { return victory_defeated_; }
bool is_embedded() const { return embedded_; }
bool is_pure_map() const { return pure_map_; }
void set_embedded(bool v) { embedded_ = v; }
/**
* Saves the map under the current filename. Filename must be valid.
* May throw an exception on failure.
*/
bool save_map();
/**
* Saves the scenario under the current filename. Filename must be valid.
* May throw an exception on failure.
*/
bool save_scenario();
void load_scenario(const config& game_config);
config to_config();
void set_map(const editor_map& map);
/**
* Performs an action (thus modifying the map). An appropriate undo action is added to
* the undo stack. The redo stack is cleared. Note that this may throw, use caution
* when calling this with a dereferenced pointer that you own (i.e. use a smart pointer).
*/
void perform_action(const editor_action& action);
/**
* Performs a partial action, assumes that the top undo action has been modified to
* maintain coherent state of the undo stacks, and so a new undo action is not
* created.
*/
void perform_partial_action(const editor_action& action);
/** @return whether the map was modified since the last save */
bool modified() const;
/** Clear the modified state */
void clear_modified();
/** @return true when undo can be performed, false otherwise */
bool can_undo() const;
/** @return true when redo can be performed, false otherwise */
bool can_redo() const;
/** @return a pointer to the last undo action or NULL if the undo stack is empty */
editor_action* last_undo_action();
/** @return a pointer to the last redo action or NULL if the undo stack is empty */
editor_action* last_redo_action();
/** const version of last_undo_action */
const editor_action* last_undo_action() const;
/** const version of last_redo_action */
const editor_action* last_redo_action() const;
/** Un-does the last action, and puts it in the redo stack for a possible redo */
void undo();
/** Re-does a previously undid action, and puts it back in the undo stack. */
void redo();
/**
* Un-does a single step from a undo action chain. The action is separated
* from the chain and it's undo (the redo) is added as a stand-alone action
* to the redo stack.
* Precondition: the last undo action has to actually be an action chain.
*/
void partial_undo();
/**
* Clear the undo and redo stacks
*/
void clear_undo_redo();
protected:
/**
* The actual filename of this map. An empty string indicates a new map.
*/
std::string filename_;
/**
* When a scenario file is loaded, the referenced map is loaded instead.
* The verbatim form of the reference is kept here.
*/
std::string map_data_key_;
/**
* Whether the map context refers to a map embedded in a scenario file.
* This distinction is important in order to avoid overwriting the scenario.
*/
bool embedded_;
/**
* Whether the map context refers to a file containing only the pure map data.
*/
bool pure_map_;
/**
* The map object of this map_context.
*/
editor_map map_;
/**
* Container type used to store actions in the undo and redo stacks
*/
typedef std::deque<editor_action*> action_stack;
/**
* Checks if an action stack reached its capacity and removes the front element if so.
*/
void trim_stack(action_stack& stack);
/**
* Clears an action stack and deletes all its contents. Helper function used when the undo
* or redo stack needs to be cleared
*/
void clear_stack(action_stack& stack);
/**
* Perform an action at the back of one stack, and then move it to the back of the other stack.
* This is the implementation of both undo and redo which only differ in the direction.
*/
void perform_action_between_stacks(action_stack& from, action_stack& to);
/**
* The undo stack. A double-ended queues due to the need to add items to one end,
* and remove from both when performing the undo or when trimming the size. This container owns
* all contents, i.e. no action in the stack shall be deleted, and unless otherwise noted the contents
* could be deleted at an time during normal operation of the stack. To work on an action, either
* remove it from the container or make a copy. Actions are inserted at the back of the container
* and disappear from the front when the capacity is exceeded.
* @todo Use boost's pointer-owning container?
*/
action_stack undo_stack_;
/**
* The redo stack. @see undo_stack_
*/
action_stack redo_stack_;
/**
* Action stack (i.e. undo and redo) maximum size
*/
static const size_t max_action_stack_size_;
/**
* Number of actions performed since the map was saved. Zero means the map was not modified.
*/
int actions_since_save_;
/**
* Cache of set starting position labels. Necessary for removing them.
*/
std::set<map_location> starting_position_label_locs_;
/**
* Refresh flag indicating the map in this context should be completely reloaded by the display
*/
bool needs_reload_;
/**
* Refresh flag indicating the terrain in the map has changed and requires a rebuild
*/
bool needs_terrain_rebuild_;
/**
* Refresh flag indicating the labels in the map have changed
*/
bool needs_labels_reset_;
std::set<map_location> changed_locations_;
bool everything_changed_;
private:
std::string scenario_id_, scenario_name_, scenario_description_;
int xp_mod_;
bool victory_defeated_, random_time_;
int active_area_;
map_labels labels_;
unit_map units_;
std::vector<team> teams_;
boost::scoped_ptr<tod_manager> tod_manager_;
mp_game_settings mp_settings_;
game_classification game_classification_;
typedef std::map<std::string, sound::music_track> music_map;
music_map music_tracks_;
typedef std::multimap<map_location, overlay> overlay_map;
overlay_map overlays_;
public:
overlay_map& get_overlays() { return overlays_; }
};
} //end namespace editor
#endif