From 8ead25eef38c8b9fa80f3e7cdd8e55034e4a6b09 Mon Sep 17 00:00:00 2001 From: Polyglot Date: Thu, 27 Nov 2025 22:01:38 +0100 Subject: [PATCH 1/5] Add tooltip documentation to web request, text, and brush nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add descriptive tooltips to web request nodes (GET/POST, string/image conversion, resource loading, image decoding) - Add tooltip to GPU rasterization node explaining footprint usage - Improve text node tooltip with clearer per_glyph_instances parameter explanation - Add tooltips to brush stamp generator and blit operations explaining their internal roles - Fix typos in tooltip and variable names (it's→its, perview→preview, instnace→instance) --- node-graph/nodes/brush/src/brush.rs | 4 ++++ node-graph/nodes/gstd/src/text.rs | 6 +++++- node-graph/nodes/gstd/src/wasm_application_io.rs | 9 ++++++++- node-graph/nodes/path-bool/src/lib.rs | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/node-graph/nodes/brush/src/brush.rs b/node-graph/nodes/brush/src/brush.rs index 0a6fdc76bc..11516cc55d 100644 --- a/node-graph/nodes/brush/src/brush.rs +++ b/node-graph/nodes/brush/src/brush.rs @@ -57,6 +57,9 @@ impl Sample for BrushStampGenerator

{ } } +/// Controls the brush shape with diameter and hardness, plus color and opacity (via flow). +/// The feather exponent is calculated from hardness to determine edge softness. +/// Used internally to create the individual brush texture before stamping it repeatedly along a stroke path. #[node_macro::node(skip_impl)] fn brush_stamp_generator(#[unit(" px")] diameter: f64, color: Color, hardness: f64, flow: f64) -> BrushStampGenerator { // Diameter @@ -76,6 +79,7 @@ fn brush_stamp_generator(#[unit(" px")] diameter: f64, color: Color, hardness: f BrushStampGenerator { color, feather_exponent, transform } } +/// Used to efficiently paint brush strokes: applies the same texture repeatedly at different positions with proper blending and boundary handling. #[node_macro::node(skip_impl)] fn blit(mut target: Table>, texture: Raster, positions: Vec, blend_mode: BlendFn) -> Table> where diff --git a/node-graph/nodes/gstd/src/text.rs b/node-graph/nodes/gstd/src/text.rs index 9dfe656351..95a7605422 100644 --- a/node-graph/nodes/gstd/src/text.rs +++ b/node-graph/nodes/gstd/src/text.rs @@ -3,6 +3,9 @@ use graph_craft::wasm_application_io::WasmEditorApi; use graphic_types::Vector; pub use text_nodes::*; +/// Converts text into editable vector shapes with customizable styling. +/// Parameters control font, size, spacing, alignment, and layout. + #[node_macro::node(category(""))] fn text<'i: 'n>( _: impl Ctx, @@ -25,7 +28,8 @@ fn text<'i: 'n>( #[default(0.)] tilt: f64, align: TextAlign, - /// Splits each text glyph into its own row in the table of vector geometry. + /// When enabled, outputs a table with one Vector per character, allowing individual character manipulation. + /// When disabled, outputs a single Vector containing all characters combined. Default is disabled. #[default(false)] per_glyph_instances: bool, ) -> Table { diff --git a/node-graph/nodes/gstd/src/wasm_application_io.rs b/node-graph/nodes/gstd/src/wasm_application_io.rs index 53a31d4b90..db753cb066 100644 --- a/node-graph/nodes/gstd/src/wasm_application_io.rs +++ b/node-graph/nodes/gstd/src/wasm_application_io.rs @@ -27,12 +27,14 @@ use wasm_bindgen::JsCast; #[cfg(target_family = "wasm")] use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement}; +/// Allocates GPU memory and rendering context for vector-to-raster conversion. Must be paired with the Rasterize node. #[cfg(feature = "wgpu")] #[node_macro::node(category("Debug: GPU"))] async fn create_surface<'a: 'n>(_: impl Ctx, editor: &'a WasmEditorApi) -> Arc { Arc::new(editor.application_io.as_ref().unwrap().create_window()) } +/// "Discard Result" runs asynchronously in the background without waiting. Useful for triggering webhooks or analytics without blocking. #[node_macro::node(category("Web Request"))] async fn get_request(_: impl Ctx, _primary: (), #[name("URL")] url: String, discard_result: bool) -> String { #[cfg(target_family = "wasm")] @@ -63,6 +65,7 @@ async fn get_request(_: impl Ctx, _primary: (), #[name("URL")] url: String, disc response.text().await.ok().unwrap_or_default() } +/// "Discard Result" runs asynchronously in the background. Useful for fire-and-forget operations like logging, webhooks, or notifications. #[node_macro::node(category("Web Request"))] async fn post_request(_: impl Ctx, _primary: (), #[name("URL")] url: String, body: Vec, discard_result: bool) -> String { #[cfg(target_family = "wasm")] @@ -97,17 +100,19 @@ async fn post_request(_: impl Ctx, _primary: (), #[name("URL")] url: String, bod response.text().await.ok().unwrap_or_default() } +/// Prepare text for transmission over HTTP or storage in binary file formats. #[node_macro::node(category("Web Request"), name("String to Bytes"))] fn string_to_bytes(_: impl Ctx, string: String) -> Vec { string.into_bytes() } +/// Extracts raw pixel data in RGBA format. Each pixel becomes 4 sequential bytes. Use before sending images over HTTP or writing to files. #[node_macro::node(category("Web Request"), name("Image to Bytes"))] fn image_to_bytes(_: impl Ctx, image: Table>) -> Vec { let Some(image) = image.iter().next() else { return vec![] }; image.element.data.iter().flat_map(|color| color.to_rgb8_srgb().into_iter()).collect::>() } - +/// Supports loading from URLs and local asset paths. Returns a transparent placeholder if the resource fails to load, allowing workflows to continue. #[node_macro::node(category("Web Request"))] async fn load_resource<'a: 'n>(_: impl Ctx, _primary: (), #[scope("editor-api")] editor: &'a WasmEditorApi, #[name("URL")] url: String) -> Arc<[u8]> { let Some(api) = editor.application_io.as_ref() else { @@ -123,6 +128,7 @@ async fn load_resource<'a: 'n>(_: impl Ctx, _primary: (), #[scope("editor-api")] data } +/// Works with any standard image format (PNG, JPEG, WebP, etc.). Automatically converts color space to linear sRGB for accurate compositing. #[node_macro::node(category("Web Request"))] fn decode_image(_: impl Ctx, data: Arc<[u8]>) -> Table> { let Some(image) = image::load_from_memory(data.as_ref()).ok() else { @@ -142,6 +148,7 @@ fn decode_image(_: impl Ctx, data: Arc<[u8]>) -> Table> { Table::new_from_element(Raster::new_cpu(image)) } +/// Renders with the resolution and transform defined by the footprint. Output respects vector strokes, gradients, and other styling details. #[cfg(target_family = "wasm")] #[node_macro::node(category(""))] async fn rasterize( diff --git a/node-graph/nodes/path-bool/src/lib.rs b/node-graph/nodes/path-bool/src/lib.rs index 0e862f243c..3c984b78f9 100644 --- a/node-graph/nodes/path-bool/src/lib.rs +++ b/node-graph/nodes/path-bool/src/lib.rs @@ -14,7 +14,7 @@ use std::ops::Mul; // Import specta so derive macros can find it use core_types::specta; -// TODO: Fix boolean ops to work by removing .transform() and .one_instnace_*() calls, +// TODO: Fix boolean ops to work by removing .transform() and .one_instance_*() calls, // TODO: since before we used a Vec of single-row tables and now we use a single table // TODO: with multiple rows while still assuming a single row for the boolean operations. From 955449d2285d6f60f62fc5bafea5262a94082ccc Mon Sep 17 00:00:00 2001 From: Polyglot Date: Fri, 28 Nov 2025 16:03:08 +0100 Subject: [PATCH 2/5] Fixed 2 issues with previous changes. Reversed order of documentation about per_glyph_instances. Can it be 3 lines? --- node-graph/nodes/gstd/src/text.rs | 5 +++-- node-graph/nodes/gstd/src/wasm_application_io.rs | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/node-graph/nodes/gstd/src/text.rs b/node-graph/nodes/gstd/src/text.rs index 95a7605422..5fa0415f58 100644 --- a/node-graph/nodes/gstd/src/text.rs +++ b/node-graph/nodes/gstd/src/text.rs @@ -28,8 +28,9 @@ fn text<'i: 'n>( #[default(0.)] tilt: f64, align: TextAlign, - /// When enabled, outputs a table with one Vector per character, allowing individual character manipulation. - /// When disabled, outputs a single Vector containing all characters combined. Default is disabled. + /// When disabled, outputs a single vector element containing all characters combined. + /// When enabled, outputs a table with one vector element per character, + /// allowing individual character manipulation by subsequent operations. #[default(false)] per_glyph_instances: bool, ) -> Table { diff --git a/node-graph/nodes/gstd/src/wasm_application_io.rs b/node-graph/nodes/gstd/src/wasm_application_io.rs index db753cb066..1183c14f89 100644 --- a/node-graph/nodes/gstd/src/wasm_application_io.rs +++ b/node-graph/nodes/gstd/src/wasm_application_io.rs @@ -112,6 +112,7 @@ fn image_to_bytes(_: impl Ctx, image: Table>) -> Vec { let Some(image) = image.iter().next() else { return vec![] }; image.element.data.iter().flat_map(|color| color.to_rgb8_srgb().into_iter()).collect::>() } + /// Supports loading from URLs and local asset paths. Returns a transparent placeholder if the resource fails to load, allowing workflows to continue. #[node_macro::node(category("Web Request"))] async fn load_resource<'a: 'n>(_: impl Ctx, _primary: (), #[scope("editor-api")] editor: &'a WasmEditorApi, #[name("URL")] url: String) -> Arc<[u8]> { From 4d567c63bff42971faa9f953402c00b49da7828e Mon Sep 17 00:00:00 2001 From: Polyglot Date: Mon, 1 Dec 2025 20:28:13 +0100 Subject: [PATCH 3/5] Improve post_request node documentation Change doc comment to describe the node's purpose rather than focusing only on the "Discard Result" parameter. Now clearly states this is an HTTP POST operation with optional async behavior. --- node-graph/nodes/gstd/src/wasm_application_io.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node-graph/nodes/gstd/src/wasm_application_io.rs b/node-graph/nodes/gstd/src/wasm_application_io.rs index 1183c14f89..7a95980cad 100644 --- a/node-graph/nodes/gstd/src/wasm_application_io.rs +++ b/node-graph/nodes/gstd/src/wasm_application_io.rs @@ -65,7 +65,7 @@ async fn get_request(_: impl Ctx, _primary: (), #[name("URL")] url: String, disc response.text().await.ok().unwrap_or_default() } -/// "Discard Result" runs asynchronously in the background. Useful for fire-and-forget operations like logging, webhooks, or notifications. +/// Fetches data from a URL via HTTP GET. When "Discard Result" is enabled, runs asynchronously without waiting for a response. #[node_macro::node(category("Web Request"))] async fn post_request(_: impl Ctx, _primary: (), #[name("URL")] url: String, body: Vec, discard_result: bool) -> String { #[cfg(target_family = "wasm")] From 41e17ff1fc850927f332b31d56caa693143044b3 Mon Sep 17 00:00:00 2001 From: Polyglot Date: Tue, 2 Dec 2025 07:42:37 +0100 Subject: [PATCH 4/5] Fix post_request documentation error Corrected doc comment to say "HTTP POST" instead of "HTTP GET" since this function performs POST requests with binary data. --- node-graph/nodes/gstd/src/wasm_application_io.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node-graph/nodes/gstd/src/wasm_application_io.rs b/node-graph/nodes/gstd/src/wasm_application_io.rs index 7a95980cad..dcf6c563e9 100644 --- a/node-graph/nodes/gstd/src/wasm_application_io.rs +++ b/node-graph/nodes/gstd/src/wasm_application_io.rs @@ -65,7 +65,7 @@ async fn get_request(_: impl Ctx, _primary: (), #[name("URL")] url: String, disc response.text().await.ok().unwrap_or_default() } -/// Fetches data from a URL via HTTP GET. When "Discard Result" is enabled, runs asynchronously without waiting for a response. +/// Sends binary data to a URL via HTTP POST. When "Discard Result" is enabled, runs asynchronously without waiting for a response. #[node_macro::node(category("Web Request"))] async fn post_request(_: impl Ctx, _primary: (), #[name("URL")] url: String, body: Vec, discard_result: bool) -> String { #[cfg(target_family = "wasm")] From 430df53385a685743fea77d07df1e7c192ccebb3 Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Tue, 13 Jan 2026 00:05:27 -0800 Subject: [PATCH 5/5] Review changes --- node-graph/nodes/brush/src/brush.rs | 4 +- node-graph/nodes/gstd/src/text.rs | 7 +-- .../nodes/gstd/src/wasm_application_io.rs | 44 ++++++++++++++----- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/node-graph/nodes/brush/src/brush.rs b/node-graph/nodes/brush/src/brush.rs index 11516cc55d..74ecf2fb4c 100644 --- a/node-graph/nodes/brush/src/brush.rs +++ b/node-graph/nodes/brush/src/brush.rs @@ -59,7 +59,7 @@ impl Sample for BrushStampGenerator

