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,16 +1,17 @@
use crate::gcore::Context;
use core::f64::consts::TAU;
use core_types::gpoll::Interrupt;
use core_types::list::List;
use core_types::registry::types::{Angle, PixelSize};
use core_types::{ATTR_TRANSFORM, CloneVarArgs, Color, Ctx, ExtractAll, InjectVarArgs, OwnedContextImpl};
use core_types::{ATTR_TRANSFORM, Color, Ctx, DeriveCtx, InjectVarArgs};
use glam::{DAffine2, DVec2};
use graphic_types::{Graphic, Vector};
use raster_types::{CPU, Raster};
use vector_types::GradientStops;
#[node_macro::node(category("Repeat"))]
async fn repeat<T: Into<Graphic> + Default + Send + Clone + 'static>(
ctx: impl ExtractAll + CloneVarArgs + Ctx,
fn repeat<T: Into<Graphic> + Default + Send + Clone + 'static>(
ctx: impl Ctx + DeriveCtx,
#[implementations(
Context -> List<Graphic>,
Context -> List<Vector>,
@@ -18,35 +19,35 @@ async fn repeat<T: Into<Graphic> + Default + Send + Clone + 'static>(
Context -> List<Color>,
Context -> List<GradientStops>,
)]
content: impl Node<'n, Context<'static>, Output = List<T>>,
content: impl Node<Context<'_>, Output = List<T>>,
#[default(1)]
#[hard(1..)]
count: u32,
reverse: bool,
) -> List<T> {
) -> Result<List<T>, Interrupt> {
// Someday this node can have the option to generate infinitely instead of a fixed count (basically `std::iter::repeat`).
let count = count as usize;
let count = count as u64;
let spilled = ctx.index_head();
let mut result_list = List::new();
for index in 0..count {
let index = if reverse { count - index - 1 } else { index };
let new_ctx = OwnedContextImpl::from(ctx.clone()).with_index(index);
let generated_content = content.eval(new_ctx.into_context()).await;
let generated_content = content.eval(&ctx.promoted(&spilled, index))?;
for generated_row in generated_content.into_iter() {
result_list.push(generated_row);
}
}
result_list
Ok(result_list)
}
#[node_macro::node(category("Repeat"))]
pub async fn repeat_array<T: Into<Graphic> + Default + Send + Clone + 'static>(
ctx: impl ExtractAll + CloneVarArgs + Ctx,
pub fn repeat_array<T: Into<Graphic> + Default + Send + Clone + 'static>(
ctx: impl Ctx + DeriveCtx,
#[implementations(
Context -> List<Graphic>,
Context -> List<Vector>,
@@ -54,7 +55,7 @@ pub async fn repeat_array<T: Into<Graphic> + Default + Send + Clone + 'static>(
Context -> List<Color>,
Context -> List<GradientStops>,
)]
content: impl Node<'n, Context<'static>, Output = List<T>>,
content: impl Node<Context<'_>, Output = List<T>>,
#[default(100., 100.)]
// TODO: When using a custom Properties panel layout in document_node_definitions.rs and this default is set, the widget weirdly doesn't show up in the Properties panel. Investigation is needed.
direction: PixelSize,
@@ -62,10 +63,11 @@ pub async fn repeat_array<T: Into<Graphic> + Default + Send + Clone + 'static>(
#[default(5)]
#[hard(1..)]
count: u32,
) -> List<T> {
) -> Result<List<T>, Interrupt> {
let angle = angle.to_radians();
// A single copy has no steps between copies, so the denominator is kept at 1 to avoid `0. / 0.` producing a NaN transform
let total = (count - 1).max(1) as f64;
let spilled = ctx.index_head();
let mut result_list = List::new();
@@ -74,8 +76,7 @@ pub async fn repeat_array<T: Into<Graphic> + Default + Send + Clone + 'static>(
let translation = index as f64 * direction / total;
let transform = DAffine2::from_angle(angle) * DAffine2::from_translation(translation);
let new_ctx = OwnedContextImpl::from(ctx.clone()).with_index(index as usize);
let generated_content = content.eval(new_ctx.into_context()).await;
let generated_content = content.eval(&ctx.promoted(&spilled, index as u64))?;
for row_index in 0..generated_content.len() {
let Some(mut row) = generated_content.clone_item(row_index) else { continue };
@@ -89,12 +90,12 @@ pub async fn repeat_array<T: Into<Graphic> + Default + Send + Clone + 'static>(
}
}
result_list
Ok(result_list)
}
#[node_macro::node(category("Repeat"))]
async fn repeat_radial<T: Into<Graphic> + Default + Send + Clone + 'static>(
ctx: impl ExtractAll + CloneVarArgs + Ctx,
fn repeat_radial<T: Into<Graphic> + Default + Send + Clone + 'static>(
ctx: impl Ctx + DeriveCtx,
#[implementations(
Context -> List<Graphic>,
Context -> List<Vector>,
@@ -102,7 +103,7 @@ async fn repeat_radial<T: Into<Graphic> + Default + Send + Clone + 'static>(
Context -> List<Color>,
Context -> List<GradientStops>,
)]
content: impl Node<'n, Context<'static>, Output = List<T>>,
content: impl Node<Context<'_>, Output = List<T>>,
start_angle: Angle,
#[unit(" px")]
#[default(5)]
@@ -110,7 +111,8 @@ async fn repeat_radial<T: Into<Graphic> + Default + Send + Clone + 'static>(
#[default(5)]
#[hard(1..)]
count: u32,
) -> List<T> {
) -> Result<List<T>, Interrupt> {
let spilled = ctx.index_head();
let mut result_list = List::new();
for index in 0..count {
@@ -118,8 +120,7 @@ async fn repeat_radial<T: Into<Graphic> + Default + Send + Clone + 'static>(
let translation = DAffine2::from_translation(radius * DVec2::Y);
let transform = angle * translation;
let new_ctx = OwnedContextImpl::from(ctx.clone()).with_index(index as usize);
let generated_content = content.eval(new_ctx.into_context()).await;
let generated_content = content.eval(&ctx.promoted(&spilled, index as u64))?;
for row_index in 0..generated_content.len() {
let Some(mut row) = generated_content.clone_item(row_index) else { continue };
@@ -133,12 +134,12 @@ async fn repeat_radial<T: Into<Graphic> + Default + Send + Clone + 'static>(
}
}
result_list
Ok(result_list)
}
#[node_macro::node(category("Repeat"), name("Repeat on Points"))]
async fn repeat_on_points<T: Into<Graphic> + Default + Send + Clone + 'static>(
ctx: impl ExtractAll + CloneVarArgs + Sync + Ctx + InjectVarArgs,
fn repeat_on_points<T: Into<Graphic> + Default + Send + Clone + 'static>(
ctx: impl Ctx + DeriveCtx + InjectVarArgs,
points: List<Vector>,
#[implementations(
Context -> List<Graphic>,
@@ -147,40 +148,36 @@ async fn repeat_on_points<T: Into<Graphic> + Default + Send + Clone + 'static>(
Context -> List<Color>,
Context -> List<GradientStops>,
)]
content: impl Node<'n, Context<'static>, Output = List<T>>,
content: impl Node<Context<'_>, Output = List<T>>,
reverse: bool,
) -> List<T> {
) -> Result<List<T>, Interrupt> {
let spilled = ctx.index_head();
let mut result_list = List::new();
for points_index in 0..points.len() {
let Some(points_element) = points.element(points_index) else { continue };
let transform: DAffine2 = points.attribute_cloned_or_default(ATTR_TRANSFORM, points_index);
let mut iteration = async |index, point| {
let positions = points_element.point_domain.positions();
let range: Box<dyn Iterator<Item = (usize, &DVec2)>> = match reverse {
true => Box::new(positions.iter().enumerate().rev()),
false => Box::new(positions.iter().enumerate()),
};
for (index, &point) in range {
let transformed_point = transform.transform_point2(point);
let new_ctx = OwnedContextImpl::from(ctx.clone()).with_index(index).with_position(transformed_point);
let generated_content = content.eval(new_ctx.into_context()).await;
let scoped = ctx.push_position(transformed_point);
let generated_content = content.eval(&scoped.ctx().promoted(&spilled, index as u64))?;
for mut generated_row in generated_content.into_iter() {
generated_row.attribute_mut_or_insert_default::<DAffine2>(ATTR_TRANSFORM).translation = transformed_point;
result_list.push(generated_row);
}
};
let range = points_element.point_domain.positions().iter().enumerate();
if reverse {
for (index, &point) in range.rev() {
iteration(index, point).await;
}
} else {
for (index, &point) in range {
iteration(index, point).await;
}
}
}
result_list
Ok(result_list)
}
#[cfg(test)]