Completely refactored internal handling of credits and enabled new dialog
This removes the ugly string markup and makes the dialog parse the config directly. This also temporarily disables the display of credits in the help browser.
This commit is contained in:
parent
04a6384beb
commit
476027f239
7 changed files with 120 additions and 412 deletions
424
src/about.cpp
424
src/about.cpp
|
@ -12,426 +12,92 @@
|
|||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Show screen with scrolling credits.
|
||||
*/
|
||||
|
||||
#include "about.hpp"
|
||||
#include "global.hpp" // for false_, bool_
|
||||
|
||||
#include "config.hpp" // for config, etc
|
||||
#include "cursor.hpp" // for setter, CURSOR_TYPE::WAIT
|
||||
#include "events.hpp" // for pump, raise_draw_event, etc
|
||||
#include "font.hpp" // for NORMAL_COLOR, SIZE_XLARGE
|
||||
#include "game_config.hpp" // for game_title_background
|
||||
#include "gettext.hpp" // for _
|
||||
#include "image.hpp" // for get_image
|
||||
#include "key.hpp" // for CKey
|
||||
#include "marked-up_text.hpp" // for draw_text, LARGE_TEXT, etc
|
||||
#include "sdl/rect.hpp" // for create_rect
|
||||
#include "sdl/utils.hpp" // for surface, sdl_blit, etc
|
||||
#include "serialization/string_utils.hpp" // for split, etc
|
||||
#include "show_dialog.hpp" // for dialog_frame, etc
|
||||
#include "tstring.hpp" // for operator==
|
||||
#include "video.hpp" // for update_rect, CVideo
|
||||
#include "widgets/button.hpp" // for button
|
||||
#include "gui/dialogs/end_credits.hpp"
|
||||
|
||||
#include <algorithm> // for max
|
||||
#include <map> // for map, map<>::mapped_type
|
||||
#include <ostream> // for operator<<, basic_ostream, etc
|
||||
|
||||
#include "sdl/alpha.hpp"
|
||||
|
||||
/**
|
||||
* @namespace about
|
||||
* Display credits %about all contributors.
|
||||
*
|
||||
* This module is used from the startup screen. \n
|
||||
* When show_about() is called, a list of contributors
|
||||
* to the game will be presented to the user.
|
||||
*/
|
||||
namespace about
|
||||
{
|
||||
static config about_list = config();
|
||||
static std::map<std::string , std::string> images;
|
||||
static std::string images_default;
|
||||
|
||||
/**
|
||||
* Given a vector of strings, and a config representing an [about] section,
|
||||
* add all the credits lines from the about section to the list of strings.
|
||||
*/
|
||||
static void add_lines(std::vector<std::string> &res, config const &c, bool split_multiline_headers) {
|
||||
std::string title = c["title"];
|
||||
if (!title.empty()) {
|
||||
if(split_multiline_headers) {
|
||||
// If the title is multi-line, we need to split it accordingly or we
|
||||
// get slight scrolling glitches in the credits screen.
|
||||
const std::vector<std::string>& lines = utils::split(c["title"], '\n');
|
||||
bool first = true;
|
||||
for(const std::string& line : lines) {
|
||||
if(first) {
|
||||
res.push_back("+" + line);
|
||||
first = false;
|
||||
} else {
|
||||
// Don't convert other lines into headers or they get extra
|
||||
// spacing on the credits screen.
|
||||
res.push_back(line);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res.push_back("+" + title);
|
||||
}
|
||||
}
|
||||
static config about_list = config();
|
||||
static std::map<std::string , std::string> images;
|
||||
static std::string images_default;
|
||||
|
||||
std::vector<std::string> lines = utils::split(c["text"], '\n');
|
||||
for(std::string &line : lines)
|
||||
{
|
||||
if (line.size() > 1 && line[0] == '+')
|
||||
line = "+ " + line.substr(1);
|
||||
else
|
||||
line = "- " + line;
|
||||
|
||||
if (!line.empty())
|
||||
{
|
||||
if (line[0] == '_')
|
||||
line = translation::gettext(line.substr(1).c_str());
|
||||
res.push_back(line);
|
||||
}
|
||||
}
|
||||
|
||||
for (const config &entry : c.child_range("entry")) {
|
||||
res.push_back("- "+ entry["name"].str());
|
||||
}
|
||||
const config& get_about_config()
|
||||
{
|
||||
return about_list;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> get_text(const std::string &campaign, bool split_multiline_headers)
|
||||
std::vector<std::string> get_background_images(const std::string& campaign)
|
||||
{
|
||||
std::vector< std::string > res;
|
||||
|
||||
config::child_itors about_entries = about_list.child_range("about");
|
||||
|
||||
if (!campaign.empty()) {
|
||||
for (const config &about : about_entries) {
|
||||
// just finished a particular campaign
|
||||
if (campaign == about["id"]) {
|
||||
add_lines(res, about, split_multiline_headers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const config &about : about_entries) {
|
||||
add_lines(res, about, split_multiline_headers);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void set_about(const config &cfg)
|
||||
{
|
||||
about_list.clear();
|
||||
images.clear();
|
||||
images_default = "";
|
||||
|
||||
for (const config &about : cfg.child_range("about"))
|
||||
{
|
||||
about_list.add_child("about", about);
|
||||
const std::string &im = about["images"];
|
||||
if (!images.empty())
|
||||
{
|
||||
if (images_default.empty())
|
||||
images_default = im;
|
||||
else
|
||||
images_default += ',' + im;
|
||||
}
|
||||
}
|
||||
|
||||
for (const config &campaign : cfg.child_range("campaign"))
|
||||
{
|
||||
config::const_child_itors abouts = campaign.child_range("about");
|
||||
if (abouts.empty()) continue;
|
||||
|
||||
config temp;
|
||||
std::ostringstream text;
|
||||
const std::string &id = campaign["id"];
|
||||
temp["title"] = campaign["name"];
|
||||
temp["id"] = id;
|
||||
std::string campaign_images;
|
||||
|
||||
for (const config &about : abouts)
|
||||
{
|
||||
const std::string &subtitle = about["title"];
|
||||
if (!subtitle.empty())
|
||||
{
|
||||
text << '+';
|
||||
if (subtitle[0] == '_')
|
||||
text << translation::gettext(subtitle.substr(1, subtitle.size() - 1).c_str());
|
||||
else
|
||||
text << subtitle;
|
||||
text << '\n';
|
||||
}
|
||||
|
||||
for (const std::string &line : utils::split(about["text"], '\n'))
|
||||
{
|
||||
text << " " << line << '\n';
|
||||
}
|
||||
|
||||
for (const config &entry : about.child_range("entry"))
|
||||
{
|
||||
text << " " << entry["name"] << '\n';
|
||||
}
|
||||
|
||||
const std::string &im = about["images"];
|
||||
if (!im.empty())
|
||||
{
|
||||
if (campaign_images.empty())
|
||||
campaign_images = im;
|
||||
else
|
||||
campaign_images += ',' + im;
|
||||
}
|
||||
}
|
||||
|
||||
images[id] = campaign_images;
|
||||
temp["text"] = text.str();
|
||||
about_list.add_child("about",temp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show credits with list of contributors.
|
||||
*
|
||||
* Names of people are shown scrolling up like in movie-credits.\n
|
||||
* Uses map from wesnoth or campaign as background.
|
||||
*/
|
||||
void show_about(CVideo &video, const std::string &campaign)
|
||||
{
|
||||
std::unique_ptr<cursor::setter> cur(new cursor::setter(cursor::WAIT));
|
||||
surface& screen = video.getSurface();
|
||||
if (screen == nullptr) return;
|
||||
|
||||
// If the title is multi-line, we need to split it accordingly or we
|
||||
// get slight scrolling glitches in the credits screen.
|
||||
std::vector<std::string> text = about::get_text(campaign, true);
|
||||
|
||||
SDL_Rect screen_rect = sdl::create_rect(0, 0, screen->w, screen->h);
|
||||
|
||||
const surface_restorer restorer(&video, screen_rect);
|
||||
|
||||
cur.reset();
|
||||
|
||||
std::vector<std::string> image_list;
|
||||
if(campaign.size() && !images[campaign].empty()){
|
||||
|
||||
if(!campaign.empty() && !images[campaign].empty()){
|
||||
image_list = utils::parenthetical_split(images[campaign], ',');
|
||||
} else{
|
||||
image_list = utils::parenthetical_split(images_default, ',');
|
||||
}
|
||||
|
||||
surface map_image, map_image_scaled;
|
||||
return image_list;
|
||||
}
|
||||
|
||||
// TODO: enable
|
||||
//gui2::tend_credits::display(text, image_list, video);
|
||||
void set_about(const config &cfg)
|
||||
{
|
||||
about_list.clear();
|
||||
|
||||
if(!image_list.empty()) {
|
||||
map_image = image::get_image(image_list[0]);
|
||||
} else {
|
||||
image_list.push_back("");
|
||||
}
|
||||
images.clear();
|
||||
images_default.clear();
|
||||
|
||||
if(!map_image){
|
||||
image_list[0]=game_config::images::game_title_background;
|
||||
map_image=image::get_image(image_list[0]);
|
||||
}
|
||||
for(const config& about : cfg.child_range("about")) {
|
||||
about_list.add_child("about", about);
|
||||
|
||||
gui::button close(video,_("Close"));
|
||||
close.set_location((screen->w/2)-(close.width()/2), screen->h - 30);
|
||||
|
||||
const int def_size = font::SIZE_XLARGE;
|
||||
const SDL_Color def_color = font::NORMAL_COLOR;
|
||||
|
||||
//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;
|
||||
const std::string& im = about["images"];
|
||||
if(!im.empty()) {
|
||||
if(images_default.empty()) {
|
||||
images_default = im;
|
||||
} else {
|
||||
images_default += ',' + im;
|
||||
}
|
||||
}
|
||||
}
|
||||
text.insert(text.begin(), 10, before_header);
|
||||
|
||||
int startline = 0;
|
||||
|
||||
//TODO: use values proportional to screen ?
|
||||
// distance from top of map image to top of scrolling text
|
||||
const int top_margin = 60;
|
||||
// distance from bottom of scrolling text to bottom of map image
|
||||
const int bottom_margin = 40;
|
||||
// distance from left of scrolling text to the frame border
|
||||
const int text_left_padding = screen->w/32;
|
||||
|
||||
int offset = 0;
|
||||
bool is_new_line = true;
|
||||
|
||||
int first_line_height = 0;
|
||||
|
||||
SDL_Rect frame_area;
|
||||
|
||||
// we use a dialog to contains the text. Strange idea but at least the style
|
||||
// will be consistent with the titlescreen
|
||||
gui::dialog_frame f(video, "", gui::dialog_frame::titlescreen_style, false);
|
||||
|
||||
// the text area's dimensions
|
||||
SDL_Rect text_rect = { 0, 0, 0, 0 };
|
||||
// we'll retain a copy to prevent SDL_blit to change its w and h
|
||||
SDL_Rect text_rect_blit;
|
||||
|
||||
surface text_surf;
|
||||
|
||||
CKey key;
|
||||
bool last_escape;
|
||||
|
||||
int image_count = 0;
|
||||
int scroll_speed = 4; // scroll_speed*50 = speed of scroll in pixel per second
|
||||
|
||||
// Initially redraw all
|
||||
bool redraw_mapimage = true;
|
||||
bool update_dimensions = true;
|
||||
int max_text_width = 0;
|
||||
|
||||
do {
|
||||
last_escape = key[SDLK_ESCAPE] != 0;
|
||||
|
||||
// check to see if background image has changed
|
||||
if(text.size() && (image_count <
|
||||
((startline * static_cast<int>(image_list.size())) /
|
||||
static_cast<int>(text.size())))){
|
||||
|
||||
image_count++;
|
||||
surface temp=image::get_image(image_list[image_count]);
|
||||
map_image=temp?temp:map_image;
|
||||
redraw_mapimage = true;
|
||||
for(const config& campaign : cfg.child_range("campaign")) {
|
||||
if(!campaign.has_child("about")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (update_dimensions) {
|
||||
// rescale the background
|
||||
map_image_scaled = scale_surface(map_image, screen->w, screen->h);
|
||||
screen_rect = sdl::create_rect(0, 0, screen->w, screen->h);
|
||||
redraw_mapimage = true;
|
||||
const std::string& id = campaign["id"];
|
||||
|
||||
// update the frame
|
||||
frame_area = sdl::create_rect(
|
||||
screen->w * 3 / 32
|
||||
, top_margin
|
||||
, screen->w * 13 / 16
|
||||
, screen->h - top_margin - bottom_margin);
|
||||
config temp;
|
||||
temp["title"] = campaign["name"];
|
||||
temp["id"] = id;
|
||||
|
||||
text_rect = f.layout(frame_area).interior;
|
||||
std::string campaign_images;
|
||||
|
||||
for(const config& about : campaign.child_range("about")) {
|
||||
temp.add_child("about", about);
|
||||
|
||||
// update the text area
|
||||
text_rect.x += text_left_padding;
|
||||
text_rect.w -= text_left_padding;
|
||||
text_rect_blit = text_rect;
|
||||
|
||||
text_surf = create_compatible_surface(screen, text_rect.w, text_rect.h);
|
||||
SDL_SetAlpha(text_surf, SDL_RLEACCEL, SDL_ALPHA_OPAQUE);
|
||||
|
||||
// relocate the close button
|
||||
close.set_location((screen->w/2)-(close.width()/2), screen->h - 30);
|
||||
|
||||
update_dimensions = false;
|
||||
}
|
||||
|
||||
if (redraw_mapimage) {
|
||||
// draw map to screen, thus erasing all text
|
||||
sdl_blit(map_image_scaled, nullptr, screen, nullptr);
|
||||
update_rect(screen_rect);
|
||||
|
||||
// redraw the dialog
|
||||
f.draw_background();
|
||||
f.draw_border();
|
||||
// cache the dialog background (alpha blending + blurred map)
|
||||
sdl_blit(screen, &text_rect, text_surf, nullptr);
|
||||
redraw_mapimage = false;
|
||||
} else {
|
||||
// redraw the saved part of the dialog where text scrolled
|
||||
// thus erasing all text
|
||||
SDL_Rect modified = sdl::create_rect(0, 0, max_text_width, text_rect.h);
|
||||
sdl_blit(text_surf, &modified, screen, &text_rect_blit);
|
||||
update_rect(text_rect);
|
||||
}
|
||||
|
||||
int y = text_rect.y - offset;
|
||||
int line = startline;
|
||||
max_text_width = 0;
|
||||
|
||||
{
|
||||
// clip to keep text into the frame (thus the new code block)
|
||||
clip_rect_setter set_clip_rect(screen, &text_rect);
|
||||
|
||||
const int line_spacing = 5;
|
||||
do {
|
||||
// draw the text (with ellipsis if needed)
|
||||
// update the max_text_width for future cleaning
|
||||
int w = font::draw_text(&video, text_rect, def_size, def_color,
|
||||
text[line], text_rect.x, y).w;
|
||||
max_text_width = std::max<int>(max_text_width, w);
|
||||
// since the real drawing on screen is clipped,
|
||||
// we do a dummy one to get the height of the not clipped line.
|
||||
// (each time because special format characters may change it)
|
||||
const int line_height = font::draw_text(nullptr, text_rect, def_size, def_color,
|
||||
text[line], 0,0).h;
|
||||
|
||||
if(is_new_line) {
|
||||
is_new_line = false;
|
||||
first_line_height = line_height + line_spacing;
|
||||
const std::string& im = about["images"];
|
||||
if(!im.empty()) {
|
||||
if(campaign_images.empty()) {
|
||||
campaign_images = im;
|
||||
} else {
|
||||
campaign_images += ',' + im;
|
||||
}
|
||||
line++;
|
||||
if(size_t(line) > text.size()-1)
|
||||
line = 0;
|
||||
y += line_height + line_spacing;
|
||||
} while(y < text_rect.y + text_rect.h);
|
||||
}
|
||||
|
||||
// performs the actual scrolling
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// handle events
|
||||
if (key[SDLK_UP] && scroll_speed < 20) {
|
||||
++scroll_speed;
|
||||
}
|
||||
if (key[SDLK_DOWN] && scroll_speed > 0) {
|
||||
--scroll_speed;
|
||||
}
|
||||
if (screen->w != screen_rect.w || screen->h != screen_rect.h) {
|
||||
update_dimensions = true;
|
||||
}
|
||||
images[id] = campaign_images;
|
||||
|
||||
events::pump();
|
||||
events::raise_process_event();
|
||||
events::raise_draw_event();
|
||||
|
||||
// flip screen and wait, so the text does not scroll too fast
|
||||
video.flip();
|
||||
CVideo::delay(20);
|
||||
|
||||
} while(!close.pressed() && (last_escape || !key[SDLK_ESCAPE]));
|
||||
about_list.add_child("credits_group", temp);
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace about
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
#include "global.hpp"
|
||||
|
||||
class CVideo;
|
||||
class config;
|
||||
|
||||
#include <vector>
|
||||
|
@ -26,9 +25,17 @@ class config;
|
|||
namespace about
|
||||
{
|
||||
|
||||
void show_about(CVideo& video, const std::string &campaign = std::string());
|
||||
/**
|
||||
* General getter methods for the credits config and image lists by campaign id
|
||||
*/
|
||||
const config& get_about_config();
|
||||
|
||||
std::vector<std::string> get_background_images(const std::string& campaign);
|
||||
|
||||
/**
|
||||
* Regenerates the credits config
|
||||
*/
|
||||
void set_about(const config& cfg);
|
||||
std::vector<std::string> get_text(const std::string &campaign = std::string(), bool split_multiline_headers = false);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "global.hpp" // for false_, bool_
|
||||
#include "game_errors.hpp"
|
||||
|
||||
#include "about.hpp" //for show_about
|
||||
#include "commandline_options.hpp" // for commandline_options
|
||||
#include "config.hpp" // for config, etc
|
||||
#include "config_assign.hpp"
|
||||
|
@ -30,6 +29,7 @@
|
|||
#include "game_end_exceptions.hpp" // for LEVEL_RESULT, etc
|
||||
#include "generators/map_generator.hpp" // for mapgen_exception
|
||||
#include "gettext.hpp" // for _
|
||||
#include "gui/dialogs/end_credits.hpp"
|
||||
#include "gui/dialogs/language_selection.hpp" // for tlanguage_selection
|
||||
#include "gui/dialogs/loadscreen.hpp"
|
||||
#include "gui/dialogs/message.hpp" //for show error message
|
||||
|
@ -955,7 +955,7 @@ void game_launcher::launch_game(RELOAD_GAME_DATA reload)
|
|||
preferences::add_completed_campaign(state_.classification().campaign, state_.classification().difficulty);
|
||||
the_end(video(), state_.classification().end_text, state_.classification().end_text_duration);
|
||||
if(state_.classification().end_credits) {
|
||||
about::show_about(video(),state_.classification().campaign);
|
||||
gui2::tend_credits::display(video(), state_.classification().campaign);
|
||||
}
|
||||
}
|
||||
} catch (savegame::load_game_exception &e) {
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
#include "gui/dialogs/end_credits.hpp"
|
||||
|
||||
#include "about.hpp"
|
||||
#include "config.hpp"
|
||||
#include "game_config.hpp"
|
||||
#include "gui/auxiliary/find_widget.hpp"
|
||||
#include "gui/core/timer.hpp"
|
||||
|
@ -24,7 +26,6 @@
|
|||
#include "gui/widgets/scroll_label.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
#include "gui/widgets/window.hpp"
|
||||
#include "formatter.hpp"
|
||||
#include "marked-up_text.hpp"
|
||||
|
||||
#include "utils/functional.hpp"
|
||||
|
@ -34,16 +35,13 @@ namespace gui2
|
|||
|
||||
REGISTER_DIALOG(end_credits)
|
||||
|
||||
tend_credits::tend_credits(const std::vector<std::string>& text, const std::vector<std::string>& backgrounds)
|
||||
: text_(text)
|
||||
, backgrounds_(backgrounds)
|
||||
tend_credits::tend_credits(const std::string& campaign)
|
||||
: focus_on_(campaign)
|
||||
, backgrounds_()
|
||||
, timer_id_()
|
||||
, text_widget_(nullptr)
|
||||
, scroll_speed_(100)
|
||||
{
|
||||
if(backgrounds_.empty()) {
|
||||
backgrounds_.push_back(game_config::images::game_title_background);
|
||||
}
|
||||
}
|
||||
|
||||
tend_credits::~tend_credits()
|
||||
|
@ -54,30 +52,60 @@ tend_credits::~tend_credits()
|
|||
}
|
||||
}
|
||||
|
||||
static void parse_about_tags(const config& cfg, std::stringstream& str)
|
||||
{
|
||||
for(const auto& about : cfg.child_range("about")) {
|
||||
str << "<span size='x-large'>" << about["title"] << "</span>" << "\n";
|
||||
|
||||
for(const auto& entry : about.child_range("entry")) {
|
||||
str << entry["name"] << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tend_credits::pre_show(twindow& window)
|
||||
{
|
||||
// Delay a little before beginning the scrolling
|
||||
add_timer(1000, [this](size_t) {
|
||||
timer_id_ = add_timer(50, std::bind(&tend_credits::timer_callback, this), true);
|
||||
add_timer(3000, [this](size_t) {
|
||||
timer_id_ = add_timer(10, std::bind(&tend_credits::timer_callback, this), true);
|
||||
last_scroll_ = SDL_GetTicks();
|
||||
});
|
||||
|
||||
connect_signal_pre_key_press(window, std::bind(&tend_credits::key_press_callback, this, _3, _4, _5));
|
||||
|
||||
// TODO: apparently, multiple images are supported... need to implement along with scrolling
|
||||
window.canvas()[0].set_variable("background_image", variant(backgrounds_[0]));
|
||||
|
||||
std::stringstream str;
|
||||
std::stringstream focus_str;
|
||||
|
||||
// BIG FAT TODO: get rid of this hacky string crap once we drop the GUI1 version
|
||||
for(const auto& line : text_) {
|
||||
if(line[0] == '-') {
|
||||
str << font::escape_text(line.substr(1)) << "\n";
|
||||
} else if(line[0] == '+') {
|
||||
str << "<span size='x-large'>" << font::escape_text(line.substr(1)) << "</span>" << "\n";
|
||||
}
|
||||
const config& credits_config = about::get_about_config();
|
||||
|
||||
// First, parse all the toplevel [about] tags
|
||||
parse_about_tags(credits_config, str);
|
||||
|
||||
// Next, parse all the grouped [about] tags (usually by campaign)
|
||||
for(const auto& group : credits_config.child_range("credits_group")) {
|
||||
std::stringstream& group_stream = (group["id"] == focus_on_) ? focus_str : str;
|
||||
|
||||
group_stream << "<span size='xx-large'>" << group["title"] << "</span>" << "\n";
|
||||
|
||||
parse_about_tags(group, group_stream);
|
||||
}
|
||||
|
||||
// TODO: this seems an inefficient way to place the focused group first
|
||||
if(!focus_str.str().empty()) {
|
||||
focus_str << str.rdbuf();
|
||||
str.swap(focus_str);
|
||||
}
|
||||
|
||||
// Get the appropriate background images
|
||||
backgrounds_ = about::get_background_images(focus_on_);
|
||||
|
||||
if(backgrounds_.empty()) {
|
||||
backgrounds_.push_back(game_config::images::game_title_background);
|
||||
}
|
||||
|
||||
// TODO: implement showing all available images as the credits scroll
|
||||
window.canvas()[0].set_variable("background_image", variant(backgrounds_[0]));
|
||||
|
||||
text_widget_ = find_widget<tscroll_label>(&window, "text", false, true);
|
||||
|
||||
text_widget_->set_use_markup(true);
|
||||
|
@ -97,12 +125,17 @@ void tend_credits::timer_callback()
|
|||
{
|
||||
uint32_t now = SDL_GetTicks();
|
||||
uint32_t missed_time = now - last_scroll_;
|
||||
|
||||
unsigned int cur_pos = text_widget_->get_vertical_scrollbar_item_position();
|
||||
|
||||
// Calculate how far the text should have scrolled by now
|
||||
// The division by 1000 is to convert milliseconds to seconds.
|
||||
unsigned int needed_dist = missed_time * scroll_speed_ / 1000;
|
||||
|
||||
text_widget_->set_vertical_scrollbar_item_position(cur_pos + needed_dist);
|
||||
|
||||
last_scroll_ = now;
|
||||
|
||||
if(text_widget_->vertical_scrollbar_at_end()) {
|
||||
remove_timer(timer_id_);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "sdl/utils.hpp"
|
||||
|
||||
class config;
|
||||
class display;
|
||||
|
||||
namespace gui2
|
||||
|
@ -30,13 +31,13 @@ class tscroll_label;
|
|||
class tend_credits : public tdialog
|
||||
{
|
||||
public:
|
||||
tend_credits(const std::vector<std::string>& text, const std::vector<std::string>& backgrounds);
|
||||
explicit tend_credits(const std::string& campaign);
|
||||
|
||||
~tend_credits();
|
||||
|
||||
static void display(const std::vector<std::string>& text, const std::vector<std::string>& backgrounds, CVideo& video)
|
||||
static void display(CVideo& video, const std::string& campaign = "")
|
||||
{
|
||||
tend_credits(text, backgrounds).show(video);
|
||||
tend_credits(campaign).show(video);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -49,7 +50,7 @@ private:
|
|||
void timer_callback();
|
||||
void key_press_callback(bool&, bool&, const SDLKey key);
|
||||
|
||||
const std::vector<std::string>& text_;
|
||||
const std::string& focus_on_;
|
||||
|
||||
std::vector<std::string> backgrounds_;
|
||||
|
||||
|
@ -57,7 +58,7 @@ private:
|
|||
|
||||
tscroll_label* text_widget_;
|
||||
|
||||
/// The speed of auto-scrolling, specified as px/s
|
||||
// The speed of auto-scrolling, specified as px/s
|
||||
int scroll_speed_;
|
||||
|
||||
uint32_t last_scroll_;
|
||||
|
|
|
@ -1012,13 +1012,14 @@ UNIT_DESCRIPTION_TYPE description_type(const unit_type &type)
|
|||
|
||||
std::string generate_about_text()
|
||||
{
|
||||
std::vector<std::string> about_lines = about::get_text();
|
||||
/*std::vector<std::string> about_lines = about::get_text();
|
||||
std::vector<std::string> res_lines;
|
||||
std::transform(about_lines.begin(), about_lines.end(), std::back_inserter(res_lines),
|
||||
about_text_formatter());
|
||||
res_lines.erase(std::remove(res_lines.begin(), res_lines.end(), ""), res_lines.end());
|
||||
std::string text = utils::join(res_lines, "\n");
|
||||
return text;
|
||||
return text;*/
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string generate_contents_links(const std::string& section_name, config const *help_cfg)
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
#include "global.hpp"
|
||||
|
||||
#include "about.hpp"
|
||||
#include "addon/manager.hpp"
|
||||
#include "build_info.hpp"
|
||||
#include "commandline_options.hpp" // for commandline_options, etc
|
||||
|
@ -31,6 +30,7 @@
|
|||
#include "game_launcher.hpp" // for game_launcher, etc
|
||||
#include "gettext.hpp"
|
||||
#include "gui/core/event/handler.hpp" // for tmanager
|
||||
#include "gui/dialogs/end_credits.hpp"
|
||||
#include "gui/dialogs/loadscreen.hpp"
|
||||
#include "gui/dialogs/title_screen.hpp" // for ttitle_screen, etc
|
||||
#include "gui/dialogs/message.hpp" // for show_error_message
|
||||
|
@ -804,7 +804,7 @@ static int do_gameloop(const std::vector<std::string>& args)
|
|||
game->start_editor();
|
||||
break;
|
||||
case gui2::ttitle_screen::SHOW_ABOUT:
|
||||
about::show_about(game->video());
|
||||
gui2::tend_credits::display(game->video());
|
||||
break;
|
||||
case gui2::ttitle_screen::LAUNCH_GAME:
|
||||
game->launch_game(should_reload);
|
||||
|
|
Loading…
Add table
Reference in a new issue