Start adapting nodes to new version

This commit is contained in:
Dennis Kobert
2026-07-26 20:59:12 +00:00
parent 44277c9636
commit f0f7d6a5d7
16 changed files with 380 additions and 357 deletions

View File

@@ -1,6 +1,7 @@
use core_types::gpoll::GPoll;
use core_types::list::List;
use core_types::transform::Footprint;
use core_types::{CacheHash, CloneVarArgs, Color, Context, Ctx, ExtractAll, ExtractAnimationTime, ExtractPointerPosition, ExtractRealTime, OwnedContextImpl};
use core_types::{CacheHash, Color, Context, Ctx, DeriveCtx, ExtractAnimationTime, ExtractPointerPosition, ExtractRealTime};
use glam::{DAffine2, DVec2};
use graphic_types::vector_types::GradientStops;
use graphic_types::{Artboard, Graphic, Vector};
@@ -61,8 +62,8 @@ fn animation_time(
}
#[node_macro::node(category("Debug"))]
async fn quantize_real_time<T>(
ctx: impl Ctx + ExtractAll + CloneVarArgs,
fn quantize_real_time<T>(
ctx: impl Ctx + ExtractRealTime + DeriveCtx,
#[implementations(
Context -> bool,
Context -> u32,
@@ -84,11 +85,11 @@ async fn quantize_real_time<T>(
Context -> List<f64>,
Context -> (),
)]
value: impl Node<'n, Context<'static>, Output = T>,
value: impl Node<Context<'_>, Output = T>,
#[default(1)]
#[unit("sec")]
quantum: f64,
) -> T {
) -> GPoll<T> {
let time = ctx.try_real_time().unwrap_or_default();
let time = time / 1000.;
let mut quantized_time = (time * quantum.recip()).round() / quantum.recip();
@@ -96,13 +97,13 @@ async fn quantize_real_time<T>(
quantized_time = time;
}
let quantized_time = quantized_time * 1000.;
let new_context = OwnedContextImpl::from(ctx).with_real_time(quantized_time);
value.eval(Some(new_context.into())).await
let scope = ctx.scope().with_real_time(Some(quantized_time));
value.eval(&ctx.with_scope(&scope))
}
#[node_macro::node(category("Debug"))]
async fn quantize_animation_time<T>(
ctx: impl Ctx + ExtractAll + CloneVarArgs,
fn quantize_animation_time<T>(
ctx: impl Ctx + ExtractAnimationTime + DeriveCtx,
#[implementations(
Context -> bool,
Context -> u32,
@@ -124,18 +125,18 @@ async fn quantize_animation_time<T>(
Context -> List<f64>,
Context -> (),
)]
value: impl Node<'n, Context<'static>, Output = T>,
value: impl Node<Context<'_>, Output = T>,
#[default(1)]
#[unit("sec")]
quantum: f64,
) -> T {
) -> GPoll<T> {
let time = ctx.try_animation_time().unwrap_or_default();
let mut quantized_time = (time * quantum.recip()).round() / quantum.recip();
if !quantized_time.is_finite() {
quantized_time = time;
}
let new_context = OwnedContextImpl::from(ctx).with_animation_time(quantized_time);
value.eval(Some(new_context.into())).await
let scope = ctx.scope().with_animation_time(Some(quantized_time));
value.eval(&ctx.with_scope(&scope))
}
/// Produces the current position of the user's pointer within the document canvas.

View File

