Files
ss/src/d/d_pad_nav.cpp
T
2025-07-26 20:19:12 +02:00

242 lines
7.0 KiB
C++

#include "d/d_pad_nav.h"
#include "d/d_pad.h"
#include "m/m_vec.h"
namespace dPadNav {
bool sIsNavEnabled = false;
bool sIsMplsNavLeftGesture = false;
bool sIsMplsNavRightGesture = false;
static bool sDisableAutoReturnToPointerNav = false;
bool sIsPointerVisible = true;
bool sPrevIsPointerVisible = true;
bool sIsCursorStickVisible = true;
s32 sFSStickDirection;
s32 sFSStickNavDirection;
static s32 sFSStickNavActiveTimer = 0;
static s32 sFSStickDirectionStableTimer = 0;
static s32 sMPLSNavGestureTimer = 0;
void init() {
sIsNavEnabled = false;
sIsPointerVisible = true;
sIsMplsNavLeftGesture = false;
sIsMplsNavRightGesture = false;
sDisableAutoReturnToPointerNav = false;
sPrevIsPointerVisible = true;
sFSStickDirection = FS_STICK_NONE;
sFSStickNavDirection = FS_STICK_NONE;
sFSStickNavActiveTimer = 0;
sFSStickDirectionStableTimer = 0;
sMPLSNavGestureTimer = 0;
setCursorStickInvisible();
}
void calc() {
sPrevIsPointerVisible = sIsPointerVisible;
sFSStickNavDirection = FS_STICK_NONE;
if (!sIsNavEnabled) {
return;
}
mVec3_c vel = dPad::ex_c::getInstance()->getMPLSVelocity();
if (sMPLSNavGestureTimer != 0) {
sMPLSNavGestureTimer--;
sIsMplsNavLeftGesture = false;
sIsMplsNavRightGesture = false;
} else {
checkForNavLeftGesture();
checkForNavRightGesture();
}
if (vel.squareMagXY() > 1.5f) {
// Large MPLS movement - stop FS stick navigation
stopFSStickNav();
return;
}
if (sIsPointerVisible) {
if (dPad::ex_c::getInstance()->getFSStickTrig()) {
// starting FS stick navigation - immediate nav event, with delay of
// 8 frames (267ms) for repeat nav event
sFSStickDirection = getFSStickDirectionTrig();
sFSStickNavDirection = sFSStickDirection;
sFSStickNavActiveTimer = 120;
sFSStickDirectionStableTimer = 8;
sIsPointerVisible = false;
}
} else {
s32 direction = getFSStickDirection();
if (sFSStickDirection != FS_STICK_NONE && direction == sFSStickDirection) {
// no change in FS stick direction
sFSStickNavActiveTimer = 120;
if (sFSStickDirectionStableTimer == 0) {
// repeat event - now with a delay of 3 frames (100ms)
sFSStickNavDirection = sFSStickDirection;
sFSStickDirectionStableTimer = 3;
} else {
sFSStickDirectionStableTimer--;
}
} else {
if (dPad::ex_c::getInstance()->getFSStickTrig()) {
// change in FS stick direction - same as if started navigation
direction = getFSStickDirectionTrig();
sFSStickDirectionStableTimer = 8;
sFSStickDirection = direction;
sFSStickNavDirection = direction;
sFSStickNavActiveTimer = 120;
} else {
// let go of FS stick
sFSStickDirection = FS_STICK_NONE;
sFSStickDirectionStableTimer = 0;
}
}
if (!sDisableAutoReturnToPointerNav) {
if (sFSStickNavActiveTimer == 0) {
// FS stick nav timer expired (or was set to 0 via explicit call),
// check if we need to return to pointer nav
if (direction != FS_STICK_NONE && sFSStickDirection == direction) {
sFSStickNavActiveTimer = 120;
} else {
if (direction == FS_STICK_NONE) {
// No direction, return to pointer nav
sFSStickDirection = FS_STICK_NONE;
sIsPointerVisible = true;
} else {
sFSStickDirectionStableTimer = 8;
// Note: Redundant check
if (!sDisableAutoReturnToPointerNav) {
sFSStickDirection = direction;
}
sFSStickNavDirection = sFSStickDirection;
sFSStickNavActiveTimer = 120;
}
}
} else {
sFSStickNavActiveTimer--;
}
}
}
}
void setNavEnabled(bool navEnabled, bool disableAutoReturnToPointerNav) {
sIsNavEnabled = navEnabled;
sIsPointerVisible = true;
if (navEnabled) {
setCursorStickVisible();
sDisableAutoReturnToPointerNav = disableAutoReturnToPointerNav;
} else {
setCursorStickInvisible();
sDisableAutoReturnToPointerNav = false;
}
}
s32 getFSStickDirectionTrig() {
if (dPad::ex_c::getInstance()->getFSStickTrig(0x1)) {
return FS_STICK_UP;
}
if (dPad::ex_c::getInstance()->getFSStickTrig(0x80)) {
return FS_STICK_UP_RIGHT;
}
if (dPad::ex_c::getInstance()->getFSStickTrig(0x40)) {
return FS_STICK_RIGHT;
}
if (dPad::ex_c::getInstance()->getFSStickTrig(0x20)) {
return FS_STICK_DOWN_RIGHT;
}
if (dPad::ex_c::getInstance()->getFSStickTrig(0x10)) {
return FS_STICK_DOWN;
}
if (dPad::ex_c::getInstance()->getFSStickTrig(0x8)) {
return FS_STICK_DOWN_LEFT;
}
if (dPad::ex_c::getInstance()->getFSStickTrig(0x4)) {
return FS_STICK_LEFT;
}
if (dPad::ex_c::getInstance()->getFSStickTrig(0x2)) {
return FS_STICK_UP_LEFT;
}
return FS_STICK_NONE;
}
s32 getFSStickDirection() {
switch (dPad::ex_c::getInstance()->mFSStickMask) {
case 0x1: return FS_STICK_UP;
case 0x80: return FS_STICK_UP_RIGHT;
case 0x40: return FS_STICK_RIGHT;
case 0x20: return FS_STICK_DOWN_RIGHT;
case 0x10: return FS_STICK_DOWN;
case 0x8: return FS_STICK_DOWN_LEFT;
case 0x4: return FS_STICK_LEFT;
case 0x2: return FS_STICK_UP_LEFT;
}
return FS_STICK_NONE;
}
void stopFSStickNav() {
sFSStickNavActiveTimer = 0;
sIsPointerVisible = true;
}
void hidePointer() {
sIsPointerVisible = false;
}
void setCursorStickInvisible() {
sIsCursorStickVisible = false;
}
void setCursorStickVisible() {
sIsCursorStickVisible = true;
}
void checkForNavLeftGesture() {
mVec3_c vel = dPad::ex_c::getInstance()->getMPLSVelocity();
if (vel.y <= 0.0f && vel.squareMagXY() > 1.5f) {
if (!sIsPointerVisible) {
sMPLSNavGestureTimer = 10;
sIsMplsNavLeftGesture = false;
} else {
sIsMplsNavLeftGesture = true;
}
} else {
sIsMplsNavLeftGesture = false;
}
}
void checkForNavRightGesture() {
mVec3_c vel = dPad::ex_c::getInstance()->getMPLSVelocity();
if (vel.y >= 0.0f && vel.squareMagXY() > 1.5f) {
if (!sIsPointerVisible) {
sMPLSNavGestureTimer = 10;
sIsMplsNavRightGesture = false;
} else {
sIsMplsNavRightGesture = true;
}
} else {
sIsMplsNavRightGesture = false;
}
}
void scrollRelated() {
sFSStickDirectionStableTimer = 3;
sFSStickNavActiveTimer = 120;
}
} // namespace dPadNav