Add workaround for cache context nullification breaking nested loop indexes (#3178)

* Disable caching for the instance repeat etc. nodes

* Add usize implementation for caching and monitor nodes

* Change return type of instance index node back to f64

* Cleanup while loop

* Remove stray usize changes

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert 2025-09-16 23:59:43 +02:00 committed by GitHub
parent 390ce023ea
commit e4d2805115
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 20 additions and 14 deletions

View file

@ -27,7 +27,7 @@ pub trait ExtractAnimationTime {
}
pub trait ExtractIndex {
fn try_index(&self) -> Option<Vec<usize>>;
fn try_index(&self) -> Option<impl Iterator<Item = usize>>;
}
// Consider returning a slice or something like that
@ -175,7 +175,7 @@ impl<T: ExtractAnimationTime + Sync> ExtractAnimationTime for Option<T> {
}
}
impl<T: ExtractIndex> ExtractIndex for Option<T> {
fn try_index(&self) -> Option<Vec<usize>> {
fn try_index(&self) -> Option<impl Iterator<Item = usize>> {
self.as_ref().and_then(|x| x.try_index())
}
}
@ -212,7 +212,7 @@ impl<T: ExtractAnimationTime + Sync> ExtractAnimationTime for Arc<T> {
}
}
impl<T: ExtractIndex> ExtractIndex for Arc<T> {
fn try_index(&self) -> Option<Vec<usize>> {
fn try_index(&self) -> Option<impl Iterator<Item = usize>> {
(**self).try_index()
}
}
@ -268,8 +268,8 @@ impl ExtractRealTime for ContextImpl<'_> {
}
}
impl ExtractIndex for ContextImpl<'_> {
fn try_index(&self) -> Option<Vec<usize>> {
self.index.clone()
fn try_index(&self) -> Option<impl Iterator<Item = usize>> {
self.index.clone().map(|x| x.into_iter())
}
}
impl ExtractVarArgs for ContextImpl<'_> {
@ -304,8 +304,8 @@ impl ExtractAnimationTime for OwnedContextImpl {
}
}
impl ExtractIndex for OwnedContextImpl {
fn try_index(&self) -> Option<Vec<usize>> {
self.index.clone()
fn try_index(&self) -> Option<impl Iterator<Item = usize>> {
self.index.clone().map(|x| x.into_iter())
}
}
impl ExtractVarArgs for OwnedContextImpl {
@ -418,7 +418,7 @@ impl OwnedContextImpl {
footprint,
varargs: None,
parent,
index,
index: index.map(|x| x.collect()),
real_time,
animation_time,
}

View file

@ -2,7 +2,7 @@ use crate::gradient::GradientStops;
use crate::raster_types::{CPU, Raster};
use crate::table::{Table, TableRowRef};
use crate::vector::Vector;
use crate::{CloneVarArgs, Context, Ctx, ExtractAll, ExtractIndex, ExtractVarArgs, Graphic, InjectIndex, InjectVarArgs, OwnedContextImpl};
use crate::{CloneVarArgs, Context, Ctx, ExtractAll, ExtractIndex, ExtractVarArgs, Graphic, InjectVarArgs, OwnedContextImpl};
use glam::DVec2;
use graphene_core_shaders::color::Color;
@ -19,7 +19,7 @@ impl std::hash::Hash for HashableDVec2 {
#[node_macro::node(name("Instance on Points"), category("Instancing"), path(graphene_core::vector))]
async fn instance_on_points<T: Into<Graphic> + Default + Send + Clone + 'static>(
ctx: impl ExtractAll + CloneVarArgs + Sync + Ctx + InjectIndex + InjectVarArgs,
ctx: impl ExtractAll + CloneVarArgs + Sync + Ctx + InjectVarArgs,
points: Table<Vector>,
#[implementations(
Context -> Table<Graphic>,
@ -63,7 +63,7 @@ async fn instance_on_points<T: Into<Graphic> + Default + Send + Clone + 'static>
#[node_macro::node(category("Instancing"), path(graphene_core::vector))]
async fn instance_repeat<T: Into<Graphic> + Default + Send + Clone + 'static>(
ctx: impl ExtractAll + CloneVarArgs + Ctx + InjectIndex,
ctx: impl ExtractAll + CloneVarArgs + Ctx,
#[implementations(
Context -> Table<Graphic>,
Context -> Table<Vector>,
@ -106,9 +106,15 @@ async fn instance_position(ctx: impl Ctx + ExtractVarArgs) -> DVec2 {
// TODO: Make this return a u32 instead of an f64, but we ned to improve math-related compatibility with integer types first.
#[node_macro::node(category("Instancing"), path(graphene_core::vector))]
async fn instance_index(ctx: impl Ctx + ExtractIndex, _primary: (), loop_level: u32) -> f64 {
ctx.try_index()
.and_then(|indexes| indexes.get(indexes.len().wrapping_sub(1).wrapping_sub(loop_level as usize)).copied())
.unwrap_or_default() as f64
let Some(index_iter) = ctx.try_index() else { return 0. };
let mut last = 0;
for (i, index) in index_iter.enumerate() {
if i == loop_level as usize {
return index as f64;
}
last = index;
}
last as f64
}
#[cfg(test)]