update scrolling using delta_time to allow for smooth scrolling at different refresh rates (ie, using fpslocker).

This commit is contained in:
ITotalJustice
2025-07-30 18:03:50 +01:00
parent f71c10619c
commit 430ee2280a
3 changed files with 26 additions and 7 deletions

View File

@@ -337,6 +337,8 @@ public:
nj::Decoder m_decoder; nj::Decoder m_decoder;
#endif #endif
double m_delta_time{};
private: // from nanovg decko3d example by adubbz private: // from nanovg decko3d example by adubbz
static constexpr unsigned NumFramebuffers = 2; static constexpr unsigned NumFramebuffers = 2;
static constexpr unsigned StaticCmdSize = 0x1000; static constexpr unsigned StaticCmdSize = 0x1000;

View File

@@ -395,12 +395,12 @@ struct Controller {
m_kup = 0; m_kup = 0;
} }
void UpdateButtonHeld(u64 buttons) { void UpdateButtonHeld(u64 buttons, double delta) {
if (m_kdown & buttons) { if (m_kdown & buttons) {
m_step = 50; m_step = 50;
m_counter = 0; m_counter = 0;
} else if (m_kheld & buttons) { } else if (m_kheld & buttons) {
m_counter += m_step; m_counter += m_step * delta;
if (m_counter >= m_MAX) { if (m_counter >= m_MAX) {
m_kdown |= m_kheld & buttons; m_kdown |= m_kheld & buttons;
@@ -411,10 +411,10 @@ struct Controller {
} }
private: private:
static constexpr int m_MAX = 1000; static constexpr double m_MAX = 1000;
static constexpr int m_MAX_STEP = 250; static constexpr double m_MAX_STEP = 250;
int m_step = 50; double m_step = 50;
int m_counter = 0; double m_counter = 0;
}; };
} // namespace sphaira } // namespace sphaira

View File

@@ -413,6 +413,14 @@ void on_i18n_change() {
} // namespace } // namespace
void App::Loop() { void App::Loop() {
// adjust these if FPSlocker ever supports different min/max fps.
constexpr double min_delta = 1000.0 / 120.0; // 120 fps
constexpr double max_delta = 1000.0 / 15.0; // 15 fps
constexpr double target_delta = 1000.0 / 60.0; // 60 fps
u64 start = armTicksToNs(armGetSystemTick());
m_delta_time = 1.0;
while (!m_quit && appletMainLoop()) { while (!m_quit && appletMainLoop()) {
if (m_widgets.empty()) { if (m_widgets.empty()) {
m_quit = true; m_quit = true;
@@ -497,6 +505,15 @@ void App::Loop() {
this->Poll(); this->Poll();
this->Update(); this->Update();
this->Draw(); this->Draw();
// check how long this frame took.
const u64 now = armTicksToNs(armGetSystemTick());
// convert to ns.
const double delta = (double)(now - start) / 1e+6;
// clamp and normalise to 1.0 as the target, higher values if we took too long.
m_delta_time = std::clamp(delta, min_delta, max_delta) / target_delta;
// save timestamp for next frame.
start = now;
} }
} }
@@ -1024,7 +1041,7 @@ void App::Poll() {
m_controller.m_kdown = padGetButtonsDown(&m_pad); m_controller.m_kdown = padGetButtonsDown(&m_pad);
m_controller.m_kheld = padGetButtons(&m_pad); m_controller.m_kheld = padGetButtons(&m_pad);
m_controller.m_kup = padGetButtonsUp(&m_pad); m_controller.m_kup = padGetButtonsUp(&m_pad);
m_controller.UpdateButtonHeld(static_cast<u64>(Button::ANY_DIRECTION)); m_controller.UpdateButtonHeld(static_cast<u64>(Button::ANY_DIRECTION), m_delta_time);
} }
} }