mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-14 01:27:00 +00:00
overlays: Redesign animation system (add easing functions, fix bugs)
Instead of speed, direction and distance, the user now specifies start/end offsets and how much time the transition should take. Fixes: - Stuttering caused from framerate estimation. - An edge case where animations would go over their supposed limit. Adds: - The ability to specify arbitrary easing functions for the animations - Implemented quadratic ease in and ease out and cubic ease in/out. - Usage of cubic ease in/out in the trophy notification
This commit is contained in:
parent
28770c1580
commit
5bace118a7
@ -1,19 +1,22 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#pragma optimize("", off)
|
||||
#include "overlay_animation.h"
|
||||
#include "overlay_controls.h"
|
||||
|
||||
#include <numeric>
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
namespace overlays
|
||||
{
|
||||
void animation_translate::apply(compiled_resource& resource)
|
||||
{
|
||||
if (progress == vector3i(0, 0, 0))
|
||||
if (!active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const vertex delta = { static_cast<float>(progress.x), static_cast<float>(progress.y), static_cast<float>(progress.z), 0.f };
|
||||
const vertex delta = { current.x, current.y, current.z, 0.f };
|
||||
for (auto& cmd : resource.draw_commands)
|
||||
{
|
||||
for (auto& v : cmd.verts)
|
||||
@ -23,49 +26,54 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
void animation_translate::update(u64 t)
|
||||
void animation_translate::update(u64 frame)
|
||||
{
|
||||
if (!active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (time == 0)
|
||||
if (frame_start == 0)
|
||||
{
|
||||
time = t;
|
||||
start = current;
|
||||
frame_start = frame;
|
||||
frame_end = u64(frame + duration * g_cfg.video.vblank_rate);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const u64 delta = (t - time);
|
||||
const u64 frames = delta / 16667;
|
||||
|
||||
if (frames)
|
||||
if (frame >= frame_end)
|
||||
{
|
||||
const int mag = frames * speed;
|
||||
const vector3i new_progress = progress + direction * mag;
|
||||
const auto d = new_progress.distance(progress_limit);
|
||||
|
||||
if (distance >= 0)
|
||||
{
|
||||
if (d > distance)
|
||||
{
|
||||
// Exit condition
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
progress = new_progress;
|
||||
distance = d;
|
||||
time = t;
|
||||
// Exit condition
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
f32 t = f32(frame - frame_start) / (frame_end - frame_start);
|
||||
|
||||
switch (type) {
|
||||
case animation_type::linear:
|
||||
break;
|
||||
case animation_type::ease_in_quad:
|
||||
t = t * t;
|
||||
break;
|
||||
case animation_type::ease_out_quad:
|
||||
t = t * (2.0 - t);
|
||||
break;
|
||||
case animation_type::ease_in_out_cubic:
|
||||
t = t > 0.5 ? 4.0 * std::pow((t - 1.0), 3.0) + 1.0 : 4.0 * std::pow(t, 3.0);
|
||||
break;
|
||||
}
|
||||
|
||||
current = (1.f - t) * start + t * end;
|
||||
}
|
||||
|
||||
void animation_translate::finish()
|
||||
{
|
||||
active = false;
|
||||
distance = -1;
|
||||
time = 0;
|
||||
frame_start = 0;
|
||||
frame_end = 0;
|
||||
current = end; // Snap current to limit in case we went over
|
||||
|
||||
if (on_finish)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
#include "Utilities/types.h"
|
||||
#include "Utilities/geometry.h"
|
||||
#include "overlay_utils.h"
|
||||
@ -9,28 +9,40 @@ namespace rsx
|
||||
{
|
||||
struct compiled_resource;
|
||||
|
||||
enum class animation_type
|
||||
{
|
||||
linear,
|
||||
ease_in_quad,
|
||||
ease_out_quad,
|
||||
ease_in_out_cubic,
|
||||
};
|
||||
|
||||
struct animation_base
|
||||
{
|
||||
bool active = false;
|
||||
animation_type type { animation_type::linear };
|
||||
|
||||
std::function<void()> on_finish;
|
||||
|
||||
virtual void apply(compiled_resource&) = 0;
|
||||
virtual void update(u64 t) = 0;
|
||||
virtual void update(u64 frame) = 0;
|
||||
};
|
||||
|
||||
struct animation_translate : animation_base
|
||||
{
|
||||
vector3i direction{};
|
||||
vector3i progress{};
|
||||
vector3i progress_limit{};
|
||||
|
||||
std::function<void()> on_finish;
|
||||
|
||||
int speed = 0;
|
||||
int distance = -1;
|
||||
u64 time = 0;
|
||||
private:
|
||||
vector3f start{}; // Set `current` instead of this
|
||||
// NOTE: Necessary because update() is called after rendering,
|
||||
// resulting in one frame of incorrect translation
|
||||
u64 frame_start = 0;
|
||||
u64 frame_end = 0;
|
||||
public:
|
||||
vector3f current{};
|
||||
vector3f end{};
|
||||
f32 duration{}; // in seconds
|
||||
|
||||
void apply(compiled_resource& data) override;
|
||||
void update(u64 t) override;
|
||||
void update(u64 frame) override;
|
||||
void finish();
|
||||
};
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "overlays.h"
|
||||
#include "Emu/RSX/RSXThread.h"
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
@ -46,10 +47,10 @@ namespace rsx
|
||||
text_view.align_text(overlay_element::text_align::center);
|
||||
text_view.back_color.a = 0.f;
|
||||
|
||||
sliding_animation.direction = { 1, 0, 0 };
|
||||
sliding_animation.speed = 10;
|
||||
sliding_animation.progress = { -int(frame.w), 0, 0 };
|
||||
sliding_animation.progress_limit = { 0, 0, 0};
|
||||
sliding_animation.duration = 1.5;
|
||||
sliding_animation.type = animation_type::ease_in_out_cubic;
|
||||
sliding_animation.current = { -f32(frame.w), 0, 0 };
|
||||
sliding_animation.end = { 0, 0, 0};
|
||||
sliding_animation.active = true;
|
||||
}
|
||||
|
||||
@ -73,8 +74,7 @@ namespace rsx
|
||||
{
|
||||
if (!sliding_animation.active)
|
||||
{
|
||||
sliding_animation.direction.x = -1;
|
||||
sliding_animation.progress_limit = { -int(frame.w), 0, 0 };
|
||||
sliding_animation.end = { -f32(frame.w), 0, 0 };
|
||||
sliding_animation.on_finish = [this]
|
||||
{
|
||||
s_trophy_semaphore.release();
|
||||
@ -87,7 +87,7 @@ namespace rsx
|
||||
|
||||
if (sliding_animation.active)
|
||||
{
|
||||
sliding_animation.update(t);
|
||||
sliding_animation.update(rsx::get_current_renderer()->vblank_count);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user