mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-05-02 02:23:56 +00:00
Improve touch UX in 3rd person camera
This commit is contained in:
parent
33436ef00f
commit
3bcd8cc908
@ -638,7 +638,7 @@ void LegoInputManager::RemoveJoystick(SDL_JoystickID p_joystickID)
|
||||
|
||||
MxBool LegoInputManager::HandleTouchEvent(SDL_Event* p_event, TouchScheme p_touchScheme)
|
||||
{
|
||||
if (Extension<MultiplayerExt>::Call(HandleTouchInput).value_or(FALSE)) {
|
||||
if (Extension<MultiplayerExt>::Call(HandleTouchInput, p_event).value_or(FALSE)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -71,9 +71,9 @@ class MultiplayerExt {
|
||||
// Returns TRUE when the third-person camera is active.
|
||||
static MxBool IsThirdPersonCameraActive();
|
||||
|
||||
// Suppresses touch input when a multi-touch camera gesture is active.
|
||||
// Returns TRUE if the caller should return early.
|
||||
static MxBool HandleTouchInput();
|
||||
// Routes touch events by screen zone: right half → camera, left half → movement.
|
||||
// Returns TRUE if the event was consumed by the camera (caller should skip movement).
|
||||
static MxBool HandleTouchInput(SDL_Event* p_event);
|
||||
|
||||
// Overrides nav controller movement for camera-relative 3rd person controls.
|
||||
// Returns TRUE if the hook handled movement (caller should return early).
|
||||
|
||||
@ -68,7 +68,13 @@ class ThirdPersonCamera {
|
||||
|
||||
// Free camera input handling
|
||||
void HandleSDLEvent(SDL_Event* p_event);
|
||||
bool IsTouchGestureActive() const { return m_touchGestureActive; }
|
||||
|
||||
// Finger-claiming API for split-screen touch zones (left=movement, right=camera)
|
||||
bool TryClaimFinger(const SDL_TouchFingerEvent& event);
|
||||
bool TryReleaseFinger(SDL_FingerID id);
|
||||
bool IsFingerTracked(SDL_FingerID id) const;
|
||||
|
||||
static constexpr float CAMERA_ZONE_X = 0.5f;
|
||||
|
||||
private:
|
||||
// Orbit camera helpers
|
||||
@ -114,7 +120,6 @@ class ThirdPersonCamera {
|
||||
float m_smoothedSpeed; // Extension-managed velocity for smooth acceleration/deceleration
|
||||
|
||||
// Touch gesture tracking
|
||||
bool m_touchGestureActive = false;
|
||||
struct TouchState {
|
||||
SDL_FingerID id[2];
|
||||
float x[2], y[2];
|
||||
|
||||
@ -11,7 +11,6 @@
|
||||
#include "legoentity.h"
|
||||
#include "legoeventnotificationparam.h"
|
||||
#include "legogamestate.h"
|
||||
#include "legoinputmanager.h"
|
||||
#include "legonavcontroller.h"
|
||||
#include "legopathactor.h"
|
||||
#include "misc.h"
|
||||
@ -310,18 +309,37 @@ MxBool MultiplayerExt::IsThirdPersonCameraActive()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MxBool MultiplayerExt::HandleTouchInput()
|
||||
MxBool MultiplayerExt::HandleTouchInput(SDL_Event* p_event)
|
||||
{
|
||||
if (s_networkManager && s_networkManager->GetThirdPersonCamera().IsActive() &&
|
||||
s_networkManager->GetThirdPersonCamera().IsTouchGestureActive()) {
|
||||
LegoInputManager* im = InputManager();
|
||||
im->m_touchFinger = 0;
|
||||
im->m_touchVirtualThumb = {0, 0};
|
||||
im->m_touchFlags.clear();
|
||||
return TRUE;
|
||||
if (!s_networkManager || !s_networkManager->GetThirdPersonCamera().IsActive()) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Multiplayer::ThirdPersonCamera& cam = s_networkManager->GetThirdPersonCamera();
|
||||
|
||||
switch (p_event->type) {
|
||||
case SDL_EVENT_FINGER_DOWN:
|
||||
if (cam.TryClaimFinger(p_event->tfinger)) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
case SDL_EVENT_FINGER_MOTION:
|
||||
if (cam.IsFingerTracked(p_event->tfinger.fingerID)) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
case SDL_EVENT_FINGER_UP:
|
||||
case SDL_EVENT_FINGER_CANCELED:
|
||||
if (cam.TryReleaseFinger(p_event->tfinger.fingerID)) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
MxBool MultiplayerExt::HandleNavOverride(
|
||||
|
||||
@ -758,6 +758,55 @@ MxBool ThirdPersonCamera::HandleCameraRelativeMovement(
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool ThirdPersonCamera::TryClaimFinger(const SDL_TouchFingerEvent& event)
|
||||
{
|
||||
if (!m_active || m_touch.count >= 2 || event.x < CAMERA_ZONE_X) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int idx = m_touch.count;
|
||||
m_touch.id[idx] = event.fingerID;
|
||||
m_touch.x[idx] = event.x;
|
||||
m_touch.y[idx] = event.y;
|
||||
m_touch.count++;
|
||||
|
||||
if (m_touch.count == 2) {
|
||||
float dx = m_touch.x[1] - m_touch.x[0];
|
||||
float dy = m_touch.y[1] - m_touch.y[0];
|
||||
m_touch.initialPinchDist = SDL_sqrtf(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThirdPersonCamera::TryReleaseFinger(SDL_FingerID id)
|
||||
{
|
||||
for (int i = 0; i < m_touch.count; i++) {
|
||||
if (m_touch.id[i] == id) {
|
||||
// Shift remaining finger down
|
||||
if (i == 0 && m_touch.count == 2) {
|
||||
m_touch.id[0] = m_touch.id[1];
|
||||
m_touch.x[0] = m_touch.x[1];
|
||||
m_touch.y[0] = m_touch.y[1];
|
||||
}
|
||||
m_touch.count--;
|
||||
m_touch.initialPinchDist = 0.0f;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ThirdPersonCamera::IsFingerTracked(SDL_FingerID id) const
|
||||
{
|
||||
for (int i = 0; i < m_touch.count; i++) {
|
||||
if (m_touch.id[i] == id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ThirdPersonCamera::HandleSDLEvent(SDL_Event* p_event)
|
||||
{
|
||||
switch (p_event->type) {
|
||||
@ -784,7 +833,10 @@ void ThirdPersonCamera::HandleSDLEvent(SDL_Event* p_event)
|
||||
}
|
||||
|
||||
case SDL_EVENT_FINGER_DOWN: {
|
||||
if (m_touch.count < 2) {
|
||||
// Finger may already be claimed via TryClaimFinger (called from HandleTouchInput).
|
||||
// Only register if not already tracked and in the camera zone.
|
||||
if (!IsFingerTracked(p_event->tfinger.fingerID) && m_touch.count < 2 &&
|
||||
p_event->tfinger.x >= CAMERA_ZONE_X) {
|
||||
int idx = m_touch.count;
|
||||
m_touch.id[idx] = p_event->tfinger.fingerID;
|
||||
m_touch.x[idx] = p_event->tfinger.x;
|
||||
@ -792,7 +844,6 @@ void ThirdPersonCamera::HandleSDLEvent(SDL_Event* p_event)
|
||||
m_touch.count++;
|
||||
|
||||
if (m_touch.count == 2) {
|
||||
m_touchGestureActive = true;
|
||||
float dx = m_touch.x[1] - m_touch.x[0];
|
||||
float dy = m_touch.y[1] - m_touch.y[0];
|
||||
m_touch.initialPinchDist = SDL_sqrtf(dx * dx + dy * dy);
|
||||
@ -802,7 +853,22 @@ void ThirdPersonCamera::HandleSDLEvent(SDL_Event* p_event)
|
||||
}
|
||||
|
||||
case SDL_EVENT_FINGER_MOTION: {
|
||||
if (m_touch.count == 2) {
|
||||
if (m_touch.count == 1) {
|
||||
// Single-finger drag: apply yaw/pitch rotation
|
||||
if (m_touch.id[0] == p_event->tfinger.fingerID) {
|
||||
float oldX = m_touch.x[0];
|
||||
float oldY = m_touch.y[0];
|
||||
m_touch.x[0] = p_event->tfinger.x;
|
||||
m_touch.y[0] = p_event->tfinger.y;
|
||||
|
||||
float moveX = m_touch.x[0] - oldX;
|
||||
float moveY = m_touch.y[0] - oldY;
|
||||
m_absoluteYaw -= moveX * 2.0f;
|
||||
m_orbitPitch += moveY * 2.0f;
|
||||
ClampPitch();
|
||||
}
|
||||
}
|
||||
else if (m_touch.count == 2) {
|
||||
// Find which finger moved
|
||||
int idx = -1;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
@ -835,7 +901,7 @@ void ThirdPersonCamera::HandleSDLEvent(SDL_Event* p_event)
|
||||
// Two-finger drag for orbit
|
||||
float moveX = m_touch.x[idx] - oldX;
|
||||
float moveY = m_touch.y[idx] - oldY;
|
||||
m_absoluteYaw += moveX * 2.0f;
|
||||
m_absoluteYaw -= moveX * 2.0f;
|
||||
m_orbitPitch += moveY * 2.0f;
|
||||
ClampPitch();
|
||||
}
|
||||
@ -844,22 +910,7 @@ void ThirdPersonCamera::HandleSDLEvent(SDL_Event* p_event)
|
||||
|
||||
case SDL_EVENT_FINGER_UP:
|
||||
case SDL_EVENT_FINGER_CANCELED: {
|
||||
for (int i = 0; i < m_touch.count; i++) {
|
||||
if (m_touch.id[i] == p_event->tfinger.fingerID) {
|
||||
// Shift remaining finger down
|
||||
if (i == 0 && m_touch.count == 2) {
|
||||
m_touch.id[0] = m_touch.id[1];
|
||||
m_touch.x[0] = m_touch.x[1];
|
||||
m_touch.y[0] = m_touch.y[1];
|
||||
}
|
||||
m_touch.count--;
|
||||
if (m_touch.count == 0) {
|
||||
m_touchGestureActive = false;
|
||||
}
|
||||
m_touch.initialPinchDist = 0.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
TryReleaseFinger(p_event->tfinger.fingerID);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user