Refactor the node macro and simply most of the node implementations (#1942)

* Add support structure for new node macro to gcore

* Fix compile issues and code generation

* Implement new node_fn macro

* Implement property translation

* Fix NodeIO type generation

* Start translating math nodes

* Move node implementation to outer scope to allow usage of local imports

* Add expose attribute to allow controlling the parameter exposure

* Add rust analyzer support for #[implementations] attribute

* Migrate logic nodes

* Handle where clause properly

* Implement argument ident pattern preservation

* Implement adjustment layer mapping

* Fix node registry types

* Fix module paths

* Improve demo artwork comptibility

* Improve macro error reporting

* Fix handling of impl node implementations

* Fix nodeio type computation

* Fix opacity node and graph type resolution

* Fix loading of demo artworks

* Fix eslint

* Fix typo in macro test

* Remove node definitions for Adjustment Nodes

* Fix type alias property generation and make adjustments footprint aware

* Convert vector nodes

* Implement path overrides

* Fix stroke node

* Fix painted dreams

* Implement experimental type level specialization

* Fix poisson disk sampling -> all demo artworks should work again

* Port text node + make node macro more robust by implementing lifetime substitution

* Fix vector node tests

* Fix red dress demo + ci

* Fix clippy warnings

* Code review

* Fix primary input issues

* Improve math nodes and audit others

* Set no_properties when no automatic properties are derived

* Port vector generator nodes (could not derive all definitions yet)

* Various QA changes and add min/max/mode_range to number parameters

* Add min and max for f64 and u32

* Convert gpu nodes and clean up unused nodes

* Partially port transform node

* Allow implementations on call arg

* Port path modify node

* Start porting graphic element nodes

* Transform nodes in graphic_element.rs

* Port brush node

* Port nodes in wasm_executior

* Rename node macro

* Fix formatting

* Fix Mandelbrot node

* Formatting

* Fix Load Image and Load Resource nodes, add scope input to node macro

* Remove unnecessary underscores

* Begin attemping to make nodes resolution-aware

* Infer a generic manual compositon type on generic call arg

* Various fixes and work towards merging

* Final changes for merge!

* Fix tests, probably

* More free line removals!

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert
2024-09-20 12:50:30 +02:00
committed by GitHub
parent ca0d102296
commit e352c7fa71
92 changed files with 4255 additions and 7275 deletions

View File

@@ -11,7 +11,8 @@ use graphene_core::raster::ImageFrame;
use graphene_core::renderer::RenderMetadata;
use graphene_core::renderer::{format_transform_matrix, GraphicElementRendered, ImageRenderMode, RenderParams, RenderSvgSegmentList, SvgRender};
use graphene_core::transform::Footprint;
use graphene_core::Node;
use graphene_core::vector::VectorData;
use graphene_core::GraphicGroup;
use graphene_core::{Color, WasmNotSend};
#[cfg(target_arch = "wasm32")]
@@ -27,24 +28,14 @@ use wasm_bindgen::JsCast;
#[cfg(target_arch = "wasm32")]
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement};
pub struct CreateSurfaceNode {}
#[node_macro::node_fn(CreateSurfaceNode)]
async fn create_surface_node<'a: 'input>(editor: &'a WasmEditorApi) -> Arc<WasmSurfaceHandle> {
#[node_macro::node(category("Debug: GPU"))]
async fn create_surface<'a: 'n>(_: (), editor: &'a WasmEditorApi) -> Arc<WasmSurfaceHandle> {
Arc::new(editor.application_io.as_ref().unwrap().create_window())
}
#[node_macro::node(category("Debug: GPU"))]
#[cfg(target_arch = "wasm32")]
pub struct DrawImageFrameNode<Surface> {
surface_handle: Surface,
}
#[node_macro::node_fn(DrawImageFrameNode)]
#[cfg(target_arch = "wasm32")]
async fn draw_image_frame_node<'a: 'input>(
image: ImageFrame<graphene_core::raster::SRGBA8>,
surface_handle: Arc<WasmSurfaceHandle>,
) -> graphene_core::application_io::SurfaceHandleFrame<HtmlCanvasElement> {
async fn draw_image_frame(_: (), image: ImageFrame<graphene_core::raster::SRGBA8>, surface_handle: Arc<WasmSurfaceHandle>) -> graphene_core::application_io::SurfaceHandleFrame<HtmlCanvasElement> {
let image_data = image.image.data;
let array: Clamped<&[u8]> = Clamped(bytemuck::cast_slice(image_data.as_slice()));
if image.image.width > 0 && image.image.height > 0 {
@@ -62,19 +53,13 @@ async fn draw_image_frame_node<'a: 'input>(
}
}
pub struct LoadResourceNode<Url> {
url: Url,
}
#[node_macro::node_fn(LoadResourceNode)]
async fn load_resource_node<'a: 'input>(editor: &'a WasmEditorApi, url: String) -> Arc<[u8]> {
#[node_macro::node(category("Network"))]
async fn load_resource<'a: 'n>(_: (), _primary: (), #[scope("editor-api")] editor: &'a WasmEditorApi, url: String) -> Arc<[u8]> {
editor.application_io.as_ref().unwrap().load_resource(url).unwrap().await.unwrap()
}
pub struct DecodeImageNode;
#[node_macro::node_fn(DecodeImageNode)]
fn decode_image_node<'a: 'input>(data: Arc<[u8]>) -> ImageFrame<Color> {
#[node_macro::node(category("Raster"))]
fn decode_image(_: (), data: Arc<[u8]>) -> ImageFrame<Color> {
let image = image::load_from_memory(data.as_ref()).expect("Failed to decode image");
let image = image.to_rgba32f();
let image = ImageFrame {
@@ -144,25 +129,21 @@ async fn render_canvas(render_config: RenderConfig, data: impl GraphicElementRen
RenderOutputType::CanvasFrame(frame)
}
#[node_macro::node(category(""))]
#[cfg(target_arch = "wasm32")]
pub struct RasterizeNode<Footprint, Surface> {
footprint: Footprint,
surface_handle: Surface,
}
#[node_macro::node_fn(RasterizeNode)]
#[cfg(target_arch = "wasm32")]
async fn rasterize<_T: GraphicElementRendered + graphene_core::transform::TransformMut + WasmNotSend>(
mut data: _T,
async fn rasterize<T: GraphicElementRendered + graphene_core::transform::TransformMut + WasmNotSend + 'n>(
_: (),
#[implementations((Footprint, VectorData), (Footprint, ImageFrame<Color>), (Footprint, GraphicGroup))] data: impl Node<Footprint, Output = T>,
footprint: Footprint,
surface_handle: Arc<SurfaceHandle<HtmlCanvasElement>>,
) -> ImageFrame<Color> {
let mut render = SvgRender::new();
if footprint.transform.matrix2.determinant() == 0. {
log::trace!("Invalid footprint received for rasterization");
return ImageFrame::default();
}
let mut data = data.eval(footprint).await;
let mut render = SvgRender::new();
let aabb = Bbox::from_transform(footprint.transform).to_axis_aligned_bbox();
let size = aabb.size();
let resolution = footprint.resolution;
@@ -204,16 +185,23 @@ async fn rasterize<_T: GraphicElementRendered + graphene_core::transform::Transf
}
}
pub struct RenderNode<EditorApi, Data, Surface> {
editor_api: EditorApi,
data: Data,
_surface_handle: Surface,
}
#[node_macro::node_fn(RenderNode)]
async fn render_node<'a: 'input, T: 'input + GraphicElementRendered + WasmNotSend>(
#[node_macro::node(category(""))]
async fn render<'a: 'n, T: 'n + GraphicElementRendered + WasmNotSend>(
render_config: RenderConfig,
editor_api: &'a WasmEditorApi,
#[implementations(
(Footprint, VectorData),
(Footprint, ImageFrame<Color>),
(Footprint, GraphicGroup),
(Footprint, graphene_core::Artboard),
(Footprint, graphene_core::ArtboardGroup),
(Footprint, Option<Color>),
(Footprint, Vec<Color>),
(Footprint, bool),
(Footprint, f32),
(Footprint, f64),
(Footprint, String),
)]
data: impl Node<Footprint, Output = T>,
_surface_handle: impl Node<(), Output = Option<wgpu_executor::WgpuSurface>>,
) -> RenderOutput {
@@ -222,9 +210,9 @@ async fn render_node<'a: 'input, T: 'input + GraphicElementRendered + WasmNotSen
let RenderConfig { hide_artboards, for_export, .. } = render_config;
let render_params = RenderParams::new(render_config.view_mode, ImageRenderMode::Base64, None, false, hide_artboards, for_export);
let data = self.data.eval(footprint).await;
let data = data.eval(footprint).await;
#[cfg(all(feature = "vello", target_arch = "wasm32"))]
let surface_handle = self._surface_handle.eval(()).await;
let surface_handle = _surface_handle.eval(()).await;
let use_vello = editor_api.editor_preferences.use_vello();
#[cfg(all(feature = "vello", target_arch = "wasm32"))]
let use_vello = use_vello && surface_handle.is_some();