432 lines
11 KiB
C++
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
|