diff --git a/src/core/client.rs b/src/core/client.rs index c5b94cf..74c9270 100644 --- a/src/core/client.rs +++ b/src/core/client.rs @@ -1,7 +1,7 @@ use super::{eventloop::EventLoop, scenegraph::Scenegraph}; use crate::{ core::registry::Registry, - nodes::{data, fields, hmd, input, items, model, root::Root, spatial, startup}, + nodes::{data, drawable, fields, hmd, input, items, root::Root, spatial, startup}, }; use anyhow::Result; use lazy_static::lazy_static; @@ -67,7 +67,7 @@ impl Client { hmd::make_alias(&client); spatial::create_interface(&client); fields::create_interface(&client); - model::create_interface(&client); + drawable::create_interface(&client); data::create_interface(&client); items::create_interface(&client); input::create_interface(&client); diff --git a/src/core/registry.rs b/src/core/registry.rs index 0c76c91..db9743d 100644 --- a/src/core/registry.rs +++ b/src/core/registry.rs @@ -7,13 +7,16 @@ use once_cell::sync::Lazy; use parking_lot::Mutex; use rustc_hash::FxHashMap; -pub struct Registry(Lazy>>>); +pub struct Registry(Lazy>>>); -impl Registry { +impl Registry { pub const fn new() -> Self { Registry(Lazy::new(|| Mutex::new(FxHashMap::default()))) } - pub fn add(&self, t: T) -> Arc { + pub fn add(&self, t: T) -> Arc + where + T: Sized, + { let t_arc = Arc::new(t); self.add_raw(&t_arc); t_arc @@ -21,7 +24,7 @@ impl Registry { pub fn add_raw(&self, t: &Arc) { self.0 .lock() - .insert(Arc::as_ptr(t) as usize, Arc::downgrade(t)); + .insert(Arc::as_ptr(t) as *const () as usize, Arc::downgrade(t)); } pub fn get_valid_contents(&self) -> Vec> { self.0 @@ -31,7 +34,9 @@ impl Registry { .collect() } pub fn remove(&self, t: &T) { - self.0.lock().remove(&(ptr::addr_of!(*t) as usize)); + self.0 + .lock() + .remove(&(ptr::addr_of!(*t) as *const () as usize)); } pub fn clear(&self) { self.0.lock().clear(); diff --git a/src/main.rs b/src/main.rs index d688811..b8e0474 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,8 @@ mod objects; mod wayland; use crate::core::destroy_queue; -use crate::nodes::model::{MODELS_TO_DROP, MODEL_REGISTRY}; +use crate::nodes::drawable::model::MODELS_TO_DROP; +use crate::nodes::drawable::DRAWABLE_REGISTRY; use crate::nodes::{hmd, input}; use crate::objects::input::mouse_pointer::MousePointer; use crate::objects::input::sk_hand::SkHand; @@ -77,8 +78,8 @@ fn main() -> Result<()> { destroy_queue::clear(); nodes::root::Root::logic_step(stereokit.time_elapsed()); - for model in MODEL_REGISTRY.get_valid_contents() { - model.draw(&stereokit, draw_ctx); + for drawable in DRAWABLE_REGISTRY.get_valid_contents() { + drawable.draw(&stereokit, draw_ctx); } MODELS_TO_DROP.lock().clear(); diff --git a/src/nodes/drawable/mod.rs b/src/nodes/drawable/mod.rs new file mode 100644 index 0000000..35d1186 --- /dev/null +++ b/src/nodes/drawable/mod.rs @@ -0,0 +1,19 @@ +pub mod model; + +use super::Node; +use crate::core::{client::Client, registry::Registry}; +use std::sync::Arc; +use stereokit::{lifecycle::DrawContext, StereoKit}; + +pub trait Drawable: Send + Sync { + fn draw(&self, sk: &StereoKit, draw_ctx: &DrawContext); +} + +pub static DRAWABLE_REGISTRY: Registry = Registry::new(); + +pub fn create_interface(client: &Arc) { + let node = Node::create(client, "", "drawable", false); + node.add_local_signal("createModelFromFile", model::create_from_file); + node.add_local_signal("createModelFromResource", model::create_from_resource); + node.add_to_scenegraph(); +} diff --git a/src/nodes/model.rs b/src/nodes/drawable/model.rs similarity index 94% rename from src/nodes/model.rs rename to src/nodes/drawable/model.rs index 4b7d06f..ce22bd7 100644 --- a/src/nodes/model.rs +++ b/src/nodes/drawable/model.rs @@ -1,8 +1,9 @@ -use super::spatial::{get_spatial_parent_flex, Spatial}; -use super::Node; +use super::{Drawable, Node}; use crate::core::client::Client; use crate::core::registry::Registry; use crate::core::resource::{NamespacedResourceID, ResourceID}; +use crate::nodes::drawable::DRAWABLE_REGISTRY; +use crate::nodes::spatial::{get_spatial_parent_flex, Spatial}; use anyhow::{anyhow, bail, ensure, Result}; use flexbuffers::FlexBufferType; use glam::Mat4; @@ -61,6 +62,7 @@ impl Model { }; node.add_local_signal("setMaterialParameter", Model::set_material_parameter); let model_arc = MODEL_REGISTRY.add(model); + DRAWABLE_REGISTRY.add_raw(&(model_arc.clone() as Arc)); let _ = model_arc.pending_model_path.set( model_arc .resource_id @@ -71,7 +73,40 @@ impl Model { Ok(model_arc) } - pub fn draw(&self, sk: &StereoKit, draw_ctx: &DrawContext) { + fn set_material_parameter( + node: &Node, + _calling_client: Arc, + data: &[u8], + ) -> Result<()> { + let model = node.model.get().unwrap(); + let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?; + let material_idx = flex_vec + .idx(0) + .get_u64() + .map_err(|_| anyhow!("Material ID is not a number!"))? as u32; + let parameter_name = flex_vec + .idx(1) + .get_str() + .map_err(|_| anyhow!("Parameter name is not a string!"))?; + + let flex_parameter_value = flex_vec.idx(2); + let parameter_value = match flex_parameter_value.flexbuffer_type() { + FlexBufferType::String => { + MaterialParameter::Texture(PathBuf::from(flex_parameter_value.as_str())) + } + _ => bail!("Invalid parameter value type"), + }; + + model + .pending_material_parameters + .lock() + .insert((material_idx, parameter_name.to_string()), parameter_value); + + Ok(()) + } +} +impl Drawable for Model { + fn draw(&self, sk: &StereoKit, draw_ctx: &DrawContext) { let sk_model = self .sk_model .get_or_try_init(|| { @@ -118,38 +153,6 @@ impl Model { ); } } - - fn set_material_parameter( - node: &Node, - _calling_client: Arc, - data: &[u8], - ) -> Result<()> { - let model = node.model.get().unwrap(); - let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?; - let material_idx = flex_vec - .idx(0) - .get_u64() - .map_err(|_| anyhow!("Material ID is not a number!"))? as u32; - let parameter_name = flex_vec - .idx(1) - .get_str() - .map_err(|_| anyhow!("Parameter name is not a string!"))?; - - let flex_parameter_value = flex_vec.idx(2); - let parameter_value = match flex_parameter_value.flexbuffer_type() { - FlexBufferType::String => { - MaterialParameter::Texture(PathBuf::from(flex_parameter_value.as_str())) - } - _ => bail!("Invalid parameter value type"), - }; - - model - .pending_material_parameters - .lock() - .insert((material_idx, parameter_name.to_string()), parameter_value); - - Ok(()) - } } impl Drop for Model { fn drop(&mut self) { @@ -157,16 +160,10 @@ impl Drop for Model { MODELS_TO_DROP.lock().push(model); } MODEL_REGISTRY.remove(self); + DRAWABLE_REGISTRY.remove(self); } } -pub fn create_interface(client: &Arc) { - let node = Node::create(client, "", "drawable", false); - node.add_local_signal("createModelFromFile", create_from_file); - node.add_local_signal("createModelFromResource", create_from_resource); - node.add_to_scenegraph(); -} - pub fn create_from_file(_node: &Node, calling_client: Arc, data: &[u8]) -> Result<()> { let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?; let node = Node::create( diff --git a/src/nodes/mod.rs b/src/nodes/mod.rs index e7c342a..37d1263 100644 --- a/src/nodes/mod.rs +++ b/src/nodes/mod.rs @@ -1,10 +1,10 @@ pub mod alias; pub mod data; +pub mod drawable; pub mod fields; pub mod hmd; pub mod input; pub mod items; -pub mod model; pub mod root; pub mod spatial; pub mod startup; @@ -28,10 +28,10 @@ use crate::core::registry::Registry; use self::alias::Alias; use self::data::{PulseReceiver, PulseSender}; +use self::drawable::model::Model; use self::fields::Field; use self::input::{InputHandler, InputMethod}; use self::items::{Item, ItemAcceptor, ItemUI}; -use self::model::Model; use self::spatial::Spatial; use self::startup::StartupSettings; diff --git a/src/wayland/surface.rs b/src/wayland/surface.rs index e668895..55c5149 100644 --- a/src/wayland/surface.rs +++ b/src/wayland/surface.rs @@ -1,7 +1,7 @@ use super::{shaders::PANEL_SHADER_BYTES, state::WaylandState}; use crate::{ core::{destroy_queue, registry::Registry}, - nodes::model::Model, + nodes::drawable::model::Model, }; use mint::Vector2; use parking_lot::Mutex;