gs_platform_impl.h 129 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841
  1. /*==============================================================================================================
  2. * Copyright (c) 2020 John Jackson
  3. * File: gs_platform_impl.h
  4. * Github: https://github.com/MrFrenik/gunslinger
  5. * All Rights Reserved
  6. * MIT License
  7. * May all those that this source may reach be blessed by the LORD and find peace and joy in life.
  8. * Everyone who drinks of this water will be thirsty again; but whoever drinks of the water
  9. * that I will give him shall never thirst; John 4:13-14
  10. * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  11. * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
  12. * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
  13. * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
  14. * The above copyright, blessing, biblical verse, notice and this permission notice shall be included in all
  15. * copies or substantial portions of the Software.
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  17. * TO THE WARRANTIES OF MECHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  19. * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. * IN THE SOFTWARE.
  21. =================================================================================================================*/
  22. #ifndef GS_PLATFORM_IMPL_H
  23. #define GS_PLATFORM_IMPL_H
  24. /*=================================
  25. // Default Platform Implemenattion
  26. =================================*/
  27. // Define default platform implementation if certain platforms are enabled
  28. #if (!defined GS_PLATFORM_IMPL_NO_DEFAULT)
  29. #define GS_PLATFORM_IMPL_DEFAULT
  30. #endif
  31. /*=============================
  32. // Default Impl
  33. =============================*/
  34. #ifdef GS_PLATFORM_IMPL_DEFAULT
  35. #if !(defined GS_PLATFORM_WIN)
  36. #include <sys/stat.h>
  37. #include <dirent.h>
  38. #include <dlfcn.h> // dlopen, RTLD_LAZY, dlsym
  39. #else
  40. #include "../external/dirent/dirent.h"
  41. #include <direct.h>
  42. #endif
  43. /*== Platform Window ==*/
  44. GS_API_DECL gs_platform_t*
  45. gs_platform_create()
  46. {
  47. // Construct new platform interface
  48. gs_platform_t* platform = gs_malloc_init(gs_platform_t);
  49. // Initialize windows
  50. platform->windows = gs_slot_array_new(gs_platform_window_t);
  51. // Set up video mode (for now, just do opengl)
  52. platform->settings.video.driver = GS_PLATFORM_VIDEO_DRIVER_TYPE_OPENGL;
  53. return platform;
  54. }
  55. GS_API_DECL void
  56. gs_platform_destroy(gs_platform_t* platform)
  57. {
  58. if (platform == NULL) return;
  59. // Free all resources
  60. gs_slot_array_free(platform->windows);
  61. // Free platform
  62. gs_free(platform);
  63. platform = NULL;
  64. }
  65. GS_API_DECL uint32_t
  66. gs_platform_window_create(const gs_platform_window_desc_t* desc)
  67. {
  68. gs_assert(gs_instance() != NULL);
  69. gs_platform_t* platform = gs_subsystem(platform);
  70. gs_platform_window_t win = gs_platform_window_create_internal(desc);
  71. // Insert and return handle
  72. return (gs_slot_array_insert(platform->windows, win));
  73. }
  74. GS_API_DECL uint32_t
  75. gs_platform_main_window()
  76. {
  77. // Should be the first element of the slot array...Great assumption to make.
  78. return 0;
  79. }
  80. /*== Platform Time ==*/
  81. GS_API_DECL const
  82. gs_platform_time_t* gs_platform_time()
  83. {
  84. return &gs_subsystem(platform)->time;
  85. }
  86. GS_API_DECL float
  87. gs_platform_delta_time()
  88. {
  89. return gs_platform_time()->delta;
  90. }
  91. GS_API_DECL float
  92. gs_platform_frame_time()
  93. {
  94. return gs_platform_time()->frame;
  95. }
  96. /*== Platform UUID ==*/
  97. GS_API_DECL struct gs_uuid_t
  98. gs_platform_uuid_generate()
  99. {
  100. gs_uuid_t uuid;
  101. srand(clock());
  102. char guid[40];
  103. int32_t t = 0;
  104. const char* sz_temp = "xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx";
  105. const char* sz_hex = "0123456789abcdef-";
  106. int32_t n_len = (int32_t)strlen(sz_temp);
  107. for (t=0; t < n_len + 1; t++)
  108. {
  109. int32_t r = rand () % 16;
  110. char c = ' ';
  111. switch (sz_temp[t])
  112. {
  113. case 'x' : { c = sz_hex [r]; } break;
  114. case 'y' : { c = sz_hex [(r & 0x03) | 0x08]; } break;
  115. case '-' : { c = '-'; } break;
  116. case '4' : { c = '4'; } break;
  117. }
  118. guid[t] = (t < n_len) ? c : 0x00;
  119. }
  120. // Convert to uuid bytes from string
  121. const char* hex_string = guid, *pos = hex_string;
  122. /* WARNING: no sanitization or error-checking whatsoever */
  123. for (size_t count = 0; count < 16; count++)
  124. {
  125. sscanf(pos, "%2hhx", &uuid.bytes[count]);
  126. pos += 2;
  127. }
  128. return uuid;
  129. }
  130. // Mutable temp buffer 'tmp_buffer'
  131. GS_API_DECL void
  132. gs_platform_uuid_to_string(char* tmp_buffer, const gs_uuid_t* uuid)
  133. {
  134. gs_snprintf
  135. (
  136. tmp_buffer,
  137. 32,
  138. "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
  139. uuid->bytes[0],
  140. uuid->bytes[1],
  141. uuid->bytes[2],
  142. uuid->bytes[3],
  143. uuid->bytes[4],
  144. uuid->bytes[5],
  145. uuid->bytes[6],
  146. uuid->bytes[7],
  147. uuid->bytes[8],
  148. uuid->bytes[9],
  149. uuid->bytes[10],
  150. uuid->bytes[11],
  151. uuid->bytes[12],
  152. uuid->bytes[13],
  153. uuid->bytes[14],
  154. uuid->bytes[15]
  155. );
  156. }
  157. uint32_t gs_platform_uuid_hash(const gs_uuid_t* uuid)
  158. {
  159. char temp_buffer[] = gs_uuid_temp_str_buffer();
  160. gs_platform_uuid_to_string(temp_buffer, uuid);
  161. return (gs_hash_str(temp_buffer));
  162. }
  163. #define __gs_input()\
  164. (&gs_subsystem(platform)->input)
  165. /*=== Platform Input ===*/
  166. GS_API_DECL gs_platform_input_t* gs_platform_input()
  167. {
  168. return &gs_subsystem(platform)->input;
  169. }
  170. void gs_platform_update_input(gs_platform_input_t* input)
  171. {
  172. // Update all input and mouse keys from previous frame
  173. // Previous key presses
  174. gs_for_range_i(GS_KEYCODE_COUNT) {
  175. input->prev_key_map[i] = input->key_map[i];
  176. }
  177. // Previous mouse button presses
  178. gs_for_range_i(GS_MOUSE_BUTTON_CODE_COUNT) {
  179. input->mouse.prev_button_map[i] = input->mouse.button_map[i];
  180. }
  181. input->mouse.wheel = gs_v2s(0.0f);
  182. input->mouse.delta = gs_v2s(0.f);
  183. input->mouse.moved_this_frame = false;
  184. // Update all touch deltas
  185. for (uint32_t i = 0; i < GS_PLATFORM_MAX_TOUCH; ++i) {
  186. input->touch.points[i].delta = gs_v2s(0.f);
  187. input->touch.points[i].down = input->touch.points[i].pressed;
  188. }
  189. }
  190. void gs_platform_poll_all_events()
  191. {
  192. gs_platform_t* platform = gs_subsystem(platform);
  193. platform->input.mouse.delta.x = 0;
  194. platform->input.mouse.delta.y = 0;
  195. // Iterate through events, don't consume
  196. gs_platform_event_t evt = gs_default_val();
  197. while (gs_platform_poll_events(&evt, false))
  198. {
  199. switch (evt.type)
  200. {
  201. case GS_PLATFORM_EVENT_MOUSE:
  202. {
  203. switch (evt.mouse.action)
  204. {
  205. case GS_PLATFORM_MOUSE_MOVE:
  206. {
  207. // If locked, then movement amount will be applied to delta,
  208. // otherwise set position
  209. if (gs_platform_mouse_locked()) {
  210. platform->input.mouse.delta = gs_vec2_add(platform->input.mouse.delta, evt.mouse.move);
  211. } else {
  212. platform->input.mouse.delta = gs_vec2_sub(evt.mouse.move, platform->input.mouse.position);
  213. platform->input.mouse.position = evt.mouse.move;
  214. }
  215. } break;
  216. case GS_PLATFORM_MOUSE_WHEEL:
  217. {
  218. platform->input.mouse.wheel = evt.mouse.wheel;
  219. } break;
  220. case GS_PLATFORM_MOUSE_BUTTON_PRESSED:
  221. {
  222. gs_platform_press_mouse_button(evt.mouse.button);
  223. } break;
  224. case GS_PLATFORM_MOUSE_BUTTON_RELEASED:
  225. {
  226. gs_platform_release_mouse_button(evt.mouse.button);
  227. } break;
  228. case GS_PLATFORM_MOUSE_BUTTON_DOWN:
  229. {
  230. gs_platform_press_mouse_button(evt.mouse.button);
  231. } break;
  232. case GS_PLATFORM_MOUSE_ENTER:
  233. {
  234. // If there are user callbacks, could trigger them here
  235. } break;
  236. case GS_PLATFORM_MOUSE_LEAVE:
  237. {
  238. // If there are user callbacks, could trigger them here
  239. } break;
  240. }
  241. } break;
  242. case GS_PLATFORM_EVENT_KEY:
  243. {
  244. switch (evt.key.action)
  245. {
  246. case GS_PLATFORM_KEY_PRESSED:
  247. {
  248. gs_platform_press_key(evt.key.keycode);
  249. } break;
  250. case GS_PLATFORM_KEY_DOWN:
  251. {
  252. gs_platform_press_key(evt.key.keycode);
  253. } break;
  254. case GS_PLATFORM_KEY_RELEASED:
  255. {
  256. gs_platform_release_key(evt.key.keycode);
  257. } break;
  258. }
  259. } break;
  260. case GS_PLATFORM_EVENT_WINDOW:
  261. {
  262. switch (evt.window.action)
  263. {
  264. default: break;
  265. }
  266. } break;
  267. case GS_PLATFORM_EVENT_TOUCH:
  268. {
  269. gs_platform_point_event_data_t* point = &evt.touch.point;
  270. switch (evt.touch.action)
  271. {
  272. case GS_PLATFORM_TOUCH_DOWN:
  273. {
  274. uintptr_t id = point->id;
  275. gs_vec2 *pos = &point->position;
  276. gs_vec2 *p = &platform->input.touch.points[id].position;
  277. gs_vec2 *d = &platform->input.touch.points[id].delta;
  278. gs_platform_press_touch(id);
  279. *p = *pos;
  280. gs_subsystem(platform)->input.touch.size++;
  281. } break;
  282. case GS_PLATFORM_TOUCH_UP:
  283. {
  284. uintptr_t id = point->id;
  285. gs_println("Releasing ID: %zu", id);
  286. gs_platform_release_touch(id);
  287. gs_subsystem(platform)->input.touch.size--;
  288. } break;
  289. case GS_PLATFORM_TOUCH_MOVE:
  290. {
  291. uintptr_t id = point->id;
  292. gs_vec2* pos = &point->position;
  293. gs_vec2* p = &platform->input.touch.points[id].position;
  294. gs_vec2* d = &platform->input.touch.points[id].delta;
  295. gs_platform_press_touch(id); // Not sure if this is causing issues...
  296. *d = gs_vec2_sub(*pos, *p);
  297. *p = *pos;
  298. } break;
  299. case GS_PLATFORM_TOUCH_CANCEL:
  300. {
  301. uintptr_t id = point->id;
  302. gs_platform_release_touch(id);
  303. gs_subsystem(platform)->input.touch.size--;
  304. } break;
  305. }
  306. } break;
  307. default: break;
  308. }
  309. }
  310. }
  311. void gs_platform_update(gs_platform_t* platform)
  312. {
  313. // Update platform input from previous frame
  314. gs_platform_update_input(&platform->input);
  315. // Process input for this frame (user dependent update)
  316. gs_platform_process_input(&platform->input);
  317. // Poll all events
  318. gs_platform_poll_all_events();
  319. gs_platform_update_internal(platform);
  320. }
  321. bool gs_platform_poll_events(gs_platform_event_t* evt, bool32_t consume)
  322. {
  323. gs_platform_t* platform = gs_subsystem(platform);
  324. if (!evt) return false;
  325. if (gs_dyn_array_empty(platform->events)) return false;
  326. if (evt->idx >= gs_dyn_array_size(platform->events)) return false;
  327. if (consume) {
  328. // Back event
  329. *evt = gs_dyn_array_back(platform->events);
  330. // Pop back
  331. gs_dyn_array_pop(platform->events);
  332. }
  333. else {
  334. uint32_t idx = evt->idx;
  335. *evt = platform->events[idx++];
  336. evt->idx = idx;
  337. }
  338. return true;
  339. }
  340. void gs_platform_add_event(gs_platform_event_t* evt)
  341. {
  342. gs_platform_t* platform = gs_subsystem(platform);
  343. if (!evt) return;
  344. gs_dyn_array_push(platform->events, *evt);
  345. }
  346. bool gs_platform_was_key_down(gs_platform_keycode code)
  347. {
  348. gs_platform_input_t* input = __gs_input();
  349. return (input->prev_key_map[code]);
  350. }
  351. bool gs_platform_key_down(gs_platform_keycode code)
  352. {
  353. gs_platform_input_t* input = __gs_input();
  354. return (input->key_map[code]);
  355. }
  356. bool gs_platform_key_pressed(gs_platform_keycode code)
  357. {
  358. gs_platform_input_t* input = __gs_input();
  359. return (gs_platform_key_down(code) && !gs_platform_was_key_down(code));
  360. }
  361. bool gs_platform_key_released(gs_platform_keycode code)
  362. {
  363. gs_platform_input_t* input = __gs_input();
  364. return (gs_platform_was_key_down(code) && !gs_platform_key_down(code));
  365. }
  366. bool gs_platform_touch_down(uint32_t idx)
  367. {
  368. gs_platform_input_t* input = __gs_input();
  369. if (idx < GS_PLATFORM_MAX_TOUCH) {
  370. return input->touch.points[idx].pressed;
  371. }
  372. return false;
  373. }
  374. bool gs_platform_touch_pressed(uint32_t idx)
  375. {
  376. gs_platform_input_t* input = __gs_input();
  377. if (idx < GS_PLATFORM_MAX_TOUCH) {
  378. return (gs_platform_was_touch_down(idx) && !gs_platform_touch_down(idx));
  379. }
  380. return false;
  381. }
  382. bool gs_platform_touch_released(uint32_t idx)
  383. {
  384. gs_platform_input_t* input = __gs_input();
  385. if (idx < GS_PLATFORM_MAX_TOUCH) {
  386. return (gs_platform_was_touch_down(idx) && !gs_platform_touch_down(idx));
  387. }
  388. return false;
  389. }
  390. bool gs_platform_was_mouse_down(gs_platform_mouse_button_code code)
  391. {
  392. gs_platform_input_t* input = __gs_input();
  393. return (input->mouse.prev_button_map[code]);
  394. }
  395. void gs_platform_press_mouse_button(gs_platform_mouse_button_code code)
  396. {
  397. gs_platform_input_t* input = __gs_input();
  398. if ((u32)code < (u32)GS_MOUSE_BUTTON_CODE_COUNT)
  399. {
  400. input->mouse.button_map[code] = true;
  401. }
  402. }
  403. void gs_platform_release_mouse_button(gs_platform_mouse_button_code code)
  404. {
  405. gs_platform_input_t* input = __gs_input();
  406. if ((u32)code < (u32)GS_MOUSE_BUTTON_CODE_COUNT)
  407. {
  408. input->mouse.button_map[code] = false;
  409. }
  410. }
  411. bool gs_platform_mouse_down(gs_platform_mouse_button_code code)
  412. {
  413. gs_platform_input_t* input = __gs_input();
  414. return (input->mouse.button_map[code]);
  415. }
  416. bool gs_platform_mouse_pressed(gs_platform_mouse_button_code code)
  417. {
  418. gs_platform_input_t* input = __gs_input();
  419. if (gs_platform_mouse_down(code) && !gs_platform_was_mouse_down(code))
  420. {
  421. return true;
  422. }
  423. return false;
  424. }
  425. bool gs_platform_mouse_released(gs_platform_mouse_button_code code)
  426. {
  427. gs_platform_input_t* input = __gs_input();
  428. return (gs_platform_was_mouse_down(code) && !gs_platform_mouse_down(code));
  429. }
  430. bool gs_platform_mouse_moved()
  431. {
  432. gs_platform_input_t* input = __gs_input();
  433. return (input->mouse.delta.x != 0.f || input->mouse.delta.y != 0.f);
  434. }
  435. void gs_platform_mouse_delta(float* x, float* y)
  436. {
  437. gs_platform_input_t* input = __gs_input();
  438. *x = input->mouse.delta.x;
  439. *y = input->mouse.delta.y;
  440. }
  441. gs_vec2 gs_platform_mouse_deltav()
  442. {
  443. gs_platform_input_t* input = __gs_input();
  444. gs_vec2 delta = gs_default_val();
  445. gs_platform_mouse_delta(&delta.x, &delta.y);
  446. return delta;
  447. }
  448. gs_vec2 gs_platform_mouse_positionv()
  449. {
  450. gs_platform_input_t* input = __gs_input();
  451. return gs_v2(
  452. input->mouse.position.x,
  453. input->mouse.position.y
  454. );
  455. }
  456. void gs_platform_mouse_position(int32_t* x, int32_t* y)
  457. {
  458. gs_platform_input_t* input = __gs_input();
  459. *x = (int32_t)input->mouse.position.x;
  460. *y = (int32_t)input->mouse.position.y;
  461. }
  462. void gs_platform_mouse_wheel(f32* x, f32* y)
  463. {
  464. gs_platform_input_t* input = __gs_input();
  465. *x = input->mouse.wheel.x;
  466. *y = input->mouse.wheel.y;
  467. }
  468. GS_API_DECL gs_vec2 gs_platform_mouse_wheelv()
  469. {
  470. gs_vec2 wheel = gs_default_val();
  471. gs_platform_mouse_wheel(&wheel.x, &wheel.y);
  472. return wheel;
  473. }
  474. bool gs_platform_mouse_locked()
  475. {
  476. return (__gs_input())->mouse.locked;
  477. }
  478. void gs_platform_touch_delta(uint32_t idx, float* x, float* y)
  479. {
  480. gs_platform_input_t* input = __gs_input();
  481. if (idx < GS_PLATFORM_MAX_TOUCH) {
  482. *x = input->touch.points[idx].delta.x;
  483. *y = input->touch.points[idx].delta.y;
  484. }
  485. }
  486. gs_vec2 gs_platform_touch_deltav(uint32_t idx)
  487. {
  488. gs_vec2 delta = gs_v2s(0.f);
  489. gs_platform_touch_delta(idx, &delta.x, &delta.y);
  490. return delta;
  491. }
  492. void gs_platform_touch_position(uint32_t idx, float* x, float* y)
  493. {
  494. gs_platform_input_t* input = __gs_input();
  495. if (idx < GS_PLATFORM_MAX_TOUCH) {
  496. *x = input->touch.points[idx].position.x;
  497. *y = input->touch.points[idx].position.y;
  498. }
  499. }
  500. gs_vec2 gs_platform_touch_positionv(uint32_t idx)
  501. {
  502. gs_vec2 p = gs_default_val();
  503. gs_platform_touch_position(idx, &p.x, &p.y);
  504. return p;
  505. }
  506. void gs_platform_press_touch(uint32_t idx)
  507. {
  508. gs_platform_input_t* input = __gs_input();
  509. if (idx < GS_PLATFORM_MAX_TOUCH) {
  510. input->touch.points[idx].pressed = true;
  511. }
  512. }
  513. void gs_platform_release_touch(uint32_t idx)
  514. {
  515. gs_platform_input_t* input = __gs_input();
  516. if (idx < GS_PLATFORM_MAX_TOUCH) {
  517. gs_println("releasing: %zu", idx);
  518. input->touch.points[idx].pressed = false;
  519. }
  520. }
  521. bool gs_platform_was_touch_down(uint32_t idx)
  522. {
  523. gs_platform_input_t* input = __gs_input();
  524. if (idx < GS_PLATFORM_MAX_TOUCH) {
  525. return input->touch.points[idx].down;
  526. }
  527. return false;
  528. }
  529. void gs_platform_press_key(gs_platform_keycode code)
  530. {
  531. gs_platform_input_t* input = __gs_input();
  532. if (code < GS_KEYCODE_COUNT) {
  533. input->key_map[code] = true;
  534. }
  535. }
  536. void gs_platform_release_key(gs_platform_keycode code)
  537. {
  538. gs_platform_input_t* input = __gs_input();
  539. if (code < GS_KEYCODE_COUNT) {
  540. input->key_map[code] = false;
  541. }
  542. }
  543. // Platform File IO
  544. char* gs_platform_read_file_contents_default_impl(const char* file_path, const char* mode, size_t* sz)
  545. {
  546. const char* path = file_path;
  547. #ifdef GS_PLATFORM_ANDROID
  548. const char* internal_data_path = gs_app()->android.internal_data_path;
  549. gs_snprintfc(tmp_path, 1024, "%s/%s", internal_data_path, file_path);
  550. path = tmp_path;
  551. #endif
  552. char* buffer = 0;
  553. FILE* fp = fopen(path, mode);
  554. size_t read_sz = 0;
  555. if (fp)
  556. {
  557. read_sz = gs_platform_file_size_in_bytes(file_path);
  558. buffer = (char*)gs_malloc(read_sz + 1);
  559. if (buffer) {
  560. size_t _r = fread(buffer, 1, read_sz, fp);
  561. }
  562. buffer[read_sz] = '\0';
  563. fclose(fp);
  564. if (sz) *sz = read_sz;
  565. }
  566. return buffer;
  567. }
  568. gs_result gs_platform_write_file_contents_default_impl(const char* file_path, const char* mode, void* data, size_t sz)
  569. {
  570. const char* path = file_path;
  571. #ifdef GS_PLATFORM_ANDROID
  572. const char* internal_data_path = gs_app()->android.internal_data_path;
  573. gs_snprintfc(tmp_path, 1024, "%s/%s", internal_data_path, file_path);
  574. path = tmp_path;
  575. #endif
  576. FILE* fp = fopen(path, mode);
  577. if (fp)
  578. {
  579. size_t ret = fwrite(data, sizeof(uint8_t), sz, fp);
  580. if (ret == sz)
  581. {
  582. fclose(fp);
  583. return GS_RESULT_SUCCESS;
  584. }
  585. fclose(fp);
  586. }
  587. return GS_RESULT_FAILURE;
  588. }
  589. GS_API_DECL bool gs_platform_dir_exists_default_impl(const char* dir_path)
  590. {
  591. DIR* dir = opendir(dir_path);
  592. if (dir)
  593. {
  594. closedir(dir);
  595. return true;
  596. }
  597. return false;
  598. }
  599. GS_API_DECL int32_t gs_platform_mkdir_default_impl(const char* dir_path, int32_t opt)
  600. {
  601. #if defined(__MINGW32__) || defined(_MSC_VER)
  602. return mkdir(dir_path);
  603. #else
  604. return mkdir(dir_path, opt);
  605. #endif
  606. }
  607. bool gs_platform_file_exists_default_impl(const char* file_path)
  608. {
  609. const char* path = file_path;
  610. #ifdef GS_PLATFORM_ANDROID
  611. const char* internal_data_path = gs_app()->android.internal_data_path;
  612. gs_snprintfc(tmp_path, 1024, "%s/%s", internal_data_path, file_path);
  613. path = tmp_path;
  614. #endif
  615. FILE* fp = fopen(path, "r");
  616. if (fp) {
  617. fclose(fp);
  618. return true;
  619. }
  620. return false;
  621. }
  622. int32_t gs_platform_file_size_in_bytes_default_impl(const char* file_path)
  623. {
  624. #ifdef GS_PLATFORM_WIN
  625. HANDLE hFile = CreateFile(file_path, GENERIC_READ,
  626. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
  627. FILE_ATTRIBUTE_NORMAL, NULL);
  628. if (hFile==INVALID_HANDLE_VALUE)
  629. return -1; // error condition, could call GetLastError to find out more
  630. LARGE_INTEGER size;
  631. if (!GetFileSizeEx(hFile, &size))
  632. {
  633. CloseHandle(hFile);
  634. return -1; // error condition, could call GetLastError to find out more
  635. }
  636. CloseHandle(hFile);
  637. return gs_util_safe_truncate_u64(size.QuadPart);
  638. #elif (defined GS_PLATFORM_ANDROID)
  639. const char* internal_data_path = gs_app()->android.internal_data_path;
  640. gs_snprintfc(tmp_path, 1024, "%s/%s", internal_data_path, file_path);
  641. struct stat st;
  642. stat(tmp_path, &st);
  643. return (int32_t)st.st_size;
  644. #else
  645. struct stat st;
  646. stat(file_path, &st);
  647. return (int32_t)st.st_size;
  648. #endif
  649. }
  650. void gs_platform_file_extension_default_impl(char* buffer, size_t buffer_sz, const char* file_path)
  651. {
  652. gs_util_get_file_extension(buffer, buffer_sz, file_path);
  653. }
  654. GS_API_DECL int32_t
  655. gs_platform_file_delete_default_impl(const char* file_path)
  656. {
  657. #if (defined GS_PLATFORM_WIN)
  658. // Non-zero if successful
  659. return DeleteFile(file_path);
  660. #elif (defined GS_PLATFORM_LINUX || defined GS_PLATFORM_APPLE || defined GS_PLATFORM_ANDROID)
  661. // Returns 0 if successful
  662. return !remove(file_path);
  663. #endif
  664. return 0;
  665. }
  666. GS_API_DECL int32_t
  667. gs_platform_file_copy_default_impl(const char* src_path, const char* dst_path)
  668. {
  669. #if (defined GS_PLATFORM_WIN)
  670. return CopyFile(src_path, dst_path, false);
  671. #elif (defined GS_PLATFORM_LINUX || defined GS_PLATFORM_APPLE || defined GS_PLATFORM_ANDROID)
  672. FILE* file_w = NULL;
  673. FILE* file_r = NULL;
  674. char buffer[2048] = gs_default_val();
  675. if ((file_w = fopen(src_path, "wb")) == NULL) {
  676. return 0;
  677. }
  678. if ((file_r = fopen(dst_path, "rb")) == NULL) {
  679. return 0;
  680. }
  681. // Read file in 2kb chunks to write to location
  682. int32_t len = 0;
  683. while ((len = fread(buffer, sizeof(buffer), 1, file_r)) > 0) {
  684. fwrite(buffer, len, 1, file_w);
  685. }
  686. // Close both files
  687. fclose(file_r);
  688. fclose(file_w);
  689. #endif
  690. return 0;
  691. }
  692. GS_API_DECL int32_t
  693. gs_platform_file_compare_time(uint64_t time_a, uint64_t time_b)
  694. {
  695. return time_a < time_b ? -1 : time_a == time_b ? 0 : 1;
  696. }
  697. GS_API_DECL gs_platform_file_stats_t
  698. gs_platform_file_stats(const char* file_path)
  699. {
  700. gs_platform_file_stats_t stats = gs_default_val();
  701. #if (defined GS_PLATFORM_WIN)
  702. WIN32_FILE_ATTRIBUTE_DATA data = gs_default_val();
  703. FILETIME ftime = gs_default_val();
  704. FILETIME ctime = gs_default_val();
  705. FILETIME atime = gs_default_val();
  706. if (GetFileAttributesExA(file_path, GetFileExInfoStandard, &data))
  707. {
  708. ftime = data.ftLastWriteTime;
  709. ctime = data.ftCreationTime;
  710. atime = data.ftLastAccessTime;
  711. }
  712. stats.modified_time = *((uint64_t*)&ftime);
  713. stats.access_time = *((uint64_t*)&atime);
  714. stats.creation_time = *((uint64_t*)&ctime);
  715. #elif (defined GS_PLATFORM_LINUX || defined GS_PLATFORM_APPLE || defined GS_PLATFORM_ANDROID)
  716. struct stat attr = gs_default_val();
  717. stat(file_path, &attr);
  718. stats.modified_time = *((uint64_t*)&attr.st_mtime);
  719. #endif
  720. return stats;
  721. }
  722. GS_API_DECL void*
  723. gs_platform_library_load_default_impl(const char* lib_path)
  724. {
  725. #if (defined GS_PLATFORM_WIN)
  726. return (void*)LoadLibraryA(lib_path);
  727. #elif (defined GS_PLATFORM_LINUX || defined GS_PLATFORM_APPLE || defined GS_PLATFORM_ANDROID)
  728. return (void*)dlopen(lib_path, RTLD_LAZY);
  729. #endif
  730. return NULL;
  731. }
  732. GS_API_DECL void
  733. gs_platform_library_unload_default_impl(void* lib)
  734. {
  735. if (!lib) return;
  736. #if (defined GS_PLATFORM_WIN)
  737. FreeLibrary((HMODULE)lib);
  738. #elif (defined GS_PLATFORM_LINUX || defined GS_PLATFORM_APPLE || defined GS_PLATFORM_ANDROID)
  739. dlclose(lib);
  740. #endif
  741. }
  742. GS_API_DECL void*
  743. gs_platform_library_proc_address_default_impl(void* lib, const char* func)
  744. {
  745. if (!lib) return NULL;
  746. #if (defined GS_PLATFORM_WIN)
  747. return (void*)GetProcAddress((HMODULE)lib, func);
  748. #elif (defined GS_PLATFORM_LINUX || defined GS_PLATFORM_APPLE || defined GS_PLATFORM_ANDROID)
  749. return (void*)dlsym(lib, func);
  750. #endif
  751. return NULL;
  752. }
  753. #undef GS_PLATFORM_IMPL_DEFAULT
  754. #endif // GS_PLATFORM_IMPL_DEFAULT
  755. /*======================
  756. // GLFW Implemenation
  757. ======================*/
  758. #ifdef GS_PLATFORM_IMPL_GLFW
  759. #define GLAD_IMPL
  760. #include "../external/glad/glad_impl.h"
  761. #define GLFW_IMPL
  762. #include "../external/glfw/glfw_impl.h"
  763. #if (defined GS_PLATFORM_APPLE || defined GS_PLATFORM_LINUX)
  764. #include <sched.h>
  765. #include <unistd.h>
  766. #elif (defined GS_PLATFORM_WINDOWS)
  767. #define WIN32_LEAN_AND_MEAN
  768. #include <windows.h>
  769. #endif
  770. // Forward Decls.
  771. void __glfw_key_callback(GLFWwindow* window, s32 key, s32 scancode, s32 action, s32 mods);
  772. void __glfw_char_callback(GLFWwindow* window, uint32_t codepoint);
  773. void __glfw_mouse_button_callback(GLFWwindow* window, s32 button, s32 action, s32 mods);
  774. void __glfw_mouse_cursor_position_callback(GLFWwindow* window, f64 x, f64 y);
  775. void __glfw_mouse_scroll_wheel_callback(GLFWwindow* window, f64 xoffset, f64 yoffset);
  776. void __glfw_mouse_cursor_enter_callback(GLFWwindow* window, s32 entered);
  777. void __glfw_frame_buffer_size_callback(GLFWwindow* window, s32 width, s32 height);
  778. void __glfw_drop_callback(GLFWwindow* window);
  779. /*
  780. #define __glfw_window_from_handle(platform, handle)\
  781. ((GLFWwindow*)(gs_slot_array_get((platform)->windows, (handle))))
  782. */
  783. /*== Platform Init / Shutdown == */
  784. void gs_platform_init(gs_platform_t* pf)
  785. {
  786. gs_assert(pf);
  787. gs_println("Initializing GLFW");
  788. glfwInit();
  789. switch (pf->settings.video.driver)
  790. {
  791. case GS_PLATFORM_VIDEO_DRIVER_TYPE_OPENGL:
  792. {
  793. #if (defined GS_PLATFORM_APPLE)
  794. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
  795. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
  796. glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  797. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  798. glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE);
  799. #else
  800. glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
  801. // glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, platform->settings.video.graphics.opengl.major_version);
  802. // glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, platform->settings.video.graphics.opengl.minor_version);
  803. // glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
  804. // glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
  805. // glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  806. // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  807. if (pf->settings.video.graphics.debug)
  808. {
  809. glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
  810. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
  811. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  812. }
  813. #endif
  814. // glfwSwapInterval(platform->settings.video.vsync_enabled);
  815. // glfwSwapInterval(0);
  816. } break;
  817. default:
  818. {
  819. // Default to no output at all.
  820. gs_println("Video format not supported.");
  821. gs_assert(false);
  822. } break;
  823. }
  824. // Construct cursors
  825. pf->cursors[(u32)GS_PLATFORM_CURSOR_ARROW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
  826. pf->cursors[(u32)GS_PLATFORM_CURSOR_IBEAM] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
  827. pf->cursors[(u32)GS_PLATFORM_CURSOR_SIZE_NW_SE] = glfwCreateStandardCursor(GLFW_CROSSHAIR_CURSOR);
  828. pf->cursors[(u32)GS_PLATFORM_CURSOR_SIZE_NE_SW] = glfwCreateStandardCursor(GLFW_CROSSHAIR_CURSOR);
  829. pf->cursors[(u32)GS_PLATFORM_CURSOR_SIZE_NS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR);
  830. pf->cursors[(u32)GS_PLATFORM_CURSOR_SIZE_WE] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);
  831. pf->cursors[(u32)GS_PLATFORM_CURSOR_SIZE_ALL] = glfwCreateStandardCursor(GLFW_CROSSHAIR_CURSOR);
  832. pf->cursors[(u32)GS_PLATFORM_CURSOR_HAND] = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
  833. pf->cursors[(u32)GS_PLATFORM_CURSOR_NO] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
  834. // Poll joysticks here
  835. for (uint32_t i = 0; i < GS_PLATFORM_GAMEPAD_MAX; ++i) {
  836. pf->input.gamepads[i].present = glfwJoystickPresent(GLFW_JOYSTICK_1 + i);
  837. if (pf->input.gamepads[i].present)
  838. {
  839. gs_log_success("Controller %d connected.", i);
  840. }
  841. }
  842. }
  843. GS_API_DECL void gs_platform_update_internal(gs_platform_t* platform)
  844. {
  845. gs_platform_input_t* input = &platform->input;
  846. // Platform time
  847. platform->time.elapsed = (glfwGetTime() * 1000.0);
  848. // Update all window/framebuffer state
  849. for (
  850. gs_slot_array_iter it = gs_slot_array_iter_new(platform->windows);
  851. gs_slot_array_iter_valid(platform->windows, it);
  852. gs_slot_array_iter_advance(platform->windows, it)
  853. )
  854. {
  855. // Cache all necessary window information
  856. int32_t wx = 0, wy = 0, fx = 0, fy = 0, wpx = 0, wpy = 0;
  857. gs_platform_window_t* win = gs_slot_array_getp(platform->windows, it);
  858. glfwGetWindowSize((GLFWwindow*)win->hndl, &wx, &wy);
  859. glfwGetFramebufferSize((GLFWwindow*)win->hndl, &fx, &fy);
  860. glfwGetWindowPos((GLFWwindow*)win->hndl, &wpx, &wpy);
  861. win->window_size = gs_v2( (float)wx, (float)wy);
  862. win->window_position = gs_v2( (float)wpx, (float)wpy);
  863. win->framebuffer_size = gs_v2( (float)fx, (float)fy);
  864. }
  865. // Update all gamepad state
  866. for (uint32_t i = 0; i < GS_PLATFORM_GAMEPAD_MAX; ++i) {
  867. gs_platform_gamepad_t* gp = &input->gamepads[i];
  868. gp->present = glfwJoystickPresent(GLFW_JOYSTICK_1 + i);
  869. if (gp->present)
  870. {
  871. int32_t count = 0;
  872. const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1 + i, &count);
  873. count = gs_min(count, GS_PLATFORM_JOYSTICK_AXIS_COUNT);
  874. for (uint32_t a = 0; a < count; ++a) {
  875. gp->axes[a] = axes[a];
  876. }
  877. const uint8_t* buttons = (uint8_t*)glfwGetJoystickButtons(GLFW_JOYSTICK_1 + i, &count);
  878. count = gs_min(count, GS_PLATFORM_GAMEPAD_BUTTON_COUNT);
  879. for (uint32_t b = 0; b < count; ++b) {
  880. gp->buttons[b] = buttons[b];
  881. }
  882. }
  883. }
  884. }
  885. void gs_platform_shutdown(gs_platform_t* pf)
  886. {
  887. // Free all windows in glfw
  888. // TODO(john): Figure out crash with glfwDestroyWindow && glfwTerminate
  889. for
  890. (
  891. gs_slot_array_iter it = 0;
  892. gs_slot_array_iter_valid(pf->windows, it);
  893. gs_slot_array_iter_advance(pf->windows, it)
  894. )
  895. {
  896. // GLFWwindow* win = __glfw_window_from_handle(pf, it);
  897. // glfwDestroyWindow(win);
  898. }
  899. // glfwTerminate();
  900. }
  901. uint32_t gs_platform_key_to_codepoint(gs_platform_keycode key)
  902. {
  903. uint32_t code = 0;
  904. switch (key)
  905. {
  906. default:
  907. case GS_KEYCODE_COUNT:
  908. case GS_KEYCODE_INVALID: code = 0; break;
  909. case GS_KEYCODE_SPACE: code = 32; break;
  910. case GS_KEYCODE_APOSTROPHE: code = 39; break;
  911. case GS_KEYCODE_COMMA: code = 44; break;
  912. case GS_KEYCODE_MINUS: code = 45; break;
  913. case GS_KEYCODE_PERIOD: code = 46; break;
  914. case GS_KEYCODE_SLASH: code = 47; break;
  915. case GS_KEYCODE_0: code = 48; break;
  916. case GS_KEYCODE_1: code = 49; break;
  917. case GS_KEYCODE_2: code = 50; break;
  918. case GS_KEYCODE_3: code = 51; break;
  919. case GS_KEYCODE_4: code = 52; break;
  920. case GS_KEYCODE_5: code = 53; break;
  921. case GS_KEYCODE_6: code = 54; break;
  922. case GS_KEYCODE_7: code = 55; break;
  923. case GS_KEYCODE_8: code = 56; break;
  924. case GS_KEYCODE_9: code = 57; break;
  925. case GS_KEYCODE_SEMICOLON: code = 59; break; /* ; */
  926. case GS_KEYCODE_EQUAL: code = 61; break; /* code = */
  927. case GS_KEYCODE_A: code = 65; break;
  928. case GS_KEYCODE_B: code = 66; break;
  929. case GS_KEYCODE_C: code = 67; break;
  930. case GS_KEYCODE_D: code = 68; break;
  931. case GS_KEYCODE_E: code = 69; break;
  932. case GS_KEYCODE_F: code = 70; break;
  933. case GS_KEYCODE_G: code = 71; break;
  934. case GS_KEYCODE_H: code = 72; break;
  935. case GS_KEYCODE_I: code = 73; break;
  936. case GS_KEYCODE_J: code = 74; break;
  937. case GS_KEYCODE_K: code = 75; break;
  938. case GS_KEYCODE_L: code = 76; break;
  939. case GS_KEYCODE_M: code = 77; break;
  940. case GS_KEYCODE_N: code = 78; break;
  941. case GS_KEYCODE_O: code = 79; break;
  942. case GS_KEYCODE_P: code = 80; break;
  943. case GS_KEYCODE_Q: code = 81; break;
  944. case GS_KEYCODE_R: code = 82; break;
  945. case GS_KEYCODE_S: code = 83; break;
  946. case GS_KEYCODE_T: code = 84; break;
  947. case GS_KEYCODE_U: code = 85; break;
  948. case GS_KEYCODE_V: code = 86; break;
  949. case GS_KEYCODE_W: code = 87; break;
  950. case GS_KEYCODE_X: code = 88; break;
  951. case GS_KEYCODE_Y: code = 89; break;
  952. case GS_KEYCODE_Z: code = 90; break;
  953. case GS_KEYCODE_LEFT_BRACKET: code = 91; break; /* [ */
  954. case GS_KEYCODE_BACKSLASH: code = 92; break; /* \ */
  955. case GS_KEYCODE_RIGHT_BRACKET: code = 93; break; /* ] */
  956. case GS_KEYCODE_GRAVE_ACCENT: code = 96; break; /* ` */
  957. case GS_KEYCODE_WORLD_1: code = 161; break; /* non-US #1 */
  958. case GS_KEYCODE_WORLD_2: code = 162; break; /* non-US #2 */
  959. case GS_KEYCODE_ESC: code = 256; break;
  960. case GS_KEYCODE_ENTER: code = 257; break;
  961. case GS_KEYCODE_TAB: code = 258; break;
  962. case GS_KEYCODE_BACKSPACE: code = 259; break;
  963. case GS_KEYCODE_INSERT: code = 260; break;
  964. case GS_KEYCODE_DELETE: code = GLFW_KEY_DELETE; break;
  965. case GS_KEYCODE_RIGHT: code = 262; break;
  966. case GS_KEYCODE_LEFT: code = 263; break;
  967. case GS_KEYCODE_DOWN: code = 264; break;
  968. case GS_KEYCODE_UP: code = 265; break;
  969. case GS_KEYCODE_PAGE_UP: code = 266; break;
  970. case GS_KEYCODE_PAGE_DOWN: code = 267; break;
  971. case GS_KEYCODE_HOME: code = 268; break;
  972. case GS_KEYCODE_END: code = 269; break;
  973. case GS_KEYCODE_CAPS_LOCK: code = 280; break;
  974. case GS_KEYCODE_SCROLL_LOCK: code = 281; break;
  975. case GS_KEYCODE_NUM_LOCK: code = 282; break;
  976. case GS_KEYCODE_PRINT_SCREEN: code = 283; break;
  977. case GS_KEYCODE_PAUSE: code = 284; break;
  978. case GS_KEYCODE_F1: code = 290; break;
  979. case GS_KEYCODE_F2: code = 291; break;
  980. case GS_KEYCODE_F3: code = 292; break;
  981. case GS_KEYCODE_F4: code = 293; break;
  982. case GS_KEYCODE_F5: code = 294; break;
  983. case GS_KEYCODE_F6: code = 295; break;
  984. case GS_KEYCODE_F7: code = 296; break;
  985. case GS_KEYCODE_F8: code = 297; break;
  986. case GS_KEYCODE_F9: code = 298; break;
  987. case GS_KEYCODE_F10: code = 299; break;
  988. case GS_KEYCODE_F11: code = 300; break;
  989. case GS_KEYCODE_F12: code = 301; break;
  990. case GS_KEYCODE_F13: code = 302; break;
  991. case GS_KEYCODE_F14: code = 303; break;
  992. case GS_KEYCODE_F15: code = 304; break;
  993. case GS_KEYCODE_F16: code = 305; break;
  994. case GS_KEYCODE_F17: code = 306; break;
  995. case GS_KEYCODE_F18: code = 307; break;
  996. case GS_KEYCODE_F19: code = 308; break;
  997. case GS_KEYCODE_F20: code = 309; break;
  998. case GS_KEYCODE_F21: code = 310; break;
  999. case GS_KEYCODE_F22: code = 311; break;
  1000. case GS_KEYCODE_F23: code = 312; break;
  1001. case GS_KEYCODE_F24: code = 313; break;
  1002. case GS_KEYCODE_F25: code = 314; break;
  1003. case GS_KEYCODE_KP_0: code = 320; break;
  1004. case GS_KEYCODE_KP_1: code = 321; break;
  1005. case GS_KEYCODE_KP_2: code = 322; break;
  1006. case GS_KEYCODE_KP_3: code = 323; break;
  1007. case GS_KEYCODE_KP_4: code = 324; break;
  1008. case GS_KEYCODE_KP_5: code = 325; break;
  1009. case GS_KEYCODE_KP_6: code = 326; break;
  1010. case GS_KEYCODE_KP_7: code = 327; break;
  1011. case GS_KEYCODE_KP_8: code = 328; break;
  1012. case GS_KEYCODE_KP_9: code = 329; break;
  1013. case GS_KEYCODE_KP_DECIMAL: code = 330; break;
  1014. case GS_KEYCODE_KP_DIVIDE: code = 331; break;
  1015. case GS_KEYCODE_KP_MULTIPLY: code = 332; break;
  1016. case GS_KEYCODE_KP_SUBTRACT: code = 333; break;
  1017. case GS_KEYCODE_KP_ADD: code = 334; break;
  1018. case GS_KEYCODE_KP_ENTER: code = 335; break;
  1019. case GS_KEYCODE_KP_EQUAL: code = 336; break;
  1020. case GS_KEYCODE_LEFT_SHIFT: code = 340; break;
  1021. case GS_KEYCODE_LEFT_CONTROL: code = 341; break;
  1022. case GS_KEYCODE_LEFT_ALT: code = 342; break;
  1023. case GS_KEYCODE_LEFT_SUPER: code = 343; break;
  1024. case GS_KEYCODE_RIGHT_SHIFT: code = 344; break;
  1025. case GS_KEYCODE_RIGHT_CONTROL: code = 345; break;
  1026. case GS_KEYCODE_RIGHT_ALT: code = 346; break;
  1027. case GS_KEYCODE_RIGHT_SUPER: code = 347; break;
  1028. case GS_KEYCODE_MENU: code = 348; break;
  1029. }
  1030. return code;
  1031. }
  1032. // This doesn't work. Have to set up keycodes for emscripten instead. FUN.
  1033. gs_platform_keycode gs_platform_codepoint_to_key(uint32_t code)
  1034. {
  1035. gs_platform_keycode key = GS_KEYCODE_INVALID;
  1036. switch (code)
  1037. {
  1038. default:
  1039. case 0: key = GS_KEYCODE_INVALID; break;
  1040. case 32: key = GS_KEYCODE_SPACE; break;
  1041. case 39: key = GS_KEYCODE_APOSTROPHE; break;
  1042. case 44: key = GS_KEYCODE_COMMA; break;
  1043. case 45: key = GS_KEYCODE_MINUS; break;
  1044. case 46: key = GS_KEYCODE_PERIOD; break;
  1045. case 47: key = GS_KEYCODE_SLASH; break;
  1046. case 48: key = GS_KEYCODE_0; break;
  1047. case 49: key = GS_KEYCODE_1; break;
  1048. case 50: key = GS_KEYCODE_2; break;
  1049. case 51: key = GS_KEYCODE_3; break;
  1050. case 52: key = GS_KEYCODE_4; break;
  1051. case 53: key = GS_KEYCODE_5; break;
  1052. case 54: key = GS_KEYCODE_6; break;
  1053. case 55: key = GS_KEYCODE_7; break;
  1054. case 56: key = GS_KEYCODE_8; break;
  1055. case 57: key = GS_KEYCODE_9; break;
  1056. case 59: key = GS_KEYCODE_SEMICOLON; break;
  1057. case 61: key = GS_KEYCODE_EQUAL; break;
  1058. case 65: key = GS_KEYCODE_A; break;
  1059. case 66: key = GS_KEYCODE_B; break;
  1060. case 67: key = GS_KEYCODE_C; break;
  1061. case 68: key = GS_KEYCODE_D; break;
  1062. case 69: key = GS_KEYCODE_E; break;
  1063. case 70: key = GS_KEYCODE_F; break;
  1064. case 71: key = GS_KEYCODE_G; break;
  1065. case 72: key = GS_KEYCODE_H; break;
  1066. case 73: key = GS_KEYCODE_I; break;
  1067. case 74: key = GS_KEYCODE_J; break;
  1068. case 75: key = GS_KEYCODE_K; break;
  1069. case 76: key = GS_KEYCODE_L; break;
  1070. case 77: key = GS_KEYCODE_M; break;
  1071. case 78: key = GS_KEYCODE_N; break;
  1072. case 79: key = GS_KEYCODE_O; break;
  1073. case 80: key = GS_KEYCODE_P; break;
  1074. case 81: key = GS_KEYCODE_Q; break;
  1075. case 82: key = GS_KEYCODE_R; break;
  1076. case 83: key = GS_KEYCODE_S; break;
  1077. case 84: key = GS_KEYCODE_T; break;
  1078. case 85: key = GS_KEYCODE_U; break;
  1079. case 86: key = GS_KEYCODE_V; break;
  1080. case 87: key = GS_KEYCODE_W; break;
  1081. case 88: key = GS_KEYCODE_X; break;
  1082. case 89: key = GS_KEYCODE_Y; break;
  1083. case 90: key = GS_KEYCODE_Z; break;
  1084. case 91: key = GS_KEYCODE_LEFT_BRACKET; break;
  1085. case 92: key = GS_KEYCODE_BACKSLASH; break;
  1086. case 93: key = GS_KEYCODE_RIGHT_BRACKET; break;
  1087. case 96: key = GS_KEYCODE_GRAVE_ACCENT; break;
  1088. case 161: key = GS_KEYCODE_WORLD_1; break;
  1089. case 162: key = GS_KEYCODE_WORLD_2; break;
  1090. case 256: key = GS_KEYCODE_ESC; break;
  1091. case 257: key = GS_KEYCODE_ENTER; break;
  1092. case 258: key = GS_KEYCODE_TAB; break;
  1093. case 259: key = GS_KEYCODE_BACKSPACE; break;
  1094. case 260: key = GS_KEYCODE_INSERT; break;
  1095. case GLFW_KEY_DELETE: key = GS_KEYCODE_DELETE; break;
  1096. case 262: key = GS_KEYCODE_RIGHT; break;
  1097. case 263: key = GS_KEYCODE_LEFT; break;
  1098. case 264: key = GS_KEYCODE_DOWN; break;
  1099. case 265: key = GS_KEYCODE_UP; break;
  1100. case 266: key = GS_KEYCODE_PAGE_UP; break;
  1101. case 267: key = GS_KEYCODE_PAGE_DOWN; break;
  1102. case 268: key = GS_KEYCODE_HOME; break;
  1103. case 269: key = GS_KEYCODE_END; break;
  1104. case 280: key = GS_KEYCODE_CAPS_LOCK; break;
  1105. case 281: key = GS_KEYCODE_SCROLL_LOCK; break;
  1106. case 282: key = GS_KEYCODE_NUM_LOCK; break;
  1107. case 283: key = GS_KEYCODE_PRINT_SCREEN; break;
  1108. case 284: key = GS_KEYCODE_PAUSE; break;
  1109. case 290: key = GS_KEYCODE_F1; break;
  1110. case 291: key = GS_KEYCODE_F2; break;
  1111. case 292: key = GS_KEYCODE_F3; break;
  1112. case 293: key = GS_KEYCODE_F4; break;
  1113. case 294: key = GS_KEYCODE_F5; break;
  1114. case 295: key = GS_KEYCODE_F6; break;
  1115. case 296: key = GS_KEYCODE_F7; break;
  1116. case 297: key = GS_KEYCODE_F8; break;
  1117. case 298: key = GS_KEYCODE_F9; break;
  1118. case 299: key = GS_KEYCODE_F10; break;
  1119. case 300: key = GS_KEYCODE_F11; break;
  1120. case 301: key = GS_KEYCODE_F12; break;
  1121. case 302: key = GS_KEYCODE_F13; break;
  1122. case 303: key = GS_KEYCODE_F14; break;
  1123. case 304: key = GS_KEYCODE_F15; break;
  1124. case 305: key = GS_KEYCODE_F16; break;
  1125. case 306: key = GS_KEYCODE_F17; break;
  1126. case 307: key = GS_KEYCODE_F18; break;
  1127. case 308: key = GS_KEYCODE_F19; break;
  1128. case 309: key = GS_KEYCODE_F20; break;
  1129. case 310: key = GS_KEYCODE_F21; break;
  1130. case 311: key = GS_KEYCODE_F22; break;
  1131. case 312: key = GS_KEYCODE_F23; break;
  1132. case 313: key = GS_KEYCODE_F24; break;
  1133. case 314: key = GS_KEYCODE_F25; break;
  1134. case 320: key = GS_KEYCODE_KP_0; break;
  1135. case 321: key = GS_KEYCODE_KP_1; break;
  1136. case 322: key = GS_KEYCODE_KP_2; break;
  1137. case 323: key = GS_KEYCODE_KP_3; break;
  1138. case 324: key = GS_KEYCODE_KP_4; break;
  1139. case 325: key = GS_KEYCODE_KP_5; break;
  1140. case 326: key = GS_KEYCODE_KP_6; break;
  1141. case 327: key = GS_KEYCODE_KP_7; break;
  1142. case 328: key = GS_KEYCODE_KP_8; break;
  1143. case 329: key = GS_KEYCODE_KP_9; break;
  1144. case 330: key = GS_KEYCODE_KP_DECIMAL; break;
  1145. case 331: key = GS_KEYCODE_KP_DIVIDE; break;
  1146. case 332: key = GS_KEYCODE_KP_MULTIPLY; break;
  1147. case 333: key = GS_KEYCODE_KP_SUBTRACT; break;
  1148. case 334: key = GS_KEYCODE_KP_ADD; break;
  1149. case 335: key = GS_KEYCODE_KP_ENTER; break;
  1150. case 336: key = GS_KEYCODE_KP_EQUAL; break;
  1151. case 340: key = GS_KEYCODE_LEFT_SHIFT; break;
  1152. case 341: key = GS_KEYCODE_LEFT_CONTROL; break;
  1153. case 342: key = GS_KEYCODE_LEFT_ALT; break;
  1154. case 343: key = GS_KEYCODE_LEFT_SUPER; break;
  1155. case 344: key = GS_KEYCODE_RIGHT_SHIFT; break;
  1156. case 345: key = GS_KEYCODE_RIGHT_CONTROL; break;
  1157. case 346: key = GS_KEYCODE_RIGHT_ALT; break;
  1158. case 347: key = GS_KEYCODE_RIGHT_SUPER; break;
  1159. case 348: key = GS_KEYCODE_MENU; break;
  1160. }
  1161. return key;
  1162. }
  1163. /*=== GLFW Callbacks ===*/
  1164. gs_platform_keycode glfw_key_to_gs_keycode(u32 code)
  1165. {
  1166. switch (code)
  1167. {
  1168. case GLFW_KEY_A: return GS_KEYCODE_A; break;
  1169. case GLFW_KEY_B: return GS_KEYCODE_B; break;
  1170. case GLFW_KEY_C: return GS_KEYCODE_C; break;
  1171. case GLFW_KEY_D: return GS_KEYCODE_D; break;
  1172. case GLFW_KEY_E: return GS_KEYCODE_E; break;
  1173. case GLFW_KEY_F: return GS_KEYCODE_F; break;
  1174. case GLFW_KEY_G: return GS_KEYCODE_G; break;
  1175. case GLFW_KEY_H: return GS_KEYCODE_H; break;
  1176. case GLFW_KEY_I: return GS_KEYCODE_I; break;
  1177. case GLFW_KEY_J: return GS_KEYCODE_J; break;
  1178. case GLFW_KEY_K: return GS_KEYCODE_K; break;
  1179. case GLFW_KEY_L: return GS_KEYCODE_L; break;
  1180. case GLFW_KEY_M: return GS_KEYCODE_M; break;
  1181. case GLFW_KEY_N: return GS_KEYCODE_N; break;
  1182. case GLFW_KEY_O: return GS_KEYCODE_O; break;
  1183. case GLFW_KEY_P: return GS_KEYCODE_P; break;
  1184. case GLFW_KEY_Q: return GS_KEYCODE_Q; break;
  1185. case GLFW_KEY_R: return GS_KEYCODE_R; break;
  1186. case GLFW_KEY_S: return GS_KEYCODE_S; break;
  1187. case GLFW_KEY_T: return GS_KEYCODE_T; break;
  1188. case GLFW_KEY_U: return GS_KEYCODE_U; break;
  1189. case GLFW_KEY_V: return GS_KEYCODE_V; break;
  1190. case GLFW_KEY_W: return GS_KEYCODE_W; break;
  1191. case GLFW_KEY_X: return GS_KEYCODE_X; break;
  1192. case GLFW_KEY_Y: return GS_KEYCODE_Y; break;
  1193. case GLFW_KEY_Z: return GS_KEYCODE_Z; break;
  1194. case GLFW_KEY_LEFT_SHIFT: return GS_KEYCODE_LEFT_SHIFT; break;
  1195. case GLFW_KEY_RIGHT_SHIFT: return GS_KEYCODE_RIGHT_SHIFT; break;
  1196. case GLFW_KEY_LEFT_ALT: return GS_KEYCODE_LEFT_ALT; break;
  1197. case GLFW_KEY_RIGHT_ALT: return GS_KEYCODE_RIGHT_ALT; break;
  1198. case GLFW_KEY_LEFT_CONTROL: return GS_KEYCODE_LEFT_CONTROL; break;
  1199. case GLFW_KEY_RIGHT_CONTROL: return GS_KEYCODE_RIGHT_CONTROL; break;
  1200. case GLFW_KEY_BACKSPACE: return GS_KEYCODE_BACKSPACE; break;
  1201. case GLFW_KEY_BACKSLASH: return GS_KEYCODE_BACKSLASH; break;
  1202. case GLFW_KEY_SLASH: return GS_KEYCODE_SLASH; break;
  1203. case GLFW_KEY_GRAVE_ACCENT: return GS_KEYCODE_GRAVE_ACCENT; break;
  1204. case GLFW_KEY_COMMA: return GS_KEYCODE_COMMA; break;
  1205. case GLFW_KEY_PERIOD: return GS_KEYCODE_PERIOD; break;
  1206. case GLFW_KEY_ESCAPE: return GS_KEYCODE_ESC; break;
  1207. case GLFW_KEY_SPACE: return GS_KEYCODE_SPACE; break;
  1208. case GLFW_KEY_LEFT: return GS_KEYCODE_LEFT; break;
  1209. case GLFW_KEY_UP: return GS_KEYCODE_UP; break;
  1210. case GLFW_KEY_RIGHT: return GS_KEYCODE_RIGHT; break;
  1211. case GLFW_KEY_DOWN: return GS_KEYCODE_DOWN; break;
  1212. case GLFW_KEY_0: return GS_KEYCODE_0; break;
  1213. case GLFW_KEY_1: return GS_KEYCODE_1; break;
  1214. case GLFW_KEY_2: return GS_KEYCODE_2; break;
  1215. case GLFW_KEY_3: return GS_KEYCODE_3; break;
  1216. case GLFW_KEY_4: return GS_KEYCODE_4; break;
  1217. case GLFW_KEY_5: return GS_KEYCODE_5; break;
  1218. case GLFW_KEY_6: return GS_KEYCODE_6; break;
  1219. case GLFW_KEY_7: return GS_KEYCODE_7; break;
  1220. case GLFW_KEY_8: return GS_KEYCODE_8; break;
  1221. case GLFW_KEY_9: return GS_KEYCODE_9; break;
  1222. case GLFW_KEY_KP_0: return GS_KEYCODE_KP_0; break;
  1223. case GLFW_KEY_KP_1: return GS_KEYCODE_KP_1; break;
  1224. case GLFW_KEY_KP_2: return GS_KEYCODE_KP_2; break;
  1225. case GLFW_KEY_KP_3: return GS_KEYCODE_KP_3; break;
  1226. case GLFW_KEY_KP_4: return GS_KEYCODE_KP_4; break;
  1227. case GLFW_KEY_KP_5: return GS_KEYCODE_KP_5; break;
  1228. case GLFW_KEY_KP_6: return GS_KEYCODE_KP_6; break;
  1229. case GLFW_KEY_KP_7: return GS_KEYCODE_KP_7; break;
  1230. case GLFW_KEY_KP_8: return GS_KEYCODE_KP_8; break;
  1231. case GLFW_KEY_KP_9: return GS_KEYCODE_KP_9; break;
  1232. case GLFW_KEY_CAPS_LOCK: return GS_KEYCODE_CAPS_LOCK; break;
  1233. case GLFW_KEY_DELETE: return GS_KEYCODE_DELETE; break;
  1234. case GLFW_KEY_END: return GS_KEYCODE_END; break;
  1235. case GLFW_KEY_F1: return GS_KEYCODE_F1; break;
  1236. case GLFW_KEY_F2: return GS_KEYCODE_F2; break;
  1237. case GLFW_KEY_F3: return GS_KEYCODE_F3; break;
  1238. case GLFW_KEY_F4: return GS_KEYCODE_F4; break;
  1239. case GLFW_KEY_F5: return GS_KEYCODE_F5; break;
  1240. case GLFW_KEY_F6: return GS_KEYCODE_F6; break;
  1241. case GLFW_KEY_F7: return GS_KEYCODE_F7; break;
  1242. case GLFW_KEY_F8: return GS_KEYCODE_F8; break;
  1243. case GLFW_KEY_F9: return GS_KEYCODE_F9; break;
  1244. case GLFW_KEY_F10: return GS_KEYCODE_F10; break;
  1245. case GLFW_KEY_F11: return GS_KEYCODE_F11; break;
  1246. case GLFW_KEY_F12: return GS_KEYCODE_F12; break;
  1247. case GLFW_KEY_HOME: return GS_KEYCODE_HOME; break;
  1248. case GLFW_KEY_EQUAL: return GS_KEYCODE_EQUAL; break;
  1249. case GLFW_KEY_MINUS: return GS_KEYCODE_MINUS; break;
  1250. case GLFW_KEY_LEFT_BRACKET: return GS_KEYCODE_LEFT_BRACKET; break;
  1251. case GLFW_KEY_RIGHT_BRACKET: return GS_KEYCODE_RIGHT_BRACKET; break;
  1252. case GLFW_KEY_SEMICOLON: return GS_KEYCODE_SEMICOLON; break;
  1253. case GLFW_KEY_ENTER: return GS_KEYCODE_ENTER; break;
  1254. case GLFW_KEY_INSERT: return GS_KEYCODE_INSERT; break;
  1255. case GLFW_KEY_PAGE_UP: return GS_KEYCODE_PAGE_UP; break;
  1256. case GLFW_KEY_PAGE_DOWN: return GS_KEYCODE_PAGE_DOWN; break;
  1257. case GLFW_KEY_NUM_LOCK: return GS_KEYCODE_NUM_LOCK; break;
  1258. case GLFW_KEY_TAB: return GS_KEYCODE_TAB; break;
  1259. case GLFW_KEY_KP_MULTIPLY: return GS_KEYCODE_KP_MULTIPLY; break;
  1260. case GLFW_KEY_KP_DIVIDE: return GS_KEYCODE_KP_DIVIDE; break;
  1261. case GLFW_KEY_KP_ADD: return GS_KEYCODE_KP_ADD; break;
  1262. case GLFW_KEY_KP_SUBTRACT: return GS_KEYCODE_KP_SUBTRACT; break;
  1263. case GLFW_KEY_KP_ENTER: return GS_KEYCODE_KP_ENTER; break;
  1264. case GLFW_KEY_KP_DECIMAL: return GS_KEYCODE_KP_DECIMAL; break;
  1265. case GLFW_KEY_PAUSE: return GS_KEYCODE_PAUSE; break;
  1266. case GLFW_KEY_PRINT_SCREEN: return GS_KEYCODE_PRINT_SCREEN; break;
  1267. default: return GS_KEYCODE_COUNT; break;
  1268. }
  1269. // Shouldn't reach here
  1270. return GS_KEYCODE_COUNT;
  1271. }
  1272. gs_platform_mouse_button_code __glfw_button_to_gs_mouse_button(s32 code)
  1273. {
  1274. switch (code)
  1275. {
  1276. case GLFW_MOUSE_BUTTON_LEFT: return GS_MOUSE_LBUTTON; break;
  1277. case GLFW_MOUSE_BUTTON_RIGHT: return GS_MOUSE_RBUTTON; break;
  1278. case GLFW_MOUSE_BUTTON_MIDDLE: return GS_MOUSE_MBUTTON; break;
  1279. }
  1280. // Shouldn't reach here
  1281. return GS_MOUSE_BUTTON_CODE_COUNT;
  1282. }
  1283. void __glfw_char_callback(GLFWwindow* window, uint32_t codepoint)
  1284. {
  1285. // Grab platform instance from engine
  1286. gs_platform_t* platform = gs_subsystem(platform);
  1287. gs_platform_event_t evt = gs_default_val();
  1288. evt.type = GS_PLATFORM_EVENT_TEXT;
  1289. evt.text.codepoint = codepoint;
  1290. // Add action
  1291. gs_platform_add_event(&evt);
  1292. }
  1293. void __glfw_key_callback(GLFWwindow* window, s32 code, s32 scancode, s32 action, s32 mods)
  1294. {
  1295. // Grab platform instance from engine
  1296. gs_platform_t* platform = gs_subsystem(platform);
  1297. // Get keycode from key
  1298. gs_platform_keycode key = glfw_key_to_gs_keycode(code);
  1299. // Push back event into platform events
  1300. gs_platform_event_t evt = gs_default_val();
  1301. evt.type = GS_PLATFORM_EVENT_KEY;
  1302. evt.key.codepoint = code;
  1303. evt.key.keycode = key;
  1304. evt.key.modifier = (gs_platform_key_modifier_type)mods;
  1305. switch (action)
  1306. {
  1307. // Released
  1308. case 0: {
  1309. gs_platform_release_key(key);
  1310. evt.key.action = GS_PLATFORM_KEY_RELEASED;
  1311. } break;
  1312. // Pressed
  1313. case 1: {
  1314. gs_platform_press_key(key);
  1315. evt.key.action = GS_PLATFORM_KEY_PRESSED;
  1316. } break;
  1317. // Down
  1318. case 2: {
  1319. gs_platform_press_key(key);
  1320. evt.key.action = GS_PLATFORM_KEY_DOWN;
  1321. } break;
  1322. default: {
  1323. } break;
  1324. }
  1325. // Add action
  1326. gs_platform_add_event(&evt);
  1327. }
  1328. void __glfw_mouse_button_callback(GLFWwindow* window, s32 code, s32 action, s32 mods)
  1329. {
  1330. // Grab platform instance from engine
  1331. gs_platform_t* platform = gs_subsystem(platform);
  1332. // Get mouse code from key
  1333. gs_platform_mouse_button_code button = __glfw_button_to_gs_mouse_button(code);
  1334. // Push back event into platform events
  1335. gs_platform_event_t evt = gs_default_val();
  1336. evt.type = GS_PLATFORM_EVENT_MOUSE;
  1337. evt.mouse.codepoint = code;
  1338. evt.mouse.button = button;
  1339. switch (action)
  1340. {
  1341. // Released
  1342. case 0:
  1343. {
  1344. gs_platform_release_mouse_button(button);
  1345. evt.mouse.action = GS_PLATFORM_MOUSE_BUTTON_RELEASED;
  1346. } break;
  1347. // Pressed
  1348. case 1:
  1349. {
  1350. gs_platform_press_mouse_button(button);
  1351. evt.mouse.action = GS_PLATFORM_MOUSE_BUTTON_PRESSED;
  1352. } break;
  1353. // Down
  1354. case 2:
  1355. {
  1356. gs_platform_press_mouse_button(button);
  1357. evt.mouse.action = GS_PLATFORM_MOUSE_BUTTON_DOWN;
  1358. } break;
  1359. }
  1360. // Add action
  1361. gs_platform_add_event(&evt);
  1362. }
  1363. void __glfw_mouse_cursor_position_callback(GLFWwindow* window, f64 x, f64 y)
  1364. {
  1365. gs_platform_t* platform = gs_subsystem(platform);
  1366. // platform->input.mouse.position = gs_v2((f32)x, (f32)y);
  1367. // platform->input.mouse.moved_this_frame = true;
  1368. gs_platform_event_t gs_evt = gs_default_val();
  1369. gs_evt.type = GS_PLATFORM_EVENT_MOUSE;
  1370. gs_evt.mouse.action = GS_PLATFORM_MOUSE_MOVE;
  1371. // gs_println("pos: <%.2f, %.2f>, old: <%.2f, %.2f>", x, y, platform->input.mouse.position.x, platform->input.mouse.position.y);
  1372. // gs_evt.mouse.move = gs_v2((f32)x, (f32)y);
  1373. // Calculate mouse move based on whether locked or not
  1374. if (gs_platform_mouse_locked()) {
  1375. gs_evt.mouse.move.x = x - platform->input.mouse.position.x;
  1376. gs_evt.mouse.move.y = y - platform->input.mouse.position.y;
  1377. platform->input.mouse.position.x = x;
  1378. platform->input.mouse.position.y = y;
  1379. } else {
  1380. gs_evt.mouse.move = gs_v2((f32)x, (f32)y);
  1381. }
  1382. // Push back event into platform events
  1383. gs_platform_add_event(&gs_evt);
  1384. }
  1385. void __glfw_mouse_scroll_wheel_callback(GLFWwindow* window, f64 x, f64 y)
  1386. {
  1387. gs_platform_t* platform = gs_subsystem(platform);
  1388. platform->input.mouse.wheel = gs_v2((f32)x, (f32)y);
  1389. // Push back event into platform events
  1390. gs_platform_event_t gs_evt = gs_default_val();
  1391. gs_evt.type = GS_PLATFORM_EVENT_MOUSE;
  1392. gs_evt.mouse.action = GS_PLATFORM_MOUSE_WHEEL;
  1393. gs_evt.mouse.wheel = gs_v2((f32)x, (f32)y);
  1394. gs_platform_add_event(&gs_evt);
  1395. }
  1396. // Gets called when mouse enters or leaves frame of window
  1397. void __glfw_mouse_cursor_enter_callback(GLFWwindow* window, s32 entered)
  1398. {
  1399. gs_platform_t* platform = gs_subsystem(platform);
  1400. gs_platform_event_t gs_evt = gs_default_val();
  1401. gs_evt.type = GS_PLATFORM_EVENT_MOUSE;
  1402. gs_evt.mouse.action = entered ? GS_PLATFORM_MOUSE_ENTER : GS_PLATFORM_MOUSE_LEAVE;
  1403. gs_platform_add_event(&gs_evt);
  1404. }
  1405. void __glfw_frame_buffer_size_callback(GLFWwindow* window, s32 width, s32 height)
  1406. {
  1407. // Nothing for now
  1408. }
  1409. /*== Platform Input == */
  1410. void gs_platform_process_input(gs_platform_input_t* input)
  1411. {
  1412. glfwPollEvents();
  1413. }
  1414. /*== Platform Util == */
  1415. void gs_platform_sleep(float ms)
  1416. {
  1417. #if (defined GS_PLATFORM_WIN)
  1418. timeBeginPeriod(1);
  1419. Sleep((uint64_t)ms);
  1420. timeEndPeriod(1);
  1421. #elif (defined GS_PLATFORM_APPLE)
  1422. usleep(ms * 1000.f); // unistd.h
  1423. #else
  1424. if (ms < 0.f) {
  1425. return;
  1426. }
  1427. struct timespec ts = gs_default_val();
  1428. int32_t res = 0;
  1429. ts.tv_sec = ms / 1000.f;
  1430. ts.tv_nsec = ((uint64_t)ms % 1000) * 1000000;
  1431. do {
  1432. res = nanosleep(&ts, &ts);
  1433. } while (res && errno == EINTR);
  1434. // usleep(ms * 1000.f); // unistd.h
  1435. #endif
  1436. }
  1437. GS_API_DECL double
  1438. gs_platform_elapsed_time()
  1439. {
  1440. gs_platform_t* platform = gs_subsystem(platform);
  1441. return platform->time.elapsed;
  1442. }
  1443. /*== Platform Video == */
  1444. GS_API_DECL void
  1445. gs_platform_enable_vsync(int32_t enabled)
  1446. {
  1447. glfwSwapInterval(enabled ? 1 : 0);
  1448. }
  1449. /*== OpenGL debug callback == */
  1450. void GLAPIENTRY __gs_platform_gl_debug(GLenum source, GLenum type, GLuint id, GLenum severity,
  1451. GLsizei len, const GLchar* msg, const void* user)
  1452. {
  1453. if (severity != GL_DEBUG_SEVERITY_NOTIFICATION)
  1454. {
  1455. gs_println("GL: %s", msg);
  1456. }
  1457. }
  1458. /*== Platform Window == */
  1459. GS_API_DECL gs_platform_window_t
  1460. gs_platform_window_create_internal(const gs_platform_window_desc_t* desc)
  1461. {
  1462. gs_platform_window_t win = gs_default_val();
  1463. if (!desc)
  1464. {
  1465. // Log warning
  1466. gs_log_warning("Window descriptor is null.");
  1467. return win;
  1468. }
  1469. // Grab window hints from application desc
  1470. u32 window_hints = desc->flags;
  1471. bool visible = ~window_hints & GS_WINDOW_FLAGS_INVISIBLE;
  1472. // Set whether or not the screen is resizable
  1473. glfwWindowHint(GLFW_RESIZABLE, (window_hints & GS_WINDOW_FLAGS_NO_RESIZE) != GS_WINDOW_FLAGS_NO_RESIZE);
  1474. glfwWindowHint(GLFW_VISIBLE, visible);
  1475. GLFWwindow* window = NULL;
  1476. #define CONSTRUCT_WINDOW(W, H, T, M, I)\
  1477. do {\
  1478. window = glfwCreateWindow(W, H, T, M, I);\
  1479. win.hndl = window;\
  1480. } while (0)
  1481. if (visible) {
  1482. // Set multi-samples
  1483. if (desc->num_samples) {
  1484. glfwWindowHint(GLFW_SAMPLES, desc->num_samples);
  1485. }
  1486. else {
  1487. glfwWindowHint(GLFW_SAMPLES, 0);
  1488. }
  1489. // Get monitor if fullscreen
  1490. GLFWmonitor* monitor = NULL;
  1491. if ((window_hints & GS_WINDOW_FLAGS_FULLSCREEN) == GS_WINDOW_FLAGS_FULLSCREEN) {
  1492. int monitor_count;
  1493. GLFWmonitor** monitors = glfwGetMonitors(&monitor_count);
  1494. if (desc->monitor_index < monitor_count) {
  1495. monitor = monitors[desc->monitor_index];
  1496. }
  1497. }
  1498. CONSTRUCT_WINDOW(desc->width, desc->height, desc->title, monitor, NULL);
  1499. // Callbacks for window
  1500. glfwMakeContextCurrent(window);
  1501. glfwSetKeyCallback(window, &__glfw_key_callback);
  1502. glfwSetCharCallback(window, &__glfw_char_callback);
  1503. glfwSetMouseButtonCallback(window, &__glfw_mouse_button_callback);
  1504. glfwSetCursorEnterCallback(window, &__glfw_mouse_cursor_enter_callback);
  1505. glfwSetCursorPosCallback(window, &__glfw_mouse_cursor_position_callback);
  1506. glfwSetScrollCallback(window, &__glfw_mouse_scroll_wheel_callback);
  1507. // Cache all necessary window information
  1508. int32_t wx = 0, wy = 0, fx = 0, fy = 0, wpx = 0, wpy = 0;
  1509. glfwGetWindowSize((GLFWwindow*)win.hndl, &wx, &wy);
  1510. glfwGetFramebufferSize((GLFWwindow*)win.hndl, &fx, &fy);
  1511. glfwGetWindowPos((GLFWwindow*)win.hndl, &wpx, &wpy);
  1512. win.window_size = gs_v2((float)wx, (float)wy);
  1513. win.window_position = gs_v2((float)wpx, (float)wpy);
  1514. win.framebuffer_size = gs_v2((float)fx, (float)fy);
  1515. }
  1516. else {
  1517. void* mwin = gs_platform_raw_window_handle(gs_platform_main_window());
  1518. CONSTRUCT_WINDOW(1, 1, desc->title, 0, (GLFWwindow*)mwin);
  1519. }
  1520. if (window == NULL) {
  1521. gs_log_error("Failed to create window.");
  1522. glfwTerminate();
  1523. return win;
  1524. }
  1525. // Need to make sure this is ONLY done once.
  1526. if (gs_slot_array_empty(gs_subsystem(platform)->windows)) {
  1527. if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
  1528. gs_log_warning("Failed to initialize GLFW.");
  1529. return win;
  1530. }
  1531. switch (gs_subsystem(platform)->settings.video.driver) {
  1532. case GS_PLATFORM_VIDEO_DRIVER_TYPE_OPENGL: {
  1533. gs_log_info("OpenGL Version: %s", glGetString(GL_VERSION));
  1534. if (gs_subsystem(platform)->settings.video.graphics.debug) {
  1535. glDebugMessageCallback(__gs_platform_gl_debug, NULL);
  1536. }
  1537. } break;
  1538. default: break;
  1539. }
  1540. }
  1541. return win;
  1542. }
  1543. // Platform callbacks
  1544. GS_API_DECL void
  1545. gs_platform_set_dropped_files_callback(uint32_t handle, gs_dropped_files_callback_t cb)
  1546. {
  1547. gs_platform_t* platform = gs_subsystem(platform);
  1548. gs_platform_window_t* win = gs_slot_array_getp(platform->windows, handle);
  1549. glfwSetDropCallback((GLFWwindow*)win->hndl, (GLFWdropfun)cb);
  1550. }
  1551. GS_API_DECL void
  1552. gs_platform_set_window_close_callback(uint32_t handle, gs_window_close_callback_t cb)
  1553. {
  1554. gs_platform_t* platform = gs_subsystem(platform);
  1555. gs_platform_window_t* win = gs_slot_array_getp(platform->windows, handle);
  1556. glfwSetWindowCloseCallback((GLFWwindow*)win->hndl, (GLFWwindowclosefun)cb);
  1557. }
  1558. GS_API_DECL void
  1559. gs_platform_set_character_callback(uint32_t handle, gs_character_callback_t cb)
  1560. {
  1561. gs_platform_t* platform = gs_subsystem(platform);
  1562. gs_platform_window_t* win = gs_slot_array_getp(platform->windows, handle);
  1563. glfwSetCharCallback((GLFWwindow*)win->hndl, (GLFWcharfun)cb);
  1564. }
  1565. GS_API_DECL void
  1566. gs_platform_set_framebuffer_resize_callback(uint32_t handle, gs_framebuffer_resize_callback_t cb)
  1567. {
  1568. gs_platform_t* platform = gs_subsystem(platform);
  1569. gs_platform_window_t* win = gs_slot_array_getp(platform->windows, handle);
  1570. glfwSetFramebufferSizeCallback((GLFWwindow*)win->hndl, (GLFWframebuffersizefun)cb);
  1571. }
  1572. GS_API_DECL void
  1573. gs_platform_mouse_set_position(uint32_t handle, float x, float y)
  1574. {
  1575. gs_platform_t* platform = gs_subsystem(platform);
  1576. gs_platform_window_t* win = gs_slot_array_getp(platform->windows, handle);
  1577. glfwSetCursorPos((GLFWwindow*)win->hndl, x, y);
  1578. }
  1579. GS_API_DECL void*
  1580. gs_platform_raw_window_handle(uint32_t handle)
  1581. {
  1582. // Grab instance of platform from engine
  1583. gs_platform_t* platform = gs_subsystem(platform);
  1584. // Grab window from handle
  1585. gs_platform_window_t* win = gs_slot_array_getp(platform->windows, handle);
  1586. return (void*)win->hndl;
  1587. }
  1588. GS_API_DECL void
  1589. gs_platform_window_swap_buffer(uint32_t handle)
  1590. {
  1591. // Grab instance of platform from engine
  1592. gs_platform_t* platform = gs_subsystem(platform);
  1593. // Grab window from handle
  1594. gs_platform_window_t* win = gs_slot_array_getp(platform->windows, handle);
  1595. glfwSwapBuffers((GLFWwindow*)win->hndl);
  1596. }
  1597. GS_API_DECL void
  1598. gs_platform_window_make_current(uint32_t hndl)
  1599. {
  1600. gs_platform_t* platform = gs_subsystem(platform);
  1601. gs_platform_window_t* win = gs_slot_array_getp(platform->windows, hndl);
  1602. glfwMakeContextCurrent((GLFWwindow*)win->hndl);
  1603. }
  1604. GS_API_DECL void
  1605. gs_platform_window_make_current_raw(void* win)
  1606. {
  1607. glfwMakeContextCurrent((GLFWwindow*)win);
  1608. }
  1609. GS_API_DECL gs_vec2
  1610. gs_platform_window_sizev(uint32_t handle)
  1611. {
  1612. gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1613. return window->window_size;
  1614. }
  1615. GS_API_DECL void
  1616. gs_platform_window_size(uint32_t handle, uint32_t* w, uint32_t* h)
  1617. {
  1618. gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1619. *w = (int32_t)window->window_size.x;
  1620. *h = (int32_t)window->window_size.y;
  1621. }
  1622. uint32_t gs_platform_window_width(uint32_t handle)
  1623. {
  1624. gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1625. return (uint32_t)window->window_size.x;
  1626. }
  1627. uint32_t gs_platform_window_height(uint32_t handle)
  1628. {
  1629. gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1630. return (uint32_t)window->window_size.y;
  1631. }
  1632. bool32_t gs_platform_window_fullscreen(uint32_t handle)
  1633. {
  1634. gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1635. return glfwGetWindowMonitor((GLFWwindow*)window->hndl) != NULL;
  1636. }
  1637. void gs_platform_window_position(uint32_t handle, uint32_t* x, uint32_t* y)
  1638. {
  1639. gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1640. *x = (uint32_t)window->window_position.x;
  1641. *y = (uint32_t)window->window_position.y;
  1642. }
  1643. gs_vec2 gs_platform_window_positionv(uint32_t handle)
  1644. {
  1645. gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1646. return window->window_position;
  1647. }
  1648. void gs_platform_set_window_size(uint32_t handle, uint32_t w, uint32_t h)
  1649. {
  1650. gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1651. glfwSetWindowSize((GLFWwindow*)window->hndl, (int32_t)w, (int32_t)h);
  1652. }
  1653. void gs_platform_set_window_sizev(uint32_t handle, gs_vec2 v)
  1654. {
  1655. gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1656. glfwSetWindowSize((GLFWwindow*)window->hndl, (uint32_t)v.x, (uint32_t)v.y);
  1657. }
  1658. void gs_platform_set_window_fullscreen(uint32_t handle, bool32_t fullscreen)
  1659. {
  1660. gs_platform_window_t* win = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1661. GLFWmonitor* monitor = NULL;
  1662. int32_t x, y, w, h;
  1663. glfwGetWindowPos((GLFWwindow*)win->hndl, &x, &y);
  1664. glfwGetWindowSize((GLFWwindow*)win->hndl, &w, &h);
  1665. if (fullscreen)
  1666. {
  1667. uint32_t monitor_index = gs_instance()->ctx.app.window.monitor_index;
  1668. int monitor_count;
  1669. GLFWmonitor** monitors = glfwGetMonitors(&monitor_count);
  1670. if (monitor_index < monitor_count)
  1671. {
  1672. monitor = monitors[monitor_index];
  1673. }
  1674. }
  1675. glfwSetWindowMonitor((GLFWwindow*)win->hndl, monitor, x, y, w, h, GLFW_DONT_CARE);
  1676. }
  1677. void gs_platform_set_window_position(uint32_t handle, uint32_t x, uint32_t y)
  1678. {
  1679. gs_platform_window_t* win = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1680. glfwSetWindowPos((GLFWwindow*)win->hndl, (int32_t)x, (int32_t)y);
  1681. }
  1682. void gs_platform_set_window_positionv(uint32_t handle, gs_vec2 v)
  1683. {
  1684. gs_platform_window_t* win = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1685. glfwSetWindowPos((GLFWwindow*)win->hndl, (int32_t)v.x, (int32_t)v.y);
  1686. }
  1687. void gs_platform_framebuffer_size(uint32_t handle, uint32_t* w, uint32_t* h)
  1688. {
  1689. gs_platform_window_t* win = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1690. *w = (uint32_t)win->framebuffer_size.x;
  1691. *h = (uint32_t)win->framebuffer_size.y;
  1692. }
  1693. gs_vec2 gs_platform_framebuffer_sizev(uint32_t handle)
  1694. {
  1695. uint32_t w = 0, h = 0;
  1696. gs_platform_framebuffer_size(handle, &w, &h);
  1697. return gs_v2((float)w, (float)h);
  1698. }
  1699. uint32_t gs_platform_framebuffer_width(uint32_t handle)
  1700. {
  1701. uint32_t w = 0, h = 0;
  1702. gs_platform_framebuffer_size(handle, &w, &h);
  1703. return w;
  1704. }
  1705. uint32_t gs_platform_framebuffer_height(uint32_t handle)
  1706. {
  1707. uint32_t w = 0, h = 0;
  1708. gs_platform_framebuffer_size(handle, &w, &h);
  1709. return h;
  1710. }
  1711. GS_API_DECL gs_vec2 gs_platform_monitor_sizev(uint32_t id)
  1712. {
  1713. gs_vec2 ms = gs_v2s(0.f);
  1714. int32_t width, height, xpos, ypos;
  1715. int32_t count;
  1716. GLFWmonitor* monitor = NULL;
  1717. gs_platform_t* platform = gs_subsystem(platform);
  1718. GLFWmonitor** monitors = glfwGetMonitors(&count);
  1719. if (count && id < count) {
  1720. monitor = monitors[id];
  1721. }
  1722. else {
  1723. monitor = glfwGetPrimaryMonitor();
  1724. }
  1725. glfwGetMonitorWorkarea(monitor, &xpos, &ypos, &width, &height);
  1726. ms.x = (float)width;
  1727. ms.y = (float)height;
  1728. return ms;
  1729. }
  1730. GS_API_DECL void gs_platform_window_set_clipboard(uint32_t handle, const char* str)
  1731. {
  1732. gs_platform_window_t* win = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1733. glfwSetClipboardString((GLFWwindow*)win->hndl, str);
  1734. }
  1735. GS_API_DECL const char* gs_platform_window_get_clipboard(uint32_t handle)
  1736. {
  1737. gs_platform_window_t* win = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1738. return glfwGetClipboardString((GLFWwindow*)win->hndl);
  1739. }
  1740. void gs_platform_set_cursor(uint32_t handle, gs_platform_cursor cursor)
  1741. {
  1742. gs_platform_t* platform = gs_subsystem(platform);
  1743. gs_platform_window_t* win = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1744. GLFWcursor* cp = ((GLFWcursor*)platform->cursors[(u32)cursor]);
  1745. glfwSetCursor((GLFWwindow*)win->hndl, cp);
  1746. }
  1747. void gs_platform_lock_mouse(uint32_t handle, bool32_t lock)
  1748. {
  1749. __gs_input()->mouse.locked = lock;
  1750. gs_platform_t* platform = gs_subsystem(platform);
  1751. gs_platform_window_t* win = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
  1752. glfwSetInputMode((GLFWwindow*)win->hndl, GLFW_CURSOR, lock ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL);
  1753. // Not sure if I want to support this or not
  1754. // if (glfwRawMouseMotionSupported()) {
  1755. // glfwSetInputMode(win, GLFW_RAW_MOUSE_MOTION, lock ? GLFW_TRUE : GLFW_FALSE);
  1756. // }
  1757. }
  1758. /* Main entry point for platform*/
  1759. #ifndef GS_NO_HIJACK_MAIN
  1760. int32_t main(int32_t argv, char** argc)
  1761. {
  1762. gs_t* inst = gs_create(gs_main(argv, argc));
  1763. while (gs_app()->is_running) {
  1764. gs_frame();
  1765. }
  1766. // Free engine
  1767. gs_free(inst);
  1768. return 0;
  1769. }
  1770. #endif // GS_NO_HIJACK_MAIN
  1771. #undef GS_PLATFORM_IMPL_GLFW
  1772. #endif // GS_PLATFORM_IMPL_GLFW
  1773. /*==========================
  1774. // Emscripten Implemenation
  1775. ==========================*/
  1776. #ifdef GS_PLATFORM_IMPL_EMSCRIPTEN
  1777. #define GL_GLEXT_PROTOTYPES
  1778. #define EGL_EGLEXT_PROTOTYPES
  1779. #include <GLES3/gl3.h>
  1780. #include <GLES2/gl2.h>
  1781. #include <GLES2/gl2ext.h>
  1782. #include <emscripten/emscripten.h>
  1783. #include <emscripten/html5.h>
  1784. // Emscripten context data
  1785. typedef struct gs_ems_t
  1786. {
  1787. const char* canvas_name;
  1788. double canvas_width;
  1789. double canvas_height;
  1790. EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx;
  1791. bool32_t mouse_down[GS_MOUSE_BUTTON_CODE_COUNT];
  1792. } gs_ems_t;
  1793. #define GS_EMS_DATA()\
  1794. ((gs_ems_t*)(gs_subsystem(platform)->user_data))
  1795. uint32_t gs_platform_key_to_codepoint(gs_platform_keycode key)
  1796. {
  1797. uint32_t code = 0;
  1798. switch (key)
  1799. {
  1800. default:
  1801. case GS_KEYCODE_COUNT:
  1802. case GS_KEYCODE_INVALID: code = 0; break;
  1803. case GS_KEYCODE_SPACE: code = 32; break;
  1804. case GS_KEYCODE_APOSTROPHE: code = 222; break;
  1805. case GS_KEYCODE_COMMA: code = 44; break;
  1806. case GS_KEYCODE_MINUS: code = 45; break;
  1807. case GS_KEYCODE_PERIOD: code = 46; break;
  1808. case GS_KEYCODE_SLASH: code = 47; break;
  1809. case GS_KEYCODE_0: code = 48; break;
  1810. case GS_KEYCODE_1: code = 49; break;
  1811. case GS_KEYCODE_2: code = 50; break;
  1812. case GS_KEYCODE_3: code = 51; break;
  1813. case GS_KEYCODE_4: code = 52; break;
  1814. case GS_KEYCODE_5: code = 53; break;
  1815. case GS_KEYCODE_6: code = 54; break;
  1816. case GS_KEYCODE_7: code = 55; break;
  1817. case GS_KEYCODE_8: code = 56; break;
  1818. case GS_KEYCODE_9: code = 57; break;
  1819. case GS_KEYCODE_SEMICOLON: code = 59; break; /* ; */
  1820. case GS_KEYCODE_EQUAL: code = 61; break; /* code = */
  1821. case GS_KEYCODE_A: code = 65 + 32; break;
  1822. case GS_KEYCODE_B: code = 66 + 32; break;
  1823. case GS_KEYCODE_C: code = 67 + 32; break;
  1824. case GS_KEYCODE_D: code = 68 + 32; break;
  1825. case GS_KEYCODE_E: code = 69 + 32; break;
  1826. case GS_KEYCODE_F: code = 70 + 32; break;
  1827. case GS_KEYCODE_G: code = 71 + 32; break;
  1828. case GS_KEYCODE_H: code = 72 + 32; break;
  1829. case GS_KEYCODE_I: code = 73 + 32; break;
  1830. case GS_KEYCODE_J: code = 74 + 32; break;
  1831. case GS_KEYCODE_K: code = 75 + 32; break;
  1832. case GS_KEYCODE_L: code = 76 + 32; break;
  1833. case GS_KEYCODE_M: code = 77 + 32; break;
  1834. case GS_KEYCODE_N: code = 78 + 32; break;
  1835. case GS_KEYCODE_O: code = 79 + 32; break;
  1836. case GS_KEYCODE_P: code = 80 + 32; break;
  1837. case GS_KEYCODE_Q: code = 81 + 32; break;
  1838. case GS_KEYCODE_R: code = 82 + 32; break;
  1839. case GS_KEYCODE_S: code = 83 + 32; break;
  1840. case GS_KEYCODE_T: code = 84 + 32; break;
  1841. case GS_KEYCODE_U: code = 85 + 32; break;
  1842. case GS_KEYCODE_V: code = 86 + 32; break;
  1843. case GS_KEYCODE_W: code = 87 + 32; break;
  1844. case GS_KEYCODE_X: code = 88 + 32; break;
  1845. case GS_KEYCODE_Y: code = 89 + 32; break;
  1846. case GS_KEYCODE_Z: code = 90 + 32; break;
  1847. case GS_KEYCODE_LEFT_BRACKET: code = 91; break; /* [ */
  1848. case GS_KEYCODE_BACKSLASH: code = 92; break; /* \ */
  1849. case GS_KEYCODE_RIGHT_BRACKET: code = 93; break; /* ] */
  1850. case GS_KEYCODE_GRAVE_ACCENT: code = 96; break; /* ` */
  1851. case GS_KEYCODE_WORLD_1: code = 161; break; /* non-US #1 */
  1852. case GS_KEYCODE_WORLD_2: code = 162; break; /* non-US #2 */
  1853. case GS_KEYCODE_ESC: code = 27; break;
  1854. case GS_KEYCODE_ENTER: code = 13; break;
  1855. case GS_KEYCODE_TAB: code = 9; break;
  1856. case GS_KEYCODE_BACKSPACE: code = 8; break;
  1857. case GS_KEYCODE_INSERT: code = 260; break;
  1858. case GS_KEYCODE_DELETE: code = 261; break;
  1859. case GS_KEYCODE_LEFT: code = 37; break;
  1860. case GS_KEYCODE_UP: code = 38; break;
  1861. case GS_KEYCODE_RIGHT: code = 39; break;
  1862. case GS_KEYCODE_DOWN: code = 40; break;
  1863. case GS_KEYCODE_PAGE_UP: code = 266; break;
  1864. case GS_KEYCODE_PAGE_DOWN: code = 267; break;
  1865. case GS_KEYCODE_HOME: code = 268; break;
  1866. case GS_KEYCODE_END: code = 269; break;
  1867. case GS_KEYCODE_CAPS_LOCK: code = 280; break;
  1868. case GS_KEYCODE_SCROLL_LOCK: code = 281; break;
  1869. case GS_KEYCODE_NUM_LOCK: code = 282; break;
  1870. case GS_KEYCODE_PRINT_SCREEN: code = 283; break;
  1871. case GS_KEYCODE_PAUSE: code = 284; break;
  1872. case GS_KEYCODE_F1: code = 290; break;
  1873. case GS_KEYCODE_F2: code = 291; break;
  1874. case GS_KEYCODE_F3: code = 292; break;
  1875. case GS_KEYCODE_F4: code = 293; break;
  1876. case GS_KEYCODE_F5: code = 294; break;
  1877. case GS_KEYCODE_F6: code = 295; break;
  1878. case GS_KEYCODE_F7: code = 296; break;
  1879. case GS_KEYCODE_F8: code = 297; break;
  1880. case GS_KEYCODE_F9: code = 298; break;
  1881. case GS_KEYCODE_F10: code = 299; break;
  1882. case GS_KEYCODE_F11: code = 300; break;
  1883. case GS_KEYCODE_F12: code = 301; break;
  1884. case GS_KEYCODE_F13: code = 302; break;
  1885. case GS_KEYCODE_F14: code = 303; break;
  1886. case GS_KEYCODE_F15: code = 304; break;
  1887. case GS_KEYCODE_F16: code = 305; break;
  1888. case GS_KEYCODE_F17: code = 306; break;
  1889. case GS_KEYCODE_F18: code = 307; break;
  1890. case GS_KEYCODE_F19: code = 308; break;
  1891. case GS_KEYCODE_F20: code = 309; break;
  1892. case GS_KEYCODE_F21: code = 310; break;
  1893. case GS_KEYCODE_F22: code = 311; break;
  1894. case GS_KEYCODE_F23: code = 312; break;
  1895. case GS_KEYCODE_F24: code = 313; break;
  1896. case GS_KEYCODE_F25: code = 314; break;
  1897. case GS_KEYCODE_KP_0: code = 320; break;
  1898. case GS_KEYCODE_KP_1: code = 321; break;
  1899. case GS_KEYCODE_KP_2: code = 322; break;
  1900. case GS_KEYCODE_KP_3: code = 323; break;
  1901. case GS_KEYCODE_KP_4: code = 324; break;
  1902. case GS_KEYCODE_KP_5: code = 325; break;
  1903. case GS_KEYCODE_KP_6: code = 326; break;
  1904. case GS_KEYCODE_KP_7: code = 327; break;
  1905. case GS_KEYCODE_KP_8: code = 328; break;
  1906. case GS_KEYCODE_KP_9: code = 329; break;
  1907. case GS_KEYCODE_KP_DECIMAL: code = 330; break;
  1908. case GS_KEYCODE_KP_DIVIDE: code = 331; break;
  1909. case GS_KEYCODE_KP_MULTIPLY: code = 332; break;
  1910. case GS_KEYCODE_KP_SUBTRACT: code = 333; break;
  1911. case GS_KEYCODE_KP_ADD: code = 334; break;
  1912. case GS_KEYCODE_KP_ENTER: code = 335; break;
  1913. case GS_KEYCODE_KP_EQUAL: code = 336; break;
  1914. case GS_KEYCODE_LEFT_SHIFT: code = 16; break;
  1915. case GS_KEYCODE_LEFT_CONTROL: code = 17; break;
  1916. case GS_KEYCODE_LEFT_ALT: code = 18; break;
  1917. case GS_KEYCODE_LEFT_SUPER: code = 343; break;
  1918. case GS_KEYCODE_RIGHT_SHIFT: code = 16; break;
  1919. case GS_KEYCODE_RIGHT_CONTROL: code = 17; break;
  1920. case GS_KEYCODE_RIGHT_ALT: code = 18; break;
  1921. case GS_KEYCODE_RIGHT_SUPER: code = 347; break;
  1922. case GS_KEYCODE_MENU: code = 348; break;
  1923. }
  1924. return code;
  1925. }
  1926. /*
  1927. key_to_code_map[count] = gs_default_val();
  1928. code_to_key_map[count] = gs_default_val();
  1929. */
  1930. // This doesn't work. Have to set up keycodes for emscripten instead. FUN.
  1931. gs_platform_keycode gs_platform_codepoint_to_key(uint32_t code)
  1932. {
  1933. gs_platform_keycode key = GS_KEYCODE_INVALID;
  1934. switch (code)
  1935. {
  1936. default:
  1937. case 0: key = GS_KEYCODE_INVALID; break;
  1938. case 32: key = GS_KEYCODE_SPACE; break;
  1939. case 222: key = GS_KEYCODE_APOSTROPHE; break;
  1940. case 44: key = GS_KEYCODE_COMMA; break;
  1941. case 45: key = GS_KEYCODE_MINUS; break;
  1942. case 46: key = GS_KEYCODE_PERIOD; break;
  1943. case 47: key = GS_KEYCODE_SLASH; break;
  1944. case 48: key = GS_KEYCODE_0; break;
  1945. case 49: key = GS_KEYCODE_1; break;
  1946. case 50: key = GS_KEYCODE_2; break;
  1947. case 51: key = GS_KEYCODE_3; break;
  1948. case 52: key = GS_KEYCODE_4; break;
  1949. case 53: key = GS_KEYCODE_5; break;
  1950. case 54: key = GS_KEYCODE_6; break;
  1951. case 55: key = GS_KEYCODE_7; break;
  1952. case 56: key = GS_KEYCODE_8; break;
  1953. case 57: key = GS_KEYCODE_9; break;
  1954. case 59: key = GS_KEYCODE_SEMICOLON; break;
  1955. case 61: key = GS_KEYCODE_EQUAL; break;
  1956. case 65: case 65 + 32: key = GS_KEYCODE_A; break;
  1957. case 66: case 66 + 32: key = GS_KEYCODE_B; break;
  1958. case 67: case 67 + 32: key = GS_KEYCODE_C; break;
  1959. case 68: case 68 + 32: key = GS_KEYCODE_D; break;
  1960. case 69: case 69 + 32: key = GS_KEYCODE_E; break;
  1961. case 70: case 70 + 32: key = GS_KEYCODE_F; break;
  1962. case 71: case 71 + 32: key = GS_KEYCODE_G; break;
  1963. case 72: case 72 + 32: key = GS_KEYCODE_H; break;
  1964. case 73: case 73 + 32: key = GS_KEYCODE_I; break;
  1965. case 74: case 74 + 32: key = GS_KEYCODE_J; break;
  1966. case 75: case 75 + 32: key = GS_KEYCODE_K; break;
  1967. case 76: case 76 + 32: key = GS_KEYCODE_L; break;
  1968. case 77: case 77 + 32: key = GS_KEYCODE_M; break;
  1969. case 78: case 78 + 32: key = GS_KEYCODE_N; break;
  1970. case 79: case 79 + 32: key = GS_KEYCODE_O; break;
  1971. case 80: case 80 + 32: key = GS_KEYCODE_P; break;
  1972. case 81: case 81 + 32: key = GS_KEYCODE_Q; break;
  1973. case 82: case 82 + 32: key = GS_KEYCODE_R; break;
  1974. case 83: case 83 + 32: key = GS_KEYCODE_S; break;
  1975. case 84: case 84 + 32: key = GS_KEYCODE_T; break;
  1976. case 85: case 85 + 32: key = GS_KEYCODE_U; break;
  1977. case 86: case 86 + 32: key = GS_KEYCODE_V; break;
  1978. case 87: case 87 + 32: key = GS_KEYCODE_W; break;
  1979. case 88: case 88 + 32: key = GS_KEYCODE_X; break;
  1980. case 89: case 89 + 32: key = GS_KEYCODE_Y; break;
  1981. case 90: case 90 + 32: key = GS_KEYCODE_Z; break;
  1982. case 91: key = GS_KEYCODE_LEFT_BRACKET; break;
  1983. case 92: key = GS_KEYCODE_BACKSLASH; break;
  1984. case 93: key = GS_KEYCODE_RIGHT_BRACKET; break;
  1985. case 96: key = GS_KEYCODE_GRAVE_ACCENT; break;
  1986. case 161: key = GS_KEYCODE_WORLD_1; break;
  1987. case 162: key = GS_KEYCODE_WORLD_2; break;
  1988. case 27: key = GS_KEYCODE_ESC; break;
  1989. case 13: key = GS_KEYCODE_ENTER; break;
  1990. case 9: key = GS_KEYCODE_TAB; break;
  1991. case 8: key = GS_KEYCODE_BACKSPACE; break;
  1992. case 260: key = GS_KEYCODE_INSERT; break;
  1993. case 261: key = GS_KEYCODE_DELETE; break;
  1994. case 37: key = GS_KEYCODE_LEFT; break;
  1995. case 38: key = GS_KEYCODE_UP; break;
  1996. case 39: key = GS_KEYCODE_RIGHT; break;
  1997. case 40: key = GS_KEYCODE_DOWN; break;
  1998. case 266: key = GS_KEYCODE_PAGE_UP; break;
  1999. case 267: key = GS_KEYCODE_PAGE_DOWN; break;
  2000. case 268: key = GS_KEYCODE_HOME; break;
  2001. case 269: key = GS_KEYCODE_END; break;
  2002. case 280: key = GS_KEYCODE_CAPS_LOCK; break;
  2003. case 281: key = GS_KEYCODE_SCROLL_LOCK; break;
  2004. case 282: key = GS_KEYCODE_NUM_LOCK; break;
  2005. case 283: key = GS_KEYCODE_PRINT_SCREEN; break;
  2006. case 284: key = GS_KEYCODE_PAUSE; break;
  2007. case 290: key = GS_KEYCODE_F1; break;
  2008. case 291: key = GS_KEYCODE_F2; break;
  2009. case 292: key = GS_KEYCODE_F3; break;
  2010. case 293: key = GS_KEYCODE_F4; break;
  2011. case 294: key = GS_KEYCODE_F5; break;
  2012. case 295: key = GS_KEYCODE_F6; break;
  2013. case 296: key = GS_KEYCODE_F7; break;
  2014. case 297: key = GS_KEYCODE_F8; break;
  2015. case 298: key = GS_KEYCODE_F9; break;
  2016. case 299: key = GS_KEYCODE_F10; break;
  2017. case 300: key = GS_KEYCODE_F11; break;
  2018. case 301: key = GS_KEYCODE_F12; break;
  2019. case 302: key = GS_KEYCODE_F13; break;
  2020. case 303: key = GS_KEYCODE_F14; break;
  2021. case 304: key = GS_KEYCODE_F15; break;
  2022. case 305: key = GS_KEYCODE_F16; break;
  2023. case 306: key = GS_KEYCODE_F17; break;
  2024. case 307: key = GS_KEYCODE_F18; break;
  2025. case 308: key = GS_KEYCODE_F19; break;
  2026. case 309: key = GS_KEYCODE_F20; break;
  2027. case 310: key = GS_KEYCODE_F21; break;
  2028. case 311: key = GS_KEYCODE_F22; break;
  2029. case 312: key = GS_KEYCODE_F23; break;
  2030. case 313: key = GS_KEYCODE_F24; break;
  2031. case 314: key = GS_KEYCODE_F25; break;
  2032. case 320: key = GS_KEYCODE_KP_0; break;
  2033. case 321: key = GS_KEYCODE_KP_1; break;
  2034. case 322: key = GS_KEYCODE_KP_2; break;
  2035. case 323: key = GS_KEYCODE_KP_3; break;
  2036. case 324: key = GS_KEYCODE_KP_4; break;
  2037. case 325: key = GS_KEYCODE_KP_5; break;
  2038. case 326: key = GS_KEYCODE_KP_6; break;
  2039. case 327: key = GS_KEYCODE_KP_7; break;
  2040. case 328: key = GS_KEYCODE_KP_8; break;
  2041. case 329: key = GS_KEYCODE_KP_9; break;
  2042. case 330: key = GS_KEYCODE_KP_DECIMAL; break;
  2043. case 331: key = GS_KEYCODE_KP_DIVIDE; break;
  2044. case 332: key = GS_KEYCODE_KP_MULTIPLY; break;
  2045. case 333: key = GS_KEYCODE_KP_SUBTRACT; break;
  2046. case 334: key = GS_KEYCODE_KP_ADD; break;
  2047. case 335: key = GS_KEYCODE_KP_ENTER; break;
  2048. case 336: key = GS_KEYCODE_KP_EQUAL; break;
  2049. case 16: key = GS_KEYCODE_LEFT_SHIFT; break;
  2050. case 17: key = GS_KEYCODE_LEFT_CONTROL; break;
  2051. case 18: key = GS_KEYCODE_LEFT_ALT; break;
  2052. case 343: key = GS_KEYCODE_LEFT_SUPER; break;
  2053. case 347: key = GS_KEYCODE_RIGHT_SUPER; break;
  2054. case 348: key = GS_KEYCODE_MENU; break;
  2055. }
  2056. return key;
  2057. }
  2058. EM_BOOL gs_ems_size_changed_cb(int32_t type, const EmscriptenUiEvent* evt, void* user_data)
  2059. {
  2060. gs_println("size changed");
  2061. gs_platform_t* platform = gs_subsystem(platform);
  2062. gs_ems_t* ems = (gs_ems_t*)platform->user_data;
  2063. (void)type;
  2064. (void)evt;
  2065. (void)user_data;
  2066. // gs_println("was: <%.2f, %.2f>", (float)ems->canvas_width, (float)ems->canvas_height);
  2067. emscripten_get_element_css_size(ems->canvas_name, &ems->canvas_width, &ems->canvas_height);
  2068. emscripten_set_canvas_element_size(ems->canvas_name, ems->canvas_width, ems->canvas_height);
  2069. // gs_println("is: <%.2f, %.2f>", (float)ems->canvas_width, (float)ems->canvas_height);
  2070. return true;
  2071. }
  2072. EM_BOOL gs_ems_fullscreenchange_cb(int32_t type, const EmscriptenFullscreenChangeEvent* evt, void* user_data)
  2073. {
  2074. (void)user_data;
  2075. (void)evt;
  2076. (void)type;
  2077. gs_ems_t* ems = GS_EMS_DATA();
  2078. // emscripten_get_element_css_size(ems->canvas_name, &ems->canvas_width, &ems->canvas_height);
  2079. if (evt->isFullscreen) {
  2080. EmscriptenFullscreenStrategy strategy;
  2081. strategy.scaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF;
  2082. strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT;
  2083. strategy.canvasResizedCallback = (int (*)(int, const void*, void*)) gs_ems_size_changed_cb;
  2084. emscripten_enter_soft_fullscreen(ems->canvas_name, &strategy);
  2085. // gs_println("fullscreen!");
  2086. // emscripten_enter_soft_fullscreen(ems->canvas_name, NULL);
  2087. // ems->canvas_width = (float)evt->screenWidth;
  2088. // ems->canvas_height = (float)evt->screenHeight;
  2089. // emscripten_set_canvas_element_size(ems->canvas_name, ems->canvas_width, ems->canvas_height);
  2090. } else {
  2091. emscripten_exit_fullscreen();
  2092. emscripten_set_canvas_element_size(ems->canvas_name, 800, 600);
  2093. }
  2094. }
  2095. EM_BOOL gs_ems_key_cb(int32_t type, const EmscriptenKeyboardEvent* evt, void* user_data)
  2096. {
  2097. (void)user_data;
  2098. // Push back event into platform events
  2099. gs_platform_event_t gs_evt = gs_default_val();
  2100. gs_evt.type = GS_PLATFORM_EVENT_KEY;
  2101. gs_evt.key.codepoint = evt->which;
  2102. gs_evt.key.keycode = gs_platform_codepoint_to_key(evt->which);
  2103. switch (type)
  2104. {
  2105. case EMSCRIPTEN_EVENT_KEYPRESS:
  2106. {
  2107. gs_evt.type = GS_PLATFORM_EVENT_TEXT;
  2108. gs_evt.text.codepoint = evt->which;
  2109. } break;
  2110. case EMSCRIPTEN_EVENT_KEYDOWN:
  2111. {
  2112. gs_evt.key.action = GS_PLATFORM_KEY_DOWN;
  2113. } break;
  2114. case EMSCRIPTEN_EVENT_KEYUP:
  2115. {
  2116. gs_evt.key.action = GS_PLATFORM_KEY_RELEASED;
  2117. } break;
  2118. default: break;
  2119. }
  2120. // Add action
  2121. gs_platform_add_event(&gs_evt);
  2122. return evt->which < 32;
  2123. }
  2124. EM_BOOL gs_ems_mouse_cb(int32_t type, const EmscriptenMouseEvent* evt, void* user_data)
  2125. {
  2126. (void)user_data;
  2127. gs_platform_t* platform = gs_subsystem(platform);
  2128. gs_ems_t* ems = GS_EMS_DATA();
  2129. gs_platform_mouse_button_code button = GS_MOUSE_LBUTTON;
  2130. switch (evt->button) {
  2131. case 0: button = GS_MOUSE_LBUTTON; break;
  2132. case 1: button = GS_MOUSE_MBUTTON; break;
  2133. case 2: button = GS_MOUSE_RBUTTON; break;
  2134. }
  2135. // Push back event into platform events
  2136. gs_platform_event_t gs_evt = gs_default_val();
  2137. gs_evt.type = GS_PLATFORM_EVENT_MOUSE;
  2138. gs_evt.mouse.codepoint = evt->button;
  2139. gs_evt.mouse.button = button;
  2140. bool add = true;
  2141. switch (type)
  2142. {
  2143. case EMSCRIPTEN_EVENT_CLICK:
  2144. {
  2145. // gs_evt.mouse.action = GS_PLATFORM_MOUSE_BUTTON_PRESSED;
  2146. // gs_println("EMS_PRESSED");
  2147. add = false;
  2148. } break;
  2149. // Emscripten doesn't register continuous presses, so have to manually store this state
  2150. case EMSCRIPTEN_EVENT_MOUSEDOWN:
  2151. {
  2152. gs_evt.mouse.action = GS_PLATFORM_MOUSE_BUTTON_DOWN;
  2153. // ems->mouse_down[(int32_t)button] = true;
  2154. } break;
  2155. case EMSCRIPTEN_EVENT_MOUSEUP:
  2156. {
  2157. gs_evt.mouse.action = GS_PLATFORM_MOUSE_BUTTON_RELEASED;
  2158. // ems->mouse_down[(int32_t)button] = false;
  2159. } break;
  2160. case EMSCRIPTEN_EVENT_MOUSEMOVE:
  2161. {
  2162. gs_evt.mouse.action = GS_PLATFORM_MOUSE_MOVE;
  2163. if (platform->input.mouse.locked) {
  2164. gs_evt.mouse.move = gs_v2((float)evt->movementX, (float)evt->movementY);
  2165. } else {
  2166. gs_evt.mouse.move = gs_v2((float)evt->targetX, (float)evt->targetY);
  2167. }
  2168. } break;
  2169. case EMSCRIPTEN_EVENT_MOUSEENTER:
  2170. {
  2171. gs_evt.mouse.action = GS_PLATFORM_MOUSE_ENTER;
  2172. // Release all buttons
  2173. /*
  2174. ems->mouse_down[0] = false;
  2175. ems->mouse_down[1] = false;
  2176. ems->mouse_down[2] = false;
  2177. */
  2178. } break;
  2179. case EMSCRIPTEN_EVENT_MOUSELEAVE:
  2180. {
  2181. gs_evt.mouse.action = GS_PLATFORM_MOUSE_LEAVE;
  2182. // Release all buttons
  2183. /*
  2184. ems->mouse_down[0] = false;
  2185. ems->mouse_down[1] = false;
  2186. ems->mouse_down[2] = false;
  2187. */
  2188. } break;
  2189. default:
  2190. {
  2191. }break;
  2192. }
  2193. if (add) gs_platform_add_event(&gs_evt);
  2194. return true;
  2195. }
  2196. EM_BOOL gs_ems_mousewheel_cb(int32_t type, const EmscriptenWheelEvent* evt, void* user_data)
  2197. {
  2198. (void)type;
  2199. (void)user_data;
  2200. // Push back event into platform events
  2201. gs_platform_event_t gs_evt = gs_default_val();
  2202. gs_evt.type = GS_PLATFORM_EVENT_MOUSE;
  2203. gs_evt.mouse.action = GS_PLATFORM_MOUSE_WHEEL;
  2204. gs_evt.mouse.wheel = gs_v2((float)evt->deltaX, -(float)evt->deltaY);
  2205. gs_platform_add_event(&gs_evt);
  2206. return true;
  2207. }
  2208. EM_BOOL gs_ems_pointerlock_cb(int32_t type, const EmscriptenPointerlockChangeEvent* evt, void* user_data)
  2209. {
  2210. (void)type;
  2211. (void)user_data;
  2212. gs_platform_t* platform = gs_subsystem(platform);
  2213. platform->input.mouse.locked = evt->isActive;
  2214. // gs_println("lock: %zu", platform->input.mouse.locked);
  2215. }
  2216. GS_API_DECL void
  2217. gs_platform_init(gs_platform_t* platform)
  2218. {
  2219. gs_println("Initializing Emscripten.");
  2220. gs_app_desc_t* app = gs_app();
  2221. platform->user_data = gs_malloc_init(gs_ems_t);
  2222. gs_ems_t* ems = (gs_ems_t*)platform->user_data;
  2223. // ems->canvas_width = app->window_width;
  2224. // ems->canvas_height = app->window_height;
  2225. // double dpi = emscripten_get_device_pixel_ratio();
  2226. // Just set this to defaults for now
  2227. ems->canvas_name = "#canvas";
  2228. emscripten_set_canvas_element_size(ems->canvas_name, app->window.width, app->window.height);
  2229. emscripten_get_element_css_size(ems->canvas_name, &ems->canvas_width, &ems->canvas_height);
  2230. // Set up callbacks
  2231. emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, true, gs_ems_fullscreenchange_cb);
  2232. emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, true, gs_ems_size_changed_cb);
  2233. emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, true, gs_ems_key_cb);
  2234. emscripten_set_keypress_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, true, gs_ems_key_cb);
  2235. emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, true, gs_ems_key_cb);
  2236. emscripten_set_click_callback(ems->canvas_name, NULL, true, gs_ems_mouse_cb);
  2237. emscripten_set_mouseenter_callback(ems->canvas_name, NULL, true, gs_ems_mouse_cb);
  2238. emscripten_set_mouseleave_callback(ems->canvas_name, NULL, true, gs_ems_mouse_cb);
  2239. emscripten_set_mousedown_callback(ems->canvas_name, NULL, true, gs_ems_mouse_cb);
  2240. emscripten_set_mouseup_callback(ems->canvas_name, NULL, true, gs_ems_mouse_cb);
  2241. emscripten_set_mousemove_callback(ems->canvas_name, NULL, true, gs_ems_mouse_cb);
  2242. emscripten_set_wheel_callback(ems->canvas_name, NULL, true, gs_ems_mousewheel_cb);
  2243. emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, true, gs_ems_pointerlock_cb);
  2244. // Set up webgl context
  2245. EmscriptenWebGLContextAttributes attrs;
  2246. emscripten_webgl_init_context_attributes(&attrs);
  2247. attrs.antialias = false;
  2248. attrs.depth = true;
  2249. attrs.premultipliedAlpha = false;
  2250. attrs.stencil = true;
  2251. attrs.majorVersion = 2;
  2252. attrs.minorVersion = 0;
  2253. attrs.enableExtensionsByDefault = true;
  2254. ems->ctx = emscripten_webgl_create_context(ems->canvas_name, &attrs);
  2255. if (!ems->ctx) {
  2256. gs_println("Emscripten Init: Unable to create webgl2 context. Reverting to webgl1.");
  2257. attrs.majorVersion = 1;
  2258. ems->ctx = emscripten_webgl_create_context(ems->canvas_name, &attrs);
  2259. } else {
  2260. gs_println("Emscripten Init: Successfully created webgl2 context.");
  2261. }
  2262. if (emscripten_webgl_make_context_current(ems->ctx) != EMSCRIPTEN_RESULT_SUCCESS) {
  2263. gs_println("Emscripten Init: Unable to set current webgl context.");
  2264. }
  2265. }
  2266. GS_API_DECL void
  2267. gs_platform_window_set_clipboard(uint32_t handle, const char* str)
  2268. {
  2269. }
  2270. GS_API_DECL const char*
  2271. gs_platform_window_get_clipboard(uint32_t handle)
  2272. {
  2273. return NULL;
  2274. }
  2275. GS_API_DECL void
  2276. gs_platform_lock_mouse(uint32_t handle, bool32_t lock)
  2277. {
  2278. gs_platform_t* platform = gs_subsystem(platform);
  2279. gs_ems_t* ems = (gs_ems_t*)platform->user_data;
  2280. // if (platform->input.mouse.locked == lock) return;
  2281. platform->input.mouse.locked = lock;
  2282. if (lock) {
  2283. emscripten_request_pointerlock(ems->canvas_name, true);
  2284. } else {
  2285. emscripten_exit_pointerlock();
  2286. }
  2287. }
  2288. GS_API_DECL void
  2289. gs_platform_shutdown(gs_platform_t* platform)
  2290. {
  2291. // Free memory
  2292. }
  2293. GS_API_DECL double
  2294. gs_platform_elapsed_time()
  2295. {
  2296. return emscripten_performance_now();
  2297. }
  2298. // Platform Video
  2299. GS_API_DECL void
  2300. gs_platform_enable_vsync(int32_t enabled)
  2301. {
  2302. // Nothing for now...
  2303. }
  2304. // Platform Util
  2305. GS_API_DECL void
  2306. gs_platform_sleep(float ms)
  2307. {
  2308. emscripten_sleep((uint32_t)ms);
  2309. }
  2310. GS_API_DECL void gs_platform_update_internal(gs_platform_t* platform)
  2311. {
  2312. }
  2313. // Platform Input
  2314. GS_API_DECL void
  2315. gs_platform_process_input(gs_platform_input_t* input)
  2316. {
  2317. gs_ems_t* ems = GS_EMS_DATA();
  2318. // Set mouse buttons
  2319. /*
  2320. for (uint32_t i = 0; i < GS_MOUSE_BUTTON_CODE_COUNT; ++i) {
  2321. if (ems->mouse_down[i]) gs_platform_press_mouse_button((gs_platform_mouse_button_code)i);
  2322. else gs_platform_release_mouse_button((gs_platform_mouse_button_code)i);
  2323. }
  2324. */
  2325. // Check for pointerlock, because Chrome is retarded.
  2326. EmscriptenPointerlockChangeEvent evt = gs_default_val();
  2327. emscripten_get_pointerlock_status(&evt);
  2328. if (gs_platform_mouse_locked() && !evt.isActive) {
  2329. gs_subsystem(platform)->input.mouse.locked = false;
  2330. }
  2331. }
  2332. GS_API_DECL void
  2333. gs_platform_mouse_set_position(uint32_t handle, float x, float y)
  2334. {
  2335. // Not sure this is possible...
  2336. struct gs_platform_t* platform = gs_subsystem(platform);
  2337. platform->input.mouse.position = gs_v2(x, y);
  2338. }
  2339. GS_API_DECL gs_platform_window_t
  2340. gs_platform_window_create_internal(const gs_platform_window_desc_t* desc)
  2341. {
  2342. // Nothing for now, since we just create this internally...
  2343. gs_platform_window_t win = gs_default_val();
  2344. return win;
  2345. }
  2346. GS_API_DECL void
  2347. gs_platform_window_swap_buffer(uint32_t handle)
  2348. {
  2349. // Nothing for emscripten...but could handle swapping manually if preferred.
  2350. }
  2351. GS_API_DECL gs_vec2
  2352. gs_platform_window_sizev(uint32_t handle)
  2353. {
  2354. gs_ems_t* ems = GS_EMS_DATA();
  2355. return gs_v2((float)ems->canvas_width, (float)ems->canvas_height);
  2356. }
  2357. GS_API_DECL void
  2358. gs_platform_window_size(uint32_t handle, uint32_t* w, uint32_t* h)
  2359. {
  2360. gs_ems_t* ems = GS_EMS_DATA();
  2361. *w = (uint32_t)ems->canvas_width;
  2362. *h = (uint32_t)ems->canvas_height;
  2363. }
  2364. GS_API_DECL uint32_t
  2365. gs_platform_window_width(uint32_t handle)
  2366. {
  2367. gs_ems_t* ems = GS_EMS_DATA();
  2368. return (uint32_t)ems->canvas_width;
  2369. }
  2370. GS_API_DECL uint32_t
  2371. gs_platform_window_height(uint32_t handle)
  2372. {
  2373. gs_ems_t* ems = GS_EMS_DATA();
  2374. return (uint32_t)ems->canvas_height;
  2375. }
  2376. GS_API_DECL bool32_t
  2377. gs_platform_window_fullscreen(uint32_t handle)
  2378. {
  2379. return false;
  2380. }
  2381. GS_API_DECL void
  2382. gs_platform_window_position(uint32_t handle, uint32_t* x, uint32_t* y)
  2383. {
  2384. }
  2385. GS_API_DECL gs_vec2
  2386. gs_platform_window_positionv(uint32_t handle)
  2387. {
  2388. return gs_v2(0, 0);
  2389. }
  2390. GS_API_DECL void
  2391. gs_platform_set_window_size(uint32_t handle, uint32_t width, uint32_t height)
  2392. {
  2393. gs_ems_t* ems = GS_EMS_DATA();
  2394. emscripten_set_canvas_element_size(ems->canvas_name, width, height);
  2395. ems->canvas_width = (uint32_t)width;
  2396. ems->canvas_height = (uint32_t)height;
  2397. }
  2398. GS_API_DECL void
  2399. gs_platform_set_window_sizev(uint32_t handle, gs_vec2 v)
  2400. {
  2401. gs_ems_t* ems = GS_EMS_DATA();
  2402. emscripten_set_canvas_element_size(ems->canvas_name, (uint32_t)v.x, (uint32_t)v.y);
  2403. ems->canvas_width = (uint32_t)v.x;
  2404. ems->canvas_height = (uint32_t)v.y;
  2405. }
  2406. GS_API_DECL void
  2407. gs_platform_set_window_fullscreen(uint32_t handle, bool32_t fullscreen)
  2408. {
  2409. }
  2410. GS_API_DECL void
  2411. gs_platform_set_window_position(uint32_t handle, uint32_t x, uint32_t y)
  2412. {
  2413. }
  2414. GS_API_DECL void
  2415. gs_platform_set_window_positionv(uint32_t handle, gs_vec2 v)
  2416. {
  2417. }
  2418. GS_API_DECL void
  2419. gs_platform_set_cursor(uint32_t handle, gs_platform_cursor cursor)
  2420. {
  2421. }
  2422. GS_API_DECL void
  2423. gs_platform_set_dropped_files_callback(uint32_t handle, gs_dropped_files_callback_t cb)
  2424. {
  2425. }
  2426. GS_API_DECL void
  2427. gs_platform_set_window_close_callback(uint32_t handle, gs_window_close_callback_t cb)
  2428. {
  2429. }
  2430. GS_API_DECL void
  2431. gs_platform_set_character_callback(uint32_t handle, gs_character_callback_t cb)
  2432. {
  2433. }
  2434. GS_API_DECL void*
  2435. gs_platform_raw_window_handle(uint32_t handle)
  2436. {
  2437. return NULL;
  2438. }
  2439. GS_API_DECL void
  2440. gs_platform_framebuffer_size(uint32_t handle, uint32_t* w, uint32_t* h)
  2441. {
  2442. gs_ems_t* ems = GS_EMS_DATA();
  2443. // double dpi = emscripten_get_device_pixel_ratio();
  2444. *w = (uint32_t)(ems->canvas_width);
  2445. *h = (uint32_t)(ems->canvas_height);
  2446. }
  2447. GS_API_DECL gs_vec2
  2448. gs_platform_framebuffer_sizev(uint32_t handle)
  2449. {
  2450. uint32_t w = 0, h = 0;
  2451. gs_platform_framebuffer_size(handle, &w, &h);
  2452. return gs_v2(w, h);
  2453. }
  2454. GS_API_DECL uint32_t
  2455. gs_platform_framebuffer_width(uint32_t handle)
  2456. {
  2457. // Get ems width for now. Don't use handle.
  2458. gs_ems_t* ems = GS_EMS_DATA();
  2459. return (uint32_t)ems->canvas_width;
  2460. }
  2461. GS_API_DECL uint32_t
  2462. gs_platform_framebuffer_height(uint32_t handle)
  2463. {
  2464. gs_ems_t* ems = GS_EMS_DATA();
  2465. return (uint32_t)ems->canvas_height;
  2466. }
  2467. #ifndef GS_NO_HIJACK_MAIN
  2468. int32_t main(int32_t argc, char** argv)
  2469. {
  2470. gs_app_desc_t app = gs_main(argc, argv);
  2471. gs_create(app);
  2472. emscripten_set_main_loop(gs_frame, (int32_t)app.window.frame_rate, true);
  2473. return 0;
  2474. }
  2475. #endif // GS_NO_HIJACK_MAIN
  2476. #undef GS_PLATFORM_IMPL_EMSCRIPTEN
  2477. #endif // GS_PLATFORM_IMPL_EMSCRIPTEN
  2478. /*=======================
  2479. // Android Implemenation
  2480. ========================*/
  2481. // Modified from sokol_app.h android impl
  2482. #ifdef GS_PLATFORM_IMPL_ANDROID
  2483. // Platform includes
  2484. #include <pthread.h>
  2485. #include <unistd.h>
  2486. #include <time.h>
  2487. #include <android/native_activity.h>
  2488. //#include <android_native_app_glue.h>
  2489. #include <android/looper.h>
  2490. #include <android/log.h>
  2491. #include <EGL/egl.h>
  2492. #include <GLES3/gl3.h>
  2493. #ifndef GL_EXT_PROTOTYPES
  2494. #define GL_GLEXT_PROTOTYPES
  2495. #endif
  2496. typedef enum gs_android_message_type {
  2497. GS_ANDROID_MSG_CREATE,
  2498. GS_ANDROID_MSG_START,
  2499. GS_ANDROID_MSG_STOP,
  2500. GS_ANDROID_MSG_RESUME,
  2501. GS_ANDROID_MSG_PAUSE,
  2502. GS_ANDROID_MSG_GAIN_FOCUS,
  2503. GS_ANDROID_MSG_LOSE_FOCUS,
  2504. GS_ANDROID_MSG_SET_NATIVE_WINDOW,
  2505. GS_ANDROID_MSG_SET_INPUT_QUEUE,
  2506. GS_ANDROID_MSG_DESTROY
  2507. } gs_android_message_type;
  2508. typedef struct gs_android_thread_t {
  2509. pthread_t thread;
  2510. pthread_mutex_t mutex;
  2511. pthread_cond_t cond;
  2512. int32_t read_from_main_fd;
  2513. int32_t write_from_main_fd;
  2514. bool is_thread_started;
  2515. bool is_thread_stopping;
  2516. bool is_thread_stopped;
  2517. bool padding;
  2518. } gs_android_thread_t;
  2519. typedef struct gs_android_resources_t {
  2520. ANativeWindow* window;
  2521. AInputQueue* input;
  2522. } gs_android_resources_t;
  2523. typedef struct gs_android_egl_t {
  2524. int32_t width;
  2525. int32_t height;
  2526. int32_t fbwidth;
  2527. int32_t fbheight;
  2528. EGLConfig config;
  2529. EGLDisplay display;
  2530. EGLContext context;
  2531. EGLSurface surface;
  2532. } gs_android_egl_t;
  2533. typedef struct gs_android_state_t {
  2534. bool has_created;
  2535. bool has_resumed;
  2536. bool has_focus;
  2537. bool padding;
  2538. } gs_android_state_t;
  2539. typedef struct gs_android_t {
  2540. ANativeActivity* activity;
  2541. gs_android_thread_t gt;
  2542. gs_android_resources_t pending;
  2543. gs_android_resources_t current;
  2544. ALooper* looper;
  2545. gs_android_egl_t egl;
  2546. gs_android_state_t state;
  2547. const char* internal_data_path;
  2548. } gs_android_t;
  2549. #define GS_PLATFORM_ANDROID_DATA(...)\
  2550. ((gs_android_t*)gs_subsystem(platform)->user_data)
  2551. bool gs_android_should_update(gs_android_t* android)
  2552. {
  2553. return (android->state.has_focus && android->state.has_resumed && android->egl.surface != EGL_NO_SURFACE);
  2554. }
  2555. void gs_android_shutdown(gs_android_t* android)
  2556. {
  2557. android->gt.is_thread_stopping = true;
  2558. }
  2559. bool gs_android_init_egl(gs_android_t* android)
  2560. {
  2561. gs_assert(android->egl.display == EGL_NO_DISPLAY);
  2562. gs_assert(android->egl.context == EGL_NO_CONTEXT);
  2563. EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  2564. if (display == EGL_NO_DISPLAY) {
  2565. return false;
  2566. }
  2567. if (eglInitialize(display, NULL, NULL) == EGL_FALSE) {
  2568. return false;
  2569. }
  2570. EGLint alpha_size = 8;
  2571. const EGLint cfg_attributes[] = {
  2572. EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
  2573. EGL_RED_SIZE, 8,
  2574. EGL_GREEN_SIZE, 8,
  2575. EGL_BLUE_SIZE, 8,
  2576. EGL_ALPHA_SIZE, alpha_size,
  2577. EGL_DEPTH_SIZE, 16,
  2578. EGL_STENCIL_SIZE, 0,
  2579. EGL_NONE,
  2580. };
  2581. EGLConfig available_cfgs[32];
  2582. EGLint cfg_count;
  2583. eglChooseConfig(display, cfg_attributes, available_cfgs, 32, &cfg_count);
  2584. gs_assert(cfg_count > 0);
  2585. gs_assert(cfg_count <= 32);
  2586. /* find config with 8-bit rgb buffer if available, ndk sample does not trust egl spec */
  2587. EGLConfig config;
  2588. bool exact_cfg_found = false;
  2589. for (int i = 0; i < cfg_count; ++i) {
  2590. EGLConfig c = available_cfgs[i];
  2591. EGLint r, g, b, a, d;
  2592. if (eglGetConfigAttrib(display, c, EGL_RED_SIZE, &r) == EGL_TRUE &&
  2593. eglGetConfigAttrib(display, c, EGL_GREEN_SIZE, &g) == EGL_TRUE &&
  2594. eglGetConfigAttrib(display, c, EGL_BLUE_SIZE, &b) == EGL_TRUE &&
  2595. eglGetConfigAttrib(display, c, EGL_ALPHA_SIZE, &a) == EGL_TRUE &&
  2596. eglGetConfigAttrib(display, c, EGL_DEPTH_SIZE, &d) == EGL_TRUE &&
  2597. r == 8 && g == 8 && b == 8 && (alpha_size == 0 || a == alpha_size) && d == 16) {
  2598. exact_cfg_found = true;
  2599. config = c;
  2600. break;
  2601. }
  2602. }
  2603. if (!exact_cfg_found) {
  2604. config = available_cfgs[0];
  2605. }
  2606. // Force GLES3 for now
  2607. EGLint ctx_attributes[] = {
  2608. EGL_CONTEXT_CLIENT_VERSION, 3,
  2609. EGL_NONE,
  2610. };
  2611. EGLContext context = eglCreateContext(display, config, EGL_NO_CONTEXT, ctx_attributes);
  2612. if (context == EGL_NO_CONTEXT) {
  2613. return false;
  2614. }
  2615. gs_println("EGL: Successfully initialized.");
  2616. android->egl.config = config;
  2617. android->egl.display = display;
  2618. android->egl.context = context;
  2619. return true;
  2620. }
  2621. bool gs_android_create_egl_surface(gs_android_t* android, ANativeWindow* window)
  2622. {
  2623. gs_assert(android);
  2624. gs_assert(android->egl.display != EGL_NO_DISPLAY);
  2625. gs_assert(android->egl.context != EGL_NO_CONTEXT);
  2626. gs_assert(window);
  2627. // Construct egl surface, make current
  2628. EGLSurface surface = eglCreateWindowSurface(android->egl.display, android->egl.config, window, NULL);
  2629. if (surface == EGL_NO_SURFACE) {
  2630. return false;
  2631. }
  2632. if (eglMakeCurrent(android->egl.display, surface, surface, android->egl.context) == EGL_FALSE) {
  2633. return false;
  2634. }
  2635. android->egl.surface = surface;
  2636. return true;
  2637. }
  2638. bool gs_android_destroy_egl_surface(gs_android_t* android)
  2639. {
  2640. if (android->egl.display == EGL_NO_DISPLAY) {
  2641. return false;
  2642. }
  2643. eglMakeCurrent(android->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  2644. if (android->egl.surface != EGL_NO_SURFACE) {
  2645. eglDestroySurface(android->egl.display, android->egl.surface);
  2646. android->egl.surface = EGL_NO_SURFACE;
  2647. }
  2648. return true;
  2649. }
  2650. void gs_android_update_dimensions(gs_android_t* android, ANativeWindow* window, bool force_update)
  2651. {
  2652. gs_assert(android->egl.display != EGL_NO_DISPLAY);
  2653. gs_assert(android->egl.context != EGL_NO_CONTEXT);
  2654. gs_assert(android->egl.surface != EGL_NO_SURFACE);
  2655. gs_assert(window);
  2656. const int32_t win_w = ANativeWindow_getWidth(window);
  2657. const int32_t win_h = ANativeWindow_getHeight(window);
  2658. gs_assert(win_w >= 0 && win_h >= 0);
  2659. const bool win_changed = (win_w != android->egl.width) || (win_h != android->egl.height);
  2660. android->egl.width = win_w;
  2661. android->egl.height = win_h;
  2662. if (win_changed || force_update) {
  2663. if (true) { // High dpi setting
  2664. /*
  2665. const int32_t buf_w = win_w / 2;
  2666. const int32_t buf_h = win_h / 2;
  2667. EGLint format;
  2668. EGLBoolean egl_result = eglGetConfigAttrib(android->egl.display, android->egl.config, EGL_NATIVE_VISUAL_ID, &format);
  2669. gs_assert(egl_result == EGL_TRUE);
  2670. int32_t result = ANativeWindow_setBuffersGeometry(window, buf_w, buf_h, format);
  2671. gs_assert(result == 0);
  2672. */
  2673. }
  2674. }
  2675. /* query surface size */
  2676. EGLint fb_w, fb_h;
  2677. EGLBoolean egl_result_w = eglQuerySurface(android->egl.display, android->egl.surface, EGL_WIDTH, &fb_w);
  2678. EGLBoolean egl_result_h = eglQuerySurface(android->egl.display, android->egl.surface, EGL_HEIGHT, &fb_h);
  2679. gs_assert(egl_result_w == EGL_TRUE);
  2680. gs_assert(egl_result_h == EGL_TRUE);
  2681. const bool fb_changed = (fb_w != android->egl.fbwidth) || (fb_h != android->egl.fbheight);
  2682. android->egl.fbwidth = fb_w;
  2683. android->egl.fbheight = fb_h;
  2684. gs_println("fb: <%.2f, %.2f>, ws: <%.2f, %.2f>", (float)fb_w, (float)fb_h, (float)win_w, (float)win_h);
  2685. // _sapp.dpi_scale = (float)_sapp.framebuffer_width / (float)_sapp.window_width;
  2686. if (win_changed || fb_changed || force_update) {
  2687. /*
  2688. if (!_sapp.first_frame) {
  2689. SOKOL_LOG("SAPP_EVENTTYPE_RESIZED");
  2690. _sapp_android_app_event(SAPP_EVENTTYPE_RESIZED);
  2691. }
  2692. */
  2693. }
  2694. }
  2695. bool gs_android_touch_event(AInputEvent* evt)
  2696. {
  2697. gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
  2698. gs_assert(android);
  2699. gs_assert(android->current.input);
  2700. if (AInputEvent_getType(evt) != AINPUT_EVENT_TYPE_MOTION) {
  2701. return false;
  2702. }
  2703. // Construct touch events here and call add into platform layer
  2704. int32_t action_idx = AMotionEvent_getAction(evt);
  2705. int32_t action = action_idx & AMOTION_EVENT_ACTION_MASK;
  2706. // Construct platform event to add
  2707. gs_platform_event_t gsevt = gs_default_val();
  2708. gsevt.type = GS_PLATFORM_EVENT_TOUCH;
  2709. switch (action) {
  2710. case AMOTION_EVENT_ACTION_DOWN:
  2711. case AMOTION_EVENT_ACTION_POINTER_DOWN: {
  2712. gsevt.touch.action = GS_PLATFORM_TOUCH_DOWN;
  2713. } break;
  2714. case AMOTION_EVENT_ACTION_UP:
  2715. case AMOTION_EVENT_ACTION_POINTER_UP: {
  2716. gsevt.touch.action = GS_PLATFORM_TOUCH_UP;
  2717. } break;
  2718. case AMOTION_EVENT_ACTION_MOVE: {
  2719. gsevt.touch.action = GS_PLATFORM_TOUCH_MOVE;
  2720. } break;
  2721. case AMOTION_EVENT_ACTION_CANCEL: {
  2722. gsevt.touch.action = GS_PLATFORM_TOUCH_CANCEL;
  2723. } break;
  2724. default: {
  2725. return false;
  2726. } break;
  2727. }
  2728. int32_t idx = action_idx >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
  2729. uint32_t num_touches = (uint32_t)AMotionEvent_getPointerCount(evt);
  2730. if (num_touches > GS_PLATFORM_MAX_TOUCH) {
  2731. num_touches = GS_PLATFORM_MAX_TOUCH;
  2732. }
  2733. for (uint32_t i = 0; i < num_touches; ++i) {
  2734. gsevt.touch.point.id = (uintptr_t)AMotionEvent_getPointerId(evt, (size_t)i);
  2735. gsevt.touch.point.position.x = (AMotionEvent_getRawX(evt, (size_t)i) / android->egl.width) * android->egl.fbwidth;
  2736. gsevt.touch.point.position.y = (AMotionEvent_getRawY(evt, (size_t)i) / android->egl.height) * android->egl.fbheight;
  2737. if (action == AMOTION_EVENT_ACTION_POINTER_DOWN ||
  2738. action == AMOTION_EVENT_ACTION_POINTER_UP) {
  2739. gsevt.touch.point.changed = (uint16_t)(i == idx);
  2740. } else {
  2741. gsevt.touch.point.changed = (uint16_t)true;
  2742. }
  2743. gs_platform_add_event(&gsevt);
  2744. }
  2745. return true;
  2746. }
  2747. bool gs_android_key_event(AInputEvent* evt)
  2748. {
  2749. if (AInputEvent_getType(evt) != AINPUT_EVENT_TYPE_KEY) {
  2750. return false;
  2751. }
  2752. // Shutdown event?
  2753. if (AKeyEvent_getKeyCode(evt) == AKEYCODE_BACK) {
  2754. gs_println("Android: back key pressed");
  2755. return false;
  2756. }
  2757. return false;
  2758. }
  2759. int32_t gs_android_input_cb(int32_t fd, int32_t events, void* data)
  2760. {
  2761. gs_android_t* android = (gs_android_t*)data;
  2762. gs_assert(android);
  2763. gs_assert(android->current.input);
  2764. if ((events & ALOOPER_EVENT_INPUT) == 0) {
  2765. gs_println("Android Main CB:Unsupported event: %zu", events);
  2766. return 1;
  2767. }
  2768. // Poll for all input events
  2769. AInputEvent* evt = NULL;
  2770. while (AInputQueue_getEvent(android->current.input, &evt) >= 0)
  2771. {
  2772. if (AInputQueue_preDispatchEvent(android->current.input, evt) != 0) {
  2773. continue;
  2774. }
  2775. // Register event with platform events
  2776. int32_t handled = 0;
  2777. if (gs_android_touch_event(evt) || gs_android_key_event(evt)) {
  2778. handled = 1;
  2779. }
  2780. // Finish events
  2781. AInputQueue_finishEvent(android->current.input, evt, handled);
  2782. }
  2783. return 1;
  2784. }
  2785. int32_t gs_android_main_cb(int32_t fd, int32_t events, void* data)
  2786. {
  2787. gs_android_t* android = (gs_android_t*)data;
  2788. gs_assert(android);
  2789. if ((events & ALOOPER_EVENT_INPUT) == 0) {
  2790. gs_println("Android Main CB:Unsupported event: %zu", events);
  2791. return 1;
  2792. }
  2793. gs_android_message_type msg;
  2794. if (read(fd, &msg, sizeof(msg)) != sizeof(msg)) {
  2795. gs_println("Could not write to read_from_main_fd");
  2796. return 1;
  2797. }
  2798. gs_platform_event_t gsevt = gs_default_val();
  2799. pthread_mutex_lock(&android->gt.mutex);
  2800. switch (msg)
  2801. {
  2802. case GS_ANDROID_MSG_CREATE: {
  2803. gs_println("MSG_CREATE");
  2804. android->state.has_created = true;
  2805. } break;
  2806. case GS_ANDROID_MSG_START: {
  2807. gs_println("MSG_START");
  2808. android->state.has_resumed = true;
  2809. if (gs_instance()) {
  2810. gsevt.type = GS_PLATFORM_EVENT_APP;
  2811. gsevt.app.action = GS_PLATFORM_APP_START;
  2812. gs_platform_add_event(&gsevt);
  2813. }
  2814. } break;
  2815. case GS_ANDROID_MSG_STOP: {
  2816. gs_println("MSG_STOP");
  2817. android->state.has_resumed = false;
  2818. if (gs_instance()) {
  2819. gsevt.type = GS_PLATFORM_EVENT_APP;
  2820. gsevt.app.action = GS_PLATFORM_APP_STOP;
  2821. gs_platform_add_event(&gsevt);
  2822. }
  2823. } break;
  2824. case GS_ANDROID_MSG_RESUME: {
  2825. gs_println("MSG_RESUME");
  2826. android->state.has_resumed = true;
  2827. if (gs_instance()) {
  2828. gsevt.type = GS_PLATFORM_EVENT_APP;
  2829. gsevt.app.action = GS_PLATFORM_APP_RESUME;
  2830. gs_platform_add_event(&gsevt);
  2831. }
  2832. } break;
  2833. case GS_ANDROID_MSG_PAUSE: {
  2834. gs_println("MSG_PAUSE");
  2835. android->state.has_resumed = false;
  2836. if (gs_instance()) {
  2837. gsevt.type = GS_PLATFORM_EVENT_APP;
  2838. gsevt.app.action = GS_PLATFORM_APP_PAUSE;
  2839. gs_platform_add_event(&gsevt);
  2840. }
  2841. } break;
  2842. case GS_ANDROID_MSG_GAIN_FOCUS: {
  2843. gs_println("MSG_GAIN_FOCUS");
  2844. android->state.has_focus = true;
  2845. if (gs_instance()) {
  2846. gsevt.type = GS_PLATFORM_EVENT_WINDOW;
  2847. gsevt.app.action = GS_PLATFORM_WINDOW_GAIN_FOCUS;
  2848. gs_platform_add_event(&gsevt);
  2849. }
  2850. } break;
  2851. case GS_ANDROID_MSG_LOSE_FOCUS: {
  2852. gs_println("MSG_NO_FOCUS");
  2853. android->state.has_focus = false;
  2854. if (gs_instance()) {
  2855. gsevt.type = GS_PLATFORM_EVENT_WINDOW;
  2856. gsevt.app.action = GS_PLATFORM_WINDOW_LOSE_FOCUS;
  2857. gs_platform_add_event(&gsevt);
  2858. }
  2859. } break;
  2860. case GS_ANDROID_MSG_SET_NATIVE_WINDOW:
  2861. {
  2862. if (!gs_instance()) {
  2863. gs_println("Creating engine...");
  2864. gs_app_desc_t app = gs_main(0, NULL);
  2865. app.android.activity = android;
  2866. app.android.internal_data_path = android->internal_data_path;
  2867. gs_create(app);
  2868. android->state.has_focus = true;
  2869. android->state.has_resumed = true;
  2870. }
  2871. else {
  2872. gs_println("MSG_SET_NATIVE_WINDOW");
  2873. if (android->current.window != android->pending.window) {
  2874. if (android->current.window != NULL) {
  2875. gs_android_destroy_egl_surface(android);
  2876. }
  2877. if (android->pending.window != NULL) {
  2878. gs_println("Creating egl surface ...");
  2879. if (gs_android_create_egl_surface(android, android->pending.window)) {
  2880. gs_println("... ok!");
  2881. gs_android_update_dimensions(android, android->pending.window, true);
  2882. } else {
  2883. gs_println("... failed!");
  2884. gs_quit();
  2885. }
  2886. }
  2887. }
  2888. }
  2889. android->current.window = android->pending.window;
  2890. } break;
  2891. case GS_ANDROID_MSG_SET_INPUT_QUEUE:
  2892. {
  2893. gs_println("MSG_SET_INPUT_QUEUE");
  2894. if (android->current.input != android->pending.input) {
  2895. if (android->current.input != NULL) {
  2896. AInputQueue_detachLooper(android->current.input);
  2897. }
  2898. if (android->pending.input != NULL) {
  2899. AInputQueue_attachLooper(
  2900. android->pending.input,
  2901. android->looper,
  2902. ALOOPER_POLL_CALLBACK,
  2903. gs_android_input_cb,
  2904. android); /* data */
  2905. }
  2906. }
  2907. android->current.input = android->pending.input;
  2908. } break;
  2909. case GS_ANDROID_MSG_DESTROY: {
  2910. gs_println("MSG_DESTROY");
  2911. if (gs_instance()) {
  2912. gsevt.type = GS_PLATFORM_EVENT_WINDOW;
  2913. gsevt.app.action = GS_PLATFORM_WINDOW_DESTROY;
  2914. gs_platform_add_event(&gsevt);
  2915. }
  2916. gs_quit();
  2917. } break;
  2918. default: {
  2919. gs_println("Unknown msg type received");
  2920. } break;
  2921. }
  2922. pthread_cond_broadcast(&android->gt.cond);
  2923. pthread_mutex_unlock(&android->gt.mutex);
  2924. return 1;
  2925. }
  2926. void gs_android_msg(gs_android_t* android, gs_android_message_type msg)
  2927. {
  2928. gs_assert(android);
  2929. if (write(android->gt.write_from_main_fd, &msg, sizeof(msg)) != sizeof(msg)) {
  2930. gs_println("Could not write to write_from_main_fd");
  2931. }
  2932. gs_println("Write message sucessfully");
  2933. }
  2934. void gs_android_msg_set_native_window(ANativeActivity* activity, ANativeWindow* window)
  2935. {
  2936. gs_android_t* android = (gs_android_t*)activity->instance;
  2937. gs_assert(android);
  2938. pthread_mutex_lock(&android->gt.mutex);
  2939. android->pending.window = window;
  2940. gs_android_msg(android, GS_ANDROID_MSG_SET_NATIVE_WINDOW);
  2941. // Spin until we set the appropriate window
  2942. while (android->current.window != window) {
  2943. pthread_cond_wait(&android->gt.cond, &android->gt.mutex);
  2944. }
  2945. pthread_mutex_unlock(&android->gt.mutex);
  2946. }
  2947. void gs_android_msg_set_input_queue(ANativeActivity* activity, AInputQueue* input)
  2948. {
  2949. gs_android_t* android = (gs_android_t*)activity->instance;
  2950. gs_assert(android);
  2951. pthread_mutex_lock(&android->gt.mutex);
  2952. android->pending.input = input;
  2953. gs_android_msg(android, GS_ANDROID_MSG_SET_INPUT_QUEUE);
  2954. while (android->current.input != input) {
  2955. pthread_cond_wait(&android->gt.cond, &android->gt.mutex);
  2956. }
  2957. pthread_mutex_unlock(&android->gt.mutex);
  2958. }
  2959. void gs_android_native_window_created_cb(ANativeActivity* activity, ANativeWindow* window)
  2960. {
  2961. gs_println("NativeActivity:onNativeWindowCreated()");
  2962. gs_android_msg_set_native_window(activity, window);
  2963. }
  2964. void gs_android_window_focus_change_cb(ANativeActivity* activity, int32_t has_focus)
  2965. {
  2966. gs_android_t* android = (gs_android_t*)activity->instance;
  2967. gs_assert(android);
  2968. gs_println("NativeActivity:onNativeWindowFocusChange()");
  2969. switch (has_focus) {
  2970. case false: gs_android_msg(android, GS_ANDROID_MSG_LOSE_FOCUS); break;
  2971. case true: gs_android_msg(android, GS_ANDROID_MSG_GAIN_FOCUS); break;
  2972. }
  2973. }
  2974. void gs_android_resume_cb(ANativeActivity* activity)
  2975. {
  2976. gs_android_t* android = (gs_android_t*)activity->instance;
  2977. gs_assert(android);
  2978. gs_println("NativeActivity:onNativeResume()");
  2979. gs_android_msg(android, GS_ANDROID_MSG_RESUME);
  2980. }
  2981. void gs_android_start_cb(ANativeActivity* activity)
  2982. {
  2983. gs_android_t* android = (gs_android_t*)activity->instance;
  2984. gs_assert(android);
  2985. gs_println("NativeActivity:onNativeStart()");
  2986. gs_android_msg(android, GS_ANDROID_MSG_START);
  2987. }
  2988. void gs_android_pause_cb(ANativeActivity* activity)
  2989. {
  2990. gs_android_t* android = (gs_android_t*)activity->instance;
  2991. gs_assert(android);
  2992. gs_println("NativeActivity:onNativePause()");
  2993. gs_android_msg(android, GS_ANDROID_MSG_PAUSE);
  2994. }
  2995. void gs_android_stop_cb(ANativeActivity* activity)
  2996. {
  2997. gs_android_t* android = (gs_android_t*)activity->instance;
  2998. gs_assert(android);
  2999. gs_println("NativeActivity:onNativeStop()");
  3000. gs_android_msg(android, GS_ANDROID_MSG_STOP);
  3001. }
  3002. void gs_android_input_queue_created_cb(ANativeActivity* activity, AInputQueue* queue)
  3003. {
  3004. gs_android_msg_set_input_queue(activity, queue);
  3005. }
  3006. void gs_android_destroy_cb(ANativeActivity* activity)
  3007. {
  3008. gs_android_t* android = (gs_android_t*)activity->instance;
  3009. gs_assert(android);
  3010. gs_println("NativeActivity:onNativeDestroy()");
  3011. gs_android_msg(android, GS_ANDROID_MSG_DESTROY);
  3012. }
  3013. void gs_android_low_memory_cb(ANativeActivity* activity)
  3014. {
  3015. gs_println("NativeActivity:onLowMemory()");
  3016. }
  3017. void gs_android_config_changed_cb(ANativeActivity* activity)
  3018. {
  3019. gs_println("NativeActivity:onConfigurationChanged()");
  3020. }
  3021. GS_API_DECL void* gs_android_loop(void* arg)
  3022. {
  3023. gs_println("main loop");
  3024. gs_android_t* android = (gs_android_t*)arg;
  3025. gs_assert(android);
  3026. // Set up callback for polling events
  3027. android->looper = ALooper_prepare(0);
  3028. ALooper_addFd(android->looper, android->gt.read_from_main_fd, ALOOPER_POLL_CALLBACK, ALOOPER_EVENT_INPUT, gs_android_main_cb, android);
  3029. // Signal to start main thread
  3030. pthread_mutex_lock(&android->gt.mutex);
  3031. android->gt.is_thread_started = true;
  3032. pthread_cond_broadcast(&android->gt.cond);
  3033. pthread_mutex_unlock(&android->gt.mutex);
  3034. // Main application loop
  3035. while (!android->gt.is_thread_stopping)
  3036. {
  3037. if (gs_android_should_update(android)) {
  3038. gs_frame();
  3039. }
  3040. // Process all window/input events as they occur
  3041. bool process = true;
  3042. while (process && !android->gt.is_thread_stopping) {
  3043. bool block_until_evt = !android->gt.is_thread_stopping && !gs_android_should_update(android);
  3044. process = ALooper_pollOnce(block_until_evt ? -1 : 0, NULL, NULL, NULL) == ALOOPER_POLL_CALLBACK;
  3045. }
  3046. }
  3047. // Cleanup thread after done
  3048. if (android->current.input != NULL) {
  3049. AInputQueue_detachLooper(android->current.input);
  3050. }
  3051. pthread_mutex_lock(&android->gt.mutex);
  3052. android->gt.is_thread_stopped = true;
  3053. pthread_cond_broadcast(&android->gt.cond);
  3054. pthread_mutex_unlock(&android->gt.mutex);
  3055. gs_println("Android:Thread cleanup done.");
  3056. return NULL;
  3057. }
  3058. JNIEXPORT
  3059. void ANativeActivity_onCreate(ANativeActivity* activity, void* saved_state, size_t saved_state_size)
  3060. {
  3061. // Construct application instance and store in activity
  3062. activity->instance = gs_malloc_init(gs_android_t);
  3063. gs_android_t* android = (gs_android_t*)activity->instance;
  3064. gs_assert(android);
  3065. // Store internal data path
  3066. gs_println("internal data path: %s", activity->internalDataPath);
  3067. android->internal_data_path = activity->internalDataPath;
  3068. int32_t pfd[2];
  3069. if (pipe(pfd) != 0) {
  3070. gs_println("Error:ANativeActivity_onCreate:Could not create thread pipe.");
  3071. return;
  3072. }
  3073. android->gt.read_from_main_fd = pfd[0];
  3074. android->gt.write_from_main_fd = pfd[1];
  3075. pthread_mutex_init(&android->gt.mutex, NULL);
  3076. pthread_cond_init(&android->gt.cond, NULL);
  3077. pthread_attr_t attr;
  3078. pthread_attr_init(&attr);
  3079. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  3080. gs_println("detach state");
  3081. pthread_create(&android->gt.thread, &attr, gs_android_loop, android);
  3082. gs_println("create pthread");
  3083. pthread_attr_destroy(&attr);
  3084. gs_println("destroy attribute");
  3085. // Wait until main loop has started
  3086. pthread_mutex_lock(&android->gt.mutex);
  3087. while (!android->gt.is_thread_started) {
  3088. pthread_cond_wait(&android->gt.cond, &android->gt.mutex);
  3089. }
  3090. pthread_mutex_unlock(&android->gt.mutex);
  3091. // Send create message
  3092. pthread_mutex_lock(&android->gt.mutex);
  3093. gs_android_msg(android, GS_ANDROID_MSG_CREATE);
  3094. while (!android->state.has_created) {
  3095. pthread_cond_wait(&android->gt.cond, &android->gt.mutex);
  3096. }
  3097. pthread_mutex_unlock(&android->gt.mutex);
  3098. // Register all callbacks
  3099. activity->callbacks->onStart = gs_android_stop_cb;
  3100. activity->callbacks->onResume = gs_android_resume_cb;
  3101. activity->callbacks->onPause = gs_android_pause_cb;
  3102. activity->callbacks->onStop = gs_android_stop_cb;
  3103. activity->callbacks->onDestroy = gs_android_destroy_cb;
  3104. // activity->callbacks->onSaveInstanceState = _sapp_android_on_save_instance_state;
  3105. activity->callbacks->onNativeWindowCreated = gs_android_native_window_created_cb;
  3106. activity->callbacks->onWindowFocusChanged = gs_android_window_focus_change_cb;
  3107. // /* activity->callbacks->onNativeWindowResized = _sapp_android_on_native_window_resized; */
  3108. // /* activity->callbacks->onNativeWindowRedrawNeeded = _sapp_android_on_native_window_redraw_needed; */
  3109. // activity->callbacks->onNativeWindowDestroyed = _sapp_android_on_native_window_destroyed;
  3110. activity->callbacks->onInputQueueCreated = gs_android_input_queue_created_cb;
  3111. // activity->callbacks->onInputQueueDestroyed = _sapp_android_on_input_queue_destroyed;
  3112. // /* activity->callbacks->onContentRectChanged = _sapp_android_on_content_rect_changed; */
  3113. activity->callbacks->onConfigurationChanged = gs_android_config_changed_cb;
  3114. activity->callbacks->onLowMemory = gs_android_low_memory_cb;
  3115. gs_println("NativeActivity successfully created");
  3116. }
  3117. GS_API_DECL void
  3118. gs_platform_init(gs_platform_t* platform)
  3119. {
  3120. // Get from application platform data
  3121. gs_android_t* android = (gs_android_t*)gs_app()->android.activity;
  3122. gs_assert(android);
  3123. gs_app_desc_t* app = gs_app();
  3124. platform->user_data = android;
  3125. gs_println("Android: Init platform");
  3126. gs_android_init_egl(platform->user_data);
  3127. gs_println("Creating egl surface ...");
  3128. if (gs_android_create_egl_surface(android, android->pending.window)) {
  3129. gs_println("... ok!");
  3130. gs_android_update_dimensions(android, android->pending.window, true);
  3131. } else {
  3132. gs_println("... failed!");
  3133. // _sapp_android_shutdown();
  3134. }
  3135. }
  3136. GS_API_DECL void
  3137. gs_platform_shutdown(gs_platform_t* platform)
  3138. {
  3139. gs_android_shutdown(platform->user_data);
  3140. }
  3141. // Platform Util
  3142. GS_API_DECL double
  3143. gs_platform_elapsed_time()
  3144. {
  3145. gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
  3146. return ((double)clock() / (double)CLOCKS_PER_SEC) * 1000.0;
  3147. }
  3148. GS_API_DECL void
  3149. gs_platform_sleep(float ms)
  3150. {
  3151. usleep(ms * 1000.f);
  3152. }
  3153. // Platform Video
  3154. GS_API_DECL void
  3155. gs_platform_enable_vsync(int32_t enabled)
  3156. {
  3157. }
  3158. // Platform Input
  3159. GS_API_DECL void
  3160. gs_platform_process_input(gs_platform_input_t* input)
  3161. {
  3162. }
  3163. GS_API_DECL uint32_t
  3164. gs_platform_key_to_codepoint(gs_platform_keycode code)
  3165. {
  3166. return 0;
  3167. }
  3168. GS_API_DECL gs_platform_keycode
  3169. gs_platform_codepoint_to_key(uint32_t code)
  3170. {
  3171. return GS_KEYCODE_INVALID;
  3172. }
  3173. GS_API_DECL void
  3174. gs_platform_mouse_set_position(uint32_t handle, float x, float y)
  3175. {
  3176. }
  3177. GS_API_DECL void
  3178. gs_platform_lock_mouse(uint32_t handle, bool32_t lock)
  3179. {
  3180. }
  3181. GS_API_DECL gs_platform_window_t
  3182. gs_platform_window_create_internal(const gs_platform_window_desc_t* desc)
  3183. {
  3184. // Nothing for now, since we just create this internally...
  3185. gs_platform_window_t win = gs_default_val();
  3186. return win;
  3187. }
  3188. GS_API_DECL void
  3189. gs_platform_window_swap_buffer(uint32_t handle)
  3190. {
  3191. gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
  3192. if (gs_android_should_update(android)) {
  3193. eglSwapBuffers(android->egl.display, android->egl.surface);
  3194. }
  3195. }
  3196. GS_API_DECL gs_vec2
  3197. gs_platform_window_sizev(uint32_t handle)
  3198. {
  3199. gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
  3200. return gs_v2(android->egl.width, android->egl.height);
  3201. }
  3202. GS_API_DECL void
  3203. gs_platform_window_size(uint32_t handle, uint32_t* width, uint32_t* height)
  3204. {
  3205. gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
  3206. *width = android->egl.width;
  3207. *height = android->egl.height;
  3208. }
  3209. GS_API_DECL uint32_t
  3210. gs_platform_window_width(uint32_t handle)
  3211. {
  3212. gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
  3213. return android->egl.width;
  3214. }
  3215. GS_API_DECL uint32_t
  3216. gs_platform_window_height(uint32_t handle)
  3217. {
  3218. gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
  3219. return android->egl.height;
  3220. }
  3221. GS_API_DECL bool32_t
  3222. gs_platform_window_fullscreen(uint32_t handle)
  3223. {
  3224. return false;
  3225. }
  3226. GS_API_DECL void
  3227. gs_platform_window_position(uint32_t handle, uint32_t* x, uint32_t* y)
  3228. {
  3229. }
  3230. GS_API_DECL gs_vec2
  3231. gs_platform_window_positionv(uint32_t handle)
  3232. {
  3233. return gs_v2(0, 0);
  3234. }
  3235. GS_API_DECL void
  3236. gs_platform_set_window_size(uint32_t handle, uint32_t width, uint32_t height)
  3237. {
  3238. }
  3239. GS_API_DECL void
  3240. gs_platform_set_window_sizev(uint32_t handle, gs_vec2 v)
  3241. {
  3242. }
  3243. GS_API_DECL void
  3244. gs_platform_set_window_fullscreen(uint32_t handle, bool32_t fullscreen)
  3245. {
  3246. }
  3247. GS_API_DECL void
  3248. gs_platform_set_window_position(uint32_t handle, uint32_t x, uint32_t y)
  3249. {
  3250. }
  3251. GS_API_DECL void
  3252. gs_platform_set_window_positionv(uint32_t handle, gs_vec2 v)
  3253. {
  3254. }
  3255. GS_API_DECL void
  3256. gs_platform_set_cursor(uint32_t handle, gs_platform_cursor cursor)
  3257. {
  3258. }
  3259. GS_API_DECL void
  3260. gs_platform_set_dropped_files_callback(uint32_t handle, gs_dropped_files_callback_t cb)
  3261. {
  3262. }
  3263. GS_API_DECL void
  3264. gs_platform_set_window_close_callback(uint32_t handle, gs_window_close_callback_t cb)
  3265. {
  3266. }
  3267. GS_API_DECL void
  3268. gs_platform_set_character_callback(uint32_t handle, gs_character_callback_t cb)
  3269. {
  3270. }
  3271. GS_API_DECL void*
  3272. gs_platform_raw_window_handle(uint32_t handle)
  3273. {
  3274. }
  3275. GS_API_DECL gs_vec2
  3276. gs_platform_framebuffer_sizev(uint32_t handle)
  3277. {
  3278. gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
  3279. return gs_v2(android->egl.fbwidth, android->egl.fbheight);
  3280. }
  3281. GS_API_DECL void
  3282. gs_platform_framebuffer_size(uint32_t handle, uint32_t* w, uint32_t* h)
  3283. {
  3284. gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
  3285. *w = android->egl.fbwidth;
  3286. *h = android->egl.fbheight;
  3287. }
  3288. GS_API_DECL uint32_t
  3289. gs_platform_framebuffer_width(uint32_t handle)
  3290. {
  3291. gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
  3292. return android->egl.fbwidth;
  3293. }
  3294. GS_API_DECL uint32_t
  3295. gs_platform_framebuffer_height(uint32_t handle)
  3296. {
  3297. gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
  3298. return android->egl.fbheight;
  3299. }
  3300. #undef GS_PLATFORM_IMPL_ANDROID
  3301. #endif // GS_PLATFORM_IMPL_ANDROID
  3302. #endif // __GS_PLATFORM_IMPL_H__