The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
outro.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2017 - 2025
3 by Charles Dang <exodia339@gmail.com>
4 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY.
12
13 See the COPYING file for more details.
14*/
15
16#define GETTEXT_DOMAIN "wesnoth-lib"
17
18#include "gui/dialogs/outro.hpp"
19
20#include "about.hpp"
21#include "formula/variant.hpp"
23#include "gettext.hpp"
27
28#include <cmath>
29
30using namespace std::chrono_literals;
31
32namespace
33{
34
35// How long text fading should take - currently a hardcoded value.
36constexpr auto fade_duration = 500ms;
37
38}
39
40namespace gui2::dialogs
41{
42REGISTER_DIALOG(outro)
43
45 : modal_dialog(window_id())
46 , text_()
47 , text_index_(0)
48 , display_duration_(info.end_text_duration)
49 , stage_(stage::fading_in)
50 , stage_start_()
51{
52 if(!info.end_text.empty()) {
53 text_.push_back(info.end_text);
54 } else {
55 text_.push_back(_("The End"));
56 }
57
58 if(info.end_credits) {
59 text_.push_back(markup::span_size("large", info.campaign_name));
60
61 if(const auto campaign_credits = about::get_campaign_credits(info.campaign)) {
62 for(const auto& about : (*campaign_credits)->sections) {
63 if(about.names.empty()) {
64 continue;
65 }
66
67 // Split the names into chunks of 5. Use float for proper ceil function!
68 static const float chunk_size = 5.0;
69
70 const unsigned num_names = about.names.size();
71 const unsigned num_chunks = std::ceil(num_names / chunk_size);
72
73 for(std::size_t i = 0; i < num_chunks; ++i) {
74 std::stringstream ss;
75
76 // Only include section title on first chunk
77 if(i == 0) {
78 ss << about.title << "\n\n";
79 }
80
81 for(std::size_t k = i * chunk_size; k < std::min<unsigned>((i + 1) * chunk_size, num_names); ++k) {
82 ss << markup::span_size("xx-small", about.names[k].first) << "\n";
83 }
84
85 // Clean up the trailing newline
86 std::string section_text = ss.str();
87 section_text.pop_back();
88
89 text_.push_back(std::move(section_text));
90 }
91 }
92 }
93 }
94
95 if(display_duration_ == 0ms) {
96 display_duration_ = 3500ms; // 3.5 seconds
97 }
98}
99
101{
102 set_enter_disabled(true);
103 get_canvas(0).set_variable("outro_text", wfl::variant(text_[0]));
104 get_canvas(0).set_variable("fade_alpha", wfl::variant(0));
105}
106
108{
109 // window doesn't immediately close, keep returning until it does
110 if(text_index_ >= text_.size()) {
111 return;
112 }
113
114 const auto now = std::chrono::steady_clock::now();
115 canvas& window_canvas = window::get_canvas(0);
116
117 // TODO: Setting this in pre_show doesn't work, since it looks like it gets
118 // overwritten by styled_widget::update_canvas. But it's also weird to have
119 // this here. Find a better way to do this...
120 window_canvas.set_variable("text_wrap_mode", wfl::variant(PANGO_ELLIPSIZE_NONE));
121
122 const auto goto_stage = [this, &now](stage new_stage) {
123 stage_ = new_stage;
124 stage_start_ = now;
125 };
126
127 if(stage_start_ == std::chrono::steady_clock::time_point{}) {
128 stage_start_ = now;
129 }
130
131 switch(stage_) {
132 case stage::fading_in:
133 if(now <= stage_start_ + fade_duration) {
134 window_canvas.set_variable("fade_alpha", wfl::variant(float_to_color(get_fade_progress(now))));
135 } else {
136 goto_stage(stage::waiting);
137 }
138 break;
139
140 case stage::waiting:
141 if(now <= stage_start_ + display_duration_) {
142 return; // zzzzzzz....
143 } else {
144 goto_stage(stage::fading_out);
145 }
146 break;
147
149 if(now <= stage_start_ + fade_duration) {
150 window_canvas.set_variable("fade_alpha", wfl::variant(float_to_color(1.0 - get_fade_progress(now))));
151 } else if(++text_index_ < text_.size()) {
152 window_canvas.set_variable("outro_text", wfl::variant(text_[text_index_]));
153 goto_stage(stage::fading_in);
154 } else {
156 }
157 break;
158
159 default:
160 break;
161 }
162
163 window_canvas.update_size_variables();
164 queue_redraw();
165}
166
167double outro::get_fade_progress(const std::chrono::steady_clock::time_point& now) const
168{
169 return chrono::normalize_progress(now - stage_start_, fade_duration);
170}
171
172} // namespace dialogs
A simple canvas which can be drawn upon.
Definition canvas.hpp:45
void set_variable(const std::string &key, wfl::variant &&value)
Definition canvas.hpp:165
void update_size_variables()
Update WFL size variables.
Definition canvas.cpp:855
Abstract base class for all modal dialogs.
Dialog to display 'The End' at the end of a campaign.
Definition outro.hpp:28
virtual void update() override
Displays a simple fading screen with any user-provided text.
Definition outro.cpp:107
std::chrono::milliseconds display_duration_
How long to display each text entry.
Definition outro.hpp:56
virtual void pre_show() override
Actions to be taken before showing the window.
Definition outro.cpp:100
std::chrono::steady_clock::time_point stage_start_
The time point at which the current stage began.
Definition outro.hpp:62
std::size_t text_index_
The index of the text currently being shown.
Definition outro.hpp:53
double get_fade_progress(const std::chrono::steady_clock::time_point &now) const
Returns a normalized [0.0 .
Definition outro.cpp:167
std::vector< std::string > text_
The text to draw.
Definition outro.hpp:50
stage
Tracks whether we're fading in, displaying text, or fading out.
Definition outro.hpp:59
enum gui2::dialogs::outro::stage stage_
canvas & get_canvas(const unsigned index)
void queue_redraw()
Indicates that this widget should be redrawn.
Definition widget.cpp:464
void set_enter_disabled(const bool enter_disabled)
Disable the enter key.
Definition window.hpp:313
void close()
Requests to close the window.
Definition window.hpp:216
constexpr uint8_t float_to_color(double n)
Convert a double in the range [0.0,1.0] to an 8-bit colour value.
Definition color.hpp:274
static std::string _(const char *str)
Definition gettext.hpp:100
This file contains the window object, this object is a top level container which has the event manage...
#define REGISTER_DIALOG(window_id)
Wrapper for REGISTER_DIALOG2.
Display credits about all contributors.
utils::optional< credits_data::const_iterator > get_campaign_credits(const std::string &campaign)
Gets credits for a given campaign.
Definition about.cpp:100
constexpr double normalize_progress(const std::chrono::duration< RepE, PeriodE > &elapsed, const std::chrono::duration< RepD, PeriodD > &duration)
Definition chrono.hpp:88
std::string span_size(std::string_view size, Args &&... data)
Applies Pango markup to the input specifying its display size.
Definition markup.hpp:146
#define i