Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 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
36 changes: 32 additions & 4 deletions node-graph/nodes/gstd/src/wasm_application_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,24 @@ use wasm_bindgen::JsCast;
#[cfg(target_family = "wasm")]
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement};

/// 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<WasmSurfaceHandle> {
Arc::new(editor.application_io.as_ref().unwrap().create_window())
}

/// 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 {
Expand Down Expand Up @@ -63,8 +73,19 @@ async fn get_request(_: impl Ctx, _primary: (), #[name("URL")] url: String, disc
response.text().await.ok().unwrap_or_default()
}

/// 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<u8>, 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<u8>,
/// 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 {
Expand Down Expand Up @@ -97,20 +118,23 @@ async fn post_request(_: impl Ctx, _primary: (), #[name("URL")] url: String, bod
response.text().await.ok().unwrap_or_default()
}

/// 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<u8> {
string.into_bytes()
}

/// 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<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>>()
}

/// 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 {
Expand All @@ -123,6 +147,9 @@ async fn load_resource<'a: 'n>(_: impl Ctx, _primary: (), #[scope("editor-api")]
data
}

/// 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<Raster<CPU>> {
let Some(image) = image::load_from_memory(data.as_ref()).ok() else {
Expand All @@ -142,6 +169,7 @@ fn decode_image(_: impl Ctx, data: Arc<[u8]>) -> Table<Raster<CPU>> {
Table::new_from_element(Raster::new_cpu(image))
}

/// 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<T: WasmNotSend + 'n>(
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
Loading