refactor: alias_id

This commit is contained in:
Nova
2024-09-11 13:55:15 -04:00
parent 79935befb7
commit 4730f0732b
26 changed files with 467 additions and 356 deletions

4
Cargo.lock generated
View File

@@ -2698,7 +2698,7 @@ checksum = "2f2b15926089e5526bb2dd738a2eb0e59034356e06eb71e1cd912358c0e62c4d"
[[package]]
name = "stardust-xr"
version = "0.45.0"
source = "git+https://github.com/StardustXR/core.git?branch=dev#8313d5ce425dfec9f460526d527536b52d58b963"
source = "git+https://github.com/StardustXR/core.git?branch=dev#22fcdda7937308a067a9f61ecbcffb0907739ecb"
dependencies = [
"cluFlock",
"dirs",
@@ -2718,7 +2718,7 @@ dependencies = [
[[package]]
name = "stardust-xr-schemas"
version = "1.5.3"
source = "git+https://github.com/StardustXR/core.git?branch=dev#8313d5ce425dfec9f460526d527536b52d58b963"
source = "git+https://github.com/StardustXR/core.git?branch=dev#22fcdda7937308a067a9f61ecbcffb0907739ecb"
dependencies = [
"flatbuffers",
"flexbuffers",

View File

@@ -64,11 +64,25 @@ fn codegen_protocol(protocol: &'static str) -> proc_macro::TokenStream {
};
let aspect = generate_aspect(&Aspect {
name: "interface".to_string(),
id: 0,
description: protocol.description.clone(),
inherits: vec![],
members: p.members,
});
quote!(#node_id #aspect)
quote! {
#node_id
#aspect
pub struct Interface;
impl crate::nodes::Aspect for Interface {
impl_aspect_for_interface_aspect!{}
}
pub fn create_interface(client: &std::sync::Arc<crate::core::client::Client>) -> color_eyre::eyre::Result<()>{
let node = crate::nodes::Node::from_id(client,INTERFACE_NODE_ID,false);
node.add_aspect(Interface);
node.add_to_scenegraph()?;
Ok(())
}
}
})
.unwrap_or_default();
let custom_enums = protocol
@@ -177,7 +191,7 @@ fn generate_aspect(aspect: &Aspect) -> TokenStream {
Span::call_site(),
);
let client_side_members = client_members
.map(generate_member)
.map(|m| generate_member(aspect.id, m))
.reduce(fold_tokens)
.map(|t| {
// TODO: properly import all dependencies
@@ -190,11 +204,6 @@ fn generate_aspect(aspect: &Aspect) -> TokenStream {
})
.unwrap_or_default();
let aspect_trait_name = Ident::new(
&format!("{}Aspect", &aspect.name.to_case(Case::Pascal)),
Span::call_site(),
);
let opcodes = aspect
.members
.iter()
@@ -219,31 +228,87 @@ fn generate_aspect(aspect: &Aspect) -> TokenStream {
let alias_info = generate_alias_info(aspect);
let server_side_members = server_members
.map(generate_member)
.map(|m| generate_member(aspect.id, m))
.reduce(fold_tokens)
.unwrap_or_default();
let add_node_members = aspect
let aspect_trait_name = Ident::new(
&format!("{}Aspect", &aspect.name.to_case(Case::Pascal)),
Span::call_site(),
);
let run_signals = aspect
.members
.iter()
.filter(|m| m.side == Side::Server)
.map(generate_handler)
.filter(|m| m._type == MemberType::Signal)
.map(|m| generate_run_member(&aspect_trait_name, MemberType::Signal, m))
.reduce(fold_tokens)
.unwrap_or_default();
let run_methods = aspect
.members
.iter()
.filter(|m| m.side == Side::Server)
.filter(|m| m._type == MemberType::Method)
.map(|m| generate_run_member(&aspect_trait_name, MemberType::Method, m))
.reduce(fold_tokens)
.map(|members| {
quote! {
fn add_node_members(node: &crate::nodes::Node) {
#members
}
}
})
.unwrap_or_default();
let server_side_members = quote! {
#[doc = #description]
pub trait #aspect_trait_name {
#add_node_members
#server_side_members
}
};
quote!(#opcodes #alias_info #client_side_members #server_side_members)
let aspect_name = aspect.name.to_case(Case::Camel);
let aspect_macro_name = Ident::new(
&format!(
"impl_aspect_for_{}_aspect",
aspect.name.to_case(Case::Snake)
),
Span::call_site(),
);
let aspect_id = aspect.id;
let aspect_macro = quote! {
macro_rules! #aspect_macro_name {
() => {
fn name(&self) -> String {
#aspect_name.to_string()
}
fn id(&self) -> u64 {
#aspect_id
}
fn as_any(self: Arc<Self>) -> Arc<dyn std::any::Any + Send + Sync + 'static> {
self
}
fn run_signal(
&self,
_calling_client: std::sync::Arc<crate::core::client::Client>,
_node: std::sync::Arc<crate::nodes::Node>,
_signal: u64,
_message: crate::nodes::Message
) -> Result<(), stardust_xr::scenegraph::ScenegraphError> {
match _signal {
#run_signals
_ => Err(stardust_xr::scenegraph::ScenegraphError::SignalNotFound)
}
}
fn run_method(
&self,
_calling_client: std::sync::Arc<crate::core::client::Client>,
_node: std::sync::Arc<crate::nodes::Node>,
_method: u64,
_message: crate::nodes::Message,
_method_response: crate::nodes::MethodResponseSender,
) {
match _method {
#run_methods
_ => {
let _ = _method_response.send(Err(stardust_xr::scenegraph::ScenegraphError::MethodNotFound));
}
}
}
};
}
};
quote!(#opcodes #alias_info #client_side_members #server_side_members #aspect_macro)
}
fn generate_alias_opcodes(aspect: &Aspect, side: Side, _type: MemberType) -> TokenStream {
@@ -293,8 +358,8 @@ fn generate_alias_info(aspect: &Aspect) -> TokenStream {
}
}
fn generate_member(member: &Member) -> TokenStream {
let id = member.opcode;
fn generate_member(aspect_id: u64, member: &Member) -> TokenStream {
let opcode = member.opcode;
let name = Ident::new(&member.name.to_case(Case::Snake), Span::call_site());
let description = &member.description;
@@ -326,27 +391,21 @@ fn generate_member(member: &Member) -> TokenStream {
.unwrap_or_else(|| quote!(()));
match (side, _type) {
(Side::Client, MemberType::Method) => {
quote! {
#[doc = #description]
pub async fn #name(#argument_decls) -> color_eyre::eyre::Result<(#return_type, Vec<std::os::fd::OwnedFd>)> {
_node.execute_remote_method_typed(#id, &(#argument_uses), vec![]).await
}
}
}
(Side::Client, MemberType::Signal) => {
quote! {
#[doc = #description]
pub fn #name(#argument_decls) -> color_eyre::eyre::Result<()> {
let serialized = stardust_xr::schemas::flex::serialize((#argument_uses))?;
_node.send_remote_signal(#id, serialized)
_node.send_remote_signal(#aspect_id, #opcode, serialized)
}
}
}
(Side::Server, MemberType::Method) => {
(Side::Client, MemberType::Method) => {
quote! {
#[doc = #description]
fn #name(#argument_decls) -> impl std::future::Future<Output = color_eyre::eyre::Result<#return_type>> + Send + 'static;
pub async fn #name(#argument_decls) -> color_eyre::eyre::Result<(#return_type, Vec<std::os::fd::OwnedFd>)> {
_node.execute_remote_method_typed(#aspect_id, #opcode, &(#argument_uses), vec![]).await
}
}
}
(Side::Server, MemberType::Signal) => {
@@ -355,9 +414,15 @@ fn generate_member(member: &Member) -> TokenStream {
fn #name(#argument_decls) -> color_eyre::eyre::Result<()>;
}
}
(Side::Server, MemberType::Method) => {
quote! {
#[doc = #description]
fn #name(#argument_decls) -> impl std::future::Future<Output = color_eyre::eyre::Result<#return_type>> + Send + Sync + 'static;
}
}
}
}
fn generate_handler(member: &Member) -> TokenStream {
fn generate_run_member(aspect_name: &Ident, _type: MemberType, member: &Member) -> TokenStream {
let opcode = member.opcode;
let member_name_ident = Ident::new(&member.name, Span::call_site());
@@ -393,21 +458,19 @@ fn generate_handler(member: &Member) -> TokenStream {
.map(|a| generate_argument_deserialize(&a.name, &a._type, a.optional))
.reduce(|a, b| quote!(#a, #b))
.unwrap_or_default();
match member._type {
match _type {
MemberType::Signal => quote! {
node.add_local_signal(#opcode, |_node, _calling_client, _message| {
#opcode => (move || {
#deserialize
Self::#member_name_ident(_node, _calling_client.clone(), #argument_uses)
});
<Self as #aspect_name>::#member_name_ident(_node, _calling_client.clone(), #argument_uses)
})().map_err(|e: color_eyre::Report| stardust_xr::scenegraph::ScenegraphError::SignalError { error: e.to_string() }),
},
MemberType::Method => quote! {
node.add_local_method(#opcode, |_node, _calling_client, _message, _method_response| {
_method_response.wrap_async(async move {
#deserialize
let result = Self::#member_name_ident(_node, _calling_client.clone(), #argument_uses).await?;
Ok((#serialize, Vec::new()))
});
});
#opcode => _method_response.wrap_async(async move {
#deserialize
let result = <Self as #aspect_name>::#member_name_ident(_node, _calling_client.clone(), #argument_uses).await?;
Ok((#serialize, Vec::<std::os::fd::OwnedFd>::new()))
}),
},
}
}

View File

@@ -1,11 +0,0 @@
#[macro_export]
macro_rules! create_interface {
($iface:ident) => {
pub fn create_interface(client: &Arc<Client>) -> Result<()> {
let node = Node::from_id(client, INTERFACE_NODE_ID, false);
<$iface as self::InterfaceAspect>::add_node_members(&node);
node.add_to_scenegraph()?;
Ok(())
}
};
}

View File

@@ -2,7 +2,6 @@ pub mod client;
pub mod client_state;
pub mod delta;
pub mod destroy_queue;
pub mod idl_utils;
pub mod registry;
pub mod resource;
pub mod scenegraph;

View File

@@ -86,19 +86,21 @@ fn map_method_return<T: Serialize>(
impl scenegraph::Scenegraph for Scenegraph {
fn send_signal(
&self,
node: u64,
node_id: u64,
aspect_id: u64,
method: u64,
data: &[u8],
fds: Vec<OwnedFd>,
) -> Result<(), ScenegraphError> {
let Some(client) = self.get_client() else {
return Err(ScenegraphError::SignalNotFound);
return Err(ScenegraphError::NodeNotFound);
};
debug_span!("Handle signal", node, method).in_scope(|| {
self.get_node(node)
debug_span!("Handle signal", aspect_id, node_id, method).in_scope(|| {
self.get_node(node_id)
.ok_or(ScenegraphError::NodeNotFound)?
.send_local_signal(
client,
aspect_id,
method,
Message {
data: data.to_vec(),
@@ -109,23 +111,25 @@ impl scenegraph::Scenegraph for Scenegraph {
}
fn execute_method(
&self,
node: u64,
node_id: u64,
aspect_id: u64,
method: u64,
data: &[u8],
fds: Vec<OwnedFd>,
response: oneshot::Sender<Result<(Vec<u8>, Vec<OwnedFd>), ScenegraphError>>,
) {
let Some(client) = self.get_client() else {
let _ = response.send(Err(ScenegraphError::MethodNotFound));
let _ = response.send(Err(ScenegraphError::NodeNotFound));
return;
};
debug!(node, method, "Handle method");
let Some(node) = self.get_node(node) else {
debug!(aspect_id, node_id, method, "Handle method");
let Some(node) = self.get_node(node_id) else {
let _ = response.send(Err(ScenegraphError::NodeNotFound));
return;
};
node.execute_local_method(
client,
aspect_id,
method,
Message {
data: data.to_vec(),

View File

@@ -262,8 +262,6 @@ fn stereokit_loop(
}
info!("Cleanly shut down StereoKit");
#[cfg(feature = "wayland")]
drop(wayland);
}
fn adaptive_sleep(

View File

@@ -69,7 +69,33 @@ impl Alias {
}
}
impl Aspect for Alias {
const NAME: &'static str = "Alias";
fn name(&self) -> String {
"Alias".to_string()
}
fn id(&self) -> u64 {
0
}
fn as_any(self: Arc<Self>) -> Arc<dyn std::any::Any + Send + Sync + 'static> {
self
}
fn run_signal(
&self,
_calling_client: Arc<Client>,
_node: Arc<Node>,
_signal: u64,
_message: super::Message,
) -> Result<(), stardust_xr::scenegraph::ScenegraphError> {
Ok(())
}
fn run_method(
&self,
_calling_client: Arc<Client>,
_node: Arc<Node>,
_method: u64,
_message: super::Message,
_response: crate::core::scenegraph::MethodResponseSender,
) {
}
}
pub fn get_original(node: Arc<Node>, stop_on_disabled: bool) -> Option<Arc<Node>> {

View File

@@ -3,9 +3,7 @@ use crate::core::client::Client;
use crate::core::destroy_queue;
use crate::core::registry::Registry;
use crate::core::resource::get_resource_file;
use crate::create_interface;
use crate::nodes::spatial::SPATIAL_ASPECT_ALIAS_INFO;
use crate::nodes::spatial::{Spatial, Transform};
use crate::nodes::spatial::{Spatial, Transform, SPATIAL_ASPECT_ALIAS_INFO};
use color_eyre::eyre::{eyre, Result};
use glam::{vec3, Vec4Swizzles};
use once_cell::sync::OnceCell;
@@ -49,7 +47,6 @@ impl Sound {
};
let sound_arc = SOUND_REGISTRY.add(sound);
node.add_aspect_raw(sound_arc.clone());
<Sound as SoundAspect>::add_node_members(node);
Ok(sound_arc)
}
@@ -72,7 +69,7 @@ impl Sound {
}
}
impl Aspect for Sound {
const NAME: &'static str = "Sound";
impl_aspect_for_sound_aspect! {}
}
impl SoundAspect for Sound {
fn play(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<()> {
@@ -101,9 +98,7 @@ pub fn update() {
}
}
create_interface!(AudioInterface);
struct AudioInterface;
impl InterfaceAspect for AudioInterface {
impl InterfaceAspect for Interface {
#[doc = "Create a sound node. WAV and MP3 are supported."]
fn create_sound(
_node: Arc<Node>,

View File

@@ -4,7 +4,6 @@ use super::spatial::{parse_transform, Spatial};
use super::{Alias, Aspect, Node};
use crate::core::client::Client;
use crate::core::registry::Registry;
use crate::create_interface;
use crate::nodes::fields::FIELD_ALIAS_INFO;
use crate::nodes::spatial::Transform;
use crate::nodes::spatial::SPATIAL_ASPECT_ALIAS_INFO;
@@ -71,7 +70,6 @@ impl PulseSender {
field_aliases: AliasList::default(),
};
// <PulseSender as PulseSenderAspect>::add_node_members(node);
let sender = PULSE_SENDER_REGISTRY.add(sender);
node.add_aspect_raw(sender.clone());
for receiver in PULSE_RECEIVER_REGISTRY.get_valid_contents() {
@@ -134,7 +132,7 @@ impl PulseSender {
}
}
impl Aspect for PulseSender {
const NAME: &'static str = "PulseSender";
impl_aspect_for_pulse_sender_aspect! {}
}
impl PulseSenderAspect for PulseSender {}
impl Drop for PulseSender {
@@ -161,7 +159,6 @@ impl PulseReceiver {
};
let receiver = PULSE_RECEIVER_REGISTRY.add(receiver);
<PulseReceiver as PulseReceiverAspect>::add_node_members(node);
node.add_aspect_raw(receiver.clone());
for sender in PULSE_SENDER_REGISTRY.get_valid_contents() {
sender.handle_new_receiver(&receiver);
@@ -170,7 +167,7 @@ impl PulseReceiver {
}
}
impl Aspect for PulseReceiver {
const NAME: &'static str = "PulseReceiver";
impl_aspect_for_pulse_receiver_aspect! {}
}
impl PulseReceiverAspect for PulseReceiver {
fn send_data(
@@ -199,9 +196,7 @@ impl Drop for PulseReceiver {
}
}
create_interface!(DataInterface);
struct DataInterface;
impl InterfaceAspect for DataInterface {
impl InterfaceAspect for Interface {
fn create_pulse_sender(
_node: Arc<Node>,
calling_client: Arc<Client>,

View File

@@ -1,7 +1,7 @@
use super::{Line, LinesAspect};
use crate::{
core::{client::Client, registry::Registry},
nodes::{spatial::Spatial, Aspect, Node},
nodes::{spatial::Spatial, Node},
};
use color_eyre::eyre::Result;
use glam::Vec3;
@@ -40,7 +40,6 @@ impl Lines {
space: node.get_aspect::<Spatial>()?.clone(),
data: Mutex::new(lines),
});
<Lines as LinesAspect>::add_node_members(node);
node.add_aspect_raw(lines.clone());
Ok(lines)
@@ -83,9 +82,6 @@ impl Lines {
}
}
}
impl Aspect for Lines {
const NAME: &'static str = "Lines";
}
impl LinesAspect for Lines {
fn set_lines(node: Arc<Node>, _calling_client: Arc<Client>, lines: Vec<Line>) -> Result<()> {
let lines_aspect = node.get_aspect::<Lines>()?;

View File

@@ -8,14 +8,12 @@ pub mod text;
use self::{lines::Lines, model::Model, text::Text};
use super::{
spatial::{Spatial, Transform},
Node,
Aspect, Node,
};
use crate::core::{client::Client, resource::get_resource_file};
use crate::nodes::spatial::SPATIAL_ASPECT_ALIAS_INFO;
use crate::{
core::{client::Client, resource::get_resource_file},
create_interface,
};
use color_eyre::eyre::{self, Result};
use model::ModelPart;
use parking_lot::Mutex;
use stardust_xr::values::ResourceID;
use std::{ffi::OsStr, path::PathBuf, sync::Arc};
@@ -43,10 +41,20 @@ static QUEUED_SKYLIGHT: Mutex<Option<PathBuf>> = Mutex::new(None);
static QUEUED_SKYTEX: Mutex<Option<PathBuf>> = Mutex::new(None);
stardust_xr_server_codegen::codegen_drawable_protocol!();
create_interface!(DrawableInterface);
impl Aspect for Lines {
impl_aspect_for_lines_aspect! {}
}
impl Aspect for Model {
impl_aspect_for_model_aspect! {}
}
impl Aspect for ModelPart {
impl_aspect_for_model_part_aspect! {}
}
impl Aspect for Text {
impl_aspect_for_text_aspect! {}
}
pub struct DrawableInterface;
impl InterfaceAspect for DrawableInterface {
impl InterfaceAspect for Interface {
fn set_sky_tex(_node: Arc<Node>, calling_client: Arc<Client>, tex: ResourceID) -> Result<()> {
let resource_path = get_resource_file(&tex, &calling_client, &[OsStr::new("hdr")])
.ok_or(eyre::eyre!("Could not find resource"))?;

View File

@@ -4,7 +4,7 @@ use crate::core::registry::Registry;
use crate::core::resource::get_resource_file;
use crate::nodes::alias::{Alias, AliasList};
use crate::nodes::spatial::Spatial;
use crate::nodes::{Aspect, Node};
use crate::nodes::Node;
use color_eyre::eyre::{bail, eyre, Result};
use glam::{Mat4, Vec2, Vec3};
use once_cell::sync::{Lazy, OnceCell};
@@ -204,7 +204,6 @@ impl ModelPart {
pending_material_replacement: Mutex::new(None),
aliases: AliasList::default(),
});
<ModelPart as ModelPartAspect>::add_node_members(&node);
node.add_aspect_raw(model_part.clone());
parts.push(model_part.clone());
Some(model_part)
@@ -278,9 +277,6 @@ impl ModelPart {
}
}
}
impl Aspect for ModelPart {
const NAME: &'static str = "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."]
fn apply_holdout_material(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<()> {
@@ -327,7 +323,6 @@ impl Model {
sk_model: OnceCell::new(),
parts: Mutex::new(Vec::default()),
});
<Model as ModelAspect>::add_node_members(node);
MODEL_REGISTRY.add_raw(&model);
// technically doing this in anything but the main thread isn't a good idea but dangit we need those model nodes ASAP
@@ -361,9 +356,6 @@ impl Model {
// TODO: proper hread safety in stereokit_rust (probably just bind stereokit directly)
unsafe impl Send for Model {}
unsafe impl Sync for Model {}
impl Aspect for Model {
const NAME: &'static str = "Model";
}
impl ModelAspect for Model {
#[doc = "Bind a model part to the node with the ID input."]
fn bind_model_part(

View File

@@ -1,6 +1,6 @@
use crate::{
core::{client::Client, destroy_queue, registry::Registry, resource::get_resource_file},
nodes::{spatial::Spatial, Aspect, Node},
nodes::{spatial::Spatial, Node},
};
use color_eyre::eyre::{eyre, Result};
use glam::{vec3, Mat4, Vec2};
@@ -53,7 +53,6 @@ impl Text {
text: Mutex::new(text),
data: Mutex::new(style),
});
<Text as TextAspect>::add_node_members(node);
node.add_aspect_raw(text.clone());
Ok(text)
@@ -132,9 +131,6 @@ impl Text {
}
}
}
impl Aspect for Text {
const NAME: &'static str = "Text";
}
impl TextAspect for Text {
fn set_character_height(
node: Arc<Node>,

View File

@@ -5,7 +5,6 @@ use super::spatial::{
};
use super::{Aspect, Node};
use crate::core::client::Client;
use crate::create_interface;
use crate::nodes::spatial::Transform;
use crate::nodes::spatial::SPATIAL_ASPECT_ALIAS_INFO;
use crate::nodes::spatial::SPATIAL_REF_ASPECT_ALIAS_INFO;
@@ -145,15 +144,59 @@ impl Field {
shape: Mutex::new(shape),
};
let field = node.add_aspect(field);
<Field as FieldRefAspect>::add_node_members(node);
<Field as FieldAspect>::add_node_members(node);
node.add_aspect(FieldRef);
Ok(field)
}
}
impl Aspect for Field {
const NAME: &'static str = "Field";
impl_aspect_for_field_aspect! {}
}
impl FieldRefAspect for Field {
impl FieldAspect for Field {
fn set_shape(node: Arc<Node>, _calling_client: Arc<Client>, shape: Shape) -> Result<()> {
let field = node.get_aspect::<Field>()?;
*field.shape.lock() = shape;
Ok(())
}
async fn export_field(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<u64> {
let id = rand::random();
EXPORTED_FIELDS.lock().insert(id, node);
Ok(id)
}
}
impl FieldTrait for Field {
fn spatial_ref(&self) -> &Spatial {
&self.spatial
}
fn local_distance(&self, p: Vec3A) -> f32 {
match self.shape.lock().clone() {
Shape::Box(size) => {
let q = vec3(
p.x.abs() - (size.x * 0.5_f32),
p.y.abs() - (size.y * 0.5_f32),
p.z.abs() - (size.z * 0.5_f32),
);
let v = vec3a(q.x.max(0_f32), q.y.max(0_f32), q.z.max(0_f32));
v.length() + q.x.max(q.y.max(q.z)).min(0_f32)
}
Shape::Cylinder(CylinderShape { length, radius }) => {
let d = vec2(p.xy().length().abs() - radius, p.z.abs() - (length * 0.5));
d.x.max(d.y).min(0.0) + d.max(vec2(0.0, 0.0)).length()
}
Shape::Sphere(radius) => p.length() - radius,
Shape::Torus(TorusShape { radius_a, radius_b }) => {
let q = vec2(p.xz().length() - radius_a, p.y);
q.length() - radius_b
}
}
}
}
pub struct FieldRef;
impl Aspect for FieldRef {
impl_aspect_for_field_ref_aspect! {}
}
impl FieldRefAspect for FieldRef {
async fn distance(
node: Arc<Node>,
_calling_client: Arc<Client>,
@@ -205,50 +248,8 @@ impl FieldRefAspect for Field {
}))
}
}
impl FieldAspect for Field {
fn set_shape(node: Arc<Node>, _calling_client: Arc<Client>, shape: Shape) -> Result<()> {
let field = node.get_aspect::<Field>()?;
*field.shape.lock() = shape;
Ok(())
}
async fn export_field(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<u64> {
let id = rand::random();
EXPORTED_FIELDS.lock().insert(id, node);
Ok(id)
}
}
impl FieldTrait for Field {
fn spatial_ref(&self) -> &Spatial {
&self.spatial
}
fn local_distance(&self, p: Vec3A) -> f32 {
match self.shape.lock().clone() {
Shape::Box(size) => {
let q = vec3(
p.x.abs() - (size.x * 0.5_f32),
p.y.abs() - (size.y * 0.5_f32),
p.z.abs() - (size.z * 0.5_f32),
);
let v = vec3a(q.x.max(0_f32), q.y.max(0_f32), q.z.max(0_f32));
v.length() + q.x.max(q.y.max(q.z)).min(0_f32)
}
Shape::Cylinder(CylinderShape { length, radius }) => {
let d = vec2(p.xy().length().abs() - radius, p.z.abs() - (length * 0.5));
d.x.max(d.y).min(0.0) + d.max(vec2(0.0, 0.0)).length()
}
Shape::Sphere(radius) => p.length() - radius,
Shape::Torus(TorusShape { radius_a, radius_b }) => {
let q = vec2(p.xz().length() - radius_a, p.y);
q.length() - radius_b
}
}
}
}
create_interface!(FieldInterface);
pub struct FieldInterface;
impl InterfaceAspect for FieldInterface {
impl InterfaceAspect for Interface {
async fn import_field_ref(
_node: Arc<Node>,
calling_client: Arc<Client>,

View File

@@ -1,5 +1,5 @@
use super::{InputHandlerAspect, INPUT_HANDLER_REGISTRY, INPUT_METHOD_REGISTRY};
use crate::nodes::{alias::AliasList, fields::Field, spatial::Spatial, Aspect, Node};
use crate::nodes::{alias::AliasList, fields::Field, spatial::Spatial, Node};
use color_eyre::eyre::Result;
use std::sync::Arc;
@@ -23,9 +23,6 @@ impl InputHandler {
Ok(())
}
}
impl Aspect for InputHandler {
const NAME: &'static str = "InputHandler";
}
impl InputHandlerAspect for InputHandler {}
impl PartialEq for InputHandler {
fn eq(&self, other: &Self) -> bool {

View File

@@ -9,7 +9,7 @@ use crate::{
alias::{Alias, AliasList},
fields::{Field, FIELD_ALIAS_INFO},
spatial::Spatial,
Aspect, Node,
Node,
},
};
use color_eyre::eyre::Result;
@@ -45,13 +45,12 @@ impl InputMethod {
internal_capture_requests: Registry::new(),
captures: Registry::new(),
};
<InputMethod as InputMethodRefAspect>::add_node_members(node);
<InputMethod as InputMethodAspect>::add_node_members(node);
for handler in INPUT_HANDLER_REGISTRY.get_valid_contents() {
method.handle_new_handler(&handler);
}
let method = INPUT_METHOD_REGISTRY.add(method);
node.add_aspect_raw(method.clone());
node.add_aspect(InputMethodRef);
Ok(method)
}
@@ -154,25 +153,6 @@ impl InputMethod {
}
}
}
impl Aspect for InputMethod {
const NAME: &'static str = "InputMethod";
}
impl InputMethodRefAspect for InputMethod {
#[doc = "Have the input handler that this method reference came from capture the method for the next frame."]
fn request_capture(
node: Arc<Node>,
_calling_client: Arc<Client>,
handler: Arc<Node>,
) -> Result<()> {
let input_method = node.get_aspect::<InputMethod>()?;
let input_handler = handler.get_aspect::<InputHandler>()?;
input_method
.internal_capture_requests
.add_raw(&input_handler);
Ok(())
}
}
impl InputMethodAspect for InputMethod {
#[doc = "Set the spatial input component of this input method. You must keep the same input data type throughout the entire thing."]
fn set_input(
@@ -231,3 +211,21 @@ impl Drop for InputMethod {
INPUT_METHOD_REGISTRY.remove(self);
}
}
pub struct InputMethodRef;
impl InputMethodRefAspect for InputMethodRef {
#[doc = "Have the input handler that this method reference came from capture the method for the next frame."]
fn request_capture(
node: Arc<Node>,
_calling_client: Arc<Client>,
handler: Arc<Node>,
) -> Result<()> {
let input_method = node.get_aspect::<InputMethod>()?;
let input_handler = handler.get_aspect::<InputHandler>()?;
input_method
.internal_capture_requests
.add_raw(&input_handler);
Ok(())
}
}

View File

@@ -11,7 +11,7 @@ pub use method::*;
use super::fields::Field;
use super::spatial::Spatial;
use crate::create_interface;
use super::Aspect;
use crate::nodes::spatial::SPATIAL_ASPECT_ALIAS_INFO;
use crate::nodes::spatial::SPATIAL_REF_ASPECT_ALIAS_INFO;
use crate::{core::client::Client, nodes::Node};
@@ -25,6 +25,16 @@ pub static INPUT_HANDLER_REGISTRY: Registry<InputHandler> = Registry::new();
stardust_xr_server_codegen::codegen_input_protocol!();
impl Aspect for InputHandler {
impl_aspect_for_input_handler_aspect! {}
}
impl Aspect for InputMethod {
impl_aspect_for_input_method_aspect! {}
}
impl Aspect for InputMethodRef {
impl_aspect_for_input_method_ref_aspect! {}
}
pub trait InputDataTrait {
fn transform(&mut self, method: &InputMethod, handler: &InputHandler);
fn distance(&self, space: &Arc<Spatial>, field: &Field) -> f32;
@@ -47,9 +57,7 @@ impl InputDataTrait for InputDataType {
}
}
create_interface!(InputInterface);
pub struct InputInterface;
impl InterfaceAspect for InputInterface {
impl InterfaceAspect for Interface {
#[doc = "Create an input method node"]
fn create_input_method(
_node: Arc<Node>,

View File

@@ -1,11 +1,9 @@
use super::{
create_item_acceptor_flex, register_item_ui_flex, Item, ItemAcceptor, ItemInterface, ItemType,
};
use super::{create_item_acceptor_flex, register_item_ui_flex, Item, ItemType};
use crate::nodes::items::ITEM_ACCEPTOR_ASPECT_ALIAS_INFO;
use crate::nodes::items::ITEM_ASPECT_ALIAS_INFO;
use crate::nodes::Aspect;
use crate::{
core::{client::Client, registry::Registry, scenegraph::MethodResponseSender},
create_interface,
nodes::{
drawable::{
model::{MaterialWrapper, ModelPart},
@@ -48,6 +46,12 @@ lazy_static! {
ui: Default::default(),
items: Registry::new(),
acceptors: Registry::new(),
add_acceptor_aspect: |node| {
node.add_aspect(CameraItemAcceptor);
},
add_ui_aspect: |node| {
node.add_aspect(CameraItemUi);
},
new_acceptor_fn: |node, acceptor, acceptor_field| {
let _ = camera_item_ui_client::create_acceptor(node, acceptor, acceptor_field);
}
@@ -85,7 +89,7 @@ impl CameraItem {
apply_to: Registry::new(),
}),
);
// <CameraItem as CameraItemAspect>::node_methods(node);
node.add_aspect(CameraItemUi);
}
fn frame_flex(
@@ -169,7 +173,17 @@ impl CameraItem {
}
impl CameraItemAspect for CameraItem {}
impl CameraItemAcceptorAspect for ItemAcceptor {
pub struct CameraItemUi;
impl Aspect for CameraItemUi {
impl_aspect_for_camera_item_ui_aspect! {}
}
impl CameraItemUiAspect for CameraItemUi {}
pub struct CameraItemAcceptor;
impl Aspect for CameraItemAcceptor {
impl_aspect_for_camera_item_acceptor_aspect! {}
}
impl CameraItemAcceptorAspect for CameraItemAcceptor {
fn capture_item(node: Arc<Node>, _calling_client: Arc<Client>, item: Arc<Node>) -> Result<()> {
super::acceptor_capture_item_flex(node, item)
}
@@ -184,8 +198,7 @@ pub fn update(token: &MainThreadToken) {
}
}
create_interface!(ItemInterface);
impl InterfaceAspect for ItemInterface {
impl InterfaceAspect for Interface {
#[doc = "Create a camera item at a specific location"]
fn create_camera_item(
_node: Arc<Node>,
@@ -206,19 +219,21 @@ impl InterfaceAspect for ItemInterface {
}
#[doc = "Register this client to manage camera items and create default 3D UI for them."]
fn register_camera_item_ui(_node: Arc<Node>, calling_client: Arc<Client>) -> Result<()> {
fn register_camera_item_ui(node: Arc<Node>, calling_client: Arc<Client>) -> Result<()> {
node.add_aspect(CameraItemUi);
register_item_ui_flex(calling_client, &ITEM_TYPE_INFO_CAMERA)
}
#[doc = "Create an item acceptor to allow temporary ownership of a given type of item. Creates a node at `/item/camera/acceptor/<name>`."]
fn create_camera_item_acceptor(
_node: Arc<Node>,
node: Arc<Node>,
calling_client: Arc<Client>,
id: u64,
parent: Arc<Node>,
transform: Transform,
field: Arc<Node>,
) -> Result<()> {
node.add_aspect(CameraItemAcceptor);
create_item_acceptor_flex(
calling_client,
id,

View File

@@ -47,6 +47,8 @@ pub struct TypeInfo {
pub ui: Mutex<Weak<ItemUI>>,
pub items: Registry<Item>,
pub acceptors: Registry<ItemAcceptor>,
pub add_ui_aspect: fn(node: &Node),
pub add_acceptor_aspect: fn(node: &Node),
pub new_acceptor_fn: fn(node: &Node, acceptor: &Arc<Node>, acceptor_field: &Arc<Node>),
}
impl Hash for TypeInfo {
@@ -81,7 +83,6 @@ impl Item {
};
let item = type_info.items.add(item);
<Item as ItemAspect>::add_node_members(node);
if let Some(ui) = type_info.ui.lock().upgrade() {
ui.handle_create_item(&item);
}
@@ -109,7 +110,7 @@ impl Item {
}
}
impl Aspect for Item {
const NAME: &'static str = "Item";
impl_aspect_for_item_aspect! {}
}
impl ItemAspect for Item {
fn release(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<()> {
@@ -285,7 +286,7 @@ impl ItemUI {
}
}
impl Aspect for ItemUI {
const NAME: &'static str = "Item";
impl_aspect_for_item_ui_aspect! {}
}
impl Drop for ItemUI {
fn drop(&mut self) {
@@ -343,7 +344,7 @@ impl ItemAcceptor {
}
}
impl Aspect for ItemAcceptor {
const NAME: &'static str = "ItemAcceptor";
impl_aspect_for_item_acceptor_aspect! {}
}
impl ItemAcceptorAspect for ItemAcceptor {}
impl Drop for ItemAcceptor {
@@ -364,6 +365,7 @@ pub fn register_item_ui_flex(
) -> Result<()> {
let ui = Node::from_id(&calling_client, type_info.ui_node_id, true).add_to_scenegraph()?;
ItemUI::add_to(&ui, type_info)?;
(type_info.add_ui_aspect)(&ui);
Ok(())
}
fn create_item_acceptor_flex(
@@ -381,6 +383,7 @@ fn create_item_acceptor_flex(
let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?;
Spatial::add_to(&node, Some(space.clone()), transform, false);
ItemAcceptor::add_to(&node, type_info, field);
(type_info.add_acceptor_aspect)(&node);
Ok(())
}
@@ -391,6 +394,3 @@ fn acceptor_capture_item_flex(node: Arc<Node>, item: Arc<Node>) -> Result<()> {
Ok(())
}
struct ItemInterface;
// create_interface!(ItemInterface);

View File

@@ -1,12 +1,13 @@
use super::{create_item_acceptor_flex, register_item_ui_flex, ItemAcceptor, ItemInterface};
use super::camera::CameraItemAcceptor;
use super::{create_item_acceptor_flex, register_item_ui_flex};
use crate::nodes::items::ITEM_ACCEPTOR_ASPECT_ALIAS_INFO;
use crate::nodes::items::ITEM_ASPECT_ALIAS_INFO;
use crate::nodes::Aspect;
use crate::{
core::{
client::{get_env, state, Client, INTERNAL_CLIENT},
registry::Registry,
},
create_interface,
nodes::{
drawable::model::ModelPart,
items::{Item, ItemType, TypeInfo},
@@ -39,6 +40,12 @@ lazy_static! {
ui: Default::default(),
items: Registry::new(),
acceptors: Registry::new(),
add_acceptor_aspect: |node| {
node.add_aspect(PanelItemUi);
},
add_ui_aspect: |node| {
node.add_aspect(PanelItemAcceptor);
},
new_acceptor_fn: |node, acceptor, acceptor_field| {
let _ = panel_item_ui_client::create_acceptor(node, acceptor, acceptor_field);
}
@@ -115,7 +122,6 @@ impl<B: Backend> PanelItem<B> {
&ITEM_TYPE_INFO_PANEL,
ItemType::Panel(generic_panel_item),
);
<Self as PanelItemAspect>::add_node_members(&node);
(node, panel_item)
}
@@ -198,8 +204,9 @@ impl<B: Backend> PanelItem<B> {
}
}
// make these stupid vectors u32 in the protocol somehow!!!!!!!1
impl<B: Backend> Aspect for PanelItem<B> {
impl_aspect_for_panel_item_aspect! {}
}
#[allow(unused)]
impl<B: Backend> PanelItemAspect for PanelItem<B> {
#[doc = "Apply the cursor as a material to a model."]
@@ -405,7 +412,17 @@ impl<B: Backend> PanelItemAspect for PanelItem<B> {
}
}
impl PanelItemAcceptorAspect for ItemAcceptor {
pub struct PanelItemUi;
impl Aspect for PanelItemUi {
impl_aspect_for_panel_item_ui_aspect! {}
}
impl PanelItemUiAspect for PanelItemUi {}
pub struct PanelItemAcceptor;
impl Aspect for PanelItemAcceptor {
impl_aspect_for_panel_item_acceptor_aspect! {}
}
impl PanelItemAcceptorAspect for PanelItemAcceptor {
fn capture_item(node: Arc<Node>, _calling_client: Arc<Client>, item: Arc<Node>) -> Result<()> {
super::acceptor_capture_item_flex(node, item)
}
@@ -435,22 +452,23 @@ impl<B: Backend> Drop for PanelItem<B> {
}
}
create_interface!(ItemInterface);
impl InterfaceAspect for ItemInterface {
impl InterfaceAspect for Interface {
#[doc = "Register this client to manage the items of a certain type and create default 3D UI for them."]
fn register_panel_item_ui(_node: Arc<Node>, calling_client: Arc<Client>) -> Result<()> {
fn register_panel_item_ui(node: Arc<Node>, calling_client: Arc<Client>) -> Result<()> {
node.add_aspect(CameraItemAcceptor);
register_item_ui_flex(calling_client, &ITEM_TYPE_INFO_PANEL)
}
#[doc = "Create an item acceptor to allow temporary ownership of a given type of item. Creates a node at `/item/<item_type>/acceptor/<name>`."]
fn create_panel_item_acceptor(
_node: Arc<Node>,
node: Arc<Node>,
calling_client: Arc<Client>,
id: u64,
parent: Arc<Node>,
transform: Transform,
field: Arc<Node>,
) -> Result<()> {
node.add_aspect(PanelItemAcceptor);
create_item_acceptor_flex(
calling_client,
id,

View File

@@ -21,7 +21,7 @@ use spatial::Spatial;
use stardust_xr::messenger::MessageSenderHandle;
use stardust_xr::scenegraph::ScenegraphError;
use stardust_xr::schemas::flex::{deserialize, serialize};
use std::any::{Any, TypeId};
use std::any::Any;
use std::fmt::Debug;
use std::os::fd::OwnedFd;
use std::sync::{Arc, Weak};
@@ -46,11 +46,26 @@ impl AsRef<[u8]> for Message {
}
}
pub type Signal = fn(Arc<Node>, Arc<Client>, Message) -> Result<()>;
pub type Method = fn(Arc<Node>, Arc<Client>, Message, MethodResponseSender);
stardust_xr_server_codegen::codegen_node_protocol!();
pub struct Owned;
impl Aspect for Owned {
impl_aspect_for_owned_aspect! {}
}
impl OwnedAspect for Owned {
fn set_enabled(node: Arc<Node>, _calling_client: Arc<Client>, enabled: bool) -> Result<()> {
node.set_enabled(enabled);
Ok(())
}
fn destroy(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<()> {
if node.destroyable {
node.destroy();
}
Ok(())
}
}
pub struct OwnedNode(pub Arc<Node>);
impl Drop for OwnedNode {
fn drop(&mut self) {
@@ -64,8 +79,6 @@ pub struct Node {
client: Weak<Client>,
message_sender_handle: Option<MessageSenderHandle>,
local_signals: Mutex<FxHashMap<u64, Signal>>,
local_methods: Mutex<FxHashMap<u64, Method>>,
aliases: Registry<Alias>,
aspects: Aspects,
destroyable: bool,
@@ -87,13 +100,11 @@ impl Node {
client: Arc::downgrade(client),
message_sender_handle: client.message_sender_handle.clone(),
id,
local_signals: Default::default(),
local_methods: Default::default(),
aliases: Default::default(),
aspects: Default::default(),
destroyable,
};
<Node as OwnedAspect>::add_node_members(&node);
node.aspects.add(Owned);
node
}
pub fn add_to_scenegraph(self) -> Result<Arc<Node>> {
@@ -146,13 +157,6 @@ impl Node {
// Ok(serialize(pid)?.into())
// }
pub fn add_local_signal(&self, id: u64, signal: Signal) {
self.local_signals.lock().insert(id, signal);
}
pub fn add_local_method(&self, id: u64, method: Method) {
self.local_methods.lock().insert(id, method);
}
pub fn add_aspect<A: Aspect>(&self, aspect: A) -> Arc<A> {
self.aspects.add(aspect)
}
@@ -166,6 +170,7 @@ impl Node {
pub fn send_local_signal(
self: Arc<Self>,
calling_client: Arc<Client>,
aspect_id: u64,
method: u64,
message: Message,
) -> Result<(), ScenegraphError> {
@@ -177,22 +182,26 @@ impl Node {
.original
.upgrade()
.ok_or(ScenegraphError::BrokenAlias)?
.send_local_signal(calling_client, method, message)
.send_local_signal(calling_client, aspect_id, method, message)
} else {
let signal = self
.local_signals
let aspect = self
.aspects
.0
.lock()
.get(&method)
.cloned()
.ok_or(ScenegraphError::SignalNotFound)?;
signal(self, calling_client, message).map_err(|error| ScenegraphError::SignalError {
error: error.to_string(),
})
.get(&aspect_id)
.ok_or(ScenegraphError::AspectNotFound)?
.clone();
aspect
.run_signal(calling_client, self.clone(), method, message)
.map_err(|error| ScenegraphError::SignalError {
error: error.to_string(),
})
}
}
pub fn execute_local_method(
self: Arc<Self>,
calling_client: Arc<Client>,
aspect_id: u64,
method: u64,
message: Message,
response: MethodResponseSender,
@@ -208,6 +217,7 @@ impl Node {
};
alias.execute_local_method(
calling_client,
aspect_id,
method,
Message {
data: message.data.clone(),
@@ -216,14 +226,19 @@ impl Node {
response,
)
} else {
let Some(method) = self.local_methods.lock().get(&method).cloned() else {
response.send(Err(ScenegraphError::MethodNotFound));
let Some(aspect) = self.aspects.0.lock().get(&aspect_id).cloned() else {
response.send(Err(ScenegraphError::AspectNotFound));
return;
};
method(self, calling_client, message, response);
aspect.run_method(calling_client, self.clone(), method, message, response);
}
}
pub fn send_remote_signal(&self, method: u64, message: impl Into<Message>) -> Result<()> {
pub fn send_remote_signal(
&self,
aspect_id: u64,
method: u64,
message: impl Into<Message>,
) -> Result<()> {
let message = message.into();
self.aliases
.get_valid_contents()
@@ -233,6 +248,7 @@ impl Node {
.for_each(|node| {
// Beware! file descriptors will not be sent to aliases!!!
let _ = node.send_remote_signal(
aspect_id,
method,
Message {
data: message.data.clone(),
@@ -241,12 +257,13 @@ impl Node {
);
});
if let Some(handle) = self.message_sender_handle.as_ref() {
handle.signal(self.id, method, &message.data, message.fds)?;
handle.signal(self.id, aspect_id, method, &message.data, message.fds)?;
}
Ok(())
}
pub async fn execute_remote_method_typed<S: Serialize, D: DeserializeOwned>(
&self,
aspect_id: u64,
method: u64,
input: S,
fds: Vec<OwnedFd>,
@@ -258,7 +275,7 @@ impl Node {
let serialized = serialize(input)?;
let result = message_sender_handle
.method(self.id, method, &serialized, fds)?
.method(self.id, aspect_id, method, &serialized, fds)?
.await
.map_err(|e| eyre!(e))?;
@@ -271,25 +288,10 @@ impl Debug for Node {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Node")
.field("id", &self.id)
.field("local_signals", &self.local_signals.lock().keys())
.field("local_methods", &self.local_methods.lock().keys())
.field("destroyable", &self.destroyable)
.finish()
}
}
impl OwnedAspect for Node {
fn set_enabled(node: Arc<Node>, _calling_client: Arc<Client>, enabled: bool) -> Result<()> {
node.set_enabled(enabled);
Ok(())
}
fn destroy(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<()> {
if node.destroyable {
node.destroy();
}
Ok(())
}
}
impl Drop for Node {
fn drop(&mut self) {
// Debug breakpoint
@@ -297,12 +299,28 @@ impl Drop for Node {
}
pub trait Aspect: Any + Send + Sync + 'static {
const NAME: &'static str;
fn name(&self) -> String;
fn id(&self) -> u64;
fn as_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync + 'static>;
fn run_signal(
&self,
calling_client: Arc<Client>,
node: Arc<Node>,
signal: u64,
message: Message,
) -> Result<(), stardust_xr::scenegraph::ScenegraphError>;
fn run_method(
&self,
calling_client: Arc<Client>,
node: Arc<Node>,
method: u64,
message: Message,
response: MethodResponseSender,
);
}
#[derive(Default)]
struct Aspects(Mutex<FxHashMap<TypeId, Arc<dyn Any + Send + Sync + 'static>>>);
struct Aspects(Mutex<FxHashMap<u64, Arc<dyn Aspect>>>);
impl Aspects {
fn add<A: Aspect>(&self, t: A) -> Arc<A> {
let aspect = Arc::new(t);
@@ -310,18 +328,15 @@ impl Aspects {
aspect
}
fn add_raw<A: Aspect>(&self, aspect: Arc<A>) {
self.0.lock().insert(Self::type_key::<A>(), aspect);
let id = aspect.id();
self.0.lock().insert(id, aspect);
}
fn get<A: Aspect>(&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>()
.values()
.find_map(|a| Arc::downcast(a.clone().as_any()).ok())
.ok_or(eyre!("Couldn't get aspect"))
}
}
impl Drop for Aspects {

View File

@@ -1,5 +1,5 @@
use super::spatial::Spatial;
use super::Node;
use super::{Aspect, Node};
use crate::core::client::Client;
use crate::core::client_state::ClientStateParsed;
use crate::core::registry::Registry;
@@ -23,14 +23,14 @@ pub struct Root {
impl Root {
pub fn create(client: &Arc<Client>, transform: Mat4) -> Result<Arc<Self>> {
let node = Node::from_id(client, 0, false);
<Self as RootAspect>::add_node_members(&node);
let node = node.add_to_scenegraph()?;
let _ = Spatial::add_to(&node, None, transform, false);
Ok(ROOT_REGISTRY.add(Root {
node,
let root_aspect = node.add_aspect(Root {
node: node.clone(),
connect_instant: Instant::now(),
}))
});
ROOT_REGISTRY.add_raw(&root_aspect);
Ok(root_aspect)
}
pub fn send_frame_events(delta: f64) {
@@ -54,6 +54,9 @@ impl Root {
Ok(root_client::save_state(&self.node).await?.0)
}
}
impl Aspect for Root {
impl_aspect_for_root_aspect! {}
}
impl RootAspect for Root {
async fn get_state(_node: Arc<Node>, calling_client: Arc<Client>) -> Result<ClientState> {
let Some(state) = calling_client.state.get() else {

View File

@@ -6,7 +6,6 @@ use super::fields::{Field, FieldTrait};
use super::Aspect;
use crate::core::client::Client;
use crate::core::registry::Registry;
use crate::create_interface;
use crate::nodes::{Node, OWNED_ASPECT_ALIAS_INFO};
use color_eyre::eyre::{eyre, OptionExt, Result};
use glam::{vec3a, Mat4, Quat, Vec3};
@@ -38,6 +37,9 @@ impl Transform {
Mat4::from_scale_rotation_translation(scale.into(), rotation.into(), position.into())
}
}
impl Aspect for Zone {
impl_aspect_for_zone_aspect! {}
}
lazy_static::lazy_static! {
pub static ref EXPORTED_SPATIALS: Mutex<FxHashMap<u64, Arc<Node>>> = Mutex::new(FxHashMap::default());
@@ -74,16 +76,14 @@ impl Spatial {
zoneable: bool,
) -> Arc<Spatial> {
let spatial = Spatial::new(Arc::downgrade(node), parent.clone(), transform);
<Spatial as SpatialAspect>::add_node_members(node);
if zoneable {
ZONEABLE_REGISTRY.add_raw(&spatial);
}
if let Some(parent) = parent {
parent.children.add_raw(&spatial);
}
<Spatial as SpatialRefAspect>::add_node_members(node);
<Spatial as SpatialAspect>::add_node_members(node);
node.add_aspect_raw(spatial.clone());
node.add_aspect(SpatialRef);
spatial
}
@@ -242,66 +242,7 @@ impl Spatial {
}
}
impl Aspect for Spatial {
const NAME: &'static str = "Spatial";
}
impl SpatialRefAspect for Spatial {
async fn get_local_bounding_box(
node: Arc<Node>,
_calling_client: Arc<Client>,
) -> Result<BoundingBox> {
let this_spatial = node.get_aspect::<Spatial>()?;
let bounds = this_spatial.get_bounding_box();
Ok(BoundingBox {
center: Vec3::from(bounds.center).into(),
size: Vec3::from(bounds.dimensions).into(),
})
}
async fn get_relative_bounding_box(
node: Arc<Node>,
_calling_client: Arc<Client>,
relative_to: Arc<Node>,
) -> Result<BoundingBox> {
let this_spatial = node.get_aspect::<Spatial>()?;
let relative_spatial = relative_to.get_aspect::<Spatial>()?;
let center = Spatial::space_to_space_matrix(Some(&this_spatial), Some(&relative_spatial))
.transform_point3([0.0; 3].into());
let mut bounds = Bounds {
center: center.into(),
dimensions: [0.0; 3].into(),
};
bounds.grown_box(
this_spatial.get_bounding_box(),
Spatial::space_to_space_matrix(Some(&this_spatial), Some(&relative_spatial)),
);
Ok(BoundingBox {
center: Vec3::from(bounds.center).into(),
size: Vec3::from(bounds.dimensions).into(),
})
}
async fn get_transform(
node: Arc<Node>,
_calling_client: Arc<Client>,
relative_to: Arc<Node>,
) -> Result<Transform> {
let this_spatial = node.get_aspect::<Spatial>()?;
let relative_spatial = relative_to.get_aspect::<Spatial>()?;
let (scale, rotation, position) = Spatial::space_to_space_matrix(
Some(this_spatial.as_ref()),
Some(relative_spatial.as_ref()),
)
.to_scale_rotation_translation();
Ok(Transform {
translation: Some(position.into()),
rotation: Some(rotation.into()),
scale: Some(scale.into()),
})
}
impl_aspect_for_spatial_aspect! {}
}
impl SpatialAspect for Spatial {
fn set_local_transform(
@@ -389,6 +330,70 @@ impl Drop for Spatial {
}
}
pub struct SpatialRef;
impl Aspect for SpatialRef {
impl_aspect_for_spatial_ref_aspect! {}
}
impl SpatialRefAspect for SpatialRef {
async fn get_local_bounding_box(
node: Arc<Node>,
_calling_client: Arc<Client>,
) -> Result<BoundingBox> {
let this_spatial = node.get_aspect::<Spatial>()?;
let bounds = this_spatial.get_bounding_box();
Ok(BoundingBox {
center: Vec3::from(bounds.center).into(),
size: Vec3::from(bounds.dimensions).into(),
})
}
async fn get_relative_bounding_box(
node: Arc<Node>,
_calling_client: Arc<Client>,
relative_to: Arc<Node>,
) -> Result<BoundingBox> {
let this_spatial = node.get_aspect::<Spatial>()?;
let relative_spatial = relative_to.get_aspect::<Spatial>()?;
let center = Spatial::space_to_space_matrix(Some(&this_spatial), Some(&relative_spatial))
.transform_point3([0.0; 3].into());
let mut bounds = Bounds {
center: center.into(),
dimensions: [0.0; 3].into(),
};
bounds.grown_box(
this_spatial.get_bounding_box(),
Spatial::space_to_space_matrix(Some(&this_spatial), Some(&relative_spatial)),
);
Ok(BoundingBox {
center: Vec3::from(bounds.center).into(),
size: Vec3::from(bounds.dimensions).into(),
})
}
async fn get_transform(
node: Arc<Node>,
_calling_client: Arc<Client>,
relative_to: Arc<Node>,
) -> Result<Transform> {
let this_spatial = node.get_aspect::<Spatial>()?;
let relative_spatial = relative_to.get_aspect::<Spatial>()?;
let (scale, rotation, position) = Spatial::space_to_space_matrix(
Some(this_spatial.as_ref()),
Some(relative_spatial.as_ref()),
)
.to_scale_rotation_translation();
Ok(Transform {
translation: Some(position.into()),
rotation: Some(rotation.into()),
scale: Some(scale.into()),
})
}
}
pub fn parse_transform(transform: Transform, position: bool, rotation: bool, scale: bool) -> Mat4 {
let position = position
.then_some(transform.translation)
@@ -406,8 +411,7 @@ pub fn parse_transform(transform: Transform, position: bool, rotation: bool, sca
Mat4::from_scale_rotation_translation(scale.into(), rotation.into(), position.into())
}
pub struct SpatialInterface;
impl InterfaceAspect for SpatialInterface {
impl InterfaceAspect for Interface {
fn create_spatial(
_node: Arc<Node>,
calling_client: Arc<Client>,
@@ -460,5 +464,3 @@ impl InterfaceAspect for SpatialInterface {
.ok_or_eyre("Couldn't find spatial with that ID")
}
}
create_interface!(SpatialInterface);

View File

@@ -7,7 +7,7 @@ use crate::{
nodes::{
alias::{get_original, Alias, AliasList},
fields::{Field, FieldTrait},
Aspect, Node,
Node,
},
};
use color_eyre::eyre::Result;
@@ -73,7 +73,6 @@ impl Zone {
intersecting: AliasList::default(),
captured: AliasList::default(),
});
<Zone as ZoneAspect>::add_node_members(node);
node.add_aspect_raw(zone.clone());
zone
}
@@ -124,9 +123,6 @@ impl Zone {
Ok(())
}
}
impl Aspect for Zone {
const NAME: &'static str = "Zone";
}
impl ZoneAspect for Zone {
fn update(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<()> {
let zone = node.get_aspect::<Zone>()?;

View File

@@ -12,7 +12,6 @@ use color_eyre::eyre::Result;
use glam::{Mat4, Quat, Vec3};
use serde::{Deserialize, Serialize};
use stardust_xr::values::Datamap;
use std::f32::INFINITY;
use std::sync::Arc;
use stereokit_rust::sk::{DisplayMode, MainThreadToken, Sk};
use stereokit_rust::system::{HandJoint, HandSource, Handed, Input, LinePoint, Lines};

View File

@@ -93,7 +93,6 @@ impl Drop for UnownedFd {
pub struct Wayland {
display: Arc<DisplayWrapper>,
pub socket_name: Option<String>,
join_handle: JoinHandle<Result<()>>,
renderer: GlesRenderer,
output: Output,
@@ -133,7 +132,6 @@ impl Wayland {
Ok(Wayland {
display,
socket_name,
join_handle,
renderer,
output,