Implemented the village ownership editor tool.

This commit is contained in:
Fabian Müller 2012-07-27 13:34:00 +00:00
parent 95a383e990
commit 179c251d96
16 changed files with 406 additions and 93 deletions

View file

@ -263,7 +263,7 @@
id=village_button_editor
image=villages_button_editor
items=editor-tool-village
tooltip= _ "Left mouse button sets the village ownership to the current side, right clears. Not implemented yet."
tooltip= _ "Left mouse button sets the village ownership to the current side, right clears."
tooltip_name_prepend=yes
rect="+6,=,+24,+24"
xanchor=right

View file

@ -639,9 +639,11 @@ set(wesnoth-main_SRC
editor/action/action.cpp
editor/action/action_label.cpp
editor/action/action_unit.cpp
editor/action/action_village.cpp
editor/action/mouse/mouse_action.cpp
editor/action/mouse/mouse_action_map_label.cpp
editor/action/mouse/mouse_action_unit.cpp
editor/action/mouse/mouse_action_village.cpp
editor/map/editor_map.cpp
editor/map/map_context.cpp
editor/map/map_fragment.cpp

View file

@ -219,9 +219,11 @@ wesnoth_sources = Split("""
editor/action/action.cpp
editor/action/action_unit.cpp
editor/action/action_label.cpp
editor/action/action_village.cpp
editor/action/mouse/mouse_action.cpp
editor/action/mouse/mouse_action_map_label.cpp
editor/action/mouse/mouse_action_unit.cpp
editor/action/mouse/mouse_action_village.cpp
editor/map/editor_map.cpp
editor/map/map_context.cpp
editor/map/map_fragment.cpp

View file

@ -121,6 +121,7 @@ display::display(unit_map* units, CVideo& video, const gamemap* map, const std::
keys_(),
animate_map_(true),
local_tod_light_(false),
flags_(),
activeTeam_(0),
drawing_buffer_(),
map_screenshot_(false),
@ -156,6 +157,8 @@ display::display(unit_map* units, CVideo& video, const gamemap* map, const std::
image::set_zoom(zoom_);
init_flags();
#if defined(__GLIBC__)
// Runtime checks for bug #17573
// Get glibc runtime version information
@ -176,6 +179,59 @@ display::~display()
singleton_ = NULL;
}
void display::init_flags() {
flags_.clear();
if (!teams_) return;
flags_.reserve(teams_->size());
std::vector<std::string> side_colors;
side_colors.reserve(teams_->size());
for(size_t i = 0; i != teams_->size(); ++i) {
std::string side_color = team::get_side_color_index(i+1);
side_colors.push_back(side_color);
std::string flag = (*teams_)[i].flag();
std::string old_rgb = game_config::flag_rgb;
std::string new_rgb = side_color;
if(flag.empty()) {
flag = game_config::images::flag;
}
LOG_DP << "Adding flag for team " << i << " from animation " << flag << "\n";
// Must recolor flag image
animated<image::locator> temp_anim;
std::vector<std::string> items = utils::split(flag);
std::vector<std::string>::const_iterator itor = items.begin();
for(; itor != items.end(); ++itor) {
const std::vector<std::string>& items = utils::split(*itor, ':');
std::string str;
int time;
if(items.size() > 1) {
str = items.front();
time = atoi(items.back().c_str());
} else {
str = *itor;
time = 100;
}
std::stringstream temp;
temp << str << "~RC(" << old_rgb << ">"<< new_rgb << ")";
image::locator flag_image(temp.str());
temp_anim.add_frame(time, flag_image);
}
flags_.push_back(temp_anim);
flags_.back().start_animation(rand()%flags_.back().get_end_time(), true);
}
image::set_team_colors(&side_colors);
}
struct is_energy_color {
bool operator()(Uint32 color) const { return (color&0xFF000000) > 0x10000000 &&
(color&0x00FF0000) < 0x00100000 &&
@ -183,6 +239,28 @@ struct is_energy_color {
(color&0x000000FF) < 0x00000010; }
};
surface display::get_flag(const map_location& loc)
{
t_translation::t_terrain terrain = get_map().get_terrain(loc);
if(!get_map().is_village(terrain)) {
return surface(NULL);
}
for(size_t i = 0; i != teams_->size(); ++i) {
if((*teams_)[i].owns_village(loc) &&
(!fogged(loc) || !(*teams_)[currentTeam_].is_enemy(i+1)))
{
flags_[i].update_last_draw_time();
const image::locator &image_flag = animate_map_ ?
flags_[i].get_current_frame() : flags_[i].get_first_frame();
return image::get_image(image_flag, image::TOD_COLORED);
}
}
return surface(NULL);
}
void display::set_team(size_t teamindex, bool show_everything)
{
assert(teamindex < teams_->size());
@ -2270,6 +2348,8 @@ void display::draw_hex(const map_location& loc) {
drawing_buffer_add(LAYER_GRID_BOTTOM, loc, xpos, ypos,
image::get_image(grid_bottom, image::TOD_COLORED));
}
// village-control flags.
drawing_buffer_add(LAYER_TERRAIN_BG, loc, xpos, ypos, get_flag(loc));
}
// Draw the time-of-day mask on top of the terrain in the hex.
@ -2676,6 +2756,16 @@ bool display::invalidate_locations_in_rect(const SDL_Rect& rect)
return result;
}
void display::invalidate_animations_location(const map_location& 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))) {
invalidate(loc);
}
}
}
void display::invalidate_animations()
{
new_animation_frame();

View file

@ -383,9 +383,9 @@ public:
/**
* Per-location invalidation called by invalidate_animations()
* defaults to no action, overridden by derived classes
* Extra game per-location invalidation (village ownership)
*/
virtual void invalidate_animations_location(const map_location& /*loc*/) {}
void invalidate_animations_location(const map_location& loc);
const gamemap& get_map() const { return *map_; }
@ -558,6 +558,11 @@ public:
private:
void read(const config& cfg);
public:
/** Inits the flag list and the team colors used by ~TC */
void init_flags();
private:
/**
* Finds the start and end rows on the energy bar image.
*
@ -725,6 +730,14 @@ protected:
/** Local cache for preferences "local_tod_lighting" */
bool local_tod_light_;
private:
// This surface must be freed by the caller
surface get_flag(const map_location& loc);
/** Animated flags for each team */
std::vector<animated<image::locator> > flags_;
public:
/**
* The layers to render something on. This value should never be stored

View file

@ -0,0 +1,97 @@
/* $Id: action_village.cpp 49125 2011-04-09 15:38:06Z fendrin $ */
/*
Copyright (C) 2008 - 2011 by Fabian Mueller <fabianmueller5@gmx.de>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
/**
* @file
* Editor label action classes
*/
#define GETTEXT_DOMAIN "wesnoth-editor"
#include "editor/action/action_village.hpp"
#include "editor/map/map_context.hpp"
namespace editor {
editor_action_village* editor_action_village::clone() const
{
return new editor_action_village(*this);
}
editor_action* editor_action_village::perform(map_context& mc) const
{
std::auto_ptr<editor_action> undo;
if(!mc.get_map().is_village(loc_)) return NULL;
std::vector<team>& teams = mc.get_map().get_teams();
team *t = unsigned(side_number_) < teams.size() ? &teams[side_number_] : NULL;
if (t && t->owns_village(loc_)) return NULL;
undo.reset(new editor_action_village_delete(loc_));
for(std::vector<team>::iterator i = teams.begin(); i != teams.end(); ++i) {
if (i->owns_village(loc_))
undo.reset(new editor_action_village(loc_, i->side() -1));
}
perform_without_undo(mc);
return undo.release();
}
void editor_action_village::perform_without_undo(map_context& mc) const
{
std::vector<team>& teams = mc.get_map().get_teams();
for(std::vector<team>::iterator i = teams.begin(); i != teams.end(); ++i) {
if (i->owns_village(loc_))
i->lose_village(loc_);
}
teams[side_number_].get_village(loc_, 0, false);
}
editor_action_village_delete* editor_action_village_delete::clone() const
{
return new editor_action_village_delete(*this);
}
editor_action* editor_action_village_delete::perform(map_context& mc) const
{
std::auto_ptr<editor_action> undo;
const std::vector<team>& teams = mc.get_map().get_teams();
for(std::vector<team>::const_iterator i = teams.begin(); i != teams.end(); ++i) {
if (i->owns_village(loc_)) {
perform_without_undo(mc);
undo.reset(new editor_action_village(loc_, i->side() -1));
}
}
return undo.release();
}
void editor_action_village_delete::perform_without_undo(map_context& mc) const
{
std::vector<team>& teams = mc.get_map().get_teams();
for(std::vector<team>::iterator i = teams.begin(); i != teams.end(); ++i) {
if (i->owns_village(loc_)) {
i->lose_village(loc_);
mc.add_changed_location(loc_);
}
}
}
} //end namespace editor

View file

@ -0,0 +1,72 @@
/* $Id: action_village.hpp 49121 2011-04-07 21:57:57Z fendrin $ */
/*
Copyright (C) 2008 - 2011 by Fabian Mueller <fabianmueller5@gmx.de>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
/**
* @file
* Editor action classes. Some important points:
* - This is a polymorphic hierarchy of classes, so actions are usually passed around
* as editor_action pointers
* - The pointers can, in general, be null. Always check for null before doing anything.
* The helper functions perform_ that take a pointer do that.
* - The perform() functions can throw when an error occurs. Use smart pointers if you
* need to ensure the pointer is deleted.
*/
#ifndef EDITOR_ACTION_VILLAGE_HPP
#define EDITOR_ACTION_VILLAGE_HPP
#include "action.hpp"
namespace editor {
/**
* Sets the ownership of a village to the current side.
*/
class editor_action_village : public editor_action_location
{
public:
editor_action_village(map_location loc, int side_number)
: editor_action_location(loc), side_number_(side_number)
{
}
editor_action_village* clone() const;
editor_action* perform(map_context& mc) const;
void perform_without_undo(map_context& mc) const;
const char* get_name() const { return "village"; }
private:
int side_number_;
};
/**
* Clears the ownership of a village.
*/
class editor_action_village_delete : public editor_action_location
{
public:
editor_action_village_delete(map_location loc)
: editor_action_location(loc)
{
}
editor_action_village_delete* clone() const;
editor_action* perform(map_context& mc) const;
void perform_without_undo(map_context& mc) const;
const char* get_name() const { return "village_delete"; }
};
} //end namespace editor
#endif

View file

@ -0,0 +1,50 @@
/* $Id: mouse_action_village.cpp 49182 2011-04-12 02:32:34Z fendrin $ */
/*
Copyright (C) 2008 - 2011 by Fabian Mueller <fabianmueller5@gmx.de>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
//TODO uncomment or remove
//#define GETTEXT_DOMAIN "wesnoth-editor"
#include "mouse_action_village.hpp"
#include "../action_village.hpp"
#include "../../editor_display.hpp"
namespace editor {
editor_action* mouse_action_village::up_left(editor_display& disp, int x, int y)
{
map_location hex = disp.hex_clicked_on(x, y);
if (!disp.get_map().on_board(hex)) return NULL;
if (!disp.get_map().is_village(hex)) return NULL;
return new editor_action_village(hex, disp.playing_team());
}
editor_action* mouse_action_village::up_right(editor_display& disp, int x, int y)
{
map_location hex = disp.hex_clicked_on(x, y);
if (!disp.get_map().on_board(hex)) return NULL;
if (!disp.get_map().is_village(hex)) return NULL;
return new editor_action_village_delete(hex);
}
void mouse_action_village::set_mouse_overlay(editor_display& /*disp*/)
{
//TODO
//set_mouse_overlay_image(disp, "editor/tool-overlay-village.png");
}
} //end namespace editor

View file

@ -0,0 +1,64 @@
/* $Id: mouse_action_village.hpp 49121 2011-04-07 21:57:57Z fendrin $ */
/*
Copyright (C) 2008 - 2011 by Fabian Mueller <fabianmueller5@gmx.de>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#ifndef EDITOR_MOUSE_ACTION_VILLAGE_HPP
#define EDITOR_MOUSE_ACTION_VILLAGE_HPP
#include "mouse_action.hpp"
class CKey;
class empty_palette;
namespace editor {
/**
* Editor mouse action class.
* Called by the editor tool to assign village ownership to defined sides.
*/
class mouse_action_village : public mouse_action
{
public:
mouse_action_village(const CKey& key, empty_palette& palette)
: mouse_action(palette, key)
{
}
/**
* No action.
*/
editor_action* click_left(editor_display& /*disp*/, int /*x*/, int /*y*/) {return NULL;}
/**
* If clicked on a village hex field, assigns the ownership of it to the current side.
*/
editor_action* up_left(editor_display& disp, int x, int y);
/**
* No action.
*/
editor_action* click_right(editor_display& /*disp*/, int /*x*/, int /*y*/) {return NULL;}
/**
* If clicked on a village hex field, unassigns it's ownership.
*/
editor_action* up_right(editor_display& disp, int x, int y);
virtual void set_mouse_overlay(editor_display& disp);
};
} //end namespace editor
#endif

View file

@ -149,6 +149,7 @@ void editor_controller::init_music(const config& game_config)
editor_controller::~editor_controller()
{
//TODO is not working like expected
// delete &toolkit_;
// delete toolkit_.get();
// delete context_manager_.get();
}
@ -291,6 +292,7 @@ bool editor_controller::can_execute_command(hotkey::HOTKEY_COMMAND command, int
case HOTKEY_EDITOR_TOOL_LABEL:
return true;
case HOTKEY_EDITOR_TOOL_UNIT:
case HOTKEY_EDITOR_TOOL_VILLAGE:
return !context_manager_->get_map().get_teams().empty();
case HOTKEY_EDITOR_CUT:
case HOTKEY_EDITOR_COPY:
@ -340,6 +342,7 @@ hotkey::ACTION_STATE editor_controller::get_action_state(hotkey::HOTKEY_COMMAND
case HOTKEY_EDITOR_TOOL_SELECT:
case HOTKEY_EDITOR_TOOL_STARTING_POSITION:
case HOTKEY_EDITOR_TOOL_UNIT:
case HOTKEY_EDITOR_TOOL_VILLAGE:
return toolkit_->is_mouse_action_set(command) ? ACTION_ON : ACTION_OFF;
case HOTKEY_EDITOR_DRAW_COORDINATES:
return gui_->get_draw_coordinates() ? ACTION_ON : ACTION_OFF;
@ -432,6 +435,7 @@ bool editor_controller::execute_command(hotkey::HOTKEY_COMMAND command, int inde
case HOTKEY_EDITOR_TOOL_STARTING_POSITION:
case HOTKEY_EDITOR_TOOL_LABEL:
case HOTKEY_EDITOR_TOOL_UNIT:
case HOTKEY_EDITOR_TOOL_VILLAGE:
toolkit_->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"
@ -497,6 +501,7 @@ bool editor_controller::execute_command(hotkey::HOTKEY_COMMAND command, int inde
return true;
case HOTKEY_EDITOR_SIDE_NEW:
context_manager_->get_map().new_side();
gui_->init_flags();
return true;
case HOTKEY_EDITOR_MAP_SAVE:
save_map();

View file

@ -67,6 +67,7 @@ public:
ec_.reload_map();
resources::state_of_game = &ec_.get_map().get_game_state();
ec_.gui().init_flags();
}
private:
context_manager& ec_;

View file

@ -19,6 +19,7 @@
#include "editor/action/mouse/mouse_action.hpp"
#include "editor/action/mouse/mouse_action_map_label.hpp"
#include "editor/action/mouse/mouse_action_unit.hpp"
#include "editor/action/mouse/mouse_action_village.hpp"
#include <boost/foreach.hpp>
@ -85,6 +86,8 @@ void editor_toolkit::init_mouse_actions(const config& game_config)
new mouse_action_map_label(key_, *palette_manager_->empty_palette_.get())));
mouse_actions_.insert(std::make_pair(hotkey::HOTKEY_EDITOR_TOOL_UNIT,
new mouse_action_unit(key_, *palette_manager_->unit_palette_.get())));
mouse_actions_.insert(std::make_pair(hotkey::HOTKEY_EDITOR_TOOL_VILLAGE,
new mouse_action_village(key_, *palette_manager_->empty_palette_.get())));
//TODO
// mouse_actions_.insert(std::make_pair(hotkey::HOTKEY_EDITOR_PASTE,

View file

@ -77,56 +77,9 @@ game_display::game_display(unit_map& units, CVideo& video, const gamemap& map,
reach_map_(),
reach_map_old_(),
reach_map_changed_(true),
game_mode_(RUNNING),
flags_()
game_mode_(RUNNING)
{
// Inits the flag list and the team colors used by ~TC
flags_.reserve(teams_->size());
std::vector<std::string> side_colors;
side_colors.reserve(teams_->size());
for(size_t i = 0; i != teams_->size(); ++i) {
std::string side_color = team::get_side_color_index(i+1);
side_colors.push_back(side_color);
std::string flag = (*teams_)[i].flag();
std::string old_rgb = game_config::flag_rgb;
std::string new_rgb = side_color;
if(flag.empty()) {
flag = game_config::images::flag;
}
LOG_DP << "Adding flag for team " << i << " from animation " << flag << "\n";
// Must recolor flag image
animated<image::locator> temp_anim;
std::vector<std::string> items = utils::split(flag);
std::vector<std::string>::const_iterator itor = items.begin();
for(; itor != items.end(); ++itor) {
const std::vector<std::string>& items = utils::split(*itor, ':');
std::string str;
int time;
if(items.size() > 1) {
str = items.front();
time = atoi(items.back().c_str());
} else {
str = *itor;
time = 100;
}
std::stringstream temp;
temp << str << "~RC(" << old_rgb << ">"<< new_rgb << ")";
image::locator flag_image(temp.str());
temp_anim.add_frame(time, flag_image);
}
flags_.push_back(temp_anim);
flags_.back().start_animation(rand()%flags_.back().get_end_time(), true);
}
image::set_team_colors(&side_colors);
clear_screen();
}
@ -340,8 +293,6 @@ void game_display::draw_hex(const map_location& loc)
image::get_image(overlays.first->second.image,image_type));
}
}
// village-control flags.
drawing_buffer_add(LAYER_TERRAIN_BG, loc, xpos, ypos, get_flag(loc));
}
// Draw reach_map information.
@ -600,27 +551,7 @@ std::vector<surface> game_display::footsteps_images(const map_location& loc)
return res;
}
surface game_display::get_flag(const map_location& loc)
{
t_translation::t_terrain terrain = get_map().get_terrain(loc);
if(!get_map().is_village(terrain)) {
return surface(NULL);
}
for(size_t i = 0; i != teams_->size(); ++i) {
if((*teams_)[i].owns_village(loc) &&
(!fogged(loc) || !(*teams_)[currentTeam_].is_enemy(i+1)))
{
flags_[i].update_last_draw_time();
const image::locator &image_flag = animate_map_ ?
flags_[i].get_current_frame() : flags_[i].get_first_frame();
return image::get_image(image_flag, image::TOD_COLORED);
}
}
return surface(NULL);
}
void game_display::highlight_reach(const pathfind::paths &paths_list)
{
@ -725,15 +656,6 @@ void game_display::float_label(const map_location& loc, const std::string& text,
font::add_floating_label(flabel);
}
void game_display::invalidate_animations_location(const map_location& 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))) {
invalidate(loc);
}
}
}
void game_display::invalidate_animations()
{

View file

@ -159,11 +159,6 @@ protected:
*/
void invalidate_animations();
/**
* Extra game per-location invalidation (village ownership)
*/
void invalidate_animations_location(const map_location& loc);
public:
/** A temporary unit that can be placed on the map.
@ -316,9 +311,6 @@ private:
void draw_sidebar();
// This surface must be freed by the caller
surface get_flag(const map_location& loc);
/// collection of units destined to be drawn but not put into the unit map
std::deque<unit*> fake_units_;
@ -387,8 +379,6 @@ private:
// For debug mode
static std::map<map_location, int> debugHighlights_;
/** Animated flags for each team */
std::vector<animated<image::locator> > flags_;
};

View file

@ -155,6 +155,8 @@ const struct {
N_("Label Tool"), false, hotkey::SCOPE_EDITOR },
{ hotkey::HOTKEY_EDITOR_TOOL_UNIT, "editor-tool-unit",
N_("Unit Tool"), false, hotkey::SCOPE_EDITOR },
{ hotkey::HOTKEY_EDITOR_TOOL_VILLAGE, "editor-tool-village",
N_("Village Tool"), false, hotkey::SCOPE_EDITOR },
{ hotkey::HOTKEY_EDITOR_BRUSH_NEXT, "editor-brush-next", N_("Next Brush"), false, hotkey::SCOPE_EDITOR },
{ hotkey::HOTKEY_EDITOR_BRUSH_DEFAULT, "editor-brush-default", N_("Default Brush"), false, hotkey::SCOPE_EDITOR },
{ hotkey::HOTKEY_EDITOR_CUT, "editor-cut", N_("Cut"), false, hotkey::SCOPE_EDITOR },

View file

@ -84,7 +84,7 @@ enum HOTKEY_COMMAND {
HOTKEY_EDITOR_TOOL_NEXT,
HOTKEY_EDITOR_TOOL_PAINT, HOTKEY_EDITOR_TOOL_FILL,
HOTKEY_EDITOR_TOOL_SELECT, HOTKEY_EDITOR_TOOL_STARTING_POSITION, HOTKEY_EDITOR_TOOL_LABEL,
HOTKEY_EDITOR_TOOL_UNIT,
HOTKEY_EDITOR_TOOL_UNIT, HOTKEY_EDITOR_TOOL_VILLAGE,
HOTKEY_EDITOR_BRUSH_NEXT, HOTKEY_EDITOR_BRUSH_DEFAULT,
HOTKEY_EDITOR_CUT, HOTKEY_EDITOR_COPY, HOTKEY_EDITOR_PASTE,
HOTKEY_EDITOR_EXPORT_SELECTION_COORDS,