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 { 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 // 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> { 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()) 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> { 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() (**self).try_index()
} }
} }
@ -268,8 +268,8 @@ impl ExtractRealTime for ContextImpl<'_> {
} }
} }
impl ExtractIndex for ContextImpl<'_> { impl ExtractIndex for ContextImpl<'_> {
fn try_index(&self) -> Option<Vec<usize>> { fn try_index(&self) -> Option<impl Iterator<Item = usize>> {
self.index.clone() self.index.clone().map(|x| x.into_iter())
} }
} }
impl ExtractVarArgs for ContextImpl<'_> { impl ExtractVarArgs for ContextImpl<'_> {
@ -304,8 +304,8 @@ impl ExtractAnimationTime for OwnedContextImpl {
} }
} }
impl ExtractIndex for OwnedContextImpl { impl ExtractIndex for OwnedContextImpl {
fn try_index(&self) -> Option<Vec<usize>> { fn try_index(&self) -> Option<impl Iterator<Item = usize>> {
self.index.clone() self.index.clone().map(|x| x.into_iter())
} }
} }
impl ExtractVarArgs for OwnedContextImpl { impl ExtractVarArgs for OwnedContextImpl {
@ -418,7 +418,7 @@ impl OwnedContextImpl {
footprint, footprint,
varargs: None, varargs: None,
parent, parent,
index, index: index.map(|x| x.collect()),
real_time, real_time,
animation_time, animation_time,
} }

View File

@ -2,7 +2,7 @@ use crate::gradient::GradientStops;
use crate::raster_types::{CPU, Raster}; use crate::raster_types::{CPU, Raster};
use crate::table::{Table, TableRowRef}; use crate::table::{Table, TableRowRef};
use crate::vector::Vector; 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 glam::DVec2;
use graphene_core_shaders::color::Color; 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))] #[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>( 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>, points: Table<Vector>,
#[implementations( #[implementations(
Context -> Table<Graphic>, 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))] #[node_macro::node(category("Instancing"), path(graphene_core::vector))]
async fn instance_repeat<T: Into<Graphic> + Default + Send + Clone + 'static>( async fn instance_repeat<T: Into<Graphic> + Default + Send + Clone + 'static>(
ctx: impl ExtractAll + CloneVarArgs + Ctx + InjectIndex, ctx: impl ExtractAll + CloneVarArgs + Ctx,
#[implementations( #[implementations(
Context -> Table<Graphic>, Context -> Table<Graphic>,
Context -> Table<Vector>, 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. // 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))] #[node_macro::node(category("Instancing"), path(graphene_core::vector))]
async fn instance_index(ctx: impl Ctx + ExtractIndex, _primary: (), loop_level: u32) -> f64 { async fn instance_index(ctx: impl Ctx + ExtractIndex, _primary: (), loop_level: u32) -> f64 {
ctx.try_index() let Some(index_iter) = ctx.try_index() else { return 0. };
.and_then(|indexes| indexes.get(indexes.len().wrapping_sub(1).wrapping_sub(loop_level as usize)).copied()) let mut last = 0;
.unwrap_or_default() as f64 for (i, index) in index_iter.enumerate() {
if i == loop_level as usize {
return index as f64;
}
last = index;
}
last as f64
} }
#[cfg(test)] #[cfg(test)]