Bevy Rewrite, attempt 2 #46
154
Cargo.lock
generated
@@ -618,6 +618,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "4b8369c16b7c017437021341521f8b4a0d98e1c70113fb358c3258ae7d661d79"
|
checksum = "4b8369c16b7c017437021341521f8b4a0d98e1c70113fb358c3258ae7d661d79"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy_internal",
|
"bevy_internal",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bevy-mesh-text-3d"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/terhechte/bevy-mesh-text-3d#77d8ae6935af636bcb85251b1debbc7f3d618f74"
|
||||||
|
dependencies = [
|
||||||
|
"bevy",
|
||||||
|
"cosmic-text 0.14.2",
|
||||||
|
"lyon",
|
||||||
|
"thiserror 2.0.12",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -686,6 +698,7 @@ dependencies = [
|
|||||||
"downcast-rs 2.0.1",
|
"downcast-rs 2.0.1",
|
||||||
"log",
|
"log",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.12",
|
||||||
|
"tracing",
|
||||||
"variadics_please",
|
"variadics_please",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
@@ -861,6 +874,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.12",
|
||||||
|
"tracing",
|
||||||
"variadics_please",
|
"variadics_please",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1092,9 +1106,11 @@ dependencies = [
|
|||||||
"bevy_ecs",
|
"bevy_ecs",
|
||||||
"bevy_utils",
|
"bevy_utils",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
"tracing-error",
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
"tracing-oslog",
|
"tracing-oslog",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
"tracing-tracy",
|
||||||
"tracing-wasm",
|
"tracing-wasm",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1165,16 +1181,6 @@ dependencies = [
|
|||||||
"glam",
|
"glam",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bevy_mod_meshtext"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "git+https://github.com/Schmarni-Dev/bevy_mod_meshtext#b623971b5a4d0ee0a93a2f89096726b9b7c9c87a"
|
|
||||||
dependencies = [
|
|
||||||
"atomicow",
|
|
||||||
"bevy",
|
|
||||||
"meshtext",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_mod_openxr"
|
name = "bevy_mod_openxr"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@@ -1388,11 +1394,13 @@ dependencies = [
|
|||||||
"naga_oil",
|
"naga_oil",
|
||||||
"nonmax",
|
"nonmax",
|
||||||
"offset-allocator",
|
"offset-allocator",
|
||||||
|
"profiling",
|
||||||
"send_wrapper",
|
"send_wrapper",
|
||||||
"serde",
|
"serde",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.12",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
"tracy-client",
|
||||||
"variadics_please",
|
"variadics_please",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
@@ -1542,7 +1550,7 @@ dependencies = [
|
|||||||
"bevy_transform",
|
"bevy_transform",
|
||||||
"bevy_utils",
|
"bevy_utils",
|
||||||
"bevy_window",
|
"bevy_window",
|
||||||
"cosmic-text",
|
"cosmic-text 0.13.2",
|
||||||
"serde",
|
"serde",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"sys-locale",
|
"sys-locale",
|
||||||
@@ -1913,16 +1921,6 @@ dependencies = [
|
|||||||
"shlex",
|
"shlex",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cdt"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b91b872294f63ef586b32aa94141561681aa35ca2d703960cca4f661f4e18184"
|
|
||||||
dependencies = [
|
|
||||||
"geometry-predicates",
|
|
||||||
"thiserror 1.0.69",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cesu8"
|
name = "cesu8"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -2283,6 +2281,29 @@ dependencies = [
|
|||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cosmic-text"
|
||||||
|
version = "0.14.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da46a9d5a8905cc538a4a5bceb6a4510de7a51049c5588c0114efce102bcbbe8"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.1",
|
||||||
|
"fontdb",
|
||||||
|
"log",
|
||||||
|
"rangemap",
|
||||||
|
"rustc-hash 1.1.0",
|
||||||
|
"rustybuzz",
|
||||||
|
"self_cell",
|
||||||
|
"smol_str",
|
||||||
|
"swash",
|
||||||
|
"sys-locale",
|
||||||
|
"ttf-parser 0.21.1",
|
||||||
|
"unicode-bidi",
|
||||||
|
"unicode-linebreak",
|
||||||
|
"unicode-script",
|
||||||
|
"unicode-segmentation",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpal"
|
name = "cpal"
|
||||||
version = "0.15.3"
|
version = "0.15.3"
|
||||||
@@ -2809,6 +2830,12 @@ dependencies = [
|
|||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "float_next_after"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
@@ -2975,12 +3002,6 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "geometry-predicates"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8dba84198cf199c11b83f1cb9243eaeb70dc50b719d2835ebf34bf2481bca010"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gethostname"
|
name = "gethostname"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
@@ -3861,6 +3882,58 @@ dependencies = [
|
|||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lyon"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91e7f9cda98b5430809e63ca5197b06c7d191bf7e26dfc467d5a3f0290e2a74f"
|
||||||
|
dependencies = [
|
||||||
|
"lyon_algorithms",
|
||||||
|
"lyon_tessellation",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lyon_algorithms"
|
||||||
|
version = "1.0.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f13c9be19d257c7d37e70608ed858e8eab4b2afcea2e3c9a622e892acbf43c08"
|
||||||
|
dependencies = [
|
||||||
|
"lyon_path",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lyon_geom"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8af69edc087272df438b3ee436c4bb6d7c04aa8af665cfd398feae627dbd8570"
|
||||||
|
dependencies = [
|
||||||
|
"arrayvec",
|
||||||
|
"euclid",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lyon_path"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0047f508cd7a85ad6bad9518f68cce7b1bf6b943fb71f6da0ee3bc1e8cb75f25"
|
||||||
|
dependencies = [
|
||||||
|
"lyon_geom",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lyon_tessellation"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "579d42360a4b09846eff2feef28f538696c7d6c7439bfa65874ff3cbe0951b2c"
|
||||||
|
dependencies = [
|
||||||
|
"float_next_after",
|
||||||
|
"lyon_path",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mach2"
|
name = "mach2"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
@@ -3930,18 +4003,6 @@ dependencies = [
|
|||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "meshtext"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8c68541f06674ef4bb1f84e3dca654998135ff1a8bb5a60cfbfe5b8615f8e555"
|
|
||||||
dependencies = [
|
|
||||||
"cdt",
|
|
||||||
"glam",
|
|
||||||
"owned_ttf_parser",
|
|
||||||
"ttf-parser 0.25.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "metal"
|
name = "metal"
|
||||||
version = "0.31.0"
|
version = "0.31.0"
|
||||||
@@ -4959,6 +5020,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d"
|
checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"profiling-procmacros",
|
"profiling-procmacros",
|
||||||
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5729,13 +5791,14 @@ name = "stardust-xr-server"
|
|||||||
version = "0.45.0"
|
version = "0.45.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy",
|
"bevy",
|
||||||
"bevy_mod_meshtext",
|
"bevy-mesh-text-3d",
|
||||||
"bevy_mod_openxr",
|
"bevy_mod_openxr",
|
||||||
"bevy_mod_xr",
|
"bevy_mod_xr",
|
||||||
"bevy_sk",
|
"bevy_sk",
|
||||||
"clap",
|
"clap",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
"console-subscriber",
|
"console-subscriber",
|
||||||
|
"cosmic-text 0.14.2",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
"directories",
|
"directories",
|
||||||
"glam",
|
"glam",
|
||||||
@@ -6339,8 +6402,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-tracy"
|
name = "tracing-tracy"
|
||||||
version = "0.11.4"
|
version = "0.11.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/nagisa/rust_tracy_client?tag=tracy-client-v0.18.1#7d084307f54959999ca3729c42bd4f4f3f0df54d"
|
||||||
checksum = "0eaa1852afa96e0fe9e44caa53dc0bd2d9d05e0f2611ce09f97f8677af56e4ba"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
@@ -6361,8 +6423,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "tracy-client"
|
name = "tracy-client"
|
||||||
version = "0.18.1"
|
version = "0.18.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/nagisa/rust_tracy_client?tag=tracy-client-v0.18.1#7d084307f54959999ca3729c42bd4f4f3f0df54d"
|
||||||
checksum = "3927832d93178f979a970d26deed7b03510586e328f31b0f9ad7a73985b8332a"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"loom",
|
"loom",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@@ -6372,11 +6433,10 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "tracy-client-sys"
|
name = "tracy-client-sys"
|
||||||
version = "0.25.0"
|
version = "0.25.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/nagisa/rust_tracy_client?tag=tracy-client-v0.18.1#7d084307f54959999ca3729c42bd4f4f3f0df54d"
|
||||||
checksum = "c032d68a49d25d9012a864fef1c64ac17aee43c87e0477bf7301d8ae8bfea7b7"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ path = "src/main.rs"
|
|||||||
default = []
|
default = []
|
||||||
wayland = ["dep:smithay", "dep:wayland-scanner", "dep:wayland-backend"]
|
wayland = ["dep:smithay", "dep:wayland-scanner", "dep:wayland-backend"]
|
||||||
|
|
|||||||
profile_tokio = ["dep:console-subscriber", "tokio/tracing"]
|
profile_tokio = ["dep:console-subscriber", "tokio/tracing"]
|
||||||
profile_app = ["dep:tracing-tracy"]
|
profile_app = ["dep:tracing-tracy", "bevy/trace_tracy"]
|
||||||
|
change_tracking = ["bevy/track_location"]
|
||||||
|
|
||||||
[package.metadata.appimage]
|
[package.metadata.appimage]
|
||||||
auto_link = true
|
auto_link = true
|
||||||
@@ -81,9 +82,10 @@ tokio = { version = "1.39.2", features = ["rt-multi-thread", "signal", "time"] }
|
|||||||
bevy = { version = "0.16", features = ["wayland", "bevy_remote"] }
|
bevy = { version = "0.16", features = ["wayland", "bevy_remote"] }
|
||||||
bevy_mod_xr = "0.3"
|
bevy_mod_xr = "0.3"
|
||||||
bevy_mod_openxr = "0.3"
|
bevy_mod_openxr = "0.3"
|
||||||
bevy_mod_meshtext.git = "https://github.com/Schmarni-Dev/bevy_mod_meshtext"
|
# bevy_mod_meshtext.git = "https://github.com/Schmarni-Dev/bevy_mod_meshtext"
|
||||||
# bevy_sk.git = "https://github.com/MalekiRe/bevy_sk"
|
# bevy_sk.git = "https://github.com/MalekiRe/bevy_sk"
|
||||||
# bevy_sk = { git = "https://github.com/Schmarni-Dev/bevy_sk", branch = "fix_mat_stuff" }
|
# bevy_sk = { git = "https://github.com/Schmarni-Dev/bevy_sk", branch = "fix_mat_stuff" }
|
||||||
|
bevy-mesh-text-3d.git = "https://github.com/terhechte/bevy-mesh-text-3d"
|
||||||
bevy_sk.path = "../bevy_sk"
|
bevy_sk.path = "../bevy_sk"
|
||||||
|
|
||||||
openxr = "0.19"
|
openxr = "0.19"
|
||||||
@@ -97,6 +99,7 @@ xkbcommon-rs = "0.1.0"
|
|||||||
# wayland
|
# wayland
|
||||||
wayland-backend = { version = "0.3.7", optional = true, default-features = false }
|
wayland-backend = { version = "0.3.7", optional = true, default-features = false }
|
||||||
wayland-scanner = { version = "0.31.4", optional = true }
|
wayland-scanner = { version = "0.31.4", optional = true }
|
||||||
|
cosmic-text = "0.14.2"
|
||||||
|
|
||||||
|
|
||||||
[dependencies.smithay]
|
[dependencies.smithay]
|
||||||
|
|||||||
@@ -7,3 +7,4 @@ pub mod registry;
|
|||||||
pub mod resource;
|
pub mod resource;
|
||||||
pub mod scenegraph;
|
pub mod scenegraph;
|
||||||
pub mod task;
|
pub mod task;
|
||||||
|
pub mod color;
|
||||||
|
|||||||
30
src/main.rs
@@ -12,28 +12,25 @@ use crate::nodes::{audio, drawable, input};
|
|||||||
|
|
||||||
use bevy::MinimalPlugins;
|
use bevy::MinimalPlugins;
|
||||||
use bevy::a11y::AccessibilityPlugin;
|
use bevy::a11y::AccessibilityPlugin;
|
||||||
use bevy::app::{App, MainScheduleOrder, ScheduleRunnerPlugin, TerminalCtrlCHandlerPlugin};
|
use bevy::app::{App, TerminalCtrlCHandlerPlugin};
|
||||||
use bevy::asset::{AssetMetaCheck, UnapprovedPathMode};
|
use bevy::asset::{AssetMetaCheck, UnapprovedPathMode};
|
||||||
use bevy::audio::AudioPlugin;
|
use bevy::audio::AudioPlugin;
|
||||||
use bevy::core_pipeline::CorePipelinePlugin;
|
use bevy::core_pipeline::CorePipelinePlugin;
|
||||||
|
use bevy::diagnostic::DiagnosticsPlugin;
|
||||||
use bevy::ecs::schedule::{ExecutorKind, ScheduleLabel};
|
use bevy::ecs::schedule::{ExecutorKind, ScheduleLabel};
|
||||||
use bevy::gizmos::GizmoPlugin;
|
use bevy::gizmos::GizmoPlugin;
|
||||||
use bevy::gltf::GltfPlugin;
|
use bevy::gltf::GltfPlugin;
|
||||||
use bevy::input::{InputPlugin, InputSystem};
|
use bevy::input::InputPlugin;
|
||||||
use bevy::pbr::PbrPlugin;
|
use bevy::pbr::PbrPlugin;
|
||||||
use bevy::remote::RemotePlugin;
|
use bevy::remote::RemotePlugin;
|
||||||
use bevy::remote::http::RemoteHttpPlugin;
|
use bevy::remote::http::RemoteHttpPlugin;
|
||||||
use bevy::render::{RenderDebugFlags, RenderPlugin};
|
use bevy::render::{RenderDebugFlags, RenderPlugin};
|
||||||
use bevy::scene::ScenePlugin;
|
use bevy::scene::ScenePlugin;
|
||||||
use bevy::text::FontLoader;
|
use bevy::text::FontLoader;
|
||||||
use bevy::winit::{WakeUp, WinitPlugin};
|
|
||||||
use bevy_mod_meshtext::MeshTextPlugin;
|
|
||||||
use bevy_mod_openxr::action_binding::OxrActionBindingPlugin;
|
|
||||||
use bevy_mod_openxr::action_set_attaching::OxrActionAttachingPlugin;
|
use bevy_mod_openxr::action_set_attaching::OxrActionAttachingPlugin;
|
||||||
use bevy_mod_openxr::action_set_syncing::OxrActionSyncingPlugin;
|
use bevy_mod_openxr::action_set_syncing::OxrActionSyncingPlugin;
|
||||||
use bevy_mod_openxr::add_xr_plugins;
|
use bevy_mod_openxr::add_xr_plugins;
|
||||||
use bevy_mod_openxr::exts::OxrExtensions;
|
use bevy_mod_openxr::exts::OxrExtensions;
|
||||||
use bevy_mod_openxr::features::handtracking::HandTrackingPlugin;
|
|
||||||
use bevy_mod_openxr::features::overlay::OxrOverlaySettings;
|
use bevy_mod_openxr::features::overlay::OxrOverlaySettings;
|
||||||
use bevy_mod_openxr::features::passthrough::OxrPassthroughPlugin;
|
use bevy_mod_openxr::features::passthrough::OxrPassthroughPlugin;
|
||||||
use bevy_mod_openxr::init::{OxrInitPlugin, should_run_frame_loop};
|
use bevy_mod_openxr::init::{OxrInitPlugin, should_run_frame_loop};
|
||||||
@@ -42,12 +39,13 @@ use bevy_mod_openxr::render::{OxrRenderPlugin, OxrWaitFrameSystem};
|
|||||||
use bevy_mod_openxr::resources::{OxrFrameState, OxrFrameWaiter, OxrSessionConfig};
|
use bevy_mod_openxr::resources::{OxrFrameState, OxrFrameWaiter, OxrSessionConfig};
|
||||||
use bevy_mod_openxr::types::AppInfo;
|
use bevy_mod_openxr::types::AppInfo;
|
||||||
use bevy_mod_xr::hand_debug_gizmos::HandGizmosPlugin;
|
use bevy_mod_xr::hand_debug_gizmos::HandGizmosPlugin;
|
||||||
use bevy_mod_xr::session::{XrFirst, XrHandleEvents, session_running};
|
use bevy_mod_xr::session::{XrFirst, XrHandleEvents};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use core::client::{Client, tick_internal_client};
|
use core::client::{Client, tick_internal_client};
|
||||||
use core::task;
|
use core::task;
|
||||||
use directories::ProjectDirs;
|
use directories::ProjectDirs;
|
||||||
use nodes::drawable::model::ModelNodePlugin;
|
use nodes::drawable::model::ModelNodePlugin;
|
||||||
|
use nodes::drawable::text::TextNodePlugin;
|
||||||
use nodes::spatial::SpatialNodePlugin;
|
use nodes::spatial::SpatialNodePlugin;
|
||||||
use objects::ServerObjects;
|
use objects::ServerObjects;
|
||||||
use objects::input::sk_controller::ControllerPlugin;
|
use objects::input::sk_controller::ControllerPlugin;
|
||||||
@@ -272,8 +270,7 @@ fn bevy_loop(
|
|||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
let mut plugins = MinimalPlugins
|
let mut plugins = MinimalPlugins
|
||||||
.build()
|
.build().add(DiagnosticsPlugin)
|
||||||
// .disable::<ScheduleRunnerPlugin>()
|
|
||||||
.add(TransformPlugin)
|
.add(TransformPlugin)
|
||||||
.add(InputPlugin)
|
.add(InputPlugin)
|
||||||
/* .add(AccessibilityPlugin) */;
|
/* .add(AccessibilityPlugin) */;
|
||||||
@@ -354,6 +351,7 @@ fn bevy_loop(
|
|||||||
.disable::<OxrActionAttachingPlugin>()
|
.disable::<OxrActionAttachingPlugin>()
|
||||||
.disable::<OxrActionSyncingPlugin>(),
|
.disable::<OxrActionSyncingPlugin>(),
|
||||||
);
|
);
|
||||||
|
// font size is in meters
|
||||||
app.add_plugins((
|
app.add_plugins((
|
||||||
bevy_sk::hand::HandPlugin,
|
bevy_sk::hand::HandPlugin,
|
||||||
bevy_sk::vr_materials::SkMaterialPlugin {
|
bevy_sk::vr_materials::SkMaterialPlugin {
|
||||||
@@ -363,7 +361,7 @@ fn bevy_loop(
|
|||||||
));
|
));
|
||||||
app.add_plugins(HandGizmosPlugin);
|
app.add_plugins(HandGizmosPlugin);
|
||||||
// app.add_plugins(MeshTextPlugin);
|
// app.add_plugins(MeshTextPlugin);
|
||||||
// app.init_asset::<Font>().init_asset_loader::<FontLoader>();
|
app.init_asset::<Font>().init_asset_loader::<FontLoader>();
|
||||||
if let Some(priority) = args.overlay_priority {
|
if let Some(priority) = args.overlay_priority {
|
||||||
app.insert_resource(OxrOverlaySettings {
|
app.insert_resource(OxrOverlaySettings {
|
||||||
session_layer_placement: priority,
|
session_layer_placement: priority,
|
||||||
@@ -388,6 +386,7 @@ fn bevy_loop(
|
|||||||
app.add_plugins((
|
app.add_plugins((
|
||||||
SpatialNodePlugin,
|
SpatialNodePlugin,
|
||||||
ModelNodePlugin,
|
ModelNodePlugin,
|
||||||
|
TextNodePlugin,
|
||||||
PlaySpacePlugin,
|
PlaySpacePlugin,
|
||||||
HandPlugin,
|
HandPlugin,
|
||||||
ControllerPlugin,
|
ControllerPlugin,
|
||||||
@@ -401,6 +400,17 @@ fn bevy_loop(
|
|||||||
.in_set(OxrWaitFrameSystem)
|
.in_set(OxrWaitFrameSystem)
|
||||||
.in_set(XrHandleEvents::FrameLoop),
|
.in_set(XrHandleEvents::FrameLoop),
|
||||||
);
|
);
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
let output = Command::new("fc-match")
|
||||||
|
.arg("-f")
|
||||||
|
.arg("%{file}")
|
||||||
|
.output()
|
||||||
|
.expect("Failed to run fc-match");
|
||||||
|
|
||||||
|
let font_path = String::from_utf8_lossy(&output.stdout);
|
||||||
|
info!("Default font path: {}", font_path);
|
||||||
|
|
||||||
app.run();
|
app.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ use stereokit_rust::{sk::MainThreadToken, system::Renderer, tex::SHCubemap};
|
|||||||
// #[instrument(level = "debug", skip(sk))]
|
// #[instrument(level = "debug", skip(sk))]
|
||||||
pub fn draw(token: &MainThreadToken) {
|
pub fn draw(token: &MainThreadToken) {
|
||||||
lines::draw_all(token);
|
lines::draw_all(token);
|
||||||
text::draw_all(token);
|
|
||||||
match QUEUED_SKYTEX.lock().take() {
|
match QUEUED_SKYTEX.lock().take() {
|
||||||
Some(Some(skytex)) => {
|
Some(Some(skytex)) => {
|
||||||
if let Ok(skytex) = SHCubemap::from_cubemap(skytex, true, 100) {
|
if let Ok(skytex) = SHCubemap::from_cubemap(skytex, true, 100) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use super::{MODEL_PART_ASPECT_ALIAS_INFO, MaterialParameter, ModelAspect, ModelPartAspect};
|
use super::{MODEL_PART_ASPECT_ALIAS_INFO, MaterialParameter, ModelAspect, ModelPartAspect};
|
||||||
|
⚠️ Potential issue Fix early return in iterator that prevents proper cleanup. Using 📝 Committable suggestion
🤖 Prompt for AI Agents_⚠️ Potential issue_
**Fix early return in iterator that prevents proper cleanup.**
Using `return` inside an iterator skips remaining entities. Should use `continue` instead.
```diff
let Some(model) = model_node.0.upgrade() else {
cmds.entity(entity).despawn();
- return;
+ continue;
};
```
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
```suggestion
let Some(model) = model_node.0.upgrade() else {
cmds.entity(entity).despawn();
continue;
};
```
</details>
<!-- suggestion_end -->
<details>
<summary>🤖 Prompt for AI Agents</summary>
```
In src/nodes/drawable/model.rs around lines 127 to 130, the use of `return`
inside the iterator prematurely exits the entire iteration, preventing cleanup
of remaining entities. Replace the `return` statement with `continue` to skip
the current iteration and allow the loop to proceed with other entities,
ensuring proper cleanup.
```
</details>
<!-- This is an auto-generated comment by CodeRabbit -->
<!-- fingerprinting:phantom:medusa:lion -->
|
|||||||
use crate::bail;
|
use crate::bail;
|
||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
|
use crate::core::color::ColorConvert as _;
|
||||||
use crate::core::error::Result;
|
use crate::core::error::Result;
|
||||||
use crate::core::registry::Registry;
|
use crate::core::registry::Registry;
|
||||||
use crate::core::resource::get_resource_file;
|
use crate::core::resource::get_resource_file;
|
||||||
@@ -27,9 +28,13 @@ impl Plugin for ModelNodePlugin {
|
|||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
let (tx, rx) = mpsc::unbounded_channel();
|
let (tx, rx) = mpsc::unbounded_channel();
|
||||||
LOAD_MODEL.set(tx).unwrap();
|
LOAD_MODEL.set(tx).unwrap();
|
||||||
|
app.init_resource::<MaterialRegistry>();
|
||||||
app.insert_resource(MpscReceiver(rx));
|
app.insert_resource(MpscReceiver(rx));
|
||||||
app.add_systems(Update, load_models);
|
app.add_systems(Update, load_models);
|
||||||
app.add_systems(PostUpdate, (gen_model_parts, apply_materials).chain());
|
app.add_systems(
|
||||||
|
PostUpdate,
|
||||||
|
(gen_model_parts, apply_materials, update_visibillity).chain(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,6 +43,24 @@ struct MpscReceiver<T>(mpsc::UnboundedReceiver<T>);
|
|||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
struct ModelNode(Weak<Model>);
|
struct ModelNode(Weak<Model>);
|
||||||
|
|
||||||
|
fn update_visibillity(mut cmds: Commands) {
|
||||||
|
for model in MODEL_REGISTRY.get_valid_contents().into_iter() {
|
||||||
|
let Some(entity) = model.bevy_scene_entity.get().copied() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
match model.spatial.node().map(|n| n.enabled()).unwrap_or(false) {
|
||||||
|
true => {
|
||||||
|
cmds.entity(entity)
|
||||||
|
.insert_recursive::<Children>(Visibility::Visible);
|
||||||
|
}
|
||||||
|
false => {
|
||||||
|
cmds.entity(entity)
|
||||||
|
.insert_recursive::<Children>(Visibility::Hidden);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn load_models(
|
fn load_models(
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
mut cmds: Commands,
|
mut cmds: Commands,
|
||||||
@@ -50,7 +73,7 @@ fn load_models(
|
|||||||
.spawn((
|
.spawn((
|
||||||
SceneRoot(handle),
|
SceneRoot(handle),
|
||||||
ModelNode(Arc::downgrade(&model)),
|
ModelNode(Arc::downgrade(&model)),
|
||||||
SpatialNode(Arc::downgrade(&model.space)),
|
SpatialNode(Arc::downgrade(&model.spatial)),
|
||||||
))
|
))
|
||||||
.id();
|
.id();
|
||||||
model.bevy_scene_entity.set(entity).unwrap();
|
model.bevy_scene_entity.set(entity).unwrap();
|
||||||
@@ -59,7 +82,7 @@ fn load_models(
|
|||||||
|
|
||||||
fn apply_materials(
|
fn apply_materials(
|
||||||
mut query: Query<&mut MeshMaterial3d<PbrMaterial>>,
|
mut query: Query<&mut MeshMaterial3d<PbrMaterial>>,
|
||||||
mut material_registry: Local<MaterialRegistry>,
|
mut material_registry: ResMut<MaterialRegistry>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
mut materials: ResMut<Assets<PbrMaterial>>,
|
mut materials: ResMut<Assets<PbrMaterial>>,
|
||||||
) -> bevy::prelude::Result {
|
) -> bevy::prelude::Result {
|
||||||
@@ -69,7 +92,9 @@ fn apply_materials(
|
|||||||
.filter_map(|p| p.parts.get())
|
.filter_map(|p| p.parts.get())
|
||||||
.flatten()
|
.flatten()
|
||||||
{
|
{
|
||||||
|
🛠️ Refactor suggestion Handle GLTF files with multiple scenes. The code assumes scene index 0 exists, which may not be true for all GLTF files. Consider making this configurable or loading the default scene. Alternatively, load the GLTF asset first to inspect available scenes: 🤖 Prompt for AI Agents_🛠️ Refactor suggestion_
**Handle GLTF files with multiple scenes.**
The code assumes scene index 0 exists, which may not be true for all GLTF files. Consider making this configurable or loading the default scene.
```diff
-let handle = asset_server.load(GltfAssetLabel::Scene(0).from_asset(path));
+// Use the default scene if available, otherwise scene 0
+let handle = asset_server.load::<Scene>(path.clone());
```
Alternatively, load the GLTF asset first to inspect available scenes:
```rust
let gltf_handle = asset_server.load::<Gltf>(path);
// Then in another system, check gltf.default_scene or iterate gltf.scenes
```
<details>
<summary>🤖 Prompt for AI Agents</summary>
```
In src/nodes/drawable/model.rs at line 68, the code currently loads a GLTF asset
assuming scene index 0 exists, which may not be valid for all GLTF files. To fix
this, first load the GLTF asset without specifying a scene, then in a separate
system or step, inspect the loaded GLTF to determine the default scene or
available scenes. Adjust the scene index dynamically based on this inspection
rather than hardcoding 0.
```
</details>
<!-- This is an auto-generated comment by CodeRabbit -->
<!-- fingerprinting:phantom:medusa:lion -->
|
|||||||
let mut mesh_mat = query.get_mut(*model_part.mesh_entity.get().unwrap())?;
|
let Ok(mut mesh_mat) = query.get_mut(*model_part.mesh_entity.get().unwrap()) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
if let Some(material) = model_part.pending_material_replacement.lock().take() {
|
if let Some(material) = model_part.pending_material_replacement.lock().take() {
|
||||||
let pbr_mat = material.to_pbr_mat(&asset_server);
|
let pbr_mat = material.to_pbr_mat(&asset_server);
|
||||||
let handle = material_registry.get_handle(pbr_mat, &mut materials);
|
let handle = material_registry.get_handle(pbr_mat, &mut materials);
|
||||||
@@ -128,8 +153,8 @@ fn gen_model_parts(
|
|||||||
let parent_spatial = parent
|
let parent_spatial = parent
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|p| p.space.clone())
|
.map(|p| p.space.clone())
|
||||||
.unwrap_or_else(|| model.space.clone());
|
.unwrap_or_else(|| model.spatial.clone());
|
||||||
let client = model.space.node()?.get_client()?;
|
let client = model.spatial.node()?.get_client()?;
|
||||||
let (spatial, model_part) =
|
let (spatial, model_part) =
|
||||||
match model.pre_bound_parts.lock().iter().find(|v| v.path == path) {
|
match model.pre_bound_parts.lock().iter().find(|v| v.path == path) {
|
||||||
None => {
|
None => {
|
||||||
@@ -341,16 +366,13 @@ impl MaterialParameter {
|
|||||||
MaterialParameter::Vec3(_val) => {
|
MaterialParameter::Vec3(_val) => {
|
||||||
// nothing uses a Vec3
|
// nothing uses a Vec3
|
||||||
}
|
}
|
||||||
MaterialParameter::Color(val) => {
|
MaterialParameter::Color(color) => match parameter_name {
|
||||||
let rgba = Srgba::new(val.c.r, val.c.g, val.c.b, val.a);
|
"color" => mat.color = color.to_bevy(),
|
||||||
match parameter_name {
|
"emission_factor" => mat.emission_factor = color.to_bevy(),
|
||||||
"color" => mat.color = rgba.into(),
|
v => {
|
||||||
"emission_factor" => mat.emission_factor = rgba.into(),
|
error!("unknown param_name ({v}) for color")
|
||||||
v => {
|
|
||||||
error!("unknown param_name ({v}) for color")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
MaterialParameter::Texture(resource) => {
|
MaterialParameter::Texture(resource) => {
|
||||||
let Some(texture_path) =
|
let Some(texture_path) =
|
||||||
get_resource_file(resource, client, &[OsStr::new("png"), OsStr::new("jpg")])
|
get_resource_file(resource, client, &[OsStr::new("png"), OsStr::new("jpg")])
|
||||||
@@ -474,11 +496,11 @@ impl ModelPartAspect for ModelPart {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Default)]
|
#[derive(Default, Resource)]
|
||||||
struct MaterialRegistry(FxHashMap<HashedPbrMaterial, Handle<PbrMaterial>>);
|
pub struct MaterialRegistry(FxHashMap<HashedPbrMaterial, Handle<PbrMaterial>>);
|
||||||
impl MaterialRegistry {
|
impl MaterialRegistry {
|
||||||
/// returns strong handle for PbrMaterial elminitating duplications
|
/// returns strong handle for PbrMaterial elminitating duplications
|
||||||
fn get_handle(
|
pub fn get_handle(
|
||||||
&mut self,
|
&mut self,
|
||||||
material: PbrMaterial,
|
material: PbrMaterial,
|
||||||
materials: &mut ResMut<Assets<PbrMaterial>>,
|
materials: &mut ResMut<Assets<PbrMaterial>>,
|
||||||
@@ -500,7 +522,7 @@ impl MaterialRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
space: Arc<Spatial>,
|
spatial: Arc<Spatial>,
|
||||||
_resource_id: ResourceID,
|
_resource_id: ResourceID,
|
||||||
bevy_scene_entity: OnceLock<Entity>,
|
bevy_scene_entity: OnceLock<Entity>,
|
||||||
parts: OnceLock<Vec<Arc<ModelPart>>>,
|
parts: OnceLock<Vec<Arc<ModelPart>>>,
|
||||||
@@ -516,7 +538,7 @@ impl Model {
|
|||||||
.ok_or_else(|| eyre!("Resource not found"))?;
|
.ok_or_else(|| eyre!("Resource not found"))?;
|
||||||
|
|
||||||
let model = Arc::new(Model {
|
let model = Arc::new(Model {
|
||||||
space: node.get_aspect::<Spatial>().unwrap().clone(),
|
spatial: node.get_aspect::<Spatial>().unwrap().clone(),
|
||||||
_resource_id: resource_id,
|
_resource_id: resource_id,
|
||||||
bevy_scene_entity: OnceLock::new(),
|
bevy_scene_entity: OnceLock::new(),
|
||||||
pre_bound_parts: Mutex::default(),
|
pre_bound_parts: Mutex::default(),
|
||||||
@@ -553,10 +575,14 @@ impl Model {
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// TODO: this could be a denail of service vector
|
// TODO: this could be a denail of service vector
|
||||||
let client = self.space.node().unwrap().get_client().unwrap();
|
let client = self.spatial.node().unwrap().get_client().unwrap();
|
||||||
let part_node = client.scenegraph.add_node(Node::generate(&client, false));
|
let part_node = client.scenegraph.add_node(Node::generate(&client, false));
|
||||||
let spatial =
|
let spatial = Spatial::add_to(
|
||||||
Spatial::add_to(&part_node, Some(self.space.clone()), Mat4::IDENTITY, false);
|
&part_node,
|
||||||
|
Some(self.spatial.clone()),
|
||||||
|
Mat4::IDENTITY,
|
||||||
|
false,
|
||||||
|
);
|
||||||
let part = part_node.add_aspect(ModelPart {
|
let part = part_node.add_aspect(ModelPart {
|
||||||
entity: OnceLock::new(),
|
entity: OnceLock::new(),
|
||||||
mesh_entity: OnceLock::new(),
|
mesh_entity: OnceLock::new(),
|
||||||
|
|||||||
@@ -1,48 +1,223 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
core::{
|
core::{
|
||||||
client::Client, destroy_queue, error::Result, registry::Registry,
|
client::Client, color::ColorConvert, error::Result, registry::Registry,
|
||||||
resource::get_resource_file,
|
resource::get_resource_file,
|
||||||
},
|
},
|
||||||
nodes::{Node, spatial::Spatial},
|
nodes::{
|
||||||
|
Node,
|
||||||
|
drawable::XAlign,
|
||||||
|
spatial::{Spatial, SpatialNode},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
use bevy::{platform::collections::HashMap, prelude::*};
|
||||||
|
use bevy_mesh_text_3d::{
|
||||||
|
Align, Attrs, MeshTextPlugin, Settings as FontSettings, generate_meshes,
|
||||||
|
text_glyphs::TextGlyphs,
|
||||||
|
};
|
||||||
|
use bevy_sk::vr_materials::PbrMaterial;
|
||||||
use color_eyre::eyre::eyre;
|
use color_eyre::eyre::eyre;
|
||||||
use glam::{Mat4, Vec2, vec3};
|
use core::f32;
|
||||||
|
use cosmic_text::Metrics;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::{
|
use std::{
|
||||||
ffi::OsStr,
|
ffi::OsStr,
|
||||||
|
mem,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
sync::{Arc, OnceLock},
|
sync::{Arc, OnceLock},
|
||||||
};
|
};
|
||||||
use stereokit_rust::{
|
use tokio::sync::mpsc;
|
||||||
font::Font,
|
|
||||||
sk::MainThreadToken,
|
|
||||||
system::{TextAlign, TextFit, TextStyle as SkTextStyle},
|
|
||||||
util::{Color32, Color128},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{TextAspect, TextStyle};
|
static SPAWN_TEXT: OnceLock<mpsc::UnboundedSender<Arc<Text>>> = OnceLock::new();
|
||||||
|
|
||||||
static TEXT_REGISTRY: Registry<Text> = Registry::new();
|
#[derive(Resource)]
|
||||||
|
struct MpscReceiver<T>(mpsc::UnboundedReceiver<T>);
|
||||||
|
|
||||||
fn convert_align(x_align: super::XAlign, y_align: super::YAlign) -> TextAlign {
|
pub struct TextNodePlugin;
|
||||||
match (x_align, y_align) {
|
|
||||||
(super::XAlign::Left, super::YAlign::Top) => TextAlign::TopLeft,
|
impl Plugin for TextNodePlugin {
|
||||||
(super::XAlign::Left, super::YAlign::Center) => TextAlign::CenterLeft,
|
fn build(&self, app: &mut App) {
|
||||||
(super::XAlign::Left, super::YAlign::Bottom) => TextAlign::BottomLeft,
|
// Text init stuff
|
||||||
(super::XAlign::Center, super::YAlign::Top) => TextAlign::Center,
|
// app.init_asset::<Font>().init_asset_loader::<FontLoader>();
|
||||||
(super::XAlign::Center, super::YAlign::Center) => TextAlign::Center,
|
// load_internal_binary_asset!(
|
||||||
(super::XAlign::Center, super::YAlign::Bottom) => TextAlign::BottomCenter,
|
// app,
|
||||||
(super::XAlign::Right, super::YAlign::Top) => TextAlign::TopRight,
|
// Handle::default(),
|
||||||
(super::XAlign::Right, super::YAlign::Center) => TextAlign::CenterRight,
|
// "assets/FiraMono-subset.ttf",
|
||||||
(super::XAlign::Right, super::YAlign::Bottom) => TextAlign::BottomRight,
|
// |bytes: &[u8], _path: String| { Font::try_from_bytes(bytes.to_vec()).unwrap() }
|
||||||
|
// );
|
||||||
|
// 1.0 for font size in meters
|
||||||
|
app.add_plugins(MeshTextPlugin::new(1.0));
|
||||||
|
app.world_mut()
|
||||||
|
.resource_mut::<FontSettings>()
|
||||||
|
.font_system
|
||||||
|
.db_mut()
|
||||||
|
.load_system_fonts();
|
||||||
|
|
||||||
|
let (tx, rx) = mpsc::unbounded_channel();
|
||||||
|
SPAWN_TEXT.set(tx).unwrap();
|
||||||
|
app.init_resource::<MaterialRegistry>();
|
||||||
|
app.insert_resource(MpscReceiver(rx));
|
||||||
|
app.add_systems(Update, (spawn_text, update_visibillity).chain());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Text {
|
fn update_visibillity(mut cmds: Commands) {
|
||||||
space: Arc<Spatial>,
|
for text in TEXT_REGISTRY.get_valid_contents().into_iter() {
|
||||||
font_path: Option<PathBuf>,
|
let Some(entity) = text.entity.lock().as_ref().copied() else {
|
||||||
style: OnceLock<SkTextStyle>,
|
continue;
|
||||||
|
};
|
||||||
|
match text.spatial.node().map(|n| n.enabled()).unwrap_or(false) {
|
||||||
|
true => {
|
||||||
|
cmds.entity(entity)
|
||||||
|
.insert_recursive::<Children>(Visibility::Visible);
|
||||||
|
}
|
||||||
|
false => {
|
||||||
|
cmds.entity(entity)
|
||||||
|
.insert_recursive::<Children>(Visibility::Hidden);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn_text(
|
||||||
|
mut mpsc: ResMut<MpscReceiver<Arc<Text>>>,
|
||||||
|
mut cmds: Commands,
|
||||||
|
mut font_settings: ResMut<FontSettings>,
|
||||||
|
mut material_registry: ResMut<MaterialRegistry>,
|
||||||
|
mut materials: ResMut<Assets<PbrMaterial>>,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
mut font_registry: Local<FontDatabaseRegistry>,
|
||||||
|
) {
|
||||||
|
while let Ok(text) = mpsc.0.try_recv() {
|
||||||
|
if let Some(entity) = text.entity.lock().take() {
|
||||||
|
cmds.entity(entity).despawn();
|
||||||
|
}
|
||||||
|
let style = text.data.lock();
|
||||||
|
let old_db = text.font_path.clone().map(|p| {
|
||||||
|
let db = font_registry.get(p);
|
||||||
|
mem::swap(font_settings.font_system.db_mut(), db);
|
||||||
|
db
|
||||||
|
});
|
||||||
|
let attrs = Attrs::new().weight(cosmic_text::Weight::BOLD);
|
||||||
|
let alignment = Some(match style.text_align_x {
|
||||||
|
super::XAlign::Left => Align::Right,
|
||||||
|
super::XAlign::Center => Align::Center,
|
||||||
|
super::XAlign::Right => Align::Left,
|
||||||
|
});
|
||||||
|
let text_string = text.text.lock().clone();
|
||||||
|
let mut text_glyphs = TextGlyphs::new(
|
||||||
|
Metrics {
|
||||||
|
font_size: style.character_height,
|
||||||
|
line_height: style.character_height,
|
||||||
|
},
|
||||||
|
[(text_string.as_str(), attrs.clone())],
|
||||||
|
&attrs,
|
||||||
|
&mut font_settings.font_system,
|
||||||
|
⚠️ Potential issue Fix incorrect height bounds calculation. The max_height is incorrectly using bounds.x instead of bounds.y. 📝 Committable suggestion
🤖 Prompt for AI Agents_⚠️ Potential issue_
**Fix incorrect height bounds calculation.**
The max_height is incorrectly using bounds.x instead of bounds.y.
```diff
let max_width = style.bounds.as_ref().map(|v| v.bounds.x);
-let max_height = style.bounds.as_ref().map(|v| v.bounds.x);
+let max_height = style.bounds.as_ref().map(|v| v.bounds.y);
```
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
```suggestion
let max_width = style.bounds.as_ref().map(|v| v.bounds.x);
let max_height = style.bounds.as_ref().map(|v| v.bounds.y);
```
</details>
<!-- suggestion_end -->
<details>
<summary>🤖 Prompt for AI Agents</summary>
```
In src/nodes/drawable/text.rs around lines 104 to 105, the max_height variable
is incorrectly assigned using bounds.x instead of bounds.y. Change the
max_height assignment to use bounds.y to correctly reflect the height bounds
from the style.
```
</details>
<!-- This is an auto-generated comment by CodeRabbit -->
<!-- fingerprinting:phantom:medusa:lion -->
|
|||||||
|
alignment,
|
||||||
|
);
|
||||||
|
let max_width = style.bounds.as_ref().map(|v| v.bounds.x);
|
||||||
|
let max_height = style.bounds.as_ref().map(|v| v.bounds.x);
|
||||||
|
let (width, height) =
|
||||||
|
text_glyphs.measure(max_width, max_height, &mut font_settings.font_system);
|
||||||
|
info!(width, height, ?style.text_align_x);
|
||||||
|
let meshes = generate_meshes(
|
||||||
|
bevy_mesh_text_3d::InputText::Simple {
|
||||||
|
text: text_string,
|
||||||
|
material: material_registry.get_handle(
|
||||||
|
PbrMaterial {
|
||||||
|
color: style.color.to_bevy(),
|
||||||
|
emission_factor: Color::WHITE,
|
||||||
|
metallic: 0.0,
|
||||||
|
roughness: 1.0,
|
||||||
|
// If alpha is supported on text we need to change this
|
||||||
|
alpha_mode: AlphaMode::Opaque,
|
||||||
|
double_sided: false,
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
&mut materials,
|
||||||
|
),
|
||||||
|
attrs,
|
||||||
|
},
|
||||||
|
&mut font_settings,
|
||||||
|
bevy_mesh_text_3d::Parameters {
|
||||||
|
extrusion_depth: 0.0,
|
||||||
|
font_size: style.character_height,
|
||||||
|
line_height: style.character_height,
|
||||||
|
alignment,
|
||||||
|
max_width,
|
||||||
|
max_height,
|
||||||
|
},
|
||||||
|
&mut meshes,
|
||||||
|
);
|
||||||
|
if let Some(db) = old_db {
|
||||||
|
mem::swap(font_settings.font_system.db_mut(), db);
|
||||||
|
}
|
||||||
|
let Ok(meshes) = meshes.inspect_err(|err| error!("unable to create text meshes: {err}"))
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let dist = meshes.iter().fold(f32::MAX, |dist, v| {
|
||||||
|
dist.min(v.transform.translation.x)
|
||||||
|
// if dist > v.transform.translation.x {
|
||||||
|
// v.transform.translation.x
|
||||||
|
// } else {
|
||||||
|
// dist
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
// TODO: text align
|
||||||
|
let letters = meshes
|
||||||
|
.into_iter()
|
||||||
|
.map(|v| {
|
||||||
|
// info!("{:?}", v.transform);
|
||||||
|
cmds.spawn((
|
||||||
|
Mesh3d(v.mesh),
|
||||||
|
MeshMaterial3d(v.material),
|
||||||
|
// rotation is sus, might be related to the gltf coordinate system
|
||||||
|
Transform::from_rotation(Quat::from_rotation_y(f32::consts::PI))
|
||||||
|
* Transform::from_xyz(
|
||||||
|
-dist
|
||||||
|
+ match style.bounds.as_ref().map(|v| v.anchor_align_x) {
|
||||||
|
Some(XAlign::Center) => width * -0.5,
|
||||||
|
Some(XAlign::Right) => width * -1.0,
|
||||||
|
Some(XAlign::Left) => 0.0,
|
||||||
|
None => 0.0,
|
||||||
|
},
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
) * v.transform,
|
||||||
|
))
|
||||||
|
.id()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let entity = cmds
|
||||||
|
.spawn((SpatialNode(Arc::downgrade(&text.spatial)),))
|
||||||
|
.add_children(&letters)
|
||||||
|
.id();
|
||||||
|
text.entity.lock().replace(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct FontDatabaseRegistry(HashMap<PathBuf, cosmic_text::fontdb::Database>);
|
||||||
|
impl FontDatabaseRegistry {
|
||||||
|
fn get(&mut self, path: PathBuf) -> &mut cosmic_text::fontdb::Database {
|
||||||
|
self.0.entry(path).or_insert_with_key(|path| {
|
||||||
|
let mut db = cosmic_text::fontdb::Database::new();
|
||||||
|
if let Err(err) = db.load_font_file(path) {
|
||||||
|
error!("unable to load font file {} {err}", path.to_string_lossy());
|
||||||
|
};
|
||||||
|
db
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
use super::{TextAspect, TextStyle, model::MaterialRegistry};
|
||||||
|
|
||||||
|
static TEXT_REGISTRY: Registry<Text> = Registry::new();
|
||||||
|
|
||||||
|
pub struct Text {
|
||||||
|
spatial: Arc<Spatial>,
|
||||||
|
font_path: Option<PathBuf>,
|
||||||
|
entity: Mutex<Option<Entity>>,
|
||||||
text: Mutex<String>,
|
text: Mutex<String>,
|
||||||
data: Mutex<TextStyle>,
|
data: Mutex<TextStyle>,
|
||||||
}
|
}
|
||||||
@@ -50,88 +225,20 @@ impl Text {
|
|||||||
pub fn add_to(node: &Arc<Node>, text: String, style: TextStyle) -> Result<Arc<Text>> {
|
pub fn add_to(node: &Arc<Node>, text: String, style: TextStyle) -> Result<Arc<Text>> {
|
||||||
let client = node.get_client().ok_or_else(|| eyre!("Client not found"))?;
|
let client = node.get_client().ok_or_else(|| eyre!("Client not found"))?;
|
||||||
let text = TEXT_REGISTRY.add(Text {
|
let text = TEXT_REGISTRY.add(Text {
|
||||||
space: node.get_aspect::<Spatial>().unwrap().clone(),
|
spatial: node.get_aspect::<Spatial>().unwrap().clone(),
|
||||||
font_path: style.font.as_ref().and_then(|res| {
|
font_path: style.font.as_ref().and_then(|res| {
|
||||||
get_resource_file(res, &client, &[OsStr::new("ttf"), OsStr::new("otf")])
|
get_resource_file(res, &client, &[OsStr::new("ttf"), OsStr::new("otf")])
|
||||||
}),
|
}),
|
||||||
style: OnceLock::new(),
|
|
||||||
|
|
||||||
|
entity: Mutex::new(None),
|
||||||
text: Mutex::new(text),
|
text: Mutex::new(text),
|
||||||
data: Mutex::new(style),
|
data: Mutex::new(style),
|
||||||
});
|
});
|
||||||
node.add_aspect_raw(text.clone());
|
node.add_aspect_raw(text.clone());
|
||||||
|
_ = SPAWN_TEXT.get().unwrap().send(text.clone());
|
||||||
|
|
||||||
Ok(text)
|
Ok(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&self, token: &MainThreadToken) {
|
|
||||||
let style = self.style.get_or_init(|| {
|
|
||||||
let font = self
|
|
||||||
.font_path
|
|
||||||
.as_deref()
|
|
||||||
.and_then(|path| Font::from_file(path).ok())
|
|
||||||
.unwrap_or_default();
|
|
||||||
SkTextStyle::from_font(font, 1.0, Color32::WHITE)
|
|
||||||
});
|
|
||||||
|
|
||||||
let text = self.text.lock();
|
|
||||||
let data = self.data.lock();
|
|
||||||
let transform = self.space.global_transform()
|
|
||||||
* Mat4::from_scale(vec3(
|
|
||||||
data.character_height,
|
|
||||||
data.character_height,
|
|
||||||
data.character_height,
|
|
||||||
));
|
|
||||||
if let Some(bounds) = &data.bounds {
|
|
||||||
stereokit_rust::system::Text::add_in(
|
|
||||||
token,
|
|
||||||
&*text,
|
|
||||||
transform,
|
|
||||||
Vec2::from(bounds.bounds) / data.character_height,
|
|
||||||
match bounds.fit {
|
|
||||||
super::TextFit::Wrap => TextFit::Wrap,
|
|
||||||
super::TextFit::Clip => TextFit::Clip,
|
|
||||||
super::TextFit::Squeeze => TextFit::Squeeze,
|
|
||||||
super::TextFit::Exact => TextFit::Exact,
|
|
||||||
super::TextFit::Overflow => TextFit::Overflow,
|
|
||||||
},
|
|
||||||
Some(*style),
|
|
||||||
Some(Color128::new(
|
|
||||||
data.color.c.r,
|
|
||||||
data.color.c.g,
|
|
||||||
data.color.c.b,
|
|
||||||
data.color.a,
|
|
||||||
)),
|
|
||||||
data.bounds
|
|
||||||
.as_ref()
|
|
||||||
.map(|b| convert_align(b.anchor_align_x, b.anchor_align_y)),
|
|
||||||
Some(convert_align(data.text_align_x, data.text_align_y)),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
stereokit_rust::system::Text::add_at(
|
|
||||||
token,
|
|
||||||
&*text,
|
|
||||||
transform,
|
|
||||||
Some(*style),
|
|
||||||
Some(Color128::new(
|
|
||||||
data.color.c.r,
|
|
||||||
data.color.c.g,
|
|
||||||
data.color.c.b,
|
|
||||||
data.color.a,
|
|
||||||
)),
|
|
||||||
data.bounds
|
|
||||||
.as_ref()
|
|
||||||
.map(|b| convert_align(b.anchor_align_x, b.anchor_align_y)),
|
|
||||||
Some(convert_align(data.text_align_x, data.text_align_y)),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
impl TextAspect for Text {
|
impl TextAspect for Text {
|
||||||
fn set_character_height(
|
fn set_character_height(
|
||||||
@@ -141,30 +248,19 @@ impl TextAspect for Text {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let this_text = node.get_aspect::<Text>()?;
|
let this_text = node.get_aspect::<Text>()?;
|
||||||
this_text.data.lock().character_height = height;
|
this_text.data.lock().character_height = height;
|
||||||
|
_ = SPAWN_TEXT.get().unwrap().send(this_text.clone());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_text(node: Arc<Node>, _calling_client: Arc<Client>, text: String) -> Result<()> {
|
fn set_text(node: Arc<Node>, _calling_client: Arc<Client>, text: String) -> Result<()> {
|
||||||
let this_text = node.get_aspect::<Text>()?;
|
let this_text = node.get_aspect::<Text>()?;
|
||||||
*this_text.text.lock() = text;
|
*this_text.text.lock() = text;
|
||||||
|
_ = SPAWN_TEXT.get().unwrap().send(this_text.clone());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Drop for Text {
|
impl Drop for Text {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(style) = self.style.take() {
|
|
||||||
destroy_queue::add(style);
|
|
||||||
}
|
|
||||||
TEXT_REGISTRY.remove(self);
|
TEXT_REGISTRY.remove(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_all(token: &MainThreadToken) {
|
|
||||||
for text in TEXT_REGISTRY.get_valid_contents() {
|
|
||||||
if let Some(node) = text.space.node() {
|
|
||||||
if node.enabled() {
|
|
||||||
text.draw(token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ mod tip;
|
|||||||
|
|
||||||
pub use handler::*;
|
pub use handler::*;
|
||||||
pub use method::*;
|
pub use method::*;
|
||||||
|
use tracing::debug_span;
|
||||||
|
|
||||||
use super::Aspect;
|
use super::Aspect;
|
||||||
use super::AspectIdentifier;
|
use super::AspectIdentifier;
|
||||||
@@ -120,6 +121,7 @@ pub fn process_input() {
|
|||||||
node.enabled()
|
node.enabled()
|
||||||
});
|
});
|
||||||
for handler in INPUT_HANDLER_REGISTRY.get_valid_contents() {
|
for handler in INPUT_HANDLER_REGISTRY.get_valid_contents() {
|
||||||
|
let _span = debug_span!("handle input handler").entered();
|
||||||
for method_alias in handler.method_aliases.get_aliases() {
|
for method_alias in handler.method_aliases.get_aliases() {
|
||||||
method_alias.set_enabled(false);
|
method_alias.set_enabled(false);
|
||||||
}
|
}
|
||||||
@@ -136,6 +138,7 @@ pub fn process_input() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let ser_span = debug_span!("serializing input").entered();
|
||||||
let (methods, datas) = methods
|
let (methods, datas) = methods
|
||||||
.clone()
|
.clone()
|
||||||
// filter out methods without the handler in their handler order
|
// filter out methods without the handler in their handler order
|
||||||
@@ -161,7 +164,9 @@ pub fn process_input() {
|
|||||||
// serialize the data
|
// serialize the data
|
||||||
.map(|(a, m)| (a.clone(), m.serialize(a.get_id(), &handler)))
|
.map(|(a, m)| (a.clone(), m.serialize(a.get_id(), &handler)))
|
||||||
.unzip::<_, _, Vec<_>, Vec<_>>();
|
.unzip::<_, _, Vec<_>, Vec<_>>();
|
||||||
|
drop(ser_span);
|
||||||
|
|
||||||
|
let _span = debug_span!("client input").entered();
|
||||||
let _ = input_handler_client::input(&handler_node, &methods, &datas);
|
let _ = input_handler_client::input(&handler_node, &methods, &datas);
|
||||||
}
|
}
|
||||||
for method in methods {
|
for method in methods {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ use crate::core::client::Client;
|
|||||||
use crate::core::error::Result;
|
use crate::core::error::Result;
|
||||||
use crate::core::registry::Registry;
|
use crate::core::registry::Registry;
|
||||||
use crate::nodes::{Node, OWNED_ASPECT_ALIAS_INFO};
|
use crate::nodes::{Node, OWNED_ASPECT_ALIAS_INFO};
|
||||||
use bevy::ecs::entity_disabling::Disabled;
|
|
||||||
use bevy::prelude::Transform as BevyTransform;
|
use bevy::prelude::Transform as BevyTransform;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use color_eyre::eyre::OptionExt;
|
use color_eyre::eyre::OptionExt;
|
||||||
@@ -18,7 +17,6 @@ use mint::Vector3;
|
|||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::sync::atomic::Ordering;
|
|
||||||
use std::sync::{Arc, OnceLock, Weak};
|
use std::sync::{Arc, OnceLock, Weak};
|
||||||
|
🛠️ Refactor suggestion Consider implementing entity cleanup for dead spatial references. The comment raises a valid concern. When the spatial weak reference can't be upgraded, the entity is orphaned and should be despawned to prevent resource leaks. Note: This would require adding
🤖 Prompt for AI Agents_🛠️ Refactor suggestion_
**Consider implementing entity cleanup for dead spatial references.**
The comment raises a valid concern. When the spatial weak reference can't be upgraded, the entity is orphaned and should be despawned to prevent resource leaks.
```diff
let Some(spatial) = spatial_node.0.upgrade() else {
- // should we despawn the entity?
+ cmds.entity(entity).despawn_recursive();
return;
};
```
Note: This would require adding `Commands` to the system parameters.
> Committable suggestion skipped: line range outside the PR's diff.
<details>
<summary>🤖 Prompt for AI Agents</summary>
```
In src/nodes/spatial/mod.rs around lines 41 to 44, the code currently returns
early when the spatial weak reference cannot be upgraded, potentially leaving
orphaned entities. To fix this, modify the system to accept Commands as a
parameter and use it to despawn the entity when the spatial reference is dead,
ensuring proper cleanup and preventing resource leaks.
```
</details>
<!-- This is an auto-generated comment by CodeRabbit -->
<!-- fingerprinting:phantom:medusa:lion -->
|
|||||||
use std::{f32, ptr};
|
use std::{f32, ptr};
|
||||||
use stereokit_rust::maths::Bounds;
|
use stereokit_rust::maths::Bounds;
|
||||||
@@ -28,62 +26,39 @@ impl Plugin for SpatialNodePlugin {
|
|||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
PostUpdate,
|
PostUpdate,
|
||||||
(replace_childof, update_spatial_nodes).before(TransformSystem::TransformPropagate),
|
update_spatial_nodes.before(TransformSystem::TransformPropagate),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_spatial_nodes(
|
fn update_spatial_nodes(
|
||||||
mut query: Query<(Entity, &mut BevyTransform, &SpatialNode, Has<Disabled>)>,
|
mut query: Query<(&mut BevyTransform, &SpatialNode, Option<&ChildOf>)>,
|
||||||
cmds: ParallelCommands,
|
parent_query: Query<&GlobalTransform>,
|
||||||
) {
|
) {
|
||||||
query
|
query
|
||||||
.par_iter_mut()
|
.par_iter_mut()
|
||||||
.for_each(|(entity, mut transform, spatial_node, disabled)| {
|
.for_each(|(mut transform, spatial_node, child_of)| {
|
||||||
let Some(spatial) = spatial_node.0.upgrade() else {
|
let Some(spatial) = spatial_node.0.upgrade() else {
|
||||||
|
// should we despawn the entity?
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if !spatial
|
|
||||||
.node()
|
|
||||||
.map(|n| n.enabled.load(Ordering::Relaxed))
|
|
||||||
.unwrap_or(true)
|
|
||||||
{
|
|
||||||
// cmds.command_scope(|mut cmds| {
|
|
||||||
// cmds.entity(entity).insert(Visibility::Hidden);
|
|
||||||
// });
|
|
||||||
// return;
|
|
||||||
}
|
|
||||||
let mat4 = spatial.global_transform();
|
let mat4 = spatial.global_transform();
|
||||||
|
match child_of {
|
||||||
let scale_zero = mat4.to_scale_rotation_translation().0.length_squared() > 0.0;
|
Some(child_of) => {
|
||||||
if scale_zero {
|
let Ok(parent) = parent_query.get(child_of.0) else {
|
||||||
// cmds.command_scope(|mut cmds| {
|
warn!("SpatialNode bevy Parent doesn't have global transform");
|
||||||
// cmds.entity(entity).insert(Visibility::Hidden);
|
return;
|
||||||
// });
|
};
|
||||||
} else if disabled {
|
*transform =
|
||||||
// cmds.command_scope(|mut cmds| {
|
BevyTransform::from_matrix(parent.compute_matrix().inverse() * mat4);
|
||||||
// cmds.entity(entity).insert(Visibility::Visible);
|
}
|
||||||
// });
|
None => {
|
||||||
|
*transform = BevyTransform::from_matrix(mat4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*transform = BevyTransform::from_matrix(mat4);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replace_childof(query: Query<(Entity, &ChildOf), With<SpatialNode>>, mut cmds: Commands) {
|
|
||||||
for (entity, parent) in &query {
|
|
||||||
cmds.entity(entity)
|
|
||||||
.insert(NonSpatialChildOf(parent.0))
|
|
||||||
.remove::<ChildOf>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Component, Default, Debug, PartialEq, Eq)]
|
|
||||||
#[relationship_target(relationship = NonSpatialChildOf, linked_spawn)]
|
|
||||||
pub struct NonSpatialChildren(Vec<Entity>);
|
|
||||||
#[derive(Component, Debug, PartialEq, Eq)]
|
|
||||||
#[relationship(relationship_target = NonSpatialChildren)]
|
|
||||||
pub struct NonSpatialChildOf(Entity);
|
|
||||||
|
|
||||||
#[derive(Clone, Component, Debug)]
|
#[derive(Clone, Component, Debug)]
|
||||||
#[require(BevyTransform)]
|
#[require(BevyTransform)]
|
||||||
pub struct SpatialNode(pub Weak<Spatial>);
|
pub struct SpatialNode(pub Weak<Spatial>);
|
||||||
|
|||||||
@@ -154,9 +154,7 @@ fn update(
|
|||||||
ref_space: Option<Res<XrPrimaryReferenceSpace>>,
|
ref_space: Option<Res<XrPrimaryReferenceSpace>>,
|
||||||
state: Option<Res<OxrFrameState>>,
|
state: Option<Res<OxrFrameState>>,
|
||||||
) {
|
) {
|
||||||
info!("calling update");
|
|
||||||
let (Some(session), Some(state), Some(ref_space)) = (session, state, ref_space) else {
|
let (Some(session), Some(state), Some(ref_space)) = (session, state, ref_space) else {
|
||||||
info!("something is missing");
|
|
||||||
controllers.left.set_enabled(false);
|
controllers.left.set_enabled(false);
|
||||||
controllers.right.set_enabled(false);
|
controllers.right.set_enabled(false);
|
||||||
return;
|
return;
|
||||||
@@ -288,6 +286,7 @@ impl SkController {
|
|||||||
let tracked = Tracked::new(connection, &path);
|
let tracked = Tracked::new(connection, &path);
|
||||||
let tip = InputDataType::Tip(Tip::default());
|
let tip = InputDataType::Tip(Tip::default());
|
||||||
let node = spatial.node().unwrap();
|
let node = spatial.node().unwrap();
|
||||||
|
node.set_enabled(false);
|
||||||
let model = Model::add_to(&node, ResourceID::Direct(CURSOR_MODEL_PATH.into())).unwrap();
|
let model = Model::add_to(&node, ResourceID::Direct(CURSOR_MODEL_PATH.into())).unwrap();
|
||||||
let model_part = model.get_model_part("Cursor".to_string()).unwrap();
|
let model_part = model.get_model_part("Cursor".to_string()).unwrap();
|
||||||
let input = InputMethod::add_to(
|
let input = InputMethod::add_to(
|
||||||
@@ -324,7 +323,6 @@ impl SkController {
|
|||||||
ref_space: XrReferenceSpace,
|
ref_space: XrReferenceSpace,
|
||||||
) {
|
) {
|
||||||
let Some(space) = self.space.as_ref() else {
|
let Some(space) = self.space.as_ref() else {
|
||||||
info!("no space 3:");
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Ok(location) = session
|
let Ok(location) = session
|
||||||
@@ -339,10 +337,8 @@ impl SkController {
|
|||||||
| SpaceLocationFlags::ORIENTATION_VALID
|
| SpaceLocationFlags::ORIENTATION_VALID
|
||||||
| SpaceLocationFlags::ORIENTATION_TRACKED,
|
| SpaceLocationFlags::ORIENTATION_TRACKED,
|
||||||
);
|
);
|
||||||
info!("{:#?}", location.location_flags);
|
|
||||||
self.set_enabled(enabled);
|
self.set_enabled(enabled);
|
||||||
if enabled {
|
if enabled {
|
||||||
info!("update");
|
|
||||||
let world_transform = Mat4::from(Affine3A::from(location.pose.to_xr_pose()));
|
let world_transform = Mat4::from(Affine3A::from(location.pose.to_xr_pose()));
|
||||||
self.model_part
|
self.model_part
|
||||||
.set_material_parameter("roughness".to_string(), MaterialParameter::Float(1.0));
|
.set_material_parameter("roughness".to_string(), MaterialParameter::Float(1.0));
|
||||||
|
|||||||
⚠️ Potential issue
Breaking change: Wayland no longer in default features.
Removing
waylandfrom default features might break existing users. Consider documenting this change prominently or keeping it as default if it's commonly used.🤖 Prompt for AI Agents