editor2 MDI feature - have more than one map open in the editor...

...with fast switching between them. Can be disabled in the editor
settings. Also changed:

* the display class now holds a pointer to the map instead of a
  reference, a pointer can be changed which permits the entire MDI
  behavior. Related bits were also changed in terrain_builder.

* mouse_handler_base no longer holds a reference to the map

* the map labels class does not hold a gamemap reference, as it can
  use the display object to access the map. Also clearing all labels
  was exposed as a public member function.

* used scoped_ptrs and forward declarations to avoid having to include
  map_label.hpp and terrain_builder.hpp in display.hpp, this reduces
  build dependencies quite a bit.

* made get_action_state use the menu index to allow a dynamic menu to
  have checkboxes. This entire chunk of code needs a rewrite.
This commit is contained in:
Tomasz Śniatowski 2008-11-21 15:42:34 +01:00
parent 9b65061bd2
commit 1589d8713c
36 changed files with 463 additions and 195 deletions

View file

@ -32,6 +32,8 @@ Version 1.5.5+svn:
This fixes an issue with some window managers grabbing the event.
* Added basic mask applying feature
* Added basic mask creation ("diff") feature
* New multiple document interface, allows more than one map to be open at the
same time. Experimental, can be turned off in the editor settings dialog.
* Graphics:
* New or updated unit frames: Troll Shaman, Naga Fighter.
* New idle animations: Deathblade, Orcish Assassin.

View file

@ -189,7 +189,29 @@
[/row]
[/grid]
[/column]
[/row]
[/row]
[row]
grow_factor = 0
[column]
grow_factor = 1
horizontal_grow = "true"
[grid]
[row]
grow_factor = 0
[column]
border = "all"
border_size = 5
horizontal_alignment = "right"
[toggle_button]
id = "use_mdi"
definition = "default"
label = _ "Allow more than one map to be open at the same time (MDI)"
[/toggle_button]
[/column]
[/row]
[/grid]
[/column]
[/row]
[row]
grow_factor = 0
[column]

View file

@ -119,7 +119,7 @@
id=menu-editor-file
title= _ "File"
image=lite
items=editor-map-new,editor-map-load,editor-map-revert,editor-map-save,editor-map-save-as,preferences,editor-settings,quit,editor-quit-to-desktop
items=editor-map-new,editor-map-load,editor-map-revert,editor-map-save,editor-map-save-as,preferences,editor-settings,editor-close-map,quit,editor-quit-to-desktop
ref=top-panel
rect="=+3,=+1,+100,=-4"
xanchor=fixed
@ -145,6 +145,16 @@
xanchor=fixed
yanchor=fixed
[/menu]
[menu]
id=menu-editor-window
title= _ "Window"
image=lite
items=editor-switch-map
rect="+2,=,+100,="
xanchor=fixed
yanchor=fixed
[/menu]
[menu]
id=menu-editor-selection
@ -240,7 +250,7 @@
[panel]
id=villages-panel
image=themes/status-bg.png
ref=menu-editor-map
ref=menu-editor-window
rect="+5,=+1,+71,+19"
xanchor=fixed
yanchor=fixed

View file

@ -46,6 +46,8 @@ Version 1.5.5+svn:
* changed the base-terrain key modifier to shift from alt.
* Added basic mask applying feature
* Added basic mask creation ("diff") feature
* New multiple document interface, allows more than one map to be open at the
same time. Experimental, can be turned off in the editor settings dialog.
* Graphics
* New or updated unit frames: Troll Shaman, Naga Fighter.

View file

@ -24,6 +24,7 @@
#include "hotkeys.hpp"
#include "log.hpp"
#include "map.hpp"
#include "map_label.hpp"
#include "menu_events.hpp"
#include "mouse_handler_base.hpp"
#include "replay.hpp"

View file

@ -111,7 +111,7 @@ void terrain_builder::tile::clear()
void terrain_builder::tilemap::reset()
{
for(std::vector<tile>::iterator it = map_.begin(); it != map_.end(); ++it)
for(std::vector<tile>::iterator it = tiles_.begin(); it != tiles_.end(); ++it)
it->clear();
}
@ -119,7 +119,7 @@ void terrain_builder::tilemap::reload(int x, int y)
{
x_ = x;
y_ = y;
map_.resize((x + 4) * (y + 4));
tiles_.resize((x + 4) * (y + 4));
}
bool terrain_builder::tilemap::on_map(const map_location &loc) const
@ -136,20 +136,20 @@ terrain_builder::tile& terrain_builder::tilemap::operator[](const map_location &
{
assert(on_map(loc));
return map_[(loc.x + 2) + (loc.y + 2) * (x_ + 4)];
return tiles_[(loc.x + 2) + (loc.y + 2) * (x_ + 4)];
}
const terrain_builder::tile& terrain_builder::tilemap::operator[] (const map_location &loc) const
{
assert(on_map(loc));
return map_[(loc.x + 2) + (loc.y + 2) * (x_ + 4)];
return tiles_[(loc.x + 2) + (loc.y + 2) * (x_ + 4)];
}
terrain_builder::terrain_builder(const config& cfg, const config& level,
const gamemap& map, const std::string& offmap_image) :
map_(map),
tile_map_(map.w(), map.h()),
const gamemap* m, const std::string& offmap_image) :
map_(m),
tile_map_(map().w(), map().h()),
terrain_by_type_(),
building_rules_()
{
@ -168,11 +168,17 @@ terrain_builder::terrain_builder(const config& cfg, const config& level,
void terrain_builder::reload_map()
{
tile_map_.reload(map_.w(), map_.h());
tile_map_.reload(map().w(), map().h());
terrain_by_type_.clear();
build_terrains();
}
void terrain_builder::change_map(const gamemap* m)
{
map_ = m;
reload_map();
}
const terrain_builder::imagelist *terrain_builder::get_terrain_at(const map_location &loc,
const std::string &tod, const ADJACENT_TERRAIN_TYPE terrain_type)
{
@ -234,16 +240,16 @@ void terrain_builder::rebuild_terrain(const map_location &loc)
btile.images_foreground.clear();
btile.images_background.clear();
const std::string filename =
map_.get_terrain_info(map_.get_terrain(loc)).minimap_image();
map().get_terrain_info(map().get_terrain(loc)).minimap_image();
animated<image::locator> img_loc;
img_loc.add_frame(100,image::locator("terrain/" + filename + ".png"));
img_loc.start_animation(0, true);
btile.images_background.push_back(img_loc);
//Combine base and overlay image if neccessary
if(map_.get_terrain_info(map_.get_terrain(loc)).is_combined()) {
if(map().get_terrain_info(map().get_terrain(loc)).is_combined()) {
const std::string filename_ovl =
map_.get_terrain_info(map_.get_terrain(loc)).minimap_image_overlay();
map().get_terrain_info(map().get_terrain(loc)).minimap_image_overlay();
animated<image::locator> img_loc_ovl;
img_loc_ovl.add_frame(100,image::locator("terrain/" + filename_ovl + ".png"));
img_loc_ovl.start_animation(0, true);
@ -872,11 +878,11 @@ bool terrain_builder::rule_matches(const terrain_builder::building_rule &rule,
return false;
}
//std::cout << "testing..." << builder_letter(map_.get_terrain(tloc))
//std::cout << "testing..." << builder_letter(map().get_terrain(tloc))
// check if terrain matches except if we already know that it does
if(cons != type_checked &&
!terrain_matches(map_.get_terrain(tloc), cons->second.terrain_types_match)) {
!terrain_matches(map().get_terrain(tloc), cons->second.terrain_types_match)) {
return false;
}
@ -937,10 +943,10 @@ void terrain_builder::build_terrains()
log_scope("terrain_builder::build_terrains");
// Builds the terrain_by_type_ cache
for(int x = -2; x <= map_.w(); ++x) {
for(int y = -2; y <= map_.h(); ++y) {
for(int x = -2; x <= map().w(); ++x) {
for(int y = -2; y <= map().h(); ++y) {
const map_location loc(x,y);
const t_translation::t_terrain t = map_.get_terrain(loc);
const t_translation::t_terrain t = map().get_terrain(loc);
terrain_by_type_[t].push_back(loc);
}

View file

@ -75,13 +75,17 @@ public:
* and '.png' suffix
*/
terrain_builder(const config& cfg, const config &level,
const gamemap& map, const std::string& offmap_image);
const gamemap* map, const std::string& offmap_image);
const gamemap& map() const { return *map_; }
/**
* Updates internals that cache map size. This should be called when the map
* size has changed.
*/
void reload_map();
void change_map(const gamemap* m);
/** Returns a vector of strings representing the images to load & blit
* together to get the built content for this tile.
@ -360,7 +364,7 @@ private:
* Constructs a tilemap of dimensions x * y
*/
tilemap(int x, int y) :
map_((x + 4) * (y + 4)),
tiles_((x + 4) * (y + 4)),
x_(x),
y_(y)
{}
@ -400,7 +404,7 @@ private:
void reload(int x, int y);
private:
/** The map */
std::vector<tile> map_;
std::vector<tile> tiles_;
/** The x dimension of the map */
int x_;
/** The y dimension of the map */
@ -716,9 +720,10 @@ private:
void build_terrains();
/**
* A reference to the gamemap class used in the current level.
* A pointer to the gamemap class used in the current level.
*/
const gamemap& map_;
const gamemap* map_;
/**
* The tile_map_ for the current level, which is filled by the
* build_terrains_ method to contain "tiles" representing images

View file

@ -20,6 +20,7 @@
#include "global.hpp"
#include "actions.hpp"
#include "builder.hpp"
#include "cursor.hpp"
#include "display.hpp"
#include "events.hpp"
@ -33,6 +34,7 @@
#include "log.hpp"
#include "marked-up_text.hpp"
#include "map.hpp"
#include "map_label.hpp"
#include "minimap.hpp"
#include "pathfind.hpp"
#include "preferences.hpp"
@ -73,7 +75,7 @@ namespace {
bool benchmark = false;
}
display::display(CVideo& video, const gamemap& map, const config& theme_cfg, const config& cfg, const config& level) :
display::display(CVideo& video, const gamemap* map, const config& theme_cfg, const config& cfg, const config& level) :
screen_(video),
map_(map),
viewpoint_(NULL),
@ -82,7 +84,7 @@ display::display(CVideo& video, const gamemap& map, const config& theme_cfg, con
theme_(theme_cfg, screen_area()),
zoom_(DefaultZoom),
last_zoom_(SmallZoom),
builder_(cfg, level, map, theme_.border().tile_image),
builder_(new terrain_builder(cfg, level, map, theme_.border().tile_image)),
minimap_(NULL),
minimap_location_(empty_rect),
redrawMinimap_(false),
@ -94,9 +96,9 @@ display::display(CVideo& video, const gamemap& map, const config& theme_cfg, con
turbo_speed_(2),
turbo_(false),
invalidateGameStatus_(true),
map_labels_(*this,map, 0),
shroud_image_("terrain/" + map_.get_terrain_info(t_translation::VOID_TERRAIN).minimap_image() + ".png"),
fog_image_("terrain/" + map_.get_terrain_info(t_translation::FOGGED).minimap_image() + ".png"),
map_labels_(new map_labels(*this, 0)),
shroud_image_("terrain/" + get_map().get_terrain_info(t_translation::VOID_TERRAIN).minimap_image() + ".png"),
fog_image_("terrain/" + get_map().get_terrain_info(t_translation::FOGGED).minimap_image() + ".png"),
tod_(time_of_day()),
_scroll_event("scrolled"),
nextDraw_(0),
@ -141,9 +143,20 @@ display::~display()
{
}
void display::rebuild_all()
{
builder_->rebuild_all();
}
void display::reload_map()
{
builder_.reload_map();
builder_->reload_map();
}
void display::change_map(const gamemap* m)
{
map_ = m;
builder_->change_map(m);
}
const SDL_Rect& display::max_map_area() const
@ -157,8 +170,8 @@ const SDL_Rect& display::max_map_area() const
// To display a hex fully on screen,
// a little bit extra space is needed.
// Also added the border two times.
max_area.w = static_cast<int>((map_.w() + 2 * theme_.border().size + 1.0/3.0) * hex_width());
max_area.h = static_cast<int>((map_.h() + 2 * theme_.border().size + 0.5) * hex_size());
max_area.w = static_cast<int>((get_map().w() + 2 * theme_.border().size + 1.0/3.0) * hex_width());
max_area.h = static_cast<int>((get_map().h() + 2 * theme_.border().size + 0.5) * hex_size());
return max_area;
}
@ -418,19 +431,19 @@ map_location display::minimap_location_on(int x, int y)
// probably more adjustements to do (border, minimap shift...)
// but the mouse and human capacity to evaluate the rectangle center
// is not pixel precise.
int px = (x - minimap_location_.x) * map_.w()*hex_width() / minimap_location_.w;
int py = (y - minimap_location_.y) * map_.h()*hex_size() / minimap_location_.h;
int px = (x - minimap_location_.x) * get_map().w()*hex_width() / minimap_location_.w;
int py = (y - minimap_location_.y) * get_map().h()*hex_size() / minimap_location_.h;
map_location loc = pixel_position_to_hex(px, py);
if (loc.x < 0)
loc.x = 0;
else if (loc.x >= map_.w())
loc.x = map_.w() - 1;
else if (loc.x >= get_map().w())
loc.x = get_map().w() - 1;
if (loc.y < 0)
loc.y = 0;
else if (loc.y >= map_.h())
loc.y = map_.h() - 1;
else if (loc.y >= get_map().h())
loc.y = get_map().h() - 1;
return loc;
}
@ -443,7 +456,7 @@ int display::screenshot(std::string filename, bool map_screenshot)
SDL_SaveBMP(screenshot_surf, filename.c_str());
size = screenshot_surf->w * screenshot_surf->h;
} else {
if (map_.empty()) {
if (get_map().empty()) {
// Map Screenshot are big, abort and warn the user if he does strange things
std::cerr << "No map, can't do a Map Screenshot. If it was not wanted, check your hotkey.\n";
return -1;
@ -590,7 +603,7 @@ std::vector<std::string> display::get_fog_shroud_graphics(const map_location& lo
// stream << "void";
//else
// stream << "fog";
stream << "terrain/" << map_.get_terrain_info(*terrain).minimap_image();
stream << "terrain/" << get_map().get_terrain_info(*terrain).minimap_image();
for(int n = 0; *terrain == tiles[i] && n != 6; i = (i+1)%6, ++n) {
stream << get_direction(i);
@ -647,7 +660,7 @@ std::vector<surface> display::get_terrain_images(const map_location &loc,
terrain_builder::ADJACENT_TERRAIN_TYPE builder_terrain_type =
(terrain_type == ADJACENT_FOREGROUND ?
terrain_builder::ADJACENT_FOREGROUND : terrain_builder::ADJACENT_BACKGROUND);
const terrain_builder::imagelist* const terrains = builder_.get_terrain_at(loc,
const terrain_builder::imagelist* const terrains = builder_->get_terrain_at(loc,
timeid, builder_terrain_type);
if(terrains != NULL) {
@ -1081,7 +1094,7 @@ bool display::draw_init()
{
bool changed = false;
if (map_.empty()) {
if (get_map().empty()) {
return changed;
}
@ -1251,7 +1264,7 @@ void display::draw_border(const map_location& loc, const int xpos, const int ypo
if(loc.x == -1 && loc.y == -1) { // top left corner
drawing_buffer_add(LAYER_BORDER, drawing_order, tblit(xpos + zoom_/4, ypos,
image::get_image(theme_.border().corner_image_top_left, image::SCALED_TO_ZOOM)));
} else if(loc.x == map_.w() && loc.y == -1) { // top right corner
} else if(loc.x == get_map().w() && loc.y == -1) { // top right corner
// We use the map idea of odd and even, and map coords are internal coords + 1
if(loc.x%2 == 0) {
drawing_buffer_add(LAYER_BORDER, drawing_order, tblit(xpos, ypos + zoom_/2,
@ -1260,11 +1273,11 @@ void display::draw_border(const map_location& loc, const int xpos, const int ypo
drawing_buffer_add(LAYER_BORDER, drawing_order, tblit(xpos, ypos,
image::get_image(theme_.border().corner_image_top_right_even, image::SCALED_TO_ZOOM)));
}
} else if(loc.x == -1 && loc.y == map_.h()) { // bottom left corner
} else if(loc.x == -1 && loc.y == get_map().h()) { // bottom left corner
drawing_buffer_add(LAYER_BORDER, drawing_order, tblit(xpos + zoom_/4, ypos,
image::get_image(theme_.border().corner_image_bottom_left, image::SCALED_TO_ZOOM)));
} else if(loc.x == map_.w() && loc.y == map_.h()) { // bottom right corner
} else if(loc.x == get_map().w() && loc.y == get_map().h()) { // bottom right corner
// We use the map idea of odd and even, and map coords are internal coords + 1
if(loc.x%2 == 1) {
drawing_buffer_add(LAYER_BORDER, drawing_order, tblit(xpos, ypos,
@ -1278,7 +1291,7 @@ void display::draw_border(const map_location& loc, const int xpos, const int ypo
} else if(loc.x == -1) { // left side
drawing_buffer_add(LAYER_BORDER, drawing_order, tblit(xpos + zoom_/4, ypos,
image::get_image(theme_.border().border_image_left, image::SCALED_TO_ZOOM)));
} else if(loc.x == map_.w()) { // right side
} else if(loc.x == get_map().w()) { // right side
drawing_buffer_add(LAYER_BORDER, drawing_order, tblit(xpos + zoom_/4, ypos,
image::get_image(theme_.border().border_image_right, image::SCALED_TO_ZOOM)));
} else if(loc.y == -1) { // top side
@ -1290,7 +1303,7 @@ void display::draw_border(const map_location& loc, const int xpos, const int ypo
drawing_buffer_add(LAYER_BORDER, drawing_order, tblit(xpos, ypos + zoom_/2,
image::get_image(theme_.border().border_image_top_odd, image::SCALED_TO_ZOOM)));
}
} else if(loc.y == map_.h()) { // bottom side
} else if(loc.y == get_map().h()) { // bottom side
// We use the map idea of odd and even, and map coords are internal coords + 1
if(loc.x%2 == 1) {
drawing_buffer_add(LAYER_BORDER, drawing_order, tblit(xpos, ypos,
@ -1306,7 +1319,7 @@ void display::draw_minimap()
{
const SDL_Rect& area = minimap_area();
if(minimap_ == NULL || minimap_->w > area.w || minimap_->h > area.h) {
minimap_ = image::getMinimap(area.w, area.h, map_, viewpoint_);
minimap_ = image::getMinimap(area.w, area.h, get_map(), viewpoint_);
if(minimap_ == NULL) {
return;
}
@ -1328,8 +1341,8 @@ void display::draw_minimap()
// calculate the visible portion of the map:
// scaling between minimap and full map images
double xscaling = 1.0*minimap_->w / (map_.w()*hex_width());
double yscaling = 1.0*minimap_->h / (map_.h()*hex_size());
double xscaling = 1.0*minimap_->w / (get_map().w()*hex_width());
double yscaling = 1.0*minimap_->h / (get_map().h()*hex_size());
// we need to shift with the border size
// and the 0.25 from the minimap balanced drawing
@ -1366,7 +1379,7 @@ void display::scroll(int xmove, int ymove)
if(dx == 0 && dy == 0)
return;
map_labels_.scroll(dx, dy);
labels().scroll(dx, dy);
font::scroll_floating_labels(dx, dy);
surface screen(screen_.getSurface());
@ -1421,7 +1434,7 @@ void display::set_zoom(int amount)
bounds_check_position();
image::set_zoom(zoom_);
map_labels_.recalculate_labels();
labels().recalculate_labels();
redraw_background_ = true;
invalidate_all();
@ -1534,7 +1547,7 @@ void display::scroll_to_xy(int screenxpos, int screenypos, SCROLL_TYPE scroll_ty
void display::scroll_to_tile(const map_location& loc, SCROLL_TYPE scroll_type, bool check_fogged)
{
if(map_.on_board(loc) == false) {
if(get_map().on_board(loc) == false) {
ERR_DP << "Tile at " << loc << " isn't on the map, can't scroll to the tile.\n";
return;
}
@ -1567,7 +1580,7 @@ void display::scroll_to_tiles(const std::vector<map_location>& locs,
bool first_tile_on_screen = false;
for(std::vector<map_location>::const_iterator itor = locs.begin(); itor != locs.end() ; itor++) {
if(map_.on_board(*itor) == false) continue;
if(get_map().on_board(*itor) == false) continue;
if(check_fogged && fogged(*itor)) continue;
int x = get_location_x(*itor);
@ -1711,8 +1724,8 @@ void display::bounds_check_position(int& xpos, int& ypos)
const int tile_width = hex_width();
// Adjust for the border 2 times
const int xend = static_cast<int>(tile_width * (map_.w() + 2 * theme_.border().size) + tile_width/3);
const int yend = static_cast<int>(zoom_ * (map_.h() + 2 * theme_.border().size) + zoom_/2);
const int xend = static_cast<int>(tile_width * (get_map().w() + 2 * theme_.border().size) + tile_width/3);
const int yend = static_cast<int>(zoom_ * (get_map().h() + 2 * theme_.border().size) + zoom_/2);
if(xpos > xend - map_area().w) {
xpos = xend - map_area().w;
@ -1775,7 +1788,7 @@ void display::redraw_everything()
panelsDrawn_ = false;
map_labels_.recalculate_labels();
labels().recalculate_labels();
redraw_background_ = true;
@ -1811,7 +1824,7 @@ void display::draw(bool update,bool force) {
invalidate_animations();
pre_draw();
update_time_of_day();
if(!map_.empty()) {
if(!get_map().empty()) {
//int simulate_delay = 0;
if(!invalidated_.empty()) {
changed = true;
@ -1829,6 +1842,16 @@ void display::draw(bool update,bool force) {
draw_wrap(update, force, changed);
}
map_labels& display::labels()
{
return *map_labels_;
}
const map_labels& display::labels() const
{
return *map_labels_;
}
void display::clear_screen()
{
surface const disp(screen_.getSurface());
@ -1849,8 +1872,8 @@ void display::draw_invalidated() {
foreach (map_location loc, invalidated_) {
int xpos = get_location_x(loc);
int ypos = get_location_y(loc);
const bool on_map = map_.on_board(loc);
const bool off_map_tile = (map_.get_terrain(loc) == t_translation::OFF_MAP_USER);
const bool on_map = get_map().on_board(loc);
const bool off_map_tile = (get_map().get_terrain(loc) == t_translation::OFF_MAP_USER);
SDL_Rect hex_rect = {xpos, ypos, zoom_, zoom_};
if(!rects_overlap(hex_rect,clip_rect)) {
continue;
@ -1868,8 +1891,8 @@ void display::draw_hex(const map_location& loc) {
int ypos = get_location_y(loc);
int drawing_order = loc.get_drawing_order();
image::TYPE image_type = get_image_type(loc);
const bool on_map = map_.on_board(loc);
const bool off_map_tile = (map_.get_terrain(loc) == t_translation::OFF_MAP_USER);
const bool on_map = get_map().on_board(loc);
const bool off_map_tile = (get_map().get_terrain(loc) == t_translation::OFF_MAP_USER);
if(!shrouded(loc)) {
// unshrouded terrain (the normal case)
drawing_buffer_add(LAYER_TERRAIN_BG, drawing_order, tblit(xpos, ypos,
@ -1901,7 +1924,7 @@ void display::draw_hex(const map_location& loc) {
if(loc == selectedHex_ && on_map && selected_hex_overlay_ != NULL) {
drawing_buffer_add(LAYER_TERRAIN_TMP_BG, drawing_order, tblit(xpos, ypos, selected_hex_overlay_));
}
if(loc == mouseoverHex_ && (on_map || (in_editor() && map_.on_board_with_border(loc))) && mouseover_hex_overlay_ != NULL) {
if(loc == mouseoverHex_ && (on_map || (in_editor() && get_map().on_board_with_border(loc))) && mouseover_hex_overlay_ != NULL) {
drawing_buffer_add(LAYER_TERRAIN_TMP_BG, drawing_order, tblit(xpos, ypos, mouseover_hex_overlay_));
}
@ -1940,7 +1963,7 @@ void display::draw_hex(const map_location& loc) {
if (draw_terrain_codes_ && (game_config::debug || !shrouded(loc))) {
int off_x = xpos + hex_size()/2;
int off_y = ypos + hex_size()/2;
surface text = font::get_rendered_text(lexical_cast<std::string>(map_.get_terrain(loc)), font::SIZE_SMALL, font::NORMAL_COLOUR);
surface text = font::get_rendered_text(lexical_cast<std::string>(get_map().get_terrain(loc)), font::SIZE_SMALL, font::NORMAL_COLOUR);
surface bg = create_neutral_surface(text->w, text->h);
SDL_Rect bg_rect = {0, 0, text->w, text->h};
SDL_FillRect(bg, &bg_rect, 0xaa000000);
@ -2226,7 +2249,7 @@ void display::invalidate_animations() {
rect_of_hexes::iterator i = hexes.begin(), end = hexes.end();
for (;i != end; ++i) {
if (!shrouded(*i)) {
if (builder_.update_animation(*i)) {
if (builder_->update_animation(*i)) {
invalidate(*i);
} else {
invalidate_animations_location(*i);

View file

@ -38,13 +38,14 @@ class gamestatus;
class team;
class unit;
class unit_map;
class terrain_builder;
class map_labels;
#include "builder.hpp"
#include "generic_event.hpp"
#include "image.hpp"
#include "font.hpp"
#include "key.hpp"
#include "map_location.hpp"
#include "map_label.hpp"
#include "reports.hpp"
#include "time_of_day.hpp"
#include "theme.hpp"
@ -58,12 +59,13 @@ class unit_map;
#include <string>
#include <boost/function.hpp>
#include <boost/scoped_ptr.hpp>
class display
{
public:
display(CVideo& video, const gamemap& map, const config& theme_cfg,
display(CVideo& video, const gamemap* map, const config& theme_cfg,
const config& cfg, const config& level);
virtual ~display();
@ -72,7 +74,9 @@ public:
* size has changed.
*/
void reload_map();
void change_map(const gamemap* m);
static Uint32 rgb(Uint8 red, Uint8 green, Uint8 blue)
{ return 0xFF000000 | (red << 16) | (green << 8) | blue; }
@ -282,7 +286,7 @@ public:
*/
virtual void invalidate_animations_location(const map_location& /*loc*/) {}
const gamemap& get_map()const { return map_;}
const gamemap& get_map()const { return *map_; }
/**
* The last action in drawing a tile is adding the overlays.
@ -329,7 +333,7 @@ public:
void update_display();
/** Rebuild all dynamic terrain. */
void rebuild_all() { builder_.rebuild_all(); }
void rebuild_all();
const theme::menu* menu_pressed();
@ -434,8 +438,8 @@ public:
*/
void draw(bool update=true, bool force=false);
map_labels& labels() { return map_labels_; }
const map_labels& labels() const { return map_labels_; }
map_labels& labels();
const map_labels& labels() const;
/** Announce a message prominently. */
void announce(const std::string msg,
@ -545,13 +549,13 @@ protected:
void scroll_to_xy(int screenxpos, int screenypos, SCROLL_TYPE scroll_type);
CVideo& screen_;
const gamemap& map_;
const gamemap* map_;
const viewpoint *viewpoint_;
int xpos_, ypos_;
theme theme_;
int zoom_;
int last_zoom_;
terrain_builder builder_;
boost::scoped_ptr<terrain_builder> builder_;
surface minimap_;
SDL_Rect minimap_location_;
bool redrawMinimap_;
@ -563,7 +567,7 @@ protected:
double turbo_speed_;
bool turbo_;
bool invalidateGameStatus_;
map_labels map_labels_;
boost::scoped_ptr<map_labels> map_labels_;
std::string shroud_image_;
std::string fog_image_;
time_of_day tod_;

View file

@ -37,16 +37,42 @@
namespace {
const char* prefkey_default_dir = "editor2_default_dir";
const char* prefkey_auto_update_transitions = "editor2_auto_update_transitions";
const char* prefkey_use_mdi = "editor2_use_mdi";
}
namespace editor2 {
/**
* Utility class to properly refresh the display when the map context object is replaced
* without duplicating code.
*/
class map_context_refresher
{
public:
map_context_refresher(editor_controller& ec, const map_context& other_mc)
: ec_(ec), size_changed_(!ec.get_map().same_size_as(other_mc.get_map())), refreshed_(false)
{
}
~map_context_refresher() {
if (!refreshed_) refresh();
}
void refresh() {
ec_.gui().change_map(&ec_.get_map());
ec_.reload_map();
}
private:
editor_controller& ec_;
bool size_changed_;
bool refreshed_;
};
editor_controller::editor_controller(const config &game_config, CVideo& video, map_context* init_map_context /*=NULL*/)
: controller_base(SDL_GetTicks(), game_config, video)
, mouse_handler_base(get_map())
, mouse_handler_base()
, rng_(NULL)
, rng_setter_(NULL)
, map_context_(NULL)
, map_contexts_()
, current_context_index_(0)
, gui_(NULL)
, map_generators_()
, tods_()
@ -68,12 +94,13 @@ editor_controller::editor_controller(const config &game_config, CVideo& video, m
, background_terrain_(t_translation::GRASS_LAND)
, clipboard_()
, auto_update_transitions_(utils::string_bool(preferences::get(prefkey_auto_update_transitions), true))
, use_mdi_(utils::string_bool(preferences::get(prefkey_use_mdi), true))
, default_dir_(preferences::get(prefkey_default_dir))
{
if (init_map_context == NULL) {
map_context_ = new map_context(editor_map(game_config, 44, 33, t_translation::GRASS_LAND));
create_default_context();
} else {
map_context_ = init_map_context;
add_map_context(init_map_context);
}
if (default_dir_.empty()) {
default_dir_ = get_dir(get_dir(get_user_data_dir() + "/editor") + "/maps");
@ -207,7 +234,9 @@ editor_controller::~editor_controller()
delete prefs_disp_manager_;
delete rng_setter_;
delete rng_;
delete map_context_;
foreach (map_context* mc, map_contexts_) {
delete mc;
}
}
EXIT_STATUS editor_controller::main_loop()
@ -225,10 +254,26 @@ EXIT_STATUS editor_controller::main_loop()
void editor_controller::quit_confirm(EXIT_STATUS mode)
{
std::string message = _("Do you really want to quit?");
if (get_map_context().modified()) {
message += " ";
message += _("There are unsaved changes in the map.");
std::vector<std::string> modified;
foreach (map_context* mc, map_contexts_) {
if (mc->modified()) {
if (!mc->get_filename().empty()) {
modified.push_back(mc->get_filename());
} else {
modified.push_back(_("(New Map)"));
}
}
}
std::string message;
if (modified.empty()) {
message = _("Do you really want to quit?");
} else if (modified.size() == 1) {
message = _("Do you really want to quit? Changes in the map since the last save will be lost.");
} else {
message = _("Do you really want to quit? The following maps were modified and all changes since the last save will be lost:");
foreach (std::string& str, modified) {
message += "\n" + str;
}
}
int res = gui::dialog(gui(),_("Quit"),message,gui::YES_NO).show();
if (res == 0) {
@ -237,10 +282,55 @@ void editor_controller::quit_confirm(EXIT_STATUS mode)
}
}
int editor_controller::add_map_context(map_context* mc)
{
map_contexts_.push_back(mc);
return map_contexts_.size() - 1;
}
void editor_controller::create_default_context()
{
map_context* mc = new map_context(editor_map(game_config_, 44, 33, t_translation::GRASS_LAND));
add_map_context(mc);
}
void editor_controller::close_current_context()
{
if (!confirm_discard()) return;
map_context* current = map_contexts_[current_context_index_];
if (map_contexts_.size() == 1) {
create_default_context();
map_contexts_.erase(map_contexts_.begin());
} else if (current_context_index_ == map_contexts_.size() - 1) {
map_contexts_.pop_back();
current_context_index_--;
} else {
map_contexts_.erase(map_contexts_.begin() + current_context_index_);
}
map_context_refresher(*this, *current);
delete current;
}
void editor_controller::switch_context(int index)
{
if (index < 0 || index >= map_contexts_.size()) {
WRN_ED << "Invalid index in switch map context: " << index << "\n";
return;
}
map_context_refresher mcr(*this, *map_contexts_[index]);
current_context_index_ = index;
}
void editor_controller::replace_map_context(const map_context& new_mc)
{
map_context_refresher mcr(*this, new_mc);
get_map_context() = new_mc;
}
void editor_controller::editor_settings_dialog()
{
if (tods_.empty()) {
gui::message_dialog(gui(), _("Error"), _("No editor time-of-day found")).show();
gui::message_dialog(gui(), _("Error"), _("No editor time-of-day found.")).show();
return;
}
@ -249,6 +339,7 @@ void editor_controller::editor_settings_dialog()
dialog.set_current_adjustment(preferences::editor_r(), preferences::editor_g(), preferences::editor_b());
dialog.set_redraw_callback(boost::bind(&editor_controller::editor_settings_dialog_redraw_callback, this, _1, _2, _3));
image::colour_adjustment_resetter adjust_resetter;
dialog.set_use_mdi(use_mdi_);
dialog.show(gui().video());
int res = dialog.get_retval();
@ -257,6 +348,8 @@ void editor_controller::editor_settings_dialog()
preferences::set_editor_r(dialog.get_red());
preferences::set_editor_g(dialog.get_green());
preferences::set_editor_b(dialog.get_blue());
use_mdi_ = dialog.get_use_mdi();
preferences::set(prefkey_use_mdi, lexical_cast<std::string>(use_mdi_));
} else {
adjust_resetter.reset();
}
@ -282,20 +375,20 @@ bool editor_controller::confirm_discard()
void editor_controller::load_map_dialog()
{
if (!confirm_discard()) return;
if (!use_mdi_ && !confirm_discard()) return;
std::string fn = get_map_context().get_filename();
if (fn.empty()) {
fn = default_dir_;
}
int res = dialogs::show_file_chooser_dialog(gui(), fn, _("Choose a Map to Load"));
if (res == 0) {
load_map(fn);
load_map(fn, use_mdi_);
}
}
void editor_controller::new_map_dialog()
{
if (!confirm_discard()) return;
if (!use_mdi_ && !confirm_discard()) return;
gui2::teditor_new_map dialog;
dialog.set_map_width(get_map().w());
dialog.set_map_height(get_map().h());
@ -306,7 +399,7 @@ void editor_controller::new_map_dialog()
int w = dialog.map_width();
int h = dialog.map_height();
t_translation::t_terrain fill = t_translation::GRASS_LAND;
new_map(w, h, fill);
new_map(w, h, fill, use_mdi_);
}
}
@ -342,7 +435,7 @@ void editor_controller::save_map_as_dialog()
void editor_controller::generate_map_dialog()
{
if (map_generators_.empty()) {
gui::message_dialog(gui(), _("Error"), _("No random map generators found")).show();
gui::message_dialog(gui(), _("Error"), _("No random map generators found.")).show();
return;
}
gui2::teditor_generate_map dialog;
@ -498,12 +591,16 @@ bool editor_controller::save_map(bool display_confirmation)
return true;
}
void editor_controller::load_map(const std::string& filename)
void editor_controller::load_map(const std::string& filename, bool new_context)
{
try {
get_map_context().load_map(game_config_, filename);
get_map_context().clear_undo_redo();
refresh_after_action();
if (new_context) {
std::auto_ptr<map_context> mc(new map_context(game_config_, filename));
int new_id = add_map_context(mc.release());
switch_context(new_id);
} else {
replace_map_context(map_context(game_config_, filename));
}
} catch (editor_map_load_exception& e) {
gui::message_dialog(gui(), _("Error loading map"), e.what()).show();
return;
@ -518,14 +615,18 @@ void editor_controller::revert_map()
ERR_ED << "Empty filename in map revert\n";
return;
}
load_map(filename);
load_map(filename, false);
}
void editor_controller::new_map(int width, int height, t_translation::t_terrain fill)
void editor_controller::new_map(int width, int height, t_translation::t_terrain fill, bool new_context)
{
get_map_context().set_map(editor_map(game_config_, width, height, fill));
get_map_context().clear_undo_redo();
refresh_after_action();
editor_map m(game_config_, width, height, fill);
if (new_context) {
int new_id = add_map_context(new map_context(m));
switch_context(new_id);
} else {
replace_map_context(map_context(m));
}
}
void editor_controller::reload_map()
@ -577,10 +678,19 @@ void editor_controller::refresh_after_action(bool drag_part)
gui().recalculate_minimap();
}
bool editor_controller::can_execute_command(hotkey::HOTKEY_COMMAND command, int /*index*/) const
bool editor_controller::can_execute_command(hotkey::HOTKEY_COMMAND command, int index) const
{
using namespace hotkey; //reduce hotkey:: clutter
switch (command) {
case HOTKEY_NULL:
if (index >= 0) {
unsigned i = static_cast<unsigned>(index);
if (i < map_contexts_.size()) {
return true;
}
}
return false;
case HOTKEY_ZOOM_IN:
case HOTKEY_ZOOM_OUT:
case HOTKEY_ZOOM_DEFAULT:
@ -610,6 +720,8 @@ bool editor_controller::can_execute_command(hotkey::HOTKEY_COMMAND command, int
case HOTKEY_EDITOR_TERRAIN_PALETTE_SWAP:
return true; //editor hotkeys we can always do
case HOTKEY_EDITOR_MAP_SAVE:
case HOTKEY_EDITOR_SWITCH_MAP:
case HOTKEY_EDITOR_CLOSE_MAP:
return true;
case HOTKEY_EDITOR_MAP_REVERT:
return !get_map_context().get_filename().empty();
@ -657,7 +769,7 @@ bool editor_controller::can_execute_command(hotkey::HOTKEY_COMMAND command, int
}
}
hotkey::ACTION_STATE editor_controller::get_action_state(hotkey::HOTKEY_COMMAND command) const {
hotkey::ACTION_STATE editor_controller::get_action_state(hotkey::HOTKEY_COMMAND command, int index) const {
using namespace hotkey;
switch (command) {
case HOTKEY_EDITOR_TOOL_PAINT:
@ -671,8 +783,10 @@ hotkey::ACTION_STATE editor_controller::get_action_state(hotkey::HOTKEY_COMMAND
return gui_->get_draw_coordinates() ? ACTION_ON : ACTION_OFF;
case HOTKEY_EDITOR_DRAW_TERRAIN_CODES:
return gui_->get_draw_terrain_codes() ? ACTION_ON : ACTION_OFF;
case HOTKEY_NULL:
return index == current_context_index_ ? ACTION_ON : ACTION_OFF;
default:
return command_executor::get_action_state(command);
return command_executor::get_action_state(command, index);
}
}
@ -681,6 +795,15 @@ bool editor_controller::execute_command(hotkey::HOTKEY_COMMAND command, int inde
SCOPE_ED;
using namespace hotkey;
switch (command) {
case HOTKEY_NULL:
if (index >= 0) {
unsigned i = static_cast<unsigned>(index);
if (i < map_contexts_.size()) {
switch_context(index);
return true;
}
}
return false;
case HOTKEY_QUIT_GAME:
quit_confirm(EXIT_NORMAL);
return true;
@ -752,6 +875,9 @@ bool editor_controller::execute_command(hotkey::HOTKEY_COMMAND command, int inde
case HOTKEY_EDITOR_SELECTION_RANDOMIZE:
perform_refresh(editor_action_shuffle_area(get_map().selection()));
return true;
case HOTKEY_EDITOR_CLOSE_MAP:
close_current_context();
return true;
case HOTKEY_EDITOR_MAP_LOAD:
load_map_dialog();
return true;
@ -812,20 +938,22 @@ bool editor_controller::execute_command(hotkey::HOTKEY_COMMAND command, int inde
return false;
}
void editor_controller::expand_starting_position_menu(std::vector<std::string>& items)
void editor_controller::expand_open_maps_menu(std::vector<std::string>& items)
{
for (unsigned int i = 0; i < items.size(); ++i) {
if (items[i] == "editor-STARTING-POSITION") {
if (items[i] == "editor-switch-map") {
items.erase(items.begin() + i);
std::vector<std::string> newitems;
std::vector<std::string> newsaves;
for (int player_i = 0; player_i < gamemap::MAX_PLAYERS; ++player_i) {
//TODO gettext format
std::string name = "Set starting position for player " + lexical_cast<std::string>(player_i);
newitems.push_back(name);
std::vector<std::string> contexts;
for (int mci = 0; mci < map_contexts_.size(); ++mci) {
std::string filename = map_contexts_[mci]->get_filename();
if (filename.empty()) {
filename = _("(New Map)");
}
std::string label = "[" + lexical_cast<std::string>(mci) + "] "
+ filename;
contexts.push_back(label);
}
items.insert(items.begin()+i, newitems.begin(), newitems.end());
items.insert(items.begin() + i, contexts.begin(), contexts.end());
break;
}
}
@ -859,21 +987,18 @@ void editor_controller::show_menu(const std::vector<std::string>& items_arg, int
}
++i;
}
expand_starting_position_menu(items);
controller_base::show_menu(items, xloc, yloc, context_menu);
expand_open_maps_menu(items);
command_executor::show_menu(items, xloc, yloc, context_menu, gui());
}
void editor_controller::cycle_brush()
{
DBG_ED << __func__ << "\n";
if (brush_ == &brushes_.back()) {
brush_ = &brushes_.front();
} else {
++brush_;
}
DBG_ED << &brushes_.front() << " " << brush_ << " " << &brushes_.back() << "\n";
update_mouse_action_highlights();
DBG_ED << "END\n";
}
void editor_controller::preferences()
@ -899,14 +1024,12 @@ void editor_controller::copy_selection()
void editor_controller::cut_selection()
{
copy_selection();
editor_action_paint_area a(get_map().selection(), background_terrain_);
perform_refresh(a);
perform_refresh(editor_action_paint_area(get_map().selection(), background_terrain_));
}
void editor_controller::fill_selection()
{
editor_action_paint_area a(get_map().selection(), foreground_terrain_);
perform_refresh(a);
perform_refresh(editor_action_paint_area(get_map().selection(), foreground_terrain_));
}
@ -1050,7 +1173,6 @@ void editor_controller::mouse_motion(int x, int y, const bool /*browse*/, bool u
if (!get_map().on_board_with_border(hex_clicked)) return;
a = get_mouse_action()->drag_right(*gui_, x, y, partial, last_undo);
}
//Partial means that the mouse action has modified the
//last undo action and the controller shouldn't add
//anything to the undo stack (hence a different
@ -1084,7 +1206,6 @@ bool editor_controller::right_click_show_menu(int /*x*/, int /*y*/, const bool /
bool editor_controller::left_click(int x, int y, const bool browse)
{
clear_mouseover_overlay();
LOG_ED << "Left click\n";
if (mouse_handler_base::left_click(x, y, browse)) return true;
LOG_ED << "Left click, after generic handling\n";
map_location hex_clicked = gui().hex_clicked_on(x, y);
@ -1112,7 +1233,6 @@ void editor_controller::left_mouse_up(int x, int y, const bool /*browse*/)
bool editor_controller::right_click(int x, int y, const bool browse)
{
clear_mouseover_overlay();
LOG_ED << "Right click\n";
if (mouse_handler_base::right_click(x, y, browse)) return true;
LOG_ED << "Right click, after generic handling\n";
map_location hex_clicked = gui().hex_clicked_on(x, y);

View file

@ -66,21 +66,26 @@ class editor_controller : public controller_base,
private boost::noncopyable
{
public:
/**
* The constructor. A initial map context can be specified here, the controller
* will assume ownership and delete the pointer during destruction, but changes
* to the map can be retrieved between the main loop's end and the controller's
* destruction.
*/
editor_controller(const config &game_config, CVideo& video, map_context* init_map_context = NULL);
~editor_controller();
/** Editor main loop */
EXIT_STATUS main_loop();
/**
* Process a hotkey quit command
*/
/** Process a hotkey quit command */
void hotkey_quit();
/**
* Show a quit confirmation dialog and if confirmed quit with the given exit status
*/
/** Show a quit confirmation dialog and if confirmed quit with the given exit status */
void quit_confirm(EXIT_STATUS status);
/** Display the settings dialog, used to control e.g. the lighting settings */
void editor_settings_dialog();
/**
@ -90,14 +95,32 @@ class editor_controller : public controller_base,
bool confirm_discard();
/** Get the current map context object */
map_context& get_map_context() { return *map_context_; }
map_context& get_map_context() { return *map_contexts_[current_context_index_]; }
/** Get the current map context object - const version */
const map_context& get_map_context() const { return *map_context_; }
const map_context& get_map_context() const { return *map_contexts_[current_context_index_]; }
/** Get the map from the current map context object */
editor_map& get_map() { return get_map_context().get_map(); }
/** Get the map from the current map context object - const version*/
const editor_map& get_map() const { return get_map_context().get_map(); }
/**
* Add a map context. The controller assumes ownership.
* @return the index of the added map context in the map_contexts_ array
*/
int add_map_context(map_context* mc);
/** Creates a default map context object, used to ensure there is always at least one. */
void create_default_context();
/** Closes the active map context. Switches to a valid context afterward or creates a dummy one. */
void close_current_context();
/** Switches the context to the one under the specified index. */
void switch_context(int idx);
/** Display a load map dialog and process user input. */
void load_map_dialog();
@ -134,12 +157,12 @@ class editor_controller : public controller_base,
/**
* Create a new map.
*/
void new_map(int width, int height, t_translation::t_terrain fill);
void new_map(int width, int height, t_translation::t_terrain fill, bool new_context);
/**
* Load a map given the filename
*/
void load_map(const std::string& filename);
void load_map(const std::string& filename, bool new_context);
/**
* Revert the map by reloading it from disk
@ -152,17 +175,22 @@ class editor_controller : public controller_base,
*/
void reload_map();
/**
* Refresh everything, i.e. invalidate all hexes and redraw them. Does *not* reload the map.
*/
void refresh_all();
/** command_executor override */
bool can_execute_command(hotkey::HOTKEY_COMMAND, int index = -1) const;
/** command_executor override */
hotkey::ACTION_STATE get_action_state(hotkey::HOTKEY_COMMAND command) const;
hotkey::ACTION_STATE get_action_state(hotkey::HOTKEY_COMMAND command, int index) const;
/** command_executor override */
bool execute_command(hotkey::HOTKEY_COMMAND command, int index = -1);
/** WIP idea for context-menu starting position setting*/
void expand_starting_position_menu(std::vector<std::string>& items);
/** Menu expanding for open maps list */
void expand_open_maps_menu(std::vector<std::string>& items);
/** controller_base override */
void show_menu(const std::vector<std::string>& items_arg, int xloc, int yloc, bool context_menu);
@ -242,7 +270,12 @@ class editor_controller : public controller_base,
*/
void perform_refresh(const editor_action& action, bool drag_part = false);
/**
* Callback for the editor settings dialog to allow on-the-fly
* updating of the lighting display on the game map behing the dialog
*/
void editor_settings_dialog_redraw_callback(int r, int g, int b);
private:
/** init the display object and general set-up */
void init_gui(CVideo& video);
@ -277,10 +310,10 @@ class editor_controller : public controller_base,
void refresh_after_action(bool drag_part = false);
/**
* Refresh everything unconditionally
* Replace the current map context and refresh accordingly
*/
void refresh_all();
void replace_map_context(const map_context& new_mc);
/**
* Callback function passed to display to be called on each redraw_everything run.
* Redraws toolbar, brush bar and related items.
@ -301,14 +334,19 @@ class editor_controller : public controller_base,
rand_rng::set_random_generator* rng_setter_;
/** The current map object */
map_context* map_context_;
/** The currently opened map context object */
std::vector<map_context*> map_contexts_;
/** Index into the map_contexts_ array */
int current_context_index_;
/** The display object used and owned by the editor. */
editor_display* gui_;
/** Available random map generators */
std::vector<map_generator*> map_generators_;
/** Pre-defined time of day lighting settings for the settings dialog */
std::vector<time_of_day> tods_;
/** Legacy object required by the legacy terrain palette and brush bar */
@ -361,6 +399,8 @@ class editor_controller : public controller_base,
/** Flag to rebuild terrain on every terrain change */
bool auto_update_transitions_;
bool use_mdi_;
/** Default directory for map load/save as dialogs */
std::string default_dir_;
};

View file

@ -12,6 +12,7 @@
*/
#include "editor_display.hpp"
#include "builder.hpp"
@ -20,7 +21,7 @@ namespace editor2 {
editor_display::editor_display(CVideo& video, const editor_map& map,
const config& theme_cfg, const config& cfg,
const config& level)
: display(video, map, theme_cfg, cfg, level)
: display(video, &map, theme_cfg, cfg, level)
, brush_locations_()
, toolbar_hint_()
{
@ -53,7 +54,7 @@ void editor_display::remove_brush_loc(const map_location& hex)
}
void editor_display::rebuild_terrain(const map_location &loc) {
builder_.rebuild_terrain(loc);
builder_->rebuild_terrain(loc);
}
void editor_display::pre_draw()
@ -95,11 +96,11 @@ const SDL_Rect& editor_display::get_clip_rect()
void editor_display::draw_sidebar()
{
// Fill in the terrain report
if(map_.on_board_with_border(mouseoverHex_)) {
refresh_report(reports::TERRAIN, reports::report(map_.get_terrain_string(mouseoverHex_)));
if(get_map().on_board_with_border(mouseoverHex_)) {
refresh_report(reports::TERRAIN, reports::report(get_map().get_terrain_string(mouseoverHex_)));
refresh_report(reports::POSITION, reports::report(lexical_cast<std::string>(mouseoverHex_)));
}
refresh_report(reports::VILLAGES, reports::report(lexical_cast<std::string>(map_.villages().size())));
refresh_report(reports::VILLAGES, reports::report(lexical_cast<std::string>(get_map().villages().size())));
refresh_report(reports::EDITOR2_TOOL_HINT, reports::report(toolbar_hint_));
}

View file

@ -31,7 +31,7 @@ public:
void set_brush_locs(const std::set<map_location>& hexes);
void clear_brush_locs();
void remove_brush_loc(const map_location& hex);
const editor_map& map() const { return static_cast<const editor_map&>(map_); }
const editor_map& map() const { return static_cast<const editor_map&>(get_map()); }
void rebuild_terrain(const map_location &loc);
void set_toolbar_hint(const std::string value) { toolbar_hint_ = value; }

View file

@ -19,6 +19,7 @@
#include "../filesystem.hpp"
#include "../foreach.hpp"
#include "../map_exception.hpp"
#include "../map_label.hpp"
#include "../pathutils.hpp"
#include "../wml_exception.hpp"
@ -279,6 +280,12 @@ gamemap editor_map::mask_to(const gamemap& target) const
return mask;
}
bool editor_map::same_size_as(const gamemap& other) const
{
return h() == other.h()
&& w() == other.w();
}
void editor_map::swap_starting_position(int x1, int y1, int x2, int y2)
{
int pos1 = is_starting_position(map_location(x1, y1));

View file

@ -146,6 +146,8 @@ public:
* will transform it into the target map.
*/
gamemap mask_to(const gamemap& target) const;
bool same_size_as(const gamemap& other) const;
protected:
void swap_starting_position(int x1, int y1, int x2, int y2);

View file

@ -18,6 +18,7 @@
#include "../display.hpp"
#include "../filesystem.hpp"
#include "../foreach.hpp"
#include "../map_label.hpp"
@ -135,9 +136,7 @@ bool map_context::everything_changed() const
void map_context::clear_starting_position_labels(display& disp)
{
foreach (const map_location& loc, starting_position_label_locs_) {
disp.labels().set_label(loc, "");
}
disp.labels().clear_all();
starting_position_label_locs_.clear();
}
@ -158,7 +157,7 @@ bool map_context::save()
{
std::string data = map_.write();
write_file(get_filename(), data);
actions_since_save_ = 0;
clear_modified();
return true;
}
@ -180,7 +179,6 @@ void map_context::set_map(const editor_map& map)
set_needs_terrain_rebuild();
}
map_ = map;
}
void map_context::perform_action(const editor_action& action)
@ -219,6 +217,11 @@ bool map_context::modified() const
return actions_since_save_ != 0;
}
void map_context::clear_modified()
{
actions_since_save_ = 0;
}
bool map_context::can_undo() const
{
return !undo_stack_.empty();

View file

@ -31,13 +31,13 @@ namespace editor2 {
* as e.g. the undo stack is part of the map, not the editor as a whole. This might allow many
* maps to be open at the same time.
*/
class map_context : private boost::noncopyable
class map_context
{
public:
/**
* A map context can only by created from an existing map
*/
map_context(const editor_map& map);
explicit map_context(const editor_map& map);
/**
* Create map_context from a map file. If the map cannot be
@ -152,6 +152,9 @@ public:
/** @return whether the map was modified since the last save */
bool modified() const;
/** Clear the modified state */
void clear_modified();
/** @return true when undo can be performed, false otherwise */
bool can_undo() const;

View file

@ -24,6 +24,7 @@
#include "halo.hpp"
#include "log.hpp"
#include "map.hpp"
#include "map_label.hpp"
#include "marked-up_text.hpp"
#include "game_preferences.hpp"
#include "gamestatus.hpp"
@ -39,7 +40,7 @@ std::map<map_location,fixed_t> game_display::debugHighlights_;
game_display::game_display(unit_map& units, CVideo& video, const gamemap& map,
const gamestatus& status, const std::vector<team>& t,
const config& theme_cfg, const config& cfg, const config& level) :
display(video, map, theme_cfg, cfg, level),
display(video, &map, theme_cfg, cfg, level),
units_(units),
temp_unit_(NULL),
temp_unit_loc_(),
@ -208,12 +209,12 @@ void game_display::select_hex(map_location hex)
void game_display::highlight_hex(map_location hex)
{
unit_map::const_iterator u = find_visible_unit(units_,hex, map_, teams_,teams_[viewing_team()]);
unit_map::const_iterator u = find_visible_unit(units_,hex, get_map(), teams_,teams_[viewing_team()]);
if (u != units_.end()) {
displayedUnitHex_ = hex;
invalidate_unit();
} else {
u = find_visible_unit(units_,mouseoverHex_, map_, teams_,teams_[viewing_team()]);
u = find_visible_unit(units_,mouseoverHex_, get_map(), teams_,teams_[viewing_team()]);
if (u != units_.end()) {
// mouse moved from unit hex to non-unit hex
if (units_.count(selectedHex_)) {
@ -230,7 +231,7 @@ void game_display::highlight_hex(map_location hex)
void game_display::display_unit_hex(map_location hex)
{
unit_map::const_iterator u = find_visible_unit(units_,hex, map_, teams_,teams_[viewing_team()]);
unit_map::const_iterator u = find_visible_unit(units_,hex, get_map(), teams_,teams_[viewing_team()]);
if (u != units_.end()) {
displayedUnitHex_ = hex;
invalidate_unit();
@ -292,11 +293,11 @@ std::vector<map_location> game_display::get_invalidated_unit_locations() {
image::TYPE game_display::get_image_type(const map_location& loc) {
// We highlight hex under the mouse, or under a selected unit.
if (map_.on_board(loc)) {
if (get_map().on_board(loc)) {
if (loc == mouseoverHex_ || loc == attack_indicator_src_) {
return image::BRIGHTENED;
} else if (loc == selectedHex_) {
unit_map::iterator un = find_visible_unit(units_, loc, map_,
unit_map::iterator un = find_visible_unit(units_, loc, get_map(),
teams_,teams_[currentTeam_]);
if (un != units_.end()) {
return image::BRIGHTENED;
@ -322,7 +323,7 @@ void game_display::post_commit()
void game_display::draw_hex(const map_location& loc)
{
const bool on_map = map_.on_board(loc);
const bool on_map = get_map().on_board(loc);
const bool is_shrouded = shrouded(loc);
const bool is_fogged = fogged(loc);
int xpos = get_location_x(loc);
@ -352,7 +353,7 @@ void game_display::draw_hex(const map_location& loc)
// Draw the time-of-day mask on top of the terrain in the hex.
// tod may differ from tod if hex is illuminated.
std::string tod_hex_mask = timeofday_at(status_,units_,loc,map_).image_mask;
std::string tod_hex_mask = timeofday_at(status_,units_,loc,get_map()).image_mask;
if(tod_hex_mask1 != NULL || tod_hex_mask2 != NULL) {
drawing_buffer_add(LAYER_TERRAIN_FG, drawing_order, tblit(xpos, ypos, tod_hex_mask1));
drawing_buffer_add(LAYER_TERRAIN_FG, drawing_order, tblit(xpos, ypos, tod_hex_mask2));
@ -431,7 +432,7 @@ void game_display::draw_report(reports::TYPE report_num)
return;
}
reports::report report = reports::generate_report(report_num,report_,map_,
reports::report report = reports::generate_report(report_num,report_,get_map(),
units_, teams_,
teams_[viewing_team()],
size_t(currentTeam_+1),size_t(activeTeam_+1),
@ -439,7 +440,7 @@ void game_display::draw_report(reports::TYPE report_num)
brighten = false;
if(report_num == reports::TIME_OF_DAY) {
time_of_day tod = timeofday_at(status_,units_,mouseoverHex_,map_);
time_of_day tod = timeofday_at(status_,units_,mouseoverHex_,get_map());
// Don't show illuminated time on fogged/shrouded tiles
if (teams_[viewing_team()].fogged(mouseoverHex_) ||
teams_[viewing_team()].shrouded(mouseoverHex_)) {
@ -477,7 +478,7 @@ void game_display::draw_sidebar()
// otherwise we display the unit that is selected.
unit_map::const_iterator i =
find_visible_unit(units_,displayedUnitHex_,
map_,
get_map(),
teams_,teams_[viewing_team()]);
if(i != units_.end()) {
@ -497,8 +498,8 @@ void game_display::draw_sidebar()
void game_display::draw_minimap_units()
{
double xscaling = 1.0 * minimap_location_.w / map_.w();
double yscaling = 1.0 * minimap_location_.h / map_.h();
double xscaling = 1.0 * minimap_location_.w / get_map().w();
double yscaling = 1.0 * minimap_location_.h / get_map().h();
for(unit_map::const_iterator u = units_.begin(); u != units_.end(); ++u) {
if(fogged(u->first) ||
@ -614,7 +615,7 @@ void game_display::draw_movement_info(const map_location& loc)
const unit_map::const_iterator un = units_.find(route_.steps.front());
if(un != units_.end()) {
// Display the def% of this terrain
const int def = 100 - un->second.defense_modifier(map_.get_terrain(loc));
const int def = 100 - un->second.defense_modifier(get_map().get_terrain(loc));
std::stringstream def_text;
def_text << def << "%";
@ -680,7 +681,7 @@ std::vector<surface> game_display::footsteps_images(const map_location& loc)
int move_cost = 1;
const unit_map::const_iterator u = units_.find(route_.steps.front());
if(u != units_.end()) {
move_cost = u->second.movement_cost(map_.get_terrain(loc));
move_cost = u->second.movement_cost(get_map().get_terrain(loc));
}
int image_number = std::min<int>(move_cost, game_config::foot_speed_prefix.size());
if (image_number < 1) {
@ -731,9 +732,9 @@ std::vector<surface> game_display::footsteps_images(const map_location& loc)
surface game_display::get_flag(const map_location& loc)
{
t_translation::t_terrain terrain = map_.get_terrain(loc);
t_translation::t_terrain terrain = get_map().get_terrain(loc);
if(!map_.is_village(terrain)) {
if(!get_map().is_village(terrain)) {
return surface(NULL);
}
@ -894,7 +895,7 @@ const SDL_Rect& game_display::calculate_energy_bar(surface surf)
}
void game_display::invalidate_animations_location(const map_location& loc) {
if (map_.is_village(loc)) {
if (get_map().is_village(loc)) {
const int owner = player_teams::village_owner(loc);
if (owner >= 0 && flags_[owner].need_update()
&& (!fogged(loc) || !teams_[currentTeam_].is_enemy(owner+1))) {

View file

@ -23,6 +23,7 @@ class team;
class unit;
class unit_map;
#include "animated.hpp"
#include "display.hpp"
#include "image.hpp"
#include "pathfind.hpp"

View file

@ -26,6 +26,7 @@
#include "gui/widgets/spacer.hpp"
#include "gui/widgets/window.hpp"
#include "map.hpp"
#include "map_label.hpp"
#include "map_exception.hpp"
#include "menu_events.hpp"
#include "replay.hpp"

View file

@ -36,7 +36,8 @@ custom_tod_toggle_field_(register_bool("custom_tod_toggle", false)),
custom_tod_red_(NULL), custom_tod_green_(NULL), custom_tod_blue_(NULL),
custom_tod_red_field_(register_integer("custom_tod_red", false)),
custom_tod_green_field_(register_integer("custom_tod_green", false)),
custom_tod_blue_field_(register_integer("custom_tod_blue", false))
custom_tod_blue_field_(register_integer("custom_tod_blue", false)),
use_mdi_field_(register_bool("use_mdi"))
{
}
@ -66,6 +67,10 @@ int teditor_settings::get_blue() const
{
return custom_tod_blue_field_->get_cache_value();
}
bool teditor_settings::get_use_mdi() const
{
return use_mdi_field_->get_cache_value();
}
void teditor_settings::update_tod_display(twindow& /*window*/)
{

View file

@ -55,6 +55,9 @@ public:
void update_selected_tod_info(twindow& window);
bool get_use_mdi() const;
void set_use_mdi(bool value) { use_mdi_ = value; }
private:
/** Inherited from tdialog. */
twindow build_window(CVideo& video);
@ -91,6 +94,10 @@ private:
tfield_integer* custom_tod_red_field_;
tfield_integer* custom_tod_green_field_;
tfield_integer* custom_tod_blue_field_;
tfield_bool* use_mdi_field_;
bool use_mdi_;
};
} // namespace gui2

View file

@ -19,7 +19,7 @@
*/
#include "global.hpp"
#include "animated.hpp"
#include "display.hpp"
#include "game_preferences.hpp"
#include "halo.hpp"

View file

@ -97,6 +97,8 @@ const struct {
#ifndef DISABLE_EDITOR2
{ hotkey::HOTKEY_EDITOR_QUIT_TO_DESKTOP, "editor-quit-to-desktop", N_("Quit to Desktop"), false, hotkey::SCOPE_EDITOR },
{ hotkey::HOTKEY_EDITOR_CLOSE_MAP, "editor-close-map", N_("Close Map"), false, hotkey::SCOPE_EDITOR },
{ hotkey::HOTKEY_EDITOR_SWITCH_MAP, "editor-switch-map", N_("Switch Map"), false, hotkey::SCOPE_EDITOR },
{ hotkey::HOTKEY_EDITOR_SETTINGS, "editor-settings", N_("Editor Settings"), false, hotkey::SCOPE_EDITOR },
{ hotkey::HOTKEY_EDITOR_PARTIAL_UNDO, "editor-partial-undo", N_("Partial Undo"), false, hotkey::SCOPE_EDITOR },
{ hotkey::HOTKEY_EDITOR_MAP_NEW, "editor-map-new", N_("New Map"), false, hotkey::SCOPE_EDITOR },
@ -966,7 +968,7 @@ void command_executor::show_menu(const std::vector<std::string>& items_arg, int
}
std::string command_executor::get_menu_image(hotkey::HOTKEY_COMMAND command, int index) const {
switch(get_action_state(command)) {
switch(get_action_state(command, index)) {
case ACTION_ON: return game_config::checked_menu_image;
case ACTION_OFF: return game_config::unchecked_menu_image;
default: return get_action_image(command, index);

View file

@ -62,6 +62,7 @@ enum HOTKEY_COMMAND {
#ifndef DISABLE_EDITOR2
HOTKEY_EDITOR_QUIT_TO_DESKTOP,
HOTKEY_EDITOR_CLOSE_MAP, HOTKEY_EDITOR_SWITCH_MAP,
HOTKEY_EDITOR_SETTINGS,
HOTKEY_EDITOR_PARTIAL_UNDO,
HOTKEY_EDITOR_MAP_NEW, HOTKEY_EDITOR_MAP_LOAD, HOTKEY_EDITOR_MAP_SAVE,
@ -295,7 +296,7 @@ public:
//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*/, int /*index*/) const { return ""; }
//Does the action control a toggle switch? If so, return the state of the action (on or off)
virtual ACTION_STATE get_action_state(hotkey::HOTKEY_COMMAND /*command*/) const { return ACTION_STATELESS; }
virtual ACTION_STATE get_action_state(hotkey::HOTKEY_COMMAND /*command*/, int /*index*/) const { return ACTION_STATELESS; }
//Returns the appropriate menu image. Checkable items will get a checked/unchecked image.
std::string get_menu_image(hotkey::HOTKEY_COMMAND command, int index=-1) const;
//Returns a vector of images for a given menu

View file

@ -15,6 +15,7 @@
#include "global.hpp"
#include "display.hpp"
#include "map_label.hpp"
namespace {
@ -31,11 +32,9 @@ static bool is_shrouded(const display& disp, const map_location& loc)
}
map_labels::map_labels(const display& disp,
const gamemap& map,
const team* team) :
disp_(disp),
team_(team),
map_(map),
labels_(),
label_cache_()
{
@ -43,12 +42,10 @@ map_labels::map_labels(const display& disp,
map_labels::map_labels(const display& disp,
const config& cfg,
const gamemap& map,
const team* team,
const variable_set *variables) :
disp_(disp),
team_(team),
map_(map),
labels_(),
label_cache_()
{

View file

@ -36,8 +36,8 @@ public:
typedef std::map<map_location,const terrain_label*> label_map;
typedef std::map<std::string,label_map> team_label_map;
map_labels(const display& disp, const gamemap& map, const team*);
map_labels(const display& disp, const config& cfg, const gamemap& map, const team*, const variable_set *variables);
map_labels(const display& disp, const team*);
map_labels(const display& disp, const config& cfg, const team*, const variable_set *variables);
~map_labels();
void write(config& res) const;
@ -71,15 +71,14 @@ public:
void set_team(const team*);
void clear_all();
private:
void clear_map(const label_map&);
void clear_all();
map_labels(const map_labels&);
void operator=(const map_labels&);
const display& disp_;
const team* team_;
const gamemap& map_;
team_label_map labels_;
label_map label_cache_;

View file

@ -27,6 +27,7 @@
#include "gettext.hpp"
#include "help.hpp"
#include "log.hpp"
#include "map_label.hpp"
#include "marked-up_text.hpp"
#include "menu_events.hpp"
#include "mouse_events.hpp"
@ -723,6 +724,7 @@ private:
} catch(game::save_game_failed&) {
gui::message_dialog(*gui_,"",_("Could not auto save the game. Please save the game manually.")).show();
//do not bother retrying, since the user can just save the game
//maybe show a yes-no dialog for "disable autosaves now"?
}
end = SDL_GetTicks();
LOG_NG << "Milliseconds to save " << savename << ": " << end - start << "\n";

View file

@ -39,7 +39,8 @@ namespace{
mouse_handler::mouse_handler(game_display* gui, std::vector<team>& teams,
unit_map& units, gamemap& map, gamestatus& status,
undo_list& undo_stack, undo_list& redo_stack) :
mouse_handler_base(map),
mouse_handler_base(),
map_(map),
gui_(gui),
teams_(teams),
units_(units),

View file

@ -88,6 +88,7 @@ protected:
unit_map::iterator find_unit(const map_location& hex);
bool unit_in_cycle(unit_map::const_iterator it);
private:
gamemap& map_;
game_display* gui_;
std::vector<team>& teams_;
unit_map& units_;

View file

@ -45,7 +45,7 @@ static bool command_active()
#endif
}
mouse_handler_base::mouse_handler_base(gamemap& map) :
mouse_handler_base::mouse_handler_base() :
minimap_scrolling_(false),
dragging_left_(false),
dragging_started_(false),
@ -54,8 +54,7 @@ mouse_handler_base::mouse_handler_base(gamemap& map) :
drag_from_y_(0),
drag_from_hex_(),
last_hex_(),
show_menu_(false),
map_(map)
show_menu_(false)
{
}

View file

@ -32,7 +32,7 @@ extern int commands_disabled;
class mouse_handler_base {
public:
mouse_handler_base(gamemap& map);
mouse_handler_base();
virtual ~mouse_handler_base() {}
/**
@ -153,8 +153,6 @@ protected:
/** Show context menu flag */
bool show_menu_;
gamemap& map_;
static const int drag_threshold_;
};

View file

@ -925,7 +925,7 @@ std::string play_controller::get_action_image(hotkey::HOTKEY_COMMAND command, in
return command_executor::get_action_image(command, index);
}
hotkey::ACTION_STATE play_controller::get_action_state(hotkey::HOTKEY_COMMAND command) const
hotkey::ACTION_STATE play_controller::get_action_state(hotkey::HOTKEY_COMMAND command, int /*index*/) const
{
switch(command) {
case hotkey::HOTKEY_DELAY_SHROUD:

View file

@ -87,7 +87,7 @@ protected:
void post_mouse_press(const SDL_Event& event);
virtual std::string get_action_image(hotkey::HOTKEY_COMMAND, int index) const;
virtual hotkey::ACTION_STATE get_action_state(hotkey::HOTKEY_COMMAND command) const;
virtual hotkey::ACTION_STATE get_action_state(hotkey::HOTKEY_COMMAND command, int index) const;
/** Check if a command can be executed. */
virtual bool can_execute_command(hotkey::HOTKEY_COMMAND command, int index=-1) const;
virtual bool execute_command(hotkey::HOTKEY_COMMAND command, int index=-1);

View file

@ -25,6 +25,7 @@
#include "gettext.hpp"
#include "intro.hpp"
#include "log.hpp"
#include "map_label.hpp"
#include "marked-up_text.hpp"
#include "sound.hpp"
#include "upload_log.hpp"

View file

@ -26,6 +26,7 @@
#include "game_events.hpp"
#include "log.hpp"
#include "map.hpp"
#include "map_label.hpp"
#include "menu_events.hpp"
#include "replay.hpp"
#include "statistics.hpp"