Browse Source

Controller support, Camera Quaternion

Thomas Buck 10 years ago
parent
commit
a2bed57177
12 changed files with 282 additions and 120 deletions
  1. 5
    0
      ChangeLog.md
  2. 10
    5
      include/Camera.h
  3. 4
    2
      include/Game.h
  4. 3
    1
      include/RunTime.h
  5. 2
    0
      include/UI.h
  6. 8
    0
      include/global.h
  7. 1
    0
      include/system/WindowSDL.h
  8. 110
    103
      src/Camera.cpp
  9. 29
    2
      src/Game.cpp
  10. 7
    2
      src/RunTime.cpp
  11. 8
    0
      src/UI.cpp
  12. 95
    5
      src/system/WindowSDL.cpp

+ 5
- 0
ChangeLog.md View File

@@ -2,6 +2,11 @@
2 2
 
3 3
 ## OpenRaider (0.1.3) xythobuz <xythobuz@xythobuz.de>
4 4
 
5
+    [ 20141227 ]
6
+    * Added rudimentary SDL2 Game Controller support.
7
+    * Camera now using Quaternion for rotation.
8
+    * Movement now done using speed and frame time delta.
9
+
5 10
     [ 20141223 ]
6 11
     * View frustum calculation now working
7 12
 

+ 10
- 5
include/Camera.h View File

@@ -11,6 +11,7 @@
11 11
 #include <glm/vec2.hpp>
12 12
 #include <glm/vec3.hpp>
13 13
 #include <glm/mat4x4.hpp>
14
+#include <glm/gtc/quaternion.hpp>
14 15
 
15 16
 #include "RoomData.h"
16 17
 
