diff --git a/art/exported/characters/base/netfishing_base_character.glb b/art/exported/characters/base/netfishing_base_character.glb index 2260131..b4bb5d1 100644 Binary files a/art/exported/characters/base/netfishing_base_character.glb and b/art/exported/characters/base/netfishing_base_character.glb differ diff --git a/art/exported/characters/faces/eyes/eyes_alligator_eyes.png b/art/exported/characters/faces/eyes/eyes_alligator_eyes.png new file mode 100644 index 0000000..74736eb Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_alligator_eyes.png differ diff --git a/art/exported/characters/faces/eyes/eyes_simple_shine_eyebrows.png.import b/art/exported/characters/faces/eyes/eyes_alligator_eyes.png.import similarity index 68% rename from art/exported/characters/faces/eyes/eyes_simple_shine_eyebrows.png.import rename to art/exported/characters/faces/eyes/eyes_alligator_eyes.png.import index 94c26e2..7f2eb8d 100644 --- a/art/exported/characters/faces/eyes/eyes_simple_shine_eyebrows.png.import +++ b/art/exported/characters/faces/eyes/eyes_alligator_eyes.png.import @@ -2,16 +2,16 @@ importer="texture" type="CompressedTexture2D" -uid="uid://8wg4k4us4baa" -path="res://.godot/imported/eyes_simple_shine_eyebrows.png-d2147df0247f280b8f63b23d590204ab.ctex" +uid="uid://br2h5sfqmool8" +path="res://.godot/imported/eyes_alligator_eyes.png-843d36964858cdf7ffafe1972ffed681.ctex" metadata={ "vram_texture": false } [deps] -source_file="res://art/exported/characters/faces/eyes/eyes_simple_shine_eyebrows.png" -dest_files=["res://.godot/imported/eyes_simple_shine_eyebrows.png-d2147df0247f280b8f63b23d590204ab.ctex"] +source_file="res://art/exported/characters/faces/eyes/eyes_alligator_eyes.png" +dest_files=["res://.godot/imported/eyes_alligator_eyes.png-843d36964858cdf7ffafe1972ffed681.ctex"] [params] diff --git a/art/exported/characters/faces/eyes/eyes_angry.png b/art/exported/characters/faces/eyes/eyes_angry.png new file mode 100644 index 0000000..f88220e Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_angry.png differ diff --git a/art/exported/characters/faces/mouth/mouth_three.png.import b/art/exported/characters/faces/eyes/eyes_angry.png.import similarity index 72% rename from art/exported/characters/faces/mouth/mouth_three.png.import rename to art/exported/characters/faces/eyes/eyes_angry.png.import index 914fcf4..3be46d5 100644 --- a/art/exported/characters/faces/mouth/mouth_three.png.import +++ b/art/exported/characters/faces/eyes/eyes_angry.png.import @@ -2,16 +2,16 @@ importer="texture" type="CompressedTexture2D" -uid="uid://crrw5vvop2gj7" -path="res://.godot/imported/mouth_three.png-b0b3775e32dfd17b6cfcac16b5c64d58.ctex" +uid="uid://b1ieqa8qos1vk" +path="res://.godot/imported/eyes_angry.png-a114dbeb3a8a14b8d1d86dd5a614b228.ctex" metadata={ "vram_texture": false } [deps] -source_file="res://art/exported/characters/faces/mouth/mouth_three.png" -dest_files=["res://.godot/imported/mouth_three.png-b0b3775e32dfd17b6cfcac16b5c64d58.ctex"] +source_file="res://art/exported/characters/faces/eyes/eyes_angry.png" +dest_files=["res://.godot/imported/eyes_angry.png-a114dbeb3a8a14b8d1d86dd5a614b228.ctex"] [params] diff --git a/art/exported/characters/faces/eyes/eyes_anime_blue.png b/art/exported/characters/faces/eyes/eyes_anime_blue.png new file mode 100644 index 0000000..39a6b86 Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_anime_blue.png differ diff --git a/art/exported/characters/faces/eyes/eyes_simple_shine.png.import b/art/exported/characters/faces/eyes/eyes_anime_blue.png.import similarity index 70% rename from art/exported/characters/faces/eyes/eyes_simple_shine.png.import rename to art/exported/characters/faces/eyes/eyes_anime_blue.png.import index 8cc687f..443c8d0 100644 --- a/art/exported/characters/faces/eyes/eyes_simple_shine.png.import +++ b/art/exported/characters/faces/eyes/eyes_anime_blue.png.import @@ -2,16 +2,16 @@ importer="texture" type="CompressedTexture2D" -uid="uid://b345yhfv8w1j5" -path="res://.godot/imported/eyes_simple_shine.png-33edcf4bb163d7f2bde9a662105cf788.ctex" +uid="uid://2ecbidhb33vy" +path="res://.godot/imported/eyes_anime_blue.png-a86f72e375fc30cac2cd8320813c7c6c.ctex" metadata={ "vram_texture": false } [deps] -source_file="res://art/exported/characters/faces/eyes/eyes_simple_shine.png" -dest_files=["res://.godot/imported/eyes_simple_shine.png-33edcf4bb163d7f2bde9a662105cf788.ctex"] +source_file="res://art/exported/characters/faces/eyes/eyes_anime_blue.png" +dest_files=["res://.godot/imported/eyes_anime_blue.png-a86f72e375fc30cac2cd8320813c7c6c.ctex"] [params] diff --git a/art/exported/characters/faces/eyes/eyes_anime_green.png b/art/exported/characters/faces/eyes/eyes_anime_green.png new file mode 100644 index 0000000..e273c6e Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_anime_green.png differ diff --git a/art/exported/characters/faces/eyes/eyes_anime_green.png.import b/art/exported/characters/faces/eyes/eyes_anime_green.png.import new file mode 100644 index 0000000..a1be2b0 --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_anime_green.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bwrxrtiv375ne" +path="res://.godot/imported/eyes_anime_green.png-a789a8f21c23e3085bca8992b3a3fc25.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_anime_green.png" +dest_files=["res://.godot/imported/eyes_anime_green.png-a789a8f21c23e3085bca8992b3a3fc25.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_beady.png b/art/exported/characters/faces/eyes/eyes_beady.png new file mode 100644 index 0000000..cdc5c2a Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_beady.png differ diff --git a/art/exported/characters/faces/eyes/eyes_beady.png.import b/art/exported/characters/faces/eyes/eyes_beady.png.import new file mode 100644 index 0000000..829845c --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_beady.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bahypju2dturm" +path="res://.godot/imported/eyes_beady.png-18d3b3ff0818d80f773d4f72d0b0061e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_beady.png" +dest_files=["res://.godot/imported/eyes_beady.png-18d3b3ff0818d80f773d4f72d0b0061e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_beady_eyebrows.png b/art/exported/characters/faces/eyes/eyes_beady_eyebrows.png new file mode 100644 index 0000000..80b1077 Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_beady_eyebrows.png differ diff --git a/art/exported/characters/faces/eyes/eyes_beady_eyebrows.png.import b/art/exported/characters/faces/eyes/eyes_beady_eyebrows.png.import new file mode 100644 index 0000000..4368bec --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_beady_eyebrows.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dp4sm67vn52um" +path="res://.godot/imported/eyes_beady_eyebrows.png-4f63e1a7ca603e9daf2d37a1d182e93f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_beady_eyebrows.png" +dest_files=["res://.godot/imported/eyes_beady_eyebrows.png-4f63e1a7ca603e9daf2d37a1d182e93f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_beady_whites.png b/art/exported/characters/faces/eyes/eyes_beady_whites.png new file mode 100644 index 0000000..960fe50 Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_beady_whites.png differ diff --git a/art/exported/characters/faces/eyes/eyes_beady_whites.png.import b/art/exported/characters/faces/eyes/eyes_beady_whites.png.import new file mode 100644 index 0000000..2b6680e --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_beady_whites.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cw34wh51s5sxi" +path="res://.godot/imported/eyes_beady_whites.png-87ce5dcbdfca9ca43a6f7c5ddca77bfa.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_beady_whites.png" +dest_files=["res://.godot/imported/eyes_beady_whites.png-87ce5dcbdfca9ca43a6f7c5ddca77bfa.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_carrot_eyes.png b/art/exported/characters/faces/eyes/eyes_carrot_eyes.png new file mode 100644 index 0000000..5a11a4b Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_carrot_eyes.png differ diff --git a/art/exported/characters/faces/eyes/eyes_carrot_eyes.png.import b/art/exported/characters/faces/eyes/eyes_carrot_eyes.png.import new file mode 100644 index 0000000..80ef07a --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_carrot_eyes.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://vn7mkjkx80ix" +path="res://.godot/imported/eyes_carrot_eyes.png-4d4af86c340a0dd0633449a9c6cc1bae.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_carrot_eyes.png" +dest_files=["res://.godot/imported/eyes_carrot_eyes.png-4d4af86c340a0dd0633449a9c6cc1bae.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_close.png b/art/exported/characters/faces/eyes/eyes_close.png new file mode 100644 index 0000000..1e0123f Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_close.png differ diff --git a/art/exported/characters/faces/eyes/eyes_close.png.import b/art/exported/characters/faces/eyes/eyes_close.png.import new file mode 100644 index 0000000..25986e6 --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_close.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://kbigjk76ejx8" +path="res://.godot/imported/eyes_close.png-13a7da90295acf57ea489edcf26fc555.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_close.png" +dest_files=["res://.godot/imported/eyes_close.png-13a7da90295acf57ea489edcf26fc555.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_cute.png b/art/exported/characters/faces/eyes/eyes_cute.png new file mode 100644 index 0000000..1e078b9 Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_cute.png differ diff --git a/art/exported/characters/faces/eyes/eyes_cute.png.import b/art/exported/characters/faces/eyes/eyes_cute.png.import new file mode 100644 index 0000000..c8d9f09 --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_cute.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b5455dbwse02f" +path="res://.godot/imported/eyes_cute.png-e2eabbdf5281c15927e85f1e2f22b127.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_cute.png" +dest_files=["res://.godot/imported/eyes_cute.png-e2eabbdf5281c15927e85f1e2f22b127.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_cute_close.png b/art/exported/characters/faces/eyes/eyes_cute_close.png new file mode 100644 index 0000000..c49f1c5 Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_cute_close.png differ diff --git a/art/exported/characters/faces/eyes/eyes_cute_close.png.import b/art/exported/characters/faces/eyes/eyes_cute_close.png.import new file mode 100644 index 0000000..5b51dc2 --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_cute_close.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://lp21yuhfqbc1" +path="res://.godot/imported/eyes_cute_close.png-7a8a1b4e10864cfef604b9ced31a3f0c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_cute_close.png" +dest_files=["res://.godot/imported/eyes_cute_close.png-7a8a1b4e10864cfef604b9ced31a3f0c.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_huge.png b/art/exported/characters/faces/eyes/eyes_huge.png new file mode 100644 index 0000000..5c1026f Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_huge.png differ diff --git a/art/exported/characters/faces/eyes/eyes_huge.png.import b/art/exported/characters/faces/eyes/eyes_huge.png.import new file mode 100644 index 0000000..2c449bd --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_huge.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://vb1eaupu8fpm" +path="res://.godot/imported/eyes_huge.png-9747926f369b1134a94639907057a08d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_huge.png" +dest_files=["res://.godot/imported/eyes_huge.png-9747926f369b1134a94639907057a08d.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_interested.png b/art/exported/characters/faces/eyes/eyes_interested.png new file mode 100644 index 0000000..4e1239e Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_interested.png differ diff --git a/art/exported/characters/faces/eyes/eyes_interested.png.import b/art/exported/characters/faces/eyes/eyes_interested.png.import new file mode 100644 index 0000000..061fe34 --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_interested.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b3481384do6m4" +path="res://.godot/imported/eyes_interested.png-5e8a34c0afaf7b4543f1b892af2227c7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_interested.png" +dest_files=["res://.godot/imported/eyes_interested.png-5e8a34c0afaf7b4543f1b892af2227c7.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_jackolantern.png b/art/exported/characters/faces/eyes/eyes_jackolantern.png new file mode 100644 index 0000000..98a0492 Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_jackolantern.png differ diff --git a/art/exported/characters/faces/eyes/eyes_jackolantern.png.import b/art/exported/characters/faces/eyes/eyes_jackolantern.png.import new file mode 100644 index 0000000..c447cdd --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_jackolantern.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cdqqfoss11muq" +path="res://.godot/imported/eyes_jackolantern.png-16dc8591f3bd827988f8fcb90bbced59.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_jackolantern.png" +dest_files=["res://.godot/imported/eyes_jackolantern.png-16dc8591f3bd827988f8fcb90bbced59.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_jackolantern_small.png b/art/exported/characters/faces/eyes/eyes_jackolantern_small.png new file mode 100644 index 0000000..1bb27fe Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_jackolantern_small.png differ diff --git a/art/exported/characters/faces/eyes/eyes_jackolantern_small.png.import b/art/exported/characters/faces/eyes/eyes_jackolantern_small.png.import new file mode 100644 index 0000000..8de58a2 --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_jackolantern_small.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://6n6riqe60s2f" +path="res://.godot/imported/eyes_jackolantern_small.png-7608ab74472a3edb79fcddb1cafbcc2f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_jackolantern_small.png" +dest_files=["res://.godot/imported/eyes_jackolantern_small.png-7608ab74472a3edb79fcddb1cafbcc2f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_sexy_blue.png b/art/exported/characters/faces/eyes/eyes_sexy_blue.png new file mode 100644 index 0000000..3dffd6c Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_sexy_blue.png differ diff --git a/art/exported/characters/faces/eyes/eyes_sexy_blue.png.import b/art/exported/characters/faces/eyes/eyes_sexy_blue.png.import new file mode 100644 index 0000000..7d2046d --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_sexy_blue.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://drajn1tk8gq4a" +path="res://.godot/imported/eyes_sexy_blue.png-f99ecb6d89cb6c453161f6ad9fd5f802.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_sexy_blue.png" +dest_files=["res://.godot/imported/eyes_sexy_blue.png-f99ecb6d89cb6c453161f6ad9fd5f802.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_sexy_brown.png b/art/exported/characters/faces/eyes/eyes_sexy_brown.png new file mode 100644 index 0000000..bc53f8f Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_sexy_brown.png differ diff --git a/art/exported/characters/faces/eyes/eyes_sexy_brown.png.import b/art/exported/characters/faces/eyes/eyes_sexy_brown.png.import new file mode 100644 index 0000000..a2b30f1 --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_sexy_brown.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c38u5tdksowpw" +path="res://.godot/imported/eyes_sexy_brown.png-e77cd183e70234d3ee7772ed2837cf34.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_sexy_brown.png" +dest_files=["res://.godot/imported/eyes_sexy_brown.png-e77cd183e70234d3ee7772ed2837cf34.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_simple_shine.png b/art/exported/characters/faces/eyes/eyes_simple_shine.png deleted file mode 100644 index 36e6859..0000000 Binary files a/art/exported/characters/faces/eyes/eyes_simple_shine.png and /dev/null differ diff --git a/art/exported/characters/faces/eyes/eyes_simple_shine_eyebrows.png b/art/exported/characters/faces/eyes/eyes_simple_shine_eyebrows.png deleted file mode 100644 index d143b91..0000000 Binary files a/art/exported/characters/faces/eyes/eyes_simple_shine_eyebrows.png and /dev/null differ diff --git a/art/exported/characters/faces/eyes/eyes_spider.png b/art/exported/characters/faces/eyes/eyes_spider.png new file mode 100644 index 0000000..239707f Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_spider.png differ diff --git a/art/exported/characters/faces/eyes/eyes_spider.png.import b/art/exported/characters/faces/eyes/eyes_spider.png.import new file mode 100644 index 0000000..3b137b9 --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_spider.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bevrdbag3eixb" +path="res://.godot/imported/eyes_spider.png-4cbe85913f69207b18d4b23095aca596.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_spider.png" +dest_files=["res://.godot/imported/eyes_spider.png-4cbe85913f69207b18d4b23095aca596.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_surprised.png b/art/exported/characters/faces/eyes/eyes_surprised.png new file mode 100644 index 0000000..be78ec8 Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_surprised.png differ diff --git a/art/exported/characters/faces/eyes/eyes_surprised.png.import b/art/exported/characters/faces/eyes/eyes_surprised.png.import new file mode 100644 index 0000000..0d7907b --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_surprised.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://chvod4aqeqn10" +path="res://.godot/imported/eyes_surprised.png-21858dc3f7520b1423e3d0aff59b6896.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_surprised.png" +dest_files=["res://.godot/imported/eyes_surprised.png-21858dc3f7520b1423e3d0aff59b6896.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_tired.png b/art/exported/characters/faces/eyes/eyes_tired.png new file mode 100644 index 0000000..061b3e4 Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_tired.png differ diff --git a/art/exported/characters/faces/eyes/eyes_tired.png.import b/art/exported/characters/faces/eyes/eyes_tired.png.import new file mode 100644 index 0000000..9de4b0f --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_tired.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bimnlu17t6u6v" +path="res://.godot/imported/eyes_tired.png-752efd150fd50cc078ee25c8bbbeeb36.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_tired.png" +dest_files=["res://.godot/imported/eyes_tired.png-752efd150fd50cc078ee25c8bbbeeb36.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_tired_flat.png b/art/exported/characters/faces/eyes/eyes_tired_flat.png new file mode 100644 index 0000000..faf123c Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_tired_flat.png differ diff --git a/art/exported/characters/faces/eyes/eyes_tired_flat.png.import b/art/exported/characters/faces/eyes/eyes_tired_flat.png.import new file mode 100644 index 0000000..5a2ec55 --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_tired_flat.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b4hmrvoblu3cl" +path="res://.godot/imported/eyes_tired_flat.png-c441cfd39c6147e6a13989a4dd86be05.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_tired_flat.png" +dest_files=["res://.godot/imported/eyes_tired_flat.png-c441cfd39c6147e6a13989a4dd86be05.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/eyes/eyes_upset.png b/art/exported/characters/faces/eyes/eyes_upset.png new file mode 100644 index 0000000..1e570a3 Binary files /dev/null and b/art/exported/characters/faces/eyes/eyes_upset.png differ diff --git a/art/exported/characters/faces/eyes/eyes_upset.png.import b/art/exported/characters/faces/eyes/eyes_upset.png.import new file mode 100644 index 0000000..0c455d4 --- /dev/null +++ b/art/exported/characters/faces/eyes/eyes_upset.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://blm1i6xyjclp5" +path="res://.godot/imported/eyes_upset.png-a8509f19cb25f577e84ebe86d28a31b1.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/eyes/eyes_upset.png" +dest_files=["res://.godot/imported/eyes_upset.png-a8509f19cb25f577e84ebe86d28a31b1.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_3.png b/art/exported/characters/faces/mouth/mouth_3.png new file mode 100644 index 0000000..dcdb30c Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_3.png differ diff --git a/art/exported/characters/faces/mouth/mouth_3.png.import b/art/exported/characters/faces/mouth/mouth_3.png.import new file mode 100644 index 0000000..eab9f48 --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_3.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b5wnxcm61q4ou" +path="res://.godot/imported/mouth_3.png-9fd9edc312c3b2c33df59da33d62bb30.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_3.png" +dest_files=["res://.godot/imported/mouth_3.png-9fd9edc312c3b2c33df59da33d62bb30.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_3_cheeky.png b/art/exported/characters/faces/mouth/mouth_3_cheeky.png new file mode 100644 index 0000000..b5f9797 Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_3_cheeky.png differ diff --git a/art/exported/characters/faces/mouth/mouth_3_cheeky.png.import b/art/exported/characters/faces/mouth/mouth_3_cheeky.png.import new file mode 100644 index 0000000..a53b280 --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_3_cheeky.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dhaec7illng60" +path="res://.godot/imported/mouth_3_cheeky.png-1c9ae1bcb18ff29fe44e13b55b692f57.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_3_cheeky.png" +dest_files=["res://.godot/imported/mouth_3_cheeky.png-1c9ae1bcb18ff29fe44e13b55b692f57.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_cheeky_smile.png b/art/exported/characters/faces/mouth/mouth_cheeky_smile.png new file mode 100644 index 0000000..addb335 Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_cheeky_smile.png differ diff --git a/art/exported/characters/faces/mouth/mouth_cheeky_smile.png.import b/art/exported/characters/faces/mouth/mouth_cheeky_smile.png.import new file mode 100644 index 0000000..926ef6c --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_cheeky_smile.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://8tdtfnv3bgft" +path="res://.godot/imported/mouth_cheeky_smile.png-d55ec6f5fd7e73fd8793d524475f9f1f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_cheeky_smile.png" +dest_files=["res://.godot/imported/mouth_cheeky_smile.png-d55ec6f5fd7e73fd8793d524475f9f1f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_cheeky_smile_onesided.png b/art/exported/characters/faces/mouth/mouth_cheeky_smile_onesided.png new file mode 100644 index 0000000..cef99aa Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_cheeky_smile_onesided.png differ diff --git a/art/exported/characters/faces/mouth/mouth_cheeky_smile_onesided.png.import b/art/exported/characters/faces/mouth/mouth_cheeky_smile_onesided.png.import new file mode 100644 index 0000000..0b1450a --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_cheeky_smile_onesided.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://8xyawmp5gru8" +path="res://.godot/imported/mouth_cheeky_smile_onesided.png-366c346f7be47b1521677b84666a672b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_cheeky_smile_onesided.png" +dest_files=["res://.godot/imported/mouth_cheeky_smile_onesided.png-366c346f7be47b1521677b84666a672b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_jackolantern.png b/art/exported/characters/faces/mouth/mouth_jackolantern.png new file mode 100644 index 0000000..80b5ebe Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_jackolantern.png differ diff --git a/art/exported/characters/faces/mouth/mouth_jackolantern.png.import b/art/exported/characters/faces/mouth/mouth_jackolantern.png.import new file mode 100644 index 0000000..1756a04 --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_jackolantern.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ck4bbdnpf6ekd" +path="res://.godot/imported/mouth_jackolantern.png-7f9373a2b59e617edd25d92ef63041f0.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_jackolantern.png" +dest_files=["res://.godot/imported/mouth_jackolantern.png-7f9373a2b59e617edd25d92ef63041f0.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_lil_c.png b/art/exported/characters/faces/mouth/mouth_lil_c.png new file mode 100644 index 0000000..bd1219a Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_lil_c.png differ diff --git a/art/exported/characters/faces/mouth/mouth_lil_c.png.import b/art/exported/characters/faces/mouth/mouth_lil_c.png.import new file mode 100644 index 0000000..1a7c28d --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_lil_c.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bfafrjmy6liy6" +path="res://.godot/imported/mouth_lil_c.png-e65a240e587f99537a3a9f1d3f241323.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_lil_c.png" +dest_files=["res://.godot/imported/mouth_lil_c.png-e65a240e587f99537a3a9f1d3f241323.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_open_small.png b/art/exported/characters/faces/mouth/mouth_open_small.png new file mode 100644 index 0000000..97c1755 Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_open_small.png differ diff --git a/art/exported/characters/faces/mouth/mouth_open_small.png.import b/art/exported/characters/faces/mouth/mouth_open_small.png.import new file mode 100644 index 0000000..9b15e51 --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_open_small.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bn68lfabdo7ga" +path="res://.godot/imported/mouth_open_small.png-30e9081c075d21159d6563a981b15378.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_open_small.png" +dest_files=["res://.godot/imported/mouth_open_small.png-30e9081c075d21159d6563a981b15378.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_p_tounge.png b/art/exported/characters/faces/mouth/mouth_p_tounge.png new file mode 100644 index 0000000..7e71399 Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_p_tounge.png differ diff --git a/art/exported/characters/faces/mouth/mouth_p_tounge.png.import b/art/exported/characters/faces/mouth/mouth_p_tounge.png.import new file mode 100644 index 0000000..1a791ce --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_p_tounge.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://nt1q6gpij6y3" +path="res://.godot/imported/mouth_p_tounge.png-f2e1b9018a58fa3c500b05c19941a1f3.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_p_tounge.png" +dest_files=["res://.godot/imported/mouth_p_tounge.png-f2e1b9018a58fa3c500b05c19941a1f3.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_sigh.png b/art/exported/characters/faces/mouth/mouth_sigh.png new file mode 100644 index 0000000..875da79 Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_sigh.png differ diff --git a/art/exported/characters/faces/mouth/mouth_sigh.png.import b/art/exported/characters/faces/mouth/mouth_sigh.png.import new file mode 100644 index 0000000..928a5d2 --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_sigh.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b0842jxg3m1ca" +path="res://.godot/imported/mouth_sigh.png-f58b2992f2709483fde720834a5e8820.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_sigh.png" +dest_files=["res://.godot/imported/mouth_sigh.png-f58b2992f2709483fde720834a5e8820.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_simple_smile.png b/art/exported/characters/faces/mouth/mouth_simple_smile.png new file mode 100644 index 0000000..9f8d430 Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_simple_smile.png differ diff --git a/art/exported/characters/faces/mouth/mouth_simple_smile.png.import b/art/exported/characters/faces/mouth/mouth_simple_smile.png.import new file mode 100644 index 0000000..82bd51a --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_simple_smile.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://nafybekpya31" +path="res://.godot/imported/mouth_simple_smile.png-029050835f365c4976c1b4e62edbc7c8.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_simple_smile.png" +dest_files=["res://.godot/imported/mouth_simple_smile.png-029050835f365c4976c1b4e62edbc7c8.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_slanted.png b/art/exported/characters/faces/mouth/mouth_slanted.png new file mode 100644 index 0000000..568eb4f Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_slanted.png differ diff --git a/art/exported/characters/faces/mouth/mouth_slanted.png.import b/art/exported/characters/faces/mouth/mouth_slanted.png.import new file mode 100644 index 0000000..01efb87 --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_slanted.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://nuj6ednwjawn" +path="res://.godot/imported/mouth_slanted.png-cb0a217a5bb11b80e53b1a6e3e94f43d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_slanted.png" +dest_files=["res://.godot/imported/mouth_slanted.png-cb0a217a5bb11b80e53b1a6e3e94f43d.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_squigle.png b/art/exported/characters/faces/mouth/mouth_squigle.png new file mode 100644 index 0000000..cffb2e8 Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_squigle.png differ diff --git a/art/exported/characters/faces/mouth/mouth_squigle.png.import b/art/exported/characters/faces/mouth/mouth_squigle.png.import new file mode 100644 index 0000000..980021f --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_squigle.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://calw27urbe3hk" +path="res://.godot/imported/mouth_squigle.png-263a4acb09e9f29aff38899ef1aac53f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_squigle.png" +dest_files=["res://.godot/imported/mouth_squigle.png-263a4acb09e9f29aff38899ef1aac53f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_three.png b/art/exported/characters/faces/mouth/mouth_three.png deleted file mode 100644 index 527f300..0000000 Binary files a/art/exported/characters/faces/mouth/mouth_three.png and /dev/null differ diff --git a/art/exported/characters/faces/mouth/mouth_vampy.png b/art/exported/characters/faces/mouth/mouth_vampy.png new file mode 100644 index 0000000..ee941f2 Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_vampy.png differ diff --git a/art/exported/characters/faces/mouth/mouth_vampy.png.import b/art/exported/characters/faces/mouth/mouth_vampy.png.import new file mode 100644 index 0000000..d191c95 --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_vampy.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bdpe0lrftqjkq" +path="res://.godot/imported/mouth_vampy.png-0f16a1970484a70927f4063fa1bab422.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_vampy.png" +dest_files=["res://.godot/imported/mouth_vampy.png-0f16a1970484a70927f4063fa1bab422.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_whiskers.png b/art/exported/characters/faces/mouth/mouth_whiskers.png new file mode 100644 index 0000000..414634f Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_whiskers.png differ diff --git a/art/exported/characters/faces/mouth/mouth_whiskers.png.import b/art/exported/characters/faces/mouth/mouth_whiskers.png.import new file mode 100644 index 0000000..7fe6438 --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_whiskers.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cpxwladf5vobh" +path="res://.godot/imported/mouth_whiskers.png-27b3d6495cd4a57de394a2ad8eb67d39.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_whiskers.png" +dest_files=["res://.godot/imported/mouth_whiskers.png-27b3d6495cd4a57de394a2ad8eb67d39.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_y.png b/art/exported/characters/faces/mouth/mouth_y.png new file mode 100644 index 0000000..600cd8c Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_y.png differ diff --git a/art/exported/characters/faces/mouth/mouth_y.png.import b/art/exported/characters/faces/mouth/mouth_y.png.import new file mode 100644 index 0000000..989fa6b --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_y.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://6w65l4rjbgq" +path="res://.godot/imported/mouth_y.png-08338d9ca7fd2d139dd64add4385096d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_y.png" +dest_files=["res://.godot/imported/mouth_y.png-08338d9ca7fd2d139dd64add4385096d.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_y_small.png b/art/exported/characters/faces/mouth/mouth_y_small.png new file mode 100644 index 0000000..f66357b Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_y_small.png differ diff --git a/art/exported/characters/faces/mouth/mouth_y_small.png.import b/art/exported/characters/faces/mouth/mouth_y_small.png.import new file mode 100644 index 0000000..205579e --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_y_small.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cchv8fvnqbtm2" +path="res://.godot/imported/mouth_y_small.png-493215adfb2e980f01f69152d24a8ef4.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_y_small.png" +dest_files=["res://.godot/imported/mouth_y_small.png-493215adfb2e980f01f69152d24a8ef4.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/mouth/mouth_y_small_pink.png b/art/exported/characters/faces/mouth/mouth_y_small_pink.png new file mode 100644 index 0000000..7f0af4a Binary files /dev/null and b/art/exported/characters/faces/mouth/mouth_y_small_pink.png differ diff --git a/art/exported/characters/faces/mouth/mouth_y_small_pink.png.import b/art/exported/characters/faces/mouth/mouth_y_small_pink.png.import new file mode 100644 index 0000000..f8237f1 --- /dev/null +++ b/art/exported/characters/faces/mouth/mouth_y_small_pink.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dvqdmhhiet5ix" +path="res://.godot/imported/mouth_y_small_pink.png-febc93e05453be68458eff8bab3d21c1.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/mouth/mouth_y_small_pink.png" +dest_files=["res://.godot/imported/mouth_y_small_pink.png-febc93e05453be68458eff8bab3d21c1.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/noses/nose_cat_real.png b/art/exported/characters/faces/noses/nose_cat_real.png new file mode 100644 index 0000000..0765f2e Binary files /dev/null and b/art/exported/characters/faces/noses/nose_cat_real.png differ diff --git a/art/exported/characters/faces/noses/nose_cat_real.png.import b/art/exported/characters/faces/noses/nose_cat_real.png.import new file mode 100644 index 0000000..aaedb17 --- /dev/null +++ b/art/exported/characters/faces/noses/nose_cat_real.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://5n0kihgof38n" +path="res://.godot/imported/nose_cat_real.png-25c7e8464e384043f0969f191e2c2950.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/noses/nose_cat_real.png" +dest_files=["res://.godot/imported/nose_cat_real.png-25c7e8464e384043f0969f191e2c2950.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/noses/nose_clown.png b/art/exported/characters/faces/noses/nose_clown.png new file mode 100644 index 0000000..cb9fb14 Binary files /dev/null and b/art/exported/characters/faces/noses/nose_clown.png differ diff --git a/art/exported/characters/faces/noses/nose_clown.png.import b/art/exported/characters/faces/noses/nose_clown.png.import new file mode 100644 index 0000000..a9afce1 --- /dev/null +++ b/art/exported/characters/faces/noses/nose_clown.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cc0nb34t7helb" +path="res://.godot/imported/nose_clown.png-bfa33a86cf06540d45ba440868a39bb3.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/noses/nose_clown.png" +dest_files=["res://.godot/imported/nose_clown.png-bfa33a86cf06540d45ba440868a39bb3.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/noses/nose_dog_real.png b/art/exported/characters/faces/noses/nose_dog_real.png new file mode 100644 index 0000000..01b3a7e Binary files /dev/null and b/art/exported/characters/faces/noses/nose_dog_real.png differ diff --git a/art/exported/characters/faces/noses/nose_dog_round.png.import b/art/exported/characters/faces/noses/nose_dog_real.png.import similarity index 77% rename from art/exported/characters/faces/noses/nose_dog_round.png.import rename to art/exported/characters/faces/noses/nose_dog_real.png.import index 6fb7b7d..9fe82cc 100644 --- a/art/exported/characters/faces/noses/nose_dog_round.png.import +++ b/art/exported/characters/faces/noses/nose_dog_real.png.import @@ -2,16 +2,16 @@ importer="texture" type="CompressedTexture2D" -uid="uid://bbx0ywjiwymrm" -path="res://.godot/imported/nose_dog_round.png-e1d92a8a7b661901752b05898a3f7c8b.ctex" +uid="uid://b8jwky86fl3ky" +path="res://.godot/imported/nose_dog_real.png-f065da766aead62076c01fa08fbffb2a.ctex" metadata={ "vram_texture": false } [deps] -source_file="res://art/exported/characters/faces/noses/nose_dog_round.png" -dest_files=["res://.godot/imported/nose_dog_round.png-e1d92a8a7b661901752b05898a3f7c8b.ctex"] +source_file="res://art/exported/characters/faces/noses/nose_dog_real.png" +dest_files=["res://.godot/imported/nose_dog_real.png-f065da766aead62076c01fa08fbffb2a.ctex"] [params] diff --git a/art/exported/characters/faces/noses/nose_dog_round.png b/art/exported/characters/faces/noses/nose_dog_round.png deleted file mode 100644 index 18a4590..0000000 Binary files a/art/exported/characters/faces/noses/nose_dog_round.png and /dev/null differ diff --git a/art/exported/characters/faces/noses/nose_dog_simple.png b/art/exported/characters/faces/noses/nose_dog_simple.png new file mode 100644 index 0000000..d3743c7 Binary files /dev/null and b/art/exported/characters/faces/noses/nose_dog_simple.png differ diff --git a/art/exported/characters/faces/noses/nose_dog_simple.png.import b/art/exported/characters/faces/noses/nose_dog_simple.png.import new file mode 100644 index 0000000..f61b74a --- /dev/null +++ b/art/exported/characters/faces/noses/nose_dog_simple.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b6d4ubqjijjux" +path="res://.godot/imported/nose_dog_simple.png-fdc0a92e3e2c82271db9ea87256058a7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/noses/nose_dog_simple.png" +dest_files=["res://.godot/imported/nose_dog_simple.png-fdc0a92e3e2c82271db9ea87256058a7.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/noses/nose_dragon.png b/art/exported/characters/faces/noses/nose_dragon.png new file mode 100644 index 0000000..157a28d Binary files /dev/null and b/art/exported/characters/faces/noses/nose_dragon.png differ diff --git a/art/exported/characters/faces/noses/nose_dragon.png.import b/art/exported/characters/faces/noses/nose_dragon.png.import new file mode 100644 index 0000000..0ba2695 --- /dev/null +++ b/art/exported/characters/faces/noses/nose_dragon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://8n1bhbyt5id6" +path="res://.godot/imported/nose_dragon.png-6c98cf6f5692ec43ffe43650115cd010.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/noses/nose_dragon.png" +dest_files=["res://.godot/imported/nose_dragon.png-6c98cf6f5692ec43ffe43650115cd010.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/noses/nose_hippo.png b/art/exported/characters/faces/noses/nose_hippo.png new file mode 100644 index 0000000..7ceabb2 Binary files /dev/null and b/art/exported/characters/faces/noses/nose_hippo.png differ diff --git a/art/exported/characters/faces/noses/nose_hippo.png.import b/art/exported/characters/faces/noses/nose_hippo.png.import new file mode 100644 index 0000000..0206809 --- /dev/null +++ b/art/exported/characters/faces/noses/nose_hippo.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bmfa44uf6u4or" +path="res://.godot/imported/nose_hippo.png-059f63ab00597454d369b0d51b5712a6.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/noses/nose_hippo.png" +dest_files=["res://.godot/imported/nose_hippo.png-059f63ab00597454d369b0d51b5712a6.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/noses/nose_human.png b/art/exported/characters/faces/noses/nose_human.png new file mode 100644 index 0000000..e0e7846 Binary files /dev/null and b/art/exported/characters/faces/noses/nose_human.png differ diff --git a/art/exported/characters/faces/noses/nose_human.png.import b/art/exported/characters/faces/noses/nose_human.png.import new file mode 100644 index 0000000..2381527 --- /dev/null +++ b/art/exported/characters/faces/noses/nose_human.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cuthoacwggro3" +path="res://.godot/imported/nose_human.png-337d9ba4f724d6241a6fa9a307a30008.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/noses/nose_human.png" +dest_files=["res://.godot/imported/nose_human.png-337d9ba4f724d6241a6fa9a307a30008.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/noses/nose_nostrils.png b/art/exported/characters/faces/noses/nose_nostrils.png new file mode 100644 index 0000000..11fb0a3 Binary files /dev/null and b/art/exported/characters/faces/noses/nose_nostrils.png differ diff --git a/art/exported/characters/faces/noses/nose_nostrils.png.import b/art/exported/characters/faces/noses/nose_nostrils.png.import new file mode 100644 index 0000000..8e9c447 --- /dev/null +++ b/art/exported/characters/faces/noses/nose_nostrils.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bvu2lox5px3ab" +path="res://.godot/imported/nose_nostrils.png-9e1c2b5c8e7adb019d72a39b1e805781.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/noses/nose_nostrils.png" +dest_files=["res://.godot/imported/nose_nostrils.png-9e1c2b5c8e7adb019d72a39b1e805781.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/noses/nose_piercing.png b/art/exported/characters/faces/noses/nose_piercing.png new file mode 100644 index 0000000..f35b3ac Binary files /dev/null and b/art/exported/characters/faces/noses/nose_piercing.png differ diff --git a/art/exported/characters/faces/noses/nose_piercing.png.import b/art/exported/characters/faces/noses/nose_piercing.png.import new file mode 100644 index 0000000..3584e75 --- /dev/null +++ b/art/exported/characters/faces/noses/nose_piercing.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://3w37sblwbd8b" +path="res://.godot/imported/nose_piercing.png-0c3316905c9f379988cc52353c88569c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/noses/nose_piercing.png" +dest_files=["res://.godot/imported/nose_piercing.png-0c3316905c9f379988cc52353c88569c.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/noses/nose_pig_snout.png b/art/exported/characters/faces/noses/nose_pig_snout.png new file mode 100644 index 0000000..0e403cf Binary files /dev/null and b/art/exported/characters/faces/noses/nose_pig_snout.png differ diff --git a/art/exported/characters/faces/noses/nose_pig_snout.png.import b/art/exported/characters/faces/noses/nose_pig_snout.png.import new file mode 100644 index 0000000..5e34829 --- /dev/null +++ b/art/exported/characters/faces/noses/nose_pig_snout.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bvran6dr0u22l" +path="res://.godot/imported/nose_pig_snout.png-40e08884db61f222d4371c6c6a798bca.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/noses/nose_pig_snout.png" +dest_files=["res://.godot/imported/nose_pig_snout.png-40e08884db61f222d4371c6c6a798bca.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/noses/nose_pig_snout_pink.png b/art/exported/characters/faces/noses/nose_pig_snout_pink.png new file mode 100644 index 0000000..6fe994f Binary files /dev/null and b/art/exported/characters/faces/noses/nose_pig_snout_pink.png differ diff --git a/art/exported/characters/faces/noses/nose_pig_snout_pink.png.import b/art/exported/characters/faces/noses/nose_pig_snout_pink.png.import new file mode 100644 index 0000000..52ab860 --- /dev/null +++ b/art/exported/characters/faces/noses/nose_pig_snout_pink.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cyigqco0dp8ph" +path="res://.godot/imported/nose_pig_snout_pink.png-da6fcfc06a8aa02d6ad664e2ed669558.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/noses/nose_pig_snout_pink.png" +dest_files=["res://.godot/imported/nose_pig_snout_pink.png-da6fcfc06a8aa02d6ad664e2ed669558.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/noses/nose_squidward.png b/art/exported/characters/faces/noses/nose_squidward.png new file mode 100644 index 0000000..ca71fc5 Binary files /dev/null and b/art/exported/characters/faces/noses/nose_squidward.png differ diff --git a/art/exported/characters/faces/noses/nose_squidward.png.import b/art/exported/characters/faces/noses/nose_squidward.png.import new file mode 100644 index 0000000..dbba070 --- /dev/null +++ b/art/exported/characters/faces/noses/nose_squidward.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ilvb5vre4kv7" +path="res://.godot/imported/nose_squidward.png-579e15cf6acfb402abda29a8a555d504.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/noses/nose_squidward.png" +dest_files=["res://.godot/imported/nose_squidward.png-579e15cf6acfb402abda29a8a555d504.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/noses/nose_triangle.png b/art/exported/characters/faces/noses/nose_triangle.png new file mode 100644 index 0000000..5f15f3a Binary files /dev/null and b/art/exported/characters/faces/noses/nose_triangle.png differ diff --git a/art/exported/characters/faces/noses/nose_triangle.png.import b/art/exported/characters/faces/noses/nose_triangle.png.import new file mode 100644 index 0000000..bc7aa21 --- /dev/null +++ b/art/exported/characters/faces/noses/nose_triangle.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bitins3gtewe" +path="res://.godot/imported/nose_triangle.png-018974a6bbf68652b8c5533c2675cc2f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/noses/nose_triangle.png" +dest_files=["res://.godot/imported/nose_triangle.png-018974a6bbf68652b8c5533c2675cc2f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/noses/nose_triangle_pink.png b/art/exported/characters/faces/noses/nose_triangle_pink.png new file mode 100644 index 0000000..2915456 Binary files /dev/null and b/art/exported/characters/faces/noses/nose_triangle_pink.png differ diff --git a/art/exported/characters/faces/noses/nose_triangle_pink.png.import b/art/exported/characters/faces/noses/nose_triangle_pink.png.import new file mode 100644 index 0000000..56712ab --- /dev/null +++ b/art/exported/characters/faces/noses/nose_triangle_pink.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://oi8qhxbtijmk" +path="res://.godot/imported/nose_triangle_pink.png-051ce6df5e7fd5932f19fd353123d7d1.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/noses/nose_triangle_pink.png" +dest_files=["res://.godot/imported/nose_triangle_pink.png-051ce6df5e7fd5932f19fd353123d7d1.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/noses/nose_triangle_small.png b/art/exported/characters/faces/noses/nose_triangle_small.png new file mode 100644 index 0000000..719e67b Binary files /dev/null and b/art/exported/characters/faces/noses/nose_triangle_small.png differ diff --git a/art/exported/characters/faces/noses/nose_triangle_small.png.import b/art/exported/characters/faces/noses/nose_triangle_small.png.import new file mode 100644 index 0000000..a659077 --- /dev/null +++ b/art/exported/characters/faces/noses/nose_triangle_small.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cedgrca26ponk" +path="res://.godot/imported/nose_triangle_small.png-64129c5fc69bf7095f684c2b7de2855b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/noses/nose_triangle_small.png" +dest_files=["res://.godot/imported/nose_triangle_small.png-64129c5fc69bf7095f684c2b7de2855b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/noses/nose_triangle_small_pink.png b/art/exported/characters/faces/noses/nose_triangle_small_pink.png new file mode 100644 index 0000000..3a4bf19 Binary files /dev/null and b/art/exported/characters/faces/noses/nose_triangle_small_pink.png differ diff --git a/art/exported/characters/faces/noses/nose_triangle_small_pink.png.import b/art/exported/characters/faces/noses/nose_triangle_small_pink.png.import new file mode 100644 index 0000000..c875ba4 --- /dev/null +++ b/art/exported/characters/faces/noses/nose_triangle_small_pink.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://0kird82ka1ug" +path="res://.godot/imported/nose_triangle_small_pink.png-fba736a5f1806c1286f1d3040592933b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/noses/nose_triangle_small_pink.png" +dest_files=["res://.godot/imported/nose_triangle_small_pink.png-fba736a5f1806c1286f1d3040592933b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/exported/characters/faces/noses/nose_under.png b/art/exported/characters/faces/noses/nose_under.png new file mode 100644 index 0000000..d7c4d7b Binary files /dev/null and b/art/exported/characters/faces/noses/nose_under.png differ diff --git a/art/exported/characters/faces/noses/nose_under.png.import b/art/exported/characters/faces/noses/nose_under.png.import new file mode 100644 index 0000000..5bf860f --- /dev/null +++ b/art/exported/characters/faces/noses/nose_under.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://u0ih35v73j5h" +path="res://.godot/imported/nose_under.png-269bae96966b3c6367d43ac9bd5b2a3f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/exported/characters/faces/noses/nose_under.png" +dest_files=["res://.godot/imported/nose_under.png-269bae96966b3c6367d43ac9bd5b2a3f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/source/characters/base/netfishing_character_source.blend b/art/source/characters/base/netfishing_character_source.blend index 9957a87..8fde03b 100644 Binary files a/art/source/characters/base/netfishing_character_source.blend and b/art/source/characters/base/netfishing_character_source.blend differ diff --git a/art/source/characters/base/netfishing_character_source.blend1 b/art/source/characters/base/netfishing_character_source.blend1 index e7d3fd3..e4808eb 100644 Binary files a/art/source/characters/base/netfishing_character_source.blend1 and b/art/source/characters/base/netfishing_character_source.blend1 differ diff --git a/fishing/catch_controller.gd b/fishing/catch_controller.gd index 6eb058e..2015dc5 100644 --- a/fishing/catch_controller.gd +++ b/fishing/catch_controller.gd @@ -46,7 +46,7 @@ class Barrier: # Fight movement uses one shared baseline. Species and quality difficulty comes # from barrier placement and health, while reel upgrades affect only the # player's progress speed. -const CHASE_START_DELAY: float = 0.5 +const CHASE_START_DELAY: float = 1.0 const CHASE_START_OFFSET: float = 0.04 const CHASE_SPEED: float = 0.07 diff --git a/fishing/fishing_spot.gd b/fishing/fishing_spot.gd index 284b6de..abe479c 100644 --- a/fishing/fishing_spot.gd +++ b/fishing/fishing_spot.gd @@ -100,11 +100,11 @@ enum FishingState { @export_range(0.0, 1.0, 0.01) var withdrawal_surface_clearance: float = 0.4 @export_category("Timing") -const BITE_QUICK_MIN_SECONDS: float = 10.0 -const BITE_QUICK_MAX_SECONDS: float = 30.0 -const BITE_TYPICAL_MAX_SECONDS: float = 90.0 -const BITE_LONG_MAX_SECONDS: float = 180.0 -const BITE_MAX_SECONDS: float = 240.0 +const BITE_QUICK_MIN_SECONDS: float = 8.0 +const BITE_QUICK_MAX_SECONDS: float = 24.0 +const BITE_TYPICAL_MAX_SECONDS: float = 72.0 +const BITE_LONG_MAX_SECONDS: float = 144.0 +const BITE_MAX_SECONDS: float = 192.0 const BITE_QUICK_PROBABILITY: float = 0.25 const BITE_TYPICAL_PROBABILITY: float = 0.65 const BITE_LONG_PROBABILITY: float = 0.08 diff --git a/main/main.tscn b/main/main.tscn index 7fb4e1b..83d11b7 100644 --- a/main/main.tscn +++ b/main/main.tscn @@ -248,7 +248,7 @@ unique_name_in_owner = true script = ExtResource("36_player_list") [node name="TestWorld" parent="." unique_id=1334932296 instance=ExtResource("1_world")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0024132729, 0, -0.00093126297) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.4475808, 0, -1.8959346) [node name="Players" type="Node3D" parent="." unique_id=550630144] diff --git a/network/network_profile_protocol.gd b/network/network_profile_protocol.gd index ac4dec5..b4c2d3a 100644 --- a/network/network_profile_protocol.gd +++ b/network/network_profile_protocol.gd @@ -49,6 +49,12 @@ static func signature_fields(data: Dictionary) -> Array: str(data.get("sender_fingerprint", "")), str(data.get("display_name", "")), str(appearance.get("species", "")), + CharacterCustomizationCatalog.character_scale_percent( + appearance.get( + CharacterCustomizationCatalog.SCALE_CATEGORY_ID, + CharacterCustomizationCatalog.DEFAULT_CHARACTER_SCALE, + ) + ), str(appearance.get("fur_pattern", "")), str(appearance.get("ears", "")), str(appearance.get("eyes", "")), diff --git a/network/network_protocol.gd b/network/network_protocol.gd index 9ba7353..23b80b6 100644 --- a/network/network_protocol.gd +++ b/network/network_protocol.gd @@ -176,6 +176,12 @@ static func client_profile_fields(data: Dictionary) -> Array: str(data.get("local_profile_id", "")), str(data.get("display_name", "")), str(appearance.get("species", "")), + CharacterCustomizationCatalog.character_scale_percent( + appearance.get( + CharacterCustomizationCatalog.SCALE_CATEGORY_ID, + CharacterCustomizationCatalog.DEFAULT_CHARACTER_SCALE, + ) + ), str(appearance.get("fur_pattern", "")), str(appearance.get("ears", "")), str(appearance.get("eyes", "")), diff --git a/network/network_surface_drawing_service.gd b/network/network_surface_drawing_service.gd index 35c28ab..5065acd 100644 --- a/network/network_surface_drawing_service.gd +++ b/network/network_surface_drawing_service.gd @@ -27,6 +27,7 @@ const MAX_REQUESTS_PER_WINDOW: int = 32 const MAX_RECENT_REQUEST_IDS: int = 64 const GRID_PREVIEW_SURFACE_OFFSET: float = 0.03 const POINTER_EDGE_MARGIN: float = 2.0 +const INVALID_POINTER_SCREEN_POSITION := Vector2(-1.0, -1.0) enum GuideAction { NONE, @@ -117,7 +118,11 @@ func setup( _emit_hud_state("") -func handle_input(event: InputEvent, can_open: bool) -> bool: +func handle_input( + event: InputEvent, + can_open: bool, + pointer_screen_position: Vector2 = INVALID_POINTER_SCREEN_POSITION, +) -> bool: if event is InputEventKey: var key_event := event as InputEventKey if ( @@ -129,7 +134,7 @@ func handle_input(event: InputEvent, can_open: bool) -> bool: deactivate() return true if can_open and can_activate(): - activate() + activate(pointer_screen_position) return true return false if not _active: @@ -167,6 +172,11 @@ func handle_input(event: InputEvent, can_open: bool) -> bool: return true if event is InputEventMouseButton: var mouse_event := event as InputEventMouseButton + _set_pointer_from_input( + mouse_event.position, + pointer_screen_position, + ) + _update_aim() if ( mouse_event.shift_pressed and mouse_event.button_index in [ @@ -216,15 +226,18 @@ func handle_input(event: InputEvent, can_open: bool) -> bool: var motion_event := event as InputEventMouseMotion if _camera_look_active: return false - _pointer_screen_position = _clamped_pointer_position( - motion_event.position + _set_pointer_from_input( + motion_event.position, + pointer_screen_position, ) _update_aim() return true return false -func activate() -> void: +func activate( + pointer_screen_position: Vector2 = INVALID_POINTER_SCREEN_POSITION, +) -> void: if _active or not can_activate(): return _active = true @@ -234,7 +247,12 @@ func activate() -> void: _refresh_local_unlocks() _rebuild_placement_preview() _reset_stroke() - _pointer_screen_position = get_viewport().get_visible_rect().size * 0.5 + var initial_pointer_position: Vector2 = pointer_screen_position + if not _is_valid_pointer_screen_position(initial_pointer_position): + initial_pointer_position = get_viewport().get_mouse_position() + _pointer_screen_position = _clamped_pointer_position( + initial_pointer_position + ) _prior_mouse_mode = Input.mouse_mode Input.mouse_mode = Input.MOUSE_MODE_VISIBLE _update_aim() @@ -1940,6 +1958,25 @@ func _clamped_pointer_position(value: Vector2) -> Vector2: ) +func _set_pointer_from_input( + event_position: Vector2, + pointer_screen_position: Vector2, +) -> void: + # GameUI receives input through a scaled SubViewport, so event_position is + # expressed in that UI viewport's render coordinates. Camera3D ray methods + # require coordinates in the camera's root viewport instead. GameUI supplies + # that authoritative window position; direct callers may still use an event + # position when they share this service's viewport. + var resolved_position: Vector2 = pointer_screen_position + if not _is_valid_pointer_screen_position(resolved_position): + resolved_position = event_position + _pointer_screen_position = _clamped_pointer_position(resolved_position) + + +func _is_valid_pointer_screen_position(value: Vector2) -> bool: + return value.x >= 0.0 and value.y >= 0.0 + + func _cycle_color(direction: int) -> void: if _color_ids.is_empty(): return diff --git a/player/held_item_attachment.tscn b/player/held_item_attachment.tscn new file mode 100644 index 0000000..05eff4b --- /dev/null +++ b/player/held_item_attachment.tscn @@ -0,0 +1,42 @@ +[gd_scene format=3] + +[node name="HeldItemAttachment" type="BoneAttachment3D"] +bone_name = "hand.R" + +[node name="HeldFishDisplay" type="Node3D" parent="."] +unique_name_in_owner = true +position = Vector3(0, 0.08, 0.04) +top_level = true +visible = false + +[node name="HeldFishSprite" type="Sprite3D" parent="HeldFishDisplay"] +unique_name_in_owner = true +pixel_size = 0.012 +shaded = false +double_sided = true +texture_filter = 0 + +[node name="HeldArtKitDisplay" type="Node3D" parent="."] +unique_name_in_owner = true +position = Vector3(0, 0.08, 0.04) +visible = false + +[node name="HeldArtKitSprite" type="Sprite3D" parent="HeldArtKitDisplay"] +unique_name_in_owner = true +pixel_size = 0.008 +shaded = false +double_sided = true +texture_filter = 1 + +[node name="CatchDisplay" type="Node3D" parent="."] +unique_name_in_owner = true +position = Vector3(0, 0.08, 0.04) +top_level = true +visible = false + +[node name="CatchSprite" type="Sprite3D" parent="CatchDisplay"] +unique_name_in_owner = true +pixel_size = 0.012 +shaded = false +double_sided = true +texture_filter = 0 diff --git a/player/player.gd b/player/player.gd index ad10369..930f15b 100644 --- a/player/player.gd +++ b/player/player.gd @@ -30,10 +30,16 @@ const ControllerMappingManagerType = preload( const FishingRodAttachmentScene = preload( "res://player/fishing_rod_attachment.tscn" ) +const HeldItemAttachmentScene = preload( + "res://player/held_item_attachment.tscn" +) const CHARACTER_IDLE_ANIMATION: StringName = &"idle" +const CHARACTER_IDLE_SHOW_ANIMATION: StringName = &"idle_show" +const CHARACTER_IDLE_SIT_ANIMATION: StringName = &"idle_sit" +const CHARACTER_IDLE_SIT_SHOW_ANIMATION: StringName = &"idle_sit_show" const CHARACTER_WALKING_ANIMATION: StringName = &"walking" -const CHARACTER_SITTING_ANIMATION: StringName = &"sitting" +const CHARACTER_WALKING_SHOW_ANIMATION: StringName = &"walking_show" const BASE_REEL_SPEED: float = 0.16 # The target Android handheld exposes its physical right trigger through # Godot's left-trigger axis. Keep the role named here so the platform mapping @@ -105,6 +111,9 @@ class ShowcaseCameraSnapshot: @export_range(0.0, 1.0, 0.01) var controller_trigger_threshold: float = 0.55 @onready var _visuals: Node3D = %Visuals +@onready var _character_rig: Node3D = get_node_or_null( + "Visuals/CharacterRig/CharacterRig" +) as Node3D @onready var _character_animation_player: AnimationPlayer = ( get_node_or_null("Visuals/CharacterRig/AnimationPlayer") as AnimationPlayer ) @@ -124,11 +133,14 @@ class ShowcaseCameraSnapshot: @onready var art_unlocks: PlayerArtUnlocksType = %ArtUnlocks @onready var experience: PlayerExperienceType = %Experience @onready var _cast_origin: Marker3D = %CastOrigin -@onready var _catch_display: Node3D = %CatchDisplay -@onready var _catch_sprite: Sprite3D = %CatchSprite -@onready var _held_fish_display: Node3D = %HeldFishDisplay -@onready var _held_fish_sprite: Sprite3D = %HeldFishSprite -@onready var _held_art_kit_sprite: Sprite3D = %HeldArtKitSprite +var _catch_display: Node3D +var _catch_sprite: Sprite3D +var _held_item_attachment: BoneAttachment3D +var _held_fish_display: Node3D +var _held_fish_attachment_offset: Vector3 = Vector3(0.0, 0.08, 0.04) +var _held_fish_sprite: Sprite3D +var _held_art_kit_sprite: Sprite3D +var _catch_attachment_offset: Vector3 = Vector3(0.0, 0.08, 0.04) var _gravity: float = float(ProjectSettings.get_setting("physics/3d/default_gravity")) var _camera_dragging: bool = false @@ -165,6 +177,8 @@ var _network_target_visual_yaw: float = 0.0 var _network_snapshot_ready: bool = false var _character_animation_name: StringName = &"" var _sitting: bool = false +var _held_fish_visible: bool = false +var _showcase_animation_active: bool = false var _fishing_rod: Node3D var _fishing_rod_tip: Marker3D var _controller_mapping_manager: ControllerMappingManagerType @@ -176,6 +190,7 @@ func _ready() -> void: _target_zoom = clampf(_spring_arm.spring_length, minimum_zoom, maximum_zoom) _spring_arm.spring_length = _target_zoom _camera.current = local_control_enabled + _initialize_held_item_attachment() func set_controller_mapping_manager( @@ -202,6 +217,32 @@ func _initialize_fishing_rod() -> void: ) as Marker3D +func _initialize_held_item_attachment() -> void: + var skeleton := get_node_or_null( + "Visuals/CharacterRig/CharacterRig/Skeleton3D" + ) as Skeleton3D + if skeleton == null: + push_error("Player character skeleton is unavailable for held items.") + return + var attachment := HeldItemAttachmentScene.instantiate() as BoneAttachment3D + if attachment == null: + push_error("Held item attachment could not be instantiated.") + return + skeleton.add_child(attachment) + _held_item_attachment = attachment + _held_fish_display = attachment.get_node("HeldFishDisplay") as Node3D + _held_fish_attachment_offset = _held_fish_display.position + _held_fish_sprite = attachment.get_node( + "HeldFishDisplay/HeldFishSprite" + ) as Sprite3D + _held_art_kit_sprite = attachment.get_node( + "HeldArtKitDisplay/HeldArtKitSprite" + ) as Sprite3D + _catch_display = attachment.get_node("CatchDisplay") as Node3D + _catch_attachment_offset = _catch_display.position + _catch_sprite = attachment.get_node("CatchDisplay/CatchSprite") as Sprite3D + + func _physics_process(delta: float) -> void: if _network_interpolation_enabled: _update_network_interpolation(delta) @@ -283,6 +324,22 @@ func _physics_process(delta: float) -> void: func _process(delta: float) -> void: _update_character_animation() + # The hand bone supplies the attachment position, but its animated wrist + # rotation should not turn the flat fish/catch artwork edge-on. Keep each + # display aligned with the character's facing while it follows the hand. + if _character_rig != null and _held_item_attachment != null: + var facing_rotation: Vector3 = _character_rig.global_rotation + for display: Node3D in [_held_fish_display, _catch_display]: + if display != null: + var attachment_offset: Vector3 = ( + _held_fish_attachment_offset + if display == _held_fish_display + else _catch_attachment_offset + ) + display.global_position = ( + _held_item_attachment.global_transform * attachment_offset + ) + display.global_rotation = facing_rotation if _remote_recovery_presentation_active: _remote_recovery_elapsed += delta _visuals.position = ( @@ -363,16 +420,65 @@ func _update_character_animation() -> void: var horizontal_speed_squared: float = ( velocity.x * velocity.x + velocity.z * velocity.z ) - var next_animation: StringName = ( - CHARACTER_SITTING_ANIMATION - if _sitting - else ( - CHARACTER_WALKING_ANIMATION - if horizontal_speed_squared > 0.0025 - else CHARACTER_IDLE_ANIMATION - ) - ) - if not _character_animation_player.has_animation(next_animation): + var is_walking: bool = horizontal_speed_squared > 0.0025 + var requested_animation: Array[StringName] = [] + if _showcase_animation_active: + if _sitting: + requested_animation = [ + CHARACTER_IDLE_SIT_SHOW_ANIMATION, + &"idle_sit_show_loop", + CHARACTER_IDLE_SIT_ANIMATION, + &"idle_sit_loop", + &"idle_loop_sit", + ] + else: + requested_animation = [ + CHARACTER_IDLE_SHOW_ANIMATION, + &"idle_show_loop", + &"show", + &"show_loop", + ] + elif _sitting: + if _held_fish_visible: + requested_animation = [ + CHARACTER_IDLE_SIT_SHOW_ANIMATION, + &"idle_sit_show_loop", + CHARACTER_IDLE_SIT_ANIMATION, + &"idle_sit_loop", + &"idle_loop_sit", + ] + else: + requested_animation = [ + CHARACTER_IDLE_SIT_ANIMATION, + &"idle_sit_loop", + &"sitting", + &"idle_loop_sit", + ] + elif is_walking and _held_fish_visible: + requested_animation = [ + CHARACTER_WALKING_SHOW_ANIMATION, + &"walking_show_loop", + ] + elif _held_fish_visible: + requested_animation = [ + CHARACTER_IDLE_SHOW_ANIMATION, + &"idle_show_loop", + &"show", + &"show_loop", + ] + elif is_walking: + requested_animation = [ + CHARACTER_WALKING_ANIMATION, + &"walking_loop", + ] + else: + requested_animation = [CHARACTER_IDLE_ANIMATION, &"idle_loop"] + var next_animation: StringName = &"" + for candidate: StringName in requested_animation: + if _character_animation_player.has_animation(candidate): + next_animation = candidate + break + if next_animation.is_empty(): return if _character_animation_name == next_animation: return @@ -385,14 +491,26 @@ func toggle_sitting() -> void: if should_sit: if ( _character_animation_player == null - or not _character_animation_player.has_animation( - CHARACTER_SITTING_ANIMATION - ) + or not _has_any_character_animation([ + CHARACTER_IDLE_SIT_ANIMATION, + &"idle_sit_loop", + &"sitting", + &"idle_loop_sit", + ]) ): return _set_sitting(should_sit) +func _has_any_character_animation(candidates: Array[StringName]) -> bool: + if _character_animation_player == null: + return false + for candidate: StringName in candidates: + if _character_animation_player.has_animation(candidate): + return true + return false + + func _set_sitting(should_sit: bool) -> void: if _sitting == should_sit: return @@ -822,10 +940,13 @@ func set_held_fish( should_show: bool, ) -> void: if not should_show or fish == null or fish.display_texture == null: + _held_fish_visible = false _held_fish_display.visible = false _held_fish_display.scale = Vector3.ONE _held_fish_sprite.texture = null + _update_character_animation() return + _held_fish_visible = true _held_fish_sprite.texture = fish.display_texture _held_fish_display.scale = ( Vector3.ONE @@ -833,6 +954,7 @@ func set_held_fish( * catch_presentation_base_scale ) _held_fish_display.visible = true + _update_character_animation() func get_cast_origin_position() -> Vector3: @@ -842,6 +964,8 @@ func get_cast_origin_position() -> Vector3: func begin_catch_showcase(fish_catch: FishCatchType) -> void: if fish_catch == null or not fish_catch.is_valid(): return + _showcase_animation_active = true + _update_character_animation() _kill_showcase_camera_tween() _kill_showcase_restore_tween() _capture_showcase_camera_snapshot() @@ -867,6 +991,8 @@ func begin_remote_catch_showcase(fish_catch: FishCatchType) -> void: if local_control_enabled or fish_catch == null or not fish_catch.is_valid(): return end_catch_showcase(Callable(), true) + _showcase_animation_active = true + _update_character_animation() _showcase_rod_visibility = _fishing_rod.visible _showcase_rod_state_stored = true _fishing_rod.visible = false @@ -883,6 +1009,8 @@ func end_catch_showcase( restored_callback: Callable = Callable(), immediate: bool = false, ) -> void: + _showcase_animation_active = false + _update_character_animation() _kill_showcase_turn_tween() _kill_showcase_camera_tween() _kill_showcase_restore_tween() diff --git a/player/player.tscn b/player/player.tscn index 2f7c0fb..2cda4eb 100644 --- a/player/player.tscn +++ b/player/player.tscn @@ -109,49 +109,6 @@ script = ExtResource("14_art_unlocks") unique_name_in_owner = true script = ExtResource("15_experience") -[node name="CatchDisplayAnchor" type="Marker3D" parent="Visuals"] -unique_name_in_owner = true -position = Vector3(0, 1.45, -1.15) - -[node name="CatchDisplay" type="Node3D" parent="Visuals/CatchDisplayAnchor"] -unique_name_in_owner = true -visible = false - -[node name="CatchSprite" type="Sprite3D" parent="Visuals/CatchDisplayAnchor/CatchDisplay"] -unique_name_in_owner = true -pixel_size = 0.012 -billboard = 1 -shaded = false -double_sided = true -texture_filter = 0 - -[node name="HeldFishAnchor" type="Marker3D" parent="Visuals"] -position = Vector3(0, 1.15, -0.9) - -[node name="HeldFishDisplay" type="Node3D" parent="Visuals/HeldFishAnchor"] -unique_name_in_owner = true -visible = false - -[node name="HeldFishSprite" type="Sprite3D" parent="Visuals/HeldFishAnchor/HeldFishDisplay"] -unique_name_in_owner = true -pixel_size = 0.012 -billboard = 1 -shaded = false -double_sided = true -texture_filter = 0 - -[node name="HeldArtKitAnchor" type="Marker3D" parent="Visuals"] -position = Vector3(0, 1.05, -0.72) - -[node name="HeldArtKitSprite" type="Sprite3D" parent="Visuals/HeldArtKitAnchor"] -unique_name_in_owner = true -visible = false -pixel_size = 0.008 -billboard = 1 -shaded = false -double_sided = true -texture_filter = 1 - [node name="CameraYaw" type="Node3D" parent="."] unique_name_in_owner = true position = Vector3(0, 1.35, 0) diff --git a/player/player_visual_presenter.gd b/player/player_visual_presenter.gd index fb291ba..8dd9f93 100644 --- a/player/player_visual_presenter.gd +++ b/player/player_visual_presenter.gd @@ -4,6 +4,44 @@ extends RefCounted const PlayerScene: PackedScene = preload("res://player/player.tscn") const RUNTIME_MATERIAL_META: StringName = &"netfishing_runtime_material" +static var _feature_uv_aspects: Dictionary = {} + + +static func feature_uv_aspect(feature_name: String) -> float: + if _feature_uv_aspects.has(feature_name): + return float(_feature_uv_aspects[feature_name]) + var visuals := instantiate_visuals() + var skeleton := visuals.find_child("Skeleton3D", true, false) as Skeleton3D + var aspects: Array[float] = [] + for head_name: String in ["head_round", "head_pointy"]: + var mesh_instance := skeleton.get_node_or_null( + "%s_%s" % [head_name, feature_name] + ) as MeshInstance3D + if mesh_instance == null or mesh_instance.mesh == null: + continue + var arrays := mesh_instance.mesh.surface_get_arrays(0) + var uv: PackedVector2Array = arrays[Mesh.ARRAY_TEX_UV] + if uv.is_empty(): + continue + var min_uv := Vector2(INF, INF) + var max_uv := Vector2(-INF, -INF) + for value: Vector2 in uv: + min_uv = min_uv.min(value) + max_uv = max_uv.max(value) + var size := max_uv - min_uv + if size.y > 0.001: + aspects.append(size.x / size.y) + visuals.free() + var result := 1.0 + if not aspects.is_empty(): + result = 0.0 + for aspect: float in aspects: + result += aspect + result /= aspects.size() + result = clampf(result, 0.35, 2.5) + _feature_uv_aspects[feature_name] = result + return result + static func instantiate_visuals() -> Node3D: var source: Player = PlayerScene.instantiate() @@ -40,6 +78,13 @@ static func apply_appearance( return # Gameplay and preview deliberately share this presentation seam. Keep all # mesh selection here so profile previews and network avatars stay identical. + var character_scale: float = CharacterCustomizationCatalog.character_scale( + snapshot.get( + CharacterCustomizationCatalog.SCALE_CATEGORY_ID, + CharacterCustomizationCatalog.DEFAULT_CHARACTER_SCALE, + ) + ) + visuals.scale = Vector3.ONE * character_scale var skeleton: Skeleton3D = visuals.find_child("Skeleton3D", true, false) as Skeleton3D if skeleton == null: return @@ -58,7 +103,12 @@ static func apply_appearance( "%s_%s" % [head_name, feature] ) as Node3D if decal != null: - decal.visible = head_name == head_id + var feature_id := CharacterCustomizationCatalog.canonical_option_id( + feature, str(snapshot.get(feature, "none")) + ) + decal.visible = ( + head_name == head_id and feature_id != "none" + ) var selected_ears: String = CharacterCustomizationCatalog.canonical_option_id( "ears", str(snapshot.get("ears", "none")) @@ -114,14 +164,20 @@ static func _set_feature_texture( feature_name: String, texture: Texture2D, ) -> void: - if texture == null: - return for head_name: String in ["head_pointy", "head_round"]: var mesh_instance: MeshInstance3D = skeleton.get_node_or_null( "%s_%s" % [head_name, feature_name] ) as MeshInstance3D + if texture == null: + if mesh_instance != null: + mesh_instance.visible = false + continue var material: StandardMaterial3D = _runtime_material(mesh_instance) if material != null: + # Feature plates are transparent geometry. The exported base model may + # have no preview texture, so enforce the runtime alpha mode when a + # drop-in PNG is assigned. + material.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA material.albedo_color = Color.WHITE material.albedo_texture = texture @@ -145,13 +201,32 @@ static func _runtime_material( if mesh_instance == null or mesh_instance.mesh == null: return null if mesh_instance.has_meta(RUNTIME_MATERIAL_META): - return mesh_instance.material_override as StandardMaterial3D + var runtime := mesh_instance.material_override as StandardMaterial3D + _configure_matte_material(runtime) + return runtime var source: StandardMaterial3D = mesh_instance.mesh.surface_get_material( 0 ) as StandardMaterial3D if source == null: return null var material: StandardMaterial3D = source.duplicate() as StandardMaterial3D + _configure_matte_material(material) mesh_instance.material_override = material mesh_instance.set_meta(RUNTIME_MATERIAL_META, true) return material + + +static func _configure_matte_material(material: StandardMaterial3D) -> void: + if material == null: + return + # Character artwork is deliberately graphic and flat. Unshaded rendering + # keeps the authored fur and facial colors invariant across world weather, + # time of day, and the isolated Profile preview. + material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + material.metallic = 0.0 + material.metallic_specular = 0.0 + material.roughness = 1.0 + material.diffuse_mode = BaseMaterial3D.DIFFUSE_LAMBERT + material.anisotropy_enabled = false + material.clearcoat_enabled = false + material.rim_enabled = false diff --git a/progression/character_customization_catalog.gd b/progression/character_customization_catalog.gd index e6fa987..fe3b249 100644 --- a/progression/character_customization_catalog.gd +++ b/progression/character_customization_catalog.gd @@ -3,6 +3,7 @@ extends RefCounted const CATEGORY_IDS: PackedStringArray = [ "species", + "scale", "fur_pattern", "ears", "eyes", @@ -13,6 +14,7 @@ const CATEGORY_IDS: PackedStringArray = [ const CATEGORY_LABELS: Dictionary = { "species": "head", + "scale": "size", "fur_pattern": "fur color", "ears": "ears", "eyes": "eyes", @@ -21,6 +23,12 @@ const CATEGORY_LABELS: Dictionary = { "tail": "tail", } +const SCALE_CATEGORY_ID: String = "scale" +const MIN_CHARACTER_SCALE: float = 0.75 +const MAX_CHARACTER_SCALE: float = 1.25 +const DEFAULT_CHARACTER_SCALE: float = 1.0 +const CHARACTER_SCALE_STEP: float = 0.05 + const FEATURE_CATEGORIES: PackedStringArray = ["eyes", "nose", "mouth"] const FEATURE_ASSET_ROOTS: Dictionary = { "eyes": "res://art/exported/characters/faces/eyes", @@ -33,19 +41,6 @@ const FEATURE_LABEL_OVERRIDES: Dictionary = { "dog_round": "round", "three": "three", } -const FEATURE_FALLBACK_TEXTURES: Dictionary = { - "eyes": { - "simple_shine": "res://art/exported/characters/faces/eyes/eyes_simple_shine.png", - "simple_shine_eyebrows": "res://art/exported/characters/faces/eyes/eyes_simple_shine_eyebrows.png", - }, - "mouth": { - "three": "res://art/exported/characters/faces/mouth/mouth_three.png", - }, - "nose": { - "dog_round": "res://art/exported/characters/faces/noses/nose_dog_round.png", - }, -} - const OPTIONS: Dictionary = { "species": [ {"id": "round", "label": "round"}, @@ -97,17 +92,34 @@ static var _feature_textures: Dictionary = {} static func default_snapshot() -> Dictionary: + _ensure_feature_assets() return { "species": "round", + "scale": DEFAULT_CHARACTER_SCALE, "fur_pattern": "white", "ears": "none", - "eyes": "simple_shine", - "nose": "dog_round", - "mouth": "three", + "eyes": _default_feature_option("eyes", "simple_shine"), + "nose": _default_feature_option("nose", "dog_round"), + "mouth": _default_feature_option("mouth", "three"), "tail": "none", } +static func _default_feature_option( + category_id: String, + legacy_id: String, +) -> String: + var options: Array = _feature_options.get(category_id, []) as Array + for option: Dictionary in options: + if str(option.get("id", "")) == legacy_id: + return legacy_id + for option: Dictionary in options: + var option_id := str(option.get("id", "")) + if option_id != "none": + return option_id + return "none" + + static func options_for(category_id: String) -> Array: if category_id in FEATURE_CATEGORIES: _ensure_feature_assets() @@ -136,7 +148,7 @@ static func _ensure_feature_assets() -> void: return _feature_assets_ready = true for category_id: String in FEATURE_CATEGORIES: - var options: Array = [] + var options: Array = [{"id": "none", "label": "none"}] var textures: Dictionary = {} var root_path := str(FEATURE_ASSET_ROOTS[category_id]) var directory := DirAccess.open(root_path) @@ -165,22 +177,6 @@ static func _ensure_feature_assets() -> void: "label": _feature_label(option_id), }) - if options.is_empty(): - for fallback: Dictionary in OPTIONS.get(category_id, []): - var fallback_id := str(fallback.get("id", "")) - options.append(fallback.duplicate(true)) - var fallback_path := str( - (FEATURE_FALLBACK_TEXTURES.get(category_id, {}) as Dictionary).get( - fallback_id, "" - ) - ) - if not fallback_path.is_empty(): - var fallback_texture := ResourceLoader.load( - fallback_path - ) as Texture2D - if fallback_texture != null: - textures[fallback_id] = fallback_texture - _feature_options[category_id] = options _feature_textures[category_id] = textures @@ -243,6 +239,10 @@ static func validate_snapshot(value: Variant) -> bool: if snapshot.size() != CATEGORY_IDS.size(): return false for category_id: String in CATEGORY_IDS: + if category_id == SCALE_CATEGORY_ID: + if not is_valid_character_scale(snapshot.get(category_id)): + return false + continue if ( typeof(snapshot.get(category_id)) != TYPE_STRING or not is_valid_option(category_id, str(snapshot[category_id])) @@ -257,9 +257,43 @@ static func sanitized_snapshot(value: Variant) -> Dictionary: return result var snapshot: Dictionary = value for category_id: String in CATEGORY_IDS: + if category_id == SCALE_CATEGORY_ID: + result[category_id] = character_scale( + snapshot.get(category_id, DEFAULT_CHARACTER_SCALE) + ) + continue var option_id: String = canonical_option_id( category_id, str(snapshot.get(category_id, "")) ) if is_valid_option(category_id, option_id): result[category_id] = option_id return result + + +static func character_scale(value: Variant) -> float: + if typeof(value) not in [TYPE_FLOAT, TYPE_INT]: + return DEFAULT_CHARACTER_SCALE + var number: float = float(value) + if not is_finite(number): + return DEFAULT_CHARACTER_SCALE + return clampf( + snappedf(number, CHARACTER_SCALE_STEP), + MIN_CHARACTER_SCALE, + MAX_CHARACTER_SCALE, + ) + + +static func is_valid_character_scale(value: Variant) -> bool: + if typeof(value) not in [TYPE_FLOAT, TYPE_INT]: + return false + var number: float = float(value) + return ( + is_finite(number) + and number >= MIN_CHARACTER_SCALE + and number <= MAX_CHARACTER_SCALE + and is_equal_approx(number, character_scale(number)) + ) + + +static func character_scale_percent(value: Variant) -> int: + return roundi(character_scale(value) * 100.0) diff --git a/tests/character_scale_validation.gd b/tests/character_scale_validation.gd new file mode 100644 index 0000000..1cc988c --- /dev/null +++ b/tests/character_scale_validation.gd @@ -0,0 +1,113 @@ +extends SceneTree + + +func _initialize() -> void: + call_deferred("_run") + + +func _run() -> void: + var legacy_snapshot: Dictionary = ( + CharacterCustomizationCatalog.default_snapshot() + ) + legacy_snapshot.erase(CharacterCustomizationCatalog.SCALE_CATEGORY_ID) + var migrated: Dictionary = ( + CharacterCustomizationCatalog.sanitized_snapshot(legacy_snapshot) + ) + assert( + is_equal_approx( + float(migrated[CharacterCustomizationCatalog.SCALE_CATEGORY_ID]), + CharacterCustomizationCatalog.DEFAULT_CHARACTER_SCALE, + ) + ) + assert(CharacterCustomizationCatalog.validate_snapshot(migrated)) + + var small_snapshot := migrated.duplicate(true) + small_snapshot[CharacterCustomizationCatalog.SCALE_CATEGORY_ID] = ( + CharacterCustomizationCatalog.MIN_CHARACTER_SCALE + ) + assert(CharacterCustomizationCatalog.validate_snapshot(small_snapshot)) + var large_snapshot := migrated.duplicate(true) + large_snapshot[CharacterCustomizationCatalog.SCALE_CATEGORY_ID] = ( + CharacterCustomizationCatalog.MAX_CHARACTER_SCALE + ) + assert(CharacterCustomizationCatalog.validate_snapshot(large_snapshot)) + var invalid_snapshot := migrated.duplicate(true) + invalid_snapshot[CharacterCustomizationCatalog.SCALE_CATEGORY_ID] = 2.0 + assert(not CharacterCustomizationCatalog.validate_snapshot(invalid_snapshot)) + + var visuals: Node3D = PlayerVisualPresenter.instantiate_visuals() + root.add_child(visuals) + PlayerVisualPresenter.apply_appearance(visuals, large_snapshot) + assert(visuals.scale.is_equal_approx( + Vector3.ONE * CharacterCustomizationCatalog.MAX_CHARACTER_SCALE + )) + var skeleton := visuals.find_child("Skeleton3D", true, false) as Skeleton3D + assert(skeleton != null) + var body := skeleton.get_node_or_null("body_main") as MeshInstance3D + assert(body != null) + var body_material := body.material_override as StandardMaterial3D + assert(body_material != null) + assert(body_material.shading_mode == BaseMaterial3D.SHADING_MODE_UNSHADED) + assert(is_zero_approx(body_material.metallic)) + assert(is_zero_approx(body_material.metallic_specular)) + assert(is_equal_approx(body_material.roughness, 1.0)) + assert(body_material.diffuse_mode == BaseMaterial3D.DIFFUSE_LAMBERT) + assert(not body_material.anisotropy_enabled) + assert(not body_material.clearcoat_enabled) + assert(not body_material.rim_enabled) + + var signed_small := {"appearance": small_snapshot} + var signed_large := {"appearance": large_snapshot} + assert( + NetworkProfileProtocol.signature_fields(signed_small) + != NetworkProfileProtocol.signature_fields(signed_large) + ) + + assert( + ProfilePreview.calculate_pixelated_grid_size( + Vector2(260.0, 330.0), + Vector2(1280.0, 720.0), + 3, + ) == Vector2i(130, 165) + ) + assert( + ProfilePreview.calculate_pixelated_grid_size( + Vector2(260.0, 330.0), + Vector2(640.0, 480.0), + 3, + ) == Vector2i(65, 83) + ) + + var profile_page := ProfilePage.new() + root.add_child(profile_page) + await process_frame + profile_page.call( + "_select_category", + CharacterCustomizationCatalog.SCALE_CATEGORY_ID, + ) + await process_frame + var slider := profile_page.find_child( + "CharacterScaleSlider", true, false + ) as HSlider + assert(slider != null) + assert(is_equal_approx( + float(slider.min_value), + CharacterCustomizationCatalog.MIN_CHARACTER_SCALE, + )) + assert(is_equal_approx( + float(slider.max_value), + CharacterCustomizationCatalog.MAX_CHARACTER_SCALE, + )) + slider.value = 1.15 + await process_frame + var draft: Dictionary = profile_page.get("_draft_appearance") + assert(is_equal_approx( + float(draft[CharacterCustomizationCatalog.SCALE_CATEGORY_ID]), + 1.15, + )) + + print("Character scale validation: PASS") + profile_page.queue_free() + visuals.queue_free() + await process_frame + quit() diff --git a/tests/character_scale_validation.gd.uid b/tests/character_scale_validation.gd.uid new file mode 100644 index 0000000..c74c5d0 --- /dev/null +++ b/tests/character_scale_validation.gd.uid @@ -0,0 +1 @@ +uid://d0w8gv1i4paii diff --git a/tests/fish_quality_validation.gd b/tests/fish_quality_validation.gd index 2ecaf66..9e42687 100644 --- a/tests/fish_quality_validation.gd +++ b/tests/fish_quality_validation.gd @@ -132,7 +132,7 @@ func _validate_barrier_challenge_curve() -> void: func _validate_fight_pacing_and_reel_upgrades() -> void: assert(is_equal_approx(CatchController.CHASE_SPEED, 0.07)) - assert(is_equal_approx(CatchController.CHASE_START_DELAY, 0.5)) + assert(is_equal_approx(CatchController.CHASE_START_DELAY, 1.0)) assert(is_equal_approx(CatchController.CHASE_START_OFFSET, 0.04)) assert(is_equal_approx(Player.BASE_REEL_SPEED, 0.16)) diff --git a/tests/fishing_surface_validation.gd b/tests/fishing_surface_validation.gd index c178aac..2f4a4b7 100644 --- a/tests/fishing_surface_validation.gd +++ b/tests/fishing_surface_validation.gd @@ -247,21 +247,21 @@ func _validate_bite_wait_distribution() -> void: var total_wait_seconds: float = 0.0 for _sample_index: int in 10000: var wait_seconds: float = fishing_spot.roll_bite_wait_time() - assert(wait_seconds >= 10.0) - assert(wait_seconds <= 240.0) + assert(wait_seconds >= FishingSpotType.BITE_QUICK_MIN_SECONDS) + assert(wait_seconds <= FishingSpotType.BITE_MAX_SECONDS) total_wait_seconds += wait_seconds - if wait_seconds < 30.0: + if wait_seconds < FishingSpotType.BITE_QUICK_MAX_SECONDS: quick_count += 1 else: typical_or_long_count += 1 - if wait_seconds >= 180.0: + if wait_seconds >= FishingSpotType.BITE_LONG_MAX_SECONDS: very_long_count += 1 var average_wait_seconds: float = total_wait_seconds / 10000.0 assert(quick_count >= 2300 and quick_count <= 2700) assert(typical_or_long_count > quick_count) assert(very_long_count >= 100 and very_long_count <= 300) - assert(average_wait_seconds >= 57.0) - assert(average_wait_seconds <= 61.0) + assert(average_wait_seconds >= 45.0) + assert(average_wait_seconds <= 49.0) fishing_spot.queue_free() await process_frame @@ -297,7 +297,10 @@ func _validate_remote_presentation() -> void: assert(fish_catch.is_valid()) presentation.play_return(fish_catch) await create_timer(0.6).timeout - var catch_display := player.get_node("%CatchDisplay") as Node3D + var catch_display := player.find_child( + "CatchDisplay", true, false + ) as Node3D + assert(catch_display != null) assert(catch_display.visible) await presentation.return_completed assert(not catch_display.visible) diff --git a/tests/logbook_runtime_validation.gd b/tests/logbook_runtime_validation.gd index 923bbf1..71f7876 100644 --- a/tests/logbook_runtime_validation.gd +++ b/tests/logbook_runtime_validation.gd @@ -136,9 +136,10 @@ func _validate_save_round_trip( player.inventory.get_catches_by_fish_id(fish_id).front() ) player.begin_catch_showcase(fish_catch) - var catch_sprite := player.get_node( - "%CatchSprite" + var catch_sprite := player.find_child( + "CatchSprite", true, false ) as Sprite3D + assert(catch_sprite != null) assert(catch_sprite.texture == fish_catch.fish.display_texture) player.end_catch_showcase(Callable(), true) diff --git a/tests/surface_drawing_runtime_validation.gd b/tests/surface_drawing_runtime_validation.gd index d730a6a..6e6e68d 100644 --- a/tests/surface_drawing_runtime_validation.gd +++ b/tests/surface_drawing_runtime_validation.gd @@ -119,9 +119,11 @@ func _validate_marker_controls( player: Player, ) -> void: var prior_mouse_mode: Input.MouseMode = Input.mouse_mode - service.activate() + var activation_pointer := Vector2(824.0, 318.0) + service.activate(activation_pointer) assert(service.is_active()) assert(service.is_placement_mode()) + assert(service.get_pointer_screen_position() == activation_pointer) if DisplayServer.get_name() != "headless": assert(Input.mouse_mode == Input.MOUSE_MODE_VISIBLE) @@ -136,6 +138,15 @@ func _validate_marker_controls( pointer_motion.position = pointer_before + Vector2(30.0, -12.0) assert(service.handle_input(pointer_motion, true)) assert(service.get_pointer_screen_position() != pointer_before) + var scaled_ui_motion := InputEventMouseMotion.new() + scaled_ui_motion.position = Vector2(260.0, 140.0) + var root_viewport_pointer := Vector2(960.0, 540.0) + assert(service.handle_input( + scaled_ui_motion, + true, + root_viewport_pointer, + )) + assert(service.get_pointer_screen_position() == root_viewport_pointer) var zoom_event := InputEventMouseButton.new() zoom_event.button_index = MOUSE_BUTTON_WHEEL_UP zoom_event.shift_pressed = true diff --git a/ui/chat_ui.gd b/ui/chat_ui.gd index fe7f731..909e307 100644 --- a/ui/chat_ui.gd +++ b/ui/chat_ui.gd @@ -21,6 +21,9 @@ const HANDLE_GAP: float = 6.0 const COLLAPSED_REVEAL_WIDTH: float = 8.0 const HINT_EDGE_MARGIN: float = 4.0 const SPEECH_BUBBLE_WIDTH: float = 320.0 +const SPEECH_POINTER_HALF_WIDTH: float = 12.0 +const SPEECH_POINTER_HEIGHT: float = 14.0 +const SPEECH_POINTER_OVERLAP: float = 3.0 const MOBILE_COMPACT_WIDTH: float = 620.0 const MOBILE_EXPANDED_WIDTH: float = 820.0 const MOBILE_COMPACT_HEIGHT: float = 220.0 @@ -571,20 +574,31 @@ func _apply_flat_chat_button(button: Button) -> void: func _speech_panel_style() -> StyleBoxFlat: var style := StyleBoxFlat.new() - style.bg_color = Color(UtilityPageStyle.PAPER_ALT, 0.96) - style.border_color = Color(UtilityPageStyle.BORDER, 0.88) - style.set_border_width_all(2) + style.bg_color = Color(UtilityPageStyle.OCEAN_PANEL_MID, 0.96) + style.set_border_width_all(0) style.set_corner_radius_all(12) + style.anti_aliasing = false style.content_margin_left = 10 style.content_margin_right = 10 style.content_margin_top = 6 style.content_margin_bottom = 6 - style.shadow_color = Color(0, 0, 0, 0.32) - style.shadow_size = 4 - style.shadow_offset = Vector2(2, 3) return style +func _create_speech_pointer() -> Polygon2D: + var pointer := Polygon2D.new() + pointer.name = "SpeechPointer" + pointer.polygon = PackedVector2Array([ + Vector2(-SPEECH_POINTER_HALF_WIDTH, 0.0), + Vector2(SPEECH_POINTER_HALF_WIDTH, 0.0), + Vector2(0.0, SPEECH_POINTER_HEIGHT), + ]) + pointer.color = Color(UtilityPageStyle.OCEAN_PANEL_MID, 0.96) + pointer.antialiased = false + pointer.z_index = -1 + return pointer + + func _send() -> void: if _send_pending: return @@ -630,6 +644,8 @@ func _on_message(message: Dictionary) -> void: bubble.mouse_filter = Control.MOUSE_FILTER_IGNORE bubble.custom_minimum_size = Vector2(SPEECH_BUBBLE_WIDTH, 0.0) bubble.add_theme_stylebox_override("panel", _speech_panel_style()) + var pointer := _create_speech_pointer() + bubble.add_child(pointer) var label := Label.new() label.text = str(message["body"]) label.custom_minimum_size = Vector2( @@ -641,11 +657,14 @@ func _on_message(message: Dictionary) -> void: label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER label.mouse_filter = Control.MOUSE_FILTER_IGNORE label.add_theme_font_override("font", UtilityPageStyle.TuffyFont) - label.add_theme_color_override("font_color", UtilityPageStyle.INK) + label.add_theme_color_override( + "font_color", UtilityPageStyle.OCEAN_TEXT_PRIMARY + ) bubble.add_child(label) _speech_layer.add_child(bubble) _speech[peer_id] = { "bubble": bubble, + "pointer": pointer, "expires": Time.get_ticks_msec() / 1000.0 + SPEECH_SECONDS, "fingerprint": str(message.get("sender_fingerprint", "")), } @@ -863,12 +882,30 @@ func _update_speech() -> void: bubble.hide() continue var desired := screen_position - Vector2( - bubble.size.x * 0.5, bubble.size.y + 8.0 + bubble.size.x * 0.5, + bubble.size.y + SPEECH_POINTER_HEIGHT, ) bubble.position = Vector2( clampf(desired.x, 8.0, viewport_size.x - bubble.size.x - 8.0), - clampf(desired.y, 8.0, viewport_size.y - bubble.size.y - 8.0), + clampf( + desired.y, + 8.0, + viewport_size.y + - bubble.size.y + - SPEECH_POINTER_HEIGHT + - 8.0, + ), ) + var pointer := state.get("pointer") as Polygon2D + if pointer != null: + pointer.position = Vector2( + clampf( + screen_position.x - bubble.position.x, + SPEECH_POINTER_HALF_WIDTH + 12.0, + bubble.size.x - SPEECH_POINTER_HALF_WIDTH - 12.0, + ), + bubble.size.y - SPEECH_POINTER_OVERLAP, + ) bubble.show() diff --git a/ui/game_ui.gd b/ui/game_ui.gd index 63e5663..830f291 100644 --- a/ui/game_ui.gd +++ b/ui/game_ui.gd @@ -78,6 +78,10 @@ const CONTROLLER_MENU_SCROLL_SPEED: float = 660.0 const VIRTUAL_MOUSE_TRIGGER_AXIS: JoyAxis = JOY_AXIS_TRIGGER_RIGHT const VIRTUAL_MOUSE_SHARED_TRIGGER_AXIS: JoyAxis = JOY_AXIS_TRIGGER_LEFT const VIRTUAL_MOUSE_SECONDARY_CLICK_AXIS: JoyAxis = JOY_AXIS_TRIGGER_LEFT +const FISHING_PANEL_DEFAULT_TOP_OFFSET: float = -210.0 +const FISHING_PANEL_DEFAULT_BOTTOM_OFFSET: float = -140.0 +const FISHING_PANEL_SHOWCASE_TOP_OFFSET: float = -174.0 +const FISHING_PANEL_SHOWCASE_BOTTOM_OFFSET: float = -104.0 @onready var _status_label: Label = %StatusLabel @onready var _gameplay_transient_hud: Control = %GameplayTransientHUD @@ -155,6 +159,7 @@ var _virtual_mouse_stick: Vector2 = Vector2.ZERO var _virtual_mouse_trigger_rest_by_device: Dictionary[int, float] = {} var _shared_trigger_rest_by_device: Dictionary[int, float] = {} var _controller_mapping_manager: ControllerMappingManagerType +var _settings_manager: PlayerSettingsManagerType func _ready() -> void: @@ -231,6 +236,7 @@ func setup( world_sun: DirectionalLight3D, ) -> void: _player = player + _settings_manager = settings_manager _fishing_spot = fishing_spot _item_effects = item_effects _experience = experience @@ -290,6 +296,15 @@ func setup( world_environment, world_sun, ) + if ( + _settings_manager != null + and not _settings_manager.settings_changed.is_connected( + _on_player_settings_changed + ) + ): + _settings_manager.settings_changed.connect(_on_player_settings_changed) + if _settings_manager != null: + _on_player_settings_changed(_settings_manager.current_settings) _hotbar_ui.setup(hotbar, bag, item_catalog, fishing_spot, inventory) _fishing_shop.setup( player, @@ -347,7 +362,11 @@ func _input(event: InputEvent) -> void: ) if ( _surface_drawing != null - and _surface_drawing.handle_input(event, drawing_can_open) + and _surface_drawing.handle_input( + event, + drawing_can_open, + _drawing_pointer_window_position(), + ) ): get_viewport().set_input_as_handled() return @@ -959,7 +978,13 @@ func _toggle_surface_drawing() -> void: if _surface_drawing.is_active(): _surface_drawing.deactivate() elif _surface_drawing.can_activate(): - _surface_drawing.activate() + _surface_drawing.activate(_drawing_pointer_window_position()) + + +func _drawing_pointer_window_position() -> Vector2: + if _virtual_mouse_active: + return _virtual_mouse_window_position + return get_window().get_mouse_position() func setup_data_and_identity( @@ -1229,6 +1254,13 @@ func set_effective_ui_pixel_size(pixel_size: int) -> void: _pause_settings_panel.set_effective_ui_pixel_size(pixel_size) +func _on_player_settings_changed(settings: PlayerSettings) -> void: + if settings != null: + _player_menu.set_profile_preview_world_pixel_size( + settings.world_pixel_size + ) + + func set_edge_docks( chat_dock_right: bool, paint_dock_right: bool, @@ -1389,11 +1421,13 @@ func _on_showcase_changed( ) -> void: _showcase_active = visible if not visible: + _set_fishing_panel_showcase_position(false) _showcase_details.text = "" _showcase_details.visible = false _set_fishing_status("") call_deferred("_start_next_experience_animation") return + _set_fishing_panel_showcase_position(true) _catch_track.visible = false _barrier_prompt_panel.visible = false _barrier_prompt.visible = false @@ -1411,6 +1445,19 @@ func _on_showcase_changed( _refresh_fishing_panel_visibility() +func _set_fishing_panel_showcase_position(showcase: bool) -> void: + _fishing_panel.offset_top = ( + FISHING_PANEL_SHOWCASE_TOP_OFFSET + if showcase + else FISHING_PANEL_DEFAULT_TOP_OFFSET + ) + _fishing_panel.offset_bottom = ( + FISHING_PANEL_SHOWCASE_BOTTOM_OFFSET + if showcase + else FISHING_PANEL_DEFAULT_BOTTOM_OFFSET + ) + + func _on_experience_awarded( amount: int, previous_total: int, diff --git a/ui/player_menu.gd b/ui/player_menu.gd index 5644a68..5e6bd32 100644 --- a/ui/player_menu.gd +++ b/ui/player_menu.gd @@ -582,6 +582,10 @@ func setup_controller_mapping( _profile_page.setup_controller_mapping(_controller_mapping_manager) +func set_profile_preview_world_pixel_size(pixel_size: int) -> void: + _profile_page.set_world_pixel_size(pixel_size) + + func _input(event: InputEvent) -> void: if event is InputEventKey and event.echo: return diff --git a/ui/profile_page.gd b/ui/profile_page.gd index 9442fce..fce7b83 100644 --- a/ui/profile_page.gd +++ b/ui/profile_page.gd @@ -33,6 +33,8 @@ var _debounce: Timer var _experience_level: Label var _experience_progress: ProgressBar var _experience_value: Label +var _feature_preview_cache: Dictionary = {} +var _scale_value_label: Label func _ready() -> void: @@ -84,6 +86,11 @@ func setup_controller_mapping( _preview.setup_controller_mapping(mapping_manager) +func set_world_pixel_size(pixel_size: int) -> void: + if _preview != null: + _preview.set_world_pixel_size(pixel_size) + + func activate() -> void: visible = true UtilityPageStyle.animate_in(self) @@ -281,48 +288,51 @@ func _build_ui() -> void: _category_list.add_theme_constant_override("separation", 5) body.add_child(_category_list) _option_list = VBoxContainer.new() - _option_list.custom_minimum_size = Vector2(170, 0) + _option_list.custom_minimum_size = Vector2(360, 0) + _option_list.size_flags_horizontal = Control.SIZE_EXPAND_FILL + _option_list.size_flags_vertical = Control.SIZE_EXPAND_FILL _option_list.add_theme_constant_override("separation", 5) body.add_child(_option_list) var body_spacer := Control.new() - body_spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL + body_spacer.custom_minimum_size.x = 12.0 + body_spacer.size_flags_horizontal = Control.SIZE_SHRINK_CENTER body.add_child(body_spacer) var preview_stack := VBoxContainer.new() - preview_stack.custom_minimum_size.x = 180.0 + preview_stack.custom_minimum_size.x = 260.0 + preview_stack.size_flags_vertical = Control.SIZE_EXPAND_FILL preview_stack.alignment = BoxContainer.ALIGNMENT_CENTER preview_stack.add_theme_constant_override("separation", 7) body.add_child(preview_stack) var preview_frame := PanelContainer.new() - preview_frame.custom_minimum_size = Vector2(180.0, 220.0) + preview_frame.custom_minimum_size = Vector2(260.0, 0.0) + preview_frame.size_flags_vertical = Control.SIZE_EXPAND_FILL preview_frame.add_theme_stylebox_override( "panel", UtilityPageStyle.rounded_style( UtilityPageStyle.OCEAN_FIELD, 18 ) ) preview_stack.add_child(preview_frame) + var preview_layer := Control.new() + preview_layer.size_flags_horizontal = Control.SIZE_EXPAND_FILL + preview_layer.size_flags_vertical = Control.SIZE_EXPAND_FILL + preview_layer.mouse_filter = Control.MOUSE_FILTER_PASS + preview_frame.add_child(preview_layer) _preview = preload("res://ui/profile_preview.tscn").instantiate() - _preview.custom_minimum_size = Vector2(180.0, 220.0) - preview_frame.add_child(_preview) - var preview_actions := VBoxContainer.new() - preview_actions.alignment = BoxContainer.ALIGNMENT_CENTER - preview_actions.add_theme_constant_override("separation", 4) - preview_stack.add_child(preview_actions) - var preview_note := Label.new() - preview_note.text = "drag or use left / right" - preview_note.custom_minimum_size.x = 180.0 - preview_note.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER - preview_note.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART - preview_note.add_theme_font_size_override("font_size", 12) - preview_note.add_theme_color_override( - "font_color", UtilityPageStyle.OCEAN_TEXT_SECONDARY - ) - preview_actions.add_child(preview_note) + _preview.custom_minimum_size = Vector2(260.0, 0.0) + _preview.size_flags_horizontal = Control.SIZE_EXPAND_FILL + _preview.size_flags_vertical = Control.SIZE_EXPAND_FILL + preview_layer.add_child(_preview) + _preview.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) var reset_view := Button.new() - reset_view.text = "reset view" - reset_view.size_flags_horizontal = Control.SIZE_SHRINK_CENTER + reset_view.text = "↶" + reset_view.tooltip_text = "reset view" + reset_view.custom_minimum_size = Vector2(36.0, 36.0) + reset_view.position = Vector2(-8.0, -8.0) + reset_view.z_index = 2 reset_view.pressed.connect(_preview.reset_view) UtilityPageStyle.apply_compact_ocean_button(reset_view) - preview_actions.add_child(reset_view) + reset_view.add_theme_font_size_override("font_size", 22) + preview_layer.add_child(reset_view) _discard_confirmation = PanelContainer.new() _discard_confirmation.visible = false @@ -396,6 +406,9 @@ func _refresh_options() -> void: "font_color", UtilityPageStyle.OCEAN_TEXT_PRIMARY ) _option_list.add_child(title) + if _category_id == CharacterCustomizationCatalog.SCALE_CATEGORY_ID: + _build_scale_option() + return var options: Array = CharacterCustomizationCatalog.options_for(_category_id) if options.is_empty(): var empty := Label.new() @@ -406,18 +419,176 @@ func _refresh_options() -> void: if _category_id == "fur_pattern": _build_fur_color_options(options) return + if _category_id in CharacterCustomizationCatalog.FEATURE_CATEGORIES: + _build_feature_preview_options(options) + return for option: Dictionary in options: var option_id := str(option["id"]) var button := Button.new() - button.text = str(option["label"]) + button.text = "×" if option_id == "none" else str(option["label"]) + button.tooltip_text = "none" if option_id == "none" else str( + option["label"] + ) button.toggle_mode = true button.custom_minimum_size.x = 170.0 button.button_pressed = _draft_appearance.get(_category_id) == option_id button.pressed.connect(_select_option.bind(_category_id, option_id)) UtilityPageStyle.apply_compact_ocean_button(button) + if option_id == "none": + button.add_theme_font_size_override("font_size", 24) _option_list.add_child(button) +func _build_scale_option() -> void: + var description := Label.new() + description.text = "Adjust your character's visual size." + description.add_theme_font_size_override("font_size", 14) + description.add_theme_color_override( + "font_color", UtilityPageStyle.OCEAN_TEXT_SECONDARY + ) + _option_list.add_child(description) + + var value_row := HBoxContainer.new() + value_row.add_theme_constant_override("separation", 10) + value_row.size_flags_horizontal = Control.SIZE_EXPAND_FILL + _option_list.add_child(value_row) + + var small_label := Label.new() + small_label.text = "small" + small_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + small_label.add_theme_color_override( + "font_color", UtilityPageStyle.OCEAN_TEXT_SECONDARY + ) + value_row.add_child(small_label) + + var slider := HSlider.new() + slider.name = "CharacterScaleSlider" + slider.min_value = CharacterCustomizationCatalog.MIN_CHARACTER_SCALE + slider.max_value = CharacterCustomizationCatalog.MAX_CHARACTER_SCALE + slider.step = CharacterCustomizationCatalog.CHARACTER_SCALE_STEP + slider.custom_minimum_size = Vector2(220.0, 40.0) + slider.size_flags_horizontal = Control.SIZE_EXPAND_FILL + slider.tooltip_text = "character size" + slider.value = CharacterCustomizationCatalog.character_scale( + _draft_appearance.get( + CharacterCustomizationCatalog.SCALE_CATEGORY_ID, + CharacterCustomizationCatalog.DEFAULT_CHARACTER_SCALE, + ) + ) + slider.value_changed.connect(_select_scale) + value_row.add_child(slider) + + var large_label := Label.new() + large_label.text = "large" + large_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + large_label.add_theme_color_override( + "font_color", UtilityPageStyle.OCEAN_TEXT_SECONDARY + ) + value_row.add_child(large_label) + + _scale_value_label = Label.new() + _scale_value_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + _scale_value_label.add_theme_font_size_override("font_size", 20) + _scale_value_label.add_theme_color_override( + "font_color", UtilityPageStyle.OCEAN_TEXT_PRIMARY + ) + _option_list.add_child(_scale_value_label) + _update_scale_value_label(float(slider.value)) + + var gameplay_note := Label.new() + gameplay_note.text = "Movement and collision stay the same." + gameplay_note.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + gameplay_note.add_theme_font_size_override("font_size", 12) + gameplay_note.add_theme_color_override( + "font_color", UtilityPageStyle.OCEAN_TEXT_SECONDARY + ) + _option_list.add_child(gameplay_note) + + +func _build_feature_preview_options(options: Array) -> void: + var scroll := ScrollContainer.new() + scroll.custom_minimum_size = Vector2(190.0, 0.0) + scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL + scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED + scroll.vertical_scroll_mode = ScrollContainer.SCROLL_MODE_AUTO + _option_list.add_child(scroll) + var grid := GridContainer.new() + grid.columns = 4 + grid.add_theme_constant_override("h_separation", 8) + grid.add_theme_constant_override("v_separation", 8) + grid.size_flags_horizontal = Control.SIZE_EXPAND_FILL + scroll.add_child(grid) + var selected_id := CharacterCustomizationCatalog.canonical_option_id( + _category_id, str(_draft_appearance.get(_category_id, "")) + ) + for option: Dictionary in options: + var option_id := str(option.get("id", "")) + var button := Button.new() + var is_none := option_id == "none" + button.text = "×" if is_none else "" + button.tooltip_text = "none" if is_none else str( + option.get("label", option_id) + ) + button.toggle_mode = true + button.button_pressed = selected_id == option_id + button.custom_minimum_size = Vector2(84.0, 64.0) + button.alignment = HORIZONTAL_ALIGNMENT_CENTER + button.clip_contents = true + button.pressed.connect(_select_option.bind(_category_id, option_id)) + UtilityPageStyle.apply_compact_ocean_button(button) + button.custom_minimum_size = Vector2(84.0, 64.0) + if is_none: + button.add_theme_font_size_override("font_size", 28) + else: + var preview := TextureRect.new() + preview.texture = _feature_preview_texture( + _category_id, option_id + ) + preview.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + preview.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED + preview.mouse_filter = Control.MOUSE_FILTER_IGNORE + var preview_height := 50.0 + var preview_width := clampf( + preview_height * PlayerVisualPresenter.feature_uv_aspect( + _category_id + ), + 32.0, + 74.0, + ) + preview.custom_minimum_size = Vector2(preview_width, preview_height) + preview.size = Vector2(preview_width, preview_height) + preview.position = Vector2((84.0 - preview_width) * 0.5, 7.0) + button.add_child(preview) + grid.add_child(button) + + +func _feature_preview_texture( + category_id: String, + option_id: String, +) -> Texture2D: + var cache_key := "%s:%s" % [category_id, option_id] + if _feature_preview_cache.has(cache_key): + return _feature_preview_cache[cache_key] as Texture2D + var source := CharacterCustomizationCatalog.texture_for( + category_id, option_id + ) + if source == null: + return null + var image := source.get_image() + var used := image.get_used_rect() + if used.size.x <= 0 or used.size.y <= 0: + _feature_preview_cache[cache_key] = source + return source + var padding := 12 + used.position -= Vector2i(padding, padding) + used.size += Vector2i(padding * 2, padding * 2) + used = used.intersection(Rect2i(Vector2i.ZERO, image.get_size())) + var cropped := image.get_region(used) + var preview := ImageTexture.create_from_image(cropped) + _feature_preview_cache[cache_key] = preview + return preview + + func _build_fur_color_options(options: Array) -> void: var grid := GridContainer.new() grid.columns = 4 @@ -469,6 +640,26 @@ func _select_option(category_id: String, option_id: String) -> void: _refresh_actions() +func _select_scale(value: float) -> void: + var resolved_scale: float = CharacterCustomizationCatalog.character_scale( + value + ) + _draft_appearance[CharacterCustomizationCatalog.SCALE_CATEGORY_ID] = ( + resolved_scale + ) + _update_scale_value_label(resolved_scale) + _preview.apply_appearance_profile(_draft_appearance) + _dirty = _draft_differs() + _refresh_actions() + + +func _update_scale_value_label(value: float) -> void: + if _scale_value_label != null: + _scale_value_label.text = "%d%%" % ( + CharacterCustomizationCatalog.character_scale_percent(value) + ) + + func _on_name_changed(value: String) -> void: _draft_name = value _allow_duplicate = false diff --git a/ui/profile_preview.gd b/ui/profile_preview.gd index f75ea22..5076cd3 100644 --- a/ui/profile_preview.gd +++ b/ui/profile_preview.gd @@ -4,7 +4,15 @@ extends SubViewportContainer const ControllerMappingManagerType = preload( "res://settings/controller_mapping_manager.gd" ) +const UIReferencePresentationType = preload( + "res://ui/ui_reference_presentation.gd" +) const FRONT_FACING_YAW: float = PI +const DEFAULT_CAMERA_DISTANCE: float = 1.9 +const MIN_CAMERA_DISTANCE: float = 1.05 +const MAX_CAMERA_DISTANCE: float = 2.8 +const CAMERA_ZOOM_STEP: float = 0.14 +const CAMERA_TARGET_HEIGHT: float = 0.95 @export_range(0.1, 2.0, 0.05) var drag_sensitivity: float = 0.012 @export_range(0.1, 4.0, 0.1) var keyboard_speed: float = 1.8 @@ -12,12 +20,18 @@ const FRONT_FACING_YAW: float = PI @onready var _preview_root: Node3D = %PreviewRoot @onready var _preview_environment: WorldEnvironment = %WorldEnvironment @onready var _preview_sun: DirectionalLight3D = %KeyLight +@onready var _preview_camera: Camera3D = $Viewport/Camera3D +@onready var _pixelation_material: ShaderMaterial = material as ShaderMaterial var _dragging: bool = false +var _camera_yaw: float = 0.0 +var _camera_pitch: float = 0.0 +var _camera_distance: float = DEFAULT_CAMERA_DISTANCE var _visuals: Node3D var _controller_mapping_manager: ControllerMappingManagerType var _source_environment: WorldEnvironment var _source_sun: DirectionalLight3D +var _world_pixel_size: int = PlayerSettings.DEFAULT_WORLD_PIXEL_SIZE func setup_controller_mapping( @@ -35,9 +49,22 @@ func setup_world_lighting( _sync_world_lighting() +func set_world_pixel_size(pixel_size: int) -> void: + _world_pixel_size = clampi( + pixel_size, + PlayerSettings.MIN_WORLD_PIXEL_SIZE, + PlayerSettings.MAX_WORLD_PIXEL_SIZE, + ) + _refresh_pixelation_filter() + + func _ready() -> void: focus_mode = Control.FOCUS_ALL + texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST gui_input.connect(_on_gui_input) + resized.connect(_refresh_pixelation_filter) + get_window().size_changed.connect(_refresh_pixelation_filter) + _configure_preview_lighting() reset_view() _visuals = PlayerVisualPresenter.instantiate_visuals() _preview_root.add_child(_visuals) @@ -47,6 +74,7 @@ func _ready() -> void: var catch_display := _visuals.find_child("CatchDisplay", true, false) as Node3D if catch_display != null: catch_display.visible = false + call_deferred("_refresh_pixelation_filter") func apply_appearance_profile(profile: Dictionary) -> void: @@ -56,6 +84,12 @@ func apply_appearance_profile(profile: Dictionary) -> void: func reset_view() -> void: _preview_root.rotation.y = FRONT_FACING_YAW + _camera_yaw = 0.0 + _camera_pitch = 0.0 + _camera_distance = DEFAULT_CAMERA_DISTANCE + _apply_camera_orbit() + if _preview_camera != null: + _preview_camera.position.z = DEFAULT_CAMERA_DISTANCE func _process(delta: float) -> void: @@ -77,13 +111,30 @@ func _process(delta: float) -> void: func _on_gui_input(event: InputEvent) -> void: - if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT: + if event is InputEventMouseButton and event.shift_pressed: + if event.button_index == MOUSE_BUTTON_WHEEL_UP and event.pressed: + _zoom_preview(-CAMERA_ZOOM_STEP) + grab_focus() + accept_event() + return + if event.button_index == MOUSE_BUTTON_WHEEL_DOWN and event.pressed: + _zoom_preview(CAMERA_ZOOM_STEP) + grab_focus() + accept_event() + return + if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT: _dragging = event.pressed if event.pressed: grab_focus() accept_event() elif event is InputEventMouseMotion and _dragging: _rotate(event.relative.x * drag_sensitivity) + _camera_pitch = clampf( + _camera_pitch + event.relative.y * drag_sensitivity, + -0.55, + 0.55, + ) + _apply_camera_orbit() accept_event() @@ -93,20 +144,96 @@ func _notification(what: int) -> void: func _rotate(amount: float) -> void: - _preview_root.rotation.y = fposmod(_preview_root.rotation.y + amount, TAU) + _camera_yaw = fposmod(_camera_yaw + amount, TAU) + _apply_camera_orbit() + + +func _zoom_preview(amount: float) -> void: + if _preview_camera == null: + return + _camera_distance = clampf( + _camera_distance + amount, + MIN_CAMERA_DISTANCE, + MAX_CAMERA_DISTANCE, + ) + _apply_camera_orbit() + + +func _apply_camera_orbit() -> void: + if _preview_camera == null: + return + var horizontal_distance := cos(_camera_pitch) * _camera_distance + _preview_camera.position = Vector3( + sin(_camera_yaw) * horizontal_distance, + CAMERA_TARGET_HEIGHT + sin(_camera_pitch) * _camera_distance, + cos(_camera_yaw) * horizontal_distance, + ) + _preview_camera.look_at( + Vector3(0.0, CAMERA_TARGET_HEIGHT, 0.0), + Vector3.UP, + ) func _sync_world_lighting() -> void: - if ( - _preview_environment == null - or _preview_sun == null - or _source_environment == null - or _source_sun == null - ): + # The customization viewport deliberately does not follow gameplay time of + # day. Keep this method as a compatibility seam for existing setup callers. + pass + + +func _configure_preview_lighting() -> void: + if _preview_environment == null or _preview_sun == null: return - _preview_environment.environment = _source_environment.environment - _preview_sun.rotation = _source_sun.global_rotation - _preview_sun.light_color = _source_sun.light_color - _preview_sun.light_energy = _source_sun.light_energy - _preview_sun.light_indirect_energy = _source_sun.light_indirect_energy - _preview_sun.shadow_enabled = _source_sun.shadow_enabled + var environment := Environment.new() + environment.background_mode = Environment.BG_COLOR + environment.background_color = Color("082431") + environment.ambient_light_source = Environment.AMBIENT_SOURCE_COLOR + environment.ambient_light_color = Color("b9d8d4") + environment.ambient_light_energy = 1.15 + environment.reflected_light_source = Environment.REFLECTION_SOURCE_DISABLED + _preview_environment.environment = environment + _preview_sun.rotation_degrees = Vector3(-35.0, -25.0, 0.0) + _preview_sun.light_color = Color("fff1d0") + _preview_sun.light_energy = 1.1 + _preview_sun.light_indirect_energy = 0.0 + _preview_sun.shadow_enabled = false + + +func _refresh_pixelation_filter() -> void: + if not is_node_ready() or _pixelation_material == null: + return + _pixelation_material.set_shader_parameter( + "logical_grid_size", + Vector2(calculate_pixelated_grid_size( + size, + Vector2(get_window().size), + _world_pixel_size, + )), + ) + + +static func calculate_pixelated_grid_size( + control_size: Vector2, + window_size: Vector2, + pixel_size: int, +) -> Vector2i: + var safe_window_size := Vector2( + maxf(window_size.x, 1.0), + maxf(window_size.y, 1.0), + ) + var world_grid_size: Vector2i = PlayerSettings.get_world_grid_size( + pixel_size, + Vector2i(roundi(safe_window_size.x), roundi(safe_window_size.y)), + ) + var world_pixel_extent: float = ( + safe_window_size.y / float(maxi(world_grid_size.y, 1)) + ) + var presentation_scale: float = UIReferencePresentationType.get_scale( + safe_window_size + ) + var grid_size: Vector2 = ( + control_size * presentation_scale / maxf(world_pixel_extent, 0.001) + ) + return Vector2i( + maxi(roundi(grid_size.x), 1), + maxi(roundi(grid_size.y), 1), + ) diff --git a/ui/profile_preview.tscn b/ui/profile_preview.tscn index 78d47cc..27313ec 100644 --- a/ui/profile_preview.tscn +++ b/ui/profile_preview.tscn @@ -1,11 +1,17 @@ -[gd_scene load_steps=3 format=3] +[gd_scene load_steps=4 format=3] [ext_resource type="Script" path="res://ui/profile_preview.gd" id="1"] +[ext_resource type="Shader" path="res://ui/profile_preview_pixelation.gdshader" id="2_pixelation"] [sub_resource type="World3D" id="PreviewWorld"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_pixelation"] +shader = ExtResource("2_pixelation") + [node name="ProfilePreview" type="SubViewportContainer"] +material = SubResource("ShaderMaterial_pixelation") custom_minimum_size = Vector2(300, 220) +texture_filter = 1 stretch = true script = ExtResource("1") @@ -27,5 +33,6 @@ shadow_enabled = false unique_name_in_owner = true [node name="Camera3D" type="Camera3D" parent="Viewport"] +unique_name_in_owner = true position = Vector3(0, 0.95, 1.9) current = true diff --git a/ui/profile_preview_pixelation.gdshader b/ui/profile_preview_pixelation.gdshader new file mode 100644 index 0000000..27a4f07 --- /dev/null +++ b/ui/profile_preview_pixelation.gdshader @@ -0,0 +1,11 @@ +shader_type canvas_item; +render_mode unshaded; + +uniform vec2 logical_grid_size = vec2(160.0, 165.0); + + +void fragment() { + vec2 safe_grid = max(logical_grid_size, vec2(1.0)); + vec2 snapped_uv = (floor(UV * safe_grid) + vec2(0.5)) / safe_grid; + COLOR = texture(TEXTURE, snapped_uv); +} diff --git a/ui/profile_preview_pixelation.gdshader.uid b/ui/profile_preview_pixelation.gdshader.uid new file mode 100644 index 0000000..dbf8e18 --- /dev/null +++ b/ui/profile_preview_pixelation.gdshader.uid @@ -0,0 +1 @@ +uid://dlbc0pxkqo028