From d4c541c25a6533ebb966ddaa581523fe9326433a Mon Sep 17 00:00:00 2001 From: Sergey Minakov Date: Tue, 7 Jul 2020 00:01:35 +0300 Subject: [PATCH 1/2] iOS Export: add option to use storyboard for launch screen --- .../godot_ios.xcodeproj/project.pbxproj | 8 +- .../SplashImage.imageset/Contents.json | 22 ++++ .../SplashImage.imageset/splash@2x.png | Bin 0 -> 21443 bytes .../SplashImage.imageset/splash@3x.png | Bin 0 -> 21443 bytes .../godot_ios/Launch Screen.storyboard | 41 ++++++ .../ios_xcode/godot_ios/godot_ios-Info.plist | 1 + platform/iphone/export/export.cpp | 123 +++++++++++++++++- 7 files changed, 190 insertions(+), 5 deletions(-) create mode 100644 misc/dist/ios_xcode/godot_ios/Images.xcassets/SplashImage.imageset/Contents.json create mode 100644 misc/dist/ios_xcode/godot_ios/Images.xcassets/SplashImage.imageset/splash@2x.png create mode 100644 misc/dist/ios_xcode/godot_ios/Images.xcassets/SplashImage.imageset/splash@3x.png create mode 100644 misc/dist/ios_xcode/godot_ios/Launch Screen.storyboard diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj index 8c92ae2a7ceb..54dda2563d47 100644 --- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj +++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ D07CD44E1C5D589C00B7FB28 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D07CD44D1C5D589C00B7FB28 /* Images.xcassets */; }; D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */; }; D0BCFE7818AEBFEB004A7AAE /* $binary.pck in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7718AEBFEB004A7AAE /* $binary.pck */; }; + $pbx_launch_screen_build_reference /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -41,6 +42,7 @@ D0BCFE4318AEBDA2004A7AAE /* $binary-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "$binary-Info.plist"; sourceTree = ""; }; D0BCFE4518AEBDA2004A7AAE /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; D0BCFE7718AEBFEB004A7AAE /* $binary.pck */ = {isa = PBXFileReference; lastKnownFileType = file; path = "$binary.pck"; sourceTree = ""; }; + $pbx_launch_screen_file_reference /* End PBXFileReference section */ $additional_pbx_files @@ -92,6 +94,7 @@ D0BCFE4118AEBDA2004A7AAE /* $binary */ = { isa = PBXGroup; children = ( + $pbx_launch_screen_copy_files 1FF4C1881F584E6300A41E41 /* $binary.entitlements */, D07CD44D1C5D589C00B7FB28 /* Images.xcassets */, D0BCFE4218AEBDA2004A7AAE /* Supporting Files */, @@ -247,6 +250,7 @@ files = ( D07CD44E1C5D589C00B7FB28 /* Images.xcassets in Resources */, D0BCFE7818AEBFEB004A7AAE /* $binary.pck in Resources */, + $pbx_launch_screen_build_phase D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */, $additional_pbx_resources_build ); @@ -367,7 +371,7 @@ buildSettings = { ARCHS = "$godot_archs"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + $pbx_launch_image_usage_setting CODE_SIGN_ENTITLEMENTS = "$binary/$binary.entitlements"; CODE_SIGN_IDENTITY = "$code_sign_identity_debug"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_debug"; @@ -397,7 +401,7 @@ buildSettings = { ARCHS = "$godot_archs"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + $pbx_launch_image_usage_setting CODE_SIGN_ENTITLEMENTS = "$binary/$binary.entitlements"; CODE_SIGN_IDENTITY = "$code_sign_identity_release"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_release"; diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/SplashImage.imageset/Contents.json b/misc/dist/ios_xcode/godot_ios/Images.xcassets/SplashImage.imageset/Contents.json new file mode 100644 index 000000000000..1e63e78edac9 --- /dev/null +++ b/misc/dist/ios_xcode/godot_ios/Images.xcassets/SplashImage.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "splash@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "splash@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/SplashImage.imageset/splash@2x.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/SplashImage.imageset/splash@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..766b0b66efb1ac8cb53d9cd6b7fa2ef70c6ec559 GIT binary patch literal 21443 zcmeEu`8$;F-}i;2QdG3an(SpM`z|WRz6&8?>|`C=7^PAa8tV|k*pp=}F`+(^Fv!@K zp~y0fk#%fio@+ke`@Ww);Q8r!j%SX;;V{Q_o!5E3&-e0rz0UXLm8r4rnNwFz0RV6Y zqIbs}0GI>-fbsr`y$me z8IoTu_G*jSd2KQMGtZXmp9qRMYMGkWM7HdBkFKwqiBs>)pEGV!sjo&(d z_Qc7v$YjUR6d(Uh^)}7W^9?w%@gA>~5O;kQ2wn<8F^Kqri`WRzps%0# z54ngOorR@gv9w`=YSbqzp+$pz@uSIizVdd0zrjLqIX2^kh9Y=rOu#HTg+OJ5wS6aK zn{xtXha&9Zha$Z}io!uHUkIXceN5n0S`W#N^JM?W6wT&HSk|Q@ot%p@d4m{SzUm&& z^e?hi{suk#lCQxOVVWI;sz8bZ(ebyxH*sUq+GpLpv4O2+B^uTrp7`)q70dDC(V^ZI zGYyXtzze$3m&fPHHX?b~f-W&Ud^&eY889>@JBkqNkw-@Obr;??EXIcYqbJ^_e+@s! z9qQRbmV)4&G0R)M35i_$EWZV1u~MCfQpl}@mPTRt?u72vQ1L|w{&iQHN?;#nOPFIz zqGt8&5Gyz0Gin_Ax{!k}l+g5t1rR%Z>MW4?aH_=^uPOxB!cPq(5@ ze+4FfF0y-0gPPSIvRuG)T%q!9@co8Mdt}F}L~#fU*%P}$T;0d_niQ)|8>+b4Ri^U| zl@_rmdi~y-s4=c_#5W2#xIrby|D5=*M`=w_Ly*xoJiiT>XH7;1FP8f@hjdu0W9#KB zKgo*P5W5@ss%nuQ4>xsjq-@)TJ!iHr$9|JL4Vvxo)iwGxSaLKp?r80mWJH)R=8*|u@Mad} z^PjUhk+^qHjCzr5H!(R}3%1fkTgaKn3BL%}*j8GjyKJBMt-%`BD_il`pi6(ATU@a1 z*0gUy8Y^H}WHlIohg1Lclu=0YTOgUgSpx z4{p4fP*+;ugsk-nd~5U2S|7lVS7c}SpH3yP-t>2B^7ROE`k4X%8!s4-0V0XFWxFj- z>vY?~{I%QQuI)b;*v}A7|0ERVM+Sb1tlzg;m{|E9r&x+nJg3&r+210$3ju)e+YF2V zN9TJ+v;;fzOChS?-o5$|_GQyd5#mYM%o4emJbhjKs(2`6+I8|cBuO+WO($;>@fc-ew7v)%uL(Nxyi=@a5P| z(lsGKYv9Th6S9->4l;WC*XG1DzR0(dFfoEJTCF53lMPBSqWO2GoT5_i6qj$Dw@OW4 zikUcNR8cWhH*t#4>NO@|b=zuy30&jFf7gg*nJ%ro+;BC*RMif0S{do?_4K`j#AJ0lBU(dCRM-I1sLM~8LHjN|QM}^a&6=kB)u^)U@`T(**iAso zEFWCiE0>>m%Qx-P|4_KaKHQBj8hrad`^hBU^+`-j^kQDb& z-mriL{89q^@&^+vX$l_rt6JA!0=wgT*Y=f&6$#<}YREE`jlk3)+@kbHc?w>O-Bdge zY{WQy1kNU7N1F~VAVVP&^JH%V^%~g`<$~ikXf{Hg`RtG2c`+<=sGN;%Yd%PtYEhW{ zM0O;S`9mo65x=*w{}5Jc`!51AoZt+P&64Gjera2dkVvU#iw67t5EJZy{Vl2`fnbud zm5J_=L+_3e#<4KXL@Gouu^x+od0-$B+2~HBCZIg8z)oeWwO(~%n|9I=e1vPs{~F;!av!AYFxd`4X30p6c~{5_&&!8tyO!P?Jnpv`f! z`Xl03c!$OZsrwSdb1+0l?r~V&EO{m+IM1AuAO7k-;;>VsWlxtCSn0PdxIk+qlLhNGQ!nYSE4PC3X#j^Qf8L4jFWDx@xA=`k(eC4QhubXI=8;e~^)G~wmH5j2naB|@ zdxH!iPyLW4skSAL-goBmTYnof$A`b>0RTxtH@_0PtPA@% zvh3^IPR>?t(x3Uf>oIJ@J^@1;;JKioh`y6dU!q@vp;7ybj1g8ZWymXrZHsKxIBArZ zG&Usej}SsC%6m7F~pfo%X@*w1zbAljXTO zv*e5P*CNLSd1c!ikwZfxmHmX>uG0527j}+^%1donKHf zy)id1S?Ym`zsDwfFNx6PehN5Xr>Bh=Y+luoa3H1GKP2U7uDDY^>Rd4xwHZ>V{0v?V z2d6f-qO6JLAQR3=`4P*dnLfJ@AW9mpH1X?-(91?`?Tzx46|u;JkSVX1^nz#bSPbZ9i7qW!V*MuUvi7XvarJ%*^ODB6%gSBC$87;E+ol4 z_P0>gT$&IMpPb-brPtOoz8bgjqNkGC07E5uRXGlG5+tTDP4Yb$M9)ah+<*Vt)I(9d z_BKTW>*BFlLZDV_|6u|+PJ(lO{SV<9L^HJxCfdBP!w09Pr;++=_=6xBv>Az2pEa(r z2Um%rU6j+n!()fYV=)6Q7I<+c?pE5U`w+gX@6Q1?z0VQ8R@HynSHlcH$x5HXW%?8t zVR=%-ivLUjn>+0YPQiy95fNFQf1j2XwFUs@bRh8-Zi@e-uGk#Gu}`jS*I54^O~y8= z7w(X6U(Yu(qeZd+$&B<#`ur@n(ZohpHZ%lZkhsKIR@~r6J)ExB$<8>Vc^(j;LmrO_ zmT9FhJEQy!t+%SK5vxCocPu*@0MMBp$|;`typ9(h48dQuU`=Cy*Mt&|-3D3v^G3QLd$&YDBdv@eO_UQOp-pYf@8oLEc{$p%N(C!eaj9Q$|->O3xEVtAV|LSI@ow& zU+%MMSa18pCrshvSI$$ocMpoz90NayoN+wqTZEp&y>8J21kP;509skdOPT)3b+Ak$ ztMFGEN6YP&cK=ij!W}$a_s1&Oxb32XA$r&~o&tNhS2Q&XZf(t-RRxx2rV$ z$UhfmGRG;W=yP`k-7Pt%N2rnz)Gj2Mt4taUAYB7%7PpFLU<(??DZ~Y2{?hN%I0ne1 zqE-Vbw6v}9btNa);&ykFkyjuc==#v*^+DW*iVg(97ahrrq)VxPDz>Fm`r#YW;oiby zo*`)}>%Z>tA|A#Tk6M-I7i*^#y#+xRn1%{3WQVRy53ANaa!GhZS=V1FfsUv-iZaE( z>CxpXy=H?IA*SACS*jgm!{fTF+R4(_U&)mfSZ-bsCGIkDZ%-raO6mDNu2Hk1UR7l0 z^OEwJ;fT#HmSylR^n=;}JBOm;VXNh8+mHxqKu~>4z5VEPqcI{PYBP*eaL$?td}*aa z;P|1sW_|dAe4O{d>xtKVu&u)ghk&ktX7W);^FnSt2U&ky$RTj!N%P-l;S#U#PLf9; z+H0ZBCv0_Jb6-kmi!`6K$8Kf_0RrAQ28I|xa7R?&D{neoA4HMN&ZDNo@Qm=Cch@X! zttbv@JP~LNq+JEc1rj5{AiorCb#H(?qxtg41};+=gL5; zg7{3<8@7CXxYATus6!#Z+R~++J{I#D#j9KE=)@+fZJdy_Z!k;|HQ@_Bgv1#R7xl0W z4a2IsVEf8VTd7QRTKJ-VZKB?QG8I&n8#a4VUQzLSt==08?hxF~P7flU!_vVa=awVg zbz$Ul`(LE_tnF=_S_fGG^eehie+Yvkeh_aL%{DL>eEYL1dfS^iyVz!GZ$DXmKnw24 zvotfy-|UObk%Dg)m6w)|Mb11oSR^J|O~!{l+W-8*%i;0i=i9yx4i5X{!7CDCZLw0nS%kDc85l z3!%lIt6Ewd@(#b11kbZq8QMmX1_*>o@2VE#HQFeVRp{S3orx>)1-B^dzDf8F#+_?h9Xn@xfDBi-FgqN98JF^Q3zYkngm zmG+crjo)8Lr;@v@+*H=anyyVFrUQbkY^>6)NOSByV+U)X11?e8XgbybLc}cZXpPcQ z_atISTGnJTe2pCt-~p4c7~{2Gv#?)BEJG6$Ss_!ctr~=Y1Kvpg5{W?k&8h%==|N!X zy<%nyjQvLFFZ98rf13^*K3;Wy7>_St;R_R(hvS$SVrI2KRq(c-Dg)wTruZY(w``4q7FE7`h;!b*@y*fVvWPu(PV% z$#=O>uJ*&J=TYKs1k>1-Y)`I7!Cs$r5nMgN4jk0Z?p;3y9MmlA(~9fz>Y56ua4ysCbDYXXG;qcamqUhj#~vSv}i92gT8g` zNUu#+W!~^1Gv!Y1-6+bE(YJ_D`<;|M2H-bX{In`OxG2G6xN6HRLHU9%lTR(VB5eK7H4`$R_7WLaPC?`%#+;5+}n zt~F`n$2+3ni5GGR`^{|IskVu;@!BDcBhiGM7Q3Uvz7H<*J=a#UK>lWflymR%X_-x{ z`k^wyEft~D{d9FFZL&7;Byi$i1ALpwohSy0Q(V1M@cLcxxC?LG`rau=jACc%DLegZ z4)&HDKPgMZgzbcbk<}JzF6Fa*&;qVcsqc3je{Su4du$<{>&Bn>cV1%-nyo?G)ge{- z1_s+}d9-)wH*AriADV&|mn&%77lubh^pOg3u%#s07>~?k_0iuk5#OottB~@_%3+(< z{R_P)S<%%_Y2~O_t$#acmbT-+2xAU-E7%8XQd5=4ao|Mkzu7I;J8Qe=VDyZ4-YvKI z*6=;W;DL@yWd(xU#m|wJ=H>;Mehqt@s5NYsymz`#8K@UXPamT9&v%R-)aW`1jw~V$ zo=v0}Z1m--|9e@)_IQ;wr0d54%+k_wX;#tkLyt7AxY!VNi*&R?wl9erRalht2ecOS zS#tp3VRgltW1+1@dGJL3;PLv5jEoiDwJ@wBZGSU()B)zXcP+_FcaTkZ|9qB8NI5;( z=R{0+W+?}KpYGh+>e$~{vqAGrSow@7!j>u!VfuOMi;vSX?$J%4tFhti5VhXXyqT!F z^^L>C3(SrZ;*tYH-^)}MG7Cex%SuY~^RK#nR<-sW>?hmG_VqIYG8gHwdW(#=iEh*G z2M2v4Dw%wysVzVM_F``2$38HJn9Y&Mq~S{l3Yu?5CMu-zb&&pICeZ$l4z!aTXr=Tb z;+1JB1p#OILMp2Ld9zHc5*>MKexlmm+&Bfqv(vZtYDRFcy7x9|#JYuA7b{gS@U(cR5Lg!nP8_aeZ=$kk0O2$^B7pzL7~|RXu52H6y5wLG{~8fAUXo zKS!AQ<=?<%fcF9*WP1OS(AW$Cwb+p!w!D0VicfQ5rn;@L*)r<}=+Djm+iY}=t8#ke zqFj>vM?@RN&JC_I03EOCKJ-8^l)AUxyT3V?ZDns;+#%~dEK{a!;eCB*e6R$h6u#5L zMeYp^3%>QDHni$$Y1*cl*9R`OldWZy_D)CC__`OKZeH6B3h>ST>laX-zqjl_PF?l_ zGG8tsJ)Ah=C*KJ3o?o!84}DIAgGwPiYz+m#gcR}E$k{r?Zgl7)jJkEZW#b3R?pB2{ zvhI;Z!qMR_v|iYzsyk!Mp`xMAV>mtib1q0F=oKxdu0Di9d=WRY@4)PQ*h{9IQ20P0y!ZoG3Ww7AIkK8IJ`%WsXg zOg7?Fk#x;3_;BY;N;kOn2iwE*Dy|W}`4)^ZaC&(;7C8IWA_V+lss9&Xu2~1!C)r{5 zhu$5+f+CYZqDhIK86PNATfO>{q1)h^ym7gyju9eYz|U-1GbSknH{M*aUx2U|^z+9uXq4tJ!IN}dZCj_JzpTA8P z3f+=K$=mWr&*$&|2$e578M)69^o_EnO82z_z-U$7%UJ5z_Z)k=ru z1dFO;rcJ@QeP_W9eMYauPhJnhevS;6GNZ^v zOX)iJo^>BMdpZbIUCv@;E|p1wwFvZcUrC2{a>W_7e&>$*WbrciWDd11(g-Fx!qR6ZyI z-<~xAcYNx_*TqZ_nboV_TVw9N;~W3m#+T5J2yMFDFL(yn2?4z$x#jlcySUshIbJhK z6Xn<INR6N5q-YrL}$^_Vctq&sml*i#!^ozQ(`0w#uSKDs!A!lkvZ+B<-h|w9@G^ z@HltfJBz!XV@_qh*S2Dw$z8vDv-;{U39B;e&-x*K577IlXVY~x1wLc{0Kc0b0}nNI zKpT&HbBA5qlCY92i_l`sb6Glj12$Uhkn?rce_~ji^7XnwZ|<$AF&im!s-gKAr=C@w z_V{-r??r(aD!q!j`cuDfgW_N8asDK}yNsFaSis{EV;{Oy0&Gg?fjTi>G4fHPK6qQ==08Ul3Q?A3<>JHh zu@eg9(_kg+e36qAEA?xoqDLO&b*r|9oYJohL(<&JD{ol&TG1%&P$Rz32TOd(;b+<% zC+lyU0KmaHFunYkme}rR&J=>Yk-y;eq0H36KJx zPVeeMx6A8;mR64t{h7BucS2ph{I-eonHbM^Sr}#a%AQezfU+l>gpk+up8dA+okJ`w zk`Uuk-ZOZBxlqgE3i8Nh(K8Z56GG}7q+>vJ9$kS~^e&SGfdBLY+(6m>L*P#f-pFkz zTpV5*xnTeFTmK)6!{v>mgiWF{8_1+p;jVK*Oq@QfP4B#Z)E{MRC_&Gz(P0c5 z2LfLi9%^>b#pWj{^;t4IM8$YHPYB*OfY~lowPtyR=q&e*@bJZe6%O5eJ4o1ZcY5aN zpKqk{-;vg6H+WE-!lEFefFNK%T_%x2zF{KG&0gUWm0#e z{8I0g=99lIpgSJb9Ke@oF;YVdC^!dF41^t87DMeprK@SfF=U4mnx*9lNv$;M*3xBb*Ao*PLuJ(aGtG zIdxk8b`1|bHeKkan>*|MCx9IzFd3cA#P*vb&fP*hJm9C*Ky0RVUY`%hG}<_O&$SrV z2A-b=ZISX}zR7hs+{h&XNnp&~4CD=bpAODLU=Xj%V@H1{pzuA)^{0O6aU`p>v?UIA z=>hz2Y>pyCr2}Vuk$y`F{g&KM2e%-IR5=gz=@6sU{R#d&JgCS&hnz;DpAUL(`@2hy zfSSI}+JrFihAg%U@MQR+kwh=gKM3p@Taggf;|-#ZM$fQUj)D-=zB;FsVpH^%_<3$& z8SlnwX?M#qBN9j4;81coA_u3?~=Oq zGcu%xZnF%bn-3fzRq`0$xpx-(m-UGwR*azI}TJ} znz#Nig>)A%-P>=cxIoris@Q=anqUIDtV=%fg4pP1$#1oeIUvFV6ToxA2wxBKW!j&e z+dV;7%b5#kmDy#+)8Ecr)NaRIa#?N{b7%|X-VQ7G?b!LbR4)$Fa4)*g#NTGH;BPK zRlni%i-ej$EIBG7JG3q|$t3WuADHOq5~s0daMs1%Qr?xnqQdZQT(lxv83SOq7khKDd$_+ZN2lMM4{1Re&J%}#1#D)#>>8^wI*{A zl;wC;3a#V%N(X0AA$DpQh2d%5vS0)7gs-QUG<^s?3H&$)mMcziSYG*&<6A{N6)ST) zn`vYnrcl?!-*dQ`cXgr~qtmY#;?ds6Rv&V~-2~$6hJudTcsjb&gZ13|Xb3{bQebLC zJ$ofgxJt}GM*BjI!XX!dWDan%GJz?0I(jq3NmO5=OQa73Iv`ohFK*yl^;jL*p<`?c z!k)ZS#d4wyM+g_anJSVNlS_qG*fCv%eMr~7ocE20F;t2lbK(ka@O z_}0?mC;A`Hl&zO&79n*pqNA+6(^x71G|?RkZWwsC5`3G6dli4tdJ$O zP4Q97Iczn@yC8EP%}W4djdUeFntt}NDcqYTXM#6`1R6P+!vPlWyKlfb$-Kte7?j%}ZknTfKAJ=)2^kq5MKr&2Qrmp%R%T?5l`zc-|!w zMAo>ASAz^+IeZstu$){sf}3E?xQhQxe!D-DJvc;DNiU<-lim)Acw*6Spy^`wk$}us z(9D+=$$rSh)L?y{PEpi&f-o=oC}Ar&Sl>?4vmQ&k7GDr2MDT~&Z>9u9Aeo0Wh4Thq zAusBeo6O};3RMPDA`8X9Rw}3755jp(Y=6is1}dV7b42B5#McF-2Ih_XtQ~KV3I=vA z&>RLlj}1BcHQFMjYW^m2!9aq4&bbAdn^8A~Bd2Y_AnaMFq@(H&8>-*{ZuxV^e_psd zV1gsOk#Z8CT1>E=q1yN}OxV z8fQL5IeM^0Zc8j!Lf}a2XBh}oS6G{cIj5i_-;Jb#rA%#6hX2fj8>ZP#(3B#kUCEnK zlp;z)cW%l?-jEi3oOh*jodriyM_$8@zP)Zv_#bS=)90!Sbj@2ZQ`PsO}2nJKs7IJGhPNVP;?9Y+wC$#-0n=~JI zGj+D=%{fKs;jcn>!eLI_o$F`F(RUaEld=5}q4T572Q$Jg_x7mv9>~66it4OV>oj2z z%KL+~6%#(+bLYo7ttX)EPjnMz7Re_1D%cp$R3YhU(YO-}WY#IFAFNH=T<2vbm(ovy zzacnWQ>4Som;fH>ljlTP-l8|Bs5N&4*DYZDjd`AdOXDC$d$F#v2rOa`PQef^#q5Ty z8HYlD_q_@VbdpmBLOl}LI1SfnAwzj%{oI}_IV7>zmDcY5Q)r3eiB+P0+ z>}%oGSi}$k@m{9F{<-BE839&Q)*QWuZ?QBR!MD5CKi-oyItVlgqVUzZpgYkp+Jl$( z$&TQh-Uj=;3=0n|$2#Rq{e3K_%r43!`oBjD;Gs35GcKqkSt1XFT{k}sPEmCwre|G} z?!jm+*wKqBZ+}ivHK(XgAIyCVh)RpcEV`6#&MEO#EKR6Oq5k+4{5knP2HYIi4nn^o zhMiL->Fph}V2k3U07@76sO?JR;>x2MnZ&uO3o5Uo9#ht^2OoI&5N0)NsGG?s_yi$| zdp_A=F5S>iL_Zfe1-3?LeV>AtV-bx%!(SKZ;GJ&4O?f(JQstzhRQ6n;Yk`zkf5j2S zS8Cx&O$RtZ1ftk{nXDN=d3(`#O!?!utN;JZ=SFzGMkP4NH$qiUFy%2!Ge6TB(jC)u zFiL0{i+k-h7ebDHRLmYfw`*{PMzzycGRNz!ef34wW(~^aPQi8l+v{Av5u9A1T>fZ< zM78(=f7e3+igelTBK-BA`;bM>e-}l={oU>0@LU=;B_EYp9>iwaW}rn`lg;lHh((nC zR0hPNL5O&3mh5C2KqK$QqAGvCCfQm&|$h zY7c3CahH4)7tkkcQG>QWm2)g+)&_U!91#B+EB$sWOMCHVyoT(7&%X;G?CC+@<@_S+ zUQ~IdR;`pMZLp{X%kzTL-mN{`=q1dgm#fDYtd$|etjz)`{MqCC+KXVmO1r4S0C4E? zbgs$uOo|nSLJ+c;HvNhBN3504&}GPlj)15FRE~sapB@8_q}fXvFf?8!Z~V?N+S>Td<(aD*Yux>)@ecCQN!iVt zY%P|1wqHN=5d2>kEHP}iDOL#g!YCNwoaDGo$so#I=+4%cd$N;%$gIMWhN3UA2uJ*Q zlMvWJlu)oF>d7;a=GlJ@l>ADkTEKK)tdyw!chnk2i^19yqdHH5nPD=3r;+`2ik?t( za_=1<7($mXckmR9KOpEHtja*>{LITarE|NVJ&l0Gxm`u&T=&7`McH-o<0 zVzomx0wGCnE?oWm?&kn79CNWr_g$L~Zh~p6zkQQxs8TiW0UmXkF#TC4KG+0e@^!2Ty9}l^!4?p{h_P`syk94d%T4HXU=!gKkc6mY`NUko53US z0BGo%9!sXJ0R++ocBKv@@e$LWSvfo+iXU-42`Fkl8vQ2)+VBMjb}|-P{lNc?A0P)) zP)J9fzfmpF&}i_s$X=gsMQ**MbF%hXQPRif$kOaw>_9wtd>vEwE#R;`d3}ni3JuLg z)k8PKWGBI6fsF;RcqnSzrWTiPh&RB5lTMIjFbTaMuI0q`l1!jG$02ZrAhD(A6{v0S zkiM5B1nJG66}fcka_{vEeivjFF|f?>GejOAsJaopAQ<01NKMIT@%zVv6M@F>4G8>^vi&)PCUn0xAB-yKj@Dy-M#l$zVFcg2QSdUr^MF4Rfu(RgW9-nT$Wvt#TW?ro=&~jgnmuY0{aa?_V6VW>GEqZYd7mf4m5rE zahci)1=miThC6f;6Yj%#*U9t~>u4ck$I0I|$dP05A@8xHiNPf(Ufw0OUNcTN`L(Y& zyI#@^6EEym?CQa|Z$83RTtq)@{YpSr}cO`@{$toxB>``=J*n#h%*p zmCP6QywWEVg+18L{|921y37WvO0HA-20`jDVWJUPk#8FsHs2Pn_F(qOI-<&42OdnT+(EWU=^7)TWW|vZ9N+xRGFGOyzHlAXwquJ z@UJ=`z}W8jptx?SGo59E~eAZ9MAF3ORT*+*pPhsoG7tOE8wYGV~qCJ zaXs_-6RY{T{?(&+g3a+$7a}%I0I^SJ^NtwCC|1nz7}Zgr>q4%?kS6hyzIg)L!S=?A zD!#*~_^EG$sHe?)rF_RK(+Q>yE@Jre2ua;AhS6jaCY91a@Sw z9Zx4~ug}~4xR_pRTIO!NWzws;PeynXU)iX}(5CN6PF*w3`cEw5%f+RR2Ed6Y^u^6;1*i^v1? z5g0(g9TYc{6F+JNEHidMMv2Ho-rudJmpX3m4dlb@}Y=00xbk=lPfzM%KXEI*f6BIi=Q<$H%e4DU1PF|3=+_zhO{IL1)-3U9956-M$dLDsuU$-l zHaI+q0MWREvc{1NgvKeBVY&u}lLQDyzPmzwk-29$KjH}pG8yH!pT7Dtb3mbtHROrS zxz6=bI#O-3ej;TjtnLTxs6F@FTbS8a7)Rjen@cvWng?63g~v6<2+|pr=LO%2#UGs$ zWCJ+qhi{$%ls4wmFhdZvK|Us@e)M5Y9(eJPQ1w_{6-4(dx8U!v{lOIf=RdA;t-Up^ z2?Tj4mgZg>X2wa7pP)iR{Y!(I4k%OVbL!qx)LW3M(`j+&ns_N7GnsA?kk`>zx%zR_ zT%GH~T!#C-I~Mcc@V+T^YCWIY{}GN1HHJ_a$Qt7WT4~II2?#~)!BX>bZkHRGc;bRF zo&ef$QEL&2?jT2}U~P&H02l&fvoa6avV|*8{C6P>rW%?1|A>L^h``!92}zK-zt3%R zp>=#`n<9U(j!M9230TArg753i+;^nP6HWS-dFZy|uN9H!GKNDaNRZet%N{)ZvZ?L? zb&*6JCZmgE7S(zQYy94xt}tmMq4Rk#%8bN;W3y!d?Gcnuf)C)Nt396Jdm~7{E}f-0 z0`-YfVik-6vZmE9s)UvS!VH-_(|ha4BS?$$?tp*oYgME^j8=@*B$D$UQ|40IKZsxt zev^+tP(&kZvnPVWk)MBu#}w84j`FDL<3X|kv#iv>l35+UC7 z#djOs1jMOtkBiVn2H?wA)>L^xa{ z64n0PlA5Bb$VS%w3{ddhc zecIa|{U(Di^{8UPKcEN##1~)0=X0=#aa^u=FdvZYPbV5ss2_CAlIEq}aYF%92UAhR zw0$~A+cOla9>YyPg8Du;7OFl2!US(A5ZJdM8<@M@)zr@49k@ha@@p2*6K!u|LZG3o zjQ+-#?>Dzs?Zg)>#a@XVT`hPB&AW-gp32dE2#1EgMa|cV#h`p;F{1{{Y^gRHt1=i+ zR=G)YVvKo6-@9I%pDcz_78WPz_8Nw+Sn9atb$dPzJl92v&)!1Vs(70Lm{Lq_hHmIR~*FbG1R4FntrVyu2eJ$+2c z10ARp+`0Qc&@}~2-t*I5&^En`S8ZD^ZGh;_(Hly+sB#XtYyui35DL|l!59dKTu=eE zuW=?JVOe{BXbB`j>7j;l5Jmc~SuhIaMxBcPN&fSE*J|&C9~5*8R-p@n3(@wyBw?t6 z*~K8>-(?+hhH5HeEQBh>gQb}MY?Z+R`M!#ib2C`yPOsj=Y#Qk6YorkIb$7`Ovi4q3 z#l=k_=nl86D#ZNe>5%4jT%s%{?o zx}weereJBnw5IlNRAB7aJ?IYAFdf1M!eu1${4EIO&7h|XtZf8$agyf0Hr-AtT~SR$ zv8E$3B~(r&J6ff4HjD&5gf@WRv@ee=}qCmYSro@qOP>$`o4Y0S z6-xc`v9HhRG>BGO6E3(>fJJ=8^+|A^x{f1t-Q4Ah<$9yNr^h|Y{E(;m9{671qsNpC zh(zKa~BK?+8YPS^qA;EX6c?c#&05b3?jZ05F*5q+h^52Ot|AqKYF(>kb{Jt@2xE| zBa3++mAVtCc~1qFl7kyjt6cR$>_}{0vfKC>XlN7K#%nikT?3Ldf4#fv7Uojt4G6$- z9`v#HJ_0MUFFn{V-EC7S2MU$W7?SX`%PYnTt->gamXQL;FxT5>NP&0VYHZ^7oF zCwf<|V{T--L#vYIAb8y8E
    +-ij9xPA7}5`PUD{SbP<{ZQg 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 NLmvp|`C=7^PAa8tV|k*pp=}F`+(^Fv!@K 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
      +-ij9xPA7}5`PUD{SbP<{ZQg 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 NLmvp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist index e0cad2e7d154..e9d22f6b4d82 100644 --- a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist +++ b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist @@ -57,5 +57,6 @@ $interface_orientations $additional_plist_content + $plist_launch_screen_name diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index 4393a4ae9f7e..2033209ca938 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -92,7 +92,8 @@ class EditorExportPlatformIOS : public EditorExportPlatform { String _get_linker_flags(); String _get_cpp_code(); void _fix_config_file(const Ref &p_preset, Vector &pfile, const IOSConfigData &p_config, bool p_debug); - Error _export_loading_screens(const Ref &p_preset, const String &p_dest_dir); + Error _export_loading_screen_images(const Ref &p_preset, const String &p_dest_dir); + Error _export_loading_screen_file(const Ref &p_preset, const String &p_dest_dir); Error _export_icons(const Ref &p_preset, const String &p_iconset_dir); Vector _get_supported_architectures(); @@ -255,6 +256,8 @@ void EditorExportPlatformIOS::get_export_options(List *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "optional_icons/spotlight_40x40", PROPERTY_HINT_FILE, "*.png"), "")); // Spotlight r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "optional_icons/spotlight_80x80", PROPERTY_HINT_FILE, "*.png"), "")); // Spotlight on devices with retina display + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_launch_screen_storyboard"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "launch_screens/generate_missing"), false)); for (uint64_t i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) { @@ -390,6 +393,48 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_ } else if (lines[i].find("$photolibrary_usage_description") != -1) { String description = p_preset->get("privacy/photolibrary_usage_description"); strnew += lines[i].replace("$photolibrary_usage_description", description) + "\n"; + } else if (lines[i].find("$plist_launch_screen_name") != -1) { + bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); + String value = is_on ? "UILaunchStoryboardName\nLaunch Screen" : ""; + strnew += lines[i].replace("$plist_launch_screen_name", value) + "\n"; + } else if (lines[i].find("$pbx_launch_screen_file_reference") != -1) { + bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); + String value = is_on ? "90DD2D9D24B36E8000717FE1 = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = \"Launch Screen.storyboard\"; sourceTree = \"\"; };" : ""; + strnew += lines[i].replace("$pbx_launch_screen_file_reference", value) + "\n"; + } else if (lines[i].find("$pbx_launch_screen_copy_files") != -1) { + bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); + String value = is_on ? "90DD2D9D24B36E8000717FE1 /* Launch Screen.storyboard */," : ""; + strnew += lines[i].replace("$pbx_launch_screen_copy_files", value) + "\n"; + } else if (lines[i].find("$pbx_launch_screen_build_phase") != -1) { + bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); + String value = is_on ? "90DD2D9E24B36E8000717FE1 /* Launch Screen.storyboard in Resources */," : ""; + strnew += lines[i].replace("$pbx_launch_screen_build_phase", value) + "\n"; + } else if (lines[i].find("$pbx_launch_screen_build_reference") != -1) { + bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); + String value = is_on ? "90DD2D9E24B36E8000717FE1 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 90DD2D9D24B36E8000717FE1 /* Launch Screen.storyboard */; };" : ""; + strnew += lines[i].replace("$pbx_launch_screen_build_reference", value) + "\n"; + } else if (lines[i].find("$pbx_launch_image_usage_setting") != -1) { + bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); + String value = is_on ? "" : "ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;"; + strnew += lines[i].replace("$pbx_launch_image_usage_setting", value) + "\n"; + } else if (lines[i].find("$launch_screen_image_mode") != -1) { + String logo_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); + bool is_on = ProjectSettings::get_singleton()->get("application/boot_splash/fullsize"); + // If custom logo is not specified, Godot does not scale default one, so we should do the same. + String value = (is_on && logo_path.length() > 0) ? "scaleAspectFit" : "center"; + strnew += lines[i].replace("$launch_screen_image_mode", value) + "\n"; + } else if (lines[i].find("$launch_screen_background_color") != -1) { + Color color = ProjectSettings::get_singleton()->get("application/boot_splash/bg_color"); + const String value_format = "red=\"$red\" green=\"$green\" blue=\"$blue\" alpha=\"$alpha\""; + + Dictionary value_dictionary; + value_dictionary["red"] = color.r; + value_dictionary["green"] = color.g; + value_dictionary["blue"] = color.b; + value_dictionary["alpha"] = color.a; + String value = value_format.format(value_dictionary, "$_"); + + strnew += lines[i].replace("$launch_screen_background_color", value) + "\n"; } else { strnew += lines[i] + "\n"; } @@ -591,7 +636,42 @@ Error EditorExportPlatformIOS::_export_icons(const Ref &p_pr return OK; } -Error EditorExportPlatformIOS::_export_loading_screens(const Ref &p_preset, const String &p_dest_dir) { +Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref &p_preset, const String &p_dest_dir) { + Ref splash; + + const String splash_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); + + if (!splash_path.empty()) { + splash.instance(); + const Error err = splash->load(splash_path); + if (err) { + splash.unref(); + } + } + + if (splash.is_null()) { + splash = Ref(memnew(Image(boot_splash_png))); + } + + // Using same image for both @2x and @3x + // because Godot's own boot logo uses single image for all resolutions. + // Also not using @1x image, because devices using this image variant + // are not supported by iOS 9, which is minimal target. + const String splash_png_path_2x = p_dest_dir.plus_file("splash@2x.png"); + const String splash_png_path_3x = p_dest_dir.plus_file("splash@3x.png"); + + if (splash->save_png(splash_png_path_2x) != OK) { + return ERR_FILE_CANT_WRITE; + } + + if (splash->save_png(splash_png_path_3x) != OK) { + return ERR_FILE_CANT_WRITE; + } + + return OK; +} + +Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref &p_preset, const String &p_dest_dir) { DirAccess *da = DirAccess::open(p_dest_dir); ERR_FAIL_COND_V_MSG(!da, ERR_CANT_OPEN, "Cannot open directory '" + p_dest_dir + "'."); @@ -1172,6 +1252,7 @@ Error EditorExportPlatformIOS::export_project(const Ref &p_p files_to_parse.insert("godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata"); files_to_parse.insert("godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme"); files_to_parse.insert("godot_ios/godot_ios.entitlements"); + files_to_parse.insert("godot_ios/Launch Screen.storyboard"); IOSConfigData config_data = { pkg_name, @@ -1347,7 +1428,43 @@ Error EditorExportPlatformIOS::export_project(const Ref &p_p return err; } - err = _export_loading_screens(p_preset, dest_dir + binary_name + "/Images.xcassets/LaunchImage.launchimage/"); + bool use_storyboard = p_preset->get("storyboard/use_launch_screen_storyboard"); + + String launch_image_path = dest_dir + binary_name + "/Images.xcassets/LaunchImage.launchimage/"; + String splash_image_path = dest_dir + binary_name + "/Images.xcassets/SplashImage.imageset/"; + + DirAccess *launch_screen_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + + if (!launch_screen_da) { + return ERR_CANT_CREATE; + } + + if (use_storyboard) { + print_line("Using Launch Storyboard"); + + if (launch_screen_da->change_dir(launch_image_path) == OK) { + launch_screen_da->erase_contents_recursive(); + launch_screen_da->remove(launch_image_path); + } + + err = _export_loading_screen_file(p_preset, splash_image_path); + } else { + print_line("Using Launch Images"); + + const String launch_screen_path = dest_dir + binary_name + "/Launch Screen.storyboard"; + + launch_screen_da->remove(launch_screen_path); + + if (launch_screen_da->change_dir(splash_image_path) == OK) { + launch_screen_da->erase_contents_recursive(); + launch_screen_da->remove(splash_image_path); + } + + err = _export_loading_screen_images(p_preset, launch_image_path); + } + + memdelete(launch_screen_da); + if (err) { return err; } From 96e204bb0d9f464b634b9064d330135ee43d51d9 Mon Sep 17 00:00:00 2001 From: Sergey Minakov Date: Tue, 7 Jul 2020 01:39:57 +0300 Subject: [PATCH 2/2] iOS Export: Storyboard custom values --- platform/iphone/export/export.cpp | 108 +++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 26 deletions(-) diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index 2033209ca938..900c60a7ac61 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -257,6 +257,11 @@ void EditorExportPlatformIOS::get_export_options(List *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "optional_icons/spotlight_80x80", PROPERTY_HINT_FILE, "*.png"), "")); // Spotlight on devices with retina display r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_launch_screen_storyboard"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "storyboard/image_scale_mode", PROPERTY_HINT_ENUM, "Same as Logo,Center,Scale To Fit,Scale To Fill,Scale"), 0)); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@2x", PROPERTY_HINT_FILE, "*.png"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@3x", PROPERTY_HINT_FILE, "*.png"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_custom_bg_color"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::COLOR, "storyboard/custom_bg_color"), Color())); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "launch_screens/generate_missing"), false)); @@ -277,6 +282,12 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_ "ad-hoc", "enterprise" }; + static const String storyboard_image_scale_mode[] = { + "center", + "scaleAspectFit", + "scaleAspectFill", + "scaleToFill" + }; String str; String strnew; str.parse_utf8((const char *)pfile.ptr(), pfile.size()); @@ -418,13 +429,25 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_ String value = is_on ? "" : "ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;"; strnew += lines[i].replace("$pbx_launch_image_usage_setting", value) + "\n"; } else if (lines[i].find("$launch_screen_image_mode") != -1) { - String logo_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); - bool is_on = ProjectSettings::get_singleton()->get("application/boot_splash/fullsize"); - // If custom logo is not specified, Godot does not scale default one, so we should do the same. - String value = (is_on && logo_path.length() > 0) ? "scaleAspectFit" : "center"; + int image_scale_mode = p_preset->get("storyboard/image_scale_mode"); + String value; + + switch (image_scale_mode) { + case 0: { + String logo_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); + bool is_on = ProjectSettings::get_singleton()->get("application/boot_splash/fullsize"); + // If custom logo is not specified, Godot does not scale default one, so we should do the same. + value = (is_on && logo_path.length() > 0) ? "scaleAspectFit" : "center"; + } break; + default: { + value = storyboard_image_scale_mode[image_scale_mode - 1]; + } + } + strnew += lines[i].replace("$launch_screen_image_mode", value) + "\n"; } else if (lines[i].find("$launch_screen_background_color") != -1) { - Color color = ProjectSettings::get_singleton()->get("application/boot_splash/bg_color"); + bool use_custom = p_preset->get("storyboard/use_custom_bg_color"); + Color color = use_custom ? p_preset->get("storyboard/custom_bg_color") : ProjectSettings::get_singleton()->get("application/boot_splash/bg_color"); const String value_format = "red=\"$red\" green=\"$green\" blue=\"$blue\" alpha=\"$alpha\""; Dictionary value_dictionary; @@ -637,35 +660,68 @@ Error EditorExportPlatformIOS::_export_icons(const Ref &p_pr } Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref &p_preset, const String &p_dest_dir) { - Ref splash; + const String custom_launch_image_2x = p_preset->get("storyboard/custom_image@2x"); + const String custom_launch_image_3x = p_preset->get("storyboard/custom_image@3x"); - const String splash_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); + if (custom_launch_image_2x.length() > 0 && custom_launch_image_3x.length() > 0) { + Ref image; + String image_path = p_dest_dir.plus_file("splash@2x.png"); + image.instance(); + Error err = image->load(custom_launch_image_2x); - if (!splash_path.empty()) { - splash.instance(); - const Error err = splash->load(splash_path); if (err) { - splash.unref(); + image.unref(); + return err; } - } - if (splash.is_null()) { - splash = Ref(memnew(Image(boot_splash_png))); - } + if (image->save_png(image_path) != OK) { + return ERR_FILE_CANT_WRITE; + } - // Using same image for both @2x and @3x - // because Godot's own boot logo uses single image for all resolutions. - // Also not using @1x image, because devices using this image variant - // are not supported by iOS 9, which is minimal target. - const String splash_png_path_2x = p_dest_dir.plus_file("splash@2x.png"); - const String splash_png_path_3x = p_dest_dir.plus_file("splash@3x.png"); + image.unref(); + image_path = p_dest_dir.plus_file("splash@3x.png"); + image.instance(); + err = image->load(custom_launch_image_3x); - if (splash->save_png(splash_png_path_2x) != OK) { - return ERR_FILE_CANT_WRITE; - } + if (err) { + image.unref(); + return err; + } + + if (image->save_png(image_path) != OK) { + return ERR_FILE_CANT_WRITE; + } + } else { + Ref splash; + + const String splash_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); + + if (!splash_path.empty()) { + splash.instance(); + const Error err = splash->load(splash_path); + if (err) { + splash.unref(); + } + } - if (splash->save_png(splash_png_path_3x) != OK) { - return ERR_FILE_CANT_WRITE; + if (splash.is_null()) { + splash = Ref(memnew(Image(boot_splash_png))); + } + + // Using same image for both @2x and @3x + // because Godot's own boot logo uses single image for all resolutions. + // Also not using @1x image, because devices using this image variant + // are not supported by iOS 9, which is minimal target. + const String splash_png_path_2x = p_dest_dir.plus_file("splash@2x.png"); + const String splash_png_path_3x = p_dest_dir.plus_file("splash@3x.png"); + + if (splash->save_png(splash_png_path_2x) != OK) { + return ERR_FILE_CANT_WRITE; + } + + if (splash->save_png(splash_png_path_3x) != OK) { + return ERR_FILE_CANT_WRITE; + } } return OK;