mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-23 08:16:05 +00:00
Super rough hit-testing logic for rotator rings
This commit is contained in:
Generated
+241
@@ -698,6 +698,19 @@ version = "0.11.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72c7586401a46f7d8e436028225c1df5288f2e0082d066b247a82466fea155c6"
|
checksum = "72c7586401a46f7d8e436028225c1df5288f2e0082d066b247a82466fea155c6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bevy_rapier3d"
|
||||||
|
version = "0.22.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "12402872b857ba490f1040ab6212915bd9bf25f8584b31f2c43cef41b33f3be4"
|
||||||
|
dependencies = [
|
||||||
|
"bevy",
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"log",
|
||||||
|
"nalgebra",
|
||||||
|
"rapier3d",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_reflect"
|
name = "bevy_reflect"
|
||||||
version = "0.11.3"
|
version = "0.11.3"
|
||||||
@@ -1337,6 +1350,20 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-channel",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-queue",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.8"
|
version = "0.5.8"
|
||||||
@@ -1347,6 +1374,40 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"memoffset",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-queue"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.16"
|
version = "0.8.16"
|
||||||
@@ -1391,6 +1452,12 @@ version = "1.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encase"
|
name = "encase"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
@@ -2033,6 +2100,12 @@ dependencies = [
|
|||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libm"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libudev-sys"
|
name = "libudev-sys"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
@@ -2086,12 +2159,31 @@ dependencies = [
|
|||||||
"regex-automata 0.1.10",
|
"regex-automata 0.1.10",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matrixmultiply"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"rawpointer",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.6.3"
|
version = "2.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
|
checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "metal"
|
name = "metal"
|
||||||
version = "0.24.0"
|
version = "0.24.0"
|
||||||
@@ -2175,6 +2267,34 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nalgebra"
|
||||||
|
version = "0.32.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "307ed9b18cc2423f29e83f84fd23a8e73628727990181f18641a8b5dc2ab1caa"
|
||||||
|
dependencies = [
|
||||||
|
"approx",
|
||||||
|
"glam",
|
||||||
|
"matrixmultiply",
|
||||||
|
"nalgebra-macros",
|
||||||
|
"num-complex",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
"simba",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nalgebra-macros"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91761aed67d03ad966ef783ae962ef9bbaca728d2dd7ceb7939ec110fffad998"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ndk"
|
name = "ndk"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@@ -2274,6 +2394,15 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-derive"
|
name = "num-derive"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
@@ -2313,6 +2442,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
|
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
|
"libm",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2449,6 +2579,12 @@ version = "1.18.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "optional"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "978aa494585d3ca4ad74929863093e87cac9790d81fe7aba2b3dc2890643a0fc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "orbclient"
|
name = "orbclient"
|
||||||
version = "0.3.46"
|
version = "0.3.46"
|
||||||
@@ -2502,6 +2638,27 @@ dependencies = [
|
|||||||
"windows-targets 0.48.5",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parry3d"
|
||||||
|
version = "0.13.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b55dc0e6db79bddbc5fd583569f7356cdcc63e1e9b2b93a9ab70dd8e717160e0"
|
||||||
|
dependencies = [
|
||||||
|
"approx",
|
||||||
|
"arrayvec",
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"downcast-rs",
|
||||||
|
"either",
|
||||||
|
"nalgebra",
|
||||||
|
"num-derive",
|
||||||
|
"num-traits",
|
||||||
|
"rustc-hash",
|
||||||
|
"simba",
|
||||||
|
"slab",
|
||||||
|
"smallvec",
|
||||||
|
"spade",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "paste"
|
name = "paste"
|
||||||
version = "1.0.14"
|
version = "1.0.14"
|
||||||
@@ -2610,12 +2767,39 @@ version = "0.1.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab"
|
checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rapier3d"
|
||||||
|
version = "0.17.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62a8a0bd9d3135f7b4eb45d0796540e7bab47b6b7c974f90567ccc5a0454f42b"
|
||||||
|
dependencies = [
|
||||||
|
"approx",
|
||||||
|
"arrayvec",
|
||||||
|
"bit-vec",
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"crossbeam",
|
||||||
|
"downcast-rs",
|
||||||
|
"instant",
|
||||||
|
"nalgebra",
|
||||||
|
"num-derive",
|
||||||
|
"num-traits",
|
||||||
|
"parry3d",
|
||||||
|
"rustc-hash",
|
||||||
|
"simba",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "raw-window-handle"
|
name = "raw-window-handle"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
|
checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rawpointer"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rectangle-pack"
|
name = "rectangle-pack"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
@@ -2681,6 +2865,12 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b"
|
checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "robust"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5864e7ef1a6b7bcf1d6ca3f655e65e724ed3b52546a0d0a663c991522f552ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rodio"
|
name = "rodio"
|
||||||
version = "0.17.1"
|
version = "0.17.1"
|
||||||
@@ -2732,6 +2922,15 @@ version = "1.0.15"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "safe_arch"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f398075ce1e6a179b46f51bd88d0598b92b00d3551f1a2d4ac49e771b56ac354"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "same-file"
|
name = "same-file"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
@@ -2793,6 +2992,19 @@ version = "1.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380"
|
checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simba"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "061507c94fc6ab4ba1c9a0305018408e312e17c041eb63bef8aa726fa33aceae"
|
||||||
|
dependencies = [
|
||||||
|
"approx",
|
||||||
|
"num-complex",
|
||||||
|
"num-traits",
|
||||||
|
"paste",
|
||||||
|
"wide",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "simd-adler32"
|
name = "simd-adler32"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
@@ -2835,6 +3047,18 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spade"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88e65803986868d2372c582007c39ba89936a36ea5f236bf7a7728dc258f04f9"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
"optional",
|
||||||
|
"robust",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spirv"
|
name = "spirv"
|
||||||
version = "0.2.0+1.5.4"
|
version = "0.2.0+1.5.4"
|
||||||
@@ -2856,6 +3080,7 @@ name = "studio"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy",
|
"bevy",
|
||||||
|
"bevy_rapier3d",
|
||||||
"bitflags 2.4.0",
|
"bitflags 2.4.0",
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
@@ -3096,6 +3321,12 @@ dependencies = [
|
|||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.12"
|
version = "1.0.12"
|
||||||
@@ -3351,6 +3582,16 @@ dependencies = [
|
|||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wide"
|
||||||
|
version = "0.7.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ebecebefc38ff1860b4bc47550bbfa63af5746061cf0d29fcd7fa63171602598"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"safe_arch",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "widestring"
|
name = "widestring"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
|
|||||||
+8
-6
@@ -13,13 +13,15 @@ name = "studio-standalone"
|
|||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasm-bindgen = { version = "0.2.84" }
|
bevy = { workspace = true }
|
||||||
|
bevy_rapier3d = { version = "0.22.0" }
|
||||||
console_error_panic_hook = { version = "0.1.7", optional = true }
|
console_error_panic_hook = { version = "0.1.7", optional = true }
|
||||||
parking_lot = "0.12.1"
|
|
||||||
bitflags = "2.4.0"
|
bitflags = "2.4.0"
|
||||||
|
parking_lot = "0.12.1"
|
||||||
|
wasm-bindgen = { version = "0.2.84" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
wasm = ["dep:console_error_panic_hook"]
|
wasm = [
|
||||||
|
"dep:console_error_panic_hook",
|
||||||
[dependencies.bevy]
|
"bevy_rapier3d/wasm-bindgen",
|
||||||
workspace = true
|
]
|
||||||
|
|||||||
@@ -0,0 +1,193 @@
|
|||||||
|
use core::fmt;
|
||||||
|
use std::f32::consts;
|
||||||
|
|
||||||
|
use bevy::{prelude::*, window::PrimaryWindow};
|
||||||
|
use bevy_rapier3d::prelude::*;
|
||||||
|
|
||||||
|
use crate::{math::NearlyEq, orbit_cam::OrbitCam};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
model::{self, Axes, Control, Gizmo, Hovered},
|
||||||
|
InteractionMode, TransformSpace, TransformType,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Component, Deref, DerefMut, Clone, Copy, Debug)]
|
||||||
|
pub(super) struct GizmoController(pub Control);
|
||||||
|
|
||||||
|
pub(super) fn update_spawns(
|
||||||
|
mut cmd: Commands,
|
||||||
|
q_needs_spawn: Query<(Entity, &Gizmo), Without<GizmoController>>,
|
||||||
|
q_needs_despawn: Query<Entity, (With<GizmoController>, Without<Gizmo>)>,
|
||||||
|
mode: Res<InteractionMode>,
|
||||||
|
) {
|
||||||
|
for (ent, gizmo) in q_needs_spawn.iter() {
|
||||||
|
let mut ent_cmd = cmd.entity(ent);
|
||||||
|
|
||||||
|
ent_cmd.insert((RigidBody::KinematicPositionBased, Sensor));
|
||||||
|
|
||||||
|
if mode.transform.contains(TransformType::ROTATE) {
|
||||||
|
ent_cmd.insert(GizmoController(Control::Rotation(Axes::XYZ)));
|
||||||
|
|
||||||
|
let Some(radius) = gizmo.iter().find_map(|el| match el.control {
|
||||||
|
Control::Rotation(axes) if !axes.contains(Axes::SCREEN) => match el.shape {
|
||||||
|
model::Shape::Ring(ring) => Some(ring.radius),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
ent_cmd.insert(Collider::ball(radius));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ent in q_needs_despawn.iter() {
|
||||||
|
cmd.entity(ent)
|
||||||
|
.remove::<(GizmoController, RigidBody, Sensor)>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn update(mut q_collider: Query<(&mut Collider, &Gizmo, &GizmoController)>) {
|
||||||
|
for (mut collider, gizmo, ctrl) in q_collider.iter_mut() {
|
||||||
|
match **ctrl {
|
||||||
|
Control::Rotation(_) => {
|
||||||
|
let Some(radius) = gizmo.iter().find_map(|el| match el.control {
|
||||||
|
Control::Rotation(axes) if !axes.contains(Axes::SCREEN) => match el.shape {
|
||||||
|
model::Shape::Ring(ring) => Some(ring.radius),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(mut ball) = collider.as_ball_mut() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
ball.set_radius(radius);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn hit_test(
|
||||||
|
mut cmd: Commands,
|
||||||
|
q_gizmo: Query<(Entity, &GlobalTransform, &GizmoController)>,
|
||||||
|
q_window: Query<&Window, With<PrimaryWindow>>,
|
||||||
|
q_camera: Query<(&Camera, &GlobalTransform), With<OrbitCam>>,
|
||||||
|
rapier_cx: Res<RapierContext>,
|
||||||
|
mode: Res<InteractionMode>,
|
||||||
|
) {
|
||||||
|
let win = q_window.single();
|
||||||
|
let (cam, cam_xform) = q_camera.single();
|
||||||
|
|
||||||
|
if let Some(ray) = win
|
||||||
|
.cursor_position()
|
||||||
|
.and_then(|pos| cam.viewport_to_world(cam_xform, pos))
|
||||||
|
{
|
||||||
|
if let Some((ent, t)) = rapier_cx.cast_ray(
|
||||||
|
ray.origin,
|
||||||
|
ray.direction,
|
||||||
|
f32::MAX,
|
||||||
|
false,
|
||||||
|
QueryFilterFlags::EXCLUDE_SOLIDS.into(),
|
||||||
|
) {
|
||||||
|
let hit_pos = ray.get_point(t);
|
||||||
|
|
||||||
|
if let Ok((_, world_xform, _gizmo_ctrl)) = q_gizmo.get(ent) {
|
||||||
|
let cam_xform = cam_xform.compute_transform();
|
||||||
|
let world_xform_mat = world_xform.compute_matrix();
|
||||||
|
let world_xform = Transform::from_matrix(world_xform_mat);
|
||||||
|
let basis = match mode.space {
|
||||||
|
TransformSpace::Local => world_xform_mat,
|
||||||
|
TransformSpace::World => Mat4::from_translation(world_xform.translation),
|
||||||
|
};
|
||||||
|
|
||||||
|
let normal = (hit_pos - world_xform.translation).normalize();
|
||||||
|
let to_camera = (cam_xform.translation - world_xform.translation).normalize();
|
||||||
|
|
||||||
|
let perpendicularity = 1. - Vec3::dot(to_camera, normal).abs();
|
||||||
|
let threshold = (perpendicularity * (consts::PI / 5.)).max(2_f32.to_radians());
|
||||||
|
|
||||||
|
let local_pos = basis.inverse().transform_point3(hit_pos);
|
||||||
|
let coords = SphericalCoords::from(local_pos);
|
||||||
|
|
||||||
|
let mut proximity_results = [
|
||||||
|
(coords.heading.abs(), Axes::X),
|
||||||
|
(coords.pitch.abs(), Axes::Y),
|
||||||
|
((90_f32.to_radians() - coords.heading.abs()).abs(), Axes::Z),
|
||||||
|
];
|
||||||
|
proximity_results
|
||||||
|
.sort_by(|(prox_a, _), (prox_b, _)| prox_a.partial_cmp(prox_b).unwrap());
|
||||||
|
|
||||||
|
let (prox, axis) = proximity_results[0];
|
||||||
|
let hit_axes = if prox < threshold { axis } else { Axes::XYZ };
|
||||||
|
|
||||||
|
cmd.entity(ent).insert(Hovered(Control::Rotation(hit_axes)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (ent, _, _) in q_gizmo.iter() {
|
||||||
|
cmd.entity(ent).remove::<Hovered>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SphericalCoords {
|
||||||
|
radius: f32,
|
||||||
|
heading: f32,
|
||||||
|
pitch: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for SphericalCoords {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
radius: 0.,
|
||||||
|
heading: 0.,
|
||||||
|
pitch: 0.,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec3> for SphericalCoords {
|
||||||
|
fn from(value: Vec3) -> Self {
|
||||||
|
let Vec3 { x, y, z } = value;
|
||||||
|
|
||||||
|
let radius = value.length();
|
||||||
|
if radius.nearly_eq(0.) {
|
||||||
|
return Self::default();
|
||||||
|
}
|
||||||
|
|
||||||
|
let pitch = f32::asin(-y / radius);
|
||||||
|
let heading = if (pitch - 90_f32.to_radians()).abs() < 1e-3_f32 {
|
||||||
|
0.
|
||||||
|
} else {
|
||||||
|
f32::atan2(x, z)
|
||||||
|
};
|
||||||
|
|
||||||
|
Self {
|
||||||
|
radius,
|
||||||
|
heading,
|
||||||
|
pitch,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for SphericalCoords {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let precision = f.precision().unwrap_or(3);
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"(r {:.3$}, h {:.3$}°, p {:.3$}°)",
|
||||||
|
self.radius,
|
||||||
|
self.heading.to_degrees(),
|
||||||
|
self.pitch.to_degrees(),
|
||||||
|
precision,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
mod composition;
|
mod composition;
|
||||||
|
mod controller;
|
||||||
mod model;
|
mod model;
|
||||||
mod view;
|
mod view;
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
use bevy_rapier3d::prelude::{NoUserData, RapierPhysicsPlugin};
|
||||||
|
|
||||||
use super::{InteractionMode, Selected, TransformSpace, TransformType};
|
use super::{InteractionMode, Selected, TransformSpace, TransformType};
|
||||||
|
|
||||||
@@ -11,8 +13,19 @@ pub(super) struct StudioGizmosPlugin;
|
|||||||
impl Plugin for StudioGizmosPlugin {
|
impl Plugin for StudioGizmosPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.insert_resource(StudioGizmoConfig::default())
|
app.insert_resource(StudioGizmoConfig::default())
|
||||||
.add_systems(PreUpdate, (model::update_spawns, view::configure))
|
.add_plugins(RapierPhysicsPlugin::<NoUserData>::default())
|
||||||
.add_systems(Update, model::update)
|
.add_systems(
|
||||||
|
PreUpdate,
|
||||||
|
(
|
||||||
|
model::update_spawns,
|
||||||
|
controller::update_spawns,
|
||||||
|
view::configure,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.add_systems(
|
||||||
|
Update,
|
||||||
|
(model::update, controller::update, controller::hit_test),
|
||||||
|
)
|
||||||
.add_systems(PostUpdate, view::draw);
|
.add_systems(PostUpdate, view::draw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ pub(super) fn update(
|
|||||||
#[derive(Component, Deref, DerefMut, Clone, Default, Debug)]
|
#[derive(Component, Deref, DerefMut, Clone, Default, Debug)]
|
||||||
pub(super) struct Gizmo(pub Vec<GizmoElement>);
|
pub(super) struct Gizmo(pub Vec<GizmoElement>);
|
||||||
|
|
||||||
|
#[derive(Component, Deref, DerefMut, Clone, Debug)]
|
||||||
|
pub(super) struct Hovered(pub Control);
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub(super) struct GizmoElement {
|
pub(super) struct GizmoElement {
|
||||||
pub shape: Shape,
|
pub shape: Shape,
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ use std::f32::consts;
|
|||||||
|
|
||||||
use bevy::{prelude::*, window::PrimaryWindow};
|
use bevy::{prelude::*, window::PrimaryWindow};
|
||||||
|
|
||||||
use crate::math::Lerp;
|
use crate::math::{Lerp, NearlyEq};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
model::{Arc, Axes, Control, Gizmo, GizmoColor, Ring, Shape},
|
model::{Arc, Axes, Control, Gizmo, GizmoColor, Hovered, Ring, Shape},
|
||||||
InteractionMode, StudioGizmoConfig, TransformSpace, TransformType,
|
InteractionMode, StudioGizmoConfig, TransformSpace, TransformType,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -22,14 +22,14 @@ pub(super) fn configure(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn draw(
|
pub(super) fn draw(
|
||||||
q_gizmo: Query<(&Gizmo, &GlobalTransform)>,
|
q_gizmo: Query<(&Gizmo, &GlobalTransform, Option<&Hovered>)>,
|
||||||
q_camera_xform: Query<&Transform, With<Camera>>,
|
q_camera_xform: Query<&Transform, With<Camera>>,
|
||||||
mut gizmos: Gizmos,
|
mut gizmos: Gizmos,
|
||||||
mode: Res<InteractionMode>,
|
mode: Res<InteractionMode>,
|
||||||
) {
|
) {
|
||||||
let cam_xform = q_camera_xform.single();
|
let cam_xform = q_camera_xform.single();
|
||||||
|
|
||||||
let Ok((gizmo, world_xform)) = q_gizmo.get_single() else {
|
let Ok((gizmo, world_xform, hovered)) = q_gizmo.get_single() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -40,10 +40,25 @@ pub(super) fn draw(
|
|||||||
(
|
(
|
||||||
Shape::Ring(ring),
|
Shape::Ring(ring),
|
||||||
GizmoColor::Single(color),
|
GizmoColor::Single(color),
|
||||||
Control::Rotation(Axes::X | Axes::Y | Axes::Z),
|
Control::Rotation(axis @ (Axes::X | Axes::Y | Axes::Z)),
|
||||||
) => {
|
) => {
|
||||||
|
let front_color = match hovered {
|
||||||
|
Some(Hovered(Control::Rotation(hovered_axes)))
|
||||||
|
if hovered_axes.intersects(axis) =>
|
||||||
|
{
|
||||||
|
color * 2.
|
||||||
|
}
|
||||||
|
_ => color,
|
||||||
|
};
|
||||||
|
|
||||||
let (front, back) = bisect_rotator_ring(&ring, cam_xform);
|
let (front, back) = bisect_rotator_ring(&ring, cam_xform);
|
||||||
gizmos.arc(front.center, front.axis, front.start, front.length, color);
|
gizmos.arc(
|
||||||
|
front.center,
|
||||||
|
front.axis,
|
||||||
|
front.start,
|
||||||
|
front.length,
|
||||||
|
front_color,
|
||||||
|
);
|
||||||
|
|
||||||
if !mode.transform.intersects(TransformType::TRANSLATE) {
|
if !mode.transform.intersects(TransformType::TRANSLATE) {
|
||||||
gizmos.arc(
|
gizmos.arc(
|
||||||
|
|||||||
Reference in New Issue
Block a user