@@ -18,15 +19,17 @@ class Camera {
18 19
   public:
19 20
 
20 21
     static void reset();
22
+    static bool update();
21 23
 
22 24
     static void handleAction(ActionEvents action, bool isFinished);
23 25
     static void handleMouseMotion(int x, int y);
24
-    static bool update();
26
+    static void handleControllerAxis(float value, KeyboardButton axis);
27
+    static void handleControllerButton(KeyboardButton button, bool released);
25 28
 
26 29
     static void setPosition(glm::vec3 p) { pos = p; }
27 30
     static glm::vec3 getPosition() { return pos; }
28 31
 
29
-    static glm::vec2 getRotation() { return rot; }
32
+    static glm::vec2 getRotation();
30 33
     static glm::mat4 getProjectionMatrix() { return projection; }
31 34
     static glm::mat4 getViewMatrix() { return view; }
32 35
 
@@ -43,10 +46,12 @@ class Camera {
43 46
     static void displayFrustum(glm::mat4 MVP);
44 47
 
45 48
   private:
49
+    static void calculateFrustumPlanes();
50
+
46 51
     static glm::vec3 pos;
47
-    static glm::vec2 rot;
48
-    static glm::vec3 lastPos;
49
-    static glm::vec2 lastRot;
52
+    static glm::quat quaternion;
53
+    static glm::vec3 posSpeed;
54
+    static glm::vec2 rotSpeed;
50 55
     static glm::vec2 lastSize;
51 56
     static glm::mat4 projection;
52 57
     static glm::mat4 view;

+ 4
- 2
include/Game.h View File

@@ -15,7 +15,6 @@
15 15
 
16 16
 class Game {
17 17
   public:
18
-
19 18
     Game();
20 19
     ~Game();
21 20
 
@@ -30,12 +29,13 @@ class Game {
30 29
     void display();
31 30
     void handleAction(ActionEvents action, bool isFinished);
32 31
     void handleMouseMotion(int xrel, int yrel, int xabs, int yabs);
32
+    void handleControllerAxis(float value, KeyboardButton axis);
33
+    void handleControllerButton(KeyboardButton button, bool released);
33 34
 
34 35
     Entity& getLara();
35 36
     void setLara(long lara);
36 37
 
37 38
   private:
38
-
39 39
     void processPakSounds();
40 40
     void processTextures();
41 41
     void processSprites();
@@ -48,6 +48,8 @@ class Game {
48 48
     bool mLoaded;
49 49
 
50 50
     long mLara;
51
+
52
+    bool activeEvents[ActionEventCount];
51 53
 };
52 54
 
53 55
 Game& getGame();

+ 3
- 1
include/RunTime.h View File

@@ -41,6 +41,8 @@ class RunTime {
41 41
     unsigned long getFPS();
42 42
     const std::vector<float>& getHistoryFPS();
43 43
 
44
+    float getLastFrameTime();
45
+
44 46
   private:
45 47
     std::string baseDir;
46 48
     std::string pakDir;
@@ -51,7 +53,7 @@ class RunTime {
51 53
     bool gameIsRunning;
52 54
     bool showFPS;
53 55
 
54
-    unsigned long lastTime;
56
+    unsigned long lastTime, lastFrameTime;
55 57
     unsigned long frameCount, frameCount2;
56 58
     unsigned long frameTimeSum, frameTimeSum2;
57 59
     unsigned long fps;

+ 2
- 0
include/UI.h View File

@@ -30,6 +30,8 @@ class UI {
30 30
     static void handleMouseClick(unsigned int x, unsigned int y, KeyboardButton button, bool released);
31 31
     static void handleMouseMotion(int xrel, int yrel, int xabs, int yabs);
32 32
     static void handleMouseScroll(int xrel, int yrel);
33
+    static void handleControllerAxis(float value, KeyboardButton axis);
34
+    static void handleControllerButton(KeyboardButton button, bool released);
33 35
 
34 36
     static void renderImGui(ImDrawList** const draw_lists, int count);
35 37
 

+ 8
- 0
include/global.h View File

@@ -43,6 +43,7 @@ typedef enum {
43 43
 
44 44
 // Keys available for binding
45 45
 typedef enum {
46
+    // Keyboard
46 47
     zeroKey = '0', oneKey = '1', twoKey = '2',
47 48
     threeKey = '3', fourKey = '4', fiveKey = '5',
48 49
     sixKey = '6', sevenKey = '7', eightKey = '8',
@@ -64,6 +65,13 @@ typedef enum {
64 65
     semicolonKey, slashKey, spaceKey, tabKey,
65 66
     leftmouseKey, middlemouseKey, rightmouseKey,
66 67
     fourthmouseKey, fifthmouseKey,
68
+
69
+    // Game Controller
70
+    aButton, bButton, xButton, yButton, backButton, startButton,
71
+    guideButton, leftStick, rightStick, leftShoulder, rightShoulder,
72
+    padUp, padDown, padLeft, padRight,
73
+    leftXAxis, leftYAxis, rightXAxis, rightYAxis, leftTrigger, rightTrigger,
74
+
67 75
     unknownKey // Should always be at the end
68 76
 } KeyboardButton;
69 77
 

+ 1
- 0
include/system/WindowSDL.h View File

@@ -45,6 +45,7 @@ class WindowSDL : public Window {
45 45
   private:
46 46
     SDL_Window* mWindow;      //!< This is the pointer to the SDL surface
47 47
     SDL_GLContext mGLContext; //!< The OpenGL Context
48
+    SDL_GameController* controller;
48 49
 };
49 50
 
50 51
 #endif

+ 110
- 103
src/Camera.cpp View File

@@ -6,9 +6,13 @@
6 6
  * \author xythobuz
7 7
  */
8 8
 
9
+#include <limits>
10
+#include <glm/gtc/epsilon.hpp>
9 11
 #include <glm/gtc/matrix_transform.hpp>
12
+#include <glm/gtx/quaternion.hpp>
10 13
 
11 14
 #include "global.h"
15
+#include "RunTime.h"
12 16
 #include "system/Window.h"
13 17
 #include "Camera.h"
14 18
 
@@ -28,153 +32,160 @@
28 32
 #define FBR 6
29 33
 #define FTR 7
30 34
 
31
-class Plane {
32
-  public:
33
-    Plane() : normal(glm::vec3(0.0f, 0.0f, 0.0f)), d(0.0f) { }
34
-    void set(glm::vec3 v1, glm::vec3 v2, glm::vec3 v3) {
35
-        normal = glm::normalize(glm::cross(v3 - v2, v1 - v2));
36
-        d = -glm::dot(normal, v2);
37
-    }
38
-    float distance(glm::vec3 p) {
39
-        return d + glm::dot(normal, p);
40
-    }
41
-  private:
42
-    glm::vec3 normal;
43
-    float d;
44
-};
45
-
46
-// ----------------------------------------------------------------------------
47
-
48 35
 const static float fov = 45.0f;
49 36
 const static float nearDist = 0.1f;
50 37
 const static float farDist = 75000.0f;
51
-const static float freeCameraStep = 256.0f;
38
+const static float maxSpeed = 2048.0f;
39
+const static float controllerViewFactor = 384.0f;
40
+
41
+const static glm::vec3 rightUnit(1.0f, 0.0f, 0.0f);
42
+const static glm::vec3 upUnit(0.0f, 1.0f, 0.0f);
43
+const static glm::vec3 dirUnit(0.0f, 0.0f, -1.0f);
52 44
 
53 45
 glm::vec3 Camera::pos(0.0f, 0.0f, 0.0f);
54
-glm::vec2 Camera::rot(0.0f, 0.0f);
55
-glm::vec3 Camera::lastPos(1.0f, 0.0f, 0.0f);
56
-glm::vec2 Camera::lastRot(1.0f, 0.0f);
46
+glm::quat Camera::quaternion(glm::vec3(0.0f, 0.0f, 0.0f));
47
+glm::vec3 Camera::posSpeed(0.0f, 0.0f, 0.0f);
48
+glm::vec2 Camera::rotSpeed(0.0f, 0.0f);
57 49
 glm::vec2 Camera::lastSize(0.0f, 0.0f);
58 50
 glm::mat4 Camera::projection(1.0f);
59 51
 glm::mat4 Camera::view(1.0f);
60 52
 float Camera::rotationDeltaX = 0.75f;
61 53
 float Camera::rotationDeltaY = 0.75f;
62 54
 bool Camera::updateViewFrustum = true;
63
-static Plane planes[6];
64
-
65
-static glm::vec3 frustumColors[6] = {
66
-    glm::vec3(1.0f, 0.0f, 0.0f), // NEAR, red
67
-    glm::vec3(0.0f, 1.0f, 0.0f), // FAR, green
68
-    glm::vec3(0.0f, 0.0f, 1.0f), // TOP, blue
69
-    glm::vec3(1.0f, 1.0f, 0.0f), // BOTTOM, yellow
70
-    glm::vec3(0.0f, 1.0f, 1.0f), // LEFT, light-blue
71
-    glm::vec3(1.0f, 0.0f, 1.0f)  // RIGHT, pink
72
-};
73
-static glm::vec3 frustumVertices[8];
74 55
 
75 56
 void Camera::reset() {
76 57
     pos = glm::vec3(0.0f, 0.0f, 0.0f);
77
-    rot = glm::vec2(0.0f, 0.0f);
78
-    lastPos = glm::vec3(1.0f, 0.0f, 0.0f);
79
-    lastRot = glm::vec2(1.0f, 0.0f);
58
+    quaternion = glm::quat(glm::vec3(0.0f, 0.0f, 0.0f));
59
+    posSpeed = glm::vec3(0.0f, 0.0f, 0.0f);
60
+    rotSpeed = glm::vec2(0.0f, 0.0f);
80 61
     lastSize = glm::vec2(0.0f, 0.0f);
81 62
     projection = glm::mat4(1.0f);
82 63
     view = glm::mat4(1.0f);
83 64
 }
84 65
 
85 66
 void Camera::handleAction(ActionEvents action, bool isFinished) {
67
+    float factor = 1.0f;
86 68
     if (isFinished)
87
-        return;
88
-
89
-    glm::vec3 dir(
90
-        glm::cos(rot.y) * glm::sin(rot.x),
91
-        glm::sin(rot.y),
92
-        glm::cos(rot.y) * glm::cos(rot.x)
93
-    );
94
-    glm::vec3 right(
95
-        glm::sin(rot.x - glm::pi<float>() / 2.0f),
96
-        0.0f,
97
-        glm::cos(rot.x - glm::pi<float>() / 2.0f)
98
-    );
99
-    glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
69
+        factor = -1.0f;
100 70
 
101 71
     if (action == forwardAction) {
102
-        pos += dir * freeCameraStep;
72
+        posSpeed += dirUnit * maxSpeed * factor;
103 73
     } else if (action == backwardAction) {
104
-        pos -= dir * freeCameraStep;
74
+        posSpeed -= dirUnit * maxSpeed * factor;
105 75
     } else if (action == leftAction) {
106
-        pos += right * freeCameraStep;
76
+        posSpeed += rightUnit * maxSpeed * factor;
107 77
     } else if (action == rightAction) {
108
-        pos -= right * freeCameraStep;
78
+        posSpeed -= rightUnit * maxSpeed * factor;
109 79
     } else if (action == jumpAction) {
110
-        pos += up * freeCameraStep;
80
+        posSpeed += upUnit * maxSpeed * factor;
111 81
     } else if (action == crouchAction) {
112
-        pos -= up * freeCameraStep;
113
-    } else if (action == useAction) {
114
-    } else if (action == holsterAction) {
115
-    } else if (action == walkAction) {
82
+        posSpeed -= upUnit * maxSpeed * factor;
116 83
     }
117 84
 }
118 85
 
119 86
 void Camera::handleMouseMotion(int x, int y) {
120
-    while (x > 0) {
121
-        rot.x += rotationDeltaX;
122
-        x--;
123
-    }
124
-    while (x < 0) {
125
-        rot.x -= rotationDeltaX;
126
-        x++;
127
-    }
128
-    while (y > 0) {
129
-        if (rot.y > -(glm::pi<float>() / 2.0f)) {
130
-            rot.y -= rotationDeltaY;
131
-        }
132
-        y--;
133
-    }
134
-    while (y < 0) {
135
-        if (rot.y < (glm::pi<float>() / 2.0f)) {
136
-            rot.y += rotationDeltaY;
137
-        }
138
-        y++;
139
-    }
87
+    if (x != 0)
88
+        quaternion = glm::quat(upUnit * rotationDeltaX * float(x)) * quaternion;
140 89
 
141
-    while (rot.x > (glm::pi<float>() * 2.0f))
142
-        rot.x -= glm::pi<float>() * 2.0f;
90
+    if (y != 0)
91
+        quaternion = glm::quat(quaternion * -rightUnit * rotationDeltaY * float(y)) * quaternion;
92
+}
93
+
94
+void Camera::handleControllerAxis(float value, KeyboardButton axis) {
95
+    if (glm::epsilonEqual(value, 0.0f, 0.01f))
96
+        value = 0.0f;
97
+
98
+    if (axis == leftXAxis) {
99
+        posSpeed.x = -maxSpeed * value;
100
+    } else if (axis == leftYAxis) {
101
+        posSpeed.z = maxSpeed * value;
102
+    } else if (axis == rightXAxis) {
103
+        rotSpeed.x = controllerViewFactor * value;
104
+    } else if (axis == rightYAxis) {
105
+        rotSpeed.y = controllerViewFactor * value;
106
+    }
107
+}
143 108
 
144
-    while (rot.x < -(glm::pi<float>() * 2.0f))
145
-        rot.x += glm::pi<float>() * 2.0f;
109
+void Camera::handleControllerButton(KeyboardButton button, bool released) {
110
+    if (button == aButton) {
111
+        handleAction(jumpAction, released);
112
+    } else if (button == bButton) {
113
+        handleAction(crouchAction, released);
114
+    } else if (button == padUp) {
115
+        handleAction(forwardAction, released);
116
+    } else if (button == padDown) {
117
+        handleAction(backwardAction, released);
118
+    } else if (button == padLeft) {
119
+        handleAction(leftAction, released);
120
+    } else if (button == padRight) {
121
+        handleAction(rightAction, released);
122
+    }
146 123
 }
147 124
 
148 125
 bool Camera::update() {
149 126
     glm::vec2 size(getWindow().getWidth(), getWindow().getHeight());
150 127
 
151
-    if ((lastPos == pos) && (lastRot == rot) && (lastSize == size))
152
-        return false;
153
-
154 128
     if (lastSize != size) {
155
-        //! \fixme TODO instead of mirroring the axes in the shader, scale here
129
+        //! \fixme TODO instead of mirroring the Y axis in the shader, scale with -1 here
156 130
         projection = glm::perspective(fov, size.x / size.y, nearDist, farDist);
157 131
         lastSize = size;
158 132
     }
159 133
 
160
-    glm::vec3 dir(
161
-        glm::cos(rot.y) * glm::sin(rot.x),
162
-        glm::sin(rot.y),
163
-        glm::cos(rot.y) * glm::cos(rot.x)
164
-    );
134
+    float dT = getRunTime().getLastFrameTime();
135
+    pos += quaternion * posSpeed * dT;
136
+
137
+    if (glm::epsilonNotEqual(rotSpeed.x, 0.0f, 0.01f))
138
+        quaternion = glm::quat(upUnit * rotationDeltaX * rotSpeed.x * dT) * quaternion;
139
+
140
+    if (glm::epsilonNotEqual(rotSpeed.y, 0.0f, 0.01f))
141
+        quaternion = glm::quat(quaternion * -rightUnit * rotationDeltaY * rotSpeed.y * dT) * quaternion;
142
+
143
+    glm::mat4 translate = glm::translate(glm::mat4(1.0f), pos);
144
+    glm::mat4 rotate = glm::toMat4(quaternion);
145
+    view = glm::inverse(translate * rotate);
146
+
147
+    if (updateViewFrustum)
148
+        calculateFrustumPlanes();
149
+
150
+    return updateViewFrustum;
151
+}
152
+
153
+glm::vec2 Camera::getRotation() {
154
+    glm::vec3 euler = glm::eulerAngles(quaternion);
155
+    return glm::vec2(euler.y, euler.x);
156
+}
157
+
158
+// ----------------------------------------------------------------------------
165 159
 
166
-    glm::vec3 right(
167
-        glm::sin(rot.x - glm::pi<float>() / 2.0f),
168
-        0.0f,
169
-        glm::cos(rot.x - glm::pi<float>() / 2.0f)
170
-    );
160
+class FrustumPlane {
161
+  public:
162
+    FrustumPlane() : normal(glm::vec3(0.0f, 0.0f, 0.0f)), d(0.0f) { }
163
+    void set(glm::vec3 v1, glm::vec3 v2, glm::vec3 v3) {
164
+        normal = glm::normalize(glm::cross(v3 - v2, v1 - v2));
165
+        d = -glm::dot(normal, v2);
166
+    }
167
+    float distance(glm::vec3 p) {
168
+        return d + glm::dot(normal, p);
169
+    }
170
+  private:
171
+    glm::vec3 normal;
172
+    float d;
173
+};
171 174
 
172
-    glm::vec3 up = glm::cross(right, dir);
173
-    view = glm::lookAt(pos, pos + dir, up);
175
+// ----------------------------------------------------------------------------
174 176
 
175
-    if (!updateViewFrustum)
176
-        return false;
177
+static FrustumPlane planes[6];
178
+static glm::vec3 frustumColors[6] = {
179
+    glm::vec3(1.0f, 0.0f, 0.0f), // NEAR, red
180
+    glm::vec3(0.0f, 1.0f, 0.0f), // FAR, green
181
+    glm::vec3(0.0f, 0.0f, 1.0f), // TOP, blue
182
+    glm::vec3(1.0f, 1.0f, 0.0f), // BOTTOM, yellow
183
+    glm::vec3(0.0f, 1.0f, 1.0f), // LEFT, light-blue
184
+    glm::vec3(1.0f, 0.0f, 1.0f)  // RIGHT, pink
185
+};
186
+static glm::vec3 frustumVertices[8];
177 187
 
188
+void Camera::calculateFrustumPlanes() {
178 189
     glm::mat4 combo = projection * view;
179 190
 
180 191
     // Calculate frustum corners to display them
@@ -200,10 +211,6 @@ bool Camera::update() {
200 211
     planes[RIGHT].set(frustumVertices[NBR], frustumVertices[NTR], frustumVertices[FBR]);
201 212
     planes[NEAR].set(frustumVertices[NTL], frustumVertices[NTR], frustumVertices[NBR]);
202 213
     planes[FAR].set(frustumVertices[FTR], frustumVertices[FTL], frustumVertices[FBL]);
203
-
204
-    lastPos = pos;
205
-    lastRot = rot;
206
-    return true;
207 214
 }
208 215
 
209 216
 bool Camera::boxInFrustum(BoundingBox b) {

+ 29
- 2
src/Game.cpp View File

@@ -31,6 +31,10 @@
31 31
 Game::Game() {
32 32
     mLoaded = false;
33 33
     mLara = -1;
34
+
35
+    for (int i = 0; i < ActionEventCount; i++) {
36
+        activeEvents[i] = false;
37
+    }
34 38
 }
35 39
 
36 40
 Game::~Game() {
@@ -124,10 +128,19 @@ int Game::loadLevel(const char* level) {
124 128
 }
125 129
 
126 130
 void Game::handleAction(ActionEvents action, bool isFinished) {
127
-    if (isFinished || (!mLoaded))
131
+    assert(action < ActionEventCount);
132
+
133
+    if (!mLoaded)
128 134
         return;
129 135
 
130
-    Camera::handleAction(action, isFinished);
136
+    if (isFinished) {
137
+        activeEvents[action] = false;
138
+        Camera::handleAction(action, isFinished);
139
+    } else {
140
+        if (!activeEvents[action])
141
+            Camera::handleAction(action, isFinished);
142
+        activeEvents[action] = true;
143
+    }
131 144
 }
132 145
 
133 146
 void Game::handleMouseMotion(int xrel, int yrel, int xabs, int yabs) {
@@ -137,6 +150,20 @@ void Game::handleMouseMotion(int xrel, int yrel, int xabs, int yabs) {
137 150
     Camera::handleMouseMotion(xrel, yrel);
138 151
 }
139 152
 
153
+void Game::handleControllerAxis(float value, KeyboardButton axis) {
154
+    if (!mLoaded)
155
+        return;
156
+
157
+    Camera::handleControllerAxis(value, axis);
158
+}
159
+
160
+void Game::handleControllerButton(KeyboardButton button, bool released) {
161
+    if (!mLoaded)
162
+        return;
163
+
164
+    Camera::handleControllerButton(button, released);
165
+}
166
+
140 167
 Entity& Game::getLara() {
141 168
     assert(mLara >= 0);
142 169
     assert(mLara < (int)getWorld().sizeEntity());

+ 7
- 2
src/RunTime.cpp View File

@@ -103,8 +103,9 @@ void RunTime::setShowFPS(bool fps) {
103 103
 
104 104
 void RunTime::updateFPS() {
105 105
     frameCount++;
106
-    frameTimeSum += (systemTimerGet() - lastTime);
107
-    frameTimeSum2 += (systemTimerGet() - lastTime);
106
+    lastFrameTime = systemTimerGet() - lastTime;
107
+    frameTimeSum += lastFrameTime;
108
+    frameTimeSum2 += lastFrameTime;
108 109
     lastTime = systemTimerGet();
109 110
     if (frameTimeSum >= 200) {
110 111
         fps = frameCount * (1000 / frameTimeSum);
@@ -126,3 +127,7 @@ const std::vector<float>& RunTime::getHistoryFPS() {
126 127
     return history;
127 128
 }
128 129
 
130
+float RunTime::getLastFrameTime() {
131
+    return lastFrameTime / 1000.0f;
132
+}
133
+

+ 8
- 0
src/UI.cpp View File

@@ -653,6 +653,14 @@ void UI::handleMouseScroll(int xrel, int yrel) {
653 653
     scrollEvents.push_back(std::make_tuple(xrel, yrel));
654 654
 }
655 655
 
656
+void UI::handleControllerAxis(float value, KeyboardButton axis) {
657
+    getGame().handleControllerAxis(value, axis);
658
+}
659
+
660
+void UI::handleControllerButton(KeyboardButton button, bool released) {
661
+    getGame().handleControllerButton(button, released);
662
+}
663
+
656 664
 void UI::setVisible(bool v) {
657 665
     visible = v;
658 666
 }

+ 95
- 5
src/system/WindowSDL.cpp View File

@@ -8,12 +8,13 @@
8 8
 #include <iostream>
9 9
 
10 10
 #include "global.h"
11
+#include "Log.h"
11 12
 #include "RunTime.h"
12 13
 #include "UI.h"
13 14
 #include "utils/strings.h"
14 15
 #include "system/WindowSDL.h"
15 16
 
16
-#define SUBSYSTEMS_USED (SDL_INIT_VIDEO | SDL_INIT_EVENTS)
17
+#define SUBSYSTEMS_USED (SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER)
17 18
 
18 19
 WindowSDL::WindowSDL() {
19 20
     mInit = false;
@@ -24,10 +25,14 @@ WindowSDL::WindowSDL() {
24 25
     mTextInput = false;
25 26
     mWindow = nullptr;
26 27
     mGLContext = nullptr;
28
+    controller = nullptr;
27 29
 }
28 30
 
29 31
 WindowSDL::~WindowSDL() {
30 32
     if (mInit) {
33
+        if (controller)
34
+            SDL_GameControllerClose(controller);
35
+
31 36
         SDL_QuitSubSystem(SUBSYSTEMS_USED);
32 37
         SDL_Quit();
33 38
     }
@@ -115,23 +120,108 @@ int WindowSDL::initialize() {
115 120
     setSize(mWidth, mHeight);
116 121
     setMousegrab(mMousegrab);
117 122
 
123
+    if (SDL_NumJoysticks() == 0) {
124
+        getLog() << "No Joystick found!" << Log::endl;
125
+        return 0;
126
+    }
127
+
128
+    SDL_GameControllerAddMapping("341a0000000000000208000000000000,"
129
+                                 "USB GAMEPAD 8116,"
130
+                                 "a:b0,x:b2,start:b7,back:b6,leftstick:b8,rightstick:b9,"
131
+                                 "leftshoulder:b4,rightshoulder:b5,"
132
+                                 "dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,"
133
+                                 "leftx:a0,lefty:a1,rightx:a3,righty:a2,"
134
+                                 "lefttrigger:,b:b1,y:b3,lefttrigger:a4,righttrigger:a4");
135
+
136
+    for (int i = 0; i < SDL_NumJoysticks(); i++) {
137
+        if (SDL_IsGameController(i)) {
138
+            controller = SDL_GameControllerOpen(i);
139
+            if (controller) {
140
+                getLog() << "Using controller \"" << SDL_GameControllerName(controller)
141
+                         << "\"..." << Log::endl;
142
+                break;
143
+            } else {
144
+                getLog() << "Couldn't open controller \"" << SDL_GameControllerNameForIndex(i)
145
+                         << "\"!" << Log::endl;
146
+            }
147
+        } else {
148
+            getLog() << "Joystick \"" << SDL_JoystickNameForIndex(i)
149
+                     << "\" is no controller!" << Log::endl;
150
+        }
151
+    }
118 152
     return 0;
119 153
 }
120 154
 
121 155
 void WindowSDL::eventHandling() {
122 156
     SDL_Event event;
157
+    KeyboardButton button;
123 158
 
124 159
     assert(mInit == true);
125 160
 
126 161
     while (SDL_PollEvent(&event)) {
127 162
         switch (event.type) {
163
+            case SDL_CONTROLLERAXISMOTION:
164
+                button = unknownKey;
165
+                if (event.caxis.axis == SDL_CONTROLLER_AXIS_LEFTX)
166
+                    button = leftXAxis;
167
+                else if (event.caxis.axis == SDL_CONTROLLER_AXIS_LEFTY)
168
+                    button = leftYAxis;
169
+                else if (event.caxis.axis == SDL_CONTROLLER_AXIS_RIGHTX)
170
+                    button = rightXAxis;
171
+                else if (event.caxis.axis == SDL_CONTROLLER_AXIS_RIGHTY)
172
+                    button = rightYAxis;
173
+                else if (event.caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT)
174
+                    button = leftTrigger;
175
+                else if (event.caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT)
176
+                    button = rightTrigger;
177
+                if (button != unknownKey)
178
+                    UI::handleControllerAxis(event.caxis.value / 32768.0f, button);
179
+                break;
180
+
181
+            case SDL_CONTROLLERBUTTONDOWN:
182
+            case SDL_CONTROLLERBUTTONUP:
183
+                button = unknownKey;
184
+                if (event.cbutton.button == SDL_CONTROLLER_BUTTON_A)
185
+                    button = aButton;
186
+                else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_B)
187
+                    button = bButton;
188
+                else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_X)
189
+                    button = xButton;
190
+                else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_Y)
191
+                    button = yButton;
192
+                else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_BACK)
193
+                    button = backButton;
194
+                else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_GUIDE)
195
+                    button = guideButton;
196
+                else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_START)
197
+                    button = startButton;
198
+                else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_LEFTSTICK)
199
+                    button = leftStick;
200
+                else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_RIGHTSTICK)
201
+                    button = rightStick;
202
+                else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER)
203
+                    button = leftShoulder;
204
+                else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
205
+                    button = rightShoulder;
206
+                else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
207
+                    button = padUp;
208
+                else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
209
+                    button = padDown;
210
+                else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
211
+                    button = padLeft;
212
+                else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
213
+                    button = padRight;
214
+                if (button != unknownKey)
215
+                    UI::handleControllerButton(button, (event.type == SDL_CONTROLLERBUTTONUP));
216
+                break;
217
+
128 218
             case SDL_MOUSEMOTION:
129 219
                 UI::handleMouseMotion(event.motion.xrel, event.motion.yrel, event.motion.x, event.motion.y);
130 220
                 break;
131 221
 
132 222
             case SDL_MOUSEBUTTONDOWN:
133 223
             case SDL_MOUSEBUTTONUP:
134
-                KeyboardButton button;
224
+                button = unknownKey;
135 225
                 if (event.button.button == SDL_BUTTON_LEFT)
136 226
                     button = leftmouseKey;
137 227
                 else if (event.button.button == SDL_BUTTON_RIGHT)
@@ -142,9 +232,9 @@ void WindowSDL::eventHandling() {
142 232
                     button = fourthmouseKey;
143 233
                 else if (event.button.button == SDL_BUTTON_X2)
144 234
                     button = fifthmouseKey;
145
-                else
146
-                    button = unknownKey;
147
-                UI::handleMouseClick(event.button.x, event.button.y, button, (event.type == SDL_MOUSEBUTTONUP));
235
+                if (button != unknownKey)
236
+                    UI::handleMouseClick(event.button.x, event.button.y, button,
237
+                                         (event.type == SDL_MOUSEBUTTONUP));
148 238
                 break;
149 239
 
150 240
             case SDL_MOUSEWHEEL:

Loading…
Cancel
Save