o}#O|wVYzY%`++&-{m|9vL^;GsL@xY
z5!)l_sEy25n5;xN*5I&7hlY{yY{*|B*SMvQqX^$l*;&TOr*c+H^htRLW29MHy)XdP
z!=|~0BmXmiGnM5UFHg&j{?-4)#>DES^*kkWr*t#qgQ!r3cpugVwYsy=*QaF5rFhx%UbDfR6Xeo;w~i$z
zU`2W0HhDaOfniGWeWylR2%luM1@{;jGJvRF=h_i=xEcjxJ|+#
z@id8y#_;KyZp+P=rJh*5DqRm*lvxDSrX6*+S^YWvY7CLF3GivC1^$ScryLf&?=WgT;@1+J=6GtPZFkNu|$$q0_DvD<6mtqkqBpFC%(^i
zB;-y_&P>YRLFP^SeJ+5c>y;hKhA3w4k-kp80sCal&3xdRT5>{;7f@3NhMX#+G|?4Y
z50G9gV3)RBs8g)a05=Apv}R5+t0oH<_%yz9Yi%+s;p?%^yGuPC>RE_6@{(Eb^wnfN
zQ=|=x1v>~^`^RF*m*v#zS$al#9au)#?61IQc;t(qmLJlIMVYElcuy&Tg#?W8twIlP
z?i^RmuCc8FR5m3iGVm-4Etl^isHSVS9ouGO_PL$~m#)WRG}3-|e{LRF4w%P982ZB2
zE?F#bdqQ~xTa<>&4#2NFFt0x{H8Ue1&c(AW=7e!);kM^JbLa6HFgBS3iBms}@-`7S}
zy0Iir<)j83hLOPv*6p&UCe|Ge5Y^2o7;aO$pnXILO~V&5@aHsQ@@k9pmAKM$v)Xip
z9cR*ks#rs{09H4e`DZ~Z0&h)LScEnzD?&O($(;p{Fgm8($7N?%P%q}UA9>Yem6A4;
zG~Sa%NO-kC*BQ<4Wyn`tZH`oGrD?ifH{UzWJO-njT%Vu
zhG?E5m&wcJ74k~Cv;P9IUY@Q(8A|Q2Hmg4WHQ&eXIGuVu>e7B4rY^PUM2{IK6vFLR
zM^SC|CBSCOkBG9b<#_>a@qUOmeFgVAK7*Mc-aF@1gOqOr
zpfqZed^UUol)F=FEr1kkO36@?HG8V-ie>e&h3NKqb9nklDjywt7Cjpjrl5FmJb{E4
zb?4B_uAkC}sQfU2>{WzR`fdTtlzbK_K{DYg)XP3#?AdX3tO@@`b;~r+IV2GYAq>H<
zzEhH(yrCX2jHcD3*0y|mQo>}??!C8;0EhzX63Mp(F6@O%5qy&2f{XrhnsM~?v}u5i
z`GIsO2z1*$U7+>`piFf$AKuRddheuUKQlbhb2!!SWY4!$boXf=M%;-WK99BskUsGQ
z2A;QdD&1Z3Xi0ff=S0wZjk!!HUS$W~q{@;1)rDVeLL;(iQ>Y)9O(anv$Z+%B4KU%U
z%BCy3S5lXL^JHGpqsAY~*WgTRQPCaZ9^dHJcdp2?sYozHInVE?>y~q88w1#*|7d_e
zvaKJ;btHUM0XP?HO3evM_=93r5@d7gPV)Maz_Tx
zjXd#oYD=U>K%8=b3>vgN<_N5RvdwDC!5HLAD733&KY#WHP}vw$6AYl|B75&AdYa4I$cn6L8-Puf+tede3fjUk;;
z(&zyj-GvZ5n@L8&kn
zwtrJ@AJGkFHT@n5k(CO!!Vt5Z&cOplZ(<HjTD)-JiO@{Q+uAaIqOL^Dy>4C<3bt^3WE7Qxvzx~tv
zX=c0+xhuyhdiZfM4%(ceWSY$H=R2wR(#AU+zm|V>G}%QY(^_!j`EoHe(DD-MwPDv1
z@t>p}m8(paT3#-A?bl^3zD3$yi89f({1f%&HhOm%0#5BTBOQj+>GT!^oU_hp_y`yS
z<8&^YSGaJ_kzRD56P)@IHLq}$s4G(|+6?|xfAc=3=ByHsgr8TuYQScr=*L_BRljm`
z{OXVzq=2XA6tE6(eCzO$lmDtO-`uydeF>z9#dC_-6nG!r@uo%Rzx55rKW=`$3R1{j
z^9mWb@$JPGhS`7X``>2=ox%ZD)34_hGhp@V^a?-M|JF-xIPlt1fq>D=^9mXka8bDF
z`NexjeE%aI0|pOvltt2_
zoR0vPt>!lRHy_KBY~?YU80`#U!$iweFxeLKg}|RoDO4>SWS
z)nKzX^FcXdu%*ziFsv9#Xd;Wk3jef^$&OIX-3gFfhk9s*eD5fq=C9r{8JNA9_Hui5
z0Jd9=)ct!h0hAySyn`w`#z8Fv7H!7Yp5z_fM^SF+VV1qe=}>Pgjh`_bZtiupMC2(#I=aFYD5Z
zgPHm-#b0J^g*{l4-6OmUj5dC0y912!r9qT^&9F`ni8KJ{*Qqx(F4yeT4cNHNw4Sf6
ziQcTQ|A8{nM6q?s0{-qHFY3esmsXqsF5zBV)GVV~1Fr)Q!l4G611*8su+ZM$yaR#h
zBxwv9)(?#SC6yNxR_~XTx}pGMU~(AImJ3&d@ibo^-oOvieDsoIHjbGX0M7%Xr3M|t;Nk`%uwWzOlQ3=kI=SbTt%}kasF9p4J8Z#U71TIaz
zSX6S$YTR0d+SmL~AV6}L&&GMXpNwhpCrEk=qrIvs29vy}yvTnKj(Zav)&UdiIBMQW
zEj&LR`Rp{yd}6yLM3APVc~LLuI0oMY?DGT2a*7&2aQMGE>oPM2x;Bb$xWFz=y-teP
z$h&1F5+8+gMp}=L-LEPh+~rMVN;3+zy~r;Hs|$JioYR1MvplA@^0gZjRjSyALsGA=
z@0qbRn-Z+~d+r8`Nl?HienQn2Fcb(T6US-8TtsS>X|4`&&LUka#i=B>O7q-b0Iy{q
zrKhWa(I;O5_>Wrm8GEO|I^~i`es}y=p`y?dBkj-ca{|5}QX#E3!|IUYv6nObpVyp(tv?zwAg9XDeUzBw=}%pHbA3*&Xg}%O|Dmk&N1$=u`;0eX{jCjj*z;@Sadw%xVc0AYXTnd|oJD38}s$_6G2oeIZPjmJt;
z6>G3zlW(`sc~JoANdXXNmSDSwZ
z5qojPL)|0jz6Yo*n2V$>kd`9?N}QGZJz%H{)QclKT!+}WwR5-9zHhECcXFX2Kkc>w
z`{SWVh1A|U&&9))3gpOJE$WQb%vd4G1HHz78SgU0#<9a*z=JjKNe3-~ZX4`yixE-j
zy9|)pU_oc9%n?A})G5(|w=YXvvV)0aFE3aTn+Vg)Rzc(s(CE_qW^#Hvs=``f2buvL
zKK`eP-e|L|OTr~W30Ms)VZ%%TucVJ-k5>R=mFZwO
z$4<%CDkkib;~$gb%h4Eu?8{x3euRpZ)$PQVo`kTkCZ+Kw6B6^9KxJk!LbiWmjvCK99|DLd%YG;u2=+2rf@nz~LUy
z@d`<#tDOr^g&+Ita)dtVzKzuhB0G#c+}AQvg;zAp22)~QI(w7H2~e2$%cDjprWAu*
z$V78dvwJCa%i)?pO(4!5K1l}J>!6#nz3Jci2Qo!y2jv%WmXI4Q*2g0ZO3?Q4xlvfv
zGg#H$vjLyF623z8W6Vr7fI2|L5XN5zf64y!sxCd8H`G1>6jZ=Gfd|Jw#2Tps_N^)r
zkv05dRD~Tj{m@c>fyQW}64hEs=_=OdB2{dg_w7U*njoVvA8Jb>TW9Mb7tbzsqdx{0enY6&)j5I+AL@+S9zlTDN#TV>yk
zp-sc)8#iepWvWpF#2|jjK~^mxd}q4H-=a9!*bY#-2WzVD%DK}-4b{=#=48>v@Cb%Z
z&;+eVHwYv9EKp1oVB{6_*=`gC
z6e7WCWWq!~QZCe{OuwQ?Uuq|e@&uq_3hap!$oTApsS1IdH4@+F1S*Dz6d9&k!XV0n
z25$>ydnr-Q)165mV*=Wi<8V@f@}lf`40c0TaKtkQ17k+&aa=|Iw}!Fc*k{fLNCvGJ
zClkWBKddbM0zn1x#gy3sB5>6*=J$S%9dODLaS9KUS|WN4VL0!Ye8EA9NXL`so>;c{
znrK_uDqDg^8EY`moBlw0ra7q4#ZNL*Xt|I4a4=CQy%MX~+3fRUL(^O3@6v{j7D4c7
zTZb=3DXIH#PxHSvj0VTpI)CA}&gRdAD#TEr`@>SVlN0eRqQy#6ts)>xde9s2iiOA+&^e)hspa|bj->X{{12hhhVKp2`2!7;!ST;r
zZqc==@>=kLKWk>rgQ2kd_DW&bI`Q@D8Oz*dBbQYri?CG_HyRQ{fwzVYFw@qcu^p=)
zuP&>)yWV{h*C8e_5(9;a?p!L%r>bauZAlWAuGVpg?QyQMV7({#?)pSiiMUW!2+wVt
zKdxWE!`j+^X?HZ*m1>8}&u?z{4xPHKL59+5aH9Mfzj4~U|DniITI=gbB`As4C-rgT004spc%v1!`+6d%UL5-e>iavpQ}&p&pA}=6t%>-7
z`9ri#fu_Fg<+uCh%%Jx#D;QF2U3`%rXp>0q9>h1Zaa!_gkFIq?mSO`)&4ury1-1V3
zu+K|!j9RsqD&E7HG&jvc`1@r-(YuiEnfa^!R_U*%++SfRV72pE(|%8#w|s(LXE{7?
zVUqT_i7lVexVZe6p_8H04TE;_U=pQ^_IxfZL%Z5O-c?Tqd%Pjk-$)#L1vt?1LF*zQ
z*+tH!q1QxpdID}Xb%xjM*Aw@rxBIKTmE=@gk8Y7TE*hOIZ1rBPW^Sx{N!zHRoo=2BwyxP+@7T_3=$xB#^F`!`)U&u(`8^F2!Erz4%$*fNnjy=(
zC#lQ5m(t(F20T-4OY{+(NnKN-Cmg$;YZs{2Uk76~k2oor&nTZ;3@87RCcFbg;=BO^
z#5T^mKlYf4!qcdE3w~#$;!DYY)6m^8n%~+m985w=aP2rDZ4zSCvLg!dC2z
zH!H*p;UtZLJ57mpM@SVwt`LV{A;CqwL
zaWcI=f8#uz6F&Mk>aez3eX~!HQ}-c_eQqbrc@kG1IxD7c)%24rL;E><#Dk2rtk
z*QUAyFy-dM(1rQUF?
zlg3pu)7mggwTXL)*oMP-h;5tnCVI|sJ~dNgs+XrvY(qk-`LpIT6WR{JEn_Ww%6*K9
zgqVU+)b|Rqu8kWBgA{X<4g|IinCH22{B_zi5M_&PRnCd81!$^jwc4$tJacwt_3g!^iql0@6iH1zwi^9LRV&jw5JZ>ELo{MZi(G1#QP1B6jRpJ6>zAi&t%k5tTJ!7+6^H~DzI6G*X
z0g{irpI%`tDJV~=(kXFX(%+OQ{tyNfPoY(mn9M^v8&t^r~;x%x31g+&5uC|m->B@N=`!@>u^nlH%
rZHWZdOL`TGAyfYVfr09E(XxF391)|t;eo9X`B?q7?y2b}vq0eF!c
literal 0
HcmV?d00001
diff --git a/godot/addons/panku_console/res/effect/square_shadow.png.import b/godot/addons/panku_console/res/effect/square_shadow.png.import
new file mode 100644
index 0000000..1d6d561
--- /dev/null
+++ b/godot/addons/panku_console/res/effect/square_shadow.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dvr12fl5prm78"
+path="res://.godot/imported/square_shadow.png-0b7f91b74dd24247868957be13db72f4.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/effect/square_shadow.png"
+dest_files=["res://.godot/imported/square_shadow.png-0b7f91b74dd24247868957be13db72f4.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=true
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=true
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/godot/addons/panku_console/res/green_gradient_1d.tres b/godot/addons/panku_console/res/green_gradient_1d.tres
new file mode 100644
index 0000000..b2e8aa1
--- /dev/null
+++ b/godot/addons/panku_console/res/green_gradient_1d.tres
@@ -0,0 +1,4 @@
+[gd_resource type="Gradient" format=3 uid="uid://nr65cgweqh8n"]
+
+[resource]
+colors = PackedColorArray(0.129412, 0.14902, 0.180392, 0.501961, 0.129412, 0.14902, 0.180392, 0)
diff --git a/godot/addons/panku_console/res/icons2/add.svg b/godot/addons/panku_console/res/icons2/add.svg
new file mode 100644
index 0000000..d0cbaf1
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/add.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/add.svg.import b/godot/addons/panku_console/res/icons2/add.svg.import
new file mode 100644
index 0000000..4332717
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/add.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dprpfr0l5xvmu"
+path="res://.godot/imported/add.svg-2a06068ce10412da423766fee4b6d4aa.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/add.svg"
+dest_files=["res://.godot/imported/add.svg-2a06068ce10412da423766fee4b6d4aa.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/arrow-down-svgrepo-com.svg b/godot/addons/panku_console/res/icons2/arrow-down-svgrepo-com.svg
new file mode 100644
index 0000000..429e411
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/arrow-down-svgrepo-com.svg
@@ -0,0 +1,12 @@
+
+
+
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/arrow-down-svgrepo-com.svg.import b/godot/addons/panku_console/res/icons2/arrow-down-svgrepo-com.svg.import
new file mode 100644
index 0000000..64bc23d
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/arrow-down-svgrepo-com.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cdxbns8lyctqp"
+path="res://.godot/imported/arrow-down-svgrepo-com.svg-38ccb799fe0295b6eb8e51628325ac00.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/arrow-down-svgrepo-com.svg"
+dest_files=["res://.godot/imported/arrow-down-svgrepo-com.svg-38ccb799fe0295b6eb8e51628325ac00.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/arrow-up-md-svgrepo-com.svg b/godot/addons/panku_console/res/icons2/arrow-up-md-svgrepo-com.svg
new file mode 100644
index 0000000..85982c5
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/arrow-up-md-svgrepo-com.svg
@@ -0,0 +1,12 @@
+
+
+
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/arrow-up-md-svgrepo-com.svg.import b/godot/addons/panku_console/res/icons2/arrow-up-md-svgrepo-com.svg.import
new file mode 100644
index 0000000..9c881ef
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/arrow-up-md-svgrepo-com.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://d0k813mm5y0d5"
+path="res://.godot/imported/arrow-up-md-svgrepo-com.svg-0d7dc8f9b4626627fc89d656dd6522e5.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/arrow-up-md-svgrepo-com.svg"
+dest_files=["res://.godot/imported/arrow-up-md-svgrepo-com.svg-0d7dc8f9b4626627fc89d656dd6522e5.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/bin-cancel-delete-remove-trash-garbage-svgrepo-com.svg b/godot/addons/panku_console/res/icons2/bin-cancel-delete-remove-trash-garbage-svgrepo-com.svg
new file mode 100644
index 0000000..8842fee
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/bin-cancel-delete-remove-trash-garbage-svgrepo-com.svg
@@ -0,0 +1,12 @@
+
+
+
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/bin-cancel-delete-remove-trash-garbage-svgrepo-com.svg.import b/godot/addons/panku_console/res/icons2/bin-cancel-delete-remove-trash-garbage-svgrepo-com.svg.import
new file mode 100644
index 0000000..c34228a
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/bin-cancel-delete-remove-trash-garbage-svgrepo-com.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cngs5d4uosvmt"
+path="res://.godot/imported/bin-cancel-delete-remove-trash-garbage-svgrepo-com.svg-b7f02697b5af6027969d40533290cf43.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/bin-cancel-delete-remove-trash-garbage-svgrepo-com.svg"
+dest_files=["res://.godot/imported/bin-cancel-delete-remove-trash-garbage-svgrepo-com.svg-b7f02697b5af6027969d40533290cf43.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/bookmark-filled-svgrepo-com.svg b/godot/addons/panku_console/res/icons2/bookmark-filled-svgrepo-com.svg
new file mode 100644
index 0000000..e3b8168
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/bookmark-filled-svgrepo-com.svg
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/bookmark-filled-svgrepo-com.svg.import b/godot/addons/panku_console/res/icons2/bookmark-filled-svgrepo-com.svg.import
new file mode 100644
index 0000000..4770d4d
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/bookmark-filled-svgrepo-com.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://x2wmejhxundv"
+path="res://.godot/imported/bookmark-filled-svgrepo-com.svg-36e232dcc8b8fb5b9792fabd49d75fb9.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/bookmark-filled-svgrepo-com.svg"
+dest_files=["res://.godot/imported/bookmark-filled-svgrepo-com.svg-36e232dcc8b8fb5b9792fabd49d75fb9.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/bookmark-svgrepo-com.svg b/godot/addons/panku_console/res/icons2/bookmark-svgrepo-com.svg
new file mode 100644
index 0000000..f7fae38
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/bookmark-svgrepo-com.svg
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/bookmark-svgrepo-com.svg.import b/godot/addons/panku_console/res/icons2/bookmark-svgrepo-com.svg.import
new file mode 100644
index 0000000..6b944e5
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/bookmark-svgrepo-com.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://232vc3pkp4kt"
+path="res://.godot/imported/bookmark-svgrepo-com.svg-ff120b5ee0d289505ac4f825e8ec66d9.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/bookmark-svgrepo-com.svg"
+dest_files=["res://.godot/imported/bookmark-svgrepo-com.svg-ff120b5ee0d289505ac4f825e8ec66d9.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/check-svgrepo-com.svg b/godot/addons/panku_console/res/icons2/check-svgrepo-com.svg
new file mode 100644
index 0000000..b0a18cf
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/check-svgrepo-com.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/check-svgrepo-com.svg.import b/godot/addons/panku_console/res/icons2/check-svgrepo-com.svg.import
new file mode 100644
index 0000000..1b60ff7
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/check-svgrepo-com.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://2cjvp0dp8ede"
+path="res://.godot/imported/check-svgrepo-com.svg-034d6c5925c00dc6c3cf6966293ed643.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/check-svgrepo-com.svg"
+dest_files=["res://.godot/imported/check-svgrepo-com.svg-034d6c5925c00dc6c3cf6966293ed643.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/checkbox_checked.svg b/godot/addons/panku_console/res/icons2/checkbox_checked.svg
new file mode 100644
index 0000000..970edd0
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/checkbox_checked.svg
@@ -0,0 +1,22 @@
+
+
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/checkbox_checked.svg.import b/godot/addons/panku_console/res/icons2/checkbox_checked.svg.import
new file mode 100644
index 0000000..3752b27
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/checkbox_checked.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bua84a0uv8ntw"
+path="res://.godot/imported/checkbox_checked.svg-b5d0aaca03398eb49c2d410cf3c86d9a.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/checkbox_checked.svg"
+dest_files=["res://.godot/imported/checkbox_checked.svg-b5d0aaca03398eb49c2d410cf3c86d9a.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/checkbox_unchecked.svg b/godot/addons/panku_console/res/icons2/checkbox_unchecked.svg
new file mode 100644
index 0000000..609e889
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/checkbox_unchecked.svg
@@ -0,0 +1,19 @@
+
+
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/checkbox_unchecked.svg.import b/godot/addons/panku_console/res/icons2/checkbox_unchecked.svg.import
new file mode 100644
index 0000000..a659b48
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/checkbox_unchecked.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dkiyle8rjahmw"
+path="res://.godot/imported/checkbox_unchecked.svg-43408d4debc25d7804c4c806c8681c45.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/checkbox_unchecked.svg"
+dest_files=["res://.godot/imported/checkbox_unchecked.svg-43408d4debc25d7804c4c806c8681c45.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/chevron_right.svg b/godot/addons/panku_console/res/icons2/chevron_right.svg
new file mode 100644
index 0000000..650d8f2
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/chevron_right.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/chevron_right.svg.import b/godot/addons/panku_console/res/icons2/chevron_right.svg.import
new file mode 100644
index 0000000..c8099a1
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/chevron_right.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ws58gucuygx1"
+path="res://.godot/imported/chevron_right.svg-2c66815dcd12ccc3ba2562028a236330.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/chevron_right.svg"
+dest_files=["res://.godot/imported/chevron_right.svg-2c66815dcd12ccc3ba2562028a236330.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/close.svg b/godot/addons/panku_console/res/icons2/close.svg
new file mode 100644
index 0000000..05fb420
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/close.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/close.svg.import b/godot/addons/panku_console/res/icons2/close.svg.import
new file mode 100644
index 0000000..cfded02
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/close.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://8g5afcuanbl6"
+path="res://.godot/imported/close.svg-3a85a46ed81631640c7e8cd4342c98f0.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/close.svg"
+dest_files=["res://.godot/imported/close.svg-3a85a46ed81631640c7e8cd4342c98f0.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/close_20x.svg b/godot/addons/panku_console/res/icons2/close_20x.svg
new file mode 100644
index 0000000..4aab7f5
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/close_20x.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/close_20x.svg.import b/godot/addons/panku_console/res/icons2/close_20x.svg.import
new file mode 100644
index 0000000..f9a6a2d
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/close_20x.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ttbgv1vr1xsc"
+path="res://.godot/imported/close_20x.svg-9ead6c9c7ae149729de0bac95295aaba.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/close_20x.svg"
+dest_files=["res://.godot/imported/close_20x.svg-9ead6c9c7ae149729de0bac95295aaba.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/expand_more.svg b/godot/addons/panku_console/res/icons2/expand_more.svg
new file mode 100644
index 0000000..61fa21d
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/expand_more.svg
@@ -0,0 +1 @@
+
diff --git a/godot/addons/panku_console/res/icons2/expand_more.svg.import b/godot/addons/panku_console/res/icons2/expand_more.svg.import
new file mode 100644
index 0000000..b7bd274
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/expand_more.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://d1qaq6vnyc2f2"
+path="res://.godot/imported/expand_more.svg-156eef34c01d1545ad526cf0292ef120.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/expand_more.svg"
+dest_files=["res://.godot/imported/expand_more.svg-156eef34c01d1545ad526cf0292ef120.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/eye.svg b/godot/addons/panku_console/res/icons2/eye.svg
new file mode 100644
index 0000000..171a612
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/eye.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/eye.svg.import b/godot/addons/panku_console/res/icons2/eye.svg.import
new file mode 100644
index 0000000..4c56efd
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/eye.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cvli654t5ybne"
+path="res://.godot/imported/eye.svg-6814b908d03cc1398c9846342a0966fc.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/eye.svg"
+dest_files=["res://.godot/imported/eye.svg-6814b908d03cc1398c9846342a0966fc.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/favorite.svg b/godot/addons/panku_console/res/icons2/favorite.svg
new file mode 100644
index 0000000..4bd196b
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/favorite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/favorite.svg.import b/godot/addons/panku_console/res/icons2/favorite.svg.import
new file mode 100644
index 0000000..e6f17dc
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/favorite.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://hf6h8otb8qkv"
+path="res://.godot/imported/favorite.svg-94e3b968ddcfab82f19abf606a6cd9bb.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/favorite.svg"
+dest_files=["res://.godot/imported/favorite.svg-94e3b968ddcfab82f19abf606a6cd9bb.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/fold-svgrepo-com.svg b/godot/addons/panku_console/res/icons2/fold-svgrepo-com.svg
new file mode 100644
index 0000000..0d9ed74
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/fold-svgrepo-com.svg
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/fold-svgrepo-com.svg.import b/godot/addons/panku_console/res/icons2/fold-svgrepo-com.svg.import
new file mode 100644
index 0000000..23349a5
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/fold-svgrepo-com.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dchvk7qgfe37m"
+path="res://.godot/imported/fold-svgrepo-com.svg-6f951c0c7f0583013a7f3fa96d045e61.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/fold-svgrepo-com.svg"
+dest_files=["res://.godot/imported/fold-svgrepo-com.svg-6f951c0c7f0583013a7f3fa96d045e61.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=true
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/gear.svg b/godot/addons/panku_console/res/icons2/gear.svg
new file mode 100644
index 0000000..569706f
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/gear.svg
@@ -0,0 +1,10 @@
+
diff --git a/godot/addons/panku_console/res/icons2/gear.svg.import b/godot/addons/panku_console/res/icons2/gear.svg.import
new file mode 100644
index 0000000..42d75bb
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/gear.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ch214eu302abt"
+path="res://.godot/imported/gear.svg-bd633691cf7fd6c996b8a22361898045.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/gear.svg"
+dest_files=["res://.godot/imported/gear.svg-bd633691cf7fd6c996b8a22361898045.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/history.svg b/godot/addons/panku_console/res/icons2/history.svg
new file mode 100644
index 0000000..0d691fe
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/history.svg
@@ -0,0 +1,9 @@
+
diff --git a/godot/addons/panku_console/res/icons2/history.svg.import b/godot/addons/panku_console/res/icons2/history.svg.import
new file mode 100644
index 0000000..dbd6d5b
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/history.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://kkrqc0j1wdi6"
+path="res://.godot/imported/history.svg-a137f2f4fbb3649b91b01d8def6f6456.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/history.svg"
+dest_files=["res://.godot/imported/history.svg-a137f2f4fbb3649b91b01d8def6f6456.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/info.svg b/godot/addons/panku_console/res/icons2/info.svg
new file mode 100644
index 0000000..0e9ea7a
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/info.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/info.svg.import b/godot/addons/panku_console/res/icons2/info.svg.import
new file mode 100644
index 0000000..ecb56ba
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/info.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dxvodkcmn4pa8"
+path="res://.godot/imported/info.svg-2b1105336c45eeebd4acdf04c60c8bdb.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/info.svg"
+dest_files=["res://.godot/imported/info.svg-2b1105336c45eeebd4acdf04c60c8bdb.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/info2.svg b/godot/addons/panku_console/res/icons2/info2.svg
new file mode 100644
index 0000000..e3db00e
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/info2.svg
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/info2.svg.import b/godot/addons/panku_console/res/icons2/info2.svg.import
new file mode 100644
index 0000000..aa5b413
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/info2.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://b6jt0ggmuoyeb"
+path="res://.godot/imported/info2.svg-c9ea3dad2575e3684098e5112249010d.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/info2.svg"
+dest_files=["res://.godot/imported/info2.svg-c9ea3dad2575e3684098e5112249010d.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/keyboard.svg b/godot/addons/panku_console/res/icons2/keyboard.svg
new file mode 100644
index 0000000..6cdb9a1
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/keyboard.svg
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/keyboard.svg.import b/godot/addons/panku_console/res/icons2/keyboard.svg.import
new file mode 100644
index 0000000..d1fcf08
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/keyboard.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bqxh6hk3op1wv"
+path="res://.godot/imported/keyboard.svg-65a8773013921e61a1cc3ef80ef82693.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/keyboard.svg"
+dest_files=["res://.godot/imported/keyboard.svg-65a8773013921e61a1cc3ef80ef82693.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/menu.svg b/godot/addons/panku_console/res/icons2/menu.svg
new file mode 100644
index 0000000..febcbbe
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/menu.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/menu.svg.import b/godot/addons/panku_console/res/icons2/menu.svg.import
new file mode 100644
index 0000000..3a56540
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/menu.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dosm26riekruh"
+path="res://.godot/imported/menu.svg-15ef2ef76b3f6c0e7fc0168d1ac05d38.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/menu.svg"
+dest_files=["res://.godot/imported/menu.svg-15ef2ef76b3f6c0e7fc0168d1ac05d38.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/more_horiz.svg b/godot/addons/panku_console/res/icons2/more_horiz.svg
new file mode 100644
index 0000000..73560d0
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/more_horiz.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/more_horiz.svg.import b/godot/addons/panku_console/res/icons2/more_horiz.svg.import
new file mode 100644
index 0000000..9430815
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/more_horiz.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bbc41a7b3jre0"
+path="res://.godot/imported/more_horiz.svg-7ca01f2b54bfa3040d05158756af7968.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/more_horiz.svg"
+dest_files=["res://.godot/imported/more_horiz.svg-7ca01f2b54bfa3040d05158756af7968.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/open_with.svg b/godot/addons/panku_console/res/icons2/open_with.svg
new file mode 100644
index 0000000..d6c2bae
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/open_with.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/open_with.svg.import b/godot/addons/panku_console/res/icons2/open_with.svg.import
new file mode 100644
index 0000000..90ce2f3
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/open_with.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://b22jdciwq07ic"
+path="res://.godot/imported/open_with.svg-4c7b4bea2cb5c0a1af405d61d3d85fa3.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/open_with.svg"
+dest_files=["res://.godot/imported/open_with.svg-4c7b4bea2cb5c0a1af405d61d3d85fa3.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/pause-1010-svgrepo-com.svg b/godot/addons/panku_console/res/icons2/pause-1010-svgrepo-com.svg
new file mode 100644
index 0000000..6aba11b
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/pause-1010-svgrepo-com.svg
@@ -0,0 +1,19 @@
+
+
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/pause-1010-svgrepo-com.svg.import b/godot/addons/panku_console/res/icons2/pause-1010-svgrepo-com.svg.import
new file mode 100644
index 0000000..812a930
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/pause-1010-svgrepo-com.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cpfnfg1aw6xso"
+path="res://.godot/imported/pause-1010-svgrepo-com.svg-8a4549394af5099adcc9e7d6754d8258.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/pause-1010-svgrepo-com.svg"
+dest_files=["res://.godot/imported/pause-1010-svgrepo-com.svg-8a4549394af5099adcc9e7d6754d8258.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/play-1001-svgrepo-com.svg b/godot/addons/panku_console/res/icons2/play-1001-svgrepo-com.svg
new file mode 100644
index 0000000..7cebe14
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/play-1001-svgrepo-com.svg
@@ -0,0 +1,19 @@
+
+
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/play-1001-svgrepo-com.svg.import b/godot/addons/panku_console/res/icons2/play-1001-svgrepo-com.svg.import
new file mode 100644
index 0000000..b9b56ee
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/play-1001-svgrepo-com.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ecmevhk0tuas"
+path="res://.godot/imported/play-1001-svgrepo-com.svg-6dda54bd1afb4351b91dc74d89d43c7f.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/play-1001-svgrepo-com.svg"
+dest_files=["res://.godot/imported/play-1001-svgrepo-com.svg-6dda54bd1afb4351b91dc74d89d43c7f.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/pop-out-svgrepo-com.svg b/godot/addons/panku_console/res/icons2/pop-out-svgrepo-com.svg
new file mode 100644
index 0000000..e59c21a
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/pop-out-svgrepo-com.svg
@@ -0,0 +1,14 @@
+
+
+
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/pop-out-svgrepo-com.svg.import b/godot/addons/panku_console/res/icons2/pop-out-svgrepo-com.svg.import
new file mode 100644
index 0000000..ad501b5
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/pop-out-svgrepo-com.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://gav3m4qtvgje"
+path="res://.godot/imported/pop-out-svgrepo-com.svg-54bb73635d5759933a88bbec8ed6aca8.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/pop-out-svgrepo-com.svg"
+dest_files=["res://.godot/imported/pop-out-svgrepo-com.svg-54bb73635d5759933a88bbec8ed6aca8.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/question.svg b/godot/addons/panku_console/res/icons2/question.svg
new file mode 100644
index 0000000..f6a29dd
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/question.svg
@@ -0,0 +1,15 @@
+
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/question.svg.import b/godot/addons/panku_console/res/icons2/question.svg.import
new file mode 100644
index 0000000..148ea93
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/question.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ca6btx2q3g7q8"
+path="res://.godot/imported/question.svg-b2322d216b84b418e5a3bac06c50c9e3.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/question.svg"
+dest_files=["res://.godot/imported/question.svg-b2322d216b84b418e5a3bac06c50c9e3.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/remove.svg b/godot/addons/panku_console/res/icons2/remove.svg
new file mode 100644
index 0000000..bee8c68
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/remove.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/remove.svg.import b/godot/addons/panku_console/res/icons2/remove.svg.import
new file mode 100644
index 0000000..55d2846
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/remove.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dnexm7u6lq3km"
+path="res://.godot/imported/remove.svg-76a0d91c4b08193a23093f3f0fc3dcaf.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/remove.svg"
+dest_files=["res://.godot/imported/remove.svg-76a0d91c4b08193a23093f3f0fc3dcaf.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/rename-svgrepo-com.svg b/godot/addons/panku_console/res/icons2/rename-svgrepo-com.svg
new file mode 100644
index 0000000..5e80b7a
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/rename-svgrepo-com.svg
@@ -0,0 +1,114 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/rename-svgrepo-com.svg.import b/godot/addons/panku_console/res/icons2/rename-svgrepo-com.svg.import
new file mode 100644
index 0000000..2aa845c
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/rename-svgrepo-com.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://brf6iwx4r6bdd"
+path="res://.godot/imported/rename-svgrepo-com.svg-5ec15595e7d5857527ce81e8c9082a28.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/rename-svgrepo-com.svg"
+dest_files=["res://.godot/imported/rename-svgrepo-com.svg-5ec15595e7d5857527ce81e8c9082a28.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/reply.svg b/godot/addons/panku_console/res/icons2/reply.svg
new file mode 100644
index 0000000..2f85918
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/reply.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/reply.svg.import b/godot/addons/panku_console/res/icons2/reply.svg.import
new file mode 100644
index 0000000..2286239
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/reply.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://b4jd6tqlie0wx"
+path="res://.godot/imported/reply.svg-198ceccf73b6dc82a4737a0814707430.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/reply.svg"
+dest_files=["res://.godot/imported/reply.svg-198ceccf73b6dc82a4737a0814707430.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/resize-svgrepo-com.svg b/godot/addons/panku_console/res/icons2/resize-svgrepo-com.svg
new file mode 100644
index 0000000..c9a716d
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/resize-svgrepo-com.svg
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/godot/addons/panku_console/res/icons2/resize-svgrepo-com.svg.import b/godot/addons/panku_console/res/icons2/resize-svgrepo-com.svg.import
new file mode 100644
index 0000000..1f743ea
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/resize-svgrepo-com.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ciu5jiw4xmkq0"
+path="res://.godot/imported/resize-svgrepo-com.svg-cd0763e17be8b93faf6e99fda452ac2a.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/resize-svgrepo-com.svg"
+dest_files=["res://.godot/imported/resize-svgrepo-com.svg-cd0763e17be8b93faf6e99fda452ac2a.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=true
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/search.svg b/godot/addons/panku_console/res/icons2/search.svg
new file mode 100644
index 0000000..e14d7af
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/search.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/godot/addons/panku_console/res/icons2/search.svg.import b/godot/addons/panku_console/res/icons2/search.svg.import
new file mode 100644
index 0000000..e7910b4
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/search.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://gtslyq1kvnxc"
+path="res://.godot/imported/search.svg-cbe7bc4d5cf71611ed1b364ee4407142.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/search.svg"
+dest_files=["res://.godot/imported/search.svg-cbe7bc4d5cf71611ed1b364ee4407142.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/icons2/swap_horiz.svg b/godot/addons/panku_console/res/icons2/swap_horiz.svg
new file mode 100644
index 0000000..4bf16b0
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/swap_horiz.svg
@@ -0,0 +1 @@
+
diff --git a/godot/addons/panku_console/res/icons2/swap_horiz.svg.import b/godot/addons/panku_console/res/icons2/swap_horiz.svg.import
new file mode 100644
index 0000000..c94e87b
--- /dev/null
+++ b/godot/addons/panku_console/res/icons2/swap_horiz.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bc2g8vv0x3d8y"
+path="res://.godot/imported/swap_horiz.svg-3fa7c06ee39a243e7a12b5915f37a894.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/panku_console/res/icons2/swap_horiz.svg"
+dest_files=["res://.godot/imported/swap_horiz.svg-3fa7c06ee39a243e7a12b5915f37a894.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/godot/addons/panku_console/res/panku_console_theme.tres b/godot/addons/panku_console/res/panku_console_theme.tres
new file mode 100644
index 0000000..69306e9
--- /dev/null
+++ b/godot/addons/panku_console/res/panku_console_theme.tres
@@ -0,0 +1,137 @@
+[gd_resource type="Theme" load_steps=26 format=3 uid="uid://bk18yfu0d77wk"]
+
+[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_1q17k"]
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_j0iw5"]
+bg_color = Color(0.160784, 0.160784, 0.160784, 0.12549)
+border_width_left = 1
+border_width_top = 1
+border_width_right = 1
+border_width_bottom = 1
+border_color = Color(0.8, 0.8, 0.8, 0.0627451)
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_2sv8t"]
+content_margin_left = 4.0
+content_margin_top = 2.0
+content_margin_right = 4.0
+content_margin_bottom = 2.0
+bg_color = Color(0, 0, 0, 0.12549)
+border_width_left = 1
+border_width_top = 1
+border_width_right = 1
+border_width_bottom = 1
+border_color = Color(0.8, 0.8, 0.8, 0.0627451)
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_oko07"]
+content_margin_left = 4.0
+content_margin_top = 2.0
+content_margin_right = 4.0
+content_margin_bottom = 2.0
+bg_color = Color(0.639216, 0.639216, 0.639216, 0.12549)
+border_width_left = 1
+border_width_top = 1
+border_width_right = 1
+border_width_bottom = 1
+border_color = Color(0.8, 0.8, 0.8, 0.0627451)
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_66h6h"]
+bg_color = Color(1, 1, 1, 0.4)
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_io0fu"]
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5a1x3"]
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_olfos"]
+content_margin_top = 8.0
+bg_color = Color(0.6, 0.6, 0.6, 0.12549)
+border_width_left = 1
+border_width_top = 1
+border_width_right = 1
+border_width_bottom = 1
+border_color = Color(0.8, 0.8, 0.8, 0.25098)
+expand_margin_top = 8.0
+
+[sub_resource type="ImageTexture" id="ImageTexture_p3ihr"]
+
+[sub_resource type="ImageTexture" id="ImageTexture_e0rko"]
+
+[sub_resource type="ImageTexture" id="ImageTexture_1il84"]
+
+[sub_resource type="ImageTexture" id="ImageTexture_amjqe"]
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_pc3w4"]
+bg_color = Color(1, 1, 1, 0.501961)
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_xodll"]
+bg_color = Color(1, 1, 1, 0.501961)
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_y3ihc"]
+content_margin_top = 23.0
+bg_color = Color(0, 0, 0, 0.25098)
+border_color = Color(0.6, 0.6, 0.6, 0.25098)
+
+[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_36yn6"]
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_1hrnt"]
+content_margin_left = 8.0
+bg_color = Color(0, 0, 0, 0.12549)
+border_width_left = 2
+border_color = Color(0.8, 0.8, 0.8, 0.25098)
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_xot6g"]
+content_margin_left = 4.0
+draw_center = false
+border_width_left = 2
+border_color = Color(0.8, 0.8, 0.8, 0.12549)
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_bcc4x"]
+bg_color = Color(0.317647, 0.317647, 0.317647, 0.901961)
+
+[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_nqr1r"]
+
+[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_abx0a"]
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_37w0u"]
+bg_color = Color(1, 1, 1, 0.501961)
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_mhjmb"]
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_iamty"]
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jdo31"]
+content_margin_left = 8.0
+bg_color = Color(0.6, 0.6, 0.6, 0.12549)
+border_width_left = 1
+border_width_top = 1
+border_width_right = 1
+border_width_bottom = 1
+border_color = Color(0.8, 0.8, 0.8, 0.25098)
+
+[resource]
+default_font_size = 16
+Button/styles/focus = SubResource("StyleBoxEmpty_1q17k")
+Button/styles/hover = SubResource("StyleBoxFlat_j0iw5")
+Button/styles/normal = SubResource("StyleBoxFlat_2sv8t")
+Button/styles/pressed = SubResource("StyleBoxFlat_oko07")
+HScrollBar/styles/grabber = SubResource("StyleBoxFlat_66h6h")
+HScrollBar/styles/grabber_highlight = SubResource("StyleBoxFlat_io0fu")
+HScrollBar/styles/grabber_pressed = SubResource("StyleBoxFlat_5a1x3")
+HScrollBar/styles/scroll = SubResource("StyleBoxFlat_olfos")
+HSlider/icons/grabber = SubResource("ImageTexture_p3ihr")
+HSlider/icons/grabber_disabled = SubResource("ImageTexture_e0rko")
+HSlider/icons/grabber_highlight = SubResource("ImageTexture_1il84")
+HSlider/icons/tick = SubResource("ImageTexture_amjqe")
+HSlider/styles/grabber_area = SubResource("StyleBoxFlat_pc3w4")
+HSlider/styles/grabber_area_highlight = SubResource("StyleBoxFlat_xodll")
+HSlider/styles/slider = SubResource("StyleBoxFlat_y3ihc")
+LineEdit/styles/focus = SubResource("StyleBoxEmpty_36yn6")
+LineEdit/styles/normal = SubResource("StyleBoxFlat_1hrnt")
+LineEdit/styles/read_only = SubResource("StyleBoxFlat_xot6g")
+PopupMenu/styles/panel = SubResource("StyleBoxFlat_bcc4x")
+RichTextLabel/colors/default_color = Color(1, 1, 1, 0.878431)
+RichTextLabel/styles/focus = SubResource("StyleBoxEmpty_nqr1r")
+RichTextLabel/styles/normal = SubResource("StyleBoxEmpty_abx0a")
+VScrollBar/styles/grabber = SubResource("StyleBoxFlat_37w0u")
+VScrollBar/styles/grabber_highlight = SubResource("StyleBoxFlat_mhjmb")
+VScrollBar/styles/grabber_pressed = SubResource("StyleBoxFlat_iamty")
+VScrollBar/styles/scroll = SubResource("StyleBoxFlat_jdo31")
diff --git a/godot/addons/panku_console/res/shader/mattias_crt.gdshader b/godot/addons/panku_console/res/shader/mattias_crt.gdshader
new file mode 100644
index 0000000..1251da1
--- /dev/null
+++ b/godot/addons/panku_console/res/shader/mattias_crt.gdshader
@@ -0,0 +1,63 @@
+// Source: https://www.shadertoy.com/view/Ms23DR
+// Loosely based on postprocessing shader by inigo quilez, License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
+
+shader_type canvas_item;
+
+uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest;
+
+vec2 curve(vec2 uv) {
+ uv = (uv - 0.5) * 2.0;
+ uv *= 1.1;
+ uv.x *= 1.0 + pow(abs(uv.y) / 5.0, 2.0);
+ uv.y *= 1.0 + pow(abs(uv.x) / 4.0, 2.0);
+ uv = (uv / 2.0) + 0.5;
+ uv = uv * 0.92 + 0.04;
+ return uv;
+}
+
+void fragment() {
+ vec2 fragCoord = FRAGCOORD.xy;
+ vec2 iResolution = 1.0 / SCREEN_PIXEL_SIZE;
+ float iTime = TIME;
+ vec2 q = fragCoord.xy / iResolution.xy;
+ vec2 uv = q;
+ uv = curve( uv );
+ vec3 oricol = texture( screen_texture, vec2(q.x,q.y) ).xyz;
+ vec3 col;
+ float x = sin(0.3*iTime+uv.y*21.0)*sin(0.7*iTime+uv.y*29.0)*sin(0.3+0.33*iTime+uv.y*31.0)*0.0017;
+
+ col.r = texture(screen_texture,vec2(x+uv.x+0.001,uv.y+0.001)).x+0.05;
+ col.g = texture(screen_texture,vec2(x+uv.x+0.000,uv.y-0.002)).y+0.05;
+ col.b = texture(screen_texture,vec2(x+uv.x-0.002,uv.y+0.000)).z+0.05;
+ col.r += 0.08*texture(screen_texture,0.75*vec2(x+0.025, -0.027)+vec2(uv.x+0.001,uv.y+0.001)).x;
+ col.g += 0.05*texture(screen_texture,0.75*vec2(x+-0.022, -0.02)+vec2(uv.x+0.000,uv.y-0.002)).y;
+ col.b += 0.08*texture(screen_texture,0.75*vec2(x+-0.02, -0.018)+vec2(uv.x-0.002,uv.y+0.000)).z;
+
+ col = clamp(col*0.6+0.4*col*col*1.0,0.0,1.0);
+
+ float vig = (0.0 + 1.0*16.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y));
+ col *= vec3(pow(vig,0.3));
+
+ col *= vec3(0.95,1.05,0.95);
+ col *= 2.8;
+
+ float scans = clamp( 0.35+0.35*sin(3.5*iTime+uv.y*iResolution.y*1.5), 0.0, 1.0);
+
+ float s = pow(scans,1.7);
+ col = col*vec3( 0.4+0.7*s) ;
+
+ col *= 1.0+0.01*sin(110.0*iTime);
+ if (uv.x < 0.0 || uv.x > 1.0)
+ col *= 0.0;
+ if (uv.y < 0.0 || uv.y > 1.0)
+ col *= 0.0;
+
+ col*=1.0-0.65*vec3(clamp((mod(fragCoord.x, 2.0)-1.0)*2.0,0.0,1.0));
+
+ float comp = smoothstep( 0.1, 0.9, sin(iTime) );
+
+ // Remove the next line to stop cross-fade between original and postprocess
+// col = mix( col, oricol, comp );
+
+ COLOR = vec4(col,1.0);
+}
diff --git a/godot/addons/panku_console/res/shader/mattias_crt.gdshader.uid b/godot/addons/panku_console/res/shader/mattias_crt.gdshader.uid
new file mode 100644
index 0000000..00bd283
--- /dev/null
+++ b/godot/addons/panku_console/res/shader/mattias_crt.gdshader.uid
@@ -0,0 +1 @@
+uid://b4q0v3umrhemp
diff --git a/godot/addons/panku_console/res/shader/simple_fast_blur.gdshader b/godot/addons/panku_console/res/shader/simple_fast_blur.gdshader
new file mode 100644
index 0000000..4667743
--- /dev/null
+++ b/godot/addons/panku_console/res/shader/simple_fast_blur.gdshader
@@ -0,0 +1,10 @@
+shader_type canvas_item;
+
+uniform float lod:hint_range(0.0, 5.0) = 0.0;
+uniform vec4 modulate:source_color = vec4(1.0);
+uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_linear_mipmap;
+
+void fragment() {
+ vec3 col = textureLod(screen_texture, SCREEN_UV, lod).rgb;
+ COLOR = vec4(mix(col, modulate.rgb, modulate.a), 1.0);
+}
diff --git a/godot/addons/panku_console/res/shader/simple_fast_blur.gdshader.uid b/godot/addons/panku_console/res/shader/simple_fast_blur.gdshader.uid
new file mode 100644
index 0000000..68a3854
--- /dev/null
+++ b/godot/addons/panku_console/res/shader/simple_fast_blur.gdshader.uid
@@ -0,0 +1 @@
+uid://b2ut3nil15x8o
diff --git a/godot/player.tscn b/godot/player.tscn
deleted file mode 100644
index 9a9540c..0000000
--- a/godot/player.tscn
+++ /dev/null
@@ -1,46 +0,0 @@
-[gd_scene load_steps=7 format=3 uid="uid://bx7xynpbusro6"]
-
-[ext_resource type="Texture2D" uid="uid://doyl1pfn8cean" path="res://art/playerGrey_up1.png" id="1_hqtel"]
-[ext_resource type="Texture2D" uid="uid://cxx2twmx2cov0" path="res://art/playerGrey_up2.png" id="2_sweqy"]
-[ext_resource type="Texture2D" uid="uid://y5fhjtmhqhdu" path="res://art/playerGrey_walk1.png" id="3_2hs0m"]
-[ext_resource type="Texture2D" uid="uid://cihvooq6h05er" path="res://art/playerGrey_walk2.png" id="4_1jxqw"]
-
-[sub_resource type="SpriteFrames" id="SpriteFrames_dw050"]
-animations = [{
-"frames": [{
-"duration": 1.0,
-"texture": ExtResource("1_hqtel")
-}, {
-"duration": 1.0,
-"texture": ExtResource("2_sweqy")
-}],
-"loop": true,
-"name": &"up",
-"speed": 5.0
-}, {
-"frames": [{
-"duration": 1.0,
-"texture": ExtResource("3_2hs0m")
-}, {
-"duration": 1.0,
-"texture": ExtResource("4_1jxqw")
-}],
-"loop": true,
-"name": &"walk",
-"speed": 5.0
-}]
-
-[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_b26j0"]
-radius = 27.0
-height = 68.0
-
-[node name="Player" type="Player"]
-metadata/_edit_group_ = true
-
-[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
-scale = Vector2(0.5, 0.5)
-sprite_frames = SubResource("SpriteFrames_dw050")
-animation = &"walk"
-
-[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
-shape = SubResource("CapsuleShape2D_b26j0")
diff --git a/godot/project.godot b/godot/project.godot
index 0fb1ea7..48ff521 100644
--- a/godot/project.godot
+++ b/godot/project.godot
@@ -30,7 +30,6 @@ config/icon="res://icon.svg"
[autoload]
-GLogging="*res://addons/glogging/glogging.gd"
Panku="*res://addons/panku_console/console.tscn"
[display]
@@ -39,7 +38,7 @@ window/stretch/mode="canvas_items"
[editor_plugins]
-enabled=PackedStringArray()
+enabled=PackedStringArray("res://addons/panku_console/plugin.cfg")
[godot_resource_groups]
@@ -71,3 +70,8 @@ move_down={
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null)
]
}
+toggle_console={
+"deadzone": 0.2,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":96,"key_label":0,"unicode":96,"location":0,"echo":false,"script":null)
+]
+}
diff --git a/godot/tests/test_runner.tscn b/godot/tests/test_runner.tscn
new file mode 100644
index 0000000..69b6077
--- /dev/null
+++ b/godot/tests/test_runner.tscn
@@ -0,0 +1,5 @@
+[gd_scene format=3 uid="uid://dag477ig1al1u"]
+
+[node name="GdTestRunner" type="GdTestRunner"]
+disallow_focus = true
+run_benchmarks = false
diff --git a/godot/trymap.tscn b/godot/trymap.tscn
index 4b8e9a4..df95f7a 100644
--- a/godot/trymap.tscn
+++ b/godot/trymap.tscn
@@ -18,10 +18,11 @@ background_color = Color(1, 0, 0, 1)
[node name="Node3D" type="Node3D"]
[node name="Mappy" type="Mappy" parent="."]
-map_width = 10
-map_height = 10
+map_width = 1024
+map_height = 1024
noise_magnitude = 50.0
texture_atlas = ExtResource("1_qcwru")
+transform = Transform3D(128, 0, 0, 0, 128, 0, 0, 0, 128, 0, 0, 0)
[node name="Player" type="Player" parent="."]
@@ -32,4 +33,5 @@ mesh = SubResource("QuadMesh_yr18d")
[node name="Camera3D" type="Camera3D" parent="Player"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 2.78414)
environment = SubResource("Environment_bol8x")
+projection = 1
current = true
diff --git a/rust/Cargo.lock b/rust/Cargo.lock
index badee07..bde2e0c 100644
--- a/rust/Cargo.lock
+++ b/rust/Cargo.lock
@@ -8,7 +8,7 @@ version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b"
dependencies = [
- "gimli",
+ "gimli 0.32.3",
]
[[package]]
@@ -17,6 +17,19 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
+[[package]]
+name = "ahash"
+version = "0.8.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
+dependencies = [
+ "cfg-if",
+ "getrandom",
+ "once_cell",
+ "version_check",
+ "zerocopy",
+]
+
[[package]]
name = "aho-corasick"
version = "1.1.3"
@@ -26,6 +39,24 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "allocator-api2"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
+
+[[package]]
+name = "ar"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d67af77d68a931ecd5cbd8a3b5987d63a1d1d1278f7f6a60ae33db485cdebb69"
+
+[[package]]
+name = "arrayvec"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
+
[[package]]
name = "autocfg"
version = "1.5.0"
@@ -42,16 +73,45 @@ dependencies = [
"cfg-if",
"libc",
"miniz_oxide",
- "object",
+ "object 0.37.3",
"rustc-demangle",
"windows-link",
]
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
[[package]]
name = "bitflags"
version = "2.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "bytemuck"
+version = "1.24.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4"
+dependencies = [
+ "bytemuck_derive",
+]
+
+[[package]]
+name = "bytemuck_derive"
+version = "1.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
[[package]]
name = "bytes"
@@ -59,18 +119,222 @@ version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
+[[package]]
+name = "camino"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "cargo-platform"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84982c6c0ae343635a3a4ee6dedef965513735c8b183caa7289fa6e27399ebd4"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "cargo-util-schemas"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dc1a6f7b5651af85774ae5a34b4e8be397d9cf4bc063b7e6dbd99a841837830"
+dependencies = [
+ "semver",
+ "serde",
+ "serde-untagged",
+ "serde-value",
+ "thiserror",
+ "toml",
+ "unicode-xid",
+ "url",
+]
+
+[[package]]
+name = "cargo_metadata"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cfca2aaa699835ba88faf58a06342a314a950d2b9686165e038286c30316868"
+dependencies = [
+ "camino",
+ "cargo-platform",
+ "cargo-util-schemas",
+ "semver",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
+[[package]]
+name = "cc"
+version = "1.2.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7"
+dependencies = [
+ "find-msvc-tools",
+ "jobserver",
+ "libc",
+ "shlex",
+]
+
[[package]]
name = "cfg-if"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
+[[package]]
+name = "convert_case"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
+
+[[package]]
+name = "crc32fast"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "derive_more"
+version = "0.99.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f"
+dependencies = [
+ "convert_case",
+ "proc-macro2",
+ "quote",
+ "rustc_version",
+ "syn",
+]
+
+[[package]]
+name = "displaydoc"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "either"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+
+[[package]]
+name = "elsa"
+version = "1.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9abf33c656a7256451ebb7d0082c5a471820c31269e49d807c538c252352186e"
+dependencies = [
+ "indexmap",
+ "stable_deref_trait",
+]
+
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+[[package]]
+name = "erased-serde"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "259d404d09818dec19332e31d94558aeb442fea04c817006456c24b5460bbd4b"
+dependencies = [
+ "serde",
+ "serde_core",
+ "typeid",
+]
+
+[[package]]
+name = "errno"
+version = "0.3.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "fallible-iterator"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
+
+[[package]]
+name = "find-msvc-tools"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127"
+
+[[package]]
+name = "flate2"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc5a4e564e38c699f2880d3fda590bedc2e69f3f84cd48b457bd892ce61d0aa9"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "foldhash"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "gd-rehearse"
+version = "0.2.1"
+source = "git+https://github.com/JoeyEamigh/gd-rehearse?branch=godot-4.5#1505d7b9ea0df99858a394fab7c366078eb88e2b"
+dependencies = [
+ "gd-rehearse-defs",
+ "gd-rehearse-macros",
+ "godot",
+]
+
+[[package]]
+name = "gd-rehearse-defs"
+version = "0.2.1"
+source = "git+https://github.com/JoeyEamigh/gd-rehearse?branch=godot-4.5#1505d7b9ea0df99858a394fab7c366078eb88e2b"
+dependencies = [
+ "godot",
+ "paste",
+]
+
+[[package]]
+name = "gd-rehearse-macros"
+version = "0.2.1"
+source = "git+https://github.com/JoeyEamigh/gd-rehearse?branch=godot-4.5#1505d7b9ea0df99858a394fab7c366078eb88e2b"
+dependencies = [
+ "gd-rehearse-defs",
+ "proc-macro2",
+ "quote",
+ "venial 0.5.0",
+]
+
[[package]]
name = "gdext-gen"
version = "0.1.1"
@@ -87,8 +351,30 @@ dependencies = [
[[package]]
name = "gdextension-api"
version = "0.3.0"
+source = "git+https://github.com/godot-rust/godot4-prebuilt?branch=release-v0.3#f70baca72747869aaac7781a0cf139f53a2aac19"
+
+[[package]]
+name = "getrandom"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e25d88dabe9fdb2e064cb545312178ec4025eefb62d9a3bbce1769088e2c381d"
+checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasi 0.14.7+wasi-0.2.4",
+]
+
+[[package]]
+name = "gimli"
+version = "0.31.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
+dependencies = [
+ "fallible-iterator",
+ "indexmap",
+ "stable_deref_trait",
+]
[[package]]
name = "gimli"
@@ -96,6 +382,15 @@ version = "0.32.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"
+[[package]]
+name = "glam"
+version = "0.24.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945"
+dependencies = [
+ "libm",
+]
+
[[package]]
name = "glam"
version = "0.30.8"
@@ -111,8 +406,7 @@ checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
[[package]]
name = "godot"
version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90b20e19a25e45460c4fd2b11b519beea3e9bcda929c1566f8d17a369b41dd82"
+source = "git+https://github.com/JoeyEamigh/gdext#a31ea94b3cd8e2871edd2b87841410258f27797e"
dependencies = [
"godot-core",
"godot-macros",
@@ -121,8 +415,7 @@ dependencies = [
[[package]]
name = "godot-bindings"
version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "508d56d01018c16b67a906bda8bcd9ade7f265990e4be7c2dffecbfdebcc3992"
+source = "git+https://github.com/JoeyEamigh/gdext#a31ea94b3cd8e2871edd2b87841410258f27797e"
dependencies = [
"gdextension-api",
]
@@ -130,14 +423,12 @@ dependencies = [
[[package]]
name = "godot-cell"
version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1794fbec9934ef375d717d02ec142d9e0c7d7482b24d7da463264b92bc14eaf"
+source = "git+https://github.com/JoeyEamigh/gdext#a31ea94b3cd8e2871edd2b87841410258f27797e"
[[package]]
name = "godot-codegen"
version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "791e05ae1859028c3a910aaed83e4910ab7701ce32fa663d2dc7cd957287cdf5"
+source = "git+https://github.com/JoeyEamigh/gdext#a31ea94b3cd8e2871edd2b87841410258f27797e"
dependencies = [
"godot-bindings",
"heck",
@@ -150,10 +441,9 @@ dependencies = [
[[package]]
name = "godot-core"
version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b1717ffba78bd2655c9ee1073752ac90d969b8a614800c469f00fc3ddc02439"
+source = "git+https://github.com/JoeyEamigh/gdext#a31ea94b3cd8e2871edd2b87841410258f27797e"
dependencies = [
- "glam",
+ "glam 0.30.8",
"godot-bindings",
"godot-cell",
"godot-codegen",
@@ -163,8 +453,7 @@ dependencies = [
[[package]]
name = "godot-ffi"
version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "419e46ba92fba076da67f35ad96faaa830c1de4e8175db2bb4251aeb58b14b08"
+source = "git+https://github.com/JoeyEamigh/gdext#a31ea94b3cd8e2871edd2b87841410258f27797e"
dependencies = [
"godot-bindings",
"godot-codegen",
@@ -175,24 +464,37 @@ dependencies = [
[[package]]
name = "godot-macros"
version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a464e26854e63825d36655759c24556c970a8777535466ebf4ecc7f8e87a4638"
+source = "git+https://github.com/JoeyEamigh/gdext#a31ea94b3cd8e2871edd2b87841410258f27797e"
dependencies = [
"godot-bindings",
"proc-macro2",
"quote",
- "venial",
+ "venial 0.6.1",
]
[[package]]
name = "godottest_rs"
version = "0.1.0"
dependencies = [
+ "bytemuck",
+ "gd-rehearse",
"gdext-gen",
"godot",
+ "spirv-builder",
"tokio",
]
+[[package]]
+name = "hashbrown"
+version = "0.15.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
+dependencies = [
+ "allocator-api2",
+ "equivalent",
+ "foldhash",
+]
+
[[package]]
name = "hashbrown"
version = "0.16.0"
@@ -205,6 +507,113 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+[[package]]
+name = "icu_collections"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"
+dependencies = [
+ "displaydoc",
+ "potential_utf",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locale_core"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
+dependencies = [
+ "displaydoc",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_normalizer_data",
+ "icu_properties",
+ "icu_provider",
+ "smallvec",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer_data"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3"
+
+[[package]]
+name = "icu_properties"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_locale_core",
+ "icu_properties_data",
+ "icu_provider",
+ "potential_utf",
+ "zerotrie",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_properties_data"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632"
+
+[[package]]
+name = "icu_provider"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af"
+dependencies = [
+ "displaydoc",
+ "icu_locale_core",
+ "stable_deref_trait",
+ "tinystr",
+ "writeable",
+ "yoke",
+ "zerofrom",
+ "zerotrie",
+ "zerovec",
+]
+
+[[package]]
+name = "idna"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
+dependencies = [
+ "idna_adapter",
+ "smallvec",
+ "utf8_iter",
+]
+
+[[package]]
+name = "idna_adapter"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
+dependencies = [
+ "icu_normalizer",
+ "icu_properties",
+]
+
[[package]]
name = "indexmap"
version = "2.11.4"
@@ -212,26 +621,90 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
dependencies = [
"equivalent",
- "hashbrown",
+ "hashbrown 0.16.0",
]
+[[package]]
+name = "internal-iterator"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "969ee3fc68ec2e88eb21434ce4d9b7e1600d1ce92ff974560a6c4a304f5124b9"
+
[[package]]
name = "io-uring"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b"
dependencies = [
- "bitflags",
+ "bitflags 2.9.4",
"cfg-if",
"libc",
]
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itertools"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
+
+[[package]]
+name = "jobserver"
+version = "0.1.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
+dependencies = [
+ "getrandom",
+ "libc",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
[[package]]
name = "libc"
version = "0.2.177"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
+[[package]]
+name = "libm"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
+
+[[package]]
+name = "litemap"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
+
[[package]]
name = "lock_api"
version = "0.4.13"
@@ -242,6 +715,27 @@ dependencies = [
"scopeguard",
]
+[[package]]
+name = "log"
+version = "0.4.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
+
+[[package]]
+name = "longest-increasing-subsequence"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86"
+
+[[package]]
+name = "matchers"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
+dependencies = [
+ "regex-automata",
+]
+
[[package]]
name = "memchr"
version = "2.7.6"
@@ -255,6 +749,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
dependencies = [
"adler2",
+ "simd-adler32",
]
[[package]]
@@ -264,7 +759,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
dependencies = [
"libc",
- "wasi",
+ "wasi 0.11.1+wasi-snapshot-preview1",
"windows-sys",
]
@@ -283,13 +778,74 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a846cbc04412cf509efcd8f3694b114fc700a035fb5a37f21517f9fb019f1ebc"
+[[package]]
+name = "noisemap"
+version = "0.1.0"
+dependencies = [
+ "glam 0.24.2",
+ "libm",
+ "spirv-std",
+]
+
+[[package]]
+name = "nu-ansi-term"
+version = "0.50.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+ "libm",
+]
+
+[[package]]
+name = "object"
+version = "0.36.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
+dependencies = [
+ "crc32fast",
+ "flate2",
+ "hashbrown 0.15.5",
+ "indexmap",
+ "memchr",
+ "ruzstd",
+]
+
[[package]]
name = "object"
version = "0.37.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
dependencies = [
+ "crc32fast",
+ "hashbrown 0.15.5",
+ "indexmap",
"memchr",
+ "wasmparser",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
+[[package]]
+name = "ordered-float"
+version = "2.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
+dependencies = [
+ "num-traits",
]
[[package]]
@@ -315,12 +871,33 @@ dependencies = [
"windows-targets",
]
+[[package]]
+name = "paste"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
+
[[package]]
name = "pin-project-lite"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
+[[package]]
+name = "potential_utf"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a"
+dependencies = [
+ "zerovec",
+]
+
[[package]]
name = "proc-macro2"
version = "1.0.101"
@@ -339,13 +916,25 @@ dependencies = [
"proc-macro2",
]
+[[package]]
+name = "r-efi"
+version = "5.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+
+[[package]]
+name = "raw-string"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0501e134c6905fee1f10fed25b0a7e1261bf676cffac9543a7d0730dec01af2"
+
[[package]]
name = "redox_syscall"
version = "0.5.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
dependencies = [
- "bitflags",
+ "bitflags 2.9.4",
]
[[package]]
@@ -377,18 +966,138 @@ version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
+[[package]]
+name = "rspirv"
+version = "0.12.0+sdk-1.3.268.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cf3a93856b6e5946537278df0d3075596371b1950ccff012f02b0f7eafec8d"
+dependencies = [
+ "rustc-hash",
+ "spirv",
+]
+
[[package]]
name = "rustc-demangle"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "rustc_codegen_spirv"
+version = "0.9.0"
+source = "git+https://github.com/Rust-GPU/rust-gpu?rev=56cc13214566af452de71daf39f7b3f2c65551c2#56cc13214566af452de71daf39f7b3f2c65551c2"
+dependencies = [
+ "ahash",
+ "ar",
+ "bytemuck",
+ "either",
+ "indexmap",
+ "itertools 0.14.0",
+ "lazy_static",
+ "libc",
+ "log",
+ "object 0.37.3",
+ "regex",
+ "rspirv",
+ "rustc-demangle",
+ "rustc_codegen_spirv-target-specs",
+ "rustc_codegen_spirv-types",
+ "rustix",
+ "sanitize-filename",
+ "smallvec",
+ "spirt",
+ "spirv-std-types",
+ "spirv-tools",
+ "thorin-dwp",
+ "tracing",
+ "tracing-subscriber",
+ "tracing-tree",
+]
+
+[[package]]
+name = "rustc_codegen_spirv-target-specs"
+version = "0.9.0"
+source = "git+https://github.com/Rust-GPU/rust-gpu?rev=56cc13214566af452de71daf39f7b3f2c65551c2#56cc13214566af452de71daf39f7b3f2c65551c2"
+
+[[package]]
+name = "rustc_codegen_spirv-types"
+version = "0.9.0"
+source = "git+https://github.com/Rust-GPU/rust-gpu?rev=56cc13214566af452de71daf39f7b3f2c65551c2#56cc13214566af452de71daf39f7b3f2c65551c2"
+dependencies = [
+ "rspirv",
+ "serde",
+ "serde_json",
+ "spirv",
+]
+
+[[package]]
+name = "rustc_version"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "rustix"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
+dependencies = [
+ "bitflags 2.9.4",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
+name = "ruzstd"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fad02996bfc73da3e301efe90b1837be9ed8f4a462b6ed410aa35d00381de89f"
+dependencies = [
+ "twox-hash",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
+
+[[package]]
+name = "sanitize-filename"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc984f4f9ceb736a7bb755c3e3bd17dc56370af2600c9780dcc48c66453da34d"
+dependencies = [
+ "regex",
+]
+
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+[[package]]
+name = "semver"
+version = "1.0.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
[[package]]
name = "serde"
version = "1.0.228"
@@ -399,6 +1108,28 @@ dependencies = [
"serde_derive",
]
+[[package]]
+name = "serde-untagged"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058"
+dependencies = [
+ "erased-serde",
+ "serde",
+ "serde_core",
+ "typeid",
+]
+
+[[package]]
+name = "serde-value"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
+dependencies = [
+ "ordered-float",
+ "serde",
+]
+
[[package]]
name = "serde_core"
version = "1.0.228"
@@ -419,6 +1150,19 @@ dependencies = [
"syn",
]
+[[package]]
+name = "serde_json"
+version = "1.0.145"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
+dependencies = [
+ "itoa",
+ "memchr",
+ "ryu",
+ "serde",
+ "serde_core",
+]
+
[[package]]
name = "serde_spanned"
version = "0.6.9"
@@ -428,6 +1172,21 @@ dependencies = [
"serde",
]
+[[package]]
+name = "sharded-slab"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
[[package]]
name = "signal-hook-registry"
version = "1.4.6"
@@ -437,6 +1196,12 @@ dependencies = [
"libc",
]
+[[package]]
+name = "simd-adler32"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
+
[[package]]
name = "slab"
version = "0.4.11"
@@ -448,6 +1213,9 @@ name = "smallvec"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+dependencies = [
+ "serde",
+]
[[package]]
name = "socket2"
@@ -459,6 +1227,114 @@ dependencies = [
"windows-sys",
]
+[[package]]
+name = "spirt"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2d5968bd2a36466468aac637b355776f080edfb0c6f769b2b99b9708260c42a"
+dependencies = [
+ "arrayvec",
+ "bytemuck",
+ "derive_more",
+ "elsa",
+ "indexmap",
+ "internal-iterator",
+ "itertools 0.10.5",
+ "lazy_static",
+ "longest-increasing-subsequence",
+ "rustc-hash",
+ "serde",
+ "serde_json",
+ "smallvec",
+]
+
+[[package]]
+name = "spirv"
+version = "0.3.0+sdk-1.3.268.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844"
+dependencies = [
+ "bitflags 2.9.4",
+ "serde",
+]
+
+[[package]]
+name = "spirv-builder"
+version = "0.9.0"
+source = "git+https://github.com/Rust-GPU/rust-gpu?rev=56cc13214566af452de71daf39f7b3f2c65551c2#56cc13214566af452de71daf39f7b3f2c65551c2"
+dependencies = [
+ "cargo_metadata",
+ "log",
+ "memchr",
+ "raw-string",
+ "rustc_codegen_spirv",
+ "rustc_codegen_spirv-target-specs",
+ "rustc_codegen_spirv-types",
+ "semver",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
+[[package]]
+name = "spirv-std"
+version = "0.9.0"
+source = "git+https://github.com/Rust-GPU/rust-gpu?rev=56cc13214566af452de71daf39f7b3f2c65551c2#56cc13214566af452de71daf39f7b3f2c65551c2"
+dependencies = [
+ "bitflags 1.3.2",
+ "glam 0.24.2",
+ "libm",
+ "num-traits",
+ "spirv-std-macros",
+ "spirv-std-types",
+]
+
+[[package]]
+name = "spirv-std-macros"
+version = "0.9.0"
+source = "git+https://github.com/Rust-GPU/rust-gpu?rev=56cc13214566af452de71daf39f7b3f2c65551c2#56cc13214566af452de71daf39f7b3f2c65551c2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "spirv-std-types",
+ "syn",
+]
+
+[[package]]
+name = "spirv-std-types"
+version = "0.9.0"
+source = "git+https://github.com/Rust-GPU/rust-gpu?rev=56cc13214566af452de71daf39f7b3f2c65551c2#56cc13214566af452de71daf39f7b3f2c65551c2"
+
+[[package]]
+name = "spirv-tools"
+version = "0.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b10991c25e3adc32c018c528be2cdef16c0cdfaf8581fbeabb033b547a599ec"
+dependencies = [
+ "spirv-tools-sys",
+]
+
+[[package]]
+name = "spirv-tools-sys"
+version = "0.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c78c1a8af381edef1b7ca7d7caea9d6454dccb4b00a35b7b968b44b8212f487"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
[[package]]
name = "syn"
version = "2.0.104"
@@ -470,6 +1346,76 @@ dependencies = [
"unicode-ident",
]
+[[package]]
+name = "synstructure"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "thiserror"
+version = "2.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "thorin-dwp"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e9c1e705f82a260173f3eec93f2ff6d7807f23ad5a8cc2e7316a891733ea7a1"
+dependencies = [
+ "gimli 0.31.1",
+ "hashbrown 0.15.5",
+ "object 0.36.7",
+ "tracing",
+]
+
+[[package]]
+name = "thread_local"
+version = "1.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "tilemap"
+version = "0.1.0"
+dependencies = [
+ "glam 0.24.2",
+ "spirv-std",
+]
+
+[[package]]
+name = "tinystr"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
+dependencies = [
+ "displaydoc",
+ "zerovec",
+]
+
[[package]]
name = "tokio"
version = "1.47.1"
@@ -543,12 +1489,154 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
+[[package]]
+name = "tracing"
+version = "0.1.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
+dependencies = [
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
+dependencies = [
+ "once_cell",
+ "valuable",
+]
+
+[[package]]
+name = "tracing-log"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
+dependencies = [
+ "log",
+ "once_cell",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-serde"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1"
+dependencies = [
+ "serde",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-subscriber"
+version = "0.3.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5"
+dependencies = [
+ "matchers",
+ "nu-ansi-term",
+ "once_cell",
+ "regex-automata",
+ "serde",
+ "serde_json",
+ "sharded-slab",
+ "smallvec",
+ "thread_local",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
+ "tracing-serde",
+]
+
+[[package]]
+name = "tracing-tree"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac87aa03b6a4d5a7e4810d1a80c19601dbe0f8a837e9177f23af721c7ba7beec"
+dependencies = [
+ "nu-ansi-term",
+ "tracing-core",
+ "tracing-log",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "twox-hash"
+version = "1.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
+dependencies = [
+ "cfg-if",
+ "static_assertions",
+]
+
+[[package]]
+name = "typeid"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
+
[[package]]
name = "unicode-ident"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
+[[package]]
+name = "unicode-xid"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
+
+[[package]]
+name = "url"
+version = "2.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+ "serde",
+]
+
+[[package]]
+name = "utf8_iter"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+
+[[package]]
+name = "valuable"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
+
+[[package]]
+name = "venial"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61584a325b16f97b5b25fcc852eb9550843a251057a5e3e5992d2376f3df4bb2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+]
+
[[package]]
name = "venial"
version = "0.6.1"
@@ -559,12 +1647,45 @@ dependencies = [
"quote",
]
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+[[package]]
+name = "wasi"
+version = "0.14.7+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c"
+dependencies = [
+ "wasip2",
+]
+
+[[package]]
+name = "wasip2"
+version = "1.0.1+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
+dependencies = [
+ "wit-bindgen",
+]
+
+[[package]]
+name = "wasmparser"
+version = "0.236.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9b1e81f3eb254cf7404a82cee6926a4a3ccc5aad80cc3d43608a070c67aa1d7"
+dependencies = [
+ "bitflags 2.9.4",
+]
+
[[package]]
name = "windows-link"
version = "0.2.1"
@@ -652,3 +1773,113 @@ checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
dependencies = [
"memchr",
]
+
+[[package]]
+name = "wit-bindgen"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
+
+[[package]]
+name = "writeable"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
+
+[[package]]
+name = "yoke"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc"
+dependencies = [
+ "serde",
+ "stable_deref_trait",
+ "yoke-derive",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.8.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
+dependencies = [
+ "zerofrom-derive",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zerotrie"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"
+dependencies = [
+ "displaydoc",
+ "yoke",
+ "zerofrom",
+]
+
+[[package]]
+name = "zerovec"
+version = "0.11.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b"
+dependencies = [
+ "yoke",
+ "zerofrom",
+ "zerovec-derive",
+]
+
+[[package]]
+name = "zerovec-derive"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/rust/Cargo.toml b/rust/Cargo.toml
index 97e0523..187cb9c 100644
--- a/rust/Cargo.toml
+++ b/rust/Cargo.toml
@@ -3,12 +3,26 @@ name = "godottest_rs"
version = "0.1.0"
edition = "2024"
+[workspace]
+resolver = "3"
+members = ["shaders/*"]
+
[lib]
crate-type = ["cdylib"]
+[features]
+default = ["gd_rehearse_tests"]
+gd_rehearse_tests = ["gd-rehearse"]
+
[dependencies]
-godot = { version = "0.4.0", features = ["api-4-5"] }
+godot = { git = "https://github.com/JoeyEamigh/gdext", features = ["api-4-5"] }
tokio = { version = "1.47.1", features = ["full"] }
+bytemuck = { version = "1.14", features = ["derive"] }
+gd-rehearse = { git = "https://github.com/JoeyEamigh/gd-rehearse", branch = "godot-4.5", optional = true }
[build-dependencies]
gdext-gen = { version = "0.1.1", features = ["dependencies", "find_icons"] }
+spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "56cc13214566af452de71daf39f7b3f2c65551c2", package = "spirv-builder" }
+
+[patch.crates-io]
+godot = { git = "https://github.com/JoeyEamigh/gdext", features = ["api-4-5"] }
diff --git a/rust/build.rs b/rust/build.rs
index 99ebad5..678d6b5 100644
--- a/rust/build.rs
+++ b/rust/build.rs
@@ -1,18 +1,26 @@
use gdext_gen::prelude::*;
-use std::io::Result;
+use spirv_builder::{MetadataPrintout, SpirvBuilder};
+
+fn main() -> Result<(), Box> {
+ SpirvBuilder::new("./shaders/tilemap", "spirv-unknown-spv1.6")
+ .print_metadata(MetadataPrintout::Full)
+ .build()?;
+
+ SpirvBuilder::new("./shaders/noisemap", "spirv-unknown-spv1.6")
+ .print_metadata(MetadataPrintout::Full)
+ .build()?;
-fn main() -> Result<()> {
// All your variable initialization and setup goes here.
generate_gdextension_file(
BaseDirectory::ProjectFolder,
Some("../rust/target".into()),
- Some("../godot/Rust.gdextension".into()),
+ Some("../godot/rust.gdextension".into()),
true,
Some(Configuration::new(
EntrySymbol::GodotRustDefault,
Some((4, 1)),
None,
- false,
+ true,
false,
)),
Some(WindowsABI::MSVC),
diff --git a/rust/rust-toolchain.toml b/rust/rust-toolchain.toml
new file mode 100644
index 0000000..1e4ccc6
--- /dev/null
+++ b/rust/rust-toolchain.toml
@@ -0,0 +1,13 @@
+[toolchain]
+channel = "nightly-2025-06-30"
+components = [
+ "rustc",
+ "cargo",
+ "rustfmt",
+ "clippy",
+ "rust-std",
+ "rust-analyzer",
+ "rust-src",
+ "llvm-tools",
+ "rustc-dev",
+]
diff --git a/rust/shaders/noisemap/Cargo.toml b/rust/shaders/noisemap/Cargo.toml
new file mode 100644
index 0000000..dcb0f6b
--- /dev/null
+++ b/rust/shaders/noisemap/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "noisemap"
+version = "0.1.0"
+edition = "2024"
+
+[lib]
+crate-type = ["dylib"]
+
+[dependencies]
+glam = { version = ">=0.22, <=0.30.7", default-features = false, features = [
+ "libm",
+] }
+spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "56cc13214566af452de71daf39f7b3f2c65551c2", package = "spirv-std" }
+libm = { version = "0.2", default-features = false }
diff --git a/rust/shaders/noisemap/src/lib.rs b/rust/shaders/noisemap/src/lib.rs
new file mode 100644
index 0000000..3dcdd94
--- /dev/null
+++ b/rust/shaders/noisemap/src/lib.rs
@@ -0,0 +1,111 @@
+#![no_std]
+// HACK(eddyb) can't easily see warnings otherwise from `spirv-builder` builds.
+#![deny(warnings)]
+#![allow(unexpected_cfgs)]
+
+use libm::{fabsf, floorf};
+use spirv_std::{RuntimeArray, glam::UVec3, spirv};
+
+#[repr(C)]
+pub struct NoiseParams {
+ pub map_width: u32,
+ pub map_height: u32,
+ pub seed: u32,
+ pub _pad0: u32,
+ pub noise_scale: f32,
+ pub noise_magnitude: f32,
+ pub _pad1: f32,
+ pub _pad2: f32,
+}
+
+#[inline(always)]
+fn fade(t: f32) -> f32 {
+ t * t * t * (t * (t * 6.0 - 15.0) + 10.0)
+}
+
+#[inline(always)]
+fn lerp(a: f32, b: f32, t: f32) -> f32 {
+ a + (b - a) * t
+}
+
+#[inline(always)]
+fn hash(seed: u32, x: i32, y: i32) -> u32 {
+ let mut v = seed ^ (x as u32).wrapping_mul(0x27d4_eb2d);
+ v = v.wrapping_add((y as u32).wrapping_mul(0x1656_67b1));
+ v ^= v >> 15;
+ v = v.wrapping_mul(0x85eb_ca6b);
+ v ^= v >> 13;
+ v = v.wrapping_mul(0xc2b2_ae35);
+ v ^ (v >> 16)
+}
+
+#[inline(always)]
+fn grad(hash: u32, x: f32, y: f32) -> f32 {
+ let h = (hash & 0x7) as i32;
+ let u = if h < 4 { x } else { y };
+ let v = if h < 4 { y } else { x };
+ let mut result = if (h & 1) == 0 { u } else { -u };
+ result += if (h & 2) == 0 { v } else { -v };
+ result
+}
+
+#[inline(always)]
+fn clampf(value: f32, min: f32, max: f32) -> f32 {
+ if value < min {
+ min
+ } else if value > max {
+ max
+ } else {
+ value
+ }
+}
+
+#[spirv(compute(threads(16, 16, 1)))]
+pub fn main(
+ #[spirv(global_invocation_id)] id: UVec3,
+ #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] params: &NoiseParams,
+ #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] output_map: &mut RuntimeArray,
+) {
+ let x = id.x;
+ let y = id.y;
+
+ if x >= params.map_width || y >= params.map_height {
+ return;
+ }
+
+ let width = params.map_width;
+ let index = (y * width + x) as usize;
+
+ let scale = if params.noise_scale.abs() < 0.0001 {
+ 1.0
+ } else {
+ params.noise_scale
+ };
+ let sample_x = (x as f32 + 0.5) * scale;
+ let sample_y = (y as f32 + 0.5) * scale;
+
+ let ix = floorf(sample_x) as i32;
+ let iy = floorf(sample_y) as i32;
+ let fx = clampf(sample_x - ix as f32, 0.0, 1.0);
+ let fy = clampf(sample_y - iy as f32, 0.0, 1.0);
+
+ let wx = fade(fx);
+ let wy = fade(fy);
+
+ let v00 = grad(hash(params.seed, ix, iy), fx, fy);
+ let v10 = grad(hash(params.seed, ix + 1, iy), fx - 1.0, fy);
+ let v01 = grad(hash(params.seed, ix, iy + 1), fx, fy - 1.0);
+ let v11 = grad(hash(params.seed, ix + 1, iy + 1), fx - 1.0, fy - 1.0);
+
+ let nx0 = lerp(v00, v10, wx);
+ let nx1 = lerp(v01, v11, wx);
+ let value = clampf(lerp(nx0, nx1, wy) * 0.707_106_77, -1.0, 1.0);
+
+ let magnitude = fabsf(params.noise_magnitude);
+ let noise = fabsf(value) * magnitude;
+ let clamped = clampf(noise, 0.0, 2_147_483_647.0);
+
+ unsafe {
+ *output_map.index_mut(index) = floorf(clamped) as u32;
+ }
+}
diff --git a/rust/shaders/tilemap/Cargo.toml b/rust/shaders/tilemap/Cargo.toml
new file mode 100644
index 0000000..612f9ab
--- /dev/null
+++ b/rust/shaders/tilemap/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "tilemap"
+version = "0.1.0"
+edition = "2024"
+
+[lib]
+crate-type = ["dylib"]
+
+[dependencies]
+glam = { version = ">=0.22, <=0.30.7", default-features = false }
+spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "56cc13214566af452de71daf39f7b3f2c65551c2", package = "spirv-std" }
diff --git a/rust/shaders/tilemap/src/lib.rs b/rust/shaders/tilemap/src/lib.rs
new file mode 100644
index 0000000..3d24c7a
--- /dev/null
+++ b/rust/shaders/tilemap/src/lib.rs
@@ -0,0 +1,89 @@
+#![no_std]
+// HACK(eddyb) can't easily see warnings otherwise from `spirv-builder` builds.
+#![deny(warnings)]
+#![allow(unexpected_cfgs)]
+
+use spirv_std::{RuntimeArray, glam::UVec3, spirv};
+
+#[repr(C)]
+pub struct TilemapParams {
+ pub out_width: u32,
+ pub out_height: u32,
+ pub tile_size: u32,
+ pub map_width: u32,
+ pub map_height: u32,
+ pub atlas_width: u32,
+ pub atlas_height: u32,
+}
+
+// 8x8 workgroup covers 64 pixels per dispatch group
+#[spirv(compute(threads(8, 8, 1)))]
+pub fn main(
+ #[spirv(global_invocation_id)] id: UVec3,
+ #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] params: &TilemapParams,
+ #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] map: &RuntimeArray,
+ #[spirv(storage_buffer, descriptor_set = 0, binding = 2)] atlas_rgba: &RuntimeArray,
+ #[spirv(storage_buffer, descriptor_set = 0, binding = 3)] output_rgba: &mut RuntimeArray,
+) {
+ let x = id.x;
+ let y = id.y;
+
+ if params.tile_size == 0 || x >= params.out_width || y >= params.out_height {
+ return;
+ }
+
+ let tile_size = params.tile_size;
+ let tile_x = x / tile_size;
+ let tile_y = y / tile_size;
+
+ if tile_x >= params.map_width || tile_y >= params.map_height {
+ return;
+ }
+
+ if params.atlas_width < tile_size {
+ return;
+ }
+
+ let atlas_tiles_per_row = params.atlas_width / tile_size;
+ if atlas_tiles_per_row == 0 {
+ return;
+ }
+
+ let map_index = tile_y * params.map_width + tile_x;
+ let map_capacity = params.map_width * params.map_height;
+ if map_index >= map_capacity {
+ return;
+ }
+
+ let tile_index = unsafe { *map.index(map_index as usize) };
+
+ let atlas_tile_x = tile_index % atlas_tiles_per_row;
+ let atlas_tile_y = tile_index / atlas_tiles_per_row;
+
+ let local_x = x % tile_size;
+ let local_y = y % tile_size;
+
+ let atlas_x = atlas_tile_x * tile_size + local_x;
+ let atlas_y = atlas_tile_y * tile_size + local_y;
+
+ if atlas_x >= params.atlas_width || atlas_y >= params.atlas_height {
+ return;
+ }
+
+ let atlas_width = params.atlas_width;
+ let dst_width = params.out_width;
+
+ let src_index = atlas_y * atlas_width + atlas_x;
+ let dst_index = y * dst_width + x;
+ let atlas_capacity = atlas_width * params.atlas_height;
+ let dst_capacity = params.out_width * params.out_height;
+
+ if src_index >= atlas_capacity || dst_index >= dst_capacity {
+ return;
+ }
+
+ let pixel = unsafe { *atlas_rgba.index(src_index as usize) };
+ unsafe {
+ *output_rgba.index_mut(dst_index as usize) = pixel;
+ }
+}
diff --git a/rust/src/Mappy.rs b/rust/src/Mappy.rs
deleted file mode 100644
index 2d9b327..0000000
--- a/rust/src/Mappy.rs
+++ /dev/null
@@ -1,194 +0,0 @@
-use std::time::{SystemTime, UNIX_EPOCH};
-
-use godot::classes::base_material_3d::{ShadingMode, TextureParam};
-use godot::classes::image::Format;
-use godot::classes::mesh::ArrayType;
-use godot::classes::{
- BaseMaterial3D, Camera3D, CompressedTexture2D, FastNoiseLite, IMeshInstance3D, Image, ImageTexture, Input,
- MeshInstance3D, QuadMesh, StandardMaterial3D, Texture2D,
-};
-use godot::global::Key;
-use godot::meta::ByOption;
-use godot::prelude::*;
-
-#[derive(GodotClass)]
-#[class(base=MeshInstance3D)]
-struct Mappy {
- #[export]
- map_width: i32,
- #[export]
- map_height: i32,
- #[export]
- noise_scale: f32,
- #[export]
- noise_magnitude: f32,
- #[export]
- texture_atlas: OnEditor>,
-
- map: Array,
-
- is_generated: bool,
-
- // required
- base: Base,
-}
-
-#[godot_api]
-impl IMeshInstance3D for Mappy {
- fn init(base: Base) -> Self {
- let mut standard_array: Array = Array::new();
- let width: i32 = 32;
- let height: i32 = 32;
- standard_array.resize((width * height) as usize, 0);
-
- Self {
- map_width: width,
- map_height: height,
- noise_scale: 1.0,
- noise_magnitude: 5.0,
- texture_atlas: OnEditor::default(),
- map: standard_array,
- is_generated: false,
- base,
- }
- }
-
- fn ready(&mut self) {
- self.is_generated = false;
- self.generateMap();
- self.createTexture();
- }
-
- fn process(&mut self, delta: f32) {
- let input = Input::singleton();
- if (input.is_action_just_pressed("ui_accept")) {
- self.generateMap();
- self.createTexture();
- }
- }
-}
-
-impl Mappy {
- fn generateMap(&mut self) {
- let mut new_map: Array = Array::new();
-
- let mut noise = FastNoiseLite::new_gd();
- let now = SystemTime::now();
- let duration_since_epoch = now.duration_since(UNIX_EPOCH).expect("Time went backwards"); // Handle potential errors if the system clock is adjusted
-
- let milliseconds = duration_since_epoch.as_millis();
- noise.set_seed(milliseconds as i32);
- new_map.resize((self.map_width * self.map_height) as usize, 0);
- for x in 0..self.map_width {
- for y in 0..self.map_height {
- new_map.set(
- (x + y * self.map_height) as usize,
- (noise.get_noise_2d(x as f32 * self.noise_scale, y as f32 * self.noise_scale) * self.noise_magnitude).abs()
- as i32,
- );
- }
- }
- self.map = new_map;
- }
-
- fn createTexture(&mut self) {
- if (self.is_generated) {
- let old_node = self.base().get_node_as::("Map Quad");
- self.base_mut().remove_child(&old_node);
- old_node.free();
- }
-
- self.is_generated = true;
- let mut quad = QuadMesh::new_gd();
- quad.set_size(Vector2::new(1.0, 1.0));
- let mut mat = StandardMaterial3D::new_gd();
- mat.set_shading_mode(ShadingMode::UNSHADED);
-
- let use_mipmaps = false;
- let format = Format::RGBA8; // Or another desired format
-
- let mut image = Image::create(self.map_width * 16, self.map_height * 16, use_mipmaps, format)
- .expect("Couldn't create texture for map");
- let atlas = self.texture_atlas.get_image();
-
- // Example: Fill the image with a solid color
- for i in 0..self.map_width {
- for j in 0..self.map_height {
- let map_index = self.map.at((i + j * self.map_width) as usize);
- image.blit_rect(
- atlas.as_ref(),
- Rect2i::new(
- Vector2i::new(map_index % 16 * 16, (map_index / 16) * 16),
- Vector2i::new(16, 16),
- ),
- Vector2i::new(i * 16, j * 16),
- );
- }
- }
-
- let mut tex = ImageTexture::new_gd();
- tex.set_image(&image);
-
- mat.set_texture(TextureParam::ALBEDO, &tex);
- quad.set_material(&mat);
-
- let mut mesh = MeshInstance3D::new_alloc();
- mesh.set_name("Map Quad");
- mesh.set_mesh(&quad);
- self.base_mut().add_child(&mesh);
- }
-}
-
-#[derive(GodotClass)]
-#[class(base=Node3D)]
-struct Player {
- #[export]
- character_name: GString,
- #[export]
- velocity: Vector3,
- #[export]
- acceleration: Vector3,
- base: Base,
-}
-
-#[godot_api]
-impl INode3D for Player {
- fn init(base: Base) -> Self {
- Self {
- character_name: GString::from("Hello"),
- velocity: Vector3::ZERO,
- acceleration: Vector3::new(1.0, 1.0, 0.0),
- base,
- }
- }
-
- fn process(&mut self, delta: f32) {
- self.processInput(delta);
- self.updatePosition(delta);
- }
-}
-
-impl Player {
- fn processInput(&mut self, delta: f32) {
- let input = Input::singleton();
- if (input.is_key_pressed(Key::W)) {
- self.velocity.y += self.acceleration.y;
- }
- if (input.is_key_pressed(Key::A)) {
- self.velocity.x -= self.acceleration.x;
- }
- if (input.is_key_pressed(Key::S)) {
- self.velocity.y -= self.acceleration.y;
- }
- if (input.is_key_pressed(Key::D)) {
- self.velocity.x += self.acceleration.x;
- }
- }
-
- fn updatePosition(&mut self, delta: f32) {
- let before_move = self.base_mut().get_transform();
- let after_move = before_move.translated(self.velocity * delta);
- self.base_mut().set_transform(after_move);
- self.velocity *= 0.5;
- }
-}
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index e325b3e..fc6de84 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -3,6 +3,7 @@ use godot::{classes::Engine, prelude::*};
mod runtime;
mod Mappy;
+mod player;
struct MyExtension;
diff --git a/rust/src/mappy.rs b/rust/src/mappy.rs
new file mode 100644
index 0000000..69dcfce
--- /dev/null
+++ b/rust/src/mappy.rs
@@ -0,0 +1,1133 @@
+use std::time::{Instant, SystemTime, UNIX_EPOCH};
+
+use bytemuck::{Pod, Zeroable, bytes_of, cast_slice};
+use godot::builtin::PackedByteArray;
+use godot::classes::base_material_3d::{ShadingMode, TextureParam};
+use godot::classes::image::Format;
+use godot::classes::rendering_device::{BufferCreationBits, ShaderStage, UniformType};
+use godot::classes::{
+ CompressedTexture2D, FastNoiseLite, IMeshInstance3D, Image, ImageTexture, Input, MeshInstance3D, QuadMesh,
+ RdShaderSpirv, RdUniform, RenderingDevice, RenderingServer, StandardMaterial3D,
+};
+use godot::prelude::*;
+
+const TILEMAP_SHADER: &[u8] = include_bytes!(env!("tilemap.spv"));
+const NOISE_SHADER: &[u8] = include_bytes!(env!("noisemap.spv"));
+const TILE_SIZE: u32 = 16;
+
+#[derive(GodotClass)]
+#[class(base=MeshInstance3D)]
+struct Mappy {
+ #[export]
+ map_width: i32,
+ #[export]
+ map_height: i32,
+ #[export]
+ noise_scale: f32,
+ #[export]
+ noise_magnitude: f32,
+ #[export]
+ texture_atlas: OnEditor>,
+
+ map: Array,
+
+ is_generated: bool,
+ map_mesh: Option>,
+ map_texture: Option>,
+ gpu_context: Option,
+
+ // required
+ base: Base,
+}
+
+#[godot_api]
+impl IMeshInstance3D for Mappy {
+ fn init(base: Base) -> Self {
+ let mut standard_array: Array = Array::new();
+ let width: i32 = 32;
+ let height: i32 = 32;
+ standard_array.resize((width * height) as usize, 0);
+
+ Self {
+ map_width: width,
+ map_height: height,
+ noise_scale: 1.0,
+ noise_magnitude: 5.0,
+ texture_atlas: OnEditor::default(),
+ map: standard_array,
+ is_generated: false,
+ map_mesh: None,
+ map_texture: None,
+ gpu_context: None,
+ base,
+ }
+ }
+
+ fn ready(&mut self) {
+ self.is_generated = false;
+ self.generate_map();
+ self.create_texture();
+ }
+
+ fn process(&mut self, _delta: f32) {
+ let input = Input::singleton();
+ if input.is_action_just_pressed("ui_accept") {
+ self.generate_map();
+ self.create_texture();
+ }
+ }
+}
+
+impl Mappy {
+ fn generate_map(&mut self) {
+ let now = SystemTime::now();
+ let duration_since_epoch = match now.duration_since(UNIX_EPOCH) {
+ Ok(duration) => duration,
+ Err(err) => {
+ godot_error!("Time went backwards during map generation: {}", err);
+ return;
+ }
+ };
+
+ let milliseconds = duration_since_epoch.as_millis();
+ let seed_u32 = (milliseconds & 0xFFFF_FFFF) as u32;
+ let seed_i32 = milliseconds as i128;
+ let seed_i32 = seed_i32 as i32;
+
+ godot_print!(
+ "Generating noise map {}x{} tiles (scale {:.2}, magnitude {:.2}, seed={})",
+ self.map_width,
+ self.map_height,
+ self.noise_scale,
+ self.noise_magnitude,
+ milliseconds
+ );
+
+ self.generate_map_cpu(seed_i32);
+ // if let Err(gpu_err) = self.generate_map_gpu(seed_u32) {
+ // godot_warn!("GPU noise generation failed: {}", gpu_err);
+ // self.gpu_context = None;
+ // self.generate_map_cpu(seed_i32);
+ // }
+ }
+
+ fn compute_context_mut(&mut self) -> Result<&mut GpuComputeContext, String> {
+ if self.gpu_context.is_none() {
+ self.gpu_context = Some(GpuComputeContext::new()?);
+ }
+ Ok(
+ self
+ .gpu_context
+ .as_mut()
+ .expect("GPU context must exist after initialization"),
+ )
+ }
+
+ fn generate_map_gpu(&mut self, seed: u32) -> Result<(), String> {
+ let map_width = self.map_width;
+ let map_height = self.map_height;
+ let noise_scale = self.noise_scale;
+ let noise_magnitude = self.noise_magnitude;
+
+ if map_width <= 0 || map_height <= 0 {
+ return Err("Map dimensions must be positive".to_string());
+ }
+
+ let tile_count = (map_width as usize)
+ .checked_mul(map_height as usize)
+ .ok_or_else(|| "Tile count overflow".to_string())?;
+
+ let params = NoiseGpuParams {
+ map_width: map_width as u32,
+ map_height: map_height as u32,
+ seed,
+ _pad0: 0,
+ noise_scale,
+ noise_magnitude: noise_magnitude.abs(),
+ _pad1: 0.0,
+ _pad2: 0.0,
+ };
+
+ let gpu_start = Instant::now();
+ let values = {
+ let context = self.compute_context_mut()?;
+ context.generate_noise(¶ms)?
+ };
+ if values.len() != tile_count {
+ return Err(format!(
+ "GPU noise output length mismatch. Expected {}, got {}",
+ tile_count,
+ values.len()
+ ));
+ }
+
+ let mut new_map: Array = Array::new();
+ new_map.resize(tile_count, 0);
+ for (index, value) in values.iter().enumerate() {
+ let clamped = (*value).min(i32::MAX as u32);
+ new_map.set(index, clamped as i32);
+ }
+ self.map = new_map;
+
+ let total_ms = gpu_start.elapsed().as_secs_f64() * 1000.0;
+ godot_print!(
+ "GPU noise map generation complete for {} tiles in {:.2} ms",
+ self.map.len(),
+ total_ms
+ );
+
+ Ok(())
+ }
+
+ fn generate_map_cpu(&mut self, seed: i32) {
+ let overall_start = Instant::now();
+ let mut new_map: Array = Array::new();
+ new_map.resize((self.map_width * self.map_height) as usize, 0);
+
+ let mut noise = FastNoiseLite::new_gd();
+ noise.set_seed(seed);
+
+ let fill_start = Instant::now();
+ for x in 0..self.map_width {
+ for y in 0..self.map_height {
+ new_map.set(
+ (x + y * self.map_height) as usize,
+ (noise.get_noise_2d(x as f32 * self.noise_scale, y as f32 * self.noise_scale) * self.noise_magnitude).abs()
+ as i32,
+ );
+ }
+ }
+ self.map = new_map;
+
+ let fill_ms = fill_start.elapsed().as_secs_f64() * 1000.0;
+ let total_ms = overall_start.elapsed().as_secs_f64() * 1000.0;
+ godot_print!(
+ "CPU noise generation complete for {} tiles in {:.2} ms (noise fill {:.2} ms)",
+ self.map.len(),
+ total_ms,
+ fill_ms
+ );
+ }
+
+ fn create_texture(&mut self) {
+ let overall_start = Instant::now();
+
+ if self.map_mesh.as_ref().is_some_and(|mesh| !mesh.is_instance_valid()) {
+ self.map_mesh = None;
+ }
+
+ if self
+ .map_texture
+ .as_ref()
+ .is_some_and(|texture| !texture.is_instance_valid())
+ {
+ self.map_texture = None;
+ }
+
+ let Some(mut atlas_image) = self.texture_atlas.get_image() else {
+ godot_error!("Texture atlas has no readable image data");
+ return;
+ };
+
+ let atlas_prepare_start = Instant::now();
+ if atlas_image.get_format() != Format::RGBA8 {
+ atlas_image.convert(Format::RGBA8);
+ }
+
+ let atlas_width = atlas_image.get_width();
+ let atlas_height = atlas_image.get_height();
+ godot_print!(
+ "Creating tilemap texture: map {}x{} tiles, tile_size {}, atlas {}x{} px",
+ self.map_width,
+ self.map_height,
+ TILE_SIZE,
+ atlas_width,
+ atlas_height
+ );
+ let atlas_prepare_ms = atlas_prepare_start.elapsed().as_secs_f64() * 1000.0;
+ godot_print!("Atlas fetch + convert finished in {:.2} ms", atlas_prepare_ms);
+
+ let map_clone = self.map.clone();
+ let map_len = map_clone.len();
+ let map_width = self.map_width;
+ let map_height = self.map_height;
+
+ let gpu_start = Instant::now();
+ let gpu_result = {
+ match self.compute_context_mut() {
+ Ok(context) => {
+ godot_print!("Attempting GPU tilemap generation for {} tiles", map_len);
+ Self::generate_texture_gpu(context, &map_clone, map_width, map_height, TILE_SIZE, &atlas_image)
+ }
+ Err(err) => Err(err),
+ }
+ };
+ let image = match gpu_result {
+ Ok(image) => {
+ let gpu_ms = gpu_start.elapsed().as_secs_f64() * 1000.0;
+ let width = image.get_width();
+ let height = image.get_height();
+ godot_print!(
+ "Generated tilemap texture on GPU in {:.2} ms ({}x{} px)",
+ gpu_ms,
+ width,
+ height
+ );
+ image
+ }
+ Err(gpu_err) => {
+ let gpu_ms = gpu_start.elapsed().as_secs_f64() * 1000.0;
+ godot_warn!("GPU tilemap generation failed after {:.2} ms: {}", gpu_ms, gpu_err);
+ godot_print!("Falling back to CPU tilemap generation path");
+ self.gpu_context = None;
+ let cpu_start = Instant::now();
+ match Self::create_texture_cpu(
+ &self.map,
+ self.map_width,
+ self.map_height,
+ TILE_SIZE,
+ &atlas_image,
+ Format::RGBA8,
+ ) {
+ Ok(image) => {
+ let cpu_ms = cpu_start.elapsed().as_secs_f64() * 1000.0;
+ let width = image.get_width();
+ let height = image.get_height();
+ godot_print!(
+ "Generated tilemap texture on CPU fallback in {:.2} ms ({}x{} px)",
+ cpu_ms,
+ width,
+ height
+ );
+ image
+ }
+ Err(cpu_err) => {
+ let cpu_ms = cpu_start.elapsed().as_secs_f64() * 1000.0;
+ godot_error!("CPU tilemap generation failed after {:.2} ms: {}", cpu_ms, cpu_err);
+ return;
+ }
+ }
+ }
+ };
+
+ let texture_handle = if let Some(tex) = self.map_texture.as_mut() {
+ tex.update(&image);
+ tex.clone()
+ } else {
+ let mut tex = ImageTexture::new_gd();
+ tex.set_image(&image);
+ let tex_clone = tex.clone();
+ self.map_texture = Some(tex);
+ tex_clone
+ };
+
+ let mut quad = QuadMesh::new_gd();
+ quad.set_size(Vector2::new(1.0, 1.0));
+ let mut mat = StandardMaterial3D::new_gd();
+ mat.set_shading_mode(ShadingMode::UNSHADED);
+ mat.set_texture(TextureParam::ALBEDO, &texture_handle);
+ quad.set_material(&mat);
+
+ if let Some(mesh) = self.map_mesh.as_mut() {
+ mesh.set_mesh(&quad);
+ } else {
+ let mut mesh = MeshInstance3D::new_alloc();
+ mesh.set_name("Map Quad");
+ mesh.set_mesh(&quad);
+ self.base_mut().add_child(&mesh);
+ self.map_mesh = Some(mesh);
+ }
+
+ self.is_generated = true;
+
+ let total_ms = overall_start.elapsed().as_secs_f64() * 1000.0;
+ godot_print!("create_texture() finished in {:.2} ms", total_ms);
+ }
+
+ fn generate_texture_gpu(
+ context: &mut GpuComputeContext,
+ map: &Array,
+ map_width: i32,
+ map_height: i32,
+ tile_size: u32,
+ atlas: &Gd,
+ ) -> Result, String> {
+ if tile_size == 0 {
+ return Err("Tile size must be positive".to_string());
+ }
+
+ if map_width <= 0 || map_height <= 0 {
+ return Err("Map dimensions must be positive".to_string());
+ }
+
+ let map_width_u32 = map_width as u32;
+ let map_height_u32 = map_height as u32;
+ let out_width = map_width_u32
+ .checked_mul(tile_size)
+ .ok_or_else(|| "Texture width overflow".to_string())?;
+ let out_height = map_height_u32
+ .checked_mul(tile_size)
+ .ok_or_else(|| "Texture height overflow".to_string())?;
+
+ if out_width == 0 || out_height == 0 {
+ return Err("Texture dimensions resolve to zero".to_string());
+ }
+
+ let atlas_width = atlas.get_width();
+ let atlas_height = atlas.get_height();
+ if atlas_width <= 0 || atlas_height <= 0 {
+ return Err("Atlas has invalid dimensions".to_string());
+ }
+
+ let atlas_width_u32 = atlas_width as u32;
+ let atlas_height_u32 = atlas_height as u32;
+
+ if !atlas_width_u32.is_multiple_of(tile_size) || !atlas_height_u32.is_multiple_of(tile_size) {
+ return Err("Atlas dimensions must be multiples of the tile size".to_string());
+ }
+
+ let atlas_bytes = atlas.get_data().to_vec();
+ let expected_atlas_bytes = (atlas_width as usize)
+ .checked_mul(atlas_height as usize)
+ .and_then(|v| v.checked_mul(4))
+ .ok_or_else(|| "Atlas size overflow".to_string())?;
+
+ if atlas_bytes.len() != expected_atlas_bytes {
+ return Err(format!(
+ "Atlas data size mismatch. Expected {}, got {}",
+ expected_atlas_bytes,
+ atlas_bytes.len()
+ ));
+ }
+
+ let map_vec = Self::map_to_vec(map, map_width_u32, map_height_u32)?;
+
+ let params = TilemapGpuParams {
+ out_width,
+ out_height,
+ tile_size,
+ map_width: map_width_u32,
+ map_height: map_height_u32,
+ atlas_width: atlas_width as u32,
+ atlas_height: atlas_height as u32,
+ };
+
+ let gpu_bytes = context.run_tilemap_compute(¶ms, &map_vec, &atlas_bytes)?;
+
+ Image::create_from_data(out_width as i32, out_height as i32, false, Format::RGBA8, &gpu_bytes)
+ .ok_or_else(|| "Failed to create image from GPU output".to_string())
+ }
+
+ fn create_texture_cpu(
+ map: &Array,
+ map_width: i32,
+ map_height: i32,
+ tile_size: u32,
+ atlas: &Gd,
+ format: Format,
+ ) -> Result, String> {
+ if tile_size == 0 {
+ return Err("Tile size must be positive".to_string());
+ }
+
+ let map_width_u32 = map_width as u32;
+ let map_height_u32 = map_height as u32;
+
+ let out_width = map_width_u32
+ .checked_mul(tile_size)
+ .ok_or_else(|| "CPU texture width overflow".to_string())?;
+ let out_height = map_height_u32
+ .checked_mul(tile_size)
+ .ok_or_else(|| "CPU texture height overflow".to_string())?;
+
+ if out_width == 0 || out_height == 0 {
+ return Err("CPU output dimensions resolve to zero".to_string());
+ }
+
+ let atlas_width = atlas.get_width();
+ let atlas_height = atlas.get_height();
+
+ if atlas_width <= 0 || atlas_height <= 0 {
+ return Err("Atlas has invalid dimensions".to_string());
+ }
+
+ let atlas_width_u32 = atlas_width as u32;
+ let atlas_height_u32 = atlas_height as u32;
+
+ if !atlas_width_u32.is_multiple_of(tile_size) || !atlas_height_u32.is_multiple_of(tile_size) {
+ return Err("Atlas dimensions must be multiples of the tile size".to_string());
+ }
+
+ let atlas_bytes = atlas.get_data().to_vec();
+ let expected_atlas_bytes = (atlas_width as usize)
+ .checked_mul(atlas_height as usize)
+ .and_then(|v| v.checked_mul(4))
+ .ok_or_else(|| "Atlas size overflow".to_string())?;
+
+ if atlas_bytes.len() != expected_atlas_bytes {
+ return Err(format!(
+ "Atlas data size mismatch. Expected {}, got {}",
+ expected_atlas_bytes,
+ atlas_bytes.len()
+ ));
+ }
+
+ let map_vec = Self::map_to_vec(map, map_width_u32, map_height_u32)?;
+
+ let output_size = (out_width as usize)
+ .checked_mul(out_height as usize)
+ .and_then(|v| v.checked_mul(4))
+ .ok_or_else(|| "CPU output size overflow".to_string())?;
+
+ let mut output = vec![0u8; output_size];
+
+ let tile_size_usize = tile_size as usize;
+ let atlas_width_usize = atlas_width_u32 as usize;
+ let out_width_usize = out_width as usize;
+ let atlas_tiles_per_row = atlas_width_usize / tile_size_usize;
+
+ if atlas_tiles_per_row == 0 {
+ return Err("Atlas cannot fit any tiles".to_string());
+ }
+
+ for tile_y in 0..map_height_u32 as usize {
+ for tile_x in 0..map_width_u32 as usize {
+ let tile_index = map_vec[tile_y * map_width_u32 as usize + tile_x] as usize;
+
+ let atlas_tile_x = tile_index % atlas_tiles_per_row;
+ let atlas_tile_y = tile_index / atlas_tiles_per_row;
+
+ for local_y in 0..tile_size_usize {
+ let dst_row = tile_y * tile_size_usize + local_y;
+ let src_row = atlas_tile_y * tile_size_usize + local_y;
+
+ let dst_offset = (dst_row * out_width_usize + tile_x * tile_size_usize) * 4;
+ let src_offset = (src_row * atlas_width_usize + atlas_tile_x * tile_size_usize) * 4;
+
+ let bytes_per_row = tile_size_usize * 4;
+
+ let dst_slice = dst_offset..dst_offset + bytes_per_row;
+ let src_slice = src_offset..src_offset + bytes_per_row;
+
+ if dst_slice.end > output.len() || src_slice.end > atlas_bytes.len() {
+ return Err("Tile copy exceeded buffer bounds".to_string());
+ }
+
+ output[dst_slice].copy_from_slice(&atlas_bytes[src_slice]);
+ }
+ }
+ }
+
+ let packed = PackedByteArray::from(output);
+
+ Image::create_from_data(out_width as i32, out_height as i32, false, format, &packed)
+ .ok_or_else(|| "Failed to create CPU image".to_string())
+ }
+
+ fn map_to_vec(map: &Array, map_width: u32, map_height: u32) -> Result, String> {
+ let expected = (map_width as usize)
+ .checked_mul(map_height as usize)
+ .ok_or_else(|| "Tilemap size overflow".to_string())?;
+
+ if map.len() != expected {
+ return Err(format!("Tilemap has {} entries but expected {}", map.len(), expected));
+ }
+
+ let mut result = Vec::with_capacity(expected);
+ for index in 0..expected {
+ let value = map.at(index);
+ result.push(if value < 0 { 0 } else { value as u32 });
+ }
+
+ Ok(result)
+ }
+}
+
+#[repr(C)]
+#[derive(Clone, Copy, Debug, Pod, Zeroable)]
+struct TilemapGpuParams {
+ out_width: u32,
+ out_height: u32,
+ tile_size: u32,
+ map_width: u32,
+ map_height: u32,
+ atlas_width: u32,
+ atlas_height: u32,
+}
+
+#[repr(C)]
+#[derive(Clone, Copy, Debug, Pod, Zeroable)]
+struct NoiseGpuParams {
+ map_width: u32,
+ map_height: u32,
+ seed: u32,
+ _pad0: u32,
+ noise_scale: f32,
+ noise_magnitude: f32,
+ _pad1: f32,
+ _pad2: f32,
+}
+
+struct GpuComputeContext {
+ device: Gd,
+ tilemap_shader: Rid,
+ tilemap_pipeline: Rid,
+ noise_shader: Rid,
+ noise_pipeline: Rid,
+}
+
+impl GpuComputeContext {
+ fn new() -> Result {
+ let mut device = match RenderingServer::singleton().create_local_rendering_device() {
+ Some(device) => device,
+ None => RenderingServer::singleton()
+ .get_rendering_device()
+ .ok_or_else(|| "Unable to acquire RenderingDevice".to_string())?,
+ };
+
+ let (tilemap_shader, tilemap_pipeline) = Self::create_pipeline(&mut device, TILEMAP_SHADER)?;
+ let (noise_shader, noise_pipeline) = Self::create_pipeline(&mut device, NOISE_SHADER)?;
+
+ godot_print!("Initialized GPU compute context for tilemap + noise");
+
+ Ok(Self {
+ device,
+ tilemap_shader,
+ tilemap_pipeline,
+ noise_shader,
+ noise_pipeline,
+ })
+ }
+
+ fn create_pipeline(device: &mut Gd, spirv: &[u8]) -> Result<(Rid, Rid), String> {
+ if !spirv.len().is_multiple_of(4) {
+ return Err("SPIR-V blob size is not a multiple of 4".to_string());
+ }
+
+ let shader_bytes = PackedByteArray::from(spirv.to_vec());
+ let mut shader_spirv = RdShaderSpirv::new_gd();
+ shader_spirv.set_stage_bytecode(ShaderStage::COMPUTE, &shader_bytes);
+
+ let shader_rid = device.shader_create_from_spirv(&shader_spirv);
+ if !shader_rid.is_valid() {
+ return Err("Failed to create compute shader".to_string());
+ }
+
+ let pipeline_rid = device.compute_pipeline_create(shader_rid);
+ if !pipeline_rid.is_valid() {
+ device.free_rid(shader_rid);
+ return Err("Failed to create compute pipeline".to_string());
+ }
+
+ Ok((shader_rid, pipeline_rid))
+ }
+
+ fn run_tilemap_compute(
+ &mut self,
+ params: &TilemapGpuParams,
+ map_data: &[u32],
+ atlas_data: &[u8],
+ ) -> Result {
+ godot_print!(
+ "run_tilemap_compute: output {}x{} px, tile_size {}, map {}x{} tiles, atlas {}x{} px",
+ params.out_width,
+ params.out_height,
+ params.tile_size,
+ params.map_width,
+ params.map_height,
+ params.atlas_width,
+ params.atlas_height
+ );
+
+ if params.tile_size == 0 {
+ return Err("Tile size cannot be zero".to_string());
+ }
+
+ if params.map_width == 0 || params.map_height == 0 {
+ return Err("Map dimensions cannot be zero".to_string());
+ }
+
+ if params.atlas_width == 0 || params.atlas_height == 0 {
+ return Err("Atlas dimensions cannot be zero".to_string());
+ }
+
+ let expected_map_entries = (params.map_width as usize)
+ .checked_mul(params.map_height as usize)
+ .ok_or_else(|| "Map size overflow".to_string())?;
+
+ if map_data.len() != expected_map_entries {
+ return Err(format!(
+ "Map buffer length mismatch. Expected {}, got {}",
+ expected_map_entries,
+ map_data.len()
+ ));
+ }
+
+ let expected_atlas_bytes = (params.atlas_width as usize)
+ .checked_mul(params.atlas_height as usize)
+ .and_then(|v| v.checked_mul(4))
+ .ok_or_else(|| "Atlas byte size overflow".to_string())?;
+
+ if atlas_data.len() != expected_atlas_bytes {
+ return Err(format!(
+ "Atlas buffer length mismatch. Expected {}, got {}",
+ expected_atlas_bytes,
+ atlas_data.len()
+ ));
+ }
+
+ if !atlas_data.len().is_multiple_of(4) {
+ return Err("Atlas buffer length must be a multiple of 4".to_string());
+ }
+
+ let output_size = (params.out_width as usize)
+ .checked_mul(params.out_height as usize)
+ .and_then(|v| v.checked_mul(4))
+ .ok_or_else(|| "Output texture is too large".to_string())?;
+
+ if output_size == 0 {
+ return Err("Output texture is empty".to_string());
+ }
+
+ let mut device = self.device.clone();
+ godot_print!("Using cached RenderingDevice for compute dispatch");
+
+ let mut allocated: Vec = Vec::new();
+
+ let result = (|| -> Result {
+ let setup_start = Instant::now();
+
+ let params_raw = bytes_of(params);
+ let params_size =
+ u32::try_from(params_raw.len()).map_err(|_| "Parameter buffer exceeds supported size".to_string())?;
+ let params_bytes = PackedByteArray::from(params_raw.to_vec());
+ let params_buffer = device
+ .storage_buffer_create_ex(params_size)
+ .data(¶ms_bytes)
+ .creation_bits(BufferCreationBits::AS_STORAGE_BIT)
+ .done();
+ if !params_buffer.is_valid() {
+ return Err("Failed to allocate parameter buffer".to_string());
+ }
+ allocated.push(params_buffer);
+
+ let map_raw: &[u8] = cast_slice(map_data);
+ let map_size = u32::try_from(map_raw.len()).map_err(|_| "Map buffer exceeds supported size".to_string())?;
+ let map_bytes = PackedByteArray::from(map_raw.to_vec());
+ let map_buffer = device
+ .storage_buffer_create_ex(map_size)
+ .data(&map_bytes)
+ .creation_bits(BufferCreationBits::AS_STORAGE_BIT)
+ .done();
+ if !map_buffer.is_valid() {
+ return Err("Failed to allocate map buffer".to_string());
+ }
+ allocated.push(map_buffer);
+
+ let atlas_size =
+ u32::try_from(atlas_data.len()).map_err(|_| "Atlas buffer exceeds supported size".to_string())?;
+ let atlas_bytes = PackedByteArray::from(atlas_data.to_vec());
+ let atlas_buffer = device
+ .storage_buffer_create_ex(atlas_size)
+ .data(&atlas_bytes)
+ .creation_bits(BufferCreationBits::AS_STORAGE_BIT)
+ .done();
+ if !atlas_buffer.is_valid() {
+ return Err("Failed to allocate atlas buffer".to_string());
+ }
+ allocated.push(atlas_buffer);
+
+ let output_size_u32 =
+ u32::try_from(output_size).map_err(|_| "Output buffer exceeds supported size".to_string())?;
+ let output_init = PackedByteArray::from(vec![0u8; output_size]);
+ let output_buffer = device
+ .storage_buffer_create_ex(output_size_u32)
+ .data(&output_init)
+ .creation_bits(BufferCreationBits::AS_STORAGE_BIT)
+ .done();
+ if !output_buffer.is_valid() {
+ return Err("Failed to allocate output buffer".to_string());
+ }
+ allocated.push(output_buffer);
+
+ let mut uniform_nodes: Vec> = Vec::new();
+ for (binding, rid) in [
+ (0_i32, params_buffer),
+ (1_i32, map_buffer),
+ (2_i32, atlas_buffer),
+ (3_i32, output_buffer),
+ ] {
+ let mut uniform = RdUniform::new_gd();
+ uniform.set_uniform_type(UniformType::STORAGE_BUFFER);
+ uniform.set_binding(binding);
+ uniform.add_id(rid);
+ uniform_nodes.push(uniform);
+ }
+
+ let mut uniforms: Array> = Array::new();
+ for uniform in &uniform_nodes {
+ uniforms.push(uniform);
+ }
+
+ let uniform_set = device.uniform_set_create(&uniforms, self.tilemap_shader, 0);
+ if !uniform_set.is_valid() {
+ return Err("Failed to create uniform set".to_string());
+ }
+ allocated.push(uniform_set);
+
+ let setup_ms = setup_start.elapsed().as_secs_f64() * 1000.0;
+ godot_print!("GPU pipeline + buffer setup finished in {:.2} ms", setup_ms);
+
+ let compute_list = device.compute_list_begin();
+ if compute_list < 0 {
+ return Err("Failed to begin compute list".to_string());
+ }
+
+ device.compute_list_bind_compute_pipeline(compute_list, self.tilemap_pipeline);
+ device.compute_list_bind_uniform_set(compute_list, uniform_set, 0);
+
+ let groups_x = params.out_width.saturating_add(7) / 8;
+ let groups_y = params.out_height.saturating_add(7) / 8;
+ let dispatch_x = groups_x.max(1);
+ let dispatch_y = groups_y.max(1);
+
+ device.compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
+ device.compute_list_end();
+ godot_print!(
+ "Dispatched compute shader with workgroups {}x{} (covering {}x{} px)",
+ dispatch_x,
+ dispatch_y,
+ params.out_width,
+ params.out_height
+ );
+
+ let dispatch_start = Instant::now();
+ device.submit();
+ device.sync();
+ let dispatch_ms = dispatch_start.elapsed().as_secs_f64() * 1000.0;
+ godot_print!("GPU dispatch + sync finished in {:.2} ms", dispatch_ms);
+
+ let readback_start = Instant::now();
+ let output_data = device.buffer_get_data(output_buffer);
+ let readback_ms = readback_start.elapsed().as_secs_f64() * 1000.0;
+ godot_print!("GPU readback finished in {:.2} ms", readback_ms);
+ godot_print!("Compute shader completed; output contains {} bytes", output_data.len());
+
+ Ok(output_data)
+ })();
+
+ for rid in allocated.into_iter().rev() {
+ if rid.is_valid() {
+ device.free_rid(rid);
+ }
+ }
+
+ result
+ }
+
+ fn generate_noise(&mut self, params: &NoiseGpuParams) -> Result, String> {
+ if params.map_width == 0 || params.map_height == 0 {
+ return Err("Noise map dimensions cannot be zero".to_string());
+ }
+
+ let tile_count = (params.map_width as usize)
+ .checked_mul(params.map_height as usize)
+ .ok_or_else(|| "Noise tile count overflow".to_string())?;
+
+ let output_size_bytes = tile_count
+ .checked_mul(std::mem::size_of::())
+ .ok_or_else(|| "Noise output exceeds supported size".to_string())?;
+
+ if output_size_bytes == 0 {
+ return Err("Noise output buffer is empty".to_string());
+ }
+
+ let mut device = self.device.clone();
+ let mut allocated: Vec = Vec::new();
+
+ let result = (|| -> Result, String> {
+ let params_raw = bytes_of(params);
+ let params_size =
+ u32::try_from(params_raw.len()).map_err(|_| "Noise parameter buffer exceeds supported size".to_string())?;
+ let params_bytes = PackedByteArray::from(params_raw.to_vec());
+ let params_buffer = device
+ .storage_buffer_create_ex(params_size)
+ .data(¶ms_bytes)
+ .creation_bits(BufferCreationBits::AS_STORAGE_BIT)
+ .done();
+ if !params_buffer.is_valid() {
+ return Err("Failed to allocate noise parameter buffer".to_string());
+ }
+ allocated.push(params_buffer);
+
+ let output_size_u32 =
+ u32::try_from(output_size_bytes).map_err(|_| "Noise output buffer exceeds supported size".to_string())?;
+ let output_init = PackedByteArray::from(vec![0u8; output_size_bytes]);
+ let output_buffer = device
+ .storage_buffer_create_ex(output_size_u32)
+ .data(&output_init)
+ .creation_bits(BufferCreationBits::AS_STORAGE_BIT)
+ .done();
+ if !output_buffer.is_valid() {
+ return Err("Failed to allocate noise output buffer".to_string());
+ }
+ allocated.push(output_buffer);
+
+ let mut uniform_nodes: Vec> = Vec::new();
+ for (binding, rid) in [(0_i32, params_buffer), (1_i32, output_buffer)] {
+ let mut uniform = RdUniform::new_gd();
+ uniform.set_uniform_type(UniformType::STORAGE_BUFFER);
+ uniform.set_binding(binding);
+ uniform.add_id(rid);
+ uniform_nodes.push(uniform);
+ }
+
+ let mut uniforms: Array> = Array::new();
+ for uniform in &uniform_nodes {
+ uniforms.push(uniform);
+ }
+
+ let uniform_set = device.uniform_set_create(&uniforms, self.noise_shader, 0);
+ if !uniform_set.is_valid() {
+ return Err("Failed to create noise uniform set".to_string());
+ }
+ allocated.push(uniform_set);
+
+ let compute_list = device.compute_list_begin();
+ if compute_list < 0 {
+ return Err("Failed to begin noise compute list".to_string());
+ }
+
+ device.compute_list_bind_compute_pipeline(compute_list, self.noise_pipeline);
+ device.compute_list_bind_uniform_set(compute_list, uniform_set, 0);
+
+ let groups_x = params.map_width.saturating_add(15) / 16;
+ let groups_y = params.map_height.saturating_add(15) / 16;
+ let dispatch_x = groups_x.max(1);
+ let dispatch_y = groups_y.max(1);
+
+ device.compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
+ device.compute_list_end();
+
+ device.submit();
+ device.sync();
+
+ let output_bytes = device.buffer_get_data(output_buffer);
+ if !output_bytes.len().is_multiple_of(4) {
+ return Err("Noise output byte count is not a multiple of 4".to_string());
+ }
+
+ let raw = output_bytes.to_vec();
+ let values: &[u32] = cast_slice(&raw);
+ Ok(values.to_vec())
+ })();
+
+ for rid in allocated.into_iter().rev() {
+ if rid.is_valid() {
+ device.free_rid(rid);
+ }
+ }
+
+ result
+ }
+}
+
+impl Drop for GpuComputeContext {
+ fn drop(&mut self) {
+ let mut device = self.device.clone();
+ if self.tilemap_pipeline.is_valid() {
+ device.free_rid(self.tilemap_pipeline);
+ }
+ if self.tilemap_shader.is_valid() {
+ device.free_rid(self.tilemap_shader);
+ }
+ if self.noise_pipeline.is_valid() {
+ device.free_rid(self.noise_pipeline);
+ }
+ if self.noise_shader.is_valid() {
+ device.free_rid(self.noise_shader);
+ }
+ }
+}
+
+#[cfg(feature = "gd_rehearse_tests")]
+mod gd_rehearse_tests {
+ use super::*;
+ use gd_rehearse::itest::*;
+ use std::time::Instant;
+
+ pub fn make_test_atlas() -> (Vec, u32, u32) {
+ let tile_size = 2u32;
+ let atlas_w = tile_size * 2; // two tiles horizontally
+ let atlas_h = tile_size; // one row
+
+ // Build atlas row-major across atlas_w
+ // Tile 0 = solid red, Tile 1 = solid green
+ let mut data = Vec::with_capacity((atlas_w * atlas_h * 4) as usize);
+ for _y in 0..atlas_h {
+ for x in 0..atlas_w {
+ if x < tile_size {
+ data.extend_from_slice(&[255u8, 0, 0, 255]);
+ } else {
+ data.extend_from_slice(&[0u8, 255, 0, 255]);
+ }
+ }
+ }
+
+ (data, atlas_w, atlas_h)
+ }
+
+ fn make_uniform_atlas(tile_size: u32, color: [u8; 4]) -> (Vec, u32, u32) {
+ let pixel_count = (tile_size * tile_size) as usize;
+ let mut data = Vec::with_capacity(pixel_count * 4);
+ for _ in 0..pixel_count {
+ data.extend_from_slice(&color);
+ }
+
+ (data, tile_size, tile_size)
+ }
+
+ fn run_tilemap_for_size(map_width: u32, map_height: u32, tile_size: u32) -> PackedByteArray {
+ godot_print!(
+ "Testing map {}x{} tiles at tile_size {} ({}x{} px output)",
+ map_width,
+ map_height,
+ tile_size,
+ map_width * tile_size,
+ map_height * tile_size
+ );
+
+ let (atlas_bytes, atlas_w, atlas_h) = make_uniform_atlas(tile_size, [0u8, 0u8, 255u8, 255u8]);
+
+ let params = TilemapGpuParams {
+ out_width: map_width * tile_size,
+ out_height: map_height * tile_size,
+ tile_size,
+ map_width,
+ map_height,
+ atlas_width: atlas_w,
+ atlas_height: atlas_h,
+ };
+
+ let tile_count = (map_width as usize)
+ .checked_mul(map_height as usize)
+ .expect("Tile count overflow in benchmark");
+ let map = vec![0u32; tile_count];
+ let start = Instant::now();
+ let mut context = GpuComputeContext::new().expect("Failed to create GPU context for benchmark");
+ let result = context
+ .run_tilemap_compute(¶ms, &map, &atlas_bytes)
+ .expect("GPU tilemap compute failed during size sweep benchmark");
+ let elapsed_ms = start.elapsed().as_secs_f64() * 1000.0;
+ godot_print!(
+ "Tilemap GPU compute finished in {:.2} ms for {} tiles ({} bytes output)",
+ elapsed_ms,
+ tile_count,
+ result.len()
+ );
+ result
+ }
+
+ fn expected_output_bytes(map_width: u32, map_height: u32, tile_size: u32) -> usize {
+ let out_width = map_width
+ .checked_mul(tile_size)
+ .expect("Output width overflow in expectation");
+ let out_height = map_height
+ .checked_mul(tile_size)
+ .expect("Output height overflow in expectation");
+
+ (out_width as usize)
+ .checked_mul(out_height as usize)
+ .and_then(|v| v.checked_mul(4))
+ .expect("Expected byte count overflow")
+ }
+
+ #[gditest(scene_path = "res://tests/test_runner.tscn")]
+ fn gpu_tilemap_produces_expected_pixels() {
+ let (atlas_bytes, atlas_w, atlas_h) = make_test_atlas();
+
+ let params = TilemapGpuParams {
+ out_width: 4,
+ out_height: 2,
+ tile_size: 2,
+ map_width: 2,
+ map_height: 1,
+ atlas_width: atlas_w,
+ atlas_height: atlas_h,
+ };
+
+ let map = vec![0u32, 1u32];
+ let start = Instant::now();
+ let mut context = GpuComputeContext::new().expect("Failed to create GPU context for sanity check");
+ let gpu_bytes = context
+ .run_tilemap_compute(¶ms, &map, &atlas_bytes)
+ .expect("GPU tilemap compute failed")
+ .to_vec();
+ let elapsed_ms = start.elapsed().as_secs_f64() * 1000.0;
+ godot_print!("Sanity GPU tilemap test finished in {:.2} ms", elapsed_ms);
+
+ assert_eq!(gpu_bytes.len(), atlas_bytes.len(), "GPU output size mismatch");
+ assert_eq!(
+ gpu_bytes, atlas_bytes,
+ "GPU tilemap output differs from atlas expectation"
+ );
+ }
+
+ #[gditest(scene_path = "res://tests/test_runner.tscn")]
+ fn gpu_noise_generation_dimensions() {
+ let mut context = GpuComputeContext::new().expect("Failed to create GPU context for noise test");
+ let params = NoiseGpuParams {
+ map_width: 64,
+ map_height: 32,
+ seed: 1,
+ _pad0: 0,
+ noise_scale: 0.75,
+ noise_magnitude: 12.0,
+ _pad1: 0.0,
+ _pad2: 0.0,
+ };
+
+ let values = context.generate_noise(¶ms).expect("GPU noise generation failed");
+ let expected = (params.map_width as usize)
+ .checked_mul(params.map_height as usize)
+ .expect("Noise test tile count overflow");
+ assert_eq!(values.len(), expected, "Noise GPU output length mismatch");
+ let max_allowed = params.noise_magnitude.ceil() as u32;
+ assert!(
+ values.iter().all(|&value| value <= max_allowed),
+ "Noise GPU output exceeded magnitude limit"
+ );
+ }
+
+ #[gditest(scene_path = "res://tests/test_runner.tscn")]
+ fn gpu_tilemap_generation_small() {
+ let output = run_tilemap_for_size(128, 128, TILE_SIZE);
+ let expected = expected_output_bytes(128, 128, TILE_SIZE);
+ assert_eq!(output.len(), expected, "Small tilemap output byte size mismatch");
+ godot_print!("Small tilemap test validated {} bytes", output.len());
+ }
+
+ #[gditest(scene_path = "res://tests/test_runner.tscn")]
+ fn gpu_tilemap_generation_medium() {
+ let output = run_tilemap_for_size(256, 256, TILE_SIZE);
+ let expected = expected_output_bytes(256, 256, TILE_SIZE);
+ assert_eq!(output.len(), expected, "Medium tilemap output byte size mismatch");
+ godot_print!("Medium tilemap test validated {} bytes", output.len());
+ }
+
+ #[gditest(scene_path = "res://tests/test_runner.tscn")]
+ fn gpu_tilemap_generation_large() {
+ let output = run_tilemap_for_size(512, 512, TILE_SIZE);
+ let expected = expected_output_bytes(512, 512, TILE_SIZE);
+ assert_eq!(output.len(), expected, "Large tilemap output byte size mismatch");
+ godot_print!("Large tilemap test validated {} bytes", output.len());
+ }
+
+ #[gditest(scene_path = "res://tests/test_runner.tscn")]
+ fn gpu_tilemap_generation_xlarge() {
+ let output = run_tilemap_for_size(1024, 1024, TILE_SIZE);
+ let expected = expected_output_bytes(1024, 1024, TILE_SIZE);
+ assert_eq!(output.len(), expected, "XL tilemap output byte size mismatch");
+ godot_print!("XL tilemap test validated {} bytes", output.len());
+ }
+}
diff --git a/rust/src/player.rs b/rust/src/player.rs
new file mode 100644
index 0000000..8d7dc75
--- /dev/null
+++ b/rust/src/player.rs
@@ -0,0 +1,55 @@
+use godot::{classes::Input, global::Key, prelude::*};
+
+#[derive(GodotClass)]
+#[class(base=Node3D)]
+struct Player {
+ #[export]
+ character_name: GString,
+ #[export]
+ velocity: Vector3,
+ #[export]
+ acceleration: Vector3,
+ base: Base,
+}
+
+#[godot_api]
+impl INode3D for Player {
+ fn init(base: Base) -> Self {
+ Self {
+ character_name: GString::from("Hello"),
+ velocity: Vector3::ZERO,
+ acceleration: Vector3::new(1.0, 1.0, 0.0),
+ base,
+ }
+ }
+
+ fn process(&mut self, delta: f32) {
+ self.process_input(delta);
+ self.update_position(delta);
+ }
+}
+
+impl Player {
+ fn process_input(&mut self, _delta: f32) {
+ let input = Input::singleton();
+ if input.is_key_pressed(Key::W) {
+ self.velocity.y += self.acceleration.y;
+ }
+ if input.is_key_pressed(Key::A) {
+ self.velocity.x -= self.acceleration.x;
+ }
+ if input.is_key_pressed(Key::S) {
+ self.velocity.y -= self.acceleration.y;
+ }
+ if input.is_key_pressed(Key::D) {
+ self.velocity.x += self.acceleration.x;
+ }
+ }
+
+ fn update_position(&mut self, delta: f32) {
+ let before_move = self.base_mut().get_transform();
+ let after_move = before_move.translated(self.velocity * delta);
+ self.base_mut().set_transform(after_move);
+ self.velocity *= 0.5;
+ }
+}