about.cpp

Go to the documentation of this file.
00001 /* $Id: about.cpp 26501 2008-05-09 22:44:58Z mordante $ */
00002 /*
00003    Copyright (C) 2003 - 2008 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License version 2
00008    or at your option any later version.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 //! @file about.cpp
00016 //! Show screen with scrolling credits.
00017 
00018 #include "about.hpp"
00019 #include "config.hpp"
00020 #include "construct_dialog.hpp"
00021 #include "display.hpp"
00022 #include "font.hpp"
00023 #include "game_config.hpp"
00024 #include "gettext.hpp"
00025 #include "marked-up_text.hpp"
00026 #include "video.hpp"
00027 #include "show_dialog.hpp"
00028 
00029 //! @namespace about
00030 //! Display credits about all contributors.
00031 //!
00032 //! This module is used from the startup screen. \n
00033 //! When show_about() is called, a list of contributors
00034 //! to the game will be presented to the user.
00035 namespace about
00036 {
00037 
00038     static config about_list = config();
00039     static std::map<std::string , std::string> images;
00040     static std::string images_default;
00041 
00042 // Given a vector of strings, and a config representing an [about] section,
00043 // add all the credits lines from the about section to the list of strings.
00044 static void add_lines(std::vector<std::string> &res, config const &c) {
00045     std::string title=c["title"];
00046     if(title.size()) {
00047         title = N_("+" + title);
00048         res.push_back(title);
00049     }
00050 
00051     std::vector<std::string> lines = utils::split(c["text"], '\n');
00052     for(std::vector<std::string>::iterator line = lines.begin();
00053         line != lines.end(); line++) {
00054         if((*line)[0] == '+' && (*line).size()>1){
00055             *line = N_("+  " + (*line).substr(1,(*line).size()-1));
00056         } else {
00057             *line = "-  " + *line;
00058         }
00059         if(line->size()) {
00060             if ((*line)[0] == '_')
00061                 *line = gettext(line->substr(1,line->size()-1).c_str());
00062             res.push_back(*line);
00063         }
00064     }
00065 
00066     config::child_list entries = c.get_children("entry");
00067     config::child_list::const_iterator entry;
00068     for(entry = entries.begin(); entry != entries.end(); entry++) {
00069         res.push_back("-  "+(**entry)["name"]);
00070     }
00071 }
00072 
00073 
00074 std::vector<std::string> get_text(std::string campaign) {
00075     std::vector< std::string > res;
00076 
00077     const config::child_list& children = about::about_list.get_children("about");
00078 
00079     for(config::child_list::const_iterator cc = children.begin(); cc != children.end(); ++cc) {
00080       // just finished a particular campaign
00081       if(campaign.size() && campaign == (**cc)["id"]){
00082         add_lines(res, **cc);
00083       }
00084     }
00085 
00086     for(config::child_list::const_iterator acc = children.begin(); acc != children.end(); ++acc) {
00087       add_lines(res, **acc);
00088     }
00089 
00090     return res;
00091 }
00092 
00093 void set_about(const config& cfg){
00094     config::child_list about = cfg.get_children("about");
00095     for(config::child_list::const_iterator A = about.begin(); A != about.end(); A++) {
00096         config AA = (**A);
00097         about_list.add_child("about",AA);
00098         if(!AA["images"].empty()){
00099             if(images_default.empty()){
00100                 images_default=AA["images"];
00101             }else{
00102                 images_default+=","+AA["images"];
00103             }
00104         }
00105     }
00106     config::child_list campaigns = cfg.get_children("campaign");
00107     for(config::child_list::const_iterator C = campaigns.begin(); C != campaigns.end(); C++) {
00108         config::child_list about = (**C).get_children("about");
00109         if(about.size()){
00110             config temp;
00111             std::string text;
00112             std::string title;
00113             std::string campaign=(**C)["id"];
00114             title=(**C)["name"];
00115             temp["title"]=title;
00116             temp["id"]=(**C)["id"];
00117             for(config::child_list::const_iterator A = about.begin(); A != about.end(); A++) {
00118                 config AA = (**A);
00119                 std::string subtitle=AA["title"];
00120                 if(subtitle.size()){
00121                 if (subtitle[0] == '_')
00122                         subtitle = gettext(subtitle.substr(1,subtitle.size()-1).c_str());
00123                     text += "+" + subtitle + "\n";
00124                 }
00125                 std::vector<std::string> lines=utils::split(AA["text"],'\n');
00126                 for(std::vector<std::string>::iterator line=lines.begin();
00127                     line != lines.end(); line++){
00128                     text+="    "+(*line)+"\n";
00129                 }
00130 
00131                 config::child_list entries = AA.get_children("entry");
00132                 config::child_list::const_iterator entry;
00133                 for(entry = entries.begin(); entry != entries.end(); entry++) {
00134                     text+="    "+(**entry)["name"]+"\n";
00135                 }
00136 
00137                 if(!AA["images"].empty()){
00138                     if(images[campaign].empty()){
00139                         images[campaign]=AA["images"];
00140                     }else{
00141                         images[campaign]+=","+AA["images"];
00142                     }
00143                 }
00144             }
00145             temp["text"]=text;
00146             about_list.add_child("about",temp);
00147         }
00148     }
00149 }
00150 
00151 //! Show credits with list of contributors.
00152 //! Names of people are shown scrolling up like in movie-credits.\n
00153 //! Uses map from wesnoth or campaign as background.
00154 void show_about(display &disp, std::string campaign)
00155 {
00156     cursor::set(cursor::WAIT);
00157     CVideo &video = disp.video();
00158     std::vector<std::string> text = about::get_text(campaign);
00159     SDL_Rect rect = {0, 0, video.getx(), video.gety()};
00160 
00161     const surface_restorer restorer(&video, rect);
00162 
00163     // Clear the screen
00164     draw_solid_tinted_rectangle(0,0,video.getx()-1,video.gety()-1,
00165                                      0,0,0,1.0,video.getSurface());
00166     update_whole_screen();
00167     cursor::set(cursor::NORMAL);
00168 
00169     std::vector<std::string> image_list;
00170     if(campaign.size() && !images[campaign].empty()){
00171         image_list=utils::split(images[campaign]);
00172     }else{
00173         image_list=utils::split(images_default,',',utils::STRIP_SPACES);
00174     }
00175     surface map_image(scale_surface(image::get_image(image_list[0]), disp.w(), disp.h()));
00176     if(! map_image){
00177         image_list[0]=game_config::game_title;
00178         map_image=surface(scale_surface(image::get_image(image_list[0]), disp.w(), disp.h()));
00179     }
00180 
00181     SDL_Rect map_rect;
00182     map_rect.x = video.getx()/2 - map_image->w/2;
00183     map_rect.y = video.gety()/2 - map_image->h/2;
00184     map_rect.w = map_image->w;
00185     map_rect.h = map_image->h;
00186 
00187     gui::button close(video,_("Close"));
00188     close.set_location((video.getx()/2)-(close.width()/2), video.gety() - 30);
00189     close.set_volatile(true);
00190 
00191     //substitute in the correct control characters for '+' and '-'
00192     std::string before_header(2, ' ');
00193     before_header[0] = font::LARGE_TEXT;
00194     for(unsigned i = 0; i < text.size(); ++i) {
00195         std::string &s = text[i];
00196         if (s.empty()) continue;
00197         char &first = s[0];
00198         if (first == '-')
00199             first = font::SMALL_TEXT;
00200         else if (first == '+') {
00201             first = font::LARGE_TEXT;
00202             text.insert(text.begin() + i, before_header);
00203             ++i;
00204         }
00205     }
00206     text.insert(text.begin(), 10, before_header);
00207 
00208     int startline = 0;
00209 
00210     // the following two lines should be changed if the image of the map is changed
00211     const int top_margin = 60;      // distance from top of map image to top of scrolling text
00212     const int bottom_margin = 40;   // distance from bottom of scrolling text to bottom of map image
00213 
00214     int offset = 0;
00215     bool is_new_line = true;
00216 
00217     int first_line_height = 0;
00218 
00219     // the following rectangles define the top, middle and bottom of the background image
00220     // the upper and lower part is later used to mask the upper and lower line of scrolling text
00221     SDL_Rect upper_src = {0, 0, map_rect.w, top_margin};
00222     SDL_Rect upper_dest = {map_rect.x, map_rect.y, map_rect.w, top_margin};
00223     SDL_Rect middle_src = {0, top_margin, map_rect.w, map_rect.h - top_margin - bottom_margin};
00224     SDL_Rect middle_dest = {map_rect.x, map_rect.y + top_margin, map_rect.w, map_rect.h - top_margin - bottom_margin};
00225     SDL_Rect lower_src = {0, map_rect.h - bottom_margin, map_rect.w, bottom_margin};
00226     SDL_Rect lower_dest = {map_rect.x, map_rect.y + map_rect.h - bottom_margin, map_rect.w, bottom_margin};
00227 
00228     CKey key;
00229     bool last_escape;
00230     int image_count=0;
00231     do {
00232         last_escape = key[SDLK_ESCAPE] != 0;
00233 
00234         // check to see if background image has changed
00235         if(text.size() && (image_count <
00236                 ((startline * static_cast<int>(image_list.size())) /
00237                 static_cast<int>(text.size())))){
00238 
00239             image_count++;
00240             surface temp=surface(scale_surface(image::get_image(image_list[image_count]), disp.w(), disp.h()));
00241             map_image=temp?temp:map_image;
00242         }
00243         // draw map to screen, thus erasing all text
00244 
00245         SDL_BlitSurface(map_image,&middle_src,video.getSurface(),&middle_dest);
00246         SDL_Rect frame_area = {
00247             map_rect.x + map_rect.w * 3/32,
00248             map_rect.y + top_margin,
00249             map_rect.w * 13 / 16,
00250             map_rect.h - top_margin - bottom_margin
00251         };
00252         gui::dialog_frame f(disp.video(), "", gui::dialog_frame::titlescreen_style, false);
00253         f.layout(frame_area);
00254         f.draw_background();
00255 
00256         // draw one screen full of text
00257         const int line_spacing = 5;
00258         int y = map_rect.y + top_margin - offset;
00259         int line = startline;
00260         int cur_line = 0;
00261 
00262         do {
00263 //          SDL_Rect tr2 = font::draw_text(&video,screen_area(),font::SIZE_XLARGE,font::BLACK_COLOUR,
00264 //                      text[line], map_rect.x + map_rect.w / 8 + 1,y + 1);
00265             SDL_Rect tr = font::draw_text(&video,screen_area(),font::SIZE_XLARGE,font::NORMAL_COLOUR,
00266                                   text[line], map_rect.x + map_rect.w / 8,y);
00267 
00268             if(is_new_line) {
00269                 is_new_line = false;
00270                 first_line_height = tr.h + line_spacing;
00271             }
00272             line++;
00273             if(size_t(line) > text.size()-1)
00274                 line = 0;
00275             y += tr.h + line_spacing;
00276             cur_line++;
00277         } while(y<map_rect.y + map_rect.h - bottom_margin);
00278 
00279         // performs the actual scrolling
00280         const int scroll_speed = 4;     // scroll_speed*50 = speed of scroll in pixel per second
00281 
00282         offset += scroll_speed;
00283         if(offset>=first_line_height) {
00284             offset -= first_line_height;
00285             is_new_line = true;
00286             startline++;
00287             if(size_t(startline) == text.size()){
00288                 startline = 0;
00289                 image_count = -1;
00290             }
00291         }
00292 
00293         // mask off the upper and lower half of the map,
00294         // so text will scroll into view rather than
00295         // suddenly appearing out of nowhere
00296         SDL_BlitSurface(map_image,&upper_src,video.getSurface(),&upper_dest);
00297         SDL_BlitSurface(map_image,&lower_src,video.getSurface(),&lower_dest);
00298 
00299         // handle events
00300         events::pump();
00301         events::raise_process_event();
00302         events::raise_draw_event();
00303 
00304         // update screen and wait, so the text does not scroll too fast
00305         update_rect(map_rect);
00306         close.set_dirty(true);
00307         disp.flip();
00308         disp.delay(20);
00309 
00310     } while(!close.pressed() && (last_escape || !key[SDLK_ESCAPE]));
00311 
00312 }
00313 
00314 } // end namespace about

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs