00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #define GETTEXT_DOMAIN "wesnoth-editor"
00021
00022 #include "editor/action.hpp"
00023 #include "editor/map_context.hpp"
00024 #include "foreach.hpp"
00025 #include "gettext.hpp"
00026 #include "util.hpp"
00027
00028 #include "resources.hpp"
00029
00030 namespace editor {
00031
00032 int editor_action::next_id_ = 1;
00033 int editor_action::instance_count_ = 0;
00034
00035 editor_action::editor_action()
00036 : id_(next_id_++)
00037 {
00038 instance_count_++;
00039 #ifdef EDITOR_DEBUG_ACTION_LIFETIME
00040 LOG_ED << "Action " << std::setw(2) << id_ << " ctor " << this << " (count is " << instance_count << "\n";
00041 #endif
00042 }
00043
00044 editor_action::~editor_action()
00045 {
00046 instance_count_--;
00047 #ifdef EDITOR_DEBUG_ACTION_LIFETIME
00048 LOG_ED << "Action " << std::setw(2) << id_ << " dtor " << this << " (count is " << instance_count << "\n";
00049 #endif
00050 }
00051
00052 int editor_action::action_count() const
00053 {
00054 return 1;
00055 }
00056
00057 std::string editor_action::get_description() const
00058 {
00059 return "Unknown action";
00060 }
00061
00062 editor_action* editor_action::perform(map_context& mc) const
00063 {
00064 util::unique_ptr<editor_action> undo(new editor_action_whole_map(mc.get_map()));
00065 perform_without_undo(mc);
00066 return undo.release();
00067 }
00068
00069 editor_action_whole_map* editor_action_whole_map::clone() const
00070 {
00071 return new editor_action_whole_map(*this);
00072 }
00073 void editor_action_whole_map::perform_without_undo(map_context& mc) const {
00074 mc.set_map(m_);
00075 }
00076
00077 editor_action_chain::editor_action_chain(const editor::editor_action_chain &other)
00078 : editor_action(), actions_()
00079 {
00080 foreach (editor_action* a, other.actions_) {
00081 actions_.push_back(a->clone());
00082 }
00083 }
00084 editor_action_chain& editor_action_chain::operator=(const editor_action_chain& other)
00085 {
00086 if (this == &other) return *this;
00087 foreach (editor_action* a, actions_) {
00088 delete a;
00089 }
00090 actions_.clear();
00091 foreach (editor_action* a, other.actions_) {
00092 actions_.push_back(a->clone());
00093 }
00094 return *this;
00095 }
00096 editor_action_chain::~editor_action_chain()
00097 {
00098 foreach (editor_action* a, actions_) {
00099 delete a;
00100 }
00101 }
00102 editor_action_chain* editor_action_chain::clone() const
00103 {
00104 return new editor_action_chain(*this);
00105 }
00106 int editor_action_chain::action_count() const {
00107 int count = 0;
00108 foreach (const editor_action* a, actions_) {
00109 if (a) {
00110 count += a->action_count();
00111 }
00112 }
00113 return count;
00114 }
00115 void editor_action_chain::append_action(editor_action* a) {
00116 actions_.push_back(a);
00117 }
00118 void editor_action_chain::prepend_action(editor_action* a) {
00119 actions_.push_front(a);
00120 }
00121 bool editor_action_chain::empty() const {
00122 return actions_.empty();
00123 }
00124 editor_action* editor_action_chain::pop_last_action() {
00125 if (empty()) throw editor_action_exception("pop_last_action requested on an empty action_chain");
00126 editor_action* last = actions_.back();
00127 actions_.pop_back();
00128 return last;
00129 }
00130 editor_action* editor_action_chain::pop_first_action() {
00131 if (empty()) throw editor_action_exception("pop_first_action requested on an empty action_chain");
00132 editor_action* last = actions_.front();
00133 actions_.pop_front();
00134 return last;
00135 }
00136 editor_action_chain* editor_action_chain::perform(map_context& mc) const {
00137 util::unique_ptr<editor_action_chain> undo(new editor_action_chain());
00138 foreach (editor_action* a, actions_) {
00139 if (a != NULL) {
00140 undo->append_action(a->perform(mc));
00141 }
00142 }
00143 std::reverse(undo->actions_.begin(), undo->actions_.end());
00144 return undo.release();
00145 }
00146 void editor_action_chain::perform_without_undo(map_context& mc) const
00147 {
00148 foreach (editor_action* a, actions_) {
00149 if (a != NULL) {
00150 a->perform_without_undo(mc);
00151 }
00152 }
00153 }
00154
00155 void editor_action_area::extend(const editor_map& , const std::set<map_location>& locs)
00156 {
00157 area_.insert(locs.begin(), locs.end());
00158 }
00159
00160 editor_action_paste* editor_action_paste::clone() const
00161 {
00162 return new editor_action_paste(*this);
00163 }
00164 void editor_action_paste::extend(const editor_map& map, const std::set<map_location>& locs)
00165 {
00166 paste_.add_tiles(map, locs);
00167 }
00168 editor_action_paste* editor_action_paste::perform(map_context& mc) const
00169 {
00170 map_fragment mf(mc.get_map(), paste_.get_offset_area(offset_));
00171 util::unique_ptr<editor_action_paste> undo(new editor_action_paste(mf));
00172 perform_without_undo(mc);
00173 return undo.release();
00174 }
00175 void editor_action_paste::perform_without_undo(map_context& mc) const
00176 {
00177 paste_.paste_into(mc.get_map(), offset_);
00178 mc.add_changed_location(paste_.get_offset_area(offset_));
00179 mc.set_needs_terrain_rebuild();
00180 }
00181
00182
00183 editor_action_paint_area* editor_action_paint_area::clone() const
00184 {
00185 return new editor_action_paint_area(*this);
00186 }
00187 editor_action_paste* editor_action_paint_area::perform(map_context& mc) const
00188 {
00189 map_fragment mf(mc.get_map(), area_);
00190 util::unique_ptr<editor_action_paste> undo(new editor_action_paste(mf));
00191 perform_without_undo(mc);
00192 return undo.release();
00193 }
00194 void editor_action_paint_area::perform_without_undo(map_context& mc) const
00195 {
00196 mc.draw_terrain(t_, area_, one_layer_);
00197 mc.set_needs_terrain_rebuild();
00198 }
00199
00200 editor_action_fill* editor_action_fill::clone() const
00201 {
00202 return new editor_action_fill(*this);
00203 }
00204 editor_action_paint_area* editor_action_fill::perform(map_context& mc) const
00205 {
00206 std::set<map_location> to_fill = mc.get_map().get_contiguous_terrain_tiles(loc_);
00207 util::unique_ptr<editor_action_paint_area> undo(new editor_action_paint_area(to_fill, mc.get_map().get_terrain(loc_)));
00208 mc.draw_terrain(t_, to_fill, one_layer_);
00209 mc.set_needs_terrain_rebuild();
00210 return undo.release();
00211 }
00212 void editor_action_fill::perform_without_undo(map_context& mc) const
00213 {
00214 std::set<map_location> to_fill = mc.get_map().get_contiguous_terrain_tiles(loc_);
00215 mc.draw_terrain(t_, to_fill, one_layer_);
00216 mc.set_needs_terrain_rebuild();
00217 }
00218
00219 editor_action_starting_position* editor_action_starting_position::clone() const
00220 {
00221 return new editor_action_starting_position(*this);
00222 }
00223 editor_action* editor_action_starting_position::perform(map_context& mc) const
00224 {
00225 util::unique_ptr<editor_action> undo;
00226 int old_player = mc.get_map().is_starting_position(loc_) + 1;
00227 map_location old_loc = mc.get_map().starting_position(player_);
00228 LOG_ED << "ssp perform, player_" << player_ << ", loc_ " << loc_ << ", old_player " << old_player << ", old_loc " << old_loc << "\n";
00229 if (old_player != -1) {
00230
00231 editor_action_chain* undo_chain = new editor_action_chain();
00232 undo_chain->append_action(new editor_action_starting_position(loc_, old_player));
00233 undo_chain->append_action(new editor_action_starting_position(old_loc, player_));
00234 undo.reset(undo_chain);
00235 LOG_ED << "ssp actual: " << old_player << " to " << map_location() << "\n";
00236 mc.get_map().set_starting_position(old_player, map_location());
00237 } else {
00238 undo.reset(new editor_action_starting_position(old_loc, player_));
00239 }
00240 LOG_ED << "ssp actual: " << player_ << " to " << loc_ << "\n";
00241 mc.get_map().set_starting_position(player_, loc_);
00242 mc.set_needs_labels_reset();
00243 return undo.release();
00244 }
00245 void editor_action_starting_position::perform_without_undo(map_context& mc) const
00246 {
00247 int old_player = mc.get_map().is_starting_position(loc_);
00248 if (old_player != -1) {
00249 mc.get_map().set_starting_position(old_player, map_location());
00250 }
00251 mc.get_map().set_starting_position(player_, loc_);
00252 mc.set_needs_labels_reset();
00253 }
00254
00255
00256 editor_action_select* editor_action_select::clone() const
00257 {
00258 return new editor_action_select(*this);
00259 }
00260 void editor_action_select::extend(const editor_map& map, const std::set<map_location>& locs)
00261 {
00262 foreach (const map_location& loc, locs) {
00263 LOG_ED << "Checking " << loc << "\n";
00264 if (map.in_selection(loc)) {
00265 LOG_ED << "Extending by " << loc << "\n";
00266 area_.insert(loc);
00267 }
00268 }
00269 }
00270 editor_action* editor_action_select::perform(map_context& mc) const
00271 {
00272 std::set<map_location> undo_locs;
00273 foreach (const map_location& loc, area_) {
00274 if (!mc.get_map().in_selection(loc)) {
00275 undo_locs.insert(loc);
00276 mc.add_changed_location(loc);
00277 }
00278 }
00279 perform_without_undo(mc);
00280 return new editor_action_deselect(undo_locs);
00281 }
00282 void editor_action_select::perform_without_undo(map_context& mc) const
00283 {
00284 foreach (const map_location& loc, area_) {
00285 mc.get_map().add_to_selection(loc);
00286 mc.add_changed_location(loc);
00287 }
00288 }
00289
00290 editor_action_deselect* editor_action_deselect::clone() const
00291 {
00292 return new editor_action_deselect(*this);
00293 }
00294 void editor_action_deselect::extend(const editor_map& map, const std::set<map_location>& locs)
00295 {
00296 foreach (const map_location& loc, locs) {
00297 LOG_ED << "Checking " << loc << "\n";
00298 if (!map.in_selection(loc)) {
00299 LOG_ED << "Extending by " << loc << "\n";
00300 area_.insert(loc);
00301 }
00302 }
00303 }
00304 editor_action* editor_action_deselect::perform(map_context& mc) const
00305 {
00306 std::set<map_location> undo_locs;
00307 foreach (const map_location& loc, area_) {
00308 if (mc.get_map().in_selection(loc)) {
00309 undo_locs.insert(loc);
00310 mc.add_changed_location(loc);
00311 }
00312 }
00313 perform_without_undo(mc);
00314 return new editor_action_select(undo_locs);
00315 }
00316 void editor_action_deselect::perform_without_undo(map_context& mc) const
00317 {
00318 foreach (const map_location& loc, area_) {
00319 mc.get_map().remove_from_selection(loc);
00320 mc.add_changed_location(loc);
00321 }
00322 }
00323
00324 editor_action_select_all* editor_action_select_all::clone() const
00325 {
00326 return new editor_action_select_all(*this);
00327 }
00328 editor_action_deselect* editor_action_select_all::perform(map_context& mc) const
00329 {
00330 std::set<map_location> current = mc.get_map().selection();
00331 mc.get_map().select_all();
00332 std::set<map_location> all = mc.get_map().selection();
00333 std::set<map_location> undo_locs;
00334 std::set_difference(all.begin(), all.end(),
00335 current.begin(), current.end(),
00336 std::inserter(undo_locs, undo_locs.begin()));
00337 mc.set_everything_changed();
00338 return new editor_action_deselect(undo_locs);
00339 }
00340 void editor_action_select_all::perform_without_undo(map_context& mc) const
00341 {
00342 mc.get_map().select_all();
00343 mc.set_everything_changed();
00344 }
00345
00346 editor_action_select_none* editor_action_select_none::clone() const
00347 {
00348 return new editor_action_select_none(*this);
00349 }
00350 editor_action_select* editor_action_select_none::perform(map_context& mc) const
00351 {
00352 std::set<map_location> current = mc.get_map().selection();
00353 mc.get_map().clear_selection();
00354 mc.set_everything_changed();
00355 return new editor_action_select(current);
00356 }
00357 void editor_action_select_none::perform_without_undo(map_context& mc) const
00358 {
00359 mc.get_map().clear_selection();
00360 mc.set_everything_changed();
00361 }
00362
00363 editor_action_select_inverse* editor_action_select_inverse::clone() const
00364 {
00365 return new editor_action_select_inverse(*this);
00366 }
00367 editor_action_select_inverse* editor_action_select_inverse::perform(map_context& mc) const
00368 {
00369 perform_without_undo(mc);
00370 return new editor_action_select_inverse();
00371 }
00372 void editor_action_select_inverse::perform_without_undo(map_context& mc) const
00373 {
00374 mc.get_map().invert_selection();
00375 mc.set_everything_changed();
00376 }
00377
00378 editor_action_resize_map* editor_action_resize_map::clone() const
00379 {
00380 return new editor_action_resize_map(*this);
00381 }
00382 void editor_action_resize_map::perform_without_undo(map_context& mc) const
00383 {
00384 mc.get_map().resize(x_size_, y_size_, x_offset_, y_offset_, fill_);
00385 mc.set_needs_reload();
00386 }
00387
00388 editor_action_apply_mask* editor_action_apply_mask::clone() const
00389 {
00390 return new editor_action_apply_mask(*this);
00391 }
00392 void editor_action_apply_mask::perform_without_undo(map_context& mc) const
00393 {
00394 mc.get_map().overlay(mask_, config(), 0, 0, true);
00395 mc.set_needs_terrain_rebuild();
00396 }
00397
00398 editor_action_create_mask* editor_action_create_mask::clone() const
00399 {
00400 return new editor_action_create_mask(*this);
00401 }
00402 void editor_action_create_mask::perform_without_undo(map_context& mc) const
00403 {
00404 mc.get_map() = mc.get_map().mask_to(target_);
00405 mc.set_needs_terrain_rebuild();
00406 }
00407
00408 editor_action_shuffle_area* editor_action_shuffle_area::clone() const
00409 {
00410 return new editor_action_shuffle_area(*this);
00411 }
00412 editor_action_paste* editor_action_shuffle_area::perform(map_context& mc) const
00413 {
00414 map_fragment mf(mc.get_map(), area_);
00415 util::unique_ptr<editor_action_paste> undo(new editor_action_paste(mf));
00416 perform_without_undo(mc);
00417 return undo.release();
00418 }
00419
00420 void editor_action_shuffle_area::perform_without_undo(map_context& mc) const
00421 {
00422 std::vector<map_location> shuffle;
00423 std::copy(area_.begin(), area_.end(), std::inserter(shuffle, shuffle.begin()));
00424 std::random_shuffle(shuffle.begin(), shuffle.end());
00425 std::vector<map_location>::const_iterator shuffle_it = shuffle.begin();
00426 std::set<map_location>::const_iterator orig_it = area_.begin();
00427 while (orig_it != area_.end()) {
00428 t_translation::t_terrain tmp = mc.get_map().get_terrain(*orig_it);
00429 mc.draw_terrain(mc.get_map().get_terrain(*shuffle_it), *orig_it);
00430 mc.draw_terrain(tmp, *shuffle_it);
00431 ++orig_it;
00432 ++shuffle_it;
00433 }
00434 mc.set_needs_terrain_rebuild();
00435 }
00436
00437 }