Flip operation added.

This commit is contained in:
Kristoffer Erlandsson 2004-05-19 23:55:55 +00:00
parent 5ced5d005f
commit 61a548307b
10 changed files with 178 additions and 11 deletions

View file

@ -191,7 +191,7 @@ height=600
[menu]
title=main_menu
image=lite
items=editnewmap,editloadmap,editresize,editrevert,undo,redo,editsavemap,editsaveas,preferences,togglegrid,editquit
items=editnewmap,editloadmap,editresize,editrevert,editflip,undo,redo,editsavemap,editsaveas,preferences,togglegrid,editquit
rect=3,1,107,22
xanchor=fixed
yanchor=fixed
@ -199,7 +199,7 @@ height=600
[menu]
is_context_menu=true
items=undo,redo,editfloodfill,editfillselection,togglegrid,editsetstartpos,editcut,editcopy,editpaste
items=undo,redo,editfloodfill,editfillselection,togglegrid,editflip,editsetstartpos,editcut,editcopy,editpaste
[/menu]
# top panel

View file

@ -495,6 +495,7 @@ action_editcopy="Copy"
action_editpaste="Paste"
action_editrevert="Revert from Disk"
action_editresize="Resize Map"
action_editflip="Flip Map"
save_hotkeys_button="Save Hotkeys"
change_hotkey_button="Change Hotkey"
hotkeys_dialog="Hotkey Settings"

View file

