Files
GTASource/game/system/TouchPadGestures.cpp
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

432 lines
11 KiB
C++

#if RSG_ORBIS
// Rage headers
#if __BANK
#include "bank/bkmgr.h"
#include "bank/bank.h"
#include "bank/combo.h"
#include "bank/slider.h"
#include "bank/group.h"
#endif
// Framework headers
#include "grcore/debugdraw.h"
#include "fwsys/timer.h"
//#include "fwmaths/Maths.h"
// Game headers
#include "System/TouchPadGestures.h"
#include "System/pad.h"
#include "frontend/PauseMenu.h"
#include "system/controlmgr.h"
#include "peds/Ped.h"
#include "scene/world/gameWorld.h"
#include "system/controlmgr.h"
#include "scene/playerswitch/PlayerSwitchInterface.h"
#include "frontend/LoadingScreens.h"
bank_s32 s_MinSwipeDistance = 200;
bank_s32 s_MinChangeSwipeDistance = 120;
bank_s32 s_MaxChangeSwipeDistance = 500;
bank_bool s_AllowDirectionChange = true;
#if __BANK
bank_bool s_DebugRender = false;
#endif
/////////////////////////////////////////////////////////////////////////////////////////////
CTouchPadGesture::CTouchPadGesture() :
m_CurrentDirection(NONE)
, m_FinalDirection(NONE)
, m_InvalidTouch(INVALID_TOUCH_ID)
, m_bMultiTouch(false)
, m_bLockDirection(false)
{
for (int i = 0; i < rage::ioPad::MAX_TOUCH_NUM; i++)
{
m_PreviousTouchId[i] = INVALID_TOUCH_ID;
#if __BANK
m_LastTouch[i].x = 0;
m_LastTouch[i].y = 0;
#endif
}
#if __BANK
m_LastTimeTouched = 0;
#endif
}
static bank_s32 s_TimeToRender = 2000;
void CTouchPadGesture::Update( CPad* pPad )
{
if (pPad && pPad->IsPs4Pad())
{
if (pPad->GetNumTouches() == 0)
{
// Terminate gesture and set state.
m_bMultiTouch = false;
for (int i = 0; i < rage::ioPad::MAX_TOUCH_NUM; i++)
{
m_PreviousTouchId[i] = INVALID_TOUCH_ID;
}
m_FinalDirection = m_CurrentDirection;
#if __DEV && 0
if (m_FinalDirection != NONE)
{
Warningf("### TouchPad (released) swipe %s", GetGestureString(m_FinalDirection));
}
#endif
m_InvalidTouch = INVALID_TOUCH_ID;
m_CurrentDirection = NONE;
#if __BANK
for(int i = 0; i < rage::ioPad::MAX_TOUCH_NUM; ++i)
{
m_LastTouch[i].x = 0;
m_LastTouch[i].y = 0;
}
#endif
m_bLockDirection = false;
}
else if (!m_bMultiTouch && pPad->GetNumTouches() == 1)
{
// Handle single touch gestures.
UpdateSingleTouch(pPad);
}
else if (m_bMultiTouch || pPad->GetNumTouches() == 2)
{
// As soon as we have two touch points, we are dealing with a multi-touch gesture.
m_bMultiTouch = true;
UpdateMultiTouch(pPad);
}
#if __BANK
bool bDebugRender = s_DebugRender;
#if DEBUG_PAD_INPUT
if (CControlMgr::IsDebugPadValuesOn() &&
(m_LastTimeTouched > 0) &&
(fwTimer::GetTimeInMilliseconds() < (m_LastTimeTouched + (u32)s_TimeToRender)))
{
bDebugRender=true;
}
#endif // DEBUG_PAD_INPUT
if(bDebugRender && (CControlMgr::GetPlayerPad() == pPad)) //only render for player pad.
{
Debug();
}
else
{
m_TrackPadHistory.Clear();
}
#endif // __BANK
}
}
void CTouchPadGesture::UpdateSingleTouch( CPad* pPad )
{
// === Detect swipe direction ===
const u8 uTouchId = pPad->GetTouchId(0);
#if __BANK
pPad->GetTouchPoint(0, m_LastTouch[0].x, m_LastTouch[0].y);
//! Add new debug record.
TouchPointTime newRecord;
newRecord.m_Touch = m_LastTouch[0];
newRecord.m_uTouchId = uTouchId;
newRecord.m_uTime = fwTimer::GetTimeInMilliseconds();
newRecord.m_nColor = m_CurrentDirection == NONE ? Color_red : Color_green;
m_TrackPadHistory.AddRecord(newRecord);
m_LastTimeTouched = fwTimer::GetTimeInMilliseconds();
#endif
if (pPad->GetTouchClick() != 0)
{
m_InvalidTouch = uTouchId;
}
m_FinalDirection = NONE;
if (uTouchId == m_InvalidTouch)
{
m_CurrentDirection = NONE;
return;
}
if (uTouchId != m_PreviousTouchId[0])
{
// Dealing with a new touch so record start point.
m_PreviousTouchId[0] = uTouchId;
pPad->GetTouchPoint(0, m_Start[0].x, m_Start[0].y);
}
else
{
// Determine direction and save delta.
u16 x, y;
pPad->GetTouchPoint(0, x, y);
s16 deltaX = x - m_Start[0].x;
s16 deltaY = y - m_Start[0].y;
float minDistance = m_CurrentDirection == NONE ? s_MinSwipeDistance : s_MinChangeSwipeDistance;
if((m_CurrentDirection != NONE) && ( (abs(deltaX) > s_MaxChangeSwipeDistance) || (abs(deltaY) > s_MaxChangeSwipeDistance) ) )
{
m_bLockDirection = true;
}
else
{
#if __BANK
SwipeDirection PrevDirection = m_CurrentDirection;
#endif
if (deltaX > minDistance || deltaX < -minDistance ||
deltaY > minDistance || deltaY < -minDistance)
{
SwipeDirection direction = NONE;
s16 deltaXAbs = (deltaX >= 0) ? deltaX : -deltaX;
s16 deltaYAbs = (deltaY >= 0) ? deltaY : -deltaY;
if (deltaXAbs > deltaYAbs)
{
direction = (deltaX >= 0) ? RIGHT : LEFT;
}
else
{
direction = (deltaY >= 0) ? DOWN : UP;
}
if (m_CurrentDirection == NONE)
{
m_CurrentDirection = direction;
}
else if (direction != m_CurrentDirection)
{
if(s_AllowDirectionChange && !m_bLockDirection)
{
m_CurrentDirection = direction;
}
else
{
// Direction changed, finalize swipe and ignore rest of gesture.
m_FinalDirection = m_CurrentDirection;
m_InvalidTouch = uTouchId;
}
#if __DEV && 0
Warningf("### TouchPad (direction change) swipe %s", GetGestureString(m_FinalDirection));
#endif
}
#if __BANK
//! Inform debug system that we have detected a gesture change. Change colour of touch history to visualize this.
if(m_CurrentDirection != PrevDirection)
{
m_TrackPadHistory.SetColourForTouchID(uTouchId, m_CurrentDirection != NONE ? Color_green : Color_red);
}
#endif
}
}
}
}
void CTouchPadGesture::UpdateMultiTouch( CPad* pPad )
{
// TODO: If one touch is released, stop updating gesture even if one touch is still held.
// TODO: Invalidate gesture if touchpad 'button' is down.
}
#if __BANK
const char *GetGestureString(CTouchPadGesture::SwipeDirection dir)
{
switch (dir)
{
case CTouchPadGesture::LEFT:
return "LEFT";
case CTouchPadGesture::RIGHT:
return "RIGHT";
case CTouchPadGesture::UP:
return "UP";
case CTouchPadGesture::DOWN:
return "DOWN";
case CTouchPadGesture::NONE:
default:
return "NONE";
}
return "NONE";
}
void CTouchPadGesture::TrackPadHistory::AddRecord(const CTouchPadGesture::TouchPointTime &touchPoint)
{
u32 currentIndex = m_nEndIndex;
if(m_nEndIndex == nMAX_HISTORY) //!Catch full ring buffer.
currentIndex = 0;
m_aTouchInputs[currentIndex] = touchPoint;
m_nEndIndex++;
if(m_nEndIndex > nMAX_HISTORY)
{
m_nEndIndex = 0;
}
//! Increment start if it equals end.
if(m_nEndIndex == m_nStartIndex)
{
m_nStartIndex++;
if(m_nStartIndex >= nMAX_HISTORY)
{
m_nStartIndex = 0;
}
}
}
void CTouchPadGesture::TrackPadHistory::Clear()
{
m_nStartIndex = 0;
m_nEndIndex = 0;
}
u32 CTouchPadGesture::TrackPadHistory::GetCount() const
{
//! init case.
if(m_nStartIndex == 0 && m_nEndIndex == 0)
{
return 0;
}
if(m_nEndIndex == nMAX_HISTORY || (m_nEndIndex > m_nStartIndex) )
{
return m_nEndIndex-m_nStartIndex;
}
//! At this point, consider pad full.
return nMAX_HISTORY;
}
CTouchPadGesture::TouchPointTime &CTouchPadGesture::TrackPadHistory::GetIndex(u32 i)
{
u32 nIndex = m_nStartIndex + i;
if(nIndex >= nMAX_HISTORY)
{
nIndex = nIndex - nMAX_HISTORY;
}
Assertf(nIndex < nMAX_HISTORY, "Index out of bounds!");
return m_aTouchInputs[nIndex];
}
void CTouchPadGesture::TrackPadHistory::SetColourForTouchID(u8 uTouchID, const Color32 &nColor)
{
//! Iterate through list and set colour for entries with the same touch ID.
for(int i = 0; i < GetCount(); ++i)
{
TouchPointTime &touchPoint = GetIndex(i);
if(touchPoint.m_uTouchId == uTouchID)
{
touchPoint.m_nColor.Set(nColor.GetColor());
}
}
};
static Vector2 s_vHistoryDebugPos(0.275f, 0.8f);
static Vector2 s_vHistoryDebugSize(0.15f, 0.1f);
//! Not sure how we get these figures, but this is what system gives us - seems pretty arbitrary.
static dev_u32 s_MaxTrackPadValueX = 1910;
static dev_u32 s_MaxTrackPadValueY = 950;
void CTouchPadGesture::InitWidgets( bkBank& bank )
{
bank.PushGroup("PS4 TouchPad Debug");
bank.AddSlider("Min Swipe Distance", &s_MinSwipeDistance, 1, 5000, 1);
bank.AddSlider("Min Change Direction Swipe Distance", &s_MinChangeSwipeDistance, 1, 5000, 1);
bank.AddSlider("Max Change Direction Swipe Distance", &s_MaxChangeSwipeDistance, 1, 5000, 1);
bank.AddToggle("Debug Render", &s_DebugRender);
bank.AddToggle("Allow direction change", &s_AllowDirectionChange);
bank.AddSlider("History Pos x", &s_vHistoryDebugPos.x, 0.0f, 1.0f, 0.01f);
bank.AddSlider("History Pos y", &s_vHistoryDebugPos.y, 0.0f, 1.0f, 0.01f);
bank.AddSlider("History Size x", &s_vHistoryDebugSize.x, 0.0f, 10.0f, 0.01f);
bank.AddSlider("History Size y", &s_vHistoryDebugSize.y, 0.0f, 10.0f, 0.01f);
bank.AddSlider("Time to render history", &s_TimeToRender, 1, 60000, 100);
bank.PopGroup();
}
void CTouchPadGesture::TrackPadHistory::Draw()
{
if(GetCount() > 1) //need at least 2 samples to draw a line.
{
//! Draw box
Vector2 vTL = s_vHistoryDebugPos;
Vector2 vTR = s_vHistoryDebugPos; vTR.x += s_vHistoryDebugSize.x;
Vector2 vBR = s_vHistoryDebugPos; vBR.x += s_vHistoryDebugSize.x; vBR.y += s_vHistoryDebugSize.y;
Vector2 vBL = s_vHistoryDebugPos; vBL.y += s_vHistoryDebugSize.y;
grcDebugDraw::Quad(vTL, vTR, vBR, vBL, Color_blue, false);
//! Get origin for box.
Vector2 vBoxOrigin = vTL;
//Draw line segments for each connecting pair.
for(int i = 0; i < (GetCount()-1); ++i)
{
const TouchPointTime &touchPoint = GetIndex(i);
const TouchPointTime &touchPointNext = GetIndex(i+1);
if( (fwTimer::GetTimeInMilliseconds() < (touchPointNext.m_uTime + (u32)s_TimeToRender)) &&
(touchPoint.m_uTouchId == touchPointNext.m_uTouchId) )
{
Vector2 TouchStart(touchPoint.m_Touch.x, touchPoint.m_Touch.y);
Vector2 TouchEnd(touchPointNext.m_Touch.x, touchPointNext.m_Touch.y);
TouchStart.x /= s_MaxTrackPadValueX;
TouchStart.y /= s_MaxTrackPadValueY;
TouchEnd.x /= s_MaxTrackPadValueX;
TouchEnd.y /= s_MaxTrackPadValueY;
Vector2 start = vBoxOrigin;
start.x += TouchStart.x * s_vHistoryDebugSize.x;
start.y += TouchStart.y * s_vHistoryDebugSize.y;
Vector2 end = vBoxOrigin;
end.x += TouchEnd.x * s_vHistoryDebugSize.x;
end.y += TouchEnd.y * s_vHistoryDebugSize.y;
grcDebugDraw::Line(start, end, touchPoint.m_nColor, touchPointNext.m_nColor);
}
}
}
}
void CTouchPadGesture::Debug()
{
if( CLoadingScreens::AreActive() || CLoadingScreens::IsInitialLoadingScreenActive() || // BS#4468680: skip debug draw during GTAO loading screens
g_PlayerSwitch.IsActive() ) // BS#4468680: skip debug draw during GTAO transition screens
return;
Vector2 vDebugPos = s_vHistoryDebugPos;
vDebugPos.y += s_vHistoryDebugSize.y + 0.01f;
static dev_float s_fTextSize = 0.02f;
char buff[128];
sprintf(buff, "Touch Pad X: %d Y: %d Gesture : %s", m_LastTouch[0].x, m_LastTouch[0].y, GetGestureString(m_CurrentDirection));
grcDebugDraw::Text(vDebugPos, Color32(255,0,0), buff);
vDebugPos.y += s_fTextSize;
m_TrackPadHistory.Draw();
}
#endif // __BANK
#endif // RSG_ORBIS