File: GlfwInputManager.h

package info (click to toggle)
jazz2-native 3.5.0-2
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid
  • size: 16,912 kB
  • sloc: cpp: 172,557; xml: 113; python: 36; makefile: 5; sh: 2
file content (207 lines) | stat: -rw-r--r-- 6,670 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#pragma once

#if defined(WITH_GLFW) || defined(DOXYGEN_GENERATING_OUTPUT)

#include "../Input/IInputManager.h"
#include "GlfwGfxDevice.h" // for WindowHandle()
#include "../../Main.h"

#include <cstdio>

#if defined(DEATH_TARGET_EMSCRIPTEN)
#	include <emscripten/html5.h>
#endif

#include <Containers/SmallVector.h>

using namespace Death::Containers;

namespace nCine::Backends
{
	class GlfwInputManager;

	/// Utility functions to convert between engine key enumerations and GLFW ones
	class GlfwKeys
	{
	public:
		static Keys keySymValueToEnum(int keysym);
		static int keyModMaskToEnumMask(int keymod);
		static int enumToKeysValue(Keys keysym);
	};

	/// Information about GLFW mouse state
	class GlfwMouseState : public MouseState
	{
	public:
		GlfwMouseState();

		bool isButtonDown(MouseButton button) const override;
	};

	/// Information about a GLFW scroll event
	class GlfwScrollEvent : public ScrollEvent
	{
	public:
		GlfwScrollEvent() {}

		friend class GlfwInputManager;
	};

	/// Information about GLFW keyboard state
	class GlfwKeyboardState : public KeyboardState
	{
	public:
		inline bool isKeyDown(Keys key) const override
		{
			const int glfwKey = GlfwKeys::enumToKeysValue(key);
			if (glfwKey == GLFW_KEY_UNKNOWN)
				return false;
			else
				return glfwGetKey(GlfwGfxDevice::windowHandle(), glfwKey) == GLFW_PRESS;
		}

		friend class GlfwInputManager;
	};

	/// Information about GLFW joystick state
	class GlfwJoystickState : public JoystickState
	{
	public:
		GlfwJoystickState()
			: numButtons_(0), numHats_(0), numAxes_(0), buttons_(nullptr), hats_(nullptr), axesValues_(nullptr) {}

		bool isButtonPressed(int buttonId) const override;
		unsigned char hatState(int hatId) const override;
		float axisValue(int axisId) const override;

	private:
		int numButtons_;
		int numHats_;
		int numAxes_;

		const unsigned char* buttons_;
		const unsigned char* hats_;
		const float* axesValues_;

		friend class GlfwInputManager;
	};

	/// Slass for parsing and dispatching GLFW input events
	class GlfwInputManager : public IInputManager
	{
	public:
		GlfwInputManager();
		~GlfwInputManager() override;

		/// Detects window focus gain/loss events
		static bool hasFocus();
		/// Updates joystick state structures and simulates events
		static void updateJoystickStates();

		const MouseState& mouseState() const override;
		inline const KeyboardState& keyboardState() const override {
			return keyboardState_;
		}

		String getClipboardText() const override;
		bool setClipboardText(StringView text) override;

		bool isJoyPresent(int joyId) const override;
		const char* joyName(int joyId) const override;
		const JoystickGuid joyGuid(int joyId) const override;
		int joyNumButtons(int joyId) const override;
		int joyNumHats(int joyId) const override;
		int joyNumAxes(int joyId) const override;
		const JoystickState& joystickState(int joyId) const override;
		bool joystickRumble(int joyId, float lowFreqIntensity, float highFreqIntensity, uint32_t durationMs) override;
		bool joystickRumbleTriggers(int joyId, float left, float right, uint32_t durationMs) override;

		void setCursor(Cursor cursor) override;

	private:
		static const int MaxNumJoysticks = GLFW_JOYSTICK_LAST - GLFW_JOYSTICK_1 + 1;

#ifndef DOXYGEN_GENERATING_OUTPUT
		// Doxygen 1.12.0 outputs also private structs/unions even if it shouldn't
		class JoystickEventsSimulator
		{
		public:
			JoystickEventsSimulator();
			void resetJoystickState(int joyId);
			void simulateButtonsEvents(int joyId, int numButtons, const unsigned char* buttons);
			void simulateHatsEvents(int joyId, int numHats, const unsigned char* hats);
			void simulateAxesEvents(int joyId, int numAxes, const float* axesValues);

		private:
			static const unsigned int MaxNumButtons = 16;
			static const unsigned int MaxNumHats = 4;
			static const unsigned int MaxNumAxes = 10;
			/// Minimum difference between two axis readings in order to trigger an event
			static const float AxisEventTolerance;

			/// Old state used to simulate joystick buttons events
			unsigned char buttonsState_[MaxNumJoysticks][MaxNumButtons];
			/// Old state used to simulate joystick hats events
			unsigned char hatsState_[MaxNumJoysticks][MaxNumHats];
			/// Old state used to simulate joystick axes events
			float axesValuesState_[MaxNumJoysticks][MaxNumAxes];
		};
#endif

		static bool windowHasFocus_;
		static GlfwMouseState mouseState_;
		static MouseEvent mouseEvent_;
		static GlfwScrollEvent scrollEvent_;
		static GlfwKeyboardState keyboardState_;
		static KeyboardEvent keyboardEvent_;
		static TextInputEvent textInputEvent_;
		static GlfwJoystickState nullJoystickState_;
		static SmallVector<GlfwJoystickState, MaxNumJoysticks> joystickStates_;
		static JoyButtonEvent joyButtonEvent_;
		static JoyHatEvent joyHatEvent_;
		static JoyAxisEvent joyAxisEvent_;
		static JoyConnectionEvent joyConnectionEvent_;
		static JoystickEventsSimulator joyEventsSimulator_;

		/// The window width before a window content scale event
		static int preScalingWidth_;
		/// The window height before a window content scale event
		static int preScalingHeight_;
		/// The last frame a window size callback was called
		static unsigned long int lastFrameWindowSizeChanged_;

		static void monitorCallback(GLFWmonitor* monitor, int event);
		static void windowCloseCallback(GLFWwindow* window);
		static void windowContentScaleCallback(GLFWwindow* window, float xscale, float yscale);
		static void windowSizeCallback(GLFWwindow* window, int width, int height);
		static void framebufferSizeCallback(GLFWwindow* window, int width, int height);
		static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
		static void charCallback(GLFWwindow* window, unsigned int c);
		static void cursorPosCallback(GLFWwindow* window, double x, double y);
		static void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
		static void scrollCallback(GLFWwindow* window, double xoffset, double yoffset);
		static void joystickCallback(int joy, int event);
#if defined(DEATH_TARGET_EMSCRIPTEN)
		static EM_BOOL emscriptenHandleTouch(int eventType, const EmscriptenTouchEvent* event, void* userData);
#endif

		static Keys keySymValueToEnum(int keysym);
		static KeyMod keyModValueToEnum(int keymod);
		static int enumToKeysValue(Keys keysym);

		friend class GlfwGfxDevice; // for setWindowPosition()
	};

	inline const MouseState& GlfwInputManager::mouseState() const
	{
		double xCursor, yCursor;

		glfwGetCursorPos(GlfwGfxDevice::windowHandle(), &xCursor, &yCursor);
		mouseState_.x = int(xCursor);
		mouseState_.y = int(yCursor);

		return mouseState_;
	}
}

#endif