viewporttexture experiment
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://c3feq8rrkjo6u"
|
||||
path="res://.godot/imported/platform.gltf-a8d62adaec6449e0d7d69986454becc1.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/platform/platform.gltf"
|
||||
dest_files=["res://.godot/imported/platform.gltf-a8d62adaec6449e0d7d69986454becc1.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=1
|
||||
gltf/embedded_image_handling=1
|
After Width: | Height: | Size: 50 KiB |
|
@ -0,0 +1,36 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dpt1fqi7kbhog"
|
||||
path.s3tc="res://.godot/imported/platform_116plsmoxingT.jpg-29d10181717c21ba5ff9a649fa80e19d.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/platform/platform_116plsmoxingT.jpg"
|
||||
dest_files=["res://.godot/imported/platform_116plsmoxingT.jpg-29d10181717c21ba5ff9a649fa80e19d.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
After Width: | Height: | Size: 767 KiB |
|
@ -0,0 +1,36 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://of8xlp10kuyf"
|
||||
path.s3tc="res://.godot/imported/platform_1225zhantai.jpg-59db1024fbfe2d16a8400af12e5054c1.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/platform/platform_1225zhantai.jpg"
|
||||
dest_files=["res://.godot/imported/platform_1225zhantai.jpg-59db1024fbfe2d16a8400af12e5054c1.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
After Width: | Height: | Size: 8.2 KiB |
|
@ -0,0 +1,36 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dyich8bbx40fo"
|
||||
path.s3tc="res://.godot/imported/platform_2cengtietu_zst.png-b1afb7c124792069329f4f2332f41751.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/platform/platform_2cengtietu_zst.png"
|
||||
dest_files=["res://.godot/imported/platform_2cengtietu_zst.png-b1afb7c124792069329f4f2332f41751.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
After Width: | Height: | Size: 330 KiB |
|
@ -0,0 +1,36 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://2xtf03ecucxo"
|
||||
path.s3tc="res://.godot/imported/platform_DKL_dimian111.jpg-c39631cac4e1cc1aa2552b0806cfd308.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/platform/platform_DKL_dimian111.jpg"
|
||||
dest_files=["res://.godot/imported/platform_DKL_dimian111.jpg-c39631cac4e1cc1aa2552b0806cfd308.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
After Width: | Height: | Size: 244 KiB |
|
@ -0,0 +1,36 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://d4ivipjugyuqr"
|
||||
path.s3tc="res://.godot/imported/platform_Godot_yanganqi.jpg-2afa7f3bb84666a93cbc91be92fba730.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/platform/platform_Godot_yanganqi.jpg"
|
||||
dest_files=["res://.godot/imported/platform_Godot_yanganqi.jpg-2afa7f3bb84666a93cbc91be92fba730.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
After Width: | Height: | Size: 378 KiB |
|
@ -0,0 +1,36 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bq6p4qky4hvri"
|
||||
path.s3tc="res://.godot/imported/platform_PBM_dandu_WUMING1.jpg-413386ed5a497e083284b10e1e5f923d.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/platform/platform_PBM_dandu_WUMING1.jpg"
|
||||
dest_files=["res://.godot/imported/platform_PBM_dandu_WUMING1.jpg-413386ed5a497e083284b10e1e5f923d.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
After Width: | Height: | Size: 63 KiB |
|
@ -0,0 +1,36 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dk4vvknrcwfvr"
|
||||
path.s3tc="res://.godot/imported/platform_QLS_qiangmian001.jpg-6a104d86c010c1b5fafed81ea997ae0f.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/platform/platform_QLS_qiangmian001.jpg"
|
||||
dest_files=["res://.godot/imported/platform_QLS_qiangmian001.jpg-6a104d86c010c1b5fafed81ea997ae0f.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
After Width: | Height: | Size: 169 KiB |
|
@ -0,0 +1,36 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bg6xr40jjqp4k"
|
||||
path.s3tc="res://.godot/imported/platform_haerbin_jz_menkuangyanse87.png-21cc209b4c0b1410d881df18062d8204.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/platform/platform_haerbin_jz_menkuangyanse87.png"
|
||||
dest_files=["res://.godot/imported/platform_haerbin_jz_menkuangyanse87.png-21cc209b4c0b1410d881df18062d8204.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
After Width: | Height: | Size: 173 KiB |
|
@ -0,0 +1,36 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bgr2aan4t7hjn"
|
||||
path.s3tc="res://.godot/imported/platform_haerbin_jz_wuzhanming.jpg-5fab5605d6646e259783c08d8bf2235d.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/platform/platform_haerbin_jz_wuzhanming.jpg"
|
||||
dest_files=["res://.godot/imported/platform_haerbin_jz_wuzhanming.jpg-5fab5605d6646e259783c08d8bf2235d.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
After Width: | Height: | Size: 18 KiB |
|
@ -0,0 +1,36 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cbk3yy5d07an4"
|
||||
path.s3tc="res://.godot/imported/platform_platform_haerbin_dandu_kongbai.jpg-f622e722f7041499de9aab939068a762.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/platform/platform_platform_haerbin_dandu_kongbai.jpg"
|
||||
dest_files=["res://.godot/imported/platform_platform_haerbin_dandu_kongbai.jpg-f622e722f7041499de9aab939068a762.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
|
@ -0,0 +1,58 @@
|
|||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://smgws0tjgxn0"
|
||||
path="res://.godot/imported/screenDoor.gltf-2a7804e98628e0c27770453c210039f4.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/screendoor/screenDoor.gltf"
|
||||
dest_files=["res://.godot/imported/screenDoor.gltf-2a7804e98628e0c27770453c210039f4.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={
|
||||
"nodes": {
|
||||
"PATH:CX1_CM1_Y": {
|
||||
"import/skip_import": true
|
||||
},
|
||||
"PATH:CX1_CM1_Z": {
|
||||
"import/skip_import": true
|
||||
},
|
||||
"PATH:JH_GD_JJTC": {
|
||||
"import/skip_import": true
|
||||
},
|
||||
"PATH:JH_GD_MTD": {
|
||||
"import/skip_import": true
|
||||
},
|
||||
"PATH:JH_GD_PSL": {
|
||||
"import/skip_import": true
|
||||
},
|
||||
"PATH:PBM1_PBM1_Y": {
|
||||
"import/skip_import": true
|
||||
},
|
||||
"PATH:PBM1_PBM1_Z": {
|
||||
"import/skip_import": true
|
||||
}
|
||||
}
|
||||
}
|
||||
gltf/naming_version=1
|
||||
gltf/embedded_image_handling=2
|
After Width: | Height: | Size: 121 KiB |
|
@ -0,0 +1,36 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cnlrebvyfclut"
|
||||
path.s3tc="res://.godot/imported/screenDoor_dt12.png-892d68978e70a4be806ff93224f2addc.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/screendoor/screenDoor_dt12.png"
|
||||
dest_files=["res://.godot/imported/screenDoor_dt12.png-892d68978e70a4be806ff93224f2addc.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
After Width: | Height: | Size: 120 KiB |
|
@ -0,0 +1,36 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bf2g7lwwpw20j"
|
||||
path.s3tc="res://.godot/imported/screenDoor_dtnb2.jpg-ca214319985668ec5306eaef1c89aafb.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/screendoor/screenDoor_dtnb2.jpg"
|
||||
dest_files=["res://.godot/imported/screenDoor_dtnb2.jpg-ca214319985668ec5306eaef1c89aafb.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
After Width: | Height: | Size: 169 KiB |
|
@ -0,0 +1,36 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dgnm1fstl304k"
|
||||
path.s3tc="res://.godot/imported/screenDoor_haerbin_jz_menkuangyanse87.png-6903df0f73aebbb4399e2ae103deeb80.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/screendoor/screenDoor_haerbin_jz_menkuangyanse87.png"
|
||||
dest_files=["res://.godot/imported/screenDoor_haerbin_jz_menkuangyanse87.png-6903df0f73aebbb4399e2ae103deeb80.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://bcf3gajson13b"
|
||||
path="res://.godot/imported/PBMceshi.fbx-45fcb4bc9dddc37e79a3cdadb4450f0d.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/screendoor1/PBMceshi.fbx"
|
||||
dest_files=["res://.godot/imported/PBMceshi.fbx-45fcb4bc9dddc37e79a3cdadb4450f0d.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=1
|
||||
gltf/embedded_image_handling=1
|
|
@ -0,0 +1,49 @@
|
|||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://biot7d8s87d3y"
|
||||
path="res://.godot/imported/screenDoor.gltf-4281b97e561fd9ddbbabbdde45e6cb26.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/models/screendoor1/screenDoor.gltf"
|
||||
dest_files=["res://.godot/imported/screenDoor.gltf-4281b97e561fd9ddbbabbdde45e6cb26.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={
|
||||
"nodes": {
|
||||
"PATH:CX1_CM1_Y": {
|
||||
"import/skip_import": true
|
||||
},
|
||||
"PATH:CX1_CM1_Z": {
|
||||
"import/skip_import": true
|
||||
},
|
||||
"PATH:JH_GD_JJTC": {
|
||||
"import/skip_import": true
|
||||
},
|
||||
"PATH:JH_GD_PSL": {
|
||||
"import/skip_import": true
|
||||
}
|
||||
}
|
||||
}
|
||||
gltf/naming_version=1
|
||||
gltf/embedded_image_handling=3
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m1 10v-4h5v-4l8 6-8 6v-4z" fill="#8da5f3" fill-opacity=".75" stroke="#8da5f3" stroke-linecap="square" stroke-miterlimit="3.2" stroke-width="2"/>
|
||||
</svg>
|
After Width: | Height: | Size: 299 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://ccvsqublgnwk0"
|
||||
path="res://.godot/imported/Arrow.svg-b46ebbd21161668ed7fc97a1bf0ae30d.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/2d_shapes/Arrow.svg"
|
||||
dest_files=["res://.godot/imported/Arrow.svg-b46ebbd21161668ed7fc97a1bf0ae30d.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="8" cy="8" r="6" fill="#8da5f3" fill-opacity=".75" stroke="#8da5f3" stroke-width="2"/>
|
||||
</svg>
|
After Width: | Height: | Size: 243 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c02gsg1f7ra7j"
|
||||
path="res://.godot/imported/Ellipse.svg-e4aaeb997f8842e6f1a13ab55b032b66.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/2d_shapes/Ellipse.svg"
|
||||
dest_files=["res://.godot/imported/Ellipse.svg-e4aaeb997f8842e6f1a13ab55b032b66.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 Dener Rosa (Technocat Dev)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bwefvbkl1pprc"
|
||||
path="res://.godot/imported/Node2D.svg-0add0097836c9633a7297abed46e1eeb.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/2d_shapes/Node2D.svg"
|
||||
dest_files=["res://.godot/imported/Node2D.svg-0add0097836c9633a7297abed46e1eeb.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="2.9231" y="2.9231" width="10.154" height="10.154" fill="#8da5f3" fill-opacity=".75" stroke="#8da5f3" stroke-linecap="square" stroke-miterlimit="3.2" stroke-width="1.8462"/>
|
||||
</svg>
|
After Width: | Height: | Size: 327 B |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c57gmrid7ke0b"
|
||||
path="res://.godot/imported/Rectangle.svg-36544af2e53ec1a165ec7b3fc3c2b2d0.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/2d_shapes/Rectangle.svg"
|
||||
dest_files=["res://.godot/imported/Rectangle.svg-36544af2e53ec1a165ec7b3fc3c2b2d0.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
|
@ -0,0 +1,32 @@
|
|||
extends "res://addons/2d_shapes/handles/ScalarHandle.gd"
|
||||
|
||||
const ScalarHandle = preload("ScalarHandle.gd")
|
||||
const Arrow = preload("../shapes/Arrow.gd")
|
||||
|
||||
var square: bool
|
||||
|
||||
|
||||
func _init(selected_shape: Arrow, position: Vector2, scalar_: String, axis_: Vector2 = Vector2.DOWN, square_: bool = false):
|
||||
super(selected_shape, position, scalar_, axis_)
|
||||
var transform_viewport := selected_shape.get_viewport_transform()
|
||||
var transform_global := selected_shape.get_global_transform_with_canvas()
|
||||
var target = selected_shape.target
|
||||
var arrow_rotation := target.angle() + PI / 2
|
||||
var arrow_transform := Transform2D(arrow_rotation, target)
|
||||
var handle_position := transform_viewport * transform_global * arrow_transform * position
|
||||
transform = Transform2D(arrow_rotation, handle_position)
|
||||
square = square_
|
||||
|
||||
|
||||
func draw(overlay: Control):
|
||||
if square:
|
||||
var global_rotation := shape.global_rotation
|
||||
overlay.draw_set_transform_matrix(transform.rotated_local(global_rotation))
|
||||
var rect := Rect2(Vector2(2,2), Vector2(4,4))
|
||||
overlay.draw_rect(Rect2(Vector2(-5,-5), Vector2(10,10)), Color.BLACK)
|
||||
overlay.draw_rect(Rect2(Vector2(-4,-4), Vector2(8,8)), Color.WHITE)
|
||||
overlay.draw_rect(Rect2(Vector2(-3,-3), Vector2(6,6)), Color.ORANGE_RED)
|
||||
overlay.draw_set_transform_matrix(Transform2D())
|
||||
else:
|
||||
super.draw(overlay)
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
extends Node
|
||||
|
||||
|
||||
const GeometricShape = preload("../shapes/GeometricShape.gd")
|
||||
|
||||
var transform: Transform2D
|
||||
var shape: GeometricShape
|
||||
|
||||
|
||||
func get_local_mouse_position() -> Vector2:
|
||||
var event_position = shape.get_viewport().get_mouse_position()
|
||||
var global_transform = shape.get_global_transform_with_canvas()
|
||||
return global_transform.affine_inverse() * transform.affine_inverse() * event_position
|
||||
|
||||
|
||||
func draw(overlay: Control) -> void:
|
||||
printerr('Function overlay was not implemented')
|
||||
pass
|
||||
|
||||
|
||||
func start_drag(event: InputEventMouseButton) -> void:
|
||||
printerr('Function start_drag was not implemented')
|
||||
pass
|
||||
|
||||
|
||||
func drag(event: InputEventMouseMotion) -> void:
|
||||
printerr('Function drag was not implemented')
|
||||
pass
|
||||
|
||||
|
||||
func end_drag(undo_redo: EditorUndoRedoManager) -> void:
|
||||
printerr('Function end_drag was not implemented')
|
||||
pass
|
||||
|
||||
|
||||
func on_shift_pressed(is_pressed: bool) -> void:
|
||||
pass
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
extends Handle
|
||||
|
||||
const Handle = preload("Handle.gd")
|
||||
|
||||
|
||||
const triangle_height_proportion = sqrt(3.0) / 2.0
|
||||
|
||||
var scalar: String
|
||||
var axis: Vector2
|
||||
var drag_start : Dictionary = {
|
||||
'mouse_position': Vector2()
|
||||
}
|
||||
|
||||
|
||||
func _init(selected_shape: GeometricShape, position: Vector2, scalar_: String, axis_: Vector2 = Vector2.DOWN):
|
||||
var transform_viewport := selected_shape.get_viewport_transform()
|
||||
var transform_global := selected_shape.get_global_transform_with_canvas()
|
||||
var pos = transform_viewport * transform_global * position
|
||||
shape = selected_shape
|
||||
scalar = scalar_
|
||||
axis = axis_
|
||||
transform = Transform2D(0.0, pos)
|
||||
|
||||
|
||||
func draw(overlay: Control):
|
||||
overlay.draw_set_transform_matrix(transform)
|
||||
overlay.draw_circle(Vector2.ZERO, 6, Color.BLACK)
|
||||
overlay.draw_circle(Vector2.ZERO, 5, Color.WHITE)
|
||||
overlay.draw_circle(Vector2.ZERO, 4, Color.ROYAL_BLUE)
|
||||
overlay.draw_set_transform_matrix(Transform2D())
|
||||
|
||||
|
||||
func start_drag(event: InputEventMouseButton):
|
||||
drag_start = {
|
||||
scalar: shape[scalar],
|
||||
'mouse_position': get_local_mouse_position()
|
||||
}
|
||||
|
||||
|
||||
func drag(event: InputEvent) -> void:
|
||||
var event_position = get_local_mouse_position()
|
||||
|
||||
var drag_delta: Vector2 = event_position - drag_start['mouse_position']
|
||||
shape[scalar] = drag_start[scalar] + drag_delta.dot(axis)
|
||||
|
||||
shape.queue_redraw()
|
||||
|
||||
|
||||
func end_drag(undo_redo: EditorUndoRedoManager):
|
||||
undo_redo.create_action("Set %s to %s" % [scalar, shape[scalar]])
|
||||
undo_redo.add_do_property(shape, scalar, shape[scalar])
|
||||
undo_redo.add_do_method(shape, "generate_geometry")
|
||||
undo_redo.add_undo_property(shape, scalar, drag_start[scalar])
|
||||
undo_redo.add_undo_method(shape, "generate_geometry")
|
||||
|
||||
undo_redo.commit_action()
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
extends Handle
|
||||
|
||||
const Handle = preload("Handle.gd")
|
||||
|
||||
|
||||
const position_offsets := [
|
||||
Vector2(-0.5, -0.5),
|
||||
Vector2(0, -0.5),
|
||||
Vector2(0.5, -0.5),
|
||||
Vector2(0.5, 0),
|
||||
Vector2(0.5, 0.5),
|
||||
Vector2(0, 0.5),
|
||||
Vector2(-0.5, 0.5),
|
||||
Vector2(-0.5, 0)
|
||||
]
|
||||
const size_transforms := [
|
||||
-Vector2.ONE,
|
||||
Vector2.UP,
|
||||
Vector2(1, -1),
|
||||
Vector2.RIGHT,
|
||||
Vector2.ONE,
|
||||
Vector2.DOWN,
|
||||
Vector2(-1, 1),
|
||||
Vector2.LEFT,
|
||||
]
|
||||
|
||||
var _index: int
|
||||
var size_transform: Vector2
|
||||
var keep_aspect_ratio := false
|
||||
|
||||
# previous drag state
|
||||
var drag_start : Dictionary = {
|
||||
'size': Vector2(),
|
||||
'transform': Transform2D(),
|
||||
'position': Vector2(),
|
||||
'mouse_position': Vector2()
|
||||
}
|
||||
|
||||
|
||||
func _init(selected_shape: GeometricShape, index: int):
|
||||
var transform_viewport := selected_shape.get_viewport_transform()
|
||||
var transform_global := selected_shape.get_global_transform_with_canvas()
|
||||
var pos = transform_viewport * transform_global * (position_offsets[index] * selected_shape.size)
|
||||
shape = selected_shape
|
||||
transform = Transform2D(0.0, pos)
|
||||
_index = index
|
||||
size_transform = size_transforms[index]
|
||||
|
||||
|
||||
func draw(overlay: Control):
|
||||
var global_rotation := shape.global_rotation
|
||||
overlay.draw_set_transform_matrix(transform.rotated_local(global_rotation))
|
||||
var rect := Rect2(Vector2(2,2), Vector2(4,4))
|
||||
overlay.draw_rect(Rect2(Vector2(-5,-5), Vector2(10,10)), Color.BLACK)
|
||||
overlay.draw_rect(Rect2(Vector2(-4,-4), Vector2(8,8)), Color.WHITE)
|
||||
overlay.draw_rect(Rect2(Vector2(-3,-3), Vector2(6,6)), Color.ORANGE_RED)
|
||||
if _index == 0:
|
||||
var transform_global := shape.get_global_transform_with_canvas()
|
||||
var transform_viewport := shape.get_viewport_transform()
|
||||
var scale_total := transform_viewport.get_scale() * transform_global.get_scale()
|
||||
var bounding_rect = Rect2(Vector2.ZERO, scale_total * shape.size)
|
||||
overlay.draw_rect(bounding_rect, Color.ORANGE_RED, false, 1)
|
||||
overlay.draw_set_transform_matrix(Transform2D())
|
||||
|
||||
|
||||
func start_drag(event: InputEventMouseButton):
|
||||
drag_start = {
|
||||
'size': shape.size,
|
||||
'transform': shape.get_global_transform_with_canvas(),
|
||||
'position': shape.position,
|
||||
'mouse_position': get_local_mouse_position()
|
||||
}
|
||||
|
||||
|
||||
func drag(event: InputEvent) -> void:
|
||||
var event_position = drag_start_get_local_mouse_position()
|
||||
var drag_delta: Vector2 = event_position - drag_start['mouse_position']
|
||||
|
||||
var new_size = drag_start['size'] + drag_delta * size_transform
|
||||
if shape.is_fixed_aspect_ratio() or keep_aspect_ratio:
|
||||
var fit_x := Vector2(new_size.x, new_size.x / drag_start['size'].aspect())
|
||||
var fit_y := Vector2(new_size.y * drag_start['size'].aspect(), new_size.y)
|
||||
shape.size = fit_x if size_transform.x else fit_y
|
||||
else:
|
||||
shape.size = new_size
|
||||
|
||||
var delta_size = shape.size - drag_start['size']
|
||||
# Transform proportionally to size change
|
||||
var position_transform = position_offsets[_index]
|
||||
shape.position = drag_start['position'] + shape.transform.basis_xform(position_transform * delta_size)
|
||||
shape.queue_redraw()
|
||||
|
||||
|
||||
func drag_start_get_local_mouse_position():
|
||||
var event_position = shape.get_viewport().get_mouse_position()
|
||||
var global_transform = drag_start['transform']
|
||||
return global_transform.affine_inverse() * transform.affine_inverse() * event_position
|
||||
|
||||
|
||||
func end_drag(undo_redo: EditorUndoRedoManager):
|
||||
undo_redo.create_action("Resize shape to %s" % shape.size)
|
||||
undo_redo.add_do_property(shape, "size", shape.size)
|
||||
undo_redo.add_do_property(shape, "position", shape.position)
|
||||
undo_redo.add_do_method(shape, "generate_geometry")
|
||||
undo_redo.add_undo_property(shape, "size", drag_start['size'])
|
||||
undo_redo.add_undo_property(shape, "position", drag_start['position'])
|
||||
undo_redo.add_undo_method(shape, "generate_geometry")
|
||||
|
||||
undo_redo.commit_action()
|
||||
|
||||
|
||||
func on_shift_pressed(is_pressed: bool):
|
||||
keep_aspect_ratio = is_pressed
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
extends Handle
|
||||
|
||||
const Handle = preload("Handle.gd")
|
||||
const Arrow = preload("../shapes/Arrow.gd")
|
||||
|
||||
const triangle_height_proportion = sqrt(3.0) / 2.0
|
||||
|
||||
var drag_start : Dictionary = {
|
||||
'target': Vector2(),
|
||||
'mouse_position': Vector2()
|
||||
}
|
||||
var snap_angle := false
|
||||
|
||||
|
||||
func _init(selected_shape: Arrow):
|
||||
var transform_viewport := selected_shape.get_viewport_transform()
|
||||
var transform_global := selected_shape.get_global_transform_with_canvas()
|
||||
var target = selected_shape.target
|
||||
var arrow_rotation := target.angle() + PI / 2
|
||||
var arrow_transform := Transform2D(arrow_rotation, target)
|
||||
var handle_position = transform_viewport * transform_global * arrow_transform * Vector2()
|
||||
transform = Transform2D(0.0, handle_position)
|
||||
shape = selected_shape
|
||||
|
||||
|
||||
func draw(overlay: Control):
|
||||
var transform_global := shape.get_global_transform_with_canvas()
|
||||
var transformed_target := transform_global.basis_xform(shape.target)
|
||||
var arrow_rotation := transformed_target.angle() + PI / 2
|
||||
overlay.draw_set_transform_matrix(transform.rotated_local(arrow_rotation))
|
||||
overlay.draw_colored_polygon(triangle(14.0), Color.BLACK)
|
||||
overlay.draw_colored_polygon(triangle(11.0), Color.WHITE)
|
||||
overlay.draw_colored_polygon(triangle(8.0), Color.ORANGE_RED)
|
||||
overlay.draw_set_transform_matrix(Transform2D())
|
||||
|
||||
|
||||
func triangle(height: float) -> PackedVector2Array:
|
||||
var side = height / triangle_height_proportion
|
||||
return [
|
||||
Vector2(-side / 2, height / 2),
|
||||
Vector2(0, -height / 2),
|
||||
Vector2(side / 2, height / 2),
|
||||
]
|
||||
|
||||
|
||||
func start_drag(event: InputEventMouseButton):
|
||||
drag_start = {
|
||||
'target': shape.target,
|
||||
'mouse_position': get_local_mouse_position()
|
||||
}
|
||||
|
||||
|
||||
func drag(event: InputEvent) -> void:
|
||||
var event_position = get_local_mouse_position()
|
||||
var drag_delta: Vector2 = event_position - drag_start['mouse_position']
|
||||
|
||||
var new_target: Vector2 = drag_start['target'] + drag_delta
|
||||
if snap_angle:
|
||||
var modulo := fmod(new_target.angle() + shape.global_rotation + TAU - PI / 24, PI / 12)
|
||||
var angle := new_target.angle() - modulo + PI / 24
|
||||
shape.target = new_target.length() * Vector2(cos(angle), sin(angle))
|
||||
else:
|
||||
shape.target = new_target
|
||||
|
||||
shape.queue_redraw()
|
||||
|
||||
|
||||
func end_drag(undo_redo: EditorUndoRedoManager):
|
||||
undo_redo.create_action("Set target to %s" % shape.target)
|
||||
undo_redo.add_do_property(shape, "target", shape.target)
|
||||
undo_redo.add_do_method(shape, "generate_geometry")
|
||||
undo_redo.add_undo_property(shape, "target", drag_start['target'])
|
||||
undo_redo.add_undo_method(shape, "generate_geometry")
|
||||
|
||||
undo_redo.commit_action()
|
||||
|
||||
func on_shift_pressed(is_pressed: bool) -> void:
|
||||
snap_angle = is_pressed
|
|
@ -0,0 +1,7 @@
|
|||
[plugin]
|
||||
|
||||
name="2D Shapes"
|
||||
description="Geometric shapes for prototyping and animation"
|
||||
author="Technocat Dev"
|
||||
version="0.1.0"
|
||||
script="plugin.gd"
|
|
@ -0,0 +1,93 @@
|
|||
@tool
|
||||
extends EditorPlugin
|
||||
|
||||
const GeometricShape = preload("./shapes/GeometricShape.gd")
|
||||
const Handle = preload("./handles/Handle.gd")
|
||||
|
||||
|
||||
var selected_shape: GeometricShape
|
||||
var dragged_handle: Handle = null
|
||||
var handles : Array
|
||||
var is_holding_shift := false
|
||||
|
||||
|
||||
#== node ==
|
||||
func _enter_tree() -> void:
|
||||
add_custom_type("Rectangle", "Node2D", preload("./shapes/Rectangle.gd"), preload("Rectangle.svg"))
|
||||
add_custom_type("Ellipse", "Node2D", preload("./shapes/Ellipse.gd"), preload("Ellipse.svg"))
|
||||
add_custom_type("Arrow", "Node2D", preload("./shapes/Arrow.gd"), preload("Arrow.svg"))
|
||||
add_undo_redo_inspector_hook_callback(undo_redo_callback)
|
||||
|
||||
|
||||
func _exit_tree() -> void:
|
||||
remove_custom_type("Rectangle")
|
||||
remove_custom_type("Ellipse")
|
||||
remove_custom_type("Arrow")
|
||||
remove_undo_redo_inspector_hook_callback(undo_redo_callback)
|
||||
|
||||
|
||||
#== plugin ==
|
||||
var undo_redo_callback = func (undo_redo: Object, modified_object:Object, property: String, new_value: Variant):
|
||||
if modified_object is GeometricShape:
|
||||
update_overlays()
|
||||
|
||||
|
||||
func _handles(object : Object) -> bool:
|
||||
return object is GeometricShape
|
||||
|
||||
|
||||
func _edit(object: Object) -> void:
|
||||
if object is GeometricShape:
|
||||
selected_shape = object
|
||||
update_overlays()
|
||||
|
||||
|
||||
func _make_visible(visible : bool) -> void:
|
||||
if not selected_shape:
|
||||
return
|
||||
if not visible:
|
||||
selected_shape = null
|
||||
update_overlays()
|
||||
|
||||
|
||||
#== drawing handles ==
|
||||
func _forward_canvas_draw_over_viewport(overlay: Control) -> void:
|
||||
if selected_shape and selected_shape.is_inside_tree():
|
||||
handles = selected_shape.draw_handles(overlay)
|
||||
|
||||
|
||||
func _forward_canvas_gui_input(event: InputEvent) -> bool:
|
||||
if not selected_shape or not selected_shape.visible:
|
||||
return false
|
||||
|
||||
# Clicking and releasing the click
|
||||
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
|
||||
if event.is_pressed():
|
||||
for handle: Handle in handles:
|
||||
if not handle.transform.origin.distance_to(event.position) < 10:
|
||||
continue
|
||||
handle.start_drag(event)
|
||||
dragged_handle = handle
|
||||
dragged_handle.on_shift_pressed(is_holding_shift)
|
||||
return true
|
||||
elif dragged_handle:
|
||||
dragged_handle.drag(event)
|
||||
dragged_handle.end_drag(get_undo_redo())
|
||||
dragged_handle = null
|
||||
return true
|
||||
|
||||
# Dragging
|
||||
if event is InputEventMouseMotion and dragged_handle:
|
||||
dragged_handle.drag(event)
|
||||
update_overlays()
|
||||
return true
|
||||
|
||||
# Pressing Shift
|
||||
if event is InputEventKey and event.keycode == KEY_SHIFT:
|
||||
is_holding_shift = event.is_pressed()
|
||||
if dragged_handle:
|
||||
dragged_handle.on_shift_pressed(event.is_pressed())
|
||||
return true
|
||||
|
||||
return false
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
@tool
|
||||
@icon("res://addons/2d_shapes/Arrow.svg")
|
||||
class_name Arrow extends GeometricShape
|
||||
|
||||
const GeometricShape = preload("GeometricShape.gd")
|
||||
const TargetHandle = preload("../handles/TargetHandle.gd")
|
||||
const ArrowScalarHandle = preload("../handles/ArrowScalarHandle.gd")
|
||||
|
||||
|
||||
const default_corner_radius := 10.0
|
||||
|
||||
|
||||
@export var target: Vector2 = Vector2.RIGHT * default_corner_radius * 10:
|
||||
get:
|
||||
return target
|
||||
set(value):
|
||||
var min_length := head_length + corner_radius
|
||||
target = value if value.length() > min_length else min_length * value.normalized()
|
||||
generate_geometry()
|
||||
|
||||
|
||||
@export var corner_radius: float = default_corner_radius:
|
||||
get:
|
||||
return corner_radius
|
||||
set(value):
|
||||
corner_radius = clamp(value, 0, min(head_width - stem_width, head_length, stem_width) / 2)
|
||||
generate_geometry()
|
||||
|
||||
|
||||
@export var head_length: float = default_corner_radius * 5:
|
||||
get:
|
||||
return head_length
|
||||
set(value):
|
||||
var arrow_length = target.length()
|
||||
head_length = clamp(value, corner_radius * 2, arrow_length - corner_radius)
|
||||
generate_geometry()
|
||||
|
||||
|
||||
@export var head_width: float = default_corner_radius * 6:
|
||||
get:
|
||||
return head_width
|
||||
set(value):
|
||||
head_width = clamp(value, corner_radius * 2 + stem_width, 10000)
|
||||
generate_geometry()
|
||||
|
||||
|
||||
@export var stem_width: float = default_corner_radius * 2:
|
||||
get:
|
||||
return stem_width
|
||||
set(value):
|
||||
stem_width = clamp(value, 2 * corner_radius, head_width - 2 * corner_radius)
|
||||
generate_geometry()
|
||||
|
||||
|
||||
func _ready():
|
||||
generate_geometry()
|
||||
|
||||
|
||||
func generate_geometry():
|
||||
var arrow_rotation := -target.angle() - PI / 2
|
||||
var arrow_length := target.length()
|
||||
var head_transform := Transform2D(arrow_rotation, Vector2(0, arrow_length))
|
||||
var nock_transform := Transform2D(arrow_rotation, Vector2.ZERO)
|
||||
polygon = head(head_transform)
|
||||
polygon.append_array(nock(nock_transform))
|
||||
queue_redraw()
|
||||
|
||||
|
||||
func head(head_transform: Transform2D) -> PackedVector2Array:
|
||||
# Find circles' centers
|
||||
var left_circle_center = Vector2(-head_width / 2 + corner_radius, head_length - corner_radius)
|
||||
var top_circle_center = Vector2(0, corner_radius)
|
||||
var right_circle_center = Vector2(head_width / 2 - corner_radius, head_length - corner_radius)
|
||||
|
||||
var points: PackedVector2Array = [Vector2(-stem_width / 2, head_length)]
|
||||
|
||||
# Left
|
||||
var left_start_angle = 3 * PI / 2
|
||||
var left_end_angle = -left_circle_center.angle_to_point(top_circle_center) + PI / 2
|
||||
points.append_array(arc(left_start_angle, left_end_angle, left_circle_center, corner_radius))
|
||||
# Top
|
||||
var top_end_angle = -left_end_angle + PI
|
||||
points.append_array(arc(left_end_angle, top_end_angle, top_circle_center, corner_radius))
|
||||
# Right
|
||||
points.append_array(arc(top_end_angle, left_start_angle, right_circle_center, corner_radius))
|
||||
points.append(Vector2(stem_width / 2, head_length))
|
||||
for i in range(points.size()):
|
||||
points[i] *= head_transform
|
||||
return points
|
||||
|
||||
|
||||
func nock(nock_transform: Transform2D) -> PackedVector2Array:
|
||||
var center_x = stem_width / 2 - corner_radius
|
||||
var points: PackedVector2Array = arc(0.0, -PI / 2, Vector2(center_x, -corner_radius), corner_radius)
|
||||
points.append_array(arc(-PI / 2, PI, Vector2(-center_x, -corner_radius), corner_radius))
|
||||
for i in range(points.size()):
|
||||
points[i] *= nock_transform
|
||||
return points
|
||||
|
||||
|
||||
func draw_handles(overlay: Control) -> Array:
|
||||
var arrow_length := target.length()
|
||||
var handles = []
|
||||
|
||||
handles.push_back(TargetHandle.new(self))
|
||||
|
||||
handles.push_back(ArrowScalarHandle.new(self, Vector2(head_width / 2 - corner_radius, head_length), 'corner_radius', Vector2.LEFT))
|
||||
handles.push_back(ArrowScalarHandle.new(self, Vector2(0, head_length), 'head_length', Vector2.DOWN, true))
|
||||
handles.push_back(ArrowScalarHandle.new(self, Vector2(-head_width / 2, head_length - corner_radius), 'head_width', Vector2.LEFT * 2, true))
|
||||
handles.push_back(ArrowScalarHandle.new(self, Vector2(stem_width / 2, head_length + (arrow_length - head_length - corner_radius) / 2), 'stem_width', Vector2.RIGHT * 2, true))
|
||||
|
||||
for i in range(handles.size() - 1, -1, -1):
|
||||
handles[i].draw(overlay)
|
||||
|
||||
return handles
|
||||
|
||||
|
||||
#func round_corners(points: PackedVector2Array) -> PackedVector2Array:
|
||||
#var new_points: PackedVector2Array = [points[0]]
|
||||
#for i in range(0, points.size() - 2):
|
||||
#var point1: Vector2 = points[i]
|
||||
#var point2: Vector2 = points[i + 1]
|
||||
#var point3: Vector2 = points[i + 2]
|
||||
#
|
||||
#var line_1_angle = positive_angle(-point2.angle_to_point(point1))
|
||||
#var line_2_angle = positive_angle(-point2.angle_to_point(point3))
|
||||
#var midway_angle = (line_1_angle + line_2_angle) / 2.0
|
||||
#var half_inside_angle = angle_difference(line_1_angle, line_2_angle) / 2.0
|
||||
#
|
||||
#var center_distance = corner_radius / sin(half_inside_angle)
|
||||
#
|
||||
#var circle_center = point2 + center_distance * Vector2(cos(midway_angle), -sin(midway_angle))
|
||||
#
|
||||
#var corner_points = corner(line_1_angle - PI / 2, line_2_angle + PI / 2, circle_center)
|
||||
#new_points.append_array(corner_points)
|
||||
#new_points.append(points[-1])
|
||||
#
|
||||
#return new_points
|
||||
|
||||
|
||||
#func max_corner_radius(points: PackedVector2Array) -> float:
|
||||
#var result = INF
|
||||
#for i in range(0, points.size() - 2):
|
||||
#var point1: Vector2 = points[i]
|
||||
#var point2: Vector2 = points[i + 1]
|
||||
#var point3: Vector2 = points[i + 2]
|
||||
#
|
||||
#var line_1_angle = positive_angle(-point2.angle_to_point(point1))
|
||||
#var line_2_angle = positive_angle(-point2.angle_to_point(point3))
|
||||
#var half_inside_angle = angle_difference(line_1_angle, line_2_angle) / 2.0
|
||||
#
|
||||
#var distance_1 := point2.distance_to(point1) if i == 0 else point2.distance_to(point1) / 2
|
||||
#var distance_2 := point2.distance_to(point3) if i == points.size() - 3 else point2.distance_to(point3) / 2
|
||||
#var max_radius = min(distance_1 * tan(half_inside_angle), distance_2 * tan(half_inside_angle))
|
||||
#result = min(result, max_radius)
|
||||
#return result
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
@tool
|
||||
@icon("res://addons/2d_shapes/Ellipse.svg")
|
||||
class_name Ellipse
|
||||
extends GeometricShape
|
||||
|
||||
const GeometricShape = preload("GeometricShape.gd")
|
||||
const SizeHandle = preload("../handles/SizeHandle.gd")
|
||||
|
||||
const default_size := 60.0
|
||||
|
||||
|
||||
func _ready():
|
||||
generate_geometry()
|
||||
|
||||
|
||||
@export var size: Vector2 = Vector2(default_size, default_size):
|
||||
get:
|
||||
return size
|
||||
set(value):
|
||||
if circle:
|
||||
var fit_x := Vector2(value.x, value.x)
|
||||
var fit_y := Vector2(value.y, value.y)
|
||||
|
||||
value = fit_x if size.y == value.y else fit_y
|
||||
|
||||
size.x = clamp(value.x, 3, 10000)
|
||||
size.y = clamp(value.y, 3, 10000)
|
||||
generate_geometry()
|
||||
|
||||
|
||||
@export var circle: bool = false:
|
||||
get:
|
||||
return circle
|
||||
set(value):
|
||||
circle = value
|
||||
size = size
|
||||
|
||||
|
||||
func is_fixed_aspect_ratio() -> bool:
|
||||
return circle
|
||||
|
||||
|
||||
func generate_geometry():
|
||||
polygon = arc(TAU, 0, Vector2.ZERO, min(size.x, size.y) / 2)
|
||||
|
||||
for i in range(polygon.size()):
|
||||
polygon[i][size.max_axis_index()] *= max(size.x, size.y) / min(size.x, size.y)
|
||||
|
||||
queue_redraw()
|
||||
|
||||
|
||||
func draw_handles(overlay: Control) -> Array:
|
||||
var handles = []
|
||||
|
||||
# Starting from top-left, clockwise order.
|
||||
for i in range(8):
|
||||
handles.push_back(SizeHandle.new(self, i))
|
||||
|
||||
# On click, the first handle on the array has priority. Visuals should reflect
|
||||
# that by drawing the first handle on top.
|
||||
for i in range(handles.size() - 1, -1, -1):
|
||||
handles[i].draw(overlay)
|
||||
|
||||
return handles
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
extends Node2D
|
||||
|
||||
|
||||
var polygon : PackedVector2Array
|
||||
|
||||
|
||||
@export_enum("Filled", "Outline", "Filled + Outline") var style: int = 0:
|
||||
get:
|
||||
return style
|
||||
set(value):
|
||||
style = value
|
||||
queue_redraw()
|
||||
|
||||
|
||||
@export var outline_width: int = 1:
|
||||
get:
|
||||
return outline_width
|
||||
set(value):
|
||||
outline_width = clamp(value, 0.01, 1000)
|
||||
queue_redraw()
|
||||
|
||||
|
||||
@export var fill_color: Color = Color.WHITE:
|
||||
get:
|
||||
return fill_color
|
||||
set(value):
|
||||
fill_color = value
|
||||
queue_redraw()
|
||||
|
||||
|
||||
@export var outline_color: Color = Color.BLACK:
|
||||
get:
|
||||
return outline_color
|
||||
set(value):
|
||||
outline_color = value
|
||||
queue_redraw()
|
||||
|
||||
|
||||
func _draw():
|
||||
if style == 0 or style == 2:
|
||||
# Polygon is assumed to be open, i.e. its last vertex is not equal the first
|
||||
# Closed polygons may fail triangulation!
|
||||
draw_colored_polygon(polygon, fill_color)
|
||||
if style == 1 or style == 2:
|
||||
var closed_polygon = polygon.duplicate()
|
||||
closed_polygon.push_back(polygon[0])
|
||||
draw_polyline(closed_polygon, outline_color, outline_width)
|
||||
|
||||
|
||||
func arc(start: float, end: float, center: Vector2, radius: float) -> PackedVector2Array:
|
||||
"""Draw arc in clockwise direction"""
|
||||
if radius < 0.01: # Skip drawing if radius is too close to zero
|
||||
return [center]
|
||||
|
||||
if start < end:
|
||||
start += TAU
|
||||
|
||||
var step: float = max(asin(4 / radius), 0.1) # Trying to keep distance between points at ~4
|
||||
var angle := start - step
|
||||
var coords: PackedVector2Array = []
|
||||
var start_point = Vector2(cos(start) * radius + center.x, -sin(start) * radius + center.y)
|
||||
var end_point = Vector2(cos(end) * radius + center.x, -sin(end) * radius + center.y)
|
||||
|
||||
coords.push_back(start_point)
|
||||
while angle > end:
|
||||
var point = Vector2(cos(angle) * radius + center.x, -sin(angle) * radius + center.y)
|
||||
if not point.distance_squared_to(end_point) < 8.0:
|
||||
coords.push_back(point)
|
||||
angle -= step
|
||||
coords.push_back(end_point)
|
||||
|
||||
return coords
|
||||
|
||||
|
||||
func draw_handles(overlay: Control) -> Array:
|
||||
printerr('Function draw_handles was not implemented')
|
||||
return []
|
||||
|
||||
|
||||
func generate_geometry() -> void:
|
||||
printerr('Function generate_geometry was not implemented')
|
||||
|
||||
|
||||
func is_fixed_aspect_ratio() -> bool:
|
||||
printerr('Function is_fixed_aspect_ratio was not implemented')
|
||||
return false
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
@tool
|
||||
@icon("res://addons/2d_shapes/Rectangle.svg")
|
||||
class_name Rectangle
|
||||
extends GeometricShape
|
||||
|
||||
const GeometricShape = preload("GeometricShape.gd")
|
||||
const Handle = preload("../handles/Handle.gd")
|
||||
const SizeHandle = preload("../handles/SizeHandle.gd")
|
||||
const ScalarHandle = preload("../handles/ScalarHandle.gd")
|
||||
|
||||
const default_corner_radius := 20.0
|
||||
const default_size := default_corner_radius * 3.0
|
||||
|
||||
|
||||
func _ready():
|
||||
generate_geometry()
|
||||
|
||||
|
||||
@export var size: Vector2 = Vector2(default_size, default_size):
|
||||
get:
|
||||
return size
|
||||
set(value):
|
||||
if square:
|
||||
var fit_x := Vector2(value.x, value.x)
|
||||
var fit_y := Vector2(value.y, value.y)
|
||||
|
||||
value = fit_x if size.y == value.y else fit_y
|
||||
|
||||
size.x = clamp(value.x, corner_radius * 2, 10000)
|
||||
size.y = clamp(value.y, corner_radius * 2, 10000)
|
||||
generate_geometry()
|
||||
|
||||
|
||||
@export var corner_radius: float = default_corner_radius:
|
||||
get:
|
||||
return corner_radius
|
||||
set(value):
|
||||
corner_radius = clamp(value, 0.0, size[size.min_axis_index()] / 2)
|
||||
generate_geometry()
|
||||
|
||||
|
||||
@export var square: bool = false:
|
||||
get:
|
||||
return square
|
||||
set(value):
|
||||
square = value
|
||||
size = size
|
||||
|
||||
|
||||
func is_fixed_aspect_ratio() -> bool:
|
||||
return square
|
||||
|
||||
|
||||
func generate_geometry():
|
||||
polygon = []
|
||||
polygon.append_array(top_left_corner())
|
||||
polygon.append_array(top_right_corner())
|
||||
polygon.append_array(bottom_right_corner())
|
||||
polygon.append_array(bottom_left_corner())
|
||||
for i in range(polygon.size()):
|
||||
polygon[i] -= size / 2
|
||||
queue_redraw()
|
||||
|
||||
|
||||
func top_left_corner() -> PackedVector2Array:
|
||||
return arc(PI, PI/2, Vector2(corner_radius, corner_radius), corner_radius)
|
||||
|
||||
|
||||
func top_right_corner() -> Array:
|
||||
return arc(PI/2, 0, Vector2(size.x - corner_radius, corner_radius), corner_radius)
|
||||
|
||||
|
||||
func bottom_right_corner() -> Array:
|
||||
return arc(2 * PI, 1.5 * PI, Vector2(size.x - corner_radius, size.y - corner_radius), corner_radius)
|
||||
|
||||
|
||||
func bottom_left_corner() -> Array:
|
||||
return arc(1.5 * PI, PI, Vector2(corner_radius, size.y - corner_radius), corner_radius)
|
||||
|
||||
|
||||
func draw_handles(overlay: Control) -> Array:
|
||||
var half_size := size / 2
|
||||
|
||||
var handles = []
|
||||
handles.push_back(ScalarHandle.new(self, Vector2(half_size.x, -half_size.y + corner_radius), 'corner_radius'))
|
||||
# Starting from top-left, clockwise order.
|
||||
for i in range(8):
|
||||
handles.push_back(SizeHandle.new(self, i))
|
||||
|
||||
# On click, the first handle on the array has priority. Visuals should reflect
|
||||
# that by drawing the first handle on top.
|
||||
for i in range(handles.size() - 1, -1, -1):
|
||||
handles[i].draw(overlay)
|
||||
|
||||
return handles
|
|
@ -0,0 +1,56 @@
|
|||
extends Node
|
||||
class_name Spherical
|
||||
|
||||
var radius: float
|
||||
var phi: float
|
||||
var theta: float
|
||||
|
||||
func _init(_radius: float = 1, _phi: float = 0, _theta: float = 0):
|
||||
radius = _radius
|
||||
phi = _phi
|
||||
theta = _theta
|
||||
|
||||
func set_to(_radius: float, _phi: float, _theta: float):
|
||||
radius = _radius
|
||||
phi = _phi
|
||||
theta = _theta
|
||||
|
||||
func copy(_other_spherical: Spherical):
|
||||
radius = _other_spherical._radius
|
||||
phi = _other_spherical._phi
|
||||
theta = _other_spherical._theta
|
||||
|
||||
func make_safe() -> void:
|
||||
var precision: float = 0.0000000000001
|
||||
phi = max(precision, min(PI - precision, phi))
|
||||
|
||||
func set_from_vector(v: Vector3):
|
||||
self.set_from_cartesian_coords(v.x, v.y, v.z)
|
||||
|
||||
func dampen(damping_factor:float) ->bool:
|
||||
theta *= (1 - damping_factor)
|
||||
phi *= (1 - damping_factor)
|
||||
if abs(theta) < 0.001:
|
||||
theta = 0.0
|
||||
if abs(phi) < 0.001:
|
||||
phi = 0.0
|
||||
if theta == 0 and phi == 0:
|
||||
radius = 0
|
||||
return abs(theta) > 0 or abs(phi) > 0
|
||||
|
||||
func set_from_cartesian_coords(x: float, y: float, z: float):
|
||||
radius = sqrt(x * x + y * y + z * z)
|
||||
if radius == 0:
|
||||
theta = 0
|
||||
phi = 0
|
||||
else:
|
||||
theta = atan2(x, z)
|
||||
phi = acos(clamp(y / radius, -1, 1))
|
||||
|
||||
func apply_to_vector(vector: Vector3) -> Vector3:
|
||||
var sin_phi_radius = sin(phi) * radius
|
||||
|
||||
vector.x = sin_phi_radius * sin(theta)
|
||||
vector.y = cos(phi) * radius
|
||||
vector.z = sin_phi_radius * cos(theta)
|
||||
return vector
|
|
@ -0,0 +1,398 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="100mm"
|
||||
height="100mm"
|
||||
viewBox="0 0 100 100"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
sodipodi:docname="godot-orbit-controls.svg"
|
||||
inkscape:export-filename="C:\Users\Luca\repos\godot_orbit_controls\icon-432-foreground.png"
|
||||
inkscape:export-xdpi="109.728"
|
||||
inkscape:export-ydpi="109.728"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
inkscape:snap-center="true"
|
||||
inkscape:snap-text-baseline="true"
|
||||
inkscape:snap-page="true"
|
||||
inkscape:zoom="1.4854841"
|
||||
inkscape:cx="122.85557"
|
||||
inkscape:cy="173.68075"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1009"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer2"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid6909" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs2">
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="marker1226"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Sstart"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(0.3) translate(-2.3,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;fill:context-stroke;stroke-width:0.62500000;stroke-linejoin:round"
|
||||
id="path1224" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible;"
|
||||
id="marker1216"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1Send"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(0.2) rotate(180) translate(6,0)"
|
||||
style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt;"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
id="path1214" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible;"
|
||||
id="Arrow1Send"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1Send"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(0.2) rotate(180) translate(6,0)"
|
||||
style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt;"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
id="path901" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="marker1198"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Sstart"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(0.3) translate(-2.3,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;fill:context-stroke;stroke-width:0.62500000;stroke-linejoin:round"
|
||||
id="path916" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible;"
|
||||
id="marker1189"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Send"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(0.3) rotate(180) translate(-2.3,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;fill:context-stroke;stroke-width:0.62500000;stroke-linejoin:round;"
|
||||
id="path919" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="marker1180"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="TriangleOutS"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(0.2)"
|
||||
style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt"
|
||||
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||
id="path1178" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="EmptyTriangleInS"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="EmptyTriangleInS"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(-0.2) translate(-3.0,0)"
|
||||
style="fill-rule:evenodd;fill:context-fill;stroke:context-stroke;stroke-width:1.0pt"
|
||||
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||
id="path1043" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="EmptyTriangleOutM"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="EmptyTriangleOutM"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(0.4) translate(-4.5,0)"
|
||||
style="fill-rule:evenodd;fill:context-fill;stroke:context-stroke;stroke-width:1.0pt"
|
||||
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||
id="path1049" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Scissors"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Scissors"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
style="fill:context-stroke;"
|
||||
d="M 9.0898857,-3.6061018 C 8.1198849,-4.7769976 6.3697607,-4.7358294 5.0623558,-4.2327734 L -3.1500488,-1.1548705 C -5.5383421,-2.4615840 -7.8983361,-2.0874077 -7.8983361,-2.7236578 C -7.8983361,-3.2209742 -7.4416699,-3.1119800 -7.5100293,-4.4068519 C -7.5756648,-5.6501286 -8.8736064,-6.5699315 -10.100428,-6.4884954 C -11.327699,-6.4958500 -12.599867,-5.5553341 -12.610769,-4.2584343 C -12.702194,-2.9520479 -11.603560,-1.7387447 -10.304005,-1.6532027 C -8.7816644,-1.4265411 -6.0857470,-2.3487593 -4.8210600,-0.082342643 C -5.7633447,1.6559151 -7.4350844,1.6607341 -8.9465707,1.5737277 C -10.201445,1.5014928 -11.708664,1.8611256 -12.307219,3.0945882 C -12.885586,4.2766744 -12.318421,5.9591904 -10.990470,6.3210002 C -9.6502788,6.8128279 -7.8098011,6.1912892 -7.4910978,4.6502760 C -7.2454393,3.4624530 -8.0864637,2.9043186 -7.7636052,2.4731223 C -7.5199917,2.1477623 -5.9728246,2.3362771 -3.2164999,1.0982979 L 5.6763468,4.2330688 C 6.8000164,4.5467672 8.1730685,4.5362646 9.1684433,3.4313614 L -0.051640930,-0.053722219 L 9.0898857,-3.6061018 z M -9.2179159,-5.5066058 C -7.9233569,-4.7838060 -8.0290767,-2.8230356 -9.3743431,-2.4433169 C -10.590861,-2.0196559 -12.145370,-3.2022863 -11.757521,-4.5207817 C -11.530373,-5.6026336 -10.104134,-6.0014137 -9.2179159,-5.5066058 z M -9.1616516,2.5107591 C -7.8108215,3.0096239 -8.0402087,5.2951947 -9.4138723,5.6023681 C -10.324932,5.9187072 -11.627422,5.4635705 -11.719569,4.3902287 C -11.897178,3.0851737 -10.363484,1.9060805 -9.1616516,2.5107591 z "
|
||||
id="schere" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="TriangleOutS"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="TriangleOutS"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(0.2)"
|
||||
style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt"
|
||||
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||
id="path1034" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Arrow2Sstart"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Sstart"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(0.3) translate(-2.3,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;fill:context-stroke;stroke-width:0.62500000;stroke-linejoin:round"
|
||||
id="path5281" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="marker8294"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="TriangleInS"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(-0.2)"
|
||||
style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt"
|
||||
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||
id="path8292" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="marker8202"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="TriangleInS"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(-0.2)"
|
||||
style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt"
|
||||
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||
id="path8200" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible;"
|
||||
id="Arrow2Send"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Send"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(0.3) rotate(180) translate(-2.3,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;fill:context-stroke;stroke-width:0.62500000;stroke-linejoin:round;"
|
||||
id="path5284" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="TriangleInS"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="TriangleInS"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(-0.2)"
|
||||
style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt"
|
||||
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||
id="path5390" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Arrow2Lstart"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(1.1) translate(1,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;fill:context-stroke;stroke-width:0.62500000;stroke-linejoin:round"
|
||||
id="path5269" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible;"
|
||||
id="Arrow2Lend"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(1.1) rotate(180) translate(1,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="fill-rule:evenodd;fill:context-stroke;stroke-width:0.62500000;stroke-linejoin:round;"
|
||||
id="path5272" />
|
||||
</marker>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
style="display:none">
|
||||
<circle
|
||||
style="fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:78.1248;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
id="path5891"
|
||||
cx="12.5"
|
||||
cy="12.5"
|
||||
r="12.5" />
|
||||
<circle
|
||||
style="fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:78.1248;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
id="path5891-1"
|
||||
cx="65.533005"
|
||||
cy="34.466991"
|
||||
r="12.5" />
|
||||
<circle
|
||||
style="fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:78.1248;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
id="path5891-2"
|
||||
cx="12.5"
|
||||
cy="87.5"
|
||||
r="12.5" />
|
||||
<circle
|
||||
style="fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:78.1248;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
id="path5891-29"
|
||||
cx="87.5"
|
||||
cy="87.5"
|
||||
r="12.5" />
|
||||
<path
|
||||
style="fill:none;stroke:#a5efac;stroke-width:12.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 12.5,87.499999 H 87.499999"
|
||||
id="path6313" />
|
||||
<path
|
||||
style="fill:none;stroke:#a5efac;stroke-width:12.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 12.5,87.499999 V 12.5"
|
||||
id="path6512" />
|
||||
<path
|
||||
style="fill:none;stroke:#a5efac;stroke-width:12.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 12.5,87.499999 65.533008,34.466992"
|
||||
id="path6512-6" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="Foreground"
|
||||
style="display:inline">
|
||||
<g
|
||||
id="g1025"
|
||||
transform="matrix(0.39797964,0,0,0.39797964,30.101018,30.101018)">
|
||||
<circle
|
||||
style="fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:78.1248;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
id="path5891-21"
|
||||
cx="12.5"
|
||||
cy="12.5"
|
||||
r="12.5" />
|
||||
<circle
|
||||
style="fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:78.1248;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
id="path5891-1-4"
|
||||
cx="65.533005"
|
||||
cy="34.466991"
|
||||
r="12.5" />
|
||||
<circle
|
||||
style="fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:78.1248;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
id="path5891-2-3"
|
||||
cx="12.5"
|
||||
cy="87.5"
|
||||
r="12.5" />
|
||||
<circle
|
||||
style="fill:#a5efac;fill-opacity:1;stroke:none;stroke-width:78.1248;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
id="path5891-29-2"
|
||||
cx="87.5"
|
||||
cy="87.5"
|
||||
r="12.5" />
|
||||
<path
|
||||
style="fill:none;stroke:#a5efac;stroke-width:12.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 12.5,87.499999 H 87.499999"
|
||||
id="path6313-7" />
|
||||
<path
|
||||
style="fill:none;stroke:#a5efac;stroke-width:12.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 12.5,87.499999 V 12.5"
|
||||
id="path6512-4" />
|
||||
<path
|
||||
style="fill:none;stroke:#a5efac;stroke-width:12.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 12.5,87.499999 65.533008,34.466992"
|
||||
id="path6512-6-6" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="g1043"
|
||||
inkscape:label="Background"
|
||||
style="display:none">
|
||||
<rect
|
||||
style="fill:#262c3b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.264583"
|
||||
id="rect1147"
|
||||
width="100"
|
||||
height="100"
|
||||
x="0"
|
||||
y="0" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 16 KiB |
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dfiu3jqg4w85u"
|
||||
path="res://.godot/imported/godot-orbit-controls.svg-88feaaf0a954aecc34fd3f505575a187.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/orbit-controls/godot-orbit-controls.svg"
|
||||
dest_files=["res://.godot/imported/godot-orbit-controls.svg-88feaaf0a954aecc34fd3f505575a187.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
After Width: | Height: | Size: 391 B |
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://d20432vdtcyfj"
|
||||
path="res://.godot/imported/node-icon.png-4ab6d8b229d64bf1f2a5d02276cf9ecd.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/orbit-controls/node-icon.png"
|
||||
dest_files=["res://.godot/imported/node-icon.png-4ab6d8b229d64bf1f2a5d02276cf9ecd.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
|
@ -0,0 +1,865 @@
|
|||
@tool
|
||||
extends Control
|
||||
|
||||
# SIGNALS #
|
||||
signal start
|
||||
signal change
|
||||
signal end
|
||||
|
||||
# ENUMS #
|
||||
|
||||
enum MOUSE {
|
||||
LEFT = 0,
|
||||
MIDDLE = 1,
|
||||
RIGHT = 2,
|
||||
ROTATE = 0,
|
||||
DOLLY = 1,
|
||||
PAN = 2
|
||||
}
|
||||
|
||||
enum STATE {
|
||||
NONE = 0,
|
||||
ROTATE = 1,
|
||||
DOLLY = 2,
|
||||
PAN = 3,
|
||||
TOUCH_ROTATE = 4,
|
||||
TOUCH_PAN = 5,
|
||||
TOUCH_DOLLY_PAN = 6,
|
||||
TOUCH_DOLLY_ROTATE = 7
|
||||
}
|
||||
|
||||
enum TOUCH {
|
||||
ROTATE,
|
||||
PAN,
|
||||
DOLLY_PAN,
|
||||
DOLLY_ROTATE
|
||||
}
|
||||
|
||||
const EPSILON:float = 0.0001
|
||||
|
||||
### PROPERTIES IN INSPECTOR ###
|
||||
|
||||
@export_category("Orbit Control Settings")
|
||||
@export
|
||||
var enabled: bool = true
|
||||
@export
|
||||
var debug: bool = false
|
||||
@export_node_path("Camera3D")
|
||||
var _camera: NodePath = NodePath()
|
||||
var camera:Camera3D = null
|
||||
|
||||
@export_group("Target")
|
||||
@export
|
||||
var target: Vector3 = Vector3(0, 0, 0)
|
||||
|
||||
# AUTO-ROTATE
|
||||
@export_group("Auto Rotate")
|
||||
@export
|
||||
var auto_rotate: bool = false
|
||||
@export_range(0.001, 10.0)
|
||||
var auto_rotate_speed: float = 1.0
|
||||
|
||||
# ROTATE
|
||||
@export_group("Rotate")
|
||||
@export
|
||||
var enable_rotate: bool = true
|
||||
@export_range(0.001, 10.0)
|
||||
var rotate_speed: float = 1.0
|
||||
|
||||
# DOLLY (Perspective Cam only)
|
||||
@export_group("Dolly")
|
||||
@export_range(0.001, 100.0)
|
||||
var min_distance: float = 0.001
|
||||
@export_range(0.001, 100.0)
|
||||
var max_distance: float = 100.0
|
||||
|
||||
# ZOOM (Orthographic Camera only)
|
||||
@export_group("Zoom")
|
||||
@export
|
||||
var enable_zoom: bool = true
|
||||
@export_range(0.001, 100.0)
|
||||
var zoom_speed: float = 1.0
|
||||
@export_range(0.001, 100.0)
|
||||
var min_zoom: float = 0.001
|
||||
@export_range(0.001, 100.0)
|
||||
var max_zoom: float = 100.0
|
||||
|
||||
# LIMITS
|
||||
@export_group("Limits")
|
||||
@export_range(0, 180, 0.001, "radians")
|
||||
var min_polar_angle: float = 0
|
||||
@export_range(0, 180, 0.001, "radians")
|
||||
var max_polar_angle: float = PI
|
||||
@export_range(-360, 360, 0.001, "radians")
|
||||
var min_azimuth_angle: float = - TAU
|
||||
@export_range(-360, 360, 0.001, "radians")
|
||||
var max_azimuth_angle: float = TAU
|
||||
|
||||
# DAMPING
|
||||
@export_group("Damping")
|
||||
@export
|
||||
var enable_damping: bool = true
|
||||
@export_range(0.001, 0.99)
|
||||
var damping_factor: float = 0.05
|
||||
|
||||
# PAN
|
||||
@export_group("Pan")
|
||||
@export
|
||||
var enable_pan: bool = true
|
||||
@export_range(0.001, 10.00)
|
||||
var pan_speed: float = 1.0
|
||||
@export
|
||||
var screen_space_panning: bool = false
|
||||
@export_range(0.001, 100.00)
|
||||
var key_pan_speed: float = 7.0
|
||||
|
||||
### END OF PROPERTIES ###
|
||||
|
||||
# Internal State
|
||||
var radius: float = 1.0
|
||||
var debug_layer: CanvasLayer = null
|
||||
var debug_nodes = {}
|
||||
|
||||
# HELPERS
|
||||
var spherical = Spherical.new()
|
||||
var spherical_delta = Spherical.new()
|
||||
|
||||
# On rotate (left click)
|
||||
var rotate_start = Vector2(0, 0)
|
||||
var rotate_end = Vector2(0, 0)
|
||||
var rotate_delta = Vector2(0, 0)
|
||||
|
||||
# On pan (right click)
|
||||
var pan_start = Vector2(0, 0)
|
||||
var pan_end = Vector2(0, 0)
|
||||
var pan_delta = Vector2(0, 0)
|
||||
|
||||
# on Dolly
|
||||
var dolly_start = Vector2(0, 0)
|
||||
var dolly_end = Vector2(0, 0)
|
||||
var dolly_delta = Vector2(0, 0)
|
||||
|
||||
var pointers = []
|
||||
var pointerPositions = {}
|
||||
|
||||
# Other
|
||||
var orbit_scale: float = 1
|
||||
var pan_offset = Vector3(0, 0, 0)
|
||||
var needs_update:bool = true
|
||||
|
||||
var mouse_buttons = { "LEFT": MOUSE.ROTATE, "MIDDLE": MOUSE.DOLLY, "RIGHT": MOUSE.PAN }
|
||||
var touches = { "ONE": TOUCH.ROTATE, "TWO": TOUCH.DOLLY_PAN }
|
||||
var state = STATE.NONE
|
||||
|
||||
# for reset
|
||||
var target0: Vector3 = Vector3(0, 0, 0)
|
||||
var position0: Vector3 = Vector3(0, 0, 0)
|
||||
var zoom0: float = 1.0
|
||||
var valid: bool = false
|
||||
|
||||
func _ready() -> void:
|
||||
|
||||
# Code to run in-game
|
||||
if not Engine.is_editor_hint():
|
||||
|
||||
valid = check_camera()
|
||||
|
||||
# for reset
|
||||
target0 = target
|
||||
position0 = camera.position
|
||||
zoom0 = camera.fov
|
||||
|
||||
if debug:
|
||||
enable_debug()
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if not valid:
|
||||
return
|
||||
|
||||
if needs_update:
|
||||
update()
|
||||
|
||||
if debug:
|
||||
debug_nodes["state"].text = "STATE: " + STATE.keys()[state]
|
||||
|
||||
func update() -> void:
|
||||
needs_update = auto_rotate
|
||||
var offset: Vector3 = Vector3(0, 0, 0)
|
||||
|
||||
# the current position of the camera
|
||||
var position: Vector3 = camera.position
|
||||
|
||||
# the current offset, copies the position into offset
|
||||
# and subtracts the target vector
|
||||
|
||||
# copy the camera position to offset
|
||||
offset = position
|
||||
|
||||
# subtract the target position
|
||||
offset -= target
|
||||
|
||||
# set the spherical coords to this offset vector
|
||||
spherical.set_from_vector(offset)
|
||||
|
||||
# enable auto rotate if configured
|
||||
if auto_rotate && state == STATE.NONE:
|
||||
rotate_left(get_auto_rotation_angle())
|
||||
|
||||
# # Dampen the actual spherical with the damping every frame
|
||||
if enable_damping:
|
||||
spherical.theta += spherical_delta.theta * damping_factor
|
||||
spherical.phi += spherical_delta.phi * damping_factor
|
||||
else: # or without damping
|
||||
spherical.theta += spherical_delta.theta
|
||||
spherical.phi += spherical_delta.phi
|
||||
|
||||
# restrict theta to be between desired limits
|
||||
var _min = min_azimuth_angle + EPSILON
|
||||
var _max = max_azimuth_angle - EPSILON
|
||||
|
||||
# some is_finite() check missing here, as godot does not seem to allow infinite numbers anyway
|
||||
if _min < - PI:
|
||||
_min += TAU
|
||||
elif _min > PI:
|
||||
_min -= TAU
|
||||
|
||||
if _max < - PI:
|
||||
_max += TAU
|
||||
elif _max > PI:
|
||||
_max -= TAU
|
||||
|
||||
if _min <= _max:
|
||||
spherical.theta = max(_min, min(_max, spherical.theta))
|
||||
else:
|
||||
if spherical.theta > (_min + _max / float(2)):
|
||||
spherical.theta = max(_min, spherical.theta)
|
||||
else:
|
||||
spherical.theta = min(_max, spherical.theta)
|
||||
|
||||
# restrict phi to be between desired limits
|
||||
spherical.phi = clampf(spherical.phi, min_polar_angle + EPSILON, max_polar_angle - EPSILON)
|
||||
|
||||
spherical.make_safe()
|
||||
|
||||
spherical.radius *= orbit_scale
|
||||
|
||||
# restrict radius to be between desired limits
|
||||
spherical.radius = max(min_distance, min(max_distance, spherical.radius))
|
||||
|
||||
# move target to panned location
|
||||
if enable_damping:
|
||||
target += pan_offset * damping_factor
|
||||
else:
|
||||
target += pan_offset
|
||||
|
||||
offset = spherical.apply_to_vector(offset)
|
||||
|
||||
position = target + offset
|
||||
|
||||
camera.look_at_from_position(position, target, Vector3.UP)
|
||||
emit_signal("change")
|
||||
|
||||
# Dampen the delta spherical by the damping factor
|
||||
if enable_damping:
|
||||
# only update during _process when still dampening
|
||||
needs_update = spherical_delta.dampen(damping_factor) or auto_rotate
|
||||
pan_offset *= (1 - damping_factor)
|
||||
if pan_offset.length_squared() > 0.001:
|
||||
needs_update = true
|
||||
|
||||
else:
|
||||
spherical_delta.set_from_cartesian_coords(0, 0, 0)
|
||||
pan_offset = Vector3.ZERO
|
||||
|
||||
orbit_scale = 1
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if enabled == false:
|
||||
return
|
||||
|
||||
# ON MOUSE DOWN (left, middle, right)
|
||||
if event is InputEventMouseButton and (event.button_index == MOUSE_BUTTON_LEFT or event.button_index == MOUSE_BUTTON_RIGHT or event.button_index == MOUSE_BUTTON_MIDDLE) and event.pressed:
|
||||
on_mouse_down(event)
|
||||
|
||||
# ON MOUSE UP
|
||||
if event is InputEventMouseButton and not event.pressed:
|
||||
on_mouse_up(event)
|
||||
|
||||
if event is InputEventMouseMotion:
|
||||
|
||||
# Windows has a bug that triggers an InputEventMouseMotion event on
|
||||
# releasing button clicks # with event.relative = 0, 0
|
||||
# so filtering that out
|
||||
if not event.relative == Vector2.ZERO:
|
||||
on_mouse_move(event)
|
||||
|
||||
# ON MOUSE WHEEL
|
||||
if event is InputEventMouseButton and (event.button_index == MOUSE_BUTTON_WHEEL_DOWN or event.button_index == MOUSE_BUTTON_WHEEL_UP):
|
||||
on_mouse_wheel(event)
|
||||
|
||||
# ON TOUCH
|
||||
if event is InputEventScreenTouch:
|
||||
if event.pressed:
|
||||
on_touch_down(event)
|
||||
else:
|
||||
on_touch_up(event)
|
||||
|
||||
# ON TOUCH DRAG
|
||||
if event is InputEventScreenDrag:
|
||||
on_touch_move(event)
|
||||
|
||||
func save_state() -> void:
|
||||
target0 = target
|
||||
position0 = camera.position
|
||||
zoom0 = camera.fov
|
||||
|
||||
func reset() -> void:
|
||||
target = target0
|
||||
camera.position = position0
|
||||
camera.fov = zoom0
|
||||
|
||||
update()
|
||||
|
||||
state = STATE.NONE
|
||||
|
||||
### Functions ###
|
||||
|
||||
## Getters
|
||||
|
||||
func get_polar_angle() -> float:
|
||||
return spherical.phi
|
||||
|
||||
func get_azimuthal_angle() -> float:
|
||||
return spherical.theta
|
||||
|
||||
func get_distance() -> float:
|
||||
return camera.position.distance_squared_to(target)
|
||||
|
||||
func get_auto_rotation_angle() -> float:
|
||||
return (TAU / 360) * auto_rotate_speed
|
||||
|
||||
func get_zoom_scale() -> float:
|
||||
return pow(0.95, zoom_speed)
|
||||
|
||||
### ROTATION ###
|
||||
|
||||
func rotate_left(angle: float) -> void:
|
||||
spherical_delta.theta -= angle
|
||||
|
||||
func rotate_up(angle: float) -> void:
|
||||
spherical_delta.phi -= angle
|
||||
|
||||
### DOLLY ###
|
||||
|
||||
func dolly_out(dolly_scale: float) -> void:
|
||||
if camera.projection == Camera3D.PROJECTION_PERSPECTIVE:
|
||||
orbit_scale /= dolly_scale
|
||||
elif camera.projection == Camera3D.PROJECTION_ORTHOGONAL:
|
||||
camera.size = max(min_zoom, min(max_zoom, camera.size))
|
||||
#zoom changed = true
|
||||
else:
|
||||
print("Unknown camera type detected. Zooming disabled")
|
||||
enable_zoom = false
|
||||
|
||||
func dolly_in(dolly_scale: float) -> void:
|
||||
if camera.projection == Camera3D.PROJECTION_PERSPECTIVE:
|
||||
orbit_scale *= dolly_scale
|
||||
elif camera.projection == Camera3D.PROJECTION_ORTHOGONAL:
|
||||
camera.size = max(min_zoom, min(max_zoom, camera.size / dolly_scale))
|
||||
else:
|
||||
print("Unknown camera type detected. Zooming disabled")
|
||||
enable_zoom = false
|
||||
|
||||
### PAN ###
|
||||
|
||||
func pan(delta_x, delta_y) -> void:
|
||||
var offset = Vector3()
|
||||
|
||||
if camera.projection == Camera3D.PROJECTION_PERSPECTIVE:
|
||||
var position = camera.position
|
||||
offset = position - target
|
||||
var target_distance = offset.length()
|
||||
|
||||
# half of the FOV is the vertical center of the screen
|
||||
target_distance *= tan(camera.fov / 2.0) * PI / 180.0
|
||||
|
||||
pan_left(2 * delta_x * target_distance / get_viewport().get_size().y, camera.transform)
|
||||
|
||||
#pan_up(1, camera.transform)
|
||||
pan_up(2 * delta_y * target_distance / get_viewport().get_size().y, camera.transform)
|
||||
|
||||
elif camera.projection == Camera3D.PROJECTION_ORTHOGONAL:
|
||||
#pan_left(delta_y)
|
||||
pass
|
||||
|
||||
else:
|
||||
print("Unknown camera type - pan disabled")
|
||||
enable_pan = false
|
||||
|
||||
func pan_left(distance, matrix) -> void:
|
||||
var v = Vector3()
|
||||
|
||||
# get x column of camera
|
||||
v = matrix.basis.x
|
||||
|
||||
v *= - distance
|
||||
|
||||
pan_offset += v
|
||||
|
||||
func pan_up(distance, matrix) -> void:
|
||||
var v = Vector3()
|
||||
|
||||
if screen_space_panning:
|
||||
v = matrix.basis.x
|
||||
else:
|
||||
v = matrix.basis.y
|
||||
v.cross(Vector3(0, 1, 0))
|
||||
|
||||
v *= distance
|
||||
|
||||
pan_offset += v
|
||||
|
||||
### POINTER HANDLING
|
||||
|
||||
func add_pointer(event):
|
||||
pointers.push_back(event)
|
||||
|
||||
func remove_pointer(event):
|
||||
|
||||
pointerPositions.erase(event.index)
|
||||
|
||||
for i in pointers.size():
|
||||
if pointers[i].index == event.index:
|
||||
pointers.remove(i)
|
||||
return
|
||||
|
||||
func track_pointer(event):
|
||||
|
||||
var pointer_index = 0
|
||||
var position = Vector2()
|
||||
|
||||
# a mouse event does not have an index
|
||||
# and assume there are no more than one mouse pointer
|
||||
if not event is InputEventMouse:
|
||||
pointer_index = event.index
|
||||
|
||||
if not pointerPositions.has(pointer_index):
|
||||
pointerPositions[pointer_index] = Vector2(0, 0)
|
||||
|
||||
pointerPositions[pointer_index].x = event.position.x
|
||||
pointerPositions[pointer_index].y = event.position.y
|
||||
|
||||
# "on_" functions define the first action after the input event
|
||||
|
||||
func on_mouse_down(event):
|
||||
var mouse_action = null
|
||||
|
||||
match event.button_index:
|
||||
MOUSE_BUTTON_LEFT:
|
||||
mouse_action = mouse_buttons.LEFT
|
||||
MOUSE_BUTTON_MIDDLE:
|
||||
mouse_action = mouse_buttons.MIDDLE
|
||||
MOUSE_BUTTON_RIGHT:
|
||||
mouse_action = mouse_buttons.RIGHT
|
||||
_:
|
||||
mouse_action = -1 # why not none?
|
||||
|
||||
match mouse_action:
|
||||
MOUSE.DOLLY:
|
||||
if not enable_zoom: return
|
||||
|
||||
handle_mouse_down_dolly(event)
|
||||
|
||||
state = STATE.DOLLY
|
||||
MOUSE.ROTATE:
|
||||
#if event.ctrlKey or event.metaKey or event.shiftkey
|
||||
#if not enable pan: return
|
||||
#handle_mouse_down_pan(event)
|
||||
#state = STATE.PAN
|
||||
#else
|
||||
if not enable_rotate: return
|
||||
|
||||
handle_mouse_down_rotate(event)
|
||||
|
||||
state = STATE.ROTATE
|
||||
|
||||
MOUSE.PAN:
|
||||
#if event.ctrlKey or event.metaKey or event.shiftkey
|
||||
#if not enable pan: return
|
||||
#handle_mouse_down_rotate(event)
|
||||
#state = STATE.PAN
|
||||
#else
|
||||
if not enable_pan: return
|
||||
|
||||
handle_mouse_down_pan(event)
|
||||
|
||||
state = STATE.PAN
|
||||
|
||||
_:
|
||||
state = STATE.NONE
|
||||
|
||||
if not state == STATE.NONE:
|
||||
emit_signal("start")
|
||||
|
||||
func on_mouse_move(event):
|
||||
#print("on_mouse_move")
|
||||
#track_pointer(event)
|
||||
|
||||
match state:
|
||||
STATE.ROTATE:
|
||||
if not enable_rotate: return
|
||||
|
||||
handle_mouse_move_rotate(event)
|
||||
|
||||
STATE.DOLLY:
|
||||
if not enable_zoom: return
|
||||
|
||||
handle_mouse_move_dolly(event)
|
||||
|
||||
STATE.PAN:
|
||||
if not enable_pan: return
|
||||
|
||||
handle_mouse_move_pan(event)
|
||||
|
||||
func on_mouse_wheel(event):
|
||||
if enabled == false or enable_zoom == false or state != STATE.NONE:
|
||||
return
|
||||
|
||||
emit_signal("start")
|
||||
|
||||
handle_mouse_wheel(event)
|
||||
|
||||
emit_signal("end")
|
||||
|
||||
func on_touch_down(event):
|
||||
add_pointer(event)
|
||||
|
||||
track_pointer(event)
|
||||
|
||||
match pointers.size():
|
||||
|
||||
1:
|
||||
|
||||
match touches.ONE:
|
||||
|
||||
TOUCH.ROTATE:
|
||||
if enable_rotate == false:
|
||||
return
|
||||
|
||||
handle_touch_start_rotate()
|
||||
|
||||
state = STATE.TOUCH_ROTATE
|
||||
|
||||
TOUCH.PAN:
|
||||
if enable_pan == false:
|
||||
return
|
||||
|
||||
handle_touch_start_pan()
|
||||
|
||||
state = STATE.TOUCH_PAN
|
||||
|
||||
_:
|
||||
state = STATE.NONE
|
||||
|
||||
2:
|
||||
|
||||
match touches.TWO:
|
||||
|
||||
TOUCH.DOLLY_PAN:
|
||||
if enable_zoom == false && enable_pan == false:
|
||||
return
|
||||
|
||||
handle_touch_start_dolly_pan()
|
||||
|
||||
state = STATE.TOUCH_DOLLY_PAN
|
||||
|
||||
TOUCH.DOLLY_ROTATE:
|
||||
if enable_zoom == false && enable_rotate == false:
|
||||
return
|
||||
|
||||
state = STATE.TOUCH_DOLLY_ROTATE
|
||||
|
||||
_:
|
||||
state = STATE.NONE
|
||||
|
||||
_:
|
||||
state = STATE.NONE
|
||||
|
||||
if state != STATE.NONE:
|
||||
emit_signal("start")
|
||||
|
||||
func on_touch_up(event):
|
||||
remove_pointer(event)
|
||||
|
||||
# how can I re-evaluate the state?
|
||||
# e.g. we are in touch_dolly_pan and lift one finger.
|
||||
# We should be in touch_rotate state then and not NONE
|
||||
state = STATE.NONE
|
||||
|
||||
func on_mouse_up(event):
|
||||
# remove_pointer not needed here
|
||||
|
||||
# how can I re-evaluate the state?
|
||||
# e.g. we are in touch_dolly_pan and lift one finger.
|
||||
# We should be in touch_rotate state then and not NONE
|
||||
state = STATE.NONE
|
||||
|
||||
# calls handle_-functions depending on number of pointers
|
||||
func on_touch_move(event):
|
||||
|
||||
track_pointer(event)
|
||||
|
||||
match state:
|
||||
|
||||
STATE.TOUCH_ROTATE:
|
||||
|
||||
if enable_rotate == false:
|
||||
return
|
||||
|
||||
handle_touch_move_rotate(event)
|
||||
|
||||
update()
|
||||
|
||||
STATE.TOUCH_PAN:
|
||||
|
||||
if enable_pan == false:
|
||||
return
|
||||
|
||||
handle_touch_move_pan(event)
|
||||
|
||||
update()
|
||||
|
||||
STATE.TOUCH_DOLLY_PAN:
|
||||
|
||||
if enable_zoom == false && enable_pan == false:
|
||||
return
|
||||
|
||||
handle_touch_move_dolly_pan(event)
|
||||
|
||||
update()
|
||||
|
||||
STATE.TOUCH_DOLLY_ROTATE:
|
||||
|
||||
if enable_zoom == false && enable_rotate == false:
|
||||
return
|
||||
|
||||
#handle_touch_move_dolly_rotate(event)
|
||||
|
||||
update()
|
||||
|
||||
_:
|
||||
state = STATE.NONE
|
||||
|
||||
func handle_mouse_down_rotate(event: InputEventMouseButton) -> void:
|
||||
rotate_start = event.position
|
||||
|
||||
func handle_mouse_move_rotate(event: InputEventMouseMotion) -> void:
|
||||
rotate_end = event.position
|
||||
|
||||
rotate_delta = (rotate_end - rotate_start) * rotate_speed
|
||||
|
||||
rotate_left(2 * PI * rotate_delta.x / get_viewport().size.y) # yes, height
|
||||
|
||||
rotate_up(2 * PI * rotate_delta.y / get_viewport().size.y)
|
||||
|
||||
rotate_start = rotate_end
|
||||
|
||||
update()
|
||||
|
||||
func handle_mouse_down_pan(event: InputEventMouseButton) -> void:
|
||||
pan_start = event.position
|
||||
|
||||
func handle_mouse_move_pan(event: InputEventMouseMotion) -> void:
|
||||
pan_end = event.position
|
||||
|
||||
pan_delta = (pan_end - pan_start) * pan_speed * 20.0
|
||||
|
||||
pan(pan_delta.x, pan_delta.y)
|
||||
|
||||
pan_start = pan_end
|
||||
|
||||
update()
|
||||
|
||||
func handle_mouse_down_dolly(event: InputEventMouseButton) -> void:
|
||||
dolly_start = event.position
|
||||
|
||||
func handle_mouse_move_dolly(event: InputEventMouseMotion) -> void:
|
||||
dolly_end = event.position
|
||||
|
||||
dolly_delta = dolly_end - dolly_start
|
||||
|
||||
if dolly_delta.y > 0:
|
||||
dolly_out(get_zoom_scale())
|
||||
elif dolly_delta.y < 0:
|
||||
dolly_in(get_zoom_scale())
|
||||
|
||||
dolly_start = dolly_end
|
||||
|
||||
update()
|
||||
|
||||
func handle_mouse_wheel(event):
|
||||
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
|
||||
dolly_in(get_zoom_scale())
|
||||
elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
|
||||
dolly_out(get_zoom_scale())
|
||||
|
||||
update()
|
||||
|
||||
func get_second_pointer_position(event) -> Vector2:
|
||||
|
||||
var pointer = null
|
||||
|
||||
if event.index == pointers[0].index:
|
||||
pointer = pointers[1]
|
||||
else:
|
||||
pointer = pointers[0]
|
||||
|
||||
return pointerPositions[pointer.index]
|
||||
|
||||
func handle_touch_start_rotate():
|
||||
if pointers.size() == 1:
|
||||
rotate_start.x = pointers[0].position.x
|
||||
rotate_start.y = pointers[0].position.y
|
||||
else:
|
||||
var x = 0.5 * (pointers[0].position.x + pointers[1].position.x)
|
||||
var y = 0.5 * (pointers[0].position.y + pointers[1].position.y)
|
||||
|
||||
rotate_start.x = x
|
||||
rotate_start.y = y
|
||||
|
||||
func handle_touch_move_rotate(event):
|
||||
if pointers.size() == 1:
|
||||
rotate_end = event.position
|
||||
else:
|
||||
var position = get_second_pointer_position(event)
|
||||
var x = 0.5 * (event.position.x + position.x)
|
||||
var y = 0.5 * (event.position.y + position.y)
|
||||
|
||||
rotate_end.x = x
|
||||
rotate_end.y = y
|
||||
|
||||
rotate_delta = (rotate_end - rotate_start) * rotate_speed
|
||||
|
||||
rotate_left(2 * PI * rotate_delta.x / get_viewport().size.y)
|
||||
|
||||
rotate_up(2 * PI * rotate_delta.y / get_viewport().size.y)
|
||||
|
||||
rotate_start = rotate_end
|
||||
|
||||
func handle_touch_move_pan(event):
|
||||
if pointers.size() == 1:
|
||||
pan_end.x = event.position.x
|
||||
pan_end.y = event.position.y
|
||||
else:
|
||||
var position = get_second_pointer_position(event)
|
||||
var x = 0.5 * (event.position.x + position.x)
|
||||
var y = 0.5 * (event.position.y + position.y)
|
||||
|
||||
pan_end.x = x
|
||||
pan_end.y = y
|
||||
|
||||
pan_delta = (pan_end - pan_start) * pan_speed * 20.0
|
||||
|
||||
pan(pan_delta.x, pan_delta.y)
|
||||
|
||||
pan_start = pan_end
|
||||
|
||||
func handle_touch_start_dolly_pan():
|
||||
if enable_zoom:
|
||||
handle_touch_start_dolly()
|
||||
if enable_pan:
|
||||
handle_touch_start_pan()
|
||||
|
||||
func handle_touch_start_dolly():
|
||||
var dx = pointers[0].position.x - pointers[1].position.x
|
||||
var dy = pointers[0].position.y - pointers[1].position.y
|
||||
|
||||
var distance = sqrt(dx * dx + dy * dy)
|
||||
|
||||
dolly_start.x = 0
|
||||
dolly_start.y = distance
|
||||
|
||||
func handle_touch_start_pan():
|
||||
if pointers.size() == 1:
|
||||
pan_start.x = pointers[0].position.x
|
||||
pan_start.y = pointers[0].position.y
|
||||
else:
|
||||
var x = 0.5 * (pointers[0].position.x + pointers[1].position.x)
|
||||
var y = 0.5 * (pointers[0].position.y + pointers[1].position.y)
|
||||
|
||||
pan_start.x = x
|
||||
pan_start.y = y
|
||||
|
||||
func handle_touch_move_dolly_pan(event):
|
||||
if enable_zoom:
|
||||
handle_touch_move_dolly(event)
|
||||
if enable_pan:
|
||||
handle_touch_move_pan(event)
|
||||
|
||||
func handle_touch_move_dolly(event):
|
||||
var position = get_second_pointer_position(event)
|
||||
|
||||
var dx = event.position.x - position.x
|
||||
var dy = event.position.y - position.y
|
||||
|
||||
var distance = sqrt(dx * dx + dy * dy)
|
||||
|
||||
dolly_end.x = 0
|
||||
dolly_end.y = distance
|
||||
|
||||
dolly_delta.x = 0
|
||||
dolly_delta.y = pow(dolly_end.y / dolly_start.y, zoom_speed)
|
||||
|
||||
dolly_out(dolly_delta.y)
|
||||
|
||||
dolly_start = dolly_end
|
||||
|
||||
### HELPER FUNCTIONS AND UTILITIES ###
|
||||
|
||||
# Check if the camera variable is actually a camera, print an error if not
|
||||
func check_camera() -> bool:
|
||||
if _camera:
|
||||
camera = get_node(_camera)
|
||||
|
||||
if not camera.is_class("Camera3D"):
|
||||
printerr("Selected Camera3D is not a camera.")
|
||||
return false
|
||||
else:
|
||||
return true
|
||||
else:
|
||||
printerr("No camera provided")
|
||||
return false
|
||||
|
||||
# Adds a debug overlay that shows current projection mode and state
|
||||
func enable_debug():
|
||||
debug_layer = CanvasLayer.new()
|
||||
debug_layer.name = "debug_layer"
|
||||
var v_box_container = VBoxContainer.new()
|
||||
v_box_container.name = "list"
|
||||
v_box_container.offset_left = 15
|
||||
v_box_container.offset_top = 15
|
||||
debug_layer.add_child(v_box_container)
|
||||
|
||||
var root_viewport = get_tree().get_root()
|
||||
var label = Label.new()
|
||||
var projection = "PERSPECTIVE" if camera.projection == Camera3D.PROJECTION_PERSPECTIVE else "ORTHOGRAPHIC"
|
||||
label.text = "OrbitControls Debug (%s)" % projection
|
||||
label.set("theme_override_colors/font_color", Color(1.0, 0.5, 0.5))
|
||||
add_to_debug(label, "Heading")
|
||||
|
||||
add_string_to_debug("state")
|
||||
add_string_to_debug("pointers")
|
||||
|
||||
root_viewport.call_deferred("add_child", debug_layer)
|
||||
|
||||
# Adds a string to the debug UI
|
||||
func add_string_to_debug(name: String):
|
||||
var string = Label.new()
|
||||
string.name = name
|
||||
add_to_debug(string, name)
|
||||
|
||||
# Adds Control nodes of any type to debug UI
|
||||
func add_to_debug(control: Control, name: String) -> void:
|
||||
var list = debug_layer.get_node("list")
|
||||
list.add_child(control)
|
||||
debug_nodes[name] = control
|
|
@ -0,0 +1,7 @@
|
|||
[plugin]
|
||||
|
||||
name="Orbit Controls"
|
||||
description="Orbit Controls for the Godot Engine"
|
||||
author="Luca Junge"
|
||||
version="1.0"
|
||||
script="plugin.gd"
|
|
@ -0,0 +1,13 @@
|
|||
@tool
|
||||
extends EditorPlugin
|
||||
|
||||
|
||||
func _enter_tree():
|
||||
# Initialization of the plugin goes here.
|
||||
# Add the new type with a name, a parent type, a script and an icon.
|
||||
add_custom_type("OrbitControls", "Control", preload("orbit-controls.gd"), preload("node-icon.png"))
|
||||
|
||||
func _exit_tree():
|
||||
# Clean-up of the plugin goes here.
|
||||
# Always remember to remove it from the engine when deactivated.
|
||||
remove_custom_type("OrbitControls")
|
|
@ -0,0 +1,64 @@
|
|||
extends MeshInstance3D
|
||||
|
||||
var rings = 50
|
||||
var radial_segments = 50
|
||||
var radius = 1
|
||||
|
||||
func _ready():
|
||||
var surface_array = []
|
||||
surface_array.resize(Mesh.ARRAY_MAX)
|
||||
|
||||
# PackedVector**Arrays for mesh construction.
|
||||
var verts = PackedVector3Array()
|
||||
var uvs = PackedVector2Array()
|
||||
var normals = PackedVector3Array()
|
||||
var indices = PackedInt32Array()
|
||||
|
||||
#######################################
|
||||
# Vertex indices.
|
||||
var thisrow = 0
|
||||
var prevrow = 0
|
||||
var point = 0
|
||||
|
||||
# Loop over rings.
|
||||
for i in range(rings + 1):
|
||||
var v = float(i) / rings
|
||||
var w = sin(PI * v)
|
||||
var y = cos(PI * v)
|
||||
|
||||
# Loop over segments in ring.
|
||||
for j in range(radial_segments + 1):
|
||||
var u = float(j) / radial_segments
|
||||
var x = sin(u * PI * 2.0)
|
||||
var z = cos(u * PI * 2.0)
|
||||
var vert = Vector3(x * radius * w, y * radius, z * radius * w)
|
||||
verts.append(vert)
|
||||
normals.append(vert.normalized())
|
||||
uvs.append(Vector2(u, v))
|
||||
point += 1
|
||||
|
||||
# Create triangles in ring using indices.
|
||||
if i > 0 and j > 0:
|
||||
indices.append(prevrow + j - 1)
|
||||
indices.append(prevrow + j)
|
||||
indices.append(thisrow + j - 1)
|
||||
|
||||
indices.append(prevrow + j)
|
||||
indices.append(thisrow + j)
|
||||
indices.append(thisrow + j - 1)
|
||||
|
||||
prevrow = thisrow
|
||||
thisrow = point
|
||||
#######################################
|
||||
|
||||
# Assign arrays to surface array.
|
||||
surface_array[Mesh.ARRAY_VERTEX] = verts
|
||||
surface_array[Mesh.ARRAY_TEX_UV] = uvs
|
||||
surface_array[Mesh.ARRAY_NORMAL] = normals
|
||||
surface_array[Mesh.ARRAY_INDEX] = indices
|
||||
|
||||
# Create mesh surface from mesh array.
|
||||
# No blendshapes, lods, or compression used.
|
||||
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array)
|
||||
|
||||
ResourceSaver.save(mesh, "res://experiments/sphere.tres", ResourceSaver.FLAG_COMPRESS)
|
|
@ -0,0 +1,5 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://crsvssw78ow3t"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://bcf3gajson13b" path="res://Assets/models/screendoor1/PBMceshi.fbx" id="1_rbo8q"]
|
||||
|
||||
[node name="Root Scene" instance=ExtResource("1_rbo8q")]
|
|
@ -0,0 +1,5 @@
|
|||
extends Node3D
|
||||
|
||||
|
||||
func _on_button_pressed():
|
||||
print("LCB 按钮按下")
|
|
@ -0,0 +1,39 @@
|
|||
[gd_scene load_steps=4 format=3 uid="uid://b5c3atssvhkwy"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://smgws0tjgxn0" path="res://Assets/models/screendoor/screenDoor.gltf" id="1_3e1st"]
|
||||
[ext_resource type="Script" path="res://experiments/lcb.gd" id="2_e83ig"]
|
||||
|
||||
[sub_resource type="ViewportTexture" id="ViewportTexture_x5cm6"]
|
||||
viewport_path = NodePath("LCB_Lable")
|
||||
|
||||
[node name="LCB" instance=ExtResource("1_3e1st")]
|
||||
script = ExtResource("2_e83ig")
|
||||
|
||||
[node name="JH_GD_LCB" parent="." index="0"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0218282, -0.0190198, -0.0356126)
|
||||
|
||||
[node name="LCB_Lable" type="SubViewport" parent="." index="1"]
|
||||
size = Vector2i(64, 32)
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="LCB_Lable" index="0"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
color = Color(0, 0.0901961, 1, 1)
|
||||
|
||||
[node name="Button" type="Button" parent="LCB_Lable" index="1"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_font_sizes/font_size = 32
|
||||
text = "LCB"
|
||||
|
||||
[node name="Sprite3D" type="Sprite3D" parent="." index="2"]
|
||||
transform = Transform3D(0.255803, 0, 0, 0, 0.255803, 0, 0, 0, 0.255803, -0.0167608, 0.0950372, 0)
|
||||
texture = SubResource("ViewportTexture_x5cm6")
|
||||
|
||||
[connection signal="pressed" from="LCB_Lable/Button" to="." method="_on_button_pressed"]
|
|
@ -0,0 +1,43 @@
|
|||
extends MeshInstance3D
|
||||
|
||||
var fnl = FastNoiseLite.new()
|
||||
var mdt = MeshDataTool.new()
|
||||
|
||||
func _ready():
|
||||
fnl.frequency = 0.7
|
||||
|
||||
mdt.create_from_surface(mesh, 0)
|
||||
|
||||
for i in range(mdt.get_vertex_count()):
|
||||
var vertex = mdt.get_vertex(i).normalized()
|
||||
# Push out vertex by noise.
|
||||
vertex = vertex * (fnl.get_noise_3dv(vertex) * 0.5 + 0.75)
|
||||
mdt.set_vertex(i, vertex)
|
||||
|
||||
# Calculate vertex normals, face-by-face.
|
||||
for i in range(mdt.get_face_count()):
|
||||
# Get the index in the vertex array.
|
||||
var a = mdt.get_face_vertex(i, 0)
|
||||
var b = mdt.get_face_vertex(i, 1)
|
||||
var c = mdt.get_face_vertex(i, 2)
|
||||
# Get vertex position using vertex index.
|
||||
var ap = mdt.get_vertex(a)
|
||||
var bp = mdt.get_vertex(b)
|
||||
var cp = mdt.get_vertex(c)
|
||||
# Calculate face normal.
|
||||
var n = (bp - cp).cross(ap - bp).normalized()
|
||||
# Add face normal to current vertex normal.
|
||||
# This will not result in perfect normals, but it will be close.
|
||||
mdt.set_vertex_normal(a, n + mdt.get_vertex_normal(a))
|
||||
mdt.set_vertex_normal(b, n + mdt.get_vertex_normal(b))
|
||||
mdt.set_vertex_normal(c, n + mdt.get_vertex_normal(c))
|
||||
|
||||
# Run through vertices one last time to normalize normals and
|
||||
# set color to normal.
|
||||
for i in range(mdt.get_vertex_count()):
|
||||
var v = mdt.get_vertex_normal(i).normalized()
|
||||
mdt.set_vertex_normal(i, v)
|
||||
mdt.set_vertex_color(i, Color(v.x, v.y, v.z))
|
||||
|
||||
mesh.clear_surfaces()
|
||||
mdt.commit_to_surface(mesh)
|
|
@ -0,0 +1,8 @@
|
|||
[gd_scene load_steps=3 format=3 uid="uid://n8hg1w1lmcm3"]
|
||||
|
||||
[ext_resource type="Script" path="res://experiments/mesh_data_tool_test.gd" id="1_2dsdn"]
|
||||
[ext_resource type="ArrayMesh" uid="uid://ckftec7be6bqo" path="res://experiments/sphere.tres" id="1_qreen"]
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D"]
|
||||
mesh = ExtResource("1_qreen")
|
||||
script = ExtResource("1_2dsdn")
|
|
@ -0,0 +1,9 @@
|
|||
[gd_scene load_steps=3 format=3 uid="uid://0vitvgnvrwmy"]
|
||||
|
||||
[ext_resource type="Script" path="res://experiments/Sphere3D.gd" id="1_5iw5b"]
|
||||
|
||||
[sub_resource type="ArrayMesh" id="ArrayMesh_x6cuk"]
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D"]
|
||||
mesh = SubResource("ArrayMesh_x6cuk")
|
||||
script = ExtResource("1_5iw5b")
|
|
@ -0,0 +1,7 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://ce2vptio0yxxc"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://smgws0tjgxn0" path="res://Assets/models/screendoor/screenDoor.gltf" id="1_57jqk"]
|
||||
|
||||
[node name="platform" type="Node3D"]
|
||||
|
||||
[node name="screenDoor" parent="." instance=ExtResource("1_57jqk")]
|
|
@ -0,0 +1,9 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://bmiexmyoh0ehv"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://c3feq8rrkjo6u" path="res://Assets/models/platform/platform.gltf" id="1_pyn6g"]
|
||||
|
||||
[node name="platform" instance=ExtResource("1_pyn6g")]
|
||||
|
||||
[node name="Label3D" type="Label3D" parent="DX" index="0"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.0204, 0, 0.203499)
|
||||
text = "车站一"
|
|
@ -0,0 +1,6 @@
|
|||
@tool
|
||||
extends Node3D
|
||||
|
||||
#func _ready():
|
||||
#var lt = $LabelTexture.get_texture()
|
||||
#$Sprite3D.texture = lt
|
|
@ -0,0 +1,18 @@
|
|||
[gd_scene load_steps=4 format=3 uid="uid://c63e3ugq35q5g"]
|
||||
|
||||
[ext_resource type="Script" path="res://experiments/psd_panel.gd" id="1_wg3fd"]
|
||||
[ext_resource type="PackedScene" uid="uid://c5vvgu50akjwl" path="res://experiments/psd_panel_ui.tscn" id="2_rtht1"]
|
||||
|
||||
[sub_resource type="ViewportTexture" id="ViewportTexture_c2vxd"]
|
||||
viewport_path = NodePath("LabelTexture")
|
||||
|
||||
[node name="PSD_Panel" type="Node3D"]
|
||||
script = ExtResource("1_wg3fd")
|
||||
|
||||
[node name="LabelTexture" type="SubViewport" parent="."]
|
||||
size = Vector2i(2048, 256)
|
||||
|
||||
[node name="PSD_Panel_UI" parent="LabelTexture" instance=ExtResource("2_rtht1")]
|
||||
|
||||
[node name="Sprite3D" type="Sprite3D" parent="."]
|
||||
texture = SubResource("ViewportTexture_c2vxd")
|
|
@ -0,0 +1,41 @@
|
|||
@tool
|
||||
extends Node2D
|
||||
|
||||
var stationLabelNode: PackedScene = preload("res://experiments/station_label.tscn")
|
||||
|
||||
class StationLable:
|
||||
var name: String
|
||||
var enName: String
|
||||
var current: bool
|
||||
func _init(n, en, cur):
|
||||
name = n
|
||||
enName = en
|
||||
current = cur
|
||||
|
||||
|
||||
var stations = [
|
||||
StationLable.new("会展中心", "Exhibition Center", true),
|
||||
StationLable.new("世纪大道", "Century Avenue", false),
|
||||
StationLable.new("交通大学", "JiaoTong Univercity", false),
|
||||
StationLable.new("市图书馆", "City Library", false),
|
||||
StationLable.new("中心医院", "Central Hospital", false),
|
||||
StationLable.new("未来路", "Wei lai lu", false),
|
||||
StationLable.new("火车站", "train station", false),
|
||||
StationLable.new("人民广场", "People's Square", false),
|
||||
StationLable.new("体育中心", "sports center", false),
|
||||
]
|
||||
|
||||
var reverseStations = stations.reverse()
|
||||
|
||||
func _ready():
|
||||
print(stationLabelNode)
|
||||
|
||||
for i in stations.size():
|
||||
var slable = stations[i]
|
||||
print(slable.name, slable.enName, slable.current)
|
||||
if slable.current:
|
||||
$VBoxContainer/CurrentStationName.text = slable.name
|
||||
$VBoxContainer/EnName.text = slable.enName
|
||||
var slScene = stationLabelNode.instantiate()
|
||||
slScene._init_station_name_and_position(slable.name, slable.enName, i)
|
||||
$Container.add_child(slScene)
|
|
@ -0,0 +1,37 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://c5vvgu50akjwl"]
|
||||
|
||||
[ext_resource type="Script" path="res://experiments/psd_panel_ui.gd" id="1_cmik1"]
|
||||
|
||||
[node name="PSD_Panel_UI" type="Node2D"]
|
||||
script = ExtResource("1_cmik1")
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="."]
|
||||
offset_right = 43.0
|
||||
offset_bottom = 25.0
|
||||
scale = Vector2(36.8932, 11.8384)
|
||||
color = Color(0.564706, 0.564706, 0.564706, 1)
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
offset_left = 136.0
|
||||
offset_top = 64.0
|
||||
offset_right = 420.0
|
||||
offset_bottom = 146.0
|
||||
alignment = 1
|
||||
|
||||
[node name="CurrentStationName" type="Label" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0, 0, 0, 1)
|
||||
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
|
||||
theme_override_font_sizes/font_size = 36
|
||||
text = "当前车站"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="EnName" type="Label" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0, 0, 0, 1)
|
||||
theme_override_font_sizes/font_size = 20
|
||||
text = "Current Station"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="Container" type="Node2D" parent="."]
|
||||
position = Vector2(584, 64)
|
|
@ -0,0 +1,13 @@
|
|||
[gd_scene load_steps=3 format=3 uid="uid://crpmwcp85khdr"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://biot7d8s87d3y" path="res://Assets/models/screendoor1/screenDoor.gltf" id="1_tvcny"]
|
||||
[ext_resource type="Script" path="res://experiments/screendoor_lcb.gd" id="2_5qyph"]
|
||||
|
||||
[node name="screenDoor" instance=ExtResource("1_tvcny")]
|
||||
|
||||
[node name="JH_GD_LCB" parent="." index="0"]
|
||||
script = ExtResource("2_5qyph")
|
||||
|
||||
[node name="Label3D" type="Label3D" parent="JH_GD_LCB" index="0"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.147186, 0)
|
||||
text = "LCB"
|
|
@ -0,0 +1,5 @@
|
|||
extends MeshInstance3D
|
||||
|
||||
func _ready():
|
||||
var gp = global_position
|
||||
print(gp)
|
|
@ -0,0 +1,6 @@
|
|||
extends Node2D
|
||||
|
||||
func _init_station_name_and_position(name, enName, i):
|
||||
$StationName/Name.text = name
|
||||
$StationName/EnName.text = enName
|
||||
self.translate(Vector2(100 * i, 0))
|
|
@ -0,0 +1,66 @@
|
|||
[gd_scene load_steps=3 format=3 uid="uid://d27g0ew7giua3"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/2d_shapes/shapes/Ellipse.gd" id="1_a73g8"]
|
||||
[ext_resource type="Script" path="res://experiments/station_label.gd" id="1_ch36d"]
|
||||
|
||||
[node name="StationLabel" type="Node2D"]
|
||||
position = Vector2(64, 88)
|
||||
script = ExtResource("1_ch36d")
|
||||
|
||||
[node name="StationName" type="Control" parent="."]
|
||||
layout_mode = 3
|
||||
anchors_preset = 0
|
||||
offset_left = -24.0
|
||||
offset_top = -8.0
|
||||
offset_right = -24.0
|
||||
offset_bottom = -8.0
|
||||
rotation = -0.785397
|
||||
size_flags_horizontal = 8
|
||||
size_flags_vertical = 8
|
||||
metadata/_edit_use_anchors_ = true
|
||||
|
||||
[node name="Name" type="Label" parent="StationName"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -24.0
|
||||
offset_top = -11.5
|
||||
offset_right = 24.0
|
||||
offset_bottom = 11.5
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
pivot_offset = Vector2(24, 11.5)
|
||||
size_flags_horizontal = 4
|
||||
theme_override_colors/font_color = Color(0, 0, 0, 1)
|
||||
text = "车站名"
|
||||
metadata/_edit_use_anchors_ = true
|
||||
|
||||
[node name="EnName" type="Label" parent="StationName"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -48.0
|
||||
offset_top = 12.0
|
||||
offset_right = 44.0
|
||||
offset_bottom = 35.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
pivot_offset = Vector2(46, 11.5)
|
||||
theme_override_colors/font_color = Color(0, 0, 0, 1)
|
||||
text = "Exhibition Center"
|
||||
metadata/_edit_use_anchors_ = true
|
||||
|
||||
[node name="Ellipse" type="Node2D" parent="."]
|
||||
position = Vector2(48, -72)
|
||||
script = ExtResource("1_a73g8")
|
||||
size = Vector2(14, 14)
|
||||
circle = true
|
||||
style = 2
|
||||
outline_width = 2
|
||||
outline_color = Color(1, 0, 0, 1)
|
|
@ -0,0 +1,11 @@
|
|||
extends Node3D
|
||||
|
||||
@onready var camera = $Camera3D
|
||||
|
||||
func _ready():
|
||||
var sp = get_screen_position($LCB)
|
||||
print("3D物体在屏幕上的位置: ", sp)
|
||||
|
||||
func get_screen_position(mesh_instance):
|
||||
var global_position = mesh_instance.global_transform.origin
|
||||
return camera.unproject_position(global_position)
|
|
@ -0,0 +1,39 @@
|
|||
[gd_scene load_steps=7 format=3 uid="uid://4ygkabji3g16"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://bmiexmyoh0ehv" path="res://experiments/platform1.tscn" id="1_cq2ki"]
|
||||
[ext_resource type="Script" path="res://experiments/test_3d.gd" id="1_uqsdo"]
|
||||
[ext_resource type="PackedScene" uid="uid://crpmwcp85khdr" path="res://experiments/screen_door_t1.tscn" id="2_rvfj7"]
|
||||
[ext_resource type="PackedScene" uid="uid://b5c3atssvhkwy" path="res://experiments/lcb.tscn" id="3_htmjl"]
|
||||
[ext_resource type="PackedScene" uid="uid://c63e3ugq35q5g" path="res://experiments/psd_panel.tscn" id="4_wjde3"]
|
||||
|
||||
[sub_resource type="Environment" id="Environment_mybsf"]
|
||||
ambient_light_color = Color(0.831373, 0.290196, 0.556863, 1)
|
||||
ambient_light_energy = 6.23
|
||||
|
||||
[node name="Node3D" type="Node3D"]
|
||||
script = ExtResource("1_uqsdo")
|
||||
|
||||
[node name="platform" parent="." instance=ExtResource("1_cq2ki")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.16258, 0)
|
||||
|
||||
[node name="LCB" parent="." instance=ExtResource("3_htmjl")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.58244, 2.40247, -7.38809)
|
||||
|
||||
[node name="PSD_Panel" parent="." instance=ExtResource("4_wjde3")]
|
||||
transform = Transform3D(0.381944, 0, 0, 0, 0.381944, 0, 0, 0, 0.381944, 4.13301, 1.83159, -7.03252)
|
||||
|
||||
[node name="screenDoor" parent="." instance=ExtResource("2_rvfj7")]
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
environment = SubResource("Environment_mybsf")
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(0.775947, 2.3125e-07, -0.630798, 0.387003, 0.789684, 0.476054, 0.498131, -0.613514, 0.612753, -0.369306, 2.06538, 1.72595)
|
||||
light_energy = 4.962
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.92041, 0.390956, 0, -0.390956, 0.92041, 4.25592, 2.82422, -2.07876)
|
||||
projection = 1
|
||||
current = true
|
||||
fov = 23.7
|
||||
size = 4.56913
|
|
@ -11,7 +11,7 @@ config_version=5
|
|||
[application]
|
||||
|
||||
config/name="godot_experiments"
|
||||
run/main_scene="res://UI/stand.tscn"
|
||||
run/main_scene="res://experiments/test_3d.tscn"
|
||||
config/features=PackedStringArray("4.2", "GL Compatibility")
|
||||
config/icon="res://icon.svg"
|
||||
|
||||
|
@ -22,6 +22,19 @@ window/size/viewport_height=1080
|
|||
window/size/initial_position_type=0
|
||||
window/stretch/mode="canvas_items"
|
||||
|
||||
[editor_plugins]
|
||||
|
||||
enabled=PackedStringArray("res://addons/2d_shapes/plugin.cfg", "res://addons/orbit-controls/plugin.cfg")
|
||||
|
||||
[importer_defaults]
|
||||
|
||||
animation_library={
|
||||
"gltf/embedded_image_handling": 2
|
||||
}
|
||||
scene={
|
||||
"gltf/embedded_image_handling": 2
|
||||
}
|
||||
|
||||
[rendering]
|
||||
|
||||
renderer/rendering_method="gl_compatibility"
|
||||
|
|