diff --git a/Cargo.lock b/Cargo.lock index 22ad5e1e8c..9a3c0711b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2130,6 +2130,7 @@ dependencies = [ "dyn-any", "glam", "graph-craft", + "graphene-application-io", "graphene-core", "iai-callgrind", "js-sys", @@ -2148,6 +2149,19 @@ dependencies = [ "winit", ] +[[package]] +name = "graphene-application-io" +version = "0.1.0" +dependencies = [ + "dyn-any", + "glam", + "graphene-core", + "log", + "serde", + "web-sys", + "wgpu", +] + [[package]] name = "graphene-cli" version = "0.1.0" @@ -2196,7 +2210,6 @@ dependencies = [ "tokio", "usvg", "vello", - "web-sys", "wgpu", ] @@ -2212,6 +2225,7 @@ dependencies = [ "futures", "glam", "graph-craft", + "graphene-application-io", "graphene-core", "image", "log", @@ -7386,6 +7400,7 @@ dependencies = [ "dyn-any", "futures", "glam", + "graphene-application-io", "graphene-core", "node-macro", "vello", diff --git a/Cargo.toml b/Cargo.toml index 959f200bf3..5d3730d0a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "proc-macros", "frontend/wasm", "frontend/src-tauri", + "node-graph/gapplication-io", "node-graph/gcore", "node-graph/gstd", "node-graph/graph-craft", @@ -35,6 +36,7 @@ bezier-rs = { path = "libraries/bezier-rs", features = ["dyn-any", "serde"] } dyn-any = { path = "libraries/dyn-any", features = ["derive", "glam", "reqwest", "log-bad-types", "rc"] } math-parser = { path = "libraries/math-parser" } path-bool = { path = "libraries/path-bool" } +graphene-application-io = { path = "node-graph/gapplication-io" } graphene-core = { path = "node-graph/gcore" } graph-craft = { path = "node-graph/graph-craft" } graphene-std = { path = "node-graph/gstd" } diff --git a/frontend/wasm/Cargo.toml b/frontend/wasm/Cargo.toml index 9182f1ad92..44ac26c2da 100644 --- a/frontend/wasm/Cargo.toml +++ b/frontend/wasm/Cargo.toml @@ -29,7 +29,7 @@ editor = { path = "../../editor", package = "graphite-editor", features = [ # Workspace dependencies graph-craft = { workspace = true } log = { workspace = true } -graphene-core = { workspace = true, features = ["wasm"] } +graphene-core = { workspace = true } serde = { workspace = true } wasm-bindgen = { workspace = true } serde-wasm-bindgen = { workspace = true } diff --git a/node-graph/gapplication-io/Cargo.toml b/node-graph/gapplication-io/Cargo.toml new file mode 100644 index 0000000000..98051ce63c --- /dev/null +++ b/node-graph/gapplication-io/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "graphene-application-io" +version = "0.1.0" +edition = "2024" +description = "graphene application io interface" +authors = ["Graphite Authors "] +license = "MIT OR Apache-2.0" + +[features] +wasm = ["dep:web-sys"] +wgpu = ["dep:wgpu"] + +[dependencies] +# Local dependencies +dyn-any = { workspace = true } +graphene-core = { workspace = true } + +# Workspace dependencies +glam = { workspace = true } +serde = { workspace = true } +log = { workspace = true } + +# Optional workspace dependencies +web-sys = { workspace = true, optional = true } +wgpu = { workspace = true, optional = true } diff --git a/node-graph/gcore/src/application_io.rs b/node-graph/gapplication-io/src/lib.rs similarity index 96% rename from node-graph/gcore/src/application_io.rs rename to node-graph/gapplication-io/src/lib.rs index c25da5fc20..06275445c9 100644 --- a/node-graph/gcore/src/application_io.rs +++ b/node-graph/gapplication-io/src/lib.rs @@ -1,8 +1,8 @@ -use crate::text::FontCache; -use crate::transform::Footprint; -use crate::vector::style::ViewMode; use dyn_any::{DynAny, StaticType, StaticTypeSized}; use glam::{DAffine2, UVec2}; +use graphene_core::text::FontCache; +use graphene_core::transform::Footprint; +use graphene_core::vector::style::ViewMode; use std::fmt::Debug; use std::future::Future; use std::hash::{Hash, Hasher}; @@ -131,6 +131,11 @@ unsafe impl StaticType for SurfaceHandleFrame { type Static = SurfaceHandleFrame; } +#[cfg(feature = "wasm")] +pub type WasmSurfaceHandle = SurfaceHandle; +#[cfg(feature = "wasm")] +pub type WasmSurfaceHandleFrame = SurfaceHandleFrame; + // TODO: think about how to automatically clean up memory /* impl<'a, Surface> Drop for SurfaceHandle<'a, Surface> { diff --git a/node-graph/gcore/Cargo.toml b/node-graph/gcore/Cargo.toml index e1a004237c..01dd3b12c6 100644 --- a/node-graph/gcore/Cargo.toml +++ b/node-graph/gcore/Cargo.toml @@ -7,10 +7,9 @@ authors = ["Graphite Authors "] license = "MIT OR Apache-2.0" [features] -default = ["serde", "wasm"] +default = ["serde"] nightly = [] type_id_logging = [] -wasm = ["web-sys"] wgpu = ["dep:wgpu"] vello = ["dep:vello", "bezier-rs/kurbo", "wgpu"] dealloc_nodes = [] @@ -47,7 +46,6 @@ base64 = { workspace = true } serde = { workspace = true, optional = true } vello = { workspace = true, optional = true } wgpu = { workspace = true, optional = true } -web-sys = { workspace = true, optional = true } [dev-dependencies] # Workspace dependencies diff --git a/node-graph/gcore/src/graphic_element/renderer.rs b/node-graph/gcore/src/graphic_element/renderer.rs index cc68f0a687..165f5a5ed6 100644 --- a/node-graph/gcore/src/graphic_element/renderer.rs +++ b/node-graph/gcore/src/graphic_element/renderer.rs @@ -299,7 +299,7 @@ impl Default for SvgRender { #[derive(Clone, Debug, Default)] pub struct RenderContext { - #[cfg(feature = "wgpu")] + #[cfg(feature = "vello")] pub resource_overrides: HashMap>, } diff --git a/node-graph/gcore/src/lib.rs b/node-graph/gcore/src/lib.rs index 4af81a6100..68cf13e46b 100644 --- a/node-graph/gcore/src/lib.rs +++ b/node-graph/gcore/src/lib.rs @@ -28,8 +28,6 @@ mod graphic_element; pub use graphic_element::*; pub mod vector; -pub mod application_io; - pub mod registry; pub use context::*; @@ -140,12 +138,6 @@ impl<'i, I, O: 'i> Node<'i, I> for Pin<&'i (dyn NodeIO<'i, I, Output = O> + 'i)> } } -pub use crate::application_io::{SurfaceFrame, SurfaceId}; -#[cfg(feature = "wasm")] -pub type WasmSurfaceHandle = application_io::SurfaceHandle; -#[cfg(feature = "wasm")] -pub type WasmSurfaceHandleFrame = application_io::SurfaceHandleFrame; - pub trait InputAccessorSource<'a, T>: InputAccessorSourceIdentifier + std::fmt::Debug { fn get_input(&'a self, index: usize) -> Option<&'a T>; fn set_input(&'a mut self, index: usize, value: T); diff --git a/node-graph/graph-craft/Cargo.toml b/node-graph/graph-craft/Cargo.toml index 91e800eb6c..963ef97e72 100644 --- a/node-graph/graph-craft/Cargo.toml +++ b/node-graph/graph-craft/Cargo.toml @@ -16,6 +16,7 @@ loading = ["serde_json"] # Local dependencies dyn-any = { workspace = true } graphene-core = { workspace = true } +graphene-application-io = { workspace = true } # Workspace dependencies log = { workspace = true } diff --git a/node-graph/graph-craft/src/document/value.rs b/node-graph/graph-craft/src/document/value.rs index f641555d99..17e1869f86 100644 --- a/node-graph/graph-craft/src/document/value.rs +++ b/node-graph/graph-craft/src/document/value.rs @@ -4,6 +4,7 @@ use crate::wasm_application_io::WasmEditorApi; use dyn_any::DynAny; pub use dyn_any::StaticType; pub use glam::{DAffine2, DVec2, IVec2, UVec2}; +use graphene_application_io::SurfaceFrame; use graphene_core::raster::brush_cache::BrushCache; use graphene_core::raster::{BlendMode, LuminanceCalculation}; use graphene_core::raster_types::CPU; @@ -30,7 +31,7 @@ macro_rules! tagged_value { None, $( $(#[$meta] ) *$identifier( $ty ), )* RenderOutput(RenderOutput), - SurfaceFrame(graphene_core::SurfaceFrame), + SurfaceFrame(SurfaceFrame), #[serde(skip)] EditorApi(Arc) } @@ -76,7 +77,7 @@ macro_rules! tagged_value { Self::None => concrete!(()), $( Self::$identifier(_) => concrete!($ty), )* Self::RenderOutput(_) => concrete!(RenderOutput), - Self::SurfaceFrame(_) => concrete!(graphene_core::SurfaceFrame), + Self::SurfaceFrame(_) => concrete!(SurfaceFrame), Self::EditorApi(_) => concrete!(&WasmEditorApi) } } @@ -89,7 +90,7 @@ macro_rules! tagged_value { x if x == TypeId::of::<()>() => Ok(TaggedValue::None), $( x if x == TypeId::of::<$ty>() => Ok(TaggedValue::$identifier(*downcast(input).unwrap())), )* x if x == TypeId::of::() => Ok(TaggedValue::RenderOutput(*downcast(input).unwrap())), - x if x == TypeId::of::() => Ok(TaggedValue::SurfaceFrame(*downcast(input).unwrap())), + x if x == TypeId::of::() => Ok(TaggedValue::SurfaceFrame(*downcast(input).unwrap())), _ => Err(format!("Cannot convert {:?} to TaggedValue", DynAny::type_name(input.as_ref()))), @@ -103,7 +104,7 @@ macro_rules! tagged_value { x if x == TypeId::of::<()>() => Ok(TaggedValue::None), $( x if x == TypeId::of::<$ty>() => Ok(TaggedValue::$identifier(<$ty as Clone>::clone(input.downcast_ref().unwrap()))), )* x if x == TypeId::of::() => Ok(TaggedValue::RenderOutput(RenderOutput::clone(input.downcast_ref().unwrap()))), - x if x == TypeId::of::() => Ok(TaggedValue::SurfaceFrame(graphene_core::SurfaceFrame::clone(input.downcast_ref().unwrap()))), + x if x == TypeId::of::() => Ok(TaggedValue::SurfaceFrame(SurfaceFrame::clone(input.downcast_ref().unwrap()))), _ => Err(format!("Cannot convert {:?} to TaggedValue",std::any::type_name_of_val(input))), } } @@ -430,7 +431,7 @@ pub struct RenderOutput { #[derive(Debug, Clone, PartialEq, dyn_any::DynAny, Hash, serde::Serialize, serde::Deserialize)] pub enum RenderOutputType { - CanvasFrame(graphene_core::SurfaceFrame), + CanvasFrame(SurfaceFrame), Svg(String), Image(Vec), } diff --git a/node-graph/graph-craft/src/wasm_application_io.rs b/node-graph/graph-craft/src/wasm_application_io.rs index 9ae94267d8..f9657bf098 100644 --- a/node-graph/graph-craft/src/wasm_application_io.rs +++ b/node-graph/graph-craft/src/wasm_application_io.rs @@ -1,5 +1,5 @@ use dyn_any::StaticType; -use graphene_core::application_io::{ApplicationError, ApplicationIo, ResourceFuture, SurfaceHandle, SurfaceId}; +use graphene_application_io::{ApplicationError, ApplicationIo, ResourceFuture, SurfaceHandle, SurfaceId}; #[cfg(target_arch = "wasm32")] use js_sys::{Object, Reflect}; use std::collections::HashMap; @@ -168,7 +168,7 @@ impl<'a> From<&'a WasmApplicationIo> for &'a WgpuExecutor { } } -pub type WasmEditorApi = graphene_core::application_io::EditorApi; +pub type WasmEditorApi = graphene_application_io::EditorApi; impl ApplicationIo for WasmApplicationIo { #[cfg(target_arch = "wasm32")] @@ -208,7 +208,7 @@ impl ApplicationIo for WasmApplicationIo { // Use Reflect API to set property Reflect::set(&canvases, &js_key, &js_value)?; Ok::<_, JsValue>(SurfaceHandle { - window_id: graphene_core::SurfaceId(id), + window_id: SurfaceId(id), surface: canvas, }) }; @@ -313,7 +313,7 @@ impl ApplicationIo for WasmApplicationIo { #[cfg(feature = "wgpu")] pub type WasmSurfaceHandle = SurfaceHandle; #[cfg(feature = "wgpu")] -pub type WasmSurfaceHandleFrame = graphene_core::application_io::SurfaceHandleFrame; +pub type WasmSurfaceHandleFrame = graphene_application_io::SurfaceHandleFrame; #[derive(Clone, Debug, PartialEq, Hash, specta::Type, serde::Serialize, serde::Deserialize)] pub struct EditorPreferences { @@ -321,7 +321,7 @@ pub struct EditorPreferences { pub use_vello: bool, } -impl graphene_core::application_io::GetEditorPreferences for EditorPreferences { +impl graphene_application_io::GetEditorPreferences for EditorPreferences { // fn hostname(&self) -> &str { // &self.imaginate_hostname // } diff --git a/node-graph/graphene-cli/src/main.rs b/node-graph/graphene-cli/src/main.rs index fc60a920d4..aab5ab85c1 100644 --- a/node-graph/graphene-cli/src/main.rs +++ b/node-graph/graphene-cli/src/main.rs @@ -6,8 +6,8 @@ use graph_craft::graphene_compiler::{Compiler, Executor}; use graph_craft::proto::ProtoNetwork; use graph_craft::util::load_network; use graph_craft::wasm_application_io::EditorPreferences; -use graphene_core::application_io::{ApplicationIo, NodeGraphUpdateSender}; use graphene_core::text::FontCache; +use graphene_std::application_io::{ApplicationIo, NodeGraphUpdateMessage, NodeGraphUpdateSender, RenderConfig}; use graphene_std::wasm_application_io::{WasmApplicationIo, WasmEditorApi}; use interpreted_executor::dynamic_executor::DynamicExecutor; use interpreted_executor::util::wrap_network_in_scope; @@ -18,7 +18,7 @@ use std::sync::Arc; struct UpdateLogger {} impl NodeGraphUpdateSender for UpdateLogger { - fn send(&self, message: graphene_core::application_io::NodeGraphUpdateMessage) { + fn send(&self, message: NodeGraphUpdateMessage) { println!("{message:?}"); } } @@ -115,7 +115,7 @@ async fn main() -> Result<(), Box> { } }); let executor = create_executor(proto_graph)?; - let render_config = graphene_core::application_io::RenderConfig::default(); + let render_config = RenderConfig::default(); loop { let result = (&executor).execute(render_config).await?; diff --git a/node-graph/gstd/Cargo.toml b/node-graph/gstd/Cargo.toml index 56e4f9b7ac..6d440e85e5 100644 --- a/node-graph/gstd/Cargo.toml +++ b/node-graph/gstd/Cargo.toml @@ -9,8 +9,8 @@ license = "MIT OR Apache-2.0" [features] default = ["wasm", "imaginate"] gpu = [] -wgpu = ["gpu", "graph-craft/wgpu"] -wasm = ["wasm-bindgen", "web-sys"] +wgpu = ["gpu", "graph-craft/wgpu", "graphene-application-io/wgpu"] +wasm = ["wasm-bindgen", "web-sys", "graphene-application-io/wasm"] imaginate = ["image/png", "base64", "web-sys", "wasm-bindgen-futures"] image-compare = [] vello = ["dep:vello", "gpu", "graphene-core/vello"] @@ -23,6 +23,7 @@ dyn-any = { workspace = true } graph-craft = { workspace = true } wgpu-executor = { workspace = true } graphene-core = { workspace = true } +graphene-application-io = { workspace = true } # Workspace dependencies fastnoise-lite = { workspace = true } diff --git a/node-graph/gstd/src/lib.rs b/node-graph/gstd/src/lib.rs index ef07c3080c..ffc6b99380 100644 --- a/node-graph/gstd/src/lib.rs +++ b/node-graph/gstd/src/lib.rs @@ -10,4 +10,5 @@ pub mod vector; #[cfg(feature = "wasm")] pub mod wasm_application_io; +pub use graphene_application_io as application_io; pub use graphene_core::*; diff --git a/node-graph/gstd/src/wasm_application_io.rs b/node-graph/gstd/src/wasm_application_io.rs index 94cc29b9fc..d3f344555e 100644 --- a/node-graph/gstd/src/wasm_application_io.rs +++ b/node-graph/gstd/src/wasm_application_io.rs @@ -1,9 +1,7 @@ use graph_craft::document::value::RenderOutput; pub use graph_craft::document::value::RenderOutputType; pub use graph_craft::wasm_application_io::*; -#[cfg(target_arch = "wasm32")] -use graphene_core::application_io::SurfaceHandle; -use graphene_core::application_io::{ApplicationIo, ExportFormat, RenderConfig}; +use graphene_application_io::{ApplicationIo, ExportFormat, RenderConfig}; #[cfg(target_arch = "wasm32")] use graphene_core::instances::Instances; #[cfg(target_arch = "wasm32")] @@ -127,7 +125,7 @@ async fn render_canvas( surface_handle: wgpu_executor::WgpuSurface, render_params: RenderParams, ) -> RenderOutputType { - use graphene_core::SurfaceFrame; + use graphene_application_io::SurfaceFrame; let footprint = render_config.viewport; let Some(exec) = editor.application_io.as_ref().unwrap().gpu_executor() else { @@ -172,7 +170,7 @@ async fn rasterize( )] mut data: Instances, footprint: Footprint, - surface_handle: Arc>, + surface_handle: Arc>, ) -> RasterDataTable where Instances: GraphicElementRendered, diff --git a/node-graph/interpreted-executor/src/node_registry.rs b/node-graph/interpreted-executor/src/node_registry.rs index 6059e24e6e..2c232e1835 100644 --- a/node-graph/interpreted-executor/src/node_registry.rs +++ b/node-graph/interpreted-executor/src/node_registry.rs @@ -13,7 +13,7 @@ use graphene_core::{fn_type_fut, future}; use graphene_std::Context; use graphene_std::GraphicElement; use graphene_std::any::{ComposeTypeErased, DowncastBothNode, DynAnyNode, IntoTypeErasedNode}; -use graphene_std::application_io::ImageTexture; +use graphene_std::application_io::{ImageTexture, SurfaceFrame}; use graphene_std::wasm_application_io::*; use node_registry_macros::{async_node, into_node}; use once_cell::sync::Lazy; @@ -80,8 +80,8 @@ fn node_registry() -> HashMap, input: Context, fn_params: [Context => WindowHandle]), async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Option]), async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => WindowHandle]), - async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_std::SurfaceFrame]), - async_node!(graphene_core::memo::MemoNode<_, _>, input: UVec2, fn_params: [UVec2 => graphene_std::SurfaceFrame]), + async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => SurfaceFrame]), + async_node!(graphene_core::memo::MemoNode<_, _>, input: UVec2, fn_params: [UVec2 => SurfaceFrame]), async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => f64]), async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => String]), async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => RenderOutput]), diff --git a/node-graph/wgpu-executor/Cargo.toml b/node-graph/wgpu-executor/Cargo.toml index 6480c056aa..7eb1c31a8f 100644 --- a/node-graph/wgpu-executor/Cargo.toml +++ b/node-graph/wgpu-executor/Cargo.toml @@ -11,7 +11,8 @@ passthrough = [] [dependencies] # Local dependencies -graphene-core = { workspace = true, features = ["wgpu"] } +graphene-core = { workspace = true, features = ["wgpu", "vello"] } +graphene-application-io = { workspace = true, features = ["wgpu"] } dyn-any = { workspace = true } node-macro = { workspace = true } diff --git a/node-graph/wgpu-executor/src/lib.rs b/node-graph/wgpu-executor/src/lib.rs index a37df118a1..948cfd5d1b 100644 --- a/node-graph/wgpu-executor/src/lib.rs +++ b/node-graph/wgpu-executor/src/lib.rs @@ -4,7 +4,7 @@ use anyhow::Result; pub use context::Context; use dyn_any::StaticType; use glam::UVec2; -use graphene_core::application_io::{ApplicationIo, EditorApi, SurfaceHandle}; +use graphene_application_io::{ApplicationIo, EditorApi, SurfaceHandle}; use graphene_core::{Color, Ctx}; use std::sync::Arc; use vello::{AaConfig, AaSupport, RenderParams, Renderer, RendererOptions, Scene}; @@ -31,7 +31,7 @@ impl<'a, T: ApplicationIo> From<&'a EditorApi> for & pub type WgpuSurface = Arc>; pub type WgpuWindow = Arc>; -impl graphene_core::application_io::Size for Surface { +impl graphene_application_io::Size for Surface { fn size(&self) -> UVec2 { self.resolution } @@ -104,7 +104,7 @@ impl WgpuExecutor { } #[cfg(target_arch = "wasm32")] - pub fn create_surface(&self, canvas: graphene_core::WasmSurfaceHandle) -> Result> { + pub fn create_surface(&self, canvas: graphene_application_io::WasmSurfaceHandle) -> Result> { let surface = self.context.instance.create_surface(wgpu::SurfaceTarget::Canvas(canvas.surface))?; Ok(SurfaceHandle {