added basic theme support

This commit is contained in:
uid68803 2003-12-27 02:27:28 +00:00
parent 6f6454b145
commit 8b2f14bd01
15 changed files with 709 additions and 21 deletions

View file

@ -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]

View file

@ -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 \

View file

@ -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 \

View file

@ -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();

View file

@ -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);

View file

@ -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;
}
}
}

View file

@ -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
View 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
View 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

View file

@ -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) {}
/**

View file

@ -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)
{

View file

@ -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
{

View file

@ -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

View file

@ -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_;

View file

@ -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);