editor/action.cpp

Go to the documentation of this file.
00001 /* $Id: action.cpp 53296 2012-02-28 10:31:13Z fendrin $ */
00002 /*
00003    Copyright (C) 2008 - 2012 by Tomasz Sniatowski <kailoran@gmail.com>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 /**
00017  * @file
00018  * Editor action classes
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& /*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         // If another player was starting at the location, we actually perform two actions, so the undo is an action_chain.
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 } //end namespace editor
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Tue Mar 13 2012 01:02:39 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs