fix: make all node aspects thread safe
This commit is contained in:
@@ -17,6 +17,7 @@ mint = "0.5.9"
|
|||||||
mio = {version = "0.8.3", features = ["net", "os-poll", "os-ext"]}
|
mio = {version = "0.8.3", features = ["net", "os-poll", "os-ext"]}
|
||||||
nanoid = "0.4.0"
|
nanoid = "0.4.0"
|
||||||
parking_lot = "0.12.1"
|
parking_lot = "0.12.1"
|
||||||
|
portable-atomic = {version = "0.3.0", features = ["float", "std"]}
|
||||||
rccell = "0.1.3"
|
rccell = "0.1.3"
|
||||||
rustc-hash = "1.1.0"
|
rustc-hash = "1.1.0"
|
||||||
slab = "0.4.6"
|
slab = "0.4.6"
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ pub struct Node<'a> {
|
|||||||
destroyable: bool,
|
destroyable: bool,
|
||||||
|
|
||||||
alias: Option<Alias<'a>>,
|
alias: Option<Alias<'a>>,
|
||||||
pub spatial: Option<Rc<Spatial>>,
|
pub spatial: Option<Arc<Spatial>>,
|
||||||
pub field: Option<Rc<Field>>,
|
pub field: Option<Arc<Field>>,
|
||||||
pub pulse_sender: Option<Arc<PulseSender>>,
|
pub pulse_sender: Option<Arc<PulseSender>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,13 @@ use anyhow::{anyhow, ensure, Result};
|
|||||||
use glam::{swizzles::*, vec2, vec3, vec3a, Mat4, Vec3, Vec3A};
|
use glam::{swizzles::*, vec2, vec3, vec3a, Mat4, Vec3, Vec3A};
|
||||||
use libstardustxr::fusion::flex::FlexBuffable;
|
use libstardustxr::fusion::flex::FlexBuffable;
|
||||||
use libstardustxr::{flex_to_quat, flex_to_vec3};
|
use libstardustxr::{flex_to_quat, flex_to_vec3};
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
use portable_atomic::AtomicF32;
|
||||||
use rccell::RcCell;
|
use rccell::RcCell;
|
||||||
use std::cell::Cell;
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub trait FieldTrait {
|
pub trait FieldTrait {
|
||||||
fn local_distance(&self, p: Vec3A) -> f32;
|
fn local_distance(&self, p: Vec3A) -> f32;
|
||||||
@@ -149,8 +152,8 @@ impl Deref for Field {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct BoxField {
|
pub struct BoxField {
|
||||||
space: Rc<Spatial>,
|
space: Arc<Spatial>,
|
||||||
size: Cell<Vec3>,
|
size: Mutex<Vec3>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BoxField {
|
impl BoxField {
|
||||||
@@ -165,17 +168,17 @@ impl BoxField {
|
|||||||
);
|
);
|
||||||
let box_field = BoxField {
|
let box_field = BoxField {
|
||||||
space: node.borrow().spatial.as_ref().unwrap().clone(),
|
space: node.borrow().spatial.as_ref().unwrap().clone(),
|
||||||
size: Cell::new(size),
|
size: Mutex::new(size),
|
||||||
};
|
};
|
||||||
box_field.add_field_methods(node);
|
box_field.add_field_methods(node);
|
||||||
node.borrow_mut()
|
node.borrow_mut()
|
||||||
.add_local_signal("setSize", BoxField::set_size_flex);
|
.add_local_signal("setSize", BoxField::set_size_flex);
|
||||||
node.borrow_mut().field = Some(Rc::new(Field::Box(box_field)));
|
node.borrow_mut().field = Some(Arc::new(Field::Box(box_field)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_size(&self, size: Vec3) {
|
pub fn set_size(&self, size: Vec3) {
|
||||||
self.size.set(size);
|
*self.size.lock() = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_size_flex(node: &Node, _calling_client: Rc<Client>, data: &[u8]) -> Result<()> {
|
pub fn set_size_flex(node: &Node, _calling_client: Rc<Client>, data: &[u8]) -> Result<()> {
|
||||||
@@ -194,7 +197,7 @@ impl BoxField {
|
|||||||
|
|
||||||
impl FieldTrait for BoxField {
|
impl FieldTrait for BoxField {
|
||||||
fn local_distance(&self, p: Vec3A) -> f32 {
|
fn local_distance(&self, p: Vec3A) -> f32 {
|
||||||
let size = self.size.get();
|
let size = self.size.lock();
|
||||||
let q = vec3(
|
let q = vec3(
|
||||||
p.x.abs() - (size.x * 0.5_f32),
|
p.x.abs() - (size.x * 0.5_f32),
|
||||||
p.y.abs() - (size.y * 0.5_f32),
|
p.y.abs() - (size.y * 0.5_f32),
|
||||||
@@ -209,9 +212,9 @@ impl FieldTrait for BoxField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct CylinderField {
|
pub struct CylinderField {
|
||||||
space: Rc<Spatial>,
|
space: Arc<Spatial>,
|
||||||
length: Cell<f32>,
|
length: AtomicF32,
|
||||||
radius: Cell<f32>,
|
radius: AtomicF32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CylinderField {
|
impl CylinderField {
|
||||||
@@ -226,19 +229,19 @@ impl CylinderField {
|
|||||||
);
|
);
|
||||||
let cylinder_field = CylinderField {
|
let cylinder_field = CylinderField {
|
||||||
space: node.borrow().spatial.as_ref().unwrap().clone(),
|
space: node.borrow().spatial.as_ref().unwrap().clone(),
|
||||||
length: Cell::new(length),
|
length: AtomicF32::new(length),
|
||||||
radius: Cell::new(radius),
|
radius: AtomicF32::new(radius),
|
||||||
};
|
};
|
||||||
cylinder_field.add_field_methods(node);
|
cylinder_field.add_field_methods(node);
|
||||||
node.borrow_mut()
|
node.borrow_mut()
|
||||||
.add_local_signal("setSize", CylinderField::set_size_flex);
|
.add_local_signal("setSize", CylinderField::set_size_flex);
|
||||||
node.borrow_mut().field = Some(Rc::new(Field::Cylinder(cylinder_field)));
|
node.borrow_mut().field = Some(Arc::new(Field::Cylinder(cylinder_field)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_size(&self, length: f32, radius: f32) {
|
pub fn set_size(&self, length: f32, radius: f32) {
|
||||||
self.length.set(length);
|
self.length.store(length, Ordering::Relaxed);
|
||||||
self.radius.set(radius);
|
self.radius.store(radius, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_size_flex(node: &Node, _calling_client: Rc<Client>, data: &[u8]) -> Result<()> {
|
pub fn set_size_flex(node: &Node, _calling_client: Rc<Client>, data: &[u8]) -> Result<()> {
|
||||||
@@ -259,10 +262,8 @@ impl CylinderField {
|
|||||||
|
|
||||||
impl FieldTrait for CylinderField {
|
impl FieldTrait for CylinderField {
|
||||||
fn local_distance(&self, p: Vec3A) -> f32 {
|
fn local_distance(&self, p: Vec3A) -> f32 {
|
||||||
let d = vec2(
|
let radius = self.length.load(Ordering::Relaxed);
|
||||||
p.xy().length().abs() - self.radius.get(),
|
let d = vec2(p.xy().length().abs() - radius, p.z.abs() - (radius * 0.5));
|
||||||
p.z.abs() - (self.length.get() * 0.5),
|
|
||||||
);
|
|
||||||
|
|
||||||
d.x.max(d.y).min(0_f32)
|
d.x.max(d.y).min(0_f32)
|
||||||
+ (if d.x >= 0_f32 && d.y >= 0_f32 {
|
+ (if d.x >= 0_f32 && d.y >= 0_f32 {
|
||||||
@@ -277,8 +278,8 @@ impl FieldTrait for CylinderField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct SphereField {
|
pub struct SphereField {
|
||||||
space: Rc<Spatial>,
|
space: Arc<Spatial>,
|
||||||
radius: Cell<f32>,
|
radius: AtomicF32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SphereField {
|
impl SphereField {
|
||||||
@@ -293,17 +294,17 @@ impl SphereField {
|
|||||||
);
|
);
|
||||||
let sphere_field = SphereField {
|
let sphere_field = SphereField {
|
||||||
space: node.borrow().spatial.as_ref().unwrap().clone(),
|
space: node.borrow().spatial.as_ref().unwrap().clone(),
|
||||||
radius: Cell::new(radius),
|
radius: AtomicF32::new(radius),
|
||||||
};
|
};
|
||||||
sphere_field.add_field_methods(node);
|
sphere_field.add_field_methods(node);
|
||||||
node.borrow_mut()
|
node.borrow_mut()
|
||||||
.add_local_signal("setRadius", SphereField::set_radius_flex);
|
.add_local_signal("setRadius", SphereField::set_radius_flex);
|
||||||
node.borrow_mut().field = Some(Rc::new(Field::Sphere(sphere_field)));
|
node.borrow_mut().field = Some(Arc::new(Field::Sphere(sphere_field)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_radius(&self, radius: f32) {
|
pub fn set_radius(&self, radius: f32) {
|
||||||
self.radius.set(radius);
|
self.radius.store(radius, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_radius_flex(node: &Node, _calling_client: Rc<Client>, data: &[u8]) -> Result<()> {
|
pub fn set_radius_flex(node: &Node, _calling_client: Rc<Client>, data: &[u8]) -> Result<()> {
|
||||||
@@ -321,13 +322,13 @@ impl SphereField {
|
|||||||
|
|
||||||
impl FieldTrait for SphereField {
|
impl FieldTrait for SphereField {
|
||||||
fn local_distance(&self, p: Vec3A) -> f32 {
|
fn local_distance(&self, p: Vec3A) -> f32 {
|
||||||
p.length() - self.radius.get()
|
p.length() - self.radius.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
fn local_normal(&self, p: Vec3A, _r: f32) -> Vec3A {
|
fn local_normal(&self, p: Vec3A, _r: f32) -> Vec3A {
|
||||||
-p.normalize()
|
-p.normalize()
|
||||||
}
|
}
|
||||||
fn local_closest_point(&self, p: Vec3A, _r: f32) -> Vec3A {
|
fn local_closest_point(&self, p: Vec3A, _r: f32) -> Vec3A {
|
||||||
p.normalize() * self.radius.get()
|
p.normalize() * self.radius.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
fn spatial_ref(&self) -> &Spatial {
|
fn spatial_ref(&self) -> &Spatial {
|
||||||
self.space.as_ref()
|
self.space.as_ref()
|
||||||
|
|||||||
@@ -5,38 +5,40 @@ use glam::{Mat4, Quat, Vec3};
|
|||||||
use libstardustxr::flex::flexbuffer_from_vector_arguments;
|
use libstardustxr::flex::flexbuffer_from_vector_arguments;
|
||||||
use libstardustxr::push_to_vec;
|
use libstardustxr::push_to_vec;
|
||||||
use libstardustxr::{flex_to_quat, flex_to_vec3};
|
use libstardustxr::{flex_to_quat, flex_to_vec3};
|
||||||
|
use parking_lot::RwLock;
|
||||||
use rccell::RcCell;
|
use rccell::RcCell;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub struct Spatial {
|
pub struct Spatial {
|
||||||
// node: WeakCell<Node<'a>>,
|
// node: WeakCell<Node<'a>>,
|
||||||
parent: RefCell<Option<Rc<Spatial>>>,
|
parent: RwLock<Option<Arc<Spatial>>>,
|
||||||
transform: Cell<Mat4>,
|
transform: RwLock<Mat4>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Spatial {
|
impl Spatial {
|
||||||
pub fn add_to(
|
pub fn add_to(
|
||||||
node: &RcCell<Node>,
|
node: &RcCell<Node>,
|
||||||
parent: Option<Rc<Spatial>>,
|
parent: Option<Arc<Spatial>>,
|
||||||
transform: Mat4,
|
transform: Mat4,
|
||||||
) -> Result<Rc<Spatial>> {
|
) -> Result<Arc<Spatial>> {
|
||||||
ensure!(
|
ensure!(
|
||||||
node.borrow_mut().spatial.is_none(),
|
node.borrow_mut().spatial.is_none(),
|
||||||
"Internal: Node already has a Spatial aspect!"
|
"Internal: Node already has a Spatial aspect!"
|
||||||
);
|
);
|
||||||
let spatial = Spatial {
|
let spatial = Spatial {
|
||||||
// node: node.downgrade(),
|
// node: node.downgrade(),
|
||||||
parent: RefCell::new(parent),
|
parent: RwLock::new(parent),
|
||||||
transform: Cell::new(transform),
|
transform: RwLock::new(transform),
|
||||||
};
|
};
|
||||||
node.borrow_mut()
|
node.borrow_mut()
|
||||||
.add_local_method("getTransform", Spatial::get_transform_flex);
|
.add_local_method("getTransform", Spatial::get_transform_flex);
|
||||||
node.borrow_mut()
|
node.borrow_mut()
|
||||||
.add_local_signal("setTransform", Spatial::set_transform_flex);
|
.add_local_signal("setTransform", Spatial::set_transform_flex);
|
||||||
let spatial_rc = Rc::new(spatial);
|
let spatial_arc = Arc::new(spatial);
|
||||||
node.borrow_mut().spatial = Some(spatial_rc.clone());
|
node.borrow_mut().spatial = Some(spatial_arc.clone());
|
||||||
Ok(spatial_rc)
|
Ok(spatial_arc)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn space_to_space_matrix(from: Option<&Spatial>, to: Option<&Spatial>) -> Mat4 {
|
pub fn space_to_space_matrix(from: Option<&Spatial>, to: Option<&Spatial>) -> Mat4 {
|
||||||
@@ -46,16 +48,16 @@ impl Spatial {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn local_transform(&self) -> Mat4 {
|
pub fn local_transform(&self) -> Mat4 {
|
||||||
self.transform.get()
|
*self.transform.read()
|
||||||
}
|
}
|
||||||
pub fn global_transform(&self) -> Mat4 {
|
pub fn global_transform(&self) -> Mat4 {
|
||||||
match self.parent.borrow().clone() {
|
match self.parent.read().clone() {
|
||||||
Some(value) => value.global_transform() * self.transform.get(),
|
Some(value) => value.global_transform() * *self.transform.read(),
|
||||||
None => self.transform.get(),
|
None => *self.transform.read(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn set_local_transform(&self, transform: Mat4) {
|
pub fn set_local_transform(&self, transform: Mat4) {
|
||||||
self.transform.set(transform);
|
*self.transform.write() = transform;
|
||||||
}
|
}
|
||||||
pub fn set_local_transform_components(
|
pub fn set_local_transform_components(
|
||||||
&self,
|
&self,
|
||||||
@@ -65,7 +67,7 @@ impl Spatial {
|
|||||||
scl: Option<Vec3>,
|
scl: Option<Vec3>,
|
||||||
) {
|
) {
|
||||||
let reference_to_parent_transform =
|
let reference_to_parent_transform =
|
||||||
Spatial::space_to_space_matrix(reference_space, self.parent.borrow().as_deref());
|
Spatial::space_to_space_matrix(reference_space, self.parent.read().as_deref());
|
||||||
let mut local_transform_in_reference_space =
|
let mut local_transform_in_reference_space =
|
||||||
reference_to_parent_transform.inverse() * self.local_transform();
|
reference_to_parent_transform.inverse() * self.local_transform();
|
||||||
let (mut reference_space_scl, mut reference_space_rot, mut reference_space_pos) =
|
let (mut reference_space_scl, mut reference_space_rot, mut reference_space_pos) =
|
||||||
|
|||||||
Reference in New Issue
Block a user