Merge pull request #5186 from Vultraz/outro_changes

[Proposal] Extended Outro dialog with campaign-specific credits
This commit is contained in:
Charles Dang 2020-10-06 14:07:50 +11:00 committed by GitHub
commit 1ec585a203
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 93 additions and 44 deletions

View File

@ -24,19 +24,29 @@
[/rectangle]
[text]
x = {GUI__TEXT_HORIZONTALLY_CENTRED}
x = 0
y = {GUI__TEXT_VERTICALLY_CENTRED}
w = "(width)"
h = "(text_height)"
maximum_width = "(width)"
font_size = 100
font_size = 80
font_family = "script"
color = "([215, 215, 215, min(ceil(as_decimal(fade_step * 25.5)), 255)])"
text = "(outro_text)"
text_markup = true
text_alignment = "center"
[/text]
[text]
x = "(screen_width - text_width - 20)"
y = "(screen_height - text_height - 20)"
w = "(text_width)"
h = "(text_height)"
font_size = {GUI_FONT_SIZE_DEFAULT}
text = _ "Press ESC to skip"
[/text]
[/draw]

View File

@ -15,6 +15,7 @@
#include "about.hpp"
#include "config.hpp"
#include "font/pango/escape.hpp"
#include "game_config_view.hpp"
#include "gettext.hpp"
#include "serialization/string_utils.hpp"
@ -81,7 +82,7 @@ credits_group::about_group::about_group(const config& cfg)
names.reserve(cfg.child_count("entry"));
for(const config& entry : cfg.child_range("entry")) {
names.emplace_back(entry["name"].str(), entry["comment"].str());
names.emplace_back(font::escape_text(entry["name"].str()), font::escape_text(entry["comment"].str()));
}
}
@ -95,6 +96,12 @@ const credits_data& get_credits_data()
return parsed_credits_data;
}
credits_data::const_iterator get_campaign_credits(const std::string& campaign)
{
return std::find_if(parsed_credits_data.begin(), parsed_credits_data.end(),
[&campaign](const credits_group& group) { return group.id == campaign; });
}
std::vector<std::string> get_background_images(const std::string& campaign)
{
if(!campaign.empty() && !images_campaigns[campaign].empty()) {

View File

@ -53,16 +53,16 @@ struct credits_group
using credits_data = std::vector<credits_group>;
/**
* General getter methods for the credits config and image lists by campaign id
*/
/** Gets all credits data. */
const credits_data& get_credits_data();
/** Gets credits for a given campaign. */
credits_data::const_iterator get_campaign_credits(const std::string& campaign);
/** Gets credit background images for a given campaaign. */
std::vector<std::string> get_background_images(const std::string& campaign);
/**
* Regenerates the credits config
*/
/** Regenerates the credits data. */
void set_about(const game_config_view& cfg);
} // namespace about

View File

@ -27,7 +27,6 @@
#include "game_config_manager.hpp" // for game_config_manager
#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 language_selection
#include "gui/dialogs/loading_screen.hpp"
#include "gui/dialogs/message.hpp" //for show error message
@ -1031,10 +1030,6 @@ void game_launcher::launch_game(RELOAD_GAME_DATA reload)
preferences::add_completed_campaign(state_.classification().campaign, state_.classification().difficulty);
gui2::dialogs::outro::display(state_.classification());
if(state_.classification().end_credits) {
gui2::dialogs::end_credits::display(state_.classification().campaign);
}
}
} catch (const savegame::load_game_exception &e) {
load_data_.reset(new savegame::load_game_metadata(std::move(e.data_)));

View File

@ -16,6 +16,7 @@
#include "gui/dialogs/outro.hpp"
#include "about.hpp"
#include "formula/variant.hpp"
#include "game_classification.hpp"
#include "gettext.hpp"
@ -31,46 +32,72 @@ namespace dialogs
REGISTER_DIALOG(outro)
outro::outro(const game_classification& info)
: text_(info.end_text)
: text_()
, current_text_()
, duration_(info.end_text_duration)
, fade_step_(0)
, fading_in_(true)
, timer_id_(0)
, next_draw_(0)
{
if(text_.empty()) {
text_ = _("The End");
if(!info.end_text.empty()) {
text_.push_back(info.end_text);
} else {
text_.push_back(_("The End"));
}
text_.push_back("<span size='large'>" + info.campaign_name + "</span>");
// We only show the end text and the title if credits were turned off
if(info.end_credits) {
for(const auto& about : about::get_campaign_credits(info.campaign)->sections) {
if(about.names.empty()) {
continue;
}
// Split the names into chunks of 5. Use float for proper ceil function!
static const float chunk_size = 5.0;
const unsigned num_names = about.names.size();
const unsigned num_chunks = std::ceil(num_names / chunk_size);
for(std::size_t i = 0; i < num_chunks; ++i) {
std::stringstream ss;
// Only include section title on first chunk
if(i == 0) {
ss << about.title << "\n\n";
}
for(std::size_t k = i * chunk_size; k < std::min<unsigned>((i + 1) * chunk_size, num_names); ++k) {
ss << "<span size='xx-small'>" << about.names[k].first << "</span>\n";
}
// Clean up the trailing newline
std::string section_text = ss.str();
section_text.pop_back();
text_.push_back(std::move(section_text));
}
}
}
current_text_ = text_.begin();
if(!duration_) {
duration_ = 3500;
duration_ = 3500; // 3.5 seconds
}
}
void outro::pre_show(window& window)
{
window.set_enter_disabled(true);
window.get_canvas(0).set_variable("outro_text", wfl::variant(text_));
window.get_canvas(0).set_variable("outro_text", wfl::variant(*current_text_));
connect_signal_on_draw(window, std::bind(&outro::draw_callback, this, std::ref(window)));
set_next_draw();
}
void outro::set_next_draw()
{
/* The UI is rendered at approximately 50 FPS - 1 frame every 20 ms - meaning fading progresses every 3 frames.
* TODO: not sure if 60 is a better value in that case?
*/
next_draw_ = SDL_GetTicks() + 60;
}
void outro::draw_callback(window& window)
{
if(SDL_GetTicks() < next_draw_) {
return;
}
/* If we've faded fully in...
*
* NOTE: we want fading to take around half a second. Given this function runs about every 3 frames, we
@ -86,13 +113,27 @@ void outro::draw_callback(window& window)
return;
}
canvas& window_canvas = window.get_canvas(0);
// If we've faded fully out...
if(!fading_in_ && fade_step_ < 0) {
window.close();
return;
}
std::advance(current_text_, 1);
canvas& window_canvas = window.get_canvas(0);
// ...and we've just showed the last text bit, close the window.
if(current_text_ == text_.end()) {
window.close();
return;
}
// ...else show the next bit.
window_canvas.set_variable("outro_text", wfl::variant(*current_text_));
fading_in_ = true;
fade_step_ = 0;
remove_timer(timer_id_);
timer_id_ = 0;
}
window_canvas.set_variable("fade_step", wfl::variant(fade_step_));
window_canvas.set_is_dirty(true);
@ -104,8 +145,6 @@ void outro::draw_callback(window& window)
} else {
fade_step_--;
}
set_next_draw();
}
void outro::post_show(window& /*window*/)

View File

@ -49,11 +49,10 @@ private:
/** Inherited from modal_dialog. */
virtual void post_show(window& window) override;
void set_next_draw();
void draw_callback(window& window);
std::string text_;
std::vector<std::string> text_;
std::vector<std::string>::iterator current_text_;
unsigned int duration_;
int fade_step_;
@ -61,7 +60,6 @@ private:
bool fading_in_;
std::size_t timer_id_;
std::size_t next_draw_;
};
} // namespace dialogs