Kaynağa Gözat

Merge branch 'master' of github.com:taylor001/crown

Daniele Bartolini 10 yıl önce
ebeveyn
işleme
89294b93fe

+ 7 - 2
README.md

@@ -1,8 +1,6 @@
 Lightweight and flexible cross-platform game engine.
 =====
 
-I'm an independent developer and your contributions are invaluable to me. If you like the work I do, please consider supporting Crown development by means of a small contribution. I'm also available for hire to work on or with Crown or somewhat related technologies/projects.
-
 [![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6FQMPUQQ8KQKW)
 
 ##What is it?
@@ -105,6 +103,13 @@ Daniele Bartolini ([@aa_dani_bart](https://twitter.com/aa_dani_bart))
 
 Project page: https://github.com/taylor001/crown
 
+Support
+-------
+
+I'm an independent developer and your contributions are invaluable to me. If you like the work I do, please consider supporting Crown development by means of a small contribution. I'm also available for hire to work on or with Crown or somewhat related technologies/projects.
+
+[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6FQMPUQQ8KQKW)
+
 Contributors
 ------------
 

+ 27 - 0
docs/lua_api.txt

@@ -861,6 +861,9 @@ Keyboard
 	**any_released** () : bool
 		Returns whether any button is released in the current frame.
 
+	**button_name** (id) : string
+		Returns the name of the button *id*.
+
 	**button_id** (name) : int
 		Returns the *id* of the button *name*.
 
@@ -910,6 +913,12 @@ Mouse
 	**axis** (id) : Vector3
 		Returns the value of the axis *id*.
 
+	**button_name** (id) : string
+		Returns the name of the button *id*.
+
+	**axis_name** (id) : string
+		Returns the name of the axis *id*.
+
 	**button_id** (name) : int
 		Returns the *id* of the button *name*.
 
@@ -958,6 +967,18 @@ Touch
 	**axis** (id) : Vector3
 		Returns the value of the axis *id*.
 
+	**button_name** (id) : string
+		Returns the name of the button *id*.
+
+	**axis_name** (id) : string
+		Returns the name of the axis *id*.
+
+	**button_id** (name) : int
+		Returns the *id* of the button *name*.
+
+	**axis_id** (name) : int
+		Returns the *id* of the axis *name*.
+
 Pad1, Pad2, Pad3, Pad4
 ----------------------
 
@@ -988,6 +1009,12 @@ Pad1, Pad2, Pad3, Pad4
 	**axis** (id) : Vector3
 		Returns the value of the axis *id*.
 
+	**button_name** (id) : string
+		Returns the name of the button *id*.
+
+	**axis_name** (id) : string
+		Returns the name of the axis *id*.
+
 	**button_id** (name) : int
 		Returns the *id* of the button *name*.
 

+ 5 - 3
src/core/error/stacktrace_windows.cpp

@@ -8,7 +8,7 @@
 #if CROWN_PLATFORM_WINDOWS
 
 #include "log.h"
-#include <windows.h>
+#include "win_headers.h"
 #include <dbghelp.h>
 
 namespace crown
@@ -63,7 +63,8 @@ void print_callstack()
 			, NULL
 			, SymFunctionTableAccess64
 			, SymGetModuleBase64
-			, NULL))
+			, NULL
+			))
 	{
 		if (stack.AddrPC.Offset == 0)
 			break;
@@ -73,7 +74,8 @@ void print_callstack()
 		BOOL res = SymGetLineFromAddr64(GetCurrentProcess()
 					, stack.AddrPC.Offset
 					, &ldsp
-					, &line);
+					, &line
+					);
 		res = res && SymFromAddr(GetCurrentProcess(), stack.AddrPC.Offset, 0, sym);
 
 		if (res == TRUE)

+ 67 - 12
src/input/input_device.cpp

@@ -7,6 +7,7 @@
 #include "error.h"
 #include "allocator.h"
 #include "string_utils.h"
+#include "string_id.h"
 #include <string.h> // strcpy, memset
 
 namespace crown
@@ -32,16 +33,16 @@ uint8_t InputDevice::num_axes() const
 	return _num_axes;
 }
 
-bool InputDevice::pressed(uint8_t i) const
+bool InputDevice::pressed(uint8_t id) const
 {
-	CE_ASSERT(i < _num_buttons, "Index out of bounds");
-	return (~_last_state[i] & _current_state[i]) != 0;
+	CE_ASSERT(id < _num_buttons, "Index out of bounds");
+	return (~_last_state[id] & _current_state[id]) != 0;
 }
 
-bool InputDevice::released(uint8_t i) const
+bool InputDevice::released(uint8_t id) const
 {
-	CE_ASSERT(i < _num_buttons, "Index out of bounds");
-	return (_last_state[i] & ~_current_state[i]) != 0;
+	CE_ASSERT(id < _num_buttons, "Index out of bounds");
+	return (_last_state[id] & ~_current_state[id]) != 0;
 }
 
 bool InputDevice::any_pressed() const
@@ -54,10 +55,46 @@ bool InputDevice::any_released() const
 	return released(_last_button);
 }
 
-Vector3 InputDevice::axis(uint8_t i) const
+Vector3 InputDevice::axis(uint8_t id) const
 {
-	CE_ASSERT(i < _num_axes, "Index out of bounds");
-	return _axis[i];
+	CE_ASSERT(id < _num_axes, "Index out of bounds");
+	return _axis[id];
+}
+
+const char* InputDevice::button_name(uint8_t id)
+{
+	CE_ASSERT(id < _num_buttons, "Index out of bounds");
+	return _button_name[id];
+}
+
+const char* InputDevice::axis_name(uint8_t id)
+{
+	CE_ASSERT(id < _num_axes, "Index out of bounds");
+	return _axis_name[id];
+}
+
+uint8_t InputDevice::button_id(StringId32 name)
+{
+	for (uint32_t i = 0; i < _num_buttons; ++i)
+	{
+		if (_button_hash[i] == name)
+			return i;
+	}
+
+	CE_ASSERT(false, "Unknown button name");
+	return 0;
+}
+
+uint8_t InputDevice::axis_id(StringId32 name)
+{
+	for (uint32_t i = 0; i < _num_axes; ++i)
+	{
+		if (_axis_hash[i] == name)
+			return i;
+	}
+
+	CE_ASSERT(false, "Unknown axis name");
+	return 0;
 }
 
 void InputDevice::set_connected(bool connected)
@@ -83,13 +120,18 @@ void InputDevice::update()
 	memcpy(_last_state, _current_state, sizeof(uint8_t)*_num_buttons);
 }
 
