refactor: improve performance a lot
Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
12
Cargo.toml
12
Cargo.toml
@@ -9,6 +9,11 @@ license = "GPLv2"
|
||||
repository = "https://github.com/StardustXR/stardust-xr-server/"
|
||||
homepage = "https://stardustxr.org"
|
||||
|
||||
[patch.crates-io]
|
||||
tracing-tracy = { git = "https://github.com/nagisa/rust_tracy_client", tag = "tracy-client-v0.17.6" }
|
||||
tracy-client = { git = "https://github.com/nagisa/rust_tracy_client", tag = "tracy-client-v0.17.6" }
|
||||
tracy-client-sys = { git = "https://github.com/nagisa/rust_tracy_client", tag = "tracy-client-v0.17.6" }
|
||||
|
||||
[workspace]
|
||||
members = ["codegen"]
|
||||
|
||||
@@ -46,7 +51,12 @@ auto_link_exclude_list = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
bevy = { version = "0.15", features = ["wayland", "mp3", "wav"] }
|
||||
bevy = { version = "0.15", features = [
|
||||
"wayland",
|
||||
"mp3",
|
||||
"wav",
|
||||
"trace_tracy",
|
||||
] }
|
||||
bevy_mod_xr = { git = "https://github.com/Schmarni-Dev/bevy_openxr", branch = "0.15rc" }
|
||||
bevy_mod_openxr = { git = "https://github.com/Schmarni-Dev/bevy_openxr", branch = "0.15rc" }
|
||||
bevy_xr_utils = { git = "https://github.com/Schmarni-Dev/bevy_openxr", branch = "0.15rc" }
|
||||
|
||||
@@ -49,6 +49,93 @@ pub fn codegen_item_panel_protocol(_input: proc_macro::TokenStream) -> proc_macr
|
||||
codegen_protocol(ITEM_PANEL_PROTOCOL)
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn codegen_id_to_name_functions(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let mut aspect_map: Vec<(u64, String)> = Vec::new();
|
||||
let mut method_map: Vec<(u64, String)> = Vec::new();
|
||||
let mut signal_map: Vec<(u64, String)> = Vec::new();
|
||||
let protocols = [
|
||||
ROOT_PROTOCOL,
|
||||
NODE_PROTOCOL,
|
||||
SPATIAL_PROTOCOL,
|
||||
FIELD_PROTOCOL,
|
||||
AUDIO_PROTOCOL,
|
||||
DRAWABLE_PROTOCOL,
|
||||
INPUT_PROTOCOL,
|
||||
ITEM_PROTOCOL,
|
||||
ITEM_CAMERA_PROTOCOL,
|
||||
ITEM_PANEL_PROTOCOL,
|
||||
];
|
||||
for aspect in protocols
|
||||
.into_iter()
|
||||
.filter_map(|p| Protocol::parse(p).ok())
|
||||
.flat_map(|v| v.aspects)
|
||||
{
|
||||
aspect_map.push((aspect.id, aspect.name));
|
||||
for m in aspect.members.into_iter() {
|
||||
match m._type {
|
||||
MemberType::Signal => &mut signal_map,
|
||||
MemberType::Method => &mut method_map,
|
||||
}
|
||||
.push((m.opcode, m.name));
|
||||
}
|
||||
}
|
||||
|
||||
let aspect_id_to_name = aspect_map
|
||||
.iter()
|
||||
.map(|(id, name)| {
|
||||
quote! {
|
||||
#id => #name,
|
||||
}
|
||||
})
|
||||
.reduce(fold_tokens);
|
||||
let aspect_id_to_name_fn = quote! {
|
||||
pub const fn aspect_id_to_name(id: u64) -> &'static str {
|
||||
match id {
|
||||
#aspect_id_to_name
|
||||
_ => "Unknown"
|
||||
}
|
||||
}
|
||||
};
|
||||
let method_id_to_name = method_map
|
||||
.iter()
|
||||
.map(|(id, name)| {
|
||||
quote! {
|
||||
#id => #name,
|
||||
}
|
||||
})
|
||||
.reduce(fold_tokens);
|
||||
let method_id_to_name_fn = quote! {
|
||||
pub const fn method_id_to_name(id: u64) -> &'static str {
|
||||
match id {
|
||||
#method_id_to_name
|
||||
_ => "Unknown"
|
||||
}
|
||||
}
|
||||
};
|
||||
let signal_id_to_name = signal_map
|
||||
.iter()
|
||||
.map(|(id, name)| {
|
||||
quote! {
|
||||
#id => #name,
|
||||
}
|
||||
})
|
||||
.reduce(fold_tokens);
|
||||
let signal_id_to_name_fn = quote! {
|
||||
pub const fn signal_id_to_name(id: u64) -> &'static str {
|
||||
match id {
|
||||
#signal_id_to_name
|
||||
_ => "Unknown"
|
||||
}
|
||||
}
|
||||
};
|
||||
quote! {
|
||||
#aspect_id_to_name_fn
|
||||
#method_id_to_name_fn
|
||||
#signal_id_to_name_fn
|
||||
}.into()
|
||||
}
|
||||
|
||||
fn codegen_protocol(protocol: &'static str) -> proc_macro::TokenStream {
|
||||
let protocol = Protocol::parse(protocol).unwrap();
|
||||
let interface = protocol
|
||||
|
||||
@@ -71,9 +71,10 @@ fn yeet_entities(
|
||||
query: Query<Entity, With<TemporaryEntity>>,
|
||||
reader: Res<DestroyEntityReader>,
|
||||
) {
|
||||
query
|
||||
.iter()
|
||||
.for_each(|e| cmds.entity(e).despawn_recursive());
|
||||
query.iter().for_each(|e| {
|
||||
info!("yeeting component entities");
|
||||
cmds.entity(e).despawn_recursive();
|
||||
});
|
||||
reader
|
||||
.0
|
||||
.try_iter()
|
||||
|
||||
@@ -7,3 +7,4 @@ pub mod registry;
|
||||
pub mod resource;
|
||||
pub mod scenegraph;
|
||||
pub mod task;
|
||||
pub mod queued_mutex;
|
||||
|
||||
119
src/core/queued_mutex.rs
Normal file
119
src/core/queued_mutex.rs
Normal file
@@ -0,0 +1,119 @@
|
||||
use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
sync::atomic::Ordering,
|
||||
};
|
||||
|
||||
use parking_lot::{
|
||||
lock_api::{MutexGuard, RwLockReadGuard},
|
||||
Mutex, RawMutex, RawRwLock, RwLock,
|
||||
};
|
||||
use portable_atomic::AtomicU8;
|
||||
|
||||
pub struct QueuedMutex<T: Clone> {
|
||||
mutable: Mutex<Option<T>>,
|
||||
readers: AtomicU8,
|
||||
inner: RwLock<T>,
|
||||
}
|
||||
|
||||
impl<T: Clone + Default> Default for QueuedMutex<T> {
|
||||
fn default() -> Self {
|
||||
Self::new(T::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> QueuedMutex<T> {
|
||||
pub const fn new(value: T) -> QueuedMutex<T> {
|
||||
Self {
|
||||
mutable: Mutex::new(None),
|
||||
readers: AtomicU8::new(0),
|
||||
inner: RwLock::new(value),
|
||||
}
|
||||
}
|
||||
pub fn lock(&self) -> QueuedMutexLockGuard<'_, T> {
|
||||
let mut guard = self.mutable.lock();
|
||||
if guard.is_none() {
|
||||
guard.replace(self.inner.read().clone());
|
||||
}
|
||||
QueuedMutexLockGuard { mutex: self, guard }
|
||||
}
|
||||
pub fn read_now(&self) -> QueuedMutexReadGuard<'_, T> {
|
||||
let guard = self.inner.read();
|
||||
self.readers.add(1, Ordering::Relaxed);
|
||||
QueuedMutexReadGuard {
|
||||
mutex: self,
|
||||
guard: Some(guard),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct QueuedMutexLockGuard<'a, T: Clone> {
|
||||
mutex: &'a QueuedMutex<T>,
|
||||
guard: MutexGuard<'a, RawMutex, Option<T>>,
|
||||
}
|
||||
impl<T: Clone> Deref for QueuedMutexLockGuard<'_, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self.guard.as_ref() {
|
||||
Some(v) => v,
|
||||
None => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T: Clone> DerefMut for QueuedMutexLockGuard<'_, T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
match self.guard.as_mut() {
|
||||
Some(v) => v,
|
||||
None => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> Drop for QueuedMutexLockGuard<'_, T> {
|
||||
fn drop(&mut self) {
|
||||
if self.mutex.readers.load(Ordering::Relaxed) != 0 {
|
||||
return;
|
||||
}
|
||||
let mut write_lock = self.mutex.inner.write();
|
||||
*write_lock = match self.guard.take() {
|
||||
Some(v) => v,
|
||||
None => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct QueuedMutexReadGuard<'a, T: Clone> {
|
||||
mutex: &'a QueuedMutex<T>,
|
||||
guard: Option<RwLockReadGuard<'a, RawRwLock, T>>,
|
||||
}
|
||||
|
||||
impl<T: Clone> Deref for QueuedMutexReadGuard<'_, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self.guard.as_ref() {
|
||||
Some(v) => v,
|
||||
None => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> Drop for QueuedMutexReadGuard<'_, T> {
|
||||
fn drop(&mut self) {
|
||||
drop(self.guard.take());
|
||||
if self
|
||||
.mutex
|
||||
.readers
|
||||
.fetch_sub(1, Ordering::Relaxed)
|
||||
.wrapping_sub(1)
|
||||
!= 0
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let mut write_lock = self.mutex.inner.write();
|
||||
if let Some(v) = self.mutex.mutable.lock().take() {
|
||||
*write_lock = v
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,8 @@ use std::sync::{Arc, Weak};
|
||||
use tokio::sync::oneshot;
|
||||
use tracing::{debug, debug_span};
|
||||
|
||||
stardust_xr_server_codegen::codegen_id_to_name_functions!();
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Scenegraph {
|
||||
pub(super) client: OnceCell<Weak<Client>>,
|
||||
@@ -96,7 +98,15 @@ impl scenegraph::Scenegraph for Scenegraph {
|
||||
let Some(client) = self.get_client() else {
|
||||
return Err(ScenegraphError::NodeNotFound);
|
||||
};
|
||||
debug_span!("Handle signal", aspect_id, node_id, method).in_scope(|| {
|
||||
debug_span!(
|
||||
"Handle signal",
|
||||
aspect_id,
|
||||
aspect_name = aspect_id_to_name(aspect_id),
|
||||
node_id,
|
||||
method,
|
||||
signal_name = signal_id_to_name(method)
|
||||
)
|
||||
.in_scope(|| {
|
||||
self.get_node(node_id)
|
||||
.ok_or(ScenegraphError::NodeNotFound)?
|
||||
.send_local_signal(
|
||||
@@ -123,7 +133,14 @@ impl scenegraph::Scenegraph for Scenegraph {
|
||||
let _ = response.send(Err(ScenegraphError::NodeNotFound));
|
||||
return;
|
||||
};
|
||||
debug!(aspect_id, node_id, method, "Handle method");
|
||||
debug!(
|
||||
aspect_id,
|
||||
aspect_name = aspect_id_to_name(aspect_id),
|
||||
node_id,
|
||||
method,
|
||||
method_name = method_id_to_name(method),
|
||||
"Handle method"
|
||||
);
|
||||
let Some(node) = self.get_node(node_id) else {
|
||||
let _ = response.send(Err(ScenegraphError::NodeNotFound));
|
||||
return;
|
||||
|
||||
@@ -42,6 +42,7 @@ use bevy_mod_xr::session::{XrFirst, XrPreDestroySession, XrSessionCreated, XrSes
|
||||
use bevy_mod_xr::spaces::XrPrimaryReferenceSpace;
|
||||
use bevy_plugin::{DbusConnection, InputUpdate, StardustBevyPlugin, StardustFirst};
|
||||
use clap::Parser;
|
||||
use tracing::level_filters::LevelFilter;
|
||||
use core::client::Client;
|
||||
use core::task;
|
||||
use directories::ProjectDirs;
|
||||
@@ -198,7 +199,7 @@ async fn setup() {
|
||||
let cli_args = cli_args.clone();
|
||||
let dbus_connection = dbus_connection.clone();
|
||||
move || {
|
||||
stereokit_loop(
|
||||
bevy_loop(
|
||||
sk_ready_notifier,
|
||||
project_dirs,
|
||||
cli_args,
|
||||
@@ -228,7 +229,7 @@ async fn setup() {
|
||||
info!("Cleanly shut down Stardust");
|
||||
}
|
||||
|
||||
fn stereokit_loop(
|
||||
fn bevy_loop(
|
||||
sk_ready_notifier: Arc<Notify>,
|
||||
project_dirs: Option<ProjectDirs>,
|
||||
args: CliArgs,
|
||||
@@ -331,6 +332,7 @@ fn stereokit_loop(
|
||||
cams.iter().for_each(|e| {
|
||||
cmds.entity(e).remove::<Skybox>();
|
||||
});
|
||||
let _span = debug_span!("spawn");
|
||||
cmds.insert_resource(ClearColor(Color::NONE));
|
||||
}
|
||||
*last_hidden = env_hidden;
|
||||
@@ -392,7 +394,7 @@ fn stereokit_loop(
|
||||
|
||||
bevy_app.insert_resource(objects);
|
||||
|
||||
let bevy_step = |world: &mut World| {
|
||||
fn bevy_step(world: &mut World) {
|
||||
let _span = debug_span!("Bevy step");
|
||||
let _span = _span.enter();
|
||||
// camera::update(token);
|
||||
@@ -428,6 +430,7 @@ fn stereokit_loop(
|
||||
.run_system_cached(should_run_frame_loop)
|
||||
.unwrap_or(true)
|
||||
{
|
||||
let _span = debug_span!("eeping").entered();
|
||||
let mut waiter = world.remove_resource::<OxrFrameWaiter>().unwrap();
|
||||
let state = waiter.wait().unwrap();
|
||||
world.insert_resource(OxrFrameState(state));
|
||||
|
||||
@@ -163,18 +163,8 @@ impl Drop for Sound {
|
||||
}
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
<<<<<<< HEAD
|
||||
create_interface!(AudioInterface);
|
||||
>>>>>>> 0ec4c0f (refactor: get models fully working)
|
||||
struct AudioInterface;
|
||||
impl InterfaceAspect for AudioInterface {
|
||||
=======
|
||||
pub fn update() {}
|
||||
|
||||
impl InterfaceAspect for Interface {
|
||||
>>>>>>> 2f5c92d (refactor: get models fully working)
|
||||
#[doc = "Create a sound node. WAV and MP3 are supported."]
|
||||
fn create_sound(
|
||||
_node: Arc<Node>,
|
||||
|
||||
@@ -19,6 +19,7 @@ use glam::{Vec3, Vec3A};
|
||||
use parking_lot::Mutex;
|
||||
use prisma::Lerp;
|
||||
use std::{collections::VecDeque, sync::Arc};
|
||||
use tracing::{debug_span, info};
|
||||
|
||||
static LINES_REGISTRY: Registry<Lines> = Registry::new();
|
||||
|
||||
@@ -27,6 +28,7 @@ pub struct Lines {
|
||||
data: Mutex<Vec<Line>>,
|
||||
}
|
||||
impl Lines {
|
||||
#[tracing::instrument]
|
||||
pub fn add_to(node: &Arc<Node>, lines: Vec<Line>) -> Result<Arc<Lines>> {
|
||||
*node
|
||||
.get_aspect::<Spatial>()
|
||||
@@ -34,15 +36,15 @@ impl Lines {
|
||||
.bounding_box_calc
|
||||
.lock() = {
|
||||
if let Ok(lines) = node.get_aspect::<Lines>() {
|
||||
Aabb3d::from_point_cloud(
|
||||
Isometry3d::IDENTITY,
|
||||
Aabb3d::from_point_cloud(Isometry3d::IDENTITY, {
|
||||
let _span = debug_span!("add_to data lock").entered();
|
||||
lines
|
||||
.data
|
||||
.lock()
|
||||
.iter()
|
||||
.flat_map(|line| line.points.iter())
|
||||
.map(|point| Vec3A::from(point.point)),
|
||||
)
|
||||
.map(|point| Vec3A::from(point.point))
|
||||
})
|
||||
} else {
|
||||
Aabb3d::new(Vec3A::ZERO, Vec3A::ZERO)
|
||||
}
|
||||
@@ -59,7 +61,9 @@ impl Lines {
|
||||
|
||||
fn draw(&self, mesh: &mut Mesh, view: &GlobalTransform) -> Transform {
|
||||
let transform_mat = self.space.global_transform();
|
||||
let _span = debug_span!("draw data lock").entered();
|
||||
let data = self.data.lock().clone();
|
||||
drop(_span);
|
||||
let global_to_view = view.compute_matrix().inverse();
|
||||
let local_to_view = transform_mat.inverse() * global_to_view;
|
||||
let view_to_local = local_to_view.inverse();
|
||||
@@ -139,12 +143,11 @@ struct BevyLinePoint {
|
||||
color: Srgba,
|
||||
thickness: f32,
|
||||
}
|
||||
impl Aspect for Lines {
|
||||
const NAME: &'static str = "Lines";
|
||||
}
|
||||
impl LinesAspect for Lines {
|
||||
#[tracing::instrument]
|
||||
fn set_lines(node: Arc<Node>, _calling_client: Arc<Client>, lines: Vec<Line>) -> Result<()> {
|
||||
let lines_aspect = node.get_aspect::<Lines>()?;
|
||||
let _span = debug_span!("set_lines data lock").entered();
|
||||
*lines_aspect.data.lock() = lines;
|
||||
Ok(())
|
||||
}
|
||||
@@ -167,9 +170,23 @@ pub fn draw_all(
|
||||
..Default::default()
|
||||
};
|
||||
let mat_handle = materials.add(material);
|
||||
for lines in LINES_REGISTRY.get_valid_contents() {
|
||||
let _span = debug_span!("line registry get valid contents").entered();
|
||||
let vec = LINES_REGISTRY.get_valid_contents();
|
||||
drop(_span);
|
||||
info!("len {}", vec.len());
|
||||
for lines in vec {
|
||||
let _span = debug_span!("outer if span").entered();
|
||||
if let Some(node) = lines.space.node() {
|
||||
if node.enabled() && !lines.data.lock().is_empty() {
|
||||
let _span = debug_span!("lines_data lock").entered();
|
||||
let w = lines.data.lock().is_empty();
|
||||
drop(_span);
|
||||
let _span = debug_span!("node enabled check").entered();
|
||||
let e = node.enabled();
|
||||
drop(_span);
|
||||
let _span = debug_span!("if span").entered();
|
||||
if e && !w {
|
||||
let _span = debug_span!("create line mesh").entered();
|
||||
info!("spawning line");
|
||||
// Does this rebuild the mesh every frame? yes, is this problematic? probably,
|
||||
// would a shader work better? yes, do i care? not right now
|
||||
let mut mesh = Mesh::new(
|
||||
|
||||
@@ -336,18 +336,6 @@ fn create_model_parts_for_loaded_models(
|
||||
|
||||
*space.bounding_box_calc.lock() = Aabb3d::new(aabb.center, aabb.half_extents);
|
||||
|
||||
<<<<<<< HEAD
|
||||
let model_part = Arc::new(ModelPart {
|
||||
entity: MainWorldEntity(entity),
|
||||
path: part_path,
|
||||
space,
|
||||
model: Arc::downgrade(model),
|
||||
pending_material_parameters: Mutex::new(FxHashMap::default()),
|
||||
pending_material_replacement: Mutex::new(None),
|
||||
aliases: AliasList::default(),
|
||||
});
|
||||
node.add_aspect_raw(model_part.clone());
|
||||
=======
|
||||
let model_part = Arc::new(ModelPart {
|
||||
entity: OnceCell::from(entity),
|
||||
path: part_path,
|
||||
@@ -361,7 +349,6 @@ fn create_model_parts_for_loaded_models(
|
||||
info!("fresh {}", &model_part.path);
|
||||
model_part
|
||||
});
|
||||
>>>>>>> 0ec4c0f (refactor: get models fully working)
|
||||
parts.push(model_part.clone());
|
||||
}
|
||||
cmds.entity(entity).remove::<UnprocessedModel>();
|
||||
@@ -440,13 +427,6 @@ impl ModelAspect for Model {
|
||||
part_path: String,
|
||||
) -> Result<()> {
|
||||
let model = node.get_aspect::<Model>()?;
|
||||
<<<<<<< HEAD
|
||||
let parts = model.parts.lock();
|
||||
let Some(part) = parts.iter().find(|p| p.path == part_path) else {
|
||||
let paths = parts.iter().map(|p| &p.path).collect::<Vec<_>>();
|
||||
bail!("Couldn't find model part at path {part_path}, all available paths: {paths:?}",);
|
||||
};
|
||||
=======
|
||||
let mut parts = model.parts.lock();
|
||||
let part =
|
||||
parts
|
||||
@@ -476,7 +456,6 @@ impl ModelAspect for Model {
|
||||
parts.push(model_part.clone());
|
||||
model_part
|
||||
});
|
||||
>>>>>>> 0ec4c0f (refactor: get models fully working)
|
||||
Alias::create_with_id(
|
||||
&part.space.node().unwrap(),
|
||||
&calling_client,
|
||||
|
||||
@@ -29,6 +29,7 @@ use glam::{vec3, Mat4, Vec2, Vec3};
|
||||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::Mutex;
|
||||
use std::{ffi::OsStr, path::PathBuf, sync::Arc};
|
||||
use tracing::{info, info_span};
|
||||
|
||||
use super::{TextAspect, TextStyle};
|
||||
|
||||
@@ -68,15 +69,14 @@ fn update_text(mut surface_query: Query<(&mut Transform)>) {
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
let data = text.data.lock();
|
||||
// let data = text.data.lock();
|
||||
|
||||
*transform = Transform::from_matrix(
|
||||
text.space.global_transform()
|
||||
* Mat4::from_scale(vec3(
|
||||
data.character_height,
|
||||
data.character_height,
|
||||
data.character_height,
|
||||
)),
|
||||
text.space.global_transform(), // * Mat4::from_scale(vec3(
|
||||
// data.character_height,
|
||||
// data.character_height,
|
||||
// data.character_height,
|
||||
// )),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,10 @@ fn spawn_text(
|
||||
asset_server: Res<AssetServer>,
|
||||
) {
|
||||
for text in reader.try_iter() {
|
||||
let _span = info_span!("spawning text").entered();
|
||||
let _span2 = info_span!("text data lock").entered();
|
||||
let data = text.data.lock();
|
||||
drop(_span2);
|
||||
let size = Extent3d {
|
||||
width: (512.0 * data.bounds.as_ref().map(|v| v.bounds.x).unwrap_or(1.0)).floor() as u32,
|
||||
height: (512.0 * data.bounds.as_ref().map(|v| v.bounds.y).unwrap_or(1.0)).floor()
|
||||
@@ -168,6 +171,8 @@ fn spawn_text(
|
||||
MeshMaterial3d(mats.add(DefaultMaterial {
|
||||
base_color_texture: Some(image_handle),
|
||||
unlit: true,
|
||||
// would Cutout be enough here?
|
||||
alpha_mode: bevy::prelude::AlphaMode::Blend,
|
||||
..default()
|
||||
})),
|
||||
))
|
||||
|
||||
@@ -8,6 +8,7 @@ mod tip;
|
||||
|
||||
pub use handler::*;
|
||||
pub use method::*;
|
||||
use tracing::debug_span;
|
||||
|
||||
use super::fields::Field;
|
||||
use super::spatial::Spatial;
|
||||
@@ -140,6 +141,7 @@ pub fn process_input() {
|
||||
.clone()
|
||||
// filter out methods without the handler in their handler order
|
||||
.filter(|a| {
|
||||
let _span = debug_span!("handlder_order lock").entered();
|
||||
a.handler_order
|
||||
.lock()
|
||||
.iter()
|
||||
|
||||
@@ -10,6 +10,7 @@ pub mod spatial;
|
||||
use self::alias::Alias;
|
||||
use crate::core::client::Client;
|
||||
use crate::core::error::{Result, ServerError};
|
||||
use crate::core::queued_mutex::QueuedMutex;
|
||||
use crate::core::registry::Registry;
|
||||
use crate::core::scenegraph::MethodResponseSender;
|
||||
use parking_lot::Mutex;
|
||||
@@ -25,6 +26,7 @@ use std::fmt::Debug;
|
||||
use std::os::fd::OwnedFd;
|
||||
use std::sync::{Arc, Weak};
|
||||
use std::vec::Vec;
|
||||
use tracing::{debug_span, info};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Message {
|
||||
@@ -125,17 +127,24 @@ impl Node {
|
||||
))
|
||||
}
|
||||
pub fn enabled(&self) -> bool {
|
||||
self.enabled.load(Ordering::Relaxed)
|
||||
&& if let Ok(spatial) = self.get_aspect::<Spatial>() {
|
||||
spatial
|
||||
.global_transform()
|
||||
.to_scale_rotation_translation()
|
||||
.0
|
||||
.length_squared()
|
||||
> 0.0
|
||||
} else {
|
||||
true
|
||||
}
|
||||
let bool = {
|
||||
let _span = debug_span!("load atomic bool").entered();
|
||||
self.enabled.load(Ordering::Relaxed)
|
||||
};
|
||||
bool && if let Ok(spatial) = {
|
||||
let _span = debug_span!("get spatial aspect").entered();
|
||||
self.get_aspect::<Spatial>()
|
||||
} {
|
||||
let _span = debug_span!("check if scale is zero").entered();
|
||||
spatial
|
||||
.global_transform()
|
||||
.to_scale_rotation_translation()
|
||||
.0
|
||||
.length_squared()
|
||||
> 0.0
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
pub fn set_enabled(&self, enabled: bool) {
|
||||
self.enabled.store(enabled, Ordering::Relaxed)
|
||||
@@ -324,7 +333,7 @@ pub trait Aspect: Any + Send + Sync + 'static {
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Aspects(Mutex<FxHashMap<u64, Arc<dyn Aspect>>>);
|
||||
struct Aspects(QueuedMutex<FxHashMap<u64, Arc<dyn Aspect>>>);
|
||||
impl Aspects {
|
||||
fn add<A: AspectIdentifier>(&self, t: A) -> Arc<A> {
|
||||
let aspect = Arc::new(t);
|
||||
|
||||
@@ -38,7 +38,7 @@ use openxr::{ActionSet, Posef};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use stardust_xr::values::Datamap;
|
||||
use std::{ops::Deref, sync::Arc};
|
||||
use tracing::error;
|
||||
use tracing::{debug_span, error};
|
||||
use zbus::Connection;
|
||||
|
||||
#[derive(Default, Debug, Deserialize, Serialize)]
|
||||
@@ -236,11 +236,15 @@ fn spawn_controllers(
|
||||
HandSide::Left => "left",
|
||||
HandSide::Right => "right",
|
||||
};
|
||||
let _span = debug_span!("create SpatialRef").entered();
|
||||
let (spatial, object_handle) = SpatialRef::create(
|
||||
&connection,
|
||||
&("/org/stardustxr/Controller/".to_string() + side),
|
||||
);
|
||||
drop(_span);
|
||||
let tip = InputDataType::Tip(Tip::default());
|
||||
|
||||
let _span = debug_span!("create input method").entered();
|
||||
let Ok(input) = (|| -> color_eyre::Result<Arc<InputMethod>> {
|
||||
Ok(InputMethod::add_to(
|
||||
&spatial.node().unwrap(),
|
||||
@@ -250,6 +254,8 @@ fn spawn_controllers(
|
||||
})() else {
|
||||
continue;
|
||||
};
|
||||
drop(_span);
|
||||
let _span = debug_span!("create actions").entered();
|
||||
let actions = {
|
||||
let set = session
|
||||
.instance()
|
||||
@@ -275,6 +281,8 @@ fn spawn_controllers(
|
||||
.unwrap(),
|
||||
}
|
||||
};
|
||||
drop(_span);
|
||||
let _span = debug_span!("spawn").entered();
|
||||
cmds.spawn((
|
||||
SceneRoot(handle.clone()),
|
||||
SkController {
|
||||
|
||||
@@ -12,7 +12,10 @@ use crate::objects::{ObjectHandle, SpatialRef};
|
||||
use crate::DefaultMaterial;
|
||||
use bevy::app::{Plugin, PostUpdate};
|
||||
use bevy::asset::{AssetServer, Assets, Handle};
|
||||
use bevy::prelude::{Commands, Component, Entity, Query, Res, ResMut};
|
||||
use bevy::prelude::{
|
||||
Commands, Component, Entity, Gizmos, IntoSystemConfigs as _, Query, Res, ResMut,
|
||||
};
|
||||
use bevy::utils::default;
|
||||
use bevy_mod_openxr::helper_traits::{ToQuat, ToVec3};
|
||||
use bevy_mod_openxr::resources::OxrFrameState;
|
||||
use bevy_mod_openxr::session::OxrSession;
|
||||
@@ -41,6 +44,13 @@ impl Plugin for StardustHandPlugin {
|
||||
fn build(&self, app: &mut bevy::prelude::App) {
|
||||
app.add_systems(XrSessionCreated, create_hands);
|
||||
app.add_systems(PostUpdate, update_hands);
|
||||
app.add_systems(PostUpdate, draw_hand_gizmos.after(update_hands));
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_hand_gizmos(mut gizmos: Gizmos, query: Query<&SkHand>) {
|
||||
for hand in query.iter() {
|
||||
gizmos.axes(hand.palm_spatial.global_transform(), 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,8 +97,6 @@ fn update_hands(
|
||||
update_joint(&mut finger.intermediate, joints[finger_index + 2]);
|
||||
update_joint(&mut finger.proximal, joints[finger_index + 1]);
|
||||
update_joint(&mut finger.metacarpal, joints[finger_index]);
|
||||
// Why?
|
||||
finger.tip.radius = 0.0;
|
||||
}
|
||||
update_joint(&mut hand_input.palm, joints[HandBone::Palm as usize]);
|
||||
hand.palm_spatial
|
||||
|
||||
Reference in New Issue
Block a user