Flip operation added.
This commit is contained in:
parent
5ced5d005f
commit
61a548307b
10 changed files with 178 additions and 11 deletions
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ""; }
|
||||
|
|
Loading…
Add table
Reference in a new issue