mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-11 13:37:08 +00:00
330 lines
10 KiB
C++
330 lines
10 KiB
C++
/* $Id$ */
|
|
/*
|
|
Copyright (C) 2003 by David White <davidnwhite@verizon.net>
|
|
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.
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY.
|
|
|
|
See the COPYING file for more details.
|
|
*/
|
|
|
|
#include "about.hpp"
|
|
#include "display.hpp"
|
|
#include "font.hpp"
|
|
#include "game_config.hpp"
|
|
#include "gettext.hpp"
|
|
#include "marked-up_text.hpp"
|
|
#include "video.hpp"
|
|
#include "show_dialog.hpp"
|
|
|
|
namespace about
|
|
{
|
|
|
|
config about_list = config();
|
|
std::map<std::string , std::string> images;
|
|
std::string images_default;
|
|
|
|
std::vector<std::string> get_text(std::string campaign) {
|
|
static const char *credits[] = {
|
|
"_" N_("+Developers"),
|
|
"- David White (Sirp)",
|
|
"- *",
|
|
"- Alfredo Beaumont (ziberpunk)",
|
|
"- András Salamon (ott)",
|
|
"- Benoît Timbert (Noyga)",
|
|
"- Bram Ridder (Morloth)",
|
|
"- Bruno Wolff III",
|
|
"- Cedric Duval",
|
|
"- Cyril Bouthors (CyrilB)",
|
|
"- Dominic Bolin (Xan)",
|
|
"- Guillaume Melquiond (silene)",
|
|
"- Isaac Clerencia",
|
|
"- Jan Zvánovec (jaz)",
|
|
"- Jérémy Rosen (Boucman)",
|
|
"- John B. Messerly",
|
|
"- John W. C. McNabb (Darth Fool)",
|
|
"- Jon Daniel (forcemstr)",
|
|
"- Jörg Hinrichs (Yogi Bear/YogiHH)",
|
|
"- Justin Zaun (jzaun)",
|
|
"- J.R. Blain (Cowboy)",
|
|
"- Kristoffer Erlandsson (erl)",
|
|
"- Maksim Orlovich (SadEagle)",
|
|
"- Nicolas Weeger (Ryo)",
|
|
"- Patrick Parker (Sapient)",
|
|
"- Philippe Plantier (Ayin)",
|
|
"- Rusty Russell (rusty)",
|
|
"- Yann Dirson",
|
|
"- Zas",
|
|
"_" N_("+General Purpose Administrators"),
|
|
"- Crossbow/Miyo",
|
|
"- Isaac Clerencia",
|
|
};
|
|
|
|
std::vector< std::string > res;
|
|
size_t len = sizeof(credits) / sizeof(*credits);
|
|
res.reserve(len);
|
|
|
|
const config::child_list& children = about::about_list.get_children("about");
|
|
|
|
for(config::child_list::const_iterator cc = children.begin(); cc != children.end(); ++cc) {
|
|
//just finished a particular campaign
|
|
if(campaign.size() && campaign == (**cc)["id"]){
|
|
std::string title=(**cc)["title"];
|
|
if(title.size()){
|
|
title = N_("+" + title);
|
|
res.push_back(title);
|
|
}
|
|
std::vector<std::string> lines=utils::split((**cc)["text"],'\n');
|
|
for(std::vector<std::string>::iterator line=lines.begin();
|
|
line != lines.end(); line++){
|
|
if((*line)[0] == '+' && (*line).size()>1){
|
|
*line = N_("+ " + (*line).substr(1,(*line).size()-1));
|
|
}else{
|
|
*line = "- " + *line;
|
|
}
|
|
if(line->size()){
|
|
if ((*line)[0] == '_')
|
|
*line = gettext(line->substr(1,line->size()-1).c_str());
|
|
res.push_back(*line);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for(size_t i = 0; i < len; ++i) {
|
|
const char *s = credits[i];
|
|
if (s[0] == '_')
|
|
s = gettext(s + 1);
|
|
res.push_back(s);
|
|
}
|
|
|
|
for(config::child_list::const_iterator acc = children.begin(); acc != children.end(); ++acc) {
|
|
std::string title=(**acc)["title"];
|
|
if(title.size()){
|
|
title = N_("+" + title);
|
|
res.push_back(title);
|
|
}
|
|
std::vector<std::string> lines=utils::split((**acc)["text"],'\n');
|
|
for(std::vector<std::string>::iterator line=lines.begin();
|
|
line != lines.end(); line++){
|
|
if((*line)[0] == '+' && (*line).size()>1){
|
|
*line = N_("+ " + (*line).substr(1,(*line).size()-1));
|
|
}else{
|
|
*line = "- " + *line;
|
|
}
|
|
if(line->size()){
|
|
if ((*line)[0] == '_')
|
|
*line = gettext(line->substr(1,line->size()-1).c_str());
|
|
res.push_back(*line);
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
void set_about(const config& cfg){
|
|
config::child_list about = cfg.get_children("about");
|
|
for(config::child_list::const_iterator A = about.begin(); A != about.end(); A++) {
|
|
config AA = (**A);
|
|
about_list.add_child("about",AA);
|
|
if(!AA["images"].empty()){
|
|
if(images_default.empty()){
|
|
images_default=AA["images"];
|
|
}else{
|
|
images_default+=","+AA["images"];
|
|
}
|
|
}
|
|
}
|
|
config::child_list campaigns = cfg.get_children("campaign");
|
|
for(config::child_list::const_iterator C = campaigns.begin(); C != campaigns.end(); C++) {
|
|
config::child_list about = (**C).get_children("about");
|
|
if(about.size()){
|
|
config temp;
|
|
std::string text;
|
|
std::string title;
|
|
std::string campaign=(**C)["id"];
|
|
title=(**C)["name"];
|
|
temp["title"]=title;
|
|
temp["id"]=(**C)["id"];
|
|
for(config::child_list::const_iterator A = about.begin(); A != about.end(); A++) {
|
|
config AA = (**A);
|
|
std::string subtitle=AA["title"];
|
|
if(subtitle.size()){
|
|
if (subtitle[0] == '_')
|
|
subtitle = gettext(subtitle.substr(1,subtitle.size()-1).c_str());
|
|
text += "+" + subtitle + "\n";
|
|
}
|
|
std::vector<std::string> lines=utils::split(AA["text"],'\n');
|
|
for(std::vector<std::string>::iterator line=lines.begin();
|
|
line != lines.end(); line++){
|
|
text+=" "+(*line)+"\n";
|
|
}
|
|
|
|
if(!AA["images"].empty()){
|
|
if(images[campaign].empty()){
|
|
images[campaign]=AA["images"];
|
|
}else{
|
|
images[campaign]+=","+AA["images"];
|
|
}
|
|
}
|
|
}
|
|
temp["text"]=text;
|
|
about_list.add_child("about",temp);
|
|
}
|
|
}
|
|
}
|
|
|
|
void show_about(display &disp, std::string campaign)
|
|
{
|
|
CVideo &video = disp.video();
|
|
std::vector<std::string> text = about::get_text(campaign);
|
|
SDL_Rect rect = {0, 0, video.getx(), video.gety()};
|
|
|
|
const surface_restorer restorer(&video, rect);
|
|
|
|
// Clear the screen
|
|
draw_solid_tinted_rectangle(0,0,video.getx()-1,video.gety()-1,
|
|
0,0,0,1.0,video.getSurface());
|
|
update_whole_screen();
|
|
|
|
std::vector<std::string> image_list;
|
|
if(campaign.size() && !images[campaign].empty()){
|
|
image_list=utils::split(images[campaign]);
|
|
}else{
|
|
image_list=utils::split(images_default,',',utils::STRIP_SPACES);
|
|
}
|
|
surface map_image(scale_surface(image::get_image(image_list[0],image::UNSCALED), disp.x(), disp.y()));
|
|
if(! map_image){
|
|
image_list[0]=game_config::game_title;
|
|
map_image=surface(scale_surface(image::get_image(image_list[0],image::UNSCALED), disp.x(), disp.y()));
|
|
}
|
|
|
|
SDL_Rect map_rect;
|
|
map_rect.x = video.getx()/2 - map_image->w/2;
|
|
map_rect.y = video.gety()/2 - map_image->h/2;
|
|
map_rect.w = map_image->w;
|
|
map_rect.h = map_image->h;
|
|
|
|
gui::button close(video,_("Close"));
|
|
close.set_location((video.getx()/2)-(close.width()/2), video.gety() - 30);
|
|
close.set_volatile(true);
|
|
|
|
//substitute in the correct control characters for '+' and '-'
|
|
std::string before_header(2, ' ');
|
|
before_header[0] = font::LARGE_TEXT;
|
|
for(unsigned i = 0; i < text.size(); ++i) {
|
|
std::string &s = text[i];
|
|
if (s.empty()) continue;
|
|
char &first = s[0];
|
|
if (first == '-')
|
|
first = font::SMALL_TEXT;
|
|
else if (first == '+') {
|
|
first = font::LARGE_TEXT;
|
|
text.insert(text.begin() + i, before_header);
|
|
++i;
|
|
}
|
|
}
|
|
text.insert(text.begin(), 10, before_header);
|
|
|
|
int startline = 0;
|
|
|
|
// the following two lines should be changed if the image of the map is changed
|
|
const int top_margin = 60; // distance from top of map image to top of scrolling text
|
|
const int bottom_margin = 40; // distance from bottom of scrolling text to bottom of map image
|
|
|
|
int offset = 0;
|
|
bool is_new_line = true;
|
|
|
|
int first_line_height = 0;
|
|
|
|
// the following rectangles define the top, middle and bottom of the background image
|
|
// the upper and lower part is later used to mask the upper and lower line of scrolling text
|
|
SDL_Rect upper_src = {0, 0, map_rect.w, top_margin};
|
|
SDL_Rect upper_dest = {map_rect.x, map_rect.y, map_rect.w, top_margin};
|
|
SDL_Rect middle_src = {0, top_margin, map_rect.w, map_rect.h - top_margin - bottom_margin};
|
|
SDL_Rect middle_dest = {map_rect.x, map_rect.y + top_margin, map_rect.w, map_rect.h - top_margin - bottom_margin};
|
|
SDL_Rect lower_src = {0, map_rect.h - bottom_margin, map_rect.w, bottom_margin};
|
|
SDL_Rect lower_dest = {map_rect.x, map_rect.y + map_rect.h - bottom_margin, map_rect.w, bottom_margin};
|
|
|
|
CKey key;
|
|
bool last_escape;
|
|
int image_count=0;
|
|
do {
|
|
last_escape = key[SDLK_ESCAPE] != 0;
|
|
|
|
// check to see if background image has changed
|
|
if(text.size() && (image_count < ((startline*(int)image_list.size())/(int)text.size()))){
|
|
image_count++;
|
|
surface temp=surface(scale_surface(image::get_image(image_list[image_count],image::UNSCALED), disp.x(), disp.y()));
|
|
map_image=temp?temp:map_image;
|
|
}
|
|
// draw map to screen, thus erasing all text
|
|
|
|
SDL_BlitSurface(map_image,&middle_src,video.getSurface(),&middle_dest);
|
|
std::string style = "mainmenu";
|
|
|
|
gui::draw_dialog_frame(map_rect.x + map_rect.w * 3/32, map_rect.y + top_margin, map_rect.w * 13 / 16, map_rect.h - top_margin - bottom_margin,disp.video(),&style);
|
|
// draw one screen full of text
|
|
const int line_spacing = 5;
|
|
int y = map_rect.y + top_margin - offset;
|
|
int line = startline;
|
|
int cur_line = 0;
|
|
|
|
do {
|
|
// SDL_Rect tr2 = font::draw_text(&video,screen_area(),font::SIZE_XLARGE,font::BLACK_COLOUR,
|
|
// text[line], map_rect.x + map_rect.w / 8 + 1,y + 1);
|
|
SDL_Rect tr = font::draw_text(&video,screen_area(),font::SIZE_XLARGE,font::NORMAL_COLOUR,
|
|
text[line], map_rect.x + map_rect.w / 8,y);
|
|
|
|
if(is_new_line) {
|
|
is_new_line = false;
|
|
first_line_height = tr.h + line_spacing;
|
|
}
|
|
line++;
|
|
if(size_t(line) > text.size()-1)
|
|
line = 0;
|
|
y += tr.h + line_spacing;
|
|
cur_line++;
|
|
} while(y<map_rect.y + map_rect.h - bottom_margin);
|
|
|
|
// performs the actual scrolling
|
|
const int scroll_speed = 4; // scroll_speed*50 = speed of scroll in pixel per second
|
|
|
|
offset += scroll_speed;
|
|
if(offset>=first_line_height) {
|
|
offset -= first_line_height;
|
|
is_new_line = true;
|
|
startline++;
|
|
if(size_t(startline) == text.size()){
|
|
startline = 0;
|
|
image_count = -1;
|
|
}
|
|
}
|
|
|
|
// mask off the upper and lower half of the map,
|
|
// so text will scroll into view rather than
|
|
// suddenly appearing out of nowhere
|
|
SDL_BlitSurface(map_image,&upper_src,video.getSurface(),&upper_dest);
|
|
SDL_BlitSurface(map_image,&lower_src,video.getSurface(),&lower_dest);
|
|
|
|
// handle events
|
|
events::pump();
|
|
events::raise_process_event();
|
|
events::raise_draw_event();
|
|
|
|
// update screen and wait, so the text does not scroll too fast
|
|
update_rect(map_rect);
|
|
close.set_dirty(true);
|
|
disp.flip();
|
|
disp.delay(20);
|
|
|
|
} while(!close.pressed() && (last_escape || !key[SDLK_ESCAPE]));
|
|
|
|
}
|
|
|
|
}
|