Compare commits

...

11 Commits

Author SHA1 Message Date
1ef6cce565 Tweaked fall kick curves
Some checks failed
linting & formatting / build (push) Failing after 4s
2025-09-29 16:49:12 -06:00
ec02444014 Added debug movement mode 2025-09-29 16:45:53 -06:00
150f3a57a4 Moved movement logic into subdirectory 2025-09-29 16:25:57 -06:00
b0c6bc7530 Added strafe banking & fall kick camera effects 2025-09-29 16:21:21 -06:00
a775865ed9 Added debug HUD 2025-09-29 15:36:35 -06:00
e4d3ca6d90 Harder shadows 2025-09-29 13:35:22 -06:00
7e998e76dc Basic character movement controls 2025-09-29 13:32:23 -06:00
589922d6b8 Basic world environment 2025-09-29 12:40:04 -06:00
ddb55e7a7a Player camera controller 2025-09-29 12:38:13 -06:00
d6d3afa701 Added PhantomCamera addon 2025-09-29 12:13:55 -06:00
425fa30ed5 World & player basics 2025-09-29 12:12:34 -06:00
151 changed files with 13164 additions and 1 deletions

View File

@ -0,0 +1 @@
uid://drvmixm5hd4cv

View File

@ -0,0 +1 @@
uid://c4qpamg7w3tpd

