diff --git a/Cargo.lock b/Cargo.lock index a5a3931..23ee020 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -873,6 +873,26 @@ dependencies = [ "web-sys", ] +[[package]] +name = "const-random" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaf16c9c2c612020bcfd042e170f6e32de9b9d75adb5277cdbbd2e2c8c8299a" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.10", + "once_cell", + "tiny-keccak", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -980,6 +1000,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -1104,6 +1130,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive-syn-parse" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79116f119dd1dba1abf1f3405f03b9b0e79a27a3883864bfebded8a3dc768cd" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -2693,6 +2730,54 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +[[package]] +name = "macro_magic" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e03844fc635e92f3a0067e25fa4bf3e3dbf3f2927bf3aa01bb7bc8f1c428949d" +dependencies = [ + "macro_magic_core", + "macro_magic_macros", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "macro_magic_core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "468155613a44cfd825f1fb0ffa532b018253920d404e6fca1e8d43155198a46d" +dependencies = [ + "const-random", + "derive-syn-parse", + "macro_magic_core_macros", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "macro_magic_core_macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea73aa640dc01d62a590d48c0c3521ed739d53b27f919b25c3551e233481654" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "macro_magic_macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef9d79ae96aaba821963320eb2b6e34d17df1e5a83d8a1985c29cc5be59577b3" +dependencies = [ + "macro_magic_core", + "quote", + "syn 2.0.38", +] + [[package]] name = "malloc_buf" version = "0.0.6" @@ -3495,6 +3580,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "prettyplease" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +dependencies = [ + "proc-macro2", + "syn 2.0.38", +] + [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -3544,6 +3639,28 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proc-util-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e6073edb3261de7793bbde3002e69e6a4baaa34f5e321e299dd30e3c7489ad" +dependencies = [ + "syn 2.0.38", +] + +[[package]] +name = "proc-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "842fd9aaf81ebd6351f2419bd99dd4dae9d97ae2824243e82c69323df4fd1e6b" +dependencies = [ + "prettyplease", + "proc-macro2", + "proc-util-macros", + "quote", + "syn 2.0.38", +] + [[package]] name = "profiling" version = "1.0.11" @@ -3577,6 +3694,7 @@ dependencies = [ "epaint", "futures-intrusive", "log", + "macro_magic", "pollster", "serde", "wgpu", @@ -3607,6 +3725,7 @@ dependencies = [ "epaint", "futures-intrusive", "log", + "macro_magic", "pollster", "radiant-core", "serde", @@ -3617,7 +3736,9 @@ dependencies = [ name = "radiant-macros" version = "0.1.0" dependencies = [ + "macro_magic", "proc-macro2", + "proc-utils", "quote", "syn 2.0.38", ] @@ -3631,6 +3752,7 @@ dependencies = [ "epaint", "futures-intrusive", "log", + "macro_magic", "pollster", "radiant-core", "serde", @@ -3650,6 +3772,7 @@ dependencies = [ "futures-intrusive", "js-sys", "log", + "macro_magic", "pollster", "radiant-core", "radiant-image-node", @@ -3684,6 +3807,7 @@ dependencies = [ "epaint", "futures-intrusive", "log", + "macro_magic", "pollster", "radiant-core", "serde", @@ -4806,6 +4930,15 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tiny-skia" version = "0.8.4" diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 00f27a9..971bd4b 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -13,4 +13,5 @@ cgmath = "0.18" serde = { version = "1.0", features = ["derive"] } epaint = { version = "0.22.0", features = ["bytemuck", "serde"] } pollster = "0.3" -futures-intrusive = "0.5" \ No newline at end of file +futures-intrusive = "0.5" +macro_magic = "0.5.0" diff --git a/crates/core/src/interactions/interaction_manager.rs b/crates/core/src/interactions/interaction_manager.rs index c44f593..9e383a8 100644 --- a/crates/core/src/interactions/interaction_manager.rs +++ b/crates/core/src/interactions/interaction_manager.rs @@ -1,7 +1,9 @@ use crate::{BoundingBoxInteraction, RadiantNode, ScreenDescriptor}; use epaint::ClippedPrimitive; use serde::{Deserialize, Serialize}; +use macro_magic::export_tokens; +#[export_tokens] #[derive(Serialize, Deserialize, Debug, Clone)] pub enum InteractionMessage { TransformNode { diff --git a/crates/core/src/tools/rectangle_tool.rs b/crates/core/src/tools/rectangle_tool.rs index 302ce6c..7c6771c 100644 --- a/crates/core/src/tools/rectangle_tool.rs +++ b/crates/core/src/tools/rectangle_tool.rs @@ -1,7 +1,8 @@ use serde::{Deserialize, Serialize}; - use crate::RadiantTool; +use macro_magic::export_tokens; +#[export_tokens] #[derive(Serialize, Deserialize, Debug, Clone)] pub enum RectangleToolMessage { AddNode { diff --git a/crates/core/src/tools/selection_tool.rs b/crates/core/src/tools/selection_tool.rs index 957e3bf..8b936cd 100644 --- a/crates/core/src/tools/selection_tool.rs +++ b/crates/core/src/tools/selection_tool.rs @@ -1,9 +1,13 @@ use crate::RadiantTool; use serde::{Deserialize, Serialize}; +use macro_magic::export_tokens; +#[export_tokens] #[derive(Serialize, Deserialize, Debug, Clone)] pub enum SelectionToolMessage { - SelectNode(u64), + SelectNode { + id: u64, + }, TransformNode { id: u64, position: [f32; 2], @@ -29,7 +33,7 @@ impl> RadiantTool for SelectionTool { fn on_mouse_down(&mut self, node_id: u64, _position: [f32; 2]) -> Option { if node_id > 0 { self.active_node_id = Some(node_id - 1); - let message = SelectionToolMessage::SelectNode(node_id - 1); + let message = SelectionToolMessage::SelectNode { id: node_id - 1 }; Some(message.into()) } else { None diff --git a/crates/image/Cargo.toml b/crates/image/Cargo.toml index f967653..e2da988 100644 --- a/crates/image/Cargo.toml +++ b/crates/image/Cargo.toml @@ -15,3 +15,4 @@ epaint = { version = "0.22.0", features = ["bytemuck", "serde"] } pollster = "0.3" futures-intrusive = "0.5" radiant-core = { path = "../core" } +macro_magic = "0.5.0" diff --git a/crates/image/src/image_message.rs b/crates/image/src/image_message.rs index 66143d8..1d2747a 100644 --- a/crates/image/src/image_message.rs +++ b/crates/image/src/image_message.rs @@ -1,5 +1,7 @@ use serde::{Deserialize, Serialize}; +use macro_magic::export_tokens; +#[export_tokens] #[derive(Serialize, Deserialize, Debug, Clone)] pub enum RadiantImageMessage { AddImage { diff --git a/crates/image/src/lib.rs b/crates/image/src/lib.rs index bdd8d07..e3177f7 100644 --- a/crates/image/src/lib.rs +++ b/crates/image/src/lib.rs @@ -1,3 +1,5 @@ pub mod image_node; +pub mod image_message; pub use image_node::*; +pub use image_message::*; diff --git a/crates/macros/Cargo.toml b/crates/macros/Cargo.toml index 8c48f37..ca9944c 100644 --- a/crates/macros/Cargo.toml +++ b/crates/macros/Cargo.toml @@ -11,3 +11,5 @@ proc-macro = true proc-macro2 = "1.0.69" quote = "1.0.33" syn = "2.0.38" +macro_magic = { version = "0.5.0", features = ["proc_support"] } +proc-utils = "0" diff --git a/crates/macros/src/lib.rs b/crates/macros/src/lib.rs index 58cffed..49169c9 100644 --- a/crates/macros/src/lib.rs +++ b/crates/macros/src/lib.rs @@ -1,6 +1,7 @@ use proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; use quote::quote; +use macro_magic::import_tokens_attr; fn derive_tessellatable_internal(item: TokenStream2) -> syn::Result { let item = syn::parse2::(item)?; @@ -121,6 +122,60 @@ fn derive_component_provider_internal(item: TokenStream2) -> syn::Result syn::Result { + let mut local_enum = syn::parse2::(item.clone())?; + let local_name = local_enum.ident.clone(); + + let foreign_enum = syn::parse2::(attr)?; + let foreign_variants = foreign_enum.variants.iter().map(|variant| { + variant.ident.clone() + }).collect::>(); + let foreign_args = foreign_enum.variants.iter().map(|variant| { + variant.fields.iter().map(|field| { + field.ident.clone() + }).collect::>() + }).collect::>(); + + foreign_enum.variants.iter().for_each(|variant| { + if local_enum.variants.iter().any(|local_variant| local_variant.ident == variant.ident) { + return; + } + local_enum.variants.push(variant.clone()); + }); + + let res = quote! { + #local_enum + + impl From<#foreign_path> for #local_name { + fn from(foreign: #foreign_path) -> Self { + match foreign { + #( + #foreign_path::#foreign_variants { #(#foreign_args,)* } => Self::#foreign_variants { #(#foreign_args,)* }, + )* + } + } + } + + impl TryInto<#foreign_path> for #local_name { + type Error = (); + + fn try_into(self) -> Result<#foreign_path, Self::Error> { + match self { + #( + Self::#foreign_variants { #(#foreign_args,)* } => Ok(#foreign_path::#foreign_variants { #(#foreign_args,)* }), + )* + _ => Err(()), + } + } + } + }; + + // use proc_utils::*; + // res.pretty_print(); + + Ok(res) +} + #[proc_macro_derive(RadiantTessellatable)] pub fn derive_tessellatable(item: TokenStream) -> TokenStream { let res = match derive_tessellatable_internal(item.into()) { @@ -146,4 +201,15 @@ pub fn derive_component_provider(item: TokenStream) -> TokenStream { Err(err) => err.to_compile_error(), }; res.into() +} + +#[import_tokens_attr] +#[proc_macro_attribute] +pub fn combine_enum(attr: TokenStream, item: TokenStream) -> TokenStream { + let foreign_path = syn::parse::(__source_path).unwrap(); + let res = match combine_enum_internal(attr.into(), item.into(), foreign_path) { + Ok(res) => res, + Err(err) => err.to_compile_error(), + }; + res.into() } \ No newline at end of file diff --git a/crates/path/Cargo.toml b/crates/path/Cargo.toml index 7e9163e..3d2f409 100644 --- a/crates/path/Cargo.toml +++ b/crates/path/Cargo.toml @@ -15,3 +15,4 @@ epaint = { version = "0.22.0", features = ["bytemuck", "serde"] } pollster = "0.3" futures-intrusive = "0.5" radiant-core = { path = "../core" } +macro_magic = "0.5.0" diff --git a/crates/path/src/path_tool.rs b/crates/path/src/path_tool.rs index a5b29e4..49b7aa0 100644 --- a/crates/path/src/path_tool.rs +++ b/crates/path/src/path_tool.rs @@ -1,10 +1,14 @@ use radiant_core::RadiantTool; use serde::{Deserialize, Serialize}; +use macro_magic::export_tokens; // Todo: This is a stub. Implement the PathTool. +#[export_tokens] #[derive(Serialize, Deserialize, Debug, Clone)] pub enum PathToolMessage { - SelectNode(u64), + SelectNode { + id: u64 + }, TransformNode { id: u64, position: [f32; 2], @@ -30,7 +34,7 @@ impl> RadiantTool for PathTool { fn on_mouse_down(&mut self, node_id: u64, _position: [f32; 2]) -> Option { if node_id > 0 { self.active_node_id = Some(node_id - 1); - let message = PathToolMessage::SelectNode(node_id - 1); + let message = PathToolMessage::SelectNode { id: node_id - 1 }; Some(message.into()) } else { None diff --git a/crates/runtime/Cargo.toml b/crates/runtime/Cargo.toml index 66f9058..d5e2f05 100644 --- a/crates/runtime/Cargo.toml +++ b/crates/runtime/Cargo.toml @@ -24,6 +24,7 @@ radiant-image-node = { path = "../image" } radiant-text-node = { path = "../text" } radiant-path-node = { path = "../path" } radiant-winit = { path = "../winit" } +macro_magic = "0.5.0" [target.'cfg(target_arch = "wasm32")'.dependencies] console_log = "1.0" @@ -36,4 +37,4 @@ web-sys = { version = "0.3", features = [ "Document", "Window", "Element", -]} \ No newline at end of file +]} diff --git a/crates/runtime/src/message.rs b/crates/runtime/src/message.rs index b2aff6f..bc9b25f 100644 --- a/crates/runtime/src/message.rs +++ b/crates/runtime/src/message.rs @@ -1,17 +1,24 @@ use epaint::Color32; -use radiant_path_node::PathToolMessage; -use serde::{Deserialize, Serialize}; - -use radiant_core::{InteractionMessage, RectangleToolMessage, SelectionToolMessage}; +use radiant_macros::combine_enum; +use serde::{Deserialize, Serialize}; use crate::RadiantNodeType; +#[combine_enum(radiant_core::RectangleToolMessage)] +#[combine_enum(radiant_core::SelectionToolMessage)] +#[combine_enum(radiant_core::InteractionMessage)] +#[combine_enum(radiant_image_node::RadiantImageMessage)] +#[combine_enum(radiant_text_node::RadiantTextMessage)] +#[combine_enum(radiant_path_node::PathToolMessage)] #[derive(Serialize, Deserialize, Debug, Clone)] pub enum RadiantMessage { - AddArtboard, - SelectArtboard(u64), - - SelectNode(u64), + AddArtboard { }, + SelectArtboard { + id: u64, + }, + SelectNode { + id: u64, + }, AddNode { node_type: String, position: [f32; 2], @@ -35,113 +42,9 @@ pub enum RadiantMessage { id: u64, stroke_color: Color32, }, - SelectTool { id: u32, }, - - AddText { - text: String, - position: [f32; 2], - }, - AddImage { - name: String, - path: String, - }, -} - -impl From for RadiantMessage { - fn from(message: RectangleToolMessage) -> Self { - match message { - RectangleToolMessage::AddNode { - node_type, - position, - scale, - } => Self::AddNode { - node_type, - position, - scale, - }, - RectangleToolMessage::TransformNode { - id, - position, - scale, - } => Self::TransformNode { - id, - position, - scale, - }, - } - } -} - -impl From for RadiantMessage { - fn from(message: SelectionToolMessage) -> Self { - match message { - SelectionToolMessage::SelectNode(id) => Self::SelectNode(id), - SelectionToolMessage::TransformNode { - id, - position, - scale, - } => Self::TransformNode { - id, - position, - scale, - }, - } - } -} - -impl From for RadiantMessage { - fn from(message: PathToolMessage) -> Self { - match message { - PathToolMessage::SelectNode(id) => Self::SelectNode(id), - PathToolMessage::TransformNode { - id, - position, - scale, - } => Self::TransformNode { - id, - position, - scale, - }, - } - } -} - -impl From for RadiantMessage { - fn from(message: InteractionMessage) -> Self { - match message { - InteractionMessage::TransformNode { - id, - position, - scale, - } => Self::TransformNode { - id, - position, - scale, - }, - } - } -} - -impl TryInto for RadiantMessage { - type Error = (); - - fn try_into(self) -> Result { - match self { - Self::TransformNode { - id, - position, - scale, - } => Ok(InteractionMessage::TransformNode { - id, - position, - scale, - }), - _ => Err(()), - } - } } #[derive(Serialize, Deserialize, Debug, Clone)] diff --git a/crates/runtime/src/runtime.rs b/crates/runtime/src/runtime.rs index e5c3665..fbc9982 100644 --- a/crates/runtime/src/runtime.rs +++ b/crates/runtime/src/runtime.rs @@ -23,13 +23,13 @@ impl RadiantRuntime { pub fn handle_message(&mut self, message: RadiantMessage) -> Option { match message { - RadiantMessage::AddArtboard => { + RadiantMessage::AddArtboard { }=> { self.app.scene.document.add_artboard(); } - RadiantMessage::SelectArtboard(id) => { + RadiantMessage::SelectArtboard{ id } => { self.app.scene.document.set_active_artboard(id); } - RadiantMessage::SelectNode(id) => { + RadiantMessage::SelectNode{ id } => { if !self.app.scene.interaction_manager.is_interaction(id) { self.app.scene.document.select(id); if let Some(node) = self.app.scene.document.get_node(id) { @@ -57,7 +57,7 @@ impl RadiantRuntime { }; if let Some(node) = node { self.app.scene.add(node); - return self.handle_message(RadiantMessage::SelectNode(id)); + return self.handle_message(RadiantMessage::SelectNode { id }); } } RadiantMessage::TransformNode { @@ -148,14 +148,14 @@ impl RadiantRuntime { texture_handle, )); self.app.scene.add(node); - return self.handle_message(RadiantMessage::SelectNode(id)); + return self.handle_message(RadiantMessage::SelectNode { id }); } RadiantMessage::AddText { position, .. } => { let id = self.app.scene.document.counter; let node = RadiantNodeType::Text(RadiantTextNode::new(id, position, [100.0, 100.0])); self.app.scene.add(node); - return self.handle_message(RadiantMessage::SelectNode(id)); + return self.handle_message(RadiantMessage::SelectNode { id }); } } None diff --git a/crates/text/Cargo.toml b/crates/text/Cargo.toml index 4280fda..b924b83 100644 --- a/crates/text/Cargo.toml +++ b/crates/text/Cargo.toml @@ -15,3 +15,4 @@ epaint = { version = "0.22.0", features = ["bytemuck", "serde"] } pollster = "0.3" futures-intrusive = "0.5" radiant-core = { path = "../core" } +macro_magic = "0.5.0" diff --git a/crates/text/src/lib.rs b/crates/text/src/lib.rs index 042b47c..ad72dec 100644 --- a/crates/text/src/lib.rs +++ b/crates/text/src/lib.rs @@ -1,3 +1,5 @@ pub mod text_node; +pub mod text_message; pub use text_node::*; +pub use text_message::*; diff --git a/crates/text/src/text_message.rs b/crates/text/src/text_message.rs new file mode 100644 index 0000000..b1ef494 --- /dev/null +++ b/crates/text/src/text_message.rs @@ -0,0 +1,12 @@ +use serde::{Deserialize, Serialize}; +use macro_magic::export_tokens; + +#[export_tokens] +#[derive(Serialize, Deserialize, Debug, Clone)] +pub enum RadiantTextMessage { + AddText { + text: String, + position: [f32; 2], + }, +} + diff --git a/examples/basic/src/main.rs b/examples/basic/src/main.rs index 6d537ab..27354ba 100644 --- a/examples/basic/src/main.rs +++ b/examples/basic/src/main.rs @@ -1,5 +1,6 @@ use radiant_runtime::{ - RadiantNodeType, RadiantPathNode, RadiantRectangleNode, RadiantResponse, RadiantRuntime, run_native, + run_native, RadiantNodeType, RadiantPathNode, RadiantRectangleNode, RadiantResponse, + RadiantRuntime, }; async fn run() {