mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-29 22:20:48 +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_animation.h"
|
||||||
#include "overlay_controls.h"
|
#include "overlay_controls.h"
|
||||||
|
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
namespace rsx
|
namespace rsx
|
||||||
{
|
{
|
||||||
namespace overlays
|
namespace overlays
|
||||||
{
|
{
|
||||||
void animation_translate::apply(compiled_resource& resource)
|
void animation_translate::apply(compiled_resource& resource)
|
||||||
{
|
{
|
||||||
if (progress == vector3i(0, 0, 0))
|
if (!active)
|
||||||
{
|
{
|
||||||
return;
|
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& cmd : resource.draw_commands)
|
||||||
{
|
{
|
||||||
for (auto& v : cmd.verts)
|
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)
|
if (!active)
|
||||||
{
|
{
|
||||||
return;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u64 delta = (t - time);
|
if (frame >= frame_end)
|
||||||
const u64 frames = delta / 16667;
|
|
||||||
|
|
||||||
if (frames)
|
|
||||||
{
|
{
|
||||||
const int mag = frames * speed;
|
// Exit condition
|
||||||
const vector3i new_progress = progress + direction * mag;
|
finish();
|
||||||
const auto d = new_progress.distance(progress_limit);
|
return;
|
||||||
|
|
||||||
if (distance >= 0)
|
|
||||||
{
|
|
||||||
if (d > distance)
|
|
||||||
{
|
|
||||||
// Exit condition
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
progress = new_progress;
|
|
||||||
distance = d;
|
|
||||||
time = t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
void animation_translate::finish()
|
||||||
{
|
{
|
||||||
active = false;
|
active = false;
|
||||||
distance = -1;
|
frame_start = 0;
|
||||||
time = 0;
|
frame_end = 0;
|
||||||
|
current = end; // Snap current to limit in case we went over
|
||||||
|
|
||||||
if (on_finish)
|
if (on_finish)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Utilities/types.h"
|
#include "Utilities/types.h"
|
||||||
#include "Utilities/geometry.h"
|
#include "Utilities/geometry.h"
|
||||||
#include "overlay_utils.h"
|
#include "overlay_utils.h"
|
||||||
@ -9,28 +9,40 @@ namespace rsx
|
|||||||
{
|
{
|
||||||
struct compiled_resource;
|
struct compiled_resource;
|
||||||
|
|
||||||
|
enum class animation_type
|
||||||
|
{
|
||||||
|
linear,
|
||||||
|
ease_in_quad,
|
||||||
|
ease_out_quad,
|
||||||
|
ease_in_out_cubic,
|
||||||
|
};
|
||||||
|
|
||||||
struct animation_base
|
struct animation_base
|
||||||
{
|
{
|
||||||
bool active = false;
|
bool active = false;
|
||||||
|
animation_type type { animation_type::linear };
|
||||||
|
|
||||||
|
std::function<void()> on_finish;
|
||||||
|
|
||||||
virtual void apply(compiled_resource&) = 0;
|
virtual void apply(compiled_resource&) = 0;
|
||||||
virtual void update(u64 t) = 0;
|
virtual void update(u64 frame) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct animation_translate : animation_base
|
struct animation_translate : animation_base
|
||||||
{
|
{
|
||||||
vector3i direction{};
|
private:
|
||||||
vector3i progress{};
|
vector3f start{}; // Set `current` instead of this
|
||||||
vector3i progress_limit{};
|
// NOTE: Necessary because update() is called after rendering,
|
||||||
|
// resulting in one frame of incorrect translation
|
||||||
std::function<void()> on_finish;
|
u64 frame_start = 0;
|
||||||
|
u64 frame_end = 0;
|
||||||
int speed = 0;
|
public:
|
||||||
int distance = -1;
|
vector3f current{};
|
||||||
u64 time = 0;
|
vector3f end{};
|
||||||
|
f32 duration{}; // in seconds
|
||||||
|
|
||||||
void apply(compiled_resource& data) override;
|
void apply(compiled_resource& data) override;
|
||||||
void update(u64 t) override;
|
void update(u64 frame) override;
|
||||||
void finish();
|
void finish();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "overlays.h"
|
#include "overlays.h"
|
||||||
|
#include "Emu/RSX/RSXThread.h"
|
||||||
|
|
||||||
namespace rsx
|
namespace rsx
|
||||||
{
|
{
|
||||||
@ -46,10 +47,10 @@ namespace rsx
|
|||||||
text_view.align_text(overlay_element::text_align::center);
|
text_view.align_text(overlay_element::text_align::center);
|
||||||
text_view.back_color.a = 0.f;
|
text_view.back_color.a = 0.f;
|
||||||
|
|
||||||
sliding_animation.direction = { 1, 0, 0 };
|
sliding_animation.duration = 1.5;
|
||||||
sliding_animation.speed = 10;
|
sliding_animation.type = animation_type::ease_in_out_cubic;
|
||||||
sliding_animation.progress = { -int(frame.w), 0, 0 };
|
sliding_animation.current = { -f32(frame.w), 0, 0 };
|
||||||
sliding_animation.progress_limit = { 0, 0, 0};
|
sliding_animation.end = { 0, 0, 0};
|
||||||
sliding_animation.active = true;
|
sliding_animation.active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,8 +74,7 @@ namespace rsx
|
|||||||
{
|
{
|
||||||
if (!sliding_animation.active)
|
if (!sliding_animation.active)
|
||||||
{
|
{
|
||||||
sliding_animation.direction.x = -1;
|
sliding_animation.end = { -f32(frame.w), 0, 0 };
|
||||||
sliding_animation.progress_limit = { -int(frame.w), 0, 0 };
|
|
||||||
sliding_animation.on_finish = [this]
|
sliding_animation.on_finish = [this]
|
||||||
{
|
{
|
||||||
s_trophy_semaphore.release();
|
s_trophy_semaphore.release();
|
||||||
@ -87,7 +87,7 @@ namespace rsx
|
|||||||
|
|
||||||
if (sliding_animation.active)
|
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