added basic theme support
This commit is contained in:
parent
6f6454b145
commit
8b2f14bd01
15 changed files with 709 additions and 21 deletions
|
@ -1,24 +1,175 @@
|
|||
[theme]
|
||||
name=default
|
||||
[resolution]
|
||||
width=800
|
||||
height=600
|
||||
[main_map]
|
||||
rect=0,0,884,768
|
||||
xanchor=left
|
||||
yanchor=proportional
|
||||
[/main_map]
|
||||
[mini_map]
|
||||
rect=897,11,120,146
|
||||
rect=897,11,1017,157
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/mini_map]
|
||||
[panel]
|
||||
image=misc/rightside.png
|
||||
rect=884,0,140,430
|
||||
rect=884,0,1024,430
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/panel]
|
||||
[panel]
|
||||
image=misc/rightside-bottom.png
|
||||
rect=884,430,140,338
|
||||
rect=884,430,1024,768
|
||||
xanchor=right
|
||||
yanchor=top
|
||||
[/panel]
|
||||
|
||||
[status]
|
||||
#the time of day image
|
||||
[time_of_day]
|
||||
rect=897,167,1017,210
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/time_of_day]
|
||||
|
||||
#the game status
|
||||
[turn]
|
||||
font_size=14
|
||||
rect=900,220,1017,236
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
prefix=turn
|
||||
prefix_literal=" "
|
||||
[/turn]
|
||||
[gold]
|
||||
font_size=14
|
||||
rect=900,236,1017,252
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
prefix=gold
|
||||
prefix_literal=": "
|
||||
[/gold]
|
||||
[villages]
|
||||
font_size=14
|
||||
rect=900,252,1017,268
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
prefix=villages
|
||||
prefix_literal=": "
|
||||
[/villages]
|
||||
[num_units]
|
||||
font_size=14
|
||||
rect=900,268,1017,284
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
prefix=units
|
||||
prefix_literal=": "
|
||||
[/num_units]
|
||||
[upkeep]
|
||||
font_size=14
|
||||
rect=900,284,1017,300
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
prefix=upkeep
|
||||
prefix_literal=": "
|
||||
[/upkeep]
|
||||
[income]
|
||||
font_size=14
|
||||
rect=900,300,1017,316
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
prefix=income
|
||||
prefix_literal=": "
|
||||
[/income]
|
||||
[terrain]
|
||||
font_size=14
|
||||
rect=900,316,1017,332
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/terrain]
|
||||
[position]
|
||||
font_size=14
|
||||
rect=900,332,1017,348
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/position]
|
||||
|
||||
#unit stats here
|
||||
[unit_image]
|
||||
rect=897,375,948,426
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_image]
|
||||
[unit_description]
|
||||
font_size=16
|
||||
rect=897,432,1024,450
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_description]
|
||||
[unit_type]
|
||||
font_size=16
|
||||
rect=897,450,1024,468
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_type]
|
||||
[unit_level]
|
||||
font_size=12
|
||||
rect=897,468,1024,482
|
||||
prefix=level
|
||||
prefix_literal=" "
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_level]
|
||||
[unit_alignment]
|
||||
font_size=14
|
||||
rect=897,482,1024,498
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_alignment]
|
||||
[unit_traits]
|
||||
font_size=14
|
||||
rect=897,498,1024,514
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_traits]
|
||||
[unit_status]
|
||||
font_size=14
|
||||
rect=897,514,1024,530
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_status]
|
||||
[unit_moves]
|
||||
font_size=14
|
||||
rect=897,530,1024,546
|
||||
prefix=movement
|
||||
prefix_literal=": "
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_moves]
|
||||
[unit_hp]
|
||||
font_size=14
|
||||
rect=897,546,1024,562
|
||||
prefix=hp
|
||||
prefix_literal=": "
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_hp]
|
||||
[unit_xp]
|
||||
font_size=14
|
||||
rect=897,562,1024,578
|
||||
prefix=xp
|
||||
prefix_literal=": "
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_xp]
|
||||
[unit_weapons]
|
||||
font_size=12
|
||||
rect=897,578,1024,690
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_weapons]
|
||||
[/status]
|
||||
[/resolution]
|
||||
[/theme]
|
||||
|
|
|
@ -55,6 +55,7 @@ wesnoth_SOURCES = about.cpp \
|
|||
preferences.cpp \
|
||||
race.cpp \
|
||||
replay.cpp \
|
||||
reports.cpp \
|
||||
sdl_utils.cpp \
|
||||
show_dialog.cpp \
|
||||
sound.cpp \
|
||||
|
@ -105,6 +106,7 @@ wesnoth_SOURCES = about.cpp \
|
|||
preferences.hpp \
|
||||
race.hpp \
|
||||
replay.hpp \
|
||||
reports.hpp \
|
||||
scoped_resource.hpp \
|
||||
sdl_utils.hpp \
|
||||
show_dialog.hpp \
|
||||
|
|
|
@ -191,6 +191,7 @@ wesnoth_SOURCES = about.cpp \
|
|||
preferences.cpp \
|
||||
race.cpp \
|
||||
replay.cpp \
|
||||
reports.cpp \
|
||||
sdl_utils.cpp \
|
||||
show_dialog.cpp \
|
||||
sound.cpp \
|
||||
|
@ -241,6 +242,7 @@ wesnoth_SOURCES = about.cpp \
|
|||
preferences.hpp \
|
||||
race.hpp \
|
||||
replay.hpp \
|
||||
reports.hpp \
|
||||
scoped_resource.hpp \
|
||||
sdl_utils.hpp \
|
||||
show_dialog.hpp \
|
||||
|
@ -295,6 +297,7 @@ wesnoth_editor_SOURCES = editor/editor.cpp \
|
|||
preferences.cpp \
|
||||
race.cpp \
|
||||
replay.cpp \
|
||||
reports.cpp \
|
||||
sdl_utils.cpp \
|
||||
show_dialog.cpp \
|
||||
sound.cpp \
|
||||
|
@ -338,6 +341,7 @@ wesnoth_editor_SOURCES = editor/editor.cpp \
|
|||
preferences.hpp \
|
||||
race.hpp \
|
||||
replay.hpp \
|
||||
reports.hpp \
|
||||
sdl_utils.hpp \
|
||||
show_dialog.hpp \
|
||||
sound.hpp \
|
||||
|
@ -426,7 +430,8 @@ am__depfiles_maybe = depfiles
|
|||
@AMDEP_TRUE@ ./$(DEPDIR)/network.Po ./$(DEPDIR)/pathfind.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/playlevel.Po ./$(DEPDIR)/playturn.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/preferences.Po ./$(DEPDIR)/race.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/replay.Po ./$(DEPDIR)/sdl_utils.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/replay.Po ./$(DEPDIR)/reports.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/sdl_utils.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/show_dialog.Po ./$(DEPDIR)/slider.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/sound.Po ./$(DEPDIR)/team.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/terrain.Po ./$(DEPDIR)/textbox.Po \
|
||||
|
|
136
src/display.cpp
136
src/display.cpp
|
@ -84,6 +84,8 @@ namespace {
|
|||
const size_t SideBarGameStatus_y = 220;
|
||||
const size_t TimeOfDay_x = 13;
|
||||
const size_t TimeOfDay_y = 167;
|
||||
|
||||
const SDL_Rect empty_rect = {0,0,0,0};
|
||||
}
|
||||
|
||||
display::display(unit_map& units, CVideo& video, const gamemap& map,
|
||||
|
@ -97,8 +99,10 @@ display::display(unit_map& units, CVideo& video, const gamemap& map,
|
|||
invalidateGameStatus_(true), panelsDrawn_(false),
|
||||
currentTeam_(0), activeTeam_(0), updatesLocked_(0),
|
||||
turbo_(false), grid_(false), sidebarScaling_(1.0),
|
||||
theme_(theme_cfg)
|
||||
theme_(theme_cfg,screen_area())
|
||||
{
|
||||
std::fill(reportRects_,reportRects_+reports::NUM_REPORTS,empty_rect);
|
||||
|
||||
new_turn();
|
||||
|
||||
image::set_zoom(zoom_);
|
||||
|
@ -423,8 +427,18 @@ void display::redraw_everything()
|
|||
if(update_locked() || teams_.empty())
|
||||
return;
|
||||
|
||||
bounds_check_position();
|
||||
|
||||
for(size_t n = 0; n != reports::NUM_REPORTS; ++n) {
|
||||
reportRects_[n] = empty_rect;
|
||||
reportSurfaces_[n].assign(NULL);
|
||||
reports_[n] = reports::report();
|
||||
}
|
||||
|
||||
tooltips::clear_tooltips();
|
||||
|
||||
theme_.set_resolution(screen_area());
|
||||
|
||||
panelsDrawn_ = false;
|
||||
invalidate_all();
|
||||
draw(true,true);
|
||||
|
@ -442,6 +456,8 @@ void draw_panel(SDL_Surface* target, const theme::panel& panel)
|
|||
surf.assign(scale_surface(surf.get(),loc.w,loc.h));
|
||||
}
|
||||
|
||||
std::cerr << "drawing panel " << loc.x << "," << loc.y << "," << loc.w << "," << loc.h << "\n";
|
||||
|
||||
SDL_BlitSurface(surf.get(),NULL,target,&loc);
|
||||
update_rect(loc);
|
||||
}
|
||||
|
@ -551,9 +567,9 @@ void display::draw_sidebar()
|
|||
}
|
||||
|
||||
if(i != units_.end() && !fogged(i->first.x,i->first.y)) {
|
||||
draw_unit_details(mapx()+SideBarText_x,SideBarUnit_y,selectedHex_,
|
||||
i->second,unitDescriptionRect_,
|
||||
mapx()+SideBarText_x,SideBarUnitProfile_y);
|
||||
for(size_t r = reports::UNIT_REPORTS_BEGIN; r != reports::UNIT_REPORTS_END; ++r) {
|
||||
draw_report(reports::TYPE(r));
|
||||
}
|
||||
}
|
||||
|
||||
invalidateUnit_ = false;
|
||||
|
@ -570,6 +586,11 @@ void display::draw_game_status(int x, int y)
|
|||
if(teams_.empty())
|
||||
return;
|
||||
|
||||
for(size_t r = reports::STATUS_REPORTS_BEGIN; r != reports::STATUS_REPORTS_END; ++r) {
|
||||
draw_report(reports::TYPE(r));
|
||||
}
|
||||
|
||||
/*
|
||||
SDL_Rect rect;
|
||||
rect.x = x;
|
||||
rect.y = y;
|
||||
|
@ -673,6 +694,112 @@ void display::draw_game_status(int x, int y)
|
|||
gameStatusRect_ = font::draw_text(this,clipRect,13,font::NORMAL_COLOUR,
|
||||
details.str(),x,y);
|
||||
update_rect(gameStatusRect_);
|
||||
*/
|
||||
}
|
||||
|
||||
void display::draw_report(reports::TYPE report_num)
|
||||
{
|
||||
if(!team_valid())
|
||||
return;
|
||||
|
||||
const theme::status_item* const item = theme_.get_status_item(reports::report_name(report_num));
|
||||
if(item != NULL) {
|
||||
const reports::report& report = reports::generate_report(report_num,map_,units_,
|
||||
teams_[viewing_team()],currentTeam_+1,
|
||||
selectedHex_,mouseoverHex_,status_);
|
||||
|
||||
SDL_Rect& rect = reportRects_[report_num];
|
||||
const SDL_Rect& new_rect = item->location(screen_area());
|
||||
|
||||
//report and its location is unchanged since last time. Do nothing.
|
||||
if(rect == new_rect && reports_[report_num] == report)
|
||||
return;
|
||||
|
||||
reports_[report_num] = report;
|
||||
|
||||
scoped_sdl_surface& surf = reportSurfaces_[report_num];
|
||||
|
||||
if(surf != NULL) {
|
||||
SDL_BlitSurface(surf,NULL,screen_.getSurface(),&rect);
|
||||
update_rect(rect);
|
||||
}
|
||||
|
||||
//if the rectangle has just changed, assign the surface to it
|
||||
if(new_rect != rect || surf == NULL) {
|
||||
surf.assign(NULL);
|
||||
rect = new_rect;
|
||||
|
||||
//if the rectangle is present, and we are blitting text, then
|
||||
//we need to backup the surface. (Images generally won't need backing
|
||||
//up unless they are transperant, but that is done later)
|
||||
if(rect.w > 0 && rect.h > 0 && report.text.empty() == false) {
|
||||
surf.assign(get_surface_portion(screen_.getSurface(),rect));
|
||||
if(reportSurfaces_[report_num] == NULL) {
|
||||
std::cerr << "Could not backup background for report!\n";
|
||||
}
|
||||
}
|
||||
|
||||
update_rect(rect);
|
||||
}
|
||||
|
||||
tooltips::clear_tooltips(rect);
|
||||
|
||||
if(report.text.empty() == false) {
|
||||
std::string str = item->prefix();
|
||||
|
||||
int nchop;
|
||||
|
||||
//if there are formatting directives on the front of the report,
|
||||
//move them to the front of the string
|
||||
for(nchop = 0; nchop != report.text.size() && font::is_format_char(report.text[nchop]); ++nchop) {
|
||||
str.insert(str.begin(),report.text[0]);
|
||||
}
|
||||
|
||||
str += report.text.substr(nchop) + item->postfix();
|
||||
|
||||
font::draw_text(this,rect,item->font_size(),font::NORMAL_COLOUR,str,rect.x,rect.y);
|
||||
}
|
||||
|
||||
if(report.image.empty() == false) {
|
||||
|
||||
scoped_sdl_surface img(image::get_image(report.image,image::UNSCALED));
|
||||
SDL_Rect visible_area = get_non_transperant_portion(img);
|
||||
if(visible_area.x != 0 || visible_area.y != 0 || visible_area.w != img->w || visible_area.h != img->h) {
|
||||
if(visible_area.w == 0 || visible_area.h == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//since we're blitting a transperant image, we need to back up
|
||||
//the surface for later restoration
|
||||
surf.assign(get_surface_portion(screen_.getSurface(),rect));
|
||||
|
||||
SDL_Rect target = rect;
|
||||
if(visible_area.w > rect.w || visible_area.h > rect.h) {
|
||||
img.assign(get_surface_portion(img,visible_area));
|
||||
img.assign(scale_surface(img,rect.w,rect.h));
|
||||
visible_area.x = 0;
|
||||
visible_area.y = 0;
|
||||
visible_area.w = img->w;
|
||||
visible_area.h = img->h;
|
||||
} else {
|
||||
target.x = rect.x + (rect.w - visible_area.w)/2;
|
||||
target.y = rect.y + (rect.h - visible_area.h)/2;
|
||||
target.w = visible_area.w;
|
||||
target.h = visible_area.h;
|
||||
}
|
||||
|
||||
SDL_BlitSurface(img,&visible_area,screen_.getSurface(),&target);
|
||||
} else {
|
||||
if(img->w != rect.w || img->h != rect.h) {
|
||||
img.assign(scale_surface(img,rect.w,rect.h));
|
||||
}
|
||||
|
||||
SDL_BlitSurface(img,NULL,screen_.getSurface(),&rect);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reportSurfaces_[report_num].assign(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void display::draw_unit_details(int x, int y, const gamemap::location& loc,
|
||||
|
@ -682,6 +809,7 @@ void display::draw_unit_details(int x, int y, const gamemap::location& loc,
|
|||
if(teams_.empty())
|
||||
return;
|
||||
|
||||
|
||||
tooltips::clear_tooltips(description_rect);
|
||||
|
||||
SDL_Rect clipRect = clip_rect != NULL ? *clip_rect : screen_area();
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "key.hpp"
|
||||
#include "map.hpp"
|
||||
#include "pathfind.hpp"
|
||||
#include "reports.hpp"
|
||||
#include "team.hpp"
|
||||
#include "theme.hpp"
|
||||
#include "unit.hpp"
|
||||
|
@ -296,6 +297,11 @@ private:
|
|||
SDL_Rect unitDescriptionRect_;
|
||||
SDL_Rect unitProfileRect_;
|
||||
|
||||
void draw_report(reports::TYPE report_num);
|
||||
SDL_Rect reportRects_[reports::NUM_REPORTS];
|
||||
scoped_sdl_surface reportSurfaces_[reports::NUM_REPORTS];
|
||||
reports::report reports_[reports::NUM_REPORTS];
|
||||
|
||||
void bounds_check_position();
|
||||
|
||||
std::vector<SDL_Surface*> getAdjacentTerrain(int x, int y, image::TYPE type);
|
||||
|
|
13
src/font.cpp
13
src/font.cpp
|
@ -290,4 +290,17 @@ SDL_Rect draw_text(display* gui, const SDL_Rect& area, int size,
|
|||
return res;
|
||||
}
|
||||
|
||||
bool is_format_char(char c)
|
||||
{
|
||||
switch(c) {
|
||||
case '+':
|
||||
case '-':
|
||||
case '#':
|
||||
case '@':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -58,6 +58,8 @@ SDL_Rect draw_text(display* gui, const SDL_Rect& area, int size,
|
|||
int x, int y, SDL_Surface* bg=NULL,
|
||||
bool use_tooltips=false, MARKUP use_markup=USE_MARKUP);
|
||||
|
||||
bool is_format_char(char c);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
198
src/reports.cpp
Normal file
198
src/reports.cpp
Normal file
|
@ -0,0 +1,198 @@
|
|||
#include "actions.hpp"
|
||||
#include "game_config.hpp"
|
||||
#include "language.hpp"
|
||||
#include "reports.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
|
||||
namespace {
|
||||
const std::string report_names[] = { "unit_description", "unit_type", "unit_level",
|
||||
"unit_traits","unit_status","unit_alignment","unit_hp","unit_xp","unit_moves",
|
||||
"unit_weapons","unit_image","unit_profile","time_of_day",
|
||||
"turn","gold","villages","num_units","upkeep", "expenses",
|
||||
"income", "terrain", "position" };
|
||||
}
|
||||
|
||||
namespace reports {
|
||||
|
||||
const std::string& report_name(TYPE type)
|
||||
{
|
||||
assert(sizeof(report_names)/sizeof(*report_names) == NUM_REPORTS);
|
||||
assert(type < NUM_REPORTS);
|
||||
|
||||
return report_names[type];
|
||||
}
|
||||
|
||||
report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
||||
const team& current_team, int current_side,
|
||||
const gamemap::location& loc, const gamemap::location& mouseover,
|
||||
const gamestatus& status, const std::string* format_string)
|
||||
{
|
||||
unit_map::const_iterator u = units.end();
|
||||
|
||||
if(type >= UNIT_REPORTS_BEGIN && type < UNIT_REPORTS_END) {
|
||||
u = units.find(mouseover);
|
||||
if(u == units.end()) {
|
||||
u = units.find(loc);
|
||||
if(u == units.end()) {
|
||||
return report();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream str;
|
||||
|
||||
switch(type) {
|
||||
case UNIT_DESCRIPTION:
|
||||
return report(u->second.description());
|
||||
case UNIT_TYPE:
|
||||
return report(u->second.type().language_name());
|
||||
case UNIT_LEVEL:
|
||||
str << u->second.type().level();
|
||||
break;
|
||||
case UNIT_TRAITS:
|
||||
return report(u->second.traits_description());
|
||||
case UNIT_STATUS:
|
||||
if(map.on_board(loc) && u->second.invisible(map.underlying_terrain(map[loc.x][loc.y])))
|
||||
return report("@" + string_table["invisible"]);
|
||||
else if(u->second.has_flag("slowed"))
|
||||
return report("#" + string_table["slowed"]);
|
||||
else if(u->second.has_flag("poisoned"))
|
||||
return report("#" + string_table["poisoned"]);
|
||||
else
|
||||
return report(string_table["healthy"]);
|
||||
case UNIT_ALIGNMENT:
|
||||
return report(unit_type::alignment_description(u->second.type().alignment()));
|
||||
case UNIT_HP:
|
||||
if(u->second.hitpoints() <= u->second.max_hitpoints()/3)
|
||||
str << "#";
|
||||
else if(u->second.hitpoints() > 2*(u->second.max_hitpoints()/3))
|
||||
str << "@";
|
||||
|
||||
str << u->second.hitpoints()
|
||||
<< "/" << u->second.max_hitpoints() << "\n";
|
||||
|
||||
break;
|
||||
case UNIT_XP:
|
||||
if(u->second.type().advances_to().empty()) {
|
||||
str << u->second.experience() << "/-";
|
||||
} else {
|
||||
//if killing a unit of the same level as us lets us advance, display in 'good' colour
|
||||
if(u->second.max_experience() - u->second.experience() <= game_config::kill_experience*u->second.type().level()) {
|
||||
str << "@";
|
||||
}
|
||||
|
||||
str << u->second.experience() << "/" << u->second.max_experience();
|
||||
}
|
||||
|
||||
break;
|
||||
case UNIT_MOVES:
|
||||
str << u->second.movement_left() << "/" << u->second.total_movement();
|
||||
break;
|
||||
case UNIT_WEAPONS: {
|
||||
const std::vector<attack_type>& attacks = u->second.attacks();
|
||||
for(std::vector<attack_type>::const_iterator at_it = attacks.begin();
|
||||
at_it != attacks.end(); ++at_it) {
|
||||
const std::string& lang_weapon = string_table["weapon_name_" + at_it->name()];
|
||||
const std::string& lang_type = string_table["weapon_type_" + at_it->type()];
|
||||
const std::string& lang_special = string_table["weapon_special_" + at_it->special()];
|
||||
str << (lang_weapon.empty() ? at_it->name():lang_weapon) << " ("
|
||||
<< (lang_type.empty() ? at_it->type():lang_type) << ")\n"
|
||||
<< (lang_special.empty() ? at_it->special():lang_special) << "\n"
|
||||
<< at_it->damage() << "-" << at_it->num_attacks() << " -- "
|
||||
<< (at_it->range() == attack_type::SHORT_RANGE ?
|
||||
string_table["short_range"] :
|
||||
string_table["long_range"]);
|
||||
|
||||
if(at_it->hexes() > 1) {
|
||||
str << " (" << at_it->hexes() << ")";
|
||||
}
|
||||
|
||||
str << "\n";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case UNIT_IMAGE:
|
||||
return report("",u->second.type().image());
|
||||
case UNIT_PROFILE:
|
||||
return report("",u->second.type().image_profile());
|
||||
case TIME_OF_DAY:
|
||||
return report("",timeofday_at(status,units,mouseover).image);
|
||||
case TURN:
|
||||
str << status.turn() << "/" << status.number_of_turns() << "\n";
|
||||
break;
|
||||
case GOLD:
|
||||
str << current_team.gold();
|
||||
break;
|
||||
case VILLAGES: {
|
||||
const team_data data = calculate_team_data(current_team,current_side,units);
|
||||
str << data.villages;
|
||||
|
||||
break;
|
||||
}
|
||||
case NUM_UNITS: {
|
||||
str << team_units(units,current_side);
|
||||
break;
|
||||
}
|
||||
case UPKEEP: {
|
||||
str << team_upkeep(units,current_side);
|
||||
break;
|
||||
}
|
||||
case EXPENSES: {
|
||||
const team_data data = calculate_team_data(current_team,current_side,units);
|
||||
str << data.expenses;
|
||||
break;
|
||||
}
|
||||
case INCOME: {
|
||||
const team_data data = calculate_team_data(current_team,current_side,units);
|
||||
str << data.net_income;
|
||||
break;
|
||||
}
|
||||
case TERRAIN: {
|
||||
if(!map.on_board(mouseover) || current_team.shrouded(mouseover.x,mouseover.y))
|
||||
break;
|
||||
|
||||
const gamemap::TERRAIN terrain = map.get_terrain(mouseover);
|
||||
const std::string& name = map.terrain_name(terrain);
|
||||
const std::string& underlying_name = map.underlying_terrain_name(terrain);
|
||||
|
||||
str << translate_string(name);
|
||||
|
||||
if(underlying_name != name) {
|
||||
str << " (" << translate_string(underlying_name) << ")";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case POSITION: {
|
||||
if(!map.on_board(mouseover))
|
||||
break;
|
||||
|
||||
str << (mouseover.x+1) << ", " << (mouseover.y+1);
|
||||
|
||||
u = units.find(mouseover);
|
||||
if(u == units.end() || current_team.shrouded(mouseover.x,mouseover.y))
|
||||
break;
|
||||
|
||||
const gamemap::TERRAIN terrain = map[mouseover.x][mouseover.y];
|
||||
|
||||
const int move_cost = u->second.movement_cost(map,terrain);
|
||||
const int defense = 100 - u->second.defense_modifier(map,terrain);
|
||||
|
||||
if(move_cost > 10) {
|
||||
str << " (-)";
|
||||
} else {
|
||||
str << " (" << defense << "%," << move_cost << ")";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return report(str.str());
|
||||
}
|
||||
|
||||
}
|
42
src/reports.hpp
Normal file
42
src/reports.hpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#ifndef REPORTS_HPP_INCLUDED
|
||||
#define REPORTS_HPP_INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "gamestatus.hpp"
|
||||
#include "map.hpp"
|
||||
#include "team.hpp"
|
||||
#include "unit.hpp"
|
||||
|
||||
//this module is responsible for outputting textual reports of
|
||||
//various game and unit statistics
|
||||
namespace reports {
|
||||
|
||||
enum TYPE { UNIT_DESCRIPTION, UNIT_TYPE, UNIT_LEVEL, UNIT_TRAITS, UNIT_STATUS,
|
||||
UNIT_ALIGNMENT, UNIT_HP, UNIT_XP, UNIT_MOVES, UNIT_WEAPONS,
|
||||
UNIT_IMAGE, UNIT_PROFILE, TIME_OF_DAY,
|
||||
TURN, GOLD, VILLAGES, NUM_UNITS, UPKEEP, EXPENSES, INCOME, TERRAIN, POSITION,
|
||||
NUM_REPORTS};
|
||||
|
||||
enum { UNIT_REPORTS_BEGIN=UNIT_DESCRIPTION, UNIT_REPORTS_END=UNIT_PROFILE+1 };
|
||||
enum { STATUS_REPORTS_BEGIN=TIME_OF_DAY, STATUS_REPORTS_END=NUM_REPORTS};
|
||||
|
||||
const std::string& report_name(TYPE type);
|
||||
|
||||
struct report {
|
||||
report() {}
|
||||
explicit report(const std::string& text) : text(text) {}
|
||||
report(const std::string& text, const std::string& image) : text(text), image(image) {}
|
||||
bool empty() const { return text.empty() && image.empty(); }
|
||||
bool operator==(const report& o) const { return o.text == text && o.image == image; }
|
||||
bool operator!=(const report& o) const { return !(o == *this); }
|
||||
std::string text, image;
|
||||
};
|
||||
|
||||
report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
||||
const team& current_team, int current_side,
|
||||
const gamemap::location& loc, const gamemap::location& mouseover,
|
||||
const gamestatus& status, const std::string* format_string=NULL);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -67,7 +67,7 @@ public:
|
|||
* @ param res This is the resource to be managed
|
||||
* @ param rel This is the functor to release the object
|
||||
*/
|
||||
scoped_resource(resource_type res,release_type rel=release_type())
|
||||
scoped_resource(resource_type res=resource_type(),release_type rel=release_type())
|
||||
: resource(res), release(rel) {}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
#include "game.hpp"
|
||||
|
@ -101,7 +102,7 @@ void adjust_surface_colour(SDL_Surface* surface, int r, int g, int b)
|
|||
|
||||
SDL_Surface* get_surface_portion(SDL_Surface* src, SDL_Rect& area)
|
||||
{
|
||||
if(area.x + area.w >= src->w || area.y + area.h >= src->h)
|
||||
if(area.x + area.w > src->w || area.y + area.h > src->h)
|
||||
return NULL;
|
||||
|
||||
const SDL_PixelFormat* const fmt = src->format;
|
||||
|
@ -116,6 +117,94 @@ SDL_Surface* get_surface_portion(SDL_Surface* src, SDL_Rect& area)
|
|||
return dst;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
const unsigned short max_pixel = 0xFFFF;
|
||||
|
||||
struct not_alpha
|
||||
{
|
||||
not_alpha(SDL_PixelFormat& format) : fmt_(format) {}
|
||||
|
||||
bool operator()(unsigned short pixel) const {
|
||||
return pixel != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
SDL_PixelFormat& fmt_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
SDL_Rect get_non_transperant_portion(const SDL_Surface* surf)
|
||||
{
|
||||
const not_alpha calc(*(surf->format));
|
||||
const unsigned short* const pixels = reinterpret_cast<const unsigned short*>(surf->pixels);
|
||||
const size_t padding = is_odd(surf->w) ? 1:0;
|
||||
SDL_Rect res = {0,0,0,0};
|
||||
size_t n;
|
||||
for(n = 0; n != surf->h; ++n) {
|
||||
const unsigned short* const start_row = pixels + n*(surf->w+padding);
|
||||
const unsigned short* const end_row = start_row + surf->w;
|
||||
|
||||
if(std::find_if(start_row,end_row,calc) != end_row)
|
||||
break;
|
||||
}
|
||||
|
||||
res.y = n;
|
||||
|
||||
for(n = 0; n != surf->h-res.y; ++n) {
|
||||
const unsigned short* const start_row = pixels + (surf->h-n-1)*(surf->w+padding);
|
||||
const unsigned short* const end_row = start_row + surf->w;
|
||||
|
||||
if(std::find_if(start_row,end_row,calc) != end_row)
|
||||
break;
|
||||
}
|
||||
|
||||
//the height is the height of the surface, minus the distance from the top and the
|
||||
//distance from the bottom
|
||||
res.h = surf->h - res.y - n;
|
||||
|
||||
for(n = 0; n != surf->w; ++n) {
|
||||
size_t y;
|
||||
for(y = 0; y != surf->h; ++y) {
|
||||
const unsigned short pixel = pixels[y*(surf->w+padding) + n];
|
||||
if(calc(pixel))
|
||||
break;
|
||||
}
|
||||
|
||||
if(y != surf->h)
|
||||
break;
|
||||
}
|
||||
|
||||
res.x = n;
|
||||
|
||||
for(n = 0; n != surf->w-res.x; ++n) {
|
||||
size_t y;
|
||||
for(y = 0; y != surf->h; ++y) {
|
||||
const unsigned short pixel = pixels[y*(surf->w+padding) + surf->w - n - 1];
|
||||
if(calc(pixel))
|
||||
break;
|
||||
}
|
||||
|
||||
if(y != surf->h)
|
||||
break;
|
||||
}
|
||||
|
||||
res.w = surf->w - res.x - n;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool operator==(const SDL_Rect& a, const SDL_Rect& b)
|
||||
{
|
||||
return a.x == b.x && a.y == b.y && a.w == b.w && a.h == b.h;
|
||||
}
|
||||
|
||||
bool operator!=(const SDL_Rect& a, const SDL_Rect& b)
|
||||
{
|
||||
return !operator==(a,b);
|
||||
}
|
||||
|
||||
surface_restorer::surface_restorer(SDL_Surface* surface, SDL_Rect& rect)
|
||||
: target_(surface), rect_(rect), surface_(NULL)
|
||||
{
|
||||
|
|
|
@ -47,7 +47,10 @@ void adjust_surface_colour(SDL_Surface* surface, int r, int g, int b);
|
|||
|
||||
SDL_Surface* get_surface_portion(SDL_Surface* src, SDL_Rect& rect);
|
||||
|
||||
SDL_Surface *rotate( SDL_Surface *s, float ang );
|
||||
SDL_Rect get_non_transperant_portion(const SDL_Surface* surf);
|
||||
|
||||
bool operator==(const SDL_Rect& a, const SDL_Rect& b);
|
||||
bool operator!=(const SDL_Rect& a, const SDL_Rect& b);
|
||||
|
||||
struct pixel_data
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "language.hpp"
|
||||
#include "sdl_utils.hpp"
|
||||
#include "theme.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
|
@ -21,26 +22,33 @@ namespace {
|
|||
rect.y = atoi(items[1].c_str());
|
||||
|
||||
if(items.size() >= 3)
|
||||
rect.w = atoi(items[2].c_str());
|
||||
rect.w = atoi(items[2].c_str()) - rect.x;
|
||||
|
||||
if(items.size() >= 4)
|
||||
rect.h = atoi(items[3].c_str());
|
||||
rect.h = atoi(items[3].c_str()) - rect.y;
|
||||
|
||||
return rect;
|
||||
}
|
||||
}
|
||||
|
||||
theme::object::object() : loc_(empty_rect),relative_loc_(empty_rect),xanchor_(), yanchor_()
|
||||
theme::object::object() : loc_(empty_rect), relative_loc_(empty_rect),
|
||||
last_screen_(empty_rect), xanchor_(), yanchor_()
|
||||
{}
|
||||
|
||||
theme::object::object(const config& cfg)
|
||||
: loc_(read_rect(cfg)), relative_loc_(empty_rect),
|
||||
last_screen_(empty_rect),
|
||||
xanchor_(read_anchor(cfg["xanchor"])),
|
||||
yanchor_(read_anchor(cfg["yanchor"]))
|
||||
{}
|
||||
|
||||
SDL_Rect& theme::object::location(const SDL_Rect& screen) const
|
||||
{
|
||||
if(last_screen_ == screen)
|
||||
return relative_loc_;
|
||||
|
||||
last_screen_ = screen;
|
||||
|
||||
switch(xanchor_) {
|
||||
case FIXED:
|
||||
relative_loc_.x = loc_.x;
|
||||
|
@ -48,7 +56,7 @@ SDL_Rect& theme::object::location(const SDL_Rect& screen) const
|
|||
break;
|
||||
case TOP_ANCHORED:
|
||||
relative_loc_.x = loc_.x;
|
||||
relative_loc_.w = screen.w - (XDim - loc_.w) - loc_.x;
|
||||
relative_loc_.w = screen.w - (XDim - loc_.w);
|
||||
break;
|
||||
case BOTTOM_ANCHORED:
|
||||
relative_loc_.x = screen.w - (XDim - loc_.x);
|
||||
|
@ -69,7 +77,7 @@ SDL_Rect& theme::object::location(const SDL_Rect& screen) const
|
|||
break;
|
||||
case TOP_ANCHORED:
|
||||
relative_loc_.y = loc_.y;
|
||||
relative_loc_.h = screen.h - (YDim - loc_.h) - loc_.h;
|
||||
relative_loc_.h = screen.h - (YDim - loc_.h);
|
||||
break;
|
||||
case BOTTOM_ANCHORED:
|
||||
relative_loc_.y = screen.h - (YDim - loc_.y);
|
||||
|
@ -186,8 +194,44 @@ const std::string& theme::panel::image() const
|
|||
return image_;
|
||||
}
|
||||
|
||||
theme::theme(const config& cfg)
|
||||
theme::theme(const config& cfg, const SDL_Rect& screen) : cfg_(cfg)
|
||||
{
|
||||
set_resolution(screen);
|
||||
}
|
||||
|
||||
bool theme::set_resolution(const SDL_Rect& screen)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
const config::child_list& resolutions = cfg_.get_children("resolution");
|
||||
int current_rating = 1000000;
|
||||
config::child_list::const_iterator i, current = resolutions.end();
|
||||
for(i = resolutions.begin(); i != resolutions.end(); ++i) {
|
||||
const int width = atoi((**i)["width"].c_str());
|
||||
const int height = atoi((**i)["height"].c_str());
|
||||
if(screen.w >= width && screen.h >= height) {
|
||||
std::cerr << "loading theme: " << width << "," << height << "\n";
|
||||
current = i;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
|
||||
const int rating = width*height;
|
||||
if(rating < current_rating) {
|
||||
current = i;
|
||||
current_rating = rating;
|
||||
}
|
||||
}
|
||||
|
||||
if(current == resolutions.end())
|
||||
return false;
|
||||
|
||||
panels_.clear();
|
||||
labels_.clear();
|
||||
status_.clear();
|
||||
|
||||
const config& cfg = **current;
|
||||
|
||||
const config* const main_map_cfg = cfg.child("main_map");
|
||||
if(main_map_cfg != NULL) {
|
||||
main_map_ = object(*main_map_cfg);
|
||||
|
@ -213,9 +257,11 @@ theme::theme(const config& cfg)
|
|||
}
|
||||
|
||||
const config::child_list& label_list = cfg.get_children("label");
|
||||
for(config::child_list::const_iterator i = label_list.begin(); i != label_list.end(); ++i) {
|
||||
labels_.push_back(label(**i));
|
||||
for(config::child_list::const_iterator lb = label_list.begin(); lb != label_list.end(); ++lb) {
|
||||
labels_.push_back(label(**lb));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const std::vector<theme::panel>& theme::panels() const
|
||||
|
|
|
@ -32,6 +32,7 @@ class theme
|
|||
private:
|
||||
SDL_Rect loc_;
|
||||
mutable SDL_Rect relative_loc_;
|
||||
mutable SDL_Rect last_screen_;
|
||||
|
||||
ANCHORING xanchor_, yanchor_;
|
||||
|
||||
|
@ -102,7 +103,8 @@ public:
|
|||
std::string image_;
|
||||
};
|
||||
|
||||
explicit theme(const config& cfg);
|
||||
explicit theme(const config& cfg, const SDL_Rect& screen);
|
||||
bool set_resolution(const SDL_Rect& screen);
|
||||
|
||||
const std::vector<panel>& panels() const;
|
||||
const std::vector<label>& labels() const;
|
||||
|
@ -113,6 +115,7 @@ public:
|
|||
const SDL_Rect& mini_map_location(const SDL_Rect& screen) const;
|
||||
|
||||
private:
|
||||
const config& cfg_;
|
||||
std::vector<panel> panels_;
|
||||
std::vector<label> labels_;
|
||||
|
||||
|
|
|
@ -194,7 +194,7 @@ struct team_data
|
|||
int units, upkeep, villages, expenses, net_income, gold;
|
||||
};
|
||||
|
||||
team_data calculate_team_data(const team& tm, int side, const unit_map& units);
|
||||
team_data calculate_team_data(const class team& tm, int side, const unit_map& units);
|
||||
|
||||
std::string get_team_name(int side, const unit_map& units);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue