| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741 |
- #ifdef __linux__
- #include "Base.h"
- #include "Platform.h"
- #include "FileSystem.h"
- #include "Game.h"
- #include "Form.h"
- #include "ScriptController.h"
- #include <X11/X.h>
- #include <X11/Xlib.h>
- #include <X11/keysym.h>
- #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>
- #include <glib.h>
- #include <glib/gi18n.h>
- #include <gtk/gtk.h>
- #define TOUCH_COUNT_MAX 4
- #define MAX_GAMEPADS 4
- using namespace std;
- int __argc = 0;
- char** __argv = 0;
- 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;
- static bool __vsync = WINDOW_VSYNC;
- static bool __mouseCaptured = false;
- static float __mouseCapturePointX = 0;
- static float __mouseCapturePointY = 0;
- static bool __multiSampling = false;
- static bool __cursorVisible = true;
- static Display* __display;
- static Window __window;
- static int __windowSize[2];
- static GLXContext __context;
- static Atom __atomWmDeleteWindow;
- static list<ConnectedGamepadDevInfo> __connectedGamepads;
- // 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 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(gameplay::Keyboard::Key key)
- {
- switch (key)
- {
- 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;
- }
- }
- // Included here to avoid the naming conflict between KEY_* defined in input.h and the ones defined in gameplay/Keyboard.h
- #include <linux/joystick.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);
- }
- extern int strcmpnocase(const char* s1, const char* s2)
- {
- return strcasecmp(s1, s2);
- }
- Platform::Platform(Game* game) : _game(game)
- {
- }
- Platform::~Platform()
- {
- }
- Platform* Platform::create(Game* game)
- {
- GP_ASSERT(game);
- 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())
- {
- Properties* config = game->getConfig()->getNamespace("window", true);
- if (config)
- {
- // 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;
- }
- }
- // 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);
- }
- }
- double timespec2millis(struct timespec *a)
- {
- GP_ASSERT(a);
- return (1000.0 * a->tv_sec) + (0.000001 * a->tv_nsec);
- }
- void updateWindowSize()
- {
- GP_ASSERT(__display);
- GP_ASSERT(__window);
- XWindowAttributes windowAttrs;
- XGetWindowAttributes(__display, __window, &windowAttrs);
- __windowSize[0] = windowAttrs.width;
- __windowSize[1] = windowAttrs.height;
- }
- // Will need to be dynamic, also should be handled in Gamepad class
- static const GamepadInfoEntry gamepadLookupTable[] =
- {
- {0x0,0x0,"Microsoft Xbox 360 Controller",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
- }
- },
- {0x54c,0x268,"Sony 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
- }
- },
- {0x79,0x6,"Generic USB Controller",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,
- }
- }
- };
- bool isGamepadDevRegistered(dev_t devId)
- {
- for (list<ConnectedGamepadDevInfo>::iterator it = __connectedGamepads.begin(); it != __connectedGamepads.end(); ++it)
- {
- if (devId == (*it).deviceId)
- return true;
- }
- return false;
- }
- void closeGamepad(const ConnectedGamepadDevInfo& gamepadDevInfo)
- {
- ::close(gamepadDevInfo.fd);
- }
- void unregisterGamepad(GamepadHandle handle)
- {
- for (list<ConnectedGamepadDevInfo>::iterator it = __connectedGamepads.begin(); it != __connectedGamepads.end(); ++it)
- {
- if (handle == (*it).fd)
- {
- closeGamepad(*it);
- __connectedGamepads.erase(it);
- return;
- }
- }
- }
- void closeAllGamepads()
- {
- for (list<ConnectedGamepadDevInfo>::iterator it = __connectedGamepads.begin(); it != __connectedGamepads.end(); ++it)
- {
- closeGamepad(*it);
- __connectedGamepads.erase(it);
- }
- }
- 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;
- }
- }
- 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)
- {
- GP_ASSERT(handle >= 0);
- 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];
- }
- 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;
- }
- 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;
- }
- 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;
- }
- 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)
- {
- int absAxisValue = 0;
- if (zeroToOne)
- absAxisValue = (axisValue + 32767) / 2.0;
- else
- absAxisValue = abs(axisValue);
- if (absAxisValue < deadZone)
- {
- return 0.0f;
- }
- else
- {
- int maxVal = 0;
- int value = 0;
- if(!zeroToOne)
- {
- value = axisValue;
- if (value < 0)
- {
- value = -1;
- maxVal = 32768;
- }
- else if (value > 0)
- {
- value = 1;
- maxVal = 32767;
- }
- else
- {
- return 0.0f;
- }
- }
- 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];
- 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))
- {
- char cursysFSPath[35];
- sprintf(cursysFSPath,sysfsPathFormat,i);
- handleConnectedGamepad(devid,curDevPath,cursysFSPath);
- }
- }
- }
- }
- void gamepadHandlingLoop()
- {
- enumGamepads();
- }
- int Platform::enterMessagePump()
- {
- GP_ASSERT(_game);
- updateWindowSize();
- 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)
- {
- poll( xpolls, 1, 16 );
- // handle all pending events in one block
- while (XPending(__display))
- {
- XNextEvent(__display, &evt);
- switch (evt.type)
- {
- case ClientMessage:
- {
- // Handle destroy window message correctly
- if (evt.xclient.data.l[0] == __atomWmDeleteWindow)
- {
- _game->exit();
- }
- }
- break;
- case DestroyNotify :
- {
- cleanupX11();
- exit(0);
- }
- break;
- case Expose:
- {
- updateWindowSize();
- }
- break;
- case KeyPress:
- {
- KeySym sym = XLookupKeysym(&evt.xkey, (evt.xkey.state & shiftDown) ? 1 : 0);
- //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);
- 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:
- {
- //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;
- }
- break;
- 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, true);
- }
- }
- break;
- 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, true);
- }
- }
- break;
- 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, true);
- }
- }
- }
- break;
- default:
- break;
- }
- }
- 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);
- }
- cleanupX11();
- return 0;
- }
- void Platform::signalShutdown()
- {
- }
- bool Platform::canExit()
- {
- return true;
- }
- unsigned int Platform::getDisplayWidth()
- {
- return __windowSize[0];
- }
- unsigned int Platform::getDisplayHeight()
- {
- return __windowSize[1];
- }
- double Platform::getAbsoluteTime()
- {
- clock_gettime(CLOCK_REALTIME, &__timespec);
- double now = timespec2millis(&__timespec);
- __timeAbsolute = now - __timeStart;
- return __timeAbsolute;
- }
- void Platform::setAbsoluteTime(double time)
- {
- __timeAbsolute = time;
- }
- 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);
- __vsync = enable;
- }
- void Platform::swapBuffers()
- {
- glXSwapBuffers(__display, __window);
- }
- void Platform::sleep(long ms)
- {
- usleep(ms * 1000);
- }
- void Platform::setMultiSampling(bool enabled)
- {
- if (enabled == __multiSampling)
- {
- return;
- }
-
- // TODO
- __multiSampling = enabled;
- }
-
- bool Platform::isMultiSampling()
- {
- return __multiSampling;
- }
- void Platform::setMultiTouch(bool enabled)
- {
- // not supported
- }
- bool Platform::isMultiTouch()
- {
- false;
- }
- bool Platform::hasAccelerometer()
- {
- return false;
- }
- void Platform::getAccelerometerValues(float* pitch, float* roll)
- {
- GP_ASSERT(pitch);
- GP_ASSERT(roll);
- *pitch = 0;
- *roll = 0;
- }
- void Platform::getSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ)
- {
- if (accelX)
- {
- *accelX = 0;
- }
- if (accelY)
- {
- *accelY = 0;
- }
- if (accelZ)
- {
- *accelZ = 0;
- }
- if (gyroX)
- {
- *gyroX = 0;
- }
- if (gyroY)
- {
- *gyroY = 0;
- }
- if (gyroZ)
- {
- *gyroZ = 0;
- }
- }
- void Platform::getArguments(int* argc, char*** argv)
- {
- if (argc)
- *argc = __argc;
- if (argv)
- *argv = __argv;
- }
- bool Platform::hasMouse()
- {
- return true;
- }
- void Platform::setMouseCaptured(bool captured)
- {
- if (captured != __mouseCaptured)
- {
- 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);
- }
- __mouseCaptured = captured;
- }
- }
- bool Platform::isMouseCaptured()
- {
- return __mouseCaptured;
- }
- void Platform::setCursorVisible(bool visible)
- {
- if (visible != __cursorVisible)
- {
- 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;
- }
- }
- bool Platform::isCursorVisible()
- {
- return __cursorVisible;
- }
- void Platform::displayKeyboard(bool display)
- {
- // not supported
- }
- void Platform::shutdownInternal()
- {
- closeAllGamepads();
- Game::getInstance()->shutdown();
- }
- bool Platform::isGestureSupported(Gesture::GestureEvent evt)
- {
- return false;
- }
- void Platform::registerGesture(Gesture::GestureEvent evt)
- {
- }
- void Platform::unregisterGesture(Gesture::GestureEvent evt)
- {
- }
- bool Platform::isGestureRegistered(Gesture::GestureEvent evt)
- {
- return false;
- }
- void Platform::pollGamepadState(Gamepad* gamepad)
- {
- GP_ASSERT(gamepad);
- struct js_event jevent;
- const GamepadInfoEntry& gpInfo = getGamepadMappedInfo(gamepad->_handle);
- 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))
- {
- unsigned int buttons = 0;
- if (jevent.value)
- buttons |= (1 << curMappingIndex);
- else
- buttons &= ~(1 << curMappingIndex);
- gamepad->setButtons(buttons);
- }
- 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))
- {
- unsigned int buttons = 0;
- if(jevent.value != 0)
- buttons |= (1 << (jevent.value > 0 ? jsInfo->mappedPosArg : jsInfo->mappedNegArg));
- else
- {
- buttons &= ~(1 << jsInfo->mappedPosArg);
- buttons &= ~(1 << jsInfo->mappedNegArg);
- }
- gamepad->setButtons(buttons);
- not_js_axis = true;
- }
- if((jsInfo->flags & GP_AXIS_IS_TRIGGER))
- {
- gamepad->setTriggerValue(jsInfo->mappedPosArg, val);
- not_js_axis = true;
- }
- if(!not_js_axis)
- {
- Vector2 jsVals;
- gamepad->getJoystickValues(jsInfo->joystickIndex,&jsVals);
- if(jsInfo->flags & GP_AXIS_IS_XAXIS)
- jsVals.x = val;
- else
- jsVals.y = val;
- gamepad->setJoystickValue(jsInfo->joystickIndex,jsVals.x,jsVals.y);
- }
- }
- }
- }
- }
- break;
- default:
- GP_WARN("unhandled gamepad event: %x\n", jevent.type);
- }
- }
- if(errno == ENODEV)
- {
- unregisterGamepad(gamepad->_handle);
- gamepadEventDisconnectedInternal(gamepad->_handle);
- }
- }
- bool Platform::launchURL(const char* url)
- {
- if (url == NULL || *url == '\0')
- return false;
- 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);
- }
- std::string Platform::displayFileDialog(size_t mode, const char* title, const char* filterDescription, const char* filterExtensions, const char* initialDirectory)
- {
- std::string filename = "";
- if (!gtk_init_check(NULL,NULL))
- return "";
- // Create the dialog in one of two modes, SAVE or OPEN
- GtkWidget *dialog;
- dialog = gtk_file_chooser_dialog_new(title, NULL,
- mode == FileSystem::SAVE ? GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_OPEN,
- _("_Cancel"), GTK_RESPONSE_CANCEL,
- mode == FileSystem::SAVE ? _("_Save") : _("_Open"),
- GTK_RESPONSE_ACCEPT, NULL);
- // Filter on extensions
- GtkFileFilter* filter = gtk_file_filter_new();
- std::istringstream f(filterExtensions);
- std::string s;
- std::string extStr;
- while (std::getline(f, s, ';'))
- {
- extStr = "*.";
- extStr += s;
- gtk_file_filter_add_pattern(filter, extStr.c_str());
- }
- gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
- // Set initial directory
- std::string initialDirectoryStr;
- if (initialDirectory == NULL)
- {
- char* currentDir = g_get_current_dir();
- initialDirectoryStr = currentDir;
- g_free(currentDir);
- }
- else
- {
- initialDirectoryStr = initialDirectory;
- }
- gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), initialDirectoryStr.c_str());
- if (mode == FileSystem::SAVE)
- {
- gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
- gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "");
- }
- // Show the dialog
- if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
- {
- char* szFilename;
- szFilename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
- filename = szFilename;
- g_free(szFilename);
- }
- gtk_widget_destroy(dialog);
- // Since we are not using gtk_main(), this will let the dialog close
- while (gtk_events_pending())
- gtk_main_iteration();
- return filename;
- }
- }
- #endif
|