Binary file not shown.

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://censw3w53gldn"
path="res://.godot/imported/PhantomCameraBtnPrimaryDefault.png-fcf3696b583a82b1078609a5bfd648f5.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/assets/PhantomCameraBtnPrimaryDefault.png"
dest_files=["res://.godot/imported/PhantomCameraBtnPrimaryDefault.png-fcf3696b583a82b1078609a5bfd648f5.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

Binary file not shown.

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://pvr8mbvl1onm"
path="res://.godot/imported/PhantomCameraBtnPrimaryHover.png-3d2e4d225f6a86ce8a9c981ee7926a16.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/assets/PhantomCameraBtnPrimaryHover.png"
dest_files=["res://.godot/imported/PhantomCameraBtnPrimaryHover.png-3d2e4d225f6a86ce8a9c981ee7926a16.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

Binary file not shown.

View File

@ -0,0 +1,36 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://c4mm3of2mc8o5"
path="res://.godot/imported/Nunito-Black.ttf-2a374efbc207a97a99b8c70bdc4b7cbb.fontdata"
[deps]
source_file="res://addons/phantom_camera/fonts/Nunito-Black.ttf"
dest_files=["res://.godot/imported/Nunito-Black.ttf-2a374efbc207a97a99b8c70bdc4b7cbb.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
modulate_color_glyphs=false
hinting=1
subpixel_positioning=1
keep_rounding_remainders=true
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}

Binary file not shown.

View File

@ -0,0 +1,36 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://dve7mgsjik4dg"
path="res://.godot/imported/Nunito-Regular.ttf-b6054d499efa1a10921004862b1e217a.fontdata"
[deps]
source_file="res://addons/phantom_camera/fonts/Nunito-Regular.ttf"
dest_files=["res://.godot/imported/Nunito-Regular.ttf-b6054d499efa1a10921004862b1e217a.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
modulate_color_glyphs=false
hinting=1
subpixel_positioning=1
keep_rounding_remainders=true
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}

BIN
addons/phantom_camera/icons/misc/PriorityOverride.svg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dy8eifa6aw2en"
path="res://.godot/imported/PriorityOverride.svg-e76e07f4bbd98169f119e17fe5f2f03f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/icons/misc/PriorityOverride.svg"
dest_files=["res://.godot/imported/PriorityOverride.svg-e76e07f4bbd98169f119e17fe5f2f03f.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

BIN
addons/phantom_camera/icons/phantom_camera_2d.svg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dchkkx4v3ikpw"
path="res://.godot/imported/phantom_camera_2d.svg-e5483cbc858fc5f95f7210b1649dff0d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/icons/phantom_camera_2d.svg"
dest_files=["res://.godot/imported/phantom_camera_2d.svg-e5483cbc858fc5f95f7210b1649dff0d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

BIN
addons/phantom_camera/icons/phantom_camera_3d.svg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c71drpb8o4prn"
path="res://.godot/imported/phantom_camera_3d.svg-41ed612e834470377fb56eebffa083fe.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/icons/phantom_camera_3d.svg"
dest_files=["res://.godot/imported/phantom_camera_3d.svg-41ed612e834470377fb56eebffa083fe.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

Binary file not shown.

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dnaykbu6ue5lo"
path="res://.godot/imported/phantom_camera_camera_3d_resource.svg-f8bf8d1a5b7442fd6933bfbed999d57d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/icons/phantom_camera_camera_3d_resource.svg"
dest_files=["res://.godot/imported/phantom_camera_camera_3d_resource.svg-f8bf8d1a5b7442fd6933bfbed999d57d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

BIN
addons/phantom_camera/icons/phantom_camera_gizmo.svg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,44 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://e36npe2rbxyg"
path.s3tc="res://.godot/imported/phantom_camera_gizmo.svg-ba1aacb9b1c5f4ef401d3bd3697a542b.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://addons/phantom_camera/icons/phantom_camera_gizmo.svg"
dest_files=["res://.godot/imported/phantom_camera_gizmo.svg-ba1aacb9b1c5f4ef401d3bd3697a542b.s3tc.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
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

BIN
addons/phantom_camera/icons/phantom_camera_glow_logo.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cjli3p2b8mfyh"
path="res://.godot/imported/phantom_camera_glow_logo.png-078f944973b55b32029ba02980211fe0.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/icons/phantom_camera_glow_logo.png"
dest_files=["res://.godot/imported/phantom_camera_glow_logo.png-078f944973b55b32029ba02980211fe0.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
addons/phantom_camera/icons/phantom_camera_host.svg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,44 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://5fatldiu7dd5"
path="res://.godot/imported/phantom_camera_host.svg-3150f8f2d82ca9ecab9a3a415da21c5b.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/icons/phantom_camera_host.svg"
dest_files=["res://.godot/imported/phantom_camera_host.svg-3150f8f2d82ca9ecab9a3a415da21c5b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=true

BIN
addons/phantom_camera/icons/phantom_camera_logo.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cc0wmici0eic8"
path="res://.godot/imported/phantom_camera_logo.png-8b8d347b5e4800c86cd8095d030a3e5a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/icons/phantom_camera_logo.png"
dest_files=["res://.godot/imported/phantom_camera_logo.png-8b8d347b5e4800c86cd8095d030a3e5a.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

Binary file not shown.

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b2r7mhd780y8d"
path="res://.godot/imported/phantom_camera_noise_emitter_2d.svg-1b3d37fe36964dc86a6ea6681d0772bb.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/icons/phantom_camera_noise_emitter_2d.svg"
dest_files=["res://.godot/imported/phantom_camera_noise_emitter_2d.svg-1b3d37fe36964dc86a6ea6681d0772bb.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

Binary file not shown.

View File

@ -0,0 +1,44 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cby76y7m6xn4f"
path.s3tc="res://.godot/imported/phantom_camera_noise_emitter_3d.svg-9b90fe54aa618f65d52ac94515d41ea4.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://addons/phantom_camera/icons/phantom_camera_noise_emitter_3d.svg"
dest_files=["res://.godot/imported/phantom_camera_noise_emitter_3d.svg-9b90fe54aa618f65d52ac94515d41ea4.s3tc.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
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

Binary file not shown.

View File

@ -0,0 +1,44 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dw4iy855s0atm"
path.s3tc="res://.godot/imported/phantom_camera_noise_emitter_gizmo.svg-9a593802655a8d5038c7f55deab3882d.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://addons/phantom_camera/icons/phantom_camera_noise_emitter_gizmo.svg"
dest_files=["res://.godot/imported/phantom_camera_noise_emitter_gizmo.svg-9a593802655a8d5038c7f55deab3882d.s3tc.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
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

Binary file not shown.

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://fudwitkewe70"
path="res://.godot/imported/phantom_camera_noise_resource.svg-a81ed223714edd2c0d9cfa00be0c3f58.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/icons/phantom_camera_noise_resource.svg"
dest_files=["res://.godot/imported/phantom_camera_noise_resource.svg-a81ed223714edd2c0d9cfa00be0c3f58.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

BIN
addons/phantom_camera/icons/phantom_camera_tween.svg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,44 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dphl04mdf3220"
path="res://.godot/imported/phantom_camera_tween.svg-16faced08ef4a5f3458264d894230dbd.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/icons/phantom_camera_tween.svg"
dest_files=["res://.godot/imported/phantom_camera_tween.svg-16faced08ef4a5f3458264d894230dbd.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=true

Binary file not shown.

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://d4j4hrb7yusyq"
path="res://.godot/imported/phantom_camera_updater_panel_icon.svg-19823e6cbee8115f8b2554d0ee6e79db.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/icons/phantom_camera_updater_panel_icon.svg"
dest_files=["res://.godot/imported/phantom_camera_updater_panel_icon.svg-19823e6cbee8115f8b2554d0ee6e79db.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

BIN
addons/phantom_camera/icons/viewfinder/Camera2DIcon.svg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ccnsrg8hq74p2"
path="res://.godot/imported/Camera2DIcon.svg-300e6f57281180711c5ecf391104d4ba.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/icons/viewfinder/Camera2DIcon.svg"
dest_files=["res://.godot/imported/Camera2DIcon.svg-300e6f57281180711c5ecf391104d4ba.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

BIN
addons/phantom_camera/icons/viewfinder/Camera3DIcon.svg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dkiefpjsrj37n"
path="res://.godot/imported/Camera3DIcon.svg-4805c46004db1c89cc9443dd740693f5.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/icons/viewfinder/Camera3DIcon.svg"
dest_files=["res://.godot/imported/Camera3DIcon.svg-4805c46004db1c89cc9443dd740693f5.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

BIN
addons/phantom_camera/icons/viewfinder/SceneTypesIcon.svg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dk7omm0x44suj"
path="res://.godot/imported/SceneTypesIcon.svg-66e2255bd3398007bec03a5cbfa4d0aa.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/icons/viewfinder/SceneTypesIcon.svg"
dest_files=["res://.godot/imported/SceneTypesIcon.svg-66e2255bd3398007bec03a5cbfa4d0aa.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

BIN
addons/phantom_camera/icons/viewfinder/Select.svg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://rghrkoqrm2ig"
path="res://.godot/imported/Select.svg-cdf90b8b400d3b91a023b70c6a823894.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/icons/viewfinder/Select.svg"
dest_files=["res://.godot/imported/Select.svg-cdf90b8b400d3b91a023b70c6a823894.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=2.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

BIN
addons/phantom_camera/icons/warning.svg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cjlv0bg7byjx0"
path="res://.godot/imported/warning.svg-c1b21c265e0842bbdc9ed10735995366.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/phantom_camera/icons/warning.svg"
dest_files=["res://.godot/imported/warning.svg-c1b21c265e0842bbdc9ed10735995366.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=2.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,46 @@
@tool
extends EditorInspectorPlugin
#var _phantom_camera_script: Script = preload("res://addons/phantom_camera/scripts/phantom_camera.gd")
# TODO - Enable again once work is resumed for inspector based tasks
#func _can_handle(object) -> bool:
# return object is _phantom_camera_script
func _parse_category(object: Object, category: String) -> void:
var _margin_container: MarginContainer = MarginContainer.new()
var _margin_v: float = 20
_margin_container.add_theme_constant_override("margin_left", 10)
_margin_container.add_theme_constant_override("margin_top", _margin_v)
_margin_container.add_theme_constant_override("margin_right", 10)
_margin_container.add_theme_constant_override("margin_bottom", _margin_v)
add_custom_control(_margin_container)
var _vbox_container: VBoxContainer = VBoxContainer.new()
_margin_container.add_child(_vbox_container)
var align_with_view_button = Button.new()
align_with_view_button.connect("pressed", _align_camera_with_view.bind(object))
align_with_view_button.set_custom_minimum_size(Vector2(0, 60))
align_with_view_button.set_text("Align with view")
_vbox_container.add_child(align_with_view_button)
var preview_camera_button = Button.new()
preview_camera_button.connect("pressed", _preview_camera.bind(object))
preview_camera_button.set_custom_minimum_size(Vector2(0, 60))
preview_camera_button.set_text("Preview Camera")
_vbox_container.add_child(preview_camera_button)
func _align_camera_with_view(object: Object) -> void:
print("Aligning camera with view")
print(object)
func _preview_camera(object: Object) -> void:
print("Previewing camera")
print(object)

View File

@ -0,0 +1 @@
uid://dhwxgngr7sn6d

View File

@ -0,0 +1 @@
uid://ppret7j0jle7

View File

@ -0,0 +1,23 @@
[gd_scene load_steps=4 format=3 uid="uid://cfdoaceoosi1w"]
[ext_resource type="Script" uid="uid://cgfwg3paxkj2x" path="res://addons/phantom_camera/scripts/panel/editor.gd" id="1_86hp7"]
[ext_resource type="PackedScene" uid="uid://cuqkqsp3ikv5u" path="res://addons/phantom_camera/panel/updater/update_button.tscn" id="1_oowcd"]
[ext_resource type="PackedScene" uid="uid://dbkr3d716wtx0" path="res://addons/phantom_camera/panel/viewfinder/viewfinder_panel.tscn" id="2_xecnk"]
[node name="EditorPanel" type="VBoxContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_86hp7")
[node name="UpdateButton" parent="." instance=ExtResource("1_oowcd")]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 1
[node name="ViewfinderPanel" parent="." instance=ExtResource("2_xecnk")]
unique_name_in_owner = true
layout_mode = 2

View File

@ -0,0 +1,253 @@
[gd_scene load_steps=15 format=3 uid="uid://b25fl4usw0nlp"]
[ext_resource type="Script" uid="uid://cjblcocen12r3" path="res://addons/phantom_camera/scripts/panel/updater/download_update_panel.gd" id="1_sx5xq"]
[ext_resource type="Texture2D" uid="uid://cc0wmici0eic8" path="res://addons/phantom_camera/icons/phantom_camera_logo.png" id="2_f3yo7"]
[ext_resource type="FontFile" uid="uid://c4mm3of2mc8o5" path="res://addons/phantom_camera/fonts/Nunito-Black.ttf" id="3_h8uk3"]
[ext_resource type="FontFile" uid="uid://dve7mgsjik4dg" path="res://addons/phantom_camera/fonts/Nunito-Regular.ttf" id="4_gwh4i"]
[ext_resource type="Texture2D" uid="uid://censw3w53gldn" path="res://addons/phantom_camera/assets/PhantomCameraBtnPrimaryDefault.png" id="5_bonti"]
[sub_resource type="ImageTexture" id="ImageTexture_sjwi2"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_insma"]
bg_color = Color(0.0190018, 0.21903, 0.16997, 1)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.0980392, 0.572549, 0.458824, 1)
border_blend = true
corner_radius_bottom_right = 12
corner_radius_bottom_left = 12
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_8m63d"]
bg_color = Color(0.0784314, 0.109804, 0.129412, 1)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.105882, 0.619608, 0.498039, 1)
corner_radius_bottom_right = 12
corner_radius_bottom_left = 12
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_yn22d"]
bg_color = Color(0.0117647, 0.164706, 0.12549, 1)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.0980392, 0.572549, 0.458824, 1)
border_blend = true
corner_radius_bottom_right = 12
corner_radius_bottom_left = 12
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_djsbc"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_xtrn6"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_o12j0"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_buptb"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_g3tf0"]
[node name="DownloadUpdatePanel" type="Control"]
custom_minimum_size = Vector2(300, 350)
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_bottom = -61.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_sx5xq")
[node name="DownloadHTTPRequest" type="HTTPRequest" parent="."]
unique_name_in_owner = true
[node name="Timer" type="Timer" parent="DownloadHTTPRequest"]
one_shot = true
[node name="VBox" type="VBoxContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/separation = 2
[node name="VBoxContainer2" type="VBoxContainer" parent="VBox"]
layout_mode = 2
theme_override_constants/separation = -20
[node name="MarginContainer" type="MarginContainer" parent="VBox/VBoxContainer2"]
layout_mode = 2
theme_override_constants/margin_top = 12
[node name="Logo" type="TextureRect" parent="VBox/VBoxContainer2/MarginContainer"]
unique_name_in_owner = true
clip_contents = true
custom_minimum_size = Vector2(300, 160)
layout_mode = 2
texture = ExtResource("2_f3yo7")
expand_mode = 3
stretch_mode = 5
[node name="VBoxContainer" type="VBoxContainer" parent="VBox/VBoxContainer2"]
layout_mode = 2
theme_override_constants/separation = -5
[node name="NameLabel" type="Label" parent="VBox/VBoxContainer2/VBoxContainer"]
layout_mode = 2
theme_override_colors/font_color = Color(0.960784, 0.960784, 0.960784, 1)
theme_override_fonts/font = ExtResource("3_h8uk3")
theme_override_font_sizes/font_size = 32
text = "Phantom Camera"
horizontal_alignment = 1
[node name="DownloadVersionLabel" type="Label" parent="VBox/VBoxContainer2/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
theme_override_colors/font_color = Color(0.960784, 0.960784, 0.960784, 1)
theme_override_fonts/font = ExtResource("4_gwh4i")
theme_override_font_sizes/font_size = 18
text = "v1.2.3 is available for download."
horizontal_alignment = 1
[node name="CurrentVersionLabel" type="Label" parent="VBox"]
unique_name_in_owner = true
visible = false
layout_mode = 2
theme_override_fonts/font = ExtResource("4_gwh4i")
text = "Current version: 0.0.0"
horizontal_alignment = 1
[node name="Center2" type="CenterContainer" parent="VBox"]
layout_mode = 2
[node name="NotesButton" type="LinkButton" parent="VBox/Center2"]
layout_mode = 2
theme_override_colors/font_color = Color(0.917647, 0.631373, 0.368627, 1)
theme_override_colors/font_hover_color = Color(0.721569, 0.454902, 0.192157, 1)
theme_override_fonts/font = ExtResource("3_h8uk3")
theme_override_font_sizes/font_size = 18
text = "Release Notes"
[node name="Center" type="CenterContainer" parent="VBox"]
layout_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="VBox/Center"]
layout_mode = 2
[node name="BreakingLabel" type="Label" parent="VBox/Center/VBoxContainer"]
unique_name_in_owner = true
visible = false
layout_mode = 2
theme_override_colors/font_color = Color(0.72549, 0.227451, 0.34902, 1)
theme_override_fonts/font = ExtResource("3_h8uk3")
theme_override_font_sizes/font_size = 18
text = "Potential Breaking Changes
in new release"
horizontal_alignment = 1
uppercase = true
[node name="BreakingMarginContainer" type="MarginContainer" parent="VBox/Center/VBoxContainer"]
unique_name_in_owner = true
visible = false
layout_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="VBox/Center/VBoxContainer/BreakingMarginContainer"]
layout_mode = 2
[node name="RichTextLabel2" type="RichTextLabel" parent="VBox/Center/VBoxContainer/BreakingMarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_fonts/normal_font = ExtResource("4_gwh4i")
theme_override_fonts/bold_font = ExtResource("3_h8uk3")
theme_override_fonts/mono_font = ExtResource("3_h8uk3")
theme_override_font_sizes/normal_font_size = 18
theme_override_font_sizes/bold_font_size = 14
theme_override_font_sizes/mono_font_size = 12
bbcode_enabled = true
text = "[center][b]I am prepared for any breaking
changes that may occur from this update[/b][/center]"
fit_content = true
[node name="BreakingOptionButton" type="OptionButton" parent="VBox/Center/VBoxContainer/BreakingMarginContainer/VBoxContainer"]
unique_name_in_owner = true
visible = false
layout_mode = 2
mouse_default_cursor_shape = 2
theme_override_fonts/font = ExtResource("3_h8uk3")
theme_override_font_sizes/font_size = 18
theme_override_icons/arrow = SubResource("ImageTexture_sjwi2")
theme_override_styles/normal = SubResource("StyleBoxFlat_insma")
theme_override_styles/hover = SubResource("StyleBoxFlat_8m63d")
theme_override_styles/pressed = SubResource("StyleBoxFlat_yn22d")
alignment = 1
item_count = 2
selected = 0
popup/item_0/text = "Confirm choice"
popup/item_0/id = 0
popup/item_1/text = "Yes, I am prepared"
popup/item_1/id = 1
[node name="DownloadButton" type="Button" parent="VBox/Center/VBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(240, 90)
layout_mode = 2
mouse_default_cursor_shape = 2
theme_override_styles/normal = SubResource("StyleBoxEmpty_djsbc")
theme_override_styles/hover = SubResource("StyleBoxEmpty_xtrn6")
theme_override_styles/pressed = SubResource("StyleBoxEmpty_o12j0")
theme_override_styles/disabled = SubResource("StyleBoxEmpty_buptb")
theme_override_styles/focus = SubResource("StyleBoxEmpty_g3tf0")
[node name="DownloadButtonBG" type="NinePatchRect" parent="VBox/Center/VBoxContainer/DownloadButton"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
texture = ExtResource("5_bonti")
patch_margin_left = 38
patch_margin_top = 37
patch_margin_right = 38
patch_margin_bottom = 39
[node name="UpdateLabel" type="Label" parent="VBox/Center/VBoxContainer/DownloadButton"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 14
anchor_top = 0.5
anchor_right = 1.0
anchor_bottom = 0.5
offset_top = -14.5
offset_bottom = 14.5
grow_horizontal = 2
grow_vertical = 2
theme_override_colors/font_color = Color(0.960784, 0.960784, 0.960784, 1)
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
theme_override_fonts/font = ExtResource("3_h8uk3")
theme_override_font_sizes/font_size = 20
text = "Update"
horizontal_alignment = 1
uppercase = true
[node name="MarginContainer" type="MarginContainer" parent="VBox"]
layout_mode = 2
theme_override_constants/margin_top = 10
[node name="RichTextLabel" type="RichTextLabel" parent="VBox/MarginContainer"]
layout_mode = 2
theme_override_fonts/normal_font = ExtResource("4_gwh4i")
theme_override_fonts/mono_font = ExtResource("3_h8uk3")
theme_override_font_sizes/normal_font_size = 12
theme_override_font_sizes/mono_font_size = 12
bbcode_enabled = true
text = "[center]The updater can be disabled within:
[code]Project Settings / Phantom Camera / Updater / Enable Updater[/code][/center]"
fit_content = true
[connection signal="pressed" from="VBox/Center2/NotesButton" to="." method="_on_notes_button_pressed"]

View File

@ -0,0 +1,101 @@
[gd_scene load_steps=10 format=3 uid="uid://cuqkqsp3ikv5u"]
[ext_resource type="FontFile" uid="uid://c4mm3of2mc8o5" path="res://addons/phantom_camera/fonts/Nunito-Black.ttf" id="1_5e5k4"]
[ext_resource type="Script" uid="uid://bwc42i46603qn" path="res://addons/phantom_camera/scripts/panel/updater/update_button.gd" id="1_xtaw5"]
[ext_resource type="Texture2D" uid="uid://d4j4hrb7yusyq" path="res://addons/phantom_camera/icons/phantom_camera_updater_panel_icon.svg" id="2_c4d83"]
[ext_resource type="PackedScene" uid="uid://b25fl4usw0nlp" path="res://addons/phantom_camera/panel/updater/download_update_panel.tscn" id="2_vtgcx"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_c7fd1"]
content_margin_left = 10.0
content_margin_top = 4.0
content_margin_right = 10.0
content_margin_bottom = 4.0
bg_color = Color(0.0980392, 0.415686, 0.341176, 1)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.227451, 0.72549, 0.603922, 1)
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_y83dj"]
content_margin_left = 10.0
content_margin_top = 4.0
content_margin_right = 10.0
content_margin_bottom = 4.0
bg_color = Color(0.0784314, 0.109804, 0.129412, 1)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.960784, 0.960784, 0.960784, 1)
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_slf6e"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_lekqh"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_dr4n4"]
content_margin_bottom = 20.0
bg_color = Color(0.0784314, 0.109804, 0.129412, 1)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.227451, 0.72549, 0.603922, 1)
[node name="UpdateButton" type="Button"]
visible = false
offset_left = 1.0
offset_right = 149.0
offset_bottom = 28.0
size_flags_vertical = 3
theme_override_colors/font_color = Color(0.960784, 0.960784, 0.960784, 1)
theme_override_colors/font_hover_color = Color(0.939288, 0.917743, 0.892615, 1)
theme_override_colors/icon_normal_color = Color(0.960784, 0.960784, 0.960784, 1)
theme_override_fonts/font = ExtResource("1_5e5k4")
theme_override_font_sizes/font_size = 14
theme_override_styles/normal = SubResource("StyleBoxFlat_c7fd1")
theme_override_styles/hover = SubResource("StyleBoxFlat_y83dj")
theme_override_styles/pressed = SubResource("StyleBoxEmpty_slf6e")
theme_override_styles/focus = SubResource("StyleBoxEmpty_lekqh")
text = "Update available"
icon = ExtResource("2_c4d83")
script = ExtResource("1_xtaw5")
[node name="HTTPRequest" type="HTTPRequest" parent="."]
unique_name_in_owner = true
[node name="DownloadDialog" type="AcceptDialog" parent="."]
unique_name_in_owner = true
transparent_bg = true
title = "New Update"
initial_position = 2
size = Vector2i(450, 480)
transient = false
unresizable = true
borderless = true
keep_title_visible = false
content_scale_mode = 1
theme_override_constants/buttons_separation = 30
theme_override_styles/panel = SubResource("StyleBoxFlat_dr4n4")
ok_button_text = "Close"
[node name="DownloadUpdatePanel" parent="DownloadDialog" instance=ExtResource("2_vtgcx")]
unique_name_in_owner = true
offset_left = 2.0
offset_top = 2.0
offset_right = -2.0
offset_bottom = -80.0
[node name="NeedsReloadDialog" type="ConfirmationDialog" parent="."]
unique_name_in_owner = true
[node name="UpdateFailedDialog" type="AcceptDialog" parent="."]
unique_name_in_owner = true

View File

@ -0,0 +1,14 @@
[gd_resource type="StyleBoxFlat" format=3 uid="uid://dpa7yvxlq043a"]
[resource]
bg_color = Color(0.227451, 0.72549, 0.603922, 0.2)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.227451, 0.72549, 0.603922, 1)
corner_detail = 1
expand_margin_left = 1.0
expand_margin_top = 1.0
expand_margin_right = 1.0
expand_margin_bottom = 1.0

View File

@ -0,0 +1,87 @@
[gd_scene load_steps=8 format=3 uid="uid://mbjdav5oqves"]
[ext_resource type="Script" uid="uid://c84cxry3t35ny" path="res://addons/phantom_camera/scripts/panel/viewfinder/host_list.gd" id="1_h6ayt"]
[ext_resource type="Texture2D" uid="uid://5fatldiu7dd5" path="res://addons/phantom_camera/icons/phantom_camera_host.svg" id="1_xlgqb"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_w002y"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_kq7gm"]
content_margin_left = 8.0
content_margin_top = 4.0
content_margin_right = 8.0
content_margin_bottom = 4.0
bg_color = Color(0.0784314, 0.109804, 0.129412, 1)
border_width_top = 2
border_width_right = 2
border_color = Color(0.960784, 0.960784, 0.960784, 1)
corner_radius_top_right = 8
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ynag5"]
content_margin_left = 8.0
content_margin_top = 4.0
content_margin_right = 8.0
content_margin_bottom = 4.0
bg_color = Color(0.960784, 0.960784, 0.960784, 1)
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
corner_radius_top_right = 6
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_q2svd"]
content_margin_left = 8.0
content_margin_top = 4.0
content_margin_right = 8.0
content_margin_bottom = 4.0
bg_color = Color(0.0784314, 0.109804, 0.129412, 1)
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.227451, 0.72549, 0.603922, 1)
corner_radius_top_right = 8
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_e0jvt"]
content_margin_left = 0.0
content_margin_top = 8.0
content_margin_right = 0.0
content_margin_bottom = 8.0
bg_color = Color(0.0784314, 0.109804, 0.129412, 1)
border_width_top = 2
border_width_right = 2
border_color = Color(0.227451, 0.72549, 0.603922, 1)
corner_radius_top_right = 10
[node name="PCamHostList" type="VBoxContainer"]
anchors_preset = 9
anchor_bottom = 1.0
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_constants/separation = -2
alignment = 2
script = ExtResource("1_h6ayt")
[node name="HostListButton" type="Button" parent="."]
unique_name_in_owner = true
custom_minimum_size = Vector2(40, 40)
layout_mode = 2
size_flags_horizontal = 0
theme_override_colors/icon_hover_color = Color(0.0784314, 0.109804, 0.129412, 1)
theme_override_colors/icon_hover_pressed_color = Color(0.0784314, 0.109804, 0.129412, 1)
theme_override_styles/focus = SubResource("StyleBoxEmpty_w002y")
theme_override_styles/hover_pressed = SubResource("StyleBoxFlat_kq7gm")
theme_override_styles/hover = SubResource("StyleBoxFlat_ynag5")
theme_override_styles/pressed = SubResource("StyleBoxFlat_kq7gm")
theme_override_styles/normal = SubResource("StyleBoxFlat_q2svd")
icon = ExtResource("1_xlgqb")
expand_icon = true
[node name="ScrollContainer" type="ScrollContainer" parent="."]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxFlat_e0jvt")
horizontal_scroll_mode = 0
[node name="HostListContainer" type="VBoxContainer" parent="ScrollContainer"]
unique_name_in_owner = true
layout_mode = 2
theme_override_constants/separation = 8

View File

@ -0,0 +1,68 @@
[gd_scene load_steps=10 format=3 uid="uid://btn6jgv0vix7"]
[ext_resource type="FontFile" uid="uid://dve7mgsjik4dg" path="res://addons/phantom_camera/fonts/Nunito-Regular.ttf" id="1_anjxo"]
[ext_resource type="Theme" uid="uid://bhppejri5dbsf" path="res://addons/phantom_camera/themes/theme.tres" id="1_wql5t"]
[ext_resource type="Texture2D" uid="uid://rghrkoqrm2ig" path="res://addons/phantom_camera/icons/viewfinder/Select.svg" id="2_71b6g"]
[ext_resource type="ButtonGroup" uid="uid://dfu0b8jbtyr1n" path="res://addons/phantom_camera/panel/viewfinder/host_list/host_list_item_group.tres" id="3_06a0y"]
[ext_resource type="Script" uid="uid://bv24ubx8mutw7" path="res://addons/phantom_camera/scripts/panel/viewfinder/host_list_item.gd" id="3_a5o8b"]
[ext_resource type="Texture2D" uid="uid://cjlv0bg7byjx0" path="res://addons/phantom_camera/icons/warning.svg" id="3_qgpy7"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_0rxfi"]
content_margin_right = 6.0
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_llqnh"]
[sub_resource type="Theme" id="Theme_7h15c"]
Button/colors/icon_hover_color = Color(0.960784, 0.960784, 0.960784, 1)
Button/colors/icon_hover_pressed_color = Color(0.227451, 0.72549, 0.603922, 1)
Button/colors/icon_normal_color = Color(0.227451, 0.72549, 0.603922, 1)
Button/colors/icon_pressed_color = Color(0.227451, 0.72549, 0.603922, 1)
Button/constants/icon_max_width = 20
Button/styles/focus = SubResource("StyleBoxEmpty_llqnh")
[node name="HostListItem" type="PanelContainer"]
offset_right = 229.0
offset_bottom = 34.0
theme_override_styles/panel = SubResource("StyleBoxEmpty_0rxfi")
script = ExtResource("3_a5o8b")
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 2
theme_override_constants/separation = 2
[node name="SelectPCamHost" type="Button" parent="HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 4
tooltip_text = "Select the Phantom Camera Host node from the scene hierarchy"
focus_mode = 0
theme = SubResource("Theme_7h15c")
icon = ExtResource("2_71b6g")
flat = true
[node name="HBoxContainer" type="HBoxContainer" parent="HBoxContainer"]
layout_mode = 2
theme_override_constants/separation = 8
[node name="ErrorPCamHost" type="TextureRect" parent="HBoxContainer/HBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(18, 18)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 4
tooltip_text = "This Phantom Camera Host node will not affect a Camera node.
See the warning in the Scene Tree for more information."
texture = ExtResource("3_qgpy7")
expand_mode = 1
[node name="SwitchPCamHost" type="Button" parent="HBoxContainer/HBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(40, 0)
layout_mode = 2
tooltip_text = "Change the viewfinder's camera to the camera of this Phantom Camera Host"
theme = ExtResource("1_wql5t")
theme_override_fonts/font = ExtResource("1_anjxo")
theme_override_font_sizes/font_size = 18
toggle_mode = true
button_group = ExtResource("3_06a0y")
text = "{ PCamHostName }"

View File

@ -0,0 +1,3 @@
[gd_resource type="ButtonGroup" format=3 uid="uid://dfu0b8jbtyr1n"]
[resource]

View File

@ -0,0 +1,563 @@
[gd_scene load_steps=28 format=3 uid="uid://dbkr3d716wtx0"]
[ext_resource type="Script" uid="uid://drmv3363t8amc" path="res://addons/phantom_camera/scripts/panel/viewfinder/viewfinder.gd" id="1_utvi8"]
[ext_resource type="StyleBox" uid="uid://dpa7yvxlq043a" path="res://addons/phantom_camera/panel/viewfinder/deadzone_style_box.tres" id="2_uabt4"]
[ext_resource type="FontFile" uid="uid://c4mm3of2mc8o5" path="res://addons/phantom_camera/fonts/Nunito-Black.ttf" id="3_li3i3"]
[ext_resource type="Texture2D" uid="uid://5fatldiu7dd5" path="res://addons/phantom_camera/icons/phantom_camera_host.svg" id="4_lcg1p"]
[ext_resource type="FontFile" uid="uid://dve7mgsjik4dg" path="res://addons/phantom_camera/fonts/Nunito-Regular.ttf" id="5_4jhax"]
[ext_resource type="Texture2D" uid="uid://dy8eifa6aw2en" path="res://addons/phantom_camera/icons/misc/PriorityOverride.svg" id="6_ptuth"]
[ext_resource type="Script" uid="uid://c84cxry3t35ny" path="res://addons/phantom_camera/scripts/panel/viewfinder/host_list.gd" id="7_kpij0"]
[ext_resource type="Theme" uid="uid://bhppejri5dbsf" path="res://addons/phantom_camera/themes/theme.tres" id="8_b4akn"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fle8t"]
bg_color = Color(0.227451, 0.72549, 0.603922, 0.2)
draw_center = false
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.227451, 0.72549, 0.603922, 1)
corner_detail = 1
expand_margin_left = 1.0
expand_margin_top = 1.0
expand_margin_right = 1.0
expand_margin_bottom = 1.0
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_xmo1t"]
draw_center = false
border_width_left = 1
border_width_top = 1
border_width_right = 1
border_width_bottom = 1
border_color = Color(0.745098, 0.858824, 0.380392, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_q7vs4"]
bg_color = Color(0.929412, 0.87451, 0.619608, 1)
border_width_left = 1
border_width_top = 1
border_width_right = 1
border_width_bottom = 1
border_color = Color(0, 0, 0, 1)
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_iho1a"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_obaj6"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_4b76l"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_yh38y"]
content_margin_left = 10.0
content_margin_top = 10.0
content_margin_right = 10.0
content_margin_bottom = 10.0
bg_color = Color(0.129412, 0.407843, 0.337255, 1)
border_width_left = 4
border_width_top = 4
border_width_right = 4
border_width_bottom = 4
border_color = Color(0.988235, 0.498039, 0.498039, 1)
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_gci88"]
content_margin_left = 10.0
content_margin_top = 10.0
content_margin_right = 10.0
content_margin_bottom = 10.0
bg_color = Color(0.180392, 0.576471, 0.482353, 1)
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fsxik"]
content_margin_left = 10.0
content_margin_top = 10.0
content_margin_right = 10.0
content_margin_bottom = 10.0
bg_color = Color(0.129412, 0.407843, 0.337255, 1)
border_width_left = 4
border_width_top = 4
border_width_right = 4
border_width_bottom = 4
border_color = Color(0.227451, 0.72549, 0.603922, 1)
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_g5wua"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_x4bx8"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_840sd"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ja3vm"]
bg_color = Color(0.53, 0.1643, 0.255725, 1)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_blend = true
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_mk273"]
bg_color = Color(0.43, 0.1333, 0.207475, 1)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_blend = true
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_agqdu"]
bg_color = Color(0.72549, 0.227451, 0.34902, 1)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_blend = true
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_w002y"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_kq7gm"]
content_margin_left = 8.0
content_margin_top = 4.0
content_margin_right = 8.0
content_margin_bottom = 4.0
bg_color = Color(0.0784314, 0.109804, 0.129412, 1)
border_width_top = 2
border_width_right = 2
border_color = Color(0.960784, 0.960784, 0.960784, 1)
corner_radius_top_right = 8
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ynag5"]
content_margin_left = 8.0
content_margin_top = 4.0
content_margin_right = 8.0
content_margin_bottom = 4.0
bg_color = Color(0.960784, 0.960784, 0.960784, 1)
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
corner_radius_top_right = 6
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_q2svd"]
content_margin_left = 8.0
content_margin_top = 4.0
content_margin_right = 8.0
content_margin_bottom = 4.0
bg_color = Color(0.0784314, 0.109804, 0.129412, 1)
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.227451, 0.72549, 0.603922, 1)
corner_radius_top_right = 8
[node name="ViewfinderPanel" type="Control"]
clip_contents = true
custom_minimum_size = Vector2(0, 300)
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
mouse_filter = 2
script = ExtResource("1_utvi8")
[node name="Viewfinder" type="Control" parent="."]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
metadata/_edit_lock_ = true
[node name="SubViewportContainer" type="SubViewportContainer" parent="Viewfinder"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
stretch = true
[node name="SubViewport" type="SubViewport" parent="Viewfinder/SubViewportContainer"]
unique_name_in_owner = true
handle_input_locally = false
canvas_item_default_texture_filter = 0
gui_disable_input = true
size = Vector2i(1152, 648)
size_2d_override_stretch = true
render_target_update_mode = 4
[node name="Camera2D" type="Camera2D" parent="Viewfinder/SubViewportContainer/SubViewport"]
unique_name_in_owner = true
editor_draw_screen = false
[node name="DeadZoneHBoxContainer" type="HBoxContainer" parent="Viewfinder"]
unique_name_in_owner = true
clip_contents = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
theme_override_constants/separation = 0
[node name="DeadZoneLeftHBoxContainer" type="VBoxContainer" parent="Viewfinder/DeadZoneHBoxContainer"]
clip_contents = true
layout_mode = 2
size_flags_horizontal = 3
mouse_filter = 2
theme_override_constants/separation = 0
[node name="DeadZoneLeftTopPanel" type="Panel" parent="Viewfinder/DeadZoneHBoxContainer/DeadZoneLeftHBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
mouse_filter = 2
theme_override_styles/panel = ExtResource("2_uabt4")
[node name="DeadZoneLeftCenterPanel" type="Panel" parent="Viewfinder/DeadZoneHBoxContainer/DeadZoneLeftHBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
mouse_filter = 2
theme_override_styles/panel = ExtResource("2_uabt4")
[node name="DeadZoneLeftBottomPanel" type="Panel" parent="Viewfinder/DeadZoneHBoxContainer/DeadZoneLeftHBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
mouse_filter = 2
theme_override_styles/panel = ExtResource("2_uabt4")
[node name="DeadZoneCenterHBoxContainer" type="VBoxContainer" parent="Viewfinder/DeadZoneHBoxContainer"]
unique_name_in_owner = true
clip_contents = true
layout_mode = 2
size_flags_horizontal = 4
mouse_filter = 2
theme_override_constants/separation = 0
[node name="DeadZoneCenterTopPanel" type="Panel" parent="Viewfinder/DeadZoneHBoxContainer/DeadZoneCenterHBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
mouse_filter = 2
theme_override_styles/panel = ExtResource("2_uabt4")
[node name="DeadZoneCenterCenterPanel" type="Panel" parent="Viewfinder/DeadZoneHBoxContainer/DeadZoneCenterHBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 4
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_fle8t")
[node name="DeadZoneCenterBottomPanel" type="Panel" parent="Viewfinder/DeadZoneHBoxContainer/DeadZoneCenterHBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
mouse_filter = 2
theme_override_styles/panel = ExtResource("2_uabt4")
[node name="DeadZoneRightHBoxContainer" type="VBoxContainer" parent="Viewfinder/DeadZoneHBoxContainer"]
clip_contents = true
layout_mode = 2
size_flags_horizontal = 3
mouse_filter = 2
theme_override_constants/separation = 0
[node name="DeadZoneRightTopPanel" type="Panel" parent="Viewfinder/DeadZoneHBoxContainer/DeadZoneRightHBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
mouse_filter = 2
theme_override_styles/panel = ExtResource("2_uabt4")
[node name="DeadZoneRightCenterPanel" type="Panel" parent="Viewfinder/DeadZoneHBoxContainer/DeadZoneRightHBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
mouse_filter = 2
theme_override_styles/panel = ExtResource("2_uabt4")
[node name="DeadZoneRightBottomPanel" type="Panel" parent="Viewfinder/DeadZoneHBoxContainer/DeadZoneRightHBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
mouse_filter = 2
theme_override_styles/panel = ExtResource("2_uabt4")
[node name="AspectRatioContainer" type="AspectRatioContainer" parent="Viewfinder"]
unique_name_in_owner = true
clip_contents = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
ratio = 1.77778
[node name="CameraViewportPanel" type="Panel" parent="Viewfinder/AspectRatioContainer"]
layout_mode = 2
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_xmo1t")
[node name="TargetPoint" type="Panel" parent="Viewfinder/AspectRatioContainer/CameraViewportPanel"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -3.0
offset_top = -3.0
offset_right = 3.0
offset_bottom = 3.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_q7vs4")
[node name="NoSupportMsg" type="Label" parent="."]
unique_name_in_owner = true
visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_top = -8.0
offset_bottom = -8.0
grow_horizontal = 2
grow_vertical = 2
theme_override_fonts/font = ExtResource("3_li3i3")
theme_override_font_sizes/font_size = 24
theme_override_styles/normal = SubResource("StyleBoxEmpty_iho1a")
text = "Control scenes are not supported"
horizontal_alignment = 1
vertical_alignment = 1
metadata/_edit_lock_ = true
[node name="EmptyStateControl" type="Control" parent="."]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
metadata/_edit_use_anchors_ = true
metadata/_edit_lock_ = true
[node name="BGColorRect" type="ColorRect" parent="EmptyStateControl"]
visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0, 0, 0, 1)
metadata/_edit_lock_ = true
[node name="VBoxContainer" type="VBoxContainer" parent="EmptyStateControl"]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -200.0
offset_top = -112.0
offset_right = 200.0
offset_bottom = 112.0
grow_horizontal = 2
grow_vertical = 2
alignment = 1
[node name="EmptyStateIcon" type="TextureRect" parent="EmptyStateControl/VBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 64)
layout_mode = 2
texture = ExtResource("4_lcg1p")
expand_mode = 1
stretch_mode = 5
[node name="EmptyStateText" type="RichTextLabel" parent="EmptyStateControl/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
theme_override_colors/default_color = Color(1, 1, 1, 1)
theme_override_fonts/normal_font = ExtResource("5_4jhax")
theme_override_fonts/bold_font = ExtResource("3_li3i3")
theme_override_font_sizes/normal_font_size = 24
theme_override_font_sizes/bold_font_size = 24
theme_override_styles/focus = SubResource("StyleBoxEmpty_obaj6")
theme_override_styles/normal = SubResource("StyleBoxEmpty_iho1a")
bbcode_enabled = true
text = "[center][b]NodeType[/b] Description [/center]"
fit_content = true
[node name="AddNodeButton" type="Button" parent="EmptyStateControl/VBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(400, 54)
layout_mode = 2
size_flags_horizontal = 4
focus_mode = 0
theme_override_colors/font_color = Color(1, 1, 1, 1)
theme_override_fonts/font = ExtResource("3_li3i3")
theme_override_font_sizes/font_size = 24
theme_override_styles/focus = SubResource("StyleBoxEmpty_4b76l")
theme_override_styles/hover = SubResource("StyleBoxFlat_yh38y")
theme_override_styles/pressed = SubResource("StyleBoxFlat_gci88")
theme_override_styles/normal = SubResource("StyleBoxFlat_fsxik")
[node name="AddNodeTypeText" type="RichTextLabel" parent="EmptyStateControl/VBoxContainer/AddNodeButton"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_top = 9.0
offset_bottom = -11.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
theme_override_colors/default_color = Color(1, 1, 1, 1)
theme_override_fonts/normal_font = ExtResource("5_4jhax")
theme_override_fonts/bold_font = ExtResource("3_li3i3")
theme_override_font_sizes/normal_font_size = 24
theme_override_font_sizes/bold_font_size = 24
theme_override_styles/focus = SubResource("StyleBoxEmpty_g5wua")
theme_override_styles/normal = SubResource("StyleBoxEmpty_x4bx8")
bbcode_enabled = true
text = "[center]Add [img=32]res://addons/phantom_camera/icons/viewfinder/Camera3DIcon.svg[/img] [b]{NodeType}[/b][/center]"
scroll_active = false
[node name="PriorityOverrideButton" type="Button" parent="."]
unique_name_in_owner = true
visible = false
layout_mode = 1
offset_left = 5.0
offset_top = 5.0
offset_right = 165.0
offset_bottom = 57.0
mouse_default_cursor_shape = 2
theme_override_styles/focus = SubResource("StyleBoxEmpty_840sd")
theme_override_styles/hover = SubResource("StyleBoxFlat_ja3vm")
theme_override_styles/pressed = SubResource("StyleBoxFlat_mk273")
theme_override_styles/normal = SubResource("StyleBoxFlat_agqdu")
metadata/_edit_lock_ = true
[node name="PriorityOverrideIcon" type="TextureRect" parent="PriorityOverrideButton"]
layout_mode = 1
offset_left = 8.0
offset_top = 4.0
offset_right = 32.0
offset_bottom = 28.0
texture = ExtResource("6_ptuth")
expand_mode = 1
[node name="PriorityOverrideByLabel" type="Label" parent="PriorityOverrideButton"]
layout_mode = 0
offset_left = 30.0
offset_top = 1.0
offset_right = 140.0
offset_bottom = 24.0
theme_override_fonts/font = ExtResource("3_li3i3")
theme_override_font_sizes/font_size = 14
text = "OVERRIDDEN BY"
vertical_alignment = 1
[node name="PriorityOverrideNameLabel" type="Label" parent="PriorityOverrideButton"]
unique_name_in_owner = true
layout_mode = 0
offset_left = 6.0
offset_top = 21.0
offset_right = 153.0
offset_bottom = 44.0
theme_override_fonts/font = ExtResource("5_4jhax")
theme_override_font_sizes/font_size = 14
text = "PCam_Name
"
vertical_alignment = 1
text_overrun_behavior = 3
[node name="SizeLabel" type="Label" parent="."]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 4
anchor_top = 0.5
anchor_bottom = 0.5
offset_top = -11.5
offset_right = 40.0
offset_bottom = 11.5
grow_vertical = 2
[node name="PCamHostList" type="VBoxContainer" parent="."]
unique_name_in_owner = true
visible = false
layout_mode = 1
anchors_preset = -1
anchor_bottom = 1.0
offset_top = 588.0
grow_vertical = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_constants/separation = -2
alignment = 2
script = ExtResource("7_kpij0")
[node name="HostListButton" type="Button" parent="PCamHostList"]
unique_name_in_owner = true
custom_minimum_size = Vector2(40, 40)
layout_mode = 2
size_flags_horizontal = 0
theme_override_colors/icon_hover_pressed_color = Color(0.0784314, 0.109804, 0.129412, 1)
theme_override_colors/icon_hover_color = Color(0.0784314, 0.109804, 0.129412, 1)
theme_override_styles/focus = SubResource("StyleBoxEmpty_w002y")
theme_override_styles/hover_pressed = SubResource("StyleBoxFlat_kq7gm")
theme_override_styles/hover = SubResource("StyleBoxFlat_ynag5")
theme_override_styles/pressed = SubResource("StyleBoxFlat_kq7gm")
theme_override_styles/normal = SubResource("StyleBoxFlat_q2svd")
icon = ExtResource("4_lcg1p")
expand_icon = true
[node name="PanelContainer" type="PanelContainer" parent="PCamHostList"]
layout_mode = 2
size_flags_vertical = 3
theme = ExtResource("8_b4akn")
[node name="ScrollContainer" type="ScrollContainer" parent="PCamHostList/PanelContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
theme = ExtResource("8_b4akn")
horizontal_scroll_mode = 0
[node name="HostListContainer" type="VBoxContainer" parent="PCamHostList/PanelContainer/ScrollContainer"]
unique_name_in_owner = true
layout_mode = 2
theme = ExtResource("8_b4akn")

View File

@ -0,0 +1,7 @@
[plugin]
name="Phantom Camera"
description="Control the movement and dynamically tween 2D & 3D cameras positions. Built for Godot 4. Inspired by Cinemachine."
author="Marcus Skov"
version="0.9.3.1"
script="plugin.gd"

View File

@ -0,0 +1,181 @@
@tool
extends EditorPlugin
#region Constants
const PCAM_HOST: String = "PhantomCameraHost"
const PCAM_2D: String = "PhantomCamera2D"
const PCAM_3D: String = "PhantomCamera3D"
const PCAM_NOISE_EMITTER_2D: String = "PhantomCameraNoiseEmitter2D"
const PCAM_NOISE_EMITTER_3D: String = "PhantomCameraNoiseEmitter3D"
const PCam3DPlugin: Script = preload("res://addons/phantom_camera/scripts/gizmos/phantom_camera_3d_gizmo_plugin.gd")
const PCam3DNoiseEmitterPlugin: Script = preload("res://addons/phantom_camera/scripts/gizmos/phantom_camera_noise_emitter_gizmo_plugin_3d.gd")
const EditorPanel: PackedScene = preload("res://addons/phantom_camera/panel/editor.tscn")
const updater_constants: Script = preload("res://addons/phantom_camera/scripts/panel/updater/updater_constants.gd")
const PHANTOM_CAMERA_MANAGER: StringName = "PhantomCameraManager"
#endregion
#region Private Variables
var _settings_show_jitter_tips: String = "phantom_camera/tips/show_jitter_tips"
var _settings_enable_editor_shortcut: String = "phantom_camera/general/enable_editor_shortcut"
var _settings_editor_shortcut: String = "phantom_camera/general/editor_shortcut"
# TODO - Pending merge of https://github.com/godotengine/godot/pull/102889 - Should only support Godot version after the release that is featured in
#var _editor_shortcut: Shortcut = Shortcut.new()
#var _editor_shortcut_input: InputEventKey
#endregion
#region Public Variables
var pcam_3d_gizmo_plugin = PCam3DPlugin.new()
var pcam_3d_noise_emitter_gizmo_plugin = PCam3DNoiseEmitterPlugin.new()
var editor_panel_instance: Control
var panel_button: Button
#var viewfinder_panel_instance
#endregion
#region Private Functions
func _enable_plugin() -> void:
print_rich("Phantom Camera documentation can be found at: [url=https://phantom-camera.dev]https://phantom-camera.dev[/url]")
if not Engine.has_singleton(PHANTOM_CAMERA_MANAGER):
add_autoload_singleton(PHANTOM_CAMERA_MANAGER, "res://addons/phantom_camera/scripts/managers/phantom_camera_manager.gd")
func _disable_plugin() -> void:
remove_autoload_singleton(PHANTOM_CAMERA_MANAGER)
func _enter_tree() -> void:
add_autoload_singleton(PHANTOM_CAMERA_MANAGER, "res://addons/phantom_camera/scripts/managers/phantom_camera_manager.gd")
# Phantom Camera Nodes
add_custom_type(PCAM_2D, "Node2D", preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_2d.gd"), preload("res://addons/phantom_camera/icons/phantom_camera_2d.svg"))
add_custom_type(PCAM_3D, "Node3D", preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_3d.gd"), preload("res://addons/phantom_camera/icons/phantom_camera_2d.svg"))
add_custom_type(PCAM_HOST, "Node", preload("res://addons/phantom_camera/scripts/phantom_camera_host/phantom_camera_host.gd"), preload("res://addons/phantom_camera/icons/phantom_camera_2d.svg"))
add_custom_type(PCAM_NOISE_EMITTER_2D, "Node2D", preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_noise_emitter_2d.gd"), preload("res://addons/phantom_camera/icons/phantom_camera_noise_emitter_2d.svg"))
add_custom_type(PCAM_NOISE_EMITTER_3D, "Node3D", preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_noise_emitter_3d.gd"), preload("res://addons/phantom_camera/icons/phantom_camera_noise_emitter_3d.svg"))
# Phantom Camera 3D Gizmo
add_node_3d_gizmo_plugin(pcam_3d_gizmo_plugin)
add_node_3d_gizmo_plugin(pcam_3d_noise_emitter_gizmo_plugin)
var setting_updater_mode: String
var setting_updater_mode_default: int
if FileAccess.file_exists("res://dev_scenes/3d/dev_scene_3d.tscn"): # For forks
setting_updater_mode = "Off, Console Output"
setting_updater_mode_default = 1
else: # For end-users
setting_updater_mode = "Off, Console Output, Updater Window"
setting_updater_mode_default = 2
if not ProjectSettings.has_setting(updater_constants.setting_updater_mode):
ProjectSettings.set_setting(updater_constants.setting_updater_mode, setting_updater_mode_default)
ProjectSettings.add_property_info({
"name": updater_constants.setting_updater_mode,
"type": TYPE_INT,
"hint": PROPERTY_HINT_ENUM,
"hint_string": setting_updater_mode,
})
ProjectSettings.set_initial_value(updater_constants.setting_updater_mode, setting_updater_mode_default)
ProjectSettings.set_as_basic(updater_constants.setting_updater_mode, true)
## Setting for enabling / disabling Jitter tips in the Output
if not ProjectSettings.has_setting(_settings_show_jitter_tips):
ProjectSettings.set_setting(_settings_show_jitter_tips, true)
ProjectSettings.add_property_info({
"name": _settings_show_jitter_tips,
"type": TYPE_BOOL,
})
ProjectSettings.set_initial_value(_settings_show_jitter_tips, true)
ProjectSettings.set_as_basic(_settings_show_jitter_tips, true)
# TODO - Pending merge of https://github.com/godotengine/godot/pull/102889 - Should only support Godot version after this release
# if not ProjectSettings.has_setting(_settings_enable_editor_shortcut):
# ProjectSettings.set_setting(_settings_enable_editor_shortcut, false)
# ProjectSettings.set_initial_value(_settings_enable_editor_shortcut, false)
# TODO - Pending merge of https://github.com/godotengine/godot/pull/102889 - Should only support Godot version after this release
# _viewfinder_shortcut_default.events = [editor_shortcut]
# if ProjectSettings.get_setting(_settings_enable_editor_shortcut):
# if not ProjectSettings.has_setting(_settings_editor_shortcut):
# ProjectSettings.set_setting(_settings_editor_shortcut, _editor_shortcut)
# ProjectSettings.set_initial_value(_settings_editor_shortcut, _editor_shortcut)
# TODO - Should be disabled unless in editor
# Viewfinder
editor_panel_instance = EditorPanel.instantiate()
editor_panel_instance.editor_plugin = self
panel_button = add_control_to_bottom_panel(editor_panel_instance, "Phantom Camera")
panel_button.toggled.connect(_btn_toggled)
if panel_button.toggle_mode: _btn_toggled(true)
scene_changed.connect(editor_panel_instance.viewfinder.scene_changed)
scene_changed.connect(_scene_changed)
func _exit_tree() -> void:
panel_button.toggled.disconnect(_btn_toggled)
scene_changed.disconnect(editor_panel_instance.viewfinder.scene_changed)
scene_changed.disconnect(_scene_changed)
remove_control_from_bottom_panel(editor_panel_instance)
editor_panel_instance.queue_free()
remove_node_3d_gizmo_plugin(pcam_3d_gizmo_plugin)
remove_node_3d_gizmo_plugin(pcam_3d_noise_emitter_gizmo_plugin)
remove_custom_type(PCAM_2D)
remove_custom_type(PCAM_3D)
remove_custom_type(PCAM_HOST)
remove_custom_type(PCAM_NOISE_EMITTER_2D)
remove_custom_type(PCAM_NOISE_EMITTER_3D)
remove_autoload_singleton(PHANTOM_CAMERA_MANAGER)
# if get_tree().root.get_node_or_null(String(PHANTOM_CAMERA_MANAGER)):
# remove_autoload_singleton(PHANTOM_CAMERA_MANAGER)
func _btn_toggled(toggled_on: bool):
editor_panel_instance.viewfinder.set_visibility(toggled_on)
# if toggled_on:
# editor_panel_instance.viewfinder.viewfinder_visible = true
# editor_panel_instance.viewfinder.visibility_check()
# else:
# editor_panel_instance.viewfinder.viewfinder_visible = false
func _make_visible(visible):
if editor_panel_instance:
editor_panel_instance.set_visible(visible)
## TODO - Signal can be added directly to the editor_panel with the changes in Godot 4.5 (https://github.com/godotengine/godot/pull/102986)
func _scene_changed(scene_root: Node) -> void:
editor_panel_instance.viewfinder.scene_changed(scene_root)
# TODO - Pending merge of https://github.com/godotengine/godot/pull/102889 - Should only support Godot version after this release
#func _set_editor_shortcut() -> InputEventKey:
# var shortcut: InputEventKey = InputEventKey.new()
# shortcut.keycode = 67 # Key = C
# shortcut.alt_pressed = true
# return shortcut
#endregion
#region Public Functions
func get_version() -> String:
var config: ConfigFile = ConfigFile.new()
config.load(get_script().resource_path.get_base_dir() + "/plugin.cfg")
return config.get_value("plugin", "version")
#endregion

View File

@ -0,0 +1 @@
uid://c7g41in1osxi6

View File

@ -0,0 +1,84 @@
@tool
extends EditorNode3DGizmo
#var pcam_3d: PhantomCamera3D
func _redraw() -> void:
clear()
var icon: Material = get_plugin().get_material(get_plugin().get_name(), self)
add_unscaled_billboard(icon, 0.035)
var pcam_3d: PhantomCamera3D = get_node_3d()
# if pcam_3d.is_following():
# _draw_target(pcam_3d, pcam_3d.get_follow_target_position(), "follow_target")
# if pcam_3d.is_looking_at():
# _draw_target(pcam_3d, pcam_3d.get_look_at_target_position(), "look_at_target")
if pcam_3d.is_active(): return
var frustum_lines: PackedVector3Array = PackedVector3Array()
var height: float = 0.25
var width: float = height * 1.25
var forward: float = height * -1.5
# Trapezoid
frustum_lines.push_back(Vector3.ZERO)
frustum_lines.push_back(Vector3(-width, height, forward))
frustum_lines.push_back(Vector3.ZERO)
frustum_lines.push_back(Vector3(width, height, forward))
frustum_lines.push_back(Vector3.ZERO)
frustum_lines.push_back(Vector3(-width, -height, forward))
frustum_lines.push_back(Vector3.ZERO)
frustum_lines.push_back(Vector3(width, -height, forward))
#######
# Frame
#######
## Left
frustum_lines.push_back(Vector3(-width, height, forward))
frustum_lines.push_back(Vector3(-width, -height, forward))
## Bottom
frustum_lines.push_back(Vector3(-width, -height, forward))
frustum_lines.push_back(Vector3(width, -height, forward))
## Right
frustum_lines.push_back(Vector3(width, -height, forward))
frustum_lines.push_back(Vector3(width, height, forward))
## Top
frustum_lines.push_back(Vector3(width, height, forward))
frustum_lines.push_back(Vector3(-width, height, forward))
##############
# Up Direction
##############
var up_height: float = height + 0.15
var up_width: float = width / 3
## Left
frustum_lines.push_back(Vector3(0, up_height, forward))
frustum_lines.push_back(Vector3(-up_width, height, forward))
## Right
frustum_lines.push_back(Vector3(0, up_height, forward))
frustum_lines.push_back(Vector3(up_width, height, forward))
var frustum_material: StandardMaterial3D = get_plugin().get_material("frustum", self)
add_lines(frustum_lines, frustum_material, false)
func _draw_target(pcam_3d: Node3D, target_position: Vector3, type: String) -> void:
var target_lines: PackedVector3Array = PackedVector3Array()
var direction: Vector3 = target_position - pcam_3d.global_position
var end_position: Vector3 = pcam_3d.global_basis.z * direction
target_lines.push_back(Vector3.ZERO)
target_lines.push_back(end_position)
var target_material: StandardMaterial3D = get_plugin().get_material(type, self)
add_lines(target_lines, target_material, false)

View File

@ -0,0 +1 @@
uid://cyr6fgximfw6q

View File

@ -0,0 +1,37 @@
@tool
extends EditorNode3DGizmoPlugin
const PhantomCamera3DNode: Script = preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_3d.gd")
const PhantomCamera3DGizmo: Script = preload("res://addons/phantom_camera/scripts/gizmos/phantom_camera_3d_gizmo.gd")
const _icon_texture: Texture2D = preload("res://addons/phantom_camera/icons/phantom_camera_gizmo.svg")
var _gizmo_name: String = "PhantomCamera3D"
var gizmo_name: String: set = set_gizmo_name
var _gizmo_icon: Texture2D
var _gizmo_spatial_script: Script = PhantomCamera3DNode
func set_gizmo_name(name: String) -> void:
_gizmo_name = name
func _get_gizmo_name() -> String:
return _gizmo_name
func _has_gizmo(spatial: Node3D) -> bool:
return spatial is PhantomCamera3D
func _init() -> void:
create_icon_material(gizmo_name, _icon_texture, false, Color.WHITE)
create_material("frustum", Color8(252, 127, 127, 255))
create_material("follow_target", Color8(185, 58, 89))
create_material("look_at_target", Color8(61, 207, 225))
func _create_gizmo(for_node_3d: Node3D) -> EditorNode3DGizmo:
if for_node_3d is PhantomCamera3DNode:
return PhantomCamera3DGizmo.new()
else:
return null

View File

@ -0,0 +1 @@
uid://bkevga3bx4rfj

View File

@ -0,0 +1,29 @@
extends EditorNode3DGizmoPlugin
var _spatial_script: Script = preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_noise_emitter_3d.gd")
var _gizmo_icon: Texture2D = preload("res://addons/phantom_camera/icons/phantom_camera_noise_emitter_gizmo.svg")
var _gizmo_name: StringName = "PhantomCameraNoiseEmitter"
func _init() -> void:
create_material("main", Color8(252, 127, 127, 255))
create_handle_material("handles")
create_icon_material(_gizmo_name, _gizmo_icon, false, Color.WHITE)
func _has_gizmo(node: Node3D):
return node.get_script() == _spatial_script
func _get_gizmo_name() -> String:
return _gizmo_name
func _redraw(gizmo: EditorNode3DGizmo):
gizmo.clear()
var icon: Material = get_material(_gizmo_name, gizmo)
gizmo.add_unscaled_billboard(icon, 0.035)
#var material = get_material("main", gizmo)
#gizmo.add_lines(_draw_frustum(), material)

View File

@ -0,0 +1 @@
uid://dddokcd2ug05i

View File

@ -0,0 +1,36 @@
using System.Linq;
using Godot;
#nullable enable
namespace PhantomCamera.Manager;
public static class PhantomCameraManager
{
private static GodotObject? _instance;
public static GodotObject Instance => _instance ??= Engine.GetSingleton("PhantomCameraManager");
public static PhantomCamera2D[] PhantomCamera2Ds =>
Instance.Call(MethodName.GetPhantomCamera2Ds).AsGodotArray<Node2D>()
.Select(node => new PhantomCamera2D(node)).ToArray();
public static PhantomCamera3D[] PhantomCamera3Ds =>
Instance.Call(MethodName.GetPhantomCamera3Ds).AsGodotArray<Node3D>()
.Select(node => new PhantomCamera3D(node)).ToArray();
public static PhantomCameraHost[] PhantomCameraHosts =>
Instance.Call(MethodName.GetPhantomCameraHosts).AsGodotArray<Node>()
.Select(node => new PhantomCameraHost(node)).ToArray();
public static PhantomCamera2D[] GetPhantomCamera2Ds() => PhantomCamera2Ds;
public static PhantomCamera3D[] GetPhantomCamera3Ds() => PhantomCamera3Ds;
public static PhantomCameraHost[] GetPhantomCameraHosts() => PhantomCameraHosts;
public static class MethodName
{
public const string GetPhantomCamera2Ds = "get_phantom_camera_2ds";
public const string GetPhantomCamera3Ds = "get_phantom_camera_3ds";
public const string GetPhantomCameraHosts = "get_phantom_camera_hosts";
}
}

View File

@ -0,0 +1 @@
uid://vtj8iqx4bp43

View File

@ -0,0 +1,149 @@
@tool
extends Node
const _CONSTANTS = preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_constants.gd")
#region Signals
# Noise
signal noise_2d_emitted(noise_output: Transform2D, emitter_layer: int)
signal noise_3d_emitted(noise_output: Transform3D, emitter_layer: int)
# PCam Host
signal pcam_host_added_to_scene(pcam_host: PhantomCameraHost)
signal pcam_host_removed_from_scene(pcam_host: PhantomCameraHost)
# PCam
signal pcam_added_to_scene(pcam: Node)
signal pcam_removed_from_scene(pcam: Node)
# Priority
signal pcam_priority_changed(pcam: Node)
signal pcam_visibility_changed(pcam: Node)
signal pcam_teleport(pcam: Node)
# Limit (2D)
signal limit_2d_changed(side: int, limit: int)
signal draw_limit_2d(enabled: bool)
# Camera3DResource (3D)
signal camera_3d_resource_changed(property: String, value: Variant)
# Viewfinder Signals
signal viewfinder_pcam_host_switch(pcam_host: PhantomCameraHost)
signal pcam_priority_override(pcam: Node, shouldOverride: bool)
signal pcam_dead_zone_changed(pcam: Node)
signal pcam_host_layer_changed(pcam: Node)
#endregion
#region Private Variables
var _phantom_camera_host_list: Array[PhantomCameraHost]
var _phantom_camera_2d_list: Array[PhantomCamera2D]
var _phantom_camera_3d_list: Array[Node] ## Note: To support disable_3d export templates for 2D projects, this is purposely not strongly typed.
#endregion
#region Public Variables
var phantom_camera_hosts: Array[PhantomCameraHost]:
get:
return _phantom_camera_host_list
var phantom_camera_2ds: Array[PhantomCamera2D]:
get:
return _phantom_camera_2d_list
var phantom_camera_3ds: Array[Node]: ## Note: To support disable_3d export templates for 2D projects, this is purposely not strongly typed.
get:
return _phantom_camera_3d_list
var screen_size: Vector2i
#endregion
#region Private Functions
func _enter_tree() -> void:
if not Engine.has_singleton(_CONSTANTS.PCAM_MANAGER_NODE_NAME):
Engine.register_singleton(_CONSTANTS.PCAM_MANAGER_NODE_NAME, self)
Engine.physics_jitter_fix = 0
func _ready() -> void:
# Setting default screensize
screen_size = Vector2i(
ProjectSettings.get_setting("display/window/size/viewport_width"),
ProjectSettings.get_setting("display/window/size/viewport_height")
)
# For editor
if Engine.is_editor_hint():
ProjectSettings.settings_changed.connect(func():
screen_size = Vector2i(
ProjectSettings.get_setting("display/window/size/viewport_width"),
ProjectSettings.get_setting("display/window/size/viewport_height")
)
)
# For runtime
else:
get_tree().get_root().size_changed.connect(func():
screen_size = get_viewport().get_visible_rect().size
)
#endregion
#region Public Functions
func pcam_host_added(caller: Node) -> void:
if is_instance_of(caller, PhantomCameraHost):
_phantom_camera_host_list.append(caller)
pcam_host_added_to_scene.emit(caller)
else:
printerr("This method can only be called from a PhantomCameraHost node")
func pcam_host_removed(caller: Node) -> void:
if is_instance_of(caller, PhantomCameraHost):
_phantom_camera_host_list.erase(caller)
pcam_host_removed_from_scene.emit(caller)
else:
printerr("This method can only be called from a PhantomCameraHost node")
func pcam_added(caller) -> void:
if is_instance_of(caller, PhantomCamera2D):
_phantom_camera_2d_list.append(caller)
pcam_added_to_scene.emit(caller)
elif caller.is_class("PhantomCamera3D"): ## Note: To support disable_3d export templates for 2D projects, this is purposely not strongly typed.
_phantom_camera_3d_list.append(caller)
pcam_added_to_scene.emit(caller)
func pcam_removed(caller) -> void:
if is_instance_of(caller, PhantomCamera2D):
_phantom_camera_2d_list.erase(caller)
pcam_removed_from_scene.emit(caller)
elif caller.is_class("PhantomCamera3D"): ## Note: To support disable_3d export templates for 2D projects, this is purposely not strongly typed.
_phantom_camera_3d_list.erase(caller)
pcam_removed_from_scene.emit(caller)
else:
printerr("This method can only be called from a PhantomCamera node")
func get_phantom_camera_hosts() -> Array[PhantomCameraHost]:
return _phantom_camera_host_list
func get_phantom_camera_2ds() -> Array[PhantomCamera2D]:
return _phantom_camera_2d_list
func get_phantom_camera_3ds() -> Array: ## Note: To support disable_3d export templates for 2D projects, this is purposely not strongly typed.
return _phantom_camera_3d_list
func scene_changed() -> void:
_phantom_camera_2d_list.clear()
_phantom_camera_3d_list.clear()
_phantom_camera_host_list.clear()
#endregion

View File

@ -0,0 +1 @@
uid://duq6jhf6unyis

View File

@ -0,0 +1,23 @@
@tool
extends VBoxContainer
#region Onready
@onready var updater: Control = %UpdateButton
@onready var viewfinder: Control = %ViewfinderPanel
#endregion
#region Public Variables
var editor_plugin: EditorPlugin
#endregion
#region Private Functions
func _ready():
updater.editor_plugin = editor_plugin
#endregion

View File

@ -0,0 +1 @@
uid://cgfwg3paxkj2x

View File

@ -0,0 +1,162 @@
#######################################################################
# Credit goes to the Dialogue Manager plugin for this script
# Check it out at: https://github.com/nathanhoad/godot_dialogue_manager
#######################################################################
@tool
extends Control
#region Constants
const TEMP_FILE_NAME = "user://temp.zip"
#endregion
#region Signals
signal failed()
signal updated(updated_to_version: String)
#endregion
#region @onready
#@onready var logo: TextureRect = %Logo
@onready var _download_verion: Label = %DownloadVersionLabel
@onready var _download_http_request: HTTPRequest = %DownloadHTTPRequest
@onready var _download_button: Button = %DownloadButton
@onready var _download_button_bg: NinePatchRect = %DownloadButtonBG
@onready var _download_label: Label = %UpdateLabel
@onready var _breaking_label: Label = %BreakingLabel
@onready var _breaking_margin_container: MarginContainer = %BreakingMarginContainer
@onready var _breaking_options_button: OptionButton = %BreakingOptionButton
#@onready var current_version_label: Label = %CurrentVersionLabel
#endregion
#region Variables
# Todo - For 4.2 upgrade - Shows current version
var _download_dialogue: AcceptDialog
var _button_texture_default: Texture2D = load("res://addons/phantom_camera/assets/PhantomCameraBtnPrimaryDefault.png")
var _button_texture_hover: Texture2D = load("res://addons/phantom_camera/assets/PhantomCameraBtnPrimaryHover.png")
var next_version_release: Dictionary:
set(value):
next_version_release = value
_download_verion.text = "%s update is available for download" % value.tag_name.substr(1)
# Todo - For 4.2 upgrade
#current_version_label.text = "Current version is " + editor_plugin.get_version()
get:
return next_version_release
var _breaking_window_height: float = 520
var _breaking_window_height_update: float = 600
#endregion
#region Private Functions
func _ready() -> void:
_download_http_request.request_completed.connect(_on_http_request_request_completed)
_download_button.pressed.connect(_on_download_button_pressed)
_download_button.mouse_entered.connect(_on_mouse_entered)
_download_button.mouse_exited.connect(_on_mouse_exited)
_breaking_label.hide()
_breaking_margin_container.hide()
_breaking_options_button.hide()
_breaking_options_button.item_selected.connect(_on_item_selected)
func _on_item_selected(index: int) -> void:
if index == 1:
_download_button.show()
_download_dialogue.size = Vector2(_download_dialogue.size.x, _breaking_window_height_update)
else:
_download_button.hide()
_download_dialogue.size = Vector2(_download_dialogue.size.x, _breaking_window_height)
func _on_download_button_pressed() -> void:
_download_http_request.request(next_version_release.zipball_url)
_download_button.disabled = true
_download_label.text = "Downloading..."
_download_button_bg.hide()
func _on_mouse_entered() -> void:
_download_button_bg.set_texture(_button_texture_hover)
func _on_mouse_exited() -> void:
_download_button_bg.set_texture(_button_texture_default)
func _on_http_request_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void:
if result != HTTPRequest.RESULT_SUCCESS:
failed.emit()
return
# Save the downloaded zip
var zip_file: FileAccess = FileAccess.open(TEMP_FILE_NAME, FileAccess.WRITE)
zip_file.store_buffer(body)
zip_file.close()
OS.move_to_trash(ProjectSettings.globalize_path("res://addons/phantom_camera"))
var zip_reader: ZIPReader = ZIPReader.new()
zip_reader.open(TEMP_FILE_NAME)
var files: PackedStringArray = zip_reader.get_files()
var base_path = files[1]
# Remove archive folder
files.remove_at(0)
# Remove assets folder
files.remove_at(0)
for path in files:
var new_file_path: String = path.replace(base_path, "")
if path.ends_with("/"):
DirAccess.make_dir_recursive_absolute("res://addons/%s" % new_file_path)
else:
var file: FileAccess = FileAccess.open("res://addons/%s" % new_file_path, FileAccess.WRITE)
file.store_buffer(zip_reader.read_file(path))
zip_reader.close()
DirAccess.remove_absolute(TEMP_FILE_NAME)
updated.emit(next_version_release.tag_name.substr(1))
func _on_notes_button_pressed() -> void:
OS.shell_open(next_version_release.html_url)
#endregion
#region Public Functions
func show_updater_warning(next_version_number: Array, current_version_number: Array) -> void:
var current_version_number_0: int = current_version_number[0] as int
var current_version_number_1: int = current_version_number[1] as int
var next_version_number_0: int = next_version_number[0] as int # Major release number in the new release
var next_version_number_1: int = next_version_number[1] as int # Minor release number in the new release
if next_version_number_0 > current_version_number_0 or \
next_version_number_1 > current_version_number_1:
_breaking_label.show()
_breaking_margin_container.show()
_breaking_options_button.show()
_download_button.hide()
_download_dialogue = get_parent()
_download_dialogue.size = Vector2(_download_dialogue.size.x, _breaking_window_height)
#endregion

View File

@ -0,0 +1 @@
uid://cjblcocen12r3

View File

@ -0,0 +1,177 @@
#######################################################################
# Credit goes to the Dialogue Manager plugin for this script
# Check it out at: https://github.com/nathanhoad/godot_dialogue_manager
#######################################################################
@tool
extends Button
#region Constants
const REMOTE_RELEASE_URL: StringName = "https://api.github.com/repos/ramokz/phantom-camera/releases"
const UPDATER_CONSTANTS := preload("res://addons/phantom_camera/scripts/panel/updater/updater_constants.gd")
#endregion
#region @onready
@onready var http_request: HTTPRequest = %HTTPRequest
@onready var download_dialog: AcceptDialog = %DownloadDialog
@onready var download_update_panel: Control = %DownloadUpdatePanel
@onready var needs_reload_dialog: AcceptDialog = %NeedsReloadDialog
@onready var update_failed_dialog: AcceptDialog = %UpdateFailedDialog
#endregion
#region Variables
# The main editor plugin
var editor_plugin: EditorPlugin
var needs_reload: bool = false
# A lambda that gets called just before refreshing the plugin. Return false to stop the reload.
var on_before_refresh: Callable = func(): return true
#endregion
#region Private Functions
func _ready() -> void:
hide()
# Check for updates on GitHub Releases
check_for_update()
pressed.connect(_on_update_button_pressed)
http_request.request_completed.connect(_request_request_completed)
download_update_panel.updated.connect(_on_download_update_panel_updated)
needs_reload_dialog.confirmed.connect(_on_needs_reload_dialog_confirmed)
func _request_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void:
if result != HTTPRequest.RESULT_SUCCESS: return
if not editor_plugin: return
var current_version: String = editor_plugin.get_version()
# Work out the next version from the releases information on GitHub
var response: Array = JSON.parse_string(body.get_string_from_utf8())
if typeof(response) != TYPE_ARRAY: return
# GitHub releases are in order of creation, not order of version
var versions: Array = response.filter(func(release):
var version: String = release.tag_name.substr(1)
return version_to_number(version) > version_to_number(current_version)
)
if versions.size() > 0:
if ProjectSettings.get_setting(UPDATER_CONSTANTS.setting_updater_mode) == 1: ## For console output mode
print_rich("
[color=#3AB99A] ********[/color]
[color=#3AB99A] ************[/color]
[color=#3AB99A]**************[/color]
[color=#3AB99A]****** *** *[/color]
[color=#3AB99A]****** ***[/color]
[color=#3AB99A]********** *****[/color]
[color=#3AB99A]******** ***********[/color]
[color=#3AB99A]******** *********** **[/color]
[color=#3AB99A]********* **************[/color]
[color=#3AB99A]********** *************[/color]
[color=#3AB99A]** ** ** ******* **[/color]
[font_size=18][b]New Phantom Camera version is available[/b][/font_size]")
if FileAccess.file_exists("res://dev_scenes/3d/dev_scene_3d.tscn"):
print_rich("[font_size=14][color=#EAA15E][b]As you're using a fork of the project, you will need to update it manually[/b][/color][/font_size]")
print_rich("[font_size=12]If you don't want to see this message, then it can be disabled inside:\n[code]Project Settings/Phantom Camera/Updater/Show New Release Info on Editor Launch in Output[/code]")
return
download_update_panel.next_version_release = versions[0]
download_update_panel.show_updater_warning(
versions[0].tag_name.substr(1).split("."),
current_version.split(".")
)
_set_scale()
editor_plugin.panel_button.add_theme_color_override("font_color", Color("#3AB99A"))
editor_plugin.panel_button.icon = load("res://addons/phantom_camera/icons/phantom_camera_updater_panel_icon.svg")
editor_plugin.panel_button.add_theme_color_override("icon_normal_color", Color("#3AB99A"))
show()
func _on_update_button_pressed() -> void:
if needs_reload:
var will_refresh = on_before_refresh.call()
if will_refresh:
EditorInterface.restart_editor(true)
else:
_set_scale()
download_dialog.popup_centered()
func _set_scale() -> void:
var scale: float = EditorInterface.get_editor_scale()
download_dialog.min_size = Vector2(300, 250) * scale
func _on_download_dialog_close_requested() -> void:
download_dialog.hide()
func _on_download_update_panel_updated(updated_to_version: String) -> void:
download_dialog.hide()
needs_reload_dialog.dialog_text = "Reload to finish update"
needs_reload_dialog.ok_button_text = "Reload"
needs_reload_dialog.cancel_button_text = "Cancel"
needs_reload_dialog.popup_centered()
needs_reload = true
text = "Reload Project"
func _on_download_update_panel_failed() -> void:
download_dialog.hide()
update_failed_dialog.dialog_text = "Updated Failed"
update_failed_dialog.popup_centered()
func _on_needs_reload_dialog_confirmed() -> void:
EditorInterface.restart_editor(true)
func _on_timer_timeout() -> void:
if not needs_reload:
check_for_update()
#endregion
#region Public Functions
# Convert a version number to an actually comparable number
func version_to_number(version: String) -> int:
var regex = RegEx.new()
regex.compile("[a-zA-Z]+")
if regex.search(str(version)): return 0
var bits = version.split(".")
var version_bit: int
var multiplier: int = 10000
for i in bits.size():
version_bit += bits[i].to_int() * multiplier / (10 ** (i))
return version_bit
func check_for_update() -> void:
if ProjectSettings.get_setting(UPDATER_CONSTANTS.setting_updater_mode) == 0: return
http_request.request(REMOTE_RELEASE_URL)
#endregion

View File

@ -0,0 +1 @@
uid://bwc42i46603qn

View File

@ -0,0 +1,8 @@
extends RefCounted
# Plugin Project Settings Sections
const setting_phantom_camera: StringName = "phantom_camera/"
const setting_updater_name: StringName = setting_phantom_camera + "updater/"
# Updater Settings
const setting_updater_mode: StringName = setting_updater_name + "updater_mode"

View File

@ -0,0 +1 @@
uid://c8qkbc38waor2

View File

@ -0,0 +1,112 @@
@tool
extends VBoxContainer
#region Constants
const _constants := preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_constants.gd")
const _host_list_item: PackedScene = preload("res://addons/phantom_camera/panel/viewfinder/host_list/host_list_item.tscn")
#endregion
signal pcam_host_removed(pcam_host: PhantomCameraHost)
@onready var _host_list_button: Button = %HostListButton
@onready var _host_list_scroll_container: ScrollContainer = %ScrollContainer
@onready var _host_list_item_container: VBoxContainer = %HostListContainer
var _host_list_open: bool = false
var _bottom_offset_value: float
var _pcam_host_list: Array[PhantomCameraHost]
var _pcam_manager: Node
var _viewfinder_panel: Control
#region Private Functions
func _ready() -> void:
_host_list_button.pressed.connect(_host_list_button_pressed)
if Engine.has_singleton(_constants.PCAM_MANAGER_NODE_NAME):
_pcam_manager = Engine.get_singleton(_constants.PCAM_MANAGER_NODE_NAME)
_pcam_manager.pcam_host_removed_from_scene.connect(_remove_pcam_host)
if not get_parent() is Control: return # To prevent errors when opening the scene on its own
_viewfinder_panel = get_parent()
_viewfinder_panel.resized.connect(_set_offset_top)
_host_list_item_container.resized.connect(_set_offset_top)
func _set_offset_top() -> void:
offset_top = _set_host_list_size()
func _host_list_button_pressed() -> void:
_host_list_open = !_host_list_open
var tween: Tween = create_tween()
var max_duration: float = 0.6
# 300 being the minimum size of the viewfinder's height
var duration: float = clampf(
max_duration / (300 / _host_list_item_container.size.y),
0.3,
max_duration)
tween.tween_property(self, "offset_top", _set_host_list_size(), duration)\
.set_ease(Tween.EASE_OUT)\
.set_trans(Tween.TRANS_QUINT)
func _set_host_list_size() -> float:
if not _host_list_open:
return clampf(
_viewfinder_panel.size.y - \
_host_list_item_container.size.y - \
_host_list_button.size.y - 20,
0,
INF
)
else:
return (_viewfinder_panel.size.y - _host_list_button.size.y / 2)
func _remove_pcam_host(pcam_host: PhantomCameraHost) -> void:
if _pcam_host_list.has(pcam_host):
_pcam_host_list.erase(pcam_host)
var freed_pcam_host: Control
for host_list_item_instance in _host_list_item_container.get_children():
if not host_list_item_instance.pcam_host == pcam_host: continue
freed_pcam_host = host_list_item_instance
host_list_item_instance.queue_free()
#endregion
#region Public Functions
func add_pcam_host(pcam_host: PhantomCameraHost, is_default: bool) -> void:
if _pcam_host_list.has(pcam_host): return
_pcam_host_list.append(pcam_host)
var host_list_item_instance: PanelContainer = _host_list_item.instantiate()
var switch_pcam_host_button: Button = host_list_item_instance.get_node("%SwitchPCamHost")
if is_default: switch_pcam_host_button.button_pressed = true
if not pcam_host.tree_exiting.is_connected(_remove_pcam_host):
pcam_host.tree_exiting.connect(_remove_pcam_host.bind(pcam_host))
host_list_item_instance.pcam_host = pcam_host
_host_list_item_container.add_child(host_list_item_instance)
func clear_pcam_host_list() -> void:
_pcam_host_list.clear()
for host_list_item_instance in _host_list_item_container.get_children():
host_list_item_instance.queue_free()
#endregion

View File

@ -0,0 +1 @@
uid://c84cxry3t35ny

View File

@ -0,0 +1,58 @@
@tool
extends Control
const button_group_resource: ButtonGroup = preload("res://addons/phantom_camera/panel/viewfinder/host_list/host_list_item_group.tres")
const _constants = preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_constants.gd")
@onready var select_pcam_host: Button = %SelectPCamHost
@onready var switch_pcam_host: Button = %SwitchPCamHost
var pcam_host: PhantomCameraHost:
set(value):
pcam_host = value
if not is_instance_valid(value): return
if not pcam_host.renamed.is_connected(_rename_pcam_host):
pcam_host.renamed.connect(_rename_pcam_host)
pcam_host.has_error.connect(_pcam_host_has_error)
get:
return pcam_host
var _pcam_manager: Node
#region Private fucntions
func _ready() -> void:
switch_pcam_host.button_group = button_group_resource
select_pcam_host.pressed.connect(_select_pcam)
switch_pcam_host.pressed.connect(_switch_pcam_host)
if not is_instance_valid(pcam_host): return
switch_pcam_host.text = pcam_host.name
_pcam_host_has_error()
func _pcam_host_has_error() -> void:
if pcam_host.show_warning:
%ErrorPCamHost.visible = true
else:
%ErrorPCamHost.visible = false
func _rename_pcam_host() -> void:
switch_pcam_host.text = pcam_host.name
func _select_pcam() -> void:
EditorInterface.get_selection().clear()
EditorInterface.get_selection().add_node(pcam_host)
func _switch_pcam_host() -> void:
if not Engine.has_singleton(_constants.PCAM_MANAGER_NODE_NAME): return
if not is_instance_valid(_pcam_manager):
_pcam_manager = Engine.get_singleton(_constants.PCAM_MANAGER_NODE_NAME)
_pcam_manager.viewfinder_pcam_host_switch.emit(pcam_host)
#endregion

View File

@ -0,0 +1 @@
uid://bv24ubx8mutw7

View File

@ -0,0 +1,605 @@
@tool
extends Control
#region Constants
const _constants = preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_constants.gd")
# TODO - Should be in a central location
const _camera_2d_icon: CompressedTexture2D = preload("res://addons/phantom_camera/icons/viewfinder/Camera2DIcon.svg")
const _camera_3d_icon: CompressedTexture2D = preload("res://addons/phantom_camera/icons/viewfinder/Camera3DIcon.svg")
const _pcam_host_icon: CompressedTexture2D = preload("res://addons/phantom_camera/icons/phantom_camera_host.svg")
const _pcam_2D_icon: CompressedTexture2D = preload("res://addons/phantom_camera/icons/phantom_camera_2d.svg")
const _pcam_3D_icon: CompressedTexture2D = preload("res://addons/phantom_camera/icons/phantom_camera_3d.svg")
const _overlay_color_alpha: float = 0.3
#endregion
#region @onready
@onready var dead_zone_center_hbox: VBoxContainer = %DeadZoneCenterHBoxContainer
@onready var dead_zone_center_center_panel: Panel = %DeadZoneCenterCenterPanel
@onready var dead_zone_left_center_panel: Panel = %DeadZoneLeftCenterPanel
@onready var dead_zone_right_center_panel: Panel = %DeadZoneRightCenterPanel
@onready var target_point: Panel = %TargetPoint
@onready var aspect_ratio_container: AspectRatioContainer = %AspectRatioContainer
@onready var camera_viewport_panel: Panel = aspect_ratio_container.get_child(0)
@onready var _viewfinder: Control = %Viewfinder
@onready var _dead_zone_h_box_container: Control = %DeadZoneHBoxContainer
@onready var sub_viewport: SubViewport = %SubViewport
@onready var _empty_state_control: Control = %EmptyStateControl
@onready var _empty_state_icon: TextureRect = %EmptyStateIcon
@onready var _empty_state_text: RichTextLabel = %EmptyStateText
@onready var _add_node_button: Button = %AddNodeButton
@onready var _add_node_button_text: RichTextLabel = %AddNodeTypeText
@onready var _priority_override_button: Button = %PriorityOverrideButton
@onready var _priority_override_name_label: Label = %PriorityOverrideNameLabel
@onready var _camera_2d: Camera2D = %Camera2D
@onready var _pcam_host_list: VBoxContainer = %PCamHostList
#endregion
#region Private Variables
var _no_open_scene_icon: CompressedTexture2D = preload("res://addons/phantom_camera/icons/viewfinder/SceneTypesIcon.svg")
var _no_open_scene_string: String = "[b]2D[/b] or [b]3D[/b] scene open"
var _selected_camera: Node
var _active_pcam: Node
var _is_2d: bool
var _pcam_manager: Node
var _root_node: Node
#endregion
#region Public Variables
var pcam_host_group: Array[PhantomCameraHost]
var is_scene: bool
var viewfinder_visible: bool
var min_horizontal: float
var max_horizontal: float
var min_vertical: float
var max_vertical: float
var pcam_host: PhantomCameraHost
#endregion
#region Private Functions
func _ready() -> void:
if not Engine.is_editor_hint():
set_process(true)
camera_viewport_panel.self_modulate.a = 0
_root_node = get_tree().current_scene
if _root_node is Node2D || _root_node is Node3D:
%SubViewportContainer.visible = false
if _root_node is Node2D:
_is_2d = true
else:
_is_2d = false
_set_viewfinder(_root_node, false)
if not Engine.is_editor_hint():
_empty_state_control.visible = false
_priority_override_button.visible = false
# Triggered when viewport size is changed in Project Settings
ProjectSettings.settings_changed.connect(_settings_changed)
# PCam Host List
_pcam_host_list.visible = false
_assign_manager()
_visibility_check()
func _pcam_host_switch(new_pcam_host: PhantomCameraHost) -> void:
_set_viewfinder_camera(new_pcam_host, true)
func _exit_tree() -> void:
if aspect_ratio_container.resized.is_connected(_resized):
aspect_ratio_container.resized.disconnect(_resized)
if _add_node_button.pressed.is_connected(_visibility_check):
_add_node_button.pressed.disconnect(_visibility_check)
if is_instance_valid(_active_pcam):
if _active_pcam.dead_zone_changed.is_connected(_on_dead_zone_changed):
_active_pcam.dead_zone_changed.disconnect(_on_dead_zone_changed)
if _priority_override_button.pressed.is_connected(_select_override_pcam):
_priority_override_button.pressed.disconnect(_select_override_pcam)
func _process(_delta: float) -> void:
if Engine.is_editor_hint() and not viewfinder_visible: return
if not is_instance_valid(_active_pcam): return
var unprojected_position_clamped: Vector2 = Vector2(
clamp(_active_pcam.viewport_position.x, min_horizontal, max_horizontal),
clamp(_active_pcam.viewport_position.y, min_vertical, max_vertical)
)
if not Engine.is_editor_hint():
target_point.position = camera_viewport_panel.size * unprojected_position_clamped - target_point.size / 2
if not _is_2d: return
if not is_instance_valid(pcam_host): return
if not is_instance_valid(pcam_host.camera_2d): return
var window_size_height: float = ProjectSettings.get_setting("display/window/size/viewport_height")
sub_viewport.size_2d_override = sub_viewport.size * (window_size_height / sub_viewport.size.y)
_camera_2d.global_transform = pcam_host.camera_2d.global_transform
_camera_2d.offset = pcam_host.camera_2d.offset
_camera_2d.zoom = pcam_host.camera_2d.zoom
_camera_2d.ignore_rotation = pcam_host.camera_2d.ignore_rotation
_camera_2d.anchor_mode = pcam_host.camera_2d.anchor_mode
_camera_2d.limit_left = pcam_host.camera_2d.limit_left
_camera_2d.limit_top = pcam_host.camera_2d.limit_top
_camera_2d.limit_right = pcam_host.camera_2d.limit_right
_camera_2d.limit_bottom = pcam_host.camera_2d.limit_bottom
func _settings_changed() -> void:
var viewport_width: float = ProjectSettings.get_setting("display/window/size/viewport_width")
var viewport_height: float = ProjectSettings.get_setting("display/window/size/viewport_height")
var ratio: float = viewport_width / viewport_height
aspect_ratio_container.set_ratio(ratio)
camera_viewport_panel.size.x = viewport_width / (viewport_height / sub_viewport.size.y)
# Applies Project Settings to Viewport
sub_viewport.canvas_item_default_texture_filter = ProjectSettings.get_setting("rendering/textures/canvas_textures/default_texture_filter")
# TODO - Add resizer for Framed Viewfinder
func _visibility_check() -> void:
if not viewfinder_visible: return
var pcam_host: PhantomCameraHost
var has_camera: bool = false
if not Engine.has_singleton(_constants.PCAM_MANAGER_NODE_NAME): return
if not Engine.get_singleton(_constants.PCAM_MANAGER_NODE_NAME).get_phantom_camera_hosts().is_empty():
has_camera = true
pcam_host = Engine.get_singleton(_constants.PCAM_MANAGER_NODE_NAME).get_phantom_camera_hosts()[0]
var root: Node = EditorInterface.get_edited_scene_root()
if root is Node2D:
var camera_2d: Camera2D
if has_camera:
camera_2d = pcam_host.camera_2d
else:
camera_2d = _get_camera_2d()
_is_2d = true
is_scene = true
_add_node_button.visible = true
_check_camera(root, camera_2d)
elif root is Node3D:
var camera_3d: Camera3D
if has_camera:
camera_3d = pcam_host.camera_3d
elif root.get_viewport() != null:
if root.get_viewport().get_camera_3d() != null:
camera_3d = root.get_viewport().get_camera_3d()
_is_2d = false
is_scene = true
_add_node_button.visible = true
_check_camera(root, camera_3d)
else:
# Is not a 2D or 3D scene
is_scene = false
_set_empty_viewfinder_state(_no_open_scene_string, _no_open_scene_icon)
_add_node_button.visible = false
# Checks if a new scene is created and changes viewfinder accordingly
if not get_tree().node_added.is_connected(_node_added_to_scene):
get_tree().node_added.connect(_node_added_to_scene)
if not _priority_override_button.pressed.is_connected(_select_override_pcam):
_priority_override_button.pressed.connect(_select_override_pcam)
func _node_added_to_scene(node: Node) -> void:
if node is Node2D or node is Node3D:
get_tree().node_added.disconnect(_node_added_to_scene)
_visibility_check()
func _get_camera_2d() -> Camera2D:
var edited_scene_root: Node = EditorInterface.get_edited_scene_root()
if edited_scene_root == null: return null
var viewport: Viewport = edited_scene_root.get_viewport()
if viewport == null: return null
var viewport_rid: RID = viewport.get_viewport_rid()
if viewport_rid == null: return null
var camerasGroupName: String = "__cameras_%d" % viewport_rid.get_id()
var cameras: Array[Node] = get_tree().get_nodes_in_group(camerasGroupName)
for camera in cameras:
if camera is Camera2D and camera.is_current:
return camera
return null
func _check_camera(root: Node, camera: Node) -> void:
var camera_string: String
var pcam_string: String
var color: Color
var camera_icon: CompressedTexture2D
var pcam_icon: CompressedTexture2D
if _is_2d:
camera_string = _constants.CAMERA_2D_NODE_NAME
pcam_string = _constants.PCAM_2D_NODE_NAME
color = _constants.COLOR_2D
camera_icon = _camera_2d_icon
pcam_icon = _pcam_2D_icon
else:
camera_string = _constants.CAMERA_3D_NODE_NAME
pcam_string = _constants.PCAM_3D_NODE_NAME
color = _constants.COLOR_3D
camera_icon = _camera_3d_icon
pcam_icon = _pcam_3D_icon
if camera:
# Has Camera
if camera.get_children().size() > 0:
for cam_child in camera.get_children():
if cam_child is PhantomCameraHost:
pcam_host = cam_child
if pcam_host:
if get_tree().root.get_node(_constants.PCAM_MANAGER_NODE_NAME).get_phantom_camera_2ds() or \
get_tree().root.get_node(_constants.PCAM_MANAGER_NODE_NAME).get_phantom_camera_3ds():
# Pcam exists in tree
_set_viewfinder(root, true)
_set_viewfinder_state()
%NoSupportMsg.visible = false
else:
# No PCam in scene
_update_button(pcam_string, pcam_icon, color)
_set_empty_viewfinder_state(pcam_string, pcam_icon)
else:
# No PCamHost in scene
_update_button(_constants.PCAM_HOST_NODE_NAME, _pcam_host_icon, _constants.PCAM_HOST_COLOR)
_set_empty_viewfinder_state(_constants.PCAM_HOST_NODE_NAME, _pcam_host_icon)
else:
# No PCamHost in scene
_update_button(_constants.PCAM_HOST_NODE_NAME, _pcam_host_icon, _constants.PCAM_HOST_COLOR)
_set_empty_viewfinder_state(_constants.PCAM_HOST_NODE_NAME, _pcam_host_icon)
else:
# No Camera
_update_button(camera_string, camera_icon, color)
_set_empty_viewfinder_state(camera_string, camera_icon)
func _update_button(text: String, icon: CompressedTexture2D, color: Color) -> void:
_add_node_button_text.set_text("[center]Add [img=32]" + icon.resource_path + "[/img] [b]"+ text + "[/b][/center]");
var button_theme_hover: StyleBoxFlat = _add_node_button.get_theme_stylebox("hover")
button_theme_hover.border_color = color
_add_node_button.add_theme_stylebox_override("hover", button_theme_hover)
func _set_viewfinder_state() -> void:
_empty_state_control.visible = false
_viewfinder.visible = true
if is_instance_valid(_active_pcam):
if _active_pcam.get_follow_mode() == _active_pcam.FollowMode.FRAMED:
_dead_zone_h_box_container.visible = true
target_point.visible = true
else:
_dead_zone_h_box_container.visible = false
target_point.visible = false
func _set_empty_viewfinder_state(text: String, icon: CompressedTexture2D) -> void:
_viewfinder.visible = false
_framed_view_visible(false)
_empty_state_control.visible = true
_empty_state_icon.texture = icon
if icon == _no_open_scene_icon:
_empty_state_text.set_text("[center]No " + text + "[/center]")
else:
_empty_state_text.set_text("[center]No [b]" + text + "[/b] in scene[/center]")
if _add_node_button.pressed.is_connected(_add_node):
_add_node_button.pressed.disconnect(_add_node)
_add_node_button.pressed.connect(_add_node.bind(text))
func _add_node(node_type: String) -> void:
var scene_root: Node = EditorInterface.get_edited_scene_root()
match node_type:
_no_open_scene_string:
pass
_constants.CAMERA_2D_NODE_NAME:
var camera: Camera2D = Camera2D.new()
_instantiate_node(scene_root, camera, _constants.CAMERA_2D_NODE_NAME)
_constants.CAMERA_3D_NODE_NAME:
var camera: Camera3D = Camera3D.new()
_instantiate_node(scene_root, camera, _constants.CAMERA_3D_NODE_NAME)
_constants.PCAM_HOST_NODE_NAME:
var pcam_host: PhantomCameraHost = PhantomCameraHost.new()
var camera_owner: Node
if _is_2d:
camera_owner = _get_camera_2d()
else:
camera_owner = get_tree().get_edited_scene_root().get_viewport().get_camera_3d()
_instantiate_node(
scene_root,
pcam_host,
_constants.PCAM_HOST_NODE_NAME,
camera_owner
)
_constants.PCAM_2D_NODE_NAME:
var pcam_2D: PhantomCamera2D = PhantomCamera2D.new()
_instantiate_node(scene_root, pcam_2D, _constants.PCAM_2D_NODE_NAME)
_constants.PCAM_3D_NODE_NAME:
var pcam_3D: PhantomCamera3D = PhantomCamera3D.new()
_instantiate_node(scene_root, pcam_3D, _constants.PCAM_3D_NODE_NAME)
_visibility_check()
func _instantiate_node(scene_root: Node, node: Node, name: String, parent: Node = scene_root) -> void:
node.set_name(name)
parent.add_child(node)
node.owner = scene_root
func _set_viewfinder(root: Node, editor: bool) -> void:
pcam_host_group = get_tree().root.get_node(_constants.PCAM_MANAGER_NODE_NAME).get_phantom_camera_hosts()
if pcam_host_group.size() != 0:
if pcam_host_group.size() == 1:
_pcam_host_list.visible = false
_set_viewfinder_camera(pcam_host_group[0], editor)
else:
_pcam_host_list.visible = true
_set_viewfinder_camera(pcam_host_group[0], editor)
for i in pcam_host_group.size():
var is_default: bool = false
if i == 0:
is_default = true
_pcam_host_list.add_pcam_host(pcam_host_group[i], is_default)
func _set_viewfinder_camera(new_pcam_host: PhantomCameraHost, editor: bool) -> void:
pcam_host = new_pcam_host
if _is_2d:
_selected_camera = pcam_host.camera_2d
if editor:
sub_viewport.disable_3d = true
pcam_host = pcam_host
_camera_2d.zoom = pcam_host.camera_2d.zoom
_camera_2d.offset = pcam_host.camera_2d.offset
_camera_2d.ignore_rotation = pcam_host.camera_2d.ignore_rotation
sub_viewport.world_2d = pcam_host.camera_2d.get_world_2d()
sub_viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
sub_viewport.render_target_clear_mode = SubViewport.CLEAR_MODE_ALWAYS
sub_viewport.size_2d_override_stretch = true
else:
_selected_camera = pcam_host.camera_3d
if editor:
var camera_3d_rid: RID = _selected_camera.get_camera_rid()
sub_viewport.disable_3d = false
sub_viewport.world_3d = pcam_host.camera_3d.get_world_3d()
RenderingServer.viewport_attach_camera(sub_viewport.get_viewport_rid(), camera_3d_rid)
if _selected_camera.keep_aspect == Camera3D.KeepAspect.KEEP_HEIGHT:
aspect_ratio_container.set_stretch_mode(AspectRatioContainer.STRETCH_HEIGHT_CONTROLS_WIDTH)
else:
aspect_ratio_container.set_stretch_mode(AspectRatioContainer.STRETCH_WIDTH_CONTROLS_HEIGHT)
set_process(true)
if not pcam_host.viewfinder_update.is_connected(_on_update_editor_viewfinder):
pcam_host.viewfinder_update.connect(_on_update_editor_viewfinder)
if not pcam_host.viewfinder_disable_dead_zone.is_connected(_disconnect_dead_zone):
pcam_host.viewfinder_disable_dead_zone.connect(_disconnect_dead_zone)
if not aspect_ratio_container.resized.is_connected(_resized):
aspect_ratio_container.resized.connect(_resized)
if is_instance_valid(pcam_host.get_active_pcam()):
_active_pcam = pcam_host.get_active_pcam()
else:
_framed_view_visible(false)
_active_pcam = null
return
if not _active_pcam.follow_mode == PhantomCamera2D.FollowMode.FRAMED: return
_framed_view_visible(true)
_on_dead_zone_changed()
_connect_dead_zone()
func _connect_dead_zone() -> void:
if not _active_pcam and is_instance_valid(pcam_host.get_active_pcam()):
_active_pcam = pcam_host.get_active_pcam()
if not _active_pcam.dead_zone_changed.is_connected(_on_dead_zone_changed):
_active_pcam.dead_zone_changed.connect(_on_dead_zone_changed)
_framed_view_visible(true)
_viewfinder.visible = true
_on_dead_zone_changed()
func _disconnect_dead_zone() -> void:
if not is_instance_valid(_active_pcam): return
_framed_view_visible(_is_framed_pcam())
if _active_pcam.follow_mode_changed.is_connected(_check_follow_mode):
_active_pcam.follow_mode_changed.disconnect(_check_follow_mode)
if _active_pcam.dead_zone_changed.is_connected(_on_dead_zone_changed):
_active_pcam.dead_zone_changed.disconnect(_on_dead_zone_changed)
func _resized() -> void:
_on_dead_zone_changed()
func _is_framed_pcam() -> bool:
if not is_instance_valid(pcam_host): return false
_active_pcam = pcam_host.get_active_pcam()
if not is_instance_valid(_active_pcam): return false
if not _active_pcam.follow_mode == PhantomCamera2D.FollowMode.FRAMED: return false
return true
func _framed_view_visible(should_show: bool) -> void:
if should_show:
target_point.visible = true
_dead_zone_h_box_container.visible = true
else:
target_point.visible = false
_dead_zone_h_box_container.visible = false
func _on_dead_zone_changed() -> void:
if not is_instance_valid(_active_pcam): return
if not _active_pcam.follow_mode == _active_pcam.FollowMode.FRAMED: return
# Waits until the camera_viewport_panel has been resized when launching the game
if camera_viewport_panel.size.x == 0:
await camera_viewport_panel.resized
if not _active_pcam == pcam_host.get_active_pcam():
_active_pcam == pcam_host.get_active_pcam()
var dead_zone_width: float = _active_pcam.dead_zone_width * camera_viewport_panel.size.x
var dead_zone_height: float = _active_pcam.dead_zone_height * camera_viewport_panel.size.y
dead_zone_center_hbox.set_custom_minimum_size(Vector2(dead_zone_width, 0))
dead_zone_center_center_panel.set_custom_minimum_size(Vector2(0, dead_zone_height))
dead_zone_left_center_panel.set_custom_minimum_size(Vector2(0, dead_zone_height))
dead_zone_right_center_panel.set_custom_minimum_size(Vector2(0, dead_zone_height))
min_horizontal = 0.5 - _active_pcam.dead_zone_width / 2
max_horizontal = 0.5 + _active_pcam.dead_zone_width / 2
min_vertical = 0.5 - _active_pcam.dead_zone_height / 2
max_vertical = 0.5 + _active_pcam.dead_zone_height / 2
func _check_follow_mode() -> void:
_framed_view_visible(_is_framed_pcam())
func _on_update_editor_viewfinder(check_framed_view: bool = false) -> void:
_active_pcam = pcam_host.get_active_pcam()
if not is_instance_valid(_active_pcam): return
if not _active_pcam.follow_mode_changed.is_connected(_check_follow_mode):
_active_pcam.follow_mode_changed.connect(_check_follow_mode)
if _active_pcam.priority_override:
_priority_override_button.visible = true
_priority_override_name_label.set_text(_active_pcam.name)
_priority_override_button.set_tooltip_text(_active_pcam.name)
else:
_priority_override_button.visible = false
_framed_view_visible(false)
if not check_framed_view: return
if _is_framed_pcam(): _connect_dead_zone()
func _select_override_pcam() -> void:
EditorInterface.get_selection().clear()
EditorInterface.get_selection().add_node(_active_pcam)
func _assign_manager() -> void:
if not is_instance_valid(_pcam_manager):
if Engine.has_singleton(_constants.PCAM_MANAGER_NODE_NAME):
_pcam_manager = Engine.get_singleton(_constants.PCAM_MANAGER_NODE_NAME)
_pcam_manager.pcam_host_added_to_scene.connect(_pcam_changed)
_pcam_manager.pcam_host_removed_from_scene.connect(_pcam_host_removed_from_scene)
_pcam_manager.pcam_added_to_scene.connect(_pcam_changed)
_pcam_manager.pcam_removed_from_scene.connect(_pcam_changed)
_pcam_manager.viewfinder_pcam_host_switch.connect(_pcam_host_switch)
func _pcam_host_removed_from_scene(pcam_host: PhantomCameraHost) -> void:
if _pcam_manager.phantom_camera_hosts.size() < 2:
_pcam_host_list.visible = false
_visibility_check()
func _pcam_changed(pcam: Node) -> void:
_visibility_check()
#endregion
#region Public Functions
func set_visibility(visible: bool) -> void:
if visible:
viewfinder_visible = true
_visibility_check()
else:
viewfinder_visible = false
func update_dead_zone() -> void:
_set_viewfinder(_root_node, true)
## TODO - Signal can be added directly to this file with the changes in Godot 4.5 (https://github.com/godotengine/godot/pull/102986)
func scene_changed(scene_root: Node) -> void:
_assign_manager()
_priority_override_button.visible = false
_pcam_host_list.clear_pcam_host_list()
if not scene_root is Node2D and not scene_root is Node3D:
is_scene = false
_pcam_host_list.visible = false
_set_empty_viewfinder_state(_no_open_scene_string, _no_open_scene_icon)
_add_node_button.visible = false
else:
_visibility_check()
#endregion

View File

@ -0,0 +1 @@
uid://drmv3363t8amc

View File

@ -0,0 +1,253 @@
using Godot;
using PhantomCamera.Noise;
#nullable enable
namespace PhantomCamera;
public enum InactiveUpdateMode
{
Always,
Never
}
public abstract class PhantomCamera
{
protected readonly GodotObject Node;
public delegate void BecameActiveEventHandler();
public delegate void BecameInactiveEventHandler();
public delegate void FollowTargetChangedEventHandler();
public delegate void DeadZoneChangedEventHandler();
public delegate void TweenStartedEventHandler();
public delegate void IsTweeningEventHandler();
public delegate void TweenCompletedEventHandler();
public event BecameActiveEventHandler? BecameActive;
public event BecameInactiveEventHandler? BecameInactive;
public event FollowTargetChangedEventHandler? FollowTargetChanged;
public event DeadZoneChangedEventHandler? DeadZoneChanged;
public event TweenStartedEventHandler? TweenStarted;
public event IsTweeningEventHandler? IsTweening;
public event TweenCompletedEventHandler? TweenCompleted;
private readonly Callable _callableBecameActive;
private readonly Callable _callableBecameInactive;
private readonly Callable _callableFollowTargetChanged;
private readonly Callable _callableDeadZoneChanged;
private readonly Callable _callableTweenStarted;
private readonly Callable _callableIsTweening;
private readonly Callable _callableTweenCompleted;
public int Priority
{
get => (int)Node.Call(MethodName.GetPriority);
set => Node.Call(MethodName.SetPriority, value);
}
public bool IsActive => (bool)Node.Call(MethodName.IsActive);
public bool FollowDamping
{
get => (bool)Node.Call(MethodName.GetFollowDamping);
set => Node.Call(MethodName.SetFollowDamping, value);
}
public bool IsFollowing => (bool)Node.Call(PhantomCamera.MethodName.IsFollowing);
public float DeadZoneWidth
{
get => (float)Node.Get(PropertyName.DeadZoneWidth);
set => Node.Set(PropertyName.DeadZoneWidth, value);
}
public float DeadZoneHeight
{
get => (float)Node.Get(PropertyName.DeadZoneHeight);
set => Node.Set(PropertyName.DeadZoneHeight, value);
}
public PhantomCameraTween TweenResource
{
get => new((Resource)Node.Call(MethodName.GetTweenResource));
set => Node.Call(MethodName.SetTweenResource, (GodotObject)value.Resource);
}
public bool TweenSkip
{
get => (bool)Node.Call(MethodName.GetTweenSkip);
set => Node.Call(MethodName.SetTweenSkip, value);
}
public float TweenDuration
{
get => (float)Node.Call(MethodName.GetTweenDuration);
set => Node.Call(MethodName.SetTweenDuration, value);
}
public TransitionType TweenTransition
{
get => (TransitionType)(int)Node.Call(MethodName.GetTweenTransition);
set => Node.Call(MethodName.SetTweenTransition, (int)value);
}
public EaseType TweenEase
{
get => (EaseType)(int)Node.Call(MethodName.GetTweenEase);
set => Node.Call(MethodName.SetTweenEase, (int)value);
}
public bool TweenOnLoad
{
get => (bool)Node.Call(MethodName.GetTweenOnLoad);
set => Node.Call(MethodName.SetTweenOnLoad, value);
}
public InactiveUpdateMode InactiveUpdateMode
{
get => (InactiveUpdateMode)(int)Node.Call(MethodName.GetInactiveUpdateMode);
set => Node.Call(MethodName.SetInactiveUpdateMode, (int)value);
}
public int HostLayers
{
get => (int)Node.Call(MethodName.GetHostLayers);
set => Node.Call(MethodName.SetHostLayers, value);
}
public int NoiseEmitterLayer
{
get => (int)Node.Call(MethodName.GetNoiseEmitterLayer);
set => Node.Call(MethodName.SetNoiseEmitterLayer, value);
}
public void TeleportPosition()
{
Node.Call(MethodName.TeleportPosition);
}
public void SetHostLayersValue(int layer, bool enabled)
{
Node.Call(MethodName.SetHostLayersValue, layer, enabled);
}
protected PhantomCamera(GodotObject phantomCameraNode)
{
Node = phantomCameraNode;
_callableBecameActive = Callable.From(() => BecameActive?.Invoke());
_callableBecameInactive = Callable.From(() => BecameInactive?.Invoke());
_callableFollowTargetChanged = Callable.From(() => FollowTargetChanged?.Invoke());
_callableDeadZoneChanged = Callable.From(() => DeadZoneChanged?.Invoke());
_callableTweenStarted = Callable.From(() => TweenStarted?.Invoke());
_callableIsTweening = Callable.From(() => IsTweening?.Invoke());
_callableTweenCompleted = Callable.From(() => TweenCompleted?.Invoke());
Node.Connect(SignalName.BecameActive, _callableBecameActive);
Node.Connect(SignalName.BecameInactive, _callableBecameInactive);
Node.Connect(SignalName.FollowTargetChanged, _callableFollowTargetChanged);
Node.Connect(SignalName.DeadZoneChanged, _callableDeadZoneChanged);
Node.Connect(SignalName.TweenStarted, _callableTweenStarted);
Node.Connect(SignalName.IsTweening, _callableIsTweening);
Node.Connect(SignalName.TweenCompleted, _callableTweenCompleted);
}
~PhantomCamera()
{
Node.Disconnect(SignalName.BecameActive, _callableBecameActive);
Node.Disconnect(SignalName.BecameInactive, _callableBecameInactive);
Node.Disconnect(SignalName.FollowTargetChanged, _callableFollowTargetChanged);
Node.Disconnect(SignalName.DeadZoneChanged, _callableDeadZoneChanged);
Node.Disconnect(SignalName.TweenStarted, _callableTweenStarted);
Node.Disconnect(SignalName.IsTweening, _callableIsTweening);
Node.Disconnect(SignalName.TweenCompleted, _callableTweenCompleted);
}
public static class MethodName
{
public const string GetFollowMode = "get_follow_mode";
public const string IsActive = "is_active";
public const string GetPriority = "get_priority";
public const string SetPriority = "set_priority";
public const string IsFollowing = "is_following";
public const string GetFollowTarget = "get_follow_target";
public const string SetFollowTarget = "set_follow_target";
public const string GetFollowTargets = "get_follow_targets";
public const string SetFollowTargets = "set_follow_targets";
public const string TeleportPosition = "teleport_position";
public const string AppendFollowTargets = "append_follow_targets";
public const string AppendFollowTargetsArray = "append_follow_targets_array";
public const string EraseFollowTargets = "erase_follow_targets";
public const string GetFollowPath = "get_follow_path";
public const string SetFollowPath = "set_follow_path";
public const string GetFollowOffset = "get_follow_offset";
public const string SetFollowOffset = "set_follow_offset";
public const string GetFollowDamping = "get_follow_damping";
public const string SetFollowDamping = "set_follow_damping";
public const string GetFollowDampingValue = "get_follow_damping_value";
public const string SetFollowDampingValue = "set_follow_damping_value";
public const string GetFollowAxisLock = "get_follow_axis_lock";
public const string SetFollowAxisLock = "set_follow_axis_lock";
public const string GetTweenResource = "get_tween_resource";
public const string SetTweenResource = "set_tween_resource";
public const string GetTweenSkip = "get_tween_skip";
public const string SetTweenSkip = "set_tween_skip";
public const string GetTweenDuration = "get_tween_duration";
public const string SetTweenDuration = "set_tween_duration";
public const string GetTweenTransition = "get_tween_transition";
public const string SetTweenTransition = "set_tween_transition";
public const string GetTweenEase = "get_tween_ease";
public const string SetTweenEase = "set_tween_ease";
public const string GetTweenOnLoad = "get_tween_on_load";
public const string SetTweenOnLoad = "set_tween_on_load";
public const string GetInactiveUpdateMode = "get_inactive_update_mode";
public const string SetInactiveUpdateMode = "set_inactive_update_mode";
public const string GetHostLayers = "get_host_layers";
public const string SetHostLayers = "set_host_layers";
public const string SetHostLayersValue = "set_host_layers_value";
public const string GetNoiseEmitterLayer = "get_noise_emitter_layer";
public const string SetNoiseEmitterLayer = "set_noise_emitter_layer";
public const string EmitNoise = "emit_noise";
}
public static class PropertyName
{
public const string DeadZoneWidth = "dead_zone_width";
public const string DeadZoneHeight = "dead_zone_height";
}
public static class SignalName
{
public const string BecameActive = "became_active";
public const string BecameInactive = "became_inactive";
public const string FollowTargetChanged = "follow_target_changed";
public const string DeadZoneChanged = "dead_zone_changed";
public const string DeadZoneReached = "dead_zone_reached";
public const string TweenStarted = "tween_started";
public const string IsTweening = "is_tweening";
public const string TweenCompleted = "tween_completed";
public const string TweenInterrupted = "tween_interrupted";
public const string NoiseEmitted = "noise_emitted";
}
}

View File

@ -0,0 +1 @@
uid://d3wh0457i0i3

View File

@ -0,0 +1,351 @@
using System.Linq;
using Godot;
using Godot.Collections;
using PhantomCamera.Noise;
#nullable enable
namespace PhantomCamera;
public enum FollowMode2D
{
None,
Glued,
Simple,
Group,
Path,
Framed
}
public enum FollowLockAxis2D
{
None,
X,
Y,
XY
}
public static class PhantomCamera2DExtensions
{
public static PhantomCamera2D AsPhantomCamera2D(this Node2D node2D)
{
return new PhantomCamera2D(node2D);
}
public static PhantomCameraNoiseEmitter2D AsPhantomCameraNoiseEmitter2D(this Node2D node2D)
{
return new PhantomCameraNoiseEmitter2D(node2D);
}
public static PhantomCameraNoise2D AsPhantomCameraNoise2D(this Resource resource)
{
return new PhantomCameraNoise2D(resource);
}
}
public class PhantomCamera2D : PhantomCamera
{
public Node2D Node2D => (Node2D)Node;
public delegate void TweenInterruptedEventHandler(Node2D pCam);
public delegate void DeadZoneReachedEventHandler(Vector2 side);
public delegate void NoiseEmittedEventHandler(Transform2D output);
public event TweenInterruptedEventHandler? TweenInterrupted;
public event DeadZoneReachedEventHandler? DeadZoneReached;
public event NoiseEmittedEventHandler? NoiseEmitted;
private readonly Callable _callableTweenInterrupted;
private readonly Callable _callableDeadZoneReached;
private readonly Callable _callableNoiseEmitted;
public Node2D FollowTarget
{
get => (Node2D)Node2D.Call(PhantomCamera.MethodName.GetFollowTarget);
set => Node2D.Call(PhantomCamera.MethodName.SetFollowTarget, value);
}
public Node2D[] FollowTargets
{
get => Node2D.Call(PhantomCamera.MethodName.GetFollowTargets).AsGodotArray<Node2D>().ToArray();
set => Node2D.Call(PhantomCamera.MethodName.SetFollowTargets, new Array<Node2D>(value));
}
public void AppendFollowTargets(Node2D target) => Node2D.Call(PhantomCamera.MethodName.AppendFollowTargets, target);
public void AppendFollowTargetsArray(Node2D[] targets) => Node2D.Call(PhantomCamera.MethodName.AppendFollowTargetsArray, targets);
public void EraseFollowTargets(Node2D target) => Node2D.Call(PhantomCamera.MethodName.EraseFollowTargets, target);
public FollowMode2D FollowMode => (FollowMode2D)(int)Node.Call(PhantomCamera.MethodName.GetFollowMode);
public Path2D FollowPath
{
get => (Path2D)Node2D.Call(PhantomCamera.MethodName.GetFollowPath);
set => Node2D.Call(PhantomCamera.MethodName.SetFollowPath, value);
}
public Vector2 FollowOffset
{
get => (Vector2)Node2D.Call(PhantomCamera.MethodName.GetFollowOffset);
set => Node2D.Call(PhantomCamera.MethodName.SetFollowOffset, value);
}
public Vector2 FollowDampingValue
{
get => (Vector2)Node2D.Call(PhantomCamera.MethodName.GetFollowDampingValue);
set => Node2D.Call(PhantomCamera.MethodName.SetFollowDampingValue, value);
}
public FollowLockAxis2D FollowAxisLock
{
get => (FollowLockAxis2D)(int)Node2D.Call(PhantomCamera.MethodName.GetFollowAxisLock);
set => Node2D.Call(PhantomCamera.MethodName.SetFollowAxisLock, (int)value);
}
public Vector2 Zoom
{
get => (Vector2)Node2D.Call(MethodName.GetZoom);
set => Node2D.Call(MethodName.SetZoom, value);
}
public bool SnapToPixel
{
get => (bool)Node2D.Call(MethodName.GetSnapToPixel);
set => Node2D.Call(MethodName.SetSnapToPixel, value);
}
public bool RotateWithTarget
{
get => (bool)Node2D.Call(MethodName.GetRotateWithTarget);
set => Node2D.Call(MethodName.SetRotateWithTarget, value);
}
public float RotationOffset
{
get => (float)Node2D.Call(MethodName.GetRotationOffset);
set => Node2D.Call(MethodName.SetRotationOffset, value);
}
public bool RotationDamping
{
get => (bool)Node2D.Call(MethodName.GetRotationDamping);
set => Node2D.Call(MethodName.SetRotationDamping, value);
}
public float RotationDampingValue
{
get => (float)Node2D.Call(MethodName.GetRotationDampingValue);
set => Node2D.Call(MethodName.SetRotationDampingValue, value);
}
public int LimitLeft
{
get => (int)Node2D.Call(MethodName.GetLimitLeft);
set => Node2D.Call(MethodName.SetLimitLeft, value);
}
public int LimitTop
{
get => (int)Node2D.Call(MethodName.GetLimitTop);
set => Node2D.Call(MethodName.SetLimitTop, value);
}
public int LimitRight
{
get => (int)Node2D.Call(MethodName.GetLimitRight);
set => Node2D.Call(MethodName.SetLimitRight, value);
}
public int LimitBottom
{
get => (int)Node2D.Call(MethodName.GetLimitBottom);
set => Node2D.Call(MethodName.SetLimitBottom, value);
}
public Vector4I LimitMargin
{
get => (Vector4I)Node2D.Call(MethodName.GetLimitMargin);
set => Node2D.Call(MethodName.SetLimitMargin, value);
}
public bool AutoZoom
{
get => (bool)Node2D.Call(MethodName.GetAutoZoom);
set => Node2D.Call(MethodName.SetAutoZoom, value);
}
public float AutoZoomMin
{
get => (float)Node2D.Call(MethodName.GetAutoZoomMin);
set => Node2D.Call(MethodName.SetAutoZoomMin, value);
}
public float AutoZoomMax
{
get => (float)Node2D.Call(MethodName.GetAutoZoomMax);
set => Node2D.Call(MethodName.SetAutoZoomMax, value);
}
public Vector4 AutoZoomMargin
{
get => (Vector4)Node2D.Call(MethodName.GetAutoZoomMargin);
set => Node2D.Call(MethodName.SetAutoZoomMargin, value);
}
public bool DrawLimits
{
get => (bool)Node2D.Get(PropertyName.DrawLimits);
set => Node2D.Set(PropertyName.DrawLimits, value);
}
public PhantomCameraNoise2D Noise
{
get => new((Resource)Node2D.Call(MethodName.GetNoise));
set => Node2D.Call(MethodName.SetNoise, (GodotObject)value.Resource);
}
public void EmitNoise(Transform2D transform) => Node2D.Call(PhantomCamera.MethodName.EmitNoise, transform);
public NodePath LimitTarget
{
get => (NodePath)Node2D.Call(MethodName.GetLimitTarget);
set => Node2D.Call(MethodName.SetLimitTarget, value);
}
public static PhantomCamera2D FromScript(string path) => new(GD.Load<GDScript>(path).New().AsGodotObject());
public static PhantomCamera2D FromScript(GDScript script) => new(script.New().AsGodotObject());
public PhantomCamera2D(GodotObject phantomCameraNode) : base(phantomCameraNode)
{
_callableTweenInterrupted = Callable.From<Node2D>(pCam => TweenInterrupted?.Invoke(pCam));
_callableDeadZoneReached = Callable.From((Vector2 side) => DeadZoneReached?.Invoke(side));
_callableNoiseEmitted = Callable.From((Transform2D output) => NoiseEmitted?.Invoke(output));
Node2D.Connect(SignalName.TweenInterrupted, _callableTweenInterrupted);
Node2D.Connect(SignalName.DeadZoneReached, _callableDeadZoneReached);
Node2D.Connect(SignalName.NoiseEmitted, _callableNoiseEmitted);
}
~PhantomCamera2D()
{
Node2D.Disconnect(SignalName.TweenInterrupted, _callableTweenInterrupted);
Node2D.Disconnect(SignalName.DeadZoneReached, _callableDeadZoneReached);
Node2D.Disconnect(SignalName.NoiseEmitted, _callableNoiseEmitted);
}
public void SetLimitTarget(TileMap tileMap)
{
Node2D.Call(MethodName.SetLimitTarget, tileMap.GetPath());
}
public void SetLimitTarget(TileMapLayer tileMapLayer)
{
Node2D.Call(MethodName.SetLimitTarget, tileMapLayer.GetPath());
}
public void SetLimitTarget(CollisionShape2D shape2D)
{
Node2D.Call(MethodName.SetLimitTarget, shape2D.GetPath());
}
public LimitTargetQueryResult? GetLimitTarget()
{
var result = (NodePath)Node2D.Call(MethodName.GetLimitTarget);
return result.IsEmpty ? null : new LimitTargetQueryResult(Node2D.GetNode(result));
}
public void SetLimit(Side side, int value)
{
Node2D.Call(MethodName.SetLimit, (int)side, value);
}
public int GetLimit(Side side)
{
return (int)Node2D.Call(MethodName.GetLimit, (int)side);
}
public new static class MethodName
{
public const string GetZoom = "get_zoom";
public const string SetZoom = "set_zoom";
public const string GetSnapToPixel = "get_snap_to_pixel";
public const string SetSnapToPixel = "set_snap_to_pixel";
public const string GetRotateWithTarget = "get_rotate_with_target";
public const string SetRotateWithTarget = "set_rotate_with_target";
public const string GetRotationOffset = "get_rotation_offset";
public const string SetRotationOffset = "set_rotation_offset";
public const string GetRotationDamping = "get_rotation_damping";
public const string SetRotationDamping = "set_rotation_damping";
public const string GetRotationDampingValue = "get_rotation_damping_value";
public const string SetRotationDampingValue = "set_rotation_damping_value";
public const string GetLimit = "get_limit";
public const string SetLimit = "set_limit";
public const string GetLimitLeft = "get_limit_left";
public const string SetLimitLeft = "set_limit_left";
public const string GetLimitTop = "get_limit_top";
public const string SetLimitTop = "set_limit_top";
public const string GetLimitRight = "get_limit_right";
public const string SetLimitRight = "set_limit_right";
public const string GetLimitBottom = "get_limit_bottom";
public const string SetLimitBottom = "set_limit_bottom";
public const string GetLimitTarget = "get_limit_target";
public const string SetLimitTarget = "set_limit_target";
public const string GetLimitMargin = "get_limit_margin";
public const string SetLimitMargin = "set_limit_margin";
public const string GetAutoZoom = "get_auto_zoom";
public const string SetAutoZoom = "set_auto_zoom";
public const string GetAutoZoomMin = "get_auto_zoom_min";
public const string SetAutoZoomMin = "set_auto_zoom_min";
public const string GetAutoZoomMax = "get_auto_zoom_max";
public const string SetAutoZoomMax = "set_auto_zoom_max";
public const string GetAutoZoomMargin = "get_auto_zoom_margin";
public const string SetAutoZoomMargin = "set_auto_zoom_margin";
public const string GetNoise = "get_noise";
public const string SetNoise = "set_noise";
}
public new static class PropertyName
{
public const string DrawLimits = "draw_limits";
}
}
public class LimitTargetQueryResult(GodotObject godotObject)
{
public bool IsTileMap => godotObject.IsClass("TileMap");
public bool IsTileMapLayer => godotObject.IsClass("TileMapLayer");
public bool IsCollisionShape2D => godotObject.IsClass("CollisionShape2D");
public TileMap? AsTileMap()
{
return IsTileMap ? (TileMap)godotObject : null;
}
public TileMapLayer? AsTileMapLayer()
{
return IsTileMapLayer ? (TileMapLayer)godotObject : null;
}
public CollisionShape2D? AsCollisionShape2D()
{
return IsCollisionShape2D ? (CollisionShape2D)godotObject : null;
}
}

View File

@ -0,0 +1 @@
uid://c38e5qhsf3fk3

View File

@ -0,0 +1,493 @@
using System.Linq;
using Godot;
using Godot.Collections;
using PhantomCamera.Noise;
#nullable enable
namespace PhantomCamera;
public enum LookAtMode
{
None,
Mimic,
Simple,
Group
}
public enum FollowMode3D
{
None,
Glued,
Simple,
Group,
Path,
Framed,
ThirdPerson
}
public enum FollowLockAxis3D
{
None,
X,
Y,
Z,
XY,
XZ,
YZ,
XYZ
}
public static class PhantomCamera3DExtensions
{
public static PhantomCamera3D AsPhantomCamera3D(this Node3D node3D)
{
return new PhantomCamera3D(node3D);
}
public static PhantomCameraNoiseEmitter3D AsPhantomCameraNoiseEmitter3D(this Node3D node3D)
{
return new PhantomCameraNoiseEmitter3D(node3D);
}
public static PhantomCameraNoise3D AsPhantomCameraNoise3D(this Resource resource)
{
return new PhantomCameraNoise3D(resource);
}
public static Camera3DResource AsCamera3DResource(this Resource resource)
{
return new Camera3DResource(resource);
}
public static Vector3 GetThirdPersonRotation(this PhantomCamera3D pCam3D) =>
(Vector3)pCam3D.Node3D.Call(PhantomCamera3D.MethodName.GetThirdPersonRotation);
public static void SetThirdPersonRotation(this PhantomCamera3D pCam3D, Vector3 rotation) =>
pCam3D.Node3D.Call(PhantomCamera3D.MethodName.SetThirdPersonRotation, rotation);
public static Vector3 GetThirdPersonRotationDegrees(this PhantomCamera3D pCam3D) =>
(Vector3)pCam3D.Node3D.Call(PhantomCamera3D.MethodName.GetThirdPersonRotationDegrees);
public static void SetThirdPersonDegrees(this PhantomCamera3D pCam3D, Vector3 rotation) =>
pCam3D.Node3D.Call(PhantomCamera3D.MethodName.SetThirdPersonRotationDegrees, rotation);
public static Quaternion GetThirdPersonQuaternion(this PhantomCamera3D pCam3D) =>
(Quaternion)pCam3D.Node3D.Call(PhantomCamera3D.MethodName.GetThirdPersonQuaternion);
public static void SetThirdPersonQuaternion(this PhantomCamera3D pCam3D, Quaternion quaternion) =>
pCam3D.Node3D.Call(PhantomCamera3D.MethodName.SetThirdPersonQuaternion, quaternion);
}
public class PhantomCamera3D : PhantomCamera
{
public Node3D Node3D => (Node3D)Node;
public delegate void LookAtTargetChangedEventHandler();
public delegate void DeadZoneReachedEventHandler();
public delegate void Camera3DResourceChangedEventHandler();
public delegate void Camera3DResourcePropertyChangedEventHandler(StringName property, Variant value);
public delegate void TweenInterruptedEventHandler(Node3D pCam);
public delegate void NoiseEmittedEventHandler(Transform3D output);
public event LookAtTargetChangedEventHandler? LookAtTargetChanged;
public event DeadZoneReachedEventHandler? DeadZoneReached;
public event Camera3DResourceChangedEventHandler? Camera3DResourceChanged;
public event Camera3DResourcePropertyChangedEventHandler? Camera3DResourcePropertyChanged;
public event TweenInterruptedEventHandler? TweenInterrupted;
public event NoiseEmittedEventHandler? NoiseEmitted;
private readonly Callable _callableLookAtTargetChanged;
private readonly Callable _callableDeadZoneReached;
private readonly Callable _callableCamera3DResourceChanged;
private readonly Callable _callableCamera3DResourcePropertyChanged;
private readonly Callable _callableTweenInterrupted;
private readonly Callable _callableNoiseEmitted;
public Node3D FollowTarget
{
get => (Node3D)Node3D.Call(PhantomCamera.MethodName.GetFollowTarget);
set => Node3D.Call(PhantomCamera.MethodName.SetFollowTarget, value);
}
public Node3D[] FollowTargets
{
get => Node3D.Call(PhantomCamera.MethodName.GetFollowTargets).AsGodotArray<Node3D>().ToArray();
set => Node3D.Call(PhantomCamera.MethodName.SetFollowTargets, new Array<Node3D>(value));
}
public void AppendFollowTarget(Node3D target) => Node3D.Call(PhantomCamera.MethodName.AppendFollowTargets, target);
public void AppendFollowTargetArray(Node3D[] targets) => Node3D.Call(PhantomCamera.MethodName.AppendFollowTargetsArray, targets);
public void EraseFollowTarget(Node3D target) => Node3D.Call(PhantomCamera.MethodName.EraseFollowTargets, target);
public FollowMode3D FollowMode => (FollowMode3D)(int)Node.Call(PhantomCamera.MethodName.GetFollowMode);
public Path3D FollowPath
{
get => (Path3D)Node3D.Call(PhantomCamera.MethodName.GetFollowPath);
set => Node3D.Call(PhantomCamera.MethodName.SetFollowPath, value);
}
public Vector3 FollowOffset
{
get => (Vector3)Node3D.Call(PhantomCamera.MethodName.GetFollowOffset);
set => Node3D.Call(PhantomCamera.MethodName.SetFollowOffset, value);
}
public Vector3 FollowDampingValue
{
get => (Vector3)Node3D.Call(PhantomCamera.MethodName.GetFollowDampingValue);
set => Node3D.Call(PhantomCamera.MethodName.SetFollowDampingValue, value);
}
public FollowLockAxis3D FollowAxisLock
{
get => (FollowLockAxis3D)(int)Node3D.Call(PhantomCamera.MethodName.GetFollowAxisLock);
set => Node3D.Call(PhantomCamera.MethodName.SetFollowAxisLock, (int)value);
}
public LookAtMode LookAtMode => (LookAtMode)(int)Node3D.Call(MethodName.GetLookAtMode);
public Camera3DResource Camera3DResource
{
get => new((Resource)Node3D.Call(MethodName.GetCamera3DResource));
set => Node3D.Call(MethodName.SetCamera3DResource, value.Resource);
}
public float SpringLength
{
get => (float)Node3D.Call(MethodName.GetSpringLength);
set => Node3D.Call(MethodName.SetSpringLength, value);
}
public float VerticalRotationOffset
{
get => (float)Node3D.Call(MethodName.GetVerticalRotationOffset);
set => Node3D.Call(MethodName.SetVerticalRotationOffset, value);
}
public float HorizontalRotationOffset
{
get => (float)Node3D.Call(MethodName.GetHorizontalRotationOffset);
set => Node3D.Call(MethodName.SetHorizontalRotationOffset, value);
}
public float FollowDistance
{
get => (float)Node3D.Call(MethodName.GetFollowDistance);
set => Node3D.Call(MethodName.SetFollowDistance, value);
}
public bool AutoFollowDistance
{
get => (bool)Node3D.Call(MethodName.GetAutoFollowDistance);
set => Node3D.Call(MethodName.SetAutoFollowDistance, value);
}
public float AutoFollowDistanceMin
{
get => (float)Node3D.Call(MethodName.GetAutoFollowDistanceMin);
set => Node3D.Call(MethodName.SetAutoFollowDistanceMin, value);
}
public float AutoFollowDistanceMax
{
get => (float)Node3D.Call(MethodName.GetAutoFollowDistanceMax);
set => Node3D.Call(MethodName.SetAutoFollowDistanceMax, value);
}
public float AutoFollowDistanceDivisor
{
get => (float)Node3D.Call(MethodName.GetAutoFollowDistanceDivisor);
set => Node3D.Call(MethodName.SetAutoFollowDistanceDivisor, value);
}
public Node3D LookAtTarget
{
get => (Node3D)Node3D.Call(MethodName.GetLookAtTarget);
set => Node3D.Call(MethodName.SetLookAtTarget, value);
}
public Node3D[] LookAtTargets
{
get => Node3D.Call(MethodName.GetLookAtTargets).AsGodotArray<Node3D>().ToArray();
set => Node3D.Call(MethodName.SetLookAtTargets, new Array<Node3D>(value));
}
public bool IsLooking => (bool)Node3D.Call(MethodName.IsLooking);
public int CollisionMask
{
get => (int)Node3D.Call(MethodName.GetCollisionMask);
set => Node3D.Call(MethodName.SetCollisionMask, value);
}
public void SetCollisionMaskValue(int maskLayer, bool enable) =>
Node3D.Call(MethodName.SetCollisionMaskValue, maskLayer, enable);
public Shape3D Shape
{
get => (Shape3D)Node3D.Call(MethodName.GetShape);
set => Node3D.Call(MethodName.SetShape, value);
}
public float Margin
{
get => (float)Node3D.Call(MethodName.GetMargin);
set => Node3D.Call(MethodName.SetMargin, value);
}
public Vector3 LookAtOffset
{
get => (Vector3)Node3D.Call(MethodName.GetLookAtOffset);
set => Node3D.Call(MethodName.SetLookAtOffset, value);
}
public bool LookAtDamping
{
get => (bool)Node3D.Call(MethodName.GetLookAtDamping);
set => Node3D.Call(MethodName.SetLookAtDamping, value);
}
public float LookAtDampingValue
{
get => (float)Node3D.Call(MethodName.GetLookAtDampingValue);
set => Node3D.Call(MethodName.SetLookAtDampingValue, value);
}
public Node3D Up
{
get => (Node3D)Node3D.Call(MethodName.GetUp);
set => Node3D.Call(MethodName.SetUp, value);
}
public Vector3 UpTarget
{
get => (Vector3)Node3D.Call(MethodName.GetUpTarget);
set => Node3D.Call(MethodName.SetUpTarget, value);
}
public int CullMask
{
get => (int)Node3D.Call(MethodName.GetCullMask);
set => Node3D.Call(MethodName.SetCullMask, value);
}
public float HOffset
{
get => (float)Node3D.Call(MethodName.GetHOffset);
set => Node3D.Call(MethodName.SetHOffset, value);
}
public float VOffset
{
get => (float)Node3D.Call(MethodName.GetVOffset);
set => Node3D.Call(MethodName.SetVOffset, value);
}
public ProjectionType Projection
{
get => (ProjectionType)(int)Node3D.Call(MethodName.GetProjection);
set => Node3D.Call(MethodName.SetProjection, (int)value);
}
public float Fov
{
get => (float)Node3D.Call(MethodName.GetFov);
set => Node3D.Call(MethodName.SetFov, value);
}
public float Size
{
get => (float)Node3D.Call(MethodName.GetSize);
set => Node3D.Call(MethodName.SetSize, value);
}
public Vector2 FrustumOffset
{
get => (Vector2)Node3D.Call(MethodName.GetFrustumOffset);
set => Node3D.Call(MethodName.SetFrustumOffset, value);
}
public float Far
{
get => (float)Node3D.Call(MethodName.GetFar);
set => Node3D.Call(MethodName.SetFar, value);
}
public float Near
{
get => (float)Node3D.Call(MethodName.GetNear);
set => Node3D.Call(MethodName.SetNear, value);
}
public Environment Environment
{
get => (Environment)Node3D.Call(MethodName.GetEnvironment);
set => Node3D.Call(MethodName.SetEnvironment, value);
}
public CameraAttributes Attributes
{
get => (CameraAttributes)Node3D.Call(MethodName.GetAttributes);
set => Node3D.Call(MethodName.SetAttributes, value);
}
public PhantomCameraNoise3D Noise
{
get => new((Resource)Node3D.Call(MethodName.GetNoise));
set => Node3D.Call(MethodName.SetNoise, (GodotObject)value.Resource);
}
public void EmitNoise(Transform3D transform) => Node3D.Call(PhantomCamera.MethodName.EmitNoise, transform);
public static PhantomCamera3D FromScript(string path) => new(GD.Load<GDScript>(path).New().AsGodotObject());
public static PhantomCamera3D FromScript(GDScript script) => new(script.New().AsGodotObject());
public PhantomCamera3D(GodotObject phantomCamera3DNode) : base(phantomCamera3DNode)
{
_callableLookAtTargetChanged = Callable.From(() => LookAtTargetChanged?.Invoke());
_callableDeadZoneReached = Callable.From(() => DeadZoneReached?.Invoke());
_callableCamera3DResourceChanged = Callable.From(() => Camera3DResourceChanged?.Invoke());
_callableCamera3DResourcePropertyChanged = Callable.From((StringName property, Variant value) =>
Camera3DResourcePropertyChanged?.Invoke(property, value));
_callableTweenInterrupted = Callable.From<Node3D>(pCam => TweenInterrupted?.Invoke(pCam));
_callableNoiseEmitted = Callable.From((Transform3D output) => NoiseEmitted?.Invoke(output));
Node3D.Connect(SignalName.LookAtTargetChanged, _callableLookAtTargetChanged);
Node3D.Connect(PhantomCamera.SignalName.DeadZoneReached, _callableDeadZoneReached);
Node3D.Connect(SignalName.Camera3DResourceChanged, _callableCamera3DResourceChanged);
Node3D.Connect(SignalName.Camera3DResourcePropertyChanged, _callableCamera3DResourcePropertyChanged);
Node3D.Connect(PhantomCamera.SignalName.TweenInterrupted, _callableTweenInterrupted);
Node3D.Connect(PhantomCamera.SignalName.NoiseEmitted, _callableNoiseEmitted);
}
~PhantomCamera3D()
{
Node3D.Disconnect(SignalName.LookAtTargetChanged, _callableLookAtTargetChanged);
Node3D.Disconnect(PhantomCamera.SignalName.DeadZoneReached, _callableDeadZoneReached);
Node3D.Disconnect(SignalName.Camera3DResourceChanged, _callableCamera3DResourceChanged);
Node3D.Disconnect(SignalName.Camera3DResourcePropertyChanged, _callableCamera3DResourcePropertyChanged);
Node3D.Disconnect(PhantomCamera.SignalName.TweenInterrupted, _callableTweenInterrupted);
Node3D.Disconnect(PhantomCamera.SignalName.NoiseEmitted, _callableNoiseEmitted);
}
public new static class MethodName
{
public const string GetLookAtMode = "get_look_at_mode";
public const string GetCamera3DResource = "get_camera_3d_resource";
public const string SetCamera3DResource = "set_camera_3d_resource";
public const string GetThirdPersonRotation = "get_third_person_rotation";
public const string SetThirdPersonRotation = "set_third_person_rotation";
public const string GetThirdPersonRotationDegrees = "get_third_person_rotation_degrees";
public const string SetThirdPersonRotationDegrees = "set_third_person_rotation_degrees";
public const string GetThirdPersonQuaternion = "get_third_person_quaternion";
public const string SetThirdPersonQuaternion = "set_third_person_quaternion";
public const string GetVerticalRotationOffset = "get_vertical_rotation_offset";
public const string SetVerticalRotationOffset = "set_vertical_rotation_offset";
public const string GetHorizontalRotationOffset = "get_horizontal_rotation_offset";
public const string SetHorizontalRotationOffset = "set_horizontal_rotation_offset";
public const string GetSpringLength = "get_spring_length";
public const string SetSpringLength = "set_spring_length";
public const string GetFollowDistance = "get_follow_distance";
public const string SetFollowDistance = "set_follow_distance";
public const string GetAutoFollowDistance = "get_auto_follow_distance";
public const string SetAutoFollowDistance = "set_auto_follow_distance";
public const string GetAutoFollowDistanceMin = "get_auto_follow_distance_min";
public const string SetAutoFollowDistanceMin = "set_auto_follow_distance_min";
public const string GetAutoFollowDistanceMax = "get_auto_follow_distance_max";
public const string SetAutoFollowDistanceMax = "set_auto_follow_distance_max";
public const string GetAutoFollowDistanceDivisor = "get_auto_follow_distance_divisor";
public const string SetAutoFollowDistanceDivisor = "set_auto_follow_distance_divisor";
public const string GetLookAtTarget = "get_look_at_target";
public const string SetLookAtTarget = "set_look_at_target";
public const string GetLookAtTargets = "get_look_at_targets";
public const string SetLookAtTargets = "set_look_at_targets";
public const string IsLooking = "is_looking";
public const string GetUp = "get_up";
public const string SetUp = "set_up";
public const string GetUpTarget = "get_up_target";
public const string SetUpTarget = "set_up_target";
public const string GetCollisionMask = "get_collision_mask";
public const string SetCollisionMask = "set_collision_mask";
public const string SetCollisionMaskValue = "set_collision_mask_value";
public const string GetShape = "get_shape";
public const string SetShape = "set_shape";
public const string GetMargin = "get_margin";
public const string SetMargin = "set_margin";
public const string GetLookAtOffset = "get_look_at_offset";
public const string SetLookAtOffset = "set_look_at_offset";
public const string GetLookAtDamping = "get_look_at_damping";
public const string SetLookAtDamping = "set_look_at_damping";
public const string GetLookAtDampingValue = "get_look_at_damping_value";
public const string SetLookAtDampingValue = "set_look_at_damping_value";
public const string GetCullMask = "get_cull_mask";
public const string SetCullMask = "set_cull_mask";
public const string GetHOffset = "get_h_offset";
public const string SetHOffset = "set_h_offset";
public const string GetVOffset = "get_v_offset";
public const string SetVOffset = "set_v_offset";
public const string GetProjection = "get_projection";
public const string SetProjection = "set_projection";
public const string GetFov = "get_fov";
public const string SetFov = "set_fov";
public const string GetSize = "get_size";
public const string SetSize = "set_size";
public const string GetFrustumOffset = "get_frustum_offset";
public const string SetFrustumOffset = "set_frustum_offset";
public const string GetFar = "get_far";
public const string SetFar = "set_far";
public const string GetNear = "get_near";
public const string SetNear = "set_near";
public const string GetEnvironment = "get_environment";
public const string SetEnvironment = "set_environment";
public const string GetAttributes = "get_attributes";
public const string SetAttributes = "set_attributes";
public const string GetNoise = "get_noise";
public const string SetNoise = "set_noise";
}
public new static class SignalName
{
public const string LookAtTargetChanged = "look_at_target_changed";
public const string Camera3DResourceChanged = "camera_3d_resource_changed";
public const string Camera3DResourcePropertyChanged = "camera_3d_resource_property_changed";
}
}

View File

@ -0,0 +1 @@
uid://bx3g7jxtwhi04

View File

@ -0,0 +1,83 @@
using Godot;
namespace PhantomCamera.Noise;
public class PhantomCameraNoiseEmitter2D(GodotObject node)
{
public Node2D Node2D = (Node2D)node;
public PhantomCameraNoise2D Noise
{
get => new((Resource)Node2D.Call(MethodName.GetNoise));
set => Node2D.Call(MethodName.SetNoise, (GodotObject)value.Resource);
}
public bool Continuous
{
get => (bool)Node2D.Call(MethodName.GetContinuous);
set => Node2D.Call(MethodName.SetContinuous, value);
}
public float GrowthTime
{
get => (float)Node2D.Call(MethodName.GetGrowthTime);
set => Node2D.Call(MethodName.SetGrowthTime, value);
}
public float Duration
{
get => (float)Node2D.Call(MethodName.GetDuration);
set => Node2D.Call(MethodName.SetDuration, value);
}
public float DecayTime
{
get => (float)Node2D.Call(MethodName.GetDecayTime);
set => Node2D.Call(MethodName.SetDecayTime, value);
}
public int NoiseEmitterLayer
{
get => (int)Node2D.Call(MethodName.GetNoiseEmitterLayer);
set => Node2D.Call(MethodName.SetNoiseEmitterLayer, value);
}
public void SetNoiseEmitterLayerValue(int layer, bool value) =>
Node2D.Call(MethodName.SetNoiseEmitterLayerValue, layer, value);
public void Emit() => Node2D.Call(MethodName.Emit);
public bool IsEmitting() => (bool)Node2D.Call(MethodName.IsEmitting);
public void Stop() => Node2D.Call(MethodName.Stop);
public void Toggle() => Node2D.Call(MethodName.Toggle);
public static class MethodName
{
public const string GetNoise = "get_noise";
public const string SetNoise = "set_noise";
public const string GetContinuous = "get_continuous";
public const string SetContinuous = "set_continuous";
public const string GetGrowthTime = "get_growth_time";
public const string SetGrowthTime = "set_growth_time";
public const string GetDuration = "get_duration";
public const string SetDuration = "set_duration";
public const string GetDecayTime = "get_decay_time";
public const string SetDecayTime = "set_decay_time";
public const string GetNoiseEmitterLayer = "get_noise_emitter_layer";
public const string SetNoiseEmitterLayer = "set_noise_emitter_layer";
public const string SetNoiseEmitterLayerValue = "set_noise_emitter_layer_value";
public const string Emit = "emit";
public const string IsEmitting = "is_emitting";
public const string Stop = "stop";
public const string Toggle = "toggle";
}
}

View File

@ -0,0 +1 @@
uid://btom8l3wlkn2j

View File

@ -0,0 +1,83 @@
using Godot;
namespace PhantomCamera.Noise;
public class PhantomCameraNoiseEmitter3D(GodotObject node)
{
public Node3D Node3D = (Node3D)node;
public PhantomCameraNoise3D Noise
{
get => new((Resource)Node3D.Call(MethodName.GetNoise));
set => Node3D.Call(MethodName.SetNoise, (GodotObject)value.Resource);
}
public bool Continuous
{
get => (bool)Node3D.Call(MethodName.GetContinuous);
set => Node3D.Call(MethodName.SetContinuous, value);
}
public float GrowthTime
{
get => (float)Node3D.Call(MethodName.GetGrowthTime);
set => Node3D.Call(MethodName.SetGrowthTime, value);
}
public float Duration
{
get => (float)Node3D.Call(MethodName.GetDuration);
set => Node3D.Call(MethodName.SetDuration, value);
}
public float DecayTime
{
get => (float)Node3D.Call(MethodName.GetDecayTime);
set => Node3D.Call(MethodName.SetDecayTime, value);
}
public int NoiseEmitterLayer
{
get => (int)Node3D.Call(MethodName.GetNoiseEmitterLayer);
set => Node3D.Call(MethodName.SetNoiseEmitterLayer, value);
}
public void SetNoiseEmitterLayerValue(int layer, bool value) =>
Node3D.Call(MethodName.SetNoiseEmitterLayerValue, layer, value);
public void Emit() => Node3D.Call(MethodName.Emit);
public bool IsEmitting() => (bool)Node3D.Call(MethodName.IsEmitting);
public void Stop() => Node3D.Call(MethodName.Stop);
public void Toggle() => Node3D.Call(MethodName.Toggle);
public static class MethodName
{
public const string GetNoise = "get_noise";
public const string SetNoise = "set_noise";
public const string GetContinuous = "get_continuous";
public const string SetContinuous = "set_continuous";
public const string GetGrowthTime = "get_growth_time";
public const string SetGrowthTime = "set_growth_time";
public const string GetDuration = "get_duration";
public const string SetDuration = "set_duration";
public const string GetDecayTime = "get_decay_time";
public const string SetDecayTime = "set_decay_time";
public const string GetNoiseEmitterLayer = "get_noise_emitter_layer";
public const string SetNoiseEmitterLayer = "set_noise_emitter_layer";
public const string SetNoiseEmitterLayerValue = "set_noise_emitter_layer_value";
public const string Emit = "emit";
public const string IsEmitting = "is_emitting";
public const string Stop = "stop";
public const string Toggle = "toggle";
}
}

View File

@ -0,0 +1 @@
uid://buvda14filkjx

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
uid://bhexx6mj1xv3q

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
uid://csjccrhj5wnx7

Some files were not shown because too many files have changed in this diff Show More