-InputDevice* InputDevice::create(Allocator& a, const char* name, uint8_t num_buttons, uint8_t num_axes)
+InputDevice* InputDevice::create(Allocator& a, const char* name, uint8_t num_buttons, uint8_t num_axes, const char** button_names, const char** axis_names)
 {
 	const uint32_t size = 0
 		+ sizeof(InputDevice)
 		+ sizeof(uint8_t)*num_buttons*2
 		+ sizeof(Vector3)*num_axes
-		+ strlen32(name) + 1;
+		+ sizeof(char*)*num_buttons
+		+ sizeof(char*)*num_axes
+		+ sizeof(StringId32)*num_buttons
+		+ sizeof(StringId32)*num_axes
+		+ strlen32(name) + 1
+		;
 
 	InputDevice* id = (InputDevice*)a.allocate(size);
 
@@ -101,11 +143,24 @@ InputDevice* InputDevice::create(Allocator& a, const char* name, uint8_t num_but
 	id->_last_state = (uint8_t*)&id[1];
 	id->_current_state = (uint8_t*)(id->_last_state + num_buttons);
 	id->_axis = (Vector3*)(id->_current_state + num_buttons);
-	id->_name = (char*)(id->_axis + num_axes);
+	id->_button_name = (const char**)(id->_axis + num_axes);
+	id->_axis_name = (const char**)(id->_button_name + num_buttons);
+	id->_button_hash = (StringId32*)(id->_axis_name + num_axes);
+	id->_axis_hash = (StringId32*)(id->_button_hash + num_buttons);
+	id->_name = (char*)(id->_axis_hash + num_axes);
 
 	memset(id->_last_state, 0, sizeof(uint8_t)*num_buttons);
 	memset(id->_current_state, 0, sizeof(uint8_t)*num_buttons);
 	memset(id->_axis, 0, sizeof(Vector3)*num_axes);
+	memcpy(id->_button_name, button_names, sizeof(const char*)*num_buttons);
+	memcpy(id->_axis_name, axis_names, sizeof(const char*)*num_axes);
+
+	for (uint32_t i = 0; i < num_buttons; ++i)
+		id->_button_hash[i] = StringId32(button_names[i]);
+
+	for (uint32_t i = 0; i < num_axes; ++i)
+		id->_axis_hash[i] = StringId32(axis_names[i]);
+
 	strcpy(id->_name, name);
 
 	return id;

+ 28 - 11
src/input/input_device.h

@@ -8,6 +8,7 @@
 #include "types.h"
 #include "math_types.h"
 #include "memory_types.h"
+#include "string_id.h"
 
 namespace crown
 {
@@ -29,11 +30,11 @@ struct InputDevice
 	/// Returns the number of axes of the input devices.
 	uint8_t num_axes() const;
 
-	/// Returns whether the specified @a b button is pressed in the current frame.
-	bool pressed(uint8_t i) const;
+	/// Returns whether the button @a id is pressed in the current frame.
+	bool pressed(uint8_t id) const;
 
-	/// Returns whether the specified @a b button is released in the current frame.
-	bool released(uint8_t i) const;
+	/// Returns whether the button @a id is released in the current frame.
+	bool released(uint8_t id) const;
 
 	/// Returns whether any button is pressed in the current frame.
 	bool any_pressed() const;
@@ -41,8 +42,20 @@ struct InputDevice
 	/// Returns whether any button is released in the current frame.
 	bool any_released() const;
 
-	/// Returns the value of the axis @a i.
-	Vector3 axis(uint8_t i) const;
+	/// Returns the value of the axis @a id.
+	Vector3 axis(uint8_t id) const;
+
+	/// Returns the name of the button @a id.
+	const char* button_name(uint8_t id);
+
+	/// Returns the name of the axis @a id.
+	const char* axis_name(uint8_t id);
+
+	/// Returns the id of the button @a name.
+	uint8_t button_id(StringId32 name);
+
+	/// Returns the id of the axis @a name.
+	uint8_t axis_id(StringId32 name);
 
 	void set_connected(bool connected);
 
@@ -59,14 +72,18 @@ public:
 	uint8_t _num_axes;
 	uint8_t _last_button;
 
-	uint8_t* _last_state;    // num_buttons
-	uint8_t* _current_state; // num_buttons
-	Vector3* _axis;          // num_axes
-	char* _name;             // strlen32(name) + 1
+	uint8_t* _last_state;      // num_buttons
+	uint8_t* _current_state;   // num_buttons
+	Vector3* _axis;            // num_axes
+	const char** _button_name; // num_buttons
+	const char** _axis_name;   // num_axes
+	StringId32* _button_hash;  // num_buttons
+	StringId32* _axis_hash;    // num_axes
+	char* _name;               // strlen32(name) + 1
 
 public:
 
-	static InputDevice* create(Allocator& a, const char* name, uint8_t num_buttons, uint8_t num_axes);
+	static InputDevice* create(Allocator& a, const char* name, uint8_t num_buttons, uint8_t num_axes, const char** button_names, const char** axis_names);
 	static void destroy(Allocator& a, InputDevice* id);
 };
 

+ 156 - 1
src/input/input_manager.cpp

@@ -10,6 +10,153 @@
 namespace crown
 {
 
+static const char* s_keyboard_button_names[] =
+{
+	"tab",          // KeyboardButton::TAB
+	"enter",        // KeyboardButton::ENTER
+	"escape",       // KeyboardButton::ESCAPE
+	"space",        // KeyboardButton::SPACE
+	"backspace",    // KeyboardButton::BACKSPACE
+	"num_lock",     // KeyboardButton::NUM_LOCK
+	"numpad_enter", // KeyboardButton::NUMPAD_ENTER
+	"numpad_.",     // KeyboardButton::NUMPAD_DELETE
+	"numpad_*",     // KeyboardButton::NUMPAD_MULTIPLY
+	"numpad_+",     // KeyboardButton::NUMPAD_ADD
+	"numpad_-",     // KeyboardButton::NUMPAD_SUBTRACT
+	"numpad_/",     // KeyboardButton::NUMPAD_DIVIDE
+	"numpad_0",     // KeyboardButton::NUMPAD_0
+	"numpad_1",     // KeyboardButton::NUMPAD_1
+	"numpad_2",     // KeyboardButton::NUMPAD_2
+	"numpad_3",     // KeyboardButton::NUMPAD_3
+	"numpad_4",     // KeyboardButton::NUMPAD_4
+	"numpad_5",     // KeyboardButton::NUMPAD_5
+	"numpad_6",     // KeyboardButton::NUMPAD_6
+	"numpad_7",     // KeyboardButton::NUMPAD_7
+	"numpad_8",     // KeyboardButton::NUMPAD_8
+	"numpad_9",     // KeyboardButton::NUMPAD_9
+	"f1",           // KeyboardButton::F1
+	"f2",           // KeyboardButton::F2
+	"f3",           // KeyboardButton::F3
+	"f4",           // KeyboardButton::F4
+	"f5",           // KeyboardButton::F5
+	"f6",           // KeyboardButton::F6
+	"f7",           // KeyboardButton::F7
+	"f8",           // KeyboardButton::F8
+	"f9",           // KeyboardButton::F9
+	"f10",          // KeyboardButton::F10
+	"f11",          // KeyboardButton::F11
+	"f12",          // KeyboardButton::F12
+	"home",         // KeyboardButton::HOME
+	"left",         // KeyboardButton::LEFT
+	"up",           // KeyboardButton::UP
+	"right",        // KeyboardButton::RIGHT
+	"down",         // KeyboardButton::DOWN
+	"page_up",      // KeyboardButton::PAGE_UP
+	"page_down",    // KeyboardButton::PAGE_DOWN
+	"delete",       // KeyboardButton::DELETE
+	"end",          // KeyboardButton::END
+	"left_ctrl",    // KeyboardButton::LEFT_CTRL
+	"right_ctrl",   // KeyboardButton::RIGHT_CTRL
+	"left_shift",   // KeyboardButton::LEFT_SHIFT
+	"right_shift",  // KeyboardButton::RIGHT_SHIFT
+	"caps_lock",    // KeyboardButton::CAPS_LOCK
+	"left_alt",     // KeyboardButton::LEFT_ALT
+	"right_alt",    // KeyboardButton::RIGHT_ALT
+	"left_super",   // KeyboardButton::LEFT_SUPER
+	"right_super",  // KeyboardButton::RIGHT_SUPER
+	"0",            // KeyboardButton::NUMBER_0
+	"1",            // KeyboardButton::NUMBER_1
+	"2",            // KeyboardButton::NUMBER_2
+	"3",            // KeyboardButton::NUMBER_3
+	"4",            // KeyboardButton::NUMBER_4
+	"5",            // KeyboardButton::NUMBER_5
+	"6",            // KeyboardButton::NUMBER_6
+	"7",            // KeyboardButton::NUMBER_7
+	"8",            // KeyboardButton::NUMBER_8
+	"9",            // KeyboardButton::NUMBER_9
+	"a",            // KeyboardButton::A
+	"b",            // KeyboardButton::B
+	"c",            // KeyboardButton::C
+	"d",            // KeyboardButton::D
+	"e",            // KeyboardButton::E
+	"f",            // KeyboardButton::F
+	"g",            // KeyboardButton::G
+	"h",            // KeyboardButton::H
+	"i",            // KeyboardButton::I
+	"j",            // KeyboardButton::J
+	"k",            // KeyboardButton::K
+	"l",            // KeyboardButton::L
+	"m",            // KeyboardButton::M
+	"n",            // KeyboardButton::N
+	"o",            // KeyboardButton::O
+	"p",            // KeyboardButton::P
+	"q",            // KeyboardButton::Q
+	"r",            // KeyboardButton::R
+	"s",            // KeyboardButton::S
+	"t",            // KeyboardButton::T
+	"u",            // KeyboardButton::U
+	"v",            // KeyboardButton::V
+	"w",            // KeyboardButton::W
+	"x",            // KeyboardButton::X
+	"y",            // KeyboardButton::Y
+	"z",            // KeyboardButton::Z
+};
+CE_STATIC_ASSERT(CE_COUNTOF(s_keyboard_button_names) == KeyboardButton::COUNT);
+
+static const char* s_mouse_button_names[] =
+{
+	"left",    // MouseButton::LEFT
+	"middle",  // MouseButton::MIDDLE
+	"right",   // MouseButton::RIGHT
+	"extra_1", // MouseButton::EXTRA_1
+	"extra_2", // MouseButton::EXTRA_2
+};
+CE_STATIC_ASSERT(CE_COUNTOF(s_mouse_button_names) == MouseButton::COUNT);
+
+static const char* s_mouse_axis_names[] =
+{
+	"cursor",       // MouseAxis::CURSOR
+	"cursor_delta", // MouseAxis::CURSOR_DELTA
+	"wheel",        // MouseAxis::WHEEL
+};
+CE_STATIC_ASSERT(CE_COUNTOF(s_mouse_axis_names) == MouseAxis::COUNT);
+
+static const char* s_touch_button_names[] =
+{
+	"pointer_0", // TouchButton::POINTER_0
+	"pointer_1", // TouchButton::POINTER_1
+	"pointer_2", // TouchButton::POINTER_2
+	"pointer_3"  // TouchButton::POINTER_3
+};
+CE_STATIC_ASSERT(CE_COUNTOF(s_touch_button_names) == TouchButton::COUNT);
+
+static const char* s_pad_button_names[] =
+{
+	"up",             // JoypadButton::UP
+	"down",           // JoypadButton::DOWN
+	"left",           // JoypadButton::LEFT
+	"right",          // JoypadButton::RIGHT
+	"start",          // JoypadButton::START
+	"back",           // JoypadButton::BACK
+	"guide",          // JoypadButton::GUIDE
+	"left_thumb",     // JoypadButton::LEFT_THUMB
+	"right_thumb",    // JoypadButton::RIGHT_THUMB
+	"left_shoulder",  // JoypadButton::LEFT_SHOULDER
+	"right_shoulder", // JoypadButton::RIGHT_SHOULDER
+	"a",              // JoypadButton::A
+	"b",              // JoypadButton::B
+	"x",              // JoypadButton::X
+	"y",              // JoypadButton::Y
+};
+CE_STATIC_ASSERT(CE_COUNTOF(s_pad_button_names) == JoypadButton::COUNT);
+
+static const char* s_pad_axis_names[] =
+{
+	"left",  // JoypadAxis::LEFT
+	"right", // JoypadAxis::RIGHT
+};
+CE_STATIC_ASSERT(CE_COUNTOF(s_pad_axis_names) == JoypadAxis::COUNT);
+
 InputManager::InputManager()
 	: _keyboard(NULL)
 	, _mouse(NULL)
@@ -19,16 +166,22 @@ InputManager::InputManager()
 		, "Keyboard"
 		, KeyboardButton::COUNT
 		, 0
+		, s_keyboard_button_names
+		, NULL
 		);
 	_mouse = InputDevice::create(default_allocator()
 		, "Mouse"
 		, MouseButton::COUNT
 		, MouseAxis::COUNT
+		, s_mouse_button_names
+		, s_mouse_axis_names
 		);
 	_touch = InputDevice::create(default_allocator()
 		, "Touch"
 		, TouchButton::COUNT
-		, TouchButton::COUNT
+		, 0
+		, s_touch_button_names
+		, NULL
 		);
 
 	for (uint8_t i = 0; i < CROWN_MAX_JOYPADS; ++i)
@@ -37,6 +190,8 @@ InputManager::InputManager()
 			, "Joypad"
 			, JoypadButton::COUNT
 			, JoypadAxis::COUNT
+			, s_pad_button_names
+			, s_pad_axis_names
 			);
 	}
 

