forked from Mirrors/openclonk
Replace Joystick controls with SDL GameController
parent
9c840724f2
commit
bd3f020068
|
@ -305,7 +305,7 @@ endif()
|
|||
# SDL
|
||||
if(USE_SDL_MAINLOOP)
|
||||
find_package(SDL2 REQUIRED)
|
||||
elseif(NOT WIN32)
|
||||
else()
|
||||
# for gamepads
|
||||
find_package(SDL2)
|
||||
endif()
|
||||
|
@ -911,8 +911,6 @@ elseif(USE_WIN32_WINDOWS)
|
|||
list(APPEND OC_GUI_SOURCES
|
||||
src/editor/C4ConsoleWin32.cpp
|
||||
src/platform/C4WindowWin32.cpp
|
||||
src/platform/StdJoystick.cpp
|
||||
src/platform/StdJoystick.h
|
||||
)
|
||||
elseif(USE_COCOA)
|
||||
list(APPEND OC_GUI_SOURCES
|
||||
|
|
|
@ -162,11 +162,9 @@ void C4AbstractApp::HandleSDLEvent(SDL_Event& e)
|
|||
SDL_GetMouseState(&x, &y);
|
||||
C4GUI::MouseMove(C4MC_Button_Wheel, x, y, flags, NULL);
|
||||
break;
|
||||
case SDL_JOYAXISMOTION:
|
||||
case SDL_JOYHATMOTION:
|
||||
case SDL_JOYBALLMOTION:
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
case SDL_JOYBUTTONUP:
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
Application.pGamePadControl->FeedEvent(e);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -32,148 +32,7 @@ void C4GamePadControl::DoAxisInput()
|
|||
Execute(true);
|
||||
}
|
||||
|
||||
#ifdef USE_WIN32_WINDOWS
|
||||
|
||||
C4GamePadControl *C4GamePadControl::pInstance = NULL;
|
||||
|
||||
C4GamePadControl::C4GamePadControl()
|
||||
{
|
||||
for (int i=0; i<CStdGamepad_MaxGamePad; ++i)
|
||||
{
|
||||
Gamepads[i].pGamepad = NULL;
|
||||
Gamepads[i].iRefCount = 0;
|
||||
}
|
||||
iNumGamepads = 0;
|
||||
// singleton
|
||||
if (!pInstance) pInstance = this;
|
||||
}
|
||||
|
||||
C4GamePadControl::~C4GamePadControl()
|
||||
{
|
||||
if (pInstance == this) pInstance = NULL;
|
||||
Clear();
|
||||
}
|
||||
|
||||
void C4GamePadControl::Clear()
|
||||
{
|
||||
for (int i=0; i<CStdGamepad_MaxGamePad; ++i)
|
||||
while (Gamepads[i].iRefCount) CloseGamepad(i);
|
||||
}
|
||||
|
||||
void C4GamePadControl::OpenGamepad(int id)
|
||||
{
|
||||
if (!Inside(id, 0, CStdGamepad_MaxGamePad-1)) return;
|
||||
// add gamepad ref
|
||||
if (!(Gamepads[id].iRefCount++))
|
||||
{
|
||||
// this is the first gamepad opening: Init it
|
||||
Pad &rPad = Gamepads[id];
|
||||
rPad.pGamepad = new CStdGamePad(id);
|
||||
rPad.Buttons= 0;
|
||||
for (int i=0; i< CStdGamepad_MaxAxis; ++i)
|
||||
{
|
||||
rPad.AxisPosis[i] = CStdGamePad::Mid;
|
||||
rPad.AxisStrengths[i] = 0;
|
||||
}
|
||||
rPad.pGamepad->SetCalibration(&(Config.Gamepads[id].AxisMin[0]), &(Config.Gamepads[id].AxisMax[0]), &(Config.Gamepads[id].AxisCalibrated[0]));
|
||||
++iNumGamepads;
|
||||
}
|
||||
}
|
||||
|
||||
void C4GamePadControl::CloseGamepad(int id)
|
||||
{
|
||||
if (!Inside(id, 0, CStdGamepad_MaxGamePad-1)) return;
|
||||
// del gamepad ref
|
||||
if (!--Gamepads[id].iRefCount)
|
||||
{
|
||||
Gamepads[id].pGamepad->GetCalibration(&(Config.Gamepads[id].AxisMin[0]), &(Config.Gamepads[id].AxisMax[0]), &(Config.Gamepads[id].AxisCalibrated[0]));
|
||||
delete Gamepads[id].pGamepad; Gamepads[id].pGamepad = NULL;
|
||||
--iNumGamepads;
|
||||
}
|
||||
}
|
||||
|
||||
int C4GamePadControl::GetGamePadCount()
|
||||
{
|
||||
JOYINFOEX joy;
|
||||
ZeroMem(&joy, sizeof(JOYINFOEX)); joy.dwSize = sizeof(JOYINFOEX); joy.dwFlags = JOY_RETURNALL;
|
||||
int iCnt=0;
|
||||
while (iCnt<CStdGamepad_MaxGamePad && ::joyGetPosEx(iCnt, &joy) == JOYERR_NOERROR) ++iCnt;
|
||||
return iCnt;
|
||||
}
|
||||
|
||||
const int MaxGamePadButton=10;
|
||||
|
||||
void C4GamePadControl::Execute(bool send_axis_strength_changes)
|
||||
{
|
||||
// Get gamepad inputs
|
||||
int iNum = iNumGamepads;
|
||||
for (int idGamepad=0; iNum && idGamepad<CStdGamepad_MaxGamePad; ++idGamepad)
|
||||
{
|
||||
Pad &rPad = Gamepads[idGamepad];
|
||||
if (!rPad.iRefCount) continue;
|
||||
--iNum;
|
||||
if (!rPad.pGamepad->Update()) continue;
|
||||
for (int iAxis = 0; iAxis < CStdGamepad_MaxAxis; ++iAxis)
|
||||
{
|
||||
int32_t iStrength = 100;
|
||||
CStdGamePad::AxisPos eAxisPos = rPad.pGamepad->GetAxisPos(iAxis, &iStrength), ePrevAxisPos = rPad.AxisPosis[iAxis];
|
||||
int32_t iPrevStrength = rPad.AxisStrengths[iAxis];
|
||||
// Evaluate changes and pass single controls
|
||||
// this is a generic Gamepad-control: Create events
|
||||
if (eAxisPos != ePrevAxisPos || (send_axis_strength_changes && Abs(iPrevStrength-iStrength) > AxisStrengthChangeThreshold))
|
||||
{
|
||||
rPad.AxisPosis[iAxis] = eAxisPos;
|
||||
rPad.AxisStrengths[iAxis] = iStrength;
|
||||
if (ePrevAxisPos != CStdGamePad::Mid && eAxisPos != ePrevAxisPos)
|
||||
Game.DoKeyboardInput(KEY_Gamepad(idGamepad, KEY_JOY_Axis(iAxis, (ePrevAxisPos==CStdGamePad::High))), KEYEV_Up, false, false, false, false);
|
||||
// it's tempting to send fRepeated here for eAxisPos == ePrevAxisPos, but it would cause the key to be ignored for sync controls
|
||||
// might improve the check in sync controls so they accept repeated keys if strength is updated?
|
||||
if (eAxisPos != CStdGamePad::Mid)
|
||||
Game.DoKeyboardInput(KEY_Gamepad(idGamepad, KEY_JOY_Axis(iAxis, (eAxisPos==CStdGamePad::High))), KEYEV_Down, false, false, false, false, NULL, false, iStrength);
|
||||
}
|
||||
}
|
||||
uint32_t Buttons = rPad.pGamepad->GetButtons();
|
||||
uint32_t PrevButtons = rPad.Buttons;
|
||||
if (Buttons != PrevButtons)
|
||||
{
|
||||
rPad.Buttons = Buttons;
|
||||
for (int iButton = 0; iButton < MaxGamePadButton; ++iButton)
|
||||
if ((Buttons & (1 << iButton)) != (PrevButtons & (1 << iButton)))
|
||||
{
|
||||
bool fRelease = ((Buttons & (1 << iButton)) == 0);
|
||||
Game.DoKeyboardInput(KEY_Gamepad(idGamepad, KEY_JOY_Button(iButton)), fRelease ? KEYEV_Up : KEYEV_Down, false, false, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool C4GamePadControl::AnyButtonDown()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
C4GamePadOpener::C4GamePadOpener(int iGamepad)
|
||||
{
|
||||
assert(C4GamePadControl::pInstance);
|
||||
this->iGamePad = iGamepad;
|
||||
C4GamePadControl::pInstance->OpenGamepad(iGamePad);
|
||||
}
|
||||
|
||||
C4GamePadOpener::~C4GamePadOpener()
|
||||
{
|
||||
if (C4GamePadControl::pInstance)
|
||||
C4GamePadControl::pInstance->CloseGamepad(iGamePad);
|
||||
}
|
||||
|
||||
void C4GamePadOpener::SetGamePad(int iNewGamePad)
|
||||
{
|
||||
if (iNewGamePad == iGamePad) return;
|
||||
assert(C4GamePadControl::pInstance);
|
||||
C4GamePadControl::pInstance->CloseGamepad(iGamePad);
|
||||
C4GamePadControl::pInstance->OpenGamepad(iGamePad = iNewGamePad);
|
||||
}
|
||||
|
||||
#elif defined(HAVE_SDL) && !defined(USE_CONSOLE)
|
||||
#if defined(HAVE_SDL) && !defined(USE_CONSOLE)
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
|
@ -184,16 +43,15 @@ bool C4GamePadControl::AnyButtonDown()
|
|||
|
||||
C4GamePadControl::C4GamePadControl()
|
||||
{
|
||||
// FIXME: Port to SDL_INIT_GAMECONTROLLER
|
||||
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_EVENTS) != 0)
|
||||
LogF("SDL_InitSubSystem(SDL_INIT_JOYSTICK): %s", SDL_GetError());
|
||||
SDL_JoystickEventState(SDL_ENABLE);
|
||||
if (!SDL_NumJoysticks()) Log("No Gamepad found");
|
||||
if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS) != 0)
|
||||
LogF("SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER): %s", SDL_GetError());
|
||||
SDL_GameControllerEventState(SDL_ENABLE);
|
||||
if (!GetGamePadCount()) Log("No Gamepad found");
|
||||
}
|
||||
|
||||
C4GamePadControl::~C4GamePadControl()
|
||||
{
|
||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_EVENTS);
|
||||
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS);
|
||||
}
|
||||
|
||||
void C4GamePadControl::Execute(bool)
|
||||
|
@ -204,11 +62,9 @@ void C4GamePadControl::Execute(bool)
|
|||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_JOYAXISMOTION:
|
||||
case SDL_JOYBALLMOTION:
|
||||
case SDL_JOYHATMOTION:
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
case SDL_JOYBUTTONUP:
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
FeedEvent(event);
|
||||
break;
|
||||
}
|
||||
|
@ -234,55 +90,18 @@ void C4GamePadControl::FeedEvent(SDL_Event& event)
|
|||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_JOYHATMOTION:
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
{
|
||||
SDL_Event fakeX;
|
||||
fakeX.jaxis.type = SDL_JOYAXISMOTION;
|
||||
fakeX.jaxis.which = event.jhat.which;
|
||||
fakeX.jaxis.axis = event.jhat.hat * 2 + 6; /* *magic*number* */
|
||||
fakeX.jaxis.value = 0;
|
||||
SDL_Event fakeY = fakeX;
|
||||
fakeY.jaxis.axis += 1;
|
||||
switch (event.jhat.value)
|
||||
{
|
||||
case SDL_HAT_LEFTUP: fakeX.jaxis.value = amplify(-1); fakeY.jaxis.value = amplify(-1); break;
|
||||
case SDL_HAT_LEFT: fakeX.jaxis.value = amplify(-1); break;
|
||||
case SDL_HAT_LEFTDOWN: fakeX.jaxis.value = amplify(-1); fakeY.jaxis.value = amplify(+1); break;
|
||||
case SDL_HAT_UP: fakeY.jaxis.value = amplify(-1); break;
|
||||
case SDL_HAT_DOWN: fakeY.jaxis.value = amplify(+1); break;
|
||||
case SDL_HAT_RIGHTUP: fakeX.jaxis.value = amplify(+1); fakeY.jaxis.value = amplify(-1); break;
|
||||
case SDL_HAT_RIGHT: fakeX.jaxis.value = amplify(+1); break;
|
||||
case SDL_HAT_RIGHTDOWN: fakeX.jaxis.value = amplify(+1); fakeY.jaxis.value = amplify(+1); break;
|
||||
}
|
||||
FeedEvent(fakeX);
|
||||
FeedEvent(fakeY);
|
||||
return;
|
||||
}
|
||||
case SDL_JOYBALLMOTION:
|
||||
{
|
||||
SDL_Event fake;
|
||||
fake.jaxis.type = SDL_JOYAXISMOTION;
|
||||
fake.jaxis.which = event.jball.which;
|
||||
fake.jaxis.axis = event.jball.ball * 2 + 12; /* *magic*number* */
|
||||
fake.jaxis.value = amplify(event.jball.xrel);
|
||||
FeedEvent(event);
|
||||
fake.jaxis.axis += 1;
|
||||
fake.jaxis.value = amplify(event.jball.yrel);
|
||||
FeedEvent(event);
|
||||
return;
|
||||
}
|
||||
case SDL_JOYAXISMOTION:
|
||||
{
|
||||
C4KeyCode minCode = KEY_Gamepad(event.jaxis.which, KEY_JOY_Axis(event.jaxis.axis, false));
|
||||
C4KeyCode maxCode = KEY_Gamepad(event.jaxis.which, KEY_JOY_Axis(event.jaxis.axis, true));
|
||||
C4KeyCode minCode = KEY_Gamepad(event.caxis.which, KEY_JOY_Axis(event.caxis.axis, false));
|
||||
C4KeyCode maxCode = KEY_Gamepad(event.caxis.which, KEY_JOY_Axis(event.caxis.axis, true));
|
||||
|
||||
// FIXME: This assumes that the axis really rests around (0, 0) if it is not used, which is not always true.
|
||||
if (event.jaxis.value < -deadZone)
|
||||
if (event.caxis.value < -deadZone)
|
||||
{
|
||||
if (PressedAxis.count(minCode) == 0)
|
||||
{
|
||||
Game.DoKeyboardInput(
|
||||
KEY_Gamepad(event.jaxis.which, minCode),
|
||||
KEY_Gamepad(event.caxis.which, minCode),
|
||||
KEYEV_Down, false, false, false, false);
|
||||
PressedAxis.insert(minCode);
|
||||
}
|
||||
|
@ -292,17 +111,17 @@ void C4GamePadControl::FeedEvent(SDL_Event& event)
|
|||
if (PressedAxis.count(minCode) != 0)
|
||||
{
|
||||
Game.DoKeyboardInput(
|
||||
KEY_Gamepad(event.jaxis.which, minCode),
|
||||
KEY_Gamepad(event.caxis.which, minCode),
|
||||
KEYEV_Up, false, false, false, false);
|
||||
PressedAxis.erase(minCode);
|
||||
}
|
||||
}
|
||||
if (event.jaxis.value > +deadZone)
|
||||
if (event.caxis.value > +deadZone)
|
||||
{
|
||||
if (PressedAxis.count(maxCode) == 0)
|
||||
{
|
||||
Game.DoKeyboardInput(
|
||||
KEY_Gamepad(event.jaxis.which, maxCode),
|
||||
KEY_Gamepad(event.caxis.which, maxCode),
|
||||
KEYEV_Down, false, false, false, false);
|
||||
PressedAxis.insert(maxCode);
|
||||
}
|
||||
|
@ -312,21 +131,21 @@ void C4GamePadControl::FeedEvent(SDL_Event& event)
|
|||
if (PressedAxis.count(maxCode) != 0)
|
||||
{
|
||||
Game.DoKeyboardInput(
|
||||
KEY_Gamepad(event.jaxis.which, maxCode),
|
||||
KEY_Gamepad(event.caxis.which, maxCode),
|
||||
KEYEV_Up, false, false, false, false);
|
||||
PressedAxis.erase(maxCode);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
Game.DoKeyboardInput(
|
||||
KEY_Gamepad(event.jbutton.which, KEY_JOY_Button(event.jbutton.button)),
|
||||
KEY_Gamepad(event.cbutton.which, KEY_JOY_Button(event.cbutton.button)),
|
||||
KEYEV_Down, false, false, false, false);
|
||||
break;
|
||||
case SDL_JOYBUTTONUP:
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
Game.DoKeyboardInput(
|
||||
KEY_Gamepad(event.jbutton.which, KEY_JOY_Button(event.jbutton.button)),
|
||||
KEY_Gamepad(event.cbutton.which, KEY_JOY_Button(event.cbutton.button)),
|
||||
KEYEV_Up, false, false, false, false);
|
||||
break;
|
||||
}
|
||||
|
@ -334,27 +153,37 @@ void C4GamePadControl::FeedEvent(SDL_Event& event)
|
|||
|
||||
int C4GamePadControl::GetGamePadCount()
|
||||
{
|
||||
return(SDL_NumJoysticks());
|
||||
// Not all Joysticks are game controllers.
|
||||
int count = 0;
|
||||
for (int i = 0; i < SDL_NumJoysticks(); i++)
|
||||
if (SDL_IsGameController(i))
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
C4GamePadOpener::C4GamePadOpener(int iGamepad)
|
||||
{
|
||||
Joy = SDL_JoystickOpen(iGamepad);
|
||||
if (!Joy) LogF("SDL: %s", SDL_GetError());
|
||||
int n = iGamepad;
|
||||
for (int i = 0; i < SDL_NumJoysticks(); i++)
|
||||
if (SDL_IsGameController(i) && n-- == 0)
|
||||
{
|
||||
controller = SDL_GameControllerOpen(i);
|
||||
if (!controller) LogF("SDL: %s", SDL_GetError());
|
||||
break;
|
||||
}
|
||||
|
||||
if (!controller) LogF("Gamepad %d not available", iGamepad);
|
||||
}
|
||||
|
||||
C4GamePadOpener::~C4GamePadOpener()
|
||||
{
|
||||
if (Joy) SDL_JoystickClose(Joy);
|
||||
if (controller) SDL_GameControllerClose(controller);
|
||||
}
|
||||
|
||||
void C4GamePadOpener::SetGamePad(int iGamepad)
|
||||
{
|
||||
if (Joy)
|
||||
SDL_JoystickClose(Joy);
|
||||
Joy = SDL_JoystickOpen(iGamepad);
|
||||
if (!Joy)
|
||||
LogF("SDL: %s", SDL_GetError());
|
||||
// TODO: why do we need this?
|
||||
LogF("SetGamePad: Not implemented yet");
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -371,4 +200,4 @@ C4GamePadOpener::C4GamePadOpener(int iGamepad) { }
|
|||
C4GamePadOpener::~C4GamePadOpener() {}
|
||||
void C4GamePadOpener::SetGamePad(int iGamepad) { }
|
||||
|
||||
#endif //_WIN32
|
||||
#endif
|
||||
|
|
|
@ -20,43 +20,20 @@
|
|||
#ifndef INC_C4GamePadCon
|
||||
#define INC_C4GamePadCon
|
||||
|
||||
#ifdef USE_WIN32_WINDOWS
|
||||
#include <StdJoystick.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SDL
|
||||
#include <C4KeyboardInput.h>
|
||||
#include <set>
|
||||
#endif
|
||||
|
||||
struct _SDL_Joystick;
|
||||
typedef struct _SDL_Joystick SDL_Joystick;
|
||||
struct _SDL_GameController;
|
||||
typedef struct _SDL_GameController SDL_GameController;
|
||||
|
||||
union SDL_Event;
|
||||
typedef union SDL_Event SDL_Event;
|
||||
|
||||
class C4GamePadControl
|
||||
{
|
||||
#ifdef USE_WIN32_WINDOWS
|
||||
private:
|
||||
struct Pad
|
||||
{
|
||||
CStdGamePad *pGamepad;
|
||||
int iRefCount;
|
||||
uint32_t Buttons;
|
||||
CStdGamePad::AxisPos AxisPosis[CStdGamepad_MaxAxis];
|
||||
int32_t AxisStrengths[CStdGamepad_MaxAxis];
|
||||
};
|
||||
Pad Gamepads[CStdGamepad_MaxGamePad];
|
||||
int iNumGamepads;
|
||||
|
||||
enum { AxisStrengthChangeThreshold = 2 }; // if axis strength change > this value, a new control is issued
|
||||
|
||||
public:
|
||||
void OpenGamepad(int id); // add gamepad ref
|
||||
void CloseGamepad(int id); // del gamepad ref
|
||||
static C4GamePadControl *pInstance; // singleton
|
||||
#elif defined(HAVE_SDL)
|
||||
#ifdef HAVE_SDL
|
||||
public:
|
||||
void FeedEvent(SDL_Event& e);
|
||||
private:
|
||||
|
@ -74,16 +51,12 @@ public:
|
|||
|
||||
class C4GamePadOpener
|
||||
{
|
||||
#ifdef USE_WIN32_WINDOWS
|
||||
int iGamePad;
|
||||
int GetGamePadIndex() const { return iGamePad; }
|
||||
#endif
|
||||
public:
|
||||
C4GamePadOpener(int iGamePad);
|
||||
~C4GamePadOpener();
|
||||
void SetGamePad(int iNewGamePad);
|
||||
#ifdef HAVE_SDL
|
||||
SDL_Joystick *Joy;
|
||||
SDL_GameController *controller;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -1,135 +0,0 @@
|
|||
/*
|
||||
* OpenClonk, http://www.openclonk.org
|
||||
*
|
||||
* Copyright (c) 1998-2000, Matthes Bender
|
||||
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
|
||||
* Copyright (c) 2010-2013, The OpenClonk Team and contributors
|
||||
*
|
||||
* Distributed under the terms of the ISC license; see accompanying file
|
||||
* "COPYING" for details.
|
||||
*
|
||||
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
|
||||
* See accompanying file "TRADEMARK" for details.
|
||||
*
|
||||
* To redistribute this file separately, substitute the full license texts
|
||||
* for the above references.
|
||||
*/
|
||||
|
||||
/* Simple joystick handling with DirectInput 1 */
|
||||
|
||||
#include "C4Include.h"
|
||||
#include <StdJoystick.h>
|
||||
|
||||
#include <C4windowswrapper.h>
|
||||
#include <windowsx.h>
|
||||
|
||||
uint32_t POV2Position(DWORD dwPOV, bool fVertical)
|
||||
{
|
||||
// POV value is a 360° angle multiplied by 100
|
||||
double dAxis;
|
||||
// Centered
|
||||
if (dwPOV == JOY_POVCENTERED)
|
||||
dAxis = 0.0;
|
||||
// Angle: convert to linear value -100 to +100
|
||||
else
|
||||
dAxis = (fVertical ? -cos((dwPOV/100) * M_PI / 180.0) : sin((dwPOV/100) * M_PI / 180.0)) * 100.0;
|
||||
// Gamepad configuration wants unsigned and gets 0 to 200
|
||||
return (uint32_t) (dAxis + 100.0);
|
||||
}
|
||||
|
||||
CStdGamePad::CStdGamePad(int id) : id(id)
|
||||
{
|
||||
ResetCalibration();
|
||||
}
|
||||
|
||||
void CStdGamePad::ResetCalibration()
|
||||
{
|
||||
// no calibration yet
|
||||
for (int i=0; i<CStdGamepad_MaxCalAxis; ++i)
|
||||
{
|
||||
fAxisCalibrated[i]=false;
|
||||
}
|
||||
}
|
||||
|
||||
void CStdGamePad::SetCalibration(uint32_t *pdwAxisMin, uint32_t *pdwAxisMax, bool *pfAxisCalibrated)
|
||||
{
|
||||
// params to calibration
|
||||
for (int i=0; i<CStdGamepad_MaxCalAxis; ++i)
|
||||
{
|
||||
dwAxisMin[i] = pdwAxisMin[i];
|
||||
dwAxisMax[i] = pdwAxisMax[i];
|
||||
fAxisCalibrated[i] = pfAxisCalibrated[i];
|
||||
}
|
||||
}
|
||||
|
||||
void CStdGamePad::GetCalibration(uint32_t *pdwAxisMin, uint32_t *pdwAxisMax, bool *pfAxisCalibrated)
|
||||
{
|
||||
// calibration to params
|
||||
for (int i=0; i<CStdGamepad_MaxCalAxis; ++i)
|
||||
{
|
||||
pdwAxisMin[i] = dwAxisMin[i];
|
||||
pdwAxisMax[i] = dwAxisMax[i];
|
||||
pfAxisCalibrated[i] = fAxisCalibrated[i];
|
||||
}
|
||||
}
|
||||
|
||||
bool CStdGamePad::Update()
|
||||
{
|
||||
joynfo.dwSize=sizeof(joynfo);
|
||||
joynfo.dwFlags=JOY_RETURNBUTTONS | JOY_RETURNRAWDATA | JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | JOY_RETURNR | JOY_RETURNU | JOY_RETURNV | JOY_RETURNPOV;
|
||||
return joyGetPosEx(JOYSTICKID1+id,&joynfo) == JOYERR_NOERROR;
|
||||
}
|
||||
|
||||
uint32_t CStdGamePad::GetButtons()
|
||||
{
|
||||
return joynfo.dwButtons;
|
||||
}
|
||||
|
||||
CStdGamePad::AxisPos CStdGamePad::GetAxisPos(int idAxis, int32_t *out_strength)
|
||||
{
|
||||
if (out_strength) *out_strength = 0; // default no strength
|
||||
if (idAxis<0 || idAxis>=CStdGamepad_MaxAxis) return Mid; // wrong axis
|
||||
// get raw axis data
|
||||
if (idAxis<CStdGamepad_MaxCalAxis)
|
||||
{
|
||||
uint32_t dwPos = (&joynfo.dwXpos)[idAxis];
|
||||
// evaluate axis calibration
|
||||
if (fAxisCalibrated[idAxis])
|
||||
{
|
||||
// update it
|
||||
dwAxisMin[idAxis] = std::min(dwAxisMin[idAxis], dwPos);
|
||||
dwAxisMax[idAxis] = std::max(dwAxisMax[idAxis], dwPos);
|
||||
// Calculate center
|
||||
DWORD dwCenter = (dwAxisMin[idAxis] + dwAxisMax[idAxis]) / 2;
|
||||
// Axis strength
|
||||
DWORD dwRange = (dwAxisMax[idAxis] - dwCenter);
|
||||
// Trigger range is 20% off center
|
||||
DWORD dwThresh = dwRange / 5;
|
||||
if (dwPos < dwCenter - dwThresh)
|
||||
{
|
||||
if (out_strength && dwRange) *out_strength = (dwCenter-dwPos)*100/dwRange;
|
||||
return Low;
|
||||
}
|
||||
if (dwPos > dwCenter + dwThresh)
|
||||
{
|
||||
if (out_strength && dwRange) *out_strength = (dwPos-dwCenter)*100/dwRange;
|
||||
return High;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// init it
|
||||
dwAxisMin[idAxis] = dwAxisMax[idAxis] = dwPos;
|
||||
fAxisCalibrated[idAxis] = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's a POV head
|
||||
DWORD dwPos = POV2Position(joynfo.dwPOV, idAxis==PAD_Axis_POVy);
|
||||
if (out_strength) *out_strength = Abs(int32_t(dwPos) - 100);
|
||||
if (dwPos > 130) return High; else if (dwPos < 70) return Low;
|
||||
}
|
||||
return Mid;
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* OpenClonk, http://www.openclonk.org
|
||||
*
|
||||
* Copyright (c) 1998-2000, Matthes Bender
|
||||
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
|
||||
* Copyright (c) 2009-2013, The OpenClonk Team and contributors
|
||||
*
|
||||
* Distributed under the terms of the ISC license; see accompanying file
|
||||
* "COPYING" for details.
|
||||
*
|
||||
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
|
||||
* See accompanying file "TRADEMARK" for details.
|
||||
*
|
||||
* To redistribute this file separately, substitute the full license texts
|
||||
* for the above references.
|
||||
*/
|
||||
|
||||
/* Simple joystick handling with DirectInput 1 */
|
||||
|
||||
#ifndef INC_StdJoystick
|
||||
#define INC_StdJoystick
|
||||
|
||||
#include <C4windowswrapper.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
const int32_t PAD_Axis_POVx = 6;
|
||||
const int32_t PAD_Axis_POVy = 7; // virtual axises of the coolie hat
|
||||
|
||||
const int CStdGamepad_MaxGamePad = 15, // maximum number of supported gamepads
|
||||
CStdGamepad_MaxCalAxis = 6, // maximum number of calibrated axises
|
||||
CStdGamepad_MaxAxis = 8; // number of axises plus coolie hat axises
|
||||
|
||||
class CStdGamePad
|
||||
{
|
||||
public:
|
||||
enum AxisPos { Low, Mid, High, }; // quantized axis positions
|
||||
private:
|
||||
int id; // gamepad number
|
||||
JOYINFOEX joynfo; // WIN32 gamepad info
|
||||
|
||||
public:
|
||||
uint32_t dwAxisMin[CStdGamepad_MaxCalAxis], dwAxisMax[CStdGamepad_MaxCalAxis]; // axis ranges - auto calibrated
|
||||
bool fAxisCalibrated[CStdGamepad_MaxCalAxis]; // set if an initial value for axis borders has been determined already
|
||||
|
||||
CStdGamePad(int id); // ctor
|
||||
|
||||
void ResetCalibration(); // resets axis min and max
|
||||
void SetCalibration(uint32_t *pdwAxisMin, uint32_t *pdwAxisMax, bool *pfAxisCalibrated);
|
||||
void GetCalibration(uint32_t *pdwAxisMin, uint32_t *pdwAxisMax, bool *pfAxisCalibrated);
|
||||
|
||||
bool Update(); // read current gamepad data
|
||||
uint32_t GetButtons(); // returns bitmask of pressed buttons for last retrieved info
|
||||
AxisPos GetAxisPos(int idAxis, int32_t *out_strength=NULL); // return axis extension - mid for error or center position
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue