Skip to content
4 changes: 4 additions & 0 deletions node-graph/nodes/brush/src/brush.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ impl<P: Pixel + Alpha> Sample for BrushStampGenerator<P> {
}
}

/// 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<Color> {
// Diameter
Expand All @@ -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<BlendFn>(mut target: Table<Raster<CPU>>, texture: Raster<CPU>, positions: Vec<DVec2>, blend_mode: BlendFn) -> Table<Raster<CPU>>
where
Expand Down
6 changes: 5 additions & 1 deletion node-graph/nodes/gstd/src/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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<Vector> {
Expand Down
9 changes: 8 additions & 1 deletion node-graph/nodes/gstd/src/wasm_application_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<WasmSurfaceHandle> {
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")]
Expand Down Expand Up @@ -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<u8>, discard_result: bool) -> String {
#[cfg(target_family = "wasm")]
Expand Down Expand Up @@ -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<u8> {
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<Raster<CPU>>) -> Vec<u8> {
let Some(image) = image.iter().next() else { return vec![] };
image.element.data.iter().flat_map(|color| color.to_rgb8_srgb().into_iter()).collect::<Vec<u8>>()
}

/// 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 {
Expand All @@ -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<Raster<CPU>> {
let Some(image) = image::load_from_memory(data.as_ref()).ok() else {
Expand All @@ -142,6 +148,7 @@ fn decode_image(_: impl Ctx, data: Arc<[u8]>) -> Table<Raster<CPU>> {
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<T: WasmNotSend + 'n>(
Expand Down
2 changes: 1 addition & 1 deletion node-graph/nodes/math/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,7 @@ fn length(_: impl Ctx, vector: DVec2) -> f64 {
vector.length()
}

/// Scales the input vector to unit length while preserving it's direction. This is equivalent to dividing the input vector by it's own magnitude.
/// Scales the input vector to unit length while preserving its direction. This is equivalent to dividing the input vector by its own magnitude.
///
/// Returns zero when the input vector is zero.
#[node_macro::node(category("Math: Vector"))]
Expand Down
2 changes: 1 addition & 1 deletion node-graph/nodes/path-bool/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
4 changes: 2 additions & 2 deletions node-graph/nodes/text/src/font_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ impl FontCache {
}

/// Insert a new font into the cache
pub fn insert(&mut self, font: Font, perview_url: String, data: Vec<u8>) {
pub fn insert(&mut self, font: Font, preview_url: String, data: Vec<u8>) {
self.font_file_data.insert(font.clone(), data);
self.preview_urls.insert(font, perview_url);
self.preview_urls.insert(font, preview_url);
}

/// Gets the preview URL for showing in text field when live editing
Expand Down