gui/outro: New clock-based timing logic for the text fading (#8454)

This version uses SDL_GetTicks() as a monotonic source to avoid the
previous version's pitfalls, namely the fact that the game's framerate
may not necessarily be a constant, and in particular, the old code
assumed a completely different framerate than what we ended up with
after the texture-based rendering changes in 1.17.x, resulting in an
almost-unnoticeable text fade due to the update() function being
called WAY more often than before.

Note that the reliance on SDL_GetTicks() means the timings break
at some point after 49 days of game runtime, exactly once. This
should result in a visible "jitter" effect if the 32-bits ticks value
wraps around in the middle of a fade sequence, but other than that
it's not that big of a deal to warrant requiring SDL 2.0.18+ for the
64-bit version.

I for one hope players wouldn't be running Wesnoth for that long
anyway. The game isn't exciting enough to justify it.
This commit is contained in:
Iris Morelle 2024-03-05 04:21:55 -03:00 committed by GitHub
parent 43dd442a4f
commit db30ca53ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 44 additions and 18 deletions

View File

@ -0,0 +1,3 @@
### User interface
* Fixed timing issue with the outro screen's text fading effect that made it so fast as
to be unnoticeable on many hardware configurations.

View File

@ -33,7 +33,7 @@
font_size = 80
font_family = "script"
color = "([215, 215, 215, min(ceil(as_decimal(fade_step * 25.5)), 255)])"
color = "([215, 215, 215, fade_alpha])"
text = "(outro_text)"
text_markup = true

View File

@ -28,6 +28,14 @@
#include <cmath>
namespace
{
// How long text fading should take - currently a hardcoded value.
const unsigned FADE_DURATION_MS = 500;
} // end unnamed namespace
namespace gui2::dialogs
{
REGISTER_DIALOG(outro)
@ -38,7 +46,8 @@ outro::outro(const game_classification& info)
, current_text_()
, text_index_(0)
, duration_(info.end_text_duration)
, fade_step_(0)
, fade_alpha_(0)
, fade_start_(0)
, fading_in_(true)
, timer_id_(0)
{
@ -105,16 +114,18 @@ void outro::update()
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
* limit ourselves to a reasonable 10 fade steps with an alpha difference (rounded up) of 25.5 each cycle.
* The actual calculation for alpha is done in the window definition in WFL.
*/
if(fading_in_ && fade_step_ > 10) {
if(fade_start_ == 0) {
fade_start_ = SDL_GetTicks();
}
// If we've faded fully in...
if(fading_in_ && fade_alpha_ >= 255) {
// Schedule the fadeout after the provided delay.
if(timer_id_ == 0) {
timer_id_ = add_timer(duration_, [this](std::size_t) { fading_in_ = false; });
timer_id_ = add_timer(duration_, [this](std::size_t) {
fading_in_ = false;
fade_start_ = 0;
});
}
return;
@ -123,7 +134,7 @@ void outro::update()
canvas& window_canvas = window::get_canvas(0);
// If we've faded fully out...
if(!fading_in_ && fade_step_ < 0) {
if(!fading_in_ && fade_alpha_ == 0) {
// ...and we've just showed the last text bit, close the window.
text_index_++;
if(text_index_ >= text_.size()) {
@ -136,20 +147,31 @@ void outro::update()
window_canvas.set_variable("outro_text", wfl::variant(current_text_));
fading_in_ = true;
fade_step_ = 0;
remove_timer(timer_id_);
timer_id_ = 0;
fade_start_ = SDL_GetTicks();
}
window_canvas.set_variable("fade_step", wfl::variant(fade_step_));
window_canvas.set_variable("fade_alpha", wfl::variant(fade_alpha_));
window_canvas.update_size_variables();
queue_redraw();
if(fading_in_) {
fade_step_++;
} else {
fade_step_--;
auto current_ticks = SDL_GetTicks();
if(fade_start_ > current_ticks) {
// 32-bit ticks counter wraps around after about 49 days, the 64-bit version
// requires SDL 2.0.18+. Just restart the counter in the worst case and let
// the player deal with the sheer ridiculousness of their predicament.
fade_start_ = current_ticks;
}
fade_alpha_ = std::clamp<int>(
std::round(255.0 * double(current_ticks - fade_start_) / double(FADE_DURATION_MS)),
0, 255);
if(!fading_in_) {
fade_alpha_ = 255 - fade_alpha_;
}
}

View File

@ -53,7 +53,8 @@ private:
std::size_t text_index_;
unsigned int duration_;
int fade_step_;
int fade_alpha_;
uint32_t fade_start_;
bool fading_in_;