Editor overhaul.

Changed how the terrain group/palettes work.

Added the map label placement tool.
This commit is contained in:
Fabian Müller 2012-02-28 10:31:13 +00:00
parent 3fe19eeb24
commit 520fafcfb9
15 changed files with 346 additions and 240 deletions

View file

@ -164,7 +164,7 @@ const terrain_builder::tile& terrain_builder::tilemap::operator[] (const map_loc
terrain_builder::terrain_builder(const config& level,
const gamemap* m, const std::string& offmap_image) :
map_(m),
tile_map_(map().w(), map().h()),
tile_map_(m ? map().w() : 0, m ? map().h() :0),
terrain_by_type_()
{
image::precache_file_existence("terrain/");
@ -182,7 +182,8 @@ terrain_builder::terrain_builder(const config& level,
// parse local rules
parse_config(level);
build_terrains();
if (m)
build_terrains();
}
void terrain_builder::flush_local_rules()

View file

@ -25,6 +25,8 @@
#include "gettext.hpp"
#include "util.hpp"
#include "resources.hpp"
namespace editor {
int editor_action::next_id_ = 1;
@ -399,7 +401,7 @@ editor_action_create_mask* editor_action_create_mask::clone() const
}
void editor_action_create_mask::perform_without_undo(map_context& mc) const
{
mc.get_map() = editor_map(mc.get_map().mask_to(target_));
mc.get_map() = mc.get_map().mask_to(target_);
mc.set_needs_terrain_rebuild();
}

View file

@ -416,7 +416,7 @@ class editor_action_apply_mask : public editor_action
class editor_action_create_mask : public editor_action
{
public:
editor_action_create_mask(const gamemap& target)
editor_action_create_mask(const editor_map& target)
: target_(target)
{
}
@ -424,7 +424,7 @@ class editor_action_create_mask : public editor_action
void perform_without_undo(map_context& mc) const;
const char* get_name() const { return "create_mask"; }
private:
gamemap target_;
editor_map target_;
};
/**

View file

@ -14,12 +14,16 @@
*/
#define GETTEXT_DOMAIN "wesnoth-editor"
//TODO
#include "wml_separators.hpp"
#include "asserts.hpp"
#include "action.hpp"
#include "editor_controller.hpp"
#include "editor_palettes.hpp"
#include "editor_preferences.hpp"
#include "mouse_action.hpp"
#include "action/mouse/mouse_action_map_label.hpp"
#include "gui/dialogs/editor_new_map.hpp"
#include "gui/dialogs/editor_generate_map.hpp"
@ -91,7 +95,7 @@ editor_controller::editor_controller(const config &game_config, CVideo& video)
, rng_setter_(NULL)
, map_contexts_()
, current_context_index_(0)
, gui_(NULL)
, gui_(new editor_display(video, NULL, get_theme(game_config, "editor"), config()))
, map_generators_()
, tods_()
, size_specs_()
@ -115,11 +119,11 @@ editor_controller::editor_controller(const config &game_config, CVideo& video)
, default_dir_(preferences::editor::default_dir())
{
create_default_context();
init_gui(video);
if (default_dir_.empty()) {
default_dir_ = get_dir(get_dir(get_user_data_dir() + "/editor") + "/maps");
}
init_gui(video);
init_brushes(game_config);
init_mouse_actions(game_config);
init_map_generators(game_config);
@ -150,10 +154,12 @@ editor_controller::editor_controller(const config &game_config, CVideo& video)
}
}
void editor_controller::init_gui(CVideo& video)
void editor_controller::init_gui(CVideo& /*video*/)
{
const config &theme_cfg = get_theme(game_config_, "editor");
gui_.reset(new editor_display(video, get_map(), theme_cfg, config()));
//TODO
//const config &theme_cfg = get_theme(game_config_, "editor");
//gui_.reset(new editor_display(video, &(get_map()), theme_cfg, config()));
gui_->change_map(&get_map());
gui_->set_grid(preferences::grid());
prefs_disp_manager_.reset(new preferences::display_manager(&gui()));
gui_->add_redraw_observer(boost::bind(&editor_controller::display_redraw_callback, this, _1));
@ -168,6 +174,7 @@ void editor_controller::init_sidebar(const config& game_config)
adjust_sizes(gui(), *size_specs_);
palette_.reset(new terrain_palette(gui(), *size_specs_, game_config,
foreground_terrain_, background_terrain_));
gui_->set_terrain_report(palette_->active_terrain_report());
brush_bar_.reset(new brush_bar(gui(), *size_specs_, brushes_, &brush_));
}
@ -194,6 +201,8 @@ void editor_controller::init_mouse_actions(const config& game_config)
new mouse_action_select(&brush_, key_)));
mouse_actions_.insert(std::make_pair(hotkey::HOTKEY_EDITOR_TOOL_STARTING_POSITION,
new mouse_action_starting_position(key_)));
mouse_actions_.insert(std::make_pair(hotkey::HOTKEY_EDITOR_TOOL_LABEL,
new mouse_action_map_label(key_)));
mouse_actions_.insert(std::make_pair(hotkey::HOTKEY_EDITOR_PASTE,
new mouse_action_paste(clipboard_, key_)));
foreach (const theme::menu& menu, gui().get_theme().menus()) {
@ -257,11 +266,11 @@ void editor_controller::init_music(const config& game_config)
}
void editor_controller::load_tooltips()
{
// Tooltips for the groups
palette_->load_tooltips();
}
//void editor_controller::load_tooltips()
//{
// // Tooltips for the groups
// palette_->load_tooltips();
//}
editor_controller::~editor_controller()
{
@ -339,11 +348,11 @@ int editor_controller::add_map_context(map_context* mc)
void editor_controller::create_default_context()
{
if(saved_windows_.empty()) {
map_context* mc = new map_context(editor_map(game_config_, 44, 33, t_translation::GRASS_LAND));
map_context* mc = new map_context(editor_map(game_config_, 44, 33, t_translation::GRASS_LAND, get_display()));
add_map_context(mc);
} else {
foreach(const std::string& filename, saved_windows_) {
map_context* mc = new map_context(game_config_, filename);
map_context* mc = new map_context(game_config_, filename, get_display());
add_map_context(mc);
}
saved_windows_.clear();
@ -506,7 +515,7 @@ void editor_controller::generate_map_dialog()
} else {
// config map;
// map["data"] = map_string;
editor_map new_map(game_config_, map_string);
editor_map new_map(game_config_, map_string, get_display());
editor_action_whole_map a(new_map);
perform_refresh(a);
}
@ -522,7 +531,7 @@ void editor_controller::apply_mask_dialog()
int res = dialogs::show_file_chooser_dialog(gui(), fn, _("Choose a Mask to Apply"));
if (res == 0) {
try {
map_context mask(game_config_, fn);
map_context mask(game_config_, fn, get_display());
editor_action_apply_mask a(mask.get_map());
perform_refresh(a);
} catch (editor_map_load_exception& e) {
@ -544,7 +553,7 @@ void editor_controller::create_mask_to_dialog()
int res = dialogs::show_file_chooser_dialog(gui(), fn, _("Choose Target Map"));
if (res == 0) {
try {
map_context map(game_config_, fn);
map_context map(game_config_, fn, get_display());
editor_action_create_mask a(map.get_map());
perform_refresh(a);
} catch (editor_map_load_exception& e) {
@ -706,7 +715,7 @@ void editor_controller::load_map(const std::string& filename, bool new_context)
if (new_context && check_switch_open_map(filename)) return;
LOG_ED << "Load map: " << filename << (new_context ? " (new)" : " (same)") << "\n";
try {
util::unique_ptr<map_context> mc(new map_context(game_config_, filename));
util::unique_ptr<map_context> mc(new map_context(game_config_, filename, get_display()));
if (mc->get_filename() != filename) {
if (new_context && check_switch_open_map(mc->get_filename())) return;
}
@ -756,7 +765,7 @@ void editor_controller::revert_map()
void editor_controller::new_map(int width, int height, t_translation::t_terrain fill, bool new_context)
{
editor_map m(game_config_, width, height, fill);
editor_map m(game_config_, width, height, fill, get_display());
if (new_context) {
int new_id = add_map_context(new map_context(m));
switch_context(new_id);
@ -826,11 +835,22 @@ bool editor_controller::can_execute_command(hotkey::HOTKEY_COMMAND command, int
case HOTKEY_NULL:
if (index >= 0) {
unsigned i = static_cast<unsigned>(index);
if (i < map_contexts_.size()) {
return true;
switch (active_menu_) {
case editor::MAP:
if (i < map_contexts_.size()) {
return true;
}
return false;
case editor::TERRAIN:
case editor::AREA:
case editor::SIDE:
return true;
}
}
return false;
case HOTKEY_EDITOR_TERRAIN_GROUPS:
return true;
case HOTKEY_ZOOM_IN:
case HOTKEY_ZOOM_OUT:
case HOTKEY_ZOOM_DEFAULT:
@ -872,6 +892,7 @@ bool editor_controller::can_execute_command(hotkey::HOTKEY_COMMAND command, int
case HOTKEY_EDITOR_TOOL_FILL:
case HOTKEY_EDITOR_TOOL_SELECT:
case HOTKEY_EDITOR_TOOL_STARTING_POSITION:
case HOTKEY_EDITOR_TOOL_LABEL:
return true; //tool selection always possible
case HOTKEY_EDITOR_CUT:
case HOTKEY_EDITOR_COPY:
@ -918,6 +939,8 @@ hotkey::ACTION_STATE editor_controller::get_action_state(hotkey::HOTKEY_COMMAND
case HOTKEY_EDITOR_TOOL_PAINT:
case HOTKEY_EDITOR_TOOL_FILL:
case HOTKEY_EDITOR_TOOL_SELECT:
case HOTKEY_EDITOR_TOOL_LABEL:
return is_mouse_action_set(command) ? ACTION_ON : ACTION_OFF;
case HOTKEY_EDITOR_TOOL_STARTING_POSITION:
return is_mouse_action_set(command) ? ACTION_ON : ACTION_OFF;
case HOTKEY_EDITOR_DRAW_COORDINATES:
@ -925,7 +948,18 @@ hotkey::ACTION_STATE editor_controller::get_action_state(hotkey::HOTKEY_COMMAND
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;
switch (active_menu_) {
case editor::MAP:
return index == current_context_index_ ? ACTION_ON : ACTION_OFF;
case editor::TERRAIN:
//return (size_t)index == palette_->active_group() ? ACTION_ON : ACTION_OFF;
return ACTION_STATELESS;
case editor::AREA:
case editor::SIDE:
return ACTION_ON;
}
case HOTKEY_EDITOR_TERRAIN_GROUPS:
return ACTION_ON;
default:
return command_executor::get_action_state(command, index);
}
@ -937,14 +971,35 @@ bool editor_controller::execute_command(hotkey::HOTKEY_COMMAND command, int inde
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;
switch (active_menu_) {
case MAP:
if (index >= 0) {
unsigned i = static_cast<unsigned>(index);
if (i < map_contexts_.size()) {
switch_context(index);
return true;
}
}
return false;
case TERRAIN:
palette_->set_group(index);
get_display().set_terrain_report(palette_->active_terrain_report());
return true;
case SIDE:
case AREA:
return true;
}
return false;
case HOTKEY_EDITOR_TERRAIN_GROUPS:
//TODO
// if (index >= 0) {
// unsigned i = static_cast<unsigned>(index);
// if (i < 80)
//TODO
// palette_->set_group(index);
// get_display().set_terrain_image(palette_->active_image());
return true;
// }
// return false;
case HOTKEY_QUIT_GAME:
quit_confirm(EXIT_NORMAL);
return true;
@ -975,6 +1030,7 @@ bool editor_controller::execute_command(hotkey::HOTKEY_COMMAND command, int inde
case HOTKEY_EDITOR_TOOL_FILL:
case HOTKEY_EDITOR_TOOL_SELECT:
case HOTKEY_EDITOR_TOOL_STARTING_POSITION:
case HOTKEY_EDITOR_TOOL_LABEL:
hotkey_set_mouse_action(command);
return true;
case HOTKEY_EDITOR_PASTE: //paste is somewhat different as it might be "one action then revert to previous mode"
@ -1090,6 +1146,7 @@ bool editor_controller::execute_command(hotkey::HOTKEY_COMMAND command, int inde
void editor_controller::expand_open_maps_menu(std::vector<std::string>& items)
{
active_menu_ = editor::MAP;
for (unsigned int i = 0; i < items.size(); ++i) {
if (items[i] == "editor-switch-map") {
items.erase(items.begin() + i);
@ -1112,6 +1169,34 @@ void editor_controller::expand_open_maps_menu(std::vector<std::string>& items)
}
}
void editor_controller::expand_terrain_groups_menu(std::vector<std::string>& items)
{
active_menu_ = editor::TERRAIN;
for (unsigned int i = 0; i < items.size(); ++i) {
if (items[i] == "editor-terrain-groups") {
items.erase(items.begin() + i);
std::vector<std::string> groups;
const std::vector<terrain_group>& terrain_groups = palette_->get_groups();
for (size_t mci = 0; mci < terrain_groups.size(); ++mci) {
std::string groupname = terrain_groups[mci].name;
if (groupname.empty()) {
groupname = _("(Unknown Group)");
}
std::string img = terrain_groups[mci].icon;
std::stringstream str;
std::string postfix = (palette_->active_group() == terrain_groups[mci].id) ? "-pressed.png" : ".png";
str << IMAGE_PREFIX << "images/buttons/" << img << postfix << COLUMN_SEPARATOR << groupname;
groups.push_back(str.str());
}
items.insert(items.begin() + i, groups.begin(), groups.end());
break;
}
}
}
void editor_controller::show_menu(const std::vector<std::string>& items_arg, int xloc, int yloc, bool context_menu)
{
if (context_menu) {
@ -1160,6 +1245,10 @@ void editor_controller::show_menu(const std::vector<std::string>& items_arg, int
expand_open_maps_menu(items);
context_menu = true; //FIXME hack to display a one-item menu
}
if (!items.empty() && items.front() == "editor-terrain-groups") {
expand_terrain_groups_menu(items);
context_menu = true; //FIXME hack to display a one-item menu
}
command_executor::show_menu(items, xloc, yloc, context_menu, gui());
}
@ -1325,7 +1414,7 @@ void editor_controller::display_redraw_callback(display&)
palette_->draw(true);
brush_bar_->draw(true);
//display::redraw_everything removes our custom tooltips so reload them
load_tooltips();
// load_tooltips();
gui().invalidate_all();
}

View file

@ -55,6 +55,13 @@ class editor_map;
std::string get_left_button_function();
enum menu_type {
MAP,
TERRAIN,
AREA,
SIDE
};
/**
* The editor_controller class containts the mouse and keyboard event handling
* routines for the editor. It also serves as the main editor class with the
@ -231,6 +238,9 @@ class editor_controller : public controller_base,
/** Menu expanding for open maps list */
void expand_open_maps_menu(std::vector<std::string>& items);
/** Menu expanding for open maps list */
void expand_terrain_groups_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);
@ -316,6 +326,10 @@ class editor_controller : public controller_base,
void editor_settings_dialog_redraw_callback(int r, int g, int b);
private:
//TODO
editor::menu_type active_menu_;
/** init the display object and general set-up */
void init_gui(CVideo& video);

View file

@ -19,11 +19,12 @@
namespace editor {
editor_display::editor_display(CVideo& video, const editor_map& map,
editor_display::editor_display(CVideo& video, const editor_map* map,
const config& theme_cfg, const config& level)
: display(video, &map, theme_cfg, level)
: display(video, map, theme_cfg, level)
, brush_locations_()
, toolbar_hint_()
, terrain_report_()
{
clear_screen();
}
@ -112,6 +113,8 @@ void editor_display::draw_sidebar()
refresh_report("villages", element);
text = toolbar_hint_;
refresh_report("editor_tool_hint", element);
refresh_report("terrain_image", terrain_report_);
}
} //end namespace editor

View file

@ -24,7 +24,7 @@ namespace editor {
class editor_display : public display
{
public:
editor_display(CVideo& video, const editor_map& map, const config& theme_cfg,
editor_display(CVideo& video, const editor_map* map, const config& theme_cfg,
const config& level);
bool in_editor() const { return true; }
@ -37,6 +37,8 @@ public:
void rebuild_terrain(const map_location &loc);
void set_toolbar_hint(const std::string& value) { toolbar_hint_ = value; }
void set_terrain_report(const config terrain_report) {terrain_report_ = terrain_report;};
protected:
void pre_draw();
/**
@ -51,6 +53,9 @@ protected:
std::set<map_location> brush_locations_;
std::string toolbar_hint_;
private:
config terrain_report_;
};
} //end namespace editor

View file

@ -25,17 +25,17 @@
namespace {
const size_t default_terrain_size = 36;
const size_t default_palette_width = 3;
const size_t default_terrain_size = 72;
const size_t default_palette_width = 2;
}
namespace editor {
size_specs::size_specs()
: terrain_size(default_terrain_size)
: default_terrain_size(default_terrain_size)
, terrain_padding(2)
, terrain_space(terrain_size + terrain_padding)
, terrain_width(default_palette_width)
, default_terrain_space(default_terrain_size + terrain_padding)
, default_terrain_width(default_palette_width)
, palette_x(0)
, palette_y(0)
, palette_h(20)
@ -49,11 +49,11 @@ size_specs::size_specs()
void adjust_sizes(const display &disp, size_specs &sizes) {
/** @todo Hardcoded coordinates for brush selection, make it themeable. */
sizes.brush_x = disp.map_outside_area().w + 10;
sizes.brush_y = 212;
sizes.brush_y = 242;
/** @todo Hardcoded coordinates for terrain palette, make it themeable. */
sizes.palette_x = disp.map_outside_area().w + 16;
sizes.palette_y = sizes.brush_y + 72;
sizes.palette_w = sizes.terrain_space * default_palette_width;
sizes.palette_x = disp.map_outside_area().w + 8;
sizes.palette_y = sizes.brush_y + 92;
sizes.palette_w = 165 ;//sizes.terrain_space * default_palette_width;
sizes.palette_h = disp.h() - sizes.palette_y;
}

View file

@ -34,10 +34,10 @@ struct size_specs {
* adjust_sizes().
*/
size_specs();
size_t terrain_size;
size_t default_terrain_size;
size_t terrain_padding;
size_t terrain_space;
size_t terrain_width;
size_t default_terrain_space;
size_t default_terrain_width;
size_t palette_x;
size_t palette_y;
size_t palette_h;

View file

@ -41,30 +41,36 @@ editor_map_load_exception wrap_exc(const char* type, const std::string& e_msg, c
return editor_map_load_exception(filename, msg);
}
editor_map::editor_map(const config& terrain_cfg)
editor_map::editor_map(const config& terrain_cfg, const display& disp)
: gamemap(terrain_cfg, "")
, selection_()
, labels_(disp, NULL)
{
}
editor_map::editor_map(const config& terrain_cfg, const config& level)
editor_map::editor_map(const config& terrain_cfg, const config& level, const display& disp)
: gamemap(terrain_cfg, level)
, selection_()
, labels_(disp, NULL)
{
labels_.read(level);
//labels_.disp().re
//labels_.disp().d
sanity_check();
}
editor_map::editor_map(const config& terrain_cfg, const std::string& data)
editor_map::editor_map(const config& terrain_cfg, const std::string& data, const display& disp)
: gamemap(terrain_cfg, data)
, selection_()
, labels_(disp, NULL)
{
sanity_check();
}
editor_map editor_map::from_string(const config& terrain_cfg, const std::string& data)
editor_map editor_map::from_string(const config& terrain_cfg, const std::string& data, const display& disp)
{
try {
return editor_map(terrain_cfg, data);
return editor_map(terrain_cfg, data, disp);
} catch (incorrect_map_format_error& e) {
throw wrap_exc("format", e.message, "");
} catch (twml_exception& e) {
@ -74,16 +80,18 @@ editor_map editor_map::from_string(const config& terrain_cfg, const std::string&
}
}
editor_map::editor_map(const config& terrain_cfg, size_t width, size_t height, t_translation::t_terrain filler)
editor_map::editor_map(const config& terrain_cfg, size_t width, size_t height, t_translation::t_terrain filler, const display& disp)
: gamemap(terrain_cfg, t_translation::write_game_map(t_translation::t_map(width + 2, t_translation::t_list(height + 2, filler))))
, selection_()
, labels_(disp, NULL)
{
sanity_check();
}
editor_map::editor_map(const gamemap& map)
editor_map::editor_map(const gamemap& map, const display& disp)
: gamemap(map)
, selection_()
, labels_(disp, NULL)
{
sanity_check();
}
@ -257,12 +265,12 @@ void editor_map::resize(int width, int height, int x_offset, int y_offset,
sanity_check();
}
gamemap editor_map::mask_to(const gamemap& target) const
editor_map editor_map::mask_to(const editor_map& target) const
{
if (target.w() != w() || target.h() != h()) {
throw editor_action_exception(_("The size of the target map is different from the current map"));
}
gamemap mask(target);
editor_map mask(target);
map_location iter;
for (iter.x = -border_size(); iter.x < w() + border_size(); ++iter.x) {
for (iter.y = -border_size(); iter.y < h() + border_size(); ++iter.y) {
@ -392,6 +400,10 @@ void editor_map::shrink_bottom(int count)
total_height_ -= count;
}
void editor_map::write(config& cfg) const {
config& map = cfg.add_child("map");
gamemap::write(map);
labels_.write(cfg);
}
} //end namespace editor

View file

@ -19,6 +19,7 @@
#include "editor_common.hpp"
#include "../map.hpp"
#include "../map_label.hpp"
#include <deque>
@ -75,31 +76,31 @@ public:
/**
* Empty map constructor
*/
explicit editor_map(const config& terrain_cfg);
explicit editor_map(const config& terrain_cfg, const display& disp);
/**
* Create an editor map from a map data string
*/
editor_map(const config& terrain_cfg, const config& level);
editor_map(const config& terrain_cfg, const config& level, const display& disp);
editor_map(const config& terrain_cfg, const std::string& data);
editor_map(const config& terrain_cfg, const std::string& data, const display& disp);
/**
* Wrapper around editor_map(cfg, data) that catches possible exceptions
* and wraps them in a editor_map_load_exception
*/
static editor_map from_string(const config& terrain_cfg, const std::string& data);
static editor_map from_string(const config& terrain_cfg, const std::string& data, const display& disp);
/**
* Create an editor map with the given dimensions and filler terrain
*/
editor_map(const config& terrain_cfg, size_t width, size_t height, t_translation::t_terrain filler);
editor_map(const config& terrain_cfg, size_t width, size_t height, t_translation::t_terrain filler, const display& disp);
/**
* Create an editor_map by upgrading an existing gamemap. The map data is
* copied. Marked "explicit" to avoid potentially harmful autmatic conversions.
* copied. Marked "explicit" to avoid potentially harmful automatic conversions.
*/
explicit editor_map(const gamemap& map);
explicit editor_map(const gamemap& map, const display& disp);
/**
* editor_map destructor
@ -118,6 +119,14 @@ public:
*/
std::set<map_location> get_contiguous_terrain_tiles(const map_location& start) const;
/**
* @return the map labels of the map
*/
map_labels& get_map_labels() { return labels_; };
const map_labels& get_map_labels() const { return labels_; };
/**
* Set labels for staring positions in the given display object.
* @return the locations where the labels were added
@ -177,7 +186,7 @@ public:
* A sort-of diff operation returning a mask that, when applied to the current editor_map,
* will transform it into the target map.
*/
gamemap mask_to(const gamemap& target) const;
editor_map mask_to(const editor_map& target) const;
/**
* A precondition to several map operations
@ -185,6 +194,8 @@ public:
*/
bool same_size_as(const gamemap& other) const;
void write(config&) const;
protected:
t_translation::t_list clone_column(int x, t_translation::t_terrain filler);
@ -202,6 +213,14 @@ protected:
* The selected hexes
*/
std::set<map_location> selection_;
private:
/**
* The labels of this map _context.
*/
map_labels labels_;
};

View file

@ -45,9 +45,8 @@ static bool is_valid_terrain(t_translation::t_terrain c) {
return !(c == t_translation::VOID_TERRAIN || c == t_translation::FOGGED);
}
terrain_group::terrain_group(const config& cfg, display& gui):
id(cfg["id"]), name(cfg["name"].t_str()),
button(gui.video(), "", gui::button::TYPE_CHECK, cfg["icon"]),
terrain_group::terrain_group(const config& cfg):
id(cfg["id"]), name(cfg["name"].t_str()), icon(cfg["icon"]),
core(cfg["core"].to_bool())
{
}
@ -57,19 +56,18 @@ terrain_palette::terrain_palette(display &gui, const size_specs &sizes,
t_translation::t_terrain& fore,
t_translation::t_terrain& back)
: gui::widget(gui.video())
, terrain_width_(1)
, terrain_size_(72)
, size_specs_(sizes)
, gui_(gui)
, tstart_(0)
, terrain_map_()
, terrains_()
, active_group_()
, terrain_groups_()
, non_core_terrains_()
, checked_group_btn_(0)
, top_button_(gui.video(), "", gui::button::TYPE_PRESS, "uparrow-button")
, bot_button_(gui.video(), "", gui::button::TYPE_PRESS, "downarrow-button")
// , checked_group_btn_(0)
, button_x_()
, top_button_y_()
, bot_button_y_()
, nterrains_()
, nmax_terrains_()
, terrain_start_()
@ -87,21 +85,14 @@ terrain_palette::terrain_palette(display &gui, const size_specs &sizes,
foreach (const config &g, cfg.child_range("editor_group"))
{
if (group_names.find(g["id"]) == group_names.end()) {
terrain_groups_.push_back(terrain_group(g, gui));
terrain_groups_.push_back(terrain_group(g));
group_names.insert(terrain_groups_.back().id);
// By default the 'all'-button is pressed
if(terrain_groups_.back().id == "all") {
terrain_groups_.back().button.set_check(true);
checked_group_btn_ = &terrain_groups_.back().button;
}
}
}
std::map<std::string, terrain_group*> id_to_group;
foreach (terrain_group& tg, terrain_groups_) {
id_to_group.insert(std::make_pair(tg.id, &tg));
}
// The rest of the code assumes this is a valid pointer
assert(checked_group_btn_ != 0);
// add the groups for all terrains to the map
foreach (const t_translation::t_terrain& t, terrains_) {
@ -143,33 +134,31 @@ terrain_palette::terrain_palette(display &gui, const size_specs &sizes,
typedef std::pair<std::string, t_translation::t_list> map_pair;
// Set the default group
terrains_ = terrain_map_["all"];
set_group("all");
if(terrains_.empty()) {
ERR_ED << "No terrain found.\n";
}
update_report();
//adjust_size();
}
void terrain_palette::adjust_size() {
scroll_top();
const size_t button_height = 24;
const size_t button_palette_padding = 8;
const size_t button_palette_padding = 4;
// Values for the group buttons fully hardcoded for now
/** @todo will be fixed later */
const size_t group_button_height = 24;
const size_t group_button_padding = 2;
const size_t group_buttons_per_row = 5;
const size_t group_buttons_per_row = 6;
// Determine number of theme button rows
size_t group_rows = terrain_groups_.size() / group_buttons_per_row;
if(terrain_groups_.size() % group_buttons_per_row != 0) {
++group_rows;
}
const size_t group_height = group_rows * (group_button_height + group_button_padding);
SDL_Rect rect = create_rect(size_specs_.palette_x
, size_specs_.palette_y
@ -177,28 +166,34 @@ void terrain_palette::adjust_size() {
, size_specs_.palette_h);
set_location(rect);
top_button_y_ = size_specs_.palette_y + group_height ;
button_x_ = size_specs_.palette_x + size_specs_.palette_w/2 - button_height/2;
terrain_start_ = top_button_y_ + button_height + button_palette_padding;
const size_t space_for_terrains = size_specs_.palette_h - (button_height + button_palette_padding) * 2 - group_height;
terrain_start_ = size_specs_.palette_y + button_palette_padding;
const size_t space_for_terrains = size_specs_.palette_h;
uint fitting = 1;
terrain_width_ = 1;
terrain_size_ = 72;
while (fitting < num_terrains()) {
terrain_width_++;
terrain_size_ = size_specs_.palette_w / terrain_width_ - size_specs_.terrain_padding;
terrain_size_ = (terrain_size_ > 72) ? 72 : terrain_size_;
fitting = ((space_for_terrains )/ (terrain_size_ + size_specs_.terrain_padding)) * terrain_width_;
}
rect.y = terrain_start_;
rect.h = space_for_terrains;
bg_register(rect);
const unsigned terrains_fitting =
static_cast<unsigned> (space_for_terrains / size_specs_.terrain_space) *
size_specs_.terrain_width;
static_cast<unsigned> (space_for_terrains / (terrain_size_ + size_specs_.terrain_padding) *
terrain_width_);
nterrains_ = std::min<int>(terrains_fitting, nmax_terrains_);
bot_button_y_ = size_specs_.palette_y + (nterrains_ / size_specs_.terrain_width) * size_specs_.terrain_space + \
button_palette_padding * size_specs_.terrain_width + button_height + group_height;
top_button_.set_location(button_x_, top_button_y_);
bot_button_.set_location(button_x_, bot_button_y_);
size_t top = size_specs_.palette_y;
size_t left = size_specs_.palette_x - 8;
size_t left = size_specs_.palette_x + 2;
for(size_t i = 0; i < terrain_groups_.size(); ++i) {
terrain_groups_[i].button.set_location(left, top);
if (terrain_map_[terrain_groups_[i].id].empty())
continue;
if(i % group_buttons_per_row == (group_buttons_per_row - 1)) {
left = size_specs_.palette_x - 8;
left = size_specs_.palette_x + 2;
top += group_button_height + group_button_padding;
} else {
left += group_button_height + group_button_padding;
@ -210,38 +205,6 @@ void terrain_palette::adjust_size() {
void terrain_palette::set_dirty(bool dirty) {
widget::set_dirty(dirty);
if (dirty) {
top_button_.set_dirty();
bot_button_.set_dirty();
for(size_t i = 0; i < terrain_groups_.size(); ++i) {
terrain_groups_[i].button.set_dirty();
}
}
}
void terrain_palette::scroll_down() {
if(tstart_ + nterrains_ + size_specs_.terrain_width <= num_terrains()) {
tstart_ += size_specs_.terrain_width;
bg_restore();
set_dirty();
}
else if (tstart_ + nterrains_ + (num_terrains() % size_specs_.terrain_width) <= num_terrains()) {
tstart_ += num_terrains() % size_specs_.terrain_width;
bg_restore();
set_dirty();
}
}
void terrain_palette::scroll_up() {
unsigned int decrement = size_specs_.terrain_width;
if (tstart_ + nterrains_ == num_terrains() && num_terrains() % size_specs_.terrain_width != 0) {
decrement = num_terrains() % size_specs_.terrain_width;
}
if(tstart_ >= decrement) {
bg_restore();
set_dirty();
tstart_ -= decrement;
}
}
void terrain_palette::scroll_top() {
@ -250,23 +213,43 @@ void terrain_palette::scroll_top() {
set_dirty();
}
void terrain_palette::scroll_bottom() {
unsigned int old_start = num_terrains();
while (old_start != tstart_) {
old_start = tstart_;
scroll_down();
}
}
void terrain_palette::set_group(const std::string& id)
{
terrains_ = terrain_map_[id];
active_group_ = id;
if(terrains_.empty()) {
ERR_ED << "No terrain found.\n";
}
scroll_top();
}
void terrain_palette::set_group(size_t index)
{
set_group(terrain_groups_[index].id);
}
size_t terrain_palette::active_group_index()
{
for (size_t i = 0 ; i < terrain_groups_.size(); i++) {
if (terrain_groups_[i].id == active_group_)
return i;
}
return 0;
}
const config terrain_palette::active_terrain_report()
{
config cfg;
config& report = cfg.add_child("element");
for (size_t i = 0 ; i < terrain_groups_.size(); i++) {
if (terrain_groups_[i].id == active_group_) {
report["image"] = "images/buttons/" + terrain_groups_[i].icon + "-pressed.png";
report["tooltip"] = terrain_groups_[i].name;
}
}
return cfg;
}
t_translation::t_terrain terrain_palette::selected_fg_terrain() const
{
return selected_fg_terrain_;
@ -360,12 +343,6 @@ void terrain_palette::handle_event(const SDL_Event& event) {
if (mouse_button_event.button == SDL_BUTTON_RIGHT) {
right_mouse_click(mousex, mousey);
}
if (mouse_button_event.button == SDL_BUTTON_WHEELUP) {
scroll_up();
}
if (mouse_button_event.button == SDL_BUTTON_WHEELDOWN) {
scroll_down();
}
}
if (mouse_button_event.type == SDL_MOUSEBUTTONUP) {
if (mouse_button_event.button == SDL_BUTTON_LEFT) {
@ -374,38 +351,14 @@ void terrain_palette::handle_event(const SDL_Event& event) {
}
void terrain_palette::draw(bool force) {
if (top_button_.pressed()) {
scroll_up();
}
if (bot_button_.pressed()) {
scroll_down();
}
foreach (terrain_group& g, terrain_groups_) {
if (g.button.pressed()) {
checked_group_btn_ = &g.button;
set_group(g.id);
break;
}
}
foreach (terrain_group& g, terrain_groups_) {
if (&g.button == checked_group_btn_) {
g.button.set_check(true);
} else {
g.button.set_check(false);
}
}
if (!dirty() && !force) {
return;
}
unsigned int starting = tstart_;
unsigned int ending = starting + nterrains_;
adjust_size();
surface screen = gui_.video().getSurface();
if(ending > num_terrains()){
ending = num_terrains();
}
const SDL_Rect &loc = location();
int y = terrain_start_;
SDL_Rect palrect;
@ -414,16 +367,15 @@ void terrain_palette::draw(bool force) {
palrect.w = size_specs_.palette_w;
palrect.h = size_specs_.palette_h;
tooltips::clear_tooltips(palrect);
for(unsigned int counter = starting; counter < ending; counter++){
for(unsigned int counter = 0; counter < terrains_.size(); counter++){
const t_translation::t_terrain terrain = terrains_[counter];
const t_translation::t_terrain base_terrain = map().get_terrain_info(terrain).default_base();
const int counter_from_zero = counter - starting;
SDL_Rect dstrect;
dstrect.x = loc.x + (counter_from_zero % size_specs_.terrain_width) * size_specs_.terrain_space;
dstrect.x = loc.x + (counter % terrain_width_) * (terrain_size_ + size_specs_.terrain_padding);
dstrect.y = y;
dstrect.w = size_specs_.terrain_size;
dstrect.h = size_specs_.terrain_size;
dstrect.w = terrain_size_;
dstrect.h = terrain_size_;
// Reset the tile background
bg_restore(dstrect);
@ -445,11 +397,11 @@ void terrain_palette::draw(bool force) {
}
}
if(static_cast<unsigned>(base_image->w) != size_specs_.terrain_size ||
static_cast<unsigned>(base_image->h) != size_specs_.terrain_size) {
if(static_cast<unsigned>(base_image->w) != terrain_size_ ||
static_cast<unsigned>(base_image->h) != terrain_size_) {
base_image.assign(scale_surface(base_image,
size_specs_.terrain_size, size_specs_.terrain_size));
terrain_size_, terrain_size_));
}
sdl_blit(base_image, NULL, screen, &dstrect);
@ -467,11 +419,11 @@ void terrain_palette::draw(bool force) {
}
}
if(static_cast<unsigned>(image->w) != size_specs_.terrain_size ||
static_cast<unsigned>(image->h) != size_specs_.terrain_size) {
if(static_cast<unsigned>(image->w) != terrain_size_ ||
static_cast<unsigned>(image->h) != terrain_size_) {
image.assign(scale_surface(image,
size_specs_.terrain_size, size_specs_.terrain_size));
terrain_size_, terrain_size_));
}
sdl_blit(image, NULL, screen, &dstrect);
@ -505,8 +457,8 @@ void terrain_palette::draw(bool force) {
<< "</span>";
}
tooltips::add_tooltip(dstrect, tooltip_text.str());
if (counter_from_zero % size_specs_.terrain_width == size_specs_.terrain_width - 1)
y += size_specs_.terrain_space;
if (((int)counter) % terrain_width_ == terrain_width_ - 1)
y += terrain_size_ + size_specs_.terrain_padding;
}
update_rect(loc);
set_dirty(false);
@ -514,10 +466,11 @@ void terrain_palette::draw(bool force) {
int terrain_palette::tile_selected(const int x, const int y) const {
for(unsigned int i = 0; i != nterrains_; i++) {
const int px = size_specs_.palette_x + (i % size_specs_.terrain_width) * size_specs_.terrain_space;
const int py = terrain_start_ + (i / size_specs_.terrain_width) * size_specs_.terrain_space;
const int pw = size_specs_.terrain_space;
const int ph = size_specs_.terrain_space;
const int px = size_specs_.palette_x + (i % terrain_width_) * (terrain_size_ + size_specs_.terrain_padding);
const int py = terrain_start_ + (i / terrain_width_) * (terrain_size_ + size_specs_.terrain_padding);
const int pw = (terrain_size_ + size_specs_.terrain_padding);
const int ph = (terrain_size_ + size_specs_.terrain_padding);
if(x > px && x < px + pw && y > py && y < py + ph) {
return i;
@ -534,25 +487,6 @@ void terrain_palette::update_report()
selected_terrain = msg.str();
}
void terrain_palette::load_tooltips()
{
for(size_t i = 0; i < terrain_groups_.size(); ++i) {
const std::string& text = terrain_groups_[i].name;
if(text !="") {
const SDL_Rect tooltip_rect = terrain_groups_[i].button.location();
tooltips::add_tooltip(tooltip_rect, text);
}
}
}
// void terrain_palette::bg_backup() {
// restorer_ = surface_restorer(&gui_.video(), get_rect());
// }
// void terrain_palette::bg_restore() {
// restorer_.restore();
// }
brush_bar::brush_bar(display &gui, const size_specs &sizes,
std::vector<brush>& brushes, brush** the_brush)
: gui::widget(gui.video()), size_specs_(sizes), gui_(gui),
@ -561,7 +495,7 @@ size_(30) {
adjust_size();
}
void brush_bar::adjust_size() {// TODO
void brush_bar::adjust_size() {
set_location(size_specs_.brush_x, size_specs_.brush_y);
set_measurements(size_ * brushes_.size() + (brushes_.size() - 1) * size_specs_.brush_padding, size_);
set_dirty();

View file

@ -36,11 +36,11 @@ std::string get_selected_terrain();
*/
struct terrain_group
{
terrain_group(const config& cfg, display& gui);
terrain_group(const config& cfg);
std::string id;
t_string name;
gui::button button;
std::string icon;
bool core;
};
@ -74,6 +74,16 @@ public:
*/
void set_group(const std::string& id);
void set_group(size_t index);
size_t active_group_index();
std::string active_group() {return active_group_;};
const config active_terrain_report();
const std::vector<terrain_group>& get_groups() const { return terrain_groups_; };
/** Return the currently selected foreground terrain. */
t_translation::t_terrain selected_fg_terrain() const;
/** Return the currently selected background terrain. */
@ -106,12 +116,12 @@ public:
*/
void adjust_size();
/** Sets the tooltips used in the palette */
void load_tooltips();
private:
void draw_old(bool);
int terrain_width_;
int terrain_size_;
/**
* To be called when a mouse click occurs.
*
@ -146,6 +156,8 @@ private:
/** A copy from the terrain_map_->second for the current active group. */
t_translation::t_list terrains_;
std::string active_group_;
/**
* The editor_groups as defined in editor-groups.cfg.
*
@ -156,16 +168,7 @@ private:
std::set<t_translation::t_terrain> non_core_terrains_;
/**
* The group buttons behave like a radio group.
*
* This one points to the selected button, this value should not be 0
* otherwise things will fail. Thus should be set in constructor.
*/
gui::button *checked_group_btn_;
gui::button top_button_, bot_button_;
size_t button_x_, top_button_y_, bot_button_y_;
size_t button_x_; //, top_button_y_, bot_button_y_;
size_t nterrains_, nmax_terrains_, terrain_start_;
t_translation::t_terrain& selected_fg_terrain_;
t_translation::t_terrain& selected_bg_terrain_;

View file

@ -27,6 +27,7 @@
#include "../serialization/parser.hpp"
#include "../wml_exception.hpp"
#include "formula_string_utils.hpp"
#include <boost/regex.hpp>
@ -53,11 +54,11 @@ map_context::map_context(const editor_map& map)
{
}
map_context::map_context(const config& game_config, const std::string& filename)
map_context::map_context(const config& game_config, const std::string& filename, const display& disp)
: filename_(filename)
, map_data_key_()
, embedded_(false)
, map_(game_config)
, map_(game_config, disp)
, undo_stack_()
, redo_stack_()
, actions_since_save_(0)
@ -84,12 +85,12 @@ map_context::map_context(const config& game_config, const std::string& filename)
config file;
::read(file, map_string);
map_ = editor_map(game_config, file);
map_ = editor_map(game_config, file, disp);
return;
} catch (config::error&) {
}
boost::regex re("map_data\\s*=\\s*\"(.+?)\"");
boost::regex re("data\\s*=\\s*\"(.+?)\"");
boost::smatch m;
if (boost::regex_search(map_string, m, re, boost::regex_constants::match_not_dot_null)) {
boost::regex re2("\\{(.+?)\\}");
@ -119,7 +120,7 @@ map_context::map_context(const config& game_config, const std::string& filename)
throw editor_map_load_exception(filename, message);
}
map_ = editor_map::from_string(game_config, map_string); //throws on error
map_ = editor_map::from_string(game_config, map_string, disp); //throws on error
}
map_context::~map_context()
@ -221,9 +222,17 @@ void map_context::reset_starting_position_labels(display& disp)
bool map_context::save()
{
//TODO the return value of this method does not need to be bool.
//We either return true or there is an exception thrown.
config data;
config& map = data.add_child("map");
map_.write(map);
map_.write(data);
std::stringstream ss;
{
config_writer out(ss, false);
out.write(data);
}
try {
if (!is_embedded()) {
@ -233,16 +242,27 @@ bool map_context::save()
write_file(get_filename(), ss.str());
} else {
std::string map_string = read_file(get_filename());
boost::regex re("(.*map_data\\s*=\\s*\")(.+?)(\".*)");
boost::regex re("(.*)(map_data\\s*=\\s*\".+?\")(.*)");
boost::smatch m;
if (boost::regex_search(map_string, m, re, boost::regex_constants::match_not_dot_null)) {
std::stringstream ss;
ss << m[1];
ss << data;
ss << m[3];
write_file(get_filename(), ss.str());
std::stringstream ss2;
ss2 << m[1];
ss2 << ss.str();
ss2 << m[3];
write_file(get_filename(), ss2.str());
} else {
throw editor_map_save_exception(_("Could not save into scenario"));
//TODO that reg expression is still not working.
boost::regex re_maptag("(.*)([map].+?)([/map].*)");
boost::smatch match_maptag;
if (boost::regex_search(map_string, match_maptag, re_maptag, boost::regex_constants::match_not_dot_null)) {
std::stringstream ss3;
ss3 << match_maptag[1];
ss3 << ss.str();
ss3 << match_maptag[3];
write_file(get_filename(), ss3.str());
} else {
throw editor_map_save_exception(_("Could not save into scenario"));
}
}
}
clear_modified();

View file

@ -17,13 +17,14 @@
#define EDITOR_MAP_CONTEXT_HPP_INCLUDED
#include "editor_map.hpp"
#include "map_label.hpp"
#include <boost/utility.hpp>
namespace editor {
/**
* This class wraps around a map to provide a conscise interface for the editor to work with.
* This class wraps around a map to provide a concise interface for the editor to work with.
* The actual map object can change rapidly (be assigned to), the map context persists
* data (like the undo stacks) in this case. The functionality is here, not in editor_controller
* as e.g. the undo stack is part of the map, not the editor as a whole. This might allow many
@ -47,7 +48,7 @@ public:
* inside scenarios do not change the filename, but set the "embedded" flag
* instead.
*/
map_context(const config& game_config, const std::string& filename);
map_context(const config& game_config, const std::string& filename, const display& disp);
/**
* Map context destructor
@ -122,6 +123,8 @@ public:
void set_everything_changed();
bool everything_changed() const;
void set_labels(display& disp);
void clear_starting_position_labels(display& disp);
void set_starting_position_labels(display& disp);
@ -226,6 +229,7 @@ protected:
*/
editor_map map_;
/**
* Container type used to store actions in the undo and redo stacks
*/