mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-29 07:28:11 +08:00
Swap the repeat node to its leveled form in place
This commit is contained in:
@@ -1,51 +1,48 @@
|
|||||||
use crate::gcore::Context;
|
use crate::gcore::Context;
|
||||||
use core::f64::consts::TAU;
|
use core::f64::consts::TAU;
|
||||||
use core_types::gpoll::Interrupt;
|
use core_types::context::IndexLink;
|
||||||
|
use core_types::extent::{ExtentIn, LevelIn, ValueIn};
|
||||||
|
use core_types::gpoll::{Extent, GPoll, GraphError, Interrupt};
|
||||||
use core_types::list::List;
|
use core_types::list::List;
|
||||||
use core_types::registry::types::{Angle, PixelSize};
|
use core_types::registry::types::{Angle, PixelSize};
|
||||||
use core_types::{ATTR_TRANSFORM, Color, Ctx, DeriveCtx, InjectVarArgs};
|
use core_types::{ATTR_TRANSFORM, Color, Ctx, DeriveCtx, ExtractIndex, InjectVarArgs};
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
use graphic_types::{Graphic, Vector};
|
use graphic_types::{Graphic, Vector};
|
||||||
use raster_types::{CPU, Raster};
|
use raster_types::{CPU, Raster};
|
||||||
use vector_types::GradientStops;
|
use vector_types::GradientStops;
|
||||||
|
|
||||||
#[node_macro::node(category("Repeat"))]
|
/// Each copy evaluates the content within the copy's index pushed in,
|
||||||
fn repeat<T: Into<Graphic> + Default + Send + Clone + 'static>(
|
/// producing a level of `count` copies.
|
||||||
ctx: impl Ctx + DeriveCtx,
|
// Someday this node can have the option to generate infinitely instead of a fixed count (basically `std::iter::repeat`).
|
||||||
#[implementations(
|
#[node_macro::node(category("Repeat"), extent(repeat_extent))]
|
||||||
Context -> List<Graphic>,
|
fn repeat<T>(
|
||||||
Context -> List<Vector>,
|
ctx: impl Ctx + DeriveCtx + ExtractIndex,
|
||||||
Context -> List<Raster<CPU>>,
|
content: impl Node<Context<'_>, Output = T>,
|
||||||
Context -> List<Color>,
|
|
||||||
Context -> List<GradientStops>,
|
|
||||||
)]
|
|
||||||
content: impl Node<Context<'_>, Output = List<T>>,
|
|
||||||
#[default(1)]
|
#[default(1)]
|
||||||
#[hard(1..)]
|
#[hard(1..)]
|
||||||
count: u32,
|
count: u32,
|
||||||
reverse: bool,
|
reverse: bool,
|
||||||
) -> Result<List<T>, Interrupt> {
|
) -> Result<IList<T>, Interrupt> {
|
||||||
// Someday this node can have the option to generate infinitely instead of a fixed count (basically `std::iter::repeat`).
|
let inner = content.inner_extent(ctx)?;
|
||||||
|
let (copy, rest) = ctx.split_innermost(inner);
|
||||||
let count = count as u64;
|
if copy >= count as u64 {
|
||||||
let spilled = ctx.index_head();
|
return Err(GraphError::past_end().into());
|
||||||
|
|
||||||
let mut result_list = List::new();
|
|
||||||
|
|
||||||
for index in 0..count {
|
|
||||||
let index = if reverse { count - index - 1 } else { index };
|
|
||||||
|
|
||||||
let mark = core_types::record::stack::sp();
|
|
||||||
let generated_content = content.eval(&ctx.promoted(&spilled, index))?;
|
|
||||||
|
|
||||||
for generated_row in generated_content.into_iter() {
|
|
||||||
result_list.push(generated_row);
|
|
||||||
}
|
|
||||||
// SAFETY: generated_content is an owned list fully moved into result_list, so no record borrow into this iteration's frames remains.
|
|
||||||
unsafe { core_types::record::stack::rewind(mark) };
|
|
||||||
}
|
}
|
||||||
|
let copy = match reverse {
|
||||||
|
true => count as u64 - 1 - copy,
|
||||||
|
false => copy,
|
||||||
|
};
|
||||||
|
let mut frame = IndexLink { index: 0, outer: None };
|
||||||
|
content.eval(&ctx.push_level(&mut frame, copy, rest))
|
||||||
|
}
|
||||||
|
|
||||||
Ok(result_list)
|
/// The pushed level's extent is the copy count; inner levels forward to the
|
||||||
|
/// content, whose extent is taken uniform across copies (queried at copy 0).
|
||||||
|
fn repeat_extent(content: ExtentIn<'_>, count: ValueIn<'_, u32>, _reverse: ValueIn<'_, bool>, level: LevelIn) -> GPoll<Extent> {
|
||||||
|
match level.pushed() {
|
||||||
|
true => count.get().map(|count| Extent::Exactly(count as usize)),
|
||||||
|
false => content.at(level),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[node_macro::node(category("Repeat"))]
|
#[node_macro::node(category("Repeat"))]
|
||||||
|
|||||||
Reference in New Issue
Block a user