diff --git a/Cargo.lock b/Cargo.lock index fb9d13c..361b88a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -880,9 +880,9 @@ checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "flatbuffers" -version = "23.5.26" +version = "24.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dac53e22462d78c16d64a1cd22371b54cc3fe94aa15e7886a2fa6e5d1ab8640" +checksum = "8add37afff2d4ffa83bc748a70b4b1370984f6980768554182424ef71447c35f" dependencies = [ "bitflags 1.3.2", "rustc_version", @@ -2483,7 +2483,7 @@ checksum = "2f2b15926089e5526bb2dd738a2eb0e59034356e06eb71e1cd912358c0e62c4d" [[package]] name = "stardust-xr" version = "0.45.0" -source = "git+https://github.com/StardustXR/core.git#6ee323df1a1e76666609c1ebfd79f3390ce43c29" +source = "git+https://github.com/StardustXR/core.git?branch=dev#47208187ffdb00627fabbb3af2bd0a12a6208194" dependencies = [ "cluFlock", "color-rs", @@ -2503,7 +2503,7 @@ dependencies = [ [[package]] name = "stardust-xr-schemas" version = "1.5.3" -source = "git+https://github.com/StardustXR/core.git#6ee323df1a1e76666609c1ebfd79f3390ce43c29" +source = "git+https://github.com/StardustXR/core.git?branch=dev#47208187ffdb00627fabbb3af2bd0a12a6208194" dependencies = [ "flatbuffers", "flexbuffers", diff --git a/Cargo.toml b/Cargo.toml index 834228c..da868c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -99,11 +99,7 @@ optional = true [dependencies.stardust-xr] git = "https://github.com/StardustXR/core.git" +branch = "dev" [dependencies.stardust-xr-server-codegen] path = "codegen" - -# [patch.crates-io.stereokit] -# path = "../stereokit-rs" -# [patch.crates-io.stereokit-sys] -# path = "../stereokit-sys" diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index 1a66a23..26cf44b 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -15,3 +15,4 @@ split-iter = "0.1.0" [dependencies.stardust-xr-schemas] git = "https://github.com/StardustXR/core.git" +branch = "dev" diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index bcf109e..96f48d6 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -40,6 +40,18 @@ pub fn codegen_drawable_protocol(_input: proc_macro::TokenStream) -> proc_macro: pub fn codegen_input_protocol(_input: proc_macro::TokenStream) -> proc_macro::TokenStream { codegen_protocol(INPUT_PROTOCOL) } +#[proc_macro] +pub fn codegen_item_protocol(_input: proc_macro::TokenStream) -> proc_macro::TokenStream { + codegen_protocol(ITEM_PROTOCOL) +} +#[proc_macro] +pub fn codegen_item_camera_protocol(_input: proc_macro::TokenStream) -> proc_macro::TokenStream { + codegen_protocol(ITEM_CAMERA_PROTOCOL) +} +#[proc_macro] +pub fn codegen_item_panel_protocol(_input: proc_macro::TokenStream) -> proc_macro::TokenStream { + codegen_protocol(ITEM_PANEL_PROTOCOL) +} fn codegen_protocol(protocol: &'static str) -> proc_macro::TokenStream { let protocol = Protocol::parse(protocol).unwrap(); @@ -457,13 +469,15 @@ fn generate_argument_decl(argument: &Argument, owned_values: bool) -> TokenStrea } fn argument_type_option_name(argument_type: &ArgumentType) -> String { match argument_type { + ArgumentType::Empty => "Empty".to_string(), ArgumentType::Bool => "Bool".to_string(), ArgumentType::Int => "Int".to_string(), ArgumentType::UInt => "UInt".to_string(), ArgumentType::Float => "Float".to_string(), - ArgumentType::Vec2 => "Vec2".to_string(), - ArgumentType::Vec3 => "Vec3".to_string(), + ArgumentType::Vec2(_) => "Vec2".to_string(), + ArgumentType::Vec3(_) => "Vec3".to_string(), ArgumentType::Quat => "Quat".to_string(), + ArgumentType::Mat4 => "Mat4".to_string(), ArgumentType::Color => "Color".to_string(), ArgumentType::String => "String".to_string(), ArgumentType::Bytes => "Bytes".to_string(), @@ -483,13 +497,21 @@ fn generate_argument_type( owned: bool, ) -> TokenStream { let _type = match argument_type { + ArgumentType::Empty => quote!(()), ArgumentType::Bool => quote!(bool), ArgumentType::Int => quote!(i32), ArgumentType::UInt => quote!(u32), ArgumentType::Float => quote!(f32), - ArgumentType::Vec2 => quote!(mint::Vector2), - ArgumentType::Vec3 => quote!(mint::Vector3), - ArgumentType::Quat => quote!(mint::Quaternion), + ArgumentType::Vec2(t) => { + let t = generate_argument_type(&t, false, true); + quote!(stardust_xr::values::Vector2<#t>) + } + ArgumentType::Vec3(t) => { + let t = generate_argument_type(&t, false, true); + quote!(stardust_xr::values::Vector3<#t>) + } + ArgumentType::Quat => quote!(stardust_xr::values::Quaternion), + ArgumentType::Mat4 => quote!(stardust_xr::values::Mat4), ArgumentType::Color => quote!(stardust_xr::values::Color), ArgumentType::Bytes => { if !owned { @@ -517,9 +539,9 @@ fn generate_argument_type( let t = generate_argument_type(&t, false, true); if !owned { - quote!(&rustc_hash::FxHashMap) + quote!(&stardust_xr::values::Map) } else { - quote!(rustc_hash::FxHashMap) + quote!(stardust_xr::values::Map) } } ArgumentType::Datamap => { diff --git a/src/core/client.rs b/src/core/client.rs index 3b1a414..aeb57fe 100644 --- a/src/core/client.rs +++ b/src/core/client.rs @@ -109,8 +109,9 @@ impl Client { drawable::create_interface(&client)?; audio::create_interface(&client)?; data::create_interface(&client)?; - items::create_interface(&client)?; input::create_interface(&client)?; + items::camera::create_interface(&client)?; + items::panel::create_interface(&client)?; client .root diff --git a/src/nodes/fields/mod.rs b/src/nodes/fields/mod.rs index 8e9ef28..5febc66 100644 --- a/src/nodes/fields/mod.rs +++ b/src/nodes/fields/mod.rs @@ -297,7 +297,3 @@ impl FieldInterfaceAspect for FieldInterface { Ok(()) } } - -pub fn find_field(client: &Client, path: &str) -> Result> { - client.get_node("Field", path)?.get_aspect::() -} diff --git a/src/nodes/items/camera.rs b/src/nodes/items/camera.rs index 5399721..1320dfe 100644 --- a/src/nodes/items/camera.rs +++ b/src/nodes/items/camera.rs @@ -1,26 +1,26 @@ -use super::{Item, ItemType}; +use super::{create_item_acceptor_flex, register_item_ui_flex, Item, ItemInterface, ItemType}; use crate::{ core::{ client::{Client, INTERNAL_CLIENT}, registry::Registry, scenegraph::MethodResponseSender, }, + create_interface, nodes::{ drawable::{model::ModelPart, shaders::UNLIT_SHADER_BYTES}, items::TypeInfo, - spatial::{parse_transform, Spatial, Transform}, + spatial::{Spatial, Transform}, Message, Node, }, }; use color_eyre::eyre::{bail, eyre, Result}; use glam::Mat4; use lazy_static::lazy_static; -use mint::{RowMatrix4, Vector2}; +use mint::{ColumnMatrix4, Vector2}; use nanoid::nanoid; use once_cell::sync::OnceCell; use parking_lot::Mutex; use send_wrapper::SendWrapper; -use serde::Deserialize; use stardust_xr::schemas::flex::{deserialize, serialize}; use std::sync::Arc; use stereokit_rust::{ @@ -33,6 +33,7 @@ use stereokit_rust::{ }; use tracing::error; +stardust_xr_server_codegen::codegen_item_camera_protocol!(); lazy_static! { pub(super) static ref ITEM_TYPE_INFO_CAMERA: TypeInfo = TypeInfo { type_name: "camera", @@ -42,6 +43,9 @@ lazy_static! { ui: Default::default(), items: Registry::new(), acceptors: Registry::new(), + new_acceptor_fn: |node, uid, acceptor, acceptor_field| { + let _ = camera_item_ui_client::create_acceptor(node, uid, acceptor, acceptor_field); + } }; } @@ -114,8 +118,11 @@ impl CameraItem { Ok(()) } - pub fn serialize_start_data(&self, id: &str) -> Result { - Ok(serialize(id)?.into()) + pub fn send_ui_item_created(&self, node: &Node, uid: &str, item: &Arc) { + let _ = camera_item_ui_client::create_item(node, uid, item); + } + pub fn send_acceptor_item_created(&self, node: &Node, uid: &str, item: &Arc) { + let _ = camera_item_acceptor_client::capture_item(node, uid, item); } pub fn update(&self, token: &MainThreadToken) { @@ -169,34 +176,55 @@ pub fn update(token: &MainThreadToken) { } } -pub(super) fn create_camera_item_flex( - _node: Arc, - calling_client: Arc, - message: Message, -) -> Result<()> { - #[derive(Deserialize)] - struct CreateCameraItemInfo<'a> { - name: &'a str, - parent_path: &'a str, +create_interface!(ItemInterface, ItemCameraInterfaceAspect, "/item/camera"); +impl ItemCameraInterfaceAspect for ItemInterface { + #[doc = "Create a camera item at a specific location"] + fn create_camera_item( + _node: Arc, + calling_client: Arc, + name: String, + parent: Arc, transform: Transform, - proj_matrix: RowMatrix4, + proj_matrix: ColumnMatrix4, px_size: Vector2, - } - let info: CreateCameraItemInfo = deserialize(message.as_ref())?; - let parent_name = format!("/item/{}/item", ITEM_TYPE_INFO_CAMERA.type_name); - let space = calling_client - .get_node("Spatial parent", info.parent_path)? - .get_aspect::()?; - let transform = parse_transform(info.transform, true, true, false); + ) -> Result<()> { + let parent_name = format!("/item/{}/item", ITEM_TYPE_INFO_CAMERA.type_name); + let space = parent.get_aspect::()?; + let transform = transform.to_mat4(true, true, false); - let node = Node::create_parent_name(&INTERNAL_CLIENT, &parent_name, info.name, false) - .add_to_scenegraph()?; - Spatial::add_to(&node, None, transform * space.global_transform(), false); - CameraItem::add_to(&node, info.proj_matrix.into(), info.px_size); - node.get_aspect::().unwrap().make_alias_named( - &calling_client, - &parent_name, - info.name, - )?; - Ok(()) + let node = Node::create_parent_name(&INTERNAL_CLIENT, &parent_name, &name, false) + .add_to_scenegraph()?; + Spatial::add_to(&node, None, transform * space.global_transform(), false); + CameraItem::add_to(&node, proj_matrix.into(), px_size); + node.get_aspect::().unwrap().make_alias_named( + &calling_client, + &parent_name, + &name, + )?; + Ok(()) + } + + #[doc = "Register this client to manage camera items and create default 3D UI for them."] + fn register_camera_item_ui(_node: Arc, calling_client: Arc) -> Result<()> { + 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/`."] + fn create_camera_item_acceptor( + _node: Arc, + calling_client: Arc, + name: String, + parent: Arc, + transform: Transform, + field: Arc, + ) -> Result<()> { + create_item_acceptor_flex( + calling_client, + name, + parent, + transform, + &ITEM_TYPE_INFO_CAMERA, + field, + ) + } } diff --git a/src/nodes/items/environment.rs b/src/nodes/items/environment.rs deleted file mode 100644 index 753c1cd..0000000 --- a/src/nodes/items/environment.rs +++ /dev/null @@ -1,97 +0,0 @@ -use super::{Item, ItemType}; -use crate::{ - core::{ - client::{Client, INTERNAL_CLIENT}, - registry::Registry, - scenegraph::MethodResponseSender, - }, - nodes::{ - items::TypeInfo, - spatial::{parse_transform, Spatial, Transform}, - Message, Node, - }, -}; -use color_eyre::eyre::{eyre, Result}; -use lazy_static::lazy_static; -use nanoid::nanoid; -use serde::Deserialize; -use stardust_xr::schemas::flex::{deserialize, serialize}; -use std::sync::Arc; - -lazy_static! { - pub(super) static ref ITEM_TYPE_INFO_ENVIRONMENT: TypeInfo = TypeInfo { - type_name: "environment", - aliased_local_signals: vec!["apply_sky_tex", "apply_sky_light"], - aliased_local_methods: vec![], - aliased_remote_signals: vec![], - ui: Default::default(), - items: Registry::new(), - acceptors: Registry::new(), - }; -} - -pub struct EnvironmentItem { - path: String, -} -impl EnvironmentItem { - pub fn add_to(node: &Arc, path: String) { - Item::add_to( - node, - nanoid!(), - &ITEM_TYPE_INFO_ENVIRONMENT, - ItemType::Environment(EnvironmentItem { path }), - ); - node.add_local_method("get_path", EnvironmentItem::get_path_flex); - } - - fn get_path_flex( - node: Arc, - _calling_client: Arc, - _message: Message, - response: MethodResponseSender, - ) { - response.wrap_sync(move || { - let ItemType::Environment(environment_item) = - &node.get_aspect::().unwrap().specialization - else { - return Err(eyre!("Wrong item type?")); - }; - Ok(serialize(environment_item.path.as_str())?.into()) - }); - } - - pub fn serialize_start_data(&self, id: &str) -> Result { - Ok(serialize((id, self.path.as_str()))?.into()) - } -} - -pub(super) fn create_environment_item_flex( - _node: Arc, - calling_client: Arc, - message: Message, -) -> Result<()> { - #[derive(Deserialize)] - struct CreateEnvironmentItemInfo<'a> { - name: &'a str, - parent_path: &'a str, - transform: Transform, - item_data: String, - } - let info: CreateEnvironmentItemInfo = deserialize(message.as_ref())?; - let parent_name = format!("/item/{}/item", ITEM_TYPE_INFO_ENVIRONMENT.type_name); - let space = calling_client - .get_node("Spatial parent", info.parent_path)? - .get_aspect::()?; - let transform = parse_transform(info.transform, true, true, false); - - let node = Node::create_parent_name(&INTERNAL_CLIENT, &parent_name, info.name, false) - .add_to_scenegraph()?; - Spatial::add_to(&node, None, transform * space.global_transform(), false); - EnvironmentItem::add_to(&node, info.item_data); - node.get_aspect::().unwrap().make_alias_named( - &calling_client, - &parent_name, - info.name, - )?; - Ok(()) -} diff --git a/src/nodes/items/mod.rs b/src/nodes/items/mod.rs index 2259324..d5f5a05 100644 --- a/src/nodes/items/mod.rs +++ b/src/nodes/items/mod.rs @@ -1,30 +1,28 @@ pub mod camera; -mod environment; pub mod panel; use self::camera::CameraItem; -use self::environment::{EnvironmentItem, ITEM_TYPE_INFO_ENVIRONMENT}; -use self::panel::{PanelItemTrait, ITEM_TYPE_INFO_PANEL}; +use self::panel::PanelItemTrait; use super::fields::Field; -use super::spatial::{parse_transform, Spatial}; +use super::spatial::Spatial; use super::{Alias, Aspect, Message, Node}; use crate::core::client::Client; use crate::core::node_collections::LifeLinkedNodeMap; use crate::core::registry::Registry; use crate::nodes::alias::AliasInfo; -use crate::nodes::fields::find_field; use crate::nodes::spatial::Transform; -use color_eyre::eyre::{ensure, eyre, Result}; +use color_eyre::eyre::{ensure, Result}; use lazy_static::lazy_static; use nanoid::nanoid; use parking_lot::Mutex; use portable_atomic::Ordering; -use serde::Deserialize; -use stardust_xr::schemas::flex::{deserialize, serialize}; +use stardust_xr::schemas::flex::deserialize; use std::hash::Hash; use std::sync::{Arc, Weak}; +stardust_xr_server_codegen::codegen_item_protocol!(); + lazy_static! { static ref ITEM_ALIAS_LOCAL_SIGNALS: Vec<&'static str> = vec![ "get_bounds", @@ -68,6 +66,8 @@ pub struct TypeInfo { pub ui: Mutex>, pub items: Registry, pub acceptors: Registry, + pub new_acceptor_fn: + fn(node: &Node, uid: &str, acceptor: &Arc, acceptor_field: &Arc), } impl Hash for TypeInfo { fn hash(&self, state: &mut H) { @@ -182,15 +182,19 @@ impl Drop for Item { pub enum ItemType { Camera(CameraItem), - Environment(EnvironmentItem), Panel(Arc), } impl ItemType { - fn serialize_start_data(&self, id: &str) -> Result { + fn send_ui_item_created(&self, node: &Node, uid: &str, item: &Arc) { match self { - ItemType::Camera(c) => c.serialize_start_data(id), - ItemType::Environment(e) => e.serialize_start_data(id), - ItemType::Panel(p) => p.serialize_start_data(id), + ItemType::Camera(c) => c.send_ui_item_created(node, uid, item), + ItemType::Panel(p) => p.send_ui_item_created(node, uid, item), + } + } + fn send_acceptor_item_created(&self, node: &Node, uid: &str, item: &Arc) { + match self { + ItemType::Camera(c) => c.send_acceptor_item_created(node, uid, item), + ItemType::Panel(p) => p.send_acceptor_item_created(node, uid, item), } } } @@ -237,16 +241,6 @@ impl ItemUI { } Ok(()) } - fn send_state(&self, state: &str, name: &str) { - let Ok(serialized_data) = serialize(name) else { - return; - }; - let _ = self - .node - .upgrade() - .unwrap() - .send_remote_signal(state, serialized_data); - } fn handle_create_item(&self, item: &Item) { let Some(node) = self.node.upgrade() else { @@ -256,38 +250,26 @@ impl ItemUI { return; }; - if let Ok(alias_node) = item.make_alias(&client, &(node.get_path().to_string() + "/item")) { - self.item_aliases.add(item.uid.clone(), &alias_node); - } - - let Ok(serialized_data) = item.specialization.serialize_start_data(&item.uid) else { + let Ok(item_alias) = item.make_alias(&client, &(node.get_path().to_string() + "/item")) + else { return; }; - let _ = node.send_remote_signal("create_item", serialized_data); - } - fn handle_destroy_item(&self, item: &Item) { - self.item_aliases.remove(&item.uid); - self.send_state("destroy_item", item.uid.as_str()); + self.item_aliases.add(item.uid.clone(), &item_alias); + + item.specialization + .send_ui_item_created(&node, &item.uid, &item_alias); } fn handle_capture_item(&self, item: &Item, acceptor: &ItemAcceptor) { - let Some(node) = self.node.upgrade() else { - return; - }; - - let Ok(message) = serialize((item.uid.as_str(), acceptor.uid.as_str())) else { - return; - }; - let _ = node.send_remote_signal("capture_item", message); + let _ = + item_ui_client::capture_item(&self.node.upgrade().unwrap(), &item.uid, &acceptor.uid); } fn handle_release_item(&self, item: &Item, acceptor: &ItemAcceptor) { - let Some(node) = self.node.upgrade() else { - return; - }; - - let Ok(message) = serialize((item.uid.as_str(), acceptor.uid.as_str())) else { - return; - }; - let _ = node.send_remote_signal("release_item", message); + let _ = + item_ui_client::release_item(&self.node.upgrade().unwrap(), &item.uid, &acceptor.uid); + } + fn handle_destroy_item(&self, item: &Item) { + let _ = item_ui_client::destroy_item(&self.node.upgrade().unwrap(), &item.uid); + self.item_aliases.remove(&item.uid); } fn handle_create_acceptor(&self, acceptor: &ItemAcceptor) { let Some(node) = self.node.upgrade() else { @@ -297,22 +279,26 @@ impl ItemUI { return; }; - let Ok((alias, field_alias)) = acceptor.make_aliases( + let Ok((acceptor_alias, acceptor_field_alias)) = acceptor.make_aliases( &client, &format!("/item/{}/acceptor", self.type_info.type_name), ) else { return; }; - self.acceptor_aliases.add(acceptor.uid.clone(), &alias); + self.acceptor_aliases + .add(acceptor.uid.clone(), &acceptor_alias); self.acceptor_field_aliases - .add(acceptor.uid.clone(), &field_alias); - let Ok(message) = serialize(&acceptor.uid) else { - return; - }; - let _ = node.send_remote_signal("create_acceptor", message); + .add(acceptor.uid.clone(), &acceptor_field_alias); + + (acceptor.type_info.new_acceptor_fn)( + &node, + &acceptor.uid, + &acceptor_alias, + &acceptor_field_alias, + ); } fn handle_destroy_acceptor(&self, acceptor: &ItemAcceptor) { - self.send_state("destroy_acceptor", acceptor.uid.as_str()); + let _ = item_ui_client::destroy_acceptor(&self.node.upgrade().unwrap(), &acceptor.uid); self.acceptor_aliases.remove(&acceptor.uid); self.acceptor_field_aliases.remove(&acceptor.uid); } @@ -397,31 +383,27 @@ impl ItemAcceptor { }; self.accepted_registry.add_raw(item); - if let Ok(alias_node) = item.make_alias(&client, &node.path) { - self.accepted_aliases.add(item.uid.clone(), &alias_node); - } - - let Ok(serialized_data) = item.specialization.serialize_start_data(&item.uid) else { + let Ok(alias_node) = item.make_alias(&client, &node.path) else { return; }; - let _ = node.send_remote_signal("capture", serialized_data); + self.accepted_aliases.add(item.uid.clone(), &alias_node); + + item.specialization + .send_acceptor_item_created(&node, &item.uid, &alias_node); } fn handle_release(&self, item: &Item) { - let Some(node) = self.node.upgrade() else { - return; - }; + if let Some(node) = self.node.upgrade() { + let _ = item_acceptor_client::release_item(&node, &item.uid); + } self.accepted_registry.remove(item); self.accepted_aliases.remove(&item.uid); - let Ok(message) = serialize(&item.uid) else { - return; - }; - let _ = node.send_remote_signal("release", message); } } impl Aspect for ItemAcceptor { const NAME: &'static str = "ItemAcceptor"; } +impl ItemAcceptorAspect for ItemAcceptor {} impl Drop for ItemAcceptor { fn drop(&mut self) { self.type_info.acceptors.remove(self); @@ -434,69 +416,31 @@ impl Drop for ItemAcceptor { } } -pub fn create_interface(client: &Arc) -> Result<()> { - let node = Node::create_parent_name(client, "", "item", false); - node.add_local_signal("create_camera_item", camera::create_camera_item_flex); - node.add_local_signal( - "create_environment_item", - environment::create_environment_item_flex, - ); - node.add_local_signal("register_item_ui", register_item_ui_flex); - node.add_local_signal("create_item_acceptor", create_item_acceptor_flex); - node.add_to_scenegraph().map(|_| ()) -} - -fn type_info(name: &str) -> Result<&'static TypeInfo> { - match name { - "environment" => Ok(&ITEM_TYPE_INFO_ENVIRONMENT), - #[cfg(feature = "wayland")] - "panel" => Ok(&ITEM_TYPE_INFO_PANEL), - _ => Err(eyre!("Invalid item type")), - } -} - pub fn register_item_ui_flex( - _node: Arc, calling_client: Arc, - message: Message, + type_info: &'static TypeInfo, ) -> Result<()> { - #[derive(Deserialize)] - struct RegisterItemUIInfo<'a> { - item_type: &'a str, - } - let info: RegisterItemUIInfo = deserialize(message.as_ref())?; - let type_info = type_info(info.item_type)?; let ui = Node::create_parent_name(&calling_client, "/item", type_info.type_name, true) .add_to_scenegraph()?; ItemUI::add_to(&ui, type_info)?; Ok(()) } - fn create_item_acceptor_flex( - _node: Arc, calling_client: Arc, - message: Message, + name: String, + parent: Arc, + transform: Transform, + type_info: &'static TypeInfo, + field: Arc, ) -> Result<()> { - #[derive(Deserialize)] - struct CreateItemAcceptorInfo<'a> { - name: &'a str, - parent_path: &'a str, - transform: Transform, - field_path: &'a str, - item_type: &'a str, - } - let info: CreateItemAcceptorInfo = deserialize(message.as_ref())?; - let space = calling_client - .get_node("Reference space", info.parent_path)? - .get_aspect::()?; - let transform = parse_transform(info.transform, true, true, false); - let field = find_field(&calling_client, info.field_path)?; - let type_info = type_info(info.item_type)?; + let space = parent.get_aspect::()?; + let field = field.get_aspect::()?; + let transform = transform.to_mat4(true, true, false); let node = Node::create_parent_name( &calling_client, &format!("/item/{}/acceptor", type_info.type_name), - info.name, + &name, true, ) .add_to_scenegraph()?; @@ -504,3 +448,6 @@ fn create_item_acceptor_flex( ItemAcceptor::add_to(&node, type_info, field); Ok(()) } + +struct ItemInterface; +// create_interface!(ItemInterface, ItemInterfaceAspect, "/item"); diff --git a/src/nodes/items/panel.rs b/src/nodes/items/panel.rs index aba523d..e34f97a 100644 --- a/src/nodes/items/panel.rs +++ b/src/nodes/items/panel.rs @@ -3,28 +3,25 @@ use crate::{ client::{get_env, state, Client, INTERNAL_CLIENT}, registry::Registry, }, + create_interface, nodes::{ drawable::model::ModelPart, items::{Item, ItemType, TypeInfo}, - spatial::Spatial, - Message, Node, + spatial::{Spatial, Transform}, + Node, }, }; -use color_eyre::eyre::{eyre, Result}; +use color_eyre::eyre::Result; use glam::Mat4; use lazy_static::lazy_static; use mint::Vector2; use nanoid::nanoid; -use rustc_hash::FxHashMap; -use serde::{ - de::{Deserializer, Error, SeqAccess, Visitor}, - ser::Serializer, - Deserialize, Serialize, -}; -use stardust_xr::schemas::flex::{deserialize, serialize}; use std::sync::{Arc, Weak}; use tracing::{debug, info}; +use super::{create_item_acceptor_flex, register_item_ui_flex, ItemInterface}; + +stardust_xr_server_codegen::codegen_item_panel_protocol!(); lazy_static! { pub static ref ITEM_TYPE_INFO_PANEL: TypeInfo = TypeInfo { type_name: "panel", @@ -61,146 +58,39 @@ lazy_static! { ui: Default::default(), items: Registry::new(), acceptors: Registry::new(), + new_acceptor_fn: |node, uid, acceptor, acceptor_field| { + let _ = panel_item_ui_client::create_acceptor(node, uid, acceptor, acceptor_field); + } }; } -/// An ID for a surface inside this panel item -#[derive(Debug, Clone)] -#[allow(dead_code)] -pub enum SurfaceID { - Cursor, - Toplevel, - Child(String), -} -impl Default for SurfaceID { - fn default() -> Self { - Self::Toplevel - } -} - -impl<'de> serde::Deserialize<'de> for SurfaceID { - fn deserialize>(deserializer: D) -> Result { - deserializer.deserialize_seq(SurfaceIDVisitor) - } -} - -struct SurfaceIDVisitor; - -impl<'de> Visitor<'de> for SurfaceIDVisitor { - type Value = SurfaceID; - - fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.write_str("idk") - } - - fn visit_seq>(self, mut seq: A) -> Result { - let Some(discrim) = seq.next_element()? else { - return Err(A::Error::missing_field("discrim")); - }; - - // idk if you wanna check for extraneous elements - // I didn't bother - - match discrim { - "Cursor" => Ok(SurfaceID::Cursor), - "Toplevel" => Ok(SurfaceID::Toplevel), - "Child" => { - let Some(text) = seq.next_element()? else { - return Err(A::Error::missing_field("child_text")); - }; - Ok(SurfaceID::Child(text)) - } - _ => Err(A::Error::unknown_variant( - discrim, - &["Cursor", "Toplevel", "Child"], - )), - } - } -} - -impl serde::Serialize for SurfaceID { - fn serialize(&self, serializer: S) -> Result { - match self { - Self::Cursor => ["Cursor"].serialize(serializer), - Self::Toplevel => ["Toplevel"].serialize(serializer), - Self::Child(text) => ["Child", text].serialize(serializer), - } - } -} - -/// The origin and size of the surface's "solid" part. -#[derive(Debug, Serialize, Clone, Copy)] -pub struct Geometry { - pub origin: Vector2, - pub size: Vector2, -} -/// The state of the panel item's toplevel. -#[derive(Debug, Clone, Serialize)] -pub struct ToplevelInfo { - /// The UID of the panel item of the parent of this toplevel, if it exists - pub parent: Option, - /// Equivalent to the window title - pub title: Option, - /// Application identifier, see - pub app_id: Option, - /// Current size in pixels - pub size: Vector2, - /// Recommended minimum size in pixels - pub min_size: Option>, - /// Recommended maximum size in pixels - pub max_size: Option>, - /// Surface geometry - pub logical_rectangle: Geometry, -} - -/// Data on positioning a child -#[derive(Debug, Clone, Serialize)] -pub struct ChildInfo { - pub parent: SurfaceID, - pub geometry: Geometry, -} - -/// The init data for the panel item. -#[derive(Debug, Clone, Serialize)] -pub struct PanelItemInitData { - /// The cursor, if applicable. - pub cursor: Option, - /// Size of the toplevel surface in pixels. - pub toplevel: ToplevelInfo, - /// Vector of childs that already exist - pub children: FxHashMap, - /// The surface, if any, that has exclusive input to the pointer. - pub pointer_grab: Option, - /// The surface, if any, that has exclusive input to the keyboard. - pub keyboard_grab: Option, -} - pub trait Backend: Send + Sync + 'static { fn start_data(&self) -> Result; - fn surface_alive(&self, surface: &SurfaceID) -> bool; + fn surface_alive(&self, surface: &SurfaceId) -> bool; - fn apply_surface_material(&self, surface: SurfaceID, model_part: &Arc); + fn apply_cursor_material(&self, model_part: &Arc); + fn apply_surface_material(&self, surface: SurfaceId, model_part: &Arc); fn close_toplevel(&self); fn auto_size_toplevel(&self); fn set_toplevel_size(&self, size: Vector2); fn set_toplevel_focused_visuals(&self, focused: bool); - fn pointer_motion(&self, surface: &SurfaceID, position: Vector2); - fn pointer_button(&self, surface: &SurfaceID, button: u32, pressed: bool); + fn pointer_motion(&self, surface: &SurfaceId, position: Vector2); + fn pointer_button(&self, surface: &SurfaceId, button: u32, pressed: bool); fn pointer_scroll( &self, - surface: &SurfaceID, + surface: &SurfaceId, scroll_distance: Option>, scroll_steps: Option>, ); - fn keyboard_keys(&self, surface: &SurfaceID, keymap_id: &str, keys: Vec); + fn keyboard_keys(&self, surface: &SurfaceId, keymap_id: &str, keys: Vec); - fn touch_down(&self, surface: &SurfaceID, id: u32, position: Vector2); + fn touch_down(&self, surface: &SurfaceId, id: u32, position: Vector2); fn touch_move(&self, id: u32, position: Vector2); fn touch_up(&self, id: u32); - fn reset_touches(&self); + fn reset_input(&self); } pub fn panel_item_from_node(node: &Node) -> Option> { @@ -211,7 +101,8 @@ pub fn panel_item_from_node(node: &Node) -> Option> { } pub trait PanelItemTrait: Backend + Send + Sync + 'static { - fn serialize_start_data(&self, id: &str) -> Result; + fn send_ui_item_created(&self, node: &Node, uid: &str, item: &Arc); + fn send_acceptor_item_created(&self, node: &Node, uid: &str, item: &Arc); } pub struct PanelItem { @@ -252,22 +143,7 @@ impl PanelItem { &ITEM_TYPE_INFO_PANEL, ItemType::Panel(generic_panel_item), ); - - node.add_local_signal("apply_surface_material", Self::apply_surface_material_flex); - node.add_local_signal("close_toplevel", Self::close_toplevel_flex); - node.add_local_signal("auto_size_toplevel", Self::auto_size_toplevel_flex); - node.add_local_signal("set_toplevel_size", Self::set_toplevel_size_flex); - - node.add_local_signal("pointer_motion", Self::pointer_motion_flex); - node.add_local_signal("pointer_button", Self::pointer_button_flex); - node.add_local_signal("pointer_scroll", Self::pointer_scroll_flex); - - node.add_local_signal("keyboard_key", Self::keyboard_keys_flex); - - node.add_local_signal("touch_down", Self::touch_down_flex); - node.add_local_signal("touch_move", Self::touch_move_flex); - node.add_local_signal("touch_up", Self::touch_up_flex); - node.add_local_signal("reset_touches", Self::reset_touches_flex); + ::add_node_members(&node); (node, panel_item) } @@ -286,265 +162,300 @@ impl PanelItem { let Some(node) = self.node.upgrade() else { return; }; - let _ = node.send_remote_signal("toplevel_parent_changed", serialize(parent).unwrap()); + panel_item_client::toplevel_parent_changed(&node, parent); } pub fn toplevel_title_changed(&self, title: &str) { let Some(node) = self.node.upgrade() else { return; }; - let _ = node.send_remote_signal("toplevel_title_changed", serialize(title).unwrap()); + panel_item_client::toplevel_title_changed(&node, title); } pub fn toplevel_app_id_changed(&self, app_id: &str) { let Some(node) = self.node.upgrade() else { return; }; - let _ = node.send_remote_signal("toplevel_app_id_changed", serialize(app_id).unwrap()); + panel_item_client::toplevel_app_id_changed(&node, app_id); } pub fn toplevel_fullscreen_active(&self, active: bool) { let Some(node) = self.node.upgrade() else { return; }; - let _ = node.send_remote_signal("toplevel_fullscreen_active", serialize(active).unwrap()); + panel_item_client::toplevel_fullscreen_active(&node, active); } pub fn toplevel_move_request(&self) { let Some(node) = self.node.upgrade() else { return; }; - let _ = node.send_remote_signal("toplevel_move_request", Vec::::new()); + panel_item_client::toplevel_move_request(&node); } pub fn toplevel_resize_request(&self, up: bool, down: bool, left: bool, right: bool) { let Some(node) = self.node.upgrade() else { return; }; - let _ = node.send_remote_signal( - "toplevel_resize_request", - serialize((up, down, left, right)).unwrap(), - ); + panel_item_client::toplevel_resize_request(&node, up, down, left, right); } pub fn toplevel_size_changed(&self, size: Vector2) { let Some(node) = self.node.upgrade() else { return; }; - let _ = node.send_remote_signal("toplevel_size_changed", serialize(size).unwrap()); + panel_item_client::toplevel_size_changed(&node, size); } pub fn set_cursor(&self, geometry: Option) { let Some(node) = self.node.upgrade() else { return; }; - let _ = node.send_remote_signal("set_cursor", serialize(geometry).unwrap()); + if let Some(geometry) = geometry { + panel_item_client::set_cursor(&node, &geometry); + } else { + panel_item_client::hide_cursor(&node); + } } - pub fn new_child(&self, uid: &str, info: ChildInfo) { + pub fn create_child(&self, uid: &str, info: ChildInfo) { let Some(node) = self.node.upgrade() else { return; }; - let _ = node.send_remote_signal("new_child", serialize((uid, info)).unwrap()); + panel_item_client::create_child(&node, uid, &info); } pub fn reposition_child(&self, uid: &str, geometry: Geometry) { let Some(node) = self.node.upgrade() else { return; }; - let _ = node.send_remote_signal("reposition_child", serialize((uid, geometry)).unwrap()); + panel_item_client::reposition_child(&node, uid, &geometry); } - pub fn drop_child(&self, uid: &str) { + pub fn destroy_child(&self, uid: &str) { let Some(node) = self.node.upgrade() else { return; }; - let _ = node.send_remote_signal("drop_child", serialize(uid).unwrap()); + panel_item_client::destroy_child(&node, uid); } } -// Local signals -macro_rules! flex_no_args { - ($fn_name: ident, $trait_fn: ident) => { - fn $fn_name( - node: Arc, - _calling_client: Arc, - _message: Message, - ) -> Result<()> { - let Some(panel_item) = panel_item_from_node(&node) else { - return Ok(()); - }; - panel_item.$trait_fn(); - Ok(()) - } - }; -} -macro_rules! flex_deserialize { - ($fn_name: ident, $trait_fn: ident) => { - fn $fn_name(node: Arc, _calling_client: Arc, message: Message) -> Result<()> { - let Some(panel_item) = panel_item_from_node(&node) else { - return Ok(()); - }; - panel_item.$trait_fn(deserialize(message.as_ref())?); - Ok(()) - } - }; -} + +// make these stupid vectors u32 in the protocol somehow!!!!!!!1 + #[allow(unused)] -impl PanelItem { - fn apply_surface_material_flex( +impl PanelItemAspect for PanelItem { + #[doc = "Apply the cursor as a material to a model."] + fn apply_cursor_material( + node: Arc, + _calling_client: Arc, + model_part: Arc, + ) -> Result<()> { + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; + let model_part = model_part.get_aspect::()?; + + panel_item.apply_cursor_material(&model_part); + Ok(()) + } + + #[doc = "Apply a surface's visuals as a material to a model."] + fn apply_surface_material( node: Arc, calling_client: Arc, - message: Message, + surface: SurfaceId, + model_part: Arc, ) -> Result<()> { let Some(panel_item) = panel_item_from_node(&node) else { return Ok(()); }; + let model_part = model_part.get_aspect::()?; - #[derive(Debug, Deserialize)] - struct SurfaceMaterialInfo<'a> { - surface: SurfaceID, - model_node_path: &'a str, - } - - let info: SurfaceMaterialInfo = deserialize(message.as_ref())?; - - let model_node = calling_client - .scenegraph - .get_node(info.model_node_path) - .ok_or_else(|| eyre!("Model node not found"))?; - let model_part = model_node.get_aspect::()?; - debug!(?info, "Apply surface material"); - - panel_item.apply_surface_material(info.surface, &model_part); - + panel_item.apply_surface_material(surface, &model_part); Ok(()) } - flex_no_args!(close_toplevel_flex, close_toplevel); - flex_no_args!(auto_size_toplevel_flex, auto_size_toplevel); - flex_deserialize!(set_toplevel_size_flex, set_toplevel_size); + #[doc = "Try to close the toplevel.\n \n The panel item UI handler or panel item acceptor will drop the panel item if this succeeds."] + fn close_toplevel(node: Arc, _calling_client: Arc) -> Result<()> { + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; + panel_item.close_toplevel(); + Ok(()) + } - fn pointer_motion_flex( + #[doc = "Request a resize of the surface to whatever size the 2D app wants."] + fn auto_size_toplevel(node: Arc, _calling_client: Arc) -> Result<()> { + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; + panel_item.auto_size_toplevel(); + Ok(()) + } + + #[doc = "Request a resize of the surface (in pixels)."] + fn set_toplevel_size( node: Arc, _calling_client: Arc, - message: Message, + size: mint::Vector2, ) -> Result<()> { let Some(panel_item) = panel_item_from_node(&node) else { return Ok(()); }; - - let (surface_id, position): (SurfaceID, Vector2) = deserialize(message.as_ref())?; - debug!(?surface_id, ?position, "Pointer deactivate"); - - panel_item.pointer_motion(&surface_id, position); - + panel_item.set_toplevel_size(size); Ok(()) } - fn pointer_button_flex( + + #[doc = "Tell the toplevel to appear focused visually if true, or unfocused if false."] + fn set_toplevel_focused_visuals( node: Arc, _calling_client: Arc, - message: Message, + focused: bool, ) -> Result<()> { let Some(panel_item) = panel_item_from_node(&node) else { return Ok(()); }; - - let (surface_id, button, state): (SurfaceID, u32, u32) = deserialize(message.as_ref())?; - debug!(?surface_id, button, state, "Pointer button"); - - panel_item.pointer_button(&surface_id, button, state != 0); + panel_item.set_toplevel_focused_visuals(focused); Ok(()) } - fn pointer_scroll_flex( + + #[doc = "Send an event to set the pointer's position (in pixels, relative to top-left of surface). This will activate the pointer."] + fn pointer_motion( node: Arc, _calling_client: Arc, - message: Message, + surface: SurfaceId, + position: mint::Vector2, ) -> Result<()> { let Some(panel_item) = panel_item_from_node(&node) else { return Ok(()); }; - - #[derive(Debug, Deserialize)] - struct PointerScrollInfo { - surface_id: SurfaceID, - axis_continuous: Option>, - axis_discrete: Option>, - } - let info: PointerScrollInfo = deserialize(message.as_ref())?; - debug!(?info, "Pointer scroll"); - - panel_item.pointer_scroll(&info.surface_id, info.axis_continuous, info.axis_discrete); - + panel_item.pointer_motion(&surface, position); Ok(()) } - fn keyboard_keys_flex( + #[doc = "Send an event to set a pointer button's state if the pointer's active. The `button` is from the `input_event_codes` crate (e.g. BTN_LEFT for left click)."] + fn pointer_button( node: Arc, _calling_client: Arc, - message: Message, + surface: SurfaceId, + button: u32, + pressed: bool, ) -> Result<()> { let Some(panel_item) = panel_item_from_node(&node) else { return Ok(()); }; - let (surface_id, keymap_id, keys): (SurfaceID, &str, Vec) = - deserialize(message.as_ref())?; - debug!(?keys, "Set keyboard key state"); - - panel_item.keyboard_keys(&surface_id, keymap_id, keys); - + panel_item.pointer_button(&surface, button, pressed); Ok(()) } - pub fn grab_keyboard(&self, sid: Option) { - let Some(node) = self.node.upgrade() else { - return; - }; - let Ok(message) = serialize(sid) else { return }; - let _ = node.send_remote_signal("grab_keyboard", message); - } - - fn touch_down_flex( + #[doc = "Send an event to scroll the pointer if it's active.\nScroll distance is a value in pixels corresponding to the `distance` the surface should be scrolled.\nScroll steps is a value in columns/rows corresponding to the wheel clicks of a mouse or such. This also supports fractions of a wheel click."] + fn pointer_scroll( node: Arc, _calling_client: Arc, - message: Message, + surface: SurfaceId, + scroll_distance: mint::Vector2, + scroll_steps: mint::Vector2, ) -> Result<()> { let Some(panel_item) = panel_item_from_node(&node) else { return Ok(()); }; - - let (surface_id, id, position): (SurfaceID, u32, Vector2) = - deserialize(message.as_ref())?; - debug!(?surface_id, id, ?position, "Touch down"); - - panel_item.touch_down(&surface_id, id, position); - + panel_item.pointer_scroll(&surface, Some(scroll_distance), Some(scroll_steps)); Ok(()) } - fn touch_move_flex( + + #[doc = "Send an event to stop scrolling the pointer."] + fn pointer_stop_scroll( node: Arc, _calling_client: Arc, - message: Message, + surface: SurfaceId, ) -> Result<()> { let Some(panel_item) = panel_item_from_node(&node) else { return Ok(()); }; - - let (id, position): (u32, Vector2) = deserialize(message.as_ref())?; - debug!(?position, "Touch move"); - - panel_item.touch_move(id, position); - + panel_item.pointer_scroll(&surface, None, None); + Ok(()) + } + + #[doc = "Send a series of key presses and releases (positive keycode for pressed, negative for released)."] + fn keyboard_keys( + node: Arc, + _calling_client: Arc, + surface: SurfaceId, + keymap_id: String, + keys: Vec, + ) -> Result<()> { + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; + panel_item.keyboard_keys(&surface, &keymap_id, keys); + Ok(()) + } + + #[doc = "Put a touch down on this surface with the unique ID `uid` at `position` (in pixels) from top left corner of the surface."] + fn touch_down( + node: Arc, + _calling_client: Arc, + surface: SurfaceId, + uid: u32, + position: mint::Vector2, + ) -> Result<()> { + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; + panel_item.touch_down(&surface, uid, position); + Ok(()) + } + + #[doc = "Move an existing touch point."] + fn touch_move( + node: Arc, + _calling_client: Arc, + uid: u32, + position: mint::Vector2, + ) -> Result<()> { + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; + panel_item.touch_move(uid, position); + Ok(()) + } + + #[doc = "Release a touch from its surface."] + fn touch_up(node: Arc, _calling_client: Arc, uid: u32) -> Result<()> { + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; + panel_item.touch_up(uid); + Ok(()) + } + + #[doc = "Reset all input, such as pressed keys and pointer clicks and touches. Useful for when it's newly captured into an item acceptor to make sure no input gets stuck."] + fn reset_input(node: Arc, _calling_client: Arc) -> Result<()> { + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; + panel_item.reset_input(); Ok(()) } - flex_deserialize!(touch_up_flex, touch_up); - flex_no_args!(reset_touches_flex, reset_touches); } impl PanelItemTrait for PanelItem { - fn serialize_start_data(&self, id: &str) -> Result { - Ok(serialize((id, self.start_data()?))?.into()) + fn send_ui_item_created(&self, node: &Node, uid: &str, item: &Arc) { + let Ok(init_data) = self.backend.start_data() else { + return; + }; + let _ = panel_item_ui_client::create_item(node, uid, item, init_data); + } + fn send_acceptor_item_created(&self, node: &Node, uid: &str, item: &Arc) { + let Ok(init_data) = self.backend.start_data() else { + return; + }; + let _ = panel_item_acceptor_client::capture_item(node, uid, item, init_data); } } impl Backend for PanelItem { fn start_data(&self) -> Result { self.backend.start_data() } - fn surface_alive(&self, surface: &SurfaceID) -> bool { + fn surface_alive(&self, surface: &SurfaceId) -> bool { self.backend.surface_alive(surface) } - fn apply_surface_material(&self, surface: SurfaceID, model_part: &Arc) { + fn apply_cursor_material(&self, model_part: &Arc) { + self.backend.apply_cursor_material(model_part) + } + fn apply_surface_material(&self, surface: SurfaceId, model_part: &Arc) { self.backend.apply_surface_material(surface, model_part) } @@ -561,15 +472,15 @@ impl Backend for PanelItem { self.backend.set_toplevel_focused_visuals(focused) } - fn pointer_motion(&self, surface: &SurfaceID, position: Vector2) { + fn pointer_motion(&self, surface: &SurfaceId, position: Vector2) { self.backend.pointer_motion(surface, position) } - fn pointer_button(&self, surface: &SurfaceID, button: u32, pressed: bool) { + fn pointer_button(&self, surface: &SurfaceId, button: u32, pressed: bool) { self.backend.pointer_button(surface, button, pressed) } fn pointer_scroll( &self, - surface: &SurfaceID, + surface: &SurfaceId, scroll_distance: Option>, scroll_steps: Option>, ) { @@ -577,11 +488,11 @@ impl Backend for PanelItem { .pointer_scroll(surface, scroll_distance, scroll_steps) } - fn keyboard_keys(&self, surface: &SurfaceID, keymap_id: &str, keys: Vec) { + fn keyboard_keys(&self, surface: &SurfaceId, keymap_id: &str, keys: Vec) { self.backend.keyboard_keys(surface, keymap_id, keys) } - fn touch_down(&self, surface: &SurfaceID, id: u32, position: Vector2) { + fn touch_down(&self, surface: &SurfaceId, id: u32, position: Vector2) { self.backend.touch_down(surface, id, position) } fn touch_move(&self, id: u32, position: Vector2) { @@ -590,8 +501,8 @@ impl Backend for PanelItem { fn touch_up(&self, id: u32) { self.backend.touch_up(id) } - fn reset_touches(&self) { - self.backend.reset_touches() + fn reset_input(&self) { + self.backend.reset_input() } } impl Drop for PanelItem { @@ -600,3 +511,30 @@ impl Drop for PanelItem { info!("Dropped panel item {}", self.uid); } } + +create_interface!(ItemInterface, ItemPanelInterfaceAspect, "/item/panel"); +impl ItemPanelInterfaceAspect for ItemInterface { + #[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, calling_client: Arc) -> Result<()> { + 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//acceptor/`."] + fn create_panel_item_acceptor( + _node: Arc, + calling_client: Arc, + name: String, + parent: Arc, + transform: Transform, + field: Arc, + ) -> Result<()> { + create_item_acceptor_flex( + calling_client, + name, + parent, + transform, + &ITEM_TYPE_INFO_PANEL, + field, + ) + } +} diff --git a/src/wayland/seat.rs b/src/wayland/seat.rs index 293f08c..8239c15 100644 --- a/src/wayland/seat.rs +++ b/src/wayland/seat.rs @@ -307,7 +307,7 @@ impl SeatWrapper { }, ); } - pub fn reset_touches(&self) { + pub fn reset_input(&self) { for id in self.touches.lock().keys() { self.touch_up(*id) } diff --git a/src/wayland/xdg_shell.rs b/src/wayland/xdg_shell.rs index 2a3549b..af7acad 100644 --- a/src/wayland/xdg_shell.rs +++ b/src/wayland/xdg_shell.rs @@ -7,7 +7,7 @@ use super::{ use crate::nodes::{ drawable::model::ModelPart, items::panel::{ - Backend, ChildInfo, Geometry, PanelItem, PanelItemInitData, SurfaceID, ToplevelInfo, + Backend, ChildInfo, Geometry, PanelItem, PanelItemInitData, SurfaceId, ToplevelInfo, }, }; use color_eyre::eyre::Result; @@ -85,7 +85,7 @@ impl XdgShellHandler for WaylandState { s.states.unset(State::Fullscreen); }); toplevel.send_configure(); - utils::insert_data(toplevel.wl_surface(), SurfaceID::Toplevel); + utils::insert_data(toplevel.wl_surface(), SurfaceId::Toplevel); CoreSurface::add_to( self.display_handle.clone(), toplevel.wl_surface(), @@ -194,7 +194,7 @@ impl XdgShellHandler for WaylandState { if popup.send_configure().is_err() { return; } - utils::insert_data(popup.wl_surface(), SurfaceID::Child(uid.clone())); + utils::insert_data(popup.wl_surface(), SurfaceId::Child(uid.clone())); utils::insert_data(popup.wl_surface(), uid.clone()); utils::insert_data(popup.wl_surface(), Arc::downgrade(&panel_item)); CoreSurface::add_to( @@ -341,18 +341,10 @@ impl XdgBackend { seat, } } - fn wl_surface_from_id(&self, id: &SurfaceID) -> Option { + fn wl_surface_from_id(&self, id: &SurfaceId) -> Option { match id { - SurfaceID::Cursor => self - .seat - .cursor_info_rx - .borrow() - .surface - .clone()? - .upgrade() - .ok(), - SurfaceID::Toplevel => Some(self.toplevel.lock().clone()?.wl_surface().clone()), - SurfaceID::Child(popup) => { + SurfaceId::Toplevel(_) => Some(self.toplevel.lock().clone()?.wl_surface().clone()), + SurfaceId::Child(popup) => { let popups = self.popups.lock(); Some(popups.get(popup)?.0.wl_surface().clone()) } @@ -371,12 +363,12 @@ impl XdgBackend { .lock() .insert(uid.to_string(), (popup, positioner)); - panel_item.new_child(uid, self.child_data(uid).unwrap()); + panel_item.create_child(uid, self.child_data(uid).unwrap()); } pub fn reposition_popup(&self, uid: &str, _popup: PopupSurface, positioner: PositionerState) { let mut popups = self.popups.lock(); let Some((_, old_positioner)) = popups.get_mut(uid) else { - return + return; }; let Some(panel_item) = self.panel_item() else { return; @@ -390,13 +382,13 @@ impl XdgBackend { let Some(panel_item) = self.panel_item() else { return; }; - panel_item.drop_child(uid); + panel_item.destroy_child(uid); } fn child_data(&self, uid: &str) -> Option { let (popup, positioner) = self.popups.lock().get(uid)?.clone(); Some(ChildInfo { - parent: (*utils::get_data::(&popup.get_parent_surface()?)?).clone(), + parent: (*utils::get_data::(&popup.get_parent_surface()?)?).clone(), geometry: positioner.get_geometry().into(), }) } @@ -448,9 +440,9 @@ impl Backend for XdgBackend { .current_state() .size .clone() - .map(|s| [s.w as u32, s.h as u32].into()) + .map(|s| Vector2::from([s.w as u32, s.h as u32])) .or_else(|| toplevel_core_surface.size()) - .unwrap_or([0; 2].into()); + .unwrap_or(Vector2::from([0; 2])); let toplevel = ToplevelInfo { parent: toplevel .parent() @@ -465,8 +457,8 @@ impl Backend for XdgBackend { { Some( [ - toplevel_cached_state.min_size.w as u32, - toplevel_cached_state.min_size.h as u32, + toplevel_cached_state.min_size.w as f32, + toplevel_cached_state.min_size.h as f32, ] .into(), ) @@ -478,8 +470,8 @@ impl Backend for XdgBackend { { Some( [ - toplevel_cached_state.max_size.w as u32, - toplevel_cached_state.max_size.h as u32, + toplevel_cached_state.max_size.w as f32, + toplevel_cached_state.max_size.h as f32, ] .into(), ) @@ -489,7 +481,7 @@ impl Backend for XdgBackend { logical_rectangle: toplevel_cached_state .geometry .map(Into::into) - .unwrap_or(Geometry { + .unwrap_or_else(|| Geometry { origin: [0; 2].into(), size, }), @@ -511,14 +503,31 @@ impl Backend for XdgBackend { }) } - fn surface_alive(&self, surface: &SurfaceID) -> bool { + fn surface_alive(&self, surface: &SurfaceId) -> bool { let Some(surface) = self.wl_surface_from_id(surface) else { return false; }; surface.is_alive() } - fn apply_surface_material(&self, surface: SurfaceID, model_part: &Arc) { + fn apply_cursor_material(&self, model_part: &Arc) { + let Some(surface) = self + .seat + .cursor_info_rx + .borrow() + .surface + .clone() + .and_then(|s| s.upgrade().ok()) + else { + return; + }; + + let Some(core_surface) = CoreSurface::from_wl_surface(&surface) else { + return; + }; + core_surface.apply_material(model_part); + } + fn apply_surface_material(&self, surface: SurfaceId, model_part: &Arc) { let Some(surface) = self.wl_surface_from_id(&surface) else { return; }; @@ -561,32 +570,32 @@ impl Backend for XdgBackend { }) } - fn pointer_motion(&self, surface: &SurfaceID, position: Vector2) { + fn pointer_motion(&self, surface: &SurfaceId, position: Vector2) { let Some(surface) = self.wl_surface_from_id(&surface) else { return; }; self.seat.pointer_motion(surface, position) } - fn pointer_button(&self, _surface: &SurfaceID, button: u32, pressed: bool) { + fn pointer_button(&self, _surface: &SurfaceId, button: u32, pressed: bool) { self.seat.pointer_button(button, pressed) } fn pointer_scroll( &self, - _surface: &SurfaceID, + _surface: &SurfaceId, scroll_distance: Option>, scroll_steps: Option>, ) { self.seat.pointer_scroll(scroll_distance, scroll_steps) } - fn keyboard_keys(&self, surface: &SurfaceID, keymap_id: &str, keys: Vec) { + fn keyboard_keys(&self, surface: &SurfaceId, keymap_id: &str, keys: Vec) { let Some(surface) = self.wl_surface_from_id(&surface) else { return; }; self.seat.keyboard_keys(surface, keymap_id, keys) } - fn touch_down(&self, surface: &SurfaceID, id: u32, position: Vector2) { + fn touch_down(&self, surface: &SurfaceId, id: u32, position: Vector2) { let Some(surface) = self.wl_surface_from_id(&surface) else { return; }; @@ -598,7 +607,7 @@ impl Backend for XdgBackend { fn touch_up(&self, id: u32) { self.seat.touch_up(id) } - fn reset_touches(&self) { - self.seat.reset_touches() + fn reset_input(&self) { + self.seat.reset_input() } }