[WIP] New tweening-based API for the outro screen
This commit is contained in:
parent
5b05815d5c
commit
f415ca9de1
7 changed files with 584 additions and 48 deletions
|
@ -401,6 +401,7 @@ utils/irdya_datetime.cpp
|
|||
utils/markov_generator.cpp
|
||||
utils/name_generator_factory.cpp
|
||||
utils/parse_network_address.cpp
|
||||
utils/tweened_value.cpp
|
||||
variable.cpp
|
||||
variable_info.cpp
|
||||
wesnothd_connection.cpp
|
||||
|
|
|
@ -32,7 +32,8 @@ namespace
|
|||
{
|
||||
|
||||
// How long text fading should take - currently a hardcoded value.
|
||||
const unsigned FADE_DURATION_MS = 500;
|
||||
using namespace std::chrono_literals;
|
||||
constexpr auto FADE_DURATION = 500ms;
|
||||
|
||||
} // end unnamed namespace
|
||||
|
||||
|
@ -42,15 +43,22 @@ REGISTER_DIALOG(outro)
|
|||
|
||||
outro::outro(const game_classification& info)
|
||||
: modal_dialog(window_id())
|
||||
, alpha_queue_()
|
||||
, text_()
|
||||
, current_text_()
|
||||
, text_index_(0)
|
||||
, duration_(info.end_text_duration)
|
||||
, fade_alpha_(0)
|
||||
, fade_start_(0)
|
||||
, fading_in_(true)
|
||||
, timer_id_(0)
|
||||
{
|
||||
// 3.5 seconds by default
|
||||
const auto show_duration = info.end_text_duration > 0 ? std::chrono::milliseconds{info.end_text_duration} : 3500ms;
|
||||
|
||||
alpha_queue_ = {
|
||||
{0, 255, FADE_DURATION, utils::ease_out_cubic},
|
||||
{255, 255, show_duration, utils::ease_out_cubic},
|
||||
{255, 0, FADE_DURATION, utils::ease_out_cubic},
|
||||
};
|
||||
|
||||
alpha_queue_.on_complete(std::bind(&outro::advance_text, this));
|
||||
|
||||
if(!info.end_text.empty()) {
|
||||
text_.push_back(info.end_text);
|
||||
} else {
|
||||
|
@ -114,23 +122,6 @@ void outro::update()
|
|||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
fade_start_ = 0;
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
canvas& window_canvas = window::get_canvas(0);
|
||||
|
||||
// If we've faded fully out...
|
||||
|
@ -141,10 +132,9 @@ void outro::update()
|
|||
window::close();
|
||||
return;
|
||||
}
|
||||
current_text_ = text_[text_index_];
|
||||
|
||||
// ...else show the next bit.
|
||||
window_canvas.set_variable("outro_text", wfl::variant(current_text_));
|
||||
window_canvas.set_variable("outro_text", wfl::variant{current_text()});
|
||||
|
||||
fading_in_ = true;
|
||||
|
||||
|
@ -156,29 +146,24 @@ void outro::update()
|
|||
|
||||
window_canvas.set_variable("fade_alpha", wfl::variant(fade_alpha_));
|
||||
window_canvas.update_size_variables();
|
||||
|
||||
queue_redraw();
|
||||
}
|
||||
|
||||
auto current_ticks = SDL_GetTicks();
|
||||
void outro::advance_text()
|
||||
{
|
||||
// Advance to the next text block, and either display it or close the window if we've shown them all.
|
||||
text_index_++;
|
||||
|
||||
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_;
|
||||
if(text_index_ < text_.size()) {
|
||||
window::get_canvas(0).set_variable("outro_text", wfl::variant{current_text()});
|
||||
} else {
|
||||
window::close();
|
||||
}
|
||||
}
|
||||
|
||||
void outro::post_show(window& /*window*/)
|
||||
{
|
||||
remove_timer(timer_id_);
|
||||
timer_id_ = 0;
|
||||
}
|
||||
|
||||
} // namespace dialogs
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "gui/dialogs/modal_dialog.hpp"
|
||||
#include "utils/tweened_value.hpp"
|
||||
|
||||
class game_classification;
|
||||
|
||||
|
@ -48,17 +49,13 @@ private:
|
|||
|
||||
virtual void post_show(window& window) override;
|
||||
|
||||
void advance_text();
|
||||
|
||||
utils::tweened_value_queue alpha_queue_;
|
||||
|
||||
std::vector<std::string> text_;
|
||||
std::string current_text_;
|
||||
std::size_t text_index_;
|
||||
|
||||
unsigned int duration_;
|
||||
int fade_alpha_;
|
||||
uint32_t fade_start_;
|
||||
|
||||
bool fading_in_;
|
||||
|
||||
std::size_t timer_id_;
|
||||
};
|
||||
|
||||
} // namespace dialogs
|
||||
|
|
293
src/utils/easings.cpp
Normal file
293
src/utils/easings.cpp
Normal file
|
@ -0,0 +1,293 @@
|
|||
//
|
||||
// This is free and unencumbered software released into the public domain.
|
||||
//
|
||||
// Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
// distribute this software, either in source code form or as a compiled
|
||||
// binary, for any purpose, commercial or non-commercial, and by any
|
||||
// means.
|
||||
//
|
||||
// In jurisdictions that recognize copyright laws, the author or authors
|
||||
// of this software dedicate any and all copyright interest in the
|
||||
// software to the public domain. We make this dedication for the benefit
|
||||
// of the public at large and to the detriment of our heirs and
|
||||
// successors. We intend this dedication to be an overt act of
|
||||
// relinquishment in perpetuity of all present and future rights to this
|
||||
// software under copyright law.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
// For more information, please refer to <https://unlicense.org>
|
||||
//
|
||||
|
||||
#include "utils/easings.hpp"
|
||||
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
using namespace boost::math::constants;
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace utils::easing
|
||||
{
|
||||
// Modeled after the line y = x
|
||||
double linear_interpolation(double p)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
// Modeled after the parabola y = x^2
|
||||
double quadratic_ease_in(double p)
|
||||
{
|
||||
return p * p;
|
||||
}
|
||||
|
||||
// Modeled after the parabola y = -x^2 + 2x
|
||||
double quadratic_ease_out(double p)
|
||||
{
|
||||
return -(p * (p - 2));
|
||||
}
|
||||
|
||||
// Modeled after the piecewise quadratic
|
||||
// y = (1/2)((2x)^2) ; [0, 0.5)
|
||||
// y = -(1/2)((2x-1)*(2x-3) - 1) ; [0.5, 1]
|
||||
double quadratic_ease_in_out(double p)
|
||||
{
|
||||
if(p < 0.5) {
|
||||
return 2 * p * p;
|
||||
} else {
|
||||
return (-2 * p * p) + (4 * p) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Modeled after the cubic y = x^3
|
||||
double cubic_ease_in(double p)
|
||||
{
|
||||
return p * p * p;
|
||||
}
|
||||
|
||||
// Modeled after the cubic y = (x - 1)^3 + 1
|
||||
double cubic_ease_out(double p)
|
||||
{
|
||||
double f = (p - 1);
|
||||
return f * f * f + 1;
|
||||
}
|
||||
|
||||
// Modeled after the piecewise cubic
|
||||
// y = (1/2)((2x)^3) ; [0, 0.5)
|
||||
// y = (1/2)((2x-2)^3 + 2) ; [0.5, 1]
|
||||
double cubic_ease_in_out(double p)
|
||||
{
|
||||
if(p < 0.5) {
|
||||
return 4 * p * p * p;
|
||||
} else {
|
||||
double f = ((2 * p) - 2);
|
||||
return 0.5 * f * f * f + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Modeled after the quartic x^4
|
||||
double quartic_ease_in(double p)
|
||||
{
|
||||
return p * p * p * p;
|
||||
}
|
||||
|
||||
// Modeled after the quartic y = 1 - (x - 1)^4
|
||||
double quartic_ease_out(double p)
|
||||
{
|
||||
double f = (p - 1);
|
||||
return f * f * f * (1 - p) + 1;
|
||||
}
|
||||
|
||||
// Modeled after the piecewise quartic
|
||||
// y = (1/2)((2x)^4) ; [0, 0.5)
|
||||
// y = -(1/2)((2x-2)^4 - 2) ; [0.5, 1]
|
||||
double quartic_ease_in_out(double p)
|
||||
{
|
||||
if(p < 0.5) {
|
||||
return 8 * p * p * p * p;
|
||||
} else {
|
||||
double f = (p - 1);
|
||||
return -8 * f * f * f * f + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Modeled after the quintic y = x^5
|
||||
double quintic_ease_in(double p)
|
||||
{
|
||||
return p * p * p * p * p;
|
||||
}
|
||||
|
||||
// Modeled after the quintic y = (x - 1)^5 + 1
|
||||
double quintic_ease_out(double p)
|
||||
{
|
||||
double f = (p - 1);
|
||||
return f * f * f * f * f + 1;
|
||||
}
|
||||
|
||||
// Modeled after the piecewise quintic
|
||||
// y = (1/2)((2x)^5) ; [0, 0.5)
|
||||
// y = (1/2)((2x-2)^5 + 2) ; [0.5, 1]
|
||||
double quintic_ease_in_out(double p)
|
||||
{
|
||||
if(p < 0.5) {
|
||||
return 16 * p * p * p * p * p;
|
||||
} else {
|
||||
double f = ((2 * p) - 2);
|
||||
return 0.5 * f * f * f * f * f + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Modeled after quarter-cycle of sine wave
|
||||
double sine_ease_in(double p)
|
||||
{
|
||||
return std::sin((p - 1) * half_pi<double>()) + 1;
|
||||
}
|
||||
|
||||
// Modeled after quarter-cycle of sine wave (different phase)
|
||||
double sine_ease_out(double p)
|
||||
{
|
||||
return std::sin(p * half_pi<double>());
|
||||
}
|
||||
|
||||
// Modeled after half sine wave
|
||||
double sine_ease_in_out(double p)
|
||||
{
|
||||
return 0.5 * (1 - std::cos(p * pi<double>()));
|
||||
}
|
||||
|
||||
// Modeled after shifted quadrant IV of unit circle
|
||||
double circular_ease_in(double p)
|
||||
{
|
||||
return 1 - std::sqrt(1 - (p * p));
|
||||
}
|
||||
|
||||
// Modeled after shifted quadrant II of unit circle
|
||||
double circular_ease_out(double p)
|
||||
{
|
||||
return std::sqrt((2 - p) * p);
|
||||
}
|
||||
|
||||
// Modeled after the piecewise circular function
|
||||
// y = (1/2)(1 - sqrt(1 - 4x^2)) ; [0, 0.5)
|
||||
// y = (1/2)(sqrt(-(2x - 3)*(2x - 1)) + 1) ; [0.5, 1]
|
||||
double circular_ease_in_out(double p)
|
||||
{
|
||||
if(p < 0.5) {
|
||||
return 0.5 * (1 - std::sqrt(1 - 4 * (p * p)));
|
||||
} else {
|
||||
return 0.5 * (std::sqrt(-((2 * p) - 3) * ((2 * p) - 1)) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Modeled after the exponential function y = 2^(10(x - 1))
|
||||
double exponential_ease_in(double p)
|
||||
{
|
||||
return (p == 0.0) ? p : std::pow(2, 10 * (p - 1));
|
||||
}
|
||||
|
||||
// Modeled after the exponential function y = -2^(-10x) + 1
|
||||
double exponential_ease_out(double p)
|
||||
{
|
||||
return (p == 1.0) ? p : 1 - std::pow(2, -10 * p);
|
||||
}
|
||||
|
||||
// Modeled after the piecewise exponential
|
||||
// y = (1/2)2^(10(2x - 1)) ; [0,0.5)
|
||||
// y = -(1/2)*2^(-10(2x - 1))) + 1 ; [0.5,1]
|
||||
double exponential_ease_in_out(double p)
|
||||
{
|
||||
if(p == 0.0 || p == 1.0)
|
||||
return p;
|
||||
|
||||
if(p < 0.5) {
|
||||
return 0.5 * std::pow(2, (20 * p) - 10);
|
||||
} else {
|
||||
return -0.5 * std::pow(2, (-20 * p) + 10) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Modeled after the damped sine wave y = sin(13pi/2*x)*pow(2, 10 * (x - 1))
|
||||
double elastic_ease_in(double p)
|
||||
{
|
||||
return sin(13 * half_pi<double>() * p) * std::pow(2, 10 * (p - 1));
|
||||
}
|
||||
|
||||
// Modeled after the damped sine wave y = sin(-13pi/2*(x + 1))*pow(2, -10x) + 1
|
||||
double elastic_ease_out(double p)
|
||||
{
|
||||
return std::sin(-13 * half_pi<double>() * (p + 1)) * std::pow(2, -10 * p) + 1;
|
||||
}
|
||||
|
||||
// Modeled after the piecewise exponentially-damped sine wave:
|
||||
// y = (1/2)*sin(13pi/2*(2*x))*pow(2, 10 * ((2*x) - 1)) ; [0,0.5)
|
||||
// y = (1/2)*(sin(-13pi/2*((2x-1)+1))*pow(2,-10(2*x-1)) + 2) ; [0.5, 1]
|
||||
double elastic_ease_in_out(double p)
|
||||
{
|
||||
if(p < 0.5) {
|
||||
return 0.5 * std::sin(13 * half_pi<double>() * (2 * p)) * std::pow(2, 10 * ((2 * p) - 1));
|
||||
} else {
|
||||
return 0.5 * (std::sin(-13 * half_pi<double>() * ((2 * p - 1) + 1)) * std::pow(2, -10 * (2 * p - 1)) + 2);
|
||||
}
|
||||
}
|
||||
|
||||
// Modeled after the overshooting cubic y = x^3-x*sin(x*pi)
|
||||
double back_ease_in(double p)
|
||||
{
|
||||
return p * p * p - p * std::sin(p * pi<double>());
|
||||
}
|
||||
|
||||
// Modeled after overshooting cubic y = 1-((1-x)^3-(1-x)*sin((1-x)*pi))
|
||||
double back_ease_out(double p)
|
||||
{
|
||||
double f = (1 - p);
|
||||
return 1 - (f * f * f - f * std::sin(f * pi<double>()));
|
||||
}
|
||||
|
||||
// Modeled after the piecewise overshooting cubic function:
|
||||
// y = (1/2)*((2x)^3-(2x)*sin(2*x*pi)) ; [0, 0.5)
|
||||
// y = (1/2)*(1-((1-x)^3-(1-x)*sin((1-x)*pi))+1) ; [0.5, 1]
|
||||
double back_ease_in_out(double p)
|
||||
{
|
||||
if(p < 0.5) {
|
||||
double f = 2 * p;
|
||||
return 0.5 * (f * f * f - f * std::sin(f * pi<double>()));
|
||||
} else {
|
||||
double f = (1 - (2 * p - 1));
|
||||
return 0.5 * (1 - (f * f * f - f * std::sin(f * pi<double>()))) + 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
double bounce_ease_in(double p)
|
||||
{
|
||||
return 1 - bounce_ease_out(1 - p);
|
||||
}
|
||||
|
||||
double bounce_ease_out(double p)
|
||||
{
|
||||
if(p < 4 / 11.0) {
|
||||
return (121 * p * p) / 16.0;
|
||||
} else if(p < 8 / 11.0) {
|
||||
return (363 / 40.0 * p * p) - (99 / 10.0 * p) + 17 / 5.0;
|
||||
} else if(p < 9 / 10.0) {
|
||||
return (4356 / 361.0 * p * p) - (35442 / 1805.0 * p) + 16061 / 1805.0;
|
||||
} else {
|
||||
return (54 / 5.0 * p * p) - (513 / 25.0 * p) + 268 / 25.0;
|
||||
}
|
||||
}
|
||||
|
||||
double bounce_ease_in_out(double p)
|
||||
{
|
||||
if(p < 0.5) {
|
||||
return 0.5 * bounce_ease_in(p * 2);
|
||||
} else {
|
||||
return 0.5 * bounce_ease_out(p * 2 - 1) + 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace utils::easing
|
86
src/utils/easings.hpp
Normal file
86
src/utils/easings.hpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
//
|
||||
// This is free and unencumbered software released into the public domain.
|
||||
//
|
||||
// Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
// distribute this software, either in source code form or as a compiled
|
||||
// binary, for any purpose, commercial or non-commercial, and by any
|
||||
// means.
|
||||
//
|
||||
// In jurisdictions that recognize copyright laws, the author or authors
|
||||
// of this software dedicate any and all copyright interest in the
|
||||
// software to the public domain. We make this dedication for the benefit
|
||||
// of the public at large and to the detriment of our heirs and
|
||||
// successors. We intend this dedication to be an overt act of
|
||||
// relinquishment in perpetuity of all present and future rights to this
|
||||
// software under copyright law.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
// For more information, please refer to <https://unlicense.org>
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace utils::easing
|
||||
{
|
||||
// Linear interpolation (no easing)
|
||||
double linear_interpolation(double p);
|
||||
|
||||
// Quadratic easing; p^2
|
||||
double quadratic_ease_in(double p);
|
||||
double quadratic_ease_out(double p);
|
||||
double quadratic_ease_in_out(double p);
|
||||
|
||||
// Cubic easing; p^3
|
||||
double cubic_ease_in(double p);
|
||||
double cubic_ease_out(double p);
|
||||
double cubic_ease_in_out(double p);
|
||||
|
||||
// Quartic easing; p^4
|
||||
double quartic_ease_in(double p);
|
||||
double quartic_ease_out(double p);
|
||||
double quartic_ease_in_out(double p);
|
||||
|
||||
// Quintic easing; p^5
|
||||
double quintic_ease_in(double p);
|
||||
double quintic_ease_out(double p);
|
||||
double quintic_ease_in_out(double p);
|
||||
|
||||
// Sine wave easing; sin(p * PI/2)
|
||||
double sine_ease_in(double p);
|
||||
double sine_ease_out(double p);
|
||||
double sine_ease_in_out(double p);
|
||||
|
||||
// Circular easing; sqrt(1 - p^2)
|
||||
double circular_ease_in(double p);
|
||||
double circular_ease_out(double p);
|
||||
double circular_ease_in_out(double p);
|
||||
|
||||
// Exponential easing, base 2
|
||||
double exponential_ease_in(double p);
|
||||
double exponential_ease_out(double p);
|
||||
double exponential_ease_in_out(double p);
|
||||
|
||||
// Exponentially-damped sine wave easing
|
||||
double elastic_ease_in(double p);
|
||||
double elastic_ease_out(double p);
|
||||
double elastic_ease_in_out(double p);
|
||||
|
||||
// Overshooting cubic easing;
|
||||
double back_ease_in(double p);
|
||||
double back_ease_out(double p);
|
||||
double back_ease_in_out(double p);
|
||||
|
||||
// Exponentially-decaying bounce easing
|
||||
double bounce_ease_in(double p);
|
||||
double bounce_ease_out(double p);
|
||||
double bounce_ease_in_out(double p);
|
||||
|
||||
} // end namespace utils::easing
|
90
src/utils/tweened_value.cpp
Normal file
90
src/utils/tweened_value.cpp
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
Copyright (C) 2024
|
||||
Part of the Battle for Wesnoth Project https://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#include "utils/tweened_value.hpp"
|
||||
#include "log.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace utils
|
||||
{
|
||||
tweened_value::tweened_value(
|
||||
int32_t value_start, int32_t value_end, tweened_value::Resolution duration, std::function<double(double)> easing)
|
||||
: duration{duration}
|
||||
, value_start{value_start}
|
||||
, delta{value_end - value_start}
|
||||
, start_time{std::nullopt}
|
||||
, easing{easing}
|
||||
{
|
||||
}
|
||||
|
||||
std::pair<int32_t, bool> tweened_value::value()
|
||||
{
|
||||
if(delta == 0) {
|
||||
// return {value_start, true};
|
||||
}
|
||||
|
||||
if(!start_time) {
|
||||
start_time = std::chrono::steady_clock::now();
|
||||
return {value_start, false};
|
||||
}
|
||||
|
||||
const auto elapsed = elapsed_time();
|
||||
if(elapsed >= duration) {
|
||||
start_time.reset();
|
||||
return {value_start + delta, true};
|
||||
}
|
||||
|
||||
const double completed = std::clamp(1.0 * elapsed / duration, 0.0, 1.0);
|
||||
return {value_start + (delta * easing(completed)), false};
|
||||
}
|
||||
|
||||
tweened_value::Resolution tweened_value::elapsed_time() const
|
||||
{
|
||||
if(start_time) {
|
||||
return std::chrono::duration_cast<Resolution>(std::chrono::steady_clock::now() - *start_time);
|
||||
} else {
|
||||
return Resolution{0};
|
||||
}
|
||||
}
|
||||
|
||||
int32_t tweened_value_queue::value()
|
||||
{
|
||||
if(queue.empty()) {
|
||||
throw std::runtime_error("Attempt to get tweened value from empty queue");
|
||||
}
|
||||
|
||||
const auto& [value, stage_complete] = queue.front().value();
|
||||
|
||||
if(stage_complete) {
|
||||
if(mode == loop_mode::loop) {
|
||||
loop_queue.push(std::exchange(queue.front(), tweened_value{}));
|
||||
}
|
||||
|
||||
queue.pop();
|
||||
}
|
||||
|
||||
if(queue.empty()) {
|
||||
if(on_queue_exhausted) {
|
||||
on_queue_exhausted();
|
||||
}
|
||||
|
||||
if(mode == loop_mode::loop) {
|
||||
std::swap(loop_queue, queue);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
} // end namespace utils
|
84
src/utils/tweened_value.hpp
Normal file
84
src/utils/tweened_value.hpp
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
Copyright (C) 2024
|
||||
Part of the Battle for Wesnoth Project https://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "utils/easings.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
#include <tuple>
|
||||
|
||||
namespace utils
|
||||
{
|
||||
class tweened_value
|
||||
{
|
||||
using Resolution = std::chrono::milliseconds;
|
||||
|
||||
public:
|
||||
tweened_value() = default;
|
||||
|
||||
tweened_value(int32_t value_start, int32_t value_end, Resolution duration, std::function<double(double)> easing);
|
||||
|
||||
std::pair<int32_t, bool> value();
|
||||
|
||||
Resolution elapsed_time() const;
|
||||
|
||||
private:
|
||||
Resolution duration;
|
||||
|
||||
int32_t value_start;
|
||||
int32_t delta;
|
||||
|
||||
std::optional<std::chrono::steady_clock::time_point> start_time;
|
||||
std::function<double(double)> easing;
|
||||
};
|
||||
|
||||
class tweened_value_queue
|
||||
{
|
||||
public:
|
||||
enum class loop_mode { once, loop };
|
||||
|
||||
tweened_value_queue() = default;
|
||||
|
||||
tweened_value_queue(std::initializer_list<tweened_value> list)
|
||||
: queue{decltype(queue)::container_type{list}}
|
||||
{
|
||||
}
|
||||
|
||||
void queue_value(tweened_value v)
|
||||
{
|
||||
queue.push(std::move(v));
|
||||
}
|
||||
|
||||
void on_complete(std::function<void()> f)
|
||||
{
|
||||
on_queue_exhausted = f;
|
||||
}
|
||||
|
||||
int32_t value();
|
||||
|
||||
private:
|
||||
std::queue<tweened_value> queue;
|
||||
std::queue<tweened_value> loop_queue;
|
||||
|
||||
std::function<void()> on_queue_exhausted;
|
||||
|
||||
loop_mode mode = loop_mode::loop;
|
||||
};
|
||||
|
||||
} // end namespace utils
|
Loading…
Add table
Reference in a new issue