mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-20 03:18:06 +08:00
Declare which index levels a node reads and nullify the rest
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use core_types::gpoll::{Extent, GPoll, GraphError, Interrupt};
|
||||
use core_types::list::List;
|
||||
use core_types::{Color, ExtractVarArgs};
|
||||
use core_types::{Ctx, ExtractIndex, ExtractPosition};
|
||||
use core_types::{Ctx, ExtractIndex, ExtractIndices, ExtractPosition};
|
||||
use glam::DVec2;
|
||||
use graphic_types::vector_types::GradientStops;
|
||||
use graphic_types::{Graphic, Vector};
|
||||
@@ -64,7 +64,7 @@ fn vararg_lanes<T: 'static>(ctx: &impl ExtractVarArgs, level: u8) -> GPoll<Exten
|
||||
|
||||
fn vararg_element<T: Clone + 'static>(ctx: &(impl ExtractVarArgs + ExtractIndex)) -> Result<T, Interrupt> {
|
||||
vararg_list::<T>(ctx)
|
||||
.and_then(|list| list.element(ctx.innermost_index() as usize))
|
||||
.and_then(|list| list.element(ctx.index() as usize))
|
||||
.cloned()
|
||||
.ok_or_else(|| GraphError::new("vararg row addressed past its items").into())
|
||||
}
|
||||
@@ -138,7 +138,9 @@ fn read_position(
|
||||
/// Nested loops can enable 2D or higher-dimensional iteration by using the *Loop Level* parameter to read the index from outer levels of loops.
|
||||
#[node_macro::node(category("Context"), path(core_types::vector))]
|
||||
fn read_index(
|
||||
ctx: impl Ctx + ExtractIndex,
|
||||
// `loop_level` is a runtime input, so no level is statically known and the
|
||||
// whole chain has to survive nullification.
|
||||
ctx: impl Ctx + ExtractIndices,
|
||||
_primary: (),
|
||||
/// The number of nested loops to traverse outwards (from the innermost loop) to get the index from. The most upstream loop is level 0, and downstream loops add levels.
|
||||
///
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use core_types::context::{ContextModification, Ctx, DeriveCtx};
|
||||
use core_types::gpoll::Interrupt;
|
||||
use core_types::context::{ContextFeatures, ContextModification, Ctx, DeriveCtx, IndexLink, nullify_index_levels};
|
||||
use core_types::gpoll::{ErrorKind, GraphError, Interrupt};
|
||||
|
||||
/// 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.
|
||||
@@ -12,5 +12,15 @@ fn context_modification<T>(
|
||||
modification: ContextModification,
|
||||
) -> Result<T, Interrupt> {
|
||||
let scope = ctx.scope().nullified(modification.features, Some(modification.sources()));
|
||||
value.eval(&ctx.nullified(modification.features, &scope))
|
||||
let exhausted = || {
|
||||
Interrupt::from(GraphError {
|
||||
kind: ErrorKind::ArenaExhausted,
|
||||
trace: Vec::new(),
|
||||
})
|
||||
};
|
||||
let index = match modification.features.contains(ContextFeatures::INDEX) {
|
||||
true => nullify_index_levels(ctx.index_head(), modification.index_levels, scope.arena()).ok_or_else(exhausted)?,
|
||||
false => IndexLink { index: 0, outer: None },
|
||||
};
|
||||
value.eval(&ctx.nullified(modification.features, index, &scope))
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ fn memoize<'e>(
|
||||
// keys with the lane normalized away.
|
||||
let leveled = content.layout().depth > 0;
|
||||
let lane = match leveled {
|
||||
true => ctx.innermost_index() as usize,
|
||||
true => ctx.index() as usize,
|
||||
false => 0,
|
||||
};
|
||||
let key = match leveled {
|
||||
@@ -203,7 +203,7 @@ fn monitor<'e>(
|
||||
// computes lane by lane. Serving THIS lane out of that batch rather than
|
||||
// evaluating the content separately is what keeps the cost linear: the extra
|
||||
// eval would double the work under every enclosing monitor.
|
||||
if content.layout().depth > 0 && ctx.innermost_index() == 0 {
|
||||
if content.layout().depth > 0 && ctx.index() == 0 {
|
||||
return match content.materialize_level(ctx, ctx.arena()) {
|
||||
LevelStatus::Batch(batch, finality) => {
|
||||
// SAFETY: the batch came from this edge, so it carries the edge's layout.
|
||||
@@ -235,7 +235,7 @@ fn monitor<'e>(
|
||||
};
|
||||
}
|
||||
let result = content.eval(&ctx);
|
||||
if ctx.innermost_index() == 0
|
||||
if ctx.index() == 0
|
||||
&& let GPoll::Final(value) | GPoll::Partial(value) = &result
|
||||
{
|
||||
// SAFETY: the value came from this edge, so it carries the edge's layout.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
use core_types::attribute::{Attr, EditorLayerPath, Opacity, RemoveAttr, Transform};
|
||||
use glam::DAffine2;
|
||||
use core_types::context::{DeriveCtx, ExtractIndex, IndexLink, InjectIndex};
|
||||
use core_types::context::{DeriveCtx, ExtractIndex, ExtractIndices, IndexLink, InjectIndex};
|
||||
use core_types::extent::{ExtentIn, LevelIn, ListIn, ValueIn};
|
||||
use core_types::gpoll::{ErrorKind, Extent, GPoll, GraphError, Interrupt, Level};
|
||||
use core_types::node::Lane;
|
||||
@@ -58,8 +58,8 @@ fn fade<T>(_: impl Ctx, (element, opacity): (T, Attr<Opacity>), factor: f64) ->
|
||||
/// writes a per-copy opacity indexed by the copy's own index.
|
||||
#[node_macro::node(category("Test"), extent(repeat_opacity_extent))]
|
||||
fn repeat_opacity(ctx: impl Ctx + ExtractIndex, element: f64, count: u32) -> IList<(f64, Attr<Opacity>)> {
|
||||
debug_assert!(ctx.innermost_index() < count as u64, "repeat addressed past its copy count");
|
||||
emit(element, Attr(ctx.innermost_index() as f64))
|
||||
debug_assert!(ctx.index() < count as u64, "repeat addressed past its copy count");
|
||||
emit(element, Attr(ctx.index() as f64))
|
||||
}
|
||||
|
||||
#[node_macro::node(category("Test"))]
|
||||
@@ -155,7 +155,7 @@ fn extend<T>(
|
||||
GPoll::Pending => return Err(Interrupt::Pending),
|
||||
_ => return Err(GraphError::new("extend over a non-exact base extent").into()),
|
||||
};
|
||||
let lane = ctx.innermost_index();
|
||||
let lane = ctx.index();
|
||||
match lane < split {
|
||||
true => base.eval(ctx),
|
||||
false => {
|
||||
@@ -210,7 +210,7 @@ fn omit_element<T>(ctx: impl Ctx + ExtractIndex + InjectIndex + Copy, content: i
|
||||
GPoll::Pending => return Err(Interrupt::Pending),
|
||||
_ => return Err(GraphError::new("omit over a non-exact extent").into()),
|
||||
};
|
||||
let lane = ctx.innermost_index();
|
||||
let lane = ctx.index();
|
||||
let source = match resolve_index(index, total) {
|
||||
Some(omitted) if lane >= omitted => lane + 1,
|
||||
_ => lane,
|
||||
@@ -270,7 +270,7 @@ fn extract_element(_: impl Ctx + InjectIndex + Copy, list: IList<f64>, index: f6
|
||||
#[node_macro::node(category("Test"), extent(mirror_extent))]
|
||||
fn mirror(ctx: impl Ctx + ExtractIndex + InjectIndex + Copy, content: IList<f64>, keep_original: bool) -> Result<IList<(f64, Attr<Transform>)>, Interrupt> {
|
||||
let total = content.len() as u64;
|
||||
let lane = ctx.innermost_index();
|
||||
let lane = ctx.index();
|
||||
let (source, mirrored) = match (keep_original, lane < total) {
|
||||
(true, true) => (lane, false),
|
||||
(true, false) => (lane - total, true),
|
||||
|
||||
Reference in New Issue
Block a user