+ 63 - 255
src/lua/lua_input.cpp

@@ -12,234 +12,6 @@
 namespace crown
 {
 
-struct KeyboardButtonInfo
-{
-	const char* name;
-	KeyboardButton::Enum button;
-};
-
-static KeyboardButtonInfo s_keyboard_button[] =
-{
-	{ "tab",          KeyboardButton::TAB             },
-	{ "enter",        KeyboardButton::ENTER           },
-	{ "escape",       KeyboardButton::ESCAPE          },
-	{ "space",        KeyboardButton::SPACE           },
-	{ "backspace",    KeyboardButton::BACKSPACE       },
-	{ "num_lock",     KeyboardButton::NUM_LOCK        },
-	{ "numpad_enter", KeyboardButton::NUMPAD_ENTER    },
-	{ "numpad_.",     KeyboardButton::NUMPAD_DELETE   },
-	{ "numpad_*",     KeyboardButton::NUMPAD_MULTIPLY },
-	{ "numpad_+",     KeyboardButton::NUMPAD_ADD      },
-	{ "numpad_-",     KeyboardButton::NUMPAD_SUBTRACT },
-	{ "numpad_/",     KeyboardButton::NUMPAD_DIVIDE   },
-	{ "numpad_0",     KeyboardButton::NUMPAD_0        },
-	{ "numpad_1",     KeyboardButton::NUMPAD_1        },
-	{ "numpad_2",     KeyboardButton::NUMPAD_2        },
-	{ "numpad_3",     KeyboardButton::NUMPAD_3        },
-	{ "numpad_4",     KeyboardButton::NUMPAD_4        },
-	{ "numpad_5",     KeyboardButton::NUMPAD_5        },
-	{ "numpad_6",     KeyboardButton::NUMPAD_6        },
-	{ "numpad_7",     KeyboardButton::NUMPAD_7        },
-	{ "numpad_8",     KeyboardButton::NUMPAD_8        },
-	{ "numpad_9",     KeyboardButton::NUMPAD_9        },
-	{ "f1",           KeyboardButton::F1              },
-	{ "f2",           KeyboardButton::F2              },
-	{ "f3",           KeyboardButton::F3              },
-	{ "f4",           KeyboardButton::F4              },
-	{ "f5",           KeyboardButton::F5              },
-	{ "f6",           KeyboardButton::F6              },
-	{ "f7",           KeyboardButton::F7              },
-	{ "f8",           KeyboardButton::F8              },
-	{ "f9",           KeyboardButton::F9              },
-	{ "f10",          KeyboardButton::F10             },
-	{ "f11",          KeyboardButton::F11             },
-	{ "f12",          KeyboardButton::F12             },
-	{ "home",         KeyboardButton::HOME            },
-	{ "left",         KeyboardButton::LEFT            },
-	{ "up",           KeyboardButton::UP              },
-	{ "right",        KeyboardButton::RIGHT           },
-	{ "down",         KeyboardButton::DOWN            },
-	{ "page_up",      KeyboardButton::PAGE_UP         },
-	{ "page_down",    KeyboardButton::PAGE_DOWN       },
-	{ "delete",       KeyboardButton::DELETE          },
-	{ "end",          KeyboardButton::END             },
-	{ "left_ctrl",    KeyboardButton::LEFT_CTRL       },
-	{ "right_ctrl",   KeyboardButton::RIGHT_CTRL      },
-	{ "left_shift",   KeyboardButton::LEFT_SHIFT      },
-	{ "right_shift",  KeyboardButton::RIGHT_SHIFT     },
-	{ "caps_lock",    KeyboardButton::CAPS_LOCK       },
-	{ "left_alt",     KeyboardButton::LEFT_ALT        },
-	{ "right_alt",    KeyboardButton::RIGHT_ALT       },
-	{ "left_super",   KeyboardButton::LEFT_SUPER      },
-	{ "right_super",  KeyboardButton::RIGHT_SUPER     },
-	{ "0",            KeyboardButton::NUMBER_0        },
-	{ "1",            KeyboardButton::NUMBER_1        },
-	{ "2",            KeyboardButton::NUMBER_2        },
-	{ "3",            KeyboardButton::NUMBER_3        },
-	{ "4",            KeyboardButton::NUMBER_4        },
-	{ "5",            KeyboardButton::NUMBER_5        },
-	{ "6",            KeyboardButton::NUMBER_6        },
-	{ "7",            KeyboardButton::NUMBER_7        },
-	{ "8",            KeyboardButton::NUMBER_8        },
-	{ "9",            KeyboardButton::NUMBER_9        },
-	{ "a",            KeyboardButton::A               },
-	{ "b",            KeyboardButton::B               },
-	{ "c",            KeyboardButton::C               },
-	{ "d",            KeyboardButton::D               },
-	{ "e",            KeyboardButton::E               },
-	{ "f",            KeyboardButton::F               },
-	{ "g",            KeyboardButton::G               },
-	{ "h",            KeyboardButton::H               },
-	{ "i",            KeyboardButton::I               },
-	{ "j",            KeyboardButton::J               },
-	{ "k",            KeyboardButton::K               },
-	{ "l",            KeyboardButton::L               },
-	{ "m",            KeyboardButton::M               },
-	{ "n",            KeyboardButton::N               },
-	{ "o",            KeyboardButton::O               },
-	{ "p",            KeyboardButton::P               },
-	{ "q",            KeyboardButton::Q               },
-	{ "r",            KeyboardButton::R               },
-	{ "s",            KeyboardButton::S               },
-	{ "t",            KeyboardButton::T               },
-	{ "u",            KeyboardButton::U               },
-	{ "v",            KeyboardButton::V               },
-	{ "w",            KeyboardButton::W               },
-	{ "x",            KeyboardButton::X               },
-	{ "y",            KeyboardButton::Y               },
-	{ "z",            KeyboardButton::Z               }
-};
-CE_STATIC_ASSERT(CE_COUNTOF(s_keyboard_button) == KeyboardButton::COUNT);
-
-struct MouseButtonInfo
-{
-	const char* name;
-	MouseButton::Enum button;
-};
-
-static MouseButtonInfo s_mouse_button[] =
-{
-	{ "left",    MouseButton::LEFT    },
-	{ "middle",  MouseButton::MIDDLE  },
-	{ "right",   MouseButton::RIGHT   },
-	{ "extra_1", MouseButton::EXTRA_1 },
-	{ "extra_2", MouseButton::EXTRA_2 }
-};
-CE_STATIC_ASSERT(CE_COUNTOF(s_mouse_button) == MouseButton::COUNT);
-
-struct MouseAxisInfo
-{
-	const char* name;
-	MouseAxis::Enum button;
-};
-
-static MouseAxisInfo s_mouse_axis[] =
-{
-	{ "cursor",       MouseAxis::CURSOR       },
-	{ "cursor_delta", MouseAxis::CURSOR_DELTA },
-	{ "wheel",        MouseAxis::WHEEL        }
-};
-CE_STATIC_ASSERT(CE_COUNTOF(s_mouse_axis) == MouseAxis::COUNT);
-
-struct PadButtonInfo
-{
-	const char* name;
-	JoypadButton::Enum button;
-};
-
-static PadButtonInfo s_pad_button[] =
-{
-	{ "up",             JoypadButton::UP             },
-	{ "down",           JoypadButton::DOWN           },
-	{ "left",           JoypadButton::LEFT           },
-	{ "right",          JoypadButton::RIGHT          },
-	{ "start",          JoypadButton::START          },
-	{ "back",           JoypadButton::BACK           },
-	{ "guide",          JoypadButton::GUIDE          },
-	{ "left_thumb",     JoypadButton::LEFT_THUMB     },
-	{ "right_thumb",    JoypadButton::RIGHT_THUMB    },
-	{ "left_shoulder",  JoypadButton::LEFT_SHOULDER  },
-	{ "right_shoulder", JoypadButton::RIGHT_SHOULDER },
-	{ "a",              JoypadButton::A              },
-	{ "b",              JoypadButton::B              },
-	{ "x",              JoypadButton::X              },
-	{ "y",              JoypadButton::Y              }
-};
-CE_STATIC_ASSERT(CE_COUNTOF(s_pad_button) == JoypadButton::COUNT);
-
-struct PadAxisInfo
-{
-	const char* name;
-	JoypadAxis::Enum button;
-};
-
-static PadAxisInfo s_pad_axis[] =
-{
-	{ "left",  JoypadAxis::LEFT  },
-	{ "right", JoypadAxis::RIGHT }
-};
-CE_STATIC_ASSERT(CE_COUNTOF(s_pad_axis) == JoypadAxis::COUNT);
-
-static KeyboardButton::Enum name_to_keyboard_button(LuaStack& stack, const char* name)
-{
-	for (uint32_t i = 0; i < CE_COUNTOF(s_keyboard_button); ++i)
-	{
-		if (strcmp(s_keyboard_button[i].name, name) == 0)
-			return s_keyboard_button[i].button;
-	}
-
-	LUA_ASSERT(false, stack, "Unknown button: %s", name);
-	return KeyboardButton::COUNT;
-}
-
-static MouseButton::Enum name_to_mouse_button(LuaStack& stack, const char* name)
-{
-	for (uint32_t i = 0; i < CE_COUNTOF(s_mouse_button); ++i)
-	{
-		if (strcmp(s_mouse_button[i].name, name) == 0)
-			return s_mouse_button[i].button;
-	}
-
-	LUA_ASSERT(false, stack, "Unknown button: %s", name);
-	return MouseButton::COUNT;
-}
-
-static MouseAxis::Enum name_to_mouse_axis(LuaStack& stack, const char* name)
-{
-	for (uint32_t i = 0; i < CE_COUNTOF(s_mouse_axis); ++i)
-	{
-		if (strcmp(s_mouse_axis[i].name, name) == 0)
-			return s_mouse_axis[i].button;
-	}
-
-	LUA_ASSERT(false, stack, "Unknown axis: %s", name);
-	return MouseAxis::COUNT;
-}
-
-static JoypadButton::Enum name_to_pad_button(LuaStack& stack, const char* name)
-{
-	for (uint32_t i = 0; i < CE_COUNTOF(s_pad_button); ++i)
-	{
-		if (strcmp(s_pad_button[i].name, name) == 0)
-			return s_pad_button[i].button;
-	}
-
-	LUA_ASSERT(false, stack, "Unknown button: %s", name);
-	return JoypadButton::COUNT;
-}
-
-static JoypadAxis::Enum name_to_pad_axis(LuaStack& stack, const char* name)
-{
-	for (uint32_t i = 0; i < CE_COUNTOF(s_pad_axis); ++i)
-	{
-		if (strcmp(s_pad_axis[i].name, name) == 0)
-			return s_pad_axis[i].button;
-	}
-
-	LUA_ASSERT(false, stack, "Unknown button: %s", name);
-	return JoypadAxis::COUNT;
-}
-
 static int input_device_name(lua_State* L, InputDevice& id)
 {
 	LuaStack stack(L);
@@ -303,38 +75,31 @@ static int input_device_axis(lua_State* L, InputDevice& id)
 	return 1;
 }
 
-static int keyboard_button_id(lua_State* L)
-{
-	LuaStack stack(L);
-	stack.push_int(name_to_keyboard_button(stack, stack.get_string(1)));
-	return 1;
-}
-
-static int mouse_button_id(lua_State* L)
+static int input_device_button_name(lua_State* L, InputDevice& id)
 {
 	LuaStack stack(L);
-	stack.push_int(name_to_mouse_button(stack, stack.get_string(1)));
+	stack.push_string(id.button_name(stack.get_int(1)));
 	return 1;
 }
 
-static int mouse_axis_id(lua_State* L)
+static int input_device_axis_name(lua_State* L, InputDevice& id)
 {
 	LuaStack stack(L);
-	stack.push_int(name_to_mouse_axis(stack, stack.get_string(1)));
+	stack.push_string(id.axis_name(stack.get_int(1)));
 	return 1;
 }
 
-static int pad_button_id(lua_State* L)
+static int input_device_button_id(lua_State* L, InputDevice& id)
 {
 	LuaStack stack(L);
-	stack.push_int(name_to_pad_button(stack, stack.get_string(1)));
+	stack.push_int(id.button_id(stack.get_string_id(1)));
 	return 1;
 }
 
-static int pad_axis_id(lua_State* L)
+static int input_device_axis_id(lua_State* L, InputDevice& id)
 {
 	LuaStack stack(L);
-	stack.push_int(name_to_pad_axis(stack, stack.get_string(1)));
+	stack.push_int(id.axis_id(stack.get_string_id(1)));
 	return 1;
 }
 
@@ -360,7 +125,11 @@ KEYBOARD(pressed)
 KEYBOARD(released)
 KEYBOARD(any_pressed)
 KEYBOARD(any_released)
-// KEYBOARD(axis) // Keyboard has no axis
+// KEYBOARD(axis)
+KEYBOARD(button_name)
+// KEYBOARD(axis_name)
+KEYBOARD(button_id)
+// KEYBOARD(axis_id)
 
 MOUSE(name)
 MOUSE(connected)
@@ -371,6 +140,10 @@ MOUSE(released)
 MOUSE(any_pressed)
 MOUSE(any_released)
 MOUSE(axis)
+MOUSE(button_name)
+MOUSE(axis_name)
+MOUSE(button_id)
+MOUSE(axis_id)
 
 TOUCH(name)
 TOUCH(connected)
@@ -381,6 +154,10 @@ TOUCH(released)
 TOUCH(any_pressed)
 TOUCH(any_released)
 TOUCH(axis)
+TOUCH(button_name)
+TOUCH(axis_name)
+TOUCH(button_id)
+TOUCH(axis_id)
 
 JOYPAD(0, name)
 JOYPAD(0, connected)
@@ -391,6 +168,10 @@ JOYPAD(0, released)
 JOYPAD(0, any_pressed)
 JOYPAD(0, any_released)
 JOYPAD(0, axis)
+JOYPAD(0, button_name)
+JOYPAD(0, axis_name)
+JOYPAD(0, button_id)
+JOYPAD(0, axis_id)
 
 JOYPAD(1, name)
 JOYPAD(1, connected)
@@ -401,6 +182,10 @@ JOYPAD(1, released)
 JOYPAD(1, any_pressed)
 JOYPAD(1, any_released)
 JOYPAD(1, axis)
+JOYPAD(1, button_name)
+JOYPAD(1, axis_name)
+JOYPAD(1, button_id)
+JOYPAD(1, axis_id)
 
 JOYPAD(2, name)
 JOYPAD(2, connected)
@@ -411,6 +196,10 @@ JOYPAD(2, released)
 JOYPAD(2, any_pressed)
 JOYPAD(2, any_released)
 JOYPAD(2, axis)
+JOYPAD(2, button_name)
+JOYPAD(2, axis_name)
+JOYPAD(2, button_id)
+JOYPAD(2, axis_id)
 
 JOYPAD(3, name)
 JOYPAD(3, connected)
@@ -421,6 +210,10 @@ JOYPAD(3, released)
 JOYPAD(3, any_pressed)
 JOYPAD(3, any_released)
 JOYPAD(3, axis)
+JOYPAD(3, button_name)
+JOYPAD(3, axis_name)
+JOYPAD(3, button_id)
+JOYPAD(3, axis_id)
 
 void load_input(LuaEnvironment& env)
 {
@@ -432,7 +225,8 @@ void load_input(LuaEnvironment& env)
 	env.load_module_function("Keyboard", "released",     KEYBOARD_FN(released));
 	env.load_module_function("Keyboard", "any_pressed",  KEYBOARD_FN(any_pressed));
 	env.load_module_function("Keyboard", "any_released", KEYBOARD_FN(any_released));
-	env.load_module_function("Keyboard", "button_id",    keyboard_button_id);
+	env.load_module_function("Keyboard", "button_name",  KEYBOARD_FN(button_name));
+	env.load_module_function("Keyboard", "button_id",    KEYBOARD_FN(button_id));
 
 	env.load_module_function("Mouse", "name",         MOUSE_FN(name));
 	env.load_module_function("Mouse", "connected",    MOUSE_FN(connected));
@@ -443,8 +237,10 @@ void load_input(LuaEnvironment& env)
 	env.load_module_function("Mouse", "any_pressed",  MOUSE_FN(any_pressed));
 	env.load_module_function("Mouse", "any_released", MOUSE_FN(any_released));
 	env.load_module_function("Mouse", "axis",         MOUSE_FN(axis));
-	env.load_module_function("Mouse", "button_id",    mouse_button_id);
-	env.load_module_function("Mouse", "axis_id",      mouse_axis_id);
+	env.load_module_function("Mouse", "button_name",  MOUSE_FN(button_name));
+	env.load_module_function("Mouse", "axis_name",    MOUSE_FN(axis_name));
+	env.load_module_function("Mouse", "button_id",    MOUSE_FN(button_id));
+	env.load_module_function("Mouse", "axis_id",      MOUSE_FN(axis_id));
 
 	env.load_module_function("Touch", "name",         TOUCH_FN(name));
 	env.load_module_function("Touch", "connected",    TOUCH_FN(connected));
@@ -455,6 +251,10 @@ void load_input(LuaEnvironment& env)
 	env.load_module_function("Touch", "any_pressed",  TOUCH_FN(any_pressed));
 	env.load_module_function("Touch", "any_released", TOUCH_FN(any_released));
 	env.load_module_function("Touch", "axis",         TOUCH_FN(axis));
+	env.load_module_function("Touch", "button_name",  TOUCH_FN(button_name));
+	env.load_module_function("Touch", "axis_name",    TOUCH_FN(axis_name));
+	env.load_module_function("Touch", "button_id",    TOUCH_FN(button_id));
+	env.load_module_function("Touch", "axis_id",      TOUCH_FN(axis_id));
 
 	env.load_module_function("Pad1", "name",         JOYPAD_FN(0, name));
 	env.load_module_function("Pad1", "connected",    JOYPAD_FN(0, connected));
@@ -465,8 +265,10 @@ void load_input(LuaEnvironment& env)
 	env.load_module_function("Pad1", "any_pressed",  JOYPAD_FN(0, any_pressed));
 	env.load_module_function("Pad1", "any_released", JOYPAD_FN(0, any_released));
 	env.load_module_function("Pad1", "axis",         JOYPAD_FN(0, axis));
-	env.load_module_function("Pad1", "button_id",    pad_button_id);
-	env.load_module_function("Pad1", "axis_id",      pad_axis_id);
+	env.load_module_function("Pad1", "button_name",  JOYPAD_FN(0, button_name));
+	env.load_module_function("Pad1", "axis_name",    JOYPAD_FN(0, axis_name));
+	env.load_module_function("Pad1", "button_id",    JOYPAD_FN(0, button_id));
+	env.load_module_function("Pad1", "axis_id",      JOYPAD_FN(0, axis_id));
 
 	env.load_module_function("Pad2", "name",         JOYPAD_FN(1, name));
 	env.load_module_function("Pad2", "connected",    JOYPAD_FN(1, connected));
@@ -477,8 +279,10 @@ void load_input(LuaEnvironment& env)
 	env.load_module_function("Pad2", "any_pressed",  JOYPAD_FN(1, any_pressed));
 	env.load_module_function("Pad2", "any_released", JOYPAD_FN(1, any_released));
 	env.load_module_function("Pad2", "axis",         JOYPAD_FN(1, axis));
-	env.load_module_function("Pad2", "button_id",    pad_button_id);
-	env.load_module_function("Pad2", "axis_id",      pad_axis_id);
+	env.load_module_function("Pad2", "button_name",  JOYPAD_FN(1, button_name));
+	env.load_module_function("Pad2", "axis_name",    JOYPAD_FN(1, axis_name));
+	env.load_module_function("Pad2", "button_id",    JOYPAD_FN(1, button_id));
+	env.load_module_function("Pad2", "axis_id",      JOYPAD_FN(1, axis_id));
 
 	env.load_module_function("Pad3", "name",         JOYPAD_FN(2, name));
 	env.load_module_function("Pad3", "connected",    JOYPAD_FN(2, connected));
@@ -489,8 +293,10 @@ void load_input(LuaEnvironment& env)
 	env.load_module_function("Pad3", "any_pressed",  JOYPAD_FN(2, any_pressed));
 	env.load_module_function("Pad3", "any_released", JOYPAD_FN(2, any_released));
 	env.load_module_function("Pad3", "axis",         JOYPAD_FN(2, axis));
-	env.load_module_function("Pad3", "button_id",    pad_button_id);
-	env.load_module_function("Pad3", "axis_id",      pad_axis_id);
+	env.load_module_function("Pad3", "button_name",  JOYPAD_FN(2, button_name));
+	env.load_module_function("Pad3", "axis_name",    JOYPAD_FN(2, axis_name));
+	env.load_module_function("Pad3", "button_id",    JOYPAD_FN(2, button_id));
+	env.load_module_function("Pad3", "axis_id",      JOYPAD_FN(2, axis_id));
 
 	env.load_module_function("Pad4", "name",         JOYPAD_FN(3, name));
 	env.load_module_function("Pad4", "connected",    JOYPAD_FN(3, connected));
@@ -501,8 +307,10 @@ void load_input(LuaEnvironment& env)
 	env.load_module_function("Pad4", "any_pressed",  JOYPAD_FN(3, any_pressed));
 	env.load_module_function("Pad4", "any_released", JOYPAD_FN(3, any_released));
 	env.load_module_function("Pad4", "axis",         JOYPAD_FN(3, axis));
-	env.load_module_function("Pad4", "button_id",    pad_button_id);
-	env.load_module_function("Pad4", "axis_id",      pad_axis_id);
+	env.load_module_function("Pad4", "button_name",  JOYPAD_FN(3, button_name));
+	env.load_module_function("Pad4", "axis_name",    JOYPAD_FN(3, axis_name));
+	env.load_module_function("Pad4", "button_id",    JOYPAD_FN(3, button_id));
+	env.load_module_function("Pad4", "axis_id",      JOYPAD_FN(3, axis_id));
 }
 
 } // namespace crown

