Added the ability to resize the map.

This commit is contained in:
Kristoffer Erlandsson 2004-05-11 20:03:02 +00:00
parent 0946c4b945
commit 9ce185a2f0
10 changed files with 245 additions and 42 deletions

View file

@ -117,8 +117,8 @@ shift=no
[hotkey]
command="editfillselection"
key="f"
ctrl=yes
alt=no
ctrl=no
alt=yes
shift=no
[/hotkey]
@ -162,6 +162,22 @@ alt=no
shift=no
[/hotkey]
[hotkey]
command="editresize"
key="r"
ctrl=yes
alt=yes
shift=no
[/hotkey]
[hotkey]
command="fullscreen"
key="f"
ctrl=yes
alt=no
shift=no
[/hotkey]
[resolution]
width=800
height=600
@ -175,7 +191,7 @@ height=600
[menu]
title=main_menu
image=lite
items=editnewmap,editloadmap,editrevert,undo,redo,editsavemap,editsaveas,preferences,togglegrid,editquit
items=editnewmap,editloadmap,editresize,editrevert,undo,redo,editsavemap,editsaveas,preferences,togglegrid,editquit
rect=3,1,107,22
xanchor=fixed
yanchor=fixed

View file

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

View file

@ -139,7 +139,17 @@ void map_editor::handle_keyboard_event(const SDL_KeyboardEvent &event,
set_abort();
}
else {
const bool old_fullscreen = preferences::fullscreen();
const std::pair<int, int> old_resolution = preferences::resolution();
hotkey::key_event(gui_, event, this);
// A key event may change the video mode. The redraw
// functionality inside the preferences module does not
// redraw our palettes so we need to check if the mode has
// changed and if so redraw everything.
if (preferences::fullscreen() != old_fullscreen
|| old_resolution != preferences::resolution()) {
redraw_everything();
}
}
}
}
@ -341,13 +351,25 @@ void map_editor::edit_revert() {
}
}
void map_editor::edit_resize() {
const std::pair<unsigned, unsigned> new_size =
resize_dialog(gui_, map_.x(), map_.y());
if (new_size.first != 0) {
const std::string resized_map =
resize_map(map_, new_size.first, new_size.second, palette_.selected_terrain());
if (resized_map != "") {
throw new_map_exception(resized_map, filename_);
}
}
}
std::string map_editor::load_map(const std::string filename) {
bool load_successful = true;
std::string msg;
std::string msg = "'";
std::string new_map;
if (!file_exists(filename) || is_directory(filename)) {
load_successful = false;
msg = filename + " does not exist or can't be read as a file.";
msg += filename + "' does not exist or can't be read as a file.";
}
else {
try {
@ -414,6 +436,7 @@ bool map_editor::can_execute_command(hotkey::HOTKEY_COMMAND command) const {
case hotkey::HOTKEY_EDIT_CUT:
case hotkey::HOTKEY_EDIT_PASTE:
case hotkey::HOTKEY_EDIT_REVERT:
case hotkey::HOTKEY_EDIT_RESIZE:
return true;
default:
return false;
@ -490,8 +513,10 @@ void map_editor::redo() {
void map_editor::preferences() {
preferences_dialog(gui_, prefs_);
// Sizes and stuff may have changed, we need to redraw and
// recalculate everything if that is the case.
redraw_everything();
}
void map_editor::redraw_everything() {
adjust_sizes(gui_, size_specs_);
palette_.adjust_size();
brush_.adjust_size();

View file

@ -131,7 +131,8 @@ public:
/// saved.
bool changed_since_save() const;
/// Recalculate layout and redraw everything.
void redraw_everything();
// Methods inherited from command_executor. Used to perform
// operations on menu/hotkey commands.
@ -153,6 +154,7 @@ public:
virtual void edit_copy();
virtual void edit_paste();
virtual void edit_revert();
virtual void edit_resize();
virtual bool can_execute_command(hotkey::HOTKEY_COMMAND command) const;

View file

@ -28,6 +28,14 @@
#include "editor_dialogs.hpp"
namespace {
const int map_min_height = 20;
const int map_min_width = 20;
const int map_max_height = 200;
const int map_max_width = 200;
}
namespace map_editor {
bool confirm_modification_disposal(display& disp) {
@ -96,20 +104,16 @@ std::string new_map_dialog(display& disp, gamemap::TERRAIN fill_terrain,
const int slider_right = xpos + width - horz_margin - right_space;
SDL_Rect slider_rect = { slider_left,width_rect.y,slider_right-slider_left,width_rect.h};
const int min_width = 20;
const int max_width = 200;
const int max_height = 200;
slider_rect.y = width_rect.y;
gui::slider width_slider(disp,slider_rect);
width_slider.set_min(min_width);
width_slider.set_max(max_width);
width_slider.set_min(map_min_width);
width_slider.set_max(map_max_width);
width_slider.set_value(map_width);
slider_rect.y = height_rect.y;
gui::slider height_slider(disp,slider_rect);
height_slider.set_min(min_width);
height_slider.set_max(max_height);
height_slider.set_min(map_min_height);
height_slider.set_max(map_max_height);
height_slider.set_value(map_height);
const config* const cfg =
@ -118,16 +122,11 @@ std::string new_map_dialog(display& disp, gamemap::TERRAIN fill_terrain,
generator.assign(create_map_generator("", cfg));
for(bool draw = true;; draw = false) {
int mousex, mousey;
const int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
const bool left_button = mouse_flags&SDL_BUTTON_LMASK;
if(cancel_button.process(mousex,mousey,left_button)) {
if(cancel_button.pressed()) {
return "";
}
if(new_map_button.process(mousex,mousey,left_button)) {
if(new_map_button.pressed()) {
draw = true;
if ((confirmation_needed &&
confirm_modification_disposal(disp))
@ -145,14 +144,14 @@ std::string new_map_dialog(display& disp, gamemap::TERRAIN fill_terrain,
return map_str.str();
}
}
if(random_map_setting_button.process(mousex,mousey,left_button)) {
if(random_map_setting_button.pressed()) {
draw = true;
if (generator.get()->allow_user_config()) {
generator.get()->user_config(disp);
}
}
if(random_map_button.process(mousex,mousey,left_button)) {
if(random_map_button.pressed()) {
draw = true;
if ((confirmation_needed
&& confirm_modification_disposal(disp))
@ -199,8 +198,8 @@ std::string new_map_dialog(display& disp, gamemap::TERRAIN fill_terrain,
random_map_setting_button.set_dirty();
cancel_button.set_dirty();
width_slider.set_min(min_width);
height_slider.set_min(min_width);
width_slider.set_min(map_min_width);
height_slider.set_min(map_min_height);
events::raise_process_event();
events::raise_draw_event();
@ -209,7 +208,7 @@ std::string new_map_dialog(display& disp, gamemap::TERRAIN fill_terrain,
update_rect(xpos,ypos,width,height);
}
disp.update_display();
SDL_Delay(10);
SDL_Delay(20);
events::pump();
}
}
@ -324,16 +323,11 @@ void preferences_dialog(display &disp, config &prefs) {
bool redraw_all = true;
for(;;) {
int mousex, mousey;
const int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
const bool left_button = mouse_flags&SDL_BUTTON_LMASK;
if(close_button.process(mousex,mousey,left_button)) {
if(close_button.pressed()) {
break;
}
if(fullscreen_button.process(mousex,mousey,left_button)) {
if(fullscreen_button.pressed()) {
//the underlying frame buffer is changing, so cancel
//the surface restorer restoring the frame buffer state
restorer.cancel();
@ -359,11 +353,11 @@ void preferences_dialog(display &disp, config &prefs) {
redraw_all = false;
}
if(grid_button.process(mousex,mousey,left_button)) {
if(grid_button.pressed()) {
preferences::set_grid(grid_button.checked());
}
if(resolution_button.process(mousex,mousey,left_button)) {
if(resolution_button.pressed()) {
const bool mode_changed = preferences::show_video_mode_dialog(disp);
if(mode_changed) {
//the underlying frame buffer is changing, so cancel
@ -373,7 +367,7 @@ void preferences_dialog(display &disp, config &prefs) {
break;
}
if(hotkeys_button.process(mousex,mousey,left_button)) {
if(hotkeys_button.pressed()) {
preferences::show_hotkeys_dialog(disp, &prefs);
break;
}
@ -390,6 +384,123 @@ void preferences_dialog(display &disp, config &prefs) {
}
}
std::pair<unsigned, unsigned>
resize_dialog(display &disp, const unsigned curr_w, const unsigned curr_h) {
const events::resize_lock prevent_resizing;
const events::event_context dialog_events_context;
int map_width(curr_w), map_height(curr_h);
const int width = 600;
const int height = 200;
const int xpos = disp.x()/2 - width/2;
const int ypos = disp.y()/2 - height/2;
const int horz_margin = 5;
const int vertical_margin = 20;
const int button_padding = 20;
SDL_Rect dialog_rect = {xpos-10,ypos-10,width+20,height+20};
surface_restorer restorer(&disp.video(),dialog_rect);
gui::draw_dialog_frame(xpos,ypos,width,height,disp);
SDL_Rect title_rect = font::draw_text(NULL,disp.screen_area(),24,font::NORMAL_COLOUR,
"Resize Map",0,0);
const std::string& width_label = string_table["map_width"] + ":";
const std::string& height_label = string_table["map_height"] + ":";
SDL_Rect width_rect = font::draw_text(NULL, disp.screen_area(), 14, font::NORMAL_COLOUR,
width_label, 0, 0);
SDL_Rect height_rect = font::draw_text(NULL, disp.screen_area(), 14, font::NORMAL_COLOUR,
height_label, 0, 0);
const int text_right = xpos + horz_margin +
maximum<int>(width_rect.w,height_rect.w);
width_rect.x = text_right - width_rect.w;
height_rect.x = text_right - height_rect.w;
width_rect.y = ypos + title_rect.h + vertical_margin*2;
height_rect.y = width_rect.y + width_rect.h + vertical_margin;
gui::button cancel_button(disp,"Cancel");
gui::button ok_button(disp,"Ok");
cancel_button.set_location(xpos + width - cancel_button.width() - horz_margin,
ypos + height - cancel_button.height()-14);
ok_button.set_location(xpos + width - cancel_button.width() - horz_margin
- ok_button.width() - button_padding,
ypos + height - ok_button.height()-14);
const int right_space = 100;
const int slider_left = text_right + 10;
const int slider_right = xpos + width - horz_margin - right_space;
SDL_Rect slider_rect = { slider_left,width_rect.y,slider_right-slider_left,width_rect.h};
slider_rect.y = width_rect.y;
gui::slider width_slider(disp,slider_rect);
width_slider.set_min(map_min_width);
width_slider.set_max(map_max_width);
width_slider.set_value(map_width);
slider_rect.y = height_rect.y;
gui::slider height_slider(disp,slider_rect);
height_slider.set_min(map_min_height);
height_slider.set_max(map_max_height);
height_slider.set_value(map_height);
for(bool draw = true;; draw = false) {
if(cancel_button.pressed()) {
return std::make_pair((unsigned)0, (unsigned)0);
}
if (width_slider.value() != map_width
|| height_slider.value() != map_height) {
draw = true;
}
if (draw) {
map_width = width_slider.value();
map_height = height_slider.value();
gui::draw_dialog_frame(xpos,ypos,width,height,disp);
title_rect = font::draw_text(&disp,disp.screen_area(),24,font::NORMAL_COLOUR,
"Resize Map",xpos+(width-title_rect.w)/2,ypos+10);
font::draw_text(&disp,disp.screen_area(),14,font::NORMAL_COLOUR,
width_label,width_rect.x,width_rect.y);
font::draw_text(&disp,disp.screen_area(),14,font::NORMAL_COLOUR,
height_label,height_rect.x,height_rect.y);
std::stringstream width_str;
width_str << map_width;
font::draw_text(&disp,disp.screen_area(),14,font::NORMAL_COLOUR,width_str.str(),
slider_right+horz_margin,width_rect.y);
std::stringstream height_str;
height_str << map_height;
font::draw_text(&disp,disp.screen_area(),14,font::NORMAL_COLOUR,height_str.str(),
slider_right+horz_margin,height_rect.y);
}
if (ok_button.pressed()) {
return std::make_pair((unsigned)map_width, (unsigned)map_height);
}
cancel_button.set_dirty();
ok_button.set_dirty();
width_slider.set_min(map_min_width);
height_slider.set_min(map_min_height);
events::raise_process_event();
events::raise_draw_event();
if (draw) {
update_rect(xpos,ypos,width,height);
}
disp.update_display();
SDL_Delay(20);
events::pump();
}
}

View file

@ -44,6 +44,12 @@ std::string load_map_dialog(display &disp);
/// editor.
void preferences_dialog(display &disp, config &prefs);
/// Show a dialog asking for the new size of the map. Return the chosen
/// width and height. Checks are made to see that the desired values
/// will result in a feasible map.
std::pair<unsigned, unsigned>
resize_dialog(display &disp, const unsigned curr_w, const unsigned curr_h);

View file

@ -11,6 +11,7 @@
*/
#include "../map.hpp"
#include "../config.hpp"
#include "map_manip.hpp"
@ -97,8 +98,32 @@ get_component(const gamemap &map, const gamemap::location &start_loc) {
return filled;
}
std::string resize_map(const gamemap &map, const unsigned new_w,
const unsigned new_h, const gamemap::TERRAIN fill_with) {
std::string str_map = map.write();
std::vector<std::string> lines = config::split(str_map, '\n');
bool map_changed = false;
const unsigned old_w = (unsigned)map.x();
const unsigned old_h = (unsigned)map.y();
if (old_h != new_h) {
const std::string one_row(old_w, fill_with);
lines.resize(new_h, one_row);
map_changed = true;
}
if (new_w != old_w) {
for (std::vector<std::string>::iterator it = lines.begin();
it != lines.end(); it++) {
(*it).resize(new_w, fill_with);
}
map_changed = true;
}
if (map_changed) {
return config::join(lines, '\n');
}
else {
return "";
}
}
}

View file

@ -20,6 +20,7 @@
namespace map_editor {
/// Return the tiles that are within radius from the location.
std::vector<gamemap::location> get_tiles(const gamemap &map,
const gamemap::location& a,
const unsigned int radius);
@ -33,9 +34,19 @@ typedef std::vector<std::pair<gamemap::location, gamemap::TERRAIN> > terrain_log
void flood_fill(gamemap &map, const gamemap::location &start_loc,
const gamemap::TERRAIN fill_with, terrain_log *log = NULL);
/// The the area that would be flood filled if a flood fill was requested.
/// Return the area that would be flood filled if a flood fill was
/// requested.
std::set<gamemap::location>
get_component(const gamemap &map, const gamemap::location &start_loc);
/// Return the string representation of the map after it has been
/// resized to new_w X new_h. If the new dimensions are smaller than the
/// current ones, the map will be cropped from the bottom and from the
/// right. If the map becomes larger than the current dimensions, the
/// new map area appeard at the bottom and/or the right and is filled
/// 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);
}

View file

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

View file

@ -43,7 +43,7 @@ enum HOTKEY_COMMAND { HOTKEY_CYCLE_UNITS, HOTKEY_END_UNIT_TURN, HOTKEY_LEADER,
HOTKEY_EDIT_SAVE_AS, HOTKEY_EDIT_SET_START_POS,
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_PASTE, HOTKEY_EDIT_REVERT, HOTKEY_EDIT_RESIZE,
HOTKEY_NULL };
struct hotkey_item {
@ -132,6 +132,7 @@ public:
virtual void edit_copy() {}
virtual void edit_paste() {}
virtual void edit_revert() {}
virtual void edit_resize() {}
//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 ""; }