1/*
2 * LegacyClonk
3 *
4 * Copyright (c) 1998-2000, Matthes Bender (RedWolf Design)
5 * Copyright (c) 2017-2020, The LegacyClonk Team and contributors
6 *
7 * Distributed under the terms of the ISC license; see accompanying file
8 * "COPYING" for details.
9 *
10 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11 * See accompanying file "TRADEMARK" for details.
12 *
13 * To redistribute this file separately, substitute the full license texts
14 * for the above references.
15 */
16
17/* Gamepad control - forwards gamepad events of opened gamepads to Game.KeyboardInput */
18
19#pragma once
20
21#ifdef _WIN32
22#include "C4Windows.h"
23#include <mmsystem.h>
24
25#include <array>
26#include <cinttypes>
27#endif
28
29#ifdef USE_SDL_FOR_GAMEPAD
30#include <C4KeyboardInput.h>
31#include <StdSdlSubSystem.h>
32#include <optional>
33#include <set>
34#endif
35
36struct _SDL_Joystick;
37typedef struct _SDL_Joystick SDL_Joystick;
38
39union SDL_Event;
40typedef union SDL_Event SDL_Event;
41
42#ifdef _WIN32
43
44class C4GamePad
45{
46public:
47 enum AxisPos { Low, Mid, High, }; // quantized axis positions
48 enum AxisPOV { X = 6, Y = 7 }; // virtual axises of the coolie hat
49
50 static constexpr int32_t MaxGamePad{15}, // maximum number of supported gamepads
51 MaxCalAxis{6}, // maximum number of calibrated axises
52 MaxAxis {8}; // number of axises plus coolie hat axises
53
54public:
55 C4GamePad(int id);
56 ~C4GamePad();
57
58public:
59 void SetCalibration(uint32_t *pdwAxisMin, uint32_t *pdwAxisMax, bool *pfAxisCalibrated);
60 void GetCalibration(uint32_t *pdwAxisMin, uint32_t *pdwAxisMax, bool *pfAxisCalibrated);
61
62 bool Update(); // read current gamepad data
63 uint32_t GetCurrentButtons(); // returns bitmask of pressed buttons for last retrieved info
64 AxisPos GetAxisPos(int idAxis); // return axis extension - mid for error or center position
65
66 void IncRef();
67 bool DecRef();
68 int32_t GetID() const { return id; }
69
70public:
71 std::array<uint32_t, MaxCalAxis> dwAxisMin;
72 std::array<uint32_t, MaxCalAxis> dwAxisMax; // axis ranges - auto calibrated
73 std::array<bool, MaxCalAxis> fAxisCalibrated; // set if an initial value for axis borders has been determined already
74 std::array<AxisPos, MaxAxis> AxisPosis;
75
76 int iRefCount;
77 uint32_t Buttons;
78
79private:
80 int id; // gamepad number
81 JOYINFOEX joynfo; // WIN32 gamepad info
82};
83#endif
84
85class C4GamePadControl
86{
87#ifdef _WIN32
88
89private:
90 std::array<C4GamePad *, C4GamePad::MaxGamePad> Gamepads{};
91 int iNumGamepads;
92
93public:
94 void OpenGamepad(int id); // add gamepad ref
95 void CloseGamepad(int id); // del gamepad ref
96 static C4GamePadControl *pInstance; // singleton
97
98#elif defined(USE_SDL_FOR_GAMEPAD)
99
100public:
101 void FeedEvent(SDL_Event &e);
102
103private:
104 std::optional<StdSdlSubSystem> sdlJoystickSubSys;
105 std::set<C4KeyCode> PressedAxis;
106
107#endif
108
109public:
110 C4GamePadControl();
111 ~C4GamePadControl();
112 void Clear();
113 int GetGamePadCount();
114 void Execute();
115};
116
117class C4GamePadOpener
118{
119#ifdef _WIN32
120 int iGamePad;
121#endif
122
123public:
124 C4GamePadOpener(int iGamePad);
125 ~C4GamePadOpener();
126 void SetGamePad(int iNewGamePad);
127#ifdef USE_SDL_FOR_GAMEPAD
128 SDL_Joystick *Joy;
129#endif
130};
131