@ -313,8 +313,8 @@ void map_editor::edit_fill_selection() {
map_.set_terrain(*it, palette_.selected_terrain());
}
}
terrain_changed(selected_hexes_, undo_action);
save_undo_action(undo_action);
invalidate_all_and_adjacent(selected_hexes_);
}
void map_editor::edit_cut() {
@ -378,6 +378,17 @@ void map_editor::edit_resize() {
}
}
void map_editor::edit_flip() {
const FLIP_AXIS flip_axis = flip_dialog(gui_);
if (flip_axis != NO_FLIP) {
const std::string flipped_map = flip_map(map_, flip_axis);
map_undo_action action;
action.set_map_data(map_.write(), flipped_map);
save_undo_action(action);
throw new_map_exception(flipped_map, filename_);
}
}
std::string map_editor::load_map(const std::string filename) {
bool load_successful = true;
std::string msg = "'";
@ -452,6 +463,7 @@ bool map_editor::can_execute_command(hotkey::HOTKEY_COMMAND command) const {
case hotkey::HOTKEY_EDIT_PASTE:
case hotkey::HOTKEY_EDIT_REVERT:
case hotkey::HOTKEY_EDIT_RESIZE:
case hotkey::HOTKEY_EDIT_FLIP:
return true;
default:
return false;
@ -1012,8 +1024,7 @@ void map_editor::main_loop() {
if (map_dirty_) {
if (!l_button_down) {
map_dirty_ = false;
// XXX Currently this rebuilds the whole map, thus we
// only want to perform it at these times.
// XXX Currently this rebuilds all terrain, so we only want to do it once.
gui_.rebuild_terrain(gamemap::location(1,1));
gui_.invalidate_all();
recalculate_starting_pos_labels();

View file

@ -105,6 +105,7 @@ public:
virtual void edit_paste();
virtual void edit_revert();
virtual void edit_resize();
virtual void edit_flip();
virtual bool can_execute_command(hotkey::HOTKEY_COMMAND command) const;
@ -198,7 +199,8 @@ private:
/// highlighted.
void highlight_selected_hexes(const bool clear_old=true);
/// Terrain has changed at the specified hex. If the hex was a
/// Terrain has changed at the specified hex through user drawing
/// (not undo/redo or other special things). If the hex was a
/// starting position, remove this position. Save additional
/// information in the undo_action and invalidate the hex and the
/// adjacent ones.

View file

@ -502,7 +502,23 @@ resize_dialog(display &disp, const unsigned curr_w, const unsigned curr_h) {
}
FLIP_AXIS flip_dialog(display &disp) {
std::vector<std::string> items;
items.push_back("X-Axis");
items.push_back("Y-Axis");
const int res =
gui::show_dialog(disp, NULL, "",
"Flip around\n(this may change the\ndimensions of the map):",
gui::OK_CANCEL, &items);
switch (res) {
case 0:
return FLIP_X;
case 1:
return FLIP_Y;
default:
return NO_FLIP;
}
}
}

View file

@ -14,6 +14,8 @@
#include "../config.hpp"
#include "../map.hpp"
#include "map_manip.hpp"
#include <map>
#ifndef EDITOR_DIALOGS_H_INCLUDED
@ -50,9 +52,7 @@ void preferences_dialog(display &disp, config &prefs);
std::pair<unsigned, unsigned>
resize_dialog(display &disp, const unsigned curr_w, const unsigned curr_h);
FLIP_AXIS flip_dialog(display &disp);
}

View file

@ -12,6 +12,7 @@
#include "../map.hpp"
#include "../config.hpp"
#include "../util.hpp"
#include "map_manip.hpp"
@ -20,6 +21,96 @@
#include <algorithm>
#include <set>
namespace {
// Grow the map, represented by lines, one step. If grow_height is
// true, the height is increased and every other column is shifted
// one step downwards. Otherwise the map is increased in width one
// step. The terrain used as padding is deducted from the surrounded
// terrain.
void grow_and_pad(const gamemap &map, std::vector<std::string> &lines,
bool grow_height) {
int i, j;
std::vector<gamemap::TERRAIN> terrains;
gamemap::TERRAIN chosen_terrain;
if (grow_height) {
lines.push_back(std::string(lines[0].size(),
gamemap::FOREST));
// Shift terrain on odd numbered columns one step downwards.
for (i = 0; (unsigned)i < lines[0].size(); i += 2) {
for (j = lines.size() - 2; j >= 0; j--) {
lines[j + 1][i] = lines[j][i];
}
}
// Set the terrain for the hexes that was used as padding.
for (i = 0; (unsigned)i < lines[0].size(); i++) {
terrains.clear();
if (is_even(i)) {
terrains.push_back(lines[1][i]);
terrains.push_back(i == 0 ? terrains[0] : lines[0][i - 1]);
terrains.push_back((unsigned)i == lines[0].size() - 1
? terrains[0] : lines[0][i + 1]);
}
else {
terrains.push_back(lines[lines.size() - 2][i]);
terrains.push_back(i == 0
? terrains[0] :
lines[lines.size() - 1][i - 1]);
terrains.push_back((unsigned)i == lines[0].size() - 1 ?
terrains[0] : lines[lines.size() - 1][i + 1]);
}
if (terrains[1] == terrains[2]) {
chosen_terrain = terrains[2];
}
else {
chosen_terrain = terrains[0];
}
if (map.is_village(chosen_terrain)) {
for (j = 0; j < 3; j++) {
if (!map.is_village(terrains[j])) {
chosen_terrain = terrains[j];
break;
}
}
}
if (map.is_village(chosen_terrain)) {
chosen_terrain = gamemap::FOREST;
}
if (is_even(i)) {
lines[0][i] = chosen_terrain;
}
else {
lines[lines.size() - 1][i] = chosen_terrain;
}
}
}
else {
for (i = 0; (unsigned)i < lines.size(); i++) {
int change;
terrains.clear();
terrains.push_back(lines[i][lines[i].length() - 1]);
if (is_even(lines[i].size()+1)) {
change = 1;
}
else {
change = -1;
}
if (i + change > 0 && (unsigned)(i + change) < lines.size()) {
terrains.push_back(lines[i + change][lines[i].length() - 1]);
}
else {
terrains.push_back(terrains[0]);
}
chosen_terrain = map.is_village(terrains[0])
? terrains[1] : terrains[0];
chosen_terrain = map.is_village(chosen_terrain)
? gamemap::FOREST : chosen_terrain;
lines[i].resize(lines[i].length() + 1, chosen_terrain);
}
}
}
}
namespace map_editor {
std::vector<gamemap::location> get_tiles(const gamemap &map,
@ -126,4 +217,40 @@ std::string resize_map(const gamemap &map, const unsigned new_w,
}
std::string flip_map(const gamemap &map, const FLIP_AXIS axis) {
const std::string str_map = map.write();
if (str_map == "") {
return str_map;
}
std::vector<std::string> lines = config::split(str_map, '\n');
std::vector<std::string> new_lines;
if (axis == FLIP_Y) {
if (is_even(lines[0].size())) {
grow_and_pad(map, lines, false);
}
new_lines.resize(lines.size());
std::vector<std::string>::iterator new_line_it = new_lines.begin();
for (std::vector<std::string>::const_iterator it = lines.begin();
it != lines.end(); it++) {
for (std::string::const_reverse_iterator sit = (*it).rbegin();
sit != (*it).rend(); sit++) {
(*new_line_it).push_back(*sit);
}
new_line_it++;
}
}
else if (axis == FLIP_X) {
std::vector<std::string>::reverse_iterator it;
for (it = lines.rbegin(); it != lines.rend(); it++) {
new_lines.push_back(*it);
}
grow_and_pad(map, new_lines, true);
}
else {
new_lines = lines;
}
return config::join(new_lines, '\n');
}
}

View file

@ -47,8 +47,11 @@ get_component(const gamemap &map, const gamemap::location &start_loc);
/// with the terrain fill_with.
std::string resize_map(const gamemap &map, const unsigned new_w,
const unsigned new_h, const gamemap::TERRAIN fill_with);
enum FLIP_AXIS {NO_FLIP, FLIP_X, FLIP_Y};
/// Return the string representation of the map after it has been
/// flipped around the axis.
std::string flip_map(const gamemap &map, const FLIP_AXIS axis);
}
#endif // MAP_MANIP_H_INCLUDED

View file

@ -80,6 +80,7 @@ HOTKEY_COMMAND string_to_command(const std::string& str)
m.insert(val("editpaste",HOTKEY_EDIT_PASTE));
m.insert(val("editrevert",HOTKEY_EDIT_REVERT));
m.insert(val("editresize",HOTKEY_EDIT_RESIZE));
m.insert(val("editflip",HOTKEY_EDIT_FLIP));
m.insert(val("delayshroud",HOTKEY_DELAY_SHROUD));
m.insert(val("updateshroud",HOTKEY_UPDATE_SHROUD));
m.insert(val("continue",HOTKEY_CONTINUE_MOVE));
@ -472,6 +473,10 @@ void execute_command(display& disp, HOTKEY_COMMAND command, command_executor* ex
if(executor)
executor->edit_resize();
break;
case HOTKEY_EDIT_FLIP:
if(executor)
executor->edit_flip();
break;
default:
std::cerr << "command_executor: unknown command number " << command << ", ignoring.\n";
break;

View file

@ -44,6 +44,7 @@ enum HOTKEY_COMMAND { HOTKEY_CYCLE_UNITS, HOTKEY_END_UNIT_TURN, HOTKEY_LEADER,
HOTKEY_EDIT_NEW_MAP, HOTKEY_EDIT_LOAD_MAP, HOTKEY_EDIT_FLOOD_FILL,
HOTKEY_EDIT_FILL_SELECTION, HOTKEY_EDIT_CUT, HOTKEY_EDIT_COPY,
HOTKEY_EDIT_PASTE, HOTKEY_EDIT_REVERT, HOTKEY_EDIT_RESIZE,
HOTKEY_EDIT_FLIP,
HOTKEY_NULL };
struct hotkey_item {
@ -133,6 +134,7 @@ public:
virtual void edit_paste() {}
virtual void edit_revert() {}
virtual void edit_resize() {}
virtual void edit_flip() {}
//Gets the action's image (if any). Displayed left of the action text in menus.
virtual std::string get_action_image(hotkey::HOTKEY_COMMAND command) const { return ""; }