{ /// Controls the brush shape with diameter and hardness, plus color and opacity (via flow). /// The feather exponent is calculated from hardness to determine edge softness. -/// Used internally to create the individual brush texture before stamping it repeatedly along a stroke path. +/// Used internally to create the brush texture before stamping it repeatedly along a stroke path. #[node_macro::node(skip_impl)] fn brush_stamp_generator(#[unit(" px")] diameter: f64, color: Color, hardness: f64, flow: f64) -> BrushStampGenerator { // Diameter @@ -79,7 +79,7 @@ fn brush_stamp_generator(#[unit(" px")] diameter: f64, color: Color, hardness: f BrushStampGenerator { color, feather_exponent, transform } } -/// Used to efficiently paint brush strokes: applies the same texture repeatedly at different positions with proper blending and boundary handling. +/// Used to efficiently paint brush strokes. Applies the same texture repeatedly at different positions with proper blending and boundary handling. #[node_macro::node(skip_impl)] fn blit(mut target: Table>, texture: Raster, positions: Vec, blend_mode: BlendFn) -> Table> where diff --git a/node-graph/nodes/gstd/src/text.rs b/node-graph/nodes/gstd/src/text.rs index 5fa0415f58..9dfe656351 100644 --- a/node-graph/nodes/gstd/src/text.rs +++ b/node-graph/nodes/gstd/src/text.rs @@ -3,9 +3,6 @@ use graph_craft::wasm_application_io::WasmEditorApi; use graphic_types::Vector; pub use text_nodes::*; -/// Converts text into editable vector shapes with customizable styling. -/// Parameters control font, size, spacing, alignment, and layout. - #[node_macro::node(category(""))] fn text<'i: 'n>( _: impl Ctx, @@ -28,9 +25,7 @@ fn text<'i: 'n>( #[default(0.)] tilt: f64, align: TextAlign, - /// When disabled, outputs a single vector element containing all characters combined. - /// When enabled, outputs a table with one vector element per character, - /// allowing individual character manipulation by subsequent operations. + /// Splits each text glyph into its own row in the table of vector geometry. #[default(false)] per_glyph_instances: bool, ) -> Table { diff --git a/node-graph/nodes/gstd/src/wasm_application_io.rs b/node-graph/nodes/gstd/src/wasm_application_io.rs index dcf6c563e9..3fd0dd13dd 100644 --- a/node-graph/nodes/gstd/src/wasm_application_io.rs +++ b/node-graph/nodes/gstd/src/wasm_application_io.rs @@ -27,16 +27,24 @@ use wasm_bindgen::JsCast; #[cfg(target_family = "wasm")] use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement}; -/// Allocates GPU memory and rendering context for vector-to-raster conversion. Must be paired with the Rasterize node. +/// Allocates GPU memory and a rendering context for vector-to-raster conversion. #[cfg(feature = "wgpu")] #[node_macro::node(category("Debug: GPU"))] async fn create_surface<'a: 'n>(_: impl Ctx, editor: &'a WasmEditorApi) -> Arc { Arc::new(editor.application_io.as_ref().unwrap().create_window()) } -/// "Discard Result" runs asynchronously in the background without waiting. Useful for triggering webhooks or analytics without blocking. +/// Sends an HTTP GET request to a specified URL and optionally waits for the response (unless discarded) which is output as a string. #[node_macro::node(category("Web Request"))] -async fn get_request(_: impl Ctx, _primary: (), #[name("URL")] url: String, discard_result: bool) -> String { +async fn get_request( + _: impl Ctx, + _primary: (), + /// The web address to send the GET request to. + #[name("URL")] + url: String, + /// Makes the request run in the background without waiting on a response. This is useful for triggering webhooks without blocking the continued execution of the graph. + discard_result: bool, +) -> String { #[cfg(target_family = "wasm")] { if discard_result { @@ -65,9 +73,19 @@ async fn get_request(_: impl Ctx, _primary: (), #[name("URL")] url: String, disc response.text().await.ok().unwrap_or_default() } -/// Sends binary data to a URL via HTTP POST. When "Discard Result" is enabled, runs asynchronously without waiting for a response. +/// Sends an HTTP POST request to a specified URL with the provided binary data and optionally waits for the response (unless discarded) which is output as a string. #[node_macro::node(category("Web Request"))] -async fn post_request(_: impl Ctx, _primary: (), #[name("URL")] url: String, body: Vec, discard_result: bool) -> String { +async fn post_request( + _: impl Ctx, + _primary: (), + /// The web address to send the POST request to. + #[name("URL")] + url: String, + /// The binary data to include in the body of the POST request. + body: Vec, + /// Makes the request run in the background without waiting on a response. This is useful for triggering webhooks without blocking the continued execution of the graph. + discard_result: bool, +) -> String { #[cfg(target_family = "wasm")] { if discard_result { @@ -100,23 +118,23 @@ async fn post_request(_: impl Ctx, _primary: (), #[name("URL")] url: String, bod response.text().await.ok().unwrap_or_default() } -/// Prepare text for transmission over HTTP or storage in binary file formats. +/// Converts a text string to raw binary data. Useful for transmission over HTTP or writing to files. #[node_macro::node(category("Web Request"), name("String to Bytes"))] fn string_to_bytes(_: impl Ctx, string: String) -> Vec { string.into_bytes() } -/// Extracts raw pixel data in RGBA format. Each pixel becomes 4 sequential bytes. Use before sending images over HTTP or writing to files. +/// Converts extracted raw RGBA pixel data from an input image. Each pixel becomes 4 sequential bytes. Useful for transmission over HTTP or writing to files. #[node_macro::node(category("Web Request"), name("Image to Bytes"))] fn image_to_bytes(_: impl Ctx, image: Table>) -> Vec { let Some(image) = image.iter().next() else { return vec![] }; image.element.data.iter().flat_map(|color| color.to_rgb8_srgb().into_iter()).collect::>() } -/// Supports loading from URLs and local asset paths. Returns a transparent placeholder if the resource fails to load, allowing workflows to continue. +/// Loads binary from URLs and local asset paths. Returns a transparent placeholder if the resource fails to load, allowing workflows to continue. #[node_macro::node(category("Web Request"))] -async fn load_resource<'a: 'n>(_: impl Ctx, _primary: (), #[scope("editor-api")] editor: &'a WasmEditorApi, #[name("URL")] url: String) -> Arc<[u8]> { - let Some(api) = editor.application_io.as_ref() else { +async fn load_resource<'a: 'n>(_: impl Ctx, _primary: (), #[scope("editor-api")] editor_resources: &'a WasmEditorApi, #[name("URL")] url: String) -> Arc<[u8]> { + let Some(api) = editor_resources.application_io.as_ref() else { return Arc::from(include_bytes!("../../../graph-craft/src/null.png").to_vec()); }; let Ok(data) = api.load_resource(url) else { @@ -129,7 +147,9 @@ async fn load_resource<'a: 'n>(_: impl Ctx, _primary: (), #[scope("editor-api")] data } -/// Works with any standard image format (PNG, JPEG, WebP, etc.). Automatically converts color space to linear sRGB for accurate compositing. +/// Converts raw binary data to a raster image. +/// +/// Works with standard image format (PNG, JPEG, WebP, etc.). Automatically converts the color space to linear sRGB for accurate compositing. #[node_macro::node(category("Web Request"))] fn decode_image(_: impl Ctx, data: Arc<[u8]>) -> Table> { let Some(image) = image::load_from_memory(data.as_ref()).ok() else { @@ -149,7 +169,7 @@ fn decode_image(_: impl Ctx, data: Arc<[u8]>) -> Table> { Table::new_from_element(Raster::new_cpu(image)) } -/// Renders with the resolution and transform defined by the footprint. Output respects vector strokes, gradients, and other styling details. +/// Renders a view of the input graphic within an area defined by the *Footprint*. #[cfg(target_family = "wasm")] #[node_macro::node(category(""))] async fn rasterize(