Add modular character customization
|
After Width: | Height: | Size: 7 KiB |
|
|
@ -0,0 +1,45 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dyjwgkgw0syo8"
|
||||||
|
path.s3tc="res://.godot/imported/netfishing_base_character_eyes_simple_shine.png-140bfa3aa0b6f662e8ff9e5721213a61.s3tc.ctex"
|
||||||
|
path.etc2="res://.godot/imported/netfishing_base_character_eyes_simple_shine.png-140bfa3aa0b6f662e8ff9e5721213a61.etc2.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc", "etc2_astc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
generator_parameters={
|
||||||
|
"md5": "c2f7c29aaaa95809e140eb308d9bb132"
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://art/exported/characters/base/netfishing_base_character_eyes_simple_shine.png"
|
||||||
|
dest_files=["res://.godot/imported/netfishing_base_character_eyes_simple_shine.png-140bfa3aa0b6f662e8ff9e5721213a61.s3tc.ctex", "res://.godot/imported/netfishing_base_character_eyes_simple_shine.png-140bfa3aa0b6f662e8ff9e5721213a61.etc2.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=0
|
||||||
|
After Width: | Height: | Size: 6.1 KiB |
|
|
@ -0,0 +1,45 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dt5gitdtjdvcd"
|
||||||
|
path.s3tc="res://.godot/imported/netfishing_base_character_mouth_three.png-90b4a98403d2a291a56a8ed42aaa8473.s3tc.ctex"
|
||||||
|
path.etc2="res://.godot/imported/netfishing_base_character_mouth_three.png-90b4a98403d2a291a56a8ed42aaa8473.etc2.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc", "etc2_astc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
generator_parameters={
|
||||||
|
"md5": "f8bf25a1006c5cc2ab5323f4a758eec7"
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://art/exported/characters/base/netfishing_base_character_mouth_three.png"
|
||||||
|
dest_files=["res://.godot/imported/netfishing_base_character_mouth_three.png-90b4a98403d2a291a56a8ed42aaa8473.s3tc.ctex", "res://.godot/imported/netfishing_base_character_mouth_three.png-90b4a98403d2a291a56a8ed42aaa8473.etc2.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=0
|
||||||
|
After Width: | Height: | Size: 7 KiB |
|
|
@ -0,0 +1,45 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bmho1ryst3smt"
|
||||||
|
path.s3tc="res://.godot/imported/netfishing_base_character_nose_dog_round.png-0008adff5271dd0403e610ef13dd52cf.s3tc.ctex"
|
||||||
|
path.etc2="res://.godot/imported/netfishing_base_character_nose_dog_round.png-0008adff5271dd0403e610ef13dd52cf.etc2.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc", "etc2_astc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
generator_parameters={
|
||||||
|
"md5": "3134f170152f9fa1512b41b61ecb01fc"
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://art/exported/characters/base/netfishing_base_character_nose_dog_round.png"
|
||||||
|
dest_files=["res://.godot/imported/netfishing_base_character_nose_dog_round.png-0008adff5271dd0403e610ef13dd52cf.s3tc.ctex", "res://.godot/imported/netfishing_base_character_nose_dog_round.png-0008adff5271dd0403e610ef13dd52cf.etc2.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=0
|
||||||
BIN
art/exported/characters/faces/eyes/eyes_simple_shine.png
Normal file
|
After Width: | Height: | Size: 7 KiB |
|
|
@ -0,0 +1,40 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://b345yhfv8w1j5"
|
||||||
|
path="res://.godot/imported/eyes_simple_shine.png-33edcf4bb163d7f2bde9a662105cf788.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"]
|
||||||
|
|
||||||
|
[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
|
||||||
|
After Width: | Height: | Size: 8.1 KiB |
|
|
@ -0,0 +1,40 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://8wg4k4us4baa"
|
||||||
|
path="res://.godot/imported/eyes_simple_shine_eyebrows.png-d2147df0247f280b8f63b23d590204ab.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"]
|
||||||
|
|
||||||
|
[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
|
||||||
BIN
art/exported/characters/faces/mouth/mouth_three.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
40
art/exported/characters/faces/mouth/mouth_three.png.import
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://crrw5vvop2gj7"
|
||||||
|
path="res://.godot/imported/mouth_three.png-b0b3775e32dfd17b6cfcac16b5c64d58.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"]
|
||||||
|
|
||||||
|
[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
|
||||||
BIN
art/exported/characters/faces/noses/nose_dog_round.png
Normal file
|
After Width: | Height: | Size: 7 KiB |
|
|
@ -0,0 +1,40 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bbx0ywjiwymrm"
|
||||||
|
path="res://.godot/imported/nose_dog_round.png-e1d92a8a7b661901752b05898a3f7c8b.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"]
|
||||||
|
|
||||||
|
[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
|
||||||
|
After Width: | Height: | Size: 7 KiB |
|
|
@ -0,0 +1,45 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://du4u6meapay05"
|
||||||
|
path.s3tc="res://.godot/imported/netfishing_character_source_eyes_simple_shine.png-965743f3716320bbc385096956ffef2d.s3tc.ctex"
|
||||||
|
path.etc2="res://.godot/imported/netfishing_character_source_eyes_simple_shine.png-965743f3716320bbc385096956ffef2d.etc2.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc", "etc2_astc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
generator_parameters={
|
||||||
|
"md5": "c2f7c29aaaa95809e140eb308d9bb132"
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://art/source/characters/base/netfishing_character_source_eyes_simple_shine.png"
|
||||||
|
dest_files=["res://.godot/imported/netfishing_character_source_eyes_simple_shine.png-965743f3716320bbc385096956ffef2d.s3tc.ctex", "res://.godot/imported/netfishing_character_source_eyes_simple_shine.png-965743f3716320bbc385096956ffef2d.etc2.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=0
|
||||||
|
After Width: | Height: | Size: 6.1 KiB |
|
|
@ -0,0 +1,45 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://di20c1x8vksi1"
|
||||||
|
path.s3tc="res://.godot/imported/netfishing_character_source_mouth_three.png-6bf79d4c9c660d30fb7fc365f0039313.s3tc.ctex"
|
||||||
|
path.etc2="res://.godot/imported/netfishing_character_source_mouth_three.png-6bf79d4c9c660d30fb7fc365f0039313.etc2.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc", "etc2_astc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
generator_parameters={
|
||||||
|
"md5": "f8bf25a1006c5cc2ab5323f4a758eec7"
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://art/source/characters/base/netfishing_character_source_mouth_three.png"
|
||||||
|
dest_files=["res://.godot/imported/netfishing_character_source_mouth_three.png-6bf79d4c9c660d30fb7fc365f0039313.s3tc.ctex", "res://.godot/imported/netfishing_character_source_mouth_three.png-6bf79d4c9c660d30fb7fc365f0039313.etc2.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=0
|
||||||
|
After Width: | Height: | Size: 7 KiB |
|
|
@ -0,0 +1,45 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://b0p55hwdry2cr"
|
||||||
|
path.s3tc="res://.godot/imported/netfishing_character_source_nose_dog_round.png-1c89150861ebff3f930698c1747a0369.s3tc.ctex"
|
||||||
|
path.etc2="res://.godot/imported/netfishing_character_source_nose_dog_round.png-1c89150861ebff3f930698c1747a0369.etc2.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc", "etc2_astc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
generator_parameters={
|
||||||
|
"md5": "3134f170152f9fa1512b41b61ecb01fc"
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://art/source/characters/base/netfishing_character_source_nose_dog_round.png"
|
||||||
|
dest_files=["res://.godot/imported/netfishing_character_source_nose_dog_round.png-1c89150861ebff3f930698c1747a0369.s3tc.ctex", "res://.godot/imported/netfishing_character_source_nose_dog_round.png-1c89150861ebff3f930698c1747a0369.etc2.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=0
|
||||||
|
|
@ -533,6 +533,8 @@ func _initialize_after_data_root() -> void:
|
||||||
_world_time,
|
_world_time,
|
||||||
_world_weather,
|
_world_weather,
|
||||||
_player_jobs,
|
_player_jobs,
|
||||||
|
_test_world.get_world_environment(),
|
||||||
|
_test_world.get_sun(),
|
||||||
)
|
)
|
||||||
_game_ui.setup_data_and_identity(
|
_game_ui.setup_data_and_identity(
|
||||||
_data_root,
|
_data_root,
|
||||||
|
|
|
||||||
|
|
@ -44,18 +44,18 @@
|
||||||
[ext_resource type="Shader" uid="uid://byw3iub66qvog" path="res://ui/player_menu_pattern.gdshader" id="42_menu_pattern"]
|
[ext_resource type="Shader" uid="uid://byw3iub66qvog" path="res://ui/player_menu_pattern.gdshader" id="42_menu_pattern"]
|
||||||
[ext_resource type="Texture2D" uid="uid://b6xws1d2dnbnn" path="res://art/patterns/pattern_moneyfish.png" id="43_shop_pattern"]
|
[ext_resource type="Texture2D" uid="uid://b6xws1d2dnbnn" path="res://art/patterns/pattern_moneyfish.png" id="43_shop_pattern"]
|
||||||
[ext_resource type="PackedScene" uid="uid://w7n4gjqq1juc" path="res://art/exported/characters/base/netfishing_base_character.glb" id="44_4pcu1"]
|
[ext_resource type="PackedScene" uid="uid://w7n4gjqq1juc" path="res://art/exported/characters/base/netfishing_base_character.glb" id="44_4pcu1"]
|
||||||
[ext_resource type="Script" path="res://network/network_fish_showcase_service.gd" id="45_fish_showcase"]
|
[ext_resource type="Script" uid="uid://m4n0bn38f34i" path="res://network/network_fish_showcase_service.gd" id="45_fish_showcase"]
|
||||||
[ext_resource type="Script" path="res://network/network_surface_drawing_service.gd" id="46_surface_drawing"]
|
[ext_resource type="Script" uid="uid://bkiepgu8j5r6t" path="res://network/network_surface_drawing_service.gd" id="46_surface_drawing"]
|
||||||
[ext_resource type="Script" path="res://world/world_time_service.gd" id="47_world_time"]
|
[ext_resource type="Script" uid="uid://5lceyulaglpf" path="res://world/world_time_service.gd" id="47_world_time"]
|
||||||
[ext_resource type="Script" path="res://world/world_time_visual_controller.gd" id="48_world_time_visuals"]
|
[ext_resource type="Script" uid="uid://svirs8vbypad" path="res://world/world_time_visual_controller.gd" id="48_world_time_visuals"]
|
||||||
[ext_resource type="Script" path="res://network/network_world_time_service.gd" id="49_network_world_time"]
|
[ext_resource type="Script" uid="uid://blig76aes25j" path="res://network/network_world_time_service.gd" id="49_network_world_time"]
|
||||||
[ext_resource type="Script" path="res://world/world_weather_service.gd" id="50_world_weather"]
|
[ext_resource type="Script" uid="uid://v4c54isq6w74" path="res://world/world_weather_service.gd" id="50_world_weather"]
|
||||||
[ext_resource type="Script" path="res://network/network_world_weather_service.gd" id="51_network_world_weather"]
|
[ext_resource type="Script" uid="uid://llj46fx0oco7" path="res://network/network_world_weather_service.gd" id="51_network_world_weather"]
|
||||||
[ext_resource type="Script" path="res://jobs/player_job_service.gd" id="52_player_jobs"]
|
[ext_resource type="Script" uid="uid://daqtje84gqgu0" path="res://jobs/player_job_service.gd" id="52_player_jobs"]
|
||||||
[ext_resource type="Script" path="res://network/network_job_service.gd" id="53_network_jobs"]
|
[ext_resource type="Script" uid="uid://drlyytr2o3uw8" path="res://network/network_job_service.gd" id="53_network_jobs"]
|
||||||
[ext_resource type="Script" path="res://world/shoreline_ambience.gd" id="54_shoreline_ambience"]
|
[ext_resource type="Script" uid="uid://b0c3o2vy76fg3" path="res://world/shoreline_ambience.gd" id="54_shoreline_ambience"]
|
||||||
[ext_resource type="AudioStream" path="res://audio/ambience/waves.wav" id="55_waves"]
|
[ext_resource type="AudioStream" uid="uid://dck3tf8qkadea" path="res://audio/ambience/waves.wav" id="55_waves"]
|
||||||
[ext_resource type="Script" path="res://settings/controller_mapping_manager.gd" id="56_controller_mapping"]
|
[ext_resource type="Script" uid="uid://c80x8jkdnx0xy" path="res://settings/controller_mapping_manager.gd" id="56_controller_mapping"]
|
||||||
|
|
||||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_title_water_native"]
|
[sub_resource type="ShaderMaterial" id="ShaderMaterial_title_water_native"]
|
||||||
shader = ExtResource("40_title_water")
|
shader = ExtResource("40_title_water")
|
||||||
|
|
@ -123,31 +123,31 @@ mouse_filter = 2
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
script = ExtResource("39_fonts")
|
script = ExtResource("39_fonts")
|
||||||
|
|
||||||
[node name="WorldTimeService" type="Node" parent="."]
|
[node name="WorldTimeService" type="Node" parent="." unique_id=1774610576]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
script = ExtResource("47_world_time")
|
script = ExtResource("47_world_time")
|
||||||
|
|
||||||
[node name="WorldTimeVisualController" type="Node" parent="."]
|
[node name="WorldTimeVisualController" type="Node" parent="." unique_id=1861087008]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
script = ExtResource("48_world_time_visuals")
|
script = ExtResource("48_world_time_visuals")
|
||||||
|
|
||||||
[node name="NetworkWorldTimeService" type="Node" parent="."]
|
[node name="NetworkWorldTimeService" type="Node" parent="." unique_id=1136962511]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
script = ExtResource("49_network_world_time")
|
script = ExtResource("49_network_world_time")
|
||||||
|
|
||||||
[node name="WorldWeatherService" type="Node" parent="."]
|
[node name="WorldWeatherService" type="Node" parent="." unique_id=1812156280]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
script = ExtResource("50_world_weather")
|
script = ExtResource("50_world_weather")
|
||||||
|
|
||||||
[node name="NetworkWorldWeatherService" type="Node" parent="."]
|
[node name="NetworkWorldWeatherService" type="Node" parent="." unique_id=266238117]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
script = ExtResource("51_network_world_weather")
|
script = ExtResource("51_network_world_weather")
|
||||||
|
|
||||||
[node name="PlayerJobService" type="Node" parent="."]
|
[node name="PlayerJobService" type="Node" parent="." unique_id=2062127535]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
script = ExtResource("52_player_jobs")
|
script = ExtResource("52_player_jobs")
|
||||||
|
|
||||||
[node name="NetworkJobService" type="Node" parent="."]
|
[node name="NetworkJobService" type="Node" parent="." unique_id=556458360]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
script = ExtResource("53_network_jobs")
|
script = ExtResource("53_network_jobs")
|
||||||
|
|
||||||
|
|
@ -223,11 +223,11 @@ script = ExtResource("23_network_shop")
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
script = ExtResource("24_network_item")
|
script = ExtResource("24_network_item")
|
||||||
|
|
||||||
[node name="NetworkFishShowcaseService" type="Node" parent="."]
|
[node name="NetworkFishShowcaseService" type="Node" parent="." unique_id=148288598]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
script = ExtResource("45_fish_showcase")
|
script = ExtResource("45_fish_showcase")
|
||||||
|
|
||||||
[node name="NetworkSurfaceDrawingService" type="Node" parent="."]
|
[node name="NetworkSurfaceDrawingService" type="Node" parent="." unique_id=80122665]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
script = ExtResource("46_surface_drawing")
|
script = ExtResource("46_surface_drawing")
|
||||||
|
|
||||||
|
|
@ -252,11 +252,11 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0024132729, 0, -0.00093126
|
||||||
|
|
||||||
[node name="Players" type="Node3D" parent="." unique_id=550630144]
|
[node name="Players" type="Node3D" parent="." unique_id=550630144]
|
||||||
|
|
||||||
[node name="SurfaceDrawings" type="Node3D" parent="."]
|
|
||||||
|
|
||||||
[node name="Player" parent="Players" unique_id=485429332 instance=ExtResource("2_player")]
|
[node name="Player" parent="Players" unique_id=485429332 instance=ExtResource("2_player")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 16)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3.3999481, 12.07081)
|
||||||
|
|
||||||
|
[node name="SurfaceDrawings" type="Node3D" parent="." unique_id=234671307]
|
||||||
|
|
||||||
[node name="FishingSpot" parent="." unique_id=1461328864 instance=ExtResource("4_spot")]
|
[node name="FishingSpot" parent="." unique_id=1461328864 instance=ExtResource("4_spot")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
|
@ -274,7 +274,7 @@ script = ExtResource("9_save")
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
script = ExtResource("10_settings")
|
script = ExtResource("10_settings")
|
||||||
|
|
||||||
[node name="ControllerMappingManager" type="Node" parent="."]
|
[node name="ControllerMappingManager" type="Node" parent="." unique_id=1198390067]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
script = ExtResource("56_controller_mapping")
|
script = ExtResource("56_controller_mapping")
|
||||||
|
|
||||||
|
|
@ -284,11 +284,11 @@ stream = ExtResource("13_title_music")
|
||||||
volume_db = -80.0
|
volume_db = -80.0
|
||||||
bus = &"Music"
|
bus = &"Music"
|
||||||
|
|
||||||
[node name="ShorelineAmbience" type="Node" parent="."]
|
[node name="ShorelineAmbience" type="Node" parent="." unique_id=1948037177]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
script = ExtResource("54_shoreline_ambience")
|
script = ExtResource("54_shoreline_ambience")
|
||||||
|
|
||||||
[node name="WavesAudio" type="AudioStreamPlayer" parent="ShorelineAmbience"]
|
[node name="WavesAudio" type="AudioStreamPlayer" parent="ShorelineAmbience" unique_id=193530658]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
stream = ExtResource("55_waves")
|
stream = ExtResource("55_waves")
|
||||||
bus = &"SFX"
|
bus = &"SFX"
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ roughness = 0.8
|
||||||
bone_name = "hand.R"
|
bone_name = "hand.R"
|
||||||
|
|
||||||
[node name="FishingRod" type="Node3D" parent="."]
|
[node name="FishingRod" type="Node3D" parent="."]
|
||||||
rotation = Vector3(-0.785398, -0.007863, 3.141593)
|
rotation_degrees = Vector3(322.6, -31.2, 248.9)
|
||||||
|
|
||||||
[node name="RodMesh" type="MeshInstance3D" parent="FishingRod"]
|
[node name="RodMesh" type="MeshInstance3D" parent="FishingRod"]
|
||||||
position = Vector3(0, 0.42, 0)
|
position = Vector3(0, 0.42, 0)
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,7 @@ var _controller_mapping_manager: ControllerMappingManagerType
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
PlayerVisualPresenter.apply_appearance(_visuals, appearance_snapshot)
|
||||||
_initialize_fishing_rod()
|
_initialize_fishing_rod()
|
||||||
_target_zoom = clampf(_spring_arm.spring_length, minimum_zoom, maximum_zoom)
|
_target_zoom = clampf(_spring_arm.spring_length, minimum_zoom, maximum_zoom)
|
||||||
_spring_arm.spring_length = _target_zoom
|
_spring_arm.spring_length = _target_zoom
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,25 @@ class_name PlayerVisualPresenter
|
||||||
extends RefCounted
|
extends RefCounted
|
||||||
|
|
||||||
const PlayerScene: PackedScene = preload("res://player/player.tscn")
|
const PlayerScene: PackedScene = preload("res://player/player.tscn")
|
||||||
|
const EYE_TEXTURES: Dictionary = {
|
||||||
|
"simple_shine": preload(
|
||||||
|
"res://art/exported/characters/faces/eyes/eyes_simple_shine.png"
|
||||||
|
),
|
||||||
|
"simple_shine_eyebrows": preload(
|
||||||
|
"res://art/exported/characters/faces/eyes/eyes_simple_shine_eyebrows.png"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
const MOUTH_TEXTURES: Dictionary = {
|
||||||
|
"three": preload(
|
||||||
|
"res://art/exported/characters/faces/mouth/mouth_three.png"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
const NOSE_TEXTURES: Dictionary = {
|
||||||
|
"dog_round": preload(
|
||||||
|
"res://art/exported/characters/faces/noses/nose_dog_round.png"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
const RUNTIME_MATERIAL_META: StringName = &"netfishing_runtime_material"
|
||||||
|
|
||||||
|
|
||||||
static func instantiate_visuals() -> Node3D:
|
static func instantiate_visuals() -> Node3D:
|
||||||
|
|
@ -32,10 +51,115 @@ static func instantiate_visuals() -> Node3D:
|
||||||
|
|
||||||
|
|
||||||
static func apply_appearance(
|
static func apply_appearance(
|
||||||
_visuals: Node3D,
|
visuals: Node3D,
|
||||||
snapshot: Dictionary,
|
snapshot: Dictionary,
|
||||||
) -> void:
|
) -> void:
|
||||||
# Gameplay and preview deliberately share this presentation seam. Modular
|
|
||||||
# visual parts can be applied here without coupling Profile to Player.
|
|
||||||
if not CharacterCustomizationCatalog.validate_snapshot(snapshot):
|
if not CharacterCustomizationCatalog.validate_snapshot(snapshot):
|
||||||
return
|
return
|
||||||
|
# Gameplay and preview deliberately share this presentation seam. Keep all
|
||||||
|
# mesh selection here so profile previews and network avatars stay identical.
|
||||||
|
var skeleton: Skeleton3D = visuals.find_child("Skeleton3D", true, false) as Skeleton3D
|
||||||
|
if skeleton == null:
|
||||||
|
return
|
||||||
|
|
||||||
|
var species_id: String = CharacterCustomizationCatalog.canonical_option_id(
|
||||||
|
"species", str(snapshot.get("species", "round"))
|
||||||
|
)
|
||||||
|
var head_id: String = "head_pointy" if species_id == "pointy" else "head_round"
|
||||||
|
var head_ids: Array[String] = ["head_pointy", "head_round"]
|
||||||
|
for head_name: String in head_ids:
|
||||||
|
var head: Node3D = skeleton.get_node_or_null(head_name) as Node3D
|
||||||
|
if head != null:
|
||||||
|
head.visible = head_name == head_id
|
||||||
|
for feature: String in ["eyes", "mouth", "nose"]:
|
||||||
|
var decal: Node3D = skeleton.get_node_or_null(
|
||||||
|
"%s_%s" % [head_name, feature]
|
||||||
|
) as Node3D
|
||||||
|
if decal != null:
|
||||||
|
decal.visible = head_name == head_id
|
||||||
|
|
||||||
|
var selected_ears: String = CharacterCustomizationCatalog.canonical_option_id(
|
||||||
|
"ears", str(snapshot.get("ears", "none"))
|
||||||
|
)
|
||||||
|
var ear_names: Array[String] = [
|
||||||
|
"ears_pointy_long",
|
||||||
|
"ears_pointy_short",
|
||||||
|
"ears_pointy_wide",
|
||||||
|
]
|
||||||
|
for ear_name: String in ear_names:
|
||||||
|
var ears: Node3D = skeleton.get_node_or_null(ear_name) as Node3D
|
||||||
|
if ears != null:
|
||||||
|
ears.visible = selected_ears == ear_name.trim_prefix("ears_")
|
||||||
|
|
||||||
|
var fur_color: Color = CharacterCustomizationCatalog.option_color(
|
||||||
|
"fur_pattern", str(snapshot.get("fur_pattern", "white"))
|
||||||
|
)
|
||||||
|
_set_mesh_color(skeleton, "body_arms", fur_color)
|
||||||
|
_set_mesh_color(skeleton, "body_main", fur_color)
|
||||||
|
_set_mesh_color(skeleton, "head_pointy", fur_color)
|
||||||
|
_set_mesh_color(skeleton, "head_round", fur_color)
|
||||||
|
for ear_name: String in ear_names:
|
||||||
|
_set_mesh_color(skeleton, ear_name, fur_color)
|
||||||
|
|
||||||
|
var eye_id: String = CharacterCustomizationCatalog.canonical_option_id(
|
||||||
|
"eyes", str(snapshot.get("eyes", "simple_shine"))
|
||||||
|
)
|
||||||
|
var mouth_id: String = CharacterCustomizationCatalog.canonical_option_id(
|
||||||
|
"mouth", str(snapshot.get("mouth", "three"))
|
||||||
|
)
|
||||||
|
var nose_id: String = CharacterCustomizationCatalog.canonical_option_id(
|
||||||
|
"nose", str(snapshot.get("nose", "dog_round"))
|
||||||
|
)
|
||||||
|
_set_feature_texture(skeleton, "eyes", EYE_TEXTURES.get(eye_id) as Texture2D)
|
||||||
|
_set_feature_texture(
|
||||||
|
skeleton, "mouth", MOUTH_TEXTURES.get(mouth_id) as Texture2D
|
||||||
|
)
|
||||||
|
_set_feature_texture(skeleton, "nose", NOSE_TEXTURES.get(nose_id) as Texture2D)
|
||||||
|
|
||||||
|
|
||||||
|
static func _set_feature_texture(
|
||||||
|
skeleton: Skeleton3D,
|
||||||
|
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
|
||||||
|
var material: StandardMaterial3D = _runtime_material(mesh_instance)
|
||||||
|
if material != null:
|
||||||
|
material.albedo_color = Color.WHITE
|
||||||
|
material.albedo_texture = texture
|
||||||
|
|
||||||
|
|
||||||
|
static func _set_mesh_color(
|
||||||
|
skeleton: Skeleton3D,
|
||||||
|
mesh_name: String,
|
||||||
|
color: Color,
|
||||||
|
) -> void:
|
||||||
|
var mesh_instance: MeshInstance3D = skeleton.get_node_or_null(
|
||||||
|
mesh_name
|
||||||
|
) as MeshInstance3D
|
||||||
|
var material: StandardMaterial3D = _runtime_material(mesh_instance)
|
||||||
|
if material != null:
|
||||||
|
material.albedo_color = color
|
||||||
|
|
||||||
|
|
||||||
|
static func _runtime_material(
|
||||||
|
mesh_instance: MeshInstance3D,
|
||||||
|
) -> StandardMaterial3D:
|
||||||
|
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 source: StandardMaterial3D = mesh_instance.mesh.surface_get_material(
|
||||||
|
0
|
||||||
|
) as StandardMaterial3D
|
||||||
|
if source == null:
|
||||||
|
return null
|
||||||
|
var material: StandardMaterial3D = source.duplicate() as StandardMaterial3D
|
||||||
|
mesh_instance.material_override = material
|
||||||
|
mesh_instance.set_meta(RUNTIME_MATERIAL_META, true)
|
||||||
|
return material
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ const CATEGORY_IDS: PackedStringArray = [
|
||||||
]
|
]
|
||||||
|
|
||||||
const CATEGORY_LABELS: Dictionary = {
|
const CATEGORY_LABELS: Dictionary = {
|
||||||
"species": "species",
|
"species": "head",
|
||||||
"fur_pattern": "fur pattern",
|
"fur_pattern": "fur color",
|
||||||
"ears": "ears",
|
"ears": "ears",
|
||||||
"eyes": "eyes",
|
"eyes": "eyes",
|
||||||
"nose": "nose",
|
"nose": "nose",
|
||||||
|
|
@ -22,24 +22,59 @@ const CATEGORY_LABELS: Dictionary = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const OPTIONS: Dictionary = {
|
const OPTIONS: Dictionary = {
|
||||||
"species": [{"id": "default", "label": "default"}],
|
"species": [
|
||||||
"fur_pattern": [{"id": "solid", "label": "solid"}],
|
{"id": "round", "label": "round"},
|
||||||
"ears": [{"id": "default", "label": "default"}],
|
{"id": "pointy", "label": "pointy"},
|
||||||
"eyes": [{"id": "default", "label": "default"}],
|
],
|
||||||
"nose": [{"id": "default", "label": "default"}],
|
# The serialized field remains `fur_pattern` for save and network
|
||||||
"mouth": [{"id": "default", "label": "default"}],
|
# compatibility. It holds the initial solid fur-color selection until the
|
||||||
|
# authored pattern layer is ready.
|
||||||
|
"fur_pattern": [
|
||||||
|
{"id": "white", "label": "white", "color": Color("f2f0e8")},
|
||||||
|
{"id": "gray", "label": "gray", "color": Color("819398")},
|
||||||
|
{"id": "charcoal", "label": "charcoal", "color": Color("34444a")},
|
||||||
|
{"id": "brown", "label": "brown", "color": Color("7b4a32")},
|
||||||
|
{"id": "orange", "label": "orange", "color": Color("c86c36")},
|
||||||
|
{"id": "yellow", "label": "yellow", "color": Color("d8c545")},
|
||||||
|
{"id": "green", "label": "green", "color": Color("6f913c")},
|
||||||
|
{"id": "teal", "label": "teal", "color": Color("3a8790")},
|
||||||
|
],
|
||||||
|
"ears": [
|
||||||
|
{"id": "none", "label": "none"},
|
||||||
|
{"id": "pointy_long", "label": "long"},
|
||||||
|
{"id": "pointy_short", "label": "short"},
|
||||||
|
{"id": "pointy_wide", "label": "wide"},
|
||||||
|
],
|
||||||
|
"eyes": [
|
||||||
|
{"id": "simple_shine", "label": "simple shine"},
|
||||||
|
{
|
||||||
|
"id": "simple_shine_eyebrows",
|
||||||
|
"label": "simple shine + eyebrows",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"nose": [{"id": "dog_round", "label": "round"}],
|
||||||
|
"mouth": [{"id": "three", "label": "three"}],
|
||||||
"tail": [{"id": "none", "label": "none"}],
|
"tail": [{"id": "none", "label": "none"}],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const LEGACY_OPTION_ALIASES: Dictionary = {
|
||||||
|
"species": {"default": "round"},
|
||||||
|
"fur_pattern": {"solid": "white"},
|
||||||
|
"ears": {"default": "none"},
|
||||||
|
"eyes": {"default": "simple_shine"},
|
||||||
|
"nose": {"default": "dog_round"},
|
||||||
|
"mouth": {"default": "three"},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static func default_snapshot() -> Dictionary:
|
static func default_snapshot() -> Dictionary:
|
||||||
return {
|
return {
|
||||||
"species": "default",
|
"species": "round",
|
||||||
"fur_pattern": "solid",
|
"fur_pattern": "white",
|
||||||
"ears": "default",
|
"ears": "none",
|
||||||
"eyes": "default",
|
"eyes": "simple_shine",
|
||||||
"nose": "default",
|
"nose": "dog_round",
|
||||||
"mouth": "default",
|
"mouth": "three",
|
||||||
"tail": "none",
|
"tail": "none",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,12 +88,26 @@ static func category_label(category_id: String) -> String:
|
||||||
|
|
||||||
|
|
||||||
static func is_valid_option(category_id: String, option_id: String) -> bool:
|
static func is_valid_option(category_id: String, option_id: String) -> bool:
|
||||||
|
option_id = canonical_option_id(category_id, option_id)
|
||||||
for option: Dictionary in options_for(category_id):
|
for option: Dictionary in options_for(category_id):
|
||||||
if str(option.get("id", "")) == option_id:
|
if str(option.get("id", "")) == option_id:
|
||||||
return true
|
return true
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
static func canonical_option_id(category_id: String, option_id: String) -> String:
|
||||||
|
var aliases: Dictionary = LEGACY_OPTION_ALIASES.get(category_id, {})
|
||||||
|
return str(aliases.get(option_id, option_id))
|
||||||
|
|
||||||
|
|
||||||
|
static func option_color(category_id: String, option_id: String) -> Color:
|
||||||
|
var canonical_id: String = canonical_option_id(category_id, option_id)
|
||||||
|
for option: Dictionary in options_for(category_id):
|
||||||
|
if str(option.get("id", "")) == canonical_id:
|
||||||
|
return option.get("color", Color.WHITE) as Color
|
||||||
|
return Color.WHITE
|
||||||
|
|
||||||
|
|
||||||
static func validate_snapshot(value: Variant) -> bool:
|
static func validate_snapshot(value: Variant) -> bool:
|
||||||
if typeof(value) != TYPE_DICTIONARY:
|
if typeof(value) != TYPE_DICTIONARY:
|
||||||
return false
|
return false
|
||||||
|
|
@ -80,7 +129,9 @@ static func sanitized_snapshot(value: Variant) -> Dictionary:
|
||||||
return result
|
return result
|
||||||
var snapshot: Dictionary = value
|
var snapshot: Dictionary = value
|
||||||
for category_id: String in CATEGORY_IDS:
|
for category_id: String in CATEGORY_IDS:
|
||||||
var option_id := str(snapshot.get(category_id, ""))
|
var option_id: String = canonical_option_id(
|
||||||
|
category_id, str(snapshot.get(category_id, ""))
|
||||||
|
)
|
||||||
if is_valid_option(category_id, option_id):
|
if is_valid_option(category_id, option_id):
|
||||||
result[category_id] = option_id
|
result[category_id] = option_id
|
||||||
return result
|
return result
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,8 @@ func setup(
|
||||||
world_time: WorldTimeServiceType,
|
world_time: WorldTimeServiceType,
|
||||||
world_weather: WorldWeatherServiceType,
|
world_weather: WorldWeatherServiceType,
|
||||||
player_jobs: PlayerJobService,
|
player_jobs: PlayerJobService,
|
||||||
|
world_environment: WorldEnvironment,
|
||||||
|
world_sun: DirectionalLight3D,
|
||||||
) -> void:
|
) -> void:
|
||||||
_player = player
|
_player = player
|
||||||
_fishing_spot = fishing_spot
|
_fishing_spot = fishing_spot
|
||||||
|
|
@ -285,6 +287,8 @@ func setup(
|
||||||
network_player_list,
|
network_player_list,
|
||||||
player_jobs,
|
player_jobs,
|
||||||
world_time,
|
world_time,
|
||||||
|
world_environment,
|
||||||
|
world_sun,
|
||||||
)
|
)
|
||||||
_hotbar_ui.setup(hotbar, bag, item_catalog, fishing_spot, inventory)
|
_hotbar_ui.setup(hotbar, bag, item_catalog, fishing_spot, inventory)
|
||||||
_fishing_shop.setup(
|
_fishing_shop.setup(
|
||||||
|
|
|
||||||
|
|
@ -508,6 +508,8 @@ func setup(
|
||||||
network_player_list: NetworkPlayerListService,
|
network_player_list: NetworkPlayerListService,
|
||||||
player_jobs: PlayerJobService,
|
player_jobs: PlayerJobService,
|
||||||
world_time: WorldTimeService,
|
world_time: WorldTimeService,
|
||||||
|
world_environment: WorldEnvironment,
|
||||||
|
world_sun: DirectionalLight3D,
|
||||||
) -> void:
|
) -> void:
|
||||||
_player = player
|
_player = player
|
||||||
_inventory = inventory
|
_inventory = inventory
|
||||||
|
|
@ -530,7 +532,12 @@ func setup(
|
||||||
_mail_page.setup(
|
_mail_page.setup(
|
||||||
network_mail_service, reservations, inventory, wallet, bag, item_catalog
|
network_mail_service, reservations, inventory, wallet, bag, item_catalog
|
||||||
)
|
)
|
||||||
_profile_page.setup(network_profile_service, experience)
|
_profile_page.setup(
|
||||||
|
network_profile_service,
|
||||||
|
experience,
|
||||||
|
world_environment,
|
||||||
|
world_sun,
|
||||||
|
)
|
||||||
_players_page.setup(network_player_list)
|
_players_page.setup(network_player_list)
|
||||||
_catalog_logbook.setup(collection_log, inventory, catalog)
|
_catalog_logbook.setup(collection_log, inventory, catalog)
|
||||||
_the_net_page.setup(player_jobs, world_time)
|
_the_net_page.setup(player_jobs, world_time)
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ var _revert_button: Button
|
||||||
var _discard_confirmation: PanelContainer
|
var _discard_confirmation: PanelContainer
|
||||||
var _confirmation_label: Label
|
var _confirmation_label: Label
|
||||||
var _confirmation_confirm: Button
|
var _confirmation_confirm: Button
|
||||||
|
var _keep_editing_button: Button
|
||||||
var _confirmation_action: String = ""
|
var _confirmation_action: String = ""
|
||||||
var _debounce: Timer
|
var _debounce: Timer
|
||||||
var _experience_level: Label
|
var _experience_level: Label
|
||||||
|
|
@ -47,6 +48,8 @@ func _ready() -> void:
|
||||||
func setup(
|
func setup(
|
||||||
service: NetworkProfileService,
|
service: NetworkProfileService,
|
||||||
experience: PlayerExperience,
|
experience: PlayerExperience,
|
||||||
|
world_environment: WorldEnvironment,
|
||||||
|
world_sun: DirectionalLight3D,
|
||||||
) -> void:
|
) -> void:
|
||||||
_service = service
|
_service = service
|
||||||
_experience = experience
|
_experience = experience
|
||||||
|
|
@ -62,6 +65,7 @@ func setup(
|
||||||
_experience.experience_changed.connect(_on_experience_changed)
|
_experience.experience_changed.connect(_on_experience_changed)
|
||||||
_load_persisted()
|
_load_persisted()
|
||||||
_refresh_experience()
|
_refresh_experience()
|
||||||
|
_preview.setup_world_lighting(world_environment, world_sun)
|
||||||
var identity_value := find_child("IdentityFingerprint", true, false) as Label
|
var identity_value := find_child("IdentityFingerprint", true, false) as Label
|
||||||
if identity_value != null:
|
if identity_value != null:
|
||||||
var fingerprint := _service.get_identity_fingerprint()
|
var fingerprint := _service.get_identity_fingerprint()
|
||||||
|
|
@ -344,16 +348,14 @@ func _build_ui() -> void:
|
||||||
_confirmation_confirm.pressed.connect(_confirm_pending_action)
|
_confirmation_confirm.pressed.connect(_confirm_pending_action)
|
||||||
UtilityPageStyle.apply_ocean_button(_confirmation_confirm)
|
UtilityPageStyle.apply_ocean_button(_confirmation_confirm)
|
||||||
confirm_buttons.add_child(_confirmation_confirm)
|
confirm_buttons.add_child(_confirmation_confirm)
|
||||||
var keep := Button.new()
|
_keep_editing_button = Button.new()
|
||||||
keep.name = "KeepEditing"
|
_keep_editing_button.text = "keep editing"
|
||||||
keep.unique_name_in_owner = true
|
_keep_editing_button.pressed.connect(func() -> void:
|
||||||
keep.text = "keep editing"
|
|
||||||
keep.pressed.connect(func() -> void:
|
|
||||||
_discard_confirmation.visible = false
|
_discard_confirmation.visible = false
|
||||||
_name_edit.grab_focus()
|
_name_edit.grab_focus()
|
||||||
)
|
)
|
||||||
UtilityPageStyle.apply_ocean_button(keep)
|
UtilityPageStyle.apply_ocean_button(_keep_editing_button)
|
||||||
confirm_buttons.add_child(keep)
|
confirm_buttons.add_child(_keep_editing_button)
|
||||||
|
|
||||||
_build_categories()
|
_build_categories()
|
||||||
|
|
||||||
|
|
@ -394,13 +396,16 @@ func _refresh_options() -> void:
|
||||||
"font_color", UtilityPageStyle.OCEAN_TEXT_PRIMARY
|
"font_color", UtilityPageStyle.OCEAN_TEXT_PRIMARY
|
||||||
)
|
)
|
||||||
_option_list.add_child(title)
|
_option_list.add_child(title)
|
||||||
var options := CharacterCustomizationCatalog.options_for(_category_id)
|
var options: Array = CharacterCustomizationCatalog.options_for(_category_id)
|
||||||
if options.is_empty():
|
if options.is_empty():
|
||||||
var empty := Label.new()
|
var empty := Label.new()
|
||||||
empty.text = "More options coming later."
|
empty.text = "More options coming later."
|
||||||
empty.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
empty.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||||
_option_list.add_child(empty)
|
_option_list.add_child(empty)
|
||||||
return
|
return
|
||||||
|
if _category_id == "fur_pattern":
|
||||||
|
_build_fur_color_options(options)
|
||||||
|
return
|
||||||
for option: Dictionary in options:
|
for option: Dictionary in options:
|
||||||
var option_id := str(option["id"])
|
var option_id := str(option["id"])
|
||||||
var button := Button.new()
|
var button := Button.new()
|
||||||
|
|
@ -413,6 +418,49 @@ func _refresh_options() -> void:
|
||||||
_option_list.add_child(button)
|
_option_list.add_child(button)
|
||||||
|
|
||||||
|
|
||||||
|
func _build_fur_color_options(options: Array) -> void:
|
||||||
|
var grid := GridContainer.new()
|
||||||
|
grid.columns = 4
|
||||||
|
grid.add_theme_constant_override("h_separation", 10)
|
||||||
|
grid.add_theme_constant_override("v_separation", 10)
|
||||||
|
_option_list.add_child(grid)
|
||||||
|
var selected_id: String = CharacterCustomizationCatalog.canonical_option_id(
|
||||||
|
"fur_pattern", str(_draft_appearance.get("fur_pattern", "white"))
|
||||||
|
)
|
||||||
|
for option: Dictionary in options:
|
||||||
|
var option_id: String = str(option.get("id", ""))
|
||||||
|
var color: Color = CharacterCustomizationCatalog.option_color(
|
||||||
|
"fur_pattern", option_id
|
||||||
|
)
|
||||||
|
var button := Button.new()
|
||||||
|
button.text = ""
|
||||||
|
button.tooltip_text = str(option.get("label", option_id))
|
||||||
|
button.toggle_mode = true
|
||||||
|
button.custom_minimum_size = Vector2(44.0, 44.0)
|
||||||
|
button.button_pressed = selected_id == option_id
|
||||||
|
button.pressed.connect(_select_option.bind("fur_pattern", option_id))
|
||||||
|
_apply_fur_swatch_style(button, color, button.button_pressed)
|
||||||
|
grid.add_child(button)
|
||||||
|
|
||||||
|
|
||||||
|
func _apply_fur_swatch_style(
|
||||||
|
button: Button,
|
||||||
|
color: Color,
|
||||||
|
selected: bool,
|
||||||
|
) -> void:
|
||||||
|
var normal: StyleBoxFlat = UtilityPageStyle.rounded_style(color, 999)
|
||||||
|
var hover: StyleBoxFlat = UtilityPageStyle.rounded_style(
|
||||||
|
color.lightened(0.12), 999
|
||||||
|
)
|
||||||
|
var selected_style: StyleBoxFlat = UtilityPageStyle.rounded_style(color, 999)
|
||||||
|
selected_style.border_color = UtilityPageStyle.OCEAN_TEXT_PRIMARY
|
||||||
|
selected_style.set_border_width_all(3 if selected else 2)
|
||||||
|
button.add_theme_stylebox_override("normal", normal)
|
||||||
|
button.add_theme_stylebox_override("hover", hover)
|
||||||
|
button.add_theme_stylebox_override("pressed", selected_style)
|
||||||
|
button.add_theme_stylebox_override("focus", selected_style)
|
||||||
|
|
||||||
|
|
||||||
func _select_option(category_id: String, option_id: String) -> void:
|
func _select_option(category_id: String, option_id: String) -> void:
|
||||||
_draft_appearance[category_id] = option_id
|
_draft_appearance[category_id] = option_id
|
||||||
_preview.apply_appearance_profile(_draft_appearance)
|
_preview.apply_appearance_profile(_draft_appearance)
|
||||||
|
|
@ -546,7 +594,7 @@ func _show_confirmation(action: String) -> void:
|
||||||
else:
|
else:
|
||||||
_confirmation_label.text = "Discard unsaved profile changes?"
|
_confirmation_label.text = "Discard unsaved profile changes?"
|
||||||
_confirmation_confirm.text = "discard changes"
|
_confirmation_confirm.text = "discard changes"
|
||||||
_discard_confirmation.get_node("%KeepEditing").grab_focus()
|
_keep_editing_button.grab_focus()
|
||||||
|
|
||||||
|
|
||||||
func _confirm_pending_action() -> void:
|
func _confirm_pending_action() -> void:
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,20 @@ extends SubViewportContainer
|
||||||
const ControllerMappingManagerType = preload(
|
const ControllerMappingManagerType = preload(
|
||||||
"res://settings/controller_mapping_manager.gd"
|
"res://settings/controller_mapping_manager.gd"
|
||||||
)
|
)
|
||||||
|
const FRONT_FACING_YAW: float = PI
|
||||||
|
|
||||||
@export_range(0.1, 2.0, 0.05) var drag_sensitivity: float = 0.012
|
@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
|
@export_range(0.1, 4.0, 0.1) var keyboard_speed: float = 1.8
|
||||||
|
|
||||||
@onready var _preview_root: Node3D = %PreviewRoot
|
@onready var _preview_root: Node3D = %PreviewRoot
|
||||||
|
@onready var _preview_environment: WorldEnvironment = %WorldEnvironment
|
||||||
|
@onready var _preview_sun: DirectionalLight3D = %KeyLight
|
||||||
|
|
||||||
var _dragging: bool = false
|
var _dragging: bool = false
|
||||||
var _visuals: Node3D
|
var _visuals: Node3D
|
||||||
var _controller_mapping_manager: ControllerMappingManagerType
|
var _controller_mapping_manager: ControllerMappingManagerType
|
||||||
|
var _source_environment: WorldEnvironment
|
||||||
|
var _source_sun: DirectionalLight3D
|
||||||
|
|
||||||
|
|
||||||
func setup_controller_mapping(
|
func setup_controller_mapping(
|
||||||
|
|
@ -21,9 +26,19 @@ func setup_controller_mapping(
|
||||||
_controller_mapping_manager = mapping_manager
|
_controller_mapping_manager = mapping_manager
|
||||||
|
|
||||||
|
|
||||||
|
func setup_world_lighting(
|
||||||
|
world_environment: WorldEnvironment,
|
||||||
|
world_sun: DirectionalLight3D,
|
||||||
|
) -> void:
|
||||||
|
_source_environment = world_environment
|
||||||
|
_source_sun = world_sun
|
||||||
|
_sync_world_lighting()
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
focus_mode = Control.FOCUS_ALL
|
focus_mode = Control.FOCUS_ALL
|
||||||
gui_input.connect(_on_gui_input)
|
gui_input.connect(_on_gui_input)
|
||||||
|
reset_view()
|
||||||
_visuals = PlayerVisualPresenter.instantiate_visuals()
|
_visuals = PlayerVisualPresenter.instantiate_visuals()
|
||||||
_preview_root.add_child(_visuals)
|
_preview_root.add_child(_visuals)
|
||||||
var rod := _visuals.find_child("FishingRod", true, false) as Node3D
|
var rod := _visuals.find_child("FishingRod", true, false) as Node3D
|
||||||
|
|
@ -40,10 +55,11 @@ func apply_appearance_profile(profile: Dictionary) -> void:
|
||||||
|
|
||||||
|
|
||||||
func reset_view() -> void:
|
func reset_view() -> void:
|
||||||
_preview_root.rotation.y = 0.0
|
_preview_root.rotation.y = FRONT_FACING_YAW
|
||||||
|
|
||||||
|
|
||||||
func _process(delta: float) -> void:
|
func _process(delta: float) -> void:
|
||||||
|
_sync_world_lighting()
|
||||||
if not has_focus():
|
if not has_focus():
|
||||||
return
|
return
|
||||||
var axis := Input.get_axis("ui_left", "ui_right")
|
var axis := Input.get_axis("ui_left", "ui_right")
|
||||||
|
|
@ -78,3 +94,19 @@ func _notification(what: int) -> void:
|
||||||
|
|
||||||
func _rotate(amount: float) -> void:
|
func _rotate(amount: float) -> void:
|
||||||
_preview_root.rotation.y = fposmod(_preview_root.rotation.y + amount, TAU)
|
_preview_root.rotation.y = fposmod(_preview_root.rotation.y + amount, TAU)
|
||||||
|
|
||||||
|
|
||||||
|
func _sync_world_lighting() -> void:
|
||||||
|
if (
|
||||||
|
_preview_environment == null
|
||||||
|
or _preview_sun == null
|
||||||
|
or _source_environment == null
|
||||||
|
or _source_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
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,8 @@
|
||||||
[gd_scene load_steps=4 format=3]
|
[gd_scene load_steps=3 format=3]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://ui/profile_preview.gd" id="1"]
|
[ext_resource type="Script" path="res://ui/profile_preview.gd" id="1"]
|
||||||
|
|
||||||
[sub_resource type="Environment" id="Environment"]
|
|
||||||
background_mode = 1
|
|
||||||
background_color = Color(0.075, 0.13, 0.16, 1)
|
|
||||||
ambient_light_source = 3
|
|
||||||
ambient_light_color = Color(0.72, 0.82, 0.86, 1)
|
|
||||||
ambient_light_energy = 0.65
|
|
||||||
|
|
||||||
[sub_resource type="World3D" id="PreviewWorld"]
|
[sub_resource type="World3D" id="PreviewWorld"]
|
||||||
environment = SubResource("Environment")
|
|
||||||
|
|
||||||
[node name="ProfilePreview" type="SubViewportContainer"]
|
[node name="ProfilePreview" type="SubViewportContainer"]
|
||||||
custom_minimum_size = Vector2(300, 220)
|
custom_minimum_size = Vector2(300, 220)
|
||||||
|
|
@ -24,18 +16,12 @@ render_target_update_mode = 4
|
||||||
world_3d = SubResource("PreviewWorld")
|
world_3d = SubResource("PreviewWorld")
|
||||||
|
|
||||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="Viewport"]
|
[node name="WorldEnvironment" type="WorldEnvironment" parent="Viewport"]
|
||||||
environment = SubResource("Environment")
|
unique_name_in_owner = true
|
||||||
|
|
||||||
[node name="KeyLight" type="DirectionalLight3D" parent="Viewport"]
|
[node name="KeyLight" type="DirectionalLight3D" parent="Viewport"]
|
||||||
rotation_degrees = Vector3(-38, -32, 0)
|
unique_name_in_owner = true
|
||||||
light_energy = 1.15
|
light_energy = 0.1
|
||||||
shadow_enabled = true
|
shadow_enabled = false
|
||||||
|
|
||||||
[node name="FillLight" type="OmniLight3D" parent="Viewport"]
|
|
||||||
position = Vector3(-1.8, 1.6, 2.2)
|
|
||||||
light_color = Color(0.72, 0.84, 1, 1)
|
|
||||||
omni_range = 5.0
|
|
||||||
light_energy = 1.3
|
|
||||||
|
|
||||||
[node name="PreviewRoot" type="Node3D" parent="Viewport"]
|
[node name="PreviewRoot" type="Node3D" parent="Viewport"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
|
|
||||||