2
0

main.cpp 191 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096
  1. /**************************************************************************/
  2. /* main.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #include "main.h"
  31. #include "core/config/project_settings.h"
  32. #include "core/core_globals.h"
  33. #include "core/crypto/crypto.h"
  34. #include "core/debugger/engine_debugger.h"
  35. #include "core/extension/extension_api_dump.h"
  36. #include "core/extension/gdextension_interface_dump.gen.h"
  37. #include "core/extension/gdextension_manager.h"
  38. #include "core/input/input.h"
  39. #include "core/input/input_map.h"
  40. #include "core/io/dir_access.h"
  41. #include "core/io/file_access_pack.h"
  42. #include "core/io/file_access_zip.h"
  43. #include "core/io/image.h"
  44. #include "core/io/image_loader.h"
  45. #include "core/io/ip.h"
  46. #include "core/io/resource_loader.h"
  47. #include "core/object/message_queue.h"
  48. #include "core/object/script_language.h"
  49. #include "core/os/os.h"
  50. #include "core/os/time.h"
  51. #include "core/register_core_types.h"
  52. #include "core/string/translation_server.h"
  53. #include "core/version.h"
  54. #include "drivers/register_driver_types.h"
  55. #include "main/app_icon.gen.h"
  56. #include "main/main_timer_sync.h"
  57. #include "main/performance.h"
  58. #include "main/splash.gen.h"
  59. #include "modules/register_module_types.h"
  60. #include "platform/register_platform_apis.h"
  61. #include "scene/main/scene_tree.h"
  62. #include "scene/main/window.h"
  63. #include "scene/property_list_helper.h"
  64. #include "scene/register_scene_types.h"
  65. #include "scene/resources/packed_scene.h"
  66. #include "scene/theme/theme_db.h"
  67. #include "servers/audio/audio_driver_dummy.h"
  68. #include "servers/audio_server.h"
  69. #include "servers/camera_server.h"
  70. #include "servers/display_server.h"
  71. #include "servers/movie_writer/movie_writer.h"
  72. #include "servers/register_server_types.h"
  73. #include "servers/rendering/rendering_server_default.h"
  74. #include "servers/text/text_server_dummy.h"
  75. #include "servers/text_server.h"
  76. // 2D
  77. #ifndef NAVIGATION_2D_DISABLED
  78. #include "servers/navigation_server_2d.h"
  79. #include "servers/navigation_server_2d_dummy.h"
  80. #endif // NAVIGATION_2D_DISABLED
  81. #ifndef PHYSICS_2D_DISABLED
  82. #include "servers/physics_server_2d.h"
  83. #include "servers/physics_server_2d_dummy.h"
  84. #endif // PHYSICS_2D_DISABLED
  85. // 3D
  86. #ifndef NAVIGATION_3D_DISABLED
  87. #include "servers/navigation_server_3d.h"
  88. #include "servers/navigation_server_3d_dummy.h"
  89. #endif // NAVIGATION_3D_DISABLED
  90. #ifndef PHYSICS_3D_DISABLED
  91. #include "servers/physics_server_3d.h"
  92. #include "servers/physics_server_3d_dummy.h"
  93. #endif // PHYSICS_3D_DISABLED
  94. #ifndef XR_DISABLED
  95. #include "servers/xr_server.h"
  96. #endif // XR_DISABLED
  97. #ifdef TESTS_ENABLED
  98. #include "tests/test_main.h"
  99. #endif
  100. #ifdef TOOLS_ENABLED
  101. #include "editor/debugger/debug_adapter/debug_adapter_server.h"
  102. #include "editor/debugger/editor_debugger_node.h"
  103. #include "editor/doc/doc_data_class_path.gen.h"
  104. #include "editor/doc/doc_tools.h"
  105. #include "editor/doc/editor_help.h"
  106. #include "editor/editor_node.h"
  107. #include "editor/file_system/editor_file_system.h"
  108. #include "editor/file_system/editor_paths.h"
  109. #include "editor/gui/progress_dialog.h"
  110. #include "editor/project_manager/project_manager.h"
  111. #include "editor/register_editor_types.h"
  112. #include "editor/settings/editor_settings.h"
  113. #include "editor/translations/editor_translation.h"
  114. #if defined(TOOLS_ENABLED) && !defined(NO_EDITOR_SPLASH)
  115. #include "main/splash_editor.gen.h"
  116. #endif
  117. #ifndef DISABLE_DEPRECATED
  118. #include "editor/project_upgrade/project_converter_3_to_4.h"
  119. #endif // DISABLE_DEPRECATED
  120. #endif // TOOLS_ENABLED
  121. #if defined(STEAMAPI_ENABLED)
  122. #include "main/steam_tracker.h"
  123. #endif
  124. #include "modules/modules_enabled.gen.h" // For mono.
  125. #if defined(MODULE_MONO_ENABLED) && defined(TOOLS_ENABLED)
  126. #include "modules/mono/editor/bindings_generator.h"
  127. #endif
  128. #ifdef MODULE_GDSCRIPT_ENABLED
  129. #include "modules/gdscript/gdscript.h"
  130. #if defined(TOOLS_ENABLED) && !defined(GDSCRIPT_NO_LSP)
  131. #include "modules/gdscript/language_server/gdscript_language_server.h"
  132. #endif // TOOLS_ENABLED && !GDSCRIPT_NO_LSP
  133. #endif // MODULE_GDSCRIPT_ENABLED
  134. /* Static members */
  135. // Singletons
  136. // Initialized in setup()
  137. static Engine *engine = nullptr;
  138. static ProjectSettings *globals = nullptr;
  139. static Input *input = nullptr;
  140. static InputMap *input_map = nullptr;
  141. static TranslationServer *translation_server = nullptr;
  142. static Performance *performance = nullptr;
  143. static PackedData *packed_data = nullptr;
  144. #ifdef MINIZIP_ENABLED
  145. static ZipArchive *zip_packed_data = nullptr;
  146. #endif
  147. static MessageQueue *message_queue = nullptr;
  148. #if defined(STEAMAPI_ENABLED)
  149. static SteamTracker *steam_tracker = nullptr;
  150. #endif
  151. // Initialized in setup2()
  152. static AudioServer *audio_server = nullptr;
  153. static CameraServer *camera_server = nullptr;
  154. static DisplayServer *display_server = nullptr;
  155. static RenderingServer *rendering_server = nullptr;
  156. static TextServerManager *tsman = nullptr;
  157. static ThemeDB *theme_db = nullptr;
  158. #ifndef PHYSICS_2D_DISABLED
  159. static PhysicsServer2DManager *physics_server_2d_manager = nullptr;
  160. static PhysicsServer2D *physics_server_2d = nullptr;
  161. #endif // PHYSICS_2D_DISABLED
  162. #ifndef PHYSICS_3D_DISABLED
  163. static PhysicsServer3DManager *physics_server_3d_manager = nullptr;
  164. static PhysicsServer3D *physics_server_3d = nullptr;
  165. #endif // PHYSICS_3D_DISABLED
  166. #ifndef XR_DISABLED
  167. static XRServer *xr_server = nullptr;
  168. #endif // XR_DISABLED
  169. // We error out if setup2() doesn't turn this true
  170. static bool _start_success = false;
  171. // Drivers
  172. String display_driver = "";
  173. String tablet_driver = "";
  174. String text_driver = "";
  175. String rendering_driver = "";
  176. String rendering_method = "";
  177. static int text_driver_idx = -1;
  178. static int audio_driver_idx = -1;
  179. // Engine config/tools
  180. static DisplayServer::AccessibilityMode accessibility_mode = DisplayServer::AccessibilityMode::ACCESSIBILITY_AUTO;
  181. static bool accessibility_mode_set = false;
  182. static bool single_window = false;
  183. static bool editor = false;
  184. static bool project_manager = false;
  185. static bool cmdline_tool = false;
  186. static String locale;
  187. static String log_file;
  188. static bool show_help = false;
  189. static uint64_t quit_after = 0;
  190. static OS::ProcessID editor_pid = 0;
  191. #ifdef TOOLS_ENABLED
  192. static bool found_project = false;
  193. static bool recovery_mode = false;
  194. static bool auto_build_solutions = false;
  195. static String debug_server_uri;
  196. static bool wait_for_import = false;
  197. static bool restore_editor_window_layout = true;
  198. #ifndef DISABLE_DEPRECATED
  199. static int converter_max_kb_file = 4 * 1024; // 4MB
  200. static int converter_max_line_length = 100000;
  201. #endif // DISABLE_DEPRECATED
  202. HashMap<Main::CLIScope, Vector<String>> forwardable_cli_arguments;
  203. #endif
  204. static bool single_threaded_scene = false;
  205. // Display
  206. static DisplayServer::WindowMode window_mode = DisplayServer::WINDOW_MODE_WINDOWED;
  207. static DisplayServer::ScreenOrientation window_orientation = DisplayServer::SCREEN_LANDSCAPE;
  208. static DisplayServer::VSyncMode window_vsync_mode = DisplayServer::VSYNC_ENABLED;
  209. static uint32_t window_flags = 0;
  210. static Size2i window_size = Size2i(1152, 648);
  211. static int init_screen = DisplayServer::SCREEN_PRIMARY;
  212. static bool init_fullscreen = false;
  213. static bool init_maximized = false;
  214. static bool init_windowed = false;
  215. static bool init_always_on_top = false;
  216. static bool init_use_custom_pos = false;
  217. static bool init_use_custom_screen = false;
  218. static Vector2 init_custom_pos;
  219. static int64_t init_embed_parent_window_id = 0;
  220. #ifdef TOOLS_ENABLED
  221. static bool init_display_scale_found = false;
  222. static int init_display_scale = 0;
  223. static bool init_custom_scale_found = false;
  224. static float init_custom_scale = 1.0;
  225. static bool init_expand_to_title = false;
  226. static bool init_expand_to_title_found = false;
  227. #endif
  228. static bool use_custom_res = true;
  229. static bool force_res = false;
  230. // Debug
  231. static bool use_debug_profiler = false;
  232. #ifdef DEBUG_ENABLED
  233. static bool debug_collisions = false;
  234. static bool debug_paths = false;
  235. static bool debug_navigation = false;
  236. static bool debug_avoidance = false;
  237. static bool debug_canvas_item_redraw = false;
  238. static bool debug_mute_audio = false;
  239. #endif
  240. static int max_fps = -1;
  241. static int frame_delay = 0;
  242. static int audio_output_latency = 0;
  243. static bool disable_render_loop = false;
  244. static int fixed_fps = -1;
  245. static MovieWriter *movie_writer = nullptr;
  246. static bool disable_vsync = false;
  247. static bool print_fps = false;
  248. #ifdef TOOLS_ENABLED
  249. static bool editor_pseudolocalization = false;
  250. static bool dump_gdextension_interface = false;
  251. static bool dump_extension_api = false;
  252. static bool include_docs_in_extension_api_dump = false;
  253. static bool validate_extension_api = false;
  254. static String validate_extension_api_file;
  255. #endif
  256. bool profile_gpu = false;
  257. // Constants.
  258. static const String NULL_DISPLAY_DRIVER("headless");
  259. static const String EMBEDDED_DISPLAY_DRIVER("embedded");
  260. static const String NULL_AUDIO_DRIVER("Dummy");
  261. // The length of the longest column in the command-line help we should align to
  262. // (excluding the 2-space left and right margins).
  263. // Currently, this is `--export-release <preset> <path>`.
  264. static const int OPTION_COLUMN_LENGTH = 32;
  265. /* Helper methods */
  266. bool Main::is_cmdline_tool() {
  267. return cmdline_tool;
  268. }
  269. #ifdef TOOLS_ENABLED
  270. const Vector<String> &Main::get_forwardable_cli_arguments(Main::CLIScope p_scope) {
  271. return forwardable_cli_arguments[p_scope];
  272. }
  273. #endif
  274. static String unescape_cmdline(const String &p_str) {
  275. return p_str.replace("%20", " ");
  276. }
  277. static String get_full_version_string() {
  278. String hash = String(GODOT_VERSION_HASH);
  279. if (!hash.is_empty()) {
  280. hash = "." + hash.left(9);
  281. }
  282. return String(GODOT_VERSION_FULL_BUILD) + hash;
  283. }
  284. #if defined(TOOLS_ENABLED) && defined(MODULE_GDSCRIPT_ENABLED)
  285. static Vector<String> get_files_with_extension(const String &p_root, const String &p_extension) {
  286. Vector<String> paths;
  287. Ref<DirAccess> dir = DirAccess::open(p_root);
  288. if (dir.is_valid()) {
  289. dir->list_dir_begin();
  290. String fn = dir->get_next();
  291. while (!fn.is_empty()) {
  292. if (!dir->current_is_hidden() && fn != "." && fn != "..") {
  293. if (dir->current_is_dir()) {
  294. paths.append_array(get_files_with_extension(p_root.path_join(fn), p_extension));
  295. } else if (fn.get_extension() == p_extension) {
  296. paths.append(p_root.path_join(fn));
  297. }
  298. }
  299. fn = dir->get_next();
  300. }
  301. dir->list_dir_end();
  302. }
  303. return paths;
  304. }
  305. #endif
  306. // FIXME: Could maybe be moved to have less code in main.cpp.
  307. void initialize_physics() {
  308. #ifndef PHYSICS_3D_DISABLED
  309. /// 3D Physics Server
  310. physics_server_3d = PhysicsServer3DManager::get_singleton()->new_server(
  311. GLOBAL_GET(PhysicsServer3DManager::setting_property_name));
  312. if (!physics_server_3d) {
  313. // Physics server not found, Use the default physics
  314. physics_server_3d = PhysicsServer3DManager::get_singleton()->new_default_server();
  315. }
  316. // Fall back to dummy if no default server has been registered.
  317. if (!physics_server_3d) {
  318. WARN_PRINT(vformat("Falling back to dummy PhysicsServer3D; 3D physics functionality will be disabled. If this is intended, set the %s project setting to Dummy.", PhysicsServer3DManager::setting_property_name));
  319. physics_server_3d = memnew(PhysicsServer3DDummy);
  320. }
  321. // Should be impossible, but make sure it's not null.
  322. ERR_FAIL_NULL_MSG(physics_server_3d, "Failed to initialize PhysicsServer3D.");
  323. physics_server_3d->init();
  324. #endif // PHYSICS_3D_DISABLED
  325. #ifndef PHYSICS_2D_DISABLED
  326. // 2D Physics server
  327. physics_server_2d = PhysicsServer2DManager::get_singleton()->new_server(
  328. GLOBAL_GET(PhysicsServer2DManager::get_singleton()->setting_property_name));
  329. if (!physics_server_2d) {
  330. // Physics server not found, Use the default physics
  331. physics_server_2d = PhysicsServer2DManager::get_singleton()->new_default_server();
  332. }
  333. // Fall back to dummy if no default server has been registered.
  334. if (!physics_server_2d) {
  335. WARN_PRINT(vformat("Falling back to dummy PhysicsServer2D; 2D physics functionality will be disabled. If this is intended, set the %s project setting to Dummy.", PhysicsServer2DManager::setting_property_name));
  336. physics_server_2d = memnew(PhysicsServer2DDummy);
  337. }
  338. // Should be impossible, but make sure it's not null.
  339. ERR_FAIL_NULL_MSG(physics_server_2d, "Failed to initialize PhysicsServer2D.");
  340. physics_server_2d->init();
  341. #endif // PHYSICS_2D_DISABLED
  342. }
  343. void finalize_physics() {
  344. #ifndef PHYSICS_3D_DISABLED
  345. physics_server_3d->finish();
  346. memdelete(physics_server_3d);
  347. #endif // PHYSICS_3D_DISABLED
  348. #ifndef PHYSICS_2D_DISABLED
  349. physics_server_2d->finish();
  350. memdelete(physics_server_2d);
  351. #endif // PHYSICS_2D_DISABLED
  352. }
  353. void finalize_display() {
  354. rendering_server->finish();
  355. memdelete(rendering_server);
  356. memdelete(display_server);
  357. }
  358. void initialize_theme_db() {
  359. theme_db = memnew(ThemeDB);
  360. }
  361. void finalize_theme_db() {
  362. memdelete(theme_db);
  363. theme_db = nullptr;
  364. }
  365. //#define DEBUG_INIT
  366. #ifdef DEBUG_INIT
  367. #define MAIN_PRINT(m_txt) print_line(m_txt)
  368. #else
  369. #define MAIN_PRINT(m_txt)
  370. #endif
  371. void Main::print_header(bool p_rich) {
  372. if (GODOT_VERSION_TIMESTAMP > 0) {
  373. // Version timestamp available.
  374. if (p_rich) {
  375. Engine::get_singleton()->print_header_rich("\u001b[38;5;39m" + String(GODOT_VERSION_NAME) + "\u001b[0m v" + get_full_version_string() + " (" + Time::get_singleton()->get_datetime_string_from_unix_time(GODOT_VERSION_TIMESTAMP, true) + " UTC) - \u001b[4m" + String(GODOT_VERSION_WEBSITE));
  376. } else {
  377. Engine::get_singleton()->print_header(String(GODOT_VERSION_NAME) + " v" + get_full_version_string() + " (" + Time::get_singleton()->get_datetime_string_from_unix_time(GODOT_VERSION_TIMESTAMP, true) + " UTC) - " + String(GODOT_VERSION_WEBSITE));
  378. }
  379. } else {
  380. if (p_rich) {
  381. Engine::get_singleton()->print_header_rich("\u001b[38;5;39m" + String(GODOT_VERSION_NAME) + "\u001b[0m v" + get_full_version_string() + " - \u001b[4m" + String(GODOT_VERSION_WEBSITE));
  382. } else {
  383. Engine::get_singleton()->print_header(String(GODOT_VERSION_NAME) + " v" + get_full_version_string() + " - " + String(GODOT_VERSION_WEBSITE));
  384. }
  385. }
  386. }
  387. /**
  388. * Prints a copyright notice in the command-line help with colored text. A newline is
  389. * automatically added at the end.
  390. */
  391. void Main::print_help_copyright(const char *p_notice) {
  392. OS::get_singleton()->print("\u001b[90m%s\u001b[0m\n", p_notice);
  393. }
  394. /**
  395. * Prints a title in the command-line help with colored text. A newline is
  396. * automatically added at beginning and at the end.
  397. */
  398. void Main::print_help_title(const char *p_title) {
  399. OS::get_singleton()->print("\n\u001b[1;93m%s:\u001b[0m\n", p_title);
  400. }
  401. /**
  402. * Returns the option string with required and optional arguments colored separately from the rest of the option.
  403. * This color replacement must be done *after* calling `rpad()` for the length padding to be done correctly.
  404. */
  405. String Main::format_help_option(const char *p_option) {
  406. return (String(p_option)
  407. .rpad(OPTION_COLUMN_LENGTH)
  408. .replace("[", "\u001b[96m[")
  409. .replace("]", "]\u001b[0m")
  410. .replace("<", "\u001b[95m<")
  411. .replace(">", ">\u001b[0m"));
  412. }
  413. /**
  414. * Prints an option in the command-line help with colored text. No newline is
  415. * added at the end. `p_availability` denotes which build types the argument is
  416. * available in. Support in release export templates implies support in debug
  417. * export templates and editor. Support in debug export templates implies
  418. * support in editor.
  419. */
  420. void Main::print_help_option(const char *p_option, const char *p_description, CLIOptionAvailability p_availability) {
  421. const bool option_empty = (p_option && !p_option[0]);
  422. if (!option_empty) {
  423. const char *availability_badge = "";
  424. switch (p_availability) {
  425. case CLI_OPTION_AVAILABILITY_EDITOR:
  426. availability_badge = "\u001b[1;91mE";
  427. break;
  428. case CLI_OPTION_AVAILABILITY_TEMPLATE_DEBUG:
  429. availability_badge = "\u001b[1;94mD";
  430. break;
  431. case CLI_OPTION_AVAILABILITY_TEMPLATE_RELEASE:
  432. availability_badge = "\u001b[1;92mR";
  433. break;
  434. case CLI_OPTION_AVAILABILITY_HIDDEN:
  435. // Use for multiline option names (but not when the option name is empty).
  436. availability_badge = " ";
  437. break;
  438. }
  439. OS::get_singleton()->print(
  440. " \u001b[92m%s %s\u001b[0m %s",
  441. format_help_option(p_option).utf8().ptr(),
  442. availability_badge,
  443. p_description);
  444. } else {
  445. // Make continuation lines for descriptions faint if the option name is empty.
  446. OS::get_singleton()->print(
  447. " \u001b[92m%s \u001b[0m \u001b[90m%s",
  448. format_help_option(p_option).utf8().ptr(),
  449. p_description);
  450. }
  451. }
  452. void Main::print_help(const char *p_binary) {
  453. print_header(true);
  454. print_help_copyright("Free and open source software under the terms of the MIT license.");
  455. print_help_copyright("(c) 2014-present Godot Engine contributors. (c) 2007-present Juan Linietsky, Ariel Manzur.");
  456. print_help_title("Usage");
  457. OS::get_singleton()->print(" %s \u001b[96m[options] [path to \"project.godot\" file]\u001b[0m\n", p_binary);
  458. #if defined(TOOLS_ENABLED)
  459. print_help_title("Option legend (this build = editor)");
  460. #elif defined(DEBUG_ENABLED)
  461. print_help_title("Option legend (this build = debug export template)");
  462. #else
  463. print_help_title("Option legend (this build = release export template)");
  464. #endif
  465. OS::get_singleton()->print(" \u001b[1;92mR\u001b[0m Available in editor builds, debug export templates and release export templates.\n");
  466. #ifdef DEBUG_ENABLED
  467. OS::get_singleton()->print(" \u001b[1;94mD\u001b[0m Available in editor builds and debug export templates only.\n");
  468. #endif
  469. #ifdef TOOLS_ENABLED
  470. OS::get_singleton()->print(" \u001b[1;91mE\u001b[0m Only available in editor builds.\n");
  471. #endif
  472. print_help_title("General options");
  473. print_help_option("-h, --help", "Display this help message.\n");
  474. print_help_option("--version", "Display the version string.\n");
  475. print_help_option("-v, --verbose", "Use verbose stdout mode.\n");
  476. print_help_option("--quiet", "Quiet mode, silences stdout messages. Errors are still displayed.\n");
  477. print_help_option("--no-header", "Do not print engine version and rendering method header on startup.\n");
  478. print_help_title("Run options");
  479. print_help_option("--, ++", "Separator for user-provided arguments. Following arguments are not used by the engine, but can be read from `OS.get_cmdline_user_args()`.\n");
  480. #ifdef TOOLS_ENABLED
  481. print_help_option("-e, --editor", "Start the editor instead of running the scene.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  482. print_help_option("-p, --project-manager", "Start the project manager, even if a project is auto-detected.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  483. print_help_option("--recovery-mode", "Start the editor in recovery mode, which disables features that can typically cause startup crashes, such as tool scripts, editor plugins, GDExtension addons, and others.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  484. print_help_option("--debug-server <uri>", "Start the editor debug server (<protocol>://<host/IP>[:port], e.g. tcp://127.0.0.1:6007)\n", CLI_OPTION_AVAILABILITY_EDITOR);
  485. print_help_option("--dap-port <port>", "Use the specified port for the GDScript Debug Adapter Protocol. Recommended port range [1024, 49151].\n", CLI_OPTION_AVAILABILITY_EDITOR);
  486. #if defined(MODULE_GDSCRIPT_ENABLED) && !defined(GDSCRIPT_NO_LSP)
  487. print_help_option("--lsp-port <port>", "Use the specified port for the GDScript Language Server Protocol. Recommended port range [1024, 49151].\n", CLI_OPTION_AVAILABILITY_EDITOR);
  488. #endif // MODULE_GDSCRIPT_ENABLED && !GDSCRIPT_NO_LSP
  489. #endif
  490. print_help_option("--quit", "Quit after the first iteration.\n");
  491. print_help_option("--quit-after <int>", "Quit after the given number of iterations. Set to 0 to disable.\n");
  492. print_help_option("-l, --language <locale>", "Use a specific locale (<locale> being a two-letter code).\n");
  493. print_help_option("--path <directory>", "Path to a project (<directory> must contain a \"project.godot\" file).\n");
  494. print_help_option("--scene <path>", "Path or UID of a scene in the project that should be started.\n");
  495. print_help_option("-u, --upwards", "Scan folders upwards for project.godot file.\n");
  496. print_help_option("--main-pack <file>", "Path to a pack (.pck) file to load.\n");
  497. #ifdef DISABLE_DEPRECATED
  498. print_help_option("--render-thread <mode>", "Render thread mode (\"safe\", \"separate\").\n");
  499. #else
  500. print_help_option("--render-thread <mode>", "Render thread mode (\"unsafe\" [deprecated], \"safe\", \"separate\").\n");
  501. #endif
  502. print_help_option("--remote-fs <address>", "Remote filesystem (<host/IP>[:<port>] address).\n");
  503. print_help_option("--remote-fs-password <password>", "Password for remote filesystem.\n");
  504. print_help_option("--audio-driver <driver>", "Audio driver [");
  505. for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) {
  506. if (i > 0) {
  507. OS::get_singleton()->print(", ");
  508. }
  509. OS::get_singleton()->print("\"%s\"", AudioDriverManager::get_driver(i)->get_name());
  510. }
  511. OS::get_singleton()->print("].\n");
  512. print_help_option("--display-driver <driver>", "Display driver (and rendering driver) [");
  513. for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
  514. if (i > 0) {
  515. OS::get_singleton()->print(", ");
  516. }
  517. OS::get_singleton()->print("\"%s\" (", DisplayServer::get_create_function_name(i));
  518. Vector<String> rd = DisplayServer::get_create_function_rendering_drivers(i);
  519. for (int j = 0; j < rd.size(); j++) {
  520. if (j > 0) {
  521. OS::get_singleton()->print(", ");
  522. }
  523. OS::get_singleton()->print("\"%s\"", rd[j].utf8().get_data());
  524. }
  525. OS::get_singleton()->print(")");
  526. }
  527. OS::get_singleton()->print("].\n");
  528. print_help_option("--audio-output-latency <ms>", "Override audio output latency in milliseconds (default is 15 ms).\n");
  529. print_help_option("", "Lower values make sound playback more reactive but increase CPU usage, and may result in audio cracking if the CPU can't keep up.\n");
  530. print_help_option("--rendering-method <renderer>", "Renderer name. Requires driver support.\n");
  531. print_help_option("--rendering-driver <driver>", "Rendering driver (depends on display driver).\n");
  532. print_help_option("--gpu-index <device_index>", "Use a specific GPU (run with --verbose to get a list of available devices).\n");
  533. print_help_option("--text-driver <driver>", "Text driver (used for font rendering, bidirectional support and shaping).\n");
  534. print_help_option("--tablet-driver <driver>", "Pen tablet input driver.\n");
  535. print_help_option("--headless", "Enable headless mode (--display-driver headless --audio-driver Dummy). Useful for servers and with --script.\n");
  536. print_help_option("--log-file <file>", "Write output/error log to the specified path instead of the default location defined by the project.\n");
  537. print_help_option("", "<file> path should be absolute or relative to the project directory.\n");
  538. print_help_option("--write-movie <file>", "Write a video to the specified path (usually with .avi or .png extension).\n");
  539. print_help_option("", "--fixed-fps is forced when enabled, but it can be used to change movie FPS.\n");
  540. print_help_option("", "--disable-vsync can speed up movie writing but makes interaction more difficult.\n");
  541. print_help_option("", "--quit-after can be used to specify the number of frames to write.\n");
  542. print_help_title("Display options");
  543. print_help_option("-f, --fullscreen", "Request fullscreen mode.\n");
  544. print_help_option("-m, --maximized", "Request a maximized window.\n");
  545. print_help_option("-w, --windowed", "Request windowed mode.\n");
  546. print_help_option("-t, --always-on-top", "Request an always-on-top window.\n");
  547. print_help_option("--resolution <W>x<H>", "Request window resolution.\n");
  548. print_help_option("--position <X>,<Y>", "Request window position.\n");
  549. print_help_option("--screen <N>", "Request window screen.\n");
  550. print_help_option("--single-window", "Use a single window (no separate subwindows).\n");
  551. #ifndef _3D_DISABLED
  552. print_help_option("--xr-mode <mode>", "Select XR (Extended Reality) mode [\"default\", \"off\", \"on\"].\n");
  553. #endif
  554. print_help_option("--wid <window_id>", "Request parented to window.\n");
  555. print_help_option("--accessibility <mode>", "Select accessibility mode ['auto' (when screen reader is running, default), 'always', 'disabled'].\n");
  556. print_help_title("Debug options");
  557. print_help_option("-d, --debug", "Debug (local stdout debugger).\n");
  558. print_help_option("-b, --breakpoints", "Breakpoint list as source::line comma-separated pairs, no spaces (use %%20 instead).\n");
  559. print_help_option("--ignore-error-breaks", "If debugger is connected, prevents sending error breakpoints.\n");
  560. print_help_option("--profiling", "Enable profiling in the script debugger.\n");
  561. print_help_option("--gpu-profile", "Show a GPU profile of the tasks that took the most time during frame rendering.\n");
  562. print_help_option("--gpu-validation", "Enable graphics API validation layers for debugging.\n");
  563. #ifdef DEBUG_ENABLED
  564. print_help_option("--gpu-abort", "Abort on graphics API usage errors (usually validation layer errors). May help see the problem if your system freezes.\n", CLI_OPTION_AVAILABILITY_TEMPLATE_DEBUG);
  565. #endif
  566. print_help_option("--generate-spirv-debug-info", "Generate SPIR-V debug information. This allows source-level shader debugging with RenderDoc.\n");
  567. #if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)
  568. print_help_option("--extra-gpu-memory-tracking", "Enables additional memory tracking (see class reference for `RenderingDevice.get_driver_and_device_memory_report()` and linked methods). Currently only implemented for Vulkan. Enabling this feature may cause crashes on some systems due to buggy drivers or bugs in the Vulkan Loader. See https://github.com/godotengine/godot/issues/95967\n");
  569. print_help_option("--accurate-breadcrumbs", "Force barriers between breadcrumbs. Useful for narrowing down a command causing GPU resets. Currently only implemented for Vulkan.\n");
  570. #endif
  571. print_help_option("--remote-debug <uri>", "Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n");
  572. print_help_option("--single-threaded-scene", "Force scene tree to run in single-threaded mode. Sub-thread groups are disabled and run on the main thread.\n");
  573. #if defined(DEBUG_ENABLED)
  574. print_help_option("--debug-collisions", "Show collision shapes when running the scene.\n", CLI_OPTION_AVAILABILITY_TEMPLATE_DEBUG);
  575. print_help_option("--debug-paths", "Show path lines when running the scene.\n", CLI_OPTION_AVAILABILITY_TEMPLATE_DEBUG);
  576. print_help_option("--debug-navigation", "Show navigation polygons when running the scene.\n", CLI_OPTION_AVAILABILITY_TEMPLATE_DEBUG);
  577. print_help_option("--debug-avoidance", "Show navigation avoidance debug visuals when running the scene.\n", CLI_OPTION_AVAILABILITY_TEMPLATE_DEBUG);
  578. print_help_option("--debug-stringnames", "Print all StringName allocations to stdout when the engine quits.\n", CLI_OPTION_AVAILABILITY_TEMPLATE_DEBUG);
  579. print_help_option("--debug-canvas-item-redraw", "Display a rectangle each time a canvas item requests a redraw (useful to troubleshoot low processor mode).\n", CLI_OPTION_AVAILABILITY_TEMPLATE_DEBUG);
  580. #endif
  581. print_help_option("--max-fps <fps>", "Set a maximum number of frames per second rendered (can be used to limit power usage). A value of 0 results in unlimited framerate.\n");
  582. print_help_option("--frame-delay <ms>", "Simulate high CPU load (delay each frame by <ms> milliseconds). Do not use as a FPS limiter; use --max-fps instead.\n");
  583. print_help_option("--time-scale <scale>", "Force time scale (higher values are faster, 1.0 is normal speed).\n");
  584. print_help_option("--disable-vsync", "Forces disabling of vertical synchronization, even if enabled in the project settings. Does not override driver-level V-Sync enforcement.\n");
  585. print_help_option("--disable-render-loop", "Disable render loop so rendering only occurs when called explicitly from script.\n");
  586. print_help_option("--disable-crash-handler", "Disable crash handler when supported by the platform code.\n");
  587. print_help_option("--fixed-fps <fps>", "Force a fixed number of frames per second. This setting disables real-time synchronization.\n");
  588. print_help_option("--delta-smoothing <enable>", "Enable or disable frame delta smoothing [\"enable\", \"disable\"].\n");
  589. print_help_option("--print-fps", "Print the frames per second to the stdout.\n");
  590. #ifdef TOOLS_ENABLED
  591. print_help_option("--editor-pseudolocalization", "Enable pseudolocalization for the editor and the project manager.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  592. #endif
  593. print_help_title("Standalone tools");
  594. print_help_option("-s, --script <script>", "Run a script.\n");
  595. print_help_option("--main-loop <main_loop_name>", "Run a MainLoop specified by its global class name.\n");
  596. print_help_option("--check-only", "Only parse for errors and quit (use with --script).\n");
  597. #ifdef TOOLS_ENABLED
  598. print_help_option("--import", "Starts the editor, waits for any resources to be imported, and then quits.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  599. print_help_option("--export-release <preset> <path>", "Export the project in release mode using the given preset and output path. The preset name should match one defined in \"export_presets.cfg\".\n", CLI_OPTION_AVAILABILITY_EDITOR);
  600. print_help_option("", "<path> should be absolute or relative to the project directory, and include the filename for the binary (e.g. \"builds/game.exe\").\n");
  601. print_help_option("", "The target directory must exist.\n");
  602. print_help_option("--export-debug <preset> <path>", "Export the project in debug mode using the given preset and output path. See --export-release description for other considerations.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  603. print_help_option("--export-pack <preset> <path>", "Export the project data only using the given preset and output path. The <path> extension determines whether it will be in PCK or ZIP format.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  604. print_help_option("--export-patch <preset> <path>", "Export pack with changed files only. See --export-pack description for other considerations.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  605. print_help_option("--patches <paths>", "List of patches to use with --export-patch. The list is comma-separated.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  606. print_help_option("--install-android-build-template", "Install the Android build template. Used in conjunction with --export-release or --export-debug.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  607. #ifndef DISABLE_DEPRECATED
  608. // Commands are long; split the description to a second line.
  609. print_help_option("--convert-3to4 ", "\n", CLI_OPTION_AVAILABILITY_HIDDEN);
  610. print_help_option(" [max_file_kb] [max_line_size]", "Converts project from Godot 3.x to Godot 4.x.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  611. print_help_option("--validate-conversion-3to4 ", "\n", CLI_OPTION_AVAILABILITY_HIDDEN);
  612. print_help_option(" [max_file_kb] [max_line_size]", "Shows what elements will be renamed when converting project from Godot 3.x to Godot 4.x.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  613. #endif // DISABLE_DEPRECATED
  614. print_help_option("--doctool [path]", "Dump the engine API reference to the given <path> (defaults to current directory) in XML format, merging if existing files are found.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  615. print_help_option("--no-docbase", "Disallow dumping the base types (used with --doctool).\n", CLI_OPTION_AVAILABILITY_EDITOR);
  616. print_help_option("--gdextension-docs", "Rather than dumping the engine API, generate API reference from all the GDExtensions loaded in the current project (used with --doctool).\n", CLI_OPTION_AVAILABILITY_EDITOR);
  617. #ifdef MODULE_GDSCRIPT_ENABLED
  618. print_help_option("--gdscript-docs <path>", "Rather than dumping the engine API, generate API reference from the inline documentation in the GDScript files found in <path> (used with --doctool).\n", CLI_OPTION_AVAILABILITY_EDITOR);
  619. #endif
  620. print_help_option("--build-solutions", "Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  621. print_help_option("--dump-gdextension-interface", "Generate a GDExtension header file \"gdextension_interface.h\" in the current folder. This file is the base file required to implement a GDExtension.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  622. print_help_option("--dump-extension-api", "Generate a JSON dump of the Godot API for GDExtension bindings named \"extension_api.json\" in the current folder.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  623. print_help_option("--dump-extension-api-with-docs", "Generate JSON dump of the Godot API like the previous option, but including documentation.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  624. print_help_option("--validate-extension-api <path>", "Validate an extension API file dumped (with one of the two previous options) from a previous version of the engine to ensure API compatibility.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  625. print_help_option("", "If incompatibilities or errors are detected, the exit code will be non-zero.\n");
  626. print_help_option("--benchmark", "Benchmark the run time and print it to console.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  627. print_help_option("--benchmark-file <path>", "Benchmark the run time and save it to a given file in JSON format. The path should be absolute.\n", CLI_OPTION_AVAILABILITY_EDITOR);
  628. #endif // TOOLS_ENABLED
  629. #ifdef TESTS_ENABLED
  630. print_help_option("--test [--help]", "Run unit tests. Use --test --help for more information.\n");
  631. #endif // TESTS_ENABLED
  632. OS::get_singleton()->print("\n");
  633. }
  634. #ifdef TESTS_ENABLED
  635. // The order is the same as in `Main::setup()`, only core and some editor types
  636. // are initialized here. This also combines `Main::setup2()` initialization.
  637. Error Main::test_setup() {
  638. Thread::make_main_thread();
  639. set_current_thread_safe_for_nodes(true);
  640. OS::get_singleton()->initialize();
  641. engine = memnew(Engine);
  642. register_core_types();
  643. register_core_driver_types();
  644. packed_data = memnew(PackedData);
  645. globals = memnew(ProjectSettings);
  646. register_core_settings(); // Here globals are present.
  647. translation_server = memnew(TranslationServer);
  648. tsman = memnew(TextServerManager);
  649. if (tsman) {
  650. Ref<TextServerDummy> ts;
  651. ts.instantiate();
  652. tsman->add_interface(ts);
  653. }
  654. #ifndef PHYSICS_3D_DISABLED
  655. physics_server_3d_manager = memnew(PhysicsServer3DManager);
  656. #endif // PHYSICS_3D_DISABLED
  657. #ifndef PHYSICS_2D_DISABLED
  658. physics_server_2d_manager = memnew(PhysicsServer2DManager);
  659. #endif // PHYSICS_2D_DISABLED
  660. // From `Main::setup2()`.
  661. register_early_core_singletons();
  662. initialize_modules(MODULE_INITIALIZATION_LEVEL_CORE);
  663. register_core_extensions();
  664. register_core_singletons();
  665. /** INITIALIZE SERVERS **/
  666. register_server_types();
  667. #ifndef XR_DISABLED
  668. XRServer::set_xr_mode(XRServer::XRMODE_OFF); // Skip in tests.
  669. #endif // XR_DISABLED
  670. initialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS);
  671. GDExtensionManager::get_singleton()->initialize_extensions(GDExtension::INITIALIZATION_LEVEL_SERVERS);
  672. translation_server->setup(); //register translations, load them, etc.
  673. if (!locale.is_empty()) {
  674. translation_server->set_locale(locale);
  675. }
  676. translation_server->load_translations();
  677. ResourceLoader::load_translation_remaps(); //load remaps for resources
  678. // Initialize ThemeDB early so that scene types can register their theme items.
  679. // Default theme will be initialized later, after modules and ScriptServer are ready.
  680. initialize_theme_db();
  681. #ifndef NAVIGATION_3D_DISABLED
  682. NavigationServer3DManager::initialize_server();
  683. #endif // NAVIGATION_3D_DISABLED
  684. #ifndef NAVIGATION_2D_DISABLED
  685. NavigationServer2DManager::initialize_server();
  686. #endif // NAVIGATION_2D_DISABLED
  687. register_scene_types();
  688. register_driver_types();
  689. register_scene_singletons();
  690. initialize_modules(MODULE_INITIALIZATION_LEVEL_SCENE);
  691. GDExtensionManager::get_singleton()->initialize_extensions(GDExtension::INITIALIZATION_LEVEL_SCENE);
  692. #ifdef TOOLS_ENABLED
  693. ClassDB::set_current_api(ClassDB::API_EDITOR);
  694. register_editor_types();
  695. initialize_modules(MODULE_INITIALIZATION_LEVEL_EDITOR);
  696. GDExtensionManager::get_singleton()->initialize_extensions(GDExtension::INITIALIZATION_LEVEL_EDITOR);
  697. ClassDB::set_current_api(ClassDB::API_CORE);
  698. #endif
  699. register_platform_apis();
  700. // Theme needs modules to be initialized so that sub-resources can be loaded.
  701. theme_db->initialize_theme_noproject();
  702. ERR_FAIL_COND_V(TextServerManager::get_singleton()->get_interface_count() == 0, ERR_CANT_CREATE);
  703. /* Use one with the most features available. */
  704. int max_features = 0;
  705. for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
  706. uint32_t features = TextServerManager::get_singleton()->get_interface(i)->get_features();
  707. int feature_number = 0;
  708. while (features) {
  709. feature_number += features & 1;
  710. features >>= 1;
  711. }
  712. if (feature_number >= max_features) {
  713. max_features = feature_number;
  714. text_driver_idx = i;
  715. }
  716. }
  717. if (text_driver_idx >= 0) {
  718. Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(text_driver_idx);
  719. TextServerManager::get_singleton()->set_primary_interface(ts);
  720. if (ts->has_feature(TextServer::FEATURE_USE_SUPPORT_DATA)) {
  721. ts->load_support_data("res://" + ts->get_support_data_filename());
  722. }
  723. } else {
  724. ERR_FAIL_V_MSG(ERR_CANT_CREATE, "TextServer: Unable to create TextServer interface.");
  725. }
  726. ClassDB::set_current_api(ClassDB::API_NONE);
  727. _start_success = true;
  728. return OK;
  729. }
  730. // The order is the same as in `Main::cleanup()`.
  731. void Main::test_cleanup() {
  732. ERR_FAIL_COND(!_start_success);
  733. for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
  734. TextServerManager::get_singleton()->get_interface(i)->cleanup();
  735. }
  736. ResourceLoader::remove_custom_loaders();
  737. ResourceSaver::remove_custom_savers();
  738. PropertyListHelper::clear_base_helpers();
  739. #ifdef TOOLS_ENABLED
  740. GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_EDITOR);
  741. uninitialize_modules(MODULE_INITIALIZATION_LEVEL_EDITOR);
  742. unregister_editor_types();
  743. #endif
  744. GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_SCENE);
  745. uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SCENE);
  746. unregister_platform_apis();
  747. unregister_driver_types();
  748. unregister_scene_types();
  749. finalize_theme_db();
  750. #ifndef NAVIGATION_2D_DISABLED
  751. NavigationServer2DManager::finalize_server();
  752. #endif // NAVIGATION_2D_DISABLED
  753. #ifndef NAVIGATION_3D_DISABLED
  754. NavigationServer3DManager::finalize_server();
  755. #endif // NAVIGATION_3D_DISABLED
  756. GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_SERVERS);
  757. uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS);
  758. unregister_server_types();
  759. EngineDebugger::deinitialize();
  760. OS::get_singleton()->finalize();
  761. if (packed_data) {
  762. memdelete(packed_data);
  763. }
  764. if (translation_server) {
  765. memdelete(translation_server);
  766. }
  767. if (tsman) {
  768. memdelete(tsman);
  769. }
  770. #ifndef PHYSICS_3D_DISABLED
  771. if (physics_server_3d_manager) {
  772. memdelete(physics_server_3d_manager);
  773. }
  774. #endif // PHYSICS_3D_DISABLED
  775. #ifndef PHYSICS_2D_DISABLED
  776. if (physics_server_2d_manager) {
  777. memdelete(physics_server_2d_manager);
  778. }
  779. #endif // PHYSICS_2D_DISABLED
  780. if (globals) {
  781. memdelete(globals);
  782. }
  783. unregister_core_driver_types();
  784. unregister_core_extensions();
  785. uninitialize_modules(MODULE_INITIALIZATION_LEVEL_CORE);
  786. if (engine) {
  787. memdelete(engine);
  788. }
  789. unregister_core_types();
  790. OS::get_singleton()->finalize_core();
  791. }
  792. #endif
  793. int Main::test_entrypoint(int argc, char *argv[], bool &tests_need_run) {
  794. for (int x = 0; x < argc; x++) {
  795. // Early return to ignore a possible user-provided "--test" argument.
  796. if ((strlen(argv[x]) == 2) && ((strncmp(argv[x], "--", 2) == 0) || (strncmp(argv[x], "++", 2) == 0))) {
  797. tests_need_run = false;
  798. return EXIT_SUCCESS;
  799. }
  800. if ((strncmp(argv[x], "--test", 6) == 0) && (strlen(argv[x]) == 6)) {
  801. tests_need_run = true;
  802. #ifdef TESTS_ENABLED
  803. // TODO: need to come up with different test contexts.
  804. // Not every test requires high-level functionality like `ClassDB`.
  805. test_setup();
  806. int status = test_main(argc, argv);
  807. test_cleanup();
  808. return status;
  809. #else
  810. ERR_PRINT(
  811. "`--test` was specified on the command line, but this Godot binary was compiled without support for unit tests. Aborting.\n"
  812. "To be able to run unit tests, use the `tests=yes` SCons option when compiling Godot.\n");
  813. return EXIT_FAILURE;
  814. #endif
  815. }
  816. }
  817. tests_need_run = false;
  818. return EXIT_SUCCESS;
  819. }
  820. /* Engine initialization
  821. *
  822. * Consists of several methods that are called by each platform's specific main(argc, argv).
  823. * To fully understand engine init, one should therefore start from the platform's main and
  824. * see how it calls into the Main class' methods.
  825. *
  826. * The initialization is typically done in 3 steps (with the setup2 step triggered either
  827. * automatically by setup, or manually in the platform's main).
  828. *
  829. * - setup(execpath, argc, argv, p_second_phase) is the main entry point for all platforms,
  830. * responsible for the initialization of all low level singletons and core types, and parsing
  831. * command line arguments to configure things accordingly.
  832. * If p_second_phase is true, it will chain into setup2() (default behavior). This is
  833. * disabled on some platforms (Android, iOS) which trigger the second step in their own time.
  834. *
  835. * - setup2(p_main_tid_override) registers high level servers and singletons, displays the
  836. * boot splash, then registers higher level types (scene, editor, etc.).
  837. *
  838. * - start() is the last step and that's where command line tools can run, or the main loop
  839. * can be created eventually and the project settings put into action. That's also where
  840. * the editor node is created, if relevant.
  841. * start() does it own argument parsing for a subset of the command line arguments described
  842. * in help, it's a bit messy and should be globalized with the setup() parsing somehow.
  843. */
  844. Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_phase) {
  845. Thread::make_main_thread();
  846. set_current_thread_safe_for_nodes(true);
  847. OS::get_singleton()->initialize();
  848. // Benchmark tracking must be done after `OS::get_singleton()->initialize()` as on some
  849. // platforms, it's used to set up the time utilities.
  850. OS::get_singleton()->benchmark_begin_measure("Startup", "Main::Setup");
  851. engine = memnew(Engine);
  852. MAIN_PRINT("Main: Initialize CORE");
  853. register_core_types();
  854. register_core_driver_types();
  855. MAIN_PRINT("Main: Initialize Globals");
  856. input_map = memnew(InputMap);
  857. globals = memnew(ProjectSettings);
  858. register_core_settings(); //here globals are present
  859. translation_server = memnew(TranslationServer);
  860. performance = memnew(Performance);
  861. GDREGISTER_CLASS(Performance);
  862. engine->add_singleton(Engine::Singleton("Performance", performance));
  863. // Only flush stdout in debug builds by default, as spamming `print()` will
  864. // decrease performance if this is enabled.
  865. GLOBAL_DEF_RST("application/run/flush_stdout_on_print", false);
  866. GLOBAL_DEF_RST("application/run/flush_stdout_on_print.debug", true);
  867. MAIN_PRINT("Main: Parse CMDLine");
  868. /* argument parsing and main creation */
  869. List<String> args;
  870. List<String> main_args;
  871. List<String> user_args;
  872. bool adding_user_args = false;
  873. List<String> platform_args = OS::get_singleton()->get_cmdline_platform_args();
  874. // Add command line arguments.
  875. for (int i = 0; i < argc; i++) {
  876. args.push_back(String::utf8(argv[i]));
  877. }
  878. // Add arguments received from macOS LaunchService (URL schemas, file associations).
  879. for (const String &arg : platform_args) {
  880. args.push_back(arg);
  881. }
  882. List<String>::Element *I = args.front();
  883. while (I) {
  884. I->get() = unescape_cmdline(I->get().strip_edges());
  885. I = I->next();
  886. }
  887. String audio_driver = "";
  888. String project_path = ".";
  889. bool upwards = false;
  890. String debug_uri = "";
  891. #if defined(TOOLS_ENABLED) && (defined(WINDOWS_ENABLED) || defined(LINUXBSD_ENABLED))
  892. bool test_rd_creation = false;
  893. bool test_rd_support = false;
  894. #endif
  895. bool skip_breakpoints = false;
  896. bool ignore_error_breaks = false;
  897. String main_pack;
  898. bool quiet_stdout = false;
  899. int separate_thread_render = -1; // Tri-state: -1 = not set, 0 = false, 1 = true.
  900. String remotefs;
  901. String remotefs_pass;
  902. Vector<String> breakpoints;
  903. bool delta_smoothing_override = false;
  904. bool load_shell_env = false;
  905. String default_renderer = "";
  906. String default_renderer_mobile = "";
  907. String renderer_hints = "";
  908. packed_data = PackedData::get_singleton();
  909. if (!packed_data) {
  910. packed_data = memnew(PackedData);
  911. }
  912. #ifdef MINIZIP_ENABLED
  913. //XXX: always get_singleton() == 0x0
  914. zip_packed_data = ZipArchive::get_singleton();
  915. //TODO: remove this temporary fix
  916. if (!zip_packed_data) {
  917. zip_packed_data = memnew(ZipArchive);
  918. }
  919. packed_data->add_pack_source(zip_packed_data);
  920. #endif
  921. // Exit error code used in the `goto error` conditions.
  922. // It's returned as the program exit code. ERR_HELP is special cased and handled as success (0).
  923. Error exit_err = ERR_INVALID_PARAMETER;
  924. I = args.front();
  925. while (I) {
  926. List<String>::Element *N = I->next();
  927. const String &arg = I->get();
  928. #ifdef MACOS_ENABLED
  929. // Ignore the process serial number argument passed by macOS Gatekeeper.
  930. // Otherwise, Godot would try to open a non-existent project on the first start and abort.
  931. if (arg.begins_with("-psn_")) {
  932. I = N;
  933. continue;
  934. }
  935. #endif
  936. #ifdef TOOLS_ENABLED
  937. if (arg == "--debug" ||
  938. arg == "--verbose" ||
  939. arg == "--disable-crash-handler") {
  940. forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(arg);
  941. forwardable_cli_arguments[CLI_SCOPE_PROJECT].push_back(arg);
  942. }
  943. if (arg == "--single-window") {
  944. forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(arg);
  945. }
  946. if (arg == "--audio-driver" ||
  947. arg == "--display-driver" ||
  948. arg == "--rendering-method" ||
  949. arg == "--rendering-driver" ||
  950. arg == "--xr-mode") {
  951. if (N) {
  952. forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(arg);
  953. forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(N->get());
  954. }
  955. }
  956. // If gpu is specified, both editor and debug instances started from editor will inherit.
  957. if (arg == "--gpu-index") {
  958. if (N) {
  959. const String &next_arg = N->get();
  960. forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(arg);
  961. forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(next_arg);
  962. forwardable_cli_arguments[CLI_SCOPE_PROJECT].push_back(arg);
  963. forwardable_cli_arguments[CLI_SCOPE_PROJECT].push_back(next_arg);
  964. }
  965. }
  966. #endif
  967. if (adding_user_args) {
  968. user_args.push_back(arg);
  969. } else if (arg == "-h" || arg == "--help" || arg == "/?") { // display help
  970. show_help = true;
  971. exit_err = ERR_HELP; // Hack to force an early exit in `main()` with a success code.
  972. goto error;
  973. } else if (arg == "--version") {
  974. print_line(get_full_version_string());
  975. exit_err = ERR_HELP; // Hack to force an early exit in `main()` with a success code.
  976. goto error;
  977. } else if (arg == "-v" || arg == "--verbose") { // verbose output
  978. OS::get_singleton()->_verbose_stdout = true;
  979. } else if (arg == "-q" || arg == "--quiet") { // quieter output
  980. quiet_stdout = true;
  981. } else if (arg == "--no-header") {
  982. Engine::get_singleton()->_print_header = false;
  983. } else if (arg == "--audio-driver") { // audio driver
  984. if (N) {
  985. audio_driver = N->get();
  986. bool found = false;
  987. for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) {
  988. if (audio_driver == AudioDriverManager::get_driver(i)->get_name()) {
  989. found = true;
  990. }
  991. }
  992. if (!found) {
  993. OS::get_singleton()->print("Unknown audio driver '%s', aborting.\nValid options are ",
  994. audio_driver.utf8().get_data());
  995. for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) {
  996. if (i == AudioDriverManager::get_driver_count() - 1) {
  997. OS::get_singleton()->print(" and ");
  998. } else if (i != 0) {
  999. OS::get_singleton()->print(", ");
  1000. }
  1001. OS::get_singleton()->print("'%s'", AudioDriverManager::get_driver(i)->get_name());
  1002. }
  1003. OS::get_singleton()->print(".\n");
  1004. goto error;
  1005. }
  1006. N = N->next();
  1007. } else {
  1008. OS::get_singleton()->print("Missing audio driver argument, aborting.\n");
  1009. goto error;
  1010. }
  1011. } else if (arg == "--audio-output-latency") {
  1012. if (N) {
  1013. audio_output_latency = N->get().to_int();
  1014. N = N->next();
  1015. } else {
  1016. OS::get_singleton()->print("Missing audio output latency argument, aborting.\n");
  1017. goto error;
  1018. }
  1019. } else if (arg == "--text-driver") {
  1020. if (N) {
  1021. text_driver = N->get();
  1022. N = N->next();
  1023. } else {
  1024. OS::get_singleton()->print("Missing text driver argument, aborting.\n");
  1025. goto error;
  1026. }
  1027. } else if (arg == "--display-driver") { // force video driver
  1028. if (N) {
  1029. display_driver = N->get();
  1030. bool found = false;
  1031. for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
  1032. if (display_driver == DisplayServer::get_create_function_name(i)) {
  1033. found = true;
  1034. }
  1035. }
  1036. if (!found) {
  1037. OS::get_singleton()->print("Unknown display driver '%s', aborting.\nValid options are ",
  1038. display_driver.utf8().get_data());
  1039. for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
  1040. if (i == DisplayServer::get_create_function_count() - 1) {
  1041. OS::get_singleton()->print(" and ");
  1042. } else if (i != 0) {
  1043. OS::get_singleton()->print(", ");
  1044. }
  1045. OS::get_singleton()->print("'%s'", DisplayServer::get_create_function_name(i));
  1046. }
  1047. OS::get_singleton()->print(".\n");
  1048. goto error;
  1049. }
  1050. N = N->next();
  1051. } else {
  1052. OS::get_singleton()->print("Missing display driver argument, aborting.\n");
  1053. goto error;
  1054. }
  1055. } else if (arg == "--rendering-method") {
  1056. if (N) {
  1057. rendering_method = N->get();
  1058. N = N->next();
  1059. } else {
  1060. OS::get_singleton()->print("Missing renderer name argument, aborting.\n");
  1061. goto error;
  1062. }
  1063. } else if (arg == "--rendering-driver") {
  1064. if (N) {
  1065. rendering_driver = N->get();
  1066. N = N->next();
  1067. } else {
  1068. OS::get_singleton()->print("Missing rendering driver argument, aborting.\n");
  1069. goto error;
  1070. }
  1071. } else if (arg == "-f" || arg == "--fullscreen") { // force fullscreen
  1072. init_fullscreen = true;
  1073. window_mode = DisplayServer::WINDOW_MODE_FULLSCREEN;
  1074. } else if (arg == "-m" || arg == "--maximized") { // force maximized window
  1075. init_maximized = true;
  1076. window_mode = DisplayServer::WINDOW_MODE_MAXIMIZED;
  1077. } else if (arg == "-w" || arg == "--windowed") { // force windowed window
  1078. init_windowed = true;
  1079. } else if (arg == "--gpu-index") {
  1080. if (N) {
  1081. Engine::singleton->gpu_idx = N->get().to_int();
  1082. N = N->next();
  1083. } else {
  1084. OS::get_singleton()->print("Missing GPU index argument, aborting.\n");
  1085. goto error;
  1086. }
  1087. } else if (arg == "--gpu-validation") {
  1088. Engine::singleton->use_validation_layers = true;
  1089. #ifdef DEBUG_ENABLED
  1090. } else if (arg == "--gpu-abort") {
  1091. Engine::singleton->abort_on_gpu_errors = true;
  1092. #endif
  1093. } else if (arg == "--generate-spirv-debug-info") {
  1094. Engine::singleton->generate_spirv_debug_info = true;
  1095. #if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)
  1096. } else if (arg == "--extra-gpu-memory-tracking") {
  1097. Engine::singleton->extra_gpu_memory_tracking = true;
  1098. } else if (arg == "--accurate-breadcrumbs") {
  1099. Engine::singleton->accurate_breadcrumbs = true;
  1100. #endif
  1101. } else if (arg == "--tablet-driver") {
  1102. if (N) {
  1103. tablet_driver = N->get();
  1104. N = N->next();
  1105. } else {
  1106. OS::get_singleton()->print("Missing tablet driver argument, aborting.\n");
  1107. goto error;
  1108. }
  1109. } else if (arg == "--delta-smoothing") {
  1110. if (N) {
  1111. String string = N->get();
  1112. bool recognized = false;
  1113. if (string == "enable") {
  1114. OS::get_singleton()->set_delta_smoothing(true);
  1115. delta_smoothing_override = true;
  1116. recognized = true;
  1117. }
  1118. if (string == "disable") {
  1119. OS::get_singleton()->set_delta_smoothing(false);
  1120. delta_smoothing_override = false;
  1121. recognized = true;
  1122. }
  1123. if (!recognized) {
  1124. OS::get_singleton()->print("Delta-smoothing argument not recognized, aborting.\n");
  1125. goto error;
  1126. }
  1127. N = N->next();
  1128. } else {
  1129. OS::get_singleton()->print("Missing delta-smoothing argument, aborting.\n");
  1130. goto error;
  1131. }
  1132. } else if (arg == "--single-window") { // force single window
  1133. single_window = true;
  1134. } else if (arg == "--accessibility") {
  1135. if (N) {
  1136. String string = N->get();
  1137. if (string == "auto") {
  1138. accessibility_mode = DisplayServer::AccessibilityMode::ACCESSIBILITY_AUTO;
  1139. accessibility_mode_set = true;
  1140. } else if (string == "always") {
  1141. accessibility_mode = DisplayServer::AccessibilityMode::ACCESSIBILITY_ALWAYS;
  1142. accessibility_mode_set = true;
  1143. } else if (string == "disabled") {
  1144. accessibility_mode = DisplayServer::AccessibilityMode::ACCESSIBILITY_DISABLED;
  1145. accessibility_mode_set = true;
  1146. } else {
  1147. OS::get_singleton()->print("Accessibility mode argument not recognized, aborting.\n");
  1148. goto error;
  1149. }
  1150. N = N->next();
  1151. } else {
  1152. OS::get_singleton()->print("Missing accessibility mode argument, aborting.\n");
  1153. goto error;
  1154. }
  1155. } else if (arg == "-t" || arg == "--always-on-top") { // force always-on-top window
  1156. init_always_on_top = true;
  1157. } else if (arg == "--resolution") { // force resolution
  1158. if (N) {
  1159. String vm = N->get();
  1160. if (!vm.contains_char('x')) { // invalid parameter format
  1161. OS::get_singleton()->print("Invalid resolution '%s', it should be e.g. '1280x720'.\n",
  1162. vm.utf8().get_data());
  1163. goto error;
  1164. }
  1165. int w = vm.get_slicec('x', 0).to_int();
  1166. int h = vm.get_slicec('x', 1).to_int();
  1167. if (w <= 0 || h <= 0) {
  1168. OS::get_singleton()->print("Invalid resolution '%s', width and height must be above 0.\n",
  1169. vm.utf8().get_data());
  1170. goto error;
  1171. }
  1172. window_size.width = w;
  1173. window_size.height = h;
  1174. force_res = true;
  1175. N = N->next();
  1176. } else {
  1177. OS::get_singleton()->print("Missing resolution argument, aborting.\n");
  1178. goto error;
  1179. }
  1180. } else if (arg == "--screen") { // set window screen
  1181. if (N) {
  1182. init_screen = N->get().to_int();
  1183. init_use_custom_screen = true;
  1184. N = N->next();
  1185. } else {
  1186. OS::get_singleton()->print("Missing screen argument, aborting.\n");
  1187. goto error;
  1188. }
  1189. } else if (arg == "--position") { // set window position
  1190. if (N) {
  1191. String vm = N->get();
  1192. if (!vm.contains_char(',')) { // invalid parameter format
  1193. OS::get_singleton()->print("Invalid position '%s', it should be e.g. '80,128'.\n",
  1194. vm.utf8().get_data());
  1195. goto error;
  1196. }
  1197. int x = vm.get_slicec(',', 0).to_int();
  1198. int y = vm.get_slicec(',', 1).to_int();
  1199. init_custom_pos = Point2(x, y);
  1200. init_use_custom_pos = true;
  1201. N = N->next();
  1202. } else {
  1203. OS::get_singleton()->print("Missing position argument, aborting.\n");
  1204. goto error;
  1205. }
  1206. } else if (arg == "--headless") { // enable headless mode (no audio, no rendering).
  1207. audio_driver = NULL_AUDIO_DRIVER;
  1208. display_driver = NULL_DISPLAY_DRIVER;
  1209. } else if (arg == "--embedded") { // Enable embedded mode.
  1210. #ifdef MACOS_ENABLED
  1211. display_driver = EMBEDDED_DISPLAY_DRIVER;
  1212. #else
  1213. OS::get_singleton()->print("--embedded is only supported on macOS, aborting.\n");
  1214. goto error;
  1215. #endif
  1216. } else if (arg == "--log-file") { // write to log file
  1217. if (N) {
  1218. log_file = N->get();
  1219. N = N->next();
  1220. } else {
  1221. OS::get_singleton()->print("Missing log file path argument, aborting.\n");
  1222. goto error;
  1223. }
  1224. } else if (arg == "--profiling") { // enable profiling
  1225. use_debug_profiler = true;
  1226. } else if (arg == "-l" || arg == "--language") { // language
  1227. if (N) {
  1228. locale = N->get();
  1229. N = N->next();
  1230. } else {
  1231. OS::get_singleton()->print("Missing language argument, aborting.\n");
  1232. goto error;
  1233. }
  1234. } else if (arg == "--remote-fs") { // remote filesystem
  1235. if (N) {
  1236. remotefs = N->get();
  1237. N = N->next();
  1238. } else {
  1239. OS::get_singleton()->print("Missing remote filesystem address, aborting.\n");
  1240. goto error;
  1241. }
  1242. } else if (arg == "--remote-fs-password") { // remote filesystem password
  1243. if (N) {
  1244. remotefs_pass = N->get();
  1245. N = N->next();
  1246. } else {
  1247. OS::get_singleton()->print("Missing remote filesystem password, aborting.\n");
  1248. goto error;
  1249. }
  1250. } else if (arg == "--render-thread") { // render thread mode
  1251. if (N) {
  1252. if (N->get() == "safe") {
  1253. separate_thread_render = 0;
  1254. #ifndef DISABLE_DEPRECATED
  1255. } else if (N->get() == "unsafe") {
  1256. OS::get_singleton()->print("The --render-thread unsafe option is unsupported in Godot 4 and will be removed.\n");
  1257. separate_thread_render = 0;
  1258. #endif
  1259. } else if (N->get() == "separate") {
  1260. separate_thread_render = 1;
  1261. } else {
  1262. OS::get_singleton()->print("Unknown render thread mode, aborting.\n");
  1263. #ifdef DISABLE_DEPRECATED
  1264. OS::get_singleton()->print("Valid options are 'safe' and 'separate'.\n");
  1265. #else
  1266. OS::get_singleton()->print("Valid options are 'unsafe', 'safe' and 'separate'.\n");
  1267. #endif
  1268. goto error;
  1269. }
  1270. N = N->next();
  1271. } else {
  1272. OS::get_singleton()->print("Missing render thread mode argument, aborting.\n");
  1273. goto error;
  1274. }
  1275. #ifdef TOOLS_ENABLED
  1276. } else if (arg == "-e" || arg == "--editor") { // starts editor
  1277. editor = true;
  1278. } else if (arg == "-p" || arg == "--project-manager") { // starts project manager
  1279. project_manager = true;
  1280. } else if (arg == "--recovery-mode") { // Enables recovery mode.
  1281. recovery_mode = true;
  1282. } else if (arg == "--debug-server") {
  1283. if (N) {
  1284. debug_server_uri = N->get();
  1285. if (!debug_server_uri.contains("://")) { // wrong address
  1286. OS::get_singleton()->print("Invalid debug server uri. It should be of the form <protocol>://<bind_address>:<port>.\n");
  1287. goto error;
  1288. }
  1289. N = N->next();
  1290. } else {
  1291. OS::get_singleton()->print("Missing remote debug server uri, aborting.\n");
  1292. goto error;
  1293. }
  1294. } else if (arg == "--single-threaded-scene") {
  1295. single_threaded_scene = true;
  1296. } else if (arg == "--build-solutions") { // Build the scripting solution such C#
  1297. auto_build_solutions = true;
  1298. editor = true;
  1299. cmdline_tool = true;
  1300. } else if (arg == "--dump-gdextension-interface") {
  1301. // Register as an editor instance to use low-end fallback if relevant.
  1302. editor = true;
  1303. cmdline_tool = true;
  1304. dump_gdextension_interface = true;
  1305. print_line("Dumping GDExtension interface header file");
  1306. // Hack. Not needed but otherwise we end up detecting that this should
  1307. // run the project instead of a cmdline tool.
  1308. // Needs full refactoring to fix properly.
  1309. main_args.push_back(arg);
  1310. } else if (arg == "--dump-extension-api") {
  1311. // Register as an editor instance to use low-end fallback if relevant.
  1312. editor = true;
  1313. cmdline_tool = true;
  1314. dump_extension_api = true;
  1315. print_line("Dumping Extension API");
  1316. // Hack. Not needed but otherwise we end up detecting that this should
  1317. // run the project instead of a cmdline tool.
  1318. // Needs full refactoring to fix properly.
  1319. main_args.push_back(arg);
  1320. } else if (arg == "--dump-extension-api-with-docs") {
  1321. // Register as an editor instance to use low-end fallback if relevant.
  1322. editor = true;
  1323. cmdline_tool = true;
  1324. dump_extension_api = true;
  1325. include_docs_in_extension_api_dump = true;
  1326. print_line("Dumping Extension API including documentation");
  1327. // Hack. Not needed but otherwise we end up detecting that this should
  1328. // run the project instead of a cmdline tool.
  1329. // Needs full refactoring to fix properly.
  1330. main_args.push_back(arg);
  1331. } else if (arg == "--validate-extension-api") {
  1332. // Register as an editor instance to use low-end fallback if relevant.
  1333. editor = true;
  1334. cmdline_tool = true;
  1335. validate_extension_api = true;
  1336. // Hack. Not needed but otherwise we end up detecting that this should
  1337. // run the project instead of a cmdline tool.
  1338. // Needs full refactoring to fix properly.
  1339. main_args.push_back(arg);
  1340. if (N) {
  1341. validate_extension_api_file = N->get();
  1342. N = N->next();
  1343. } else {
  1344. OS::get_singleton()->print("Missing file to load argument after --validate-extension-api, aborting.");
  1345. goto error;
  1346. }
  1347. } else if (arg == "--import") {
  1348. editor = true;
  1349. cmdline_tool = true;
  1350. wait_for_import = true;
  1351. quit_after = 1;
  1352. } else if (arg == "--export-release" || arg == "--export-debug" ||
  1353. arg == "--export-pack" || arg == "--export-patch") { // Export project
  1354. // Actually handling is done in start().
  1355. editor = true;
  1356. cmdline_tool = true;
  1357. wait_for_import = true;
  1358. main_args.push_back(arg);
  1359. } else if (arg == "--patches") {
  1360. if (N) {
  1361. // Actually handling is done in start().
  1362. main_args.push_back(arg);
  1363. main_args.push_back(N->get());
  1364. N = N->next();
  1365. } else {
  1366. OS::get_singleton()->print("Missing comma-separated list of patches after --patches, aborting.\n");
  1367. goto error;
  1368. }
  1369. #ifndef DISABLE_DEPRECATED
  1370. } else if (arg == "--export") { // For users used to 3.x syntax.
  1371. OS::get_singleton()->print("The Godot 3 --export option was changed to more explicit --export-release / --export-debug / --export-pack options.\nSee the --help output for details.\n");
  1372. goto error;
  1373. } else if (arg == "--convert-3to4") {
  1374. // Actually handling is done in start().
  1375. cmdline_tool = true;
  1376. main_args.push_back(arg);
  1377. if (N && !N->get().begins_with("-")) {
  1378. if (itos(N->get().to_int()) == N->get()) {
  1379. converter_max_kb_file = N->get().to_int();
  1380. }
  1381. if (N->next() && !N->next()->get().begins_with("-")) {
  1382. if (itos(N->next()->get().to_int()) == N->next()->get()) {
  1383. converter_max_line_length = N->next()->get().to_int();
  1384. }
  1385. }
  1386. }
  1387. } else if (arg == "--validate-conversion-3to4") {
  1388. // Actually handling is done in start().
  1389. cmdline_tool = true;
  1390. main_args.push_back(arg);
  1391. if (N && !N->get().begins_with("-")) {
  1392. if (itos(N->get().to_int()) == N->get()) {
  1393. converter_max_kb_file = N->get().to_int();
  1394. }
  1395. if (N->next() && !N->next()->get().begins_with("-")) {
  1396. if (itos(N->next()->get().to_int()) == N->next()->get()) {
  1397. converter_max_line_length = N->next()->get().to_int();
  1398. }
  1399. }
  1400. }
  1401. #endif // DISABLE_DEPRECATED
  1402. } else if (arg == "--doctool") {
  1403. // Actually handling is done in start().
  1404. cmdline_tool = true;
  1405. // `--doctool` implies `--headless` to avoid spawning an unnecessary window
  1406. // and speed up class reference generation.
  1407. audio_driver = NULL_AUDIO_DRIVER;
  1408. display_driver = NULL_DISPLAY_DRIVER;
  1409. main_args.push_back(arg);
  1410. #ifdef MODULE_GDSCRIPT_ENABLED
  1411. } else if (arg == "--gdscript-docs") {
  1412. if (N) {
  1413. project_path = N->get();
  1414. // Will be handled in start()
  1415. main_args.push_back(arg);
  1416. main_args.push_back(N->get());
  1417. N = N->next();
  1418. // GDScript docgen requires Autoloads, but loading those also creates a main loop.
  1419. // This forces main loop to quit without adding more GDScript-specific exceptions to setup.
  1420. quit_after = 1;
  1421. } else {
  1422. OS::get_singleton()->print("Missing relative or absolute path to project for --gdscript-docs, aborting.\n");
  1423. goto error;
  1424. }
  1425. #endif // MODULE_GDSCRIPT_ENABLED
  1426. #endif // TOOLS_ENABLED
  1427. } else if (arg == "--path") { // set path of project to start or edit
  1428. if (N) {
  1429. String p = N->get();
  1430. if (OS::get_singleton()->set_cwd(p) != OK) {
  1431. OS::get_singleton()->print("Invalid project path specified: \"%s\", aborting.\n", p.utf8().get_data());
  1432. goto error;
  1433. }
  1434. N = N->next();
  1435. } else {
  1436. OS::get_singleton()->print("Missing relative or absolute path, aborting.\n");
  1437. goto error;
  1438. }
  1439. } else if (arg == "-u" || arg == "--upwards") { // scan folders upwards
  1440. upwards = true;
  1441. } else if (arg == "--quit") { // Auto quit at the end of the first main loop iteration
  1442. quit_after = 1;
  1443. } else if (arg == "--quit-after") { // Quit after the given number of iterations
  1444. if (N) {
  1445. quit_after = N->get().to_int();
  1446. N = N->next();
  1447. } else {
  1448. OS::get_singleton()->print("Missing number of iterations, aborting.\n");
  1449. goto error;
  1450. }
  1451. } else if (arg.ends_with("project.godot")) {
  1452. String path;
  1453. String file = arg;
  1454. int sep = MAX(file.rfind_char('/'), file.rfind_char('\\'));
  1455. if (sep == -1) {
  1456. path = ".";
  1457. } else {
  1458. path = file.substr(0, sep);
  1459. }
  1460. if (OS::get_singleton()->set_cwd(path) == OK) {
  1461. // path already specified, don't override
  1462. } else {
  1463. project_path = path;
  1464. }
  1465. #ifdef TOOLS_ENABLED
  1466. editor = true;
  1467. #endif
  1468. } else if (arg == "-b" || arg == "--breakpoints") { // add breakpoints
  1469. if (N) {
  1470. String bplist = N->get();
  1471. breakpoints = bplist.split(",");
  1472. N = N->next();
  1473. } else {
  1474. OS::get_singleton()->print("Missing list of breakpoints, aborting.\n");
  1475. goto error;
  1476. }
  1477. } else if (arg == "--max-fps") { // set maximum rendered FPS
  1478. if (N) {
  1479. max_fps = N->get().to_int();
  1480. N = N->next();
  1481. } else {
  1482. OS::get_singleton()->print("Missing maximum FPS argument, aborting.\n");
  1483. goto error;
  1484. }
  1485. } else if (arg == "--frame-delay") { // force frame delay
  1486. if (N) {
  1487. frame_delay = N->get().to_int();
  1488. N = N->next();
  1489. } else {
  1490. OS::get_singleton()->print("Missing frame delay argument, aborting.\n");
  1491. goto error;
  1492. }
  1493. } else if (arg == "--time-scale") { // force time scale
  1494. if (N) {
  1495. Engine::get_singleton()->set_time_scale(N->get().to_float());
  1496. N = N->next();
  1497. } else {
  1498. OS::get_singleton()->print("Missing time scale argument, aborting.\n");
  1499. goto error;
  1500. }
  1501. } else if (arg == "--main-pack") {
  1502. if (N) {
  1503. main_pack = N->get();
  1504. N = N->next();
  1505. } else {
  1506. OS::get_singleton()->print("Missing path to main pack file, aborting.\n");
  1507. goto error;
  1508. }
  1509. } else if (arg == "-d" || arg == "--debug") {
  1510. debug_uri = "local://";
  1511. OS::get_singleton()->_debug_stdout = true;
  1512. #if defined(DEBUG_ENABLED)
  1513. } else if (arg == "--debug-collisions") {
  1514. debug_collisions = true;
  1515. } else if (arg == "--debug-paths") {
  1516. debug_paths = true;
  1517. } else if (arg == "--debug-navigation") {
  1518. debug_navigation = true;
  1519. } else if (arg == "--debug-avoidance") {
  1520. debug_avoidance = true;
  1521. } else if (arg == "--debug-canvas-item-redraw") {
  1522. debug_canvas_item_redraw = true;
  1523. } else if (arg == "--debug-stringnames") {
  1524. StringName::set_debug_stringnames(true);
  1525. } else if (arg == "--debug-mute-audio") {
  1526. debug_mute_audio = true;
  1527. #endif
  1528. #if defined(TOOLS_ENABLED) && (defined(WINDOWS_ENABLED) || defined(LINUXBSD_ENABLED))
  1529. } else if (arg == "--test-rd-support") {
  1530. test_rd_support = true;
  1531. } else if (arg == "--test-rd-creation") {
  1532. test_rd_creation = true;
  1533. #endif
  1534. } else if (arg == "--remote-debug") {
  1535. if (N) {
  1536. debug_uri = N->get();
  1537. if (!debug_uri.contains("://")) { // wrong address
  1538. OS::get_singleton()->print(
  1539. "Invalid debug host address, it should be of the form <protocol>://<host/IP>:<port>.\n");
  1540. goto error;
  1541. }
  1542. N = N->next();
  1543. } else {
  1544. OS::get_singleton()->print("Missing remote debug host address, aborting.\n");
  1545. goto error;
  1546. }
  1547. } else if (arg == "--editor-pid") { // not exposed to user
  1548. if (N) {
  1549. editor_pid = N->get().to_int();
  1550. N = N->next();
  1551. } else {
  1552. OS::get_singleton()->print("Missing editor PID argument, aborting.\n");
  1553. goto error;
  1554. }
  1555. } else if (arg == "--disable-render-loop") {
  1556. disable_render_loop = true;
  1557. } else if (arg == "--fixed-fps") {
  1558. if (N) {
  1559. fixed_fps = N->get().to_int();
  1560. N = N->next();
  1561. } else {
  1562. OS::get_singleton()->print("Missing fixed-fps argument, aborting.\n");
  1563. goto error;
  1564. }
  1565. } else if (arg == "--write-movie") {
  1566. if (N) {
  1567. Engine::get_singleton()->set_write_movie_path(N->get());
  1568. N = N->next();
  1569. if (fixed_fps == -1) {
  1570. fixed_fps = 60;
  1571. }
  1572. OS::get_singleton()->_writing_movie = true;
  1573. } else {
  1574. OS::get_singleton()->print("Missing write-movie argument, aborting.\n");
  1575. goto error;
  1576. }
  1577. } else if (arg == "--disable-vsync") {
  1578. disable_vsync = true;
  1579. } else if (arg == "--print-fps") {
  1580. print_fps = true;
  1581. #ifdef TOOLS_ENABLED
  1582. } else if (arg == "--editor-pseudolocalization") {
  1583. editor_pseudolocalization = true;
  1584. #endif // TOOLS_ENABLED
  1585. } else if (arg == "--profile-gpu") {
  1586. profile_gpu = true;
  1587. } else if (arg == "--disable-crash-handler") {
  1588. OS::get_singleton()->disable_crash_handler();
  1589. } else if (arg == "--skip-breakpoints") {
  1590. skip_breakpoints = true;
  1591. } else if (I->get() == "--ignore-error-breaks") {
  1592. ignore_error_breaks = true;
  1593. #ifndef XR_DISABLED
  1594. } else if (arg == "--xr-mode") {
  1595. if (N) {
  1596. String xr_mode = N->get().to_lower();
  1597. N = N->next();
  1598. if (xr_mode == "default") {
  1599. XRServer::set_xr_mode(XRServer::XRMODE_DEFAULT);
  1600. } else if (xr_mode == "off") {
  1601. XRServer::set_xr_mode(XRServer::XRMODE_OFF);
  1602. } else if (xr_mode == "on") {
  1603. XRServer::set_xr_mode(XRServer::XRMODE_ON);
  1604. } else {
  1605. OS::get_singleton()->print("Unknown --xr-mode argument \"%s\", aborting.\n", xr_mode.ascii().get_data());
  1606. goto error;
  1607. }
  1608. } else {
  1609. OS::get_singleton()->print("Missing --xr-mode argument, aborting.\n");
  1610. goto error;
  1611. }
  1612. #endif // XR_DISABLED
  1613. } else if (arg == "--benchmark") {
  1614. OS::get_singleton()->set_use_benchmark(true);
  1615. } else if (arg == "--benchmark-file") {
  1616. if (N) {
  1617. OS::get_singleton()->set_use_benchmark(true);
  1618. String benchmark_file = N->get();
  1619. OS::get_singleton()->set_benchmark_file(benchmark_file);
  1620. N = N->next();
  1621. } else {
  1622. OS::get_singleton()->print("Missing <path> argument for --benchmark-file <path>.\n");
  1623. goto error;
  1624. }
  1625. #if defined(TOOLS_ENABLED) && defined(MODULE_GDSCRIPT_ENABLED) && !defined(GDSCRIPT_NO_LSP)
  1626. } else if (arg == "--lsp-port") {
  1627. if (N) {
  1628. int port_override = N->get().to_int();
  1629. if (port_override < 0 || port_override > 65535) {
  1630. OS::get_singleton()->print("<port> argument for --lsp-port <port> must be between 0 and 65535.\n");
  1631. goto error;
  1632. }
  1633. GDScriptLanguageServer::port_override = port_override;
  1634. N = N->next();
  1635. } else {
  1636. OS::get_singleton()->print("Missing <port> argument for --lsp-port <port>.\n");
  1637. goto error;
  1638. }
  1639. #endif // TOOLS_ENABLED && MODULE_GDSCRIPT_ENABLED && !GDSCRIPT_NO_LSP
  1640. #if defined(TOOLS_ENABLED)
  1641. } else if (arg == "--dap-port") {
  1642. if (N) {
  1643. int port_override = N->get().to_int();
  1644. if (port_override < 0 || port_override > 65535) {
  1645. OS::get_singleton()->print("<port> argument for --dap-port <port> must be between 0 and 65535.\n");
  1646. goto error;
  1647. }
  1648. DebugAdapterServer::port_override = port_override;
  1649. N = N->next();
  1650. } else {
  1651. OS::get_singleton()->print("Missing <port> argument for --dap-port <port>.\n");
  1652. goto error;
  1653. }
  1654. #endif // TOOLS_ENABLED
  1655. } else if (arg == "--wid") {
  1656. if (N) {
  1657. init_embed_parent_window_id = N->get().to_int();
  1658. if (init_embed_parent_window_id == 0) {
  1659. OS::get_singleton()->print("<window_id> argument for --wid <window_id> must be different then 0.\n");
  1660. goto error;
  1661. }
  1662. OS::get_singleton()->_embedded_in_editor = true;
  1663. Engine::get_singleton()->set_embedded_in_editor(true);
  1664. N = N->next();
  1665. } else {
  1666. OS::get_singleton()->print("Missing <window_id> argument for --wid <window_id>.\n");
  1667. goto error;
  1668. }
  1669. } else if (arg == "--" || arg == "++") {
  1670. adding_user_args = true;
  1671. } else {
  1672. main_args.push_back(arg);
  1673. }
  1674. I = N;
  1675. }
  1676. #ifdef TOOLS_ENABLED
  1677. if (editor && project_manager) {
  1678. OS::get_singleton()->print(
  1679. "Error: Command line arguments implied opening both editor and project manager, which is not possible. Aborting.\n");
  1680. goto error;
  1681. }
  1682. #endif
  1683. // Network file system needs to be configured before globals, since globals are based on the
  1684. // 'project.godot' file which will only be available through the network if this is enabled
  1685. if (!remotefs.is_empty()) {
  1686. int port;
  1687. if (remotefs.contains_char(':')) {
  1688. port = remotefs.get_slicec(':', 1).to_int();
  1689. remotefs = remotefs.get_slicec(':', 0);
  1690. } else {
  1691. port = 6010;
  1692. }
  1693. Error err = OS::get_singleton()->setup_remote_filesystem(remotefs, port, remotefs_pass, project_path);
  1694. if (err) {
  1695. OS::get_singleton()->printerr("Could not connect to remotefs: %s:%i.\n", remotefs.utf8().get_data(), port);
  1696. goto error;
  1697. }
  1698. }
  1699. OS::get_singleton()->_in_editor = editor;
  1700. if (globals->setup(project_path, main_pack, upwards, editor) == OK) {
  1701. #ifdef TOOLS_ENABLED
  1702. found_project = true;
  1703. #endif
  1704. } else {
  1705. #ifdef TOOLS_ENABLED
  1706. editor = false;
  1707. #else
  1708. const String error_msg = "Error: Couldn't load project data at path \"" + project_path + "\". Is the .pck file missing?\nIf you've renamed the executable, the associated .pck file should also be renamed to match the executable's name (without the extension).\n";
  1709. OS::get_singleton()->print("%s", error_msg.utf8().get_data());
  1710. OS::get_singleton()->alert(error_msg);
  1711. goto error;
  1712. #endif
  1713. }
  1714. // Initialize WorkerThreadPool.
  1715. {
  1716. #ifdef THREADS_ENABLED
  1717. if (editor || project_manager) {
  1718. WorkerThreadPool::get_singleton()->init(-1, 0.75);
  1719. } else {
  1720. int worker_threads = GLOBAL_GET("threading/worker_pool/max_threads");
  1721. float low_priority_ratio = GLOBAL_GET("threading/worker_pool/low_priority_thread_ratio");
  1722. WorkerThreadPool::get_singleton()->init(worker_threads, low_priority_ratio);
  1723. }
  1724. #else
  1725. WorkerThreadPool::get_singleton()->init(0, 0);
  1726. #endif
  1727. }
  1728. #ifdef TOOLS_ENABLED
  1729. if (!project_manager && !editor) {
  1730. // If we didn't find a project, we fall back to the project manager.
  1731. project_manager = !found_project && !cmdline_tool;
  1732. }
  1733. {
  1734. // Synced with https://github.com/baldurk/renderdoc/blob/2b01465c7/renderdoc/driver/vulkan/vk_layer.cpp#L118-L165
  1735. LocalVector<String> layers_to_disable = {
  1736. "DISABLE_RTSS_LAYER", // GH-57937.
  1737. "DISABLE_VULKAN_OBS_CAPTURE", // GH-103800.
  1738. "DISABLE_VULKAN_OW_OBS_CAPTURE", // GH-104154.
  1739. "DISABLE_SAMPLE_LAYER", // GH-104154.
  1740. "DISABLE_GAMEPP_LAYER", // GH-104154.
  1741. "DISABLE_VK_LAYER_TENCENT_wegame_cross_overlay_1", // GH-104154.
  1742. // "NODEVICE_SELECT", // Kept as it's useful - GH-104592.
  1743. "VK_LAYER_bandicam_helper_DEBUG_1", // GH-101480.
  1744. "DISABLE_VK_LAYER_bandicam_helper_1", // GH-101480.
  1745. "DISABLE_VK_LAYER_reshade_1", // GH-70849.
  1746. "DISABLE_VK_LAYER_GPUOpen_GRS", // GH-104154.
  1747. "DISABLE_LAYER", // GH-104154 (fpsmon).
  1748. "DISABLE_MANGOHUD", // GH-57403.
  1749. "DISABLE_VKBASALT",
  1750. };
  1751. #if defined(WINDOWS_ENABLED) || defined(LINUXBSD_ENABLED)
  1752. if (editor || project_manager || test_rd_support || test_rd_creation) {
  1753. #else
  1754. if (editor || project_manager) {
  1755. #endif
  1756. // Disable Vulkan overlays in editor, they cause various issues.
  1757. for (const String &layer_disable : layers_to_disable) {
  1758. OS::get_singleton()->set_environment(layer_disable, "1");
  1759. }
  1760. } else {
  1761. // Re-allow using Vulkan overlays, disabled while using the editor.
  1762. for (const String &layer_disable : layers_to_disable) {
  1763. OS::get_singleton()->unset_environment(layer_disable);
  1764. }
  1765. }
  1766. }
  1767. #endif
  1768. #if defined(TOOLS_ENABLED) && (defined(WINDOWS_ENABLED) || defined(LINUXBSD_ENABLED))
  1769. if (test_rd_support) {
  1770. // Test Rendering Device creation and exit.
  1771. OS::get_singleton()->set_crash_handler_silent();
  1772. if (OS::get_singleton()->_test_create_rendering_device(display_driver)) {
  1773. exit_err = ERR_HELP;
  1774. } else {
  1775. exit_err = ERR_UNAVAILABLE;
  1776. }
  1777. goto error;
  1778. } else if (test_rd_creation) {
  1779. // Test OpenGL context and Rendering Device simultaneous creation and exit.
  1780. OS::get_singleton()->set_crash_handler_silent();
  1781. if (OS::get_singleton()->_test_create_rendering_device_and_gl(display_driver)) {
  1782. exit_err = ERR_HELP;
  1783. } else {
  1784. exit_err = ERR_UNAVAILABLE;
  1785. }
  1786. goto error;
  1787. }
  1788. #endif
  1789. #ifdef TOOLS_ENABLED
  1790. if (editor) {
  1791. Engine::get_singleton()->set_editor_hint(true);
  1792. Engine::get_singleton()->set_extension_reloading_enabled(true);
  1793. // Create initialization lock file to detect crashes during startup.
  1794. OS::get_singleton()->create_lock_file();
  1795. main_args.push_back("--editor");
  1796. if (!init_windowed && !init_fullscreen) {
  1797. init_maximized = true;
  1798. window_mode = DisplayServer::WINDOW_MODE_MAXIMIZED;
  1799. }
  1800. }
  1801. if (project_manager) {
  1802. Engine::get_singleton()->set_project_manager_hint(true);
  1803. }
  1804. if (recovery_mode) {
  1805. if (project_manager || !editor) {
  1806. OS::get_singleton()->print("Error: Recovery mode can only be used in the editor. Aborting.\n");
  1807. goto error;
  1808. }
  1809. Engine::get_singleton()->set_recovery_mode_hint(true);
  1810. }
  1811. #endif
  1812. OS::get_singleton()->set_cmdline(execpath, main_args, user_args);
  1813. Engine::get_singleton()->set_physics_ticks_per_second(GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "physics/common/physics_ticks_per_second", PROPERTY_HINT_RANGE, "1,1000,1"), 60));
  1814. Engine::get_singleton()->set_max_physics_steps_per_frame(GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "physics/common/max_physics_steps_per_frame", PROPERTY_HINT_RANGE, "1,100,1"), 8));
  1815. Engine::get_singleton()->set_physics_jitter_fix(GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/common/physics_jitter_fix", PROPERTY_HINT_RANGE, "0,2,0.001,or_greater"), 0.5));
  1816. Engine::get_singleton()->set_max_fps(GLOBAL_DEF(PropertyInfo(Variant::INT, "application/run/max_fps", PROPERTY_HINT_RANGE, "0,1000,1"), 0));
  1817. if (max_fps >= 0) {
  1818. Engine::get_singleton()->set_max_fps(max_fps);
  1819. }
  1820. // Initialize user data dir.
  1821. OS::get_singleton()->ensure_user_data_dir();
  1822. OS::get_singleton()->set_low_processor_usage_mode(GLOBAL_DEF("application/run/low_processor_mode", false));
  1823. OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(
  1824. GLOBAL_DEF(PropertyInfo(Variant::INT, "application/run/low_processor_mode_sleep_usec", PROPERTY_HINT_RANGE, "0,33200,1,or_greater"), 6900)); // Roughly 144 FPS
  1825. GLOBAL_DEF("application/run/delta_smoothing", true);
  1826. if (!delta_smoothing_override) {
  1827. OS::get_singleton()->set_delta_smoothing(GLOBAL_GET("application/run/delta_smoothing"));
  1828. }
  1829. GLOBAL_DEF("debug/settings/stdout/print_fps", false);
  1830. GLOBAL_DEF("debug/settings/stdout/print_gpu_profile", false);
  1831. GLOBAL_DEF("debug/settings/stdout/verbose_stdout", false);
  1832. GLOBAL_DEF("debug/settings/physics_interpolation/enable_warnings", true);
  1833. if (!OS::get_singleton()->_verbose_stdout) { // Not manually overridden.
  1834. OS::get_singleton()->_verbose_stdout = GLOBAL_GET("debug/settings/stdout/verbose_stdout");
  1835. }
  1836. register_early_core_singletons();
  1837. initialize_modules(MODULE_INITIALIZATION_LEVEL_CORE);
  1838. register_core_extensions(); // core extensions must be registered after globals setup and before display
  1839. ResourceUID::get_singleton()->load_from_cache(true); // load UUIDs from cache.
  1840. if (ProjectSettings::get_singleton()->has_custom_feature("dedicated_server")) {
  1841. audio_driver = NULL_AUDIO_DRIVER;
  1842. display_driver = NULL_DISPLAY_DRIVER;
  1843. }
  1844. GLOBAL_DEF(PropertyInfo(Variant::INT, "network/limits/debugger/max_chars_per_second", PROPERTY_HINT_RANGE, "256,4096,1,or_greater"), 32768);
  1845. GLOBAL_DEF(PropertyInfo(Variant::INT, "network/limits/debugger/max_queued_messages", PROPERTY_HINT_RANGE, "128,8192,1,or_greater"), 2048);
  1846. GLOBAL_DEF(PropertyInfo(Variant::INT, "network/limits/debugger/max_errors_per_second", PROPERTY_HINT_RANGE, "1,200,1,or_greater"), 400);
  1847. GLOBAL_DEF(PropertyInfo(Variant::INT, "network/limits/debugger/max_warnings_per_second", PROPERTY_HINT_RANGE, "1,200,1,or_greater"), 400);
  1848. EngineDebugger::initialize(debug_uri, skip_breakpoints, ignore_error_breaks, breakpoints, []() {
  1849. if (editor_pid) {
  1850. DisplayServer::get_singleton()->enable_for_stealing_focus(editor_pid);
  1851. }
  1852. });
  1853. #ifdef TOOLS_ENABLED
  1854. if (editor) {
  1855. packed_data->set_disabled(true);
  1856. }
  1857. #endif
  1858. GLOBAL_DEF("debug/file_logging/enable_file_logging", false);
  1859. // Only file logging by default on desktop platforms as logs can't be
  1860. // accessed easily on mobile/Web platforms (if at all).
  1861. // This also prevents logs from being created for the editor instance, as feature tags
  1862. // are disabled while in the editor (even if they should logically apply).
  1863. GLOBAL_DEF("debug/file_logging/enable_file_logging.pc", true);
  1864. GLOBAL_DEF("debug/file_logging/log_path", "user://logs/godot.log");
  1865. GLOBAL_DEF(PropertyInfo(Variant::INT, "debug/file_logging/max_log_files", PROPERTY_HINT_RANGE, "0,20,1,or_greater"), 5);
  1866. // If `--log-file` is used to override the log path, allow creating logs for the project manager or editor
  1867. // and even if file logging is disabled in the Project Settings.
  1868. // `--log-file` can be used with any path (including absolute paths outside the project folder),
  1869. // so check for filesystem access if it's used.
  1870. if (FileAccess::get_create_func(!log_file.is_empty() ? FileAccess::ACCESS_FILESYSTEM : FileAccess::ACCESS_USERDATA) &&
  1871. (!log_file.is_empty() || (!project_manager && !editor && GLOBAL_GET("debug/file_logging/enable_file_logging")))) {
  1872. // Don't create logs for the project manager as they would be written to
  1873. // the current working directory, which is inconvenient.
  1874. String base_path;
  1875. int max_files;
  1876. if (!log_file.is_empty()) {
  1877. base_path = log_file;
  1878. // Ensure log file name respects the specified override by disabling log rotation.
  1879. max_files = 1;
  1880. } else {
  1881. base_path = GLOBAL_GET("debug/file_logging/log_path");
  1882. max_files = GLOBAL_GET("debug/file_logging/max_log_files");
  1883. }
  1884. OS::get_singleton()->add_logger(memnew(RotatedFileLogger(base_path, max_files)));
  1885. }
  1886. if (main_args.is_empty() && String(GLOBAL_GET("application/run/main_scene")) == "") {
  1887. #ifdef TOOLS_ENABLED
  1888. if (!editor && !project_manager) {
  1889. #endif
  1890. const String error_msg = "Error: Can't run project: no main scene defined in the project.\n";
  1891. OS::get_singleton()->print("%s", error_msg.utf8().get_data());
  1892. OS::get_singleton()->alert(error_msg);
  1893. goto error;
  1894. #ifdef TOOLS_ENABLED
  1895. }
  1896. #endif
  1897. }
  1898. if (editor || project_manager) {
  1899. Engine::get_singleton()->set_editor_hint(true);
  1900. use_custom_res = false;
  1901. input_map->load_default(); //keys for editor
  1902. } else {
  1903. input_map->load_from_project_settings(); //keys for game
  1904. }
  1905. if (bool(GLOBAL_GET("application/run/disable_stdout"))) {
  1906. quiet_stdout = true;
  1907. }
  1908. if (bool(GLOBAL_GET("application/run/disable_stderr"))) {
  1909. CoreGlobals::print_error_enabled = false;
  1910. }
  1911. if (!bool(GLOBAL_GET("application/run/print_header"))) {
  1912. // --no-header option for project settings.
  1913. Engine::get_singleton()->_print_header = false;
  1914. }
  1915. if (quiet_stdout) {
  1916. CoreGlobals::print_line_enabled = false;
  1917. }
  1918. Logger::set_flush_stdout_on_print(GLOBAL_GET("application/run/flush_stdout_on_print"));
  1919. // Rendering drivers configuration.
  1920. // Always include all supported drivers as hint, as this is used by the editor host platform
  1921. // for project settings. For example, a Linux user should be able to configure that they want
  1922. // to export for D3D12 on Windows and Metal on macOS even if their host platform can't use those.
  1923. {
  1924. // RenderingDevice driver overrides per platform.
  1925. GLOBAL_DEF_RST("rendering/rendering_device/driver", "vulkan");
  1926. GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.windows", PROPERTY_HINT_ENUM, "vulkan,d3d12"), "vulkan");
  1927. GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.linuxbsd", PROPERTY_HINT_ENUM, "vulkan"), "vulkan");
  1928. GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.android", PROPERTY_HINT_ENUM, "vulkan"), "vulkan");
  1929. GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.ios", PROPERTY_HINT_ENUM, "metal,vulkan"), "metal");
  1930. GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.visionos", PROPERTY_HINT_ENUM, "metal"), "metal");
  1931. GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.macos", PROPERTY_HINT_ENUM, "metal,vulkan"), "metal");
  1932. GLOBAL_DEF_RST("rendering/rendering_device/fallback_to_vulkan", true);
  1933. GLOBAL_DEF_RST("rendering/rendering_device/fallback_to_d3d12", true);
  1934. GLOBAL_DEF_RST("rendering/rendering_device/fallback_to_opengl3", true);
  1935. }
  1936. {
  1937. // GL Compatibility driver overrides per platform.
  1938. GLOBAL_DEF_RST("rendering/gl_compatibility/driver", "opengl3");
  1939. GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.windows", PROPERTY_HINT_ENUM, "opengl3,opengl3_angle"), "opengl3");
  1940. GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.linuxbsd", PROPERTY_HINT_ENUM, "opengl3,opengl3_es"), "opengl3");
  1941. GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.web", PROPERTY_HINT_ENUM, "opengl3"), "opengl3");
  1942. GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.android", PROPERTY_HINT_ENUM, "opengl3"), "opengl3");
  1943. GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.ios", PROPERTY_HINT_ENUM, "opengl3"), "opengl3");
  1944. GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.macos", PROPERTY_HINT_ENUM, "opengl3,opengl3_angle"), "opengl3");
  1945. GLOBAL_DEF_RST("rendering/gl_compatibility/nvidia_disable_threaded_optimization", true);
  1946. GLOBAL_DEF_RST("rendering/gl_compatibility/fallback_to_angle", true);
  1947. GLOBAL_DEF_RST("rendering/gl_compatibility/fallback_to_native", true);
  1948. GLOBAL_DEF_RST("rendering/gl_compatibility/fallback_to_gles", true);
  1949. Array force_angle_list;
  1950. #define FORCE_ANGLE(m_vendor, m_name) \
  1951. { \
  1952. Dictionary device; \
  1953. device["vendor"] = m_vendor; \
  1954. device["name"] = m_name; \
  1955. force_angle_list.push_back(device); \
  1956. }
  1957. // AMD GPUs.
  1958. FORCE_ANGLE("ATI", "Radeon 9"); // ATI Radeon 9000 Series
  1959. FORCE_ANGLE("ATI", "Radeon X"); // ATI Radeon X500-X2000 Series
  1960. FORCE_ANGLE("ATI", "Radeon HD 2"); // AMD/ATI (Mobility) Radeon HD 2xxx Series
  1961. FORCE_ANGLE("ATI", "Radeon HD 3"); // AMD/ATI (Mobility) Radeon HD 3xxx Series
  1962. FORCE_ANGLE("ATI", "Radeon HD 4"); // AMD/ATI (Mobility) Radeon HD 4xxx Series
  1963. FORCE_ANGLE("ATI", "Radeon HD 5"); // AMD/ATI (Mobility) Radeon HD 5xxx Series
  1964. FORCE_ANGLE("ATI", "Radeon HD 6"); // AMD/ATI (Mobility) Radeon HD 6xxx Series
  1965. FORCE_ANGLE("ATI", "Radeon HD 7"); // AMD/ATI (Mobility) Radeon HD 7xxx Series
  1966. FORCE_ANGLE("ATI", "Radeon HD 8"); // AMD/ATI (Mobility) Radeon HD 8xxx Series
  1967. FORCE_ANGLE("ATI", "Radeon(TM) R2 Graphics"); // APUs
  1968. FORCE_ANGLE("ATI", "Radeon(TM) R3 Graphics");
  1969. FORCE_ANGLE("ATI", "Radeon(TM) R4 Graphics");
  1970. FORCE_ANGLE("ATI", "Radeon(TM) R5 Graphics");
  1971. FORCE_ANGLE("ATI", "Radeon(TM) R6 Graphics");
  1972. FORCE_ANGLE("ATI", "Radeon(TM) R7 Graphics");
  1973. FORCE_ANGLE("AMD", "Radeon(TM) R7 Graphics");
  1974. FORCE_ANGLE("AMD", "Radeon(TM) R8 Graphics");
  1975. FORCE_ANGLE("ATI", "Radeon R5 Graphics");
  1976. FORCE_ANGLE("ATI", "Radeon R6 Graphics");
  1977. FORCE_ANGLE("ATI", "Radeon R7 Graphics");
  1978. FORCE_ANGLE("AMD", "Radeon R7 Graphics");
  1979. FORCE_ANGLE("AMD", "Radeon R8 Graphics");
  1980. FORCE_ANGLE("ATI", "Radeon R5 2"); // Rx 2xx Series
  1981. FORCE_ANGLE("ATI", "Radeon R7 2");
  1982. FORCE_ANGLE("ATI", "Radeon R9 2");
  1983. FORCE_ANGLE("ATI", "Radeon R5 M2"); // Rx M2xx Series
  1984. FORCE_ANGLE("ATI", "Radeon R7 M2");
  1985. FORCE_ANGLE("ATI", "Radeon R9 M2");
  1986. FORCE_ANGLE("ATI", "Radeon (TM) R9 Fury");
  1987. FORCE_ANGLE("ATI", "Radeon (TM) R5 3"); // Rx 3xx Series
  1988. FORCE_ANGLE("AMD", "Radeon (TM) R5 3");
  1989. FORCE_ANGLE("ATI", "Radeon (TM) R7 3");
  1990. FORCE_ANGLE("AMD", "Radeon (TM) R7 3");
  1991. FORCE_ANGLE("ATI", "Radeon (TM) R9 3");
  1992. FORCE_ANGLE("AMD", "Radeon (TM) R9 3");
  1993. FORCE_ANGLE("ATI", "Radeon (TM) R5 M3"); // Rx M3xx Series
  1994. FORCE_ANGLE("AMD", "Radeon (TM) R5 M3");
  1995. FORCE_ANGLE("ATI", "Radeon (TM) R7 M3");
  1996. FORCE_ANGLE("AMD", "Radeon (TM) R7 M3");
  1997. FORCE_ANGLE("ATI", "Radeon (TM) R9 M3");
  1998. FORCE_ANGLE("AMD", "Radeon (TM) R9 M3");
  1999. // Intel GPUs.
  2000. FORCE_ANGLE("0x8086", "0x0042"); // HD Graphics, Gen5, Clarkdale
  2001. FORCE_ANGLE("0x8086", "0x0046"); // HD Graphics, Gen5, Arrandale
  2002. FORCE_ANGLE("0x8086", "0x010A"); // HD Graphics, Gen6, Sandy Bridge
  2003. FORCE_ANGLE("Intel", "Intel HD Graphics 2000");
  2004. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 2000");
  2005. FORCE_ANGLE("0x8086", "0x0102"); // HD Graphics 2000, Gen6, Sandy Bridge
  2006. FORCE_ANGLE("0x8086", "0x0116"); // HD Graphics 3000, Gen6, Sandy Bridge
  2007. FORCE_ANGLE("Intel", "Intel HD Graphics 3000");
  2008. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 3000");
  2009. FORCE_ANGLE("0x8086", "0x0126"); // HD Graphics 3000, Gen6, Sandy Bridge
  2010. FORCE_ANGLE("Intel", "Intel HD Graphics P3000");
  2011. FORCE_ANGLE("Intel", "Intel(R) HD Graphics P3000");
  2012. FORCE_ANGLE("0x8086", "0x0112"); // HD Graphics P3000, Gen6, Sandy Bridge
  2013. FORCE_ANGLE("0x8086", "0x0122");
  2014. FORCE_ANGLE("0x8086", "0x015A"); // HD Graphics, Gen7, Ivy Bridge
  2015. FORCE_ANGLE("Intel", "Intel HD Graphics 2500");
  2016. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 2500");
  2017. FORCE_ANGLE("0x8086", "0x0152"); // HD Graphics 2500, Gen7, Ivy Bridge
  2018. FORCE_ANGLE("Intel", "Intel HD Graphics 4000");
  2019. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 4000");
  2020. FORCE_ANGLE("0x8086", "0x0162"); // HD Graphics 4000, Gen7, Ivy Bridge
  2021. FORCE_ANGLE("0x8086", "0x0166");
  2022. FORCE_ANGLE("Intel", "Intel HD Graphics P4000");
  2023. FORCE_ANGLE("Intel", "Intel(R) HD Graphics P4000");
  2024. FORCE_ANGLE("0x8086", "0x016A"); // HD Graphics P4000, Gen7, Ivy Bridge
  2025. FORCE_ANGLE("Intel", "Intel(R) Vallyview Graphics");
  2026. FORCE_ANGLE("0x8086", "0x0F30"); // Intel(R) Vallyview Graphics, Gen7, Vallyview
  2027. FORCE_ANGLE("0x8086", "0x0F31");
  2028. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 4200");
  2029. FORCE_ANGLE("0x8086", "0x0A1E"); // Intel(R) HD Graphics 4200, Gen7.5, Haswell
  2030. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 4400");
  2031. FORCE_ANGLE("0x8086", "0x0A16"); // Intel(R) HD Graphics 4400, Gen7.5, Haswell
  2032. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 4600");
  2033. FORCE_ANGLE("0x8086", "0x0412"); // Intel(R) HD Graphics 4600, Gen7.5, Haswell
  2034. FORCE_ANGLE("0x8086", "0x0416");
  2035. FORCE_ANGLE("0x8086", "0x0426");
  2036. FORCE_ANGLE("0x8086", "0x0D12");
  2037. FORCE_ANGLE("0x8086", "0x0D16");
  2038. FORCE_ANGLE("Intel", "Intel(R) HD Graphics P4600/P4700");
  2039. FORCE_ANGLE("0x8086", "0x041A"); // Intel(R) HD Graphics P4600/P4700, Gen7.5, Haswell
  2040. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 5000");
  2041. FORCE_ANGLE("0x8086", "0x0422"); // Intel(R) HD Graphics 5000, Gen7.5, Haswell
  2042. FORCE_ANGLE("0x8086", "0x042A");
  2043. FORCE_ANGLE("0x8086", "0x0A26");
  2044. FORCE_ANGLE("Intel", "Intel(R) Iris(TM) Graphics 5100");
  2045. FORCE_ANGLE("0x8086", "0x0A22"); // Intel(R) Iris(TM) Graphics 5100, Gen7.5, Haswell
  2046. FORCE_ANGLE("0x8086", "0x0A2A");
  2047. FORCE_ANGLE("0x8086", "0x0A2B");
  2048. FORCE_ANGLE("0x8086", "0x0A2E");
  2049. FORCE_ANGLE("Intel", "Intel(R) Iris(TM) Pro Graphics 5200");
  2050. FORCE_ANGLE("0x8086", "0x0D22"); // Intel(R) Iris(TM) Pro Graphics 5200, Gen7.5, Haswell
  2051. FORCE_ANGLE("0x8086", "0x0D26");
  2052. FORCE_ANGLE("0x8086", "0x0D2A");
  2053. FORCE_ANGLE("0x8086", "0x0D2B");
  2054. FORCE_ANGLE("0x8086", "0x0D2E");
  2055. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 400");
  2056. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 405");
  2057. FORCE_ANGLE("0x8086", "0x22B0"); // Intel(R) HD Graphics, Gen8, Cherryview Braswell
  2058. FORCE_ANGLE("0x8086", "0x22B1");
  2059. FORCE_ANGLE("0x8086", "0x22B2");
  2060. FORCE_ANGLE("0x8086", "0x22B3");
  2061. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 5300");
  2062. FORCE_ANGLE("0x8086", "0x161E"); // Intel(R) HD Graphics 5300, Gen8, Broadwell
  2063. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 5500");
  2064. FORCE_ANGLE("0x8086", "0x1616"); // Intel(R) HD Graphics 5500, Gen8, Broadwell
  2065. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 5600");
  2066. FORCE_ANGLE("0x8086", "0x1612"); // Intel(R) HD Graphics 5600, Gen8, Broadwell
  2067. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 6000");
  2068. FORCE_ANGLE("0x8086", "0x1626"); // Intel(R) HD Graphics 6000, Gen8, Broadwell
  2069. FORCE_ANGLE("Intel", "Intel(R) Iris(TM) Graphics 6100");
  2070. FORCE_ANGLE("0x8086", "0x162B"); // Intel(R) Iris(TM) Graphics 6100, Gen8, Broadwell
  2071. FORCE_ANGLE("Intel", "Intel(R) Iris(TM) Pro Graphics 6200");
  2072. FORCE_ANGLE("0x8086", "0x1622"); // Intel(R) Iris(TM) Pro Graphics 6200, Gen8, Broadwell
  2073. FORCE_ANGLE("Intel", "Intel(R) Iris(TM) Pro Graphics P6300");
  2074. FORCE_ANGLE("0x8086", "0x162A"); // Intel(R) Iris(TM) Pro Graphics P6300, Gen8, Broadwell
  2075. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 500");
  2076. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 505");
  2077. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 510");
  2078. FORCE_ANGLE("0x8086", "0x1902"); // Intel(R) HD Graphics 510, Gen9, Skylake
  2079. FORCE_ANGLE("0x8086", "0x1906");
  2080. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 520");
  2081. FORCE_ANGLE("0x8086", "0x1916"); // Intel(R) HD Graphics 520, Gen9, Skylake
  2082. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 530");
  2083. FORCE_ANGLE("0x8086", "0x1912"); // Intel(R) HD Graphics 530, Gen9, Skylake
  2084. FORCE_ANGLE("0x8086", "0x191B");
  2085. FORCE_ANGLE("Intel", "Intel(R) HD Graphics P530");
  2086. FORCE_ANGLE("0x8086", "0x191D"); // Intel(R) HD Graphics P530, Gen9, Skylake
  2087. FORCE_ANGLE("Intel", "Intel(R) HD Graphics 515");
  2088. FORCE_ANGLE("0x8086", "0x191E"); // Intel(R) HD Graphics 515, Gen9, Skylake
  2089. FORCE_ANGLE("Intel", "Intel(R) Iris Graphics 540");
  2090. FORCE_ANGLE("0x8086", "0x1926"); // Intel(R) Iris Graphics 540, Gen9, Skylake
  2091. FORCE_ANGLE("0x8086", "0x1927");
  2092. FORCE_ANGLE("Intel", "Intel(R) Iris Pro Graphics 580");
  2093. FORCE_ANGLE("0x8086", "0x193B"); // Intel(R) Iris Pro Graphics 580, Gen9, Skylake
  2094. FORCE_ANGLE("Intel", "Intel(R) Iris Pro Graphics P580");
  2095. FORCE_ANGLE("0x8086", "0x193D"); // Intel(R) Iris Pro Graphics P580, Gen9, Skylake
  2096. #undef FORCE_ANGLE
  2097. GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::ARRAY, "rendering/gl_compatibility/force_angle_on_devices", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::DICTIONARY, PROPERTY_HINT_NONE, String())), force_angle_list);
  2098. }
  2099. // Start with RenderingDevice-based backends.
  2100. #ifdef RD_ENABLED
  2101. renderer_hints = "forward_plus,mobile";
  2102. default_renderer_mobile = "mobile";
  2103. #endif
  2104. // And Compatibility next, or first if Vulkan is disabled.
  2105. #ifdef GLES3_ENABLED
  2106. if (!renderer_hints.is_empty()) {
  2107. renderer_hints += ",";
  2108. }
  2109. renderer_hints += "gl_compatibility";
  2110. if (default_renderer_mobile.is_empty()) {
  2111. default_renderer_mobile = "gl_compatibility";
  2112. }
  2113. // Default to Compatibility when using the project manager.
  2114. if (rendering_driver.is_empty() && rendering_method.is_empty() && project_manager) {
  2115. rendering_driver = "opengl3";
  2116. rendering_method = "gl_compatibility";
  2117. default_renderer_mobile = "gl_compatibility";
  2118. }
  2119. #endif
  2120. if (!rendering_method.is_empty()) {
  2121. if (rendering_method != "forward_plus" &&
  2122. rendering_method != "mobile" &&
  2123. rendering_method != "gl_compatibility" &&
  2124. rendering_method != "dummy") {
  2125. OS::get_singleton()->print("Unknown rendering method '%s', aborting.\nValid options are ",
  2126. rendering_method.utf8().get_data());
  2127. Vector<String> rendering_method_hints = renderer_hints.split(",");
  2128. rendering_method_hints.push_back("dummy");
  2129. for (int i = 0; i < rendering_method_hints.size(); i++) {
  2130. if (i == rendering_method_hints.size() - 1) {
  2131. OS::get_singleton()->print(" and ");
  2132. } else if (i != 0) {
  2133. OS::get_singleton()->print(", ");
  2134. }
  2135. OS::get_singleton()->print("'%s'", rendering_method_hints[i].utf8().get_data());
  2136. }
  2137. OS::get_singleton()->print(".\n");
  2138. goto error;
  2139. }
  2140. }
  2141. if (renderer_hints.is_empty()) {
  2142. renderer_hints = "dummy";
  2143. }
  2144. if (!rendering_driver.is_empty()) {
  2145. // As the rendering drivers available may depend on the display driver and renderer
  2146. // selected, we can't do an exhaustive check here, but we can look through all
  2147. // the options in all the display drivers for a match.
  2148. bool found = false;
  2149. for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
  2150. Vector<String> r_drivers = DisplayServer::get_create_function_rendering_drivers(i);
  2151. for (int d = 0; d < r_drivers.size(); d++) {
  2152. if (rendering_driver == r_drivers[d]) {
  2153. found = true;
  2154. break;
  2155. }
  2156. }
  2157. }
  2158. if (!found) {
  2159. OS::get_singleton()->print("Unknown rendering driver '%s', aborting.\nValid options are ",
  2160. rendering_driver.utf8().get_data());
  2161. // Deduplicate driver entries, as a rendering driver may be supported by several display servers.
  2162. Vector<String> unique_rendering_drivers;
  2163. for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
  2164. Vector<String> r_drivers = DisplayServer::get_create_function_rendering_drivers(i);
  2165. for (int d = 0; d < r_drivers.size(); d++) {
  2166. if (!unique_rendering_drivers.has(r_drivers[d])) {
  2167. unique_rendering_drivers.append(r_drivers[d]);
  2168. }
  2169. }
  2170. }
  2171. for (int i = 0; i < unique_rendering_drivers.size(); i++) {
  2172. if (i == unique_rendering_drivers.size() - 1) {
  2173. OS::get_singleton()->print(" and ");
  2174. } else if (i != 0) {
  2175. OS::get_singleton()->print(", ");
  2176. }
  2177. OS::get_singleton()->print("'%s'", unique_rendering_drivers[i].utf8().get_data());
  2178. }
  2179. OS::get_singleton()->print(".\n");
  2180. goto error;
  2181. }
  2182. // Set a default renderer if none selected. Try to choose one that matches the driver.
  2183. if (rendering_method.is_empty()) {
  2184. if (rendering_driver == "dummy") {
  2185. rendering_method = "dummy";
  2186. } else if (rendering_driver == "opengl3" || rendering_driver == "opengl3_angle" || rendering_driver == "opengl3_es") {
  2187. rendering_method = "gl_compatibility";
  2188. } else {
  2189. rendering_method = "forward_plus";
  2190. }
  2191. }
  2192. // Now validate whether the selected driver matches with the renderer.
  2193. bool valid_combination = false;
  2194. Vector<String> available_drivers;
  2195. if (rendering_method == "forward_plus" || rendering_method == "mobile") {
  2196. #ifdef VULKAN_ENABLED
  2197. available_drivers.push_back("vulkan");
  2198. #endif
  2199. #ifdef D3D12_ENABLED
  2200. available_drivers.push_back("d3d12");
  2201. #endif
  2202. #ifdef METAL_ENABLED
  2203. available_drivers.push_back("metal");
  2204. #endif
  2205. }
  2206. #ifdef GLES3_ENABLED
  2207. if (rendering_method == "gl_compatibility") {
  2208. available_drivers.push_back("opengl3");
  2209. available_drivers.push_back("opengl3_angle");
  2210. available_drivers.push_back("opengl3_es");
  2211. }
  2212. #endif
  2213. if (rendering_method == "dummy") {
  2214. available_drivers.push_back("dummy");
  2215. }
  2216. if (available_drivers.is_empty()) {
  2217. OS::get_singleton()->print("Unknown renderer name '%s', aborting.\n", rendering_method.utf8().get_data());
  2218. goto error;
  2219. }
  2220. for (int i = 0; i < available_drivers.size(); i++) {
  2221. if (rendering_driver == available_drivers[i]) {
  2222. valid_combination = true;
  2223. break;
  2224. }
  2225. }
  2226. if (!valid_combination) {
  2227. OS::get_singleton()->print("Invalid renderer/driver combination '%s' and '%s', aborting. %s only supports the following drivers ", rendering_method.utf8().get_data(), rendering_driver.utf8().get_data(), rendering_method.utf8().get_data());
  2228. for (int d = 0; d < available_drivers.size(); d++) {
  2229. OS::get_singleton()->print("'%s', ", available_drivers[d].utf8().get_data());
  2230. }
  2231. OS::get_singleton()->print(".\n");
  2232. goto error;
  2233. }
  2234. }
  2235. default_renderer = renderer_hints.get_slicec(',', 0);
  2236. GLOBAL_DEF_RST_BASIC(PropertyInfo(Variant::STRING, "rendering/renderer/rendering_method", PROPERTY_HINT_ENUM, renderer_hints), default_renderer);
  2237. GLOBAL_DEF_RST_BASIC("rendering/renderer/rendering_method.mobile", default_renderer_mobile);
  2238. GLOBAL_DEF_RST_BASIC(PropertyInfo(Variant::STRING, "rendering/renderer/rendering_method.web", PROPERTY_HINT_ENUM, "gl_compatibility"), "gl_compatibility"); // This is a bit of a hack until we have WebGPU support.
  2239. // Default to ProjectSettings default if nothing set on the command line.
  2240. if (rendering_method.is_empty()) {
  2241. rendering_method = GLOBAL_GET("rendering/renderer/rendering_method");
  2242. }
  2243. if (rendering_driver.is_empty()) {
  2244. if (rendering_method == "dummy") {
  2245. rendering_driver = "dummy";
  2246. } else if (rendering_method == "gl_compatibility") {
  2247. rendering_driver = GLOBAL_GET("rendering/gl_compatibility/driver");
  2248. } else {
  2249. rendering_driver = GLOBAL_GET("rendering/rendering_device/driver");
  2250. }
  2251. }
  2252. // always convert to lower case for consistency in the code
  2253. rendering_driver = rendering_driver.to_lower();
  2254. OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
  2255. OS::get_singleton()->set_current_rendering_method(rendering_method);
  2256. #ifdef TOOLS_ENABLED
  2257. if (!force_res && project_manager) {
  2258. // Ensure splash screen size matches the project manager window size
  2259. // (see `editor/project_manager.cpp` for defaults).
  2260. window_size.width = ProjectManager::DEFAULT_WINDOW_WIDTH;
  2261. window_size.height = ProjectManager::DEFAULT_WINDOW_HEIGHT;
  2262. }
  2263. #endif
  2264. if (use_custom_res) {
  2265. if (!force_res) {
  2266. window_size.width = GLOBAL_GET("display/window/size/viewport_width");
  2267. window_size.height = GLOBAL_GET("display/window/size/viewport_height");
  2268. if (globals->has_setting("display/window/size/window_width_override") &&
  2269. globals->has_setting("display/window/size/window_height_override")) {
  2270. int desired_width = GLOBAL_GET("display/window/size/window_width_override");
  2271. if (desired_width > 0) {
  2272. window_size.width = desired_width;
  2273. }
  2274. int desired_height = GLOBAL_GET("display/window/size/window_height_override");
  2275. if (desired_height > 0) {
  2276. window_size.height = desired_height;
  2277. }
  2278. }
  2279. }
  2280. if (!bool(GLOBAL_GET("display/window/size/resizable"))) {
  2281. window_flags |= DisplayServer::WINDOW_FLAG_RESIZE_DISABLED_BIT;
  2282. }
  2283. if (bool(GLOBAL_GET("display/window/size/minimize_disabled"))) {
  2284. window_flags |= DisplayServer::WINDOW_FLAG_MINIMIZE_DISABLED_BIT;
  2285. }
  2286. if (bool(GLOBAL_GET("display/window/size/maximize_disabled"))) {
  2287. window_flags |= DisplayServer::WINDOW_FLAG_MAXIMIZE_DISABLED_BIT;
  2288. }
  2289. if (bool(GLOBAL_GET("display/window/size/borderless"))) {
  2290. window_flags |= DisplayServer::WINDOW_FLAG_BORDERLESS_BIT;
  2291. }
  2292. if (bool(GLOBAL_GET("display/window/size/always_on_top"))) {
  2293. window_flags |= DisplayServer::WINDOW_FLAG_ALWAYS_ON_TOP_BIT;
  2294. }
  2295. if (bool(GLOBAL_GET("display/window/size/transparent"))) {
  2296. window_flags |= DisplayServer::WINDOW_FLAG_TRANSPARENT_BIT;
  2297. }
  2298. if (bool(GLOBAL_GET("display/window/size/extend_to_title"))) {
  2299. window_flags |= DisplayServer::WINDOW_FLAG_EXTEND_TO_TITLE_BIT;
  2300. }
  2301. if (bool(GLOBAL_GET("display/window/size/no_focus"))) {
  2302. window_flags |= DisplayServer::WINDOW_FLAG_NO_FOCUS_BIT;
  2303. }
  2304. if (bool(GLOBAL_GET("display/window/size/sharp_corners"))) {
  2305. window_flags |= DisplayServer::WINDOW_FLAG_SHARP_CORNERS_BIT;
  2306. }
  2307. window_mode = (DisplayServer::WindowMode)(GLOBAL_GET("display/window/size/mode").operator int());
  2308. int initial_position_type = GLOBAL_GET("display/window/size/initial_position_type").operator int();
  2309. if (initial_position_type == Window::WINDOW_INITIAL_POSITION_ABSOLUTE) { // Absolute.
  2310. if (!init_use_custom_pos) {
  2311. init_custom_pos = GLOBAL_GET("display/window/size/initial_position").operator Vector2i();
  2312. init_use_custom_pos = true;
  2313. }
  2314. } else if (initial_position_type == Window::WINDOW_INITIAL_POSITION_CENTER_PRIMARY_SCREEN || initial_position_type == Window::WINDOW_INITIAL_POSITION_CENTER_MAIN_WINDOW_SCREEN) { // Center of Primary Screen.
  2315. if (!init_use_custom_screen) {
  2316. init_screen = DisplayServer::SCREEN_PRIMARY;
  2317. init_use_custom_screen = true;
  2318. }
  2319. } else if (initial_position_type == Window::WINDOW_INITIAL_POSITION_CENTER_OTHER_SCREEN) { // Center of Other Screen.
  2320. if (!init_use_custom_screen) {
  2321. init_screen = GLOBAL_GET("display/window/size/initial_screen").operator int();
  2322. init_use_custom_screen = true;
  2323. }
  2324. } else if (initial_position_type == Window::WINDOW_INITIAL_POSITION_CENTER_SCREEN_WITH_MOUSE_FOCUS) { // Center of Screen With Mouse Pointer.
  2325. if (!init_use_custom_screen) {
  2326. init_screen = DisplayServer::SCREEN_WITH_MOUSE_FOCUS;
  2327. init_use_custom_screen = true;
  2328. }
  2329. } else if (initial_position_type == Window::WINDOW_INITIAL_POSITION_CENTER_SCREEN_WITH_KEYBOARD_FOCUS) { // Center of Screen With Keyboard Focus.
  2330. if (!init_use_custom_screen) {
  2331. init_screen = DisplayServer::SCREEN_WITH_KEYBOARD_FOCUS;
  2332. init_use_custom_screen = true;
  2333. }
  2334. }
  2335. }
  2336. OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", true);
  2337. OS::get_singleton()->_allow_layered = GLOBAL_DEF_RST("display/window/per_pixel_transparency/allowed", false);
  2338. load_shell_env = GLOBAL_DEF("application/run/load_shell_environment", false);
  2339. #ifdef TOOLS_ENABLED
  2340. if (editor || project_manager) {
  2341. // The editor and project manager always detect and use hiDPI if needed.
  2342. OS::get_singleton()->_allow_hidpi = true;
  2343. load_shell_env = true;
  2344. }
  2345. #endif
  2346. if (load_shell_env) {
  2347. OS::get_singleton()->load_shell_environment();
  2348. }
  2349. if (separate_thread_render == -1) {
  2350. separate_thread_render = (int)GLOBAL_DEF("rendering/driver/threads/thread_model", OS::RENDER_THREAD_SAFE) == OS::RENDER_SEPARATE_THREAD;
  2351. }
  2352. if (editor || project_manager) {
  2353. // Editor and project manager cannot run with rendering in a separate thread (they will crash on startup).
  2354. separate_thread_render = 0;
  2355. }
  2356. #if !defined(THREADS_ENABLED)
  2357. separate_thread_render = 0;
  2358. #endif
  2359. OS::get_singleton()->_separate_thread_render = separate_thread_render;
  2360. /* Determine audio and video drivers */
  2361. // Display driver, e.g. X11, Wayland.
  2362. // Make sure that headless is the last one, which it is assumed to be by design.
  2363. DEV_ASSERT(NULL_DISPLAY_DRIVER == DisplayServer::get_create_function_name(DisplayServer::get_create_function_count() - 1));
  2364. GLOBAL_DEF_NOVAL("display/display_server/driver", "default");
  2365. GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.windows", PROPERTY_HINT_ENUM_SUGGESTION, "default,windows,headless"), "default");
  2366. GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.linuxbsd", PROPERTY_HINT_ENUM_SUGGESTION, "default,x11,wayland,headless"), "default");
  2367. GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.android", PROPERTY_HINT_ENUM_SUGGESTION, "default,android,headless"), "default");
  2368. GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.ios", PROPERTY_HINT_ENUM_SUGGESTION, "default,iOS,headless"), "default");
  2369. GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.visionos", PROPERTY_HINT_ENUM_SUGGESTION, "default,visionOS,headless"), "default");
  2370. GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.macos", PROPERTY_HINT_ENUM_SUGGESTION, "default,macos,headless"), "default");
  2371. GLOBAL_DEF_RST_NOVAL("audio/driver/driver", AudioDriverManager::get_driver(0)->get_name());
  2372. if (audio_driver.is_empty()) { // Specified in project.godot.
  2373. if (project_manager) {
  2374. // The project manager doesn't need to play sound (TTS audio output is not emitted by Godot, but by the system itself).
  2375. // Disable audio output so it doesn't appear in the list of applications outputting sound in the OS.
  2376. // On macOS, this also prevents the project manager from inhibiting suspend.
  2377. audio_driver = "Dummy";
  2378. } else {
  2379. audio_driver = GLOBAL_GET("audio/driver/driver");
  2380. }
  2381. }
  2382. // Make sure that dummy is the last one, which it is assumed to be by design.
  2383. DEV_ASSERT(NULL_AUDIO_DRIVER == AudioDriverManager::get_driver(AudioDriverManager::get_driver_count() - 1)->get_name());
  2384. for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) {
  2385. if (audio_driver == AudioDriverManager::get_driver(i)->get_name()) {
  2386. audio_driver_idx = i;
  2387. break;
  2388. }
  2389. }
  2390. if (audio_driver_idx < 0) {
  2391. // If the requested driver wasn't found, pick the first entry.
  2392. // If all else failed it would be the dummy driver (no sound).
  2393. audio_driver_idx = 0;
  2394. }
  2395. if (Engine::get_singleton()->get_write_movie_path() != String()) {
  2396. // Always use dummy driver for audio driver (which is last), also in no threaded mode.
  2397. audio_driver_idx = AudioDriverManager::get_driver_count() - 1;
  2398. AudioDriverDummy::get_dummy_singleton()->set_use_threads(false);
  2399. }
  2400. {
  2401. window_orientation = DisplayServer::ScreenOrientation(int(GLOBAL_DEF_BASIC("display/window/handheld/orientation", DisplayServer::ScreenOrientation::SCREEN_LANDSCAPE)));
  2402. }
  2403. {
  2404. window_vsync_mode = DisplayServer::VSyncMode(int(GLOBAL_DEF_BASIC("display/window/vsync/vsync_mode", DisplayServer::VSyncMode::VSYNC_ENABLED)));
  2405. if (disable_vsync) {
  2406. window_vsync_mode = DisplayServer::VSyncMode::VSYNC_DISABLED;
  2407. }
  2408. }
  2409. GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "audio/driver/output_latency", PROPERTY_HINT_RANGE, "1,100,1"), 15);
  2410. // Use a safer default output_latency for web to avoid audio cracking on low-end devices, especially mobile.
  2411. GLOBAL_DEF_RST("audio/driver/output_latency.web", 50);
  2412. Engine::get_singleton()->set_audio_output_latency(GLOBAL_GET("audio/driver/output_latency"));
  2413. #if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
  2414. OS::get_singleton()->set_environment("MVK_CONFIG_LOG_LEVEL", OS::get_singleton()->_verbose_stdout ? "3" : "1"); // 1 = Errors only, 3 = Info
  2415. #endif
  2416. if (frame_delay == 0) {
  2417. frame_delay = GLOBAL_DEF(PropertyInfo(Variant::INT, "application/run/frame_delay_msec", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), 0);
  2418. if (Engine::get_singleton()->is_editor_hint()) {
  2419. frame_delay = 0;
  2420. }
  2421. }
  2422. if (audio_output_latency >= 1) {
  2423. Engine::get_singleton()->set_audio_output_latency(audio_output_latency);
  2424. }
  2425. GLOBAL_DEF("display/window/ios/allow_high_refresh_rate", true);
  2426. GLOBAL_DEF("display/window/ios/hide_home_indicator", true);
  2427. GLOBAL_DEF("display/window/ios/hide_status_bar", true);
  2428. GLOBAL_DEF("display/window/ios/suppress_ui_gesture", true);
  2429. #ifndef _3D_DISABLED
  2430. // XR project settings.
  2431. GLOBAL_DEF_RST_BASIC("xr/openxr/enabled", false);
  2432. GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "xr/openxr/default_action_map", PROPERTY_HINT_FILE, "*.tres"), "res://openxr_action_map.tres");
  2433. GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/form_factor", PROPERTY_HINT_ENUM, "Head Mounted,Handheld"), "0");
  2434. GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/view_configuration", PROPERTY_HINT_ENUM, "Mono,Stereo"), "1"); // "Mono,Stereo,Quad,Observer"
  2435. GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/reference_space", PROPERTY_HINT_ENUM, "Local,Stage,Local Floor"), "1");
  2436. GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/environment_blend_mode", PROPERTY_HINT_ENUM, "Opaque,Additive,Alpha"), "0");
  2437. GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/foveation_level", PROPERTY_HINT_ENUM, "Off,Low,Medium,High"), "0");
  2438. GLOBAL_DEF_BASIC("xr/openxr/foveation_dynamic", false);
  2439. GLOBAL_DEF_BASIC("xr/openxr/submit_depth_buffer", false);
  2440. GLOBAL_DEF_BASIC("xr/openxr/startup_alert", true);
  2441. // OpenXR project extensions settings.
  2442. GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/extensions/debug_utils", PROPERTY_HINT_ENUM, "Disabled,Error,Warning,Info,Verbose"), "0");
  2443. GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/extensions/debug_message_types", PROPERTY_HINT_FLAGS, "General,Validation,Performance,Conformance"), "15");
  2444. GLOBAL_DEF_BASIC("xr/openxr/extensions/hand_tracking", false);
  2445. GLOBAL_DEF_BASIC("xr/openxr/extensions/hand_tracking_unobstructed_data_source", false); // XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT
  2446. GLOBAL_DEF_BASIC("xr/openxr/extensions/hand_tracking_controller_data_source", false); // XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT
  2447. GLOBAL_DEF_RST_BASIC("xr/openxr/extensions/hand_interaction_profile", false);
  2448. GLOBAL_DEF_RST_BASIC("xr/openxr/extensions/eye_gaze_interaction", false);
  2449. GLOBAL_DEF_BASIC("xr/openxr/extensions/render_model", false);
  2450. // OpenXR Binding modifier settings
  2451. GLOBAL_DEF_BASIC("xr/openxr/binding_modifiers/analog_threshold", false);
  2452. GLOBAL_DEF_RST_BASIC("xr/openxr/binding_modifiers/dpad_binding", false);
  2453. #ifdef TOOLS_ENABLED
  2454. // Disabled for now, using XR inside of the editor we'll be working on during the coming months.
  2455. // editor settings (it seems we're too early in the process when setting up rendering, to access editor settings...)
  2456. // EDITOR_DEF_RST("xr/openxr/in_editor", false);
  2457. // GLOBAL_DEF("xr/openxr/in_editor", false);
  2458. #endif // TOOLS_ENABLED
  2459. #endif // _3D_DISABLED
  2460. Engine::get_singleton()->set_frame_delay(frame_delay);
  2461. message_queue = memnew(MessageQueue);
  2462. Thread::release_main_thread(); // If setup2() is called from another thread, that one will become main thread, so preventively release this one.
  2463. set_current_thread_safe_for_nodes(false);
  2464. #if defined(STEAMAPI_ENABLED)
  2465. if (editor || project_manager) {
  2466. steam_tracker = memnew(SteamTracker);
  2467. }
  2468. #endif
  2469. OS::get_singleton()->benchmark_end_measure("Startup", "Main::Setup");
  2470. if (p_second_phase) {
  2471. exit_err = setup2();
  2472. if (exit_err != OK) {
  2473. goto error;
  2474. }
  2475. }
  2476. return OK;
  2477. error:
  2478. text_driver = "";
  2479. display_driver = "";
  2480. audio_driver = "";
  2481. tablet_driver = "";
  2482. Engine::get_singleton()->set_write_movie_path(String());
  2483. project_path = "";
  2484. args.clear();
  2485. main_args.clear();
  2486. if (show_help) {
  2487. print_help(execpath);
  2488. }
  2489. if (editor) {
  2490. OS::get_singleton()->remove_lock_file();
  2491. }
  2492. EngineDebugger::deinitialize();
  2493. if (performance) {
  2494. memdelete(performance);
  2495. }
  2496. if (input_map) {
  2497. memdelete(input_map);
  2498. }
  2499. if (translation_server) {
  2500. memdelete(translation_server);
  2501. }
  2502. if (globals) {
  2503. memdelete(globals);
  2504. }
  2505. if (packed_data) {
  2506. memdelete(packed_data);
  2507. }
  2508. unregister_core_driver_types();
  2509. unregister_core_extensions();
  2510. if (engine) {
  2511. memdelete(engine);
  2512. }
  2513. unregister_core_types();
  2514. OS::get_singleton()->_cmdline.clear();
  2515. OS::get_singleton()->_user_args.clear();
  2516. if (message_queue) {
  2517. memdelete(message_queue);
  2518. }
  2519. OS::get_singleton()->benchmark_end_measure("Startup", "Main::Setup");
  2520. #if defined(STEAMAPI_ENABLED)
  2521. if (steam_tracker) {
  2522. memdelete(steam_tracker);
  2523. }
  2524. #endif
  2525. OS::get_singleton()->finalize_core();
  2526. locale = String();
  2527. return exit_err;
  2528. }
  2529. Error _parse_resource_dummy(void *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
  2530. VariantParser::Token token;
  2531. VariantParser::get_token(p_stream, token, line, r_err_str);
  2532. if (token.type != VariantParser::TK_NUMBER && token.type != VariantParser::TK_STRING) {
  2533. r_err_str = "Expected number (old style sub-resource index) or String (ext-resource ID)";
  2534. return ERR_PARSE_ERROR;
  2535. }
  2536. r_res.unref();
  2537. VariantParser::get_token(p_stream, token, line, r_err_str);
  2538. if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
  2539. r_err_str = "Expected ')'";
  2540. return ERR_PARSE_ERROR;
  2541. }
  2542. return OK;
  2543. }
  2544. Error Main::setup2(bool p_show_boot_logo) {
  2545. OS::get_singleton()->benchmark_begin_measure("Startup", "Main::Setup2");
  2546. Thread::make_main_thread(); // Make whatever thread call this the main thread.
  2547. set_current_thread_safe_for_nodes(true);
  2548. // Don't use rich formatting to prevent ANSI escape codes from being written to log files.
  2549. print_header(false);
  2550. #ifdef TOOLS_ENABLED
  2551. int accessibility_mode_editor = 0;
  2552. int tablet_driver_editor = -1;
  2553. if (editor || project_manager || cmdline_tool) {
  2554. OS::get_singleton()->benchmark_begin_measure("Startup", "Initialize Early Settings");
  2555. EditorPaths::create();
  2556. // Editor setting class is not available, load config directly.
  2557. if (!init_use_custom_screen && (editor || project_manager) && EditorPaths::get_singleton()->are_paths_valid()) {
  2558. ERR_FAIL_COND_V(!DirAccess::dir_exists_absolute(EditorPaths::get_singleton()->get_config_dir()), FAILED);
  2559. String config_file_path = EditorSettings::get_existing_settings_path();
  2560. if (FileAccess::exists(config_file_path)) {
  2561. Error err;
  2562. Ref<FileAccess> f = FileAccess::open(config_file_path, FileAccess::READ, &err);
  2563. if (f.is_valid()) {
  2564. VariantParser::StreamFile stream;
  2565. stream.f = f;
  2566. String assign;
  2567. Variant value;
  2568. VariantParser::Tag next_tag;
  2569. int lines = 0;
  2570. String error_text;
  2571. VariantParser::ResourceParser rp_new;
  2572. rp_new.ext_func = _parse_resource_dummy;
  2573. rp_new.sub_func = _parse_resource_dummy;
  2574. bool screen_found = false;
  2575. String screen_property;
  2576. bool prefer_wayland_found = false;
  2577. bool prefer_wayland = false;
  2578. bool tablet_found = false;
  2579. bool ac_found = false;
  2580. if (editor) {
  2581. screen_property = "interface/editor/editor_screen";
  2582. } else if (project_manager) {
  2583. screen_property = "interface/editor/project_manager_screen";
  2584. } else {
  2585. // Skip.
  2586. screen_found = true;
  2587. }
  2588. if (!display_driver.is_empty()) {
  2589. // Skip.
  2590. prefer_wayland_found = true;
  2591. }
  2592. while (!screen_found || !init_expand_to_title_found || !init_display_scale_found || !init_custom_scale_found || !prefer_wayland_found || !tablet_found || !ac_found) {
  2593. assign = Variant();
  2594. next_tag.fields.clear();
  2595. next_tag.name = String();
  2596. err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp_new, true);
  2597. if (err == ERR_FILE_EOF) {
  2598. break;
  2599. }
  2600. if (err == OK && !assign.is_empty()) {
  2601. if (!screen_found && assign == screen_property) {
  2602. init_screen = value;
  2603. screen_found = true;
  2604. if (editor) {
  2605. restore_editor_window_layout = value.operator int() == EditorSettings::InitialScreen::INITIAL_SCREEN_AUTO;
  2606. }
  2607. }
  2608. if (!ac_found && assign == "interface/accessibility/accessibility_support") {
  2609. accessibility_mode_editor = value;
  2610. ac_found = true;
  2611. } else if (!init_expand_to_title_found && assign == "interface/editor/expand_to_title") {
  2612. init_expand_to_title = value;
  2613. init_expand_to_title_found = true;
  2614. } else if (!init_display_scale_found && assign == "interface/editor/display_scale") {
  2615. init_display_scale = value;
  2616. init_display_scale_found = true;
  2617. } else if (!init_custom_scale_found && assign == "interface/editor/custom_display_scale") {
  2618. init_custom_scale = value;
  2619. init_custom_scale_found = true;
  2620. } else if (!prefer_wayland_found && assign == "run/platforms/linuxbsd/prefer_wayland") {
  2621. prefer_wayland = value;
  2622. prefer_wayland_found = true;
  2623. } else if (!tablet_found && assign == "interface/editor/tablet_driver") {
  2624. tablet_driver_editor = value;
  2625. tablet_found = true;
  2626. }
  2627. }
  2628. }
  2629. if (display_driver.is_empty()) {
  2630. if (prefer_wayland) {
  2631. display_driver = "wayland";
  2632. } else {
  2633. display_driver = "default";
  2634. }
  2635. }
  2636. }
  2637. }
  2638. }
  2639. if (found_project && EditorPaths::get_singleton()->is_self_contained()) {
  2640. if (ProjectSettings::get_singleton()->get_resource_path() == OS::get_singleton()->get_executable_path().get_base_dir()) {
  2641. ERR_PRINT("You are trying to run a self-contained editor at the same location as a project. This is not allowed, since editor files will mix with project files.");
  2642. OS::get_singleton()->set_exit_code(EXIT_FAILURE);
  2643. return FAILED;
  2644. }
  2645. }
  2646. bool has_command_line_window_override = init_use_custom_pos || init_use_custom_screen || init_windowed;
  2647. if (editor && !has_command_line_window_override && restore_editor_window_layout) {
  2648. Ref<ConfigFile> config;
  2649. config.instantiate();
  2650. // Load and amend existing config if it exists.
  2651. Error err = config->load(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg"));
  2652. if (err == OK) {
  2653. init_screen = config->get_value("EditorWindow", "screen", init_screen);
  2654. String mode = config->get_value("EditorWindow", "mode", "maximized");
  2655. window_size = config->get_value("EditorWindow", "size", window_size);
  2656. if (mode == "windowed") {
  2657. window_mode = DisplayServer::WINDOW_MODE_WINDOWED;
  2658. init_windowed = true;
  2659. } else if (mode == "fullscreen") {
  2660. window_mode = DisplayServer::WINDOW_MODE_FULLSCREEN;
  2661. init_fullscreen = true;
  2662. } else {
  2663. window_mode = DisplayServer::WINDOW_MODE_MAXIMIZED;
  2664. init_maximized = true;
  2665. }
  2666. if (init_windowed) {
  2667. init_use_custom_pos = true;
  2668. init_custom_pos = config->get_value("EditorWindow", "position", Vector2i(0, 0));
  2669. }
  2670. }
  2671. }
  2672. if (init_screen == EditorSettings::InitialScreen::INITIAL_SCREEN_AUTO) {
  2673. init_screen = DisplayServer::SCREEN_PRIMARY;
  2674. }
  2675. OS::get_singleton()->benchmark_end_measure("Startup", "Initialize Early Settings");
  2676. }
  2677. #endif
  2678. OS::get_singleton()->benchmark_begin_measure("Startup", "Servers");
  2679. tsman = memnew(TextServerManager);
  2680. if (tsman) {
  2681. Ref<TextServerDummy> ts;
  2682. ts.instantiate();
  2683. tsman->add_interface(ts);
  2684. }
  2685. #ifndef PHYSICS_3D_DISABLED
  2686. physics_server_3d_manager = memnew(PhysicsServer3DManager);
  2687. #endif // PHYSICS_3D_DISABLED
  2688. #ifndef PHYSICS_2D_DISABLED
  2689. physics_server_2d_manager = memnew(PhysicsServer2DManager);
  2690. #endif // PHYSICS_2D_DISABLED
  2691. register_server_types();
  2692. {
  2693. OS::get_singleton()->benchmark_begin_measure("Servers", "Modules and Extensions");
  2694. initialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS);
  2695. GDExtensionManager::get_singleton()->initialize_extensions(GDExtension::INITIALIZATION_LEVEL_SERVERS);
  2696. OS::get_singleton()->benchmark_end_measure("Servers", "Modules and Extensions");
  2697. }
  2698. /* Initialize Input */
  2699. {
  2700. OS::get_singleton()->benchmark_begin_measure("Servers", "Input");
  2701. input = memnew(Input);
  2702. OS::get_singleton()->initialize_joypads();
  2703. OS::get_singleton()->benchmark_end_measure("Servers", "Input");
  2704. }
  2705. /* Initialize Display Server */
  2706. {
  2707. OS::get_singleton()->benchmark_begin_measure("Servers", "Display");
  2708. if (display_driver.is_empty()) {
  2709. display_driver = GLOBAL_GET("display/display_server/driver");
  2710. }
  2711. int display_driver_idx = -1;
  2712. if (display_driver.is_empty() || display_driver == "default") {
  2713. display_driver_idx = 0;
  2714. } else {
  2715. for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
  2716. String name = DisplayServer::get_create_function_name(i);
  2717. if (display_driver == name) {
  2718. display_driver_idx = i;
  2719. break;
  2720. }
  2721. }
  2722. if (display_driver_idx < 0) {
  2723. // If the requested driver wasn't found, pick the first entry.
  2724. // If all else failed it would be the headless server.
  2725. display_driver_idx = 0;
  2726. }
  2727. }
  2728. Vector2i *window_position = nullptr;
  2729. Vector2i position = init_custom_pos;
  2730. if (init_use_custom_pos) {
  2731. window_position = &position;
  2732. }
  2733. Color boot_bg_color = GLOBAL_DEF_BASIC("application/boot_splash/bg_color", boot_splash_bg_color);
  2734. DisplayServer::set_early_window_clear_color_override(true, boot_bg_color);
  2735. DisplayServer::Context context;
  2736. if (editor) {
  2737. context = DisplayServer::CONTEXT_EDITOR;
  2738. } else if (project_manager) {
  2739. context = DisplayServer::CONTEXT_PROJECTMAN;
  2740. } else {
  2741. context = DisplayServer::CONTEXT_ENGINE;
  2742. }
  2743. if (init_embed_parent_window_id) {
  2744. // Reset flags and other settings to be sure it's borderless and windowed. The position and size should have been initialized correctly
  2745. // from --position and --resolution parameters.
  2746. window_mode = DisplayServer::WINDOW_MODE_WINDOWED;
  2747. window_flags = DisplayServer::WINDOW_FLAG_BORDERLESS_BIT;
  2748. if (bool(GLOBAL_GET("display/window/size/transparent"))) {
  2749. window_flags |= DisplayServer::WINDOW_FLAG_TRANSPARENT_BIT;
  2750. }
  2751. }
  2752. #ifdef TOOLS_ENABLED
  2753. if ((project_manager || editor) && init_expand_to_title) {
  2754. window_flags |= DisplayServer::WINDOW_FLAG_EXTEND_TO_TITLE_BIT;
  2755. }
  2756. #endif
  2757. if (!accessibility_mode_set) {
  2758. #ifdef TOOLS_ENABLED
  2759. if (editor || project_manager || cmdline_tool) {
  2760. accessibility_mode = (DisplayServer::AccessibilityMode)accessibility_mode_editor;
  2761. } else {
  2762. #else
  2763. {
  2764. #endif
  2765. accessibility_mode = (DisplayServer::AccessibilityMode)GLOBAL_GET("accessibility/general/accessibility_support").operator int64_t();
  2766. }
  2767. }
  2768. DisplayServer::accessibility_set_mode(accessibility_mode);
  2769. // rendering_driver now held in static global String in main and initialized in setup()
  2770. Error err;
  2771. display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_vsync_mode, window_flags, window_position, window_size, init_screen, context, init_embed_parent_window_id, err);
  2772. if (err != OK || display_server == nullptr) {
  2773. String last_name = DisplayServer::get_create_function_name(display_driver_idx);
  2774. // We can't use this display server, try other ones as fallback.
  2775. // Skip headless (always last registered) because that's not what users
  2776. // would expect if they didn't request it explicitly.
  2777. for (int i = 0; i < DisplayServer::get_create_function_count() - 1; i++) {
  2778. if (i == display_driver_idx) {
  2779. continue; // Don't try the same twice.
  2780. }
  2781. String name = DisplayServer::get_create_function_name(i);
  2782. WARN_PRINT(vformat("Display driver %s failed, falling back to %s.", last_name, name));
  2783. display_server = DisplayServer::create(i, rendering_driver, window_mode, window_vsync_mode, window_flags, window_position, window_size, init_screen, context, init_embed_parent_window_id, err);
  2784. if (err == OK && display_server != nullptr) {
  2785. break;
  2786. }
  2787. }
  2788. }
  2789. if (err != OK || display_server == nullptr) {
  2790. ERR_PRINT("Unable to create DisplayServer, all display drivers failed.\nUse \"--headless\" command line argument to run the engine in headless mode if this is desired (e.g. for continuous integration).");
  2791. if (display_server) {
  2792. memdelete(display_server);
  2793. }
  2794. GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_SERVERS);
  2795. uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS);
  2796. unregister_server_types();
  2797. if (input) {
  2798. memdelete(input);
  2799. }
  2800. if (tsman) {
  2801. memdelete(tsman);
  2802. }
  2803. #ifndef PHYSICS_3D_DISABLED
  2804. if (physics_server_3d_manager) {
  2805. memdelete(physics_server_3d_manager);
  2806. }
  2807. #endif // PHYSICS_3D_DISABLED
  2808. #ifndef PHYSICS_2D_DISABLED
  2809. if (physics_server_2d_manager) {
  2810. memdelete(physics_server_2d_manager);
  2811. }
  2812. #endif // PHYSICS_2D_DISABLED
  2813. return err;
  2814. }
  2815. #ifdef TOOLS_ENABLED
  2816. if (project_manager) {
  2817. float ui_scale = init_custom_scale;
  2818. switch (init_display_scale) {
  2819. case 0:
  2820. ui_scale = EditorSettings::get_auto_display_scale();
  2821. break;
  2822. case 1:
  2823. ui_scale = 0.75;
  2824. break;
  2825. case 2:
  2826. ui_scale = 1.0;
  2827. break;
  2828. case 3:
  2829. ui_scale = 1.25;
  2830. break;
  2831. case 4:
  2832. ui_scale = 1.5;
  2833. break;
  2834. case 5:
  2835. ui_scale = 1.75;
  2836. break;
  2837. case 6:
  2838. ui_scale = 2.0;
  2839. break;
  2840. default:
  2841. break;
  2842. }
  2843. if (!(force_res || use_custom_res)) {
  2844. display_server->window_set_size(Size2(window_size) * ui_scale, DisplayServer::MAIN_WINDOW_ID);
  2845. }
  2846. if (display_server->has_feature(DisplayServer::FEATURE_SUBWINDOWS) && !display_server->has_feature(DisplayServer::FEATURE_SELF_FITTING_WINDOWS)) {
  2847. Size2 real_size = DisplayServer::get_singleton()->window_get_size();
  2848. Rect2i scr_rect = display_server->screen_get_usable_rect(init_screen);
  2849. display_server->window_set_position(scr_rect.position + (scr_rect.size - real_size) / 2, DisplayServer::MAIN_WINDOW_ID);
  2850. }
  2851. }
  2852. #endif
  2853. if (display_server->has_feature(DisplayServer::FEATURE_SUBWINDOWS)) {
  2854. display_server->show_window(DisplayServer::MAIN_WINDOW_ID);
  2855. }
  2856. if (display_server->has_feature(DisplayServer::FEATURE_ORIENTATION)) {
  2857. display_server->screen_set_orientation(window_orientation);
  2858. }
  2859. OS::get_singleton()->benchmark_end_measure("Servers", "Display");
  2860. }
  2861. // Max FPS needs to be set after the DisplayServer is created.
  2862. RenderingDevice *rd = RenderingDevice::get_singleton();
  2863. if (rd) {
  2864. rd->_set_max_fps(engine->get_max_fps());
  2865. }
  2866. #ifdef TOOLS_ENABLED
  2867. // If the editor is running in windowed mode, ensure the window rect fits
  2868. // the screen in case screen count or position has changed.
  2869. if (editor && init_windowed) {
  2870. // We still need to check we are actually in windowed mode, because
  2871. // certain platform might only support one fullscreen window.
  2872. if (DisplayServer::get_singleton()->window_get_mode() == DisplayServer::WINDOW_MODE_WINDOWED) {
  2873. Vector2i current_size = DisplayServer::get_singleton()->window_get_size();
  2874. Vector2i current_pos = DisplayServer::get_singleton()->window_get_position();
  2875. int screen = DisplayServer::get_singleton()->window_get_current_screen();
  2876. Rect2i screen_rect = DisplayServer::get_singleton()->screen_get_usable_rect(screen);
  2877. Vector2i adjusted_end = screen_rect.get_end().min(current_pos + current_size);
  2878. Vector2i adjusted_pos = screen_rect.get_position().max(adjusted_end - current_size);
  2879. Vector2i adjusted_size = DisplayServer::get_singleton()->window_get_min_size().max(adjusted_end - adjusted_pos);
  2880. if (current_pos != adjusted_end || current_size != adjusted_size) {
  2881. DisplayServer::get_singleton()->window_set_position(adjusted_pos);
  2882. DisplayServer::get_singleton()->window_set_size(adjusted_size);
  2883. }
  2884. }
  2885. }
  2886. #endif
  2887. if (GLOBAL_GET("debug/settings/stdout/print_fps") || print_fps) {
  2888. // Print requested V-Sync mode at startup to diagnose the printed FPS not going above the monitor refresh rate.
  2889. switch (window_vsync_mode) {
  2890. case DisplayServer::VSyncMode::VSYNC_DISABLED:
  2891. print_line("Requested V-Sync mode: Disabled");
  2892. break;
  2893. case DisplayServer::VSyncMode::VSYNC_ENABLED:
  2894. print_line("Requested V-Sync mode: Enabled - FPS will likely be capped to the monitor refresh rate.");
  2895. break;
  2896. case DisplayServer::VSyncMode::VSYNC_ADAPTIVE:
  2897. print_line("Requested V-Sync mode: Adaptive");
  2898. break;
  2899. case DisplayServer::VSyncMode::VSYNC_MAILBOX:
  2900. print_line("Requested V-Sync mode: Mailbox");
  2901. break;
  2902. }
  2903. }
  2904. if (OS::get_singleton()->_separate_thread_render) {
  2905. WARN_PRINT("The separate rendering thread feature is experimental. Feel free to try it since it will eventually become a stable feature.\n"
  2906. "However, bear in mind that at the moment it can lead to project crashes or instability.\n"
  2907. "So, unless you want to test the engine, set the \"rendering/driver/threads/thread_model\" project setting to 'Safe'.");
  2908. }
  2909. /* Initialize Pen Tablet Driver */
  2910. {
  2911. OS::get_singleton()->benchmark_begin_measure("Servers", "Tablet Driver");
  2912. GLOBAL_DEF_RST_NOVAL("input_devices/pen_tablet/driver", "");
  2913. GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "input_devices/pen_tablet/driver.windows", PROPERTY_HINT_ENUM, "auto,winink,wintab,dummy"), "");
  2914. #ifdef TOOLS_ENABLED
  2915. if (tablet_driver.is_empty() && tablet_driver_editor != -1) {
  2916. tablet_driver = DisplayServer::get_singleton()->tablet_get_driver_name(tablet_driver_editor);
  2917. }
  2918. #endif
  2919. if (tablet_driver.is_empty()) { // specified in project.godot
  2920. tablet_driver = GLOBAL_GET("input_devices/pen_tablet/driver");
  2921. if (tablet_driver.is_empty()) {
  2922. tablet_driver = DisplayServer::get_singleton()->tablet_get_driver_name(0);
  2923. }
  2924. }
  2925. for (int i = 0; i < DisplayServer::get_singleton()->tablet_get_driver_count(); i++) {
  2926. if (tablet_driver == DisplayServer::get_singleton()->tablet_get_driver_name(i)) {
  2927. DisplayServer::get_singleton()->tablet_set_current_driver(DisplayServer::get_singleton()->tablet_get_driver_name(i));
  2928. break;
  2929. }
  2930. }
  2931. if (DisplayServer::get_singleton()->tablet_get_current_driver().is_empty()) {
  2932. DisplayServer::get_singleton()->tablet_set_current_driver(DisplayServer::get_singleton()->tablet_get_driver_name(0));
  2933. }
  2934. print_verbose("Using \"" + DisplayServer::get_singleton()->tablet_get_current_driver() + "\" pen tablet driver...");
  2935. OS::get_singleton()->benchmark_end_measure("Servers", "Tablet Driver");
  2936. }
  2937. /* Initialize Rendering Server */
  2938. {
  2939. OS::get_singleton()->benchmark_begin_measure("Servers", "Rendering");
  2940. rendering_server = memnew(RenderingServerDefault(OS::get_singleton()->is_separate_thread_rendering_enabled()));
  2941. rendering_server->init();
  2942. //rendering_server->call_set_use_vsync(OS::get_singleton()->_use_vsync);
  2943. rendering_server->set_render_loop_enabled(!disable_render_loop);
  2944. if (profile_gpu || (!editor && bool(GLOBAL_GET("debug/settings/stdout/print_gpu_profile")))) {
  2945. rendering_server->set_print_gpu_profile(true);
  2946. }
  2947. OS::get_singleton()->benchmark_end_measure("Servers", "Rendering");
  2948. }
  2949. #ifdef UNIX_ENABLED
  2950. // Print warning after initializing the renderer but before initializing audio.
  2951. if (OS::get_singleton()->get_environment("USER") == "root" && !OS::get_singleton()->has_environment("GODOT_SILENCE_ROOT_WARNING")) {
  2952. WARN_PRINT("Started the engine as `root`/superuser. This is a security risk, and subsystems like audio may not work correctly.\nSet the environment variable `GODOT_SILENCE_ROOT_WARNING` to 1 to silence this warning.");
  2953. }
  2954. #endif
  2955. /* Initialize Audio Driver */
  2956. {
  2957. OS::get_singleton()->benchmark_begin_measure("Servers", "Audio");
  2958. AudioDriverManager::initialize(audio_driver_idx);
  2959. // Right moment to create and initialize the audio server.
  2960. audio_server = memnew(AudioServer);
  2961. audio_server->init();
  2962. OS::get_singleton()->benchmark_end_measure("Servers", "Audio");
  2963. }
  2964. #ifndef XR_DISABLED
  2965. /* Initialize XR Server */
  2966. {
  2967. OS::get_singleton()->benchmark_begin_measure("Servers", "XR");
  2968. xr_server = memnew(XRServer);
  2969. OS::get_singleton()->benchmark_end_measure("Servers", "XR");
  2970. }
  2971. #endif // XR_DISABLED
  2972. OS::get_singleton()->benchmark_end_measure("Startup", "Servers");
  2973. #ifndef WEB_ENABLED
  2974. // Add a blank line for readability.
  2975. Engine::get_singleton()->print_header("");
  2976. #endif // WEB_ENABLED
  2977. register_core_singletons();
  2978. /* Initialize the main window and boot screen */
  2979. {
  2980. OS::get_singleton()->benchmark_begin_measure("Startup", "Setup Window and Boot");
  2981. MAIN_PRINT("Main: Setup Logo");
  2982. if (!init_embed_parent_window_id) {
  2983. if (init_windowed) {
  2984. //do none..
  2985. } else if (init_maximized) {
  2986. DisplayServer::get_singleton()->window_set_mode(DisplayServer::WINDOW_MODE_MAXIMIZED);
  2987. } else if (init_fullscreen) {
  2988. DisplayServer::get_singleton()->window_set_mode(DisplayServer::WINDOW_MODE_FULLSCREEN);
  2989. }
  2990. if (init_always_on_top) {
  2991. DisplayServer::get_singleton()->window_set_flag(DisplayServer::WINDOW_FLAG_ALWAYS_ON_TOP, true);
  2992. }
  2993. }
  2994. Color clear = GLOBAL_DEF_BASIC("rendering/environment/defaults/default_clear_color", Color(0.3, 0.3, 0.3));
  2995. RenderingServer::get_singleton()->set_default_clear_color(clear);
  2996. if (p_show_boot_logo) {
  2997. setup_boot_logo();
  2998. }
  2999. MAIN_PRINT("Main: Clear Color");
  3000. DisplayServer::set_early_window_clear_color_override(false);
  3001. GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "application/config/icon", PROPERTY_HINT_FILE, "*.png,*.bmp,*.hdr,*.jpg,*.jpeg,*.svg,*.tga,*.exr,*.webp"), String());
  3002. GLOBAL_DEF(PropertyInfo(Variant::STRING, "application/config/macos_native_icon", PROPERTY_HINT_FILE, "*.icns"), String());
  3003. GLOBAL_DEF(PropertyInfo(Variant::STRING, "application/config/windows_native_icon", PROPERTY_HINT_FILE, "*.ico"), String());
  3004. MAIN_PRINT("Main: Touch Input");
  3005. Input *id = Input::get_singleton();
  3006. if (id) {
  3007. bool agile_input_event_flushing = GLOBAL_DEF("input_devices/buffering/agile_event_flushing", false);
  3008. id->set_agile_input_event_flushing(agile_input_event_flushing);
  3009. if (bool(GLOBAL_DEF_BASIC("input_devices/pointing/emulate_touch_from_mouse", false)) &&
  3010. !(editor || project_manager)) {
  3011. if (!DisplayServer::get_singleton()->is_touchscreen_available()) {
  3012. //only if no touchscreen ui hint, set emulation
  3013. id->set_emulate_touch_from_mouse(true);
  3014. }
  3015. }
  3016. id->set_emulate_mouse_from_touch(bool(GLOBAL_DEF_BASIC("input_devices/pointing/emulate_mouse_from_touch", true)));
  3017. if (editor) {
  3018. id->set_emulate_mouse_from_touch(true);
  3019. }
  3020. }
  3021. OS::get_singleton()->benchmark_end_measure("Startup", "Setup Window and Boot");
  3022. }
  3023. MAIN_PRINT("Main: Load Translations and Remaps");
  3024. /* Setup translations and remaps */
  3025. {
  3026. OS::get_singleton()->benchmark_begin_measure("Startup", "Translations and Remaps");
  3027. translation_server->setup(); //register translations, load them, etc.
  3028. if (!locale.is_empty()) {
  3029. translation_server->set_locale(locale);
  3030. }
  3031. translation_server->load_translations();
  3032. ResourceLoader::load_translation_remaps(); //load remaps for resources
  3033. OS::get_singleton()->benchmark_end_measure("Startup", "Translations and Remaps");
  3034. }
  3035. MAIN_PRINT("Main: Load TextServer");
  3036. /* Setup Text Server */
  3037. {
  3038. OS::get_singleton()->benchmark_begin_measure("Startup", "Text Server");
  3039. /* Enum text drivers */
  3040. GLOBAL_DEF_RST("internationalization/rendering/text_driver", "");
  3041. String text_driver_options;
  3042. for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
  3043. const String driver_name = TextServerManager::get_singleton()->get_interface(i)->get_name();
  3044. if (driver_name == "Dummy") {
  3045. // Dummy text driver cannot draw any text, making the editor unusable if selected.
  3046. continue;
  3047. }
  3048. if (!text_driver_options.is_empty() && !text_driver_options.contains_char(',')) {
  3049. // Not the first option; add a comma before it as a separator for the property hint.
  3050. text_driver_options += ",";
  3051. }
  3052. text_driver_options += driver_name;
  3053. }
  3054. ProjectSettings::get_singleton()->set_custom_property_info(PropertyInfo(Variant::STRING, "internationalization/rendering/text_driver", PROPERTY_HINT_ENUM, text_driver_options));
  3055. /* Determine text driver */
  3056. if (text_driver.is_empty()) {
  3057. text_driver = GLOBAL_GET("internationalization/rendering/text_driver");
  3058. }
  3059. if (!text_driver.is_empty()) {
  3060. /* Load user selected text server. */
  3061. for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
  3062. if (TextServerManager::get_singleton()->get_interface(i)->get_name() == text_driver) {
  3063. text_driver_idx = i;
  3064. break;
  3065. }
  3066. }
  3067. }
  3068. if (text_driver_idx < 0) {
  3069. /* If not selected, use one with the most features available. */
  3070. int max_features = 0;
  3071. for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
  3072. uint32_t features = TextServerManager::get_singleton()->get_interface(i)->get_features();
  3073. int feature_number = 0;
  3074. while (features) {
  3075. feature_number += features & 1;
  3076. features >>= 1;
  3077. }
  3078. if (feature_number >= max_features) {
  3079. max_features = feature_number;
  3080. text_driver_idx = i;
  3081. }
  3082. }
  3083. }
  3084. if (text_driver_idx >= 0) {
  3085. Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(text_driver_idx);
  3086. TextServerManager::get_singleton()->set_primary_interface(ts);
  3087. if (ts->has_feature(TextServer::FEATURE_USE_SUPPORT_DATA)) {
  3088. ts->load_support_data("res://" + ts->get_support_data_filename());
  3089. }
  3090. } else {
  3091. ERR_FAIL_V_MSG(ERR_CANT_CREATE, "TextServer: Unable to create TextServer interface.");
  3092. }
  3093. OS::get_singleton()->benchmark_end_measure("Startup", "Text Server");
  3094. }
  3095. MAIN_PRINT("Main: Load Scene Types");
  3096. OS::get_singleton()->benchmark_begin_measure("Startup", "Scene");
  3097. // Initialize ThemeDB early so that scene types can register their theme items.
  3098. // Default theme will be initialized later, after modules and ScriptServer are ready.
  3099. initialize_theme_db();
  3100. #if !defined(NAVIGATION_2D_DISABLED) || !defined(NAVIGATION_3D_DISABLED)
  3101. MAIN_PRINT("Main: Load Navigation");
  3102. #endif // !defined(NAVIGATION_2D_DISABLED) || !defined(NAVIGATION_3D_DISABLED)
  3103. #ifndef NAVIGATION_3D_DISABLED
  3104. NavigationServer3DManager::initialize_server();
  3105. #endif // NAVIGATION_3D_DISABLED
  3106. #ifndef NAVIGATION_2D_DISABLED
  3107. NavigationServer2DManager::initialize_server();
  3108. #endif // NAVIGATION_2D_DISABLED
  3109. register_scene_types();
  3110. register_driver_types();
  3111. register_scene_singletons();
  3112. {
  3113. OS::get_singleton()->benchmark_begin_measure("Scene", "Modules and Extensions");
  3114. initialize_modules(MODULE_INITIALIZATION_LEVEL_SCENE);
  3115. GDExtensionManager::get_singleton()->initialize_extensions(GDExtension::INITIALIZATION_LEVEL_SCENE);
  3116. OS::get_singleton()->benchmark_end_measure("Scene", "Modules and Extensions");
  3117. // We need to initialize the movie writer here in case
  3118. // one of the user-provided GDExtensions subclasses MovieWriter.
  3119. if (Engine::get_singleton()->get_write_movie_path() != String()) {
  3120. movie_writer = MovieWriter::find_writer_for_file(Engine::get_singleton()->get_write_movie_path());
  3121. if (movie_writer == nullptr) {
  3122. ERR_PRINT("Can't find movie writer for file type, aborting: " + Engine::get_singleton()->get_write_movie_path());
  3123. Engine::get_singleton()->set_write_movie_path(String());
  3124. }
  3125. }
  3126. }
  3127. PackedStringArray extensions;
  3128. extensions.push_back("gd");
  3129. if (ClassDB::class_exists("CSharpScript")) {
  3130. extensions.push_back("cs");
  3131. }
  3132. extensions.push_back("gdshader");
  3133. GLOBAL_DEF_NOVAL(PropertyInfo(Variant::PACKED_STRING_ARRAY, "editor/script/search_in_file_extensions"), extensions); // Note: should be defined after Scene level modules init to see .NET.
  3134. OS::get_singleton()->benchmark_end_measure("Startup", "Scene");
  3135. #ifdef TOOLS_ENABLED
  3136. ClassDB::set_current_api(ClassDB::API_EDITOR);
  3137. register_editor_types();
  3138. {
  3139. OS::get_singleton()->benchmark_begin_measure("Editor", "Modules and Extensions");
  3140. initialize_modules(MODULE_INITIALIZATION_LEVEL_EDITOR);
  3141. GDExtensionManager::get_singleton()->initialize_extensions(GDExtension::INITIALIZATION_LEVEL_EDITOR);
  3142. OS::get_singleton()->benchmark_end_measure("Editor", "Modules and Extensions");
  3143. }
  3144. ClassDB::set_current_api(ClassDB::API_CORE);
  3145. #endif
  3146. MAIN_PRINT("Main: Load Platforms");
  3147. OS::get_singleton()->benchmark_begin_measure("Startup", "Platforms");
  3148. register_platform_apis();
  3149. OS::get_singleton()->benchmark_end_measure("Startup", "Platforms");
  3150. GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "display/mouse_cursor/custom_image", PROPERTY_HINT_FILE, "*.png,*.bmp,*.hdr,*.jpg,*.jpeg,*.svg,*.tga,*.exr,*.webp"), String());
  3151. GLOBAL_DEF_BASIC("display/mouse_cursor/custom_image_hotspot", Vector2());
  3152. GLOBAL_DEF_BASIC("display/mouse_cursor/tooltip_position_offset", Point2(10, 10));
  3153. if (String(GLOBAL_GET("display/mouse_cursor/custom_image")) != String()) {
  3154. Ref<Texture2D> cursor = ResourceLoader::load(
  3155. GLOBAL_GET("display/mouse_cursor/custom_image"));
  3156. if (cursor.is_valid()) {
  3157. Vector2 hotspot = GLOBAL_GET("display/mouse_cursor/custom_image_hotspot");
  3158. Input::get_singleton()->set_custom_mouse_cursor(cursor, Input::CURSOR_ARROW, hotspot);
  3159. }
  3160. }
  3161. OS::get_singleton()->benchmark_begin_measure("Startup", "Finalize Setup");
  3162. camera_server = CameraServer::create();
  3163. MAIN_PRINT("Main: Load Physics");
  3164. initialize_physics();
  3165. register_server_singletons();
  3166. // This loads global classes, so it must happen before custom loaders and savers are registered
  3167. ScriptServer::init_languages();
  3168. #if TOOLS_ENABLED
  3169. // Setting up the callback to execute a scan for UIDs on disk when a UID
  3170. // does not exist in the UID cache on startup. This prevents invalid UID errors
  3171. // when opening a project without a UID cache file or with an invalid cache.
  3172. if (editor) {
  3173. ResourceUID::scan_for_uid_on_startup = EditorFileSystem::scan_for_uid;
  3174. }
  3175. #endif
  3176. theme_db->initialize_theme();
  3177. audio_server->load_default_bus_layout();
  3178. #if defined(MODULE_MONO_ENABLED) && defined(TOOLS_ENABLED)
  3179. // Hacky to have it here, but we don't have good facility yet to let modules
  3180. // register command line options to call at the right time. This needs to happen
  3181. // after init'ing the ScriptServer, but also after init'ing the ThemeDB,
  3182. // for the C# docs generation in the bindings.
  3183. List<String> cmdline_args = OS::get_singleton()->get_cmdline_args();
  3184. BindingsGenerator::handle_cmdline_args(cmdline_args);
  3185. #endif
  3186. if (use_debug_profiler && EngineDebugger::is_active()) {
  3187. // Start the "scripts" profiler, used in local debugging.
  3188. // We could add more, and make the CLI arg require a comma-separated list of profilers.
  3189. EngineDebugger::get_singleton()->profiler_enable("scripts", true);
  3190. }
  3191. if (!project_manager) {
  3192. // If not running the project manager, and now that the engine is
  3193. // able to load resources, load the global shader variables.
  3194. // If running on editor, don't load the textures because the editor
  3195. // may want to import them first. Editor will reload those later.
  3196. rendering_server->global_shader_parameters_load_settings(!editor);
  3197. }
  3198. OS::get_singleton()->benchmark_end_measure("Startup", "Finalize Setup");
  3199. _start_success = true;
  3200. ClassDB::set_current_api(ClassDB::API_NONE); //no more APIs are registered at this point
  3201. print_verbose("CORE API HASH: " + uitos(ClassDB::get_api_hash(ClassDB::API_CORE)));
  3202. print_verbose("EDITOR API HASH: " + uitos(ClassDB::get_api_hash(ClassDB::API_EDITOR)));
  3203. MAIN_PRINT("Main: Done");
  3204. OS::get_singleton()->benchmark_end_measure("Startup", "Main::Setup2");
  3205. return OK;
  3206. }
  3207. void Main::setup_boot_logo() {
  3208. MAIN_PRINT("Main: Load Boot Image");
  3209. #if !defined(TOOLS_ENABLED) && defined(WEB_ENABLED)
  3210. bool show_logo = false;
  3211. #else
  3212. bool show_logo = true;
  3213. #endif
  3214. if (show_logo) { //boot logo!
  3215. const bool boot_logo_image = GLOBAL_DEF_BASIC("application/boot_splash/show_image", true);
  3216. const bool boot_logo_scale = GLOBAL_DEF_BASIC("application/boot_splash/fullsize", true);
  3217. const bool boot_logo_filter = GLOBAL_DEF_BASIC("application/boot_splash/use_filter", true);
  3218. String boot_logo_path = GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "application/boot_splash/image", PROPERTY_HINT_FILE, "*.png"), String());
  3219. // If the UID cache is missing or invalid, it could be 'normal' for the UID to not exist in memory.
  3220. // It's too soon to scan the project files since the ResourceFormatImporter is not loaded yet,
  3221. // so to prevent printing errors, we will just skip the custom boot logo this time.
  3222. if (boot_logo_path.begins_with("uid://")) {
  3223. const ResourceUID::ID logo_id = ResourceUID::get_singleton()->text_to_id(boot_logo_path);
  3224. if (ResourceUID::get_singleton()->has_id(logo_id)) {
  3225. boot_logo_path = ResourceUID::get_singleton()->get_id_path(logo_id).strip_edges();
  3226. } else {
  3227. boot_logo_path = String();
  3228. }
  3229. }
  3230. Ref<Image> boot_logo;
  3231. if (boot_logo_image) {
  3232. if (!boot_logo_path.is_empty()) {
  3233. boot_logo.instantiate();
  3234. Error load_err = ImageLoader::load_image(boot_logo_path, boot_logo);
  3235. if (load_err) {
  3236. String msg = (boot_logo_path.ends_with(".png") ? "" : "The only supported format is PNG.");
  3237. ERR_PRINT("Non-existing or invalid boot splash at '" + boot_logo_path + +"'. " + msg + " Loading default splash.");
  3238. }
  3239. }
  3240. } else {
  3241. // Create a 1×1 transparent image. This will effectively hide the splash image.
  3242. boot_logo.instantiate();
  3243. boot_logo->initialize_data(1, 1, false, Image::FORMAT_RGBA8);
  3244. boot_logo->set_pixel(0, 0, Color(0, 0, 0, 0));
  3245. }
  3246. Color boot_bg_color = GLOBAL_GET("application/boot_splash/bg_color");
  3247. #if defined(TOOLS_ENABLED) && !defined(NO_EDITOR_SPLASH)
  3248. boot_bg_color = GLOBAL_DEF_BASIC("application/boot_splash/bg_color", (editor || project_manager) ? boot_splash_editor_bg_color : boot_splash_bg_color);
  3249. #endif
  3250. if (boot_logo.is_valid()) {
  3251. RenderingServer::get_singleton()->set_boot_image(boot_logo, boot_bg_color, boot_logo_scale, boot_logo_filter);
  3252. } else {
  3253. #ifndef NO_DEFAULT_BOOT_LOGO
  3254. MAIN_PRINT("Main: Create bootsplash");
  3255. #if defined(TOOLS_ENABLED) && !defined(NO_EDITOR_SPLASH)
  3256. Ref<Image> splash = (editor || project_manager) ? memnew(Image(boot_splash_editor_png)) : memnew(Image(boot_splash_png));
  3257. #else
  3258. Ref<Image> splash = memnew(Image(boot_splash_png));
  3259. #endif
  3260. MAIN_PRINT("Main: ClearColor");
  3261. RenderingServer::get_singleton()->set_default_clear_color(boot_bg_color);
  3262. MAIN_PRINT("Main: Image");
  3263. RenderingServer::get_singleton()->set_boot_image(splash, boot_bg_color, false);
  3264. #endif
  3265. }
  3266. #if defined(TOOLS_ENABLED) && defined(MACOS_ENABLED)
  3267. if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_ICON) && OS::get_singleton()->get_bundle_icon_path().is_empty()) {
  3268. Ref<Image> icon = memnew(Image(app_icon_png));
  3269. DisplayServer::get_singleton()->set_icon(icon);
  3270. }
  3271. #endif
  3272. }
  3273. RenderingServer::get_singleton()->set_default_clear_color(
  3274. GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
  3275. }
  3276. String Main::get_rendering_driver_name() {
  3277. return rendering_driver;
  3278. }
  3279. // everything the main loop needs to know about frame timings
  3280. static MainTimerSync main_timer_sync;
  3281. // Return value should be EXIT_SUCCESS if we start successfully
  3282. // and should move on to `OS::run`, and EXIT_FAILURE otherwise for
  3283. // an early exit with that error code.
  3284. int Main::start() {
  3285. OS::get_singleton()->benchmark_begin_measure("Startup", "Main::Start");
  3286. ERR_FAIL_COND_V(!_start_success, EXIT_FAILURE);
  3287. bool has_icon = false;
  3288. String positional_arg;
  3289. String game_path;
  3290. String script;
  3291. String main_loop_type;
  3292. bool check_only = false;
  3293. #ifdef TOOLS_ENABLED
  3294. String doc_tool_path;
  3295. bool doc_tool_implicit_cwd = false;
  3296. BitField<DocTools::GenerateFlags> gen_flags = {};
  3297. String _export_preset;
  3298. Vector<String> patches;
  3299. bool export_debug = false;
  3300. bool export_pack_only = false;
  3301. bool install_android_build_template = false;
  3302. bool export_patch = false;
  3303. #ifdef MODULE_GDSCRIPT_ENABLED
  3304. String gdscript_docs_path;
  3305. #endif
  3306. #ifndef DISABLE_DEPRECATED
  3307. bool converting_project = false;
  3308. bool validating_converting_project = false;
  3309. #endif // DISABLE_DEPRECATED
  3310. #endif // TOOLS_ENABLED
  3311. main_timer_sync.init(OS::get_singleton()->get_ticks_usec());
  3312. List<String> args = OS::get_singleton()->get_cmdline_args();
  3313. for (List<String>::Element *E = args.front(); E; E = E->next()) {
  3314. // First check parameters that do not have an argument to the right.
  3315. // Doctest Unit Testing Handler
  3316. // Designed to override and pass arguments to the unit test handler.
  3317. if (E->get() == "--check-only") {
  3318. check_only = true;
  3319. #ifdef TOOLS_ENABLED
  3320. } else if (E->get() == "--no-docbase") {
  3321. gen_flags.set_flag(DocTools::GENERATE_FLAG_SKIP_BASIC_TYPES);
  3322. } else if (E->get() == "--gdextension-docs") {
  3323. gen_flags.set_flag(DocTools::GENERATE_FLAG_SKIP_BASIC_TYPES);
  3324. gen_flags.set_flag(DocTools::GENERATE_FLAG_EXTENSION_CLASSES_ONLY);
  3325. #ifndef DISABLE_DEPRECATED
  3326. } else if (E->get() == "--convert-3to4") {
  3327. converting_project = true;
  3328. } else if (E->get() == "--validate-conversion-3to4") {
  3329. validating_converting_project = true;
  3330. #endif // DISABLE_DEPRECATED
  3331. } else if (E->get() == "-e" || E->get() == "--editor") {
  3332. editor = true;
  3333. } else if (E->get() == "-p" || E->get() == "--project-manager") {
  3334. project_manager = true;
  3335. } else if (E->get() == "--recovery-mode") {
  3336. recovery_mode = true;
  3337. } else if (E->get() == "--install-android-build-template") {
  3338. install_android_build_template = true;
  3339. #endif // TOOLS_ENABLED
  3340. } else if (E->get() == "--scene") {
  3341. E = E->next();
  3342. if (E) {
  3343. game_path = ResourceUID::ensure_path(E->get());
  3344. } else {
  3345. ERR_FAIL_V_MSG(EXIT_FAILURE, "Missing scene path, aborting.");
  3346. }
  3347. } else if (E->get().length() && E->get()[0] != '-' && positional_arg.is_empty() && game_path.is_empty()) {
  3348. positional_arg = E->get();
  3349. String scene_path = ResourceUID::ensure_path(E->get());
  3350. if (scene_path.ends_with(".scn") ||
  3351. scene_path.ends_with(".tscn") ||
  3352. scene_path.ends_with(".escn") ||
  3353. scene_path.ends_with(".res") ||
  3354. scene_path.ends_with(".tres")) {
  3355. // Only consider the positional argument to be a scene path if it ends with
  3356. // a file extension associated with Godot scenes. This makes it possible
  3357. // for projects to parse command-line arguments for custom CLI arguments
  3358. // or other file extensions without trouble. This can be used to implement
  3359. // "drag-and-drop onto executable" logic, which can prove helpful
  3360. // for non-game applications.
  3361. game_path = scene_path;
  3362. }
  3363. }
  3364. // Then parameters that have an argument to the right.
  3365. else if (E->next()) {
  3366. bool parsed_pair = true;
  3367. if (E->get() == "-s" || E->get() == "--script") {
  3368. script = E->next()->get();
  3369. } else if (E->get() == "--main-loop") {
  3370. main_loop_type = E->next()->get();
  3371. #ifdef TOOLS_ENABLED
  3372. } else if (E->get() == "--doctool") {
  3373. doc_tool_path = E->next()->get();
  3374. if (doc_tool_path.begins_with("-")) {
  3375. // Assuming other command line arg, so default to cwd.
  3376. doc_tool_path = ".";
  3377. doc_tool_implicit_cwd = true;
  3378. parsed_pair = false;
  3379. }
  3380. #ifdef MODULE_GDSCRIPT_ENABLED
  3381. } else if (E->get() == "--gdscript-docs") {
  3382. gdscript_docs_path = E->next()->get();
  3383. #endif
  3384. } else if (E->get() == "--export-release") {
  3385. ERR_FAIL_COND_V_MSG(!editor && !found_project, EXIT_FAILURE, "Please provide a valid project path when exporting, aborting.");
  3386. editor = true; //needs editor
  3387. _export_preset = E->next()->get();
  3388. } else if (E->get() == "--export-debug") {
  3389. ERR_FAIL_COND_V_MSG(!editor && !found_project, EXIT_FAILURE, "Please provide a valid project path when exporting, aborting.");
  3390. editor = true; //needs editor
  3391. _export_preset = E->next()->get();
  3392. export_debug = true;
  3393. } else if (E->get() == "--export-pack") {
  3394. ERR_FAIL_COND_V_MSG(!editor && !found_project, EXIT_FAILURE, "Please provide a valid project path when exporting, aborting.");
  3395. editor = true;
  3396. _export_preset = E->next()->get();
  3397. export_pack_only = true;
  3398. } else if (E->get() == "--export-patch") {
  3399. ERR_FAIL_COND_V_MSG(!editor && !found_project, EXIT_FAILURE, "Please provide a valid project path when exporting, aborting.");
  3400. editor = true;
  3401. _export_preset = E->next()->get();
  3402. export_pack_only = true;
  3403. export_patch = true;
  3404. } else if (E->get() == "--patches") {
  3405. patches = E->next()->get().split(",", false);
  3406. #endif
  3407. } else {
  3408. // The parameter does not match anything known, don't skip the next argument
  3409. parsed_pair = false;
  3410. }
  3411. if (parsed_pair) {
  3412. E = E->next();
  3413. }
  3414. } else if (E->get().begins_with("--export-")) {
  3415. ERR_FAIL_V_MSG(EXIT_FAILURE, "Missing export preset name, aborting.");
  3416. }
  3417. #ifdef TOOLS_ENABLED
  3418. // Handle case where no path is given to --doctool.
  3419. else if (E->get() == "--doctool") {
  3420. doc_tool_path = ".";
  3421. doc_tool_implicit_cwd = true;
  3422. }
  3423. #endif
  3424. }
  3425. uint64_t minimum_time_msec = GLOBAL_DEF(PropertyInfo(Variant::INT, "application/boot_splash/minimum_display_time", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:ms"), 0);
  3426. if (Engine::get_singleton()->is_editor_hint()) {
  3427. minimum_time_msec = 0;
  3428. }
  3429. #ifdef TOOLS_ENABLED
  3430. #ifdef MODULE_GDSCRIPT_ENABLED
  3431. if (!doc_tool_path.is_empty() && gdscript_docs_path.is_empty()) {
  3432. #else
  3433. if (!doc_tool_path.is_empty()) {
  3434. #endif
  3435. // Needed to instance editor-only classes for their default values
  3436. Engine::get_singleton()->set_editor_hint(true);
  3437. // Translate the class reference only when `-l LOCALE` parameter is given.
  3438. if (!locale.is_empty() && locale != "en") {
  3439. load_doc_translations(locale);
  3440. }
  3441. {
  3442. Ref<DirAccess> da = DirAccess::open(doc_tool_path);
  3443. ERR_FAIL_COND_V_MSG(da.is_null(), EXIT_FAILURE, "Argument supplied to --doctool must be a valid directory path.");
  3444. // Ensure that doctool is running in the root dir, but only if
  3445. // user did not manually specify a path as argument.
  3446. if (doc_tool_implicit_cwd) {
  3447. ERR_FAIL_COND_V_MSG(!da->dir_exists("doc"), EXIT_FAILURE, "--doctool must be run from the Godot repository's root folder, or specify a path that points there.");
  3448. }
  3449. }
  3450. #ifndef MODULE_MONO_ENABLED
  3451. // Hack to define .NET-specific project settings even on non-.NET builds,
  3452. // so that we don't lose their descriptions and default values in DocTools.
  3453. // Default values should be synced with mono_gd/gd_mono.cpp.
  3454. GLOBAL_DEF("dotnet/project/assembly_name", "");
  3455. GLOBAL_DEF("dotnet/project/solution_directory", "");
  3456. GLOBAL_DEF(PropertyInfo(Variant::INT, "dotnet/project/assembly_reload_attempts", PROPERTY_HINT_RANGE, "1,16,1,or_greater"), 3);
  3457. #endif
  3458. Error err;
  3459. DocTools doc;
  3460. doc.generate(gen_flags);
  3461. DocTools docsrc;
  3462. HashMap<String, String> doc_data_classes;
  3463. HashSet<String> checked_paths;
  3464. print_line("Loading docs...");
  3465. const bool gdextension_docs = gen_flags.has_flag(DocTools::GENERATE_FLAG_EXTENSION_CLASSES_ONLY);
  3466. if (!gdextension_docs) {
  3467. for (int i = 0; i < _doc_data_class_path_count; i++) {
  3468. // Custom modules are always located by absolute path.
  3469. String path = _doc_data_class_paths[i].path;
  3470. if (path.is_relative_path()) {
  3471. path = doc_tool_path.path_join(path);
  3472. }
  3473. String name = _doc_data_class_paths[i].name;
  3474. doc_data_classes[name] = path;
  3475. if (!checked_paths.has(path)) {
  3476. checked_paths.insert(path);
  3477. // Create the module documentation directory if it doesn't exist
  3478. Ref<DirAccess> da = DirAccess::create_for_path(path);
  3479. err = da->make_dir_recursive(path);
  3480. ERR_FAIL_COND_V_MSG(err != OK, EXIT_FAILURE, "Error: Can't create directory: " + path + ": " + itos(err));
  3481. print_line("Loading docs from: " + path);
  3482. err = docsrc.load_classes(path);
  3483. ERR_FAIL_COND_V_MSG(err != OK, EXIT_FAILURE, "Error loading docs from: " + path + ": " + itos(err));
  3484. }
  3485. }
  3486. }
  3487. // For GDExtension docs, use a path that is compatible with Godot modules.
  3488. String index_path = gdextension_docs ? doc_tool_path.path_join("doc_classes") : doc_tool_path.path_join("doc/classes");
  3489. // Create the main documentation directory if it doesn't exist
  3490. Ref<DirAccess> da = DirAccess::create_for_path(index_path);
  3491. err = da->make_dir_recursive(index_path);
  3492. ERR_FAIL_COND_V_MSG(err != OK, EXIT_FAILURE, "Error: Can't create index directory: " + index_path + ": " + itos(err));
  3493. print_line("Loading classes from: " + index_path);
  3494. err = docsrc.load_classes(index_path);
  3495. ERR_FAIL_COND_V_MSG(err != OK, EXIT_FAILURE, "Error loading classes from: " + index_path + ": " + itos(err));
  3496. checked_paths.insert(index_path);
  3497. print_line("Merging docs...");
  3498. doc.merge_from(docsrc);
  3499. for (const String &E : checked_paths) {
  3500. print_line("Erasing old docs at: " + E);
  3501. err = DocTools::erase_classes(E);
  3502. ERR_FAIL_COND_V_MSG(err != OK, EXIT_FAILURE, "Error erasing old docs at: " + E + ": " + itos(err));
  3503. }
  3504. print_line("Generating new docs...");
  3505. err = doc.save_classes(index_path, doc_data_classes, !gdextension_docs);
  3506. ERR_FAIL_COND_V_MSG(err != OK, EXIT_FAILURE, "Error saving new docs:" + itos(err));
  3507. print_line("Deleting docs cache...");
  3508. if (FileAccess::exists(EditorHelp::get_cache_full_path())) {
  3509. DirAccess::remove_file_or_error(EditorHelp::get_cache_full_path());
  3510. }
  3511. return EXIT_SUCCESS;
  3512. }
  3513. // GDExtension API and interface.
  3514. {
  3515. if (dump_gdextension_interface) {
  3516. GDExtensionInterfaceDump::generate_gdextension_interface_file("gdextension_interface.h");
  3517. }
  3518. if (dump_extension_api) {
  3519. Engine::get_singleton()->set_editor_hint(true); // "extension_api.json" should always contains editor singletons.
  3520. GDExtensionAPIDump::generate_extension_json_file("extension_api.json", include_docs_in_extension_api_dump);
  3521. }
  3522. if (dump_gdextension_interface || dump_extension_api) {
  3523. return EXIT_SUCCESS;
  3524. }
  3525. if (validate_extension_api) {
  3526. Engine::get_singleton()->set_editor_hint(true); // "extension_api.json" should always contains editor singletons.
  3527. bool valid = GDExtensionAPIDump::validate_extension_json_file(validate_extension_api_file) == OK;
  3528. return valid ? EXIT_SUCCESS : EXIT_FAILURE;
  3529. }
  3530. }
  3531. #ifndef DISABLE_DEPRECATED
  3532. if (converting_project) {
  3533. int ret = ProjectConverter3To4(converter_max_kb_file, converter_max_line_length).convert();
  3534. return ret ? EXIT_SUCCESS : EXIT_FAILURE;
  3535. }
  3536. if (validating_converting_project) {
  3537. bool ret = ProjectConverter3To4(converter_max_kb_file, converter_max_line_length).validate_conversion();
  3538. return ret ? EXIT_SUCCESS : EXIT_FAILURE;
  3539. }
  3540. #endif // DISABLE_DEPRECATED
  3541. #endif // TOOLS_ENABLED
  3542. if (script.is_empty() && game_path.is_empty()) {
  3543. game_path = ResourceUID::ensure_path(GLOBAL_GET("application/run/main_scene"));
  3544. }
  3545. #ifdef TOOLS_ENABLED
  3546. if (!editor && !project_manager && !cmdline_tool && script.is_empty() && game_path.is_empty()) {
  3547. // If we end up here, it means we didn't manage to detect what we want to run.
  3548. // Let's throw an error gently. The code leading to this is pretty brittle so
  3549. // this might end up triggered by valid usage, in which case we'll have to
  3550. // fine-tune further.
  3551. OS::get_singleton()->alert("Couldn't detect whether to run the editor, the project manager or a specific project. Aborting.");
  3552. ERR_FAIL_V_MSG(EXIT_FAILURE, "Couldn't detect whether to run the editor, the project manager or a specific project. Aborting.");
  3553. }
  3554. #endif
  3555. MainLoop *main_loop = nullptr;
  3556. if (editor) {
  3557. main_loop = memnew(SceneTree);
  3558. }
  3559. if (main_loop_type.is_empty()) {
  3560. main_loop_type = GLOBAL_GET("application/run/main_loop_type");
  3561. }
  3562. if (!script.is_empty()) {
  3563. Ref<Script> script_res = ResourceLoader::load(script);
  3564. ERR_FAIL_COND_V_MSG(script_res.is_null(), EXIT_FAILURE, "Can't load script: " + script);
  3565. if (check_only) {
  3566. return script_res->is_valid() ? EXIT_SUCCESS : EXIT_FAILURE;
  3567. }
  3568. if (script_res->can_instantiate()) {
  3569. StringName instance_type = script_res->get_instance_base_type();
  3570. Object *obj = ClassDB::instantiate(instance_type);
  3571. MainLoop *script_loop = Object::cast_to<MainLoop>(obj);
  3572. if (!script_loop) {
  3573. if (obj) {
  3574. memdelete(obj);
  3575. }
  3576. OS::get_singleton()->alert(vformat("Can't load the script \"%s\" as it doesn't inherit from SceneTree or MainLoop.", script));
  3577. ERR_FAIL_V_MSG(EXIT_FAILURE, vformat("Can't load the script \"%s\" as it doesn't inherit from SceneTree or MainLoop.", script));
  3578. }
  3579. script_loop->set_script(script_res);
  3580. main_loop = script_loop;
  3581. } else {
  3582. return EXIT_FAILURE;
  3583. }
  3584. } else { // Not based on script path.
  3585. if (!editor && !ClassDB::class_exists(main_loop_type) && ScriptServer::is_global_class(main_loop_type)) {
  3586. String script_path = ScriptServer::get_global_class_path(main_loop_type);
  3587. Ref<Script> script_res = ResourceLoader::load(script_path);
  3588. if (script_res.is_null()) {
  3589. OS::get_singleton()->alert("Error: Could not load MainLoop script type: " + main_loop_type);
  3590. ERR_FAIL_V_MSG(EXIT_FAILURE, vformat("Could not load global class %s.", main_loop_type));
  3591. }
  3592. StringName script_base = script_res->get_instance_base_type();
  3593. Object *obj = ClassDB::instantiate(script_base);
  3594. MainLoop *script_loop = Object::cast_to<MainLoop>(obj);
  3595. if (!script_loop) {
  3596. if (obj) {
  3597. memdelete(obj);
  3598. }
  3599. OS::get_singleton()->alert("Error: Invalid MainLoop script base type: " + script_base);
  3600. ERR_FAIL_V_MSG(EXIT_FAILURE, vformat("The global class %s does not inherit from SceneTree or MainLoop.", main_loop_type));
  3601. }
  3602. script_loop->set_script(script_res);
  3603. main_loop = script_loop;
  3604. }
  3605. }
  3606. if (!main_loop && main_loop_type.is_empty()) {
  3607. main_loop_type = "SceneTree";
  3608. }
  3609. if (!main_loop) {
  3610. if (!ClassDB::class_exists(main_loop_type)) {
  3611. OS::get_singleton()->alert("Error: MainLoop type doesn't exist: " + main_loop_type);
  3612. return EXIT_FAILURE;
  3613. } else {
  3614. Object *ml = ClassDB::instantiate(main_loop_type);
  3615. ERR_FAIL_NULL_V_MSG(ml, EXIT_FAILURE, "Can't instance MainLoop type.");
  3616. main_loop = Object::cast_to<MainLoop>(ml);
  3617. if (!main_loop) {
  3618. memdelete(ml);
  3619. ERR_FAIL_V_MSG(EXIT_FAILURE, "Invalid MainLoop type.");
  3620. }
  3621. }
  3622. }
  3623. OS::get_singleton()->set_main_loop(main_loop);
  3624. SceneTree *sml = Object::cast_to<SceneTree>(main_loop);
  3625. if (sml) {
  3626. #ifdef DEBUG_ENABLED
  3627. if (debug_collisions) {
  3628. sml->set_debug_collisions_hint(true);
  3629. }
  3630. if (debug_paths) {
  3631. sml->set_debug_paths_hint(true);
  3632. }
  3633. if (debug_navigation) {
  3634. sml->set_debug_navigation_hint(true);
  3635. #ifndef NAVIGATION_2D_DISABLED
  3636. NavigationServer2D::get_singleton()->set_debug_navigation_enabled(true);
  3637. #endif // NAVIGATION_2D_DISABLED
  3638. #ifndef NAVIGATION_3D_DISABLED
  3639. NavigationServer3D::get_singleton()->set_debug_navigation_enabled(true);
  3640. #endif // NAVIGATION_3D_DISABLED
  3641. }
  3642. if (debug_avoidance) {
  3643. #ifndef NAVIGATION_2D_DISABLED
  3644. NavigationServer2D::get_singleton()->set_debug_avoidance_enabled(true);
  3645. #endif // NAVIGATION_2D_DISABLED
  3646. #ifndef NAVIGATION_3D_DISABLED
  3647. NavigationServer3D::get_singleton()->set_debug_avoidance_enabled(true);
  3648. #endif // NAVIGATION_3D_DISABLED
  3649. }
  3650. if (debug_navigation || debug_avoidance) {
  3651. #ifndef NAVIGATION_2D_DISABLED
  3652. NavigationServer2D::get_singleton()->set_active(true);
  3653. NavigationServer2D::get_singleton()->set_debug_enabled(true);
  3654. #endif // NAVIGATION_2D_DISABLED
  3655. #ifndef NAVIGATION_3D_DISABLED
  3656. NavigationServer3D::get_singleton()->set_active(true);
  3657. NavigationServer3D::get_singleton()->set_debug_enabled(true);
  3658. #endif // NAVIGATION_3D_DISABLED
  3659. }
  3660. if (debug_canvas_item_redraw) {
  3661. RenderingServer::get_singleton()->canvas_item_set_debug_redraw(true);
  3662. }
  3663. if (debug_mute_audio) {
  3664. AudioServer::get_singleton()->set_debug_mute(true);
  3665. }
  3666. #endif
  3667. if (single_threaded_scene) {
  3668. sml->set_disable_node_threading(true);
  3669. }
  3670. bool embed_subwindows = GLOBAL_GET("display/window/subwindows/embed_subwindows");
  3671. if (single_window || (!project_manager && !editor && embed_subwindows) || !DisplayServer::get_singleton()->has_feature(DisplayServer::Feature::FEATURE_SUBWINDOWS)) {
  3672. sml->get_root()->set_embedding_subwindows(true);
  3673. }
  3674. ResourceLoader::add_custom_loaders();
  3675. ResourceSaver::add_custom_savers();
  3676. if (!project_manager && !editor) { // game
  3677. if (!game_path.is_empty() || !script.is_empty()) {
  3678. //autoload
  3679. OS::get_singleton()->benchmark_begin_measure("Startup", "Load Autoloads");
  3680. HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
  3681. //first pass, add the constants so they exist before any script is loaded
  3682. for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : autoloads) {
  3683. const ProjectSettings::AutoloadInfo &info = E.value;
  3684. if (info.is_singleton) {
  3685. for (int i = 0; i < ScriptServer::get_language_count(); i++) {
  3686. ScriptServer::get_language(i)->add_global_constant(info.name, Variant());
  3687. }
  3688. }
  3689. }
  3690. //second pass, load into global constants
  3691. List<Node *> to_add;
  3692. for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : autoloads) {
  3693. const ProjectSettings::AutoloadInfo &info = E.value;
  3694. Node *n = nullptr;
  3695. if (ResourceLoader::get_resource_type(info.path) == "PackedScene") {
  3696. // Cache the scene reference before loading it (for cyclic references)
  3697. Ref<PackedScene> scn;
  3698. scn.instantiate();
  3699. scn->set_path(info.path);
  3700. scn->reload_from_file();
  3701. ERR_CONTINUE_MSG(scn.is_null(), vformat("Failed to instantiate an autoload, can't load from path: %s.", info.path));
  3702. if (scn.is_valid()) {
  3703. n = scn->instantiate();
  3704. }
  3705. } else {
  3706. Ref<Resource> res = ResourceLoader::load(info.path);
  3707. ERR_CONTINUE_MSG(res.is_null(), vformat("Failed to instantiate an autoload, can't load from path: %s.", info.path));
  3708. Ref<Script> script_res = res;
  3709. if (script_res.is_valid()) {
  3710. StringName ibt = script_res->get_instance_base_type();
  3711. bool valid_type = ClassDB::is_parent_class(ibt, "Node");
  3712. ERR_CONTINUE_MSG(!valid_type, vformat("Failed to instantiate an autoload, script '%s' does not inherit from 'Node'.", info.path));
  3713. Object *obj = ClassDB::instantiate(ibt);
  3714. ERR_CONTINUE_MSG(!obj, vformat("Failed to instantiate an autoload, cannot instantiate '%s'.", ibt));
  3715. n = Object::cast_to<Node>(obj);
  3716. n->set_script(script_res);
  3717. }
  3718. }
  3719. ERR_CONTINUE_MSG(!n, vformat("Failed to instantiate an autoload, path is not pointing to a scene or a script: %s.", info.path));
  3720. n->set_name(info.name);
  3721. //defer so references are all valid on _ready()
  3722. to_add.push_back(n);
  3723. if (info.is_singleton) {
  3724. for (int i = 0; i < ScriptServer::get_language_count(); i++) {
  3725. ScriptServer::get_language(i)->add_global_constant(info.name, n);
  3726. }
  3727. }
  3728. }
  3729. for (Node *E : to_add) {
  3730. sml->get_root()->add_child(E);
  3731. }
  3732. OS::get_singleton()->benchmark_end_measure("Startup", "Load Autoloads");
  3733. }
  3734. }
  3735. #ifdef TOOLS_ENABLED
  3736. #ifdef MODULE_GDSCRIPT_ENABLED
  3737. if (!doc_tool_path.is_empty() && !gdscript_docs_path.is_empty()) {
  3738. DocTools docs;
  3739. Error err;
  3740. Vector<String> paths = get_files_with_extension(gdscript_docs_path, "gd");
  3741. ERR_FAIL_COND_V_MSG(paths.is_empty(), EXIT_FAILURE, "Couldn't find any GDScript files under the given directory: " + gdscript_docs_path);
  3742. for (const String &path : paths) {
  3743. Ref<GDScript> gdscript = ResourceLoader::load(path);
  3744. for (const DocData::ClassDoc &class_doc : gdscript->get_documentation()) {
  3745. docs.add_doc(class_doc);
  3746. }
  3747. }
  3748. if (doc_tool_implicit_cwd) {
  3749. doc_tool_path = "./docs";
  3750. }
  3751. Ref<DirAccess> da = DirAccess::create_for_path(doc_tool_path);
  3752. err = da->make_dir_recursive(doc_tool_path);
  3753. ERR_FAIL_COND_V_MSG(err != OK, EXIT_FAILURE, "Error: Can't create GDScript docs directory: " + doc_tool_path + ": " + itos(err));
  3754. HashMap<String, String> doc_data_classes;
  3755. err = docs.save_classes(doc_tool_path, doc_data_classes, false);
  3756. ERR_FAIL_COND_V_MSG(err != OK, EXIT_FAILURE, "Error saving GDScript docs:" + itos(err));
  3757. return EXIT_SUCCESS;
  3758. }
  3759. #endif // MODULE_GDSCRIPT_ENABLED
  3760. EditorNode *editor_node = nullptr;
  3761. if (editor) {
  3762. OS::get_singleton()->benchmark_begin_measure("Startup", "Editor");
  3763. sml->get_root()->set_translation_domain("godot.editor");
  3764. if (editor_pseudolocalization) {
  3765. translation_server->get_editor_domain()->set_pseudolocalization_enabled(true);
  3766. }
  3767. editor_node = memnew(EditorNode);
  3768. sml->get_root()->add_child(editor_node);
  3769. if (!_export_preset.is_empty()) {
  3770. editor_node->export_preset(_export_preset, positional_arg, export_debug, export_pack_only, install_android_build_template, export_patch, patches);
  3771. game_path = ""; // Do not load anything.
  3772. }
  3773. OS::get_singleton()->benchmark_end_measure("Startup", "Editor");
  3774. }
  3775. #endif
  3776. sml->set_auto_accept_quit(GLOBAL_GET("application/config/auto_accept_quit"));
  3777. sml->set_quit_on_go_back(GLOBAL_GET("application/config/quit_on_go_back"));
  3778. if (!editor && !project_manager) {
  3779. //standard helpers that can be changed from main config
  3780. String stretch_mode = GLOBAL_GET("display/window/stretch/mode");
  3781. String stretch_aspect = GLOBAL_GET("display/window/stretch/aspect");
  3782. Size2i stretch_size = Size2i(GLOBAL_GET("display/window/size/viewport_width"),
  3783. GLOBAL_GET("display/window/size/viewport_height"));
  3784. real_t stretch_scale = GLOBAL_GET("display/window/stretch/scale");
  3785. String stretch_scale_mode = GLOBAL_GET("display/window/stretch/scale_mode");
  3786. Window::ContentScaleMode cs_sm = Window::CONTENT_SCALE_MODE_DISABLED;
  3787. if (stretch_mode == "canvas_items") {
  3788. cs_sm = Window::CONTENT_SCALE_MODE_CANVAS_ITEMS;
  3789. } else if (stretch_mode == "viewport") {
  3790. cs_sm = Window::CONTENT_SCALE_MODE_VIEWPORT;
  3791. }
  3792. Window::ContentScaleAspect cs_aspect = Window::CONTENT_SCALE_ASPECT_IGNORE;
  3793. if (stretch_aspect == "keep") {
  3794. cs_aspect = Window::CONTENT_SCALE_ASPECT_KEEP;
  3795. } else if (stretch_aspect == "keep_width") {
  3796. cs_aspect = Window::CONTENT_SCALE_ASPECT_KEEP_WIDTH;
  3797. } else if (stretch_aspect == "keep_height") {
  3798. cs_aspect = Window::CONTENT_SCALE_ASPECT_KEEP_HEIGHT;
  3799. } else if (stretch_aspect == "expand") {
  3800. cs_aspect = Window::CONTENT_SCALE_ASPECT_EXPAND;
  3801. }
  3802. Window::ContentScaleStretch cs_stretch = Window::CONTENT_SCALE_STRETCH_FRACTIONAL;
  3803. if (stretch_scale_mode == "integer") {
  3804. cs_stretch = Window::CONTENT_SCALE_STRETCH_INTEGER;
  3805. }
  3806. sml->get_root()->set_content_scale_mode(cs_sm);
  3807. sml->get_root()->set_content_scale_aspect(cs_aspect);
  3808. sml->get_root()->set_content_scale_stretch(cs_stretch);
  3809. sml->get_root()->set_content_scale_size(stretch_size);
  3810. sml->get_root()->set_content_scale_factor(stretch_scale);
  3811. sml->set_auto_accept_quit(GLOBAL_GET("application/config/auto_accept_quit"));
  3812. sml->set_quit_on_go_back(GLOBAL_GET("application/config/quit_on_go_back"));
  3813. String appname = GLOBAL_GET("application/config/name");
  3814. appname = TranslationServer::get_singleton()->translate(appname);
  3815. #ifdef DEBUG_ENABLED
  3816. // Append a suffix to the window title to denote that the project is running
  3817. // from a debug build (including the editor). Since this results in lower performance,
  3818. // this should be clearly presented to the user.
  3819. DisplayServer::get_singleton()->window_set_title(vformat("%s (DEBUG)", appname));
  3820. #else
  3821. DisplayServer::get_singleton()->window_set_title(appname);
  3822. #endif
  3823. bool snap_controls = GLOBAL_GET("gui/common/snap_controls_to_pixels");
  3824. sml->get_root()->set_snap_controls_to_pixels(snap_controls);
  3825. bool font_oversampling = GLOBAL_GET("gui/fonts/dynamic_fonts/use_oversampling");
  3826. sml->get_root()->set_use_oversampling(font_oversampling);
  3827. int texture_filter = GLOBAL_GET("rendering/textures/canvas_textures/default_texture_filter");
  3828. int texture_repeat = GLOBAL_GET("rendering/textures/canvas_textures/default_texture_repeat");
  3829. sml->get_root()->set_default_canvas_item_texture_filter(
  3830. Viewport::DefaultCanvasItemTextureFilter(texture_filter));
  3831. sml->get_root()->set_default_canvas_item_texture_repeat(
  3832. Viewport::DefaultCanvasItemTextureRepeat(texture_repeat));
  3833. }
  3834. #ifdef TOOLS_ENABLED
  3835. if (editor) {
  3836. bool editor_embed_subwindows = EDITOR_GET("interface/editor/single_window_mode");
  3837. if (editor_embed_subwindows) {
  3838. sml->get_root()->set_embedding_subwindows(true);
  3839. }
  3840. restore_editor_window_layout = EDITOR_GET("interface/editor/editor_screen").operator int() == EditorSettings::InitialScreen::INITIAL_SCREEN_AUTO;
  3841. }
  3842. #endif
  3843. String local_game_path;
  3844. if (!game_path.is_empty() && !project_manager) {
  3845. local_game_path = game_path.replace_char('\\', '/');
  3846. if (!local_game_path.begins_with("res://")) {
  3847. bool absolute =
  3848. (local_game_path.size() > 1) && (local_game_path[0] == '/' || local_game_path[1] == ':');
  3849. if (!absolute) {
  3850. if (ProjectSettings::get_singleton()->is_using_datapack()) {
  3851. local_game_path = "res://" + local_game_path;
  3852. } else {
  3853. int sep = local_game_path.rfind_char('/');
  3854. if (sep == -1) {
  3855. Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
  3856. ERR_FAIL_COND_V(da.is_null(), EXIT_FAILURE);
  3857. local_game_path = da->get_current_dir().path_join(local_game_path);
  3858. } else {
  3859. Ref<DirAccess> da = DirAccess::open(local_game_path.substr(0, sep));
  3860. if (da.is_valid()) {
  3861. local_game_path = da->get_current_dir().path_join(
  3862. local_game_path.substr(sep + 1));
  3863. }
  3864. }
  3865. }
  3866. }
  3867. }
  3868. local_game_path = ProjectSettings::get_singleton()->localize_path(local_game_path);
  3869. #ifdef TOOLS_ENABLED
  3870. if (editor) {
  3871. if (!recovery_mode && (game_path != ResourceUID::ensure_path(String(GLOBAL_GET("application/run/main_scene"))) || !editor_node->has_scenes_in_session())) {
  3872. Error serr = editor_node->load_scene(local_game_path);
  3873. if (serr != OK) {
  3874. ERR_PRINT("Failed to load scene");
  3875. }
  3876. }
  3877. if (!debug_server_uri.is_empty()) {
  3878. EditorDebuggerNode::get_singleton()->start(debug_server_uri);
  3879. EditorDebuggerNode::get_singleton()->set_keep_open(true);
  3880. }
  3881. }
  3882. #endif
  3883. }
  3884. if (!project_manager && !editor) { // game
  3885. OS::get_singleton()->benchmark_begin_measure("Startup", "Load Game");
  3886. // Load SSL Certificates from Project Settings (or builtin).
  3887. Crypto::load_default_certificates(GLOBAL_GET("network/tls/certificate_bundle_override"));
  3888. if (!game_path.is_empty()) {
  3889. Node *scene = nullptr;
  3890. Ref<PackedScene> scenedata = ResourceLoader::load(local_game_path);
  3891. if (scenedata.is_valid()) {
  3892. scene = scenedata->instantiate();
  3893. }
  3894. ERR_FAIL_NULL_V_MSG(scene, EXIT_FAILURE, "Failed loading scene: " + local_game_path + ".");
  3895. sml->add_current_scene(scene);
  3896. #ifdef MACOS_ENABLED
  3897. String mac_icon_path = GLOBAL_GET("application/config/macos_native_icon");
  3898. if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_ICON) && !mac_icon_path.is_empty()) {
  3899. DisplayServer::get_singleton()->set_native_icon(mac_icon_path);
  3900. has_icon = true;
  3901. }
  3902. #endif
  3903. #ifdef WINDOWS_ENABLED
  3904. String win_icon_path = GLOBAL_GET("application/config/windows_native_icon");
  3905. if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_ICON) && !win_icon_path.is_empty()) {
  3906. DisplayServer::get_singleton()->set_native_icon(win_icon_path);
  3907. has_icon = true;
  3908. }
  3909. #endif
  3910. String icon_path = GLOBAL_GET("application/config/icon");
  3911. if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_ICON) && !icon_path.is_empty() && !has_icon) {
  3912. Ref<Image> icon;
  3913. icon.instantiate();
  3914. if (ImageLoader::load_image(icon_path, icon) == OK) {
  3915. DisplayServer::get_singleton()->set_icon(icon);
  3916. has_icon = true;
  3917. }
  3918. }
  3919. }
  3920. OS::get_singleton()->benchmark_end_measure("Startup", "Load Game");
  3921. }
  3922. #ifdef TOOLS_ENABLED
  3923. if (project_manager) {
  3924. OS::get_singleton()->benchmark_begin_measure("Startup", "Project Manager");
  3925. Engine::get_singleton()->set_editor_hint(true);
  3926. sml->get_root()->set_translation_domain("godot.editor");
  3927. if (editor_pseudolocalization) {
  3928. translation_server->get_editor_domain()->set_pseudolocalization_enabled(true);
  3929. }
  3930. ProjectManager *pmanager = memnew(ProjectManager);
  3931. ProgressDialog *progress_dialog = memnew(ProgressDialog);
  3932. pmanager->add_child(progress_dialog);
  3933. sml->get_root()->add_child(pmanager);
  3934. OS::get_singleton()->benchmark_end_measure("Startup", "Project Manager");
  3935. }
  3936. if (project_manager || editor) {
  3937. // Load SSL Certificates from Editor Settings (or builtin)
  3938. Crypto::load_default_certificates(
  3939. EditorSettings::get_singleton()->get_setting("network/tls/editor_tls_certificates").operator String());
  3940. }
  3941. if (recovery_mode) {
  3942. Engine::get_singleton()->set_recovery_mode_hint(true);
  3943. }
  3944. #endif
  3945. }
  3946. if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_ICON) && !has_icon && OS::get_singleton()->get_bundle_icon_path().is_empty()) {
  3947. Ref<Image> icon = memnew(Image(app_icon_png));
  3948. DisplayServer::get_singleton()->set_icon(icon);
  3949. }
  3950. if (movie_writer) {
  3951. movie_writer->begin(DisplayServer::get_singleton()->window_get_size(), fixed_fps, Engine::get_singleton()->get_write_movie_path());
  3952. }
  3953. GDExtensionManager::get_singleton()->startup();
  3954. if (minimum_time_msec) {
  3955. uint64_t minimum_time = 1000 * minimum_time_msec;
  3956. uint64_t elapsed_time = OS::get_singleton()->get_ticks_usec();
  3957. if (elapsed_time < minimum_time) {
  3958. OS::get_singleton()->delay_usec(minimum_time - elapsed_time);
  3959. }
  3960. }
  3961. OS::get_singleton()->benchmark_end_measure("Startup", "Main::Start");
  3962. OS::get_singleton()->benchmark_dump();
  3963. return EXIT_SUCCESS;
  3964. }
  3965. /* Main iteration
  3966. *
  3967. * This is the iteration of the engine's game loop, advancing the state of physics,
  3968. * rendering and audio.
  3969. * It's called directly by the platform's OS::run method, where the loop is created
  3970. * and monitored.
  3971. *
  3972. * The OS implementation can impact its draw step with the Main::force_redraw() method.
  3973. */
  3974. uint64_t Main::last_ticks = 0;
  3975. uint32_t Main::frames = 0;
  3976. uint32_t Main::hide_print_fps_attempts = 3;
  3977. uint32_t Main::frame = 0;
  3978. bool Main::force_redraw_requested = false;
  3979. int Main::iterating = 0;
  3980. bool Main::is_iterating() {
  3981. return iterating > 0;
  3982. }
  3983. // For performance metrics.
  3984. static uint64_t physics_process_max = 0;
  3985. static uint64_t process_max = 0;
  3986. static uint64_t navigation_process_max = 0;
  3987. // Return false means iterating further, returning true means `OS::run`
  3988. // will terminate the program. In case of failure, the OS exit code needs
  3989. // to be set explicitly here (defaults to EXIT_SUCCESS).
  3990. bool Main::iteration() {
  3991. iterating++;
  3992. const uint64_t ticks = OS::get_singleton()->get_ticks_usec();
  3993. Engine::get_singleton()->_frame_ticks = ticks;
  3994. main_timer_sync.set_cpu_ticks_usec(ticks);
  3995. main_timer_sync.set_fixed_fps(fixed_fps);
  3996. const uint64_t ticks_elapsed = ticks - last_ticks;
  3997. const int physics_ticks_per_second = Engine::get_singleton()->get_physics_ticks_per_second();
  3998. const double physics_step = 1.0 / physics_ticks_per_second;
  3999. const double time_scale = Engine::get_singleton()->get_time_scale();
  4000. MainFrameTime advance = main_timer_sync.advance(physics_step, physics_ticks_per_second);
  4001. double process_step = advance.process_step;
  4002. double scaled_step = process_step * time_scale;
  4003. Engine::get_singleton()->_process_step = process_step;
  4004. Engine::get_singleton()->_physics_interpolation_fraction = advance.interpolation_fraction;
  4005. uint64_t physics_process_ticks = 0;
  4006. uint64_t process_ticks = 0;
  4007. #if !defined(NAVIGATION_2D_DISABLED) || !defined(NAVIGATION_3D_DISABLED)
  4008. uint64_t navigation_process_ticks = 0;
  4009. #endif // !defined(NAVIGATION_2D_DISABLED) || !defined(NAVIGATION_3D_DISABLED)
  4010. frame += ticks_elapsed;
  4011. last_ticks = ticks;
  4012. const int max_physics_steps = Engine::get_singleton()->get_max_physics_steps_per_frame();
  4013. if (fixed_fps == -1 && advance.physics_steps > max_physics_steps) {
  4014. process_step -= (advance.physics_steps - max_physics_steps) * physics_step;
  4015. advance.physics_steps = max_physics_steps;
  4016. }
  4017. bool exit = false;
  4018. // process all our active interfaces
  4019. #ifndef XR_DISABLED
  4020. XRServer::get_singleton()->_process();
  4021. #endif // XR_DISABLED
  4022. for (int iters = 0; iters < advance.physics_steps; ++iters) {
  4023. if (Input::get_singleton()->is_agile_input_event_flushing()) {
  4024. Input::get_singleton()->flush_buffered_events();
  4025. }
  4026. Engine::get_singleton()->_in_physics = true;
  4027. Engine::get_singleton()->_physics_frames++;
  4028. uint64_t physics_begin = OS::get_singleton()->get_ticks_usec();
  4029. // Prepare the fixed timestep interpolated nodes BEFORE they are updated
  4030. // by the physics server, otherwise the current and previous transforms
  4031. // may be the same, and no interpolation takes place.
  4032. OS::get_singleton()->get_main_loop()->iteration_prepare();
  4033. #ifndef PHYSICS_3D_DISABLED
  4034. PhysicsServer3D::get_singleton()->sync();
  4035. PhysicsServer3D::get_singleton()->flush_queries();
  4036. #endif // PHYSICS_3D_DISABLED
  4037. #ifndef PHYSICS_2D_DISABLED
  4038. PhysicsServer2D::get_singleton()->sync();
  4039. PhysicsServer2D::get_singleton()->flush_queries();
  4040. #endif // PHYSICS_2D_DISABLED
  4041. if (OS::get_singleton()->get_main_loop()->physics_process(physics_step * time_scale)) {
  4042. #ifndef PHYSICS_3D_DISABLED
  4043. PhysicsServer3D::get_singleton()->end_sync();
  4044. #endif // PHYSICS_3D_DISABLED
  4045. #ifndef PHYSICS_2D_DISABLED
  4046. PhysicsServer2D::get_singleton()->end_sync();
  4047. #endif // PHYSICS_2D_DISABLED
  4048. Engine::get_singleton()->_in_physics = false;
  4049. exit = true;
  4050. break;
  4051. }
  4052. #if !defined(NAVIGATION_2D_DISABLED) || !defined(NAVIGATION_3D_DISABLED)
  4053. uint64_t navigation_begin = OS::get_singleton()->get_ticks_usec();
  4054. #ifndef NAVIGATION_2D_DISABLED
  4055. NavigationServer2D::get_singleton()->physics_process(physics_step * time_scale);
  4056. #endif // NAVIGATION_2D_DISABLED
  4057. #ifndef NAVIGATION_3D_DISABLED
  4058. NavigationServer3D::get_singleton()->physics_process(physics_step * time_scale);
  4059. #endif // NAVIGATION_3D_DISABLED
  4060. navigation_process_ticks = MAX(navigation_process_ticks, OS::get_singleton()->get_ticks_usec() - navigation_begin); // keep the largest one for reference
  4061. navigation_process_max = MAX(OS::get_singleton()->get_ticks_usec() - navigation_begin, navigation_process_max);
  4062. message_queue->flush();
  4063. #endif // !defined(NAVIGATION_2D_DISABLED) || !defined(NAVIGATION_3D_DISABLED)
  4064. #ifndef PHYSICS_3D_DISABLED
  4065. PhysicsServer3D::get_singleton()->end_sync();
  4066. PhysicsServer3D::get_singleton()->step(physics_step * time_scale);
  4067. #endif // PHYSICS_3D_DISABLED
  4068. #ifndef PHYSICS_2D_DISABLED
  4069. PhysicsServer2D::get_singleton()->end_sync();
  4070. PhysicsServer2D::get_singleton()->step(physics_step * time_scale);
  4071. #endif // PHYSICS_2D_DISABLED
  4072. message_queue->flush();
  4073. OS::get_singleton()->get_main_loop()->iteration_end();
  4074. physics_process_ticks = MAX(physics_process_ticks, OS::get_singleton()->get_ticks_usec() - physics_begin); // keep the largest one for reference
  4075. physics_process_max = MAX(OS::get_singleton()->get_ticks_usec() - physics_begin, physics_process_max);
  4076. Engine::get_singleton()->_in_physics = false;
  4077. }
  4078. if (Input::get_singleton()->is_agile_input_event_flushing()) {
  4079. Input::get_singleton()->flush_buffered_events();
  4080. }
  4081. uint64_t process_begin = OS::get_singleton()->get_ticks_usec();
  4082. if (OS::get_singleton()->get_main_loop()->process(process_step * time_scale)) {
  4083. exit = true;
  4084. }
  4085. message_queue->flush();
  4086. #ifndef NAVIGATION_2D_DISABLED
  4087. NavigationServer2D::get_singleton()->process(process_step * time_scale);
  4088. #endif // NAVIGATION_2D_DISABLED
  4089. #ifndef NAVIGATION_3D_DISABLED
  4090. NavigationServer3D::get_singleton()->process(process_step * time_scale);
  4091. #endif // NAVIGATION_3D_DISABLED
  4092. RenderingServer::get_singleton()->sync(); //sync if still drawing from previous frames.
  4093. const bool has_pending_resources_for_processing = RD::get_singleton() && RD::get_singleton()->has_pending_resources_for_processing();
  4094. bool wants_present = (DisplayServer::get_singleton()->can_any_window_draw() ||
  4095. DisplayServer::get_singleton()->has_additional_outputs()) &&
  4096. RenderingServer::get_singleton()->is_render_loop_enabled();
  4097. if (wants_present || has_pending_resources_for_processing) {
  4098. wants_present |= force_redraw_requested;
  4099. if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) {
  4100. if (RenderingServer::get_singleton()->has_changed()) {
  4101. RenderingServer::get_singleton()->draw(wants_present, scaled_step); // flush visual commands
  4102. Engine::get_singleton()->increment_frames_drawn();
  4103. }
  4104. } else {
  4105. RenderingServer::get_singleton()->draw(wants_present, scaled_step); // flush visual commands
  4106. Engine::get_singleton()->increment_frames_drawn();
  4107. force_redraw_requested = false;
  4108. }
  4109. }
  4110. process_ticks = OS::get_singleton()->get_ticks_usec() - process_begin;
  4111. process_max = MAX(process_ticks, process_max);
  4112. uint64_t frame_time = OS::get_singleton()->get_ticks_usec() - ticks;
  4113. GDExtensionManager::get_singleton()->frame();
  4114. for (int i = 0; i < ScriptServer::get_language_count(); i++) {
  4115. ScriptServer::get_language(i)->frame();
  4116. }
  4117. AudioServer::get_singleton()->update();
  4118. if (EngineDebugger::is_active()) {
  4119. EngineDebugger::get_singleton()->iteration(frame_time, process_ticks, physics_process_ticks, physics_step);
  4120. }
  4121. frames++;
  4122. Engine::get_singleton()->_process_frames++;
  4123. if (frame > 1000000) {
  4124. // Wait a few seconds before printing FPS, as FPS reporting just after the engine has started is inaccurate.
  4125. if (hide_print_fps_attempts == 0) {
  4126. if (editor || project_manager) {
  4127. if (print_fps) {
  4128. print_line(vformat("Editor FPS: %d (%s mspf)", frames, rtos(1000.0 / frames).pad_decimals(2)));
  4129. }
  4130. } else if (print_fps || GLOBAL_GET("debug/settings/stdout/print_fps")) {
  4131. print_line(vformat("Project FPS: %d (%s mspf)", frames, rtos(1000.0 / frames).pad_decimals(2)));
  4132. }
  4133. } else {
  4134. hide_print_fps_attempts--;
  4135. }
  4136. Engine::get_singleton()->_fps = frames;
  4137. performance->set_process_time(USEC_TO_SEC(process_max));
  4138. performance->set_physics_process_time(USEC_TO_SEC(physics_process_max));
  4139. performance->set_navigation_process_time(USEC_TO_SEC(navigation_process_max));
  4140. process_max = 0;
  4141. physics_process_max = 0;
  4142. navigation_process_max = 0;
  4143. frame %= 1000000;
  4144. frames = 0;
  4145. }
  4146. iterating--;
  4147. if (movie_writer) {
  4148. movie_writer->add_frame();
  4149. }
  4150. #ifdef TOOLS_ENABLED
  4151. bool quit_after_timeout = false;
  4152. #endif
  4153. if ((quit_after > 0) && (Engine::get_singleton()->_process_frames >= quit_after)) {
  4154. #ifdef TOOLS_ENABLED
  4155. quit_after_timeout = true;
  4156. #endif
  4157. exit = true;
  4158. }
  4159. #ifdef TOOLS_ENABLED
  4160. if (wait_for_import && EditorFileSystem::get_singleton() && EditorFileSystem::get_singleton()->doing_first_scan()) {
  4161. exit = false;
  4162. }
  4163. #endif
  4164. if (fixed_fps != -1) {
  4165. return exit;
  4166. }
  4167. SceneTree *scene_tree = SceneTree::get_singleton();
  4168. bool wake_for_events = scene_tree && scene_tree->is_accessibility_enabled();
  4169. OS::get_singleton()->add_frame_delay(DisplayServer::get_singleton()->window_can_draw(), wake_for_events);
  4170. #ifdef TOOLS_ENABLED
  4171. if (auto_build_solutions) {
  4172. auto_build_solutions = false;
  4173. // Only relevant when running the editor.
  4174. if (!editor) {
  4175. OS::get_singleton()->set_exit_code(EXIT_FAILURE);
  4176. ERR_FAIL_V_MSG(true,
  4177. "Command line option --build-solutions was passed, but no project is being edited. Aborting.");
  4178. }
  4179. if (!EditorNode::get_singleton()->call_build()) {
  4180. OS::get_singleton()->set_exit_code(EXIT_FAILURE);
  4181. ERR_FAIL_V_MSG(true,
  4182. "Command line option --build-solutions was passed, but the build callback failed. Aborting.");
  4183. }
  4184. }
  4185. #endif
  4186. #ifdef TOOLS_ENABLED
  4187. if (exit && quit_after_timeout && EditorNode::get_singleton()) {
  4188. EditorNode::get_singleton()->unload_editor_addons();
  4189. }
  4190. #endif
  4191. return exit;
  4192. }
  4193. void Main::force_redraw() {
  4194. force_redraw_requested = true;
  4195. }
  4196. /* Engine deinitialization
  4197. *
  4198. * Responsible for freeing all the memory allocated by previous setup steps,
  4199. * so that the engine closes cleanly without leaking memory or crashing.
  4200. * The order matters as some of those steps are linked with each other.
  4201. */
  4202. void Main::cleanup(bool p_force) {
  4203. OS::get_singleton()->benchmark_begin_measure("Shutdown", "Main::Cleanup");
  4204. if (!p_force) {
  4205. ERR_FAIL_COND(!_start_success);
  4206. }
  4207. #ifdef DEBUG_ENABLED
  4208. if (input) {
  4209. input->flush_frame_parsed_events();
  4210. }
  4211. #endif
  4212. GDExtensionManager::get_singleton()->shutdown();
  4213. for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
  4214. TextServerManager::get_singleton()->get_interface(i)->cleanup();
  4215. }
  4216. if (movie_writer) {
  4217. movie_writer->end();
  4218. }
  4219. ResourceLoader::clear_thread_load_tasks();
  4220. ResourceLoader::remove_custom_loaders();
  4221. ResourceSaver::remove_custom_savers();
  4222. PropertyListHelper::clear_base_helpers();
  4223. // Remove the lock file if the engine exits successfully. Some automated processes such as
  4224. // --export/--import can bypass and/or finish faster than the existing check to remove the lock file.
  4225. if (OS::get_singleton()->get_exit_code() == EXIT_SUCCESS) {
  4226. OS::get_singleton()->remove_lock_file();
  4227. }
  4228. // Flush before uninitializing the scene, but delete the MessageQueue as late as possible.
  4229. message_queue->flush();
  4230. OS::get_singleton()->delete_main_loop();
  4231. OS::get_singleton()->_cmdline.clear();
  4232. OS::get_singleton()->_user_args.clear();
  4233. OS::get_singleton()->_execpath = "";
  4234. OS::get_singleton()->_local_clipboard = "";
  4235. ResourceLoader::clear_translation_remaps();
  4236. WorkerThreadPool::get_singleton()->exit_languages_threads();
  4237. ScriptServer::finish_languages();
  4238. // Sync pending commands that may have been queued from a different thread during ScriptServer finalization
  4239. RenderingServer::get_singleton()->sync();
  4240. //clear global shader variables before scene and other graphics stuff are deinitialized.
  4241. rendering_server->global_shader_parameters_clear();
  4242. #ifndef XR_DISABLED
  4243. if (xr_server) {
  4244. // Now that we're unregistering properly in plugins we need to keep access to xr_server for a little longer
  4245. // We do however unset our primary interface
  4246. xr_server->set_primary_interface(Ref<XRInterface>());
  4247. }
  4248. #endif // XR_DISABLED
  4249. #ifdef TOOLS_ENABLED
  4250. GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_EDITOR);
  4251. uninitialize_modules(MODULE_INITIALIZATION_LEVEL_EDITOR);
  4252. unregister_editor_types();
  4253. #endif
  4254. ImageLoader::cleanup();
  4255. GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_SCENE);
  4256. uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SCENE);
  4257. unregister_platform_apis();
  4258. unregister_driver_types();
  4259. unregister_scene_types();
  4260. finalize_theme_db();
  4261. // Before deinitializing server extensions, finalize servers which may be loaded as extensions.
  4262. #ifndef NAVIGATION_2D_DISABLED
  4263. NavigationServer2DManager::finalize_server();
  4264. #endif // NAVIGATION_2D_DISABLED
  4265. #ifndef NAVIGATION_3D_DISABLED
  4266. NavigationServer3DManager::finalize_server();
  4267. #endif // NAVIGATION_3D_DISABLED
  4268. finalize_physics();
  4269. GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_SERVERS);
  4270. uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS);
  4271. unregister_server_types();
  4272. EngineDebugger::deinitialize();
  4273. #ifndef XR_DISABLED
  4274. if (xr_server) {
  4275. memdelete(xr_server);
  4276. }
  4277. #endif // XR_DISABLED
  4278. if (audio_server) {
  4279. audio_server->finish();
  4280. memdelete(audio_server);
  4281. }
  4282. if (camera_server) {
  4283. memdelete(camera_server);
  4284. }
  4285. OS::get_singleton()->finalize();
  4286. finalize_display();
  4287. if (input) {
  4288. memdelete(input);
  4289. }
  4290. if (packed_data) {
  4291. memdelete(packed_data);
  4292. }
  4293. if (performance) {
  4294. memdelete(performance);
  4295. }
  4296. if (input_map) {
  4297. memdelete(input_map);
  4298. }
  4299. if (translation_server) {
  4300. memdelete(translation_server);
  4301. }
  4302. if (tsman) {
  4303. memdelete(tsman);
  4304. }
  4305. #ifndef PHYSICS_3D_DISABLED
  4306. if (physics_server_3d_manager) {
  4307. memdelete(physics_server_3d_manager);
  4308. }
  4309. #endif // PHYSICS_3D_DISABLED
  4310. #ifndef PHYSICS_2D_DISABLED
  4311. if (physics_server_2d_manager) {
  4312. memdelete(physics_server_2d_manager);
  4313. }
  4314. #endif // PHYSICS_2D_DISABLED
  4315. if (globals) {
  4316. memdelete(globals);
  4317. }
  4318. if (OS::get_singleton()->is_restart_on_exit_set()) {
  4319. //attempt to restart with arguments
  4320. List<String> args = OS::get_singleton()->get_restart_on_exit_arguments();
  4321. OS::get_singleton()->create_instance(args);
  4322. OS::get_singleton()->set_restart_on_exit(false, List<String>()); //clear list (uses memory)
  4323. }
  4324. // Now should be safe to delete MessageQueue (famous last words).
  4325. message_queue->flush();
  4326. memdelete(message_queue);
  4327. #if defined(STEAMAPI_ENABLED)
  4328. if (steam_tracker) {
  4329. memdelete(steam_tracker);
  4330. }
  4331. #endif
  4332. unregister_core_driver_types();
  4333. unregister_core_extensions();
  4334. uninitialize_modules(MODULE_INITIALIZATION_LEVEL_CORE);
  4335. if (engine) {
  4336. memdelete(engine);
  4337. }
  4338. unregister_core_types();
  4339. OS::get_singleton()->benchmark_end_measure("Shutdown", "Main::Cleanup");
  4340. OS::get_singleton()->benchmark_dump();
  4341. OS::get_singleton()->finalize_core();
  4342. }