diff --git a/.import/Glass.png-3b2015c0dd629c60d3c1b09d9013c59c.md5 b/.import/Glass.png-3b2015c0dd629c60d3c1b09d9013c59c.md5 new file mode 100644 index 0000000..df63c5b --- /dev/null +++ b/.import/Glass.png-3b2015c0dd629c60d3c1b09d9013c59c.md5 @@ -0,0 +1,3 @@ +source_md5="e48338fdf043e69d0c0549bc35a336d3" +dest_md5="80b05a4161e3e44efe54c5f703abc6a1" + diff --git a/.import/Glass.png-3b2015c0dd629c60d3c1b09d9013c59c.stex b/.import/Glass.png-3b2015c0dd629c60d3c1b09d9013c59c.stex new file mode 100644 index 0000000..d566acb Binary files /dev/null and b/.import/Glass.png-3b2015c0dd629c60d3c1b09d9013c59c.stex differ diff --git a/.import/Glass.png-8678c0300c4ceb28841173a60adcbab3.md5 b/.import/Glass.png-8678c0300c4ceb28841173a60adcbab3.md5 new file mode 100644 index 0000000..e17e61d --- /dev/null +++ b/.import/Glass.png-8678c0300c4ceb28841173a60adcbab3.md5 @@ -0,0 +1,3 @@ +source_md5="ae48a5a22aa6a99422a8318ffed1feaa" +dest_md5="d181a180dfaeadaadbdfd93dc388012c" + diff --git a/.import/Glass.png-8678c0300c4ceb28841173a60adcbab3.stex b/.import/Glass.png-8678c0300c4ceb28841173a60adcbab3.stex new file mode 100644 index 0000000..0313439 Binary files /dev/null and b/.import/Glass.png-8678c0300c4ceb28841173a60adcbab3.stex differ diff --git a/.import/Icon_4.png-dc833624655055ecbac60caa1ff8c787.md5 b/.import/Icon_4.png-dc833624655055ecbac60caa1ff8c787.md5 new file mode 100644 index 0000000..ac466eb --- /dev/null +++ b/.import/Icon_4.png-dc833624655055ecbac60caa1ff8c787.md5 @@ -0,0 +1,3 @@ +source_md5="45ec5f2645e0daca30e1b8b1cac95ed7" +dest_md5="36d9e9829a4519107ca15adfa13d9043" + diff --git a/.import/Icon_4.png-dc833624655055ecbac60caa1ff8c787.stex b/.import/Icon_4.png-dc833624655055ecbac60caa1ff8c787.stex new file mode 100644 index 0000000..ac3bbdf Binary files /dev/null and b/.import/Icon_4.png-dc833624655055ecbac60caa1ff8c787.stex differ diff --git a/.import/Icon_5.png-5996b0b5e4a48ab5d0c5454fa98a17bd.md5 b/.import/Icon_5.png-5996b0b5e4a48ab5d0c5454fa98a17bd.md5 new file mode 100644 index 0000000..5e613a0 --- /dev/null +++ b/.import/Icon_5.png-5996b0b5e4a48ab5d0c5454fa98a17bd.md5 @@ -0,0 +1,3 @@ +source_md5="9fd4edb2bc0911b9a18417c61fe8cdd1" +dest_md5="911caff935a9e06a4c65b7d79a85fbc8" + diff --git a/.import/Icon_5.png-5996b0b5e4a48ab5d0c5454fa98a17bd.stex b/.import/Icon_5.png-5996b0b5e4a48ab5d0c5454fa98a17bd.stex new file mode 100644 index 0000000..24cf3aa Binary files /dev/null and b/.import/Icon_5.png-5996b0b5e4a48ab5d0c5454fa98a17bd.stex differ diff --git a/.import/Icon_6.png-f5c5c36d0c8e2c99b2c8998b12e2dca2.md5 b/.import/Icon_6.png-f5c5c36d0c8e2c99b2c8998b12e2dca2.md5 new file mode 100644 index 0000000..7eb55d3 --- /dev/null +++ b/.import/Icon_6.png-f5c5c36d0c8e2c99b2c8998b12e2dca2.md5 @@ -0,0 +1,3 @@ +source_md5="2d4fa181450a5668b22bdb6e9831919f" +dest_md5="768bf56328bd931108e594a6f275fa0c" + diff --git a/.import/Icon_6.png-f5c5c36d0c8e2c99b2c8998b12e2dca2.stex b/.import/Icon_6.png-f5c5c36d0c8e2c99b2c8998b12e2dca2.stex new file mode 100644 index 0000000..b18a6cb Binary files /dev/null and b/.import/Icon_6.png-f5c5c36d0c8e2c99b2c8998b12e2dca2.stex differ diff --git a/.import/Icon_7.png-e5599ba2a6360063be55af65767b9beb.md5 b/.import/Icon_7.png-e5599ba2a6360063be55af65767b9beb.md5 new file mode 100644 index 0000000..d37d405 --- /dev/null +++ b/.import/Icon_7.png-e5599ba2a6360063be55af65767b9beb.md5 @@ -0,0 +1,3 @@ +source_md5="42cdc1e1592e52083e73e551f21c2fa9" +dest_md5="45d459381756e367f5d750e422e98474" + diff --git a/.import/Icon_7.png-e5599ba2a6360063be55af65767b9beb.stex b/.import/Icon_7.png-e5599ba2a6360063be55af65767b9beb.stex new file mode 100644 index 0000000..200f264 Binary files /dev/null and b/.import/Icon_7.png-e5599ba2a6360063be55af65767b9beb.stex differ diff --git a/.import/Icon_8.png-058c48e4cc637de37413544fee2a9a2b.md5 b/.import/Icon_8.png-058c48e4cc637de37413544fee2a9a2b.md5 new file mode 100644 index 0000000..4e2aba8 --- /dev/null +++ b/.import/Icon_8.png-058c48e4cc637de37413544fee2a9a2b.md5 @@ -0,0 +1,3 @@ +source_md5="7e380c1c224c308f607885c419a9cf73" +dest_md5="3c31581c74d855625078446a4795fe21" + diff --git a/.import/Icon_8.png-058c48e4cc637de37413544fee2a9a2b.stex b/.import/Icon_8.png-058c48e4cc637de37413544fee2a9a2b.stex new file mode 100644 index 0000000..ae00135 Binary files /dev/null and b/.import/Icon_8.png-058c48e4cc637de37413544fee2a9a2b.stex differ diff --git a/.import/Icon_9.png-50a7db6b6a1fee5a30051fa84f0c1a0b.md5 b/.import/Icon_9.png-50a7db6b6a1fee5a30051fa84f0c1a0b.md5 new file mode 100644 index 0000000..99e7c4c --- /dev/null +++ b/.import/Icon_9.png-50a7db6b6a1fee5a30051fa84f0c1a0b.md5 @@ -0,0 +1,3 @@ +source_md5="71bc1217289de16605b99e80fd1fae32" +dest_md5="84842298ad49aff82aaae5f911bfa156" + diff --git a/.import/Icon_9.png-50a7db6b6a1fee5a30051fa84f0c1a0b.stex b/.import/Icon_9.png-50a7db6b6a1fee5a30051fa84f0c1a0b.stex new file mode 100644 index 0000000..8789519 Binary files /dev/null and b/.import/Icon_9.png-50a7db6b6a1fee5a30051fa84f0c1a0b.stex differ diff --git a/.import/bg.png-5046840dce817dc9e1d61a818df550fc.md5 b/.import/bg.png-5046840dce817dc9e1d61a818df550fc.md5 new file mode 100644 index 0000000..0b64965 --- /dev/null +++ b/.import/bg.png-5046840dce817dc9e1d61a818df550fc.md5 @@ -0,0 +1,3 @@ +source_md5="d607510048c43b15d9f908666abc10ce" +dest_md5="f56c36e2e2d12453433c9dfc95b37c0f" + diff --git a/.import/bg.png-5046840dce817dc9e1d61a818df550fc.stex b/.import/bg.png-5046840dce817dc9e1d61a818df550fc.stex new file mode 100644 index 0000000..3f47cea Binary files /dev/null and b/.import/bg.png-5046840dce817dc9e1d61a818df550fc.stex differ diff --git a/.import/break.sfxr-c1c1594a22628fd278421b7f8a79a149.md5 b/.import/break.sfxr-c1c1594a22628fd278421b7f8a79a149.md5 new file mode 100644 index 0000000..25d52ba --- /dev/null +++ b/.import/break.sfxr-c1c1594a22628fd278421b7f8a79a149.md5 @@ -0,0 +1,3 @@ +source_md5="24213acfa75e1afe51371161b047d97d" +dest_md5="403bc96e74c0979fac5728f0848ea056" + diff --git a/.import/break.sfxr-c1c1594a22628fd278421b7f8a79a149.sample b/.import/break.sfxr-c1c1594a22628fd278421b7f8a79a149.sample new file mode 100644 index 0000000..dcfcef8 Binary files /dev/null and b/.import/break.sfxr-c1c1594a22628fd278421b7f8a79a149.sample differ diff --git a/.import/floor.png-bad02a3061f4734a68e01c2ddec9b22e.md5 b/.import/floor.png-bad02a3061f4734a68e01c2ddec9b22e.md5 index e46a709..5177d61 100644 --- a/.import/floor.png-bad02a3061f4734a68e01c2ddec9b22e.md5 +++ b/.import/floor.png-bad02a3061f4734a68e01c2ddec9b22e.md5 @@ -1,3 +1,3 @@ -source_md5="3196a70615a1d1f1c96fca3d269ddeff" -dest_md5="4c22a8d7c72569ce9d922ab1d5c3ab8e" +source_md5="1f4a7c7ec834bc28fa063d92219b7203" +dest_md5="870ad9fa6e7fb0b91f691e9c3514386c" diff --git a/.import/floor.png-bad02a3061f4734a68e01c2ddec9b22e.stex b/.import/floor.png-bad02a3061f4734a68e01c2ddec9b22e.stex index 9cad6c9..806dc8f 100644 Binary files a/.import/floor.png-bad02a3061f4734a68e01c2ddec9b22e.stex and b/.import/floor.png-bad02a3061f4734a68e01c2ddec9b22e.stex differ diff --git a/.import/icon.png-487276ed1e3a0c39cad0279d744ee560.md5 b/.import/icon.png-487276ed1e3a0c39cad0279d744ee560.md5 index 5328bc7..bd2e7d9 100644 --- a/.import/icon.png-487276ed1e3a0c39cad0279d744ee560.md5 +++ b/.import/icon.png-487276ed1e3a0c39cad0279d744ee560.md5 @@ -1,3 +1,3 @@ -source_md5="47313fa4c47a9963fddd764e1ec6e4a8" -dest_md5="26ea799ea0a3da9e753b3ebe822e0570" +source_md5="bc69b7f51a5c3e10bbb3a38f62ff6284" +dest_md5="253c7a0063b8268d86be8cb737ff1111" diff --git a/.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex b/.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex index 71f6913..8b3d7df 100644 Binary files a/.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex and b/.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex differ diff --git a/.import/overview.PNG-3372de55fcb4add320565bad41f71587.md5 b/.import/overview.PNG-3372de55fcb4add320565bad41f71587.md5 new file mode 100644 index 0000000..8d11c02 --- /dev/null +++ b/.import/overview.PNG-3372de55fcb4add320565bad41f71587.md5 @@ -0,0 +1,3 @@ +source_md5="ad923036df9b2572bacd6749ae2024f0" +dest_md5="245c6fd0f699a6ee53e6c878da599b50" + diff --git a/.import/progress.png-1546df883425497bf4494dd92b12d7b4.md5 b/.import/progress.png-1546df883425497bf4494dd92b12d7b4.md5 new file mode 100644 index 0000000..9195a29 --- /dev/null +++ b/.import/progress.png-1546df883425497bf4494dd92b12d7b4.md5 @@ -0,0 +1,3 @@ +source_md5="653c99928be1524b21d2add32ae8d13f" +dest_md5="892389819376be6bfe0deb52ff6fed11" + diff --git a/.import/progress.png-1546df883425497bf4494dd92b12d7b4.stex b/.import/progress.png-1546df883425497bf4494dd92b12d7b4.stex new file mode 100644 index 0000000..2e6be0a Binary files /dev/null and b/.import/progress.png-1546df883425497bf4494dd92b12d7b4.stex differ diff --git a/.import/punch.sfxr-ce24cf25ac6de08473bbda5685c58ae5.md5 b/.import/punch.sfxr-ce24cf25ac6de08473bbda5685c58ae5.md5 new file mode 100644 index 0000000..64ef855 --- /dev/null +++ b/.import/punch.sfxr-ce24cf25ac6de08473bbda5685c58ae5.md5 @@ -0,0 +1,3 @@ +source_md5="85a9cb49e771d72d839a8409b3f9b9ce" +dest_md5="c3251c8663f0f35e65cb0f58382bc6b0" + diff --git a/.import/punch.sfxr-ce24cf25ac6de08473bbda5685c58ae5.sample b/.import/punch.sfxr-ce24cf25ac6de08473bbda5685c58ae5.sample new file mode 100644 index 0000000..1f02d62 Binary files /dev/null and b/.import/punch.sfxr-ce24cf25ac6de08473bbda5685c58ae5.sample differ diff --git a/.import/table.png-6287c5224e3a2223ad79685cc0bf8f85.md5 b/.import/table.png-6287c5224e3a2223ad79685cc0bf8f85.md5 new file mode 100644 index 0000000..fe18a51 --- /dev/null +++ b/.import/table.png-6287c5224e3a2223ad79685cc0bf8f85.md5 @@ -0,0 +1,3 @@ +source_md5="9dd651cc55c5cf69f617ef98c9759a3a" +dest_md5="2da991840fabf6730dc8918b7e936144" + diff --git a/.import/table.png-6287c5224e3a2223ad79685cc0bf8f85.stex b/.import/table.png-6287c5224e3a2223ad79685cc0bf8f85.stex new file mode 100644 index 0000000..96627c3 Binary files /dev/null and b/.import/table.png-6287c5224e3a2223ad79685cc0bf8f85.stex differ diff --git a/.import/under.png-d21cca1445c6a2663bc52f4f2384a623.md5 b/.import/under.png-d21cca1445c6a2663bc52f4f2384a623.md5 new file mode 100644 index 0000000..f51e6e4 --- /dev/null +++ b/.import/under.png-d21cca1445c6a2663bc52f4f2384a623.md5 @@ -0,0 +1,3 @@ +source_md5="31cd1f8a917c5075e663ae258d562cd7" +dest_md5="65f32199154fd5ec5e092e0d77471819" + diff --git a/.import/under.png-d21cca1445c6a2663bc52f4f2384a623.stex b/.import/under.png-d21cca1445c6a2663bc52f4f2384a623.stex new file mode 100644 index 0000000..bbf0b13 Binary files /dev/null and b/.import/under.png-d21cca1445c6a2663bc52f4f2384a623.stex differ diff --git a/.import/wardrobe.png-67445500d100c0d821e09597f4b6463a.md5 b/.import/wardrobe.png-67445500d100c0d821e09597f4b6463a.md5 new file mode 100644 index 0000000..6c71d25 --- /dev/null +++ b/.import/wardrobe.png-67445500d100c0d821e09597f4b6463a.md5 @@ -0,0 +1,3 @@ +source_md5="f3ddc145ab52891047b639168d925bc9" +dest_md5="3afb1cf0f019a3c071a05c5995aec7d8" + diff --git a/.import/wardrobe.png-67445500d100c0d821e09597f4b6463a.stex b/.import/wardrobe.png-67445500d100c0d821e09597f4b6463a.stex new file mode 100644 index 0000000..e2899c1 Binary files /dev/null and b/.import/wardrobe.png-67445500d100c0d821e09597f4b6463a.stex differ diff --git a/Scenes/End.tscn b/Scenes/End.tscn new file mode 100644 index 0000000..34da616 --- /dev/null +++ b/Scenes/End.tscn @@ -0,0 +1,44 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://fonts/dotty.ttf" type="DynamicFontData" id=2] +[ext_resource path="res://Scripts/End.gd" type="Script" id=3] + +[sub_resource type="DynamicFont" id=1] +size = 128 +font_data = ExtResource( 2 ) + +[sub_resource type="DynamicFont" id=2] +size = 64 +font_data = ExtResource( 2 ) + +[node name="Control" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource( 3 ) + +[node name="Label" type="Label" parent="."] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -288.0 +margin_top = -76.0 +margin_right = 288.0 +margin_bottom = 4.0 +custom_fonts/font = SubResource( 1 ) +text = "Game Over!" +align = 1 +valign = 1 + +[node name="Points" type="Label" parent="."] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -128.0 +margin_top = 4.0 +margin_right = 128.0 +margin_bottom = 52.0 +custom_fonts/font = SubResource( 2 ) +text = "Points:" +align = 1 diff --git a/Scenes/Game.tscn b/Scenes/Game.tscn index ce58015..dc9d675 100644 --- a/Scenes/Game.tscn +++ b/Scenes/Game.tscn @@ -1,34 +1,66 @@ -[gd_scene load_steps=4 format=2] +[gd_scene load_steps=9 format=2] [ext_resource path="res://Sprites/tileset.tres" type="TileSet" id=1] [ext_resource path="res://Scenes/Player.tscn" type="PackedScene" id=2] [ext_resource path="res://Scenes/WaterThings/Jug.tscn" type="PackedScene" id=3] +[ext_resource path="res://fonts/dotty.ttf" type="DynamicFontData" id=4] +[ext_resource path="res://Sprites/furniture.tres" type="TileSet" id=5] +[ext_resource path="res://Scripts/Game.gd" type="Script" id=6] +[ext_resource path="res://Scenes/WaterThings/Glass.tscn" type="PackedScene" id=7] + +[sub_resource type="DynamicFont" id=1] +font_data = ExtResource( 4 ) [node name="Game" type="Node2D"] +script = ExtResource( 6 ) [node name="TileMap" type="TileMap" parent="."] tile_set = ExtResource( 1 ) cell_size = Vector2( 8, 8 ) +cell_custom_transform = Transform2D( 16, 0, 0, 16, 0, 0 ) +format = 1 +tile_data = PoolIntArray( 0, 1, 0, 1, 1, 0, 2, 1, 0, 3, 1, 0, 4, 1, 0, 5, 1, 0, 6, 1, 0, 7, 1, 0, 8, 1, 0, 9, 1, 0, 10, 1, 0, 11, 1, 0, 12, 1, 0, 13, 1, 0, 14, 1, 0, 15, 1, 0, 16, 1, 0, 17, 1, 0, 18, 1, 0, 19, 1, 0, 20, 1, 0, 21, 1, 0, 22, 1, 0, 23, 1, 0, 24, 1, 0, 25, 1, 0, 26, 1, 0, 27, 1, 0, 28, 1, 0, 29, 1, 0, 30, 1, 0, 31, 1, 0, 32, 1, 0, 33, 1, 0, 65536, 1, 0, 65537, 3, 0, 65538, 3, 0, 65539, 3, 0, 65540, 3, 0, 65541, 3, 0, 65542, 3, 0, 65543, 3, 0, 65544, 3, 0, 65545, 3, 0, 65546, 3, 0, 65547, 3, 0, 65548, 3, 0, 65549, 3, 0, 65550, 3, 0, 65551, 3, 0, 65552, 3, 0, 65553, 3, 0, 65554, 3, 0, 65555, 3, 0, 65556, 3, 0, 65557, 3, 0, 65558, 1, 0, 65559, 3, 0, 65560, 3, 0, 65561, 3, 0, 65562, 3, 0, 65563, 3, 0, 65564, 3, 0, 65565, 3, 0, 65566, 3, 0, 65567, 3, 0, 65568, 3, 0, 65569, 1, 0, 131072, 1, 0, 131073, 0, 0, 131074, 0, 0, 131075, 0, 0, 131076, 0, 0, 131077, 0, 0, 131078, 0, 0, 131079, 0, 0, 131080, 0, 0, 131081, 0, 0, 131082, 0, 0, 131083, 0, 0, 131084, 0, 0, 131085, 0, 0, 131086, 0, 0, 131087, 0, 0, 131088, 0, 0, 131089, 0, 0, 131090, 0, 0, 131091, 0, 0, 131092, 0, 0, 131093, 0, 0, 131094, 1, 0, 131095, 2, 0, 131096, 2, 0, 131097, 2, 0, 131098, 2, 0, 131099, 2, 0, 131100, 2, 0, 131101, 2, 0, 131102, 2, 0, 131103, 2, 0, 131104, 2, 0, 131105, 1, 0, 196608, 1, 0, 196609, 0, 0, 196610, 0, 0, 196611, 0, 0, 196612, 0, 0, 196613, 0, 0, 196614, 0, 0, 196615, 0, 0, 196616, 0, 0, 196617, 0, 0, 196618, 0, 0, 196619, 0, 0, 196620, 0, 0, 196621, 0, 0, 196622, 0, 0, 196623, 0, 0, 196624, 0, 0, 196625, 0, 0, 196626, 0, 0, 196627, 0, 0, 196628, 0, 0, 196629, 0, 0, 196630, 1, 0, 196631, 2, 0, 196632, 2, 0, 196633, 2, 0, 196634, 2, 0, 196635, 2, 0, 196636, 2, 0, 196637, 2, 0, 196638, 2, 0, 196639, 2, 0, 196640, 2, 0, 196641, 1, 0, 262144, 1, 0, 262145, 0, 0, 262146, 0, 0, 262147, 0, 0, 262148, 0, 0, 262149, 0, 0, 262150, 0, 0, 262151, 0, 0, 262152, 0, 0, 262153, 0, 0, 262154, 0, 0, 262155, 0, 0, 262156, 0, 0, 262157, 0, 0, 262158, 0, 0, 262159, 0, 0, 262160, 0, 0, 262161, 0, 0, 262162, 0, 0, 262163, 0, 0, 262164, 0, 0, 262165, 0, 0, 262166, 1, 0, 262167, 2, 0, 262168, 2, 0, 262169, 2, 0, 262170, 2, 0, 262171, 2, 0, 262172, 2, 0, 262173, 2, 0, 262174, 2, 0, 262175, 2, 0, 262176, 2, 0, 262177, 1, 0, 327680, 1, 0, 327681, 0, 0, 327682, 0, 0, 327683, 0, 0, 327684, 0, 0, 327685, 0, 0, 327686, 0, 0, 327687, 0, 0, 327688, 0, 0, 327689, 0, 0, 327690, 0, 0, 327691, 0, 0, 327692, 0, 0, 327693, 0, 0, 327694, 0, 0, 327695, 0, 0, 327696, 0, 0, 327697, 0, 0, 327698, 0, 0, 327699, 0, 0, 327700, 0, 0, 327701, 0, 0, 327702, 1, 0, 327703, 2, 0, 327704, 2, 0, 327705, 2, 0, 327706, 2, 0, 327707, 2, 0, 327708, 2, 0, 327709, 2, 0, 327710, 2, 0, 327711, 2, 0, 327712, 2, 0, 327713, 1, 0, 393216, 1, 0, 393217, 0, 0, 393218, 0, 0, 393219, 0, 0, 393220, 0, 0, 393221, 0, 0, 393222, 0, 0, 393223, 0, 0, 393224, 0, 0, 393225, 0, 0, 393226, 0, 0, 393227, 0, 0, 393228, 0, 0, 393229, 0, 0, 393230, 0, 0, 393231, 0, 0, 393232, 0, 0, 393233, 0, 0, 393234, 0, 0, 393235, 0, 0, 393236, 0, 0, 393237, 0, 0, 393238, 1, 0, 393239, 2, 0, 393240, 2, 0, 393241, 2, 0, 393242, 2, 0, 393243, 2, 0, 393244, 2, 0, 393245, 2, 0, 393246, 2, 0, 393247, 2, 0, 393248, 2, 0, 393249, 1, 0, 458752, 1, 0, 458753, 0, 0, 458754, 0, 0, 458755, 0, 0, 458756, 0, 0, 458757, 0, 0, 458758, 0, 0, 458759, 0, 0, 458760, 0, 0, 458761, 0, 0, 458762, 0, 0, 458763, 0, 0, 458764, 0, 0, 458765, 0, 0, 458766, 0, 0, 458767, 0, 0, 458768, 0, 0, 458769, 0, 0, 458770, 0, 0, 458771, 0, 0, 458772, 0, 0, 458773, 0, 0, 458774, 1, 0, 458775, 2, 0, 458776, 2, 0, 458777, 2, 0, 458778, 2, 0, 458779, 2, 0, 458780, 2, 0, 458781, 2, 0, 458782, 2, 0, 458783, 2, 0, 458784, 2, 0, 458785, 1, 0, 524288, 1, 0, 524289, 0, 0, 524290, 0, 0, 524291, 0, 0, 524292, 0, 0, 524293, 0, 0, 524294, 0, 0, 524295, 0, 0, 524296, 0, 0, 524297, 0, 0, 524298, 0, 0, 524299, 0, 0, 524300, 0, 0, 524301, 0, 0, 524302, 0, 0, 524303, 0, 0, 524304, 0, 0, 524305, 0, 0, 524306, 0, 0, 524307, 0, 0, 524308, 0, 0, 524309, 0, 0, 524310, 1, 0, 524311, 2, 0, 524312, 2, 0, 524313, 2, 0, 524314, 2, 0, 524315, 2, 0, 524316, 2, 0, 524317, 2, 0, 524318, 2, 0, 524319, 2, 0, 524320, 2, 0, 524321, 1, 0, 589824, 1, 0, 589825, 0, 0, 589826, 0, 0, 589827, 0, 0, 589828, 0, 0, 589829, 0, 0, 589830, 0, 0, 589831, 0, 0, 589832, 0, 0, 589833, 0, 0, 589834, 0, 0, 589835, 0, 0, 589836, 0, 0, 589837, 0, 0, 589838, 0, 0, 589839, 0, 0, 589840, 0, 0, 589841, 0, 0, 589842, 0, 0, 589843, 0, 0, 589844, 0, 0, 589845, 0, 0, 589846, 1, 0, 589847, 1, 0, 589848, 1, 0, 589849, 1, 0, 589850, 1, 0, 589851, 1, 0, 589852, 1, 0, 589853, 1, 0, 589854, 2, 0, 589855, 2, 0, 589856, 1, 0, 589857, 1, 0, 655360, 1, 0, 655361, 0, 0, 655362, 0, 0, 655363, 0, 0, 655364, 0, 0, 655365, 0, 0, 655366, 0, 0, 655367, 0, 0, 655368, 0, 0, 655369, 0, 0, 655370, 0, 0, 655371, 0, 0, 655372, 0, 0, 655373, 0, 0, 655374, 0, 0, 655375, 0, 0, 655376, 0, 0, 655377, 0, 0, 655378, 0, 0, 655379, 0, 0, 655380, 0, 0, 655381, 0, 0, 655382, 3, 0, 655383, 3, 0, 655384, 3, 0, 655385, 3, 0, 655386, 3, 0, 655387, 3, 0, 655388, 3, 0, 655389, 3, 0, 655390, 2, 0, 655391, 2, 0, 655392, 3, 0, 655393, 1, 0, 720896, 1, 0, 720897, 0, 0, 720898, 0, 0, 720899, 0, 0, 720900, 0, 0, 720901, 0, 0, 720902, 0, 0, 720903, 0, 0, 720904, 0, 0, 720905, 0, 0, 720906, 0, 0, 720907, 0, 0, 720908, 0, 0, 720909, 0, 0, 720910, 0, 0, 720911, 0, 0, 720912, 0, 0, 720913, 0, 0, 720914, 0, 0, 720915, 0, 0, 720916, 0, 0, 720917, 0, 0, 720918, 3, 0, 720919, 3, 0, 720920, 3, 0, 720921, 3, 0, 720922, 3, 0, 720923, 3, 0, 720924, 3, 0, 720925, 3, 0, 720926, 0, 0, 720927, 0, 0, 720928, 3, 0, 720929, 1, 0, 786432, 1, 0, 786433, 1, 0, 786434, 1, 0, 786435, 1, 0, 786436, 1, 0, 786437, 1, 0, 786438, 0, 0, 786439, 0, 0, 786440, 1, 0, 786441, 1, 0, 786442, 1, 0, 786443, 0, 0, 786444, 0, 0, 786445, 0, 0, 786446, 0, 0, 786447, 0, 0, 786448, 0, 0, 786449, 0, 0, 786450, 0, 0, 786451, 0, 0, 786452, 0, 0, 786453, 0, 0, 786454, 0, 0, 786455, 0, 0, 786456, 0, 0, 786457, 0, 0, 786458, 0, 0, 786459, 0, 0, 786460, 0, 0, 786461, 0, 0, 786462, 0, 0, 786463, 0, 0, 786464, 0, 0, 786465, 1, 0, 851968, 1, 0, 851969, 3, 0, 851970, 3, 0, 851971, 3, 0, 851972, 3, 0, 851973, 3, 0, 851974, 0, 0, 851975, 0, 0, 851976, 3, 0, 851977, 3, 0, 851978, 1, 0, 851979, 0, 0, 851980, 0, 0, 851981, 0, 0, 851982, 0, 0, 851983, 0, 0, 851984, 0, 0, 851985, 0, 0, 851986, 0, 0, 851987, 0, 0, 851988, 0, 0, 851989, 0, 0, 851990, 0, 0, 851991, 0, 0, 851992, 0, 0, 851993, 0, 0, 851994, 0, 0, 851995, 0, 0, 851996, 0, 0, 851997, 0, 0, 851998, 0, 0, 851999, 0, 0, 852000, 0, 0, 852001, 1, 0, 917504, 1, 0, 917505, 3, 0, 917506, 3, 0, 917507, 3, 0, 917508, 3, 0, 917509, 3, 0, 917510, 0, 0, 917511, 0, 0, 917512, 3, 0, 917513, 3, 0, 917514, 1, 0, 917515, 0, 0, 917516, 0, 0, 917517, 0, 0, 917518, 0, 0, 917519, 0, 0, 917520, 0, 0, 917521, 0, 0, 917522, 0, 0, 917523, 0, 0, 917524, 0, 0, 917525, 0, 0, 917526, 0, 0, 917527, 0, 0, 917528, 0, 0, 917529, 0, 0, 917530, 0, 0, 917531, 0, 0, 917532, 0, 0, 917533, 0, 0, 917534, 0, 0, 917535, 0, 0, 917536, 0, 0, 917537, 1, 0, 983040, 1, 0, 983041, 0, 0, 983042, 0, 0, 983043, 0, 0, 983044, 0, 0, 983045, 0, 0, 983046, 0, 0, 983047, 0, 0, 983048, 0, 0, 983049, 0, 0, 983050, 1, 0, 983051, 0, 0, 983052, 0, 0, 983053, 0, 0, 983054, 0, 0, 983055, 0, 0, 983056, 0, 0, 983057, 0, 0, 983058, 0, 0, 983059, 0, 0, 983060, 0, 0, 983061, 0, 0, 983062, 0, 0, 983063, 0, 0, 983064, 0, 0, 983065, 0, 0, 983066, 0, 0, 983067, 0, 0, 983068, 0, 0, 983069, 0, 0, 983070, 0, 0, 983071, 0, 0, 983072, 0, 0, 983073, 1, 0, 1048576, 1, 0, 1048577, 0, 0, 1048578, 0, 0, 1048579, 0, 0, 1048580, 0, 0, 1048581, 0, 0, 1048582, 0, 0, 1048583, 0, 0, 1048584, 0, 0, 1048585, 0, 0, 1048586, 1, 0, 1048587, 0, 0, 1048588, 0, 0, 1048589, 0, 0, 1048590, 0, 0, 1048591, 0, 0, 1048592, 0, 0, 1048593, 0, 0, 1048594, 0, 0, 1048595, 0, 0, 1048596, 0, 0, 1048597, 0, 0, 1048598, 0, 0, 1048599, 0, 0, 1048600, 0, 0, 1048601, 0, 0, 1048602, 0, 0, 1048603, 0, 0, 1048604, 0, 0, 1048605, 0, 0, 1048606, 0, 0, 1048607, 0, 0, 1048608, 0, 0, 1048609, 1, 0, 1114112, 1, 0, 1114113, 0, 0, 1114114, 0, 0, 1114115, 0, 0, 1114116, 0, 0, 1114117, 0, 0, 1114118, 0, 0, 1114119, 0, 0, 1114120, 0, 0, 1114121, 0, 0, 1114122, 1, 0, 1114123, 0, 0, 1114124, 0, 0, 1114125, 0, 0, 1114126, 0, 0, 1114127, 0, 0, 1114128, 0, 0, 1114129, 0, 0, 1114130, 0, 0, 1114131, 0, 0, 1114132, 0, 0, 1114133, 0, 0, 1114134, 0, 0, 1114135, 0, 0, 1114136, 0, 0, 1114137, 0, 0, 1114138, 0, 0, 1114139, 0, 0, 1114140, 0, 0, 1114141, 0, 0, 1114142, 0, 0, 1114143, 0, 0, 1114144, 0, 0, 1114145, 1, 0, 1179648, 1, 0, 1179649, 0, 0, 1179650, 0, 0, 1179651, 0, 0, 1179652, 0, 0, 1179653, 0, 0, 1179654, 0, 0, 1179655, 0, 0, 1179656, 0, 0, 1179657, 0, 0, 1179658, 1, 0, 1179659, 0, 0, 1179660, 0, 0, 1179661, 0, 0, 1179662, 0, 0, 1179663, 0, 0, 1179664, 0, 0, 1179665, 0, 0, 1179666, 0, 0, 1179667, 0, 0, 1179668, 0, 0, 1179669, 0, 0, 1179670, 0, 0, 1179671, 0, 0, 1179672, 0, 0, 1179673, 0, 0, 1179674, 0, 0, 1179675, 0, 0, 1179676, 0, 0, 1179677, 0, 0, 1179678, 0, 0, 1179679, 0, 0, 1179680, 0, 0, 1179681, 1, 0, 1245184, 1, 0, 1245185, 1, 0, 1245186, 1, 0, 1245187, 1, 0, 1245188, 1, 0, 1245189, 1, 0, 1245190, 1, 0, 1245191, 1, 0, 1245192, 1, 0, 1245193, 1, 0, 1245194, 1, 0, 1245195, 1, 0, 1245196, 1, 0, 1245197, 1, 0, 1245198, 1, 0, 1245199, 1, 0, 1245200, 1, 0, 1245201, 1, 0, 1245202, 1, 0, 1245203, 1, 0, 1245204, 1, 0, 1245205, 1, 0, 1245206, 1, 0, 1245207, 1, 0, 1245208, 1, 0, 1245209, 1, 0, 1245210, 1, 0, 1245211, 1, 0, 1245212, 1, 0, 1245213, 1, 0, 1245214, 1, 0, 1245215, 1, 0, 1245216, 1, 0, 1245217, 1, 0 ) + +[node name="Furniture" type="TileMap" parent="."] +tile_set = ExtResource( 5 ) +cell_size = Vector2( 8, 8 ) +cell_quadrant_size = 8 cell_custom_transform = Transform2D( 8, 0, 0, 8, 0, 0 ) show_collision = true format = 1 -tile_data = PoolIntArray( 0, 1, 0, 1, 1, 0, 2, 1, 0, 3, 1, 0, 4, 1, 0, 5, 1, 0, 6, 1, 0, 7, 1, 0, 8, 1, 0, 9, 1, 0, 10, 1, 0, 11, 1, 0, 12, 1, 0, 13, 1, 0, 14, 1, 0, 15, 1, 0, 16, 1, 0, 17, 1, 0, 18, 1, 0, 19, 1, 0, 20, 1, 0, 21, 1, 0, 22, 1, 0, 23, 1, 0, 24, 1, 0, 25, 1, 0, 26, 1, 0, 27, 1, 0, 28, 1, 0, 29, 1, 0, 30, 1, 0, 31, 1, 0, 32, 1, 0, 33, 1, 0, 65536, 1, 0, 65537, 3, 0, 65538, 3, 0, 65539, 3, 0, 65540, 3, 0, 65541, 3, 0, 65542, 3, 0, 65543, 3, 0, 65544, 3, 0, 65545, 3, 0, 65546, 3, 0, 65547, 3, 0, 65548, 3, 0, 65549, 3, 0, 65550, 3, 0, 65551, 3, 0, 65552, 3, 0, 65553, 3, 0, 65554, 3, 0, 65555, 3, 0, 65556, 3, 0, 65557, 3, 0, 65558, 1, 0, 65559, 3, 0, 65560, 3, 0, 65561, 3, 0, 65562, 3, 0, 65563, 3, 0, 65564, 3, 0, 65565, 3, 0, 65566, 3, 0, 65567, 3, 0, 65568, 3, 0, 65569, 1, 0, 131072, 1, 0, 131073, 0, 0, 131074, 0, 0, 131075, 0, 0, 131076, 0, 0, 131077, 0, 0, 131078, 0, 0, 131079, 0, 0, 131080, 0, 0, 131081, 0, 0, 131082, 0, 0, 131083, 0, 0, 131084, 0, 0, 131085, 0, 0, 131086, 0, 0, 131087, 0, 0, 131088, 0, 0, 131089, 0, 0, 131090, 0, 0, 131091, 0, 0, 131092, 0, 0, 131093, 0, 0, 131094, 1, 0, 131095, 2, 0, 131096, 2, 0, 131097, 2, 0, 131098, 2, 0, 131099, 2, 0, 131100, 2, 0, 131101, 2, 0, 131102, 2, 0, 131103, 2, 0, 131104, 2, 0, 131105, 1, 0, 196608, 1, 0, 196609, 0, 0, 196610, 0, 0, 196611, 0, 0, 196612, 0, 0, 196613, 0, 0, 196614, 0, 0, 196615, 0, 0, 196616, 0, 0, 196617, 0, 0, 196618, 0, 0, 196619, 0, 0, 196620, 0, 0, 196621, 0, 0, 196622, 0, 0, 196623, 0, 0, 196624, 0, 0, 196625, 0, 0, 196626, 0, 0, 196627, 0, 0, 196628, 0, 0, 196629, 0, 0, 196630, 1, 0, 196631, 2, 0, 196632, 2, 0, 196633, 2, 0, 196634, 2, 0, 196635, 2, 0, 196636, 2, 0, 196637, 2, 0, 196638, 2, 0, 196639, 2, 0, 196640, 2, 0, 196641, 1, 0, 262144, 1, 0, 262145, 0, 0, 262146, 0, 0, 262147, 0, 0, 262148, 0, 0, 262149, 0, 0, 262150, 0, 0, 262151, 0, 0, 262152, 0, 0, 262153, 0, 0, 262154, 0, 0, 262155, 0, 0, 262156, 0, 0, 262157, 0, 0, 262158, 0, 0, 262159, 0, 0, 262160, 0, 0, 262161, 0, 0, 262162, 0, 0, 262163, 0, 0, 262164, 0, 0, 262165, 0, 0, 262166, 1, 0, 262167, 2, 0, 262168, 2, 0, 262169, 2, 0, 262170, 2, 0, 262171, 2, 0, 262172, 2, 0, 262173, 2, 0, 262174, 2, 0, 262175, 2, 0, 262176, 2, 0, 262177, 1, 0, 327680, 1, 0, 327681, 0, 0, 327682, 0, 0, 327683, 0, 0, 327684, 0, 0, 327685, 0, 0, 327686, 0, 0, 327687, 0, 0, 327688, 0, 0, 327689, 0, 0, 327690, 0, 0, 327691, 0, 0, 327692, 0, 0, 327693, 0, 0, 327694, 0, 0, 327695, 0, 0, 327696, 0, 0, 327697, 0, 0, 327698, 0, 0, 327699, 0, 0, 327700, 0, 0, 327701, 0, 0, 327702, 1, 0, 327703, 2, 0, 327704, 2, 0, 327705, 2, 0, 327706, 2, 0, 327707, 2, 0, 327708, 2, 0, 327709, 2, 0, 327710, 2, 0, 327711, 2, 0, 327712, 2, 0, 327713, 1, 0, 393216, 1, 0, 393217, 0, 0, 393218, 0, 0, 393219, 0, 0, 393220, 0, 0, 393221, 0, 0, 393222, 0, 0, 393223, 0, 0, 393224, 0, 0, 393225, 0, 0, 393226, 0, 0, 393227, 0, 0, 393228, 0, 0, 393229, 0, 0, 393230, 0, 0, 393231, 0, 0, 393232, 0, 0, 393233, 0, 0, 393234, 0, 0, 393235, 0, 0, 393236, 0, 0, 393237, 0, 0, 393238, 1, 0, 393239, 2, 0, 393240, 2, 0, 393241, 2, 0, 393242, 2, 0, 393243, 2, 0, 393244, 2, 0, 393245, 2, 0, 393246, 2, 0, 393247, 2, 0, 393248, 2, 0, 393249, 1, 0, 458752, 1, 0, 458753, 0, 0, 458754, 0, 0, 458755, 0, 0, 458756, 0, 0, 458757, 0, 0, 458758, 0, 0, 458759, 0, 0, 458760, 0, 0, 458761, 0, 0, 458762, 0, 0, 458763, 0, 0, 458764, 0, 0, 458765, 0, 0, 458766, 0, 0, 458767, 0, 0, 458768, 0, 0, 458769, 0, 0, 458770, 0, 0, 458771, 0, 0, 458772, 0, 0, 458773, 0, 0, 458774, 1, 0, 458775, 2, 0, 458776, 2, 0, 458777, 2, 0, 458778, 2, 0, 458779, 2, 0, 458780, 2, 0, 458781, 2, 0, 458782, 2, 0, 458783, 2, 0, 458784, 2, 0, 458785, 1, 0, 524288, 1, 0, 524289, 0, 0, 524290, 0, 0, 524291, 0, 0, 524292, 0, 0, 524293, 0, 0, 524294, 0, 0, 524295, 0, 0, 524296, 0, 0, 524297, 0, 0, 524298, 0, 0, 524299, 0, 0, 524300, 0, 0, 524301, 0, 0, 524302, 0, 0, 524303, 0, 0, 524304, 0, 0, 524305, 0, 0, 524306, 0, 0, 524307, 0, 0, 524308, 0, 0, 524309, 0, 0, 524310, 1, 0, 524311, 2, 0, 524312, 2, 0, 524313, 2, 0, 524314, 2, 0, 524315, 2, 0, 524316, 2, 0, 524317, 2, 0, 524318, 2, 0, 524319, 2, 0, 524320, 2, 0, 524321, 1, 0, 589824, 1, 0, 589825, 0, 0, 589826, 0, 0, 589827, 0, 0, 589828, 0, 0, 589829, 0, 0, 589830, 0, 0, 589831, 0, 0, 589832, 0, 0, 589833, 0, 0, 589834, 0, 0, 589835, 0, 0, 589836, 0, 0, 589837, 0, 0, 589838, 0, 0, 589839, 0, 0, 589840, 0, 0, 589841, 0, 0, 589842, 0, 0, 589843, 0, 0, 589844, 0, 0, 589845, 0, 0, 589846, 1, 0, 589847, 1, 0, 589848, 1, 0, 589849, 1, 0, 589850, 1, 0, 589851, 1, 0, 589852, 1, 0, 589853, 1, 0, 589854, 2, 0, 589855, 2, 0, 589856, 1, 0, 589857, 1, 0, 655360, 1, 0, 655361, 0, 0, 655362, 0, 0, 655363, 0, 0, 655364, 0, 0, 655365, 0, 0, 655366, 0, 0, 655367, 0, 0, 655368, 0, 0, 655369, 0, 0, 655370, 0, 0, 655371, 0, 0, 655372, 0, 0, 655373, 0, 0, 655374, 0, 0, 655375, 0, 0, 655376, 0, 0, 655377, 0, 0, 655378, 0, 0, 655379, 0, 0, 655380, 0, 0, 655381, 0, 0, 655382, 3, 0, 655383, 3, 0, 655384, 3, 0, 655385, 3, 0, 655386, 3, 0, 655387, 3, 0, 655388, 3, 0, 655389, 3, 0, 655390, 0, 0, 655391, 0, 0, 655392, 3, 0, 655393, 1, 0, 720896, 1, 0, 720897, 0, 0, 720898, 0, 0, 720899, 0, 0, 720900, 0, 0, 720901, 0, 0, 720902, 0, 0, 720903, 0, 0, 720904, 0, 0, 720905, 0, 0, 720906, 0, 0, 720907, 0, 0, 720908, 0, 0, 720909, 0, 0, 720910, 0, 0, 720911, 0, 0, 720912, 0, 0, 720913, 0, 0, 720914, 0, 0, 720915, 0, 0, 720916, 0, 0, 720917, 0, 0, 720918, 0, 0, 720919, 0, 0, 720920, 0, 0, 720921, 0, 0, 720922, 0, 0, 720923, 0, 0, 720924, 0, 0, 720925, 0, 0, 720926, 0, 0, 720927, 0, 0, 720928, 0, 0, 720929, 1, 0, 786432, 1, 0, 786433, 0, 0, 786434, 0, 0, 786435, 0, 0, 786436, 0, 0, 786437, 0, 0, 786438, 0, 0, 786439, 0, 0, 786440, 0, 0, 786441, 0, 0, 786442, 0, 0, 786443, 0, 0, 786444, 0, 0, 786445, 0, 0, 786446, 0, 0, 786447, 0, 0, 786448, 0, 0, 786449, 0, 0, 786450, 0, 0, 786451, 0, 0, 786452, 0, 0, 786453, 0, 0, 786454, 0, 0, 786455, 0, 0, 786456, 0, 0, 786457, 0, 0, 786458, 0, 0, 786459, 0, 0, 786460, 0, 0, 786461, 0, 0, 786462, 0, 0, 786463, 0, 0, 786464, 0, 0, 786465, 1, 0, 851968, 1, 0, 851969, 0, 0, 851970, 0, 0, 851971, 0, 0, 851972, 0, 0, 851973, 0, 0, 851974, 0, 0, 851975, 0, 0, 851976, 0, 0, 851977, 0, 0, 851978, 0, 0, 851979, 0, 0, 851980, 0, 0, 851981, 0, 0, 851982, 0, 0, 851983, 0, 0, 851984, 0, 0, 851985, 0, 0, 851986, 0, 0, 851987, 0, 0, 851988, 0, 0, 851989, 0, 0, 851990, 0, 0, 851991, 0, 0, 851992, 0, 0, 851993, 0, 0, 851994, 0, 0, 851995, 0, 0, 851996, 0, 0, 851997, 0, 0, 851998, 0, 0, 851999, 0, 0, 852000, 0, 0, 852001, 1, 0, 917504, 1, 0, 917505, 0, 0, 917506, 0, 0, 917507, 0, 0, 917508, 0, 0, 917509, 0, 0, 917510, 0, 0, 917511, 0, 0, 917512, 0, 0, 917513, 0, 0, 917514, 0, 0, 917515, 0, 0, 917516, 0, 0, 917517, 0, 0, 917518, 0, 0, 917519, 0, 0, 917520, 0, 0, 917521, 0, 0, 917522, 0, 0, 917523, 0, 0, 917524, 0, 0, 917525, 0, 0, 917526, 0, 0, 917527, 0, 0, 917528, 0, 0, 917529, 0, 0, 917530, 0, 0, 917531, 0, 0, 917532, 0, 0, 917533, 0, 0, 917534, 0, 0, 917535, 0, 0, 917536, 0, 0, 917537, 1, 0, 983040, 1, 0, 983041, 0, 0, 983042, 0, 0, 983043, 0, 0, 983044, 0, 0, 983045, 0, 0, 983046, 0, 0, 983047, 0, 0, 983048, 0, 0, 983049, 0, 0, 983050, 0, 0, 983051, 0, 0, 983052, 0, 0, 983053, 0, 0, 983054, 0, 0, 983055, 0, 0, 983056, 0, 0, 983057, 0, 0, 983058, 0, 0, 983059, 0, 0, 983060, 0, 0, 983061, 0, 0, 983062, 0, 0, 983063, 0, 0, 983064, 0, 0, 983065, 0, 0, 983066, 0, 0, 983067, 0, 0, 983068, 0, 0, 983069, 0, 0, 983070, 0, 0, 983071, 0, 0, 983072, 0, 0, 983073, 1, 0, 1048576, 1, 0, 1048577, 0, 0, 1048578, 0, 0, 1048579, 0, 0, 1048580, 0, 0, 1048581, 0, 0, 1048582, 0, 0, 1048583, 0, 0, 1048584, 0, 0, 1048585, 0, 0, 1048586, 0, 0, 1048587, 0, 0, 1048588, 0, 0, 1048589, 0, 0, 1048590, 0, 0, 1048591, 0, 0, 1048592, 0, 0, 1048593, 0, 0, 1048594, 0, 0, 1048595, 0, 0, 1048596, 0, 0, 1048597, 0, 0, 1048598, 0, 0, 1048599, 0, 0, 1048600, 0, 0, 1048601, 0, 0, 1048602, 0, 0, 1048603, 0, 0, 1048604, 0, 0, 1048605, 0, 0, 1048606, 0, 0, 1048607, 0, 0, 1048608, 0, 0, 1048609, 1, 0, 1114112, 1, 0, 1114113, 0, 0, 1114114, 0, 0, 1114115, 0, 0, 1114116, 0, 0, 1114117, 0, 0, 1114118, 0, 0, 1114119, 0, 0, 1114120, 0, 0, 1114121, 0, 0, 1114122, 0, 0, 1114123, 0, 0, 1114124, 0, 0, 1114125, 0, 0, 1114126, 0, 0, 1114127, 0, 0, 1114128, 0, 0, 1114129, 0, 0, 1114130, 0, 0, 1114131, 0, 0, 1114132, 0, 0, 1114133, 0, 0, 1114134, 0, 0, 1114135, 0, 0, 1114136, 0, 0, 1114137, 0, 0, 1114138, 0, 0, 1114139, 0, 0, 1114140, 0, 0, 1114141, 0, 0, 1114142, 0, 0, 1114143, 0, 0, 1114144, 0, 0, 1114145, 1, 0, 1179648, 1, 0, 1179649, 0, 0, 1179650, 0, 0, 1179651, 0, 0, 1179652, 0, 0, 1179653, 0, 0, 1179654, 0, 0, 1179655, 0, 0, 1179656, 0, 0, 1179657, 0, 0, 1179658, 0, 0, 1179659, 0, 0, 1179660, 0, 0, 1179661, 0, 0, 1179662, 0, 0, 1179663, 0, 0, 1179664, 0, 0, 1179665, 0, 0, 1179666, 0, 0, 1179667, 0, 0, 1179668, 0, 0, 1179669, 0, 0, 1179670, 0, 0, 1179671, 0, 0, 1179672, 0, 0, 1179673, 0, 0, 1179674, 0, 0, 1179675, 0, 0, 1179676, 0, 0, 1179677, 0, 0, 1179678, 0, 0, 1179679, 0, 0, 1179680, 0, 0, 1179681, 1, 0, 1245184, 1, 0, 1245185, 1, 0, 1245186, 1, 0, 1245187, 1, 0, 1245188, 1, 0, 1245189, 1, 0, 1245190, 1, 0, 1245191, 1, 0, 1245192, 1, 0, 1245193, 1, 0, 1245194, 1, 0, 1245195, 1, 0, 1245196, 1, 0, 1245197, 1, 0, 1245198, 1, 0, 1245199, 1, 0, 1245200, 1, 0, 1245201, 1, 0, 1245202, 1, 0, 1245203, 1, 0, 1245204, 1, 0, 1245205, 1, 0, 1245206, 1, 0, 1245207, 1, 0, 1245208, 1, 0, 1245209, 1, 0, 1245210, 1, 0, 1245211, 1, 0, 1245212, 1, 0, 1245213, 1, 0, 1245214, 1, 0, 1245215, 1, 0, 1245216, 1, 0, 1245217, 1, 0 ) +tile_data = PoolIntArray( 524300, 3, 0, 917505, 0, 0 ) [node name="WaterThings" type="Node2D" parent="."] [node name="Jug" parent="WaterThings" instance=ExtResource( 3 )] -position = Vector2( 125, 24 ) +position = Vector2( 237, 20 ) [node name="Jug2" parent="WaterThings" instance=ExtResource( 3 )] +position = Vector2( 15, 109 ) -[node name="Jug3" parent="WaterThings" instance=ExtResource( 3 )] -position = Vector2( 77, 84 ) +[node name="Glass" parent="WaterThings" instance=ExtResource( 7 )] +position = Vector2( 102, 68 ) -[node name="Jug4" parent="WaterThings" instance=ExtResource( 3 )] -position = Vector2( 36, 42 ) +[node name="Glass2" parent="WaterThings" instance=ExtResource( 7 )] +position = Vector2( 144, 52 ) -[node name="Jug5" parent="WaterThings" instance=ExtResource( 3 )] -position = Vector2( 160, 56 ) +[node name="Glass3" parent="WaterThings" instance=ExtResource( 7 )] +position = Vector2( 116, 78 ) + +[node name="Glass4" parent="WaterThings" instance=ExtResource( 7 )] +position = Vector2( 158, 63 ) + +[node name="Glass5" parent="WaterThings" instance=ExtResource( 7 )] +position = Vector2( 73, 45 ) + +[node name="Glass6" parent="WaterThings" instance=ExtResource( 7 )] +position = Vector2( 115, 29 ) + +[node name="Glass7" parent="WaterThings" instance=ExtResource( 7 )] +position = Vector2( 87, 55 ) + +[node name="Glass8" parent="WaterThings" instance=ExtResource( 7 )] +position = Vector2( 129, 40 ) [node name="Player" parent="." instance=ExtResource( 2 )] position = Vector2( 136, 80 ) @@ -37,3 +69,28 @@ position = Vector2( 136, 80 ) position = Vector2( 136, 80 ) current = true zoom = Vector2( 0.265, 0.265 ) + +[node name="UI" type="Control" parent="."] +margin_right = 272.0 +margin_bottom = 160.0 +__meta__ = { +"_edit_lock_": true +} + +[node name="TimeLeft" type="Label" parent="UI"] +margin_right = 73.0 +margin_bottom = 14.0 +custom_fonts/font = SubResource( 1 ) +text = "Time Left: " + +[node name="Points" type="Label" parent="UI"] +margin_top = 8.0 +margin_right = 73.0 +margin_bottom = 22.0 +custom_fonts/font = SubResource( 1 ) +text = "Points:" + +[node name="Timer" type="Timer" parent="."] +wait_time = 30.0 +one_shot = true +autostart = true diff --git a/Scenes/Player.tscn b/Scenes/Player.tscn index 8143faa..70cda4c 100644 --- a/Scenes/Player.tscn +++ b/Scenes/Player.tscn @@ -1,10 +1,13 @@ -[gd_scene load_steps=6 format=2] +[gd_scene load_steps=7 format=2] [ext_resource path="res://Sprites/player.png" type="Texture" id=1] [ext_resource path="res://Scripts/Player.gd" type="Script" id=2] -[sub_resource type="RectangleShape2D" id=1] -extents = Vector2( 5, 10.2143 ) +[sub_resource type="CircleShape2D" id=5] +radius = 6.0 + +[sub_resource type="RectangleShape2D" id=4] +extents = Vector2( 5.71429, 11.4286 ) [sub_resource type="Animation" id=2] length = 0.001 @@ -46,9 +49,16 @@ script = ExtResource( 2 ) texture = ExtResource( 1 ) [node name="CollisionShape2D" type="CollisionShape2D" parent="."] -position = Vector2( 0, 1.64286 ) +position = Vector2( 0, 5.92858 ) scale = Vector2( 1, 1 ) -shape = SubResource( 1 ) +shape = SubResource( 5 ) + +[node name="PlayerArea" type="Area2D" parent="."] +scale = Vector2( 1, 1 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="PlayerArea"] +position = Vector2( -1.70299e-07, -3.40598e-07 ) +shape = SubResource( 4 ) [node name="AnimationPlayer" type="AnimationPlayer" parent="."] anims/RESET = SubResource( 2 ) diff --git a/Scenes/Start.tscn b/Scenes/Start.tscn new file mode 100644 index 0000000..fa41939 --- /dev/null +++ b/Scenes/Start.tscn @@ -0,0 +1,86 @@ +[gd_scene load_steps=13 format=2] + +[ext_resource path="res://fonts/game over.ttf" type="DynamicFontData" id=1] +[ext_resource path="res://Sprites/bg.png" type="Texture" id=2] +[ext_resource path="res://fonts/dotty.ttf" type="DynamicFontData" id=3] +[ext_resource path="res://Scripts/Start.gd" type="Script" id=4] + +[sub_resource type="DynamicFont" id=1] +size = 64 +font_data = ExtResource( 1 ) + +[sub_resource type="StyleBoxEmpty" id=2] + +[sub_resource type="StyleBoxEmpty" id=3] + +[sub_resource type="StyleBoxEmpty" id=4] + +[sub_resource type="StyleBoxEmpty" id=5] + +[sub_resource type="StyleBoxEmpty" id=6] + +[sub_resource type="DynamicFont" id=7] +size = 128 +font_data = ExtResource( 1 ) + +[sub_resource type="DynamicFont" id=8] +size = 64 +font_data = ExtResource( 3 ) + +[node name="Control" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource( 4 ) + +[node name="Background" type="TextureRect" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +texture = ExtResource( 2 ) +expand = true + +[node name="Button" type="Button" parent="."] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -80.0 +margin_top = 84.0 +margin_right = 80.0 +margin_bottom = 130.0 +custom_colors/font_color_hover = Color( 0.290196, 0.517647, 1, 1 ) +custom_fonts/font = SubResource( 1 ) +custom_styles/hover = SubResource( 2 ) +custom_styles/pressed = SubResource( 3 ) +custom_styles/focus = SubResource( 4 ) +custom_styles/disabled = SubResource( 5 ) +custom_styles/normal = SubResource( 6 ) +text = "Start" + +[node name="Label" type="Label" parent="."] +anchor_left = 0.5 +anchor_right = 0.5 +margin_left = -200.0 +margin_top = 64.0 +margin_right = 200.0 +margin_bottom = 144.0 +custom_fonts/font = SubResource( 7 ) +text = "H2Grow" + +[node name="Label2" type="Label" parent="."] +anchor_left = 0.5 +anchor_top = 1.0 +anchor_right = 0.5 +anchor_bottom = 1.0 +margin_left = -512.0 +margin_top = -64.0 +margin_right = 512.0 +custom_colors/font_color = Color( 1, 0.262745, 0.262745, 1 ) +custom_colors/font_outline_modulate = Color( 1, 1, 1, 1 ) +custom_fonts/font = SubResource( 8 ) +text = "Read instructions on itch.io before playing the game!" +align = 1 +valign = 1 +autowrap = true +clip_text = true + +[connection signal="pressed" from="Button" to="." method="_on_Button_pressed"] diff --git a/Scenes/WaterThings/Glass.tscn b/Scenes/WaterThings/Glass.tscn new file mode 100644 index 0000000..b5c6198 --- /dev/null +++ b/Scenes/WaterThings/Glass.tscn @@ -0,0 +1,28 @@ +[gd_scene load_steps=6 format=2] + +[ext_resource path="res://Scripts/WaterThing.gd" type="Script" id=1] +[ext_resource path="res://Sprites/Water/Glass.png" type="Texture" id=2] +[ext_resource path="res://Sounds/Sfxr/break.sfxr" type="AudioStream" id=3] +[ext_resource path="res://Sounds/Sfxr/punch.sfxr" type="AudioStream" id=4] + +[sub_resource type="RectangleShape2D" id=1] +extents = Vector2( 5, 6 ) + +[node name="Glass" type="Area2D"] +scale = Vector2( 0.5, 0.5 ) +script = ExtResource( 1 ) + +[node name="Sprite" type="Sprite" parent="."] +texture = ExtResource( 2 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource( 1 ) + +[node name="PunchPlayer" type="AudioStreamPlayer" parent="."] +stream = ExtResource( 4 ) + +[node name="BreakPlayer" type="AudioStreamPlayer" parent="."] +stream = ExtResource( 3 ) + +[connection signal="area_entered" from="." to="." method="_on_body_entered"] +[connection signal="area_exited" from="." to="." method="_on_body_exited"] diff --git a/Scenes/WaterThings/Jug.tscn b/Scenes/WaterThings/Jug.tscn index 2c19b7f..0e9e5c3 100644 --- a/Scenes/WaterThings/Jug.tscn +++ b/Scenes/WaterThings/Jug.tscn @@ -1,7 +1,9 @@ -[gd_scene load_steps=4 format=2] +[gd_scene load_steps=6 format=2] [ext_resource path="res://Sprites/Water/Jug.png" type="Texture" id=1] [ext_resource path="res://Scripts/WaterThing.gd" type="Script" id=2] +[ext_resource path="res://Sounds/Sfxr/punch.sfxr" type="AudioStream" id=3] +[ext_resource path="res://Sounds/Sfxr/break.sfxr" type="AudioStream" id=4] [sub_resource type="RectangleShape2D" id=1] extents = Vector2( 5, 6 ) @@ -17,5 +19,11 @@ texture = ExtResource( 1 ) position = Vector2( 1, 0 ) shape = SubResource( 1 ) -[connection signal="body_entered" from="." to="." method="_on_body_entered"] -[connection signal="body_exited" from="." to="." method="_on_body_exited"] +[node name="PunchPlayer" type="AudioStreamPlayer" parent="."] +stream = ExtResource( 3 ) + +[node name="BreakPlayer" type="AudioStreamPlayer" parent="."] +stream = ExtResource( 4 ) + +[connection signal="area_entered" from="." to="." method="_on_body_entered"] +[connection signal="area_exited" from="." to="." method="_on_body_exited"] diff --git a/Scripts/End.gd b/Scripts/End.gd new file mode 100644 index 0000000..e6cc109 --- /dev/null +++ b/Scripts/End.gd @@ -0,0 +1,4 @@ +extends Control + +func _ready(): + $Points.text += " " + str(Utils.points) diff --git a/Scripts/Game.gd b/Scripts/Game.gd new file mode 100644 index 0000000..5ffe693 --- /dev/null +++ b/Scripts/Game.gd @@ -0,0 +1,7 @@ +extends Node2D + +func _process(delta): + $UI/TimeLeft.text = "Time left: " + str($Timer.time_left) + $UI/Points.text = "Points: " + str(Utils.points) + if ($Timer.time_left == 0): + get_tree().change_scene("res://Scenes/End.tscn") diff --git a/Scripts/Player.gd b/Scripts/Player.gd index c1452bd..cd6a6e8 100644 --- a/Scripts/Player.gd +++ b/Scripts/Player.gd @@ -9,6 +9,7 @@ func _ready(): func _physics_process(delta): velocity = Vector2() + # Input if Input.is_action_pressed("down"): velocity.y += speed if Input.is_action_pressed("up"): @@ -17,7 +18,8 @@ func _physics_process(delta): velocity.x -= speed if Input.is_action_pressed("right"): velocity.x += speed - + + # Animation if Input.is_action_pressed("right") || Input.is_action_pressed("left") \ || Input.is_action_pressed("up") || Input.is_action_pressed("down"): $AnimationPlayer.play("Walk") diff --git a/Scripts/Start.gd b/Scripts/Start.gd new file mode 100644 index 0000000..9dd1915 --- /dev/null +++ b/Scripts/Start.gd @@ -0,0 +1,4 @@ +extends Control + +func _on_Button_pressed(): + get_tree().change_scene("res://Scenes/Game.tscn") diff --git a/Scripts/Utils.gd b/Scripts/Utils.gd new file mode 100644 index 0000000..b210d13 --- /dev/null +++ b/Scripts/Utils.gd @@ -0,0 +1,3 @@ +extends Node + +var points = 0 diff --git a/Scripts/WaterThing.gd b/Scripts/WaterThing.gd index 9e9d1ec..3842412 100644 --- a/Scripts/WaterThing.gd +++ b/Scripts/WaterThing.gd @@ -1,7 +1,7 @@ extends Area2D var broken = false -var hits_left = 2 +var hits_left = 3 var player = false var player_body = null @@ -13,12 +13,12 @@ func replace_numbers(name: String) -> String: return new_name func _on_body_entered(body): - if body.name == "Player" and !broken: + if body.get_parent().name == "Player": player = true - player_body = body + player_body = body.get_parent() func _on_body_exited(body): - if body.name == "Player" and !broken: + if body.get_parent().name == "Player": player = false player_body = null @@ -26,8 +26,16 @@ func _process(delta): if player && player_body != null: if Input.is_action_just_pressed("punch"): if hits_left > 0: + $PunchPlayer.play() hits_left -= 1 - if hits_left == 0 && broken == false: + if hits_left == 0 && !broken: + # Mod Thing + $BreakPlayer.play() $Sprite.texture = load("res://Sprites/Water/Broken/" + replace_numbers(name) + ".png") - player_body.scale += Vector2(0.05, 0.05) broken = true + # Mod Player + player_body.scale += Vector2(0.05, 0.05) + player_body.get_node("CollisionShape2D").scale -= Vector2(0.05, 0.05) + player_body.speed -= 0.5 + # Add points + Utils.points += 1 diff --git a/Sounds/Sfxr/break.sfxr b/Sounds/Sfxr/break.sfxr new file mode 100644 index 0000000..737ead2 Binary files /dev/null and b/Sounds/Sfxr/break.sfxr differ diff --git a/Sounds/Sfxr/break.sfxr.import b/Sounds/Sfxr/break.sfxr.import new file mode 100644 index 0000000..54d1554 --- /dev/null +++ b/Sounds/Sfxr/break.sfxr.import @@ -0,0 +1,16 @@ +[remap] + +importer="com.timothyqiu.gdfxr.importer" +type="AudioStreamSample" +path="res://.import/break.sfxr-c1c1594a22628fd278421b7f8a79a149.sample" + +[deps] + +source_file="res://Sounds/Sfxr/break.sfxr" +dest_files=[ "res://.import/break.sfxr-c1c1594a22628fd278421b7f8a79a149.sample" ] + +[params] + +loop=false +bit_depth=0 +sample_rate=0 diff --git a/Sounds/Sfxr/punch.sfxr b/Sounds/Sfxr/punch.sfxr new file mode 100644 index 0000000..35a6149 Binary files /dev/null and b/Sounds/Sfxr/punch.sfxr differ diff --git a/Sounds/Sfxr/punch.sfxr.import b/Sounds/Sfxr/punch.sfxr.import new file mode 100644 index 0000000..e4e38eb --- /dev/null +++ b/Sounds/Sfxr/punch.sfxr.import @@ -0,0 +1,16 @@ +[remap] + +importer="com.timothyqiu.gdfxr.importer" +type="AudioStreamSample" +path="res://.import/punch.sfxr-ce24cf25ac6de08473bbda5685c58ae5.sample" + +[deps] + +source_file="res://Sounds/Sfxr/punch.sfxr" +dest_files=[ "res://.import/punch.sfxr-ce24cf25ac6de08473bbda5685c58ae5.sample" ] + +[params] + +loop=false +bit_depth=0 +sample_rate=0 diff --git a/Sprites/Water/Broken/Glass.png b/Sprites/Water/Broken/Glass.png new file mode 100644 index 0000000..b1d362c Binary files /dev/null and b/Sprites/Water/Broken/Glass.png differ diff --git a/Sprites/Water/Broken/Glass.png.import b/Sprites/Water/Broken/Glass.png.import new file mode 100644 index 0000000..9896134 --- /dev/null +++ b/Sprites/Water/Broken/Glass.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/Glass.png-3b2015c0dd629c60d3c1b09d9013c59c.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Sprites/Water/Broken/Glass.png" +dest_files=[ "res://.import/Glass.png-3b2015c0dd629c60d3c1b09d9013c59c.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=false +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=false +svg/scale=1.0 diff --git a/Sprites/Water/Glass.png b/Sprites/Water/Glass.png new file mode 100644 index 0000000..e8e3fe9 Binary files /dev/null and b/Sprites/Water/Glass.png differ diff --git a/Sprites/Water/Glass.png.import b/Sprites/Water/Glass.png.import new file mode 100644 index 0000000..f8bfe5d --- /dev/null +++ b/Sprites/Water/Glass.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/Glass.png-8678c0300c4ceb28841173a60adcbab3.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Sprites/Water/Glass.png" +dest_files=[ "res://.import/Glass.png-8678c0300c4ceb28841173a60adcbab3.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=false +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=false +svg/scale=1.0 diff --git a/Sprites/bg.png b/Sprites/bg.png new file mode 100644 index 0000000..3d006e3 Binary files /dev/null and b/Sprites/bg.png differ diff --git a/Sprites/bg.png.import b/Sprites/bg.png.import new file mode 100644 index 0000000..0e6ab3b --- /dev/null +++ b/Sprites/bg.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/bg.png-5046840dce817dc9e1d61a818df550fc.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Sprites/bg.png" +dest_files=[ "res://.import/bg.png-5046840dce817dc9e1d61a818df550fc.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=false +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=false +svg/scale=1.0 diff --git a/Sprites/floor.png b/Sprites/floor.png index 988ad88..397d163 100644 Binary files a/Sprites/floor.png and b/Sprites/floor.png differ diff --git a/Sprites/furniture.tres b/Sprites/furniture.tres new file mode 100644 index 0000000..190d3e1 --- /dev/null +++ b/Sprites/furniture.tres @@ -0,0 +1,68 @@ +[gd_resource type="TileSet" load_steps=5 format=2] + +[ext_resource path="res://Sprites/wardrobe.png" type="Texture" id=1] +[ext_resource path="res://Sprites/table.png" type="Texture" id=2] + +[sub_resource type="ConvexPolygonShape2D" id=1] +points = PoolVector2Array( 16, 11.2241, 0, 11.3539, 0, 0, 16, 0 ) + +[sub_resource type="ConvexPolygonShape2D" id=2] +points = PoolVector2Array( 12, 12, 0, 12, 0, 0, 12, 0 ) + +[resource] +0/name = "wardrobe.png 0" +0/texture = ExtResource( 1 ) +0/tex_offset = Vector2( 0, 0 ) +0/modulate = Color( 1, 1, 1, 1 ) +0/region = Rect2( 0, 0, 16, 16 ) +0/tile_mode = 0 +0/occluder_offset = Vector2( 0, 0 ) +0/navigation_offset = Vector2( 0, 0 ) +0/shape_offset = Vector2( 0, 0 ) +0/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) +0/shape = SubResource( 1 ) +0/shape_one_way = false +0/shape_one_way_margin = 1.0 +0/shapes = [ { +"autotile_coord": Vector2( 0, 0 ), +"one_way": false, +"one_way_margin": 1.0, +"shape": SubResource( 1 ), +"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) +} ] +0/z_index = 0 +2/name = "table.png 2" +2/texture = ExtResource( 2 ) +2/tex_offset = Vector2( 0, 0 ) +2/modulate = Color( 1, 1, 1, 1 ) +2/region = Rect2( 3, 1, 0, 0 ) +2/tile_mode = 0 +2/occluder_offset = Vector2( 0, 0 ) +2/navigation_offset = Vector2( 0, 0 ) +2/shape_offset = Vector2( 0, 0 ) +2/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) +2/shape_one_way = false +2/shape_one_way_margin = 0.0 +2/shapes = [ ] +2/z_index = 0 +3/name = "table.png 3" +3/texture = ExtResource( 2 ) +3/tex_offset = Vector2( 0, 0 ) +3/modulate = Color( 1, 1, 1, 1 ) +3/region = Rect2( 0, 0, 12, 12 ) +3/tile_mode = 0 +3/occluder_offset = Vector2( 0, 0 ) +3/navigation_offset = Vector2( 0, 0 ) +3/shape_offset = Vector2( 0, 0 ) +3/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) +3/shape = SubResource( 2 ) +3/shape_one_way = false +3/shape_one_way_margin = 1.0 +3/shapes = [ { +"autotile_coord": Vector2( 0, 0 ), +"one_way": false, +"one_way_margin": 1.0, +"shape": SubResource( 2 ), +"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) +} ] +3/z_index = 0 diff --git a/Sprites/table.png b/Sprites/table.png new file mode 100644 index 0000000..03f94a5 Binary files /dev/null and b/Sprites/table.png differ diff --git a/Sprites/table.png.import b/Sprites/table.png.import new file mode 100644 index 0000000..4fa83b3 --- /dev/null +++ b/Sprites/table.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/table.png-6287c5224e3a2223ad79685cc0bf8f85.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Sprites/table.png" +dest_files=[ "res://.import/table.png-6287c5224e3a2223ad79685cc0bf8f85.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=false +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=false +svg/scale=1.0 diff --git a/Sprites/wardrobe.png b/Sprites/wardrobe.png new file mode 100644 index 0000000..13ee3b6 Binary files /dev/null and b/Sprites/wardrobe.png differ diff --git a/Sprites/wardrobe.png.import b/Sprites/wardrobe.png.import new file mode 100644 index 0000000..7183ec7 --- /dev/null +++ b/Sprites/wardrobe.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/wardrobe.png-67445500d100c0d821e09597f4b6463a.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Sprites/wardrobe.png" +dest_files=[ "res://.import/wardrobe.png-67445500d100c0d821e09597f4b6463a.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=false +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=false +svg/scale=1.0 diff --git a/addons/gdfxr/Base58.gd b/addons/gdfxr/Base58.gd new file mode 100644 index 0000000..6f484bd --- /dev/null +++ b/addons/gdfxr/Base58.gd @@ -0,0 +1,38 @@ +extends Object + +const BASE_58_ALPHABET := "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" + + +static func b58decode(v: String) -> StreamPeerBuffer: + # Base 58 is a number expressed in the base-58 numeral system. + # When encoding data, big-endian is used and leading zeros are encoded as leading `1`s. + + var original_length := v.length() + v = v.lstrip(BASE_58_ALPHABET[0]) + var zeros := original_length - v.length() + + var buffer := PoolByteArray() + buffer.resize(v.length()) # Won't be as long as base 58 string since the buffer is 256-based. + buffer.fill(0) + + var length := 0 + for c in v: + var carry := BASE_58_ALPHABET.find(c) + if carry == -1: + return null + var i := 0 + while carry != 0 or i < length: + var pos := buffer.size() - 1 - i + carry += 58 * buffer[pos] + buffer[pos] = carry % 256 + carry /= 256 + i += 1 + length = i + + var result := StreamPeerBuffer.new() + for _i in zeros: + result.put_8(0) + result.put_data(buffer.subarray(buffer.size() - length, -1)) + result.seek(0) + + return result diff --git a/addons/gdfxr/LICENSE b/addons/gdfxr/LICENSE new file mode 100644 index 0000000..4544320 --- /dev/null +++ b/addons/gdfxr/LICENSE @@ -0,0 +1,7 @@ +Copyright 2022 Haoyu Qiu + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/addons/gdfxr/SFXRConfig.gd b/addons/gdfxr/SFXRConfig.gd new file mode 100644 index 0000000..a290ff1 --- /dev/null +++ b/addons/gdfxr/SFXRConfig.gd @@ -0,0 +1,511 @@ +# GDScript port of the original SFXR +# https://www.drpetter.se/project_sfxr.html + +enum WaveType { + SQUARE_WAVE, + SAWTOOTH, + SINE_WAVE, + NOISE, +} + +enum Category { + PICKUP_COIN, + LASER_SHOOT, + EXPLOSION, + POWERUP, + HIT_HURT, + JUMP, + BLIP_SELECT, +} + +const Base58 := preload("res://addons/gdfxr/Base58.gd") + +var wave_type: int = WaveType.SQUARE_WAVE + +var p_env_attack := 0.0 # Attack Time +var p_env_sustain := 0.3 # Sustain Time +var p_env_punch := 0.0 # Sustain Punch +var p_env_decay := 0.4 # Decay Time + +var p_base_freq := 0.3 # Start Frequency +var p_freq_limit := 0.0 # Min Frequency +var p_freq_ramp := 0.0 # Slide +var p_freq_dramp := 0.0 # Delta Slide +var p_vib_strength := 0.0 # Vibrato Depth +var p_vib_speed := 0.0 # Vibrato Speed + +var p_duty := 0.0 # Square Duty +var p_duty_ramp := 0.0 # Duty Sweep + +var p_arp_mod := 0.0 # Change Amount +var p_arp_speed := 0.0 # Change Speed + +var p_repeat_speed := 0.0 # Repeat Speed + +var p_pha_offset := 0.0 # Phaser Offset +var p_pha_ramp := 0.0 # Phaser Weep + +var p_lpf_freq := 1.0 # Lp Filter Cutoff +var p_lpf_ramp := 0.0 # Lp Filter Cutoff Sweep +var p_lpf_resonance := 0.0 # Lp Filter Resonance +var p_hpf_freq := 0.0 # Hp Filter Cutoff +var p_hpf_ramp := 0.0 # Hp Filter Cutoff Sweep + +var sound_vol := 0.5 + + +func load(path: String) -> int: # Error + var f := File.new() + var err := f.open(path, File.READ) + if err != OK: + return err + + var version := f.get_32() + if not [100, 101, 102].has(version): + return ERR_FILE_UNRECOGNIZED + + wave_type = f.get_32() + sound_vol = 0.5 + if version == 102: + sound_vol = f.get_float() + + p_base_freq = f.get_float() + p_freq_limit = f.get_float() + p_freq_ramp = f.get_float() + if version >= 101: + p_freq_dramp = f.get_float() + p_duty = f.get_float() + p_duty_ramp = f.get_float() + + p_vib_strength = f.get_float() + p_vib_speed = f.get_float() + f.get_float() # p_vib_delay + + p_env_attack = f.get_float() + p_env_sustain = f.get_float() + p_env_decay = f.get_float() + p_env_punch = f.get_float() + + f.get_8() # filter_on + p_lpf_resonance = f.get_float() + p_lpf_freq = f.get_float() + p_lpf_ramp = f.get_float() + p_hpf_freq = f.get_float() + p_hpf_ramp = f.get_float() + + p_pha_offset = f.get_float() + p_pha_ramp = f.get_float() + + p_repeat_speed = f.get_float() + + if version >= 101: + p_arp_speed = f.get_float() + p_arp_mod = f.get_float() + + return OK + + +func save(path: String) -> int: # Error + var f := File.new() + var err := f.open(path, File.WRITE) + if err != OK: + return err + + f.store_32(102) + f.store_32(wave_type) + f.store_float(sound_vol) + + f.store_float(p_base_freq) + f.store_float(p_freq_limit) + f.store_float(p_freq_ramp) + f.store_float(p_freq_dramp) + f.store_float(p_duty) + f.store_float(p_duty_ramp) + + f.store_float(p_vib_strength) + f.store_float(p_vib_speed) + f.store_float(0) # p_vib_delay + + f.store_float(p_env_attack) + f.store_float(p_env_sustain) + f.store_float(p_env_decay) + f.store_float(p_env_punch) + + f.store_8(true) # filter_on + f.store_float(p_lpf_resonance) + f.store_float(p_lpf_freq) + f.store_float(p_lpf_ramp) + f.store_float(p_hpf_freq) + f.store_float(p_hpf_ramp) + + f.store_float(p_pha_offset) + f.store_float(p_pha_ramp) + + f.store_float(p_repeat_speed) + + f.store_float(p_arp_speed) + f.store_float(p_arp_mod) + + return OK + + +func randomize_in_category(category: int) -> void: + reset() + + match category: + Category.PICKUP_COIN: + p_base_freq = rand_range(0.4, 0.9) + p_env_attack = 0.0 + p_env_sustain = rand_range(0.0, 0.1) + p_env_decay = rand_range(0.1, 0.5) + p_env_punch = rand_range(0.3, 0.6) + if randi() % 2: + p_arp_speed = rand_range(0.5, 0.7) + p_arp_mod = rand_range(0.2, 0.6) + + Category.LASER_SHOOT: + wave_type = randi() % 3 + if wave_type == 2 and randi() % 2: + wave_type = randi() % 2 + p_base_freq = rand_range(0.5, 1.0) + p_freq_limit = max(0.2, p_base_freq - rand_range(0.2, 0.8)) + p_freq_ramp = rand_range(-0.35, -0.15) + if randi() % 3 == 0: + p_base_freq = rand_range(0.3, 0.9) + p_freq_limit = rand_range(0, 0.1) + p_freq_ramp = rand_range(-0.65, -0.35) + if randi() % 2: + p_duty = rand_range(0, 0.5) + p_duty_ramp = rand_range(0, 0.2) + else: + p_duty = rand_range(0.4, 0.9) + p_duty_ramp = rand_range(-0.7, 0) + p_env_attack = 0.0 + p_env_sustain = rand_range(0.1, 0.3) + p_env_decay = rand_range(0.0, 0.4) + if randi() % 2: + p_env_punch = rand_range(0, 0.3) + if randi() % 3 == 0: + p_pha_offset = rand_range(0, 0.2) + p_pha_ramp = rand_range(0, 0.2) + if randi() % 2: + p_hpf_freq = rand_range(0, 0.3) + + Category.EXPLOSION: + wave_type = WaveType.NOISE + if randi() % 2: + p_base_freq = rand_range(0.1, 0.4) + p_freq_ramp = rand_range(-0.1, 0.3) + else: + p_base_freq = rand_range(0.2, 0.9) + p_freq_ramp = rand_range(-0.4, -0.2) + p_base_freq *= p_base_freq + if randi() % 5 == 0: + p_freq_ramp = 0.0 + if randi() % 3 == 0: + p_repeat_speed = rand_range(0.3, 0.8) + p_env_attack = 0.0 + p_env_sustain = rand_range(0.1, 0.4) + p_env_decay = rand_range(0, 0.5) + if randi() % 2: + p_pha_offset = rand_range(-0.3, 0.6) + p_pha_ramp = rand_range(-0.3, 0) + p_env_punch = rand_range(0.2, 0.8) + if randi() % 2: + p_vib_strength = rand_range(0, 0.7) + p_vib_speed = rand_range(0, 0.6) + if randi() % 3: + p_arp_speed = rand_range(0.6, 0.9) + p_arp_mod = rand_range(-0.8, 0.8) + + Category.POWERUP: + if randi() % 2: + wave_type = WaveType.SAWTOOTH + else: + p_duty = rand_range(0, 0.6) + if randi() % 2: + p_base_freq = rand_range(0.2, 0.5) + p_freq_ramp = rand_range(0.1, 0.5) + p_repeat_speed = rand_range(0.4, 0.8) + else: + p_base_freq = rand_range(0.2, 0.5) + p_freq_ramp = rand_range(0.05, 0.25) + if randi() % 2: + p_vib_strength = rand_range(0, 0.7) + p_vib_speed = rand_range(0, 0.6) + p_env_attack = 0.0 + p_env_sustain = rand_range(0, 0.4) + p_env_decay = rand_range(0.1, 0.5) + + Category.HIT_HURT: + wave_type = randi() % 3 + match wave_type: + WaveType.SINE_WAVE: + wave_type = WaveType.NOISE + WaveType.SQUARE_WAVE: + p_duty = rand_range(0, 0.6) + p_base_freq = rand_range(0.2, 0.8) + p_freq_ramp = rand_range(-0.7, -0.3) + p_env_attack = 0.0 + p_env_sustain = rand_range(0, 0.1) + p_env_decay = rand_range(0.1, 0.3) + if randi() % 2: + p_hpf_freq = rand_range(0, 0.3) + + Category.JUMP: + wave_type = WaveType.SQUARE_WAVE + p_duty = rand_range(0, 0.6) + p_base_freq = rand_range(0.3, 0.6) + p_freq_ramp = rand_range(0.1, 0.3) + p_env_attack = 0.0 + p_env_sustain = rand_range(0.1, 0.4) + p_env_decay = rand_range(0.1, 0.3) + if randi() % 2: + p_hpf_freq = rand_range(0, 0.3) + if randi() % 2: + p_lpf_freq = rand_range(0.4, 1.0) + + Category.BLIP_SELECT: + wave_type = randi() % 2 + if wave_type == WaveType.SQUARE_WAVE: + p_duty = rand_range(0, 0.6) + p_base_freq = rand_range(0.2, 0.6) + p_env_attack = 0.0 + p_env_sustain = rand_range(0.1, 0.2) + p_env_decay = rand_range(0, 0.2) + p_hpf_freq = 0.1 + + +func randomize() -> void: + p_base_freq = pow(rand_range(-1.0, +1.0), 2.0) + if randi() % 2: + p_base_freq = pow(rand_range(-1.0, +1.0), 3.0) + 0.5 + p_freq_limit = 0.0 + p_freq_ramp = pow(rand_range(-1.0, +1.0), 5.0) + if p_base_freq > 0.7 and p_freq_ramp > 0.2: + p_freq_ramp = -p_freq_ramp + if p_base_freq < 0.2 and p_freq_ramp < -0.05: + p_freq_ramp = -p_freq_ramp + p_freq_dramp = pow(rand_range(-1.0, +1.0), 3.0) + p_duty = rand_range(-1.0, +1.0) + p_duty_ramp = pow(rand_range(-1.0, +1.0), 3.0) + p_vib_strength = pow(rand_range(-1.0, +1.0), 3.0) + p_vib_speed = rand_range(-1.0, +1.0) + # p_vib_delay = rand_range(-1.0, +1.0) + p_env_attack = pow(rand_range(-1.0, +1.0), 3.0) + p_env_sustain = pow(rand_range(-1.0, +1.0), 2.0) + p_env_decay = rand_range(-1.0, +1.0) + p_env_punch = pow(rand_range(0, 0.8), 2.0) + if p_env_attack + p_env_sustain + p_env_decay < 0.2: + p_env_sustain += rand_range(0.2, 0.5) + p_env_decay += rand_range(0.2, 0.5) + p_lpf_resonance = rand_range(-1.0, +1.0) + p_lpf_freq = 1.0 - pow(randf(), 3.0) + p_lpf_ramp = pow(rand_range(-1.0, +1.0), 3.0) + if p_lpf_freq < 0.1 and p_lpf_ramp < -0.05: + p_lpf_ramp = -p_lpf_ramp + p_hpf_freq = pow(randf(), 5.0) + p_hpf_ramp = pow(rand_range(-1.0, +1.0), 5.0) + p_pha_offset = pow(rand_range(-1.0, +1.0), 3.0) + p_pha_ramp = pow(rand_range(-1.0, +1.0), 3.0) + p_repeat_speed = rand_range(-1.0, +1.0) + p_arp_speed = rand_range(-1.0, +1.0) + p_arp_mod = rand_range(-1.0, +1.0) + + +func mutate() -> void: + if randi() % 2: + p_base_freq += rand_range(-0.05, +0.05) + if randi() % 2: + p_freq_limit += rand_range(-0.05, +0.05) + if randi() % 2: + p_freq_ramp += rand_range(-0.05, +0.05) + if randi() % 2: + p_freq_dramp += rand_range(-0.05, +0.05) + if randi() % 2: + p_duty += rand_range(-0.05, +0.05) + if randi() % 2: + p_duty_ramp += rand_range(-0.05, +0.05) + if randi() % 2: + p_vib_strength += rand_range(-0.05, +0.05) + if randi() % 2: + p_vib_speed += rand_range(-0.05, +0.05) +# if randi() % 2: +# p_vib_delay += rand_range(-0.05, +0.05) + if randi() % 2: + p_env_attack += rand_range(-0.05, +0.05) + if randi() % 2: + p_env_sustain += rand_range(-0.05, +0.05) + if randi() % 2: + p_env_decay += rand_range(-0.05, +0.05) + if randi() % 2: + p_env_punch += rand_range(-0.05, +0.05) + if randi() % 2: + p_lpf_resonance += rand_range(-0.05, +0.05) + if randi() % 2: + p_lpf_freq += rand_range(-0.05, +0.05) + if randi() % 2: + p_lpf_ramp += rand_range(-0.05, +0.05) + if randi() % 2: + p_hpf_freq += rand_range(-0.05, +0.05) + if randi() % 2: + p_hpf_ramp += rand_range(-0.05, +0.05) + if randi() % 2: + p_pha_offset += rand_range(-0.05, +0.05) + if randi() % 2: + p_pha_ramp += rand_range(-0.05, +0.05) + if randi() % 2: + p_repeat_speed += rand_range(-0.05, +0.05) + if randi() % 2: + p_arp_speed += rand_range(-0.05, +0.05) + if randi() % 2: + p_arp_mod += rand_range(-0.05, +0.05) + + +func reset(): + wave_type = WaveType.SQUARE_WAVE + + p_base_freq = 0.3 + p_freq_limit = 0.0 + p_freq_ramp = 0.0 + p_freq_dramp = 0.0 + p_duty = 0.0 + p_duty_ramp = 0.0 + + p_vib_strength = 0.0 + p_vib_speed = 0.0 + # p_vib_delay = 0.0 + + p_env_attack = 0.0 + p_env_sustain = 0.3 + p_env_decay = 0.4 + p_env_punch = 0.0 + + # filter_on = false + p_lpf_resonance = 0.0 + p_lpf_freq = 1.0 + p_lpf_ramp = 0.0 + p_hpf_freq = 0.0 + p_hpf_ramp = 0.0 + + p_pha_offset = 0.0 + p_pha_ramp = 0.0 + + p_repeat_speed = 0.0 + + p_arp_speed = 0.0 + p_arp_mod = 0.0 + + +func copy_from(other: Reference) -> void: # SFXRConfig + wave_type = other.wave_type + + p_env_attack = other.p_env_attack + p_env_sustain = other.p_env_sustain + p_env_punch = other.p_env_punch + p_env_decay = other.p_env_decay + + p_base_freq = other.p_base_freq + p_freq_limit = other.p_freq_limit + p_freq_ramp = other.p_freq_ramp + p_freq_dramp = other.p_freq_dramp + p_vib_strength = other.p_vib_strength + p_vib_speed = other.p_vib_speed + + p_duty = other.p_duty + p_duty_ramp = other.p_duty_ramp + + p_arp_mod = other.p_arp_mod + p_arp_speed = other.p_arp_speed + + p_repeat_speed = other.p_repeat_speed + + p_pha_offset = other.p_pha_offset + p_pha_ramp = other.p_pha_ramp + + p_lpf_freq = other.p_lpf_freq + p_lpf_ramp = other.p_lpf_ramp + p_lpf_resonance = other.p_lpf_resonance + p_hpf_freq = other.p_hpf_freq + p_hpf_ramp = other.p_hpf_ramp + + sound_vol = other.sound_vol + + +func is_equal(other: Reference) -> bool: # SFXRConfig + return ( + wave_type == other.wave_type + + and p_env_attack == other.p_env_attack + and p_env_sustain == other.p_env_sustain + and p_env_punch == other.p_env_punch + and p_env_decay == other.p_env_decay + + and p_base_freq == other.p_base_freq + and p_freq_limit == other.p_freq_limit + and p_freq_ramp == other.p_freq_ramp + and p_freq_dramp == other.p_freq_dramp + and p_vib_strength == other.p_vib_strength + and p_vib_speed == other.p_vib_speed + + and p_duty == other.p_duty + and p_duty_ramp == other.p_duty_ramp + + and p_arp_mod == other.p_arp_mod + and p_arp_speed == other.p_arp_speed + + and p_repeat_speed == other.p_repeat_speed + + and p_pha_offset == other.p_pha_offset + and p_pha_ramp == other.p_pha_ramp + + and p_lpf_freq == other.p_lpf_freq + and p_lpf_ramp == other.p_lpf_ramp + and p_lpf_resonance == other.p_lpf_resonance + and p_hpf_freq == other.p_hpf_freq + and p_hpf_ramp == other.p_hpf_ramp + + and sound_vol == other.sound_vol + ) + + +# Load base58 string copied from jsfxr +# See https://github.com/chr15m/jsfxr/blob/a708164e6ce200008d88202e1aaf2b9171a17ec2/sfxr.js#L132-L175 +func load_from_base58(v: String) -> int: # Error + var buffer := Base58.b58decode(v) + if not buffer: + return ERR_INVALID_DATA + if buffer.get_size() != 89: + return ERR_INVALID_DATA + + var params_order = [ + "p_env_attack", + "p_env_sustain", + "p_env_punch", + "p_env_decay", + "p_base_freq", + "p_freq_limit", + "p_freq_ramp", + "p_freq_dramp", + "p_vib_strength", + "p_vib_speed", + "p_arp_mod", + "p_arp_speed", + "p_duty", + "p_duty_ramp", + "p_repeat_speed", + "p_pha_offset", + "p_pha_ramp", + "p_lpf_freq", + "p_lpf_ramp", + "p_lpf_resonance", + "p_hpf_freq", + "p_hpf_ramp", + ] + + wave_type = buffer.get_8() + + for param in params_order: + set(param, buffer.get_float()) + + return OK diff --git a/addons/gdfxr/SFXRGenerator.gd b/addons/gdfxr/SFXRGenerator.gd new file mode 100644 index 0000000..111edc0 --- /dev/null +++ b/addons/gdfxr/SFXRGenerator.gd @@ -0,0 +1,274 @@ +# GDScript port of the original SFXR +# https://www.drpetter.se/project_sfxr.html + +const SFXRConfig := preload("SFXRConfig.gd") + +const master_vol := 0.05 + +enum WavBits { + WAV_BITS_8, + WAV_BITS_16, +} +enum WavFreq { + WAV_FREQ_44100, + WAV_FREQ_22050, +} + +var _config: SFXRConfig + +var rep_time: int +var rep_limit: int +var arp_time: int +var arp_limit: int +var arp_mod: float +var period: int +var fperiod: float +var fmaxperiod: float +var fslide: float +var fdslide: float +var vib_amp: float +var vib_phase: float +var vib_speed: float +var square_duty: float +var square_slide: float +var env_vol: float +var env_length := PoolIntArray([0, 0, 0]) +var phase: int +var fphase: float +var fdphase: float +var iphase: int +var flthp: float +var flthp_d: float +var noise_buffer := PoolRealArray([]) +var phaser_buffer := PoolRealArray([]) +var ipp: int +var fltp: float +var fltdp: float +var fltw: float +var fltw_d: float +var fltdmp: float +var fltphp: float + + +func generate_audio_stream( + config: SFXRConfig, + wav_bits: int = WavBits.WAV_BITS_8, + wav_freq: int = WavFreq.WAV_FREQ_44100 +) -> AudioStreamSample: + var stream := AudioStreamSample.new() + stream.format = AudioStreamSample.FORMAT_8_BITS if wav_bits == WavBits.WAV_BITS_8 else AudioStreamSample.FORMAT_16_BITS + stream.mix_rate = 44100 if wav_freq == WavFreq.WAV_FREQ_44100 else 22050 + + _config = config + stream.data = _generate_samples(wav_bits, wav_freq).data_array + _config = null + + return stream + + +func generate_samples( + config: SFXRConfig, + wav_bits: int = WavBits.WAV_BITS_8, + wav_freq: int = WavFreq.WAV_FREQ_44100 +) -> PoolByteArray: + _config = config + var data := _generate_samples(wav_bits, wav_freq).data_array + _config = null + return data + + +func _generate_samples(wav_bits: int, wav_freq: int) -> StreamPeerBuffer: + _reset_sample(true) + + var playing_sample := true + var env_stage := 0 + var env_time := 0 + var filesample: float = 0 + var fileacc := 0 + var buffer := StreamPeerBuffer.new() + + # SynthSample + while playing_sample: + rep_time += 1 + if rep_limit != 0 and rep_time >= rep_limit: + rep_time = 0 + _reset_sample(false) + + # frequency envelopes/arpeggios + arp_time += 1 + if arp_limit != 0 and arp_time >= arp_limit: + arp_limit = 0 + fperiod *= arp_mod + fslide += fdslide + fperiod *= fslide + if fperiod > fmaxperiod: + fperiod = fmaxperiod + if _config.p_freq_limit > 0: + playing_sample = false + var rfperiod := fperiod + if vib_amp > 0.0: + vib_phase += vib_speed + rfperiod = fperiod * (1.0 + sin(vib_phase) * vib_amp) + period = int(max(8, rfperiod)) + square_duty = clamp(square_duty + square_slide, 0.0, 0.5) + + # volume envelope + env_time += 1 # Note: this skips 0 of env_stage 0. Seems problematic. + if env_time > env_length[env_stage]: + env_time = 0 + + while true: + env_stage += 1 + if env_stage == 3: + playing_sample = false + break + if env_length[env_stage] != 0: + break + + match env_stage: + 0: + env_vol = float(env_time) / env_length[0] + 1: + env_vol = 1.0 + pow(1.0 - float(env_time) / env_length[1], 1.0) * 2.0 * _config.p_env_punch + 2: + env_vol = 1.0 - float(env_time) / env_length[2] + + # phaser step + fphase += fdphase + iphase = int(min(abs(fphase), 1023)) + + if flthp_d != 0.0: + flthp = clamp(flthp * flthp_d, 0.00001, 0.1) + + var ssample := 0.0 + for si in 8: # 8x supersampling + var sample := 0.0 + phase += 1 + if phase >= period: + phase %= period + if _config.wave_type == SFXRConfig.WaveType.NOISE: + for j in 32: + noise_buffer[j] = rand_range(-1.0, +1.0) + + # base waveform + var fp := float(phase) / period + match _config.wave_type: + SFXRConfig.WaveType.SQUARE_WAVE: + sample = 0.5 if fp < square_duty else -0.5 + SFXRConfig.WaveType.SAWTOOTH: + sample = 1.0 - fp * 2 + SFXRConfig.WaveType.SINE_WAVE: + sample = sin(fp * 2 * PI) + SFXRConfig.WaveType.NOISE: + sample = noise_buffer[phase * 32 / period] + + # lp filter + var pp := fltp + fltw = clamp(fltw * fltw_d, 0.0, 0.1) + if _config.p_lpf_freq == 1.0: + fltp = sample + fltdp = 0.0 + else: + fltdp += (sample - fltp) * fltw + fltdp -= fltdp * fltdmp + fltp += fltdp + + # hp filter + fltphp += fltp - pp + fltphp -= fltphp * flthp + sample = fltphp + + # phaser + phaser_buffer[ipp & 1023] = sample + sample += phaser_buffer[(ipp - iphase + 1024) & 1023] + ipp = (ipp + 1) & 1023 + + # final accumulation and envelope application + ssample += sample * env_vol + + ssample = ssample / 8 * master_vol + + ssample *= 2.0 * _config.sound_vol + + ssample *= 4.0 # arbitrary gain to get reasonable output volume... + ssample = clamp(ssample, -1.0, +1.0) + + filesample += ssample + fileacc += 1 + + if wav_freq == WavFreq.WAV_FREQ_44100 or fileacc == 2: + filesample /= fileacc + fileacc = 0 + + if wav_bits == WavBits.WAV_BITS_8: + buffer.put_8(filesample * 255) + else: + buffer.put_16(filesample * 32000) + + filesample = 0 + + return buffer + + +func _reset_sample(restart: bool) -> void: + fperiod = 100.0 / (_config.p_base_freq * _config.p_base_freq + 0.001) + period = int(fperiod) + fmaxperiod = 100.0 / (_config.p_freq_limit * _config.p_freq_limit + 0.001) + fslide = 1.0 - pow(_config.p_freq_ramp, 3.0) * 0.01 + fdslide = -pow(_config.p_freq_dramp, 3.0) * 0.000001 + square_duty = 0.5 - _config.p_duty * 0.5 + square_slide = -_config.p_duty_ramp * 0.00005 + if _config.p_arp_mod >= 0.0: + arp_mod = 1.0 - pow(_config.p_arp_mod, 2.0) * 0.9 + else: + arp_mod = 1.0 + pow(_config.p_arp_mod, 2.0) * 10.0 + arp_time = 0 + arp_limit = int(pow(1.0 - _config.p_arp_speed, 2.0) * 20000 + 32) + if _config.p_arp_speed == 1.0: + arp_limit = 0 + + if restart: + phase = 0 + + # Reset filter. + fltp = 0.0 + fltdp = 0.0 + fltw = pow(_config.p_lpf_freq, 3.0) * 0.1 + fltw_d = 1.0 + _config.p_lpf_ramp * 0.0001 + fltdmp = min(5.0 / (1.0 + pow(_config.p_lpf_resonance, 2.0) * 20.0) * (0.01 + fltw), 0.8) + fltphp = 0.0 + flthp = pow(_config.p_hpf_freq, 2.0) * 0.1 + flthp_d = 1.0 + _config.p_hpf_ramp * 0.0003 + + # Reset vibrato + vib_phase = 0.0 + vib_speed = pow(_config.p_vib_speed, 2.0) * 0.01 + vib_amp = _config.p_vib_strength * 0.5 + + # Reset envelope + env_vol = 0.0 + env_length[0] = int(_config.p_env_attack * _config.p_env_attack * 100000.0) + env_length[1] = int(_config.p_env_sustain * _config.p_env_sustain * 100000.0) + env_length[2] = int(_config.p_env_decay * _config.p_env_decay * 100000.0) + + fphase = pow(_config.p_pha_offset, 2.0) * 1020.0 + if _config.p_pha_offset < 0.0: + fphase = -fphase + fdphase = pow(_config.p_pha_ramp, 2.0) * 1.0 + if _config.p_pha_ramp < 0.0: + fdphase = -fdphase + iphase = int(abs(fphase)) + ipp = 0 + + phaser_buffer.resize(1024) + for i in phaser_buffer.size(): + phaser_buffer[i] = 0.0 + + noise_buffer.resize(32) + for i in noise_buffer.size(): + noise_buffer[i] = rand_range(-1.0, +1.0) + + rep_time = 0 + rep_limit = int(pow(1.0 - _config.p_repeat_speed, 2.0) * 20000 + 32) + if _config.p_repeat_speed == 0.0: + rep_limit = 0 diff --git a/addons/gdfxr/editor/EditSlider.gd b/addons/gdfxr/editor/EditSlider.gd new file mode 100644 index 0000000..217a900 --- /dev/null +++ b/addons/gdfxr/editor/EditSlider.gd @@ -0,0 +1,203 @@ +tool +extends Control + +signal value_changed(value) + +export var value: float = 0.0 setget set_value +export var min_value: float = 0.0 +export var max_value: float = 1.0 + +var _line_edit: LineEdit + +var _stylebox_normal: StyleBox +var _stylebox_hover: StyleBox +var _stylebox_editing: StyleBox +var _stylebox_value: StyleBox + +var _line_edit_just_closed := false +var _mouse_hovering := false +var _is_editing := false + +var _drag_start_position: Vector2 +var _drag_cancelled := true +var _drag_dist := 0.0 +var _drag_start_factor: float + + +func _init() -> void: + mouse_default_cursor_shape = Control.CURSOR_HSIZE + rect_clip_content = true + focus_mode = Control.FOCUS_ALL + + var style := StyleBoxEmpty.new() + style.content_margin_left = 8 + style.content_margin_right = 8 + + _line_edit = LineEdit.new() + _line_edit.set_as_toplevel(true) + _line_edit.visible = false + _line_edit.add_stylebox_override("normal", style) + _line_edit.add_stylebox_override("focus", StyleBoxEmpty.new()) + + var _ret: int + _ret = _line_edit.connect("focus_exited", self, "_on_line_edit_focus_exited") + _ret = _line_edit.connect("text_entered", self, "_on_line_edit_text_entered") + _ret = _line_edit.connect("visibility_changed", self, "_on_line_edit_visibility_changed") + + add_child(_line_edit) + + +func _draw() -> void: + var font := get_font("font", "LineEdit") + var color := get_color("highlighted_font_color" if _mouse_hovering else "font_color", "Editor") + var number_string := "%.3f" % value + var number_size := font.get_string_size(number_string) + var pos := Vector2( + (rect_size.x - number_size.x) / 2, + (rect_size.y - number_size.y) / 2 + font.get_ascent() + ) + + var stylebox := _stylebox_editing if _is_editing else _stylebox_hover if _mouse_hovering else _stylebox_normal + + if _line_edit.visible: + draw_style_box(stylebox, Rect2(Vector2.ZERO, rect_size)) + else: + var value_width := rect_size.x * ((value - min_value) / (max_value - min_value)) + draw_style_box(stylebox, Rect2(value_width, 0, rect_size.x - value_width, rect_size.y)) + draw_style_box(_stylebox_value, Rect2(0, 0, value_width, rect_size.y)) + draw_string(font, pos, number_string, color) + + +func _get_minimum_size() -> Vector2: + var ms := _stylebox_normal.get_minimum_size() + ms.y += get_font("font", "LineEdit").get_height() + return ms + + +func _gui_input(event: InputEvent) -> void: + var mb := event as InputEventMouseButton + if mb and mb.button_index == BUTTON_LEFT: + if mb.pressed: + _drag_prepare(mb) + else: + _drag_done() + if _drag_cancelled: + _show_text_edit() + _drag_cancelled = true + _is_editing = mb.pressed + update() + + var mm := event as InputEventMouseMotion + if mm and mm.button_mask & BUTTON_MASK_LEFT: + _drag_motion(mm) + _drag_cancelled = false + + +func _notification(what: int) -> void: + match what: + NOTIFICATION_ENTER_TREE, NOTIFICATION_THEME_CHANGED: + _update_stylebox() + + NOTIFICATION_MOUSE_ENTER: + _mouse_hovering = true + update() + + NOTIFICATION_MOUSE_EXIT: + _mouse_hovering = false + update() + + NOTIFICATION_FOCUS_ENTER: + if (Input.is_action_pressed("ui_focus_next") or Input.is_action_pressed("ui_focus_prev")) and not _line_edit_just_closed: + _show_text_edit() + _line_edit_just_closed = false + + +func set_value(v: float) -> void: + if is_equal_approx(v, value): + return + value = v + emit_signal("value_changed", value) + update() + + +func _update_stylebox() -> void: + _stylebox_normal = get_stylebox("normal", "LineEdit") + _stylebox_hover = StyleBoxFlat.new() + _stylebox_hover.bg_color = get_color("highlight_color", "Editor") + _stylebox_editing = StyleBoxFlat.new() + _stylebox_editing.bg_color = get_color("dark_color_2", "Editor") + _stylebox_value = StyleBoxFlat.new() + _stylebox_value.bg_color = get_color("accent_color", "Editor") * Color(1, 1, 1, 0.4) + + +func _drag_prepare(mouse: InputEventMouse) -> void: + _drag_dist = 0.0 + _drag_start_factor = (value - min_value) / (max_value - min_value) + _drag_start_position = mouse.global_position + Input.mouse_mode = Input.MOUSE_MODE_CAPTURED + + +func _drag_done() -> void: + Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + + if _drag_cancelled: + Input.warp_mouse_position(_drag_start_position) + else: + Input.warp_mouse_position(rect_global_position + rect_size * Vector2( + (value - min_value) / (max_value - min_value), + 0.5 + )) + + +func _drag_motion(motion: InputEventMouseMotion) -> void: + _drag_dist += motion.relative.x + + var factor := _drag_start_factor + _drag_dist / rect_size.x + if factor < 0 or 1 < factor: + factor = clamp(factor, 0, 1) + _drag_dist = (factor - _drag_start_factor) * rect_size.x + + var v := factor * (max_value - min_value) + min_value + var snap := motion.command or motion.shift + if snap and not (is_equal_approx(v, min_value) or is_equal_approx(v, max_value)): + if motion.shift and motion.command: + v = round(v * 1000.0) * 0.001 + elif motion.shift: + v = round(v * 100.0) * 0.01 + else: + v = round(v * 10.0) * 0.1 + + set_value(clamp(v, min_value, max_value)) + + update() + + +func _show_text_edit() -> void: + var gr := get_global_rect() + _line_edit.text = str(value) + _line_edit.set_position(gr.position) + _line_edit.set_size(gr.size) + _line_edit.show_modal() + _line_edit.select_all() + _line_edit.grab_focus() + _line_edit.focus_next = find_next_valid_focus().get_path() + _line_edit.focus_previous = find_prev_valid_focus().get_path() + + +func _on_line_edit_focus_exited(): + if _line_edit.get_menu().visible: + return + if _line_edit.text.is_valid_float(): + set_value(clamp(_line_edit.text.to_float(), min_value, max_value)) + if not _line_edit_just_closed: + _line_edit.hide() + update() + + +func _on_line_edit_text_entered(_text: String): + _line_edit.hide() + + +func _on_line_edit_visibility_changed(): + if not _line_edit.visible: + _line_edit_just_closed = true diff --git a/addons/gdfxr/editor/Editor.gd b/addons/gdfxr/editor/Editor.gd new file mode 100644 index 0000000..b6028d3 --- /dev/null +++ b/addons/gdfxr/editor/Editor.gd @@ -0,0 +1,387 @@ +tool +extends Container + +enum ExtraOption { SAVE_AS, COPY, PASTE, PASTE_JSFXR, RECENT } +enum DefaultFilename { EMPTY, GUESS_FOR_SAVE } + +const SFXRConfig := preload("../SFXRConfig.gd") +const SFXRGenerator := preload("../SFXRGenerator.gd") +const Base58 := preload("../Base58.gd") +const NUM_RECENTS := 4 + +class RecentEntry: + var title: String + var config := SFXRConfig.new() + +var plugin: EditorPlugin + +var _config := SFXRConfig.new() +var _config_defaults := SFXRConfig.new() +var _config_clipboard: SFXRConfig +var _config_recents: Array +var _recents_id := 0 +var _generator := SFXRGenerator.new() +var _path: String +var _modified := false +var _param_map := {} +var _syncing_ui := false # a hack since Range set_value emits value_changed +var _category_names := {} + +onready var audio_player := $AudioStreamPlayer as AudioStreamPlayer +onready var filename_label := find_node("Filename") as Label +onready var save_button := find_node("Save") as Button +onready var restore_button := find_node("Restore") as Button +onready var extra_button := find_node("Extra") as MenuButton +onready var version_button := find_node("VersionButton") +onready var translator := $PluginTranslator + + +func _ready(): + if not plugin: + return # Running in the edited scene instead of from Plugin + + for child in get_children(): + _hook_plugin(child) + + var popup := extra_button.get_popup() + popup.add_item(translator.tr("Save As..."), ExtraOption.SAVE_AS) + popup.add_separator() + popup.add_item(translator.tr("Copy"), ExtraOption.COPY) + popup.add_item(translator.tr("Paste"), ExtraOption.PASTE) + popup.add_item(translator.tr("Paste from jsfxr"), ExtraOption.PASTE_JSFXR) + popup.add_separator(translator.tr("Recently Generated")) + popup.connect("id_pressed", self, "_on_Extra_id_pressed") + + _category_names = { + SFXRConfig.Category.PICKUP_COIN: translator.tr("Pickup/Coin"), + SFXRConfig.Category.LASER_SHOOT: translator.tr("Laser/Shoot"), + SFXRConfig.Category.EXPLOSION: translator.tr("Explosion"), + SFXRConfig.Category.POWERUP: translator.tr("Powerup"), + SFXRConfig.Category.HIT_HURT: translator.tr("Hit/Hurt"), + SFXRConfig.Category.JUMP: translator.tr("Jump"), + SFXRConfig.Category.BLIP_SELECT: translator.tr("Blip/Select"), + } + + var params := find_node("Params") as Container + for category in params.get_children(): + for control in category.get_children(): + _param_map[control.parameter] = control + control.connect("param_changed", self, "_on_param_changed") + control.connect("param_reset", self, "_on_param_reset") + + _set_editing_file("") + + +func _notification(what: int): + if not plugin: + return # Running in the edited scene instead of from Plugin + + match what: + NOTIFICATION_ENTER_TREE, NOTIFICATION_THEME_CHANGED: + find_node("ScrollContainer").add_stylebox_override("bg", get_stylebox("bg", "Tree")) + + if extra_button: + var popup = extra_button.get_popup() + popup.set_item_icon(popup.get_item_index(ExtraOption.COPY), get_icon("ActionCopy", "EditorIcons")) + popup.set_item_icon(popup.get_item_index(ExtraOption.PASTE), get_icon("ActionPaste", "EditorIcons")) + + +func edit(path: String) -> void: + if _modified: + _popup_confirm( + translator.tr("There are unsaved changes.\nOpen '%s' anyway?") % path, + "_set_editing_file", [path] + ) + else: + _set_editing_file(path) + + +func _hook_plugin(node: Node) -> void: + if "plugin" in node: + node.plugin = plugin + for child in node.get_children(): + _hook_plugin(child) + + +func _push_recent(title: String) -> void: + var recent: RecentEntry + if _config_recents.size() < NUM_RECENTS: + recent = RecentEntry.new() + else: + recent = _config_recents.pop_back() + + _recents_id += 1 + recent.title = "#%d %s" % [_recents_id, title] + recent.config.copy_from(_config) + + _config_recents.push_front(recent) + + +func _popup_confirm(content: String, callback: String, binds := []) -> void: + var dialog := ConfirmationDialog.new() + add_child(dialog) + dialog.dialog_text = content + dialog.window_title = translator.tr("SFXR Editor") + dialog.connect("confirmed", self, callback, binds) + dialog.connect("popup_hide", dialog, "queue_free") + dialog.popup_centered() + + +func _popup_message(content: String) -> void: + var dialog := AcceptDialog.new() + add_child(dialog) + dialog.dialog_text = content + dialog.window_title = translator.tr("SFXR Editor") + dialog.connect("popup_hide", dialog, "queue_free") + dialog.popup_centered() + + +func _popup_file_dialog(mode: int, callback: String, default_filename: int = DefaultFilename.EMPTY) -> void: + var dialog := EditorFileDialog.new() + add_child(dialog) + dialog.access = EditorFileDialog.ACCESS_RESOURCES + dialog.mode = mode + + match default_filename: + DefaultFilename.EMPTY: + pass + + DefaultFilename.GUESS_FOR_SAVE: + if _path: + dialog.current_path = _generate_serial_path(_path) + + dialog.add_filter("*.sfxr; %s" % translator.tr("SFXR Audio")) + dialog.connect("popup_hide", dialog, "queue_free") + dialog.connect("file_selected", self, callback) + dialog.popup_centered_ratio() + + +func _reset_defaults() -> void: + _config_defaults.copy_from(_config) + _set_modified(false) + _sync_ui() + + +func _restore_from_config(config: SFXRConfig) -> void: + _config.copy_from(config) + _sync_ui() + _set_modified(not config.is_equal(_config_defaults)) + audio_player.stream = null + + +func _set_editing_file(path: String) -> int: # Error + if path.empty(): + _config.reset() + audio_player.stream = null + else: + var err := _config.load(path) + if err != OK: + _popup_message(translator.tr("'%s' is not a valid SFXR file.") % path) + return err + audio_player.stream = load(path) + + _path = path + _reset_defaults() + return OK + + +func _set_modified(value: bool) -> void: + _modified = value + + var has_file := not _path.empty() + var base = _path if has_file else translator.tr("Unsaved sound") + if _modified: + base += "(*)" + filename_label.text = base + restore_button.disabled = not _modified + save_button.disabled = has_file and not _modified + + +func _sync_ui() -> void: + _syncing_ui = true + for name in _param_map: + var control = _param_map[name] + var value = _config.get(name) + control.set_value(value) + control.set_resetable(value != _config_defaults.get(name)) + _syncing_ui = false + + +func _generate_serial_path(path: String) -> String: + var directory := Directory.new() + if directory.open(path.get_base_dir()) != OK: + return path + + if not directory.file_exists(path.get_file()): + return path + + var basename := path.get_basename() + var extension := path.get_extension() + + # Extract trailing number. + var num_string: String + for i in range(basename.length() - 1, -1, -1): + var c: String = basename[i] + if "0" <= c and c <= "9": + num_string = c + num_string + else: + break + var number := num_string.to_int() if num_string else 0 + var name_string: String = basename.substr(0, basename.length() - num_string.length()) + + while true: + number += 1 + var attemp := "%s%d.%s" % [name_string, number, extension] + if not directory.file_exists(attemp): + return attemp + + return path # Unreachable + + +func _on_param_changed(name, value): + if _syncing_ui: + return + + _config.set(name, value) + + _param_map[name].set_resetable(value != _config_defaults.get(name)) + + _set_modified(not _config.is_equal(_config_defaults)) + audio_player.stream = null + + +func _on_param_reset(name): + var value = _config_defaults.get(name) + _config.set(name, value) + + _syncing_ui = true + var control = _param_map[name] + control.set_value(value) + control.set_resetable(false) + _syncing_ui = false + + _set_modified(not _config.is_equal(_config_defaults)) + audio_player.stream = null + + +func _on_Play_pressed(force_regenerate := false): + if force_regenerate or audio_player.stream == null: + audio_player.stream = _generator.generate_audio_stream(_config) + audio_player.play() + + +func _on_Randomize_pressed(category: int): + if category == -1: + _config.randomize() + _push_recent(translator.tr("Randomize")) + else: + _config.randomize_in_category(category) + _push_recent(_category_names.get(category, "Unknown")) + + _set_modified(true) + _sync_ui() + _on_Play_pressed(true) + + +func _on_Mutate_pressed(): + _config.mutate() + + _push_recent(translator.tr("Mutate")) + _set_modified(true) + _sync_ui() + _on_Play_pressed(true) + + +func _on_Restore_pressed(): + _set_editing_file(_path) + + +func _on_New_pressed(): + if _modified: + _popup_confirm( + translator.tr("There are unsaved changes.\nCreate a new one anyway?"), + "_on_New_confirmed" + ) + else: + _on_New_confirmed() + + +func _on_New_confirmed() -> void: + _set_editing_file("") + + +func _on_Save_pressed(): + if _path.empty(): + _popup_file_dialog(EditorFileDialog.MODE_SAVE_FILE, "_on_SaveAsDialog_confirmed") + else: + _config.save(_path) + plugin.get_editor_interface().get_resource_filesystem().scan_sources() + _reset_defaults() + + +func _on_SaveAsDialog_confirmed(path: String): + _path = path + _config.save(path) + plugin.get_editor_interface().get_resource_filesystem().scan() + _reset_defaults() + + +func _on_Load_pressed(): + if _modified: + _popup_confirm( + translator.tr("There are unsaved changes.\nLoad anyway?"), + "_popup_file_dialog", [EditorFileDialog.MODE_OPEN_FILE, "_set_editing_file"] + ) + else: + _popup_file_dialog(EditorFileDialog.MODE_OPEN_FILE, "_set_editing_file") + + +func _on_Extra_about_to_show(): + var popup := extra_button.get_popup() + popup.set_item_disabled(popup.get_item_index(ExtraOption.PASTE), _config_clipboard == null) + popup.set_item_disabled(popup.get_item_index(ExtraOption.PASTE_JSFXR), not OS.has_clipboard()) + + # Rebuild recents menu everytime :) + var first_recent_index := popup.get_item_index(ExtraOption.RECENT) + if first_recent_index != -1: + var count := popup.get_item_count() + for i in count - first_recent_index: + popup.remove_item(count - 1 - i) + + if _config_recents.empty(): + popup.add_item(translator.tr("None"), ExtraOption.RECENT) + popup.set_item_disabled(popup.get_item_index(ExtraOption.RECENT), true) + else: + for i in _config_recents.size(): + popup.add_item(_config_recents[i].title, ExtraOption.RECENT + i) + + +func _on_Extra_id_pressed(id: int) -> void: + match id: + ExtraOption.SAVE_AS: + _popup_file_dialog(EditorFileDialog.MODE_SAVE_FILE, "_on_SaveAsDialog_confirmed", DefaultFilename.GUESS_FOR_SAVE) + + ExtraOption.COPY: + if not _config_clipboard: + _config_clipboard = SFXRConfig.new() + _config_clipboard.copy_from(_config) + + ExtraOption.PASTE: + _restore_from_config(_config_clipboard) + + ExtraOption.PASTE_JSFXR: + var pasted := SFXRConfig.new() + if pasted.load_from_base58(OS.clipboard) == OK: + _restore_from_config(pasted) + else: + _popup_message(translator.tr("Clipboard does not contain code copied from jsfxr.")) + + _: + var i := id - ExtraOption.RECENT as int + if i < 0 or _config_recents.size() <= i: + printerr("Bad index %d (%d in total)" % [i, _config_recents.size()]) + return + var recent: RecentEntry = _config_recents[i] + _restore_from_config(recent.config) + _on_Play_pressed() + diff --git a/addons/gdfxr/editor/Editor.tscn b/addons/gdfxr/editor/Editor.tscn new file mode 100644 index 0000000..3641981 --- /dev/null +++ b/addons/gdfxr/editor/Editor.tscn @@ -0,0 +1,394 @@ +[gd_scene load_steps=7 format=2] + +[ext_resource path="res://addons/gdfxr/editor/EditorIconButton.gd" type="Script" id=1] +[ext_resource path="res://addons/gdfxr/editor/Editor.gd" type="Script" id=2] +[ext_resource path="res://addons/gdfxr/editor/ParamSlider.tscn" type="PackedScene" id=3] +[ext_resource path="res://addons/gdfxr/editor/ParamOption.tscn" type="PackedScene" id=4] +[ext_resource path="res://addons/gdfxr/editor/PluginTranslator.tscn" type="PackedScene" id=5] +[ext_resource path="res://addons/gdfxr/editor/VersionButton.tscn" type="PackedScene" id=6] + +[node name="Editor" type="VBoxContainer"] +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource( 2 ) + +[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] + +[node name="Toolbar" type="HBoxContainer" parent="."] +margin_right = 1024.0 +margin_bottom = 22.0 + +[node name="New" type="ToolButton" parent="Toolbar"] +margin_right = 12.0 +margin_bottom = 22.0 +hint_tooltip = "New" +script = ExtResource( 1 ) +icon_name = "New" + +[node name="Load" type="ToolButton" parent="Toolbar"] +margin_left = 16.0 +margin_right = 28.0 +margin_bottom = 22.0 +hint_tooltip = "Load" +script = ExtResource( 1 ) +icon_name = "Load" + +[node name="Save" type="ToolButton" parent="Toolbar"] +margin_left = 32.0 +margin_right = 44.0 +margin_bottom = 22.0 +hint_tooltip = "Save" +script = ExtResource( 1 ) +icon_name = "Save" + +[node name="Extra" type="MenuButton" parent="Toolbar"] +margin_left = 48.0 +margin_right = 60.0 +margin_bottom = 22.0 +hint_tooltip = "Extra Options" +script = ExtResource( 1 ) +icon_name = "GuiTabMenuHl" + +[node name="VSeparator" type="VSeparator" parent="Toolbar"] +margin_left = 64.0 +margin_right = 68.0 +margin_bottom = 22.0 + +[node name="Play" type="Button" parent="Toolbar"] +margin_left = 72.0 +margin_right = 152.0 +margin_bottom = 22.0 +rect_min_size = Vector2( 80, 0 ) +size_flags_horizontal = 0 +text = "Play" +script = ExtResource( 1 ) +icon_name = "Play" + +[node name="Restore" type="Button" parent="Toolbar"] +margin_left = 156.0 +margin_right = 236.0 +margin_bottom = 22.0 +rect_min_size = Vector2( 80, 0 ) +hint_tooltip = "Restore" +disabled = true +text = "Restore" +script = ExtResource( 1 ) +icon_name = "Reload" + +[node name="VSeparator2" type="VSeparator" parent="Toolbar"] +margin_left = 240.0 +margin_right = 244.0 +margin_bottom = 22.0 + +[node name="Filename" type="Label" parent="Toolbar"] +margin_left = 248.0 +margin_top = 4.0 +margin_right = 1020.0 +margin_bottom = 18.0 +size_flags_horizontal = 3 +text = "Unsaved sound" +clip_text = true + +[node name="VersionButton" parent="Toolbar" instance=ExtResource( 6 )] +margin_top = 4.0 +margin_bottom = 18.0 +website = "https://github.com/timothyqiu/gdfxr" + +[node name="HSeparator" type="HSeparator" parent="."] +margin_top = 26.0 +margin_right = 1024.0 +margin_bottom = 30.0 + +[node name="Editor" type="HBoxContainer" parent="."] +margin_top = 34.0 +margin_right = 1024.0 +margin_bottom = 600.0 +size_flags_vertical = 3 + +[node name="Generators" type="VBoxContainer" parent="Editor"] +margin_right = 128.0 +margin_bottom = 566.0 +rect_min_size = Vector2( 128, 0 ) + +[node name="Button" type="Button" parent="Editor/Generators"] +margin_right = 128.0 +margin_bottom = 20.0 +text = "Pickup/Coin" + +[node name="Button2" type="Button" parent="Editor/Generators"] +margin_top = 24.0 +margin_right = 128.0 +margin_bottom = 44.0 +text = "Laser/Shoot" + +[node name="Button3" type="Button" parent="Editor/Generators"] +margin_top = 48.0 +margin_right = 128.0 +margin_bottom = 68.0 +text = "Explosion" + +[node name="Button4" type="Button" parent="Editor/Generators"] +margin_top = 72.0 +margin_right = 128.0 +margin_bottom = 92.0 +text = "Powerup" + +[node name="Button5" type="Button" parent="Editor/Generators"] +margin_top = 96.0 +margin_right = 128.0 +margin_bottom = 116.0 +text = "Hit/Hurt" + +[node name="Button6" type="Button" parent="Editor/Generators"] +margin_top = 120.0 +margin_right = 128.0 +margin_bottom = 140.0 +text = "Jump" + +[node name="Button7" type="Button" parent="Editor/Generators"] +margin_top = 144.0 +margin_right = 128.0 +margin_bottom = 164.0 +text = "Blip/Select" + +[node name="HSeparator" type="HSeparator" parent="Editor/Generators"] +margin_top = 168.0 +margin_right = 128.0 +margin_bottom = 172.0 + +[node name="Button8" type="Button" parent="Editor/Generators"] +margin_top = 176.0 +margin_right = 128.0 +margin_bottom = 196.0 +size_flags_horizontal = 3 +text = "Mutate" + +[node name="Button9" type="Button" parent="Editor/Generators"] +margin_top = 200.0 +margin_right = 128.0 +margin_bottom = 220.0 +size_flags_horizontal = 3 +text = "Randomize" + +[node name="ScrollContainer" type="ScrollContainer" parent="Editor"] +margin_left = 132.0 +margin_right = 1024.0 +margin_bottom = 566.0 +size_flags_horizontal = 3 +scroll_vertical_enabled = false + +[node name="Params" type="HBoxContainer" parent="Editor/ScrollContainer"] +margin_top = 188.0 +margin_right = 895.0 +margin_bottom = 366.0 +size_flags_horizontal = 6 +size_flags_vertical = 6 + +[node name="Envolope" type="VBoxContainer" parent="Editor/ScrollContainer/Params"] +margin_right = 211.0 +margin_bottom = 178.0 + +[node name="ParamSlider" parent="Editor/ScrollContainer/Params/Envolope" instance=ExtResource( 3 )] +margin_right = 211.0 +margin_bottom = 22.0 +label = "Attack Time" +parameter = "p_env_attack" + +[node name="ParamSlider2" parent="Editor/ScrollContainer/Params/Envolope" instance=ExtResource( 3 )] +margin_top = 26.0 +margin_right = 211.0 +margin_bottom = 48.0 +label = "Sustain Time" +parameter = "p_env_sustain" + +[node name="ParamSlider3" parent="Editor/ScrollContainer/Params/Envolope" instance=ExtResource( 3 )] +margin_top = 52.0 +margin_right = 211.0 +margin_bottom = 74.0 +label = "Sustain Punch" +parameter = "p_env_punch" + +[node name="ParamSlider4" parent="Editor/ScrollContainer/Params/Envolope" instance=ExtResource( 3 )] +margin_top = 78.0 +margin_right = 211.0 +margin_bottom = 100.0 +label = "Decay Time" +parameter = "p_env_decay" + +[node name="ParamSlider5" parent="Editor/ScrollContainer/Params/Envolope" instance=ExtResource( 3 )] +margin_top = 104.0 +margin_right = 211.0 +margin_bottom = 126.0 +label = "Change Amount" +parameter = "p_arp_mod" +bipolar = true + +[node name="ParamSlider6" parent="Editor/ScrollContainer/Params/Envolope" instance=ExtResource( 3 )] +margin_top = 130.0 +margin_right = 211.0 +margin_bottom = 152.0 +label = "Change Speed" +parameter = "p_arp_speed" + +[node name="ParamSlider7" parent="Editor/ScrollContainer/Params/Envolope" instance=ExtResource( 3 )] +margin_top = 156.0 +margin_right = 211.0 +margin_bottom = 178.0 +label = "Volume" +parameter = "sound_vol" + +[node name="Frequency" type="VBoxContainer" parent="Editor/ScrollContainer/Params"] +margin_left = 215.0 +margin_right = 425.0 +margin_bottom = 178.0 + +[node name="ParamSlider" parent="Editor/ScrollContainer/Params/Frequency" instance=ExtResource( 3 )] +margin_right = 210.0 +margin_bottom = 22.0 +label = "Start Frequency" +parameter = "p_base_freq" + +[node name="ParamSlider2" parent="Editor/ScrollContainer/Params/Frequency" instance=ExtResource( 3 )] +margin_top = 26.0 +margin_right = 210.0 +margin_bottom = 48.0 +label = "Min Frequency" +parameter = "p_freq_limit" + +[node name="ParamSlider3" parent="Editor/ScrollContainer/Params/Frequency" instance=ExtResource( 3 )] +margin_top = 52.0 +margin_right = 210.0 +margin_bottom = 74.0 +label = "Slide" +parameter = "p_freq_ramp" +bipolar = true + +[node name="ParamSlider4" parent="Editor/ScrollContainer/Params/Frequency" instance=ExtResource( 3 )] +margin_top = 78.0 +margin_right = 210.0 +margin_bottom = 100.0 +label = "Delta Slide" +parameter = "p_freq_dramp" +bipolar = true + +[node name="ParamSlider5" parent="Editor/ScrollContainer/Params/Frequency" instance=ExtResource( 3 )] +margin_top = 104.0 +margin_right = 210.0 +margin_bottom = 126.0 +label = "Vibrato Depth" +parameter = "p_vib_strength" + +[node name="ParamSlider6" parent="Editor/ScrollContainer/Params/Frequency" instance=ExtResource( 3 )] +margin_top = 130.0 +margin_right = 210.0 +margin_bottom = 152.0 +label = "Vibrato Speed" +parameter = "p_vib_speed" + +[node name="ParamSlider7" parent="Editor/ScrollContainer/Params/Frequency" instance=ExtResource( 3 )] +margin_top = 156.0 +margin_right = 210.0 +margin_bottom = 178.0 +label = "Repeat Speed" +parameter = "p_repeat_speed" + +[node name="Waveform" type="VBoxContainer" parent="Editor/ScrollContainer/Params"] +margin_left = 429.0 +margin_right = 649.0 +margin_bottom = 178.0 + +[node name="WaveformOption" parent="Editor/ScrollContainer/Params/Waveform" instance=ExtResource( 4 )] +margin_right = 220.0 +margin_bottom = 22.0 +options = [ "Square", "Sawtooth", "Sine", "Noise" ] +parameter = "wave_type" + +[node name="ParamSlider" parent="Editor/ScrollContainer/Params/Waveform" instance=ExtResource( 3 )] +margin_top = 26.0 +margin_right = 220.0 +margin_bottom = 48.0 +label = "Square Duty" +parameter = "p_duty" + +[node name="ParamSlider2" parent="Editor/ScrollContainer/Params/Waveform" instance=ExtResource( 3 )] +margin_top = 52.0 +margin_right = 220.0 +margin_bottom = 74.0 +label = "Duty Sweep" +parameter = "p_duty_ramp" +bipolar = true + +[node name="ParamSlider5" parent="Editor/ScrollContainer/Params/Waveform" instance=ExtResource( 3 )] +margin_top = 78.0 +margin_right = 220.0 +margin_bottom = 100.0 +label = "Phaser Offset" +parameter = "p_pha_offset" +bipolar = true + +[node name="ParamSlider3" parent="Editor/ScrollContainer/Params/Waveform" instance=ExtResource( 3 )] +margin_top = 104.0 +margin_right = 220.0 +margin_bottom = 126.0 +label = "Phaser Sweep" +parameter = "p_pha_ramp" +bipolar = true + +[node name="Filter" type="VBoxContainer" parent="Editor/ScrollContainer/Params"] +margin_left = 653.0 +margin_right = 895.0 +margin_bottom = 178.0 + +[node name="ParamSlider" parent="Editor/ScrollContainer/Params/Filter" instance=ExtResource( 3 )] +margin_right = 242.0 +margin_bottom = 22.0 +label = "Low-pass Cutoff" +parameter = "p_lpf_freq" + +[node name="ParamSlider2" parent="Editor/ScrollContainer/Params/Filter" instance=ExtResource( 3 )] +margin_top = 26.0 +margin_right = 242.0 +margin_bottom = 48.0 +label = "Low-pass Sweep" +parameter = "p_lpf_ramp" +bipolar = true + +[node name="ParamSlider5" parent="Editor/ScrollContainer/Params/Filter" instance=ExtResource( 3 )] +margin_top = 52.0 +margin_right = 242.0 +margin_bottom = 74.0 +label = "Low-pass Resonance" +parameter = "p_lpf_resonance" + +[node name="ParamSlider3" parent="Editor/ScrollContainer/Params/Filter" instance=ExtResource( 3 )] +margin_top = 78.0 +margin_right = 242.0 +margin_bottom = 100.0 +label = "High-pass Cutoff" +parameter = "p_hpf_freq" + +[node name="ParamSlider4" parent="Editor/ScrollContainer/Params/Filter" instance=ExtResource( 3 )] +margin_top = 104.0 +margin_right = 242.0 +margin_bottom = 126.0 +label = "High-pass Sweep" +parameter = "p_hpf_ramp" +bipolar = true + +[node name="PluginTranslator" parent="." instance=ExtResource( 5 )] + +[connection signal="pressed" from="Toolbar/New" to="." method="_on_New_pressed"] +[connection signal="pressed" from="Toolbar/Load" to="." method="_on_Load_pressed"] +[connection signal="pressed" from="Toolbar/Save" to="." method="_on_Save_pressed"] +[connection signal="about_to_show" from="Toolbar/Extra" to="." method="_on_Extra_about_to_show"] +[connection signal="pressed" from="Toolbar/Play" to="." method="_on_Play_pressed"] +[connection signal="pressed" from="Toolbar/Restore" to="." method="_on_Restore_pressed"] +[connection signal="pressed" from="Editor/Generators/Button" to="." method="_on_Randomize_pressed" binds= [ 0 ]] +[connection signal="pressed" from="Editor/Generators/Button2" to="." method="_on_Randomize_pressed" binds= [ 1 ]] +[connection signal="pressed" from="Editor/Generators/Button3" to="." method="_on_Randomize_pressed" binds= [ 2 ]] +[connection signal="pressed" from="Editor/Generators/Button4" to="." method="_on_Randomize_pressed" binds= [ 3 ]] +[connection signal="pressed" from="Editor/Generators/Button5" to="." method="_on_Randomize_pressed" binds= [ 4 ]] +[connection signal="pressed" from="Editor/Generators/Button6" to="." method="_on_Randomize_pressed" binds= [ 5 ]] +[connection signal="pressed" from="Editor/Generators/Button7" to="." method="_on_Randomize_pressed" binds= [ 6 ]] +[connection signal="pressed" from="Editor/Generators/Button8" to="." method="_on_Mutate_pressed"] +[connection signal="pressed" from="Editor/Generators/Button9" to="." method="_on_Randomize_pressed" binds= [ -1 ]] diff --git a/addons/gdfxr/editor/EditorIconButton.gd b/addons/gdfxr/editor/EditorIconButton.gd new file mode 100644 index 0000000..9a16ad0 --- /dev/null +++ b/addons/gdfxr/editor/EditorIconButton.gd @@ -0,0 +1,16 @@ +tool +extends Button + +export var icon_name: String + +var plugin: EditorPlugin # a hack to know if this is executing as plugin + + +func _notification(what: int): + if not plugin: + return + + match what: + NOTIFICATION_ENTER_TREE, NOTIFICATION_THEME_CHANGED: + if icon_name: + icon = get_icon(icon_name, "EditorIcons") diff --git a/addons/gdfxr/editor/ParamOption.gd b/addons/gdfxr/editor/ParamOption.gd new file mode 100644 index 0000000..29402ff --- /dev/null +++ b/addons/gdfxr/editor/ParamOption.gd @@ -0,0 +1,43 @@ +tool +extends HBoxContainer + +signal param_changed(name, value) +signal param_reset(name) + +export var options: Array setget set_options +export var parameter: String # Could be PoolStringArray, but pybabel won't catch that + +onready var option_button := $OptionButton as OptionButton + + +func _ready(): + set_options(options) + + +func set_options(v: Array) -> void: + options = v + + if is_inside_tree(): + option_button.clear() + for item in options: + option_button.add_item(item) + + +func set_value(v: int) -> void: + option_button.select(v) + + +func get_value() -> int: + return option_button.selected + + +func set_resetable(v: bool) -> void: + $Reset.disabled = not v + + +func _on_OptionButton_item_selected(index: int): + emit_signal("param_changed", parameter, index) + + +func _on_Reset_pressed(): + emit_signal("param_reset", parameter) diff --git a/addons/gdfxr/editor/ParamOption.tscn b/addons/gdfxr/editor/ParamOption.tscn new file mode 100644 index 0000000..41452da --- /dev/null +++ b/addons/gdfxr/editor/ParamOption.tscn @@ -0,0 +1,43 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://addons/gdfxr/editor/ParamOption.gd" type="Script" id=1] +[ext_resource path="res://addons/gdfxr/editor/EditorIconButton.gd" type="Script" id=2] + +[node name="WaveformOption" type="HBoxContainer"] +margin_right = 253.0 +margin_bottom = 40.0 +rect_pivot_offset = Vector2( 41, -65 ) +size_flags_horizontal = 3 +script = ExtResource( 1 ) + +[node name="Label" type="Label" parent="."] +margin_top = 13.0 +margin_right = 128.0 +margin_bottom = 27.0 +rect_min_size = Vector2( 100, 0 ) +size_flags_horizontal = 3 +text = "Waveform" +align = 2 + +[node name="OptionButton" type="OptionButton" parent="."] +margin_left = 132.0 +margin_top = 10.0 +margin_right = 237.0 +margin_bottom = 30.0 +rect_min_size = Vector2( 105, 0 ) +size_flags_vertical = 4 +clip_text = true + +[node name="Reset" type="ToolButton" parent="."] +margin_left = 241.0 +margin_top = 9.0 +margin_right = 253.0 +margin_bottom = 31.0 +focus_mode = 0 +size_flags_vertical = 4 +enabled_focus_mode = 0 +script = ExtResource( 2 ) +icon_name = "ReloadSmall" + +[connection signal="item_selected" from="OptionButton" to="." method="_on_OptionButton_item_selected"] +[connection signal="pressed" from="Reset" to="." method="_on_Reset_pressed"] diff --git a/addons/gdfxr/editor/ParamSlider.gd b/addons/gdfxr/editor/ParamSlider.gd new file mode 100644 index 0000000..c88a258 --- /dev/null +++ b/addons/gdfxr/editor/ParamSlider.gd @@ -0,0 +1,43 @@ +tool +extends HBoxContainer + +signal param_changed(name, value) +signal param_reset(name) + +export var label: String setget set_label +export var parameter: String +export var bipolar := false setget set_bipolar + + +func set_label(v: String) -> void: + label = v + $Label.text = v + + +func set_bipolar(v: bool) -> void: + bipolar = v + if bipolar: + $HSlider.min_value = -1.0 + else: + $HSlider.min_value = 0.0 + + +func set_value(v: float) -> void: + $HSlider.value = v + + +func get_value() -> float: + return $HSlider.value + + +func set_resetable(v: bool) -> void: + $Reset.disabled = not v + + +func _on_HSlider_value_changed(value: float): + emit_signal("param_changed", parameter, value) + + +func _on_Reset_pressed(): + emit_signal("param_reset", parameter) + diff --git a/addons/gdfxr/editor/ParamSlider.tscn b/addons/gdfxr/editor/ParamSlider.tscn new file mode 100644 index 0000000..33ba555 --- /dev/null +++ b/addons/gdfxr/editor/ParamSlider.tscn @@ -0,0 +1,42 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://addons/gdfxr/editor/ParamSlider.gd" type="Script" id=1] +[ext_resource path="res://addons/gdfxr/editor/EditorIconButton.gd" type="Script" id=2] +[ext_resource path="res://addons/gdfxr/editor/EditSlider.gd" type="Script" id=3] + +[node name="ParamSlider" type="HBoxContainer"] +margin_right = 253.0 +margin_bottom = 40.0 +size_flags_horizontal = 3 +script = ExtResource( 1 ) + +[node name="Label" type="Label" parent="."] +margin_top = 13.0 +margin_right = 128.0 +margin_bottom = 27.0 +rect_min_size = Vector2( 100, 0 ) +size_flags_horizontal = 3 +align = 2 + +[node name="HSlider" type="Control" parent="."] +margin_left = 132.0 +margin_right = 237.0 +margin_bottom = 40.0 +rect_min_size = Vector2( 105, 0 ) +rect_clip_content = true +focus_mode = 2 +mouse_default_cursor_shape = 10 +script = ExtResource( 3 ) + +[node name="Reset" type="ToolButton" parent="."] +margin_left = 241.0 +margin_top = 9.0 +margin_right = 253.0 +margin_bottom = 31.0 +focus_mode = 0 +size_flags_vertical = 4 +script = ExtResource( 2 ) +icon_name = "ReloadSmall" + +[connection signal="value_changed" from="HSlider" to="." method="_on_HSlider_value_changed"] +[connection signal="pressed" from="Reset" to="." method="_on_Reset_pressed"] diff --git a/addons/gdfxr/editor/PluginTranslator.gd b/addons/gdfxr/editor/PluginTranslator.gd new file mode 100644 index 0000000..c4f9017 --- /dev/null +++ b/addons/gdfxr/editor/PluginTranslator.gd @@ -0,0 +1,56 @@ +tool +extends Node + +var plugin: EditorPlugin setget set_plugin + +var _translation: Translation + + +func set_plugin(v: EditorPlugin) -> void: + if plugin == v: + return + if not v: + plugin = null + _translation = null + return + + plugin = v + var locale: String = plugin.get_editor_interface().get_editor_settings().get('interface/editor/editor_language') + var script := get_script() as Script + var path := script.resource_path.get_base_dir().plus_file("translations/%s.po" % locale) + if ResourceLoader.exists(path): + _translation = ResourceLoader.load(path) + + if _translation: + _translate_node(get_parent()) + + +func tr(message: String) -> String: + if _translation: + var translated := _translation.get_message(message) + if not translated.empty(): + return translated + return message + + +func _translate_node(node: Node): + if node is Control: + node.hint_tooltip = tr(node.hint_tooltip) + + if node is HBoxContainer and node.has_method("set_options"): + var options = [] + for item in node.options: + options.append(tr(item)) + node.options = options + + if node is Button and not node is OptionButton: + node.text = tr(node.text) + + if node is Label: + node.text = tr(node.text) + + if node is Slider: + node.hint_tooltip = tr(node.hint_tooltip) + + for child in node.get_children(): + _translate_node(child) diff --git a/addons/gdfxr/editor/PluginTranslator.tscn b/addons/gdfxr/editor/PluginTranslator.tscn new file mode 100644 index 0000000..1868f2a --- /dev/null +++ b/addons/gdfxr/editor/PluginTranslator.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://addons/gdfxr/editor/PluginTranslator.gd" type="Script" id=1] + +[node name="PluginTranslator" type="Node"] +script = ExtResource( 1 ) diff --git a/addons/gdfxr/editor/VersionButton.gd b/addons/gdfxr/editor/VersionButton.gd new file mode 100644 index 0000000..3baa0dd --- /dev/null +++ b/addons/gdfxr/editor/VersionButton.gd @@ -0,0 +1,25 @@ +tool +extends LinkButton + +export var website: String + +var plugin: EditorPlugin setget set_plugin + + +func set_plugin(v: EditorPlugin) -> void: + plugin = v + + var script := get_script() as Script + var path := script.resource_path.get_base_dir().plus_file("../plugin.cfg") + + var cfg := ConfigFile.new() + var err := cfg.load(path) + text = "%s v%s" % [ + cfg.get_value("plugin", "name", "plugin"), + cfg.get_value("plugin", "version", "1.0"), + ] + + +func _on_VersionButton_pressed(): + if website: + OS.shell_open(website) diff --git a/addons/gdfxr/editor/VersionButton.tscn b/addons/gdfxr/editor/VersionButton.tscn new file mode 100644 index 0000000..c0161b4 --- /dev/null +++ b/addons/gdfxr/editor/VersionButton.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://addons/gdfxr/editor/VersionButton.gd" type="Script" id=1] + +[node name="VersionButton" type="LinkButton"] +self_modulate = Color( 1, 1, 1, 0.65 ) +margin_left = 1024.0 +margin_top = 5.0 +margin_right = 1024.0 +margin_bottom = 19.0 +focus_mode = 2 +size_flags_vertical = 4 +underline = 1 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[connection signal="pressed" from="." to="." method="_on_VersionButton_pressed"] diff --git a/addons/gdfxr/editor/translations/zh_CN.po b/addons/gdfxr/editor/translations/zh_CN.po new file mode 100644 index 0000000..9ca15d9 --- /dev/null +++ b/addons/gdfxr/editor/translations/zh_CN.po @@ -0,0 +1,265 @@ +# Translations template for gdfxr. +# Copyright (C) 2022 Haoyu Qiu +# This file is distributed under the same license as the gdfxr project. +# Haoyu Qiu , 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: gdfxr 1.0\n" +"Report-Msgid-Bugs-To: timothyqiu32@gmail.com\n" +"POT-Creation-Date: 2022-12-04 13:45+0800\n" +"PO-Revision-Date: 2022-12-04 13:45+0800\n" +"Last-Translator: Haoyu Qiu \n" +"Language-Team: \n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"Generated-By: Babel 2.9.1\n" +"X-Generator: Poedit 3.2.1\n" + +#: addons/gdfxr/editor/Editor.gd +msgid "Save As..." +msgstr "另存为..." + +#: addons/gdfxr/editor/Editor.gd +msgid "Copy" +msgstr "复制" + +#: addons/gdfxr/editor/Editor.gd +msgid "Paste" +msgstr "粘贴" + +#: addons/gdfxr/editor/Editor.gd +msgid "Paste from jsfxr" +msgstr "从 jsfxr 粘贴" + +#: addons/gdfxr/editor/Editor.gd +msgid "Recently Generated" +msgstr "最近生成" + +#: addons/gdfxr/editor/Editor.gd addons/gdfxr/editor/Editor.tscn +msgid "Pickup/Coin" +msgstr "拾取/金币" + +#: addons/gdfxr/editor/Editor.gd addons/gdfxr/editor/Editor.tscn +msgid "Laser/Shoot" +msgstr "激光/射击" + +#: addons/gdfxr/editor/Editor.gd addons/gdfxr/editor/Editor.tscn +msgid "Explosion" +msgstr "爆炸" + +#: addons/gdfxr/editor/Editor.gd addons/gdfxr/editor/Editor.tscn +msgid "Powerup" +msgstr "升级" + +#: addons/gdfxr/editor/Editor.gd addons/gdfxr/editor/Editor.tscn +msgid "Hit/Hurt" +msgstr "击中/受伤" + +#: addons/gdfxr/editor/Editor.gd addons/gdfxr/editor/Editor.tscn +msgid "Jump" +msgstr "跳跃" + +#: addons/gdfxr/editor/Editor.gd addons/gdfxr/editor/Editor.tscn +msgid "Blip/Select" +msgstr "短滴/选择" + +#: addons/gdfxr/editor/Editor.gd +#, python-format +msgid "" +"There are unsaved changes.\n" +"Open '%s' anyway?" +msgstr "" +"存在未保存的修改。\n" +"仍然要打开“%s”吗?" + +#: addons/gdfxr/editor/Editor.gd +msgid "SFXR Editor" +msgstr "SFXR 编辑器" + +#: addons/gdfxr/editor/Editor.gd +msgid "SFXR Audio" +msgstr "SFXR 音频" + +#: addons/gdfxr/editor/Editor.gd +#, python-format +msgid "'%s' is not a valid SFXR file." +msgstr "“%s”不是有效的 SFXR 文件。" + +#: addons/gdfxr/editor/Editor.gd addons/gdfxr/editor/Editor.tscn +msgid "Unsaved sound" +msgstr "未保存音效" + +#: addons/gdfxr/editor/Editor.gd addons/gdfxr/editor/Editor.tscn +msgid "Randomize" +msgstr "随机" + +#: addons/gdfxr/editor/Editor.gd addons/gdfxr/editor/Editor.tscn +msgid "Mutate" +msgstr "演化" + +#: addons/gdfxr/editor/Editor.gd +msgid "" +"There are unsaved changes.\n" +"Create a new one anyway?" +msgstr "" +"存在未保存的修改。\n" +"仍然要新建吗?" + +#: addons/gdfxr/editor/Editor.gd +msgid "" +"There are unsaved changes.\n" +"Load anyway?" +msgstr "" +"存在未保存的修改。\n" +"仍然要加载吗?" + +#: addons/gdfxr/editor/Editor.gd +msgid "None" +msgstr "无" + +#: addons/gdfxr/editor/Editor.gd +msgid "Clipboard does not contain code copied from jsfxr." +msgstr "剪贴板中没有从 jsfxr 复制的代码。" + +#: addons/gdfxr/editor/Editor.tscn +msgid "New" +msgstr "新建" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Load" +msgstr "加载" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Save" +msgstr "保存" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Extra Options" +msgstr "更多选项" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Play" +msgstr "播放" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Restore" +msgstr "恢复" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Attack Time" +msgstr "起音时间" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Sustain Time" +msgstr "延音时间" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Sustain Punch" +msgstr "延音冲击" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Decay Time" +msgstr "释音时间" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Change Amount" +msgstr "改变强度" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Change Speed" +msgstr "改变速度" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Volume" +msgstr "音量" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Start Frequency" +msgstr "起始频率" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Min Frequency" +msgstr "最低频率" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Slide" +msgstr "滑音" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Delta Slide" +msgstr "滑音增量" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Vibrato Depth" +msgstr "颤音深度" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Vibrato Speed" +msgstr "颤音速度" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Repeat Speed" +msgstr "重复速度" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Square" +msgstr "方波" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Sawtooth" +msgstr "锯齿波" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Sine" +msgstr "正弦波" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Noise" +msgstr "噪波" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Square Duty" +msgstr "方波工作" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Duty Sweep" +msgstr "工作变频" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Phaser Offset" +msgstr "相位偏移" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Phaser Sweep" +msgstr "相位变频" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Low-pass Cutoff" +msgstr "低通截频" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Low-pass Sweep" +msgstr "低通变频" + +#: addons/gdfxr/editor/Editor.tscn +msgid "Low-pass Resonance" +msgstr "低通共振" + +#: addons/gdfxr/editor/Editor.tscn +msgid "High-pass Cutoff" +msgstr "高通截频" + +#: addons/gdfxr/editor/Editor.tscn +msgid "High-pass Sweep" +msgstr "高通变频" + +#: addons/gdfxr/editor/ParamOption.tscn +msgid "Waveform" +msgstr "波形" + +#~ msgid "Hold Ctrl to snap to 0.01 increments." +#~ msgstr "按住 Ctrl 吸附到 0.01 增量。" diff --git a/addons/gdfxr/import_plugin.gd b/addons/gdfxr/import_plugin.gd new file mode 100644 index 0000000..5dce8ff --- /dev/null +++ b/addons/gdfxr/import_plugin.gd @@ -0,0 +1,76 @@ +tool +extends EditorImportPlugin + +const SFXRConfig = preload("SFXRConfig.gd") +const SFXRGenerator = preload("SFXRGenerator.gd") + + +func get_importer_name(): + return "com.timothyqiu.gdfxr.importer" + + +func get_visible_name(): + return "SFXR Audio" + + +func get_recognized_extensions(): + return ["sfxr"] + + +func get_save_extension(): + return "sample" + + +func get_resource_type(): + return "AudioStreamSample" + + +func get_preset_count(): + return 1 + + +func get_preset_name(preset): + return "Default" + + +func get_import_options(preset): + return [ + { + name="loop", + default_value=false, + }, + { + name="bit_depth", + property_hint=PROPERTY_HINT_ENUM, + hint_string="8 Bits,16 Bits", + default_value=SFXRGenerator.WavBits.WAV_BITS_8, + }, + { + name="sample_rate", + property_hint=PROPERTY_HINT_ENUM, + hint_string="44100 Hz,22050 Hz", + default_value=SFXRGenerator.WavFreq.WAV_FREQ_44100, + }, + ] + + +func get_option_visibility(option, options): + return true + + +func import(source_file, save_path, options, platform_variants, gen_files): + var config := SFXRConfig.new() + var err := config.load(source_file) + if err != OK: + printerr("Failed to open %s: %d" % [source_file, err]) + return err + + var stream := SFXRGenerator.new().generate_audio_stream( + config, options.bit_depth, options.sample_rate + ) + if options.loop: + stream.loop_mode = AudioStreamSample.LOOP_FORWARD + stream.loop_end = stream.data.size() + + var filename = save_path + "." + get_save_extension() + return ResourceSaver.save(filename, stream) diff --git a/addons/gdfxr/plugin.cfg b/addons/gdfxr/plugin.cfg new file mode 100644 index 0000000..253bebe --- /dev/null +++ b/addons/gdfxr/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="gdfxr" +description="A Godot plugin that ports sfxr, the popular program of choice to make retro sound effects for games." +author="Haoyu Qiu" +version="1.3" +script="plugin.gd" diff --git a/addons/gdfxr/plugin.gd b/addons/gdfxr/plugin.gd new file mode 100644 index 0000000..25bb1e9 --- /dev/null +++ b/addons/gdfxr/plugin.gd @@ -0,0 +1,39 @@ +tool +extends EditorPlugin + + +var import_plugin: EditorImportPlugin +var sfxr_editor: Control + + +func _enter_tree(): + import_plugin = preload("import_plugin.gd").new() + add_import_plugin(import_plugin) + + sfxr_editor = preload("editor/Editor.tscn").instance() + sfxr_editor.plugin = self + add_control_to_bottom_panel(sfxr_editor, "gdfxr") + + +func _exit_tree(): + remove_control_from_bottom_panel(sfxr_editor) + sfxr_editor.queue_free() + sfxr_editor = null + + remove_import_plugin(import_plugin) + import_plugin = null + + +func handles(object: Object) -> bool: + return object is AudioStreamSample and object.resource_path.ends_with(".sfxr") + + +func edit(object: Object): + sfxr_editor.edit(object.resource_path) # Should already passed `handles()` checks + + +func make_visible(visible: bool): + if visible: + make_bottom_panel_item_visible(sfxr_editor) + elif sfxr_editor.is_visible_in_tree(): + hide_bottom_panel() diff --git a/fonts/dotty.ttf b/fonts/dotty.ttf new file mode 100644 index 0000000..4ce2814 Binary files /dev/null and b/fonts/dotty.ttf differ diff --git a/fonts/game over.ttf b/fonts/game over.ttf new file mode 100644 index 0000000..0555013 Binary files /dev/null and b/fonts/game over.ttf differ diff --git a/icon.png b/icon.png index c98fbb6..bbe1ec2 100644 Binary files a/icon.png and b/icon.png differ diff --git a/project.godot b/project.godot index 30ad535..b8382ac 100644 --- a/project.godot +++ b/project.godot @@ -11,13 +11,22 @@ config_version=4 [application] config/name="H2Grow" +run/main_scene="res://Scenes/Start.tscn" config/icon="res://icon.png" +[autoload] + +Utils="*res://Scripts/Utils.gd" + [display] window/size/resizable=false window/vsync/use_vsync=false +[editor_plugins] + +enabled=PoolStringArray( "res://addons/gdfxr/plugin.cfg" ) + [gui] common/drop_mouse_on_gui_input_disabled=true