@@ -1,5 +1,6 @@
use core::f64;
use core_types::context::{CloneVarArgs, Context, ContextFeatures, Ctx, ExtractAll};
use core_types::context::{Context, ContextFeatures, 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;
@@ -12,8 +13,8 @@ use raster_types::{CPU, GPU, Raster};
/// Filters out what should be unused components of the context based on the specified requirements.
/// This node is inserted by the compiler to "zero out" unused context components.
#[node_macro::node(category(""))]
async fn context_modification<T>(
ctx: impl Ctx + CloneVarArgs + ExtractAll,
fn context_modification<T>(
ctx: impl Ctx + DeriveCtx,
/// The data to pass through, evaluated with the stripped down context.
#[implementations(
Context -> (),
@@ -41,13 +42,12 @@ async fn context_modification<T>(
Context -> AttributeValueDyn,
Context -> ListDyn,
)]
value: impl Node<Context<'static>, Output = T>,
value: impl Node<Context<'_>, Output = T>,
/// The parts of the context to keep when evaluating the input value. All other parts are nullified.
features_to_keep: ContextFeatures,
) -> T {
let new_context = OwnedContextImpl::from_flags(ctx, features_to_keep);
value.eval(Some(new_context.into())).await
) -> GPoll<T> {
let scope = ctx.scope().nullified(features_to_keep);
value.eval(&ctx.nullified(features_to_keep, &scope))
}
#[cfg(test)]

View File

@@ -1,4 +1,4 @@
use core_types::WasmNotSend;
use core_types::gpoll::Interrupt;
use core_types::graphene_hash::CacheHash;
use core_types::memo::*;
use std::hash::DefaultHasher;
@@ -10,7 +10,7 @@ use std::sync::Mutex;
///
/// Stores the last evaluated data that flowed through this node and immediately returns that data on subsequent renders if the context has not changed.
#[node_macro::node(category("General"), path(graphene_core::memo), skip_impl)]
async fn memoize<I: CacheHash + Send + 'n, T: Clone + WasmNotSend>(input: I, #[data] cache: Arc<Mutex<Option<(u64, T)>>>, content: impl Node<I, Output = T>) -> T {
fn memoize<I: CacheHash, T: Clone>(input: I, #[data] cache: Arc<Mutex<Option<(u64, T)>>>, content: impl Node<I, Output = T>) -> Result<T, Interrupt> {
// Caches the output of a given node called with a specific input.
//
// A cache miss occurs when the Option is None. In this case, the node evaluates the inner node and memoizes (stores) the result.
@@ -24,28 +24,31 @@ async fn memoize<I: CacheHash + Send + 'n, T: Clone + WasmNotSend>(input: I, #[d
let hash = hasher.finish();
if let Some(data) = cache.lock().as_ref().unwrap().as_ref().and_then(|data| (data.0 == hash).then_some(data.1.clone())) {
return data;
return Ok(data);
}
let value = content.eval(input).await;
let value = content.eval(input)?;
*cache.lock().unwrap() = Some((hash, value.clone()));
value
Ok(value)
}
type MonitorValue<I, T> = Arc<Mutex<Option<Arc<IORecord<I, T>>>>>;
/// The Monitor node is used by the editor to access the data flowing through it.
#[node_macro::node(category(""), path(graphene_core::memo), serialize(serialize_monitor), properties("monitor_properties"), skip_impl)]
async fn monitor<I: Clone + 'static + Send + Sync, T: Clone + 'static + Send + Sync>(
fn monitor<I: Clone + 'static + Send + Sync, T: Clone + 'static + Send + Sync>(
input: I,
#[allow(clippy::type_complexity)]
#[data]
io: MonitorValue<I, T>,
content: impl Node<I, Output = T>,
) -> T {
let output = content.eval(input.clone()).await;
*io.lock().unwrap() = Some(Arc::new(IORecord { input, output: output.clone() }));
output
) -> Result<T, Interrupt> {
let output = content.eval(input)?;
*io.lock().unwrap() = Some(Arc::new(IORecord {
input: input.clone(),
output: output.clone(),
}));
Ok(output)
}
fn serialize_monitor<I: Clone + 'static + Send + Sync, T: Clone + 'static + Send + Sync>(io: &MonitorValue<I, T>) -> Option<Arc<dyn std::any::Any + Send + Sync>> {

View File

@@ -16,8 +16,8 @@ fn into<'i, T: 'i + Send + Into<O>, O: 'i + Send>(_: impl Ctx, value: T, _out_ty
}
#[node_macro::node(category(""), skip_impl)]
async fn convert<'i, T: 'i + Send + Convert<O, C>, O: 'i + Send, C: 'i + Send>(ctx: impl Ctx + ExtractFootprint, value: T, converter: C, _out_ty: PhantomData<O>) -> O {
value.convert(*ctx.try_footprint().unwrap_or(&Footprint::DEFAULT), converter).await
fn convert<T: Send + Convert<O, C>, O: Send, C: Send>(ctx: impl Ctx + ExtractFootprint, value: T, converter: C, _out_ty: PhantomData<O>) -> O {
value.convert(*ctx.try_footprint().unwrap_or(&Footprint::DEFAULT), converter)
}
#[cfg(test)]