feat: x360 input lib
This commit is contained in:
1 parent
f8ec357c45
commit
f9c9b27e33
22 files changed
+2147
-8
No files matched your search
@@ -0,0 +1,166 @@
|
||||
#include "4J_Input.h"
|
||||
#include "INP_Main.h"
|
||||
|
||||
C_4JInput InputManager;
|
||||
|
||||
void C_4JInput::Initialise(int iInputStateC, unsigned char ucMapC, unsigned char ucActionC, unsigned char ucMenuActionC)
|
||||
{
|
||||
InternalInputManager.Initialise(iInputStateC, ucMapC, ucActionC, ucMenuActionC);
|
||||
}
|
||||
|
||||
void C_4JInput::Tick(void)
|
||||
{
|
||||
InternalInputManager.Tick();
|
||||
}
|
||||
|
||||
void C_4JInput::SetDeadzoneAndMovementRange(unsigned int uiDeadzone, unsigned int uiMovementRangeMax)
|
||||
{
|
||||
InternalInputManager.SetDeadzoneAndMovementRange(uiDeadzone, uiMovementRangeMax);
|
||||
}
|
||||
|
||||
void C_4JInput::SetGameJoypadMaps(unsigned char ucMap, unsigned char ucAction, unsigned int uiActionVal)
|
||||
{
|
||||
InternalInputManager.SetGameJoypadMaps(ucMap, ucAction, uiActionVal);
|
||||
}
|
||||
|
||||
unsigned int C_4JInput::GetGameJoypadMaps(unsigned char ucMap, unsigned char ucAction)
|
||||
{
|
||||
return InternalInputManager.GetGameJoypadMaps(ucMap, ucAction);
|
||||
}
|
||||
|
||||
void C_4JInput::SetJoypadMapVal(int iPad, unsigned char ucMap)
|
||||
{
|
||||
InternalInputManager.SetJoypadMapVal(iPad, ucMap);
|
||||
}
|
||||
|
||||
unsigned char C_4JInput::GetJoypadMapVal(int iPad)
|
||||
{
|
||||
return InternalInputManager.GetJoypadMapVal(iPad);
|
||||
}
|
||||
|
||||
void C_4JInput::SetJoypadSensitivity(int iPad, float fSensitivity)
|
||||
{
|
||||
InternalInputManager.SetJoypadSensitivity(iPad, fSensitivity);
|
||||
}
|
||||
|
||||
unsigned int C_4JInput::GetValue(int iPad, unsigned char ucAction, bool bRepeat)
|
||||
{
|
||||
return InternalInputManager.GetValue(iPad, ucAction, bRepeat);
|
||||
}
|
||||
|
||||
bool C_4JInput::ButtonPressed(int iPad, unsigned char ucAction)
|
||||
{
|
||||
return InternalInputManager.ButtonPressed(iPad, ucAction);
|
||||
}
|
||||
|
||||
bool C_4JInput::ButtonReleased(int iPad, unsigned char ucAction)
|
||||
{
|
||||
return InternalInputManager.ButtonReleased(iPad, ucAction);
|
||||
}
|
||||
|
||||
bool C_4JInput::ButtonDown(int iPad, unsigned char ucAction)
|
||||
{
|
||||
return InternalInputManager.ButtonDown(iPad, ucAction);
|
||||
}
|
||||
|
||||
void C_4JInput::SetJoypadStickAxisMap(int iPad, unsigned int uiFrom, unsigned int uiTo)
|
||||
{
|
||||
InternalInputManager.SetJoypadStickAxisMap(iPad, uiFrom, uiTo);
|
||||
}
|
||||
|
||||
void C_4JInput::SetJoypadStickTriggerMap(int iPad, unsigned int uiFrom, unsigned int uiTo)
|
||||
{
|
||||
InternalInputManager.SetJoypadStickTriggerMap(iPad, uiFrom, uiTo);
|
||||
}
|
||||
|
||||
void C_4JInput::SetKeyRepeatRate(float fRepeatDelaySecs, float fRepeatRateSecs)
|
||||
{
|
||||
InternalInputManager.SetKeyRepeatRate(fRepeatDelaySecs, fRepeatRateSecs);
|
||||
}
|
||||
|
||||
void C_4JInput::SetDebugSequence(const char *chSequenceA, int (*Func)(LPVOID), LPVOID lpParam)
|
||||
{
|
||||
InternalInputManager.SetDebugSequence(chSequenceA, Func, lpParam);
|
||||
}
|
||||
|
||||
FLOAT C_4JInput::GetIdleSeconds(int iPad)
|
||||
{
|
||||
return InternalInputManager.GetIdleSeconds(iPad);
|
||||
}
|
||||
|
||||
bool C_4JInput::IsPadConnected(int iPad)
|
||||
{
|
||||
return InternalInputManager.IsPadConnected(iPad);
|
||||
}
|
||||
|
||||
float C_4JInput::GetJoypadStick_LX(int iPad, bool bCheckMenuDisplay)
|
||||
{
|
||||
return InternalInputManager.GetJoypadStick_LX(iPad, bCheckMenuDisplay);
|
||||
}
|
||||
|
||||
float C_4JInput::GetJoypadStick_LY(int iPad, bool bCheckMenuDisplay)
|
||||
{
|
||||
return InternalInputManager.GetJoypadStick_LY(iPad, bCheckMenuDisplay);
|
||||
}
|
||||
|
||||
float C_4JInput::GetJoypadStick_RX(int iPad, bool bCheckMenuDisplay)
|
||||
{
|
||||
return InternalInputManager.GetJoypadStick_RX(iPad, bCheckMenuDisplay);
|
||||
}
|
||||
|
||||
float C_4JInput::GetJoypadStick_RY(int iPad, bool bCheckMenuDisplay)
|
||||
{
|
||||
return InternalInputManager.GetJoypadStick_RY(iPad, bCheckMenuDisplay);
|
||||
}
|
||||
|
||||
unsigned char C_4JInput::GetJoypadLTrigger(int iPad, bool bCheckMenuDisplay)
|
||||
{
|
||||
return InternalInputManager.GetJoypadLTrigger(iPad, bCheckMenuDisplay);
|
||||
}
|
||||
|
||||
unsigned char C_4JInput::GetJoypadRTrigger(int iPad, bool bCheckMenuDisplay)
|
||||
{
|
||||
return InternalInputManager.GetJoypadRTrigger(iPad, bCheckMenuDisplay);
|
||||
}
|
||||
|
||||
void C_4JInput::SetMenuDisplayed(int iPad, bool bVal)
|
||||
{
|
||||
InternalInputManager.SetMenuDisplayed(iPad, bVal);
|
||||
}
|
||||
|
||||
C_4JInput::EKeyboardResult C_4JInput::RequestKeyboard(LPCWSTR uiTitle, LPCWSTR uiText, DWORD dwPad, WCHAR *pwchResult, UINT uiMaxChars, int(*Func)(LPVOID, const bool), LPVOID lpParam, EKeyboardMode eMode)
|
||||
{
|
||||
return InternalInputManager.m_Keyboard.RequestKeyboard(uiTitle, uiText, NULL, dwPad, pwchResult, uiMaxChars, Func, lpParam, eMode);
|
||||
}
|
||||
|
||||
C_4JInput::EKeyboardResult C_4JInput::RequestKeyboard(LPCWSTR uiTitle, LPCWSTR pwchDefault, LPCWSTR uiDesc, DWORD dwPad, WCHAR *pwchResult, UINT uiMaxChars, int(*Func)(LPVOID, const bool), LPVOID lpParam, EKeyboardMode eMode)
|
||||
{
|
||||
return InternalInputManager.m_Keyboard.RequestKeyboard(uiTitle, pwchDefault, uiDesc, dwPad, pwchResult, uiMaxChars, Func, lpParam, eMode);
|
||||
}
|
||||
|
||||
//str1k3r - 3rd RequestKeyboard is for how iggy calls it
|
||||
C_4JInput::EKeyboardResult C_4JInput::RequestKeyboard(LPCWSTR uiTitle, LPCWSTR uiDesc, DWORD dwPad, UINT uiMaxChars, int(*Func)(LPVOID, const bool), LPVOID lpParam, EKeyboardMode eMode)
|
||||
{
|
||||
return InternalInputManager.m_Keyboard.RequestKeyboard(uiTitle, NULL, uiDesc, dwPad, NULL, uiMaxChars, Func, lpParam, eMode);
|
||||
}
|
||||
|
||||
C4JStorage::EMessageResult C_4JInput::RequestMessageBox(LPCWSTR uiTitle, LPCWSTR uiText, LPCWSTR *uiButtons, UINT uiButtonCount, DWORD dwPad, int(*Func)(LPVOID, int, const C4JStorage::EMessageResult), LPVOID lpParam, DWORD dwFocusButton)
|
||||
{
|
||||
return InternalInputManager.m_MessageUI.RequestMessageBox(uiTitle, uiText, uiButtons, uiButtonCount, dwPad, Func, lpParam, dwFocusButton);
|
||||
}
|
||||
|
||||
/*void C_4JInput::GetText(uint16_t *UTF16String)
|
||||
{
|
||||
InternalInputManager.m_Keyboard.GetText(UTF16String);
|
||||
}
|
||||
|
||||
bool C_4JInput::VerifyStrings(WCHAR **pwStringA, int iStringC, int (*Func)(LPVOID, STRING_VERIFY_RESPONSE *), LPVOID lpParam)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void C_4JInput::CancelQueuedVerifyStrings(int (*Func)(LPVOID, STRING_VERIFY_RESPONSE *), LPVOID lpParam) {}
|
||||
|
||||
void C_4JInput::CancelAllVerifyInProgress(void) {}
|
||||
|
||||
bool C_4JInput::InputDetected(DWORD dwUserIndex,WCHAR *pwchInput) {}*/
|
||||
@@ -0,0 +1,111 @@
|
||||
#include "INP_ForceFeedback.h"
|
||||
#include "INP_Main.h"
|
||||
|
||||
void CForceFeedback::Initialise(int iInputStateC, unsigned char ucMapC, unsigned char ucActionC, unsigned char ucMenuActionC)
|
||||
{
|
||||
m_Effects = new FF_EFFECT[MAX_EFFECTS];
|
||||
m_EffectC = 0;
|
||||
|
||||
LARGE_INTEGER qwTicksPerSec;
|
||||
QueryPerformanceFrequency(&qwTicksPerSec);
|
||||
|
||||
m_TicksPerSecond = qwTicksPerSec.LowPart;
|
||||
m_unkBool = 0;
|
||||
}
|
||||
|
||||
void CForceFeedback::RumbleEnable(int iQuadrant, bool bRumbleEnabled) {}
|
||||
|
||||
void CForceFeedback::CreateEffect(void)
|
||||
{
|
||||
assert(m_EffectC < MAX_EFFECTS);
|
||||
|
||||
FF_EFFECT *pEffect = &m_Effects[m_EffectC];
|
||||
pEffect->m_uiDurationMs = 5;
|
||||
pEffect->m_uiMagnitude = 500;
|
||||
pEffect->m_uiEffectType = 0;
|
||||
pEffect->dword18 = 10;
|
||||
pEffect->dword18 = 100;
|
||||
|
||||
m_EffectC++;
|
||||
}
|
||||
|
||||
void CForceFeedback::AddEffectInstance(unsigned int uiEffect)
|
||||
{
|
||||
FF_EFFECT_INSTANCE *pEffectInst = new FF_EFFECT_INSTANCE();
|
||||
pEffectInst->m_Effect = &m_Effects[uiEffect];
|
||||
pEffectInst->m_uiInst = 0;
|
||||
|
||||
m_EffectList.AddToTail(pEffectInst);
|
||||
}
|
||||
|
||||
void CForceFeedback::SetEffectInstanceState(unsigned int uiEffectInstance, unsigned int uiState)
|
||||
{
|
||||
int iCount = 0;
|
||||
LinkedList::_LL_NODE *pNode;
|
||||
for (pNode = m_EffectList.m_Head;; pNode = pNode->m_Next)
|
||||
{
|
||||
if ((iCount++) == uiEffectInstance)
|
||||
break;
|
||||
}
|
||||
pNode->GetDataAs<FF_EFFECT_INSTANCE>()->m_bIsActive = true;
|
||||
}
|
||||
|
||||
void CForceFeedback::ProcessEventInstance(FF_EFFECT_INSTANCE *pEffectInst) {}
|
||||
|
||||
void CForceFeedback::PauseEventInstance(FF_EFFECT_INSTANCE *pEffectInst) {}
|
||||
|
||||
void CForceFeedback::AddRumble(unsigned int uiPad, WORD leftMotorSpeed, WORD rightMotorSpeed, float fSeconds)
|
||||
{
|
||||
RUMBLE_EFFECT *pRumble = new RUMBLE_EFFECT();
|
||||
|
||||
LARGE_INTEGER qwCurrentTime;
|
||||
QueryPerformanceCounter(&qwCurrentTime);
|
||||
|
||||
pRumble->m_TimeLeft = (m_TicksPerSecond * fSeconds) + qwCurrentTime.QuadPart;
|
||||
pRumble->m_RumbleData.wLeftMotorSpeed = leftMotorSpeed;
|
||||
pRumble->m_RumbleData.wRightMotorSpeed = rightMotorSpeed;
|
||||
pRumble->m_Pad = uiPad;
|
||||
|
||||
m_RumbleList.AddToTail(pRumble);
|
||||
}
|
||||
|
||||
void CForceFeedback::Tick(void)
|
||||
{
|
||||
for (LinkedList::_LL_NODE *pEffectNode = m_EffectList.m_Head; pEffectNode; pEffectNode = pEffectNode->m_Next)
|
||||
{
|
||||
if (pEffectNode->GetDataAs<FF_EFFECT_INSTANCE>()->m_bIsActive)
|
||||
{
|
||||
ProcessEventInstance(pEffectNode->GetDataAs<FF_EFFECT_INSTANCE>());
|
||||
}
|
||||
}
|
||||
|
||||
LARGE_INTEGER qwCurrentTime;
|
||||
QueryPerformanceCounter(&qwCurrentTime);
|
||||
|
||||
LinkedList::_LL_NODE *pRumbleNode = m_RumbleList.m_Head;
|
||||
while (pRumbleNode)
|
||||
{
|
||||
if (pRumbleNode->GetDataAs<RUMBLE_EFFECT>()->m_TimeLeft <= qwCurrentTime.QuadPart)
|
||||
{
|
||||
RUMBLE_EFFECT *pRumble = pRumbleNode->GetDataAs<RUMBLE_EFFECT>();
|
||||
|
||||
pRumble->m_RumbleData.wLeftMotorSpeed = 0;
|
||||
pRumble->m_RumbleData.wRightMotorSpeed = 0;
|
||||
|
||||
XInputSetState(pRumble->m_Pad, &pRumble->m_RumbleData);
|
||||
|
||||
m_RumbleList.RemoveNode(pRumbleNode);
|
||||
|
||||
LinkedList::_LL_NODE *pTemp = pRumbleNode;
|
||||
pRumbleNode = pRumbleNode->m_Next;
|
||||
|
||||
delete pTemp->GetDataAs<RUMBLE_EFFECT>();
|
||||
delete pTemp;
|
||||
}
|
||||
else
|
||||
{
|
||||
XInputSetState(pRumbleNode->GetDataAs<RUMBLE_EFFECT>()->m_Pad, &pRumbleNode->GetDataAs<RUMBLE_EFFECT>()->m_RumbleData);
|
||||
pRumbleNode = pRumbleNode->m_Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
#include "LinkedList.h"
|
||||
|
||||
#define MAX_EFFECTS 10
|
||||
|
||||
class CForceFeedback
|
||||
{
|
||||
public:
|
||||
enum FF_PARAMS
|
||||
{
|
||||
FF_PARAMS_RAMP,
|
||||
FF_PARAMS_PERIODIC
|
||||
};
|
||||
|
||||
struct RUMBLE_EFFECT
|
||||
{
|
||||
DWORD m_Pad;
|
||||
uint64_t m_TimeLeft;
|
||||
XINPUT_VIBRATION m_RumbleData;
|
||||
WORD unk;
|
||||
};
|
||||
|
||||
struct FF_EFFECT
|
||||
{
|
||||
unsigned int m_uiEffectType;
|
||||
unsigned int m_uiDurationMs;
|
||||
BYTE gap8[4];
|
||||
unsigned int m_uiMagnitude;
|
||||
BYTE gap10[8];
|
||||
DWORD dword18;
|
||||
DWORD dword1C;
|
||||
};
|
||||
|
||||
struct FF_EFFECT_INSTANCE
|
||||
{
|
||||
bool m_bIsActive;
|
||||
unsigned int m_uiInst;
|
||||
CForceFeedback::FF_EFFECT *m_Effect;
|
||||
};
|
||||
|
||||
void Initialise(int iInputStateC, unsigned char ucMapC, unsigned char ucActionC, unsigned char ucMenuActionC);
|
||||
void RumbleEnable(int iQuadrant, bool bRumbleEnabled);
|
||||
void CreateEffect(void);
|
||||
void AddEffectInstance(unsigned int uiEffect);
|
||||
void SetEffectInstanceState(unsigned int uiEffectInstance, unsigned int uiState);
|
||||
|
||||
void ProcessEventInstance(FF_EFFECT_INSTANCE *pEffectInst);
|
||||
void PauseEventInstance(FF_EFFECT_INSTANCE *pEffectInst);
|
||||
|
||||
void AddRumble(unsigned int uiPad, WORD leftMotorSpeed, WORD rightMotorSpeed, float fSeconds);
|
||||
|
||||
void Tick(void);
|
||||
|
||||
LinkedList m_EffectList;
|
||||
FF_EFFECT *m_Effects;
|
||||
int m_EffectC;
|
||||
LinkedList m_RumbleList;
|
||||
float m_TicksPerSecond;
|
||||
bool m_unkBool;
|
||||
};
|
||||
@@ -0,0 +1,70 @@
|
||||
#include "4J_Profile.h"
|
||||
#include "INP_Keyboard.h"
|
||||
|
||||
CKeyboard::CKeyboard()
|
||||
{
|
||||
bActive = false;
|
||||
}
|
||||
|
||||
void CKeyboard::Tick(void)
|
||||
{
|
||||
if (bActive == true && KeyboardOverlap.InternalLow != ERROR_IO_PENDING)
|
||||
{
|
||||
if(Func != NULL) Func(lpParam, KeyboardOverlap.dwExtendedError == 0);
|
||||
bActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
C_4JInput::EKeyboardResult CKeyboard::RequestKeyboard(LPCWSTR uiTitle, LPCWSTR uiText, LPCWSTR uiDesc, DWORD dwPad, WCHAR *pwchResult, UINT uiMaxChars, int (*Func)(LPVOID, const bool), LPVOID lpParam, C_4JInput::EKeyboardMode eMode)
|
||||
{
|
||||
if (bActive == true)
|
||||
return C_4JInput::EKeyboard_Cancelled;
|
||||
|
||||
this->iPad = (int)dwPad;
|
||||
this->pwchResult = pwchResult;
|
||||
this->uiMaxChars = uiMaxChars;
|
||||
this->Func = Func;
|
||||
this->lpParam = lpParam;
|
||||
|
||||
int LockedProfile = this->iPad;
|
||||
if (LockedProfile == -1)
|
||||
{
|
||||
LockedProfile = ProfileManager.GetLockedProfile();
|
||||
if (LockedProfile == -1)
|
||||
{
|
||||
LockedProfile = ProfileManager.GetLockedProfile();
|
||||
if (LockedProfile == -1)
|
||||
return C_4JInput::EKeyboard_Cancelled;
|
||||
}
|
||||
}
|
||||
|
||||
ZeroMemory(&KeyboardOverlap, sizeof(XOVERLAPPED));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
DWORD result = XShowKeyboardUI(LockedProfile, 0, uiText, uiTitle, uiDesc, this->pwchResult, this->uiMaxChars, &KeyboardOverlap);
|
||||
if (result == ERROR_IO_PENDING)
|
||||
break;
|
||||
if (result != ERROR_ACCESS_DENIED)
|
||||
return C_4JInput::EKeyboard_Cancelled;
|
||||
Sleep(250);
|
||||
}
|
||||
|
||||
bActive = true;
|
||||
return eState;
|
||||
}
|
||||
|
||||
//str1k3r - These 2 only exist cause of iggy
|
||||
C_4JInput::EKeyboardResult CKeyboard::RequestKeyboard(LPCWSTR uiTitle, LPCWSTR uiText, LPCWSTR uiDesc, DWORD dwPad, UINT uiMaxChars, int(*Func)(LPVOID, const bool), LPVOID lpParam, C_4JInput::EKeyboardMode eMode)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void CKeyboard::GetText(uint16_t *UTF16String)
|
||||
{
|
||||
//uint16_t *keyString;
|
||||
//for (unsigned int index = 0; keyString[index] && index < 0x200; index++)
|
||||
//{
|
||||
// UTF16String[index] = keyString[index];
|
||||
//}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include "4J_Input.h"
|
||||
|
||||
class CKeyboard
|
||||
{
|
||||
private:
|
||||
XOVERLAPPED KeyboardOverlap;
|
||||
C_4JInput::EKeyboardResult eState;
|
||||
|
||||
int iPad;
|
||||
UINT uiMaxChars;
|
||||
WCHAR *pwchResult;
|
||||
bool bActive;
|
||||
|
||||
int(*Func)(LPVOID lpParam, bool bSet);
|
||||
LPVOID lpParam;
|
||||
public:
|
||||
CKeyboard();
|
||||
void Tick(void);
|
||||
|
||||
C_4JInput::EKeyboardResult RequestKeyboard(LPCWSTR uiTitle, LPCWSTR uiText, LPCWSTR uiDesc, DWORD dwPad, WCHAR *pwchResult, UINT uiMaxChars, int (*Func)(LPVOID, const bool), LPVOID lpParam, C_4JInput::EKeyboardMode eMode = C_4JInput::EKeyboardMode_Default);
|
||||
|
||||
//str1k3r - These 2 only exist cause of iggy
|
||||
C_4JInput::EKeyboardResult RequestKeyboard(LPCWSTR uiTitle, LPCWSTR uiText, LPCWSTR uiDesc, DWORD dwPad, UINT uiMaxChars, int(*Func)(LPVOID, const bool), LPVOID lpParam, C_4JInput::EKeyboardMode eMode);
|
||||
void GetText(uint16_t *UTF16String);
|
||||
};
|
||||
@@ -0,0 +1,734 @@
|
||||
#include "INP_Main.h"
|
||||
|
||||
CInput InternalInputManager;
|
||||
|
||||
CInput::CInput()
|
||||
{
|
||||
m_Keyboard = CKeyboard();
|
||||
|
||||
m_uiSigninJoypadMask = 0;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
m_bIsMenuDisplayed[i] = 0;
|
||||
|
||||
InitTime();
|
||||
|
||||
m_fRepeatDelaySecs = 0.5f;
|
||||
m_fRepeatRateSecs = 0.8f;
|
||||
m_sDebugSequenceName = 0;
|
||||
m_uiDebugSequenceIndex = 0;
|
||||
m_pDebugSequenceFn = 0;
|
||||
}
|
||||
|
||||
void CInput::Initialise(int iInputStateC, unsigned char ucMapC, unsigned char ucActionC, unsigned char ucMenuActionC)
|
||||
{
|
||||
assert(iInputStateC > 0);
|
||||
assert(ucMapC > 0);
|
||||
assert(ucActionC > 0);
|
||||
|
||||
ZeroMemory(m_Joypads, sizeof(m_Joypads));
|
||||
|
||||
m_ucInputStateC = iInputStateC;
|
||||
|
||||
m_iDeadzone = 0x2710;
|
||||
m_iMovementRangeMax = 0x7FFF;
|
||||
|
||||
m_iEffectiveRange = m_iMovementRangeMax - m_iDeadzone;
|
||||
m_iHalfRange = m_iEffectiveRange / 2;
|
||||
m_fEffectiveRange = (float)m_iEffectiveRange;
|
||||
|
||||
for (int i = 0; i < MAX_JOYPADS; i++)
|
||||
{
|
||||
m_Joypads[i].m_pInputStates = new XINPUT_STATE[m_ucInputStateC];
|
||||
m_Joypads[i].m_ucInputStateIndex = -1;
|
||||
m_Joypads[i].m_pfLeftThumbXAxisMap = &m_Joypads[i].m_fNormalizedLeftThumbX;
|
||||
m_Joypads[i].m_pfLeftThumbYAxisMap = &m_Joypads[i].m_fNormalizedLeftThumbY;
|
||||
m_Joypads[i].m_pfRightThumbXAxisMap = &m_Joypads[i].m_fNormalizedRightThumbX;
|
||||
m_Joypads[i].m_pfRightThumbYAxisMap = &m_Joypads[i].m_fNormalizedRightThumbY;
|
||||
m_Joypads[i].m_pucLeftTriggerAxisMap = &m_Joypads[i].m_ucLeftTriggerState;
|
||||
m_Joypads[i].m_pucRightTriggerAxisMap = &m_Joypads[i].m_ucRightTriggerState;
|
||||
m_Joypads[i].m_fSensitivity = 1.0f;
|
||||
}
|
||||
|
||||
m_JoypadMap = (unsigned int **)operator new[](ucMapC * sizeof(int *));
|
||||
for (int i = 0; i < ucMapC; i++)
|
||||
{
|
||||
m_JoypadMap[i] = (unsigned int *)operator new[](ucActionC * sizeof(int));
|
||||
}
|
||||
|
||||
m_ucJoypadMapC = ucMapC;
|
||||
m_ucJoypadMapActionC = ucActionC;
|
||||
m_ucMenuActionC = ucMenuActionC;
|
||||
m_bJoypadMapArrayIsSetup = false;
|
||||
}
|
||||
|
||||
void CInput::Tick(void)
|
||||
{
|
||||
UpdateJoypads();
|
||||
m_Keyboard.Tick();
|
||||
}
|
||||
|
||||
void CInput::SetJoypadValues(JOYPAD *pThisPad)
|
||||
{
|
||||
XINPUT_GAMEPAD *pGamePad = &pThisPad->m_pInputStates[pThisPad->m_ucInputStateIndex].Gamepad;
|
||||
|
||||
if (pGamePad->bLeftTrigger > 0x7Fu)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_LT;
|
||||
}
|
||||
if (pGamePad->bRightTrigger > 0x7Fu)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_RT;
|
||||
}
|
||||
|
||||
if ((pGamePad->wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) != 0)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_RB;
|
||||
}
|
||||
if ((pGamePad->wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) != 0)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_LB;
|
||||
}
|
||||
|
||||
if ((pGamePad->wButtons & XINPUT_GAMEPAD_A) != 0)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_A;
|
||||
}
|
||||
if ((pGamePad->wButtons & XINPUT_GAMEPAD_B) != 0)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_B;
|
||||
}
|
||||
|
||||
if ((pGamePad->wButtons & XINPUT_GAMEPAD_X) != 0)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_X;
|
||||
}
|
||||
if ((pGamePad->wButtons & XINPUT_GAMEPAD_Y) != 0)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_Y;
|
||||
}
|
||||
|
||||
if ((pGamePad->wButtons & XINPUT_GAMEPAD_START) != 0)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_START;
|
||||
}
|
||||
if ((pGamePad->wButtons & XINPUT_GAMEPAD_BACK) != 0)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_BACK;
|
||||
}
|
||||
|
||||
if ((pGamePad->wButtons & XINPUT_GAMEPAD_LEFT_THUMB) != 0)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_LTHUMB;
|
||||
}
|
||||
if ((pGamePad->wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) != 0)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_RTHUMB;
|
||||
}
|
||||
|
||||
if ((pGamePad->wButtons & XINPUT_GAMEPAD_DPAD_UP) != 0)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_DPAD_UP;
|
||||
}
|
||||
if ((pGamePad->wButtons & XINPUT_GAMEPAD_DPAD_DOWN) != 0)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_DPAD_DOWN;
|
||||
}
|
||||
if ((pGamePad->wButtons & XINPUT_GAMEPAD_DPAD_LEFT) != 0)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_DPAD_LEFT;
|
||||
}
|
||||
if ((pGamePad->wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) != 0)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_DPAD_RIGHT;
|
||||
}
|
||||
|
||||
if (pGamePad->sThumbLX > m_iHalfRange + m_iDeadzone)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_LSTICK_RIGHT;
|
||||
}
|
||||
if (pGamePad->sThumbLX < -m_iDeadzone - m_iHalfRange)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_LSTICK_LEFT;
|
||||
}
|
||||
|
||||
if (pGamePad->sThumbRY < -m_iDeadzone - m_iHalfRange)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_RSTICK_DOWN;
|
||||
}
|
||||
if (pGamePad->sThumbRY > m_iHalfRange + m_iDeadzone)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_RSTICK_UP;
|
||||
}
|
||||
if (pGamePad->sThumbRX > m_iHalfRange + m_iDeadzone)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_RSTICK_RIGHT;
|
||||
}
|
||||
if (pGamePad->sThumbRX < -m_iDeadzone - m_iHalfRange)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_RSTICK_LEFT;
|
||||
}
|
||||
|
||||
if (pGamePad->sThumbLY < -m_iDeadzone - m_iHalfRange)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_LSTICK_DOWN;
|
||||
}
|
||||
if (pGamePad->sThumbLY > m_iHalfRange + m_iDeadzone)
|
||||
{
|
||||
pThisPad->m_uiButtons |= _360_JOY_BUTTON_LSTICK_UP;
|
||||
}
|
||||
|
||||
pThisPad->m_ucLeftTriggerState = pGamePad->bLeftTrigger;
|
||||
pThisPad->m_ucRightTriggerState = pGamePad->bRightTrigger;
|
||||
|
||||
if (pGamePad->sThumbRX <= m_iDeadzone)
|
||||
{
|
||||
if (pGamePad->sThumbRX >= -m_iDeadzone)
|
||||
pThisPad->m_iRightThumbX = 0;
|
||||
else
|
||||
pThisPad->m_iRightThumbX = m_iDeadzone + pGamePad->sThumbRX;
|
||||
}
|
||||
else
|
||||
{
|
||||
pThisPad->m_iRightThumbX = pGamePad->sThumbRX - m_iDeadzone;
|
||||
}
|
||||
if (pGamePad->sThumbRY <= m_iDeadzone)
|
||||
{
|
||||
if (pGamePad->sThumbRY >= -m_iDeadzone)
|
||||
pThisPad->m_iRightThumbY = 0;
|
||||
else
|
||||
pThisPad->m_iRightThumbY = m_iDeadzone + pGamePad->sThumbRY;
|
||||
}
|
||||
else
|
||||
{
|
||||
pThisPad->m_iRightThumbY = pGamePad->sThumbRY - m_iDeadzone;
|
||||
}
|
||||
if (pGamePad->sThumbLX <= m_iDeadzone)
|
||||
{
|
||||
if (pGamePad->sThumbLX >= -m_iDeadzone)
|
||||
pThisPad->m_iLeftThumbX = 0;
|
||||
else
|
||||
pThisPad->m_iLeftThumbX = m_iDeadzone + pGamePad->sThumbLX;
|
||||
}
|
||||
else
|
||||
{
|
||||
pThisPad->m_iLeftThumbX = pGamePad->sThumbLX - m_iDeadzone;
|
||||
}
|
||||
if (pGamePad->sThumbLY <= m_iDeadzone)
|
||||
{
|
||||
if (pGamePad->sThumbLY >= -m_iDeadzone)
|
||||
pThisPad->m_iLeftThumbY = 0;
|
||||
else
|
||||
pThisPad->m_iLeftThumbY = m_iDeadzone + pGamePad->sThumbLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
pThisPad->m_iLeftThumbY = pGamePad->sThumbLY - m_iDeadzone;
|
||||
}
|
||||
|
||||
pThisPad->m_iNormalizedLeftThumbX = pThisPad->m_iLeftThumbX / m_iEffectiveRange;
|
||||
pThisPad->m_iNormalizedLeftThumbY = pThisPad->m_iLeftThumbY / m_iEffectiveRange;
|
||||
pThisPad->m_iNormalizedRightThumbX = pThisPad->m_iRightThumbX / m_iEffectiveRange;
|
||||
pThisPad->m_iNormalizedRightThumbY = pThisPad->m_iRightThumbY / m_iEffectiveRange;
|
||||
|
||||
pThisPad->m_fNormalizedLeftThumbX = pThisPad->m_iLeftThumbX / m_fEffectiveRange;
|
||||
pThisPad->m_fNormalizedLeftThumbY = pThisPad->m_iLeftThumbY / m_fEffectiveRange;
|
||||
pThisPad->m_fNormalizedRightThumbX = pThisPad->m_iRightThumbX / m_fEffectiveRange;
|
||||
pThisPad->m_fNormalizedRightThumbY = pThisPad->m_iRightThumbY / m_fEffectiveRange;
|
||||
}
|
||||
|
||||
void CInput::SetDeadzoneAndMovementRange(unsigned int uiDeadzone, unsigned int uiMovementRangeMax)
|
||||
{
|
||||
m_iDeadzone = uiDeadzone;
|
||||
m_iMovementRangeMax = uiMovementRangeMax;
|
||||
m_iEffectiveRange = uiMovementRangeMax - uiDeadzone;
|
||||
m_iHalfRange = m_iEffectiveRange / 2;
|
||||
}
|
||||
|
||||
void CInput::SetJoypadSensitivity(int iPad, float fSensitivity)
|
||||
{
|
||||
m_Joypads[iPad].m_fSensitivity = fSensitivity;
|
||||
}
|
||||
|
||||
void CInput::SetGameJoypadMaps(unsigned char ucMap, unsigned char ucAction, unsigned int uiActionVal)
|
||||
{
|
||||
assert(ucMap < m_ucJoypadMapC);
|
||||
assert(ucAction < m_ucJoypadMapActionC);
|
||||
|
||||
m_JoypadMap[ucMap][ucAction] = uiActionVal;
|
||||
}
|
||||
|
||||
unsigned int CInput::GetGameJoypadMaps(unsigned char ucMap, unsigned char ucAction)
|
||||
{
|
||||
assert(ucMap < m_ucJoypadMapC);
|
||||
assert(ucAction < m_ucJoypadMapActionC);
|
||||
|
||||
return m_JoypadMap[ucMap][ucAction];
|
||||
}
|
||||
|
||||
void CInput::SetJoypadMapVal(int iPad, unsigned char ucMap)
|
||||
{
|
||||
m_bJoypadMapArrayIsSetup = true;
|
||||
m_Joypads[iPad].m_ucMappingValue = ucMap;
|
||||
}
|
||||
|
||||
unsigned char CInput::GetJoypadMapVal(int iPad)
|
||||
{
|
||||
return m_Joypads[iPad].m_ucMappingValue;
|
||||
}
|
||||
|
||||
void CInput::SetJoypadStickAxisMap(int iPad, unsigned int uiFrom, unsigned int uiTo)
|
||||
{
|
||||
float *pfTo = nullptr;
|
||||
|
||||
switch (uiTo)
|
||||
{
|
||||
case AXIS_MAP_LX:
|
||||
pfTo = &m_Joypads[iPad].m_fNormalizedLeftThumbX;
|
||||
break;
|
||||
case AXIS_MAP_LY:
|
||||
pfTo = &m_Joypads[iPad].m_fNormalizedLeftThumbY;
|
||||
break;
|
||||
case AXIS_MAP_RX:
|
||||
pfTo = &m_Joypads[iPad].m_fNormalizedRightThumbX;
|
||||
break;
|
||||
case AXIS_MAP_RY:
|
||||
pfTo = &m_Joypads[iPad].m_fNormalizedRightThumbY;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (uiFrom)
|
||||
{
|
||||
case AXIS_MAP_LX:
|
||||
m_Joypads[iPad].m_pfLeftThumbXAxisMap = pfTo;
|
||||
break;
|
||||
case AXIS_MAP_LY:
|
||||
m_Joypads[iPad].m_pfLeftThumbYAxisMap = pfTo;
|
||||
break;
|
||||
case AXIS_MAP_RX:
|
||||
m_Joypads[iPad].m_pfRightThumbXAxisMap = pfTo;
|
||||
break;
|
||||
case AXIS_MAP_RY:
|
||||
m_Joypads[iPad].m_pfRightThumbYAxisMap = pfTo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CInput::SetJoypadStickTriggerMap(int iPad, unsigned int uiFrom, unsigned int uiTo)
|
||||
{
|
||||
unsigned char *pucTo = nullptr;
|
||||
|
||||
switch (uiTo)
|
||||
{
|
||||
case TRIGGER_MAP_0:
|
||||
pucTo = &m_Joypads[iPad].m_ucRightTriggerState;
|
||||
break;
|
||||
case TRIGGER_MAP_1:
|
||||
pucTo = &m_Joypads[iPad].m_ucLeftTriggerState;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (uiFrom)
|
||||
{
|
||||
case TRIGGER_MAP_0:
|
||||
m_Joypads[iPad].m_pucRightTriggerAxisMap = pucTo;
|
||||
break;
|
||||
case TRIGGER_MAP_1:
|
||||
m_Joypads[iPad].m_pucLeftTriggerAxisMap = pucTo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool CInput::IsPadConnected(int iPad)
|
||||
{
|
||||
return m_Joypads[iPad].m_bIsConnected;
|
||||
}
|
||||
|
||||
void CInput::SetSigninJoypadMask(unsigned int mask)
|
||||
{
|
||||
m_uiSigninJoypadMask = mask;
|
||||
}
|
||||
|
||||
unsigned int CInput::GetValue(int iPad, unsigned char ucAction, bool bRepeat)
|
||||
{
|
||||
if (m_bIsMenuDisplayed[iPad] && ucAction > this->m_ucMenuActionC)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char ucMap = this->m_Joypads[iPad].m_ucMappingValue;
|
||||
unsigned int uiVal = this->m_JoypadMap[ucMap][ucAction] & this->m_Joypads[iPad].m_uiButtons;
|
||||
if (!uiVal || !bRepeat)
|
||||
{
|
||||
return uiVal;
|
||||
}
|
||||
|
||||
int iKeyVal = 0;
|
||||
for (int iKey = this->m_JoypadMap[ucMap][ucAction]; (iKey & 1) == 0; iKey >>= 1)
|
||||
{
|
||||
iKeyVal++;
|
||||
}
|
||||
|
||||
if (m_fRepeatDelaySecs <= m_Timers[iPad][iKeyVal].m_fTotalHoldTime || m_Timers[iPad][iKeyVal].m_bInitialPressHandled)
|
||||
{
|
||||
if (m_Timers[iPad][iKeyVal].m_fTotalHoldTime < m_fRepeatDelaySecs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (m_Timers[iPad][iKeyVal].m_fLastRepeatTime == 0.0f)
|
||||
{
|
||||
m_Timers[iPad][iKeyVal].m_fLastRepeatTime = m_fRepeatDelaySecs;
|
||||
return uiVal;
|
||||
}
|
||||
else if ((m_Timers[iPad][iKeyVal].m_fTotalHoldTime - m_Timers[iPad][iKeyVal].m_fLastRepeatTime) <= m_fRepeatRateSecs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Timers[iPad][iKeyVal].m_fLastRepeatTime = m_Timers[iPad][iKeyVal].m_fLastRepeatTime + m_fRepeatRateSecs;
|
||||
return uiVal;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Timers[iPad][iKeyVal].m_bInitialPressHandled = true;
|
||||
return uiVal;
|
||||
}
|
||||
}
|
||||
|
||||
bool CInput::IsSet(int iPad, unsigned char ucAction)
|
||||
{
|
||||
return (!m_bIsMenuDisplayed[iPad] || ucAction <= m_ucMenuActionC) &&
|
||||
(m_JoypadMap[m_Joypads[iPad].m_ucMappingValue][ucAction] & m_Joypads[iPad].m_uiButtons) != 0;
|
||||
}
|
||||
|
||||
bool CInput::ButtonPressed(int iPad, unsigned char ucAction)
|
||||
{
|
||||
if (ucAction == 255)
|
||||
{
|
||||
return m_Joypads[iPad].m_uiButtonsPressed != 0;
|
||||
}
|
||||
|
||||
if (m_bIsMenuDisplayed[iPad] && ucAction > m_ucMenuActionC)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (m_JoypadMap[m_Joypads[iPad].m_ucMappingValue][ucAction] & m_Joypads[iPad].m_uiButtonsPressed) != 0;
|
||||
}
|
||||
|
||||
bool CInput::ButtonReleased(int iPad, unsigned char ucAction)
|
||||
{
|
||||
return (!m_bIsMenuDisplayed[iPad] || ucAction <= m_ucMenuActionC) &&
|
||||
(m_JoypadMap[m_Joypads[iPad].m_ucMappingValue][ucAction] & m_Joypads[iPad].m_uiButtonsReleased) != 0;
|
||||
}
|
||||
|
||||
bool CInput::ButtonDown(int iPad, unsigned char ucAction)
|
||||
{
|
||||
if (ucAction == 255)
|
||||
{
|
||||
return m_Joypads[iPad].m_uiButtons != 0;
|
||||
}
|
||||
|
||||
if (m_bIsMenuDisplayed[iPad] && ucAction > m_ucMenuActionC)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (m_JoypadMap[m_Joypads[iPad].m_ucMappingValue][ucAction] & m_Joypads[iPad].m_uiButtons) != 0;
|
||||
}
|
||||
|
||||
float CInput::GetJoypadStick_Menu_LX(unsigned char ucPad)
|
||||
{
|
||||
return m_Joypads[ucPad].m_iNormalizedLeftThumbX;
|
||||
}
|
||||
|
||||
float CInput::GetJoypadStick_Menu_LY(unsigned char ucPad)
|
||||
{
|
||||
return m_Joypads[ucPad].m_iNormalizedLeftThumbY;
|
||||
}
|
||||
|
||||
float CInput::GetJoypadStick_Menu_RX(unsigned char ucPad)
|
||||
{
|
||||
return m_Joypads[ucPad].m_iNormalizedRightThumbX;
|
||||
}
|
||||
|
||||
float CInput::GetJoypadStick_Menu_RY(unsigned char ucPad)
|
||||
{
|
||||
return m_Joypads[ucPad].m_iNormalizedRightThumbY;
|
||||
}
|
||||
|
||||
unsigned char CInput::GetJoypadLTrigger_Menu(unsigned char ucPad)
|
||||
{
|
||||
return m_Joypads[ucPad].m_ucLeftTriggerState;
|
||||
}
|
||||
|
||||
unsigned char CInput::GetJoypadRTrigger_Menu(unsigned char ucPad)
|
||||
{
|
||||
return m_Joypads[ucPad].m_ucRightTriggerState;
|
||||
}
|
||||
|
||||
float CInput::GetJoypadStick_LX(int iPad, bool bCheckMenuDisplay)
|
||||
{
|
||||
if (bCheckMenuDisplay && m_bIsMenuDisplayed[iPad])
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return *m_Joypads[iPad].m_pfLeftThumbXAxisMap * m_Joypads[iPad].m_fSensitivity;
|
||||
}
|
||||
|
||||
float CInput::GetJoypadStick_LY(int iPad, bool bCheckMenuDisplay)
|
||||
{
|
||||
if (bCheckMenuDisplay && m_bIsMenuDisplayed[iPad])
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return *m_Joypads[iPad].m_pfLeftThumbYAxisMap * m_Joypads[iPad].m_fSensitivity;
|
||||
}
|
||||
|
||||
float CInput::GetJoypadStick_RX(int iPad, bool bCheckMenuDisplay)
|
||||
{
|
||||
if (bCheckMenuDisplay && m_bIsMenuDisplayed[iPad])
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return *m_Joypads[iPad].m_pfRightThumbXAxisMap * m_Joypads[iPad].m_fSensitivity;
|
||||
}
|
||||
|
||||
float CInput::GetJoypadStick_RY(int iPad, bool bCheckMenuDisplay)
|
||||
{
|
||||
if (bCheckMenuDisplay && m_bIsMenuDisplayed[iPad])
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return *m_Joypads[iPad].m_pfRightThumbYAxisMap * m_Joypads[iPad].m_fSensitivity;
|
||||
}
|
||||
|
||||
unsigned char CInput::GetJoypadLTrigger(int iPad, bool bCheckMenuDisplay)
|
||||
{
|
||||
if (bCheckMenuDisplay && m_bIsMenuDisplayed[iPad])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return *m_Joypads[iPad].m_pucLeftTriggerAxisMap;
|
||||
}
|
||||
|
||||
unsigned char CInput::GetJoypadRTrigger(int iPad, bool bCheckMenuDisplay)
|
||||
{
|
||||
if (bCheckMenuDisplay && m_bIsMenuDisplayed[iPad])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return *m_Joypads[iPad].m_pucRightTriggerAxisMap;
|
||||
}
|
||||
|
||||
void CInput::SetMenuDisplayed(int iPad, bool bVal)
|
||||
{
|
||||
m_bIsMenuDisplayed[iPad] = bVal;
|
||||
}
|
||||
|
||||
void CInput::SetKeyRepeatRate(float fRepeatDelaySecs, float fRepeatRateSecs)
|
||||
{
|
||||
m_fRepeatDelaySecs = fRepeatDelaySecs;
|
||||
m_fRepeatRateSecs = fRepeatRateSecs;
|
||||
}
|
||||
|
||||
void CInput::SetDebugSequence(const char *chSequenceA, int (*Func)(LPVOID), LPVOID lpParam)
|
||||
{
|
||||
int iLen = strlen(chSequenceA);
|
||||
|
||||
m_sDebugSequenceName = (char *)operator new[](iLen);
|
||||
strcpy(m_sDebugSequenceName, chSequenceA);
|
||||
|
||||
m_pDebugSequenceFn = Func;
|
||||
m_pDebugSequenceParam = lpParam;
|
||||
}
|
||||
|
||||
FLOAT CInput::GetIdleSeconds(int iPad)
|
||||
{
|
||||
LARGE_INTEGER qwDeltaTime;
|
||||
QueryPerformanceCounter(&qwDeltaTime);
|
||||
|
||||
LARGE_INTEGER fElapsedTime = this->m_LastActivityTime[iPad];
|
||||
uint64_t qwNewTime = qwDeltaTime.QuadPart - fElapsedTime.QuadPart;
|
||||
|
||||
return this->m_fTickToSeconds * (qwDeltaTime.LowPart - fElapsedTime.LowPart);
|
||||
}
|
||||
|
||||
bool CInput::UpdateJoypads()
|
||||
{
|
||||
assert(m_bJoypadMapArrayIsSetup);
|
||||
|
||||
for (int i = 0; i < MAX_JOYPADS; i++)
|
||||
{
|
||||
JOYPAD *pThisPad = &m_Joypads[i];
|
||||
|
||||
pThisPad->m_uiOldButtons = pThisPad->m_uiButtons;
|
||||
pThisPad->m_uiButtons = 0;
|
||||
pThisPad->m_iRightThumbY = 0;
|
||||
pThisPad->m_iRightThumbX = 0;
|
||||
pThisPad->m_iLeftThumbY = 0;
|
||||
pThisPad->m_iLeftThumbX = 0;
|
||||
pThisPad->m_ucLeftTriggerState = 0;
|
||||
pThisPad->m_ucRightTriggerState = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_JOYPADS; i++)
|
||||
{
|
||||
if (!m_Joypads[i].m_bIsDisabled)
|
||||
{
|
||||
JOYPAD *pThisPad = &m_Joypads[i];
|
||||
|
||||
bool bOldIsConnected = pThisPad->m_bIsConnected;
|
||||
|
||||
pThisPad->m_ucInputStateIndex = pThisPad->m_ucInputStateIndex++;
|
||||
if (pThisPad->m_ucInputStateIndex == m_ucInputStateC)
|
||||
{
|
||||
pThisPad->m_ucInputStateIndex = 0;
|
||||
}
|
||||
|
||||
pThisPad->m_bIsConnected = XInputGetState(i, &pThisPad->m_pInputStates[pThisPad->m_ucInputStateIndex]) == 0;
|
||||
|
||||
bool bWasConnected = bOldIsConnected && !pThisPad->m_bIsConnected;
|
||||
pThisPad->m_bWasConnected = bWasConnected;
|
||||
|
||||
bool bHasConnected = !bOldIsConnected && pThisPad->m_bIsConnected;
|
||||
pThisPad->m_bHasConnected = bHasConnected;
|
||||
|
||||
if (pThisPad->m_bIsConnected)
|
||||
{
|
||||
SetJoypadValues(pThisPad);
|
||||
|
||||
pThisPad->m_uiButtonsPressed = ~pThisPad->m_uiOldButtons & pThisPad->m_uiButtons;
|
||||
pThisPad->m_uiButtonsReleased = ~pThisPad->m_uiButtons & pThisPad->m_uiOldButtons;
|
||||
|
||||
for (int bit = 0; bit < 24; ++bit)
|
||||
{
|
||||
if ((pThisPad->m_uiButtonsPressed & (1 << bit)) != 0)
|
||||
{
|
||||
GetStartTime(i, bit);
|
||||
}
|
||||
else if ((pThisPad->m_uiButtons & (1 << bit)) != 0)
|
||||
{
|
||||
UpdateTime(i, bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pThisPad->m_bWasConnected)
|
||||
{
|
||||
ClearJoypadValues(pThisPad);
|
||||
}
|
||||
|
||||
if (m_pDebugSequenceFn && (pThisPad->m_uiButtonsPressed & (_360_JOY_BUTTON_A | _360_JOY_BUTTON_B | _360_JOY_BUTTON_X | _360_JOY_BUTTON_Y |
|
||||
_360_JOY_BUTTON_RB | _360_JOY_BUTTON_LB)) != 0)
|
||||
{
|
||||
char chSeq;
|
||||
|
||||
if ((pThisPad->m_uiButtonsPressed & _360_JOY_BUTTON_A) == _360_JOY_BUTTON_A)
|
||||
{
|
||||
chSeq = 'A';
|
||||
}
|
||||
else if ((pThisPad->m_uiButtonsPressed & _360_JOY_BUTTON_B) == _360_JOY_BUTTON_B)
|
||||
{
|
||||
chSeq = 'B';
|
||||
}
|
||||
else if ((pThisPad->m_uiButtonsPressed & _360_JOY_BUTTON_X) == _360_JOY_BUTTON_X)
|
||||
{
|
||||
chSeq = 'X';
|
||||
}
|
||||
else if ((pThisPad->m_uiButtonsPressed & _360_JOY_BUTTON_Y) == _360_JOY_BUTTON_Y)
|
||||
{
|
||||
chSeq = 'Y';
|
||||
}
|
||||
else if ((pThisPad->m_uiButtonsPressed & _360_JOY_BUTTON_LB) == _360_JOY_BUTTON_LB)
|
||||
{
|
||||
chSeq = 'L';
|
||||
}
|
||||
else if ((pThisPad->m_uiButtonsPressed & _360_JOY_BUTTON_RB) == _360_JOY_BUTTON_RB)
|
||||
{
|
||||
chSeq = 'R';
|
||||
}
|
||||
|
||||
if (m_sDebugSequenceName[m_uiDebugSequenceIndex] == chSeq)
|
||||
{
|
||||
if (!m_sDebugSequenceName[m_uiDebugSequenceIndex++])
|
||||
{
|
||||
m_uiDebugSequenceIndex = 0;
|
||||
(m_pDebugSequenceFn)(m_pDebugSequenceParam);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_uiDebugSequenceIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CInput::ClearJoypadValues(JOYPAD *pThisPad)
|
||||
{
|
||||
pThisPad->m_uiButtonsPressed = 0;
|
||||
pThisPad->m_uiButtonsReleased = 0;
|
||||
pThisPad->m_uiButtons = 0;
|
||||
pThisPad->m_ucLeftTriggerState = 0;
|
||||
pThisPad->m_ucRightTriggerState = 0;
|
||||
pThisPad->m_iRightThumbX = 0;
|
||||
pThisPad->m_iRightThumbY = 0;
|
||||
pThisPad->m_iLeftThumbX = 0;
|
||||
pThisPad->m_iLeftThumbY = 0;
|
||||
pThisPad->m_iNormalizedLeftThumbX = 0;
|
||||
pThisPad->m_iNormalizedLeftThumbY = 0;
|
||||
pThisPad->m_iNormalizedRightThumbX = 0;
|
||||
pThisPad->m_iNormalizedRightThumbY = 0;
|
||||
pThisPad->m_fNormalizedLeftThumbX = 0.0f;
|
||||
pThisPad->m_fNormalizedLeftThumbY = 0.0f;
|
||||
pThisPad->m_fNormalizedRightThumbX = 0.0f;
|
||||
pThisPad->m_fNormalizedRightThumbY = 0.0f;
|
||||
}
|
||||
|
||||
void CInput::InitTime(void)
|
||||
{
|
||||
LARGE_INTEGER qwTicksPerSec;
|
||||
QueryPerformanceFrequency(&qwTicksPerSec);
|
||||
|
||||
m_fTickToSeconds = 1.0 / (float)(int)qwTicksPerSec.LowPart;
|
||||
for (int i = 0; i < MAX_JOYPADS; i++)
|
||||
{
|
||||
m_LastActivityTime[i].QuadPart = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CInput::GetStartTime(int iPad, int iKey)
|
||||
{
|
||||
QueryPerformanceCounter(&m_Timers[iPad][iKey].m_qwStartTime);
|
||||
|
||||
m_Timers[iPad][iKey].m_qwTotalHoldTicks.QuadPart = 0;
|
||||
m_Timers[iPad][iKey].m_fTotalHoldTime = 0;
|
||||
m_Timers[iPad][iKey].m_fLastRepeatTime = 0;
|
||||
m_Timers[iPad][iKey].m_bInitialPressHandled = false;
|
||||
|
||||
m_LastActivityTime[iPad].QuadPart = m_Timers[iPad][iKey].m_qwStartTime.QuadPart;
|
||||
}
|
||||
|
||||
void CInput::UpdateTime(int iPad, int iKey)
|
||||
{
|
||||
LARGE_INTEGER qwDeltaTime;
|
||||
QueryPerformanceCounter(&qwDeltaTime);
|
||||
|
||||
uint64_t qwNewTime = qwDeltaTime.QuadPart - m_Timers[iPad][iKey].m_qwStartTime.QuadPart;
|
||||
m_Timers[iPad][iKey].m_qwTotalHoldTicks.QuadPart += qwNewTime;
|
||||
|
||||
m_Timers[iPad][iKey].m_qwStartTime = qwDeltaTime;
|
||||
m_Timers[iPad][iKey].m_fTotalHoldTime = m_Timers[iPad][iKey].m_fTotalHoldTime + (m_fTickToSeconds * qwNewTime);
|
||||
|
||||
m_LastActivityTime[iPad].QuadPart = m_Timers[iPad][iKey].m_qwStartTime.QuadPart;
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
#pragma once
|
||||
#include "INP_Keyboard.h"
|
||||
#include "INP_MessageUI.h"
|
||||
|
||||
#define MAX_JOYPADS 4
|
||||
|
||||
class CInput
|
||||
{
|
||||
public:
|
||||
struct JOYPAD
|
||||
{
|
||||
bool m_bIsDisabled;
|
||||
bool m_bIsConnected;
|
||||
bool m_bWasConnected;
|
||||
bool m_bHasConnected;
|
||||
|
||||
unsigned int m_uiButtons;
|
||||
unsigned int m_uiOldButtons;
|
||||
int m_uiButtonsPressed;
|
||||
int m_uiButtonsReleased;
|
||||
|
||||
int m_iRightThumbX;
|
||||
int m_iRightThumbY;
|
||||
int m_iLeftThumbX;
|
||||
int m_iLeftThumbY;
|
||||
|
||||
DWORD m_iNormalizedRightThumbX;
|
||||
DWORD m_iNormalizedRightThumbY;
|
||||
DWORD m_iNormalizedLeftThumbX;
|
||||
DWORD m_iNormalizedLeftThumbY;
|
||||
|
||||
float m_fNormalizedRightThumbX;
|
||||
float m_fNormalizedRightThumbY;
|
||||
float m_fNormalizedLeftThumbX;
|
||||
float m_fNormalizedLeftThumbY;
|
||||
|
||||
unsigned char m_ucLeftTriggerState;
|
||||
unsigned char m_ucRightTriggerState;
|
||||
|
||||
float *m_pfLeftThumbXAxisMap;
|
||||
float *m_pfLeftThumbYAxisMap;
|
||||
float *m_pfRightThumbXAxisMap;
|
||||
float *m_pfRightThumbYAxisMap;
|
||||
|
||||
float m_fSensitivity;
|
||||
|
||||
BYTE *m_pucLeftTriggerAxisMap;
|
||||
BYTE *m_pucRightTriggerAxisMap;
|
||||
|
||||
unsigned char m_ucMappingValue;
|
||||
unsigned char m_ucInputStateIndex;
|
||||
XINPUT_STATE *m_pInputStates;
|
||||
};
|
||||
|
||||
struct JOYPADS
|
||||
{
|
||||
};
|
||||
|
||||
struct TimeInfo
|
||||
{
|
||||
LARGE_INTEGER m_qwStartTime;
|
||||
LARGE_INTEGER m_qwTotalHoldTicks;
|
||||
float m_fTotalHoldTime;
|
||||
float m_fLastRepeatTime;
|
||||
bool m_bInitialPressHandled;
|
||||
};
|
||||
|
||||
CInput();
|
||||
|
||||
void Initialise(int iInputStateC, unsigned char ucMapC, unsigned char ucActionC, unsigned char ucMenuActionC);
|
||||
void Tick(void);
|
||||
|
||||
void SetJoypadValues(JOYPAD *pThisPad);
|
||||
void SetDeadzoneAndMovementRange(unsigned int uiDeadzone, unsigned int uiMovementRangeMax);
|
||||
void SetJoypadSensitivity(int iPad, float fSensitivity);
|
||||
|
||||
void SetGameJoypadMaps(unsigned char ucMap, unsigned char ucAction, unsigned int uiActionVal);
|
||||
unsigned int GetGameJoypadMaps(unsigned char ucMap, unsigned char ucAction);
|
||||
void SetJoypadMapVal(int iPad, unsigned char ucMap);
|
||||
unsigned char GetJoypadMapVal(int iPad);
|
||||
|
||||
void SetJoypadStickAxisMap(int iPad, unsigned int uiFrom, unsigned int uiTo);
|
||||
void SetJoypadStickTriggerMap(int iPad, unsigned int uiFrom, unsigned int uiTo);
|
||||
|
||||
bool IsPadConnected(int iPad);
|
||||
void SetSigninJoypadMask(unsigned int mask);
|
||||
unsigned int GetValue(int iPad, unsigned char ucAction, bool bRepeat = false);
|
||||
bool IsSet(int iPad, unsigned char ucAction);
|
||||
|
||||
bool ButtonPressed(int iPad, unsigned char ucAction = 255); // toggled
|
||||
bool ButtonReleased(int iPad, unsigned char ucAction); // toggled
|
||||
bool ButtonDown(int iPad, unsigned char ucAction = 255); // button held down
|
||||
|
||||
float GetJoypadStick_Menu_LX(unsigned char ucPad);
|
||||
float GetJoypadStick_Menu_LY(unsigned char ucPad);
|
||||
float GetJoypadStick_Menu_RX(unsigned char ucPad);
|
||||
float GetJoypadStick_Menu_RY(unsigned char ucPad);
|
||||
unsigned char GetJoypadLTrigger_Menu(unsigned char ucPad);
|
||||
unsigned char GetJoypadRTrigger_Menu(unsigned char ucPad);
|
||||
|
||||
float GetJoypadStick_LX(int iPad, bool bCheckMenuDisplay = true);
|
||||
float GetJoypadStick_LY(int iPad, bool bCheckMenuDisplay = true);
|
||||
float GetJoypadStick_RX(int iPad, bool bCheckMenuDisplay = true);
|
||||
float GetJoypadStick_RY(int iPad, bool bCheckMenuDisplay = true);
|
||||
unsigned char GetJoypadLTrigger(int iPad, bool bCheckMenuDisplay = true);
|
||||
unsigned char GetJoypadRTrigger(int iPad, bool bCheckMenuDisplay = true);
|
||||
|
||||
void SetMenuDisplayed(int iPad, bool bVal);
|
||||
|
||||
void SetKeyRepeatRate(float fRepeatDelaySecs, float fRepeatRateSecs);
|
||||
void SetDebugSequence(const char *chSequenceA, int (*Func)(LPVOID), LPVOID lpParam);
|
||||
FLOAT GetIdleSeconds(int iPad);
|
||||
|
||||
bool UpdateJoypads(void);
|
||||
void ClearJoypadValues(JOYPAD *pThisPad);
|
||||
|
||||
void InitTime(void);
|
||||
void GetStartTime(int iPad, int iKey);
|
||||
void UpdateTime(int iPad, int iKey);
|
||||
|
||||
BYTE gap0[16];
|
||||
|
||||
JOYPAD m_Joypads[MAX_JOYPADS];
|
||||
|
||||
int m_iDeadzone;
|
||||
int m_iMovementRangeMax;
|
||||
int m_iEffectiveRange;
|
||||
int m_iHalfRange;
|
||||
float m_fEffectiveRange;
|
||||
|
||||
unsigned char m_ucInputStateC;
|
||||
unsigned char m_ucJoypadMapC;
|
||||
unsigned char m_ucJoypadMapActionC;
|
||||
unsigned char m_ucMenuActionC;
|
||||
|
||||
unsigned int **m_JoypadMap;
|
||||
|
||||
bool m_bJoypadMapArrayIsSetup;
|
||||
unsigned int m_uiSigninJoypadMask;
|
||||
bool m_bIsMenuDisplayed[MAX_JOYPADS];
|
||||
|
||||
CKeyboard m_Keyboard;
|
||||
CMessageUI m_MessageUI;
|
||||
|
||||
float m_fTickToSeconds;
|
||||
float m_fRepeatDelaySecs;
|
||||
float m_fRepeatRateSecs;
|
||||
|
||||
TimeInfo m_Timers[MAX_JOYPADS][24];
|
||||
LARGE_INTEGER m_LastActivityTime[MAX_JOYPADS];
|
||||
|
||||
char *m_sDebugSequenceName;
|
||||
unsigned int m_uiDebugSequenceIndex;
|
||||
int (*m_pDebugSequenceFn)(void *);
|
||||
LPVOID m_pDebugSequenceParam;
|
||||
};
|
||||
|
||||
// Singleton
|
||||
extern CInput InternalInputManager;
|
||||
@@ -0,0 +1,110 @@
|
||||
#include "4J_Storage.h"
|
||||
#include "INP_MessageUI.h"
|
||||
|
||||
CMessageUI::CMessageUI()
|
||||
{
|
||||
bCancel = false;
|
||||
}
|
||||
|
||||
C4JStorage::EMessageResult CMessageUI::RequestMessageBox(LPCWSTR uiTitle, LPCWSTR uiText, LPCWSTR *uiButtons, UINT uiButtonCount, DWORD dwPad, int(*Func)(LPVOID, int, const C4JStorage::EMessageResult), LPVOID lpParam, DWORD dwFocusButton)
|
||||
{
|
||||
if (eState == C4JStorage::EMessage_Pending)
|
||||
return C4JStorage::EMessage_Busy;
|
||||
|
||||
eState = C4JStorage::EMessage_Pending;
|
||||
|
||||
for (UINT i = 0; i < uiButtonCount; i++)
|
||||
this->uiButtons[i] = uiButtons[i];
|
||||
this->uiTitle = uiTitle;
|
||||
this->uiText = uiText;
|
||||
this->uiButtonCount = uiButtonCount;
|
||||
this->dwPad = dwPad;
|
||||
this->dwFocusButton = dwFocusButton;
|
||||
this->Func = Func;
|
||||
this->lpParam = lpParam;
|
||||
|
||||
CreateThread(NULL, 0, CreateMessageBoxUIFn, this, 0, NULL);
|
||||
|
||||
return eState;
|
||||
}
|
||||
|
||||
DWORD WINAPI CMessageUI::CreateMessageBoxUIFn(LPVOID lpParam)
|
||||
{
|
||||
CMessageUI *self = (CMessageUI *)lpParam;
|
||||
|
||||
XOVERLAPPED MessageBoxOverlap;
|
||||
ZeroMemory(&MessageBoxOverlap, sizeof(XOVERLAPPED));
|
||||
|
||||
MESSAGEBOX_RESULT MessageResult;
|
||||
ZeroMemory(&MessageResult, sizeof(MESSAGEBOX_RESULT));
|
||||
|
||||
bool bShown = true;
|
||||
do
|
||||
{
|
||||
DWORD result = XShowMessageBoxUI(self->dwPad, self->uiTitle, self->uiText, self->uiButtonCount, self->uiButtons, self->dwFocusButton, 0, &MessageResult, &MessageBoxOverlap);
|
||||
if (result != ERROR_ACCESS_DENIED)
|
||||
break;
|
||||
Sleep(250);
|
||||
if (self->bCancel)
|
||||
bShown = false;
|
||||
} while (bShown);
|
||||
|
||||
C4JStorage::EMessageResult state;
|
||||
|
||||
if (!bShown)
|
||||
{
|
||||
state = C4JStorage::EMessage_Cancelled;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (MessageBoxOverlap.InternalLow == ERROR_IO_PENDING)
|
||||
{
|
||||
Sleep(250);
|
||||
if (self->bCancel)
|
||||
{
|
||||
XCancelOverlapped(&MessageBoxOverlap);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->bCancel || XGetOverlappedResult(&MessageBoxOverlap, NULL, TRUE) == ERROR_CANCELLED)
|
||||
{
|
||||
state = C4JStorage::EMessage_Cancelled;
|
||||
}
|
||||
else switch (MessageResult.dwButtonPressed)
|
||||
{
|
||||
case 0:
|
||||
state = C4JStorage::EMessage_ResultAccept;
|
||||
break;
|
||||
case 1:
|
||||
state = C4JStorage::EMessage_ResultDecline;
|
||||
break;
|
||||
case 2:
|
||||
state = C4JStorage::EMessage_ResultThirdOption;
|
||||
break;
|
||||
case 3:
|
||||
state = C4JStorage::EMessage_ResultFourthOption;
|
||||
break;
|
||||
default:
|
||||
state = C4JStorage::EMessage_Cancelled;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self->eState = state;
|
||||
|
||||
if (self->Func)
|
||||
self->Func(self->lpParam, self->dwPad, state);
|
||||
|
||||
ExitThread(0);
|
||||
}
|
||||
|
||||
void CMessageUI::CancelMessageBoxRequest()
|
||||
{
|
||||
bCancel = true;
|
||||
}
|
||||
|
||||
C4JStorage::EMessageResult CMessageUI::GetMessageBoxResult()
|
||||
{
|
||||
return eState;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "4J_Input.h"
|
||||
|
||||
class CMessageUI
|
||||
{
|
||||
private:
|
||||
C4JStorage::EMessageResult eState;
|
||||
LPCWSTR uiTitle;
|
||||
LPCWSTR uiText;
|
||||
LPCWSTR uiButtons[3];
|
||||
UINT uiButtonCount;
|
||||
DWORD dwPad;
|
||||
DWORD dwFocusButton;
|
||||
int(*Func)(LPVOID, int, C4JStorage::EMessageResult);
|
||||
LPVOID lpParam;
|
||||
bool bCancel;
|
||||
public:
|
||||
CMessageUI();
|
||||
C4JStorage::EMessageResult RequestMessageBox(LPCWSTR uiTitle, LPCWSTR uiText, LPCWSTR *uiButtons, UINT uiButtonCount, DWORD dwPad = XUSER_INDEX_ANY, int(*Func)(LPVOID, int, const C4JStorage::EMessageResult) = NULL, LPVOID lpParam = NULL, DWORD dwFocusButton = 0);
|
||||
static DWORD WINAPI CreateMessageBoxUIFn(LPVOID lpParam);
|
||||
void CancelMessageBoxRequest();
|
||||
C4JStorage::EMessageResult GetMessageBoxResult();
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
#include "INP_StringCheck.h"
|
||||
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
@@ -0,0 +1,102 @@
|
||||
#include "LinkedList.h"
|
||||
|
||||
LinkedList::LinkedList()
|
||||
{
|
||||
this->m_NodeC = 0;
|
||||
this->m_Head = nullptr;
|
||||
this->m_Tail = nullptr;
|
||||
}
|
||||
|
||||
void LinkedList::AddToHead(void *pvData)
|
||||
{
|
||||
_LL_NODE *pNode = new _LL_NODE();
|
||||
pNode->m_pvData = pvData;
|
||||
|
||||
if (!m_Tail)
|
||||
{
|
||||
m_Tail = pNode;
|
||||
}
|
||||
|
||||
if (m_Head)
|
||||
{
|
||||
m_Head->m_Prev = pNode;
|
||||
pNode->m_Next = m_Head;
|
||||
}
|
||||
|
||||
m_Head = pNode;
|
||||
m_NodeC++;
|
||||
}
|
||||
|
||||
void LinkedList::AddToTail(void *pvData)
|
||||
{
|
||||
_LL_NODE *pNode = new _LL_NODE();
|
||||
pNode->m_pvData = pvData;
|
||||
|
||||
if (!m_Head)
|
||||
{
|
||||
m_Head = pNode;
|
||||
}
|
||||
|
||||
if (m_Tail)
|
||||
{
|
||||
m_Tail->m_Next = pNode;
|
||||
pNode->m_Prev = m_Tail;
|
||||
}
|
||||
|
||||
pNode->m_Next = nullptr;
|
||||
pNode->m_Prev = m_Tail;
|
||||
|
||||
m_Tail = pNode;
|
||||
m_NodeC++;
|
||||
}
|
||||
|
||||
void LinkedList::RemoveNode(_LL_NODE *pNodeToRemove)
|
||||
{
|
||||
_LL_NODE *pCurrentNode;
|
||||
for (pCurrentNode = m_Head; pCurrentNode != pNodeToRemove; pCurrentNode = pCurrentNode->m_Next)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
if (pCurrentNode == m_Head)
|
||||
{
|
||||
m_Head = m_Head->m_Next;
|
||||
}
|
||||
else
|
||||
{
|
||||
pCurrentNode->m_Prev->m_Next = pCurrentNode->m_Next;
|
||||
|
||||
if (pCurrentNode->m_Next)
|
||||
{
|
||||
pCurrentNode->m_Next->m_Prev = pCurrentNode->m_Prev;
|
||||
}
|
||||
}
|
||||
|
||||
m_NodeC--;
|
||||
}
|
||||
|
||||
LinkedList::_LL_NODE *LinkedList::RemoveHeadNode()
|
||||
{
|
||||
_LL_NODE *pHeadNode = m_Head;
|
||||
|
||||
if (m_NodeC > 0)
|
||||
{
|
||||
m_Head = m_Head->m_Next;
|
||||
m_NodeC--;
|
||||
}
|
||||
|
||||
return pHeadNode;
|
||||
}
|
||||
|
||||
void LinkedList::ClearList()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
_LL_NODE *pHeadNode = RemoveHeadNode();
|
||||
if (!pHeadNode)
|
||||
{
|
||||
break;
|
||||
}
|
||||
delete pHeadNode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
class LinkedList
|
||||
{
|
||||
public:
|
||||
struct _LL_NODE
|
||||
{
|
||||
template <typename T>
|
||||
T *GetDataAs()
|
||||
{
|
||||
return (T *)m_pvData;
|
||||
}
|
||||
|
||||
void *m_pvData;
|
||||
_LL_NODE *m_Next;
|
||||
_LL_NODE *m_Prev;
|
||||
};
|
||||
|
||||
int m_NodeC;
|
||||
_LL_NODE *m_Head;
|
||||
_LL_NODE *m_Tail;
|
||||
|
||||
LinkedList();
|
||||
void AddToHead(void *pvData);
|
||||
void AddToTail(void *pvData);
|
||||
void RemoveNode(_LL_NODE *pNodeToRemove);
|
||||
_LL_NODE *RemoveHeadNode();
|
||||
void ClearList();
|
||||
};
|
||||
Reference in new issue
Block a user