+ 1 - 1
src/lua/lua_stack.h

@@ -213,7 +213,7 @@ struct LuaStack
 
 	StringId32 get_string_id(int i)
 	{
-		return StringId32(uint32_t(CHECKINTEGER(L, i)));
+		return StringId32(get_string(i));
 	}
 
 	float get_float(int i)

+ 161 - 1
src/main/main_linux.cpp

@@ -177,6 +177,158 @@ static KeyboardButton::Enum x11_translate_key(KeySym x11_key)
 	}
 }
 
+#define JS_EVENT_BUTTON 0x01 /* button pressed/released */
+#define JS_EVENT_AXIS   0x02 /* joystick moved */
+#define JS_EVENT_INIT   0x80 /* initial state of device */
+
+#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE  7849
+#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
+#define XINPUT_GAMEPAD_THRESHOLD            30
+
+static uint8_t s_button[] =
+{
+	JoypadButton::A,
+	JoypadButton::B,
+	JoypadButton::X,
+	JoypadButton::Y,
+	JoypadButton::LEFT_SHOULDER,
+	JoypadButton::RIGHT_SHOULDER,
+	JoypadButton::BACK,
+	JoypadButton::START,
+	JoypadButton::GUIDE,
+	JoypadButton::LEFT_THUMB,
+	JoypadButton::RIGHT_THUMB,
+	JoypadButton::UP, // FIXME (reported as axis...)
+	JoypadButton::DOWN,
+	JoypadButton::LEFT,
+	JoypadButton::RIGHT
+};
+
+static uint16_t s_deadzone[] =
+{
+	XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE,
+	XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE,
+	XINPUT_GAMEPAD_THRESHOLD,
+	XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE,
+	XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE,
+	XINPUT_GAMEPAD_THRESHOLD
+};
+
+struct JoypadEvent
+{
+	uint32_t time;  /* event timestamp in milliseconds */
+	int16_t value;  /* value */
+	uint8_t type;   /* event type */
+	uint8_t number; /* axis/button number */
+};
+
+struct Joypad
+{
+	void init()
+	{
+		char jspath[] = "/dev/input/jsX";
+		char* num = strchr(jspath, 'X');
+
+		for (uint8_t i = 0; i < CROWN_MAX_JOYPADS; ++i)
+		{
+			*num = '0' + i;
+			_fd[i] = open(jspath, O_RDONLY | O_NONBLOCK);
+		}
+
+		memset(_connected, 0, sizeof(_connected));
+		memset(_axis, 0, sizeof(_axis));
+	}
+
+	void shutdown()
+	{
+		for (uint8_t i = 0; i < CROWN_MAX_JOYPADS; ++i)
+		{
+			if (_fd[i] != -1)
+				close(_fd[i]);
+		}
+	}
+
+	void update(OsEventQueue& queue)
+	{
+		JoypadEvent ev;
+		memset(&ev, 0, sizeof(ev));
+
+		for (uint8_t i = 0; i < CROWN_MAX_JOYPADS; ++i)
+		{
+			const int fd = _fd[i];
+			const bool connected = fd != -1;
+
+			if (connected != _connected[i])
+				queue.push_joypad_event(i, connected);
+
+			_connected[i] = connected;
+
+			if (!connected)
+				continue;
+
+			while(read(fd, &ev, sizeof(ev)) != -1)
+			{
+				const uint8_t num = ev.number;
+				const int16_t val = ev.value;
+
+				switch (ev.type &= ~JS_EVENT_INIT)
+				{
+					case JS_EVENT_AXIS:
+					{
+						AxisData& axis = _axis[i];
+						// Indices into axis.left/right respectively
+						const uint8_t axis_idx[] = { 0, 1, 2, 0, 1, 2 };
+						const int16_t deadzone = s_deadzone[num];
+
+						int16_t value = val > deadzone || val < -deadzone ? val : 0;
+
+						// Remap triggers to [0, INT16_MAX]
+						if (num == 2 || num == 5)
+							value = (value + INT16_MAX) >> 1;
+
+						float* values = num > 2 ? axis.right : axis.left;
+
+						values[axis_idx[num]] = value != 0
+							? float(value + (value < 0 ? deadzone : -deadzone)) / float(INT16_MAX - deadzone)
+							: 0.0f
+							;
+
+						queue.push_joypad_event(i
+							, num > 2 ? 1 : 0
+							, values[0]
+							, -values[1]
+							, values[2]
+							);
+						break;
+					}
+					case JS_EVENT_BUTTON:
+					{
+						if (ev.number < CE_COUNTOF(s_button))
+						{
+							queue.push_joypad_event(i
+								, s_button[ev.number]
+								, val == 1
+								);
+						}
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	int _fd[CROWN_MAX_JOYPADS];
+	bool _connected[CROWN_MAX_JOYPADS];
+
+	struct AxisData
+	{
+		float left[3];
+		float right[3];
+	};
+
+	AxisData _axis[CROWN_MAX_JOYPADS];
+};
+
 static bool s_exit = false;
 
 struct MainThreadArgs
@@ -233,7 +385,8 @@ struct LinuxDevice
 			| ButtonPressMask
 			| ButtonReleaseMask
 			| PointerMotionMask
-			| EnterWindowMask;
+			| EnterWindowMask
+			;
 
 		_x11_window = XCreateWindow(_x11_display
 			, parent_window
@@ -284,11 +437,15 @@ struct LinuxDevice
 		Thread main_thread;
 		main_thread.start(func, &mta);
 
+		_joypad.init();
+
 		while (!s_exit)
 		{
 			pump_events();
 		}
 
+		_joypad.shutdown();
+
 		main_thread.stop();
 
 		// Restore previous screen configuration
@@ -314,6 +471,8 @@ struct LinuxDevice
 
 	void pump_events()
 	{
+		_joypad.update(_queue);
+
 		while (XPending(_x11_display))
 		{
 			XEvent event;
@@ -411,6 +570,7 @@ public:
 	XRRScreenConfiguration* _screen_config;
 	bool _x11_detectable_autorepeat;
 	OsEventQueue _queue;
+	Joypad _joypad;
 };
 
 static LinuxDevice s_ldvc;

+ 31 - 13
src/main/main_windows.cpp

@@ -190,64 +190,82 @@ struct Joypad
 
 			if (state.Gamepad.sThumbLX != gamepad.sThumbLX)
 			{
-				int32_t value = state.Gamepad.sThumbLX;
+				SHORT value = state.Gamepad.sThumbLX;
 				value = value > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE || value < -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE
 					? value : 0;
 
-				_axis[0].lx = (float)value / (float)INT16_MAX;
+				_axis[0].lx = value != 0
+					? float(value + (value < 0 ? XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE : -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)) / float(INT16_MAX - XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
+					: 0.0f
+					;
 				queue.push_joypad_event(i, JoypadAxis::LEFT, _axis[0].lx, _axis[0].ly, _axis[0].lz);
 
 				gamepad.sThumbLX = state.Gamepad.sThumbLX;
 			}
 			if (state.Gamepad.sThumbLY != gamepad.sThumbLY)
 			{
-				int32_t value = state.Gamepad.sThumbLY;
+				SHORT value = state.Gamepad.sThumbLY;
 				value = value > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE || value < -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE
 					? value : 0;
 
-				_axis[0].ly = (float)value / (float)INT16_MAX;
+				_axis[0].ly = value != 0
+					? float(value + (value < 0 ? XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE : -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)) / float(INT16_MAX - XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
+					: 0.0f
+					;
 				queue.push_joypad_event(i, JoypadAxis::LEFT, _axis[0].lx, _axis[0].ly, _axis[0].lz);
 
 				gamepad.sThumbLY = state.Gamepad.sThumbLY;
 			}
 			if (state.Gamepad.bLeftTrigger != gamepad.bLeftTrigger)
 			{
-				int32_t value = state.Gamepad.bLeftTrigger;
-				value = value >XINPUT_GAMEPAD_TRIGGER_THRESHOLD ? value : 0;
+				BYTE value = state.Gamepad.bLeftTrigger;
+				value = value > XINPUT_GAMEPAD_TRIGGER_THRESHOLD ? value : 0;
 
-				_axis[0].lz = (float)value / (float)UINT8_MAX;
+				_axis[0].lz = value != 0
+					? float(value + (value < 0 ? XINPUT_GAMEPAD_TRIGGER_THRESHOLD : -XINPUT_GAMEPAD_TRIGGER_THRESHOLD)) / float(UINT8_MAX - XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
+					: 0.0f
+					;
 				queue.push_joypad_event(i, JoypadAxis::LEFT, _axis[0].lx, _axis[0].ly, _axis[0].lz);
 
 				gamepad.bLeftTrigger = state.Gamepad.bLeftTrigger;
 			}
 			if (state.Gamepad.sThumbRX != gamepad.sThumbRX)
 			{
-				int32_t value = state.Gamepad.sThumbRX;
+				SHORT value = state.Gamepad.sThumbRX;
 				value = value > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE || value < -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE
 					? value : 0;
 
-				_axis[0].rx = (float)value / (float)INT16_MAX;
+				_axis[0].rx = value != 0
+					? float(value + (value < 0 ? XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE : -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)) / float(INT16_MAX - XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
+					: 0.0f
+					;
 				queue.push_joypad_event(i, JoypadAxis::RIGHT, _axis[0].rx, _axis[0].ry, _axis[0].rz);
 
 				gamepad.sThumbRX = state.Gamepad.sThumbRX;
 			}
 			if (state.Gamepad.sThumbRY != gamepad.sThumbRY)
 			{
-				int32_t value = state.Gamepad.sThumbRY;
+				SHORT value = state.Gamepad.sThumbRY;
 				value = value > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE || value < -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE
 					? value : 0;
 
-				_axis[0].ry = (float)value / (float)INT16_MAX;
+				_axis[0].ry = value != 0
+					? float(value + (value < 0 ? XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE : -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)) / float(INT16_MAX - XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
+					: 0.0f
+					;
 				queue.push_joypad_event(i, JoypadAxis::RIGHT, _axis[0].rx, _axis[0].ry, _axis[0].rz);
 
 				gamepad.sThumbRY = state.Gamepad.sThumbRY;
 			}
 			if (state.Gamepad.bRightTrigger != gamepad.bRightTrigger)
 			{
-				int32_t value = state.Gamepad.bRightTrigger;
+				BYTE value = state.Gamepad.bRightTrigger;
 				value = value > XINPUT_GAMEPAD_TRIGGER_THRESHOLD ? value : 0;
 
-				_axis[0].rz = (float)value / (float)UINT8_MAX;
+				_axis[0].rz = value != 0
+					? float(value + (value < 0 ? XINPUT_GAMEPAD_TRIGGER_THRESHOLD : -XINPUT_GAMEPAD_TRIGGER_THRESHOLD)) / float(UINT8_MAX - XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
+					: 0.0f
+					;
 				queue.push_joypad_event(i, JoypadAxis::RIGHT, _axis[0].rx, _axis[0].ry, _axis[0].rz);
 
 				gamepad.bRightTrigger = state.Gamepad.bRightTrigger;

+ 5 - 5
src/renderers/debug_line.cpp

@@ -55,11 +55,11 @@ namespace debug_line
 #elif CROWN_PLATFORM_WINDOWS
 	static const uint8_t vs_h[419] =
 	{
-		0x56, 0x53, 0x48, 0x03, 0xa4, 0x8b, 0xef, 0x49, 0x01, 0x00, 0x0f, 0x75, 0x5f, 0x6d, 0x6f, 0x64, // VSH....I...u_mod
-		0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x09, 0x01, 0x00, 0x00, 0x04, 0x00, // elViewProj......
+		0x56, 0x53, 0x48, 0x04, 0xa4, 0x8b, 0xef, 0x49, 0x01, 0x00, 0x0f, 0x75, 0x5f, 0x6d, 0x6f, 0x64, // VSH....I...u_mod
+		0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x04, 0x01, 0x00, 0x00, 0x04, 0x00, // elViewProj......
 		0x80, 0x01, 0x00, 0x03, 0xfe, 0xff, 0xfe, 0xff, 0x23, 0x00, 0x43, 0x54, 0x41, 0x42, 0x1c, 0x00, // ........#.CTAB..
 		0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, // ..W.............
-		0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, // ......P...0.....
+		0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, // ......P...0.....
 		0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, // [email protected]_
 		0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x00, 0x03, 0x00, // modelViewProj...
 		0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x73, // ..............vs
@@ -86,9 +86,9 @@ namespace debug_line
 
 	static const uint8_t fs_h[137] =
 	{
-		0x46, 0x53, 0x48, 0x03, 0xa4, 0x8b, 0xef, 0x49, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x03, 0xff, 0xff, // FSH....I..|.....
+		0x46, 0x53, 0x48, 0x04, 0xa4, 0x8b, 0xef, 0x49, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x03, 0xff, 0xff, // FSH....I..|.....
 		0xfe, 0xff, 0x16, 0x00, 0x43, 0x54, 0x41, 0x42, 0x1c, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, // ....CTAB....#...
-		0x00, 0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, // ................
+		0x00, 0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, // ................
 		0x1c, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5f, 0x33, 0x5f, 0x30, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, // ....ps_3_0.Micro
 		0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, // soft (R) HLSL Sh
 		0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, // ader Compiler 9.