refactor: use typemap for aspects!
This commit is contained in:
19
Cargo.lock
generated
19
Cargo.lock
generated
@@ -786,6 +786,24 @@ dependencies = [
|
|||||||
"pin-utils",
|
"pin-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fxhash"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fxtypemap"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c11c87c936dd5cbf3389179749cf020d886f32cc577fc214a7a65eaac5c569db"
|
||||||
|
dependencies = [
|
||||||
|
"fxhash",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generator"
|
name = "generator"
|
||||||
version = "0.7.5"
|
version = "0.7.5"
|
||||||
@@ -2108,6 +2126,7 @@ dependencies = [
|
|||||||
"console-subscriber",
|
"console-subscriber",
|
||||||
"ctrlc",
|
"ctrlc",
|
||||||
"directories",
|
"directories",
|
||||||
|
"fxtypemap",
|
||||||
"glam 0.23.0",
|
"glam 0.23.0",
|
||||||
"global_counter",
|
"global_counter",
|
||||||
"input-event-codes",
|
"input-event-codes",
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ nix = "0.27.1"
|
|||||||
wayland-scanner = "0.31.0"
|
wayland-scanner = "0.31.0"
|
||||||
wayland-backend = "0.3.2"
|
wayland-backend = "0.3.2"
|
||||||
cluFlock = "1.2.7"
|
cluFlock = "1.2.7"
|
||||||
|
fxtypemap = "0.2.0"
|
||||||
|
|
||||||
[dependencies.smithay]
|
[dependencies.smithay]
|
||||||
# git = "https://github.com/technobaboo/smithay.git" # Until we get stereokit to understand OES samplers and external textures
|
# git = "https://github.com/technobaboo/smithay.git" # Until we get stereokit to understand OES samplers and external textures
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use super::{
|
use super::{
|
||||||
client_state::{ClientState, CLIENT_STATES},
|
client_state::{ClientState, CLIENT_STATES},
|
||||||
|
destroy_queue,
|
||||||
scenegraph::Scenegraph,
|
scenegraph::Scenegraph,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -209,7 +210,9 @@ impl Client {
|
|||||||
if let Some(flush_join_handle) = self.flush_join_handle.get() {
|
if let Some(flush_join_handle) = self.flush_join_handle.get() {
|
||||||
flush_join_handle.abort();
|
flush_join_handle.abort();
|
||||||
}
|
}
|
||||||
CLIENTS.remove(self);
|
if let Some(client) = CLIENTS.remove(self) {
|
||||||
|
destroy_queue::add(client);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Drop for Client {
|
impl Drop for Client {
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ impl ClientState {
|
|||||||
}
|
}
|
||||||
fn spatial_transform(client: &Client, path: &str) -> Option<Mat4> {
|
fn spatial_transform(client: &Client, path: &str) -> Option<Mat4> {
|
||||||
let node = client.scenegraph.get_node(path)?;
|
let node = client.scenegraph.get_node(path)?;
|
||||||
let spatial = node.spatial.get()?;
|
let spatial = node.get_aspect::<Spatial>().ok()?;
|
||||||
Some(spatial.global_transform())
|
Some(spatial.global_transform())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ impl ClientState {
|
|||||||
let node = Node::create_parent_name(client, "/spatial/anchor", k, true)
|
let node = Node::create_parent_name(client, "/spatial/anchor", k, true)
|
||||||
.add_to_scenegraph()
|
.add_to_scenegraph()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Spatial::add_to(&node, None, *v, false).unwrap();
|
Spatial::add_to(&node, None, *v, false);
|
||||||
k.clone()
|
k.clone()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,12 +1,22 @@
|
|||||||
|
use once_cell::sync::Lazy;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
use tokio::sync::mpsc::{self, unbounded_channel};
|
||||||
|
|
||||||
static MAIN_DESTROY_QUEUE: Mutex<Vec<Box<dyn Any + Send + Sync>>> = Mutex::new(Vec::new());
|
static MAIN_DESTROY_QUEUE: Lazy<(
|
||||||
|
mpsc::UnboundedSender<Box<dyn Any + Send + Sync>>,
|
||||||
|
Mutex<mpsc::UnboundedReceiver<Box<dyn Any + Send + Sync>>>,
|
||||||
|
)> = Lazy::new(|| {
|
||||||
|
let (tx, rx) = unbounded_channel();
|
||||||
|
(tx, Mutex::new(rx))
|
||||||
|
});
|
||||||
|
|
||||||
pub fn add<T: Any + Sync + Send>(thing: T) {
|
pub fn add<T: Any + Sync + Send>(thing: T) {
|
||||||
MAIN_DESTROY_QUEUE.lock().push(Box::new(thing));
|
MAIN_DESTROY_QUEUE.0.send(Box::new(thing)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear() {
|
pub fn clear() {
|
||||||
MAIN_DESTROY_QUEUE.lock().clear();
|
while let Ok(thing) = MAIN_DESTROY_QUEUE.1.lock().try_recv() {
|
||||||
|
drop(thing)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use rustc_hash::FxHashMap;
|
|||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Registry<T: Send + Sync + ?Sized>(Mutex<Option<FxHashMap<usize, Weak<T>>>>);
|
pub struct Registry<T: Send + Sync + ?Sized>(Mutex<Option<FxHashMap<usize, Weak<T>>>>);
|
||||||
|
|
||||||
impl<T: Send + Sync + ?Sized> Registry<T> {
|
impl<T: Send + Sync + ?Sized> Registry<T> {
|
||||||
@@ -56,7 +57,9 @@ impl<T: Send + Sync + ?Sized> Registry<T> {
|
|||||||
}
|
}
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
let registry = self.0.lock();
|
let registry = self.0.lock();
|
||||||
let Some(registry) = &*registry else {return true};
|
let Some(registry) = &*registry else {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
if registry.is_empty() {
|
if registry.is_empty() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -68,6 +71,11 @@ impl<T: Send + Sync + ?Sized> Clone for Registry<T> {
|
|||||||
Self(Mutex::new(self.0.lock().clone()))
|
Self(Mutex::new(self.0.lock().clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<T: Send + Sync + ?Sized> Default for Registry<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct OwnedRegistry<T: Send + Sync + ?Sized>(Mutex<Option<FxHashMap<usize, Arc<T>>>>);
|
pub struct OwnedRegistry<T: Send + Sync + ?Sized>(Mutex<Option<FxHashMap<usize, Arc<T>>>>);
|
||||||
|
|
||||||
@@ -98,9 +106,12 @@ impl<T: Send + Sync + ?Sized> OwnedRegistry<T> {
|
|||||||
self.lock()
|
self.lock()
|
||||||
.contains_key(&(ptr::addr_of!(*t) as *const () as usize))
|
.contains_key(&(ptr::addr_of!(*t) as *const () as usize))
|
||||||
}
|
}
|
||||||
pub fn remove(&self, t: &T) {
|
pub fn remove(&self, t: &T) -> Option<Arc<T>>
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
self.lock()
|
self.lock()
|
||||||
.remove(&(ptr::addr_of!(*t) as *const () as usize));
|
.remove(&(ptr::addr_of!(*t) as *const () as usize))
|
||||||
}
|
}
|
||||||
pub fn clear(&self) {
|
pub fn clear(&self) {
|
||||||
self.lock().clear();
|
self.lock().clear();
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::nodes::alias::Alias;
|
||||||
use crate::nodes::Node;
|
use crate::nodes::Node;
|
||||||
use crate::{core::client::Client, nodes::Message};
|
use crate::{core::client::Client, nodes::Message};
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
@@ -39,7 +40,7 @@ impl Scenegraph {
|
|||||||
|
|
||||||
pub fn get_node(&self, path: &str) -> Option<Arc<Node>> {
|
pub fn get_node(&self, path: &str) -> Option<Arc<Node>> {
|
||||||
let mut node = self.nodes.lock().get(path)?.clone();
|
let mut node = self.nodes.lock().get(path)?.clone();
|
||||||
while let Some(alias) = node.alias.get() {
|
while let Ok(alias) = node.get_aspect::<Alias>() {
|
||||||
if alias.enabled.load(Ordering::Acquire) {
|
if alias.enabled.load(Ordering::Acquire) {
|
||||||
node = alias.original.upgrade()?;
|
node = alias.original.upgrade()?;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use super::Node;
|
use super::{Aspect, Node};
|
||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
use color_eyre::eyre::{ensure, Result};
|
use color_eyre::eyre::{ensure, Result};
|
||||||
use portable_atomic::AtomicBool;
|
use portable_atomic::AtomicBool;
|
||||||
@@ -43,7 +43,10 @@ impl Alias {
|
|||||||
info,
|
info,
|
||||||
};
|
};
|
||||||
let alias = original.aliases.add(alias);
|
let alias = original.aliases.add(alias);
|
||||||
let _ = node.alias.set(alias);
|
node.add_aspect_raw(alias);
|
||||||
Ok(node)
|
Ok(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Aspect for Alias {
|
||||||
|
const NAME: &'static str = "Alias";
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
use super::spatial::get_spatial;
|
use super::{Aspect, Node};
|
||||||
use super::Node;
|
|
||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
use crate::core::destroy_queue;
|
use crate::core::destroy_queue;
|
||||||
use crate::core::registry::Registry;
|
use crate::core::registry::Registry;
|
||||||
use crate::core::resource::get_resource_file;
|
use crate::core::resource::get_resource_file;
|
||||||
use crate::create_interface;
|
use crate::create_interface;
|
||||||
use crate::nodes::spatial::{Spatial, Transform};
|
use crate::nodes::spatial::{Spatial, Transform};
|
||||||
use color_eyre::eyre::{ensure, eyre, Result};
|
use color_eyre::eyre::{eyre, Result};
|
||||||
use glam::{vec3, Vec4Swizzles};
|
use glam::{vec3, Vec4Swizzles};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
@@ -33,10 +32,6 @@ pub struct Sound {
|
|||||||
}
|
}
|
||||||
impl Sound {
|
impl Sound {
|
||||||
pub fn add_to(node: &Arc<Node>, resource_id: ResourceID) -> Result<Arc<Sound>> {
|
pub fn add_to(node: &Arc<Node>, resource_id: ResourceID) -> Result<Arc<Sound>> {
|
||||||
ensure!(
|
|
||||||
node.spatial.get().is_some(),
|
|
||||||
"Internal: Node does not have a spatial attached!"
|
|
||||||
);
|
|
||||||
let pending_audio_path = get_resource_file(
|
let pending_audio_path = get_resource_file(
|
||||||
&resource_id,
|
&resource_id,
|
||||||
&*node.get_client().ok_or_else(|| eyre!("Client not found"))?,
|
&*node.get_client().ok_or_else(|| eyre!("Client not found"))?,
|
||||||
@@ -44,7 +39,7 @@ impl Sound {
|
|||||||
)
|
)
|
||||||
.ok_or_else(|| eyre!("Resource not found"))?;
|
.ok_or_else(|| eyre!("Resource not found"))?;
|
||||||
let sound = Sound {
|
let sound = Sound {
|
||||||
space: node.spatial.get().unwrap().clone(),
|
space: node.get_aspect::<Spatial>().unwrap().clone(),
|
||||||
volume: 1.0,
|
volume: 1.0,
|
||||||
pending_audio_path,
|
pending_audio_path,
|
||||||
sk_sound: OnceCell::new(),
|
sk_sound: OnceCell::new(),
|
||||||
@@ -53,7 +48,7 @@ impl Sound {
|
|||||||
play: Mutex::new(None),
|
play: Mutex::new(None),
|
||||||
};
|
};
|
||||||
let sound_arc = SOUND_REGISTRY.add(sound);
|
let sound_arc = SOUND_REGISTRY.add(sound);
|
||||||
let _ = node.sound.set(sound_arc.clone());
|
node.add_aspect_raw(sound_arc.clone());
|
||||||
<Sound as SoundAspect>::add_node_members(node);
|
<Sound as SoundAspect>::add_node_members(node);
|
||||||
Ok(sound_arc)
|
Ok(sound_arc)
|
||||||
}
|
}
|
||||||
@@ -79,14 +74,17 @@ impl Sound {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Aspect for Sound {
|
||||||
|
const NAME: &'static str = "Sound";
|
||||||
|
}
|
||||||
impl SoundAspect for Sound {
|
impl SoundAspect for Sound {
|
||||||
fn play(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<()> {
|
fn play(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<()> {
|
||||||
let sound = node.sound.get().unwrap();
|
let sound = node.get_aspect::<Sound>().unwrap();
|
||||||
sound.play.lock().replace(());
|
sound.play.lock().replace(());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn stop(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<()> {
|
fn stop(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<()> {
|
||||||
let sound = node.sound.get().unwrap();
|
let sound = node.get_aspect::<Sound>().unwrap();
|
||||||
sound.stop.lock().replace(());
|
sound.stop.lock().replace(());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -120,10 +118,10 @@ impl AudioInterfaceAspect for AudioInterface {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let node =
|
let node =
|
||||||
Node::create_parent_name(&calling_client, Self::CREATE_SOUND_PARENT_PATH, &name, true);
|
Node::create_parent_name(&calling_client, Self::CREATE_SOUND_PARENT_PATH, &name, true);
|
||||||
let parent = get_spatial(&parent, "Spatial parent")?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = transform.to_mat4(true, true, true);
|
let transform = transform.to_mat4(true, true, true);
|
||||||
let node = node.add_to_scenegraph()?;
|
let node = node.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, Some(parent), transform, false)?;
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
Sound::add_to(&node, resource)?;
|
Sound::add_to(&node, resource)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use super::alias::AliasInfo;
|
use super::alias::AliasInfo;
|
||||||
use super::fields::get_field;
|
use super::fields::Field;
|
||||||
use super::spatial::{get_spatial, parse_transform, Spatial};
|
use super::spatial::{parse_transform, Spatial};
|
||||||
use super::{Alias, Node};
|
use super::{Alias, Aspect, Node};
|
||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
use crate::core::node_collections::LifeLinkedNodeMap;
|
use crate::core::node_collections::LifeLinkedNodeMap;
|
||||||
use crate::core::registry::Registry;
|
use crate::core::registry::Registry;
|
||||||
@@ -62,11 +62,6 @@ pub struct PulseSender {
|
|||||||
}
|
}
|
||||||
impl PulseSender {
|
impl PulseSender {
|
||||||
pub fn add_to(node: &Arc<Node>, mask: Datamap) -> Result<Arc<PulseSender>> {
|
pub fn add_to(node: &Arc<Node>, mask: Datamap) -> Result<Arc<PulseSender>> {
|
||||||
ensure!(
|
|
||||||
node.spatial.get().is_some(),
|
|
||||||
"Internal: Node does not have a spatial attached!"
|
|
||||||
);
|
|
||||||
|
|
||||||
let sender = PulseSender {
|
let sender = PulseSender {
|
||||||
node: Arc::downgrade(node),
|
node: Arc::downgrade(node),
|
||||||
mask,
|
mask,
|
||||||
@@ -75,7 +70,7 @@ impl PulseSender {
|
|||||||
|
|
||||||
// <PulseSender as PulseSenderAspect>::add_node_members(node);
|
// <PulseSender as PulseSenderAspect>::add_node_members(node);
|
||||||
let sender = PULSE_SENDER_REGISTRY.add(sender);
|
let sender = PULSE_SENDER_REGISTRY.add(sender);
|
||||||
let _ = node.pulse_sender.set(sender.clone());
|
node.add_aspect_raw(sender.clone());
|
||||||
for receiver in PULSE_RECEIVER_REGISTRY.get_valid_contents() {
|
for receiver in PULSE_RECEIVER_REGISTRY.get_valid_contents() {
|
||||||
sender.handle_new_receiver(&receiver);
|
sender.handle_new_receiver(&receiver);
|
||||||
}
|
}
|
||||||
@@ -114,7 +109,7 @@ impl PulseSender {
|
|||||||
&tx_client,
|
&tx_client,
|
||||||
rx_alias.get_path(),
|
rx_alias.get_path(),
|
||||||
"field",
|
"field",
|
||||||
&rx_node.pulse_receiver.get().unwrap().field_node,
|
&rx_node.get_aspect::<PulseReceiver>().unwrap().field_node,
|
||||||
FIELD_ALIAS_INFO.clone(),
|
FIELD_ALIAS_INFO.clone(),
|
||||||
) else {
|
) else {
|
||||||
return;
|
return;
|
||||||
@@ -136,6 +131,9 @@ impl PulseSender {
|
|||||||
let _ = pulse_sender_client::drop_receiver(&tx_node, uid);
|
let _ = pulse_sender_client::drop_receiver(&tx_node, uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Aspect for PulseSender {
|
||||||
|
const NAME: &'static str = "PulseSender";
|
||||||
|
}
|
||||||
impl PulseSenderAspect for PulseSender {}
|
impl PulseSenderAspect for PulseSender {}
|
||||||
impl Drop for PulseSender {
|
impl Drop for PulseSender {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
@@ -155,11 +153,6 @@ impl PulseReceiver {
|
|||||||
field_node: Arc<Node>,
|
field_node: Arc<Node>,
|
||||||
mask: Datamap,
|
mask: Datamap,
|
||||||
) -> Result<Arc<PulseReceiver>> {
|
) -> Result<Arc<PulseReceiver>> {
|
||||||
ensure!(
|
|
||||||
node.spatial.get().is_some(),
|
|
||||||
"Internal: Node does not have a spatial attached!"
|
|
||||||
);
|
|
||||||
|
|
||||||
let receiver = PulseReceiver {
|
let receiver = PulseReceiver {
|
||||||
uid: nanoid!(),
|
uid: nanoid!(),
|
||||||
node: Arc::downgrade(node),
|
node: Arc::downgrade(node),
|
||||||
@@ -169,13 +162,16 @@ impl PulseReceiver {
|
|||||||
let receiver = PULSE_RECEIVER_REGISTRY.add(receiver);
|
let receiver = PULSE_RECEIVER_REGISTRY.add(receiver);
|
||||||
|
|
||||||
<PulseReceiver as PulseReceiverAspect>::add_node_members(node);
|
<PulseReceiver as PulseReceiverAspect>::add_node_members(node);
|
||||||
let _ = node.pulse_receiver.set(receiver.clone());
|
node.add_aspect_raw(receiver.clone());
|
||||||
for sender in PULSE_SENDER_REGISTRY.get_valid_contents() {
|
for sender in PULSE_SENDER_REGISTRY.get_valid_contents() {
|
||||||
sender.handle_new_receiver(&receiver);
|
sender.handle_new_receiver(&receiver);
|
||||||
}
|
}
|
||||||
Ok(receiver)
|
Ok(receiver)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Aspect for PulseReceiver {
|
||||||
|
const NAME: &'static str = "PulseReceiver";
|
||||||
|
}
|
||||||
impl PulseReceiverAspect for PulseReceiver {
|
impl PulseReceiverAspect for PulseReceiver {
|
||||||
fn send_data(
|
fn send_data(
|
||||||
node: Arc<Node>,
|
node: Arc<Node>,
|
||||||
@@ -183,7 +179,7 @@ impl PulseReceiverAspect for PulseReceiver {
|
|||||||
sender: Arc<Node>,
|
sender: Arc<Node>,
|
||||||
data: Datamap,
|
data: Datamap,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let this_receiver = node.pulse_receiver.get().unwrap();
|
let this_receiver = node.get_aspect::<PulseReceiver>().unwrap();
|
||||||
|
|
||||||
ensure!(
|
ensure!(
|
||||||
mask_matches(&this_receiver.mask, &data),
|
mask_matches(&this_receiver.mask, &data),
|
||||||
@@ -221,11 +217,11 @@ impl DataInterfaceAspect for DataInterface {
|
|||||||
&name,
|
&name,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
let parent = get_spatial(&parent, "Spatial parent")?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = transform.to_mat4(true, true, false);
|
let transform = transform.to_mat4(true, true, false);
|
||||||
|
|
||||||
let node = node.add_to_scenegraph()?;
|
let node = node.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, Some(parent), transform, false)?;
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
PulseSender::add_to(&node, mask)?;
|
PulseSender::add_to(&node, mask)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -246,12 +242,12 @@ impl DataInterfaceAspect for DataInterface {
|
|||||||
&name,
|
&name,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
let parent = get_spatial(&parent, "Spatial parent")?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = parse_transform(transform, true, true, false);
|
let transform = parse_transform(transform, true, true, false);
|
||||||
get_field(&field)?;
|
let _ = field.get_aspect::<Field>()?;
|
||||||
|
|
||||||
let node = node.add_to_scenegraph()?;
|
let node = node.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, Some(parent), transform, false)?;
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
PulseReceiver::add_to(&node, field, mask)?;
|
PulseReceiver::add_to(&node, field, mask)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use super::{Drawable, Line, LinesAspect};
|
use super::{Line, LinesAspect};
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{client::Client, registry::Registry},
|
core::{client::Client, registry::Registry},
|
||||||
nodes::{spatial::Spatial, Node},
|
nodes::{spatial::Spatial, Aspect, Node},
|
||||||
};
|
};
|
||||||
use color_eyre::eyre::{bail, ensure, Result};
|
use color_eyre::eyre::Result;
|
||||||
use glam::Vec3A;
|
use glam::Vec3A;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use portable_atomic::{AtomicBool, Ordering};
|
use portable_atomic::{AtomicBool, Ordering};
|
||||||
@@ -20,31 +20,29 @@ pub struct Lines {
|
|||||||
}
|
}
|
||||||
impl Lines {
|
impl Lines {
|
||||||
pub fn add_to(node: &Arc<Node>, lines: Vec<Line>) -> Result<Arc<Lines>> {
|
pub fn add_to(node: &Arc<Node>, lines: Vec<Line>) -> Result<Arc<Lines>> {
|
||||||
ensure!(
|
let _ = node
|
||||||
node.drawable.get().is_none(),
|
.get_aspect::<Spatial>()
|
||||||
"Internal: Node already has a drawable attached!"
|
.unwrap()
|
||||||
);
|
.bounding_box_calc
|
||||||
|
.set(|node| {
|
||||||
let _ = node.spatial.get().unwrap().bounding_box_calc.set(|node| {
|
|
||||||
let mut bounds = Bounds::default();
|
let mut bounds = Bounds::default();
|
||||||
let Some(Drawable::Lines(lines)) = node.drawable.get() else {
|
if let Ok(lines) = node.get_aspect::<Lines>() {
|
||||||
return bounds;
|
|
||||||
};
|
|
||||||
for line in &*lines.data.lock() {
|
for line in &*lines.data.lock() {
|
||||||
for point in &line.points {
|
for point in &line.points {
|
||||||
bounds = bounds_grow_to_fit_pt(bounds, point.point);
|
bounds = bounds_grow_to_fit_pt(bounds, point.point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
bounds
|
bounds
|
||||||
});
|
});
|
||||||
|
|
||||||
let lines = LINES_REGISTRY.add(Lines {
|
let lines = LINES_REGISTRY.add(Lines {
|
||||||
enabled: node.enabled.clone(),
|
enabled: node.enabled.clone(),
|
||||||
space: node.get_aspect("Lines", "spatial", |n| &n.spatial)?.clone(),
|
space: node.get_aspect::<Spatial>()?.clone(),
|
||||||
data: Mutex::new(lines),
|
data: Mutex::new(lines),
|
||||||
});
|
});
|
||||||
<Lines as LinesAspect>::add_node_members(node);
|
<Lines as LinesAspect>::add_node_members(node);
|
||||||
let _ = node.drawable.set(Drawable::Lines(lines.clone()));
|
node.add_aspect_raw(lines.clone());
|
||||||
|
|
||||||
Ok(lines)
|
Ok(lines)
|
||||||
}
|
}
|
||||||
@@ -94,12 +92,12 @@ impl Lines {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Aspect for Lines {
|
||||||
|
const NAME: &'static str = "Lines";
|
||||||
|
}
|
||||||
impl LinesAspect for Lines {
|
impl LinesAspect for Lines {
|
||||||
fn set_lines(node: Arc<Node>, _calling_client: Arc<Client>, lines: Vec<Line>) -> Result<()> {
|
fn set_lines(node: Arc<Node>, _calling_client: Arc<Client>, lines: Vec<Line>) -> Result<()> {
|
||||||
let Some(Drawable::Lines(lines_aspect)) = node.drawable.get() else {
|
let lines_aspect = node.get_aspect::<Lines>()?;
|
||||||
bail!("Not a drawable??")
|
|
||||||
};
|
|
||||||
|
|
||||||
*lines_aspect.data.lock() = lines;
|
*lines_aspect.data.lock() = lines;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,9 @@ pub mod model;
|
|||||||
pub mod shaders;
|
pub mod shaders;
|
||||||
pub mod text;
|
pub mod text;
|
||||||
|
|
||||||
use self::{
|
use self::{lines::Lines, model::Model, text::Text};
|
||||||
lines::Lines,
|
|
||||||
model::{Model, ModelPart},
|
|
||||||
text::Text,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
spatial::{get_spatial, Spatial, Transform},
|
spatial::{Spatial, Transform},
|
||||||
Node,
|
Node,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -23,13 +18,6 @@ use stardust_xr::values::ResourceID;
|
|||||||
use std::{ffi::OsStr, path::PathBuf, sync::Arc};
|
use std::{ffi::OsStr, path::PathBuf, sync::Arc};
|
||||||
use stereokit::StereoKitDraw;
|
use stereokit::StereoKitDraw;
|
||||||
|
|
||||||
pub enum Drawable {
|
|
||||||
Lines(Arc<Lines>),
|
|
||||||
Model(Arc<Model>),
|
|
||||||
ModelPart(Arc<ModelPart>),
|
|
||||||
Text(Arc<Text>),
|
|
||||||
}
|
|
||||||
|
|
||||||
// #[instrument(level = "debug", skip(sk))]
|
// #[instrument(level = "debug", skip(sk))]
|
||||||
pub fn draw(sk: &impl StereoKitDraw) {
|
pub fn draw(sk: &impl StereoKitDraw) {
|
||||||
lines::draw_all(sk);
|
lines::draw_all(sk);
|
||||||
@@ -87,11 +75,11 @@ impl DrawableInterfaceAspect for DrawableInterface {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let node =
|
let node =
|
||||||
Node::create_parent_name(&calling_client, Self::CREATE_LINES_PARENT_PATH, &name, true);
|
Node::create_parent_name(&calling_client, Self::CREATE_LINES_PARENT_PATH, &name, true);
|
||||||
let parent = get_spatial(&parent, "Spatial parent")?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = transform.to_mat4(true, true, true);
|
let transform = transform.to_mat4(true, true, true);
|
||||||
|
|
||||||
let node = node.add_to_scenegraph()?;
|
let node = node.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, Some(parent), transform, false)?;
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
Lines::add_to(&node, lines)?;
|
Lines::add_to(&node, lines)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -107,10 +95,10 @@ impl DrawableInterfaceAspect for DrawableInterface {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let node =
|
let node =
|
||||||
Node::create_parent_name(&calling_client, Self::LOAD_MODEL_PARENT_PATH, &name, true);
|
Node::create_parent_name(&calling_client, Self::LOAD_MODEL_PARENT_PATH, &name, true);
|
||||||
let parent = get_spatial(&parent, "Spatial parent")?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = transform.to_mat4(true, true, true);
|
let transform = transform.to_mat4(true, true, true);
|
||||||
let node = node.add_to_scenegraph()?;
|
let node = node.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, Some(parent), transform, false)?;
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
Model::add_to(&node, model)?;
|
Model::add_to(&node, model)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -127,11 +115,11 @@ impl DrawableInterfaceAspect for DrawableInterface {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let node =
|
let node =
|
||||||
Node::create_parent_name(&calling_client, Self::CREATE_TEXT_PARENT_PATH, &name, true);
|
Node::create_parent_name(&calling_client, Self::CREATE_TEXT_PARENT_PATH, &name, true);
|
||||||
let parent = get_spatial(&parent, "Spatial parent")?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = transform.to_mat4(true, true, true);
|
let transform = transform.to_mat4(true, true, true);
|
||||||
|
|
||||||
let node = node.add_to_scenegraph()?;
|
let node = node.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, Some(parent), transform, false)?;
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
Text::add_to(&node, text, style)?;
|
Text::add_to(&node, text, style)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ use crate::core::destroy_queue;
|
|||||||
use crate::core::node_collections::LifeLinkedNodeMap;
|
use crate::core::node_collections::LifeLinkedNodeMap;
|
||||||
use crate::core::registry::Registry;
|
use crate::core::registry::Registry;
|
||||||
use crate::core::resource::get_resource_file;
|
use crate::core::resource::get_resource_file;
|
||||||
use crate::nodes::drawable::Drawable;
|
|
||||||
use crate::nodes::spatial::Spatial;
|
use crate::nodes::spatial::Spatial;
|
||||||
|
use crate::nodes::Aspect;
|
||||||
use crate::SK_MULTITHREAD;
|
use crate::SK_MULTITHREAD;
|
||||||
use color_eyre::eyre::{bail, ensure, eyre, Result};
|
use color_eyre::eyre::{eyre, Result};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use portable_atomic::{AtomicBool, Ordering};
|
use portable_atomic::{AtomicBool, Ordering};
|
||||||
@@ -133,10 +133,7 @@ impl ModelPart {
|
|||||||
.and_then(|id| model.parts.get(&id));
|
.and_then(|id| model.parts.get(&id));
|
||||||
let parent_part = parent_node
|
let parent_part = parent_node
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|node| match node.drawable.get() {
|
.and_then(|node| node.get_aspect::<ModelPart>().ok());
|
||||||
Some(Drawable::ModelPart(model_part)) => Some(model_part),
|
|
||||||
_ => None,
|
|
||||||
});
|
|
||||||
|
|
||||||
let stardust_model_part = model.space.node()?;
|
let stardust_model_part = model.space.node()?;
|
||||||
let client = stardust_model_part.get_client()?;
|
let client = stardust_model_part.get_client()?;
|
||||||
@@ -149,18 +146,21 @@ impl ModelPart {
|
|||||||
false,
|
false,
|
||||||
));
|
));
|
||||||
let spatial_parent = parent_node
|
let spatial_parent = parent_node
|
||||||
.and_then(|n| n.spatial.get().cloned())
|
.and_then(|n| n.get_aspect::<Spatial>().ok())
|
||||||
.unwrap_or_else(|| model.space.clone());
|
.unwrap_or_else(|| model.space.clone());
|
||||||
let space = Spatial::add_to(
|
let space = Spatial::add_to(
|
||||||
&node,
|
&node,
|
||||||
Some(spatial_parent),
|
Some(spatial_parent),
|
||||||
sk.model_node_get_transform_local(sk_model, id),
|
sk.model_node_get_transform_local(sk_model, id),
|
||||||
false,
|
false,
|
||||||
)
|
);
|
||||||
.ok()?;
|
|
||||||
|
|
||||||
let _ = node.spatial.get().unwrap().bounding_box_calc.set(|node| {
|
let _ = node
|
||||||
let Some(Drawable::ModelPart(model_part)) = node.drawable.get() else {
|
.get_aspect::<Spatial>()
|
||||||
|
.unwrap()
|
||||||
|
.bounding_box_calc
|
||||||
|
.set(|node| {
|
||||||
|
let Ok(model_part) = node.get_aspect::<ModelPart>() else {
|
||||||
return Bounds::default();
|
return Bounds::default();
|
||||||
};
|
};
|
||||||
let Some(sk) = SK_MULTITHREAD.get() else {
|
let Some(sk) = SK_MULTITHREAD.get() else {
|
||||||
@@ -187,7 +187,7 @@ impl ModelPart {
|
|||||||
pending_material_replacement: Mutex::new(None),
|
pending_material_replacement: Mutex::new(None),
|
||||||
});
|
});
|
||||||
<ModelPart as ModelPartAspect>::add_node_members(&node);
|
<ModelPart as ModelPartAspect>::add_node_members(&node);
|
||||||
let _ = node.drawable.set(Drawable::ModelPart(model_part.clone()));
|
node.add_aspect_raw(model_part.clone());
|
||||||
model.parts.add(id, &node);
|
model.parts.add(id, &node);
|
||||||
Some(model_part)
|
Some(model_part)
|
||||||
}
|
}
|
||||||
@@ -232,12 +232,13 @@ impl ModelPart {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Aspect for ModelPart {
|
||||||
|
const NAME: &'static str = "ModelPart";
|
||||||
|
}
|
||||||
impl ModelPartAspect for ModelPart {
|
impl ModelPartAspect for ModelPart {
|
||||||
#[doc = "Set this model part's material to one that cuts a hole in the world. Often used for overlays/passthrough where you want to show the background through an object."]
|
#[doc = "Set this model part's material to one that cuts a hole in the world. Often used for overlays/passthrough where you want to show the background through an object."]
|
||||||
fn apply_holdout_material(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<()> {
|
fn apply_holdout_material(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<()> {
|
||||||
let Some(Drawable::ModelPart(model_part)) = node.drawable.get() else {
|
let model_part = node.get_aspect::<ModelPart>()?;
|
||||||
bail!("Not a drawable??")
|
|
||||||
};
|
|
||||||
model_part.replace_material(HOLDOUT_MATERIAL.get().unwrap().clone());
|
model_part.replace_material(HOLDOUT_MATERIAL.get().unwrap().clone());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -249,10 +250,7 @@ impl ModelPartAspect for ModelPart {
|
|||||||
parameter_name: String,
|
parameter_name: String,
|
||||||
value: MaterialParameter,
|
value: MaterialParameter,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let Some(Drawable::ModelPart(model_part)) = node.drawable.get() else {
|
let model_part = node.get_aspect::<ModelPart>()?;
|
||||||
bail!("Not a drawable??")
|
|
||||||
};
|
|
||||||
|
|
||||||
model_part
|
model_part
|
||||||
.pending_material_parameters
|
.pending_material_parameters
|
||||||
.lock()
|
.lock()
|
||||||
@@ -275,15 +273,6 @@ unsafe impl Sync for Model {}
|
|||||||
|
|
||||||
impl Model {
|
impl Model {
|
||||||
pub fn add_to(node: &Arc<Node>, resource_id: ResourceID) -> Result<Arc<Model>> {
|
pub fn add_to(node: &Arc<Node>, resource_id: ResourceID) -> Result<Arc<Model>> {
|
||||||
ensure!(
|
|
||||||
node.spatial.get().is_some(),
|
|
||||||
"Internal: Node does not have a spatial attached!"
|
|
||||||
);
|
|
||||||
ensure!(
|
|
||||||
node.drawable.get().is_none(),
|
|
||||||
"Internal: Node already has a drawable attached!"
|
|
||||||
);
|
|
||||||
|
|
||||||
let pending_model_path = get_resource_file(
|
let pending_model_path = get_resource_file(
|
||||||
&resource_id,
|
&resource_id,
|
||||||
&*node.get_client().ok_or_else(|| eyre!("Client not found"))?,
|
&*node.get_client().ok_or_else(|| eyre!("Client not found"))?,
|
||||||
@@ -294,7 +283,7 @@ impl Model {
|
|||||||
let model = Arc::new_cyclic(|self_ref| Model {
|
let model = Arc::new_cyclic(|self_ref| Model {
|
||||||
self_ref: self_ref.clone(),
|
self_ref: self_ref.clone(),
|
||||||
enabled: node.enabled.clone(),
|
enabled: node.enabled.clone(),
|
||||||
space: node.spatial.get().unwrap().clone(),
|
space: node.get_aspect::<Spatial>().unwrap().clone(),
|
||||||
_resource_id: resource_id,
|
_resource_id: resource_id,
|
||||||
sk_model: OnceCell::new(),
|
sk_model: OnceCell::new(),
|
||||||
parts: LifeLinkedNodeMap::default(),
|
parts: LifeLinkedNodeMap::default(),
|
||||||
@@ -307,7 +296,7 @@ impl Model {
|
|||||||
);
|
);
|
||||||
ModelPart::create_for_model(sk, &model.self_ref.upgrade().unwrap(), &sk_model);
|
ModelPart::create_for_model(sk, &model.self_ref.upgrade().unwrap(), &sk_model);
|
||||||
let _ = model.sk_model.set(sk_model);
|
let _ = model.sk_model.set(sk_model);
|
||||||
let _ = node.drawable.set(Drawable::Model(model.clone()));
|
node.add_aspect_raw(model.clone());
|
||||||
Ok(model)
|
Ok(model)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,10 +305,9 @@ impl Model {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
for model_node_node in self.parts.nodes() {
|
for model_node_node in self.parts.nodes() {
|
||||||
let Some(Drawable::ModelPart(model_node)) = model_node_node.drawable.get() else {
|
if let Ok(model_node) = model_node_node.get_aspect::<ModelPart>() {
|
||||||
continue;
|
|
||||||
};
|
|
||||||
model_node.update(sk);
|
model_node.update(sk);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
sk.model_draw(
|
sk.model_draw(
|
||||||
@@ -330,6 +318,9 @@ impl Model {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Aspect for Model {
|
||||||
|
const NAME: &'static str = "Model";
|
||||||
|
}
|
||||||
impl ModelAspect for Model {}
|
impl ModelAspect for Model {}
|
||||||
impl Drop for Model {
|
impl Drop for Model {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
core::{client::Client, destroy_queue, registry::Registry, resource::get_resource_file},
|
core::{client::Client, destroy_queue, registry::Registry, resource::get_resource_file},
|
||||||
nodes::{drawable::Drawable, spatial::Spatial, Node},
|
nodes::{spatial::Spatial, Aspect, Node},
|
||||||
};
|
};
|
||||||
use color_eyre::eyre::{bail, ensure, eyre, Result};
|
use color_eyre::eyre::{eyre, Result};
|
||||||
use glam::{vec3, Mat4, Vec2};
|
use glam::{vec3, Mat4, Vec2};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
@@ -42,19 +42,10 @@ pub struct Text {
|
|||||||
}
|
}
|
||||||
impl Text {
|
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>> {
|
||||||
ensure!(
|
|
||||||
node.spatial.get().is_some(),
|
|
||||||
"Internal: Node does not have a spatial attached!"
|
|
||||||
);
|
|
||||||
ensure!(
|
|
||||||
node.drawable.get().is_none(),
|
|
||||||
"Internal: Node already has a drawable attached!"
|
|
||||||
);
|
|
||||||
|
|
||||||
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 {
|
||||||
enabled: node.enabled.clone(),
|
enabled: node.enabled.clone(),
|
||||||
space: node.spatial.get().unwrap().clone(),
|
space: 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")])
|
||||||
}),
|
}),
|
||||||
@@ -64,7 +55,7 @@ impl Text {
|
|||||||
data: Mutex::new(style),
|
data: Mutex::new(style),
|
||||||
});
|
});
|
||||||
<Text as TextAspect>::add_node_members(node);
|
<Text as TextAspect>::add_node_members(node);
|
||||||
let _ = node.drawable.set(Drawable::Text(text.clone()));
|
node.add_aspect_raw(text.clone());
|
||||||
|
|
||||||
Ok(text)
|
Ok(text)
|
||||||
}
|
}
|
||||||
@@ -122,26 +113,23 @@ impl Text {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Aspect for Text {
|
||||||
|
const NAME: &'static str = "Text";
|
||||||
|
}
|
||||||
impl TextAspect for Text {
|
impl TextAspect for Text {
|
||||||
fn set_character_height(
|
fn set_character_height(
|
||||||
node: Arc<Node>,
|
node: Arc<Node>,
|
||||||
_calling_client: Arc<Client>,
|
_calling_client: Arc<Client>,
|
||||||
height: f32,
|
height: f32,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let Some(Drawable::Text(text)) = node.drawable.get() else {
|
let this_text = node.get_aspect::<Text>()?;
|
||||||
bail!("Not a drawable??")
|
this_text.data.lock().character_height = height;
|
||||||
};
|
|
||||||
|
|
||||||
text.data.lock().character_height = height;
|
|
||||||
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 Some(Drawable::Text(text_aspect)) = node.drawable.get() else {
|
let this_text = node.get_aspect::<Text>()?;
|
||||||
bail!("Not a drawable??")
|
*this_text.text.lock() = text;
|
||||||
};
|
|
||||||
|
|
||||||
*text_aspect.text.lock() = text;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use super::{get_field, BoxFieldAspect, Field, FieldTrait, Node};
|
use super::{BoxFieldAspect, FieldTrait, Node};
|
||||||
use crate::core::client::Client;
|
|
||||||
use crate::nodes::fields::FieldAspect;
|
use crate::nodes::fields::FieldAspect;
|
||||||
use crate::nodes::spatial::Spatial;
|
use crate::nodes::spatial::Spatial;
|
||||||
use color_eyre::eyre::{ensure, Result};
|
use crate::{core::client::Client, nodes::fields::Field};
|
||||||
|
use color_eyre::eyre::Result;
|
||||||
use glam::{vec3, vec3a, Vec3, Vec3A};
|
use glam::{vec3, vec3a, Vec3, Vec3A};
|
||||||
use mint::Vector3;
|
use mint::Vector3;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
@@ -14,24 +14,14 @@ pub struct BoxField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BoxField {
|
impl BoxField {
|
||||||
pub fn add_to(node: &Arc<Node>, size: Vector3<f32>) -> Result<Arc<Field>> {
|
pub fn add_to(node: &Arc<Node>, size: Vector3<f32>) {
|
||||||
ensure!(
|
|
||||||
node.spatial.get().is_some(),
|
|
||||||
"Internal: Node does not have a spatial attached!"
|
|
||||||
);
|
|
||||||
ensure!(
|
|
||||||
node.field.get().is_none(),
|
|
||||||
"Internal: Node already has a field attached!"
|
|
||||||
);
|
|
||||||
let box_field = BoxField {
|
let box_field = BoxField {
|
||||||
space: node.spatial.get().unwrap().clone(),
|
space: node.get_aspect::<Spatial>().unwrap().clone(),
|
||||||
size: Mutex::new(size.into()),
|
size: Mutex::new(size.into()),
|
||||||
};
|
};
|
||||||
<BoxField as FieldAspect>::add_node_members(node);
|
<BoxField as FieldAspect>::add_node_members(node);
|
||||||
<BoxField as BoxFieldAspect>::add_node_members(node);
|
<BoxField as BoxFieldAspect>::add_node_members(node);
|
||||||
let field = Arc::new(Field::Box(box_field));
|
node.add_aspect(Field::Box(box_field));
|
||||||
let _ = node.field.set(field.clone());
|
|
||||||
Ok(field)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_size(&self, size: Vector3<f32>) {
|
pub fn set_size(&self, size: Vector3<f32>) {
|
||||||
@@ -60,7 +50,8 @@ impl BoxFieldAspect for BoxField {
|
|||||||
_calling_client: Arc<Client>,
|
_calling_client: Arc<Client>,
|
||||||
size: mint::Vector3<f32>,
|
size: mint::Vector3<f32>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let Field::Box(this_field) = &*get_field(&node)? else {
|
let this_field = node.get_aspect::<Field>()?;
|
||||||
|
let Field::Box(this_field) = &*this_field else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
this_field.set_size(size.into());
|
this_field.set_size(size.into());
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use super::{get_field, CylinderFieldAspect, Field, FieldTrait, Node};
|
use super::{CylinderFieldAspect, Field, FieldTrait, Node};
|
||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
use crate::nodes::fields::FieldAspect;
|
use crate::nodes::fields::FieldAspect;
|
||||||
use crate::nodes::spatial::Spatial;
|
use crate::nodes::spatial::Spatial;
|
||||||
use color_eyre::eyre::{ensure, Result};
|
use color_eyre::eyre::Result;
|
||||||
use glam::{swizzles::*, vec2, Vec3A};
|
use glam::{swizzles::*, vec2, Vec3A};
|
||||||
use portable_atomic::AtomicF32;
|
use portable_atomic::AtomicF32;
|
||||||
|
|
||||||
@@ -16,24 +16,15 @@ pub struct CylinderField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CylinderField {
|
impl CylinderField {
|
||||||
pub fn add_to(node: &Arc<Node>, length: f32, radius: f32) -> Result<()> {
|
pub fn add_to(node: &Arc<Node>, length: f32, radius: f32) {
|
||||||
ensure!(
|
|
||||||
node.spatial.get().is_some(),
|
|
||||||
"Internal: Node does not have a spatial attached!"
|
|
||||||
);
|
|
||||||
ensure!(
|
|
||||||
node.field.get().is_none(),
|
|
||||||
"Internal: Node already has a field attached!"
|
|
||||||
);
|
|
||||||
let cylinder_field = CylinderField {
|
let cylinder_field = CylinderField {
|
||||||
space: node.spatial.get().unwrap().clone(),
|
space: node.get_aspect::<Spatial>().unwrap().clone(),
|
||||||
length: AtomicF32::new(length.abs()),
|
length: AtomicF32::new(length.abs()),
|
||||||
radius: AtomicF32::new(radius.abs()),
|
radius: AtomicF32::new(radius.abs()),
|
||||||
};
|
};
|
||||||
<CylinderField as FieldAspect>::add_node_members(node);
|
<CylinderField as FieldAspect>::add_node_members(node);
|
||||||
<CylinderField as CylinderFieldAspect>::add_node_members(node);
|
<CylinderField as CylinderFieldAspect>::add_node_members(node);
|
||||||
let _ = node.field.set(Arc::new(Field::Cylinder(cylinder_field)));
|
node.add_aspect(Field::Cylinder(cylinder_field));
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_size(&self, length: f32, radius: f32) {
|
pub fn set_size(&self, length: f32, radius: f32) {
|
||||||
@@ -60,7 +51,8 @@ impl CylinderFieldAspect for CylinderField {
|
|||||||
length: f32,
|
length: f32,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let Field::Cylinder(this_field) = &*get_field(&node)? else {
|
let this_field = node.get_aspect::<Field>()?;
|
||||||
|
let Field::Cylinder(this_field) = &*this_field else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
this_field.set_size(length, radius);
|
this_field.set_size(length, radius);
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ use self::sphere::SphereField;
|
|||||||
use self::torus::TorusField;
|
use self::torus::TorusField;
|
||||||
|
|
||||||
use super::alias::AliasInfo;
|
use super::alias::AliasInfo;
|
||||||
use super::spatial::{get_spatial, Spatial};
|
use super::spatial::Spatial;
|
||||||
use super::Node;
|
use super::{Aspect, Node};
|
||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
use crate::create_interface;
|
use crate::create_interface;
|
||||||
use crate::nodes::spatial::Transform;
|
use crate::nodes::spatial::Transform;
|
||||||
@@ -30,7 +30,7 @@ pub static FIELD_ALIAS_INFO: Lazy<AliasInfo> = Lazy::new(|| AliasInfo {
|
|||||||
|
|
||||||
stardust_xr_server_codegen::codegen_field_protocol!();
|
stardust_xr_server_codegen::codegen_field_protocol!();
|
||||||
|
|
||||||
pub trait FieldTrait {
|
pub trait FieldTrait: Send + Sync + 'static {
|
||||||
fn spatial_ref(&self) -> &Spatial;
|
fn spatial_ref(&self) -> &Spatial;
|
||||||
|
|
||||||
fn local_distance(&self, p: Vec3A) -> f32;
|
fn local_distance(&self, p: Vec3A) -> f32;
|
||||||
@@ -114,9 +114,9 @@ impl<Fi: FieldTrait + 'static> FieldAspect for Fi {
|
|||||||
space: Arc<Node>,
|
space: Arc<Node>,
|
||||||
point: mint::Vector3<f32>,
|
point: mint::Vector3<f32>,
|
||||||
) -> Result<f32> {
|
) -> Result<f32> {
|
||||||
let reference_space = get_spatial(&space, "Reference space")?;
|
let reference_space = space.get_aspect::<Spatial>()?;
|
||||||
let this_field = node.field.get().unwrap();
|
let this_field = node.get_aspect::<Field>()?;
|
||||||
Ok(this_field.distance(reference_space.as_ref(), point.into()))
|
Ok((*this_field).distance(reference_space.as_ref(), point.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn normal(
|
async fn normal(
|
||||||
@@ -125,8 +125,8 @@ impl<Fi: FieldTrait + 'static> FieldAspect for Fi {
|
|||||||
space: Arc<Node>,
|
space: Arc<Node>,
|
||||||
point: mint::Vector3<f32>,
|
point: mint::Vector3<f32>,
|
||||||
) -> Result<Vector3<f32>> {
|
) -> Result<Vector3<f32>> {
|
||||||
let reference_space = get_spatial(&space, "Reference space")?;
|
let reference_space = space.get_aspect::<Spatial>()?;
|
||||||
let this_field = node.field.get().unwrap();
|
let this_field = node.get_aspect::<Field>()?;
|
||||||
Ok(this_field
|
Ok(this_field
|
||||||
.normal(reference_space.as_ref(), point.into(), 0.001)
|
.normal(reference_space.as_ref(), point.into(), 0.001)
|
||||||
.into())
|
.into())
|
||||||
@@ -138,8 +138,8 @@ impl<Fi: FieldTrait + 'static> FieldAspect for Fi {
|
|||||||
space: Arc<Node>,
|
space: Arc<Node>,
|
||||||
point: mint::Vector3<f32>,
|
point: mint::Vector3<f32>,
|
||||||
) -> Result<Vector3<f32>> {
|
) -> Result<Vector3<f32>> {
|
||||||
let reference_space = get_spatial(&space, "Reference space")?;
|
let reference_space = space.get_aspect::<Spatial>()?;
|
||||||
let this_field = node.field.get().unwrap();
|
let this_field = node.get_aspect::<Field>()?;
|
||||||
Ok(this_field
|
Ok(this_field
|
||||||
.closest_point(reference_space.as_ref(), point.into(), 0.001)
|
.closest_point(reference_space.as_ref(), point.into(), 0.001)
|
||||||
.into())
|
.into())
|
||||||
@@ -152,12 +152,12 @@ impl<Fi: FieldTrait + 'static> FieldAspect for Fi {
|
|||||||
ray_origin: mint::Vector3<f32>,
|
ray_origin: mint::Vector3<f32>,
|
||||||
ray_direction: mint::Vector3<f32>,
|
ray_direction: mint::Vector3<f32>,
|
||||||
) -> Result<RayMarchResult> {
|
) -> Result<RayMarchResult> {
|
||||||
let reference_space = get_spatial(&space, "Reference space")?;
|
let reference_space = space.get_aspect::<Spatial>()?;
|
||||||
let this_field = node.field.get().unwrap();
|
let this_field = node.get_aspect::<Field>()?;
|
||||||
Ok(this_field.ray_march(Ray {
|
Ok(this_field.ray_march(Ray {
|
||||||
origin: ray_origin.into(),
|
origin: ray_origin.into(),
|
||||||
direction: ray_direction.into(),
|
direction: ray_direction.into(),
|
||||||
space: reference_space,
|
space: reference_space.clone(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,6 +183,9 @@ pub enum Field {
|
|||||||
Sphere(SphereField),
|
Sphere(SphereField),
|
||||||
Torus(TorusField),
|
Torus(TorusField),
|
||||||
}
|
}
|
||||||
|
impl Aspect for Field {
|
||||||
|
const NAME: &'static str = "Field";
|
||||||
|
}
|
||||||
impl Deref for Field {
|
impl Deref for Field {
|
||||||
type Target = dyn FieldTrait;
|
type Target = dyn FieldTrait;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
@@ -194,6 +197,72 @@ impl Deref for Field {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// impl FieldTrait for Field {
|
||||||
|
// fn spatial_ref(&self) -> &Spatial {
|
||||||
|
// match self {
|
||||||
|
// Field::Box(field) => field.spatial_ref(),
|
||||||
|
// Field::Cylinder(field) => field.spatial_ref(),
|
||||||
|
// Field::Sphere(field) => field.spatial_ref(),
|
||||||
|
// Field::Torus(field) => field.spatial_ref(),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// fn local_distance(&self, p: Vec3A) -> f32 {
|
||||||
|
// match self {
|
||||||
|
// Field::Box(field) => field.local_distance(p),
|
||||||
|
// Field::Cylinder(field) => field.local_distance(p),
|
||||||
|
// Field::Sphere(field) => field.local_distance(p),
|
||||||
|
// Field::Torus(field) => field.local_distance(p),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// fn local_normal(&self, p: Vec3A, r: f32) -> Vec3A {
|
||||||
|
// match self {
|
||||||
|
// Field::Box(field) => field.local_normal(p, r),
|
||||||
|
// Field::Cylinder(field) => field.local_normal(p, r),
|
||||||
|
// Field::Sphere(field) => field.local_normal(p, r),
|
||||||
|
// Field::Torus(field) => field.local_normal(p, r),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// fn local_closest_point(&self, p: Vec3A, r: f32) -> Vec3A {
|
||||||
|
// match self {
|
||||||
|
// Field::Box(field) => field.local_closest_point(p, r),
|
||||||
|
// Field::Cylinder(field) => field.local_closest_point(p, r),
|
||||||
|
// Field::Sphere(field) => field.local_closest_point(p, r),
|
||||||
|
// Field::Torus(field) => field.local_closest_point(p, r),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// fn distance(&self, reference_space: &Spatial, p: Vec3A) -> f32 {
|
||||||
|
// match self {
|
||||||
|
// Field::Box(field) => field.distance(reference_space, p),
|
||||||
|
// Field::Cylinder(field) => field.distance(reference_space, p),
|
||||||
|
// Field::Sphere(field) => field.distance(reference_space, p),
|
||||||
|
// Field::Torus(field) => field.distance(reference_space, p),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// fn normal(&self, reference_space: &Spatial, p: Vec3A, r: f32) -> Vec3A {
|
||||||
|
// match self {
|
||||||
|
// Field::Box(field) => field.normal(reference_space, p, r),
|
||||||
|
// Field::Cylinder(field) => field.normal(reference_space, p, r),
|
||||||
|
// Field::Sphere(field) => field.normal(reference_space, p, r),
|
||||||
|
// Field::Torus(field) => field.normal(reference_space, p, r),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// fn closest_point(&self, reference_space: &Spatial, p: Vec3A, r: f32) -> Vec3A {
|
||||||
|
// match self {
|
||||||
|
// Field::Box(field) => field.closest_point(reference_space, p, r),
|
||||||
|
// Field::Cylinder(field) => field.closest_point(reference_space, p, r),
|
||||||
|
// Field::Sphere(field) => field.closest_point(reference_space, p, r),
|
||||||
|
// Field::Torus(field) => field.closest_point(reference_space, p, r),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// fn ray_march(&self, ray: Ray) -> RayMarchResult {
|
||||||
|
// match self {
|
||||||
|
// Field::Box(field) => field.ray_march(ray),
|
||||||
|
// Field::Cylinder(field) => field.ray_march(ray),
|
||||||
|
// Field::Sphere(field) => field.ray_march(ray),
|
||||||
|
// Field::Torus(field) => field.ray_march(ray),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
create_interface!(FieldInterface, FieldInterfaceAspect, "/field");
|
create_interface!(FieldInterface, FieldInterfaceAspect, "/field");
|
||||||
pub struct FieldInterface;
|
pub struct FieldInterface;
|
||||||
@@ -207,7 +276,7 @@ impl FieldInterfaceAspect for FieldInterface {
|
|||||||
size: mint::Vector3<f32>,
|
size: mint::Vector3<f32>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let transform = transform.to_mat4(true, true, false);
|
let transform = transform.to_mat4(true, true, false);
|
||||||
let parent = get_spatial(&parent, "Spatial parent")?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let node = Node::create_parent_name(
|
let node = Node::create_parent_name(
|
||||||
&calling_client,
|
&calling_client,
|
||||||
Self::CREATE_BOX_FIELD_PARENT_PATH,
|
Self::CREATE_BOX_FIELD_PARENT_PATH,
|
||||||
@@ -215,8 +284,8 @@ impl FieldInterfaceAspect for FieldInterface {
|
|||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
.add_to_scenegraph()?;
|
.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, Some(parent), transform, false)?;
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
BoxField::add_to(&node, size)?;
|
BoxField::add_to(&node, size);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +299,7 @@ impl FieldInterfaceAspect for FieldInterface {
|
|||||||
radius: f32,
|
radius: f32,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let transform = transform.to_mat4(true, true, false);
|
let transform = transform.to_mat4(true, true, false);
|
||||||
let parent = get_spatial(&parent, "Spatial parent")?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let node = Node::create_parent_name(
|
let node = Node::create_parent_name(
|
||||||
&calling_client,
|
&calling_client,
|
||||||
Self::CREATE_CYLINDER_FIELD_PARENT_PATH,
|
Self::CREATE_CYLINDER_FIELD_PARENT_PATH,
|
||||||
@@ -238,8 +307,8 @@ impl FieldInterfaceAspect for FieldInterface {
|
|||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
.add_to_scenegraph()?;
|
.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, Some(parent), transform, false)?;
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
CylinderField::add_to(&node, length, radius)?;
|
CylinderField::add_to(&node, length, radius);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,7 +320,7 @@ impl FieldInterfaceAspect for FieldInterface {
|
|||||||
position: mint::Vector3<f32>,
|
position: mint::Vector3<f32>,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let parent = get_spatial(&parent, "Spatial parent")?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let node = Node::create_parent_name(
|
let node = Node::create_parent_name(
|
||||||
&calling_client,
|
&calling_client,
|
||||||
Self::CREATE_SPHERE_FIELD_PARENT_PATH,
|
Self::CREATE_SPHERE_FIELD_PARENT_PATH,
|
||||||
@@ -261,11 +330,11 @@ impl FieldInterfaceAspect for FieldInterface {
|
|||||||
.add_to_scenegraph()?;
|
.add_to_scenegraph()?;
|
||||||
Spatial::add_to(
|
Spatial::add_to(
|
||||||
&node,
|
&node,
|
||||||
Some(parent),
|
Some(parent.clone()),
|
||||||
Mat4::from_translation(position.into()),
|
Mat4::from_translation(position.into()),
|
||||||
false,
|
false,
|
||||||
)?;
|
);
|
||||||
SphereField::add_to(&node, radius)?;
|
SphereField::add_to(&node, radius);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,7 +348,7 @@ impl FieldInterfaceAspect for FieldInterface {
|
|||||||
radius_b: f32,
|
radius_b: f32,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let transform = transform.to_mat4(true, true, false);
|
let transform = transform.to_mat4(true, true, false);
|
||||||
let parent = get_spatial(&parent, "Spatial parent")?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let node = Node::create_parent_name(
|
let node = Node::create_parent_name(
|
||||||
&calling_client,
|
&calling_client,
|
||||||
Self::CREATE_TORUS_FIELD_PARENT_PATH,
|
Self::CREATE_TORUS_FIELD_PARENT_PATH,
|
||||||
@@ -287,18 +356,12 @@ impl FieldInterfaceAspect for FieldInterface {
|
|||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
.add_to_scenegraph()?;
|
.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, Some(parent), transform, false)?;
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
TorusField::add_to(&node, radius_a, radius_b)?;
|
TorusField::add_to(&node, radius_a, radius_b);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_field(client: &Client, path: &str) -> Result<Arc<Field>> {
|
pub fn find_field(client: &Client, path: &str) -> Result<Arc<Field>> {
|
||||||
client
|
client.get_node("Field", path)?.get_aspect::<Field>()
|
||||||
.get_node("Field", path)?
|
|
||||||
.get_aspect("Field", "info", |n| &n.field)
|
|
||||||
.cloned()
|
|
||||||
}
|
|
||||||
pub fn get_field(node: &Node) -> Result<Arc<Field>> {
|
|
||||||
node.get_aspect("Field", "info", |n| &n.field).cloned()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use super::{get_field, Field, FieldTrait, Node, SphereFieldAspect};
|
use super::{Field, FieldTrait, Node, SphereFieldAspect};
|
||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
use crate::nodes::fields::FieldAspect;
|
use crate::nodes::fields::FieldAspect;
|
||||||
use crate::nodes::spatial::Spatial;
|
use crate::nodes::spatial::Spatial;
|
||||||
use color_eyre::eyre::{ensure, Result};
|
use color_eyre::eyre::Result;
|
||||||
use glam::Vec3A;
|
use glam::Vec3A;
|
||||||
use portable_atomic::AtomicF32;
|
use portable_atomic::AtomicF32;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
@@ -14,23 +14,14 @@ pub struct SphereField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SphereField {
|
impl SphereField {
|
||||||
pub fn add_to(node: &Arc<Node>, radius: f32) -> Result<()> {
|
pub fn add_to(node: &Arc<Node>, radius: f32) {
|
||||||
ensure!(
|
|
||||||
node.spatial.get().is_some(),
|
|
||||||
"Internal: Node does not have a spatial attached!"
|
|
||||||
);
|
|
||||||
ensure!(
|
|
||||||
node.field.get().is_none(),
|
|
||||||
"Internal: Node already has a field attached!"
|
|
||||||
);
|
|
||||||
let sphere_field = SphereField {
|
let sphere_field = SphereField {
|
||||||
space: node.spatial.get().unwrap().clone(),
|
space: node.get_aspect::<Spatial>().unwrap().clone(),
|
||||||
radius: AtomicF32::new(radius),
|
radius: AtomicF32::new(radius),
|
||||||
};
|
};
|
||||||
<SphereField as FieldAspect>::add_node_members(node);
|
<SphereField as FieldAspect>::add_node_members(node);
|
||||||
<SphereField as SphereFieldAspect>::add_node_members(node);
|
<SphereField as SphereFieldAspect>::add_node_members(node);
|
||||||
let _ = node.field.set(Arc::new(Field::Sphere(sphere_field)));
|
node.add_aspect(Field::Sphere(sphere_field));
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_radius(&self, radius: f32) {
|
pub fn set_radius(&self, radius: f32) {
|
||||||
@@ -54,7 +45,8 @@ impl FieldTrait for SphereField {
|
|||||||
}
|
}
|
||||||
impl SphereFieldAspect for SphereField {
|
impl SphereFieldAspect for SphereField {
|
||||||
fn set_radius(node: Arc<Node>, _calling_client: Arc<Client>, radius: f32) -> Result<()> {
|
fn set_radius(node: Arc<Node>, _calling_client: Arc<Client>, radius: f32) -> Result<()> {
|
||||||
let Field::Sphere(this_field) = &*get_field(&node)? else {
|
let this_field = node.get_aspect::<Field>()?;
|
||||||
|
let Field::Sphere(this_field) = &*this_field else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
this_field.set_radius(radius);
|
this_field.set_radius(radius);
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
use super::{get_field, Field, FieldTrait, Node, TorusFieldAspect};
|
use super::{Field, FieldTrait, Node, TorusFieldAspect};
|
||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
use crate::nodes::fields::FieldAspect;
|
use crate::nodes::fields::FieldAspect;
|
||||||
use crate::nodes::spatial::Spatial;
|
use crate::nodes::spatial::Spatial;
|
||||||
use crate::nodes::Message;
|
use color_eyre::eyre::Result;
|
||||||
use color_eyre::eyre::{ensure, Result};
|
|
||||||
use glam::{swizzles::*, vec2, Vec3A};
|
use glam::{swizzles::*, vec2, Vec3A};
|
||||||
use portable_atomic::AtomicF32;
|
use portable_atomic::AtomicF32;
|
||||||
use stardust_xr::schemas::flex::deserialize;
|
|
||||||
|
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -18,45 +16,21 @@ pub struct TorusField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TorusField {
|
impl TorusField {
|
||||||
pub fn add_to(node: &Arc<Node>, radius_a: f32, radius_b: f32) -> Result<()> {
|
pub fn add_to(node: &Arc<Node>, radius_a: f32, radius_b: f32) {
|
||||||
ensure!(
|
|
||||||
node.spatial.get().is_some(),
|
|
||||||
"Internal: Node does not have a spatial attached!"
|
|
||||||
);
|
|
||||||
ensure!(
|
|
||||||
node.field.get().is_none(),
|
|
||||||
"Internal: Node already has a field attached!"
|
|
||||||
);
|
|
||||||
let torus_field = TorusField {
|
let torus_field = TorusField {
|
||||||
space: node.spatial.get().unwrap().clone(),
|
space: node.get_aspect::<Spatial>().unwrap().clone(),
|
||||||
radius_a: AtomicF32::new(radius_a.abs()),
|
radius_a: AtomicF32::new(radius_a.abs()),
|
||||||
radius_b: AtomicF32::new(radius_b.abs()),
|
radius_b: AtomicF32::new(radius_b.abs()),
|
||||||
};
|
};
|
||||||
<TorusField as FieldAspect>::add_node_members(node);
|
<TorusField as FieldAspect>::add_node_members(node);
|
||||||
<TorusField as TorusFieldAspect>::add_node_members(node);
|
<TorusField as TorusFieldAspect>::add_node_members(node);
|
||||||
node.add_local_signal("set_size", TorusField::set_size_flex);
|
node.add_aspect(Field::Torus(torus_field));
|
||||||
let _ = node.field.set(Arc::new(Field::Torus(torus_field)));
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_size(&self, radius_a: f32, radius_b: f32) {
|
pub fn set_size(&self, radius_a: f32, radius_b: f32) {
|
||||||
self.radius_a.store(radius_a.abs(), Ordering::Relaxed);
|
self.radius_a.store(radius_a.abs(), Ordering::Relaxed);
|
||||||
self.radius_b.store(radius_b.abs(), Ordering::Relaxed);
|
self.radius_b.store(radius_b.abs(), Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_size_flex(
|
|
||||||
node: Arc<Node>,
|
|
||||||
_calling_client: Arc<Client>,
|
|
||||||
message: Message,
|
|
||||||
) -> Result<()> {
|
|
||||||
let Field::Torus(torus_field) = node.field.get().unwrap().as_ref() else {
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
let (radius_a, radius_b) = deserialize(message.as_ref())?;
|
|
||||||
torus_field.set_size(radius_a, radius_b);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
impl FieldTrait for TorusField {
|
impl FieldTrait for TorusField {
|
||||||
fn local_distance(&self, p: Vec3A) -> f32 {
|
fn local_distance(&self, p: Vec3A) -> f32 {
|
||||||
@@ -76,7 +50,8 @@ impl TorusFieldAspect for TorusField {
|
|||||||
radius_a: f32,
|
radius_a: f32,
|
||||||
radius_b: f32,
|
radius_b: f32,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let Field::Torus(this_field) = &*get_field(&node)? else {
|
let this_field = node.get_aspect::<Field>()?;
|
||||||
|
let Field::Torus(this_field) = &*this_field else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
this_field.set_size(radius_a, radius_b);
|
this_field.set_size(radius_a, radius_b);
|
||||||
|
|||||||
@@ -14,16 +14,13 @@ lazy_static::lazy_static! {
|
|||||||
|
|
||||||
fn create() -> Arc<Node> {
|
fn create() -> Arc<Node> {
|
||||||
let node = Arc::new(Node::create_parent_name(&INTERNAL_CLIENT, "", "hmd", false));
|
let node = Arc::new(Node::create_parent_name(&INTERNAL_CLIENT, "", "hmd", false));
|
||||||
Spatial::add_to(&node, None, Mat4::IDENTITY, false).expect("Unable to make spatial for HMD");
|
Spatial::add_to(&node, None, Mat4::IDENTITY, false);
|
||||||
|
|
||||||
node
|
node
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn frame(sk: &impl StereoKitMultiThread) {
|
pub fn frame(sk: &impl StereoKitMultiThread) {
|
||||||
let spatial = HMD
|
let spatial = HMD.get_aspect::<Spatial>().unwrap();
|
||||||
.spatial
|
|
||||||
.get()
|
|
||||||
.expect("Unable to get spatial to update HMD");
|
|
||||||
let hmd_pose = sk.input_head();
|
let hmd_pose = sk.input_head();
|
||||||
*spatial.transform.lock() = Mat4::from_scale_rotation_translation(
|
*spatial.transform.lock() = Mat4::from_scale_rotation_translation(
|
||||||
vec3(1.0, 1.0, 1.0),
|
vec3(1.0, 1.0, 1.0),
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ use self::tip::Tip;
|
|||||||
use super::{
|
use super::{
|
||||||
alias::{Alias, AliasInfo},
|
alias::{Alias, AliasInfo},
|
||||||
fields::{find_field, Field, FIELD_ALIAS_INFO},
|
fields::{find_field, Field, FIELD_ALIAS_INFO},
|
||||||
spatial::{find_spatial_parent, parse_transform, Spatial},
|
spatial::{parse_transform, Spatial},
|
||||||
Message, Node,
|
Aspect, Message, Node,
|
||||||
};
|
};
|
||||||
use crate::core::{client::Client, node_collections::LifeLinkedNodeMap};
|
use crate::core::{client::Client, node_collections::LifeLinkedNodeMap};
|
||||||
use crate::{core::registry::Registry, nodes::spatial::Transform};
|
use crate::{core::registry::Registry, nodes::spatial::Transform};
|
||||||
use color_eyre::eyre::{ensure, Result};
|
use color_eyre::eyre::Result;
|
||||||
use glam::Mat4;
|
use glam::Mat4;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
@@ -76,11 +76,6 @@ impl InputMethod {
|
|||||||
specialization: InputType,
|
specialization: InputType,
|
||||||
datamap: Option<Datamap>,
|
datamap: Option<Datamap>,
|
||||||
) -> Result<Arc<InputMethod>> {
|
) -> Result<Arc<InputMethod>> {
|
||||||
ensure!(
|
|
||||||
node.spatial.get().is_some(),
|
|
||||||
"Internal: Node does not have a spatial attached!"
|
|
||||||
);
|
|
||||||
|
|
||||||
node.add_local_signal("capture", InputMethod::capture_flex);
|
node.add_local_signal("capture", InputMethod::capture_flex);
|
||||||
node.add_local_signal("set_datamap", InputMethod::set_datamap_flex);
|
node.add_local_signal("set_datamap", InputMethod::set_datamap_flex);
|
||||||
node.add_local_signal("set_handlers", InputMethod::set_handlers_flex);
|
node.add_local_signal("set_handlers", InputMethod::set_handlers_flex);
|
||||||
@@ -89,7 +84,7 @@ impl InputMethod {
|
|||||||
node: Arc::downgrade(node),
|
node: Arc::downgrade(node),
|
||||||
uid: node.uid.clone(),
|
uid: node.uid.clone(),
|
||||||
enabled: Mutex::new(true),
|
enabled: Mutex::new(true),
|
||||||
spatial: node.spatial.get().unwrap().clone(),
|
spatial: node.get_aspect::<Spatial>().unwrap().clone(),
|
||||||
specialization: Mutex::new(specialization),
|
specialization: Mutex::new(specialization),
|
||||||
captures: Registry::new(),
|
captures: Registry::new(),
|
||||||
datamap: Mutex::new(datamap),
|
datamap: Mutex::new(datamap),
|
||||||
@@ -101,12 +96,11 @@ impl InputMethod {
|
|||||||
method.make_alias(&handler);
|
method.make_alias(&handler);
|
||||||
}
|
}
|
||||||
let method = INPUT_METHOD_REGISTRY.add(method);
|
let method = INPUT_METHOD_REGISTRY.add(method);
|
||||||
let _ = node.input_method.set(method.clone());
|
node.add_aspect_raw(method.clone());
|
||||||
Ok(method)
|
Ok(method)
|
||||||
}
|
}
|
||||||
fn get(node: &Node) -> Result<Arc<Self>> {
|
fn get(node: &Node) -> Result<Arc<Self>> {
|
||||||
node.get_aspect("Input Method", "input method", |n| &n.input_method)
|
node.get_aspect::<Self>()
|
||||||
.cloned()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn capture_flex(node: Arc<Node>, calling_client: Arc<Client>, message: Message) -> Result<()> {
|
fn capture_flex(node: Arc<Node>, calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||||
@@ -242,6 +236,9 @@ impl InputMethod {
|
|||||||
let _ = tx_node.send_remote_signal("handler_destroyed", data);
|
let _ = tx_node.send_remote_signal("handler_destroyed", data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Aspect for InputMethod {
|
||||||
|
const NAME: &'static str = "InputMethod";
|
||||||
|
}
|
||||||
impl Drop for InputMethod {
|
impl Drop for InputMethod {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
INPUT_METHOD_REGISTRY.remove(self);
|
INPUT_METHOD_REGISTRY.remove(self);
|
||||||
@@ -294,16 +291,11 @@ pub struct InputHandler {
|
|||||||
}
|
}
|
||||||
impl InputHandler {
|
impl InputHandler {
|
||||||
pub fn add_to(node: &Arc<Node>, field: &Arc<Field>) -> Result<()> {
|
pub fn add_to(node: &Arc<Node>, field: &Arc<Field>) -> Result<()> {
|
||||||
ensure!(
|
|
||||||
node.spatial.get().is_some(),
|
|
||||||
"Internal: Node does not have a spatial attached!"
|
|
||||||
);
|
|
||||||
|
|
||||||
let handler = InputHandler {
|
let handler = InputHandler {
|
||||||
enabled: node.enabled.clone(),
|
enabled: node.enabled.clone(),
|
||||||
uid: node.uid.clone(),
|
uid: node.uid.clone(),
|
||||||
node: Arc::downgrade(node),
|
node: Arc::downgrade(node),
|
||||||
spatial: node.spatial.get().unwrap().clone(),
|
spatial: node.get_aspect::<Spatial>().unwrap().clone(),
|
||||||
field: field.clone(),
|
field: field.clone(),
|
||||||
method_aliases: LifeLinkedNodeMap::default(),
|
method_aliases: LifeLinkedNodeMap::default(),
|
||||||
};
|
};
|
||||||
@@ -312,15 +304,11 @@ impl InputHandler {
|
|||||||
method.handle_new_handler(&handler);
|
method.handle_new_handler(&handler);
|
||||||
}
|
}
|
||||||
let handler = INPUT_HANDLER_REGISTRY.add(handler);
|
let handler = INPUT_HANDLER_REGISTRY.add(handler);
|
||||||
let _ = node.input_handler.set(handler);
|
node.add_aspect_raw(handler);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn find(client: &Client, path: &str) -> Result<Arc<Self>> {
|
fn find(client: &Client, path: &str) -> Result<Arc<Self>> {
|
||||||
InputHandler::get(&*client.get_node("Input Handler", path)?)
|
client.get_node("Input Handler", path)?.get_aspect::<Self>()
|
||||||
}
|
|
||||||
fn get(node: &Node) -> Result<Arc<Self>> {
|
|
||||||
node.get_aspect("Input Handler", "input handler", |n| &n.input_handler)
|
|
||||||
.cloned()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, distance_link))]
|
#[instrument(level = "debug", skip(self, distance_link))]
|
||||||
@@ -337,6 +325,9 @@ impl InputHandler {
|
|||||||
let _ = node.send_remote_signal("input", distance_link.serialize(order, captured, datamap));
|
let _ = node.send_remote_signal("input", distance_link.serialize(order, captured, datamap));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Aspect for InputHandler {
|
||||||
|
const NAME: &'static str = "InputHandler";
|
||||||
|
}
|
||||||
impl PartialEq for InputHandler {
|
impl PartialEq for InputHandler {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.spatial == other.spatial
|
self.spatial == other.spatial
|
||||||
@@ -372,13 +363,15 @@ pub fn create_input_handler_flex(
|
|||||||
field_path: &'a str,
|
field_path: &'a str,
|
||||||
}
|
}
|
||||||
let info: CreateInputHandlerInfo = deserialize(message.as_ref())?;
|
let info: CreateInputHandlerInfo = deserialize(message.as_ref())?;
|
||||||
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
|
let parent = calling_client
|
||||||
|
.get_node("Spatial parent", info.parent_path)?
|
||||||
|
.get_aspect::<Spatial>()?;
|
||||||
let transform = parse_transform(info.transform, true, true, true);
|
let transform = parse_transform(info.transform, true, true, true);
|
||||||
let field = find_field(&calling_client, info.field_path)?;
|
let field = find_field(&calling_client, info.field_path)?;
|
||||||
|
|
||||||
let node = Node::create_parent_name(&calling_client, "/input/handler", info.name, true)
|
let node = Node::create_parent_name(&calling_client, "/input/handler", info.name, true)
|
||||||
.add_to_scenegraph()?;
|
.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, Some(parent), transform, false)?;
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
InputHandler::add_to(&node, &field)?;
|
InputHandler::add_to(&node, &field)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -441,7 +434,7 @@ pub fn process_input() {
|
|||||||
.handler
|
.handler
|
||||||
.method_aliases
|
.method_aliases
|
||||||
.get(&(Arc::as_ptr(&distance_link.method) as usize))
|
.get(&(Arc::as_ptr(&distance_link.method) as usize))
|
||||||
.and_then(|a| a.alias.get().cloned())
|
.and_then(|a| a.get_aspect::<Alias>().ok())
|
||||||
{
|
{
|
||||||
method_alias.enabled.store(true, Ordering::Release);
|
method_alias.enabled.store(true, Ordering::Release);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use super::{DistanceLink, InputSpecialization};
|
|||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
use crate::nodes::fields::{Field, Ray, RayMarchResult};
|
use crate::nodes::fields::{Field, Ray, RayMarchResult};
|
||||||
use crate::nodes::input::{InputMethod, InputType};
|
use crate::nodes::input::{InputMethod, InputType};
|
||||||
use crate::nodes::spatial::{find_spatial_parent, parse_transform, Spatial, Transform};
|
use crate::nodes::spatial::{parse_transform, Spatial, Transform};
|
||||||
use crate::nodes::{Message, Node};
|
use crate::nodes::{Message, Node};
|
||||||
use glam::{vec3, Mat4};
|
use glam::{vec3, Mat4};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
@@ -79,11 +79,13 @@ pub fn create_pointer_flex(
|
|||||||
}
|
}
|
||||||
let info: CreatePointerInfo = deserialize(message.as_ref())?;
|
let info: CreatePointerInfo = deserialize(message.as_ref())?;
|
||||||
let node = Node::create_parent_name(&calling_client, "/input/method/pointer", info.name, true);
|
let node = Node::create_parent_name(&calling_client, "/input/method/pointer", info.name, true);
|
||||||
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
|
let parent = calling_client
|
||||||
|
.get_node("Spatial parent", info.parent_path)?
|
||||||
|
.get_aspect::<Spatial>()?;
|
||||||
let transform = parse_transform(info.transform, true, true, false);
|
let transform = parse_transform(info.transform, true, true, false);
|
||||||
|
|
||||||
let node = node.add_to_scenegraph()?;
|
let node = node.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, Some(parent), transform, false)?;
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
InputMethod::add_to(
|
InputMethod::add_to(
|
||||||
&node,
|
&node,
|
||||||
InputType::Pointer(Pointer),
|
InputType::Pointer(Pointer),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use super::{DistanceLink, InputSpecialization};
|
|||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
use crate::nodes::fields::Field;
|
use crate::nodes::fields::Field;
|
||||||
use crate::nodes::input::{InputMethod, InputType};
|
use crate::nodes::input::{InputMethod, InputType};
|
||||||
use crate::nodes::spatial::{find_spatial_parent, parse_transform, Spatial, Transform};
|
use crate::nodes::spatial::{parse_transform, Spatial, Transform};
|
||||||
use crate::nodes::{Message, Node};
|
use crate::nodes::{Message, Node};
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use glam::{vec3a, Mat4};
|
use glam::{vec3a, Mat4};
|
||||||
@@ -19,7 +19,8 @@ pub struct Tip {
|
|||||||
}
|
}
|
||||||
impl Tip {
|
impl Tip {
|
||||||
fn set_radius(node: Arc<Node>, _calling_client: Arc<Client>, message: Message) -> Result<()> {
|
fn set_radius(node: Arc<Node>, _calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||||
if let InputType::Tip(tip) = &mut *node.input_method.get().unwrap().specialization.lock() {
|
let input_method = node.get_aspect::<InputMethod>()?;
|
||||||
|
if let InputType::Tip(tip) = &mut *input_method.specialization.lock() {
|
||||||
tip.radius = deserialize(message.as_ref())?;
|
tip.radius = deserialize(message.as_ref())?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -61,11 +62,13 @@ pub fn create_tip_flex(
|
|||||||
}
|
}
|
||||||
let info: CreateTipInfo = deserialize(message.as_ref())?;
|
let info: CreateTipInfo = deserialize(message.as_ref())?;
|
||||||
let node = Node::create_parent_name(&calling_client, "/input/method/tip", info.name, true);
|
let node = Node::create_parent_name(&calling_client, "/input/method/tip", info.name, true);
|
||||||
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
|
let parent = calling_client
|
||||||
|
.get_node("Spatial parent", info.parent_path)?
|
||||||
|
.get_aspect::<Spatial>()?;
|
||||||
let transform = parse_transform(info.transform, true, true, false);
|
let transform = parse_transform(info.transform, true, true, false);
|
||||||
|
|
||||||
let node = node.add_to_scenegraph()?;
|
let node = node.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, Some(parent), transform, false)?;
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
InputMethod::add_to(
|
InputMethod::add_to(
|
||||||
&node,
|
&node,
|
||||||
InputType::Tip(Tip {
|
InputType::Tip(Tip {
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ use crate::{
|
|||||||
scenegraph::MethodResponseSender,
|
scenegraph::MethodResponseSender,
|
||||||
},
|
},
|
||||||
nodes::{
|
nodes::{
|
||||||
drawable::{model::ModelPart, shaders::UNLIT_SHADER_BYTES, Drawable},
|
drawable::{model::ModelPart, shaders::UNLIT_SHADER_BYTES},
|
||||||
items::TypeInfo,
|
items::TypeInfo,
|
||||||
spatial::{find_spatial_parent, parse_transform, Spatial, Transform},
|
spatial::{parse_transform, Spatial, Transform},
|
||||||
Message, Node,
|
Message, Node,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -58,7 +58,7 @@ impl CameraItem {
|
|||||||
nanoid!(),
|
nanoid!(),
|
||||||
&ITEM_TYPE_INFO_CAMERA,
|
&ITEM_TYPE_INFO_CAMERA,
|
||||||
ItemType::Camera(CameraItem {
|
ItemType::Camera(CameraItem {
|
||||||
space: node.spatial.get().unwrap().clone(),
|
space: node.get_aspect::<Spatial>().unwrap().clone(),
|
||||||
frame_info: Mutex::new(FrameInfo {
|
frame_info: Mutex::new(FrameInfo {
|
||||||
proj_matrix,
|
proj_matrix,
|
||||||
px_size,
|
px_size,
|
||||||
@@ -83,7 +83,8 @@ impl CameraItem {
|
|||||||
response: MethodResponseSender,
|
response: MethodResponseSender,
|
||||||
) {
|
) {
|
||||||
response.wrap_sync(move || {
|
response.wrap_sync(move || {
|
||||||
let ItemType::Camera(_camera) = &node.item.get().unwrap().specialization else {
|
let ItemType::Camera(_camera) = &node.get_aspect::<Item>().unwrap().specialization
|
||||||
|
else {
|
||||||
return Err(eyre!("Wrong item type?"));
|
return Err(eyre!("Wrong item type?"));
|
||||||
};
|
};
|
||||||
Ok(serialize(())?.into())
|
Ok(serialize(())?.into())
|
||||||
@@ -95,18 +96,14 @@ impl CameraItem {
|
|||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
message: Message,
|
message: Message,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ItemType::Camera(camera) = &node.item.get().unwrap().specialization else {
|
let ItemType::Camera(camera) = &node.get_aspect::<Item>().unwrap().specialization else {
|
||||||
bail!("Wrong item type?")
|
bail!("Wrong item type?")
|
||||||
};
|
};
|
||||||
let model_part_node =
|
let model_part_node =
|
||||||
calling_client.get_node("Model part", deserialize(&message.data).unwrap())?;
|
calling_client.get_node("Model part", deserialize(&message.data).unwrap())?;
|
||||||
let Drawable::ModelPart(model_part) =
|
let model_part = model_part_node.get_aspect::<ModelPart>()?;
|
||||||
model_part_node.get_aspect("Model part", "model part", |n| &n.drawable)?
|
camera.applied_to.add_raw(&model_part);
|
||||||
else {
|
camera.apply_to.add_raw(&model_part);
|
||||||
bail!("Drawable is not a model node")
|
|
||||||
};
|
|
||||||
camera.applied_to.add_raw(model_part);
|
|
||||||
camera.apply_to.add_raw(model_part);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,16 +175,19 @@ pub(super) fn create_camera_item_flex(
|
|||||||
}
|
}
|
||||||
let info: CreateCameraItemInfo = deserialize(message.as_ref())?;
|
let info: CreateCameraItemInfo = deserialize(message.as_ref())?;
|
||||||
let parent_name = format!("/item/{}/item", ITEM_TYPE_INFO_CAMERA.type_name);
|
let parent_name = format!("/item/{}/item", ITEM_TYPE_INFO_CAMERA.type_name);
|
||||||
let space = find_spatial_parent(&calling_client, info.parent_path)?;
|
let space = calling_client
|
||||||
|
.get_node("Spatial parent", info.parent_path)?
|
||||||
|
.get_aspect::<Spatial>()?;
|
||||||
let transform = parse_transform(info.transform, true, true, false);
|
let transform = parse_transform(info.transform, true, true, false);
|
||||||
|
|
||||||
let node = Node::create_parent_name(&INTERNAL_CLIENT, &parent_name, info.name, false)
|
let node = Node::create_parent_name(&INTERNAL_CLIENT, &parent_name, info.name, false)
|
||||||
.add_to_scenegraph()?;
|
.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, None, transform * space.global_transform(), false)?;
|
Spatial::add_to(&node, None, transform * space.global_transform(), false);
|
||||||
CameraItem::add_to(&node, info.proj_matrix.into(), info.px_size);
|
CameraItem::add_to(&node, info.proj_matrix.into(), info.px_size);
|
||||||
node.item
|
node.get_aspect::<Item>().unwrap().make_alias_named(
|
||||||
.get()
|
&calling_client,
|
||||||
.unwrap()
|
&parent_name,
|
||||||
.make_alias_named(&calling_client, &parent_name, info.name)?;
|
info.name,
|
||||||
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
nodes::{
|
nodes::{
|
||||||
items::TypeInfo,
|
items::TypeInfo,
|
||||||
spatial::{find_spatial_parent, parse_transform, Spatial, Transform},
|
spatial::{parse_transform, Spatial, Transform},
|
||||||
Message, Node,
|
Message, Node,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -51,7 +51,8 @@ impl EnvironmentItem {
|
|||||||
response: MethodResponseSender,
|
response: MethodResponseSender,
|
||||||
) {
|
) {
|
||||||
response.wrap_sync(move || {
|
response.wrap_sync(move || {
|
||||||
let ItemType::Environment(environment_item) = &node.item.get().unwrap().specialization
|
let ItemType::Environment(environment_item) =
|
||||||
|
&node.get_aspect::<Item>().unwrap().specialization
|
||||||
else {
|
else {
|
||||||
return Err(eyre!("Wrong item type?"));
|
return Err(eyre!("Wrong item type?"));
|
||||||
};
|
};
|
||||||
@@ -78,16 +79,19 @@ pub(super) fn create_environment_item_flex(
|
|||||||
}
|
}
|
||||||
let info: CreateEnvironmentItemInfo = deserialize(message.as_ref())?;
|
let info: CreateEnvironmentItemInfo = deserialize(message.as_ref())?;
|
||||||
let parent_name = format!("/item/{}/item", ITEM_TYPE_INFO_ENVIRONMENT.type_name);
|
let parent_name = format!("/item/{}/item", ITEM_TYPE_INFO_ENVIRONMENT.type_name);
|
||||||
let space = find_spatial_parent(&calling_client, info.parent_path)?;
|
let space = calling_client
|
||||||
|
.get_node("Spatial parent", info.parent_path)?
|
||||||
|
.get_aspect::<Spatial>()?;
|
||||||
let transform = parse_transform(info.transform, true, true, false);
|
let transform = parse_transform(info.transform, true, true, false);
|
||||||
|
|
||||||
let node = Node::create_parent_name(&INTERNAL_CLIENT, &parent_name, info.name, false)
|
let node = Node::create_parent_name(&INTERNAL_CLIENT, &parent_name, info.name, false)
|
||||||
.add_to_scenegraph()?;
|
.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, None, transform * space.global_transform(), false)?;
|
Spatial::add_to(&node, None, transform * space.global_transform(), false);
|
||||||
EnvironmentItem::add_to(&node, info.item_data);
|
EnvironmentItem::add_to(&node, info.item_data);
|
||||||
node.item
|
node.get_aspect::<Item>().unwrap().make_alias_named(
|
||||||
.get()
|
&calling_client,
|
||||||
.unwrap()
|
&parent_name,
|
||||||
.make_alias_named(&calling_client, &parent_name, info.name)?;
|
info.name,
|
||||||
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ use self::camera::CameraItem;
|
|||||||
use self::environment::{EnvironmentItem, ITEM_TYPE_INFO_ENVIRONMENT};
|
use self::environment::{EnvironmentItem, ITEM_TYPE_INFO_ENVIRONMENT};
|
||||||
use self::panel::{PanelItemTrait, ITEM_TYPE_INFO_PANEL};
|
use self::panel::{PanelItemTrait, ITEM_TYPE_INFO_PANEL};
|
||||||
use super::fields::Field;
|
use super::fields::Field;
|
||||||
use super::spatial::{find_spatial_parent, parse_transform, Spatial};
|
use super::spatial::{parse_transform, Spatial};
|
||||||
use super::{Alias, Message, Node};
|
use super::{Alias, Aspect, Message, Node};
|
||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
use crate::core::node_collections::LifeLinkedNodeMap;
|
use crate::core::node_collections::LifeLinkedNodeMap;
|
||||||
use crate::core::registry::Registry;
|
use crate::core::registry::Registry;
|
||||||
@@ -108,7 +108,7 @@ impl Item {
|
|||||||
if let Some(ui) = type_info.ui.lock().upgrade() {
|
if let Some(ui) = type_info.ui.lock().upgrade() {
|
||||||
ui.handle_create_item(&item);
|
ui.handle_create_item(&item);
|
||||||
}
|
}
|
||||||
let _ = node.item.set(item.clone());
|
node.add_aspect_raw(item.clone());
|
||||||
|
|
||||||
// if let Some(auto_acceptor) = node.get_client().and_then(|client| {
|
// if let Some(auto_acceptor) = node.get_client().and_then(|client| {
|
||||||
// client
|
// client
|
||||||
@@ -161,12 +161,15 @@ impl Item {
|
|||||||
_calling_client: Arc<Client>,
|
_calling_client: Arc<Client>,
|
||||||
_message: Message,
|
_message: Message,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let item = node.get_aspect("Item", "item", |n| &n.item)?;
|
let item = node.get_aspect::<Item>()?;
|
||||||
release(item);
|
release(&item);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Aspect for Item {
|
||||||
|
const NAME: &'static str = "Item";
|
||||||
|
}
|
||||||
impl Drop for Item {
|
impl Drop for Item {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.type_info.items.remove(self);
|
self.type_info.items.remove(self);
|
||||||
@@ -224,7 +227,7 @@ impl ItemUI {
|
|||||||
acceptor_field_aliases: Default::default(),
|
acceptor_field_aliases: Default::default(),
|
||||||
});
|
});
|
||||||
*type_info.ui.lock() = Arc::downgrade(&ui);
|
*type_info.ui.lock() = Arc::downgrade(&ui);
|
||||||
let _ = node.item_ui.set(ui.clone());
|
node.add_aspect_raw(ui.clone());
|
||||||
|
|
||||||
for item in type_info.items.get_valid_contents() {
|
for item in type_info.items.get_valid_contents() {
|
||||||
ui.handle_create_item(&item);
|
ui.handle_create_item(&item);
|
||||||
@@ -314,6 +317,9 @@ impl ItemUI {
|
|||||||
self.acceptor_field_aliases.remove(&acceptor.uid);
|
self.acceptor_field_aliases.remove(&acceptor.uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Aspect for ItemUI {
|
||||||
|
const NAME: &'static str = "Item";
|
||||||
|
}
|
||||||
impl Drop for ItemUI {
|
impl Drop for ItemUI {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
*self.type_info.ui.lock() = Weak::new();
|
*self.type_info.ui.lock() = Weak::new();
|
||||||
@@ -342,7 +348,7 @@ impl ItemAcceptor {
|
|||||||
if let Some(ui) = type_info.ui.lock().upgrade() {
|
if let Some(ui) = type_info.ui.lock().upgrade() {
|
||||||
ui.handle_create_acceptor(&acceptor);
|
ui.handle_create_acceptor(&acceptor);
|
||||||
}
|
}
|
||||||
let _ = node.item_acceptor.set(acceptor);
|
node.add_aspect_raw(acceptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn capture_flex(node: Arc<Node>, calling_client: Arc<Client>, message: Message) -> Result<()> {
|
fn capture_flex(node: Arc<Node>, calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||||
@@ -350,11 +356,11 @@ impl ItemAcceptor {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let acceptor = node.item_acceptor.get().unwrap();
|
let acceptor = node.get_aspect::<ItemAcceptor>().unwrap();
|
||||||
let item_path: &str = deserialize(message.as_ref())?;
|
let item_path: &str = deserialize(message.as_ref())?;
|
||||||
let item_node = calling_client.get_node("Item", item_path)?;
|
let item_node = calling_client.get_node("Item", item_path)?;
|
||||||
let item = item_node.get_aspect("Item", "item", |n| &n.item)?;
|
let item = item_node.get_aspect::<Item>()?;
|
||||||
capture(item, acceptor);
|
capture(&item, &acceptor);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -413,6 +419,9 @@ impl ItemAcceptor {
|
|||||||
let _ = node.send_remote_signal("release", message);
|
let _ = node.send_remote_signal("release", message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Aspect for ItemAcceptor {
|
||||||
|
const NAME: &'static str = "ItemAcceptor";
|
||||||
|
}
|
||||||
impl Drop for ItemAcceptor {
|
impl Drop for ItemAcceptor {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.type_info.acceptors.remove(self);
|
self.type_info.acceptors.remove(self);
|
||||||
@@ -477,7 +486,9 @@ fn create_item_acceptor_flex(
|
|||||||
item_type: &'a str,
|
item_type: &'a str,
|
||||||
}
|
}
|
||||||
let info: CreateItemAcceptorInfo = deserialize(message.as_ref())?;
|
let info: CreateItemAcceptorInfo = deserialize(message.as_ref())?;
|
||||||
let space = find_spatial_parent(&calling_client, info.parent_path)?;
|
let space = calling_client
|
||||||
|
.get_node("Reference space", info.parent_path)?
|
||||||
|
.get_aspect::<Spatial>()?;
|
||||||
let transform = parse_transform(info.transform, true, true, false);
|
let transform = parse_transform(info.transform, true, true, false);
|
||||||
let field = find_field(&calling_client, info.field_path)?;
|
let field = find_field(&calling_client, info.field_path)?;
|
||||||
let type_info = type_info(info.item_type)?;
|
let type_info = type_info(info.item_type)?;
|
||||||
@@ -489,7 +500,7 @@ fn create_item_acceptor_flex(
|
|||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
.add_to_scenegraph()?;
|
.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, Some(space), transform, false)?;
|
Spatial::add_to(&node, Some(space.clone()), transform, false);
|
||||||
ItemAcceptor::add_to(&node, type_info, field);
|
ItemAcceptor::add_to(&node, type_info, field);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ use crate::{
|
|||||||
registry::Registry,
|
registry::Registry,
|
||||||
},
|
},
|
||||||
nodes::{
|
nodes::{
|
||||||
drawable::{model::ModelPart, Drawable},
|
drawable::model::ModelPart,
|
||||||
items::{Item, ItemType, TypeInfo},
|
items::{Item, ItemType, TypeInfo},
|
||||||
spatial::Spatial,
|
spatial::Spatial,
|
||||||
Message, Node,
|
Message, Node,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use color_eyre::eyre::{bail, eyre, Result};
|
use color_eyre::eyre::{eyre, Result};
|
||||||
use glam::Mat4;
|
use glam::Mat4;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
@@ -203,7 +203,7 @@ pub trait Backend: Send + Sync + 'static {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn panel_item_from_node(node: &Node) -> Option<Arc<dyn PanelItemTrait>> {
|
pub fn panel_item_from_node(node: &Node) -> Option<Arc<dyn PanelItemTrait>> {
|
||||||
let ItemType::Panel(panel_item) = &node.item.get()?.specialization else {
|
let ItemType::Panel(panel_item) = &node.get_aspect::<Item>().ok()?.specialization else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
Some(panel_item.clone())
|
Some(panel_item.clone())
|
||||||
@@ -231,7 +231,7 @@ impl<B: Backend + ?Sized> PanelItem<B> {
|
|||||||
let node = Node::create_parent_name(&INTERNAL_CLIENT, "/item/panel/item", &uid, true)
|
let node = Node::create_parent_name(&INTERNAL_CLIENT, "/item/panel/item", &uid, true)
|
||||||
.add_to_scenegraph()
|
.add_to_scenegraph()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false).unwrap();
|
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false);
|
||||||
if let Some(startup_settings) = &startup_settings {
|
if let Some(startup_settings) = &startup_settings {
|
||||||
spatial.set_local_transform(startup_settings.root);
|
spatial.set_local_transform(startup_settings.root);
|
||||||
}
|
}
|
||||||
@@ -402,12 +402,10 @@ impl<B: Backend + ?Sized> PanelItem<B> {
|
|||||||
.scenegraph
|
.scenegraph
|
||||||
.get_node(info.model_node_path)
|
.get_node(info.model_node_path)
|
||||||
.ok_or_else(|| eyre!("Model node not found"))?;
|
.ok_or_else(|| eyre!("Model node not found"))?;
|
||||||
let Some(Drawable::ModelPart(model_part)) = model_node.drawable.get() else {
|
let model_part = model_node.get_aspect::<ModelPart>()?;
|
||||||
bail!("Node is not a model")
|
|
||||||
};
|
|
||||||
debug!(?info, "Apply surface material");
|
debug!(?info, "Apply surface material");
|
||||||
|
|
||||||
panel_item.apply_surface_material(info.surface, model_part);
|
panel_item.apply_surface_material(info.surface, &model_part);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
108
src/nodes/mod.rs
108
src/nodes/mod.rs
@@ -11,7 +11,6 @@ pub mod spatial;
|
|||||||
|
|
||||||
use color_eyre::eyre::{eyre, Result};
|
use color_eyre::eyre::{eyre, Result};
|
||||||
use nanoid::nanoid;
|
use nanoid::nanoid;
|
||||||
use once_cell::sync::OnceCell;
|
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use portable_atomic::{AtomicBool, Ordering};
|
use portable_atomic::{AtomicBool, Ordering};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
@@ -19,6 +18,7 @@ use serde::{de::DeserializeOwned, Serialize};
|
|||||||
use stardust_xr::messenger::MessageSenderHandle;
|
use stardust_xr::messenger::MessageSenderHandle;
|
||||||
use stardust_xr::scenegraph::ScenegraphError;
|
use stardust_xr::scenegraph::ScenegraphError;
|
||||||
use stardust_xr::schemas::flex::{deserialize, serialize};
|
use stardust_xr::schemas::flex::{deserialize, serialize};
|
||||||
|
use std::any::{Any, TypeId};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::os::fd::OwnedFd;
|
use std::os::fd::OwnedFd;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
@@ -29,14 +29,6 @@ use crate::core::registry::Registry;
|
|||||||
use crate::core::scenegraph::MethodResponseSender;
|
use crate::core::scenegraph::MethodResponseSender;
|
||||||
|
|
||||||
use self::alias::Alias;
|
use self::alias::Alias;
|
||||||
use self::audio::Sound;
|
|
||||||
use self::data::{PulseReceiver, PulseSender};
|
|
||||||
use self::drawable::Drawable;
|
|
||||||
use self::fields::Field;
|
|
||||||
use self::input::{InputHandler, InputMethod};
|
|
||||||
use self::items::{Item, ItemAcceptor, ItemUI};
|
|
||||||
use self::spatial::zone::Zone;
|
|
||||||
use self::spatial::Spatial;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Message {
|
pub struct Message {
|
||||||
@@ -71,33 +63,9 @@ pub struct Node {
|
|||||||
// trailing_slash_pos: usize,
|
// trailing_slash_pos: usize,
|
||||||
local_signals: Mutex<FxHashMap<String, Signal>>,
|
local_signals: Mutex<FxHashMap<String, Signal>>,
|
||||||
local_methods: Mutex<FxHashMap<String, Method>>,
|
local_methods: Mutex<FxHashMap<String, Method>>,
|
||||||
destroyable: bool,
|
|
||||||
|
|
||||||
pub alias: OnceCell<Arc<Alias>>,
|
|
||||||
aliases: Registry<Alias>,
|
aliases: Registry<Alias>,
|
||||||
|
aspects: Aspects,
|
||||||
pub spatial: OnceCell<Arc<Spatial>>,
|
destroyable: bool,
|
||||||
pub field: OnceCell<Arc<Field>>,
|
|
||||||
pub zone: OnceCell<Arc<Zone>>,
|
|
||||||
|
|
||||||
// Data
|
|
||||||
pub pulse_sender: OnceCell<Arc<PulseSender>>,
|
|
||||||
pub pulse_receiver: OnceCell<Arc<PulseReceiver>>,
|
|
||||||
|
|
||||||
// Drawable
|
|
||||||
pub drawable: OnceCell<Drawable>,
|
|
||||||
|
|
||||||
// Input
|
|
||||||
pub input_method: OnceCell<Arc<InputMethod>>,
|
|
||||||
pub input_handler: OnceCell<Arc<InputHandler>>,
|
|
||||||
|
|
||||||
// Item
|
|
||||||
pub item: OnceCell<Arc<Item>>,
|
|
||||||
pub item_acceptor: OnceCell<Arc<ItemAcceptor>>,
|
|
||||||
pub item_ui: OnceCell<Arc<ItemUI>>,
|
|
||||||
|
|
||||||
// Sound
|
|
||||||
pub sound: OnceCell<Arc<Sound>>,
|
|
||||||
}
|
}
|
||||||
impl Node {
|
impl Node {
|
||||||
pub fn get_client(&self) -> Option<Arc<Client>> {
|
pub fn get_client(&self) -> Option<Arc<Client>> {
|
||||||
@@ -131,23 +99,9 @@ impl Node {
|
|||||||
// trailing_slash_pos: parent.len(),
|
// trailing_slash_pos: parent.len(),
|
||||||
local_signals: Default::default(),
|
local_signals: Default::default(),
|
||||||
local_methods: Default::default(),
|
local_methods: Default::default(),
|
||||||
|
aliases: Default::default(),
|
||||||
|
aspects: Default::default(),
|
||||||
destroyable,
|
destroyable,
|
||||||
|
|
||||||
alias: OnceCell::new(),
|
|
||||||
aliases: Registry::new(),
|
|
||||||
|
|
||||||
spatial: OnceCell::new(),
|
|
||||||
field: OnceCell::new(),
|
|
||||||
zone: OnceCell::new(),
|
|
||||||
pulse_sender: OnceCell::new(),
|
|
||||||
pulse_receiver: OnceCell::new(),
|
|
||||||
drawable: OnceCell::new(),
|
|
||||||
input_method: OnceCell::new(),
|
|
||||||
input_handler: OnceCell::new(),
|
|
||||||
item: OnceCell::new(),
|
|
||||||
item_acceptor: OnceCell::new(),
|
|
||||||
item_ui: OnceCell::new(),
|
|
||||||
sound: OnceCell::new(),
|
|
||||||
};
|
};
|
||||||
<Node as NodeAspect>::add_node_members(&node);
|
<Node as NodeAspect>::add_node_members(&node);
|
||||||
node
|
node
|
||||||
@@ -186,13 +140,14 @@ impl Node {
|
|||||||
self.local_methods.lock().insert(name.to_string(), method);
|
self.local_methods.lock().insert(name.to_string(), method);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_aspect<F, T>(&self, node_name: &str, aspect_type: &str, aspect_fn: F) -> Result<&T>
|
pub fn add_aspect<A: Aspect>(&self, aspect: A) -> Arc<A> {
|
||||||
where
|
self.aspects.add(aspect)
|
||||||
F: FnOnce(&Node) -> &OnceCell<T>,
|
}
|
||||||
{
|
pub fn add_aspect_raw<A: Aspect>(&self, aspect: Arc<A>) {
|
||||||
aspect_fn(self)
|
self.aspects.add_raw(aspect)
|
||||||
.get()
|
}
|
||||||
.ok_or_else(|| eyre!("{} is not a {} node", node_name, aspect_type))
|
pub fn get_aspect<A: Aspect>(&self) -> Result<Arc<A>> {
|
||||||
|
self.aspects.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_local_signal(
|
pub fn send_local_signal(
|
||||||
@@ -201,7 +156,7 @@ impl Node {
|
|||||||
method: &str,
|
method: &str,
|
||||||
message: Message,
|
message: Message,
|
||||||
) -> Result<(), ScenegraphError> {
|
) -> Result<(), ScenegraphError> {
|
||||||
if let Some(alias) = self.alias.get() {
|
if let Ok(alias) = self.get_aspect::<Alias>() {
|
||||||
if !alias.info.server_signals.iter().any(|e| e == &method) {
|
if !alias.info.server_signals.iter().any(|e| e == &method) {
|
||||||
return Err(ScenegraphError::SignalNotFound);
|
return Err(ScenegraphError::SignalNotFound);
|
||||||
}
|
}
|
||||||
@@ -229,7 +184,7 @@ impl Node {
|
|||||||
message: Message,
|
message: Message,
|
||||||
response: MethodResponseSender,
|
response: MethodResponseSender,
|
||||||
) {
|
) {
|
||||||
if let Some(alias) = self.alias.get() {
|
if let Ok(alias) = self.get_aspect::<Alias>() {
|
||||||
if !alias.info.server_methods.iter().any(|e| e == &method) {
|
if !alias.info.server_methods.iter().any(|e| e == &method) {
|
||||||
response.send(Err(ScenegraphError::MethodNotFound));
|
response.send(Err(ScenegraphError::MethodNotFound));
|
||||||
return;
|
return;
|
||||||
@@ -327,3 +282,36 @@ impl Drop for Node {
|
|||||||
// Debug breakpoint
|
// Debug breakpoint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Aspect: Any + Send + Sync + 'static {
|
||||||
|
const NAME: &'static str;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct Aspects(Mutex<FxHashMap<TypeId, Arc<dyn Any + Send + Sync + 'static>>>);
|
||||||
|
impl Aspects {
|
||||||
|
fn add<A: Aspect>(&self, t: A) -> Arc<A> {
|
||||||
|
let aspect = Arc::new(t);
|
||||||
|
self.add_raw(aspect.clone());
|
||||||
|
aspect
|
||||||
|
}
|
||||||
|
fn add_raw<A: Aspect>(&self, aspect: Arc<A>) {
|
||||||
|
self.0.lock().insert(Self::type_key::<A>(), aspect);
|
||||||
|
}
|
||||||
|
fn get<A: Aspect + Any + Send + Sync + 'static>(&self) -> Result<Arc<A>> {
|
||||||
|
self.0
|
||||||
|
.lock()
|
||||||
|
.get(&Self::type_key::<A>())
|
||||||
|
.and_then(|a| Arc::downcast(a.clone()).ok())
|
||||||
|
.ok_or(eyre!("Couldn't get aspect {}", A::NAME.to_lowercase()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_key<A: 'static>() -> TypeId {
|
||||||
|
TypeId::of::<A>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Drop for Aspects {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.0.lock().clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ impl Root {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_transform(&self, transform: Mat4) {
|
pub fn set_transform(&self, transform: Mat4) {
|
||||||
let spatial = self.node.spatial.get().unwrap();
|
let spatial = self.node.get_aspect::<Spatial>().unwrap();
|
||||||
spatial.set_spatial_parent(None).unwrap();
|
spatial.set_spatial_parent(None).unwrap();
|
||||||
spatial.set_local_transform(transform);
|
spatial.set_local_transform(transform);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
pub mod zone;
|
pub mod zone;
|
||||||
|
|
||||||
use self::zone::Zone;
|
use self::zone::Zone;
|
||||||
use super::fields::get_field;
|
use super::fields::Field;
|
||||||
use super::Node;
|
use super::{Aspect, Node};
|
||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
use crate::core::registry::Registry;
|
use crate::core::registry::Registry;
|
||||||
use crate::create_interface;
|
use crate::create_interface;
|
||||||
use color_eyre::eyre::{ensure, eyre, Result};
|
use color_eyre::eyre::{eyre, Result};
|
||||||
use glam::{vec3a, Mat4, Quat};
|
use glam::{vec3a, Mat4, Quat};
|
||||||
use mint::Vector3;
|
use mint::Vector3;
|
||||||
use nanoid::nanoid;
|
use nanoid::nanoid;
|
||||||
@@ -42,7 +42,6 @@ static ZONEABLE_REGISTRY: Registry<Spatial> = Registry::new();
|
|||||||
pub struct Spatial {
|
pub struct Spatial {
|
||||||
uid: String,
|
uid: String,
|
||||||
pub(super) node: Weak<Node>,
|
pub(super) node: Weak<Node>,
|
||||||
self_ref: Weak<Spatial>,
|
|
||||||
parent: Mutex<Option<Arc<Spatial>>>,
|
parent: Mutex<Option<Arc<Spatial>>>,
|
||||||
old_parent: Mutex<Option<Arc<Spatial>>>,
|
old_parent: Mutex<Option<Arc<Spatial>>>,
|
||||||
pub(super) transform: Mutex<Mat4>,
|
pub(super) transform: Mutex<Mat4>,
|
||||||
@@ -53,10 +52,9 @@ pub struct Spatial {
|
|||||||
|
|
||||||
impl Spatial {
|
impl Spatial {
|
||||||
pub fn new(node: Weak<Node>, parent: Option<Arc<Spatial>>, transform: Mat4) -> Arc<Self> {
|
pub fn new(node: Weak<Node>, parent: Option<Arc<Spatial>>, transform: Mat4) -> Arc<Self> {
|
||||||
Arc::new_cyclic(|self_ref| Spatial {
|
Arc::new(Spatial {
|
||||||
uid: nanoid!(),
|
uid: nanoid!(),
|
||||||
node,
|
node,
|
||||||
self_ref: self_ref.clone(),
|
|
||||||
parent: Mutex::new(parent),
|
parent: Mutex::new(parent),
|
||||||
old_parent: Mutex::new(None),
|
old_parent: Mutex::new(None),
|
||||||
transform: Mutex::new(transform),
|
transform: Mutex::new(transform),
|
||||||
@@ -70,11 +68,7 @@ impl Spatial {
|
|||||||
parent: Option<Arc<Spatial>>,
|
parent: Option<Arc<Spatial>>,
|
||||||
transform: Mat4,
|
transform: Mat4,
|
||||||
zoneable: bool,
|
zoneable: bool,
|
||||||
) -> Result<Arc<Spatial>> {
|
) -> Arc<Spatial> {
|
||||||
ensure!(
|
|
||||||
node.spatial.get().is_none(),
|
|
||||||
"Internal: Node already has a Spatial aspect!"
|
|
||||||
);
|
|
||||||
let spatial = Spatial::new(Arc::downgrade(node), parent.clone(), transform);
|
let spatial = Spatial::new(Arc::downgrade(node), parent.clone(), transform);
|
||||||
<Spatial as SpatialAspect>::add_node_members(node);
|
<Spatial as SpatialAspect>::add_node_members(node);
|
||||||
if zoneable {
|
if zoneable {
|
||||||
@@ -83,8 +77,9 @@ impl Spatial {
|
|||||||
if let Some(parent) = parent {
|
if let Some(parent) = parent {
|
||||||
parent.children.add_raw(&spatial);
|
parent.children.add_raw(&spatial);
|
||||||
}
|
}
|
||||||
let _ = node.spatial.set(spatial.clone());
|
<Spatial as SpatialAspect>::add_node_members(node);
|
||||||
Ok(spatial)
|
node.add_aspect_raw(spatial.clone());
|
||||||
|
spatial
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node(&self) -> Option<Arc<Node>> {
|
pub fn node(&self) -> Option<Arc<Node>> {
|
||||||
@@ -190,23 +185,21 @@ impl Spatial {
|
|||||||
fn get_parent(&self) -> Option<Arc<Spatial>> {
|
fn get_parent(&self) -> Option<Arc<Spatial>> {
|
||||||
self.parent.lock().clone()
|
self.parent.lock().clone()
|
||||||
}
|
}
|
||||||
fn set_parent(&self, new_parent: Option<Arc<Spatial>>) {
|
fn set_parent(self: &Arc<Self>, new_parent: Option<&Arc<Spatial>>) {
|
||||||
if let Some(parent) = self.get_parent() {
|
if let Some(parent) = self.get_parent() {
|
||||||
parent.children.remove(self);
|
parent.children.remove(&self);
|
||||||
}
|
}
|
||||||
if let Some(new_parent) = &new_parent {
|
if let Some(new_parent) = &new_parent {
|
||||||
new_parent
|
new_parent.children.add_raw(self);
|
||||||
.children
|
|
||||||
.add_raw(&self.self_ref.upgrade().unwrap());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*self.parent.lock() = new_parent;
|
*self.parent.lock() = new_parent.cloned();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_spatial_parent(&self, parent: Option<Arc<Spatial>>) -> Result<()> {
|
pub fn set_spatial_parent(self: &Arc<Self>, parent: Option<&Arc<Spatial>>) -> Result<()> {
|
||||||
let is_ancestor = parent
|
let is_ancestor = parent
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|parent| self.is_ancestor_of(parent.clone()))
|
.map(|parent| self.is_ancestor_of((*parent).clone()))
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
if is_ancestor {
|
if is_ancestor {
|
||||||
return Err(eyre!("Setting spatial parent would cause a loop"));
|
return Err(eyre!("Setting spatial parent would cause a loop"));
|
||||||
@@ -215,18 +208,21 @@ impl Spatial {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn set_spatial_parent_in_place(&self, parent: Option<Arc<Spatial>>) -> Result<()> {
|
pub fn set_spatial_parent_in_place(
|
||||||
|
self: &Arc<Self>,
|
||||||
|
parent: Option<&Arc<Spatial>>,
|
||||||
|
) -> Result<()> {
|
||||||
let is_ancestor = parent
|
let is_ancestor = parent
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|parent| self.is_ancestor_of(parent.clone()))
|
.map(|parent| self.is_ancestor_of((*parent).clone()))
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
if is_ancestor {
|
if is_ancestor {
|
||||||
return Err(eyre!("Setting spatial parent would cause a loop"));
|
return Err(eyre!("Setting spatial parent would cause a loop"));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.set_local_transform(Spatial::space_to_space_matrix(
|
self.set_local_transform(Spatial::space_to_space_matrix(
|
||||||
Some(self),
|
Some(&self),
|
||||||
parent.as_deref(),
|
parent.map(AsRef::as_ref),
|
||||||
));
|
));
|
||||||
self.set_parent(parent);
|
self.set_parent(parent);
|
||||||
|
|
||||||
@@ -242,15 +238,15 @@ impl Spatial {
|
|||||||
.unwrap_or(f32::MAX)
|
.unwrap_or(f32::MAX)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Aspect for Spatial {
|
||||||
|
const NAME: &'static str = "Spatial";
|
||||||
|
}
|
||||||
impl SpatialAspect for Spatial {
|
impl SpatialAspect for Spatial {
|
||||||
async fn get_local_bounding_box(
|
async fn get_local_bounding_box(
|
||||||
node: Arc<Node>,
|
node: Arc<Node>,
|
||||||
_calling_client: Arc<Client>,
|
_calling_client: Arc<Client>,
|
||||||
) -> Result<BoundingBox> {
|
) -> Result<BoundingBox> {
|
||||||
let this_spatial = node
|
let this_spatial = node.get_aspect::<Spatial>()?;
|
||||||
.spatial
|
|
||||||
.get()
|
|
||||||
.ok_or_else(|| eyre!("Node doesn't have a spatial?"))?;
|
|
||||||
let bounds = this_spatial.get_bounding_box();
|
let bounds = this_spatial.get_bounding_box();
|
||||||
|
|
||||||
Ok(BoundingBox {
|
Ok(BoundingBox {
|
||||||
@@ -264,11 +260,8 @@ impl SpatialAspect for Spatial {
|
|||||||
_calling_client: Arc<Client>,
|
_calling_client: Arc<Client>,
|
||||||
relative_to: Arc<Node>,
|
relative_to: Arc<Node>,
|
||||||
) -> Result<BoundingBox> {
|
) -> Result<BoundingBox> {
|
||||||
let this_spatial = node
|
let this_spatial = node.get_aspect::<Spatial>()?;
|
||||||
.spatial
|
let relative_spatial = relative_to.get_aspect::<Spatial>()?;
|
||||||
.get()
|
|
||||||
.ok_or_else(|| eyre!("Node doesn't have a spatial?"))?;
|
|
||||||
let relative_spatial = get_spatial(&relative_to, "Relative node")?;
|
|
||||||
let center = Spatial::space_to_space_matrix(Some(&this_spatial), Some(&relative_spatial))
|
let center = Spatial::space_to_space_matrix(Some(&this_spatial), Some(&relative_spatial))
|
||||||
.transform_point3([0.0; 3].into());
|
.transform_point3([0.0; 3].into());
|
||||||
let bounds = Bounds {
|
let bounds = Bounds {
|
||||||
@@ -295,11 +288,8 @@ impl SpatialAspect for Spatial {
|
|||||||
_calling_client: Arc<Client>,
|
_calling_client: Arc<Client>,
|
||||||
relative_to: Arc<Node>,
|
relative_to: Arc<Node>,
|
||||||
) -> Result<Transform> {
|
) -> Result<Transform> {
|
||||||
let this_spatial = node
|
let this_spatial = node.get_aspect::<Spatial>()?;
|
||||||
.spatial
|
let relative_spatial = relative_to.get_aspect::<Spatial>()?;
|
||||||
.get()
|
|
||||||
.ok_or_else(|| eyre!("Node doesn't have a spatial?"))?;
|
|
||||||
let relative_spatial = get_spatial(&relative_to, "Relative node")?;
|
|
||||||
|
|
||||||
let (scale, rotation, position) = Spatial::space_to_space_matrix(
|
let (scale, rotation, position) = Spatial::space_to_space_matrix(
|
||||||
Some(this_spatial.as_ref()),
|
Some(this_spatial.as_ref()),
|
||||||
@@ -319,10 +309,7 @@ impl SpatialAspect for Spatial {
|
|||||||
_calling_client: Arc<Client>,
|
_calling_client: Arc<Client>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let this_spatial = node
|
let this_spatial = node.get_aspect::<Spatial>()?;
|
||||||
.spatial
|
|
||||||
.get()
|
|
||||||
.ok_or_else(|| eyre!("Node doesn't have a spatial?"))?;
|
|
||||||
this_spatial.set_local_transform_components(None, transform);
|
this_spatial.set_local_transform_components(None, transform);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -332,11 +319,8 @@ impl SpatialAspect for Spatial {
|
|||||||
relative_to: Arc<Node>,
|
relative_to: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let this_spatial = node
|
let this_spatial = node.get_aspect::<Spatial>()?;
|
||||||
.spatial
|
let relative_spatial = relative_to.get_aspect::<Spatial>()?;
|
||||||
.get()
|
|
||||||
.ok_or_else(|| eyre!("Node doesn't have a spatial?"))?;
|
|
||||||
let relative_spatial = get_spatial(&relative_to, "Relative node")?;
|
|
||||||
|
|
||||||
this_spatial.set_local_transform_components(Some(&relative_spatial), transform);
|
this_spatial.set_local_transform_components(Some(&relative_spatial), transform);
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -347,13 +331,10 @@ impl SpatialAspect for Spatial {
|
|||||||
_calling_client: Arc<Client>,
|
_calling_client: Arc<Client>,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let this_spatial = node
|
let this_spatial = node.get_aspect::<Spatial>()?;
|
||||||
.spatial
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
.get()
|
|
||||||
.ok_or_else(|| eyre!("Node doesn't have a spatial?"))?;
|
|
||||||
let parent = get_spatial(&parent, "Parent")?;
|
|
||||||
|
|
||||||
this_spatial.set_spatial_parent(Some(parent))?;
|
this_spatial.set_spatial_parent(Some(&parent))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,23 +343,20 @@ impl SpatialAspect for Spatial {
|
|||||||
_calling_client: Arc<Client>,
|
_calling_client: Arc<Client>,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let this_spatial = node
|
let this_spatial = node.get_aspect::<Spatial>()?;
|
||||||
.spatial
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
.get()
|
|
||||||
.ok_or_else(|| eyre!("Node doesn't have a spatial?"))?;
|
|
||||||
let parent = get_spatial(&parent, "Parent")?;
|
|
||||||
|
|
||||||
this_spatial.set_spatial_parent_in_place(Some(parent))?;
|
this_spatial.set_spatial_parent_in_place(Some(&parent))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_zoneable(node: Arc<Node>, _calling_client: Arc<Client>, zoneable: bool) -> Result<()> {
|
fn set_zoneable(node: Arc<Node>, _calling_client: Arc<Client>, zoneable: bool) -> Result<()> {
|
||||||
let spatial = node.spatial.get().unwrap();
|
let spatial = node.get_aspect::<Spatial>()?;
|
||||||
if zoneable {
|
if zoneable {
|
||||||
ZONEABLE_REGISTRY.add_raw(spatial);
|
ZONEABLE_REGISTRY.add_raw(&spatial);
|
||||||
} else {
|
} else {
|
||||||
ZONEABLE_REGISTRY.remove(spatial);
|
ZONEABLE_REGISTRY.remove(&spatial);
|
||||||
zone::release(spatial);
|
zone::release(&spatial);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -400,8 +378,8 @@ impl Debug for Spatial {
|
|||||||
}
|
}
|
||||||
impl Drop for Spatial {
|
impl Drop for Spatial {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
zone::release_drop(self);
|
||||||
ZONEABLE_REGISTRY.remove(self);
|
ZONEABLE_REGISTRY.remove(self);
|
||||||
zone::release(self);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,24 +400,6 @@ pub fn parse_transform(transform: Transform, position: bool, rotation: bool, sca
|
|||||||
Mat4::from_scale_rotation_translation(scale.into(), rotation.into(), position.into())
|
Mat4::from_scale_rotation_translation(scale.into(), rotation.into(), position.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_spatial(
|
|
||||||
calling_client: &Arc<Client>,
|
|
||||||
node_name: &'static str,
|
|
||||||
node_path: &str,
|
|
||||||
) -> Result<Arc<Spatial>> {
|
|
||||||
calling_client
|
|
||||||
.get_node(node_name, node_path)?
|
|
||||||
.get_aspect(node_name, "spatial", |n| &n.spatial)
|
|
||||||
.cloned()
|
|
||||||
}
|
|
||||||
pub fn find_spatial_parent(calling_client: &Arc<Client>, node_path: &str) -> Result<Arc<Spatial>> {
|
|
||||||
find_spatial(calling_client, "Spatial parent", node_path)
|
|
||||||
}
|
|
||||||
pub fn get_spatial(node: &Arc<Node>, node_name: &str) -> Result<Arc<Spatial>> {
|
|
||||||
node.get_aspect(node_name, "spatial", |n| &n.spatial)
|
|
||||||
.cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SpatialInterface;
|
pub struct SpatialInterface;
|
||||||
impl SpatialInterfaceAspect for SpatialInterface {
|
impl SpatialInterfaceAspect for SpatialInterface {
|
||||||
fn create_spatial(
|
fn create_spatial(
|
||||||
@@ -450,11 +410,11 @@ impl SpatialInterfaceAspect for SpatialInterface {
|
|||||||
transform: Transform,
|
transform: Transform,
|
||||||
zoneable: bool,
|
zoneable: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let parent = get_spatial(&parent, "Spatial parent")?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = parse_transform(transform, true, true, true);
|
let transform = parse_transform(transform, true, true, true);
|
||||||
let node = Node::create_parent_name(&calling_client, "/spatial/spatial", &name, true)
|
let node = Node::create_parent_name(&calling_client, "/spatial/spatial", &name, true)
|
||||||
.add_to_scenegraph()?;
|
.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, Some(parent), transform, zoneable)?;
|
Spatial::add_to(&node, Some(parent.clone()), transform, zoneable);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn create_zone(
|
fn create_zone(
|
||||||
@@ -465,13 +425,13 @@ impl SpatialInterfaceAspect for SpatialInterface {
|
|||||||
transform: Transform,
|
transform: Transform,
|
||||||
field: Arc<Node>,
|
field: Arc<Node>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let parent = get_spatial(&parent, "Spatial parent")?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = parse_transform(transform, true, true, false);
|
let transform = parse_transform(transform, true, true, false);
|
||||||
let field = get_field(&field)?;
|
let field = field.get_aspect::<Field>()?;
|
||||||
|
|
||||||
let node = Node::create_parent_name(&calling_client, "/spatial/zone", &name, true)
|
let node = Node::create_parent_name(&calling_client, "/spatial/zone", &name, true)
|
||||||
.add_to_scenegraph()?;
|
.add_to_scenegraph()?;
|
||||||
let space = Spatial::add_to(&node, Some(parent), transform, false)?;
|
let space = Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
Zone::add_to(&node, space, &field);
|
Zone::add_to(&node, space, &field);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use super::{get_spatial, Spatial, ZoneAspect, ZONEABLE_REGISTRY};
|
use super::{Spatial, ZoneAspect, ZONEABLE_REGISTRY};
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{client::Client, registry::Registry},
|
core::{client::Client, registry::Registry},
|
||||||
nodes::{
|
nodes::{
|
||||||
alias::{Alias, AliasInfo},
|
alias::{Alias, AliasInfo},
|
||||||
fields::Field,
|
fields::Field,
|
||||||
Node,
|
Aspect, Node,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use glam::vec3a;
|
use glam::vec3a;
|
||||||
@@ -30,8 +30,8 @@ pub fn capture(spatial: &Arc<Spatial>, zone: &Arc<Zone>) {
|
|||||||
let _ = super::zone_client::capture(&node, &spatial.uid);
|
let _ = super::zone_client::capture(&node, &spatial.uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn release(spatial: &Spatial) {
|
pub fn release(spatial: &Arc<Spatial>) {
|
||||||
let _ = spatial.set_spatial_parent_in_place(spatial.old_parent.lock().take());
|
let _ = spatial.set_spatial_parent_in_place(spatial.old_parent.lock().take().as_ref());
|
||||||
let mut spatial_zone = spatial.zone.lock();
|
let mut spatial_zone = spatial.zone.lock();
|
||||||
if let Some(spatial_zone) = spatial_zone.upgrade() {
|
if let Some(spatial_zone) = spatial_zone.upgrade() {
|
||||||
let Some(node) = spatial_zone.spatial.node.upgrade() else {
|
let Some(node) = spatial_zone.spatial.node.upgrade() else {
|
||||||
@@ -42,6 +42,16 @@ pub fn release(spatial: &Spatial) {
|
|||||||
}
|
}
|
||||||
*spatial_zone = Weak::new();
|
*spatial_zone = Weak::new();
|
||||||
}
|
}
|
||||||
|
pub(super) fn release_drop(spatial: &Spatial) {
|
||||||
|
let spatial_zone = spatial.zone.lock();
|
||||||
|
if let Some(spatial_zone) = spatial_zone.upgrade() {
|
||||||
|
let Some(node) = spatial_zone.spatial.node.upgrade() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
spatial_zone.captured.remove(spatial);
|
||||||
|
let _ = super::zone_client::release(&node, &spatial.uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Zone {
|
pub struct Zone {
|
||||||
spatial: Arc<Spatial>,
|
spatial: Arc<Spatial>,
|
||||||
@@ -58,13 +68,16 @@ impl Zone {
|
|||||||
captured: Registry::new(),
|
captured: Registry::new(),
|
||||||
});
|
});
|
||||||
<Zone as ZoneAspect>::add_node_members(node);
|
<Zone as ZoneAspect>::add_node_members(node);
|
||||||
let _ = node.zone.set(zone.clone());
|
node.add_aspect_raw(zone.clone());
|
||||||
zone
|
zone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Aspect for Zone {
|
||||||
|
const NAME: &'static str = "Zone";
|
||||||
|
}
|
||||||
impl ZoneAspect for Zone {
|
impl ZoneAspect for Zone {
|
||||||
fn update(node: Arc<Node>, _calling_client: Arc<Client>) -> color_eyre::eyre::Result<()> {
|
fn update(node: Arc<Node>, _calling_client: Arc<Client>) -> color_eyre::eyre::Result<()> {
|
||||||
let zone = node.zone.get().unwrap();
|
let zone = node.get_aspect::<Zone>()?;
|
||||||
let Some(field) = zone.field.upgrade() else {
|
let Some(field) = zone.field.upgrade() else {
|
||||||
return Err(color_eyre::eyre::eyre!("Zone's field has been destroyed"));
|
return Err(color_eyre::eyre::eyre!("Zone's field has been destroyed"));
|
||||||
};
|
};
|
||||||
@@ -137,9 +150,9 @@ impl ZoneAspect for Zone {
|
|||||||
_calling_client: Arc<Client>,
|
_calling_client: Arc<Client>,
|
||||||
spatial: Arc<Node>,
|
spatial: Arc<Node>,
|
||||||
) -> color_eyre::eyre::Result<()> {
|
) -> color_eyre::eyre::Result<()> {
|
||||||
let zone = node.zone.get().unwrap();
|
let zone = node.get_aspect::<Zone>()?;
|
||||||
let spatial = get_spatial(&spatial, "Spatial")?;
|
let spatial = spatial.get_aspect()?;
|
||||||
capture(&spatial, zone);
|
capture(&spatial, &zone);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +161,7 @@ impl ZoneAspect for Zone {
|
|||||||
_calling_client: Arc<Client>,
|
_calling_client: Arc<Client>,
|
||||||
spatial: Arc<Node>,
|
spatial: Arc<Node>,
|
||||||
) -> color_eyre::eyre::Result<()> {
|
) -> color_eyre::eyre::Result<()> {
|
||||||
let spatial = get_spatial(&spatial, "Spatial")?;
|
let spatial = spatial.get_aspect()?;
|
||||||
release(&spatial);
|
release(&spatial);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ impl EyePointer {
|
|||||||
pub fn new() -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
let node = Node::create_parent_name(&INTERNAL_CLIENT, "", &nanoid!(), false)
|
let node = Node::create_parent_name(&INTERNAL_CLIENT, "", &nanoid!(), false)
|
||||||
.add_to_scenegraph()?;
|
.add_to_scenegraph()?;
|
||||||
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false).unwrap();
|
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false);
|
||||||
let pointer =
|
let pointer =
|
||||||
InputMethod::add_to(&node, InputType::Pointer(Pointer::default()), None).unwrap();
|
InputMethod::add_to(&node, InputType::Pointer(Pointer::default()), None).unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::{
|
|||||||
data::{
|
data::{
|
||||||
mask_matches, pulse_receiver_client, PulseSender, KEYMAPS, PULSE_RECEIVER_REGISTRY,
|
mask_matches, pulse_receiver_client, PulseSender, KEYMAPS, PULSE_RECEIVER_REGISTRY,
|
||||||
},
|
},
|
||||||
fields::Ray,
|
fields::{Field, Ray},
|
||||||
input::{pointer::Pointer, InputMethod, InputType},
|
input::{pointer::Pointer, InputMethod, InputType},
|
||||||
spatial::Spatial,
|
spatial::Spatial,
|
||||||
Node,
|
Node,
|
||||||
@@ -60,7 +60,7 @@ impl MousePointer {
|
|||||||
pub fn new() -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
let node = Node::create_parent_name(&INTERNAL_CLIENT, "", &nanoid!(), false)
|
let node = Node::create_parent_name(&INTERNAL_CLIENT, "", &nanoid!(), false)
|
||||||
.add_to_scenegraph()?;
|
.add_to_scenegraph()?;
|
||||||
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false).unwrap();
|
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false);
|
||||||
let pointer =
|
let pointer =
|
||||||
InputMethod::add_to(&node, InputType::Pointer(Pointer::default()), None).unwrap();
|
InputMethod::add_to(&node, InputType::Pointer(Pointer::default()), None).unwrap();
|
||||||
|
|
||||||
@@ -140,7 +140,7 @@ impl MousePointer {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|rx| mask_matches(&rx.mask, &self.keyboard_sender.mask))
|
.filter(|rx| mask_matches(&rx.mask, &self.keyboard_sender.mask))
|
||||||
.map(|rx| {
|
.map(|rx| {
|
||||||
let result = rx.field_node.field.get().unwrap().ray_march(Ray {
|
let result = rx.field_node.get_aspect::<Field>().unwrap().ray_march(Ray {
|
||||||
origin: vec3(0.0, 0.0, 0.0),
|
origin: vec3(0.0, 0.0, 0.0),
|
||||||
direction: vec3(0.0, 0.0, -1.0),
|
direction: vec3(0.0, 0.0, -1.0),
|
||||||
space: self.spatial.clone(),
|
space: self.spatial.clone(),
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ impl SkController {
|
|||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
.add_to_scenegraph()?;
|
.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&_node, None, Mat4::IDENTITY, false)?;
|
Spatial::add_to(&_node, None, Mat4::IDENTITY, false);
|
||||||
let model = sk.model_create_mem("cursor.glb", include_bytes!("cursor.glb"), None)?;
|
let model = sk.model_create_mem("cursor.glb", include_bytes!("cursor.glb"), None)?;
|
||||||
let tip = InputType::Tip(Tip::default());
|
let tip = InputType::Tip(Tip::default());
|
||||||
let input = InputMethod::add_to(&_node, tip, None)?;
|
let input = InputMethod::add_to(&_node, tip, None)?;
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ impl SkHand {
|
|||||||
pub fn new(handed: Handed) -> Result<Self> {
|
pub fn new(handed: Handed) -> Result<Self> {
|
||||||
let _node = Node::create_parent_name(&INTERNAL_CLIENT, "", &nanoid!(), false)
|
let _node = Node::create_parent_name(&INTERNAL_CLIENT, "", &nanoid!(), false)
|
||||||
.add_to_scenegraph()?;
|
.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&_node, None, Mat4::IDENTITY, false)?;
|
Spatial::add_to(&_node, None, Mat4::IDENTITY, false);
|
||||||
let hand = InputType::Hand(Box::new(Hand {
|
let hand = InputType::Hand(Box::new(Hand {
|
||||||
base: FlatHand {
|
base: FlatHand {
|
||||||
right: handed == Handed::Right,
|
right: handed == Handed::Right,
|
||||||
|
|||||||
@@ -42,8 +42,9 @@ impl PlaySpace {
|
|||||||
pub fn new() -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
let node = Node::create_parent_name(&INTERNAL_CLIENT, "", &nanoid!(), false)
|
let node = Node::create_parent_name(&INTERNAL_CLIENT, "", &nanoid!(), false)
|
||||||
.add_to_scenegraph()?;
|
.add_to_scenegraph()?;
|
||||||
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false)?;
|
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false);
|
||||||
let field = BoxField::add_to(&node, [0.0; 3].into())?;
|
BoxField::add_to(&node, [0.0; 3].into());
|
||||||
|
let field = node.get_aspect::<Field>()?.clone();
|
||||||
|
|
||||||
let pulse_rx = PulseReceiver::add_to(
|
let pulse_rx = PulseReceiver::add_to(
|
||||||
&node,
|
&node,
|
||||||
|
|||||||
Reference in New Issue
Block a user