This commit is contained in:
Dennis Kobert
2026-07-30 19:11:22 +02:00
parent e2a8420fee
commit f13806efcd
18 changed files with 60 additions and 71 deletions

View File

@@ -4,13 +4,13 @@ use crate::application_io::resource::Resource;
use crate::proto::Any as DAny;
use brush_nodes::brush_stroke::BrushStroke;
use core_types::color::SRGBA8;
use core_types::list::List;
use core_types::transform::Footprint;
use core_types::uuid::NodeId;
use core_types::context::Context;
use core_types::gnode::GNode;
use core_types::gpoll::GPoll;
use core_types::list::List;
use core_types::registry::{EdgeHandle, edge_type};
use core_types::transform::Footprint;
use core_types::uuid::NodeId;
use core_types::value::value_edge;
use core_types::{CacheHash, Color, ContextModification, MemoHash, Node, Type, TypeDescriptor};
use dyn_any::DynAny;

View File

@@ -459,10 +459,10 @@ impl BorrowTree {
#[cfg(test)]
mod test {
use super::*;
use graph_craft::document::value::TaggedValue;
use core_types::arena::ArenaCell;
use core_types::context::{ExtractFootprint, ExtractVarArgs};
use core_types::runtime::{SourceFuture, Spawner};
use graph_craft::document::value::TaggedValue;
struct InertSpawner;

View File

@@ -13,12 +13,12 @@ use graphene_std::raster::GPU;
use graphene_std::raster::color::Color;
use graphene_std::raster::*;
use graphene_std::raster::{CPU, Raster};
use graphene_std::registry::{ConstructionError, EdgeHandle, ErasedGNode, NodeIOTypes, RegistryEntry};
use graphene_std::render_node::RenderIntermediate;
use graphene_std::runtime::RuntimeHandle;
use graphene_std::transform::Footprint;
use graphene_std::uuid::NodeId;
use graphene_std::vector::Vector;
use graphene_std::registry::{ConstructionError, EdgeHandle, ErasedGNode, NodeIOTypes, RegistryEntry};
use graphene_std::runtime::RuntimeHandle;
use graphene_std::{Artboard, Context, Graphic, ProtoNodeIdentifier, SourceId, concrete, fn_type};
use node_registry_macros::{async_node, convert_node, into_node};
use std::collections::HashMap;

View File

@@ -86,10 +86,7 @@ struct LendStringNode {
impl LendStringNode {
fn new(value: String) -> Self {
Self {
value,
cell: ArenaCell::new(),
}
Self { value, cell: ArenaCell::new() }
}
}

View File

@@ -168,10 +168,7 @@ impl StatusCell {
}
pub fn no_partial() -> Self {
Self {
no_partial: true,
..Self::new()
}
Self { no_partial: true, ..Self::new() }
}
pub fn eval_input<Input, N: GNode<Input>>(&self, input_index: usize, node: &N, input: &Input) -> Result<N::Output, Interrupt> {

View File

@@ -117,10 +117,7 @@ impl<N: ?Sized> SharedEdge<N> {
}
pub fn share(&self) -> Self {
Self {
ptr: self.ptr,
own: self.own.clone(),
}
Self { ptr: self.ptr, own: self.own.clone() }
}
}
@@ -152,12 +149,7 @@ where
unsafe { self.ptr.as_ref() }.serialize()
}
fn eval_batch<'a>(
&self,
input: &'a Input,
range: std::ops::Range<u64>,
scratch: Option<&'a mut [std::mem::MaybeUninit<Self::Output>]>,
) -> crate::gnode::BatchStatus<'a, Self::Output>
fn eval_batch<'a>(&self, input: &'a Input, range: std::ops::Range<u64>, scratch: Option<&'a mut [std::mem::MaybeUninit<Self::Output>]>) -> crate::gnode::BatchStatus<'a, Self::Output>
where
Input: crate::context::InjectIndex + Copy,
{
@@ -235,10 +227,7 @@ impl EdgeHandle {
pub fn downcast_erased<N: ?Sized + 'static>(self, expected: Type) -> Result<SharedEdge<N>, ConstructionError> {
let found = self.ty;
self.node
.downcast::<SharedEdge<N>>()
.map(|edge| *edge)
.map_err(|_| ConstructionError::Type { expected, found })
self.node.downcast::<SharedEdge<N>>().map(|edge| *edge).map_err(|_| ConstructionError::Type { expected, found })
}
}
@@ -364,7 +353,7 @@ mod tests {
#[test]
fn derive_ctx_repeat_pushes_index_levels_through_the_erased_edge() {
use crate::context::{Derived, DeriveCtx, ExtractIndex};
use crate::context::{DeriveCtx, Derived, ExtractIndex};
struct RepeatNode<Node0> {
content: Node0,
@@ -421,7 +410,7 @@ mod tests {
#[test]
fn derive_ctx_footprint_replace_reaches_the_content() {
use crate::context::{Derived, DeriveCtx, ExtractFootprint};
use crate::context::{DeriveCtx, Derived, ExtractFootprint};
use crate::transform::Footprint;
struct ShiftFootprintNode<Node0> {

View File

@@ -300,12 +300,7 @@ mod tests {
let gate = Arc::new(std::sync::atomic::AtomicBool::new(false));
let runtime = Arc::new(MockRuntime::default());
let graph = StagedSumNode::new(
SourceNode(40.0f64),
GatedSource(gate.clone(), 2.0),
SourceNode(RuntimeHandle(runtime.clone())),
SourceNode(9u64),
);
let graph = StagedSumNode::new(SourceNode(40.0f64), GatedSource(gate.clone(), 2.0), SourceNode(RuntimeHandle(runtime.clone())), SourceNode(9u64));
assert_eq!(GNode::eval(&graph, &ctx), GPoll::Pending);
assert_eq!(runtime.drain(), Vec::<SourceId>::new(), "an interrupted prologue must not spawn or claim the slot");

View File

@@ -9,11 +9,11 @@ use crate::texture_cache::TextureCache;
use anyhow::Result;
use core_types::Color;
use core_types::color::SRGBA8;
use std::sync::Mutex;
use glam::UVec2;
use graphene_application_io::{ApplicationIo, EditorApi};
use raster_types::Texture;
use std::sync::Arc;
use std::sync::Mutex;
use vello::{AaConfig, AaSupport, RenderParams, Renderer, RendererOptions, Scene};
use wgpu::{Origin3d, TextureAspect};

View File

@@ -2,10 +2,10 @@ use crate::WgpuContext;
use crate::shader_runtime::{FULLSCREEN_VERTEX_SHADER_NAME, ShaderRuntime};
use core_types::list::{Item, List};
use core_types::shaders::buffer_struct::BufferStruct;
use std::sync::Mutex;
use raster_types::{GPU, Raster};
use std::borrow::Cow;
use std::collections::HashMap;
use std::sync::Mutex;
use wgpu::util::{BufferInitDescriptor, DeviceExt};
use wgpu::{
BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource, BindingType, Buffer, BufferBinding, BufferBindingType, BufferUsages, ColorTargetState, Face,

View File

@@ -1,4 +1,5 @@
use crate::WgpuExecutor;
use crate::WgpuExecutorHandle;
use core_types::Color;
use core_types::Ctx;
use core_types::color::SRGBA8;
@@ -8,7 +9,6 @@ use core_types::runtime::SourceFuture;
use core_types::transform::Footprint;
use raster_types::Image;
use raster_types::{CPU, GPU, Raster};
use crate::WgpuExecutorHandle;
use wgpu::util::{DeviceExt, TextureDataOrder};
use wgpu::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages};
@@ -40,7 +40,6 @@ fn upload_to_texture(device: &wgpu::Device, queue: &wgpu::Queue, image: &Raster<
)
}
/// Passthrough conversion for GPU `List`s - no conversion needed
impl Convert<List<Raster<GPU>>, WgpuExecutorHandle> for List<Raster<GPU>> {
fn convert(self, _: Footprint, _converter: WgpuExecutorHandle) -> List<Raster<GPU>> {

View File

@@ -165,7 +165,10 @@ pub(crate) fn generate_gnode_code(crate_ident: &CrateIdent, parsed: &ParsedNodeF
}
let clampable_bounds = regular_fields.iter().filter_map(|field| {
let ParsedFieldType::Regular(RegularParsedField { ty, number_hard_min, number_hard_max, .. }) = &field.ty else {
let ParsedFieldType::Regular(RegularParsedField {
ty, number_hard_min, number_hard_max, ..
}) = &field.ty
else {
return None;
};
(number_hard_min.is_some() || number_hard_max.is_some()).then(|| quote!(#ty: #core_types::misc::Clampable))
@@ -617,9 +620,7 @@ fn entries_tokens(parsed: &ParsedNodeFn, struct_name: &Ident, data_field_generic
let types = row.iter();
let edge_types = row.iter().map(|ty| quote!(gcore::registry::SharedEdge<gcore::registry::ErasedGNode<#ty>>));
let output = quote!(<#struct_name<#(#edge_types),*> as gcore::gnode::GNode<gcore::context::ContextImpl<'static>>>::Output);
let downcasts = names.iter().zip(row.iter()).map(|(name, ty)| {
quote!(let #name = inputs.next().unwrap().downcast::<#ty>()?;)
});
let downcasts = names.iter().zip(row.iter()).map(|(name, ty)| quote!(let #name = inputs.next().unwrap().downcast::<#ty>()?;));
quote! {
gcore::registry::RegistryEntry {
io: gcore::registry::NodeIOTypes::new(
@@ -666,15 +667,14 @@ fn implementation_rows(parsed: &ParsedNodeFn, regular_fields: &[&ParsedField]) -
},
ParsedFieldType::Node(NodeParsedField { output_type, implementations, .. }) => match implementations.is_empty() {
false => Some(implementations.iter().map(|implementation| implementation.output.clone()).collect()),
true => open_generics.iter().all(|generic| !crate::codegen::type_contains_ident(output_type, generic)).then(|| vec![output_type.clone()]),
true => open_generics
.iter()
.all(|generic| !crate::codegen::type_contains_ident(output_type, generic))
.then(|| vec![output_type.clone()]),
},
})
.collect::<Option<_>>()?;
let row_count = candidates.iter().map(|types| types.len()).max().unwrap_or(1).max(1);
Some(
(0..row_count)
.map(|row| candidates.iter().map(|types| types[row.min(types.len() - 1)].clone()).collect())
.collect(),
)
Some((0..row_count).map(|row| candidates.iter().map(|types| types[row.min(types.len() - 1)].clone()).collect()).collect())
}

View File

@@ -33,7 +33,10 @@ fn validate_async_source(parsed: &ParsedNodeFn) {
}
if !parsed.is_async {
if snapshot_ctx {
emit_error!(parsed.input.pat_ident.span(), "`CtxSnapshot` is the async source context; synchronous nodes take `impl Ctx` and read through extract bounds");
emit_error!(
parsed.input.pat_ident.span(),
"`CtxSnapshot` is the async source context; synchronous nodes take `impl Ctx` and read through extract bounds"
);
}
if !future_kernel {
return;

View File

@@ -1,5 +1,6 @@
use crate::brush_cache::BrushCache;
use crate::brush_stroke::{BrushStroke, BrushStyle};
use core_types::Ctx;
use core_types::blending::BlendMode;
use core_types::bounds::{BoundingBox, RenderBoundingBox};
use core_types::color::{Alpha, Color, Pixel, Sample};
@@ -8,7 +9,6 @@ use core_types::math::bbox::{AxisAlignedBbox, Bbox};
use core_types::transform::Transform;
use core_types::uuid::NodeId;
use core_types::{ATTR_BLEND_MODE, ATTR_CLIPPING_MASK, ATTR_EDITOR_LAYER_PATH, ATTR_OPACITY, ATTR_OPACITY_FILL, ATTR_TRANSFORM};
use core_types::Ctx;
use glam::{DAffine2, DVec2};
use raster_nodes::blending_nodes::blend_colors;
use raster_nodes::std_nodes::{empty_image, extend_image_to_bounds};
@@ -295,10 +295,12 @@ fn brush(
_ => BlendMode::Restore,
};
erase_restore_mask = blit(&(), List::new_from_item(erase_restore_mask), brush_texture, positions, move |a, b| blend_colors(a, b, mask_blend_mode, 1.))
.into_iter()
.next()
.unwrap_or_default();
erase_restore_mask = blit(&(), List::new_from_item(erase_restore_mask), brush_texture, positions, move |a, b| {
blend_colors(a, b, mask_blend_mode, 1.)
})
.into_iter()
.next()
.unwrap_or_default();
}
actual_image = blend_image_closure(erase_restore_mask, actual_image, |a, b| blend_colors(a, b, BlendMode::MultiplyAlpha, 1.));

View File

@@ -1,10 +1,10 @@
use core::f64;
use core_types::Color;
use core_types::context::{Context, ContextModification, Ctx, DeriveCtx};
use core_types::gpoll::GPoll;
use core_types::list::{AttributeDyn, AttributeValueDyn, List, ListDyn};
use core_types::transform::Footprint;
use core_types::uuid::NodeId;
use core_types::Color;
use glam::{DAffine2, DVec2};
use graphic_types::vector_types::GradientStops;
use graphic_types::{Artboard, Graphic, Vector};

View File

@@ -3,15 +3,15 @@ use base64::Engine;
#[cfg(target_family = "wasm")]
use canvas_utils::{Canvas, CanvasHandle};
use core_types::color::SRGBA8;
use core_types::gpoll::GPoll;
use core_types::list::{Item, List};
#[cfg(target_family = "wasm")]
use core_types::math::bbox::Bbox;
use core_types::runtime::SourceFuture;
#[cfg(target_family = "wasm")]
use core_types::transform::Footprint;
#[cfg(target_family = "wasm")]
use core_types::{ATTR_EDITOR_MERGED_LAYERS, ATTR_TRANSFORM, WasmNotSend};
use core_types::gpoll::GPoll;
use core_types::runtime::SourceFuture;
use core_types::{Color, Ctx};
pub use graph_craft::application_io::resource::{Resource, ResourceHash};
pub use graph_craft::application_io::*;

View File

@@ -12,11 +12,7 @@ use wgpu::util::DeviceExt;
use wgpu_executor::{WgpuExecutor, WgpuPipeline, WgpuPipelineCache};
#[node_macro::node(category(""))]
fn render_background<'a>(
ctx: impl Ctx + ExtractFootprint + ExtractVarArgs,
#[scope(composite_background_pipeline::IDENTIFIER)] pipeline: WgpuPipelineCache,
data: RenderOutput,
) -> RenderOutput {
fn render_background<'a>(ctx: impl Ctx + ExtractFootprint + ExtractVarArgs, #[scope(composite_background_pipeline::IDENTIFIER)] pipeline: WgpuPipelineCache, data: RenderOutput) -> RenderOutput {
let footprint = ctx.footprint();
let render_params = ctx
.vararg(0)

View File

@@ -209,7 +209,11 @@ mod tests {
assert_eq!(ctx.try_animation_time(), Some(2.0));
assert_eq!(ctx.try_pointer_position(), Some(glam::DVec2::new(3.0, 4.0)));
GPoll::Final(RenderOutput {
data: RenderOutputType::Buffer { data: Vec::new(), width: 0, height: 0 },
data: RenderOutputType::Buffer {
data: Vec::new(),
width: 0,
height: 0,
},
metadata: RenderMetadata::default(),
})
}
@@ -240,6 +244,13 @@ mod tests {
let GPoll::Final(result) = <CreateContextNode<ProbeNode> as GNode<ContextImpl>>::eval(&graph, &ctx) else {
panic!("create_context must complete synchronously");
};
assert_eq!(result.data, RenderOutputType::Buffer { data: Vec::new(), width: 0, height: 0 });
assert_eq!(
result.data,
RenderOutputType::Buffer {
data: Vec::new(),
width: 0,
height: 0
}
);
}
}

View File

@@ -3,11 +3,11 @@ use core::f64::consts::{PI, TAU};
use core::hash::{Hash, Hasher};
use core_types::blending::BlendMode;
use core_types::bounds::{BoundingBox, RenderBoundingBox};
use core_types::gpoll::Interrupt;
use core_types::list::{ATTR_FILL, ATTR_STROKE, Item, ItemAttributeValues, List, ListDyn};
use core_types::registry::types::{Angle, Length, Multiplier, Percentage, PixelLength, Progression, SeedValue};
use core_types::transform::{Footprint, Transform};
use core_types::uuid::NodeId;
use core_types::gpoll::Interrupt;
use core_types::{
ATTR_BLEND_MODE, ATTR_CLIPPING_MASK, ATTR_EDITOR_LAYER_PATH, ATTR_EDITOR_MERGED_LAYERS, ATTR_GRADIENT_TYPE, ATTR_OPACITY, ATTR_OPACITY_FILL, ATTR_SPREAD_METHOD, ATTR_TRANSFORM, Color, Context,
Ctx, DeriveCtx,
@@ -116,7 +116,7 @@ fn assign_colors<T>(
repeat_every: u32,
) -> T
where
T: VectorListIterMut+ Send,
T: VectorListIterMut + Send,
{
let Some(row) = gradient.into_iter().next() else { return content };
@@ -157,7 +157,7 @@ where
/// Applies a fill style to the vector content, giving an appearance to the area within the interior of the geometry.
#[node_macro::node(category("Vector: Style"), path(graphene_core::vector), properties("fill_properties"))]
fn fill<V: VectorListIterMut+ Send, F: IntoGraphicList+ Send + 'static>(
fn fill<V: VectorListIterMut + Send, F: IntoGraphicList + Send + 'static>(
_: impl Ctx,
/// The content with vector paths to apply the fill style to.
#[implementations(
@@ -252,7 +252,7 @@ impl IntoF64Vec for String {
/// Applies a stroke style to the vector content, giving an appearance to the area within the outline of the geometry.
#[node_macro::node(category("Vector: Style"), path(graphene_core::vector), properties("stroke_properties"))]
fn stroke<V, L: IntoF64Vec, P: IntoGraphicList+ Send + 'static>(
fn stroke<V, L: IntoF64Vec, P: IntoGraphicList + Send + 'static>(
_: impl Ctx,
/// The content with vector paths to apply the stroke style to.
#[implementations(
@@ -324,7 +324,7 @@ fn stroke<V, L: IntoF64Vec, P: IntoGraphicList+ Send + 'static>(
dash_offset: f64,
) -> List<V>
where
List<V>: VectorListIterMut+ Send,
List<V>: VectorListIterMut + Send,
{
let dash_lengths = dash_lengths.into_vec().into_iter().map(|length| length.max(0.)).collect();