|
|
@@ -13,11 +13,66 @@
|
|
|
#include <sys/time.h>
|
|
|
#include <GL/glxew.h>
|
|
|
#include <poll.h>
|
|
|
+#include <sys/types.h>
|
|
|
+#include <sys/stat.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <fcntl.h>
|
|
|
+#include <errno.h>
|
|
|
+#include <fstream>
|
|
|
|
|
|
#define TOUCH_COUNT_MAX 4
|
|
|
+#define MAX_GAMEPADS 4
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
+enum GamepadAxisInfoFlags
|
|
|
+{
|
|
|
+ GP_AXIS_SKIP = 0x1,
|
|
|
+ GP_AXIS_IS_DPAD = 0x2,
|
|
|
+ GP_AXIS_IS_NEG = 0x4,
|
|
|
+ GP_AXIS_IS_XAXIS = 0x8,
|
|
|
+ GP_AXIS_IS_TRIGGER = 0x10
|
|
|
+};
|
|
|
+
|
|
|
+enum GamepadAxisInfoNormalizeFunction
|
|
|
+{
|
|
|
+ NEG_TO_POS,
|
|
|
+ ZERO_TO_POS
|
|
|
+};
|
|
|
+
|
|
|
+struct GamepadJoystickAxisInfo
|
|
|
+{
|
|
|
+ int axisIndex;
|
|
|
+ unsigned int joystickIndex;
|
|
|
+ unsigned long flags;
|
|
|
+ int mappedPosArg;
|
|
|
+ int mappedNegArg;
|
|
|
+ float deadZone;
|
|
|
+ GamepadAxisInfoNormalizeFunction mapFunc;
|
|
|
+};
|
|
|
+
|
|
|
+struct GamepadInfoEntry
|
|
|
+{
|
|
|
+ unsigned int vendorId;
|
|
|
+ unsigned int productId;
|
|
|
+ const char* productName;
|
|
|
+ unsigned int numberOfJS;
|
|
|
+ unsigned int numberOfAxes;
|
|
|
+ unsigned int numberOfButtons;
|
|
|
+ unsigned int numberOfTriggers;
|
|
|
+
|
|
|
+ GamepadJoystickAxisInfo* axes;
|
|
|
+ long* buttons;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+struct ConnectedGamepadDevInfo
|
|
|
+{
|
|
|
+ dev_t deviceId;
|
|
|
+ gameplay::GamepadHandle fd;
|
|
|
+ const GamepadInfoEntry& gamepadInfo;
|
|
|
+};
|
|
|
+
|
|
|
struct timespec __timespec;
|
|
|
static double __timeStart;
|
|
|
static double __timeAbsolute;
|
|
|
@@ -35,1166 +90,1585 @@ static int __windowSize[2];
|
|
|
static GLXContext __context;
|
|
|
static Window __attachToWindow;
|
|
|
static Atom __atomWmDeleteWindow;
|
|
|
+static list<ConnectedGamepadDevInfo> __connectedGamepads;
|
|
|
|
|
|
-namespace gameplay
|
|
|
-{
|
|
|
|
|
|
-// Gets the Keyboard::Key enumeration constant that corresponds to the given X11 key symbol.
|
|
|
-static Keyboard::Key getKey(KeySym sym)
|
|
|
+// Gets the gameplay::Keyboard::Key enumeration constant that corresponds to the given X11 key symbol.
|
|
|
+static gameplay::Keyboard::Key getKey(KeySym sym)
|
|
|
{
|
|
|
switch (sym)
|
|
|
{
|
|
|
- case XK_Sys_Req:
|
|
|
- return Keyboard::KEY_SYSREQ;
|
|
|
- case XK_Break:
|
|
|
- return Keyboard::KEY_BREAK;
|
|
|
- case XK_Menu :
|
|
|
- return Keyboard::KEY_MENU;
|
|
|
- case XK_KP_Enter:
|
|
|
- return Keyboard::KEY_KP_ENTER;
|
|
|
- case XK_Pause:
|
|
|
- return Keyboard::KEY_PAUSE;
|
|
|
- case XK_Scroll_Lock:
|
|
|
- return Keyboard::KEY_SCROLL_LOCK;
|
|
|
- case XK_Print:
|
|
|
- return Keyboard::KEY_PRINT;
|
|
|
- case XK_Escape:
|
|
|
- return Keyboard::KEY_ESCAPE;
|
|
|
- case XK_BackSpace:
|
|
|
- return Keyboard::KEY_BACKSPACE;
|
|
|
- case XK_Tab:
|
|
|
- return Keyboard::KEY_TAB;
|
|
|
- case XK_Return:
|
|
|
- return Keyboard::KEY_RETURN;
|
|
|
- case XK_Caps_Lock:
|
|
|
- return Keyboard::KEY_CAPS_LOCK;
|
|
|
- case XK_Shift_L:
|
|
|
- case XK_Shift_R:
|
|
|
- return Keyboard::KEY_SHIFT;
|
|
|
- case XK_Control_L:
|
|
|
- case XK_Control_R:
|
|
|
- return Keyboard::KEY_CTRL;
|
|
|
- case XK_Alt_L:
|
|
|
- case XK_Alt_R:
|
|
|
- return Keyboard::KEY_ALT;
|
|
|
- case XK_Hyper_L:
|
|
|
- case XK_Hyper_R:
|
|
|
- return Keyboard::KEY_HYPER;
|
|
|
- case XK_Insert:
|
|
|
- return Keyboard::KEY_INSERT;
|
|
|
- case XK_Home:
|
|
|
- return Keyboard::KEY_HOME;
|
|
|
- case XK_Page_Up:
|
|
|
- return Keyboard::KEY_PG_UP;
|
|
|
- case XK_Delete:
|
|
|
- return Keyboard::KEY_DELETE;
|
|
|
- case XK_End:
|
|
|
- return Keyboard::KEY_END;
|
|
|
- case XK_Page_Down:
|
|
|
- return Keyboard::KEY_PG_DOWN;
|
|
|
- case XK_Left:
|
|
|
- return Keyboard::KEY_LEFT_ARROW;
|
|
|
- case XK_Right:
|
|
|
- return Keyboard::KEY_RIGHT_ARROW;
|
|
|
- case XK_Up:
|
|
|
- return Keyboard::KEY_UP_ARROW;
|
|
|
- case XK_Down:
|
|
|
- return Keyboard::KEY_DOWN_ARROW;
|
|
|
- case XK_Num_Lock:
|
|
|
- return Keyboard::KEY_NUM_LOCK;
|
|
|
- case XK_KP_Add:
|
|
|
- return Keyboard::KEY_KP_PLUS;
|
|
|
- case XK_KP_Subtract:
|
|
|
- return Keyboard::KEY_KP_MINUS;
|
|
|
- case XK_KP_Multiply:
|
|
|
- return Keyboard::KEY_KP_MULTIPLY;
|
|
|
- case XK_KP_Divide:
|
|
|
- return Keyboard::KEY_KP_DIVIDE;
|
|
|
- case XK_KP_Home:
|
|
|
- return Keyboard::KEY_KP_HOME;
|
|
|
- case XK_KP_Up:
|
|
|
- return Keyboard::KEY_KP_UP;
|
|
|
- case XK_KP_Page_Up:
|
|
|
- return Keyboard::KEY_KP_PG_UP;
|
|
|
- case XK_KP_Left:
|
|
|
- return Keyboard::KEY_KP_LEFT;
|
|
|
- case XK_KP_5:
|
|
|
- return Keyboard::KEY_KP_FIVE;
|
|
|
- case XK_KP_Right:
|
|
|
- return Keyboard::KEY_KP_RIGHT;
|
|
|
- case XK_KP_End:
|
|
|
- return Keyboard::KEY_KP_END;
|
|
|
- case XK_KP_Down:
|
|
|
- return Keyboard::KEY_KP_DOWN;
|
|
|
- case XK_KP_Page_Down:
|
|
|
- return Keyboard::KEY_KP_PG_DOWN;
|
|
|
- case XK_KP_Insert:
|
|
|
- return Keyboard::KEY_KP_INSERT;
|
|
|
- case XK_KP_Delete:
|
|
|
- return Keyboard::KEY_KP_DELETE;
|
|
|
- case XK_F1:
|
|
|
- return Keyboard::KEY_F1;
|
|
|
- case XK_F2:
|
|
|
- return Keyboard::KEY_F2;
|
|
|
- case XK_F3:
|
|
|
- return Keyboard::KEY_F3;
|
|
|
- case XK_F4:
|
|
|
- return Keyboard::KEY_F4;
|
|
|
- case XK_F5:
|
|
|
- return Keyboard::KEY_F5;
|
|
|
- case XK_F6:
|
|
|
- return Keyboard::KEY_F6;
|
|
|
- case XK_F7:
|
|
|
- return Keyboard::KEY_F7;
|
|
|
- case XK_F8:
|
|
|
- return Keyboard::KEY_F8;
|
|
|
- case XK_F9:
|
|
|
- return Keyboard::KEY_F9;
|
|
|
- case XK_F10:
|
|
|
- return Keyboard::KEY_F10;
|
|
|
- case XK_F11:
|
|
|
- return Keyboard::KEY_F11;
|
|
|
- case XK_F12:
|
|
|
- return Keyboard::KEY_F12;
|
|
|
- case XK_KP_Space:
|
|
|
- case XK_space:
|
|
|
- return Keyboard::KEY_SPACE;
|
|
|
- case XK_parenright:
|
|
|
- return Keyboard::KEY_RIGHT_PARENTHESIS;
|
|
|
- case XK_0:
|
|
|
- return Keyboard::KEY_ZERO;
|
|
|
- case XK_exclam:
|
|
|
- return Keyboard::KEY_EXCLAM;
|
|
|
- case XK_1:
|
|
|
- return Keyboard::KEY_ONE;
|
|
|
- case XK_at:
|
|
|
- return Keyboard::KEY_AT;
|
|
|
- case XK_2:
|
|
|
- return Keyboard::KEY_TWO;
|
|
|
- case XK_numbersign:
|
|
|
- return Keyboard::KEY_NUMBER;
|
|
|
- case XK_3:
|
|
|
- return Keyboard::KEY_THREE;
|
|
|
- case XK_dollar:
|
|
|
- return Keyboard::KEY_DOLLAR;
|
|
|
- case XK_4:
|
|
|
- return Keyboard::KEY_FOUR;
|
|
|
- case XK_percent:
|
|
|
- case XK_asciicircum :
|
|
|
- return Keyboard::KEY_CIRCUMFLEX;
|
|
|
- return Keyboard::KEY_PERCENT;
|
|
|
- case XK_5:
|
|
|
- return Keyboard::KEY_FIVE;
|
|
|
- case XK_6:
|
|
|
- return Keyboard::KEY_SIX;
|
|
|
- case XK_ampersand:
|
|
|
- return Keyboard::KEY_AMPERSAND;
|
|
|
- case XK_7:
|
|
|
- return Keyboard::KEY_SEVEN;
|
|
|
- case XK_asterisk:
|
|
|
- return Keyboard::KEY_ASTERISK;
|
|
|
- case XK_8:
|
|
|
- return Keyboard::KEY_EIGHT;
|
|
|
- case XK_parenleft:
|
|
|
- return Keyboard::KEY_LEFT_PARENTHESIS;
|
|
|
- case XK_9:
|
|
|
- return Keyboard::KEY_NINE;
|
|
|
- case XK_equal:
|
|
|
- return Keyboard::KEY_EQUAL;
|
|
|
- case XK_plus:
|
|
|
- return Keyboard::KEY_PLUS;
|
|
|
- case XK_less:
|
|
|
- return Keyboard::KEY_LESS_THAN;
|
|
|
- case XK_comma:
|
|
|
- return Keyboard::KEY_COMMA;
|
|
|
- case XK_underscore:
|
|
|
- return Keyboard::KEY_UNDERSCORE;
|
|
|
- case XK_minus:
|
|
|
- return Keyboard::KEY_MINUS;
|
|
|
- case XK_greater:
|
|
|
- return Keyboard::KEY_GREATER_THAN;
|
|
|
- case XK_period:
|
|
|
- return Keyboard::KEY_PERIOD;
|
|
|
- case XK_colon:
|
|
|
- return Keyboard::KEY_COLON;
|
|
|
- case XK_semicolon:
|
|
|
- return Keyboard::KEY_SEMICOLON;
|
|
|
- case XK_question:
|
|
|
- return Keyboard::KEY_QUESTION;
|
|
|
- case XK_slash:
|
|
|
- return Keyboard::KEY_SLASH;
|
|
|
- case XK_grave:
|
|
|
- return Keyboard::KEY_GRAVE;
|
|
|
- case XK_asciitilde:
|
|
|
- return Keyboard::KEY_TILDE;
|
|
|
- case XK_braceleft:
|
|
|
- return Keyboard::KEY_LEFT_BRACE;
|
|
|
- case XK_bracketleft:
|
|
|
- return Keyboard::KEY_LEFT_BRACKET;
|
|
|
- case XK_bar:
|
|
|
- return Keyboard::KEY_BAR;
|
|
|
- case XK_backslash:
|
|
|
- return Keyboard::KEY_BACK_SLASH;
|
|
|
- case XK_braceright:
|
|
|
- return Keyboard::KEY_RIGHT_BRACE;
|
|
|
- case XK_bracketright:
|
|
|
- return Keyboard::KEY_RIGHT_BRACKET;
|
|
|
- case XK_quotedbl:
|
|
|
- return Keyboard::KEY_QUOTE;
|
|
|
- case XK_apostrophe:
|
|
|
- return Keyboard::KEY_APOSTROPHE;
|
|
|
- case XK_EuroSign:
|
|
|
- return Keyboard::KEY_EURO;
|
|
|
- case XK_sterling:
|
|
|
- return Keyboard::KEY_POUND;
|
|
|
- case XK_yen:
|
|
|
- return Keyboard::KEY_YEN;
|
|
|
- case XK_periodcentered:
|
|
|
- return Keyboard::KEY_MIDDLE_DOT;
|
|
|
- case XK_A:
|
|
|
- return Keyboard::KEY_CAPITAL_A;
|
|
|
- case XK_a:
|
|
|
- return Keyboard::KEY_A;
|
|
|
- case XK_B:
|
|
|
- return Keyboard::KEY_CAPITAL_B;
|
|
|
- case XK_b:
|
|
|
- return Keyboard::KEY_B;
|
|
|
- case XK_C:
|
|
|
- return Keyboard::KEY_CAPITAL_C;
|
|
|
- case XK_c:
|
|
|
- return Keyboard::KEY_C;
|
|
|
- case XK_D:
|
|
|
- return Keyboard::KEY_CAPITAL_D;
|
|
|
- case XK_d:
|
|
|
- return Keyboard::KEY_D;
|
|
|
- case XK_E:
|
|
|
- return Keyboard::KEY_CAPITAL_E;
|
|
|
- case XK_e:
|
|
|
- return Keyboard::KEY_E;
|
|
|
- case XK_F:
|
|
|
- return Keyboard::KEY_CAPITAL_F;
|
|
|
- case XK_f:
|
|
|
- return Keyboard::KEY_F;
|
|
|
- case XK_G:
|
|
|
- return Keyboard::KEY_CAPITAL_G;
|
|
|
- case XK_g:
|
|
|
- return Keyboard::KEY_G;
|
|
|
- case XK_H:
|
|
|
- return Keyboard::KEY_CAPITAL_H;
|
|
|
- case XK_h:
|
|
|
- return Keyboard::KEY_H;
|
|
|
- case XK_I:
|
|
|
- return Keyboard::KEY_CAPITAL_I;
|
|
|
- case XK_i:
|
|
|
- return Keyboard::KEY_I;
|
|
|
- case XK_J:
|
|
|
- return Keyboard::KEY_CAPITAL_J;
|
|
|
- case XK_j:
|
|
|
- return Keyboard::KEY_J;
|
|
|
- case XK_K:
|
|
|
- return Keyboard::KEY_CAPITAL_K;
|
|
|
- case XK_k:
|
|
|
- return Keyboard::KEY_K;
|
|
|
- case XK_L:
|
|
|
- return Keyboard::KEY_CAPITAL_L;
|
|
|
- case XK_l:
|
|
|
- return Keyboard::KEY_L;
|
|
|
- case XK_M:
|
|
|
- return Keyboard::KEY_CAPITAL_M;
|
|
|
- case XK_m:
|
|
|
- return Keyboard::KEY_M;
|
|
|
- case XK_N:
|
|
|
- return Keyboard::KEY_CAPITAL_N;
|
|
|
- case XK_n:
|
|
|
- return Keyboard::KEY_N;
|
|
|
- case XK_O:
|
|
|
- return Keyboard::KEY_CAPITAL_O;
|
|
|
- case XK_o:
|
|
|
- return Keyboard::KEY_O;
|
|
|
- case XK_P:
|
|
|
- return Keyboard::KEY_CAPITAL_P;
|
|
|
- case XK_p:
|
|
|
- return Keyboard::KEY_P;
|
|
|
- case XK_Q:
|
|
|
- return Keyboard::KEY_CAPITAL_Q;
|
|
|
- case XK_q:
|
|
|
- return Keyboard::KEY_Q;
|
|
|
- case XK_R:
|
|
|
- return Keyboard::KEY_CAPITAL_R;
|
|
|
- case XK_r:
|
|
|
- return Keyboard::KEY_R;
|
|
|
- case XK_S:
|
|
|
- return Keyboard::KEY_CAPITAL_S;
|
|
|
- case XK_s:
|
|
|
- return Keyboard::KEY_S;
|
|
|
- case XK_T:
|
|
|
- return Keyboard::KEY_CAPITAL_T;
|
|
|
- case XK_t:
|
|
|
- return Keyboard::KEY_T;
|
|
|
- case XK_U:
|
|
|
- return Keyboard::KEY_CAPITAL_U;
|
|
|
- case XK_u:
|
|
|
- return Keyboard::KEY_U;
|
|
|
- case XK_V:
|
|
|
- return Keyboard::KEY_CAPITAL_V;
|
|
|
- case XK_v:
|
|
|
- return Keyboard::KEY_V;
|
|
|
- case XK_W:
|
|
|
- return Keyboard::KEY_CAPITAL_W;
|
|
|
- case XK_w:
|
|
|
- return Keyboard::KEY_W;
|
|
|
- case XK_X:
|
|
|
- return Keyboard::KEY_CAPITAL_X;
|
|
|
- case XK_x:
|
|
|
- return Keyboard::KEY_X;
|
|
|
- case XK_Y:
|
|
|
- return Keyboard::KEY_CAPITAL_Y;
|
|
|
- case XK_y:
|
|
|
- return Keyboard::KEY_Y;
|
|
|
- case XK_Z:
|
|
|
- return Keyboard::KEY_CAPITAL_Z;
|
|
|
- case XK_z:
|
|
|
- return Keyboard::KEY_Z;
|
|
|
- default:
|
|
|
- return Keyboard::KEY_NONE;
|
|
|
+ case XK_Sys_Req:
|
|
|
+ return gameplay::Keyboard::KEY_SYSREQ;
|
|
|
+ case XK_Break:
|
|
|
+ return gameplay::Keyboard::KEY_BREAK;
|
|
|
+ case XK_Menu :
|
|
|
+ return gameplay::Keyboard::KEY_MENU;
|
|
|
+ case XK_KP_Enter:
|
|
|
+ return gameplay::Keyboard::KEY_KP_ENTER;
|
|
|
+ case XK_Pause:
|
|
|
+ return gameplay::Keyboard::KEY_PAUSE;
|
|
|
+ case XK_Scroll_Lock:
|
|
|
+ return gameplay::Keyboard::KEY_SCROLL_LOCK;
|
|
|
+ case XK_Print:
|
|
|
+ return gameplay::Keyboard::KEY_PRINT;
|
|
|
+ case XK_Escape:
|
|
|
+ return gameplay::Keyboard::KEY_ESCAPE;
|
|
|
+ case XK_BackSpace:
|
|
|
+ return gameplay::Keyboard::KEY_BACKSPACE;
|
|
|
+ case XK_Tab:
|
|
|
+ return gameplay::Keyboard::KEY_TAB;
|
|
|
+ case XK_Return:
|
|
|
+ return gameplay::Keyboard::KEY_RETURN;
|
|
|
+ case XK_Caps_Lock:
|
|
|
+ return gameplay::Keyboard::KEY_CAPS_LOCK;
|
|
|
+ case XK_Shift_L:
|
|
|
+ case XK_Shift_R:
|
|
|
+ return gameplay::Keyboard::KEY_SHIFT;
|
|
|
+ case XK_Control_L:
|
|
|
+ case XK_Control_R:
|
|
|
+ return gameplay::Keyboard::KEY_CTRL;
|
|
|
+ case XK_Alt_L:
|
|
|
+ case XK_Alt_R:
|
|
|
+ return gameplay::Keyboard::KEY_ALT;
|
|
|
+ case XK_Hyper_L:
|
|
|
+ case XK_Hyper_R:
|
|
|
+ return gameplay::Keyboard::KEY_HYPER;
|
|
|
+ case XK_Insert:
|
|
|
+ return gameplay::Keyboard::KEY_INSERT;
|
|
|
+ case XK_Home:
|
|
|
+ return gameplay::Keyboard::KEY_HOME;
|
|
|
+ case XK_Page_Up:
|
|
|
+ return gameplay::Keyboard::KEY_PG_UP;
|
|
|
+ case XK_Delete:
|
|
|
+ return gameplay::Keyboard::KEY_DELETE;
|
|
|
+ case XK_End:
|
|
|
+ return gameplay::Keyboard::KEY_END;
|
|
|
+ case XK_Page_Down:
|
|
|
+ return gameplay::Keyboard::KEY_PG_DOWN;
|
|
|
+ case XK_Left:
|
|
|
+ return gameplay::Keyboard::KEY_LEFT_ARROW;
|
|
|
+ case XK_Right:
|
|
|
+ return gameplay::Keyboard::KEY_RIGHT_ARROW;
|
|
|
+ case XK_Up:
|
|
|
+ return gameplay::Keyboard::KEY_UP_ARROW;
|
|
|
+ case XK_Down:
|
|
|
+ return gameplay::Keyboard::KEY_DOWN_ARROW;
|
|
|
+ case XK_Num_Lock:
|
|
|
+ return gameplay::Keyboard::KEY_NUM_LOCK;
|
|
|
+ case XK_KP_Add:
|
|
|
+ return gameplay::Keyboard::KEY_KP_PLUS;
|
|
|
+ case XK_KP_Subtract:
|
|
|
+ return gameplay::Keyboard::KEY_KP_MINUS;
|
|
|
+ case XK_KP_Multiply:
|
|
|
+ return gameplay::Keyboard::KEY_KP_MULTIPLY;
|
|
|
+ case XK_KP_Divide:
|
|
|
+ return gameplay::Keyboard::KEY_KP_DIVIDE;
|
|
|
+ case XK_KP_Home:
|
|
|
+ return gameplay::Keyboard::KEY_KP_HOME;
|
|
|
+ case XK_KP_Up:
|
|
|
+ return gameplay::Keyboard::KEY_KP_UP;
|
|
|
+ case XK_KP_Page_Up:
|
|
|
+ return gameplay::Keyboard::KEY_KP_PG_UP;
|
|
|
+ case XK_KP_Left:
|
|
|
+ return gameplay::Keyboard::KEY_KP_LEFT;
|
|
|
+ case XK_KP_5:
|
|
|
+ return gameplay::Keyboard::KEY_KP_FIVE;
|
|
|
+ case XK_KP_Right:
|
|
|
+ return gameplay::Keyboard::KEY_KP_RIGHT;
|
|
|
+ case XK_KP_End:
|
|
|
+ return gameplay::Keyboard::KEY_KP_END;
|
|
|
+ case XK_KP_Down:
|
|
|
+ return gameplay::Keyboard::KEY_KP_DOWN;
|
|
|
+ case XK_KP_Page_Down:
|
|
|
+ return gameplay::Keyboard::KEY_KP_PG_DOWN;
|
|
|
+ case XK_KP_Insert:
|
|
|
+ return gameplay::Keyboard::KEY_KP_INSERT;
|
|
|
+ case XK_KP_Delete:
|
|
|
+ return gameplay::Keyboard::KEY_KP_DELETE;
|
|
|
+ case XK_F1:
|
|
|
+ return gameplay::Keyboard::KEY_F1;
|
|
|
+ case XK_F2:
|
|
|
+ return gameplay::Keyboard::KEY_F2;
|
|
|
+ case XK_F3:
|
|
|
+ return gameplay::Keyboard::KEY_F3;
|
|
|
+ case XK_F4:
|
|
|
+ return gameplay::Keyboard::KEY_F4;
|
|
|
+ case XK_F5:
|
|
|
+ return gameplay::Keyboard::KEY_F5;
|
|
|
+ case XK_F6:
|
|
|
+ return gameplay::Keyboard::KEY_F6;
|
|
|
+ case XK_F7:
|
|
|
+ return gameplay::Keyboard::KEY_F7;
|
|
|
+ case XK_F8:
|
|
|
+ return gameplay::Keyboard::KEY_F8;
|
|
|
+ case XK_F9:
|
|
|
+ return gameplay::Keyboard::KEY_F9;
|
|
|
+ case XK_F10:
|
|
|
+ return gameplay::Keyboard::KEY_F10;
|
|
|
+ case XK_F11:
|
|
|
+ return gameplay::Keyboard::KEY_F11;
|
|
|
+ case XK_F12:
|
|
|
+ return gameplay::Keyboard::KEY_F12;
|
|
|
+ case XK_KP_Space:
|
|
|
+ case XK_space:
|
|
|
+ return gameplay::Keyboard::KEY_SPACE;
|
|
|
+ case XK_parenright:
|
|
|
+ return gameplay::Keyboard::KEY_RIGHT_PARENTHESIS;
|
|
|
+ case XK_0:
|
|
|
+ return gameplay::Keyboard::KEY_ZERO;
|
|
|
+ case XK_exclam:
|
|
|
+ return gameplay::Keyboard::KEY_EXCLAM;
|
|
|
+ case XK_1:
|
|
|
+ return gameplay::Keyboard::KEY_ONE;
|
|
|
+ case XK_at:
|
|
|
+ return gameplay::Keyboard::KEY_AT;
|
|
|
+ case XK_2:
|
|
|
+ return gameplay::Keyboard::KEY_TWO;
|
|
|
+ case XK_numbersign:
|
|
|
+ return gameplay::Keyboard::KEY_NUMBER;
|
|
|
+ case XK_3:
|
|
|
+ return gameplay::Keyboard::KEY_THREE;
|
|
|
+ case XK_dollar:
|
|
|
+ return gameplay::Keyboard::KEY_DOLLAR;
|
|
|
+ case XK_4:
|
|
|
+ return gameplay::Keyboard::KEY_FOUR;
|
|
|
+ case XK_percent:
|
|
|
+ case XK_asciicircum :
|
|
|
+ return gameplay::Keyboard::KEY_CIRCUMFLEX;
|
|
|
+ return gameplay::Keyboard::KEY_PERCENT;
|
|
|
+ case XK_5:
|
|
|
+ return gameplay::Keyboard::KEY_FIVE;
|
|
|
+ case XK_6:
|
|
|
+ return gameplay::Keyboard::KEY_SIX;
|
|
|
+ case XK_ampersand:
|
|
|
+ return gameplay::Keyboard::KEY_AMPERSAND;
|
|
|
+ case XK_7:
|
|
|
+ return gameplay::Keyboard::KEY_SEVEN;
|
|
|
+ case XK_asterisk:
|
|
|
+ return gameplay::Keyboard::KEY_ASTERISK;
|
|
|
+ case XK_8:
|
|
|
+ return gameplay::Keyboard::KEY_EIGHT;
|
|
|
+ case XK_parenleft:
|
|
|
+ return gameplay::Keyboard::KEY_LEFT_PARENTHESIS;
|
|
|
+ case XK_9:
|
|
|
+ return gameplay::Keyboard::KEY_NINE;
|
|
|
+ case XK_equal:
|
|
|
+ return gameplay::Keyboard::KEY_EQUAL;
|
|
|
+ case XK_plus:
|
|
|
+ return gameplay::Keyboard::KEY_PLUS;
|
|
|
+ case XK_less:
|
|
|
+ return gameplay::Keyboard::KEY_LESS_THAN;
|
|
|
+ case XK_comma:
|
|
|
+ return gameplay::Keyboard::KEY_COMMA;
|
|
|
+ case XK_underscore:
|
|
|
+ return gameplay::Keyboard::KEY_UNDERSCORE;
|
|
|
+ case XK_minus:
|
|
|
+ return gameplay::Keyboard::KEY_MINUS;
|
|
|
+ case XK_greater:
|
|
|
+ return gameplay::Keyboard::KEY_GREATER_THAN;
|
|
|
+ case XK_period:
|
|
|
+ return gameplay::Keyboard::KEY_PERIOD;
|
|
|
+ case XK_colon:
|
|
|
+ return gameplay::Keyboard::KEY_COLON;
|
|
|
+ case XK_semicolon:
|
|
|
+ return gameplay::Keyboard::KEY_SEMICOLON;
|
|
|
+ case XK_question:
|
|
|
+ return gameplay::Keyboard::KEY_QUESTION;
|
|
|
+ case XK_slash:
|
|
|
+ return gameplay::Keyboard::KEY_SLASH;
|
|
|
+ case XK_grave:
|
|
|
+ return gameplay::Keyboard::KEY_GRAVE;
|
|
|
+ case XK_asciitilde:
|
|
|
+ return gameplay::Keyboard::KEY_TILDE;
|
|
|
+ case XK_braceleft:
|
|
|
+ return gameplay::Keyboard::KEY_LEFT_BRACE;
|
|
|
+ case XK_bracketleft:
|
|
|
+ return gameplay::Keyboard::KEY_LEFT_BRACKET;
|
|
|
+ case XK_bar:
|
|
|
+ return gameplay::Keyboard::KEY_BAR;
|
|
|
+ case XK_backslash:
|
|
|
+ return gameplay::Keyboard::KEY_BACK_SLASH;
|
|
|
+ case XK_braceright:
|
|
|
+ return gameplay::Keyboard::KEY_RIGHT_BRACE;
|
|
|
+ case XK_bracketright:
|
|
|
+ return gameplay::Keyboard::KEY_RIGHT_BRACKET;
|
|
|
+ case XK_quotedbl:
|
|
|
+ return gameplay::Keyboard::KEY_QUOTE;
|
|
|
+ case XK_apostrophe:
|
|
|
+ return gameplay::Keyboard::KEY_APOSTROPHE;
|
|
|
+ case XK_EuroSign:
|
|
|
+ return gameplay::Keyboard::KEY_EURO;
|
|
|
+ case XK_sterling:
|
|
|
+ return gameplay::Keyboard::KEY_POUND;
|
|
|
+ case XK_yen:
|
|
|
+ return gameplay::Keyboard::KEY_YEN;
|
|
|
+ case XK_periodcentered:
|
|
|
+ return gameplay::Keyboard::KEY_MIDDLE_DOT;
|
|
|
+ case XK_A:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_A;
|
|
|
+ case XK_a:
|
|
|
+ return gameplay::Keyboard::KEY_A;
|
|
|
+ case XK_B:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_B;
|
|
|
+ case XK_b:
|
|
|
+ return gameplay::Keyboard::KEY_B;
|
|
|
+ case XK_C:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_C;
|
|
|
+ case XK_c:
|
|
|
+ return gameplay::Keyboard::KEY_C;
|
|
|
+ case XK_D:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_D;
|
|
|
+ case XK_d:
|
|
|
+ return gameplay::Keyboard::KEY_D;
|
|
|
+ case XK_E:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_E;
|
|
|
+ case XK_e:
|
|
|
+ return gameplay::Keyboard::KEY_E;
|
|
|
+ case XK_F:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_F;
|
|
|
+ case XK_f:
|
|
|
+ return gameplay::Keyboard::KEY_F;
|
|
|
+ case XK_G:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_G;
|
|
|
+ case XK_g:
|
|
|
+ return gameplay::Keyboard::KEY_G;
|
|
|
+ case XK_H:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_H;
|
|
|
+ case XK_h:
|
|
|
+ return gameplay::Keyboard::KEY_H;
|
|
|
+ case XK_I:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_I;
|
|
|
+ case XK_i:
|
|
|
+ return gameplay::Keyboard::KEY_I;
|
|
|
+ case XK_J:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_J;
|
|
|
+ case XK_j:
|
|
|
+ return gameplay::Keyboard::KEY_J;
|
|
|
+ case XK_K:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_K;
|
|
|
+ case XK_k:
|
|
|
+ return gameplay::Keyboard::KEY_K;
|
|
|
+ case XK_L:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_L;
|
|
|
+ case XK_l:
|
|
|
+ return gameplay::Keyboard::KEY_L;
|
|
|
+ case XK_M:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_M;
|
|
|
+ case XK_m:
|
|
|
+ return gameplay::Keyboard::KEY_M;
|
|
|
+ case XK_N:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_N;
|
|
|
+ case XK_n:
|
|
|
+ return gameplay::Keyboard::KEY_N;
|
|
|
+ case XK_O:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_O;
|
|
|
+ case XK_o:
|
|
|
+ return gameplay::Keyboard::KEY_O;
|
|
|
+ case XK_P:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_P;
|
|
|
+ case XK_p:
|
|
|
+ return gameplay::Keyboard::KEY_P;
|
|
|
+ case XK_Q:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_Q;
|
|
|
+ case XK_q:
|
|
|
+ return gameplay::Keyboard::KEY_Q;
|
|
|
+ case XK_R:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_R;
|
|
|
+ case XK_r:
|
|
|
+ return gameplay::Keyboard::KEY_R;
|
|
|
+ case XK_S:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_S;
|
|
|
+ case XK_s:
|
|
|
+ return gameplay::Keyboard::KEY_S;
|
|
|
+ case XK_T:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_T;
|
|
|
+ case XK_t:
|
|
|
+ return gameplay::Keyboard::KEY_T;
|
|
|
+ case XK_U:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_U;
|
|
|
+ case XK_u:
|
|
|
+ return gameplay::Keyboard::KEY_U;
|
|
|
+ case XK_V:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_V;
|
|
|
+ case XK_v:
|
|
|
+ return gameplay::Keyboard::KEY_V;
|
|
|
+ case XK_W:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_W;
|
|
|
+ case XK_w:
|
|
|
+ return gameplay::Keyboard::KEY_W;
|
|
|
+ case XK_X:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_X;
|
|
|
+ case XK_x:
|
|
|
+ return gameplay::Keyboard::KEY_X;
|
|
|
+ case XK_Y:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_Y;
|
|
|
+ case XK_y:
|
|
|
+ return gameplay::Keyboard::KEY_Y;
|
|
|
+ case XK_Z:
|
|
|
+ return gameplay::Keyboard::KEY_CAPITAL_Z;
|
|
|
+ case XK_z:
|
|
|
+ return gameplay::Keyboard::KEY_Z;
|
|
|
+ default:
|
|
|
+ return gameplay::Keyboard::KEY_NONE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Returns the unicode value for the given keycode or zero if the key is not a valid printable character.
|
|
|
*/
|
|
|
-static int getUnicode(Keyboard::Key key)
|
|
|
+static int getUnicode(gameplay::Keyboard::Key key)
|
|
|
{
|
|
|
-
|
|
|
switch (key)
|
|
|
{
|
|
|
- case Keyboard::KEY_BACKSPACE:
|
|
|
- return 0x0008;
|
|
|
- case Keyboard::KEY_TAB:
|
|
|
- return 0x0009;
|
|
|
- case Keyboard::KEY_RETURN:
|
|
|
- case Keyboard::KEY_KP_ENTER:
|
|
|
- return 0x000A;
|
|
|
- case Keyboard::KEY_ESCAPE:
|
|
|
- return 0x001B;
|
|
|
- case Keyboard::KEY_SPACE:
|
|
|
- case Keyboard::KEY_EXCLAM:
|
|
|
- case Keyboard::KEY_QUOTE:
|
|
|
- case Keyboard::KEY_NUMBER:
|
|
|
- case Keyboard::KEY_DOLLAR:
|
|
|
- case Keyboard::KEY_PERCENT:
|
|
|
- case Keyboard::KEY_CIRCUMFLEX:
|
|
|
- case Keyboard::KEY_AMPERSAND:
|
|
|
- case Keyboard::KEY_APOSTROPHE:
|
|
|
- case Keyboard::KEY_LEFT_PARENTHESIS:
|
|
|
- case Keyboard::KEY_RIGHT_PARENTHESIS:
|
|
|
- case Keyboard::KEY_ASTERISK:
|
|
|
- case Keyboard::KEY_PLUS:
|
|
|
- case Keyboard::KEY_COMMA:
|
|
|
- case Keyboard::KEY_MINUS:
|
|
|
- case Keyboard::KEY_PERIOD:
|
|
|
- case Keyboard::KEY_SLASH:
|
|
|
- case Keyboard::KEY_ZERO:
|
|
|
- case Keyboard::KEY_ONE:
|
|
|
- case Keyboard::KEY_TWO:
|
|
|
- case Keyboard::KEY_THREE:
|
|
|
- case Keyboard::KEY_FOUR:
|
|
|
- case Keyboard::KEY_FIVE:
|
|
|
- case Keyboard::KEY_SIX:
|
|
|
- case Keyboard::KEY_SEVEN:
|
|
|
- case Keyboard::KEY_EIGHT:
|
|
|
- case Keyboard::KEY_NINE:
|
|
|
- case Keyboard::KEY_COLON:
|
|
|
- case Keyboard::KEY_SEMICOLON:
|
|
|
- case Keyboard::KEY_LESS_THAN:
|
|
|
- case Keyboard::KEY_EQUAL:
|
|
|
- case Keyboard::KEY_GREATER_THAN:
|
|
|
- case Keyboard::KEY_QUESTION:
|
|
|
- case Keyboard::KEY_AT:
|
|
|
- case Keyboard::KEY_CAPITAL_A:
|
|
|
- case Keyboard::KEY_CAPITAL_B:
|
|
|
- case Keyboard::KEY_CAPITAL_C:
|
|
|
- case Keyboard::KEY_CAPITAL_D:
|
|
|
- case Keyboard::KEY_CAPITAL_E:
|
|
|
- case Keyboard::KEY_CAPITAL_F:
|
|
|
- case Keyboard::KEY_CAPITAL_G:
|
|
|
- case Keyboard::KEY_CAPITAL_H:
|
|
|
- case Keyboard::KEY_CAPITAL_I:
|
|
|
- case Keyboard::KEY_CAPITAL_J:
|
|
|
- case Keyboard::KEY_CAPITAL_K:
|
|
|
- case Keyboard::KEY_CAPITAL_L:
|
|
|
- case Keyboard::KEY_CAPITAL_M:
|
|
|
- case Keyboard::KEY_CAPITAL_N:
|
|
|
- case Keyboard::KEY_CAPITAL_O:
|
|
|
- case Keyboard::KEY_CAPITAL_P:
|
|
|
- case Keyboard::KEY_CAPITAL_Q:
|
|
|
- case Keyboard::KEY_CAPITAL_R:
|
|
|
- case Keyboard::KEY_CAPITAL_S:
|
|
|
- case Keyboard::KEY_CAPITAL_T:
|
|
|
- case Keyboard::KEY_CAPITAL_U:
|
|
|
- case Keyboard::KEY_CAPITAL_V:
|
|
|
- case Keyboard::KEY_CAPITAL_W:
|
|
|
- case Keyboard::KEY_CAPITAL_X:
|
|
|
- case Keyboard::KEY_CAPITAL_Y:
|
|
|
- case Keyboard::KEY_CAPITAL_Z:
|
|
|
- case Keyboard::KEY_LEFT_BRACKET:
|
|
|
- case Keyboard::KEY_BACK_SLASH:
|
|
|
- case Keyboard::KEY_RIGHT_BRACKET:
|
|
|
- case Keyboard::KEY_UNDERSCORE:
|
|
|
- case Keyboard::KEY_GRAVE:
|
|
|
- case Keyboard::KEY_A:
|
|
|
- case Keyboard::KEY_B:
|
|
|
- case Keyboard::KEY_C:
|
|
|
- case Keyboard::KEY_D:
|
|
|
- case Keyboard::KEY_E:
|
|
|
- case Keyboard::KEY_F:
|
|
|
- case Keyboard::KEY_G:
|
|
|
- case Keyboard::KEY_H:
|
|
|
- case Keyboard::KEY_I:
|
|
|
- case Keyboard::KEY_J:
|
|
|
- case Keyboard::KEY_K:
|
|
|
- case Keyboard::KEY_L:
|
|
|
- case Keyboard::KEY_M:
|
|
|
- case Keyboard::KEY_N:
|
|
|
- case Keyboard::KEY_O:
|
|
|
- case Keyboard::KEY_P:
|
|
|
- case Keyboard::KEY_Q:
|
|
|
- case Keyboard::KEY_R:
|
|
|
- case Keyboard::KEY_S:
|
|
|
- case Keyboard::KEY_T:
|
|
|
- case Keyboard::KEY_U:
|
|
|
- case Keyboard::KEY_V:
|
|
|
- case Keyboard::KEY_W:
|
|
|
- case Keyboard::KEY_X:
|
|
|
- case Keyboard::KEY_Y:
|
|
|
- case Keyboard::KEY_Z:
|
|
|
- case Keyboard::KEY_LEFT_BRACE:
|
|
|
- case Keyboard::KEY_BAR:
|
|
|
- case Keyboard::KEY_RIGHT_BRACE:
|
|
|
- case Keyboard::KEY_TILDE:
|
|
|
- return key;
|
|
|
- default:
|
|
|
- return 0;
|
|
|
+ case gameplay::Keyboard::KEY_BACKSPACE:
|
|
|
+ return 0x0008;
|
|
|
+ case gameplay::Keyboard::KEY_TAB:
|
|
|
+ return 0x0009;
|
|
|
+ case gameplay::Keyboard::KEY_RETURN:
|
|
|
+ case gameplay::Keyboard::KEY_KP_ENTER:
|
|
|
+ return 0x000A;
|
|
|
+ case gameplay::Keyboard::KEY_ESCAPE:
|
|
|
+ return 0x001B;
|
|
|
+ case gameplay::Keyboard::KEY_SPACE:
|
|
|
+ case gameplay::Keyboard::KEY_EXCLAM:
|
|
|
+ case gameplay::Keyboard::KEY_QUOTE:
|
|
|
+ case gameplay::Keyboard::KEY_NUMBER:
|
|
|
+ case gameplay::Keyboard::KEY_DOLLAR:
|
|
|
+ case gameplay::Keyboard::KEY_PERCENT:
|
|
|
+ case gameplay::Keyboard::KEY_CIRCUMFLEX:
|
|
|
+ case gameplay::Keyboard::KEY_AMPERSAND:
|
|
|
+ case gameplay::Keyboard::KEY_APOSTROPHE:
|
|
|
+ case gameplay::Keyboard::KEY_LEFT_PARENTHESIS:
|
|
|
+ case gameplay::Keyboard::KEY_RIGHT_PARENTHESIS:
|
|
|
+ case gameplay::Keyboard::KEY_ASTERISK:
|
|
|
+ case gameplay::Keyboard::KEY_PLUS:
|
|
|
+ case gameplay::Keyboard::KEY_COMMA:
|
|
|
+ case gameplay::Keyboard::KEY_MINUS:
|
|
|
+ case gameplay::Keyboard::KEY_PERIOD:
|
|
|
+ case gameplay::Keyboard::KEY_SLASH:
|
|
|
+ case gameplay::Keyboard::KEY_ZERO:
|
|
|
+ case gameplay::Keyboard::KEY_ONE:
|
|
|
+ case gameplay::Keyboard::KEY_TWO:
|
|
|
+ case gameplay::Keyboard::KEY_THREE:
|
|
|
+ case gameplay::Keyboard::KEY_FOUR:
|
|
|
+ case gameplay::Keyboard::KEY_FIVE:
|
|
|
+ case gameplay::Keyboard::KEY_SIX:
|
|
|
+ case gameplay::Keyboard::KEY_SEVEN:
|
|
|
+ case gameplay::Keyboard::KEY_EIGHT:
|
|
|
+ case gameplay::Keyboard::KEY_NINE:
|
|
|
+ case gameplay::Keyboard::KEY_COLON:
|
|
|
+ case gameplay::Keyboard::KEY_SEMICOLON:
|
|
|
+ case gameplay::Keyboard::KEY_LESS_THAN:
|
|
|
+ case gameplay::Keyboard::KEY_EQUAL:
|
|
|
+ case gameplay::Keyboard::KEY_GREATER_THAN:
|
|
|
+ case gameplay::Keyboard::KEY_QUESTION:
|
|
|
+ case gameplay::Keyboard::KEY_AT:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_A:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_B:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_C:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_D:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_E:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_F:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_G:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_H:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_I:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_J:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_K:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_L:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_M:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_N:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_O:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_P:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_Q:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_R:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_S:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_T:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_U:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_V:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_W:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_X:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_Y:
|
|
|
+ case gameplay::Keyboard::KEY_CAPITAL_Z:
|
|
|
+ case gameplay::Keyboard::KEY_LEFT_BRACKET:
|
|
|
+ case gameplay::Keyboard::KEY_BACK_SLASH:
|
|
|
+ case gameplay::Keyboard::KEY_RIGHT_BRACKET:
|
|
|
+ case gameplay::Keyboard::KEY_UNDERSCORE:
|
|
|
+ case gameplay::Keyboard::KEY_GRAVE:
|
|
|
+ case gameplay::Keyboard::KEY_A:
|
|
|
+ case gameplay::Keyboard::KEY_B:
|
|
|
+ case gameplay::Keyboard::KEY_C:
|
|
|
+ case gameplay::Keyboard::KEY_D:
|
|
|
+ case gameplay::Keyboard::KEY_E:
|
|
|
+ case gameplay::Keyboard::KEY_F:
|
|
|
+ case gameplay::Keyboard::KEY_G:
|
|
|
+ case gameplay::Keyboard::KEY_H:
|
|
|
+ case gameplay::Keyboard::KEY_I:
|
|
|
+ case gameplay::Keyboard::KEY_J:
|
|
|
+ case gameplay::Keyboard::KEY_K:
|
|
|
+ case gameplay::Keyboard::KEY_L:
|
|
|
+ case gameplay::Keyboard::KEY_M:
|
|
|
+ case gameplay::Keyboard::KEY_N:
|
|
|
+ case gameplay::Keyboard::KEY_O:
|
|
|
+ case gameplay::Keyboard::KEY_P:
|
|
|
+ case gameplay::Keyboard::KEY_Q:
|
|
|
+ case gameplay::Keyboard::KEY_R:
|
|
|
+ case gameplay::Keyboard::KEY_S:
|
|
|
+ case gameplay::Keyboard::KEY_T:
|
|
|
+ case gameplay::Keyboard::KEY_U:
|
|
|
+ case gameplay::Keyboard::KEY_V:
|
|
|
+ case gameplay::Keyboard::KEY_W:
|
|
|
+ case gameplay::Keyboard::KEY_X:
|
|
|
+ case gameplay::Keyboard::KEY_Y:
|
|
|
+ case gameplay::Keyboard::KEY_Z:
|
|
|
+ case gameplay::Keyboard::KEY_LEFT_BRACE:
|
|
|
+ case gameplay::Keyboard::KEY_BAR:
|
|
|
+ case gameplay::Keyboard::KEY_RIGHT_BRACE:
|
|
|
+ case gameplay::Keyboard::KEY_TILDE:
|
|
|
+ return key;
|
|
|
+ default:
|
|
|
+ return 0;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-extern void print(const char* format, ...)
|
|
|
-{
|
|
|
- GP_ASSERT(format);
|
|
|
- va_list argptr;
|
|
|
- va_start(argptr, format);
|
|
|
- vfprintf(stderr, format, argptr);
|
|
|
- va_end(argptr);
|
|
|
-}
|
|
|
-
|
|
|
-Platform::Platform(Game* game) : _game(game)
|
|
|
-{
|
|
|
-}
|
|
|
-
|
|
|
-Platform::~Platform()
|
|
|
+#include <linux/joystick.h> //included here so i avoid the naming conflict between KEY_* defined in input.h and the ones defined in gameplay/Keyboard.h
|
|
|
+namespace gameplay
|
|
|
{
|
|
|
-}
|
|
|
+ extern void print(const char* format, ...)
|
|
|
+ {
|
|
|
+ GP_ASSERT(format);
|
|
|
+ va_list argptr;
|
|
|
+ va_start(argptr, format);
|
|
|
+ vfprintf(stderr, format, argptr);
|
|
|
+ va_end(argptr);
|
|
|
+ }
|
|
|
|
|
|
-Platform* Platform::create(Game* game, void* attachToWindow)
|
|
|
-{
|
|
|
+ Platform::Platform(Game* game) : _game(game)
|
|
|
+ {
|
|
|
+ }
|
|
|
|
|
|
- GP_ASSERT(game);
|
|
|
-
|
|
|
- __attachToWindow = (Window)attachToWindow;
|
|
|
- FileSystem::setResourcePath("./");
|
|
|
- Platform* platform = new Platform(game);
|
|
|
-
|
|
|
- // Get the display and initialize
|
|
|
- __display = XOpenDisplay(NULL);
|
|
|
- if (__display == NULL)
|
|
|
+ Platform::~Platform()
|
|
|
{
|
|
|
- perror("XOpenDisplay");
|
|
|
- return NULL;
|
|
|
}
|
|
|
-
|
|
|
- // Get the window configuration values
|
|
|
- const char *title = NULL;
|
|
|
- int __x = 0, __y = 0, __width = 1280, __height = 800, __samples = 0;
|
|
|
- bool fullscreen = false;
|
|
|
- if (game->getConfig())
|
|
|
+
|
|
|
+ Platform* Platform::create(Game* game, void* attachToWindow)
|
|
|
{
|
|
|
- Properties* config = game->getConfig()->getNamespace("window", true);
|
|
|
- if (config)
|
|
|
+
|
|
|
+ GP_ASSERT(game);
|
|
|
+
|
|
|
+ __attachToWindow = (Window)attachToWindow;
|
|
|
+ FileSystem::setResourcePath("./");
|
|
|
+ Platform* platform = new Platform(game);
|
|
|
+
|
|
|
+ // Get the display and initialize
|
|
|
+ __display = XOpenDisplay(NULL);
|
|
|
+ if (__display == NULL)
|
|
|
+ {
|
|
|
+ perror("XOpenDisplay");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get the window configuration values
|
|
|
+ const char *title = NULL;
|
|
|
+ int __x = 0, __y = 0, __width = 1280, __height = 800, __samples = 0;
|
|
|
+ bool fullscreen = false;
|
|
|
+ if (game->getConfig())
|
|
|
{
|
|
|
- // Read window title.
|
|
|
- title = config->getString("title");
|
|
|
-
|
|
|
- // Read window rect.
|
|
|
- int x = config->getInt("x");
|
|
|
- int y = config->getInt("y");
|
|
|
- int width = config->getInt("width");
|
|
|
- int height = config->getInt("height");
|
|
|
- int samples = config->getInt("samples");
|
|
|
- fullscreen = config->getBool("fullscreen");
|
|
|
-
|
|
|
- if (fullscreen && width == 0 && height == 0)
|
|
|
+ Properties* config = game->getConfig()->getNamespace("window", true);
|
|
|
+ if (config)
|
|
|
{
|
|
|
- // Use the screen resolution if fullscreen is true but width and height were not set in the config
|
|
|
- int screen_num = DefaultScreen(__display);
|
|
|
- width = DisplayWidth(__display, screen_num);
|
|
|
- height = DisplayHeight(__display, screen_num);
|
|
|
+ // Read window title.
|
|
|
+ title = config->getString("title");
|
|
|
+
|
|
|
+ // Read window rect.
|
|
|
+ int x = config->getInt("x");
|
|
|
+ int y = config->getInt("y");
|
|
|
+ int width = config->getInt("width");
|
|
|
+ int height = config->getInt("height");
|
|
|
+ int samples = config->getInt("samples");
|
|
|
+ fullscreen = config->getBool("fullscreen");
|
|
|
+
|
|
|
+ if (fullscreen && width == 0 && height == 0)
|
|
|
+ {
|
|
|
+ // Use the screen resolution if fullscreen is true but width and height were not set in the config
|
|
|
+ int screen_num = DefaultScreen(__display);
|
|
|
+ width = DisplayWidth(__display, screen_num);
|
|
|
+ height = DisplayHeight(__display, screen_num);
|
|
|
+ }
|
|
|
+ if (x != 0) __x = x;
|
|
|
+ if (y != 0) __y = y;
|
|
|
+ if (width != 0) __width = width;
|
|
|
+ if (height != 0) __height = height;
|
|
|
+ if (samples != 0) __samples = samples;
|
|
|
}
|
|
|
- if (x != 0) __x = x;
|
|
|
- if (y != 0) __y = y;
|
|
|
- if (width != 0) __width = width;
|
|
|
- if (height != 0) __height = height;
|
|
|
- if (samples != 0) __samples = samples;
|
|
|
+ }
|
|
|
+
|
|
|
+ // GLX version
|
|
|
+ GLint majorGLX, minorGLX = 0;
|
|
|
+ glXQueryVersion(__display, &majorGLX, &minorGLX);
|
|
|
+ if (majorGLX == 1 && minorGLX < 2)
|
|
|
+ {
|
|
|
+ perror("GLX 1.2 or greater is required.");
|
|
|
+ XCloseDisplay(__display);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ printf( "GLX version: %d.%d\n", majorGLX , minorGLX);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get the GLX Functions
|
|
|
+ glXCreateContextAttribsARB = (GLXContext(*)(Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list))glXGetProcAddressARB((GLubyte*)"glXCreateContextAttribsARB");
|
|
|
+ glXChooseFBConfig = (GLXFBConfig*(*)(Display *dpy, int screen, const int *attrib_list, int *nelements))glXGetProcAddressARB((GLubyte*)"glXChooseFBConfig");
|
|
|
+ glXGetVisualFromFBConfig = (XVisualInfo*(*)(Display *dpy, GLXFBConfig config))glXGetProcAddressARB((GLubyte*)"glXGetVisualFromFBConfig");
|
|
|
+ glXGetFBConfigAttrib = (int(*)(Display *dpy, GLXFBConfig config, int attribute, int *value))glXGetProcAddressARB((GLubyte*)"glXGetFBConfigAttrib");
|
|
|
+ glXSwapIntervalEXT = (void(*)(Display* dpy, GLXDrawable drawable, int interval))glXGetProcAddressARB((GLubyte*)"glXSwapIntervalEXT");
|
|
|
+ glXSwapIntervalMESA = (int(*)(unsigned int interval))glXGetProcAddressARB((GLubyte*)"glXSwapIntervalMESA");
|
|
|
+
|
|
|
+ // Get the configs
|
|
|
+ int configAttribs[] =
|
|
|
+ {
|
|
|
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
|
|
+ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
|
|
+ GLX_X_RENDERABLE, True,
|
|
|
+ GLX_DEPTH_SIZE, 24,
|
|
|
+ GLX_STENCIL_SIZE, 8,
|
|
|
+ GLX_RED_SIZE, 8,
|
|
|
+ GLX_GREEN_SIZE, 8,
|
|
|
+ GLX_BLUE_SIZE, 8,
|
|
|
+ GLX_DOUBLEBUFFER, True,
|
|
|
+ GLX_SAMPLE_BUFFERS, __samples > 0 ? 1 : 0,
|
|
|
+ GLX_SAMPLES, __samples,
|
|
|
+ 0
|
|
|
+ };
|
|
|
+ __multiSampling = __samples > 0;
|
|
|
+
|
|
|
+ GLXFBConfig* configs;
|
|
|
+ int configCount = 0;
|
|
|
+ configs = glXChooseFBConfig(__display, DefaultScreen(__display), configAttribs, &configCount);
|
|
|
+ if ( configCount == 0 || configs == 0 )
|
|
|
+ {
|
|
|
+ perror( "glXChooseFBConfig" );
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create the windows
|
|
|
+ XVisualInfo* visualInfo;
|
|
|
+ visualInfo = glXGetVisualFromFBConfig(__display, configs[0]);
|
|
|
+
|
|
|
+ XSetWindowAttributes winAttribs;
|
|
|
+ long eventMask;
|
|
|
+ eventMask = ExposureMask | VisibilityChangeMask | StructureNotifyMask |
|
|
|
+ KeyPressMask | KeyReleaseMask | PointerMotionMask |
|
|
|
+ ButtonPressMask | ButtonReleaseMask |
|
|
|
+ EnterWindowMask | LeaveWindowMask;
|
|
|
+ winAttribs.event_mask = eventMask;
|
|
|
+ winAttribs.border_pixel = 0;
|
|
|
+ winAttribs.bit_gravity = StaticGravity;
|
|
|
+ winAttribs.colormap = XCreateColormap(__display, RootWindow(__display, visualInfo->screen), visualInfo->visual, AllocNone);
|
|
|
+
|
|
|
+ GLint winMask;
|
|
|
+ winMask = CWBorderPixel | CWBitGravity | CWEventMask| CWColormap;
|
|
|
+
|
|
|
+ __window = XCreateWindow(__display, DefaultRootWindow(__display), __x, __y, __width, __height, 0,
|
|
|
+ visualInfo->depth, InputOutput, visualInfo->visual, winMask,
|
|
|
+ &winAttribs);
|
|
|
+
|
|
|
+ // Tell the window manager that it should send the delete window notification through ClientMessage
|
|
|
+ __atomWmDeleteWindow = XInternAtom(__display, "WM_DELETE_WINDOW", False);
|
|
|
+ XSetWMProtocols(__display, __window, &__atomWmDeleteWindow, 1);
|
|
|
+
|
|
|
+ XMapWindow(__display, __window);
|
|
|
+
|
|
|
+ // Send fullscreen atom message to the window; most window managers respect WM_STATE messages
|
|
|
+ // Note: fullscreen mode will use native desktop resolution and won't care about width/height specified
|
|
|
+ if (fullscreen)
|
|
|
+ {
|
|
|
+ XEvent xev;
|
|
|
+ Atom atomWm_state = XInternAtom(__display, "_NET_WM_STATE", False);
|
|
|
+ Atom atomFullscreen = XInternAtom(__display, "_NET_WM_STATE_FULLSCREEN", False);
|
|
|
+
|
|
|
+ memset(&xev, 0, sizeof(xev));
|
|
|
+ xev.type = ClientMessage;
|
|
|
+ xev.xclient.window = __window;
|
|
|
+ xev.xclient.message_type = atomWm_state;
|
|
|
+ xev.xclient.format = 32;
|
|
|
+ xev.xclient.data.l[0] = 1;
|
|
|
+ xev.xclient.data.l[1] = atomFullscreen;
|
|
|
+ xev.xclient.data.l[2] = 0;
|
|
|
+
|
|
|
+ XSendEvent(__display, DefaultRootWindow(__display), false, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
|
|
|
+ }
|
|
|
+
|
|
|
+ XStoreName(__display, __window, title ? title : "");
|
|
|
+
|
|
|
+ __context = glXCreateContext(__display, visualInfo, NULL, True);
|
|
|
+ if (!__context)
|
|
|
+ {
|
|
|
+ perror("glXCreateContext");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ glXMakeCurrent(__display, __window, __context);
|
|
|
+
|
|
|
+ // Use OpenGL 2.x with GLEW
|
|
|
+ glewExperimental = GL_TRUE;
|
|
|
+ GLenum glewStatus = glewInit();
|
|
|
+ if (glewStatus != GLEW_OK)
|
|
|
+ {
|
|
|
+ perror("glewInit");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ // GL Version
|
|
|
+ int versionGL[2] = {-1, -1};
|
|
|
+ glGetIntegerv(GL_MAJOR_VERSION, versionGL);
|
|
|
+ glGetIntegerv(GL_MINOR_VERSION, versionGL + 1);
|
|
|
+ printf("GL version: %d.%d\n", versionGL[0], versionGL[1]);
|
|
|
+
|
|
|
+ // TODO: Get this workings
|
|
|
+ if (glXSwapIntervalEXT)
|
|
|
+ glXSwapIntervalEXT(__display, __window, __vsync ? 1 : 0);
|
|
|
+ else if(glXSwapIntervalMESA)
|
|
|
+ glXSwapIntervalMESA(__vsync ? 1 : 0);
|
|
|
+
|
|
|
+ return platform;
|
|
|
+ }
|
|
|
+
|
|
|
+ void cleanupX11()
|
|
|
+ {
|
|
|
+ if (__display)
|
|
|
+ {
|
|
|
+ glXMakeCurrent(__display, None, NULL);
|
|
|
+
|
|
|
+ if (__context)
|
|
|
+ glXDestroyContext(__display, __context);
|
|
|
+ if (__window)
|
|
|
+ XDestroyWindow(__display, __window);
|
|
|
+
|
|
|
+ XCloseDisplay(__display);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // GLX version
|
|
|
- GLint majorGLX, minorGLX = 0;
|
|
|
- glXQueryVersion(__display, &majorGLX, &minorGLX);
|
|
|
- if (majorGLX == 1 && minorGLX < 2)
|
|
|
+ double timespec2millis(struct timespec *a)
|
|
|
{
|
|
|
- perror("GLX 1.2 or greater is required.");
|
|
|
- XCloseDisplay(__display);
|
|
|
- return NULL;
|
|
|
+ GP_ASSERT(a);
|
|
|
+ return (1000.0 * a->tv_sec) + (0.000001 * a->tv_nsec);
|
|
|
}
|
|
|
- else
|
|
|
+
|
|
|
+ void updateWindowSize()
|
|
|
{
|
|
|
- printf( "GLX version: %d.%d\n", majorGLX , minorGLX);
|
|
|
+ GP_ASSERT(__display);
|
|
|
+ GP_ASSERT(__window);
|
|
|
+ XWindowAttributes windowAttrs;
|
|
|
+ XGetWindowAttributes(__display, __window, &windowAttrs);
|
|
|
+ __windowSize[0] = windowAttrs.width;
|
|
|
+ __windowSize[1] = windowAttrs.height;
|
|
|
}
|
|
|
-
|
|
|
- // Get the GLX Functions
|
|
|
- glXCreateContextAttribsARB = (GLXContext(*)(Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list))glXGetProcAddressARB((GLubyte*)"glXCreateContextAttribsARB");
|
|
|
- glXChooseFBConfig = (GLXFBConfig*(*)(Display *dpy, int screen, const int *attrib_list, int *nelements))glXGetProcAddressARB((GLubyte*)"glXChooseFBConfig");
|
|
|
- glXGetVisualFromFBConfig = (XVisualInfo*(*)(Display *dpy, GLXFBConfig config))glXGetProcAddressARB((GLubyte*)"glXGetVisualFromFBConfig");
|
|
|
- glXGetFBConfigAttrib = (int(*)(Display *dpy, GLXFBConfig config, int attribute, int *value))glXGetProcAddressARB((GLubyte*)"glXGetFBConfigAttrib");
|
|
|
- glXSwapIntervalEXT = (void(*)(Display* dpy, GLXDrawable drawable, int interval))glXGetProcAddressARB((GLubyte*)"glXSwapIntervalEXT");
|
|
|
- glXSwapIntervalMESA = (int(*)(unsigned int interval))glXGetProcAddressARB((GLubyte*)"glXSwapIntervalMESA");
|
|
|
-
|
|
|
- // Get the configs
|
|
|
- int configAttribs[] =
|
|
|
+
|
|
|
+
|
|
|
+ //Will need to be dynamic, also should be handled in Gamepad class
|
|
|
+ static const GamepadInfoEntry gamepadLookupTable[] =
|
|
|
{
|
|
|
- GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
|
|
- GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
|
|
- GLX_X_RENDERABLE, True,
|
|
|
- GLX_DEPTH_SIZE, 24,
|
|
|
- GLX_STENCIL_SIZE, 8,
|
|
|
- GLX_RED_SIZE, 8,
|
|
|
- GLX_GREEN_SIZE, 8,
|
|
|
- GLX_BLUE_SIZE, 8,
|
|
|
- GLX_DOUBLEBUFFER, True,
|
|
|
- GLX_SAMPLE_BUFFERS, __samples > 0 ? 1 : 0,
|
|
|
- GLX_SAMPLES, __samples,
|
|
|
- 0
|
|
|
+ {0x0,0x0,"GENERIC XBOX360",2,6,20,2,
|
|
|
+ (GamepadJoystickAxisInfo[]) {
|
|
|
+ {0,0,GP_AXIS_IS_XAXIS,0,0,2240,NEG_TO_POS},
|
|
|
+ {1,0,GP_AXIS_IS_NEG,0,0,2240,NEG_TO_POS},
|
|
|
+ {2,1,GP_AXIS_IS_XAXIS,0,0,2240,NEG_TO_POS},
|
|
|
+ {3,1,GP_AXIS_IS_NEG,0,0,2240,NEG_TO_POS},
|
|
|
+ {4,2,GP_AXIS_IS_TRIGGER,0,0,2240,ZERO_TO_POS},
|
|
|
+ {5,2,GP_AXIS_IS_TRIGGER,1,0,2240,ZERO_TO_POS},
|
|
|
+ {-1,0,0,0,0,0,NEG_TO_POS}
|
|
|
+ },
|
|
|
+ (long[]) {
|
|
|
+ -1,
|
|
|
+ -1,
|
|
|
+ -1,
|
|
|
+ -1,
|
|
|
+ -1,
|
|
|
+ Gamepad::BUTTON_UP,
|
|
|
+ Gamepad::BUTTON_DOWN,
|
|
|
+ Gamepad::BUTTON_LEFT,
|
|
|
+ Gamepad::BUTTON_RIGHT,
|
|
|
+ Gamepad::BUTTON_MENU2,
|
|
|
+ Gamepad::BUTTON_MENU1,
|
|
|
+ Gamepad::BUTTON_L3,
|
|
|
+ Gamepad::BUTTON_R3,
|
|
|
+ Gamepad::BUTTON_L1,
|
|
|
+ Gamepad::BUTTON_R1,
|
|
|
+ Gamepad::BUTTON_MENU3,
|
|
|
+ Gamepad::BUTTON_A,
|
|
|
+ Gamepad::BUTTON_B,
|
|
|
+ Gamepad::BUTTON_X,
|
|
|
+ Gamepad::BUTTON_Y
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {0x79,0x6,"DragonRise Inc. Generic USB Joystick",2,7,12,0,
|
|
|
+ (GamepadJoystickAxisInfo[]) {
|
|
|
+ {0,1, GP_AXIS_IS_XAXIS,0,0,2240,NEG_TO_POS},
|
|
|
+ {1,1,GP_AXIS_IS_NEG,0,0,2240,NEG_TO_POS},
|
|
|
+ {2,0,GP_AXIS_SKIP,0,0,2240,NEG_TO_POS},
|
|
|
+ {3,0,GP_AXIS_IS_XAXIS,0,0,2240,NEG_TO_POS},
|
|
|
+ {4,0,GP_AXIS_IS_NEG,0,0,2240,NEG_TO_POS},
|
|
|
+ {5,2,GP_AXIS_IS_DPAD, Gamepad::BUTTON_RIGHT, Gamepad::BUTTON_LEFT,2240,NEG_TO_POS},
|
|
|
+ {6,2,GP_AXIS_IS_DPAD, Gamepad::BUTTON_DOWN, Gamepad::BUTTON_UP,2240,NEG_TO_POS},
|
|
|
+ {-1,0,0,0,0,0,NEG_TO_POS}
|
|
|
+ },
|
|
|
+ (long[]) {
|
|
|
+ Gamepad::BUTTON_Y,
|
|
|
+ Gamepad::BUTTON_B,
|
|
|
+ Gamepad::BUTTON_A,
|
|
|
+ Gamepad::BUTTON_X,
|
|
|
+ Gamepad::BUTTON_L1,
|
|
|
+ Gamepad::BUTTON_R1,
|
|
|
+ Gamepad::BUTTON_L2,
|
|
|
+ Gamepad::BUTTON_R2,
|
|
|
+ Gamepad::BUTTON_MENU1,
|
|
|
+ Gamepad::BUTTON_MENU2,
|
|
|
+ Gamepad::BUTTON_L3,
|
|
|
+ Gamepad::BUTTON_R3,
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {0x54c,0x268,"Sony Corp. Batoh Device / PlayStation 3 Controller",2,27,19,2,
|
|
|
+ (GamepadJoystickAxisInfo[]) {
|
|
|
+ {0,0,GP_AXIS_IS_XAXIS,0,0,2240,NEG_TO_POS},
|
|
|
+ {1,0,GP_AXIS_IS_NEG,0,0,2240,NEG_TO_POS},
|
|
|
+ {2,1,GP_AXIS_IS_XAXIS,0,0,2240,NEG_TO_POS},
|
|
|
+ {3,1,GP_AXIS_IS_NEG,0,0,2240,NEG_TO_POS},
|
|
|
+ {12,1,GP_AXIS_IS_TRIGGER,0,0,2240,ZERO_TO_POS},
|
|
|
+ {13,2,GP_AXIS_IS_TRIGGER,1,0,2240,ZERO_TO_POS},
|
|
|
+ {-1,0,0,0,0,0,NEG_TO_POS}
|
|
|
+ },
|
|
|
+ (long[]) {
|
|
|
+ Gamepad::BUTTON_MENU1,
|
|
|
+ Gamepad::BUTTON_L3,
|
|
|
+ Gamepad::BUTTON_R3,
|
|
|
+ Gamepad::BUTTON_MENU2,
|
|
|
+ Gamepad::BUTTON_UP,
|
|
|
+ Gamepad::BUTTON_RIGHT,
|
|
|
+ Gamepad::BUTTON_DOWN,
|
|
|
+ Gamepad::BUTTON_LEFT,
|
|
|
+ Gamepad::BUTTON_L2, //Use Trigger Instead of BUTTON_L2? or both should be called
|
|
|
+ Gamepad::BUTTON_R2, //Use Trigger Instead of BUTTON_R2? or both should be called
|
|
|
+ Gamepad::BUTTON_L1,
|
|
|
+ Gamepad::BUTTON_R1,
|
|
|
+ Gamepad::BUTTON_Y,
|
|
|
+ Gamepad::BUTTON_B,
|
|
|
+ Gamepad::BUTTON_A,
|
|
|
+ Gamepad::BUTTON_X,
|
|
|
+ Gamepad::BUTTON_MENU3,
|
|
|
+ -1,
|
|
|
+ -1
|
|
|
+ }
|
|
|
+ }
|
|
|
};
|
|
|
- __multiSampling = __samples > 0;
|
|
|
|
|
|
- GLXFBConfig* configs;
|
|
|
- int configCount = 0;
|
|
|
- configs = glXChooseFBConfig(__display, DefaultScreen(__display), configAttribs, &configCount);
|
|
|
- if ( configCount == 0 || configs == 0 )
|
|
|
+ bool isGamepadDevRegistered(dev_t devId)
|
|
|
{
|
|
|
- perror( "glXChooseFBConfig" );
|
|
|
- return NULL;
|
|
|
+ for(list<ConnectedGamepadDevInfo>::iterator it = __connectedGamepads.begin(); it != __connectedGamepads.end();++it)
|
|
|
+ {
|
|
|
+ if(devId == (*it).deviceId) return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
- // Create the windows
|
|
|
- XVisualInfo* visualInfo;
|
|
|
- visualInfo = glXGetVisualFromFBConfig(__display, configs[0]);
|
|
|
-
|
|
|
- XSetWindowAttributes winAttribs;
|
|
|
- long eventMask;
|
|
|
- eventMask = ExposureMask | VisibilityChangeMask | StructureNotifyMask |
|
|
|
- KeyPressMask | KeyReleaseMask | PointerMotionMask |
|
|
|
- ButtonPressMask | ButtonReleaseMask |
|
|
|
- EnterWindowMask | LeaveWindowMask;
|
|
|
- winAttribs.event_mask = eventMask;
|
|
|
- winAttribs.border_pixel = 0;
|
|
|
- winAttribs.bit_gravity = StaticGravity;
|
|
|
- winAttribs.colormap = XCreateColormap(__display, RootWindow(__display, visualInfo->screen), visualInfo->visual, AllocNone);
|
|
|
-
|
|
|
- GLint winMask;
|
|
|
- winMask = CWBorderPixel | CWBitGravity | CWEventMask| CWColormap;
|
|
|
-
|
|
|
- __window = XCreateWindow(__display, DefaultRootWindow(__display), __x, __y, __width, __height, 0,
|
|
|
- visualInfo->depth, InputOutput, visualInfo->visual, winMask,
|
|
|
- &winAttribs);
|
|
|
-
|
|
|
- // Tell the window manager that it should send the delete window notification through ClientMessage
|
|
|
- __atomWmDeleteWindow = XInternAtom(__display, "WM_DELETE_WINDOW", False);
|
|
|
- XSetWMProtocols(__display, __window, &__atomWmDeleteWindow, 1);
|
|
|
-
|
|
|
- XMapWindow(__display, __window);
|
|
|
-
|
|
|
- // Send fullscreen atom message to the window; most window managers respect WM_STATE messages
|
|
|
- // Note: fullscreen mode will use native desktop resolution and won't care about width/height specified
|
|
|
- if (fullscreen)
|
|
|
+ void closeGamepad(const ConnectedGamepadDevInfo& gamepadDevInfo)
|
|
|
{
|
|
|
- XEvent xev;
|
|
|
- Atom atomWm_state = XInternAtom(__display, "_NET_WM_STATE", False);
|
|
|
- Atom atomFullscreen = XInternAtom(__display, "_NET_WM_STATE_FULLSCREEN", False);
|
|
|
-
|
|
|
- memset(&xev, 0, sizeof(xev));
|
|
|
- xev.type = ClientMessage;
|
|
|
- xev.xclient.window = __window;
|
|
|
- xev.xclient.message_type = atomWm_state;
|
|
|
- xev.xclient.format = 32;
|
|
|
- xev.xclient.data.l[0] = 1;
|
|
|
- xev.xclient.data.l[1] = atomFullscreen;
|
|
|
- xev.xclient.data.l[2] = 0;
|
|
|
-
|
|
|
- XSendEvent(__display, DefaultRootWindow(__display), false, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
|
|
|
+ ::close(gamepadDevInfo.fd);
|
|
|
}
|
|
|
-
|
|
|
- XStoreName(__display, __window, title ? title : "");
|
|
|
|
|
|
- __context = glXCreateContext(__display, visualInfo, NULL, True);
|
|
|
- if (!__context)
|
|
|
+ void unregisterGamepad(GamepadHandle handle)
|
|
|
{
|
|
|
- perror("glXCreateContext");
|
|
|
- return NULL;
|
|
|
+ for(list<ConnectedGamepadDevInfo>::iterator it = __connectedGamepads.begin(); it != __connectedGamepads.end();++it)
|
|
|
+ {
|
|
|
+ if(handle == (*it).fd)
|
|
|
+ {
|
|
|
+ closeGamepad(*it);
|
|
|
+ __connectedGamepads.erase(it);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- glXMakeCurrent(__display, __window, __context);
|
|
|
|
|
|
- // Use OpenGL 2.x with GLEW
|
|
|
- glewExperimental = GL_TRUE;
|
|
|
- GLenum glewStatus = glewInit();
|
|
|
- if (glewStatus != GLEW_OK)
|
|
|
+ void closeAllGamepads()
|
|
|
{
|
|
|
- perror("glewInit");
|
|
|
- return NULL;
|
|
|
+ for(list<ConnectedGamepadDevInfo>::iterator it = __connectedGamepads.begin(); it != __connectedGamepads.end();++it)
|
|
|
+ {
|
|
|
+ closeGamepad(*it);
|
|
|
+ __connectedGamepads.erase(it);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- // GL Version
|
|
|
- int versionGL[2] = {-1, -1};
|
|
|
- glGetIntegerv(GL_MAJOR_VERSION, versionGL);
|
|
|
- glGetIntegerv(GL_MINOR_VERSION, versionGL + 1);
|
|
|
- printf("GL version: %d.%d\n", versionGL[0], versionGL[1]);
|
|
|
-
|
|
|
- // TODO: Get this workings
|
|
|
- if (glXSwapIntervalEXT)
|
|
|
- glXSwapIntervalEXT(__display, __window, __vsync ? 1 : 0);
|
|
|
- else if(glXSwapIntervalMESA)
|
|
|
- glXSwapIntervalMESA(__vsync ? 1 : 0);
|
|
|
-
|
|
|
- return platform;
|
|
|
-}
|
|
|
+ const GamepadInfoEntry& getGamepadMappedInfo(unsigned int vendorId, unsigned int productId, unsigned int numberOfAxes, unsigned int numberOfButtons)
|
|
|
+ {
|
|
|
+ for(int i=0;i<sizeof(gamepadLookupTable)/sizeof(GamepadInfoEntry);i++)
|
|
|
+ {
|
|
|
+ const GamepadInfoEntry& curEntry = gamepadLookupTable[i];
|
|
|
+ if(curEntry.vendorId == vendorId && curEntry.productId == productId)
|
|
|
+ {
|
|
|
+ return curEntry;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-void cleanupX11()
|
|
|
-{
|
|
|
- if (__display)
|
|
|
+ for(int i=0;i<sizeof(gamepadLookupTable)/sizeof(GamepadInfoEntry);i++)
|
|
|
+ {
|
|
|
+ const GamepadInfoEntry& curEntry = gamepadLookupTable[i];
|
|
|
+ if(curEntry.vendorId == 0 && curEntry.productId == 0 && curEntry.numberOfAxes == numberOfAxes && curEntry.numberOfButtons == numberOfButtons)
|
|
|
+ {
|
|
|
+ return curEntry;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return gamepadLookupTable[0];
|
|
|
+ }
|
|
|
+
|
|
|
+ const GamepadInfoEntry& getGamepadMappedInfo(const GamepadHandle handle)
|
|
|
{
|
|
|
- glXMakeCurrent(__display, None, NULL);
|
|
|
+ GP_ASSERT(pad);
|
|
|
|
|
|
- if (__context)
|
|
|
- glXDestroyContext(__display, __context);
|
|
|
- if (__window)
|
|
|
- XDestroyWindow(__display, __window);
|
|
|
+ for(list<ConnectedGamepadDevInfo>::iterator it = __connectedGamepads.begin(); it != __connectedGamepads.end();++it)
|
|
|
+ {
|
|
|
+ if(handle == (*it).fd)
|
|
|
+ {
|
|
|
+ return it->gamepadInfo;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ GP_WARN("Gamepad not connected but yet trying to get its data. Falling back to generic one.");
|
|
|
+ return gamepadLookupTable[0];
|
|
|
+ }
|
|
|
|
|
|
- XCloseDisplay(__display);
|
|
|
+ const GamepadJoystickAxisInfo* tryGetGamepadMappedAxisInfo(const GamepadInfoEntry& gpinfo, unsigned int axisNumber)
|
|
|
+ {
|
|
|
+ if(axisNumber >= 0 && axisNumber < gpinfo.numberOfAxes)
|
|
|
+ {
|
|
|
+ int i = 0;
|
|
|
+ while(true)
|
|
|
+ {
|
|
|
+ const GamepadJoystickAxisInfo* curAxisInfo = &gpinfo.axes[i++];
|
|
|
+ if(curAxisInfo->axisIndex == axisNumber)
|
|
|
+ return curAxisInfo;
|
|
|
+ else if(curAxisInfo->axisIndex < 0)
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return NULL;
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-double timespec2millis(struct timespec *a)
|
|
|
-{
|
|
|
- GP_ASSERT(a);
|
|
|
- return (1000.0 * a->tv_sec) + (0.000001 * a->tv_nsec);
|
|
|
-}
|
|
|
+ bool tryGetGamepadMappedButton(const GamepadInfoEntry& gpinfo, unsigned long btnNumber, long& outMap)
|
|
|
+ {
|
|
|
+ if(btnNumber >= 0 && btnNumber < gpinfo.numberOfButtons )
|
|
|
+ {
|
|
|
+ if(gpinfo.buttons[btnNumber] >= 0)
|
|
|
+ {
|
|
|
+ outMap = gpinfo.buttons[btnNumber];
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ GP_WARN("Unmapped gamepad button: %u.",btnNumber);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
-void updateWindowSize()
|
|
|
-{
|
|
|
- GP_ASSERT(__display);
|
|
|
- GP_ASSERT(__window);
|
|
|
- XWindowAttributes windowAttrs;
|
|
|
- XGetWindowAttributes(__display, __window, &windowAttrs);
|
|
|
- __windowSize[0] = windowAttrs.width;
|
|
|
- __windowSize[1] = windowAttrs.height;
|
|
|
-}
|
|
|
+ unsigned int readIntegerGamepadIdPropery(const char* sysFSIdPath, const char* propertyName)
|
|
|
+ {
|
|
|
+ unsigned int ret = 0;
|
|
|
+ try {
|
|
|
+ ifstream propStream;
|
|
|
+ propStream.open((string(sysFSIdPath) + propertyName).c_str(),ifstream::in);
|
|
|
+ propStream >> std::hex >> ret;
|
|
|
+ propStream.close();
|
|
|
+ } catch (exception e) {
|
|
|
+ GP_WARN("Could not read propery from SysFS for Gamepad: %s", propertyName);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
|
|
|
-int Platform::enterMessagePump()
|
|
|
-{
|
|
|
- GP_ASSERT(_game);
|
|
|
-
|
|
|
- updateWindowSize();
|
|
|
-
|
|
|
- static const float ACCELEROMETER_X_FACTOR = 90.0f / __windowSize[0];
|
|
|
- static const float ACCELEROMETER_Y_FACTOR = 90.0f / __windowSize[1];
|
|
|
- static int lx = 0;
|
|
|
- static int ly = 0;
|
|
|
- static bool shiftDown = false;
|
|
|
- static bool capsOn = false;
|
|
|
- static XEvent evt;
|
|
|
-
|
|
|
- // Get the initial time.
|
|
|
- clock_gettime(CLOCK_REALTIME, &__timespec);
|
|
|
- __timeStart = timespec2millis(&__timespec);
|
|
|
- __timeAbsolute = 0L;
|
|
|
-
|
|
|
- // Run the game.
|
|
|
- _game->run();
|
|
|
-
|
|
|
- // Setup select for message handling (to allow non-blocking)
|
|
|
- int x11_fd = ConnectionNumber(__display);
|
|
|
-
|
|
|
- pollfd xpolls[1];
|
|
|
- xpolls[0].fd = x11_fd;
|
|
|
- xpolls[0].events = POLLIN|POLLPRI;
|
|
|
-
|
|
|
- // Message loop.
|
|
|
- while (true)
|
|
|
+ bool isBlackListed(unsigned int vendorId, unsigned int productId)
|
|
|
+ {
|
|
|
+ switch(vendorId)
|
|
|
+ {
|
|
|
+ case 0x0e0f: //virtual machine devices
|
|
|
+ if(productId == 0x0003) // Virtual Mouse
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ void handleConnectedGamepad(dev_t devId, const char* devPath, const char* sysFSIdPath)
|
|
|
+ {
|
|
|
+ GP_ASSERT(devPath);
|
|
|
+
|
|
|
+ unsigned int vendorId =readIntegerGamepadIdPropery(sysFSIdPath,"vendor");
|
|
|
+ unsigned int productId =readIntegerGamepadIdPropery(sysFSIdPath,"product");
|
|
|
+
|
|
|
+ if(isBlackListed(vendorId,productId)) return;
|
|
|
+
|
|
|
+ GamepadHandle handle = ::open(devPath,O_RDONLY | O_NONBLOCK);
|
|
|
+ if(handle < 0)
|
|
|
+ {
|
|
|
+ GP_WARN("Could not open Gamepad device.");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!(fcntl(handle, F_GETFL) != -1 || errno != EBADF))
|
|
|
+ return;
|
|
|
+
|
|
|
+ char axesNum, btnsNum, name[256];
|
|
|
+ ioctl(handle, JSIOCGNAME(256), name);
|
|
|
+ ioctl (handle, JSIOCGAXES, &axesNum);
|
|
|
+ ioctl (handle, JSIOCGBUTTONS, &btnsNum);
|
|
|
+
|
|
|
+ const GamepadInfoEntry& gpInfo = getGamepadMappedInfo(vendorId,productId,(unsigned int)axesNum,(unsigned int)btnsNum);
|
|
|
+ unsigned int numJS = gpInfo.numberOfJS;
|
|
|
+ unsigned int numTR = gpInfo.numberOfTriggers;
|
|
|
+
|
|
|
+
|
|
|
+ Platform::gamepadEventConnectedInternal(handle,btnsNum,numJS,numTR,vendorId,productId,"",name);
|
|
|
+
|
|
|
+ ConnectedGamepadDevInfo info = {devId,handle,gpInfo};
|
|
|
+ __connectedGamepads.push_back(info);
|
|
|
+ }
|
|
|
+
|
|
|
+ static float normalizeJoystickAxis(int axisValue, int deadZone, bool zeroToOne)
|
|
|
{
|
|
|
- poll( xpolls, 1, 16 );
|
|
|
- // handle all pending events in one block
|
|
|
- while (XPending(__display))
|
|
|
+ int absAxisValue = 0;
|
|
|
+ if(zeroToOne)
|
|
|
+ absAxisValue = (axisValue + 32767) / 2.0;
|
|
|
+ else
|
|
|
+ absAxisValue = abs(axisValue);
|
|
|
+
|
|
|
+ if (absAxisValue < deadZone)
|
|
|
+ {
|
|
|
+ return 0.0f;
|
|
|
+ }
|
|
|
+ else
|
|
|
{
|
|
|
- XNextEvent(__display, &evt);
|
|
|
-
|
|
|
- switch (evt.type)
|
|
|
+ int maxVal = 0;
|
|
|
+ int value = 0;
|
|
|
+ if(!zeroToOne)
|
|
|
{
|
|
|
- case ClientMessage:
|
|
|
+ value = axisValue;
|
|
|
+ if (value < 0)
|
|
|
{
|
|
|
- // Handle destroy window message correctly
|
|
|
- if (evt.xclient.data.l[0] == __atomWmDeleteWindow)
|
|
|
- {
|
|
|
- _game->exit();
|
|
|
- }
|
|
|
+ value = -1;
|
|
|
+ maxVal = 32768;
|
|
|
}
|
|
|
- break;
|
|
|
- case DestroyNotify :
|
|
|
+ else if (value > 0)
|
|
|
{
|
|
|
- cleanupX11();
|
|
|
- exit(0);
|
|
|
+ value = 1;
|
|
|
+ maxVal = 32767;
|
|
|
}
|
|
|
- break;
|
|
|
-
|
|
|
- case Expose:
|
|
|
+ else
|
|
|
{
|
|
|
- updateWindowSize();
|
|
|
+ return 0.0f;
|
|
|
}
|
|
|
- break;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ value = 1;
|
|
|
+ maxVal = 32767;
|
|
|
+ }
|
|
|
+
|
|
|
+ float ret = value * (absAxisValue - deadZone) / (float)(maxVal - deadZone);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void enumGamepads()
|
|
|
+ {
|
|
|
+ const int maxDevs = 16;
|
|
|
+ const char* devPathFormat = "/dev/input/js%u";
|
|
|
+ const char* sysfsPathFormat = "/sys/class/input/js%u/device/id/";
|
|
|
+ char curDevPath[20];
|
|
|
|
|
|
- case KeyPress:
|
|
|
+ for(int i=0;i<maxDevs;i++)
|
|
|
+ {
|
|
|
+ sprintf(curDevPath,devPathFormat,i);
|
|
|
+ struct stat gpstat;
|
|
|
+ if(::stat(curDevPath,&gpstat) == 0)
|
|
|
+ {
|
|
|
+ dev_t devid = gpstat.st_rdev;
|
|
|
+ if(!isGamepadDevRegistered(devid))
|
|
|
{
|
|
|
- KeySym sym = XLookupKeysym(&evt.xkey, (evt.xkey.state & shiftDown) ? 1 : 0);
|
|
|
+ char cursysFSPath[35];
|
|
|
+ sprintf(cursysFSPath,sysfsPathFormat,i);
|
|
|
+ handleConnectedGamepad(devid,curDevPath,cursysFSPath);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
+ void gamepadHandlingLoop()
|
|
|
+ {
|
|
|
+ enumGamepads();
|
|
|
+ }
|
|
|
|
|
|
- //TempSym needed because XConvertCase operates on two keysyms: One lower and the other upper, we are only interested in the upper case
|
|
|
- KeySym tempSym;
|
|
|
- if (capsOn && !shiftDown)
|
|
|
- XConvertCase(sym, &tempSym, &sym);
|
|
|
+ int Platform::enterMessagePump()
|
|
|
+ {
|
|
|
+ GP_ASSERT(_game);
|
|
|
|
|
|
- Keyboard::Key key = getKey(sym);
|
|
|
- gameplay::Platform::keyEventInternal(gameplay::Keyboard::KEY_PRESS, key);
|
|
|
+ updateWindowSize();
|
|
|
|
|
|
- if (key == Keyboard::KEY_CAPS_LOCK)
|
|
|
- capsOn = !capsOn;
|
|
|
- if (key == Keyboard::KEY_SHIFT)
|
|
|
- shiftDown = true;
|
|
|
+ static const float ACCELEROMETER_X_FACTOR = 90.0f / __windowSize[0];
|
|
|
+ static const float ACCELEROMETER_Y_FACTOR = 90.0f / __windowSize[1];
|
|
|
+ static int lx = 0;
|
|
|
+ static int ly = 0;
|
|
|
+ static bool shiftDown = false;
|
|
|
+ static bool capsOn = false;
|
|
|
+ static XEvent evt;
|
|
|
|
|
|
- if (int character = getUnicode(key))
|
|
|
- gameplay::Platform::keyEventInternal(gameplay::Keyboard::KEY_CHAR, character);
|
|
|
+ // Get the initial time.
|
|
|
+ clock_gettime(CLOCK_REALTIME, &__timespec);
|
|
|
+ __timeStart = timespec2millis(&__timespec);
|
|
|
+ __timeAbsolute = 0L;
|
|
|
|
|
|
- }
|
|
|
- break;
|
|
|
+ // Run the game.
|
|
|
+ _game->run();
|
|
|
|
|
|
- case KeyRelease:
|
|
|
- {
|
|
|
- //detect and drop repeating keystrokes (no other way to do this using the event interface)
|
|
|
- XEvent next;
|
|
|
- if ( XPending(__display) )
|
|
|
- {
|
|
|
- XPeekEvent(__display,&next);
|
|
|
- if ( next.type == KeyPress
|
|
|
- && next.xkey.time == evt.xkey.time
|
|
|
- && next.xkey.keycode == evt.xkey.keycode )
|
|
|
- {
|
|
|
- XNextEvent(__display,&next);
|
|
|
- continue;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- KeySym sym = XLookupKeysym(&evt.xkey, 0);
|
|
|
- Keyboard::Key key = getKey(sym);
|
|
|
- gameplay::Platform::keyEventInternal(gameplay::Keyboard::KEY_RELEASE, key);
|
|
|
+ // Setup select for message handling (to allow non-blocking)
|
|
|
+ int x11_fd = ConnectionNumber(__display);
|
|
|
|
|
|
- if (key == Keyboard::KEY_SHIFT)
|
|
|
- shiftDown = false;
|
|
|
- }
|
|
|
- break;
|
|
|
+ pollfd xpolls[1];
|
|
|
+ xpolls[0].fd = x11_fd;
|
|
|
+ xpolls[0].events = POLLIN|POLLPRI;
|
|
|
|
|
|
- case ButtonPress:
|
|
|
- {
|
|
|
- gameplay::Mouse::MouseEvent mouseEvt;
|
|
|
- switch (evt.xbutton.button)
|
|
|
- {
|
|
|
- case 1:
|
|
|
- mouseEvt = gameplay::Mouse::MOUSE_PRESS_LEFT_BUTTON;
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- mouseEvt = gameplay::Mouse::MOUSE_PRESS_MIDDLE_BUTTON;
|
|
|
- break;
|
|
|
- case 3:
|
|
|
- mouseEvt = gameplay::Mouse::MOUSE_PRESS_RIGHT_BUTTON;
|
|
|
- break;
|
|
|
- case 4:
|
|
|
- case 5:
|
|
|
- gameplay::Platform::mouseEventInternal(gameplay::Mouse::MOUSE_WHEEL,
|
|
|
- evt.xbutton.x, evt.xbutton.y,
|
|
|
- evt.xbutton.button == Button4 ? 1 : -1);
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- if (!gameplay::Platform::mouseEventInternal(mouseEvt, evt.xbutton.x, evt.xbutton.y, 0))
|
|
|
- {
|
|
|
- gameplay::Platform::touchEventInternal(gameplay::Touch::TOUCH_PRESS, evt.xbutton.x, evt.xbutton.y, 0);
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
+ // Message loop.
|
|
|
+ while (true)
|
|
|
+ {
|
|
|
+ poll( xpolls, 1, 16 );
|
|
|
+ // handle all pending events in one block
|
|
|
+ while (XPending(__display))
|
|
|
+ {
|
|
|
+ XNextEvent(__display, &evt);
|
|
|
|
|
|
- case ButtonRelease:
|
|
|
- {
|
|
|
- gameplay::Mouse::MouseEvent mouseEvt;
|
|
|
- switch (evt.xbutton.button)
|
|
|
- {
|
|
|
- case 1:
|
|
|
- mouseEvt = gameplay::Mouse::MOUSE_RELEASE_LEFT_BUTTON;
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- mouseEvt = gameplay::Mouse::MOUSE_RELEASE_MIDDLE_BUTTON;
|
|
|
- break;
|
|
|
- case 3:
|
|
|
- mouseEvt = gameplay::Mouse::MOUSE_RELEASE_RIGHT_BUTTON;
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- if (!gameplay::Platform::mouseEventInternal(mouseEvt, evt.xbutton.x, evt.xbutton.y, 0))
|
|
|
- {
|
|
|
- gameplay::Platform::touchEventInternal(gameplay::Touch::TOUCH_RELEASE, evt.xbutton.x, evt.xbutton.y, 0);
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case MotionNotify:
|
|
|
+ switch (evt.type)
|
|
|
{
|
|
|
- int x = evt.xmotion.x;
|
|
|
- int y = evt.xmotion.y;
|
|
|
+ case ClientMessage:
|
|
|
+ {
|
|
|
+ // Handle destroy window message correctly
|
|
|
+ if (evt.xclient.data.l[0] == __atomWmDeleteWindow)
|
|
|
+ {
|
|
|
+ _game->exit();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case DestroyNotify :
|
|
|
+ {
|
|
|
+ cleanupX11();
|
|
|
+ exit(0);
|
|
|
+ }
|
|
|
+ break;
|
|
|
|
|
|
- if (__mouseCaptured)
|
|
|
- {
|
|
|
- if (x == __mouseCapturePointX && y == __mouseCapturePointY)
|
|
|
+ case Expose:
|
|
|
{
|
|
|
- // Discard the first MotionNotify following capture
|
|
|
- // since it contains bogus x,y data.
|
|
|
- break;
|
|
|
+ updateWindowSize();
|
|
|
}
|
|
|
+ break;
|
|
|
+
|
|
|
+ case KeyPress:
|
|
|
+ {
|
|
|
+ KeySym sym = XLookupKeysym(&evt.xkey, (evt.xkey.state & shiftDown) ? 1 : 0);
|
|
|
|
|
|
- // Convert to deltas
|
|
|
- x -= __mouseCapturePointX;
|
|
|
- y -= __mouseCapturePointY;
|
|
|
|
|
|
- // Warp mouse back to center of screen.
|
|
|
- XWarpPointer(__display, None, __window, 0, 0, 0, 0, __mouseCapturePointX, __mouseCapturePointY);
|
|
|
- }
|
|
|
+ //TempSym needed because XConvertCase operates on two keysyms: One lower and the other upper, we are only interested in the upper case
|
|
|
+ KeySym tempSym;
|
|
|
+ if (capsOn && !shiftDown)
|
|
|
+ XConvertCase(sym, &tempSym, &sym);
|
|
|
|
|
|
- if (!gameplay::Platform::mouseEventInternal(gameplay::Mouse::MOUSE_MOVE, x, y, 0))
|
|
|
- {
|
|
|
- if (evt.xmotion.state & Button1Mask)
|
|
|
+ Keyboard::Key key = getKey(sym);
|
|
|
+ gameplay::Platform::keyEventInternal(gameplay::Keyboard::KEY_PRESS, key);
|
|
|
+
|
|
|
+ if (key == Keyboard::KEY_CAPS_LOCK)
|
|
|
+ capsOn = !capsOn;
|
|
|
+ if (key == Keyboard::KEY_SHIFT)
|
|
|
+ shiftDown = true;
|
|
|
+
|
|
|
+ if (int character = getUnicode(key))
|
|
|
+ gameplay::Platform::keyEventInternal(gameplay::Keyboard::KEY_CHAR, character);
|
|
|
+
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case KeyRelease:
|
|
|
{
|
|
|
- gameplay::Platform::touchEventInternal(gameplay::Touch::TOUCH_MOVE, x, y, 0);
|
|
|
+ //detect and drop repeating keystrokes (no other way to do this using the event interface)
|
|
|
+ XEvent next;
|
|
|
+ if ( XPending(__display) )
|
|
|
+ {
|
|
|
+ XPeekEvent(__display,&next);
|
|
|
+ if ( next.type == KeyPress
|
|
|
+ && next.xkey.time == evt.xkey.time
|
|
|
+ && next.xkey.keycode == evt.xkey.keycode )
|
|
|
+ {
|
|
|
+ XNextEvent(__display,&next);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ KeySym sym = XLookupKeysym(&evt.xkey, 0);
|
|
|
+ Keyboard::Key key = getKey(sym);
|
|
|
+ gameplay::Platform::keyEventInternal(gameplay::Keyboard::KEY_RELEASE, key);
|
|
|
+
|
|
|
+ if (key == Keyboard::KEY_SHIFT)
|
|
|
+ shiftDown = false;
|
|
|
}
|
|
|
- else if (evt.xmotion.state & Button3Mask)
|
|
|
+ break;
|
|
|
+
|
|
|
+ case ButtonPress:
|
|
|
{
|
|
|
- // Update the pitch and roll by adding the scaled deltas.
|
|
|
- __roll += (float)(x - lx) * ACCELEROMETER_X_FACTOR;
|
|
|
- __pitch += -(float)(y - ly) * ACCELEROMETER_Y_FACTOR;
|
|
|
+ gameplay::Mouse::MouseEvent mouseEvt;
|
|
|
+ switch (evt.xbutton.button)
|
|
|
+ {
|
|
|
+ case 1:
|
|
|
+ mouseEvt = gameplay::Mouse::MOUSE_PRESS_LEFT_BUTTON;
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ mouseEvt = gameplay::Mouse::MOUSE_PRESS_MIDDLE_BUTTON;
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ mouseEvt = gameplay::Mouse::MOUSE_PRESS_RIGHT_BUTTON;
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ case 5:
|
|
|
+ gameplay::Platform::mouseEventInternal(gameplay::Mouse::MOUSE_WHEEL,
|
|
|
+ evt.xbutton.x, evt.xbutton.y,
|
|
|
+ evt.xbutton.button == Button4 ? 1 : -1);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!gameplay::Platform::mouseEventInternal(mouseEvt, evt.xbutton.x, evt.xbutton.y, 0))
|
|
|
+ {
|
|
|
+ gameplay::Platform::touchEventInternal(gameplay::Touch::TOUCH_PRESS, evt.xbutton.x, evt.xbutton.y, 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
|
|
|
- // Clamp the values to the valid range.
|
|
|
- __roll = max(min(__roll, 90.0f), -90.0f);
|
|
|
- __pitch = max(min(__pitch, 90.0f), -90.0f);
|
|
|
+ case ButtonRelease:
|
|
|
+ {
|
|
|
+ gameplay::Mouse::MouseEvent mouseEvt;
|
|
|
+ switch (evt.xbutton.button)
|
|
|
+ {
|
|
|
+ case 1:
|
|
|
+ mouseEvt = gameplay::Mouse::MOUSE_RELEASE_LEFT_BUTTON;
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ mouseEvt = gameplay::Mouse::MOUSE_RELEASE_MIDDLE_BUTTON;
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ mouseEvt = gameplay::Mouse::MOUSE_RELEASE_RIGHT_BUTTON;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!gameplay::Platform::mouseEventInternal(mouseEvt, evt.xbutton.x, evt.xbutton.y, 0))
|
|
|
+ {
|
|
|
+ gameplay::Platform::touchEventInternal(gameplay::Touch::TOUCH_RELEASE, evt.xbutton.x, evt.xbutton.y, 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
|
|
|
- // Update the last X/Y values.
|
|
|
- lx = x;
|
|
|
- ly = y;
|
|
|
+ case MotionNotify:
|
|
|
+ {
|
|
|
+ int x = evt.xmotion.x;
|
|
|
+ int y = evt.xmotion.y;
|
|
|
+
|
|
|
+ if (__mouseCaptured)
|
|
|
+ {
|
|
|
+ if (x == __mouseCapturePointX && y == __mouseCapturePointY)
|
|
|
+ {
|
|
|
+ // Discard the first MotionNotify following capture
|
|
|
+ // since it contains bogus x,y data.
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Convert to deltas
|
|
|
+ x -= __mouseCapturePointX;
|
|
|
+ y -= __mouseCapturePointY;
|
|
|
+
|
|
|
+ // Warp mouse back to center of screen.
|
|
|
+ XWarpPointer(__display, None, __window, 0, 0, 0, 0, __mouseCapturePointX, __mouseCapturePointY);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!gameplay::Platform::mouseEventInternal(gameplay::Mouse::MOUSE_MOVE, x, y, 0))
|
|
|
+ {
|
|
|
+ if (evt.xmotion.state & Button1Mask)
|
|
|
+ {
|
|
|
+ gameplay::Platform::touchEventInternal(gameplay::Touch::TOUCH_MOVE, x, y, 0);
|
|
|
+ }
|
|
|
+ else if (evt.xmotion.state & Button3Mask)
|
|
|
+ {
|
|
|
+ // Update the pitch and roll by adding the scaled deltas.
|
|
|
+ __roll += (float)(x - lx) * ACCELEROMETER_X_FACTOR;
|
|
|
+ __pitch += -(float)(y - ly) * ACCELEROMETER_Y_FACTOR;
|
|
|
+
|
|
|
+ // Clamp the values to the valid range.
|
|
|
+ __roll = max(min(__roll, 90.0f), -90.0f);
|
|
|
+ __pitch = max(min(__pitch, 90.0f), -90.0f);
|
|
|
+
|
|
|
+ // Update the last X/Y values.
|
|
|
+ lx = x;
|
|
|
+ ly = y;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
}
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- break;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- if (_game)
|
|
|
- {
|
|
|
- // Game state will be uninitialized if game was closed through Game::exit()
|
|
|
- if (_game->getState() == Game::UNINITIALIZED)
|
|
|
- break;
|
|
|
-
|
|
|
- _game->frame();
|
|
|
+ gamepadHandlingLoop();
|
|
|
+
|
|
|
+ if (_game)
|
|
|
+ {
|
|
|
+ // Game state will be uninitialized if game was closed through Game::exit()
|
|
|
+ if (_game->getState() == Game::UNINITIALIZED)
|
|
|
+ break;
|
|
|
+
|
|
|
+ _game->frame();
|
|
|
+ }
|
|
|
+
|
|
|
+ glXSwapBuffers(__display, __window);
|
|
|
}
|
|
|
|
|
|
- glXSwapBuffers(__display, __window);
|
|
|
+ cleanupX11();
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
- cleanupX11();
|
|
|
+ void Platform::signalShutdown()
|
|
|
+ {
|
|
|
+ }
|
|
|
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-void Platform::signalShutdown()
|
|
|
-{
|
|
|
- // nothing to do
|
|
|
-}
|
|
|
+ bool Platform::canExit()
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
|
|
|
-bool Platform::canExit()
|
|
|
-{
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-unsigned int Platform::getDisplayWidth()
|
|
|
-{
|
|
|
- return __windowSize[0];
|
|
|
-}
|
|
|
+ unsigned int Platform::getDisplayWidth()
|
|
|
+ {
|
|
|
+ return __windowSize[0];
|
|
|
+ }
|
|
|
|
|
|
-unsigned int Platform::getDisplayHeight()
|
|
|
-{
|
|
|
- return __windowSize[1];
|
|
|
-}
|
|
|
+ unsigned int Platform::getDisplayHeight()
|
|
|
+ {
|
|
|
+ return __windowSize[1];
|
|
|
+ }
|
|
|
|
|
|
-double Platform::getAbsoluteTime()
|
|
|
-{
|
|
|
+ double Platform::getAbsoluteTime()
|
|
|
+ {
|
|
|
|
|
|
- clock_gettime(CLOCK_REALTIME, &__timespec);
|
|
|
- double now = timespec2millis(&__timespec);
|
|
|
- __timeAbsolute = now - __timeStart;
|
|
|
+ clock_gettime(CLOCK_REALTIME, &__timespec);
|
|
|
+ double now = timespec2millis(&__timespec);
|
|
|
+ __timeAbsolute = now - __timeStart;
|
|
|
|
|
|
- return __timeAbsolute;
|
|
|
-}
|
|
|
+ return __timeAbsolute;
|
|
|
+ }
|
|
|
|
|
|
-void Platform::setAbsoluteTime(double time)
|
|
|
-{
|
|
|
- __timeAbsolute = time;
|
|
|
-}
|
|
|
+ void Platform::setAbsoluteTime(double time)
|
|
|
+ {
|
|
|
+ __timeAbsolute = time;
|
|
|
+ }
|
|
|
|
|
|
-bool Platform::isVsync()
|
|
|
-{
|
|
|
- return __vsync;
|
|
|
-}
|
|
|
+ bool Platform::isVsync()
|
|
|
+ {
|
|
|
+ return __vsync;
|
|
|
+ }
|
|
|
|
|
|
-void Platform::setVsync(bool enable)
|
|
|
-{
|
|
|
- if (glXSwapIntervalEXT)
|
|
|
- glXSwapIntervalEXT(__display, __window, __vsync ? 1 : 0);
|
|
|
- else if(glXSwapIntervalMESA)
|
|
|
- glXSwapIntervalMESA(__vsync ? 1 : 0);
|
|
|
+ void Platform::setVsync(bool enable)
|
|
|
+ {
|
|
|
+ if (glXSwapIntervalEXT)
|
|
|
+ glXSwapIntervalEXT(__display, __window, __vsync ? 1 : 0);
|
|
|
+ else if(glXSwapIntervalMESA)
|
|
|
+ glXSwapIntervalMESA(__vsync ? 1 : 0);
|
|
|
|
|
|
- __vsync = enable;
|
|
|
-}
|
|
|
+ __vsync = enable;
|
|
|
+ }
|
|
|
|
|
|
-void Platform::swapBuffers()
|
|
|
-{
|
|
|
- glXSwapBuffers(__display, __window);
|
|
|
-}
|
|
|
+ void Platform::swapBuffers()
|
|
|
+ {
|
|
|
+ glXSwapBuffers(__display, __window);
|
|
|
+ }
|
|
|
|
|
|
-void Platform::sleep(long ms)
|
|
|
-{
|
|
|
- usleep(ms * 1000);
|
|
|
-}
|
|
|
+ void Platform::sleep(long ms)
|
|
|
+ {
|
|
|
+ usleep(ms * 1000);
|
|
|
+ }
|
|
|
|
|
|
-void Platform::setMultiSampling(bool enabled)
|
|
|
-{
|
|
|
- if (enabled == __multiSampling)
|
|
|
+ void Platform::setMultiSampling(bool enabled)
|
|
|
{
|
|
|
- return;
|
|
|
+ if (enabled == __multiSampling)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ //todo
|
|
|
+
|
|
|
+ __multiSampling = enabled;
|
|
|
}
|
|
|
-
|
|
|
- //todo
|
|
|
-
|
|
|
- __multiSampling = enabled;
|
|
|
-}
|
|
|
-
|
|
|
-bool Platform::isMultiSampling()
|
|
|
-{
|
|
|
- return __multiSampling;
|
|
|
-}
|
|
|
+
|
|
|
+ bool Platform::isMultiSampling()
|
|
|
+ {
|
|
|
+ return __multiSampling;
|
|
|
+ }
|
|
|
|
|
|
-void Platform::setMultiTouch(bool enabled)
|
|
|
-{
|
|
|
- // not supported
|
|
|
-}
|
|
|
+ void Platform::setMultiTouch(bool enabled)
|
|
|
+ {
|
|
|
+ // not supported
|
|
|
+ }
|
|
|
|
|
|
-bool Platform::isMultiTouch()
|
|
|
-{
|
|
|
- false;
|
|
|
-}
|
|
|
+ bool Platform::isMultiTouch()
|
|
|
+ {
|
|
|
+ false;
|
|
|
+ }
|
|
|
|
|
|
-void Platform::getAccelerometerValues(float* pitch, float* roll)
|
|
|
-{
|
|
|
- GP_ASSERT(pitch);
|
|
|
- GP_ASSERT(roll);
|
|
|
+ void Platform::getAccelerometerValues(float* pitch, float* roll)
|
|
|
+ {
|
|
|
+ GP_ASSERT(pitch);
|
|
|
+ GP_ASSERT(roll);
|
|
|
|
|
|
- *pitch = __pitch;
|
|
|
- *roll = __roll;
|
|
|
-}
|
|
|
+ *pitch = __pitch;
|
|
|
+ *roll = __roll;
|
|
|
+ }
|
|
|
|
|
|
-bool Platform::hasMouse()
|
|
|
-{
|
|
|
- return true;
|
|
|
-}
|
|
|
+ bool Platform::hasMouse()
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
|
|
|
-void Platform::setMouseCaptured(bool captured)
|
|
|
-{
|
|
|
- if (captured != __mouseCaptured)
|
|
|
+ void Platform::setMouseCaptured(bool captured)
|
|
|
{
|
|
|
- if (captured)
|
|
|
+ if (captured != __mouseCaptured)
|
|
|
{
|
|
|
- // Hide the cursor and warp it to the center of the screen
|
|
|
- __mouseCapturePointX = getDisplayWidth() / 2;
|
|
|
- __mouseCapturePointY = getDisplayHeight() / 2;
|
|
|
+ if (captured)
|
|
|
+ {
|
|
|
+ // Hide the cursor and warp it to the center of the screen
|
|
|
+ __mouseCapturePointX = getDisplayWidth() / 2;
|
|
|
+ __mouseCapturePointY = getDisplayHeight() / 2;
|
|
|
+
|
|
|
+ setCursorVisible(false);
|
|
|
+ XWarpPointer(__display, None, __window, 0, 0, 0, 0, __mouseCapturePointX, __mouseCapturePointY);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Restore cursor
|
|
|
+ XWarpPointer(__display, None, __window, 0, 0, 0, 0, __mouseCapturePointX, __mouseCapturePointY);
|
|
|
+ setCursorVisible(true);
|
|
|
+ }
|
|
|
|
|
|
- setCursorVisible(false);
|
|
|
- XWarpPointer(__display, None, __window, 0, 0, 0, 0, __mouseCapturePointX, __mouseCapturePointY);
|
|
|
+ __mouseCaptured = captured;
|
|
|
}
|
|
|
- else
|
|
|
+ }
|
|
|
+
|
|
|
+ bool Platform::isMouseCaptured()
|
|
|
+ {
|
|
|
+ return __mouseCaptured;
|
|
|
+ }
|
|
|
+
|
|
|
+ void Platform::setCursorVisible(bool visible)
|
|
|
+ {
|
|
|
+ if (visible != __cursorVisible)
|
|
|
{
|
|
|
- // Restore cursor
|
|
|
- XWarpPointer(__display, None, __window, 0, 0, 0, 0, __mouseCapturePointX, __mouseCapturePointY);
|
|
|
- setCursorVisible(true);
|
|
|
+ if (visible)
|
|
|
+ {
|
|
|
+ Cursor invisibleCursor;
|
|
|
+ Pixmap bitmapNoData;
|
|
|
+ XColor black;
|
|
|
+ static char noData[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
|
|
+ black.red = black.green = black.blue = 0;
|
|
|
+ bitmapNoData = XCreateBitmapFromData(__display, __window, noData, 8, 8);
|
|
|
+ invisibleCursor = XCreatePixmapCursor(__display, bitmapNoData, bitmapNoData, &black, &black, 0, 0);
|
|
|
+
|
|
|
+ XDefineCursor(__display, __window, invisibleCursor);
|
|
|
+ XFreeCursor(__display, invisibleCursor);
|
|
|
+ XFreePixmap(__display, bitmapNoData);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ XUndefineCursor(__display, __window);
|
|
|
+ }
|
|
|
+ XFlush(__display);
|
|
|
+ __cursorVisible = visible;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- __mouseCaptured = captured;
|
|
|
+ bool Platform::isCursorVisible()
|
|
|
+ {
|
|
|
+ return __cursorVisible;
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-bool Platform::isMouseCaptured()
|
|
|
-{
|
|
|
- return __mouseCaptured;
|
|
|
-}
|
|
|
+ void Platform::displayKeyboard(bool display)
|
|
|
+ {
|
|
|
+ // not supported
|
|
|
+ }
|
|
|
|
|
|
-void Platform::setCursorVisible(bool visible)
|
|
|
-{
|
|
|
- if (visible != __cursorVisible)
|
|
|
+ void Platform::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
|
|
|
+ {
|
|
|
+ if (!Form::touchEventInternal(evt, x, y, contactIndex))
|
|
|
+ {
|
|
|
+ Game::getInstance()->touchEvent(evt, x, y, contactIndex);
|
|
|
+ Game::getInstance()->getScriptController()->touchEvent(evt, x, y, contactIndex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void Platform::keyEventInternal(Keyboard::KeyEvent evt, int key)
|
|
|
{
|
|
|
- if (visible)
|
|
|
+ if (!Form::keyEventInternal(evt, key))
|
|
|
+ {
|
|
|
+ Game::getInstance()->keyEvent(evt, key);
|
|
|
+ Game::getInstance()->getScriptController()->keyEvent(evt, key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ bool Platform::mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
|
|
|
+ {
|
|
|
+ if (Form::mouseEventInternal(evt, x, y, wheelDelta))
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else if (Game::getInstance()->mouseEvent(evt, x, y, wheelDelta))
|
|
|
{
|
|
|
- Cursor invisibleCursor;
|
|
|
- Pixmap bitmapNoData;
|
|
|
- XColor black;
|
|
|
- static char noData[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
|
|
- black.red = black.green = black.blue = 0;
|
|
|
- bitmapNoData = XCreateBitmapFromData(__display, __window, noData, 8, 8);
|
|
|
- invisibleCursor = XCreatePixmapCursor(__display, bitmapNoData, bitmapNoData, &black, &black, 0, 0);
|
|
|
-
|
|
|
- XDefineCursor(__display, __window, invisibleCursor);
|
|
|
- XFreeCursor(__display, invisibleCursor);
|
|
|
- XFreePixmap(__display, bitmapNoData);
|
|
|
+ return true;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- XUndefineCursor(__display, __window);
|
|
|
+ return Game::getInstance()->getScriptController()->mouseEvent(evt, x, y, wheelDelta);
|
|
|
}
|
|
|
- XFlush(__display);
|
|
|
- __cursorVisible = visible;
|
|
|
}
|
|
|
-}
|
|
|
+
|
|
|
+ void Platform::gamepadEventConnectedInternal(GamepadHandle handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
|
|
|
+ unsigned int vendorId, unsigned int productId, const char* vendorString, const char* productString)
|
|
|
+ {
|
|
|
+ Gamepad::add(handle, buttonCount, joystickCount, triggerCount, vendorId, productId, vendorString, productString);
|
|
|
+ }
|
|
|
|
|
|
-bool Platform::isCursorVisible()
|
|
|
-{
|
|
|
- return __cursorVisible;
|
|
|
-}
|
|
|
+ void Platform::gamepadEventDisconnectedInternal(GamepadHandle handle)
|
|
|
+ {
|
|
|
+ Gamepad::remove(handle);
|
|
|
+ }
|
|
|
|
|
|
-void Platform::displayKeyboard(bool display)
|
|
|
-{
|
|
|
- // not supported
|
|
|
-}
|
|
|
+ void Platform::shutdownInternal()
|
|
|
+ {
|
|
|
+ closeAllGamepads();
|
|
|
+ Game::getInstance()->shutdown();
|
|
|
+ }
|
|
|
|
|
|
-void Platform::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
|
|
|
-{
|
|
|
- if (!Form::touchEventInternal(evt, x, y, contactIndex))
|
|
|
+ bool Platform::isGestureSupported(Gesture::GestureEvent evt)
|
|
|
{
|
|
|
- Game::getInstance()->touchEvent(evt, x, y, contactIndex);
|
|
|
- Game::getInstance()->getScriptController()->touchEvent(evt, x, y, contactIndex);
|
|
|
+ return false;
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-void Platform::keyEventInternal(Keyboard::KeyEvent evt, int key)
|
|
|
-{
|
|
|
- if (!Form::keyEventInternal(evt, key))
|
|
|
+ void Platform::registerGesture(Gesture::GestureEvent evt)
|
|
|
{
|
|
|
- Game::getInstance()->keyEvent(evt, key);
|
|
|
- Game::getInstance()->getScriptController()->keyEvent(evt, key);
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-bool Platform::mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
|
|
|
-{
|
|
|
- if (Form::mouseEventInternal(evt, x, y, wheelDelta))
|
|
|
+ void Platform::unregisterGesture(Gesture::GestureEvent evt)
|
|
|
{
|
|
|
- return true;
|
|
|
}
|
|
|
- else if (Game::getInstance()->mouseEvent(evt, x, y, wheelDelta))
|
|
|
+
|
|
|
+ bool Platform::isGestureRegistered(Gesture::GestureEvent evt)
|
|
|
{
|
|
|
- return true;
|
|
|
+ return false;
|
|
|
}
|
|
|
- else
|
|
|
+
|
|
|
+ void Platform::pollGamepadState(Gamepad* gamepad)
|
|
|
{
|
|
|
- return Game::getInstance()->getScriptController()->mouseEvent(evt, x, y, wheelDelta);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void Platform::gamepadEventConnectedInternal(GamepadHandle handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
|
|
|
- unsigned int vendorId, unsigned int productId, const char* vendorString, const char* productString)
|
|
|
-{
|
|
|
- Gamepad::add(handle, buttonCount, joystickCount, triggerCount, vendorId, productId, vendorString, productString);
|
|
|
-}
|
|
|
+ GP_ASSERT(gamepad);
|
|
|
|
|
|
-void Platform::gamepadEventDisconnectedInternal(GamepadHandle handle)
|
|
|
-{
|
|
|
- Gamepad::remove(handle);
|
|
|
-}
|
|
|
+ struct js_event jevent;
|
|
|
+ const GamepadInfoEntry& gpInfo = getGamepadMappedInfo(gamepad->_handle);
|
|
|
|
|
|
-void Platform::shutdownInternal()
|
|
|
-{
|
|
|
- Game::getInstance()->shutdown();
|
|
|
-}
|
|
|
+ while (read(gamepad->_handle, &jevent, sizeof(struct js_event)) > 0)
|
|
|
+ {
|
|
|
+ switch (jevent.type)
|
|
|
+ {
|
|
|
+ case JS_EVENT_BUTTON:
|
|
|
+ case JS_EVENT_BUTTON | JS_EVENT_INIT:
|
|
|
+ {
|
|
|
+ long curMappingIndex = -1;
|
|
|
+ if(tryGetGamepadMappedButton(gpInfo, jevent.number, curMappingIndex))
|
|
|
+ {
|
|
|
+ if (jevent.value)
|
|
|
+ gamepad->_buttons |= (1 << curMappingIndex);
|
|
|
+ else
|
|
|
+ gamepad->_buttons &= ~(1 << curMappingIndex);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case JS_EVENT_AXIS:
|
|
|
+ case JS_EVENT_AXIS | JS_EVENT_INIT:
|
|
|
+ {
|
|
|
+ if(jevent.number < gpInfo.numberOfAxes)
|
|
|
+ {
|
|
|
+ const GamepadJoystickAxisInfo* jsInfo = tryGetGamepadMappedAxisInfo(gpInfo,jevent.number);
|
|
|
+ if(jsInfo)
|
|
|
+ {
|
|
|
+ float val = normalizeJoystickAxis(jevent.value,jsInfo->deadZone,jsInfo->mapFunc == ZERO_TO_POS);
|
|
|
+ if(!(jsInfo->flags & GP_AXIS_SKIP))
|
|
|
+ {
|
|
|
+ if((jsInfo->flags & GP_AXIS_IS_NEG))
|
|
|
+ val = -1.0f * val;
|
|
|
+
|
|
|
+ bool not_js_axis = false;
|
|
|
+ if((jsInfo->flags & GP_AXIS_IS_DPAD))
|
|
|
+ {
|
|
|
+ if(jevent.value != 0)
|
|
|
+ gamepad->_buttons |= (1 << (jevent.value > 0 ? jsInfo->mappedPosArg : jsInfo->mappedNegArg));
|
|
|
+ else
|
|
|
+ {
|
|
|
+ gamepad->_buttons &= ~(1 << jsInfo->mappedPosArg);
|
|
|
+ gamepad->_buttons &= ~(1 << jsInfo->mappedNegArg);
|
|
|
+ }
|
|
|
+ not_js_axis = true;
|
|
|
+ }
|
|
|
+ if((jsInfo->flags & GP_AXIS_IS_TRIGGER))
|
|
|
+ {
|
|
|
+ gamepad->_triggers[jsInfo->mappedPosArg] = val;
|
|
|
+ not_js_axis = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!not_js_axis)
|
|
|
+ {
|
|
|
+ if(jsInfo->flags & GP_AXIS_IS_XAXIS)
|
|
|
+ gamepad->_joysticks[jsInfo->joystickIndex].x = val;
|
|
|
+ else
|
|
|
+ gamepad->_joysticks[jsInfo->joystickIndex].y = val;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
|
|
|
-bool Platform::isGestureSupported(Gesture::GestureEvent evt)
|
|
|
-{
|
|
|
- return false;
|
|
|
-}
|
|
|
+ default:
|
|
|
+ GP_WARN("unhandled gamepad event: %x\n", jevent.type);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(errno == ENODEV)
|
|
|
+ {
|
|
|
+ unregisterGamepad(gamepad->_handle);
|
|
|
+ gamepadEventDisconnectedInternal(gamepad->_handle);
|
|
|
+ }
|
|
|
|
|
|
-void Platform::registerGesture(Gesture::GestureEvent evt)
|
|
|
-{
|
|
|
-}
|
|
|
+ }
|
|
|
|
|
|
-void Platform::unregisterGesture(Gesture::GestureEvent evt)
|
|
|
-{
|
|
|
-}
|
|
|
-
|
|
|
-bool Platform::isGestureRegistered(Gesture::GestureEvent evt)
|
|
|
-{
|
|
|
- return false;
|
|
|
-}
|
|
|
+ bool Platform::launchURL(const char* url)
|
|
|
+ {
|
|
|
+ if (url == NULL || *url == '\0')
|
|
|
+ return false;
|
|
|
|
|
|
-void Platform::pollGamepadState(Gamepad* gamepad)
|
|
|
-{
|
|
|
-}
|
|
|
+ int len = strlen(url);
|
|
|
|
|
|
-bool Platform::launchURL(const char* url)
|
|
|
-{
|
|
|
- if (url == NULL || *url == '\0')
|
|
|
- return false;
|
|
|
+ char* cmd = new char[11 + len];
|
|
|
+ sprintf(cmd, "xdg-open %s", url);
|
|
|
+ int r = system(cmd);
|
|
|
+ SAFE_DELETE_ARRAY(cmd);
|
|
|
|
|
|
- int len = strlen(url);
|
|
|
-
|
|
|
- char* cmd = new char[11 + len];
|
|
|
- sprintf(cmd, "xdg-open %s", url);
|
|
|
- int r = system(cmd);
|
|
|
- SAFE_DELETE_ARRAY(cmd);
|
|
|
-
|
|
|
- return (r == 0);
|
|
|
-}
|
|
|
+ return (r == 0);
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|