| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841 |
- /*==============================================================================================================
- * Copyright (c) 2020 John Jackson
- * File: gs_platform_impl.h
- * Github: https://github.com/MrFrenik/gunslinger
- * All Rights Reserved
- * MIT License
- * May all those that this source may reach be blessed by the LORD and find peace and joy in life.
- * Everyone who drinks of this water will be thirsty again; but whoever drinks of the water
- * that I will give him shall never thirst; John 4:13-14
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
- * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
- * The above copyright, blessing, biblical verse, notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
- * TO THE WARRANTIES OF MECHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
-
- =================================================================================================================*/
- #ifndef GS_PLATFORM_IMPL_H
- #define GS_PLATFORM_IMPL_H
- /*=================================
- // Default Platform Implemenattion
- =================================*/
- // Define default platform implementation if certain platforms are enabled
- #if (!defined GS_PLATFORM_IMPL_NO_DEFAULT)
- #define GS_PLATFORM_IMPL_DEFAULT
- #endif
- /*=============================
- // Default Impl
- =============================*/
- #ifdef GS_PLATFORM_IMPL_DEFAULT
- #if !(defined GS_PLATFORM_WIN)
- #include <sys/stat.h>
- #include <dirent.h>
- #include <dlfcn.h> // dlopen, RTLD_LAZY, dlsym
- #else
- #include "../external/dirent/dirent.h"
- #include <direct.h>
- #endif
- /*== Platform Window ==*/
- GS_API_DECL gs_platform_t*
- gs_platform_create()
- {
- // Construct new platform interface
- gs_platform_t* platform = gs_malloc_init(gs_platform_t);
- // Initialize windows
- platform->windows = gs_slot_array_new(gs_platform_window_t);
- // Set up video mode (for now, just do opengl)
- platform->settings.video.driver = GS_PLATFORM_VIDEO_DRIVER_TYPE_OPENGL;
- return platform;
- }
- GS_API_DECL void
- gs_platform_destroy(gs_platform_t* platform)
- {
- if (platform == NULL) return;
- // Free all resources
- gs_slot_array_free(platform->windows);
- // Free platform
- gs_free(platform);
- platform = NULL;
- }
- GS_API_DECL uint32_t
- gs_platform_window_create(const gs_platform_window_desc_t* desc)
- {
- gs_assert(gs_instance() != NULL);
- gs_platform_t* platform = gs_subsystem(platform);
- gs_platform_window_t win = gs_platform_window_create_internal(desc);
- // Insert and return handle
- return (gs_slot_array_insert(platform->windows, win));
- }
- GS_API_DECL uint32_t
- gs_platform_main_window()
- {
- // Should be the first element of the slot array...Great assumption to make.
- return 0;
- }
- /*== Platform Time ==*/
- GS_API_DECL const
- gs_platform_time_t* gs_platform_time()
- {
- return &gs_subsystem(platform)->time;
- }
- GS_API_DECL float
- gs_platform_delta_time()
- {
- return gs_platform_time()->delta;
- }
- GS_API_DECL float
- gs_platform_frame_time()
- {
- return gs_platform_time()->frame;
- }
- /*== Platform UUID ==*/
- GS_API_DECL struct gs_uuid_t
- gs_platform_uuid_generate()
- {
- gs_uuid_t uuid;
- srand(clock());
- char guid[40];
- int32_t t = 0;
- const char* sz_temp = "xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx";
- const char* sz_hex = "0123456789abcdef-";
- int32_t n_len = (int32_t)strlen(sz_temp);
- for (t=0; t < n_len + 1; t++)
- {
- int32_t r = rand () % 16;
- char c = ' ';
- switch (sz_temp[t])
- {
- case 'x' : { c = sz_hex [r]; } break;
- case 'y' : { c = sz_hex [(r & 0x03) | 0x08]; } break;
- case '-' : { c = '-'; } break;
- case '4' : { c = '4'; } break;
- }
- guid[t] = (t < n_len) ? c : 0x00;
- }
- // Convert to uuid bytes from string
- const char* hex_string = guid, *pos = hex_string;
- /* WARNING: no sanitization or error-checking whatsoever */
- for (size_t count = 0; count < 16; count++)
- {
- sscanf(pos, "%2hhx", &uuid.bytes[count]);
- pos += 2;
- }
- return uuid;
- }
- // Mutable temp buffer 'tmp_buffer'
- GS_API_DECL void
- gs_platform_uuid_to_string(char* tmp_buffer, const gs_uuid_t* uuid)
- {
- gs_snprintf
- (
- tmp_buffer,
- 32,
- "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
- uuid->bytes[0],
- uuid->bytes[1],
- uuid->bytes[2],
- uuid->bytes[3],
- uuid->bytes[4],
- uuid->bytes[5],
- uuid->bytes[6],
- uuid->bytes[7],
- uuid->bytes[8],
- uuid->bytes[9],
- uuid->bytes[10],
- uuid->bytes[11],
- uuid->bytes[12],
- uuid->bytes[13],
- uuid->bytes[14],
- uuid->bytes[15]
- );
- }
- uint32_t gs_platform_uuid_hash(const gs_uuid_t* uuid)
- {
- char temp_buffer[] = gs_uuid_temp_str_buffer();
- gs_platform_uuid_to_string(temp_buffer, uuid);
- return (gs_hash_str(temp_buffer));
- }
- #define __gs_input()\
- (&gs_subsystem(platform)->input)
- /*=== Platform Input ===*/
- GS_API_DECL gs_platform_input_t* gs_platform_input()
- {
- return &gs_subsystem(platform)->input;
- }
- void gs_platform_update_input(gs_platform_input_t* input)
- {
- // Update all input and mouse keys from previous frame
- // Previous key presses
- gs_for_range_i(GS_KEYCODE_COUNT) {
- input->prev_key_map[i] = input->key_map[i];
- }
- // Previous mouse button presses
- gs_for_range_i(GS_MOUSE_BUTTON_CODE_COUNT) {
- input->mouse.prev_button_map[i] = input->mouse.button_map[i];
- }
- input->mouse.wheel = gs_v2s(0.0f);
- input->mouse.delta = gs_v2s(0.f);
- input->mouse.moved_this_frame = false;
- // Update all touch deltas
- for (uint32_t i = 0; i < GS_PLATFORM_MAX_TOUCH; ++i) {
- input->touch.points[i].delta = gs_v2s(0.f);
- input->touch.points[i].down = input->touch.points[i].pressed;
- }
- }
- void gs_platform_poll_all_events()
- {
- gs_platform_t* platform = gs_subsystem(platform);
-
- platform->input.mouse.delta.x = 0;
- platform->input.mouse.delta.y = 0;
- // Iterate through events, don't consume
- gs_platform_event_t evt = gs_default_val();
- while (gs_platform_poll_events(&evt, false))
- {
- switch (evt.type)
- {
- case GS_PLATFORM_EVENT_MOUSE:
- {
- switch (evt.mouse.action)
- {
- case GS_PLATFORM_MOUSE_MOVE:
- {
- // If locked, then movement amount will be applied to delta,
- // otherwise set position
- if (gs_platform_mouse_locked()) {
- platform->input.mouse.delta = gs_vec2_add(platform->input.mouse.delta, evt.mouse.move);
- } else {
- platform->input.mouse.delta = gs_vec2_sub(evt.mouse.move, platform->input.mouse.position);
- platform->input.mouse.position = evt.mouse.move;
- }
- } break;
- case GS_PLATFORM_MOUSE_WHEEL:
- {
- platform->input.mouse.wheel = evt.mouse.wheel;
- } break;
- case GS_PLATFORM_MOUSE_BUTTON_PRESSED:
- {
- gs_platform_press_mouse_button(evt.mouse.button);
- } break;
- case GS_PLATFORM_MOUSE_BUTTON_RELEASED:
- {
- gs_platform_release_mouse_button(evt.mouse.button);
- } break;
- case GS_PLATFORM_MOUSE_BUTTON_DOWN:
- {
- gs_platform_press_mouse_button(evt.mouse.button);
- } break;
- case GS_PLATFORM_MOUSE_ENTER:
- {
- // If there are user callbacks, could trigger them here
- } break;
- case GS_PLATFORM_MOUSE_LEAVE:
- {
- // If there are user callbacks, could trigger them here
- } break;
- }
- } break;
- case GS_PLATFORM_EVENT_KEY:
- {
- switch (evt.key.action)
- {
- case GS_PLATFORM_KEY_PRESSED:
- {
- gs_platform_press_key(evt.key.keycode);
- } break;
- case GS_PLATFORM_KEY_DOWN:
- {
- gs_platform_press_key(evt.key.keycode);
- } break;
- case GS_PLATFORM_KEY_RELEASED:
- {
- gs_platform_release_key(evt.key.keycode);
- } break;
- }
- } break;
- case GS_PLATFORM_EVENT_WINDOW:
- {
- switch (evt.window.action)
- {
- default: break;
- }
- } break;
- case GS_PLATFORM_EVENT_TOUCH:
- {
- gs_platform_point_event_data_t* point = &evt.touch.point;
- switch (evt.touch.action)
- {
- case GS_PLATFORM_TOUCH_DOWN:
- {
- uintptr_t id = point->id;
- gs_vec2 *pos = &point->position;
- gs_vec2 *p = &platform->input.touch.points[id].position;
- gs_vec2 *d = &platform->input.touch.points[id].delta;
- gs_platform_press_touch(id);
- *p = *pos;
- gs_subsystem(platform)->input.touch.size++;
- } break;
- case GS_PLATFORM_TOUCH_UP:
- {
- uintptr_t id = point->id;
- gs_println("Releasing ID: %zu", id);
- gs_platform_release_touch(id);
- gs_subsystem(platform)->input.touch.size--;
- } break;
- case GS_PLATFORM_TOUCH_MOVE:
- {
- uintptr_t id = point->id;
- gs_vec2* pos = &point->position;
- gs_vec2* p = &platform->input.touch.points[id].position;
- gs_vec2* d = &platform->input.touch.points[id].delta;
- gs_platform_press_touch(id); // Not sure if this is causing issues...
- *d = gs_vec2_sub(*pos, *p);
- *p = *pos;
- } break;
- case GS_PLATFORM_TOUCH_CANCEL:
- {
- uintptr_t id = point->id;
- gs_platform_release_touch(id);
- gs_subsystem(platform)->input.touch.size--;
- } break;
- }
- } break;
- default: break;
- }
- }
- }
- void gs_platform_update(gs_platform_t* platform)
- {
- // Update platform input from previous frame
- gs_platform_update_input(&platform->input);
- // Process input for this frame (user dependent update)
- gs_platform_process_input(&platform->input);
- // Poll all events
- gs_platform_poll_all_events();
- gs_platform_update_internal(platform);
- }
- bool gs_platform_poll_events(gs_platform_event_t* evt, bool32_t consume)
- {
- gs_platform_t* platform = gs_subsystem(platform);
- if (!evt) return false;
- if (gs_dyn_array_empty(platform->events)) return false;
- if (evt->idx >= gs_dyn_array_size(platform->events)) return false;
- if (consume) {
- // Back event
- *evt = gs_dyn_array_back(platform->events);
- // Pop back
- gs_dyn_array_pop(platform->events);
- }
- else {
- uint32_t idx = evt->idx;
- *evt = platform->events[idx++];
- evt->idx = idx;
- }
- return true;
- }
- void gs_platform_add_event(gs_platform_event_t* evt)
- {
- gs_platform_t* platform = gs_subsystem(platform);
- if (!evt) return;
- gs_dyn_array_push(platform->events, *evt);
- }
- bool gs_platform_was_key_down(gs_platform_keycode code)
- {
- gs_platform_input_t* input = __gs_input();
- return (input->prev_key_map[code]);
- }
- bool gs_platform_key_down(gs_platform_keycode code)
- {
- gs_platform_input_t* input = __gs_input();
- return (input->key_map[code]);
- }
- bool gs_platform_key_pressed(gs_platform_keycode code)
- {
- gs_platform_input_t* input = __gs_input();
- return (gs_platform_key_down(code) && !gs_platform_was_key_down(code));
- }
- bool gs_platform_key_released(gs_platform_keycode code)
- {
- gs_platform_input_t* input = __gs_input();
- return (gs_platform_was_key_down(code) && !gs_platform_key_down(code));
- }
- bool gs_platform_touch_down(uint32_t idx)
- {
- gs_platform_input_t* input = __gs_input();
- if (idx < GS_PLATFORM_MAX_TOUCH) {
- return input->touch.points[idx].pressed;
- }
- return false;
- }
- bool gs_platform_touch_pressed(uint32_t idx)
- {
- gs_platform_input_t* input = __gs_input();
- if (idx < GS_PLATFORM_MAX_TOUCH) {
- return (gs_platform_was_touch_down(idx) && !gs_platform_touch_down(idx));
- }
- return false;
- }
- bool gs_platform_touch_released(uint32_t idx)
- {
- gs_platform_input_t* input = __gs_input();
- if (idx < GS_PLATFORM_MAX_TOUCH) {
- return (gs_platform_was_touch_down(idx) && !gs_platform_touch_down(idx));
- }
- return false;
- }
- bool gs_platform_was_mouse_down(gs_platform_mouse_button_code code)
- {
- gs_platform_input_t* input = __gs_input();
- return (input->mouse.prev_button_map[code]);
- }
- void gs_platform_press_mouse_button(gs_platform_mouse_button_code code)
- {
- gs_platform_input_t* input = __gs_input();
- if ((u32)code < (u32)GS_MOUSE_BUTTON_CODE_COUNT)
- {
- input->mouse.button_map[code] = true;
- }
- }
- void gs_platform_release_mouse_button(gs_platform_mouse_button_code code)
- {
- gs_platform_input_t* input = __gs_input();
- if ((u32)code < (u32)GS_MOUSE_BUTTON_CODE_COUNT)
- {
- input->mouse.button_map[code] = false;
- }
- }
- bool gs_platform_mouse_down(gs_platform_mouse_button_code code)
- {
- gs_platform_input_t* input = __gs_input();
- return (input->mouse.button_map[code]);
- }
- bool gs_platform_mouse_pressed(gs_platform_mouse_button_code code)
- {
- gs_platform_input_t* input = __gs_input();
- if (gs_platform_mouse_down(code) && !gs_platform_was_mouse_down(code))
- {
- return true;
- }
- return false;
- }
- bool gs_platform_mouse_released(gs_platform_mouse_button_code code)
- {
- gs_platform_input_t* input = __gs_input();
- return (gs_platform_was_mouse_down(code) && !gs_platform_mouse_down(code));
- }
- bool gs_platform_mouse_moved()
- {
- gs_platform_input_t* input = __gs_input();
- return (input->mouse.delta.x != 0.f || input->mouse.delta.y != 0.f);
- }
- void gs_platform_mouse_delta(float* x, float* y)
- {
- gs_platform_input_t* input = __gs_input();
- *x = input->mouse.delta.x;
- *y = input->mouse.delta.y;
- }
- gs_vec2 gs_platform_mouse_deltav()
- {
- gs_platform_input_t* input = __gs_input();
- gs_vec2 delta = gs_default_val();
- gs_platform_mouse_delta(&delta.x, &delta.y);
- return delta;
- }
- gs_vec2 gs_platform_mouse_positionv()
- {
- gs_platform_input_t* input = __gs_input();
- return gs_v2(
- input->mouse.position.x,
- input->mouse.position.y
- );
- }
- void gs_platform_mouse_position(int32_t* x, int32_t* y)
- {
- gs_platform_input_t* input = __gs_input();
- *x = (int32_t)input->mouse.position.x;
- *y = (int32_t)input->mouse.position.y;
- }
- void gs_platform_mouse_wheel(f32* x, f32* y)
- {
- gs_platform_input_t* input = __gs_input();
- *x = input->mouse.wheel.x;
- *y = input->mouse.wheel.y;
- }
- GS_API_DECL gs_vec2 gs_platform_mouse_wheelv()
- {
- gs_vec2 wheel = gs_default_val();
- gs_platform_mouse_wheel(&wheel.x, &wheel.y);
- return wheel;
- }
- bool gs_platform_mouse_locked()
- {
- return (__gs_input())->mouse.locked;
- }
- void gs_platform_touch_delta(uint32_t idx, float* x, float* y)
- {
- gs_platform_input_t* input = __gs_input();
- if (idx < GS_PLATFORM_MAX_TOUCH) {
- *x = input->touch.points[idx].delta.x;
- *y = input->touch.points[idx].delta.y;
- }
- }
- gs_vec2 gs_platform_touch_deltav(uint32_t idx)
- {
- gs_vec2 delta = gs_v2s(0.f);
- gs_platform_touch_delta(idx, &delta.x, &delta.y);
- return delta;
- }
- void gs_platform_touch_position(uint32_t idx, float* x, float* y)
- {
- gs_platform_input_t* input = __gs_input();
- if (idx < GS_PLATFORM_MAX_TOUCH) {
- *x = input->touch.points[idx].position.x;
- *y = input->touch.points[idx].position.y;
- }
- }
- gs_vec2 gs_platform_touch_positionv(uint32_t idx)
- {
- gs_vec2 p = gs_default_val();
- gs_platform_touch_position(idx, &p.x, &p.y);
- return p;
- }
- void gs_platform_press_touch(uint32_t idx)
- {
- gs_platform_input_t* input = __gs_input();
- if (idx < GS_PLATFORM_MAX_TOUCH) {
- input->touch.points[idx].pressed = true;
- }
- }
- void gs_platform_release_touch(uint32_t idx)
- {
- gs_platform_input_t* input = __gs_input();
- if (idx < GS_PLATFORM_MAX_TOUCH) {
- gs_println("releasing: %zu", idx);
- input->touch.points[idx].pressed = false;
- }
- }
- bool gs_platform_was_touch_down(uint32_t idx)
- {
- gs_platform_input_t* input = __gs_input();
- if (idx < GS_PLATFORM_MAX_TOUCH) {
- return input->touch.points[idx].down;
- }
- return false;
- }
- void gs_platform_press_key(gs_platform_keycode code)
- {
- gs_platform_input_t* input = __gs_input();
- if (code < GS_KEYCODE_COUNT) {
- input->key_map[code] = true;
- }
- }
- void gs_platform_release_key(gs_platform_keycode code)
- {
- gs_platform_input_t* input = __gs_input();
- if (code < GS_KEYCODE_COUNT) {
- input->key_map[code] = false;
- }
- }
- // Platform File IO
- char* gs_platform_read_file_contents_default_impl(const char* file_path, const char* mode, size_t* sz)
- {
- const char* path = file_path;
- #ifdef GS_PLATFORM_ANDROID
- const char* internal_data_path = gs_app()->android.internal_data_path;
- gs_snprintfc(tmp_path, 1024, "%s/%s", internal_data_path, file_path);
- path = tmp_path;
- #endif
- char* buffer = 0;
- FILE* fp = fopen(path, mode);
- size_t read_sz = 0;
- if (fp)
- {
- read_sz = gs_platform_file_size_in_bytes(file_path);
- buffer = (char*)gs_malloc(read_sz + 1);
- if (buffer) {
- size_t _r = fread(buffer, 1, read_sz, fp);
- }
- buffer[read_sz] = '\0';
- fclose(fp);
- if (sz) *sz = read_sz;
- }
- return buffer;
- }
- gs_result gs_platform_write_file_contents_default_impl(const char* file_path, const char* mode, void* data, size_t sz)
- {
- const char* path = file_path;
- #ifdef GS_PLATFORM_ANDROID
- const char* internal_data_path = gs_app()->android.internal_data_path;
- gs_snprintfc(tmp_path, 1024, "%s/%s", internal_data_path, file_path);
- path = tmp_path;
- #endif
- FILE* fp = fopen(path, mode);
- if (fp)
- {
- size_t ret = fwrite(data, sizeof(uint8_t), sz, fp);
- if (ret == sz)
- {
- fclose(fp);
- return GS_RESULT_SUCCESS;
- }
- fclose(fp);
- }
- return GS_RESULT_FAILURE;
- }
- GS_API_DECL bool gs_platform_dir_exists_default_impl(const char* dir_path)
- {
- DIR* dir = opendir(dir_path);
- if (dir)
- {
- closedir(dir);
- return true;
- }
- return false;
- }
- GS_API_DECL int32_t gs_platform_mkdir_default_impl(const char* dir_path, int32_t opt)
- {
- #if defined(__MINGW32__) || defined(_MSC_VER)
- return mkdir(dir_path);
- #else
- return mkdir(dir_path, opt);
- #endif
- }
- bool gs_platform_file_exists_default_impl(const char* file_path)
- {
- const char* path = file_path;
- #ifdef GS_PLATFORM_ANDROID
- const char* internal_data_path = gs_app()->android.internal_data_path;
- gs_snprintfc(tmp_path, 1024, "%s/%s", internal_data_path, file_path);
- path = tmp_path;
- #endif
- FILE* fp = fopen(path, "r");
- if (fp) {
- fclose(fp);
- return true;
- }
- return false;
- }
- int32_t gs_platform_file_size_in_bytes_default_impl(const char* file_path)
- {
- #ifdef GS_PLATFORM_WIN
- HANDLE hFile = CreateFile(file_path, GENERIC_READ,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile==INVALID_HANDLE_VALUE)
- return -1; // error condition, could call GetLastError to find out more
- LARGE_INTEGER size;
- if (!GetFileSizeEx(hFile, &size))
- {
- CloseHandle(hFile);
- return -1; // error condition, could call GetLastError to find out more
- }
- CloseHandle(hFile);
- return gs_util_safe_truncate_u64(size.QuadPart);
- #elif (defined GS_PLATFORM_ANDROID)
- const char* internal_data_path = gs_app()->android.internal_data_path;
- gs_snprintfc(tmp_path, 1024, "%s/%s", internal_data_path, file_path);
- struct stat st;
- stat(tmp_path, &st);
- return (int32_t)st.st_size;
- #else
- struct stat st;
- stat(file_path, &st);
- return (int32_t)st.st_size;
- #endif
- }
- void gs_platform_file_extension_default_impl(char* buffer, size_t buffer_sz, const char* file_path)
- {
- gs_util_get_file_extension(buffer, buffer_sz, file_path);
- }
- GS_API_DECL int32_t
- gs_platform_file_delete_default_impl(const char* file_path)
- {
- #if (defined GS_PLATFORM_WIN)
- // Non-zero if successful
- return DeleteFile(file_path);
- #elif (defined GS_PLATFORM_LINUX || defined GS_PLATFORM_APPLE || defined GS_PLATFORM_ANDROID)
- // Returns 0 if successful
- return !remove(file_path);
- #endif
- return 0;
- }
- GS_API_DECL int32_t
- gs_platform_file_copy_default_impl(const char* src_path, const char* dst_path)
- {
- #if (defined GS_PLATFORM_WIN)
- return CopyFile(src_path, dst_path, false);
- #elif (defined GS_PLATFORM_LINUX || defined GS_PLATFORM_APPLE || defined GS_PLATFORM_ANDROID)
- FILE* file_w = NULL;
- FILE* file_r = NULL;
- char buffer[2048] = gs_default_val();
- if ((file_w = fopen(src_path, "wb")) == NULL) {
- return 0;
- }
- if ((file_r = fopen(dst_path, "rb")) == NULL) {
- return 0;
- }
- // Read file in 2kb chunks to write to location
- int32_t len = 0;
- while ((len = fread(buffer, sizeof(buffer), 1, file_r)) > 0) {
- fwrite(buffer, len, 1, file_w);
- }
- // Close both files
- fclose(file_r);
- fclose(file_w);
- #endif
- return 0;
- }
- GS_API_DECL int32_t
- gs_platform_file_compare_time(uint64_t time_a, uint64_t time_b)
- {
- return time_a < time_b ? -1 : time_a == time_b ? 0 : 1;
- }
- GS_API_DECL gs_platform_file_stats_t
- gs_platform_file_stats(const char* file_path)
- {
- gs_platform_file_stats_t stats = gs_default_val();
- #if (defined GS_PLATFORM_WIN)
-
- WIN32_FILE_ATTRIBUTE_DATA data = gs_default_val();
- FILETIME ftime = gs_default_val();
- FILETIME ctime = gs_default_val();
- FILETIME atime = gs_default_val();
- if (GetFileAttributesExA(file_path, GetFileExInfoStandard, &data))
- {
- ftime = data.ftLastWriteTime;
- ctime = data.ftCreationTime;
- atime = data.ftLastAccessTime;
- }
- stats.modified_time = *((uint64_t*)&ftime);
- stats.access_time = *((uint64_t*)&atime);
- stats.creation_time = *((uint64_t*)&ctime);
- #elif (defined GS_PLATFORM_LINUX || defined GS_PLATFORM_APPLE || defined GS_PLATFORM_ANDROID)
- struct stat attr = gs_default_val();
- stat(file_path, &attr);
- stats.modified_time = *((uint64_t*)&attr.st_mtime);
- #endif
- return stats;
- }
- GS_API_DECL void*
- gs_platform_library_load_default_impl(const char* lib_path)
- {
- #if (defined GS_PLATFORM_WIN)
- return (void*)LoadLibraryA(lib_path);
- #elif (defined GS_PLATFORM_LINUX || defined GS_PLATFORM_APPLE || defined GS_PLATFORM_ANDROID)
- return (void*)dlopen(lib_path, RTLD_LAZY);
- #endif
- return NULL;
- }
- GS_API_DECL void
- gs_platform_library_unload_default_impl(void* lib)
- {
- if (!lib) return;
- #if (defined GS_PLATFORM_WIN)
-
- FreeLibrary((HMODULE)lib);
- #elif (defined GS_PLATFORM_LINUX || defined GS_PLATFORM_APPLE || defined GS_PLATFORM_ANDROID)
- dlclose(lib);
- #endif
- }
- GS_API_DECL void*
- gs_platform_library_proc_address_default_impl(void* lib, const char* func)
- {
- if (!lib) return NULL;
- #if (defined GS_PLATFORM_WIN)
- return (void*)GetProcAddress((HMODULE)lib, func);
- #elif (defined GS_PLATFORM_LINUX || defined GS_PLATFORM_APPLE || defined GS_PLATFORM_ANDROID)
- return (void*)dlsym(lib, func);
- #endif
- return NULL;
- }
- #undef GS_PLATFORM_IMPL_DEFAULT
- #endif // GS_PLATFORM_IMPL_DEFAULT
- /*======================
- // GLFW Implemenation
- ======================*/
- #ifdef GS_PLATFORM_IMPL_GLFW
- #define GLAD_IMPL
- #include "../external/glad/glad_impl.h"
- #define GLFW_IMPL
- #include "../external/glfw/glfw_impl.h"
- #if (defined GS_PLATFORM_APPLE || defined GS_PLATFORM_LINUX)
- #include <sched.h>
- #include <unistd.h>
- #elif (defined GS_PLATFORM_WINDOWS)
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #endif
- // Forward Decls.
- void __glfw_key_callback(GLFWwindow* window, s32 key, s32 scancode, s32 action, s32 mods);
- void __glfw_char_callback(GLFWwindow* window, uint32_t codepoint);
- void __glfw_mouse_button_callback(GLFWwindow* window, s32 button, s32 action, s32 mods);
- void __glfw_mouse_cursor_position_callback(GLFWwindow* window, f64 x, f64 y);
- void __glfw_mouse_scroll_wheel_callback(GLFWwindow* window, f64 xoffset, f64 yoffset);
- void __glfw_mouse_cursor_enter_callback(GLFWwindow* window, s32 entered);
- void __glfw_frame_buffer_size_callback(GLFWwindow* window, s32 width, s32 height);
- void __glfw_drop_callback(GLFWwindow* window);
- /*
- #define __glfw_window_from_handle(platform, handle)\
- ((GLFWwindow*)(gs_slot_array_get((platform)->windows, (handle))))
- */
- /*== Platform Init / Shutdown == */
- void gs_platform_init(gs_platform_t* pf)
- {
- gs_assert(pf);
- gs_println("Initializing GLFW");
- glfwInit();
- switch (pf->settings.video.driver)
- {
- case GS_PLATFORM_VIDEO_DRIVER_TYPE_OPENGL:
- {
- #if (defined GS_PLATFORM_APPLE)
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
- glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
- glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE);
- #else
- glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
- // glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, platform->settings.video.graphics.opengl.major_version);
- // glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, platform->settings.video.graphics.opengl.minor_version);
- // glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
- // glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
- // glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
- // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
- if (pf->settings.video.graphics.debug)
- {
- glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
- }
- #endif
- // glfwSwapInterval(platform->settings.video.vsync_enabled);
- // glfwSwapInterval(0);
- } break;
- default:
- {
- // Default to no output at all.
- gs_println("Video format not supported.");
- gs_assert(false);
- } break;
- }
- // Construct cursors
- pf->cursors[(u32)GS_PLATFORM_CURSOR_ARROW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
- pf->cursors[(u32)GS_PLATFORM_CURSOR_IBEAM] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
- pf->cursors[(u32)GS_PLATFORM_CURSOR_SIZE_NW_SE] = glfwCreateStandardCursor(GLFW_CROSSHAIR_CURSOR);
- pf->cursors[(u32)GS_PLATFORM_CURSOR_SIZE_NE_SW] = glfwCreateStandardCursor(GLFW_CROSSHAIR_CURSOR);
- pf->cursors[(u32)GS_PLATFORM_CURSOR_SIZE_NS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR);
- pf->cursors[(u32)GS_PLATFORM_CURSOR_SIZE_WE] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);
- pf->cursors[(u32)GS_PLATFORM_CURSOR_SIZE_ALL] = glfwCreateStandardCursor(GLFW_CROSSHAIR_CURSOR);
- pf->cursors[(u32)GS_PLATFORM_CURSOR_HAND] = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
- pf->cursors[(u32)GS_PLATFORM_CURSOR_NO] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
- // Poll joysticks here
- for (uint32_t i = 0; i < GS_PLATFORM_GAMEPAD_MAX; ++i) {
- pf->input.gamepads[i].present = glfwJoystickPresent(GLFW_JOYSTICK_1 + i);
- if (pf->input.gamepads[i].present)
- {
- gs_log_success("Controller %d connected.", i);
- }
- }
- }
- GS_API_DECL void gs_platform_update_internal(gs_platform_t* platform)
- {
- gs_platform_input_t* input = &platform->input;
- // Platform time
- platform->time.elapsed = (glfwGetTime() * 1000.0);
- // Update all window/framebuffer state
- for (
- gs_slot_array_iter it = gs_slot_array_iter_new(platform->windows);
- gs_slot_array_iter_valid(platform->windows, it);
- gs_slot_array_iter_advance(platform->windows, it)
- )
- {
- // Cache all necessary window information
- int32_t wx = 0, wy = 0, fx = 0, fy = 0, wpx = 0, wpy = 0;
- gs_platform_window_t* win = gs_slot_array_getp(platform->windows, it);
- glfwGetWindowSize((GLFWwindow*)win->hndl, &wx, &wy);
- glfwGetFramebufferSize((GLFWwindow*)win->hndl, &fx, &fy);
- glfwGetWindowPos((GLFWwindow*)win->hndl, &wpx, &wpy);
- win->window_size = gs_v2( (float)wx, (float)wy);
- win->window_position = gs_v2( (float)wpx, (float)wpy);
- win->framebuffer_size = gs_v2( (float)fx, (float)fy);
- }
- // Update all gamepad state
- for (uint32_t i = 0; i < GS_PLATFORM_GAMEPAD_MAX; ++i) {
- gs_platform_gamepad_t* gp = &input->gamepads[i];
- gp->present = glfwJoystickPresent(GLFW_JOYSTICK_1 + i);
- if (gp->present)
- {
- int32_t count = 0;
- const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1 + i, &count);
- count = gs_min(count, GS_PLATFORM_JOYSTICK_AXIS_COUNT);
- for (uint32_t a = 0; a < count; ++a) {
- gp->axes[a] = axes[a];
- }
- const uint8_t* buttons = (uint8_t*)glfwGetJoystickButtons(GLFW_JOYSTICK_1 + i, &count);
- count = gs_min(count, GS_PLATFORM_GAMEPAD_BUTTON_COUNT);
- for (uint32_t b = 0; b < count; ++b) {
- gp->buttons[b] = buttons[b];
- }
- }
- }
- }
- void gs_platform_shutdown(gs_platform_t* pf)
- {
- // Free all windows in glfw
- // TODO(john): Figure out crash with glfwDestroyWindow && glfwTerminate
- for
- (
- gs_slot_array_iter it = 0;
- gs_slot_array_iter_valid(pf->windows, it);
- gs_slot_array_iter_advance(pf->windows, it)
- )
- {
- // GLFWwindow* win = __glfw_window_from_handle(pf, it);
- // glfwDestroyWindow(win);
- }
- // glfwTerminate();
- }
- uint32_t gs_platform_key_to_codepoint(gs_platform_keycode key)
- {
- uint32_t code = 0;
- switch (key)
- {
- default:
- case GS_KEYCODE_COUNT:
- case GS_KEYCODE_INVALID: code = 0; break;
- case GS_KEYCODE_SPACE: code = 32; break;
- case GS_KEYCODE_APOSTROPHE: code = 39; break;
- case GS_KEYCODE_COMMA: code = 44; break;
- case GS_KEYCODE_MINUS: code = 45; break;
- case GS_KEYCODE_PERIOD: code = 46; break;
- case GS_KEYCODE_SLASH: code = 47; break;
- case GS_KEYCODE_0: code = 48; break;
- case GS_KEYCODE_1: code = 49; break;
- case GS_KEYCODE_2: code = 50; break;
- case GS_KEYCODE_3: code = 51; break;
- case GS_KEYCODE_4: code = 52; break;
- case GS_KEYCODE_5: code = 53; break;
- case GS_KEYCODE_6: code = 54; break;
- case GS_KEYCODE_7: code = 55; break;
- case GS_KEYCODE_8: code = 56; break;
- case GS_KEYCODE_9: code = 57; break;
- case GS_KEYCODE_SEMICOLON: code = 59; break; /* ; */
- case GS_KEYCODE_EQUAL: code = 61; break; /* code = */
- case GS_KEYCODE_A: code = 65; break;
- case GS_KEYCODE_B: code = 66; break;
- case GS_KEYCODE_C: code = 67; break;
- case GS_KEYCODE_D: code = 68; break;
- case GS_KEYCODE_E: code = 69; break;
- case GS_KEYCODE_F: code = 70; break;
- case GS_KEYCODE_G: code = 71; break;
- case GS_KEYCODE_H: code = 72; break;
- case GS_KEYCODE_I: code = 73; break;
- case GS_KEYCODE_J: code = 74; break;
- case GS_KEYCODE_K: code = 75; break;
- case GS_KEYCODE_L: code = 76; break;
- case GS_KEYCODE_M: code = 77; break;
- case GS_KEYCODE_N: code = 78; break;
- case GS_KEYCODE_O: code = 79; break;
- case GS_KEYCODE_P: code = 80; break;
- case GS_KEYCODE_Q: code = 81; break;
- case GS_KEYCODE_R: code = 82; break;
- case GS_KEYCODE_S: code = 83; break;
- case GS_KEYCODE_T: code = 84; break;
- case GS_KEYCODE_U: code = 85; break;
- case GS_KEYCODE_V: code = 86; break;
- case GS_KEYCODE_W: code = 87; break;
- case GS_KEYCODE_X: code = 88; break;
- case GS_KEYCODE_Y: code = 89; break;
- case GS_KEYCODE_Z: code = 90; break;
- case GS_KEYCODE_LEFT_BRACKET: code = 91; break; /* [ */
- case GS_KEYCODE_BACKSLASH: code = 92; break; /* \ */
- case GS_KEYCODE_RIGHT_BRACKET: code = 93; break; /* ] */
- case GS_KEYCODE_GRAVE_ACCENT: code = 96; break; /* ` */
- case GS_KEYCODE_WORLD_1: code = 161; break; /* non-US #1 */
- case GS_KEYCODE_WORLD_2: code = 162; break; /* non-US #2 */
- case GS_KEYCODE_ESC: code = 256; break;
- case GS_KEYCODE_ENTER: code = 257; break;
- case GS_KEYCODE_TAB: code = 258; break;
- case GS_KEYCODE_BACKSPACE: code = 259; break;
- case GS_KEYCODE_INSERT: code = 260; break;
- case GS_KEYCODE_DELETE: code = GLFW_KEY_DELETE; break;
- case GS_KEYCODE_RIGHT: code = 262; break;
- case GS_KEYCODE_LEFT: code = 263; break;
- case GS_KEYCODE_DOWN: code = 264; break;
- case GS_KEYCODE_UP: code = 265; break;
- case GS_KEYCODE_PAGE_UP: code = 266; break;
- case GS_KEYCODE_PAGE_DOWN: code = 267; break;
- case GS_KEYCODE_HOME: code = 268; break;
- case GS_KEYCODE_END: code = 269; break;
- case GS_KEYCODE_CAPS_LOCK: code = 280; break;
- case GS_KEYCODE_SCROLL_LOCK: code = 281; break;
- case GS_KEYCODE_NUM_LOCK: code = 282; break;
- case GS_KEYCODE_PRINT_SCREEN: code = 283; break;
- case GS_KEYCODE_PAUSE: code = 284; break;
- case GS_KEYCODE_F1: code = 290; break;
- case GS_KEYCODE_F2: code = 291; break;
- case GS_KEYCODE_F3: code = 292; break;
- case GS_KEYCODE_F4: code = 293; break;
- case GS_KEYCODE_F5: code = 294; break;
- case GS_KEYCODE_F6: code = 295; break;
- case GS_KEYCODE_F7: code = 296; break;
- case GS_KEYCODE_F8: code = 297; break;
- case GS_KEYCODE_F9: code = 298; break;
- case GS_KEYCODE_F10: code = 299; break;
- case GS_KEYCODE_F11: code = 300; break;
- case GS_KEYCODE_F12: code = 301; break;
- case GS_KEYCODE_F13: code = 302; break;
- case GS_KEYCODE_F14: code = 303; break;
- case GS_KEYCODE_F15: code = 304; break;
- case GS_KEYCODE_F16: code = 305; break;
- case GS_KEYCODE_F17: code = 306; break;
- case GS_KEYCODE_F18: code = 307; break;
- case GS_KEYCODE_F19: code = 308; break;
- case GS_KEYCODE_F20: code = 309; break;
- case GS_KEYCODE_F21: code = 310; break;
- case GS_KEYCODE_F22: code = 311; break;
- case GS_KEYCODE_F23: code = 312; break;
- case GS_KEYCODE_F24: code = 313; break;
- case GS_KEYCODE_F25: code = 314; break;
- case GS_KEYCODE_KP_0: code = 320; break;
- case GS_KEYCODE_KP_1: code = 321; break;
- case GS_KEYCODE_KP_2: code = 322; break;
- case GS_KEYCODE_KP_3: code = 323; break;
- case GS_KEYCODE_KP_4: code = 324; break;
- case GS_KEYCODE_KP_5: code = 325; break;
- case GS_KEYCODE_KP_6: code = 326; break;
- case GS_KEYCODE_KP_7: code = 327; break;
- case GS_KEYCODE_KP_8: code = 328; break;
- case GS_KEYCODE_KP_9: code = 329; break;
- case GS_KEYCODE_KP_DECIMAL: code = 330; break;
- case GS_KEYCODE_KP_DIVIDE: code = 331; break;
- case GS_KEYCODE_KP_MULTIPLY: code = 332; break;
- case GS_KEYCODE_KP_SUBTRACT: code = 333; break;
- case GS_KEYCODE_KP_ADD: code = 334; break;
- case GS_KEYCODE_KP_ENTER: code = 335; break;
- case GS_KEYCODE_KP_EQUAL: code = 336; break;
- case GS_KEYCODE_LEFT_SHIFT: code = 340; break;
- case GS_KEYCODE_LEFT_CONTROL: code = 341; break;
- case GS_KEYCODE_LEFT_ALT: code = 342; break;
- case GS_KEYCODE_LEFT_SUPER: code = 343; break;
- case GS_KEYCODE_RIGHT_SHIFT: code = 344; break;
- case GS_KEYCODE_RIGHT_CONTROL: code = 345; break;
- case GS_KEYCODE_RIGHT_ALT: code = 346; break;
- case GS_KEYCODE_RIGHT_SUPER: code = 347; break;
- case GS_KEYCODE_MENU: code = 348; break;
- }
- return code;
- }
- // This doesn't work. Have to set up keycodes for emscripten instead. FUN.
- gs_platform_keycode gs_platform_codepoint_to_key(uint32_t code)
- {
- gs_platform_keycode key = GS_KEYCODE_INVALID;
- switch (code)
- {
- default:
- case 0: key = GS_KEYCODE_INVALID; break;
- case 32: key = GS_KEYCODE_SPACE; break;
- case 39: key = GS_KEYCODE_APOSTROPHE; break;
- case 44: key = GS_KEYCODE_COMMA; break;
- case 45: key = GS_KEYCODE_MINUS; break;
- case 46: key = GS_KEYCODE_PERIOD; break;
- case 47: key = GS_KEYCODE_SLASH; break;
- case 48: key = GS_KEYCODE_0; break;
- case 49: key = GS_KEYCODE_1; break;
- case 50: key = GS_KEYCODE_2; break;
- case 51: key = GS_KEYCODE_3; break;
- case 52: key = GS_KEYCODE_4; break;
- case 53: key = GS_KEYCODE_5; break;
- case 54: key = GS_KEYCODE_6; break;
- case 55: key = GS_KEYCODE_7; break;
- case 56: key = GS_KEYCODE_8; break;
- case 57: key = GS_KEYCODE_9; break;
- case 59: key = GS_KEYCODE_SEMICOLON; break;
- case 61: key = GS_KEYCODE_EQUAL; break;
- case 65: key = GS_KEYCODE_A; break;
- case 66: key = GS_KEYCODE_B; break;
- case 67: key = GS_KEYCODE_C; break;
- case 68: key = GS_KEYCODE_D; break;
- case 69: key = GS_KEYCODE_E; break;
- case 70: key = GS_KEYCODE_F; break;
- case 71: key = GS_KEYCODE_G; break;
- case 72: key = GS_KEYCODE_H; break;
- case 73: key = GS_KEYCODE_I; break;
- case 74: key = GS_KEYCODE_J; break;
- case 75: key = GS_KEYCODE_K; break;
- case 76: key = GS_KEYCODE_L; break;
- case 77: key = GS_KEYCODE_M; break;
- case 78: key = GS_KEYCODE_N; break;
- case 79: key = GS_KEYCODE_O; break;
- case 80: key = GS_KEYCODE_P; break;
- case 81: key = GS_KEYCODE_Q; break;
- case 82: key = GS_KEYCODE_R; break;
- case 83: key = GS_KEYCODE_S; break;
- case 84: key = GS_KEYCODE_T; break;
- case 85: key = GS_KEYCODE_U; break;
- case 86: key = GS_KEYCODE_V; break;
- case 87: key = GS_KEYCODE_W; break;
- case 88: key = GS_KEYCODE_X; break;
- case 89: key = GS_KEYCODE_Y; break;
- case 90: key = GS_KEYCODE_Z; break;
- case 91: key = GS_KEYCODE_LEFT_BRACKET; break;
- case 92: key = GS_KEYCODE_BACKSLASH; break;
- case 93: key = GS_KEYCODE_RIGHT_BRACKET; break;
- case 96: key = GS_KEYCODE_GRAVE_ACCENT; break;
- case 161: key = GS_KEYCODE_WORLD_1; break;
- case 162: key = GS_KEYCODE_WORLD_2; break;
- case 256: key = GS_KEYCODE_ESC; break;
- case 257: key = GS_KEYCODE_ENTER; break;
- case 258: key = GS_KEYCODE_TAB; break;
- case 259: key = GS_KEYCODE_BACKSPACE; break;
- case 260: key = GS_KEYCODE_INSERT; break;
- case GLFW_KEY_DELETE: key = GS_KEYCODE_DELETE; break;
- case 262: key = GS_KEYCODE_RIGHT; break;
- case 263: key = GS_KEYCODE_LEFT; break;
- case 264: key = GS_KEYCODE_DOWN; break;
- case 265: key = GS_KEYCODE_UP; break;
- case 266: key = GS_KEYCODE_PAGE_UP; break;
- case 267: key = GS_KEYCODE_PAGE_DOWN; break;
- case 268: key = GS_KEYCODE_HOME; break;
- case 269: key = GS_KEYCODE_END; break;
- case 280: key = GS_KEYCODE_CAPS_LOCK; break;
- case 281: key = GS_KEYCODE_SCROLL_LOCK; break;
- case 282: key = GS_KEYCODE_NUM_LOCK; break;
- case 283: key = GS_KEYCODE_PRINT_SCREEN; break;
- case 284: key = GS_KEYCODE_PAUSE; break;
- case 290: key = GS_KEYCODE_F1; break;
- case 291: key = GS_KEYCODE_F2; break;
- case 292: key = GS_KEYCODE_F3; break;
- case 293: key = GS_KEYCODE_F4; break;
- case 294: key = GS_KEYCODE_F5; break;
- case 295: key = GS_KEYCODE_F6; break;
- case 296: key = GS_KEYCODE_F7; break;
- case 297: key = GS_KEYCODE_F8; break;
- case 298: key = GS_KEYCODE_F9; break;
- case 299: key = GS_KEYCODE_F10; break;
- case 300: key = GS_KEYCODE_F11; break;
- case 301: key = GS_KEYCODE_F12; break;
- case 302: key = GS_KEYCODE_F13; break;
- case 303: key = GS_KEYCODE_F14; break;
- case 304: key = GS_KEYCODE_F15; break;
- case 305: key = GS_KEYCODE_F16; break;
- case 306: key = GS_KEYCODE_F17; break;
- case 307: key = GS_KEYCODE_F18; break;
- case 308: key = GS_KEYCODE_F19; break;
- case 309: key = GS_KEYCODE_F20; break;
- case 310: key = GS_KEYCODE_F21; break;
- case 311: key = GS_KEYCODE_F22; break;
- case 312: key = GS_KEYCODE_F23; break;
- case 313: key = GS_KEYCODE_F24; break;
- case 314: key = GS_KEYCODE_F25; break;
- case 320: key = GS_KEYCODE_KP_0; break;
- case 321: key = GS_KEYCODE_KP_1; break;
- case 322: key = GS_KEYCODE_KP_2; break;
- case 323: key = GS_KEYCODE_KP_3; break;
- case 324: key = GS_KEYCODE_KP_4; break;
- case 325: key = GS_KEYCODE_KP_5; break;
- case 326: key = GS_KEYCODE_KP_6; break;
- case 327: key = GS_KEYCODE_KP_7; break;
- case 328: key = GS_KEYCODE_KP_8; break;
- case 329: key = GS_KEYCODE_KP_9; break;
- case 330: key = GS_KEYCODE_KP_DECIMAL; break;
- case 331: key = GS_KEYCODE_KP_DIVIDE; break;
- case 332: key = GS_KEYCODE_KP_MULTIPLY; break;
- case 333: key = GS_KEYCODE_KP_SUBTRACT; break;
- case 334: key = GS_KEYCODE_KP_ADD; break;
- case 335: key = GS_KEYCODE_KP_ENTER; break;
- case 336: key = GS_KEYCODE_KP_EQUAL; break;
- case 340: key = GS_KEYCODE_LEFT_SHIFT; break;
- case 341: key = GS_KEYCODE_LEFT_CONTROL; break;
- case 342: key = GS_KEYCODE_LEFT_ALT; break;
- case 343: key = GS_KEYCODE_LEFT_SUPER; break;
- case 344: key = GS_KEYCODE_RIGHT_SHIFT; break;
- case 345: key = GS_KEYCODE_RIGHT_CONTROL; break;
- case 346: key = GS_KEYCODE_RIGHT_ALT; break;
- case 347: key = GS_KEYCODE_RIGHT_SUPER; break;
- case 348: key = GS_KEYCODE_MENU; break;
- }
- return key;
- }
- /*=== GLFW Callbacks ===*/
- gs_platform_keycode glfw_key_to_gs_keycode(u32 code)
- {
- switch (code)
- {
- case GLFW_KEY_A: return GS_KEYCODE_A; break;
- case GLFW_KEY_B: return GS_KEYCODE_B; break;
- case GLFW_KEY_C: return GS_KEYCODE_C; break;
- case GLFW_KEY_D: return GS_KEYCODE_D; break;
- case GLFW_KEY_E: return GS_KEYCODE_E; break;
- case GLFW_KEY_F: return GS_KEYCODE_F; break;
- case GLFW_KEY_G: return GS_KEYCODE_G; break;
- case GLFW_KEY_H: return GS_KEYCODE_H; break;
- case GLFW_KEY_I: return GS_KEYCODE_I; break;
- case GLFW_KEY_J: return GS_KEYCODE_J; break;
- case GLFW_KEY_K: return GS_KEYCODE_K; break;
- case GLFW_KEY_L: return GS_KEYCODE_L; break;
- case GLFW_KEY_M: return GS_KEYCODE_M; break;
- case GLFW_KEY_N: return GS_KEYCODE_N; break;
- case GLFW_KEY_O: return GS_KEYCODE_O; break;
- case GLFW_KEY_P: return GS_KEYCODE_P; break;
- case GLFW_KEY_Q: return GS_KEYCODE_Q; break;
- case GLFW_KEY_R: return GS_KEYCODE_R; break;
- case GLFW_KEY_S: return GS_KEYCODE_S; break;
- case GLFW_KEY_T: return GS_KEYCODE_T; break;
- case GLFW_KEY_U: return GS_KEYCODE_U; break;
- case GLFW_KEY_V: return GS_KEYCODE_V; break;
- case GLFW_KEY_W: return GS_KEYCODE_W; break;
- case GLFW_KEY_X: return GS_KEYCODE_X; break;
- case GLFW_KEY_Y: return GS_KEYCODE_Y; break;
- case GLFW_KEY_Z: return GS_KEYCODE_Z; break;
- case GLFW_KEY_LEFT_SHIFT: return GS_KEYCODE_LEFT_SHIFT; break;
- case GLFW_KEY_RIGHT_SHIFT: return GS_KEYCODE_RIGHT_SHIFT; break;
- case GLFW_KEY_LEFT_ALT: return GS_KEYCODE_LEFT_ALT; break;
- case GLFW_KEY_RIGHT_ALT: return GS_KEYCODE_RIGHT_ALT; break;
- case GLFW_KEY_LEFT_CONTROL: return GS_KEYCODE_LEFT_CONTROL; break;
- case GLFW_KEY_RIGHT_CONTROL: return GS_KEYCODE_RIGHT_CONTROL; break;
- case GLFW_KEY_BACKSPACE: return GS_KEYCODE_BACKSPACE; break;
- case GLFW_KEY_BACKSLASH: return GS_KEYCODE_BACKSLASH; break;
- case GLFW_KEY_SLASH: return GS_KEYCODE_SLASH; break;
- case GLFW_KEY_GRAVE_ACCENT: return GS_KEYCODE_GRAVE_ACCENT; break;
- case GLFW_KEY_COMMA: return GS_KEYCODE_COMMA; break;
- case GLFW_KEY_PERIOD: return GS_KEYCODE_PERIOD; break;
- case GLFW_KEY_ESCAPE: return GS_KEYCODE_ESC; break;
- case GLFW_KEY_SPACE: return GS_KEYCODE_SPACE; break;
- case GLFW_KEY_LEFT: return GS_KEYCODE_LEFT; break;
- case GLFW_KEY_UP: return GS_KEYCODE_UP; break;
- case GLFW_KEY_RIGHT: return GS_KEYCODE_RIGHT; break;
- case GLFW_KEY_DOWN: return GS_KEYCODE_DOWN; break;
- case GLFW_KEY_0: return GS_KEYCODE_0; break;
- case GLFW_KEY_1: return GS_KEYCODE_1; break;
- case GLFW_KEY_2: return GS_KEYCODE_2; break;
- case GLFW_KEY_3: return GS_KEYCODE_3; break;
- case GLFW_KEY_4: return GS_KEYCODE_4; break;
- case GLFW_KEY_5: return GS_KEYCODE_5; break;
- case GLFW_KEY_6: return GS_KEYCODE_6; break;
- case GLFW_KEY_7: return GS_KEYCODE_7; break;
- case GLFW_KEY_8: return GS_KEYCODE_8; break;
- case GLFW_KEY_9: return GS_KEYCODE_9; break;
- case GLFW_KEY_KP_0: return GS_KEYCODE_KP_0; break;
- case GLFW_KEY_KP_1: return GS_KEYCODE_KP_1; break;
- case GLFW_KEY_KP_2: return GS_KEYCODE_KP_2; break;
- case GLFW_KEY_KP_3: return GS_KEYCODE_KP_3; break;
- case GLFW_KEY_KP_4: return GS_KEYCODE_KP_4; break;
- case GLFW_KEY_KP_5: return GS_KEYCODE_KP_5; break;
- case GLFW_KEY_KP_6: return GS_KEYCODE_KP_6; break;
- case GLFW_KEY_KP_7: return GS_KEYCODE_KP_7; break;
- case GLFW_KEY_KP_8: return GS_KEYCODE_KP_8; break;
- case GLFW_KEY_KP_9: return GS_KEYCODE_KP_9; break;
- case GLFW_KEY_CAPS_LOCK: return GS_KEYCODE_CAPS_LOCK; break;
- case GLFW_KEY_DELETE: return GS_KEYCODE_DELETE; break;
- case GLFW_KEY_END: return GS_KEYCODE_END; break;
- case GLFW_KEY_F1: return GS_KEYCODE_F1; break;
- case GLFW_KEY_F2: return GS_KEYCODE_F2; break;
- case GLFW_KEY_F3: return GS_KEYCODE_F3; break;
- case GLFW_KEY_F4: return GS_KEYCODE_F4; break;
- case GLFW_KEY_F5: return GS_KEYCODE_F5; break;
- case GLFW_KEY_F6: return GS_KEYCODE_F6; break;
- case GLFW_KEY_F7: return GS_KEYCODE_F7; break;
- case GLFW_KEY_F8: return GS_KEYCODE_F8; break;
- case GLFW_KEY_F9: return GS_KEYCODE_F9; break;
- case GLFW_KEY_F10: return GS_KEYCODE_F10; break;
- case GLFW_KEY_F11: return GS_KEYCODE_F11; break;
- case GLFW_KEY_F12: return GS_KEYCODE_F12; break;
- case GLFW_KEY_HOME: return GS_KEYCODE_HOME; break;
- case GLFW_KEY_EQUAL: return GS_KEYCODE_EQUAL; break;
- case GLFW_KEY_MINUS: return GS_KEYCODE_MINUS; break;
- case GLFW_KEY_LEFT_BRACKET: return GS_KEYCODE_LEFT_BRACKET; break;
- case GLFW_KEY_RIGHT_BRACKET: return GS_KEYCODE_RIGHT_BRACKET; break;
- case GLFW_KEY_SEMICOLON: return GS_KEYCODE_SEMICOLON; break;
- case GLFW_KEY_ENTER: return GS_KEYCODE_ENTER; break;
- case GLFW_KEY_INSERT: return GS_KEYCODE_INSERT; break;
- case GLFW_KEY_PAGE_UP: return GS_KEYCODE_PAGE_UP; break;
- case GLFW_KEY_PAGE_DOWN: return GS_KEYCODE_PAGE_DOWN; break;
- case GLFW_KEY_NUM_LOCK: return GS_KEYCODE_NUM_LOCK; break;
- case GLFW_KEY_TAB: return GS_KEYCODE_TAB; break;
- case GLFW_KEY_KP_MULTIPLY: return GS_KEYCODE_KP_MULTIPLY; break;
- case GLFW_KEY_KP_DIVIDE: return GS_KEYCODE_KP_DIVIDE; break;
- case GLFW_KEY_KP_ADD: return GS_KEYCODE_KP_ADD; break;
- case GLFW_KEY_KP_SUBTRACT: return GS_KEYCODE_KP_SUBTRACT; break;
- case GLFW_KEY_KP_ENTER: return GS_KEYCODE_KP_ENTER; break;
- case GLFW_KEY_KP_DECIMAL: return GS_KEYCODE_KP_DECIMAL; break;
- case GLFW_KEY_PAUSE: return GS_KEYCODE_PAUSE; break;
- case GLFW_KEY_PRINT_SCREEN: return GS_KEYCODE_PRINT_SCREEN; break;
- default: return GS_KEYCODE_COUNT; break;
- }
- // Shouldn't reach here
- return GS_KEYCODE_COUNT;
- }
- gs_platform_mouse_button_code __glfw_button_to_gs_mouse_button(s32 code)
- {
- switch (code)
- {
- case GLFW_MOUSE_BUTTON_LEFT: return GS_MOUSE_LBUTTON; break;
- case GLFW_MOUSE_BUTTON_RIGHT: return GS_MOUSE_RBUTTON; break;
- case GLFW_MOUSE_BUTTON_MIDDLE: return GS_MOUSE_MBUTTON; break;
- }
- // Shouldn't reach here
- return GS_MOUSE_BUTTON_CODE_COUNT;
- }
- void __glfw_char_callback(GLFWwindow* window, uint32_t codepoint)
- {
- // Grab platform instance from engine
- gs_platform_t* platform = gs_subsystem(platform);
- gs_platform_event_t evt = gs_default_val();
- evt.type = GS_PLATFORM_EVENT_TEXT;
- evt.text.codepoint = codepoint;
- // Add action
- gs_platform_add_event(&evt);
- }
- void __glfw_key_callback(GLFWwindow* window, s32 code, s32 scancode, s32 action, s32 mods)
- {
- // Grab platform instance from engine
- gs_platform_t* platform = gs_subsystem(platform);
- // Get keycode from key
- gs_platform_keycode key = glfw_key_to_gs_keycode(code);
- // Push back event into platform events
- gs_platform_event_t evt = gs_default_val();
- evt.type = GS_PLATFORM_EVENT_KEY;
- evt.key.codepoint = code;
- evt.key.keycode = key;
- evt.key.modifier = (gs_platform_key_modifier_type)mods;
- switch (action)
- {
- // Released
- case 0: {
- gs_platform_release_key(key);
- evt.key.action = GS_PLATFORM_KEY_RELEASED;
- } break;
- // Pressed
- case 1: {
- gs_platform_press_key(key);
- evt.key.action = GS_PLATFORM_KEY_PRESSED;
- } break;
- // Down
- case 2: {
- gs_platform_press_key(key);
- evt.key.action = GS_PLATFORM_KEY_DOWN;
- } break;
- default: {
- } break;
- }
- // Add action
- gs_platform_add_event(&evt);
- }
- void __glfw_mouse_button_callback(GLFWwindow* window, s32 code, s32 action, s32 mods)
- {
- // Grab platform instance from engine
- gs_platform_t* platform = gs_subsystem(platform);
- // Get mouse code from key
- gs_platform_mouse_button_code button = __glfw_button_to_gs_mouse_button(code);
- // Push back event into platform events
- gs_platform_event_t evt = gs_default_val();
- evt.type = GS_PLATFORM_EVENT_MOUSE;
- evt.mouse.codepoint = code;
- evt.mouse.button = button;
- switch (action)
- {
- // Released
- case 0:
- {
- gs_platform_release_mouse_button(button);
- evt.mouse.action = GS_PLATFORM_MOUSE_BUTTON_RELEASED;
- } break;
- // Pressed
- case 1:
- {
- gs_platform_press_mouse_button(button);
- evt.mouse.action = GS_PLATFORM_MOUSE_BUTTON_PRESSED;
- } break;
- // Down
- case 2:
- {
- gs_platform_press_mouse_button(button);
- evt.mouse.action = GS_PLATFORM_MOUSE_BUTTON_DOWN;
- } break;
- }
- // Add action
- gs_platform_add_event(&evt);
- }
- void __glfw_mouse_cursor_position_callback(GLFWwindow* window, f64 x, f64 y)
- {
- gs_platform_t* platform = gs_subsystem(platform);
- // platform->input.mouse.position = gs_v2((f32)x, (f32)y);
- // platform->input.mouse.moved_this_frame = true;
- gs_platform_event_t gs_evt = gs_default_val();
- gs_evt.type = GS_PLATFORM_EVENT_MOUSE;
- gs_evt.mouse.action = GS_PLATFORM_MOUSE_MOVE;
- // gs_println("pos: <%.2f, %.2f>, old: <%.2f, %.2f>", x, y, platform->input.mouse.position.x, platform->input.mouse.position.y);
- // gs_evt.mouse.move = gs_v2((f32)x, (f32)y);
- // Calculate mouse move based on whether locked or not
- if (gs_platform_mouse_locked()) {
- gs_evt.mouse.move.x = x - platform->input.mouse.position.x;
- gs_evt.mouse.move.y = y - platform->input.mouse.position.y;
- platform->input.mouse.position.x = x;
- platform->input.mouse.position.y = y;
- } else {
- gs_evt.mouse.move = gs_v2((f32)x, (f32)y);
- }
- // Push back event into platform events
- gs_platform_add_event(&gs_evt);
- }
- void __glfw_mouse_scroll_wheel_callback(GLFWwindow* window, f64 x, f64 y)
- {
- gs_platform_t* platform = gs_subsystem(platform);
- platform->input.mouse.wheel = gs_v2((f32)x, (f32)y);
- // Push back event into platform events
- gs_platform_event_t gs_evt = gs_default_val();
- gs_evt.type = GS_PLATFORM_EVENT_MOUSE;
- gs_evt.mouse.action = GS_PLATFORM_MOUSE_WHEEL;
- gs_evt.mouse.wheel = gs_v2((f32)x, (f32)y);
- gs_platform_add_event(&gs_evt);
- }
- // Gets called when mouse enters or leaves frame of window
- void __glfw_mouse_cursor_enter_callback(GLFWwindow* window, s32 entered)
- {
- gs_platform_t* platform = gs_subsystem(platform);
- gs_platform_event_t gs_evt = gs_default_val();
- gs_evt.type = GS_PLATFORM_EVENT_MOUSE;
- gs_evt.mouse.action = entered ? GS_PLATFORM_MOUSE_ENTER : GS_PLATFORM_MOUSE_LEAVE;
- gs_platform_add_event(&gs_evt);
- }
- void __glfw_frame_buffer_size_callback(GLFWwindow* window, s32 width, s32 height)
- {
- // Nothing for now
- }
- /*== Platform Input == */
- void gs_platform_process_input(gs_platform_input_t* input)
- {
- glfwPollEvents();
- }
- /*== Platform Util == */
- void gs_platform_sleep(float ms)
- {
- #if (defined GS_PLATFORM_WIN)
- timeBeginPeriod(1);
- Sleep((uint64_t)ms);
- timeEndPeriod(1);
- #elif (defined GS_PLATFORM_APPLE)
- usleep(ms * 1000.f); // unistd.h
- #else
- if (ms < 0.f) {
- return;
- }
- struct timespec ts = gs_default_val();
- int32_t res = 0;
- ts.tv_sec = ms / 1000.f;
- ts.tv_nsec = ((uint64_t)ms % 1000) * 1000000;
- do {
- res = nanosleep(&ts, &ts);
- } while (res && errno == EINTR);
- // usleep(ms * 1000.f); // unistd.h
- #endif
- }
- GS_API_DECL double
- gs_platform_elapsed_time()
- {
- gs_platform_t* platform = gs_subsystem(platform);
- return platform->time.elapsed;
- }
- /*== Platform Video == */
- GS_API_DECL void
- gs_platform_enable_vsync(int32_t enabled)
- {
- glfwSwapInterval(enabled ? 1 : 0);
- }
- /*== OpenGL debug callback == */
- void GLAPIENTRY __gs_platform_gl_debug(GLenum source, GLenum type, GLuint id, GLenum severity,
- GLsizei len, const GLchar* msg, const void* user)
- {
- if (severity != GL_DEBUG_SEVERITY_NOTIFICATION)
- {
- gs_println("GL: %s", msg);
- }
- }
- /*== Platform Window == */
- GS_API_DECL gs_platform_window_t
- gs_platform_window_create_internal(const gs_platform_window_desc_t* desc)
- {
- gs_platform_window_t win = gs_default_val();
- if (!desc)
- {
- // Log warning
- gs_log_warning("Window descriptor is null.");
- return win;
- }
- // Grab window hints from application desc
- u32 window_hints = desc->flags;
- bool visible = ~window_hints & GS_WINDOW_FLAGS_INVISIBLE;
- // Set whether or not the screen is resizable
- glfwWindowHint(GLFW_RESIZABLE, (window_hints & GS_WINDOW_FLAGS_NO_RESIZE) != GS_WINDOW_FLAGS_NO_RESIZE);
- glfwWindowHint(GLFW_VISIBLE, visible);
- GLFWwindow* window = NULL;
- #define CONSTRUCT_WINDOW(W, H, T, M, I)\
- do {\
- window = glfwCreateWindow(W, H, T, M, I);\
- win.hndl = window;\
- } while (0)
- if (visible) {
- // Set multi-samples
- if (desc->num_samples) {
- glfwWindowHint(GLFW_SAMPLES, desc->num_samples);
- }
- else {
- glfwWindowHint(GLFW_SAMPLES, 0);
- }
- // Get monitor if fullscreen
- GLFWmonitor* monitor = NULL;
- if ((window_hints & GS_WINDOW_FLAGS_FULLSCREEN) == GS_WINDOW_FLAGS_FULLSCREEN) {
- int monitor_count;
- GLFWmonitor** monitors = glfwGetMonitors(&monitor_count);
- if (desc->monitor_index < monitor_count) {
- monitor = monitors[desc->monitor_index];
- }
- }
- CONSTRUCT_WINDOW(desc->width, desc->height, desc->title, monitor, NULL);
- // Callbacks for window
- glfwMakeContextCurrent(window);
- glfwSetKeyCallback(window, &__glfw_key_callback);
- glfwSetCharCallback(window, &__glfw_char_callback);
- glfwSetMouseButtonCallback(window, &__glfw_mouse_button_callback);
- glfwSetCursorEnterCallback(window, &__glfw_mouse_cursor_enter_callback);
- glfwSetCursorPosCallback(window, &__glfw_mouse_cursor_position_callback);
- glfwSetScrollCallback(window, &__glfw_mouse_scroll_wheel_callback);
- // Cache all necessary window information
- int32_t wx = 0, wy = 0, fx = 0, fy = 0, wpx = 0, wpy = 0;
- glfwGetWindowSize((GLFWwindow*)win.hndl, &wx, &wy);
- glfwGetFramebufferSize((GLFWwindow*)win.hndl, &fx, &fy);
- glfwGetWindowPos((GLFWwindow*)win.hndl, &wpx, &wpy);
- win.window_size = gs_v2((float)wx, (float)wy);
- win.window_position = gs_v2((float)wpx, (float)wpy);
- win.framebuffer_size = gs_v2((float)fx, (float)fy);
- }
- else {
- void* mwin = gs_platform_raw_window_handle(gs_platform_main_window());
- CONSTRUCT_WINDOW(1, 1, desc->title, 0, (GLFWwindow*)mwin);
- }
- if (window == NULL) {
- gs_log_error("Failed to create window.");
- glfwTerminate();
- return win;
- }
- // Need to make sure this is ONLY done once.
- if (gs_slot_array_empty(gs_subsystem(platform)->windows)) {
- if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
- gs_log_warning("Failed to initialize GLFW.");
- return win;
- }
- switch (gs_subsystem(platform)->settings.video.driver) {
- case GS_PLATFORM_VIDEO_DRIVER_TYPE_OPENGL: {
- gs_log_info("OpenGL Version: %s", glGetString(GL_VERSION));
- if (gs_subsystem(platform)->settings.video.graphics.debug) {
- glDebugMessageCallback(__gs_platform_gl_debug, NULL);
- }
- } break;
- default: break;
- }
- }
- return win;
- }
- // Platform callbacks
- GS_API_DECL void
- gs_platform_set_dropped_files_callback(uint32_t handle, gs_dropped_files_callback_t cb)
- {
- gs_platform_t* platform = gs_subsystem(platform);
- gs_platform_window_t* win = gs_slot_array_getp(platform->windows, handle);
- glfwSetDropCallback((GLFWwindow*)win->hndl, (GLFWdropfun)cb);
- }
- GS_API_DECL void
- gs_platform_set_window_close_callback(uint32_t handle, gs_window_close_callback_t cb)
- {
- gs_platform_t* platform = gs_subsystem(platform);
- gs_platform_window_t* win = gs_slot_array_getp(platform->windows, handle);
- glfwSetWindowCloseCallback((GLFWwindow*)win->hndl, (GLFWwindowclosefun)cb);
- }
- GS_API_DECL void
- gs_platform_set_character_callback(uint32_t handle, gs_character_callback_t cb)
- {
- gs_platform_t* platform = gs_subsystem(platform);
- gs_platform_window_t* win = gs_slot_array_getp(platform->windows, handle);
- glfwSetCharCallback((GLFWwindow*)win->hndl, (GLFWcharfun)cb);
- }
- GS_API_DECL void
- gs_platform_set_framebuffer_resize_callback(uint32_t handle, gs_framebuffer_resize_callback_t cb)
- {
- gs_platform_t* platform = gs_subsystem(platform);
- gs_platform_window_t* win = gs_slot_array_getp(platform->windows, handle);
- glfwSetFramebufferSizeCallback((GLFWwindow*)win->hndl, (GLFWframebuffersizefun)cb);
- }
- GS_API_DECL void
- gs_platform_mouse_set_position(uint32_t handle, float x, float y)
- {
- gs_platform_t* platform = gs_subsystem(platform);
- gs_platform_window_t* win = gs_slot_array_getp(platform->windows, handle);
- glfwSetCursorPos((GLFWwindow*)win->hndl, x, y);
- }
- GS_API_DECL void*
- gs_platform_raw_window_handle(uint32_t handle)
- {
- // Grab instance of platform from engine
- gs_platform_t* platform = gs_subsystem(platform);
- // Grab window from handle
- gs_platform_window_t* win = gs_slot_array_getp(platform->windows, handle);
- return (void*)win->hndl;
- }
- GS_API_DECL void
- gs_platform_window_swap_buffer(uint32_t handle)
- {
- // Grab instance of platform from engine
- gs_platform_t* platform = gs_subsystem(platform);
- // Grab window from handle
- gs_platform_window_t* win = gs_slot_array_getp(platform->windows, handle);
- glfwSwapBuffers((GLFWwindow*)win->hndl);
- }
- GS_API_DECL void
- gs_platform_window_make_current(uint32_t hndl)
- {
- gs_platform_t* platform = gs_subsystem(platform);
- gs_platform_window_t* win = gs_slot_array_getp(platform->windows, hndl);
- glfwMakeContextCurrent((GLFWwindow*)win->hndl);
- }
- GS_API_DECL void
- gs_platform_window_make_current_raw(void* win)
- {
- glfwMakeContextCurrent((GLFWwindow*)win);
- }
- GS_API_DECL gs_vec2
- gs_platform_window_sizev(uint32_t handle)
- {
- gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- return window->window_size;
- }
- GS_API_DECL void
- gs_platform_window_size(uint32_t handle, uint32_t* w, uint32_t* h)
- {
- gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- *w = (int32_t)window->window_size.x;
- *h = (int32_t)window->window_size.y;
- }
- uint32_t gs_platform_window_width(uint32_t handle)
- {
- gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- return (uint32_t)window->window_size.x;
- }
- uint32_t gs_platform_window_height(uint32_t handle)
- {
- gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- return (uint32_t)window->window_size.y;
- }
- bool32_t gs_platform_window_fullscreen(uint32_t handle)
- {
- gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- return glfwGetWindowMonitor((GLFWwindow*)window->hndl) != NULL;
- }
- void gs_platform_window_position(uint32_t handle, uint32_t* x, uint32_t* y)
- {
- gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- *x = (uint32_t)window->window_position.x;
- *y = (uint32_t)window->window_position.y;
- }
- gs_vec2 gs_platform_window_positionv(uint32_t handle)
- {
- gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- return window->window_position;
- }
- void gs_platform_set_window_size(uint32_t handle, uint32_t w, uint32_t h)
- {
- gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- glfwSetWindowSize((GLFWwindow*)window->hndl, (int32_t)w, (int32_t)h);
- }
- void gs_platform_set_window_sizev(uint32_t handle, gs_vec2 v)
- {
- gs_platform_window_t* window = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- glfwSetWindowSize((GLFWwindow*)window->hndl, (uint32_t)v.x, (uint32_t)v.y);
- }
- void gs_platform_set_window_fullscreen(uint32_t handle, bool32_t fullscreen)
- {
- gs_platform_window_t* win = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- GLFWmonitor* monitor = NULL;
- int32_t x, y, w, h;
- glfwGetWindowPos((GLFWwindow*)win->hndl, &x, &y);
- glfwGetWindowSize((GLFWwindow*)win->hndl, &w, &h);
- if (fullscreen)
- {
- uint32_t monitor_index = gs_instance()->ctx.app.window.monitor_index;
- int monitor_count;
- GLFWmonitor** monitors = glfwGetMonitors(&monitor_count);
- if (monitor_index < monitor_count)
- {
- monitor = monitors[monitor_index];
- }
- }
- glfwSetWindowMonitor((GLFWwindow*)win->hndl, monitor, x, y, w, h, GLFW_DONT_CARE);
- }
- void gs_platform_set_window_position(uint32_t handle, uint32_t x, uint32_t y)
- {
- gs_platform_window_t* win = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- glfwSetWindowPos((GLFWwindow*)win->hndl, (int32_t)x, (int32_t)y);
- }
- void gs_platform_set_window_positionv(uint32_t handle, gs_vec2 v)
- {
- gs_platform_window_t* win = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- glfwSetWindowPos((GLFWwindow*)win->hndl, (int32_t)v.x, (int32_t)v.y);
- }
- void gs_platform_framebuffer_size(uint32_t handle, uint32_t* w, uint32_t* h)
- {
- gs_platform_window_t* win = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- *w = (uint32_t)win->framebuffer_size.x;
- *h = (uint32_t)win->framebuffer_size.y;
- }
- gs_vec2 gs_platform_framebuffer_sizev(uint32_t handle)
- {
- uint32_t w = 0, h = 0;
- gs_platform_framebuffer_size(handle, &w, &h);
- return gs_v2((float)w, (float)h);
- }
- uint32_t gs_platform_framebuffer_width(uint32_t handle)
- {
- uint32_t w = 0, h = 0;
- gs_platform_framebuffer_size(handle, &w, &h);
- return w;
- }
- uint32_t gs_platform_framebuffer_height(uint32_t handle)
- {
- uint32_t w = 0, h = 0;
- gs_platform_framebuffer_size(handle, &w, &h);
- return h;
- }
- GS_API_DECL gs_vec2 gs_platform_monitor_sizev(uint32_t id)
- {
- gs_vec2 ms = gs_v2s(0.f);
- int32_t width, height, xpos, ypos;
- int32_t count;
- GLFWmonitor* monitor = NULL;
- gs_platform_t* platform = gs_subsystem(platform);
- GLFWmonitor** monitors = glfwGetMonitors(&count);
- if (count && id < count) {
- monitor = monitors[id];
- }
- else {
- monitor = glfwGetPrimaryMonitor();
- }
- glfwGetMonitorWorkarea(monitor, &xpos, &ypos, &width, &height);
- ms.x = (float)width;
- ms.y = (float)height;
- return ms;
- }
- GS_API_DECL void gs_platform_window_set_clipboard(uint32_t handle, const char* str)
- {
- gs_platform_window_t* win = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- glfwSetClipboardString((GLFWwindow*)win->hndl, str);
- }
- GS_API_DECL const char* gs_platform_window_get_clipboard(uint32_t handle)
- {
- gs_platform_window_t* win = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- return glfwGetClipboardString((GLFWwindow*)win->hndl);
- }
- void gs_platform_set_cursor(uint32_t handle, gs_platform_cursor cursor)
- {
- gs_platform_t* platform = gs_subsystem(platform);
- gs_platform_window_t* win = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- GLFWcursor* cp = ((GLFWcursor*)platform->cursors[(u32)cursor]);
- glfwSetCursor((GLFWwindow*)win->hndl, cp);
- }
- void gs_platform_lock_mouse(uint32_t handle, bool32_t lock)
- {
- __gs_input()->mouse.locked = lock;
- gs_platform_t* platform = gs_subsystem(platform);
- gs_platform_window_t* win = gs_slot_array_getp(gs_subsystem(platform)->windows, handle);
- glfwSetInputMode((GLFWwindow*)win->hndl, GLFW_CURSOR, lock ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL);
- // Not sure if I want to support this or not
- // if (glfwRawMouseMotionSupported()) {
- // glfwSetInputMode(win, GLFW_RAW_MOUSE_MOTION, lock ? GLFW_TRUE : GLFW_FALSE);
- // }
- }
- /* Main entry point for platform*/
- #ifndef GS_NO_HIJACK_MAIN
- int32_t main(int32_t argv, char** argc)
- {
- gs_t* inst = gs_create(gs_main(argv, argc));
- while (gs_app()->is_running) {
- gs_frame();
- }
- // Free engine
- gs_free(inst);
- return 0;
- }
- #endif // GS_NO_HIJACK_MAIN
- #undef GS_PLATFORM_IMPL_GLFW
- #endif // GS_PLATFORM_IMPL_GLFW
- /*==========================
- // Emscripten Implemenation
- ==========================*/
- #ifdef GS_PLATFORM_IMPL_EMSCRIPTEN
- #define GL_GLEXT_PROTOTYPES
- #define EGL_EGLEXT_PROTOTYPES
- #include <GLES3/gl3.h>
- #include <GLES2/gl2.h>
- #include <GLES2/gl2ext.h>
- #include <emscripten/emscripten.h>
- #include <emscripten/html5.h>
- // Emscripten context data
- typedef struct gs_ems_t
- {
- const char* canvas_name;
- double canvas_width;
- double canvas_height;
- EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx;
- bool32_t mouse_down[GS_MOUSE_BUTTON_CODE_COUNT];
- } gs_ems_t;
- #define GS_EMS_DATA()\
- ((gs_ems_t*)(gs_subsystem(platform)->user_data))
- uint32_t gs_platform_key_to_codepoint(gs_platform_keycode key)
- {
- uint32_t code = 0;
- switch (key)
- {
- default:
- case GS_KEYCODE_COUNT:
- case GS_KEYCODE_INVALID: code = 0; break;
- case GS_KEYCODE_SPACE: code = 32; break;
- case GS_KEYCODE_APOSTROPHE: code = 222; break;
- case GS_KEYCODE_COMMA: code = 44; break;
- case GS_KEYCODE_MINUS: code = 45; break;
- case GS_KEYCODE_PERIOD: code = 46; break;
- case GS_KEYCODE_SLASH: code = 47; break;
- case GS_KEYCODE_0: code = 48; break;
- case GS_KEYCODE_1: code = 49; break;
- case GS_KEYCODE_2: code = 50; break;
- case GS_KEYCODE_3: code = 51; break;
- case GS_KEYCODE_4: code = 52; break;
- case GS_KEYCODE_5: code = 53; break;
- case GS_KEYCODE_6: code = 54; break;
- case GS_KEYCODE_7: code = 55; break;
- case GS_KEYCODE_8: code = 56; break;
- case GS_KEYCODE_9: code = 57; break;
- case GS_KEYCODE_SEMICOLON: code = 59; break; /* ; */
- case GS_KEYCODE_EQUAL: code = 61; break; /* code = */
- case GS_KEYCODE_A: code = 65 + 32; break;
- case GS_KEYCODE_B: code = 66 + 32; break;
- case GS_KEYCODE_C: code = 67 + 32; break;
- case GS_KEYCODE_D: code = 68 + 32; break;
- case GS_KEYCODE_E: code = 69 + 32; break;
- case GS_KEYCODE_F: code = 70 + 32; break;
- case GS_KEYCODE_G: code = 71 + 32; break;
- case GS_KEYCODE_H: code = 72 + 32; break;
- case GS_KEYCODE_I: code = 73 + 32; break;
- case GS_KEYCODE_J: code = 74 + 32; break;
- case GS_KEYCODE_K: code = 75 + 32; break;
- case GS_KEYCODE_L: code = 76 + 32; break;
- case GS_KEYCODE_M: code = 77 + 32; break;
- case GS_KEYCODE_N: code = 78 + 32; break;
- case GS_KEYCODE_O: code = 79 + 32; break;
- case GS_KEYCODE_P: code = 80 + 32; break;
- case GS_KEYCODE_Q: code = 81 + 32; break;
- case GS_KEYCODE_R: code = 82 + 32; break;
- case GS_KEYCODE_S: code = 83 + 32; break;
- case GS_KEYCODE_T: code = 84 + 32; break;
- case GS_KEYCODE_U: code = 85 + 32; break;
- case GS_KEYCODE_V: code = 86 + 32; break;
- case GS_KEYCODE_W: code = 87 + 32; break;
- case GS_KEYCODE_X: code = 88 + 32; break;
- case GS_KEYCODE_Y: code = 89 + 32; break;
- case GS_KEYCODE_Z: code = 90 + 32; break;
- case GS_KEYCODE_LEFT_BRACKET: code = 91; break; /* [ */
- case GS_KEYCODE_BACKSLASH: code = 92; break; /* \ */
- case GS_KEYCODE_RIGHT_BRACKET: code = 93; break; /* ] */
- case GS_KEYCODE_GRAVE_ACCENT: code = 96; break; /* ` */
- case GS_KEYCODE_WORLD_1: code = 161; break; /* non-US #1 */
- case GS_KEYCODE_WORLD_2: code = 162; break; /* non-US #2 */
- case GS_KEYCODE_ESC: code = 27; break;
- case GS_KEYCODE_ENTER: code = 13; break;
- case GS_KEYCODE_TAB: code = 9; break;
- case GS_KEYCODE_BACKSPACE: code = 8; break;
- case GS_KEYCODE_INSERT: code = 260; break;
- case GS_KEYCODE_DELETE: code = 261; break;
- case GS_KEYCODE_LEFT: code = 37; break;
- case GS_KEYCODE_UP: code = 38; break;
- case GS_KEYCODE_RIGHT: code = 39; break;
- case GS_KEYCODE_DOWN: code = 40; break;
- case GS_KEYCODE_PAGE_UP: code = 266; break;
- case GS_KEYCODE_PAGE_DOWN: code = 267; break;
- case GS_KEYCODE_HOME: code = 268; break;
- case GS_KEYCODE_END: code = 269; break;
- case GS_KEYCODE_CAPS_LOCK: code = 280; break;
- case GS_KEYCODE_SCROLL_LOCK: code = 281; break;
- case GS_KEYCODE_NUM_LOCK: code = 282; break;
- case GS_KEYCODE_PRINT_SCREEN: code = 283; break;
- case GS_KEYCODE_PAUSE: code = 284; break;
- case GS_KEYCODE_F1: code = 290; break;
- case GS_KEYCODE_F2: code = 291; break;
- case GS_KEYCODE_F3: code = 292; break;
- case GS_KEYCODE_F4: code = 293; break;
- case GS_KEYCODE_F5: code = 294; break;
- case GS_KEYCODE_F6: code = 295; break;
- case GS_KEYCODE_F7: code = 296; break;
- case GS_KEYCODE_F8: code = 297; break;
- case GS_KEYCODE_F9: code = 298; break;
- case GS_KEYCODE_F10: code = 299; break;
- case GS_KEYCODE_F11: code = 300; break;
- case GS_KEYCODE_F12: code = 301; break;
- case GS_KEYCODE_F13: code = 302; break;
- case GS_KEYCODE_F14: code = 303; break;
- case GS_KEYCODE_F15: code = 304; break;
- case GS_KEYCODE_F16: code = 305; break;
- case GS_KEYCODE_F17: code = 306; break;
- case GS_KEYCODE_F18: code = 307; break;
- case GS_KEYCODE_F19: code = 308; break;
- case GS_KEYCODE_F20: code = 309; break;
- case GS_KEYCODE_F21: code = 310; break;
- case GS_KEYCODE_F22: code = 311; break;
- case GS_KEYCODE_F23: code = 312; break;
- case GS_KEYCODE_F24: code = 313; break;
- case GS_KEYCODE_F25: code = 314; break;
- case GS_KEYCODE_KP_0: code = 320; break;
- case GS_KEYCODE_KP_1: code = 321; break;
- case GS_KEYCODE_KP_2: code = 322; break;
- case GS_KEYCODE_KP_3: code = 323; break;
- case GS_KEYCODE_KP_4: code = 324; break;
- case GS_KEYCODE_KP_5: code = 325; break;
- case GS_KEYCODE_KP_6: code = 326; break;
- case GS_KEYCODE_KP_7: code = 327; break;
- case GS_KEYCODE_KP_8: code = 328; break;
- case GS_KEYCODE_KP_9: code = 329; break;
- case GS_KEYCODE_KP_DECIMAL: code = 330; break;
- case GS_KEYCODE_KP_DIVIDE: code = 331; break;
- case GS_KEYCODE_KP_MULTIPLY: code = 332; break;
- case GS_KEYCODE_KP_SUBTRACT: code = 333; break;
- case GS_KEYCODE_KP_ADD: code = 334; break;
- case GS_KEYCODE_KP_ENTER: code = 335; break;
- case GS_KEYCODE_KP_EQUAL: code = 336; break;
- case GS_KEYCODE_LEFT_SHIFT: code = 16; break;
- case GS_KEYCODE_LEFT_CONTROL: code = 17; break;
- case GS_KEYCODE_LEFT_ALT: code = 18; break;
- case GS_KEYCODE_LEFT_SUPER: code = 343; break;
- case GS_KEYCODE_RIGHT_SHIFT: code = 16; break;
- case GS_KEYCODE_RIGHT_CONTROL: code = 17; break;
- case GS_KEYCODE_RIGHT_ALT: code = 18; break;
- case GS_KEYCODE_RIGHT_SUPER: code = 347; break;
- case GS_KEYCODE_MENU: code = 348; break;
- }
- return code;
- }
- /*
- key_to_code_map[count] = gs_default_val();
- code_to_key_map[count] = gs_default_val();
- */
- // This doesn't work. Have to set up keycodes for emscripten instead. FUN.
- gs_platform_keycode gs_platform_codepoint_to_key(uint32_t code)
- {
- gs_platform_keycode key = GS_KEYCODE_INVALID;
- switch (code)
- {
- default:
- case 0: key = GS_KEYCODE_INVALID; break;
- case 32: key = GS_KEYCODE_SPACE; break;
- case 222: key = GS_KEYCODE_APOSTROPHE; break;
- case 44: key = GS_KEYCODE_COMMA; break;
- case 45: key = GS_KEYCODE_MINUS; break;
- case 46: key = GS_KEYCODE_PERIOD; break;
- case 47: key = GS_KEYCODE_SLASH; break;
- case 48: key = GS_KEYCODE_0; break;
- case 49: key = GS_KEYCODE_1; break;
- case 50: key = GS_KEYCODE_2; break;
- case 51: key = GS_KEYCODE_3; break;
- case 52: key = GS_KEYCODE_4; break;
- case 53: key = GS_KEYCODE_5; break;
- case 54: key = GS_KEYCODE_6; break;
- case 55: key = GS_KEYCODE_7; break;
- case 56: key = GS_KEYCODE_8; break;
- case 57: key = GS_KEYCODE_9; break;
- case 59: key = GS_KEYCODE_SEMICOLON; break;
- case 61: key = GS_KEYCODE_EQUAL; break;
- case 65: case 65 + 32: key = GS_KEYCODE_A; break;
- case 66: case 66 + 32: key = GS_KEYCODE_B; break;
- case 67: case 67 + 32: key = GS_KEYCODE_C; break;
- case 68: case 68 + 32: key = GS_KEYCODE_D; break;
- case 69: case 69 + 32: key = GS_KEYCODE_E; break;
- case 70: case 70 + 32: key = GS_KEYCODE_F; break;
- case 71: case 71 + 32: key = GS_KEYCODE_G; break;
- case 72: case 72 + 32: key = GS_KEYCODE_H; break;
- case 73: case 73 + 32: key = GS_KEYCODE_I; break;
- case 74: case 74 + 32: key = GS_KEYCODE_J; break;
- case 75: case 75 + 32: key = GS_KEYCODE_K; break;
- case 76: case 76 + 32: key = GS_KEYCODE_L; break;
- case 77: case 77 + 32: key = GS_KEYCODE_M; break;
- case 78: case 78 + 32: key = GS_KEYCODE_N; break;
- case 79: case 79 + 32: key = GS_KEYCODE_O; break;
- case 80: case 80 + 32: key = GS_KEYCODE_P; break;
- case 81: case 81 + 32: key = GS_KEYCODE_Q; break;
- case 82: case 82 + 32: key = GS_KEYCODE_R; break;
- case 83: case 83 + 32: key = GS_KEYCODE_S; break;
- case 84: case 84 + 32: key = GS_KEYCODE_T; break;
- case 85: case 85 + 32: key = GS_KEYCODE_U; break;
- case 86: case 86 + 32: key = GS_KEYCODE_V; break;
- case 87: case 87 + 32: key = GS_KEYCODE_W; break;
- case 88: case 88 + 32: key = GS_KEYCODE_X; break;
- case 89: case 89 + 32: key = GS_KEYCODE_Y; break;
- case 90: case 90 + 32: key = GS_KEYCODE_Z; break;
- case 91: key = GS_KEYCODE_LEFT_BRACKET; break;
- case 92: key = GS_KEYCODE_BACKSLASH; break;
- case 93: key = GS_KEYCODE_RIGHT_BRACKET; break;
- case 96: key = GS_KEYCODE_GRAVE_ACCENT; break;
- case 161: key = GS_KEYCODE_WORLD_1; break;
- case 162: key = GS_KEYCODE_WORLD_2; break;
- case 27: key = GS_KEYCODE_ESC; break;
- case 13: key = GS_KEYCODE_ENTER; break;
- case 9: key = GS_KEYCODE_TAB; break;
- case 8: key = GS_KEYCODE_BACKSPACE; break;
- case 260: key = GS_KEYCODE_INSERT; break;
- case 261: key = GS_KEYCODE_DELETE; break;
- case 37: key = GS_KEYCODE_LEFT; break;
- case 38: key = GS_KEYCODE_UP; break;
- case 39: key = GS_KEYCODE_RIGHT; break;
- case 40: key = GS_KEYCODE_DOWN; break;
- case 266: key = GS_KEYCODE_PAGE_UP; break;
- case 267: key = GS_KEYCODE_PAGE_DOWN; break;
- case 268: key = GS_KEYCODE_HOME; break;
- case 269: key = GS_KEYCODE_END; break;
- case 280: key = GS_KEYCODE_CAPS_LOCK; break;
- case 281: key = GS_KEYCODE_SCROLL_LOCK; break;
- case 282: key = GS_KEYCODE_NUM_LOCK; break;
- case 283: key = GS_KEYCODE_PRINT_SCREEN; break;
- case 284: key = GS_KEYCODE_PAUSE; break;
- case 290: key = GS_KEYCODE_F1; break;
- case 291: key = GS_KEYCODE_F2; break;
- case 292: key = GS_KEYCODE_F3; break;
- case 293: key = GS_KEYCODE_F4; break;
- case 294: key = GS_KEYCODE_F5; break;
- case 295: key = GS_KEYCODE_F6; break;
- case 296: key = GS_KEYCODE_F7; break;
- case 297: key = GS_KEYCODE_F8; break;
- case 298: key = GS_KEYCODE_F9; break;
- case 299: key = GS_KEYCODE_F10; break;
- case 300: key = GS_KEYCODE_F11; break;
- case 301: key = GS_KEYCODE_F12; break;
- case 302: key = GS_KEYCODE_F13; break;
- case 303: key = GS_KEYCODE_F14; break;
- case 304: key = GS_KEYCODE_F15; break;
- case 305: key = GS_KEYCODE_F16; break;
- case 306: key = GS_KEYCODE_F17; break;
- case 307: key = GS_KEYCODE_F18; break;
- case 308: key = GS_KEYCODE_F19; break;
- case 309: key = GS_KEYCODE_F20; break;
- case 310: key = GS_KEYCODE_F21; break;
- case 311: key = GS_KEYCODE_F22; break;
- case 312: key = GS_KEYCODE_F23; break;
- case 313: key = GS_KEYCODE_F24; break;
- case 314: key = GS_KEYCODE_F25; break;
- case 320: key = GS_KEYCODE_KP_0; break;
- case 321: key = GS_KEYCODE_KP_1; break;
- case 322: key = GS_KEYCODE_KP_2; break;
- case 323: key = GS_KEYCODE_KP_3; break;
- case 324: key = GS_KEYCODE_KP_4; break;
- case 325: key = GS_KEYCODE_KP_5; break;
- case 326: key = GS_KEYCODE_KP_6; break;
- case 327: key = GS_KEYCODE_KP_7; break;
- case 328: key = GS_KEYCODE_KP_8; break;
- case 329: key = GS_KEYCODE_KP_9; break;
- case 330: key = GS_KEYCODE_KP_DECIMAL; break;
- case 331: key = GS_KEYCODE_KP_DIVIDE; break;
- case 332: key = GS_KEYCODE_KP_MULTIPLY; break;
- case 333: key = GS_KEYCODE_KP_SUBTRACT; break;
- case 334: key = GS_KEYCODE_KP_ADD; break;
- case 335: key = GS_KEYCODE_KP_ENTER; break;
- case 336: key = GS_KEYCODE_KP_EQUAL; break;
- case 16: key = GS_KEYCODE_LEFT_SHIFT; break;
- case 17: key = GS_KEYCODE_LEFT_CONTROL; break;
- case 18: key = GS_KEYCODE_LEFT_ALT; break;
- case 343: key = GS_KEYCODE_LEFT_SUPER; break;
- case 347: key = GS_KEYCODE_RIGHT_SUPER; break;
- case 348: key = GS_KEYCODE_MENU; break;
- }
- return key;
- }
- EM_BOOL gs_ems_size_changed_cb(int32_t type, const EmscriptenUiEvent* evt, void* user_data)
- {
- gs_println("size changed");
- gs_platform_t* platform = gs_subsystem(platform);
- gs_ems_t* ems = (gs_ems_t*)platform->user_data;
- (void)type;
- (void)evt;
- (void)user_data;
- // gs_println("was: <%.2f, %.2f>", (float)ems->canvas_width, (float)ems->canvas_height);
- emscripten_get_element_css_size(ems->canvas_name, &ems->canvas_width, &ems->canvas_height);
- emscripten_set_canvas_element_size(ems->canvas_name, ems->canvas_width, ems->canvas_height);
- // gs_println("is: <%.2f, %.2f>", (float)ems->canvas_width, (float)ems->canvas_height);
- return true;
- }
- EM_BOOL gs_ems_fullscreenchange_cb(int32_t type, const EmscriptenFullscreenChangeEvent* evt, void* user_data)
- {
- (void)user_data;
- (void)evt;
- (void)type;
- gs_ems_t* ems = GS_EMS_DATA();
- // emscripten_get_element_css_size(ems->canvas_name, &ems->canvas_width, &ems->canvas_height);
- if (evt->isFullscreen) {
- EmscriptenFullscreenStrategy strategy;
- strategy.scaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF;
- strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT;
- strategy.canvasResizedCallback = (int (*)(int, const void*, void*)) gs_ems_size_changed_cb;
- emscripten_enter_soft_fullscreen(ems->canvas_name, &strategy);
- // gs_println("fullscreen!");
- // emscripten_enter_soft_fullscreen(ems->canvas_name, NULL);
- // ems->canvas_width = (float)evt->screenWidth;
- // ems->canvas_height = (float)evt->screenHeight;
- // emscripten_set_canvas_element_size(ems->canvas_name, ems->canvas_width, ems->canvas_height);
- } else {
- emscripten_exit_fullscreen();
- emscripten_set_canvas_element_size(ems->canvas_name, 800, 600);
- }
- }
- EM_BOOL gs_ems_key_cb(int32_t type, const EmscriptenKeyboardEvent* evt, void* user_data)
- {
- (void)user_data;
- // Push back event into platform events
- gs_platform_event_t gs_evt = gs_default_val();
- gs_evt.type = GS_PLATFORM_EVENT_KEY;
- gs_evt.key.codepoint = evt->which;
- gs_evt.key.keycode = gs_platform_codepoint_to_key(evt->which);
- switch (type)
- {
- case EMSCRIPTEN_EVENT_KEYPRESS:
- {
- gs_evt.type = GS_PLATFORM_EVENT_TEXT;
- gs_evt.text.codepoint = evt->which;
- } break;
- case EMSCRIPTEN_EVENT_KEYDOWN:
- {
- gs_evt.key.action = GS_PLATFORM_KEY_DOWN;
- } break;
- case EMSCRIPTEN_EVENT_KEYUP:
- {
- gs_evt.key.action = GS_PLATFORM_KEY_RELEASED;
- } break;
- default: break;
- }
- // Add action
- gs_platform_add_event(&gs_evt);
- return evt->which < 32;
- }
- EM_BOOL gs_ems_mouse_cb(int32_t type, const EmscriptenMouseEvent* evt, void* user_data)
- {
- (void)user_data;
- gs_platform_t* platform = gs_subsystem(platform);
- gs_ems_t* ems = GS_EMS_DATA();
- gs_platform_mouse_button_code button = GS_MOUSE_LBUTTON;
- switch (evt->button) {
- case 0: button = GS_MOUSE_LBUTTON; break;
- case 1: button = GS_MOUSE_MBUTTON; break;
- case 2: button = GS_MOUSE_RBUTTON; break;
- }
- // Push back event into platform events
- gs_platform_event_t gs_evt = gs_default_val();
- gs_evt.type = GS_PLATFORM_EVENT_MOUSE;
- gs_evt.mouse.codepoint = evt->button;
- gs_evt.mouse.button = button;
- bool add = true;
- switch (type)
- {
- case EMSCRIPTEN_EVENT_CLICK:
- {
- // gs_evt.mouse.action = GS_PLATFORM_MOUSE_BUTTON_PRESSED;
- // gs_println("EMS_PRESSED");
- add = false;
- } break;
- // Emscripten doesn't register continuous presses, so have to manually store this state
- case EMSCRIPTEN_EVENT_MOUSEDOWN:
- {
- gs_evt.mouse.action = GS_PLATFORM_MOUSE_BUTTON_DOWN;
- // ems->mouse_down[(int32_t)button] = true;
- } break;
- case EMSCRIPTEN_EVENT_MOUSEUP:
- {
- gs_evt.mouse.action = GS_PLATFORM_MOUSE_BUTTON_RELEASED;
- // ems->mouse_down[(int32_t)button] = false;
- } break;
- case EMSCRIPTEN_EVENT_MOUSEMOVE:
- {
- gs_evt.mouse.action = GS_PLATFORM_MOUSE_MOVE;
- if (platform->input.mouse.locked) {
- gs_evt.mouse.move = gs_v2((float)evt->movementX, (float)evt->movementY);
- } else {
- gs_evt.mouse.move = gs_v2((float)evt->targetX, (float)evt->targetY);
- }
- } break;
- case EMSCRIPTEN_EVENT_MOUSEENTER:
- {
- gs_evt.mouse.action = GS_PLATFORM_MOUSE_ENTER;
- // Release all buttons
- /*
- ems->mouse_down[0] = false;
- ems->mouse_down[1] = false;
- ems->mouse_down[2] = false;
- */
- } break;
- case EMSCRIPTEN_EVENT_MOUSELEAVE:
- {
- gs_evt.mouse.action = GS_PLATFORM_MOUSE_LEAVE;
- // Release all buttons
- /*
- ems->mouse_down[0] = false;
- ems->mouse_down[1] = false;
- ems->mouse_down[2] = false;
- */
- } break;
- default:
- {
- }break;
- }
- if (add) gs_platform_add_event(&gs_evt);
- return true;
- }
- EM_BOOL gs_ems_mousewheel_cb(int32_t type, const EmscriptenWheelEvent* evt, void* user_data)
- {
- (void)type;
- (void)user_data;
- // Push back event into platform events
- gs_platform_event_t gs_evt = gs_default_val();
- gs_evt.type = GS_PLATFORM_EVENT_MOUSE;
- gs_evt.mouse.action = GS_PLATFORM_MOUSE_WHEEL;
- gs_evt.mouse.wheel = gs_v2((float)evt->deltaX, -(float)evt->deltaY);
- gs_platform_add_event(&gs_evt);
- return true;
- }
- EM_BOOL gs_ems_pointerlock_cb(int32_t type, const EmscriptenPointerlockChangeEvent* evt, void* user_data)
- {
- (void)type;
- (void)user_data;
- gs_platform_t* platform = gs_subsystem(platform);
- platform->input.mouse.locked = evt->isActive;
- // gs_println("lock: %zu", platform->input.mouse.locked);
- }
- GS_API_DECL void
- gs_platform_init(gs_platform_t* platform)
- {
- gs_println("Initializing Emscripten.");
- gs_app_desc_t* app = gs_app();
- platform->user_data = gs_malloc_init(gs_ems_t);
- gs_ems_t* ems = (gs_ems_t*)platform->user_data;
- // ems->canvas_width = app->window_width;
- // ems->canvas_height = app->window_height;
- // double dpi = emscripten_get_device_pixel_ratio();
- // Just set this to defaults for now
- ems->canvas_name = "#canvas";
- emscripten_set_canvas_element_size(ems->canvas_name, app->window.width, app->window.height);
- emscripten_get_element_css_size(ems->canvas_name, &ems->canvas_width, &ems->canvas_height);
- // Set up callbacks
- emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, true, gs_ems_fullscreenchange_cb);
- emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, true, gs_ems_size_changed_cb);
- emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, true, gs_ems_key_cb);
- emscripten_set_keypress_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, true, gs_ems_key_cb);
- emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, true, gs_ems_key_cb);
- emscripten_set_click_callback(ems->canvas_name, NULL, true, gs_ems_mouse_cb);
- emscripten_set_mouseenter_callback(ems->canvas_name, NULL, true, gs_ems_mouse_cb);
- emscripten_set_mouseleave_callback(ems->canvas_name, NULL, true, gs_ems_mouse_cb);
- emscripten_set_mousedown_callback(ems->canvas_name, NULL, true, gs_ems_mouse_cb);
- emscripten_set_mouseup_callback(ems->canvas_name, NULL, true, gs_ems_mouse_cb);
- emscripten_set_mousemove_callback(ems->canvas_name, NULL, true, gs_ems_mouse_cb);
- emscripten_set_wheel_callback(ems->canvas_name, NULL, true, gs_ems_mousewheel_cb);
- emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, true, gs_ems_pointerlock_cb);
- // Set up webgl context
- EmscriptenWebGLContextAttributes attrs;
- emscripten_webgl_init_context_attributes(&attrs);
- attrs.antialias = false;
- attrs.depth = true;
- attrs.premultipliedAlpha = false;
- attrs.stencil = true;
- attrs.majorVersion = 2;
- attrs.minorVersion = 0;
- attrs.enableExtensionsByDefault = true;
- ems->ctx = emscripten_webgl_create_context(ems->canvas_name, &attrs);
- if (!ems->ctx) {
- gs_println("Emscripten Init: Unable to create webgl2 context. Reverting to webgl1.");
- attrs.majorVersion = 1;
- ems->ctx = emscripten_webgl_create_context(ems->canvas_name, &attrs);
- } else {
- gs_println("Emscripten Init: Successfully created webgl2 context.");
- }
- if (emscripten_webgl_make_context_current(ems->ctx) != EMSCRIPTEN_RESULT_SUCCESS) {
- gs_println("Emscripten Init: Unable to set current webgl context.");
- }
- }
- GS_API_DECL void
- gs_platform_window_set_clipboard(uint32_t handle, const char* str)
- {
- }
- GS_API_DECL const char*
- gs_platform_window_get_clipboard(uint32_t handle)
- {
- return NULL;
- }
- GS_API_DECL void
- gs_platform_lock_mouse(uint32_t handle, bool32_t lock)
- {
- gs_platform_t* platform = gs_subsystem(platform);
- gs_ems_t* ems = (gs_ems_t*)platform->user_data;
- // if (platform->input.mouse.locked == lock) return;
- platform->input.mouse.locked = lock;
- if (lock) {
- emscripten_request_pointerlock(ems->canvas_name, true);
- } else {
- emscripten_exit_pointerlock();
- }
- }
- GS_API_DECL void
- gs_platform_shutdown(gs_platform_t* platform)
- {
- // Free memory
- }
- GS_API_DECL double
- gs_platform_elapsed_time()
- {
- return emscripten_performance_now();
- }
- // Platform Video
- GS_API_DECL void
- gs_platform_enable_vsync(int32_t enabled)
- {
- // Nothing for now...
- }
- // Platform Util
- GS_API_DECL void
- gs_platform_sleep(float ms)
- {
- emscripten_sleep((uint32_t)ms);
- }
- GS_API_DECL void gs_platform_update_internal(gs_platform_t* platform)
- {
- }
- // Platform Input
- GS_API_DECL void
- gs_platform_process_input(gs_platform_input_t* input)
- {
- gs_ems_t* ems = GS_EMS_DATA();
- // Set mouse buttons
- /*
- for (uint32_t i = 0; i < GS_MOUSE_BUTTON_CODE_COUNT; ++i) {
- if (ems->mouse_down[i]) gs_platform_press_mouse_button((gs_platform_mouse_button_code)i);
- else gs_platform_release_mouse_button((gs_platform_mouse_button_code)i);
- }
- */
- // Check for pointerlock, because Chrome is retarded.
- EmscriptenPointerlockChangeEvent evt = gs_default_val();
- emscripten_get_pointerlock_status(&evt);
- if (gs_platform_mouse_locked() && !evt.isActive) {
- gs_subsystem(platform)->input.mouse.locked = false;
- }
- }
- GS_API_DECL void
- gs_platform_mouse_set_position(uint32_t handle, float x, float y)
- {
- // Not sure this is possible...
- struct gs_platform_t* platform = gs_subsystem(platform);
- platform->input.mouse.position = gs_v2(x, y);
- }
- GS_API_DECL gs_platform_window_t
- gs_platform_window_create_internal(const gs_platform_window_desc_t* desc)
- {
- // Nothing for now, since we just create this internally...
- gs_platform_window_t win = gs_default_val();
- return win;
- }
- GS_API_DECL void
- gs_platform_window_swap_buffer(uint32_t handle)
- {
- // Nothing for emscripten...but could handle swapping manually if preferred.
- }
- GS_API_DECL gs_vec2
- gs_platform_window_sizev(uint32_t handle)
- {
- gs_ems_t* ems = GS_EMS_DATA();
- return gs_v2((float)ems->canvas_width, (float)ems->canvas_height);
- }
- GS_API_DECL void
- gs_platform_window_size(uint32_t handle, uint32_t* w, uint32_t* h)
- {
- gs_ems_t* ems = GS_EMS_DATA();
- *w = (uint32_t)ems->canvas_width;
- *h = (uint32_t)ems->canvas_height;
- }
- GS_API_DECL uint32_t
- gs_platform_window_width(uint32_t handle)
- {
- gs_ems_t* ems = GS_EMS_DATA();
- return (uint32_t)ems->canvas_width;
- }
- GS_API_DECL uint32_t
- gs_platform_window_height(uint32_t handle)
- {
- gs_ems_t* ems = GS_EMS_DATA();
- return (uint32_t)ems->canvas_height;
- }
- GS_API_DECL bool32_t
- gs_platform_window_fullscreen(uint32_t handle)
- {
- return false;
- }
- GS_API_DECL void
- gs_platform_window_position(uint32_t handle, uint32_t* x, uint32_t* y)
- {
- }
- GS_API_DECL gs_vec2
- gs_platform_window_positionv(uint32_t handle)
- {
- return gs_v2(0, 0);
- }
- GS_API_DECL void
- gs_platform_set_window_size(uint32_t handle, uint32_t width, uint32_t height)
- {
- gs_ems_t* ems = GS_EMS_DATA();
- emscripten_set_canvas_element_size(ems->canvas_name, width, height);
- ems->canvas_width = (uint32_t)width;
- ems->canvas_height = (uint32_t)height;
- }
- GS_API_DECL void
- gs_platform_set_window_sizev(uint32_t handle, gs_vec2 v)
- {
- gs_ems_t* ems = GS_EMS_DATA();
- emscripten_set_canvas_element_size(ems->canvas_name, (uint32_t)v.x, (uint32_t)v.y);
- ems->canvas_width = (uint32_t)v.x;
- ems->canvas_height = (uint32_t)v.y;
- }
- GS_API_DECL void
- gs_platform_set_window_fullscreen(uint32_t handle, bool32_t fullscreen)
- {
- }
- GS_API_DECL void
- gs_platform_set_window_position(uint32_t handle, uint32_t x, uint32_t y)
- {
- }
- GS_API_DECL void
- gs_platform_set_window_positionv(uint32_t handle, gs_vec2 v)
- {
- }
- GS_API_DECL void
- gs_platform_set_cursor(uint32_t handle, gs_platform_cursor cursor)
- {
- }
- GS_API_DECL void
- gs_platform_set_dropped_files_callback(uint32_t handle, gs_dropped_files_callback_t cb)
- {
- }
- GS_API_DECL void
- gs_platform_set_window_close_callback(uint32_t handle, gs_window_close_callback_t cb)
- {
- }
- GS_API_DECL void
- gs_platform_set_character_callback(uint32_t handle, gs_character_callback_t cb)
- {
- }
- GS_API_DECL void*
- gs_platform_raw_window_handle(uint32_t handle)
- {
- return NULL;
- }
- GS_API_DECL void
- gs_platform_framebuffer_size(uint32_t handle, uint32_t* w, uint32_t* h)
- {
- gs_ems_t* ems = GS_EMS_DATA();
- // double dpi = emscripten_get_device_pixel_ratio();
- *w = (uint32_t)(ems->canvas_width);
- *h = (uint32_t)(ems->canvas_height);
- }
- GS_API_DECL gs_vec2
- gs_platform_framebuffer_sizev(uint32_t handle)
- {
- uint32_t w = 0, h = 0;
- gs_platform_framebuffer_size(handle, &w, &h);
- return gs_v2(w, h);
- }
- GS_API_DECL uint32_t
- gs_platform_framebuffer_width(uint32_t handle)
- {
- // Get ems width for now. Don't use handle.
- gs_ems_t* ems = GS_EMS_DATA();
- return (uint32_t)ems->canvas_width;
- }
- GS_API_DECL uint32_t
- gs_platform_framebuffer_height(uint32_t handle)
- {
- gs_ems_t* ems = GS_EMS_DATA();
- return (uint32_t)ems->canvas_height;
- }
- #ifndef GS_NO_HIJACK_MAIN
- int32_t main(int32_t argc, char** argv)
- {
- gs_app_desc_t app = gs_main(argc, argv);
- gs_create(app);
- emscripten_set_main_loop(gs_frame, (int32_t)app.window.frame_rate, true);
- return 0;
- }
- #endif // GS_NO_HIJACK_MAIN
- #undef GS_PLATFORM_IMPL_EMSCRIPTEN
- #endif // GS_PLATFORM_IMPL_EMSCRIPTEN
- /*=======================
- // Android Implemenation
- ========================*/
- // Modified from sokol_app.h android impl
- #ifdef GS_PLATFORM_IMPL_ANDROID
- // Platform includes
- #include <pthread.h>
- #include <unistd.h>
- #include <time.h>
- #include <android/native_activity.h>
- //#include <android_native_app_glue.h>
- #include <android/looper.h>
- #include <android/log.h>
- #include <EGL/egl.h>
- #include <GLES3/gl3.h>
- #ifndef GL_EXT_PROTOTYPES
- #define GL_GLEXT_PROTOTYPES
- #endif
- typedef enum gs_android_message_type {
- GS_ANDROID_MSG_CREATE,
- GS_ANDROID_MSG_START,
- GS_ANDROID_MSG_STOP,
- GS_ANDROID_MSG_RESUME,
- GS_ANDROID_MSG_PAUSE,
- GS_ANDROID_MSG_GAIN_FOCUS,
- GS_ANDROID_MSG_LOSE_FOCUS,
- GS_ANDROID_MSG_SET_NATIVE_WINDOW,
- GS_ANDROID_MSG_SET_INPUT_QUEUE,
- GS_ANDROID_MSG_DESTROY
- } gs_android_message_type;
- typedef struct gs_android_thread_t {
- pthread_t thread;
- pthread_mutex_t mutex;
- pthread_cond_t cond;
- int32_t read_from_main_fd;
- int32_t write_from_main_fd;
- bool is_thread_started;
- bool is_thread_stopping;
- bool is_thread_stopped;
- bool padding;
- } gs_android_thread_t;
- typedef struct gs_android_resources_t {
- ANativeWindow* window;
- AInputQueue* input;
- } gs_android_resources_t;
- typedef struct gs_android_egl_t {
- int32_t width;
- int32_t height;
- int32_t fbwidth;
- int32_t fbheight;
- EGLConfig config;
- EGLDisplay display;
- EGLContext context;
- EGLSurface surface;
- } gs_android_egl_t;
- typedef struct gs_android_state_t {
- bool has_created;
- bool has_resumed;
- bool has_focus;
- bool padding;
- } gs_android_state_t;
- typedef struct gs_android_t {
- ANativeActivity* activity;
- gs_android_thread_t gt;
- gs_android_resources_t pending;
- gs_android_resources_t current;
- ALooper* looper;
- gs_android_egl_t egl;
- gs_android_state_t state;
- const char* internal_data_path;
- } gs_android_t;
- #define GS_PLATFORM_ANDROID_DATA(...)\
- ((gs_android_t*)gs_subsystem(platform)->user_data)
- bool gs_android_should_update(gs_android_t* android)
- {
- return (android->state.has_focus && android->state.has_resumed && android->egl.surface != EGL_NO_SURFACE);
- }
- void gs_android_shutdown(gs_android_t* android)
- {
- android->gt.is_thread_stopping = true;
- }
- bool gs_android_init_egl(gs_android_t* android)
- {
- gs_assert(android->egl.display == EGL_NO_DISPLAY);
- gs_assert(android->egl.context == EGL_NO_CONTEXT);
- EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (display == EGL_NO_DISPLAY) {
- return false;
- }
- if (eglInitialize(display, NULL, NULL) == EGL_FALSE) {
- return false;
- }
- EGLint alpha_size = 8;
- const EGLint cfg_attributes[] = {
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, alpha_size,
- EGL_DEPTH_SIZE, 16,
- EGL_STENCIL_SIZE, 0,
- EGL_NONE,
- };
- EGLConfig available_cfgs[32];
- EGLint cfg_count;
- eglChooseConfig(display, cfg_attributes, available_cfgs, 32, &cfg_count);
- gs_assert(cfg_count > 0);
- gs_assert(cfg_count <= 32);
- /* find config with 8-bit rgb buffer if available, ndk sample does not trust egl spec */
- EGLConfig config;
- bool exact_cfg_found = false;
- for (int i = 0; i < cfg_count; ++i) {
- EGLConfig c = available_cfgs[i];
- EGLint r, g, b, a, d;
- if (eglGetConfigAttrib(display, c, EGL_RED_SIZE, &r) == EGL_TRUE &&
- eglGetConfigAttrib(display, c, EGL_GREEN_SIZE, &g) == EGL_TRUE &&
- eglGetConfigAttrib(display, c, EGL_BLUE_SIZE, &b) == EGL_TRUE &&
- eglGetConfigAttrib(display, c, EGL_ALPHA_SIZE, &a) == EGL_TRUE &&
- eglGetConfigAttrib(display, c, EGL_DEPTH_SIZE, &d) == EGL_TRUE &&
- r == 8 && g == 8 && b == 8 && (alpha_size == 0 || a == alpha_size) && d == 16) {
- exact_cfg_found = true;
- config = c;
- break;
- }
- }
- if (!exact_cfg_found) {
- config = available_cfgs[0];
- }
- // Force GLES3 for now
- EGLint ctx_attributes[] = {
- EGL_CONTEXT_CLIENT_VERSION, 3,
- EGL_NONE,
- };
- EGLContext context = eglCreateContext(display, config, EGL_NO_CONTEXT, ctx_attributes);
- if (context == EGL_NO_CONTEXT) {
- return false;
- }
- gs_println("EGL: Successfully initialized.");
- android->egl.config = config;
- android->egl.display = display;
- android->egl.context = context;
- return true;
- }
- bool gs_android_create_egl_surface(gs_android_t* android, ANativeWindow* window)
- {
- gs_assert(android);
- gs_assert(android->egl.display != EGL_NO_DISPLAY);
- gs_assert(android->egl.context != EGL_NO_CONTEXT);
- gs_assert(window);
- // Construct egl surface, make current
- EGLSurface surface = eglCreateWindowSurface(android->egl.display, android->egl.config, window, NULL);
- if (surface == EGL_NO_SURFACE) {
- return false;
- }
- if (eglMakeCurrent(android->egl.display, surface, surface, android->egl.context) == EGL_FALSE) {
- return false;
- }
- android->egl.surface = surface;
- return true;
- }
- bool gs_android_destroy_egl_surface(gs_android_t* android)
- {
- if (android->egl.display == EGL_NO_DISPLAY) {
- return false;
- }
- eglMakeCurrent(android->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- if (android->egl.surface != EGL_NO_SURFACE) {
- eglDestroySurface(android->egl.display, android->egl.surface);
- android->egl.surface = EGL_NO_SURFACE;
- }
- return true;
- }
- void gs_android_update_dimensions(gs_android_t* android, ANativeWindow* window, bool force_update)
- {
- gs_assert(android->egl.display != EGL_NO_DISPLAY);
- gs_assert(android->egl.context != EGL_NO_CONTEXT);
- gs_assert(android->egl.surface != EGL_NO_SURFACE);
- gs_assert(window);
- const int32_t win_w = ANativeWindow_getWidth(window);
- const int32_t win_h = ANativeWindow_getHeight(window);
- gs_assert(win_w >= 0 && win_h >= 0);
- const bool win_changed = (win_w != android->egl.width) || (win_h != android->egl.height);
- android->egl.width = win_w;
- android->egl.height = win_h;
- if (win_changed || force_update) {
- if (true) { // High dpi setting
- /*
- const int32_t buf_w = win_w / 2;
- const int32_t buf_h = win_h / 2;
- EGLint format;
- EGLBoolean egl_result = eglGetConfigAttrib(android->egl.display, android->egl.config, EGL_NATIVE_VISUAL_ID, &format);
- gs_assert(egl_result == EGL_TRUE);
- int32_t result = ANativeWindow_setBuffersGeometry(window, buf_w, buf_h, format);
- gs_assert(result == 0);
- */
- }
- }
- /* query surface size */
- EGLint fb_w, fb_h;
- EGLBoolean egl_result_w = eglQuerySurface(android->egl.display, android->egl.surface, EGL_WIDTH, &fb_w);
- EGLBoolean egl_result_h = eglQuerySurface(android->egl.display, android->egl.surface, EGL_HEIGHT, &fb_h);
- gs_assert(egl_result_w == EGL_TRUE);
- gs_assert(egl_result_h == EGL_TRUE);
- const bool fb_changed = (fb_w != android->egl.fbwidth) || (fb_h != android->egl.fbheight);
- android->egl.fbwidth = fb_w;
- android->egl.fbheight = fb_h;
- gs_println("fb: <%.2f, %.2f>, ws: <%.2f, %.2f>", (float)fb_w, (float)fb_h, (float)win_w, (float)win_h);
- // _sapp.dpi_scale = (float)_sapp.framebuffer_width / (float)_sapp.window_width;
- if (win_changed || fb_changed || force_update) {
- /*
- if (!_sapp.first_frame) {
- SOKOL_LOG("SAPP_EVENTTYPE_RESIZED");
- _sapp_android_app_event(SAPP_EVENTTYPE_RESIZED);
- }
- */
- }
- }
- bool gs_android_touch_event(AInputEvent* evt)
- {
- gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
- gs_assert(android);
- gs_assert(android->current.input);
- if (AInputEvent_getType(evt) != AINPUT_EVENT_TYPE_MOTION) {
- return false;
- }
- // Construct touch events here and call add into platform layer
- int32_t action_idx = AMotionEvent_getAction(evt);
- int32_t action = action_idx & AMOTION_EVENT_ACTION_MASK;
- // Construct platform event to add
- gs_platform_event_t gsevt = gs_default_val();
- gsevt.type = GS_PLATFORM_EVENT_TOUCH;
- switch (action) {
- case AMOTION_EVENT_ACTION_DOWN:
- case AMOTION_EVENT_ACTION_POINTER_DOWN: {
- gsevt.touch.action = GS_PLATFORM_TOUCH_DOWN;
- } break;
- case AMOTION_EVENT_ACTION_UP:
- case AMOTION_EVENT_ACTION_POINTER_UP: {
- gsevt.touch.action = GS_PLATFORM_TOUCH_UP;
- } break;
- case AMOTION_EVENT_ACTION_MOVE: {
- gsevt.touch.action = GS_PLATFORM_TOUCH_MOVE;
- } break;
- case AMOTION_EVENT_ACTION_CANCEL: {
- gsevt.touch.action = GS_PLATFORM_TOUCH_CANCEL;
- } break;
- default: {
- return false;
- } break;
- }
- int32_t idx = action_idx >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
- uint32_t num_touches = (uint32_t)AMotionEvent_getPointerCount(evt);
- if (num_touches > GS_PLATFORM_MAX_TOUCH) {
- num_touches = GS_PLATFORM_MAX_TOUCH;
- }
- for (uint32_t i = 0; i < num_touches; ++i) {
- gsevt.touch.point.id = (uintptr_t)AMotionEvent_getPointerId(evt, (size_t)i);
- gsevt.touch.point.position.x = (AMotionEvent_getRawX(evt, (size_t)i) / android->egl.width) * android->egl.fbwidth;
- gsevt.touch.point.position.y = (AMotionEvent_getRawY(evt, (size_t)i) / android->egl.height) * android->egl.fbheight;
- if (action == AMOTION_EVENT_ACTION_POINTER_DOWN ||
- action == AMOTION_EVENT_ACTION_POINTER_UP) {
- gsevt.touch.point.changed = (uint16_t)(i == idx);
- } else {
- gsevt.touch.point.changed = (uint16_t)true;
- }
- gs_platform_add_event(&gsevt);
- }
- return true;
- }
- bool gs_android_key_event(AInputEvent* evt)
- {
- if (AInputEvent_getType(evt) != AINPUT_EVENT_TYPE_KEY) {
- return false;
- }
- // Shutdown event?
- if (AKeyEvent_getKeyCode(evt) == AKEYCODE_BACK) {
- gs_println("Android: back key pressed");
- return false;
- }
- return false;
- }
- int32_t gs_android_input_cb(int32_t fd, int32_t events, void* data)
- {
- gs_android_t* android = (gs_android_t*)data;
- gs_assert(android);
- gs_assert(android->current.input);
- if ((events & ALOOPER_EVENT_INPUT) == 0) {
- gs_println("Android Main CB:Unsupported event: %zu", events);
- return 1;
- }
- // Poll for all input events
- AInputEvent* evt = NULL;
- while (AInputQueue_getEvent(android->current.input, &evt) >= 0)
- {
- if (AInputQueue_preDispatchEvent(android->current.input, evt) != 0) {
- continue;
- }
- // Register event with platform events
- int32_t handled = 0;
- if (gs_android_touch_event(evt) || gs_android_key_event(evt)) {
- handled = 1;
- }
- // Finish events
- AInputQueue_finishEvent(android->current.input, evt, handled);
- }
- return 1;
- }
- int32_t gs_android_main_cb(int32_t fd, int32_t events, void* data)
- {
- gs_android_t* android = (gs_android_t*)data;
- gs_assert(android);
- if ((events & ALOOPER_EVENT_INPUT) == 0) {
- gs_println("Android Main CB:Unsupported event: %zu", events);
- return 1;
- }
- gs_android_message_type msg;
- if (read(fd, &msg, sizeof(msg)) != sizeof(msg)) {
- gs_println("Could not write to read_from_main_fd");
- return 1;
- }
- gs_platform_event_t gsevt = gs_default_val();
- pthread_mutex_lock(&android->gt.mutex);
- switch (msg)
- {
- case GS_ANDROID_MSG_CREATE: {
- gs_println("MSG_CREATE");
- android->state.has_created = true;
- } break;
- case GS_ANDROID_MSG_START: {
- gs_println("MSG_START");
- android->state.has_resumed = true;
- if (gs_instance()) {
- gsevt.type = GS_PLATFORM_EVENT_APP;
- gsevt.app.action = GS_PLATFORM_APP_START;
- gs_platform_add_event(&gsevt);
- }
- } break;
- case GS_ANDROID_MSG_STOP: {
- gs_println("MSG_STOP");
- android->state.has_resumed = false;
- if (gs_instance()) {
- gsevt.type = GS_PLATFORM_EVENT_APP;
- gsevt.app.action = GS_PLATFORM_APP_STOP;
- gs_platform_add_event(&gsevt);
- }
- } break;
- case GS_ANDROID_MSG_RESUME: {
- gs_println("MSG_RESUME");
- android->state.has_resumed = true;
- if (gs_instance()) {
- gsevt.type = GS_PLATFORM_EVENT_APP;
- gsevt.app.action = GS_PLATFORM_APP_RESUME;
- gs_platform_add_event(&gsevt);
- }
- } break;
- case GS_ANDROID_MSG_PAUSE: {
- gs_println("MSG_PAUSE");
- android->state.has_resumed = false;
- if (gs_instance()) {
- gsevt.type = GS_PLATFORM_EVENT_APP;
- gsevt.app.action = GS_PLATFORM_APP_PAUSE;
- gs_platform_add_event(&gsevt);
- }
- } break;
- case GS_ANDROID_MSG_GAIN_FOCUS: {
- gs_println("MSG_GAIN_FOCUS");
- android->state.has_focus = true;
- if (gs_instance()) {
- gsevt.type = GS_PLATFORM_EVENT_WINDOW;
- gsevt.app.action = GS_PLATFORM_WINDOW_GAIN_FOCUS;
- gs_platform_add_event(&gsevt);
- }
- } break;
- case GS_ANDROID_MSG_LOSE_FOCUS: {
- gs_println("MSG_NO_FOCUS");
- android->state.has_focus = false;
- if (gs_instance()) {
- gsevt.type = GS_PLATFORM_EVENT_WINDOW;
- gsevt.app.action = GS_PLATFORM_WINDOW_LOSE_FOCUS;
- gs_platform_add_event(&gsevt);
- }
- } break;
- case GS_ANDROID_MSG_SET_NATIVE_WINDOW:
- {
- if (!gs_instance()) {
- gs_println("Creating engine...");
- gs_app_desc_t app = gs_main(0, NULL);
- app.android.activity = android;
- app.android.internal_data_path = android->internal_data_path;
- gs_create(app);
- android->state.has_focus = true;
- android->state.has_resumed = true;
- }
- else {
- gs_println("MSG_SET_NATIVE_WINDOW");
- if (android->current.window != android->pending.window) {
- if (android->current.window != NULL) {
- gs_android_destroy_egl_surface(android);
- }
- if (android->pending.window != NULL) {
- gs_println("Creating egl surface ...");
- if (gs_android_create_egl_surface(android, android->pending.window)) {
- gs_println("... ok!");
- gs_android_update_dimensions(android, android->pending.window, true);
- } else {
- gs_println("... failed!");
- gs_quit();
- }
- }
- }
- }
- android->current.window = android->pending.window;
- } break;
- case GS_ANDROID_MSG_SET_INPUT_QUEUE:
- {
- gs_println("MSG_SET_INPUT_QUEUE");
- if (android->current.input != android->pending.input) {
- if (android->current.input != NULL) {
- AInputQueue_detachLooper(android->current.input);
- }
- if (android->pending.input != NULL) {
- AInputQueue_attachLooper(
- android->pending.input,
- android->looper,
- ALOOPER_POLL_CALLBACK,
- gs_android_input_cb,
- android); /* data */
- }
- }
- android->current.input = android->pending.input;
- } break;
- case GS_ANDROID_MSG_DESTROY: {
- gs_println("MSG_DESTROY");
- if (gs_instance()) {
- gsevt.type = GS_PLATFORM_EVENT_WINDOW;
- gsevt.app.action = GS_PLATFORM_WINDOW_DESTROY;
- gs_platform_add_event(&gsevt);
- }
- gs_quit();
- } break;
- default: {
- gs_println("Unknown msg type received");
- } break;
- }
- pthread_cond_broadcast(&android->gt.cond);
- pthread_mutex_unlock(&android->gt.mutex);
- return 1;
- }
- void gs_android_msg(gs_android_t* android, gs_android_message_type msg)
- {
- gs_assert(android);
- if (write(android->gt.write_from_main_fd, &msg, sizeof(msg)) != sizeof(msg)) {
- gs_println("Could not write to write_from_main_fd");
- }
- gs_println("Write message sucessfully");
- }
- void gs_android_msg_set_native_window(ANativeActivity* activity, ANativeWindow* window)
- {
- gs_android_t* android = (gs_android_t*)activity->instance;
- gs_assert(android);
- pthread_mutex_lock(&android->gt.mutex);
- android->pending.window = window;
- gs_android_msg(android, GS_ANDROID_MSG_SET_NATIVE_WINDOW);
- // Spin until we set the appropriate window
- while (android->current.window != window) {
- pthread_cond_wait(&android->gt.cond, &android->gt.mutex);
- }
- pthread_mutex_unlock(&android->gt.mutex);
- }
- void gs_android_msg_set_input_queue(ANativeActivity* activity, AInputQueue* input)
- {
- gs_android_t* android = (gs_android_t*)activity->instance;
- gs_assert(android);
- pthread_mutex_lock(&android->gt.mutex);
- android->pending.input = input;
- gs_android_msg(android, GS_ANDROID_MSG_SET_INPUT_QUEUE);
- while (android->current.input != input) {
- pthread_cond_wait(&android->gt.cond, &android->gt.mutex);
- }
- pthread_mutex_unlock(&android->gt.mutex);
- }
- void gs_android_native_window_created_cb(ANativeActivity* activity, ANativeWindow* window)
- {
- gs_println("NativeActivity:onNativeWindowCreated()");
- gs_android_msg_set_native_window(activity, window);
- }
- void gs_android_window_focus_change_cb(ANativeActivity* activity, int32_t has_focus)
- {
- gs_android_t* android = (gs_android_t*)activity->instance;
- gs_assert(android);
- gs_println("NativeActivity:onNativeWindowFocusChange()");
- switch (has_focus) {
- case false: gs_android_msg(android, GS_ANDROID_MSG_LOSE_FOCUS); break;
- case true: gs_android_msg(android, GS_ANDROID_MSG_GAIN_FOCUS); break;
- }
- }
- void gs_android_resume_cb(ANativeActivity* activity)
- {
- gs_android_t* android = (gs_android_t*)activity->instance;
- gs_assert(android);
- gs_println("NativeActivity:onNativeResume()");
- gs_android_msg(android, GS_ANDROID_MSG_RESUME);
- }
- void gs_android_start_cb(ANativeActivity* activity)
- {
- gs_android_t* android = (gs_android_t*)activity->instance;
- gs_assert(android);
- gs_println("NativeActivity:onNativeStart()");
- gs_android_msg(android, GS_ANDROID_MSG_START);
- }
- void gs_android_pause_cb(ANativeActivity* activity)
- {
- gs_android_t* android = (gs_android_t*)activity->instance;
- gs_assert(android);
- gs_println("NativeActivity:onNativePause()");
- gs_android_msg(android, GS_ANDROID_MSG_PAUSE);
- }
- void gs_android_stop_cb(ANativeActivity* activity)
- {
- gs_android_t* android = (gs_android_t*)activity->instance;
- gs_assert(android);
- gs_println("NativeActivity:onNativeStop()");
- gs_android_msg(android, GS_ANDROID_MSG_STOP);
- }
- void gs_android_input_queue_created_cb(ANativeActivity* activity, AInputQueue* queue)
- {
- gs_android_msg_set_input_queue(activity, queue);
- }
- void gs_android_destroy_cb(ANativeActivity* activity)
- {
- gs_android_t* android = (gs_android_t*)activity->instance;
- gs_assert(android);
- gs_println("NativeActivity:onNativeDestroy()");
- gs_android_msg(android, GS_ANDROID_MSG_DESTROY);
- }
- void gs_android_low_memory_cb(ANativeActivity* activity)
- {
- gs_println("NativeActivity:onLowMemory()");
- }
- void gs_android_config_changed_cb(ANativeActivity* activity)
- {
- gs_println("NativeActivity:onConfigurationChanged()");
- }
- GS_API_DECL void* gs_android_loop(void* arg)
- {
- gs_println("main loop");
- gs_android_t* android = (gs_android_t*)arg;
- gs_assert(android);
- // Set up callback for polling events
- android->looper = ALooper_prepare(0);
- ALooper_addFd(android->looper, android->gt.read_from_main_fd, ALOOPER_POLL_CALLBACK, ALOOPER_EVENT_INPUT, gs_android_main_cb, android);
- // Signal to start main thread
- pthread_mutex_lock(&android->gt.mutex);
- android->gt.is_thread_started = true;
- pthread_cond_broadcast(&android->gt.cond);
- pthread_mutex_unlock(&android->gt.mutex);
- // Main application loop
- while (!android->gt.is_thread_stopping)
- {
- if (gs_android_should_update(android)) {
- gs_frame();
- }
- // Process all window/input events as they occur
- bool process = true;
- while (process && !android->gt.is_thread_stopping) {
- bool block_until_evt = !android->gt.is_thread_stopping && !gs_android_should_update(android);
- process = ALooper_pollOnce(block_until_evt ? -1 : 0, NULL, NULL, NULL) == ALOOPER_POLL_CALLBACK;
- }
- }
- // Cleanup thread after done
- if (android->current.input != NULL) {
- AInputQueue_detachLooper(android->current.input);
- }
- pthread_mutex_lock(&android->gt.mutex);
- android->gt.is_thread_stopped = true;
- pthread_cond_broadcast(&android->gt.cond);
- pthread_mutex_unlock(&android->gt.mutex);
- gs_println("Android:Thread cleanup done.");
- return NULL;
- }
- JNIEXPORT
- void ANativeActivity_onCreate(ANativeActivity* activity, void* saved_state, size_t saved_state_size)
- {
- // Construct application instance and store in activity
- activity->instance = gs_malloc_init(gs_android_t);
- gs_android_t* android = (gs_android_t*)activity->instance;
- gs_assert(android);
- // Store internal data path
- gs_println("internal data path: %s", activity->internalDataPath);
- android->internal_data_path = activity->internalDataPath;
- int32_t pfd[2];
- if (pipe(pfd) != 0) {
- gs_println("Error:ANativeActivity_onCreate:Could not create thread pipe.");
- return;
- }
- android->gt.read_from_main_fd = pfd[0];
- android->gt.write_from_main_fd = pfd[1];
- pthread_mutex_init(&android->gt.mutex, NULL);
- pthread_cond_init(&android->gt.cond, NULL);
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- gs_println("detach state");
- pthread_create(&android->gt.thread, &attr, gs_android_loop, android);
- gs_println("create pthread");
- pthread_attr_destroy(&attr);
- gs_println("destroy attribute");
- // Wait until main loop has started
- pthread_mutex_lock(&android->gt.mutex);
- while (!android->gt.is_thread_started) {
- pthread_cond_wait(&android->gt.cond, &android->gt.mutex);
- }
- pthread_mutex_unlock(&android->gt.mutex);
- // Send create message
- pthread_mutex_lock(&android->gt.mutex);
- gs_android_msg(android, GS_ANDROID_MSG_CREATE);
- while (!android->state.has_created) {
- pthread_cond_wait(&android->gt.cond, &android->gt.mutex);
- }
- pthread_mutex_unlock(&android->gt.mutex);
- // Register all callbacks
- activity->callbacks->onStart = gs_android_stop_cb;
- activity->callbacks->onResume = gs_android_resume_cb;
- activity->callbacks->onPause = gs_android_pause_cb;
- activity->callbacks->onStop = gs_android_stop_cb;
- activity->callbacks->onDestroy = gs_android_destroy_cb;
- // activity->callbacks->onSaveInstanceState = _sapp_android_on_save_instance_state;
- activity->callbacks->onNativeWindowCreated = gs_android_native_window_created_cb;
- activity->callbacks->onWindowFocusChanged = gs_android_window_focus_change_cb;
- // /* activity->callbacks->onNativeWindowResized = _sapp_android_on_native_window_resized; */
- // /* activity->callbacks->onNativeWindowRedrawNeeded = _sapp_android_on_native_window_redraw_needed; */
- // activity->callbacks->onNativeWindowDestroyed = _sapp_android_on_native_window_destroyed;
- activity->callbacks->onInputQueueCreated = gs_android_input_queue_created_cb;
- // activity->callbacks->onInputQueueDestroyed = _sapp_android_on_input_queue_destroyed;
- // /* activity->callbacks->onContentRectChanged = _sapp_android_on_content_rect_changed; */
- activity->callbacks->onConfigurationChanged = gs_android_config_changed_cb;
- activity->callbacks->onLowMemory = gs_android_low_memory_cb;
- gs_println("NativeActivity successfully created");
- }
- GS_API_DECL void
- gs_platform_init(gs_platform_t* platform)
- {
- // Get from application platform data
- gs_android_t* android = (gs_android_t*)gs_app()->android.activity;
- gs_assert(android);
- gs_app_desc_t* app = gs_app();
- platform->user_data = android;
- gs_println("Android: Init platform");
- gs_android_init_egl(platform->user_data);
- gs_println("Creating egl surface ...");
- if (gs_android_create_egl_surface(android, android->pending.window)) {
- gs_println("... ok!");
- gs_android_update_dimensions(android, android->pending.window, true);
- } else {
- gs_println("... failed!");
- // _sapp_android_shutdown();
- }
- }
- GS_API_DECL void
- gs_platform_shutdown(gs_platform_t* platform)
- {
- gs_android_shutdown(platform->user_data);
- }
- // Platform Util
- GS_API_DECL double
- gs_platform_elapsed_time()
- {
- gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
- return ((double)clock() / (double)CLOCKS_PER_SEC) * 1000.0;
- }
- GS_API_DECL void
- gs_platform_sleep(float ms)
- {
- usleep(ms * 1000.f);
- }
- // Platform Video
- GS_API_DECL void
- gs_platform_enable_vsync(int32_t enabled)
- {
- }
- // Platform Input
- GS_API_DECL void
- gs_platform_process_input(gs_platform_input_t* input)
- {
- }
- GS_API_DECL uint32_t
- gs_platform_key_to_codepoint(gs_platform_keycode code)
- {
- return 0;
- }
- GS_API_DECL gs_platform_keycode
- gs_platform_codepoint_to_key(uint32_t code)
- {
- return GS_KEYCODE_INVALID;
- }
- GS_API_DECL void
- gs_platform_mouse_set_position(uint32_t handle, float x, float y)
- {
- }
- GS_API_DECL void
- gs_platform_lock_mouse(uint32_t handle, bool32_t lock)
- {
- }
- GS_API_DECL gs_platform_window_t
- gs_platform_window_create_internal(const gs_platform_window_desc_t* desc)
- {
- // Nothing for now, since we just create this internally...
- gs_platform_window_t win = gs_default_val();
- return win;
- }
- GS_API_DECL void
- gs_platform_window_swap_buffer(uint32_t handle)
- {
- gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
- if (gs_android_should_update(android)) {
- eglSwapBuffers(android->egl.display, android->egl.surface);
- }
- }
- GS_API_DECL gs_vec2
- gs_platform_window_sizev(uint32_t handle)
- {
- gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
- return gs_v2(android->egl.width, android->egl.height);
- }
- GS_API_DECL void
- gs_platform_window_size(uint32_t handle, uint32_t* width, uint32_t* height)
- {
- gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
- *width = android->egl.width;
- *height = android->egl.height;
- }
- GS_API_DECL uint32_t
- gs_platform_window_width(uint32_t handle)
- {
- gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
- return android->egl.width;
- }
- GS_API_DECL uint32_t
- gs_platform_window_height(uint32_t handle)
- {
- gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
- return android->egl.height;
- }
- GS_API_DECL bool32_t
- gs_platform_window_fullscreen(uint32_t handle)
- {
- return false;
- }
- GS_API_DECL void
- gs_platform_window_position(uint32_t handle, uint32_t* x, uint32_t* y)
- {
- }
- GS_API_DECL gs_vec2
- gs_platform_window_positionv(uint32_t handle)
- {
- return gs_v2(0, 0);
- }
- GS_API_DECL void
- gs_platform_set_window_size(uint32_t handle, uint32_t width, uint32_t height)
- {
- }
- GS_API_DECL void
- gs_platform_set_window_sizev(uint32_t handle, gs_vec2 v)
- {
- }
- GS_API_DECL void
- gs_platform_set_window_fullscreen(uint32_t handle, bool32_t fullscreen)
- {
- }
- GS_API_DECL void
- gs_platform_set_window_position(uint32_t handle, uint32_t x, uint32_t y)
- {
- }
- GS_API_DECL void
- gs_platform_set_window_positionv(uint32_t handle, gs_vec2 v)
- {
- }
- GS_API_DECL void
- gs_platform_set_cursor(uint32_t handle, gs_platform_cursor cursor)
- {
- }
- GS_API_DECL void
- gs_platform_set_dropped_files_callback(uint32_t handle, gs_dropped_files_callback_t cb)
- {
- }
- GS_API_DECL void
- gs_platform_set_window_close_callback(uint32_t handle, gs_window_close_callback_t cb)
- {
- }
- GS_API_DECL void
- gs_platform_set_character_callback(uint32_t handle, gs_character_callback_t cb)
- {
- }
- GS_API_DECL void*
- gs_platform_raw_window_handle(uint32_t handle)
- {
- }
- GS_API_DECL gs_vec2
- gs_platform_framebuffer_sizev(uint32_t handle)
- {
- gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
- return gs_v2(android->egl.fbwidth, android->egl.fbheight);
- }
- GS_API_DECL void
- gs_platform_framebuffer_size(uint32_t handle, uint32_t* w, uint32_t* h)
- {
- gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
- *w = android->egl.fbwidth;
- *h = android->egl.fbheight;
- }
- GS_API_DECL uint32_t
- gs_platform_framebuffer_width(uint32_t handle)
- {
- gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
- return android->egl.fbwidth;
- }
- GS_API_DECL uint32_t
- gs_platform_framebuffer_height(uint32_t handle)
- {
- gs_android_t* android = GS_PLATFORM_ANDROID_DATA();
- return android->egl.fbheight;
- }
- #undef GS_PLATFORM_IMPL_ANDROID
- #endif // GS_PLATFORM_IMPL_ANDROID
- #endif // __GS_PLATFORM_IMPL_H__
|