mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-01 17:58:12 +08:00
Add multi-level loop indexing with the 'Instance Repeat' node
This commit is contained in:
@@ -969,6 +969,19 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the "Depth" parameter to the "Instance Index" node
|
||||||
|
if reference == "Instance Index" && inputs_count == 0 {
|
||||||
|
let mut node_template = resolve_document_node_type(reference)?.default_node_template();
|
||||||
|
document.network_interface.replace_implementation(node_id, network_path, &mut node_template);
|
||||||
|
|
||||||
|
document.network_interface.add_import(TaggedValue::None, false, 0, "Primary", "", &[*node_id]);
|
||||||
|
document.network_interface.add_import(TaggedValue::U32(0), false, 1, "Loop Level", "TODO", &[*node_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================================
|
||||||
|
// PUT ALL MIGRATIONS ABOVE THIS LINE
|
||||||
|
// ==================================
|
||||||
|
|
||||||
// Ensure layers are positioned as stacks if they are upstream siblings of another layer
|
// Ensure layers are positioned as stacks if they are upstream siblings of another layer
|
||||||
document.network_interface.load_structure();
|
document.network_interface.load_structure();
|
||||||
let all_layers = LayerNodeIdentifier::ROOT_PARENT.descendants(document.network_interface.document_metadata()).collect::<Vec<_>>();
|
let all_layers = LayerNodeIdentifier::ROOT_PARENT.descendants(document.network_interface.document_metadata()).collect::<Vec<_>>();
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ pub trait ExtractAnimationTime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait ExtractIndex {
|
pub trait ExtractIndex {
|
||||||
fn try_index(&self) -> Option<usize>;
|
fn try_index(&self) -> Option<Vec<usize>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consider returning a slice or something like that
|
// Consider returning a slice or something like that
|
||||||
@@ -91,7 +91,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<usize> {
|
fn try_index(&self) -> Option<Vec<usize>> {
|
||||||
self.as_ref().and_then(|x| x.try_index())
|
self.as_ref().and_then(|x| x.try_index())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,7 +122,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<usize> {
|
fn try_index(&self) -> Option<Vec<usize>> {
|
||||||
(**self).try_index()
|
(**self).try_index()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,8 +170,8 @@ impl ExtractTime for ContextImpl<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ExtractIndex for ContextImpl<'_> {
|
impl ExtractIndex for ContextImpl<'_> {
|
||||||
fn try_index(&self) -> Option<usize> {
|
fn try_index(&self) -> Option<Vec<usize>> {
|
||||||
self.index
|
self.index.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ExtractVarArgs for ContextImpl<'_> {
|
impl ExtractVarArgs for ContextImpl<'_> {
|
||||||
@@ -202,8 +202,8 @@ impl ExtractAnimationTime for OwnedContextImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ExtractIndex for OwnedContextImpl {
|
impl ExtractIndex for OwnedContextImpl {
|
||||||
fn try_index(&self) -> Option<usize> {
|
fn try_index(&self) -> Option<Vec<usize>> {
|
||||||
self.index
|
self.index.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ExtractVarArgs for OwnedContextImpl {
|
impl ExtractVarArgs for OwnedContextImpl {
|
||||||
@@ -244,7 +244,7 @@ pub struct OwnedContextImpl {
|
|||||||
varargs: Option<Arc<[DynBox]>>,
|
varargs: Option<Arc<[DynBox]>>,
|
||||||
parent: Option<Arc<dyn ExtractVarArgs + Sync + Send>>,
|
parent: Option<Arc<dyn ExtractVarArgs + Sync + Send>>,
|
||||||
// This could be converted into a single enum to save extra bytes
|
// This could be converted into a single enum to save extra bytes
|
||||||
index: Option<usize>,
|
index: Option<Vec<usize>>,
|
||||||
real_time: Option<f64>,
|
real_time: Option<f64>,
|
||||||
animation_time: Option<f64>,
|
animation_time: Option<f64>,
|
||||||
}
|
}
|
||||||
@@ -334,7 +334,11 @@ impl OwnedContextImpl {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn with_index(mut self, index: usize) -> Self {
|
pub fn with_index(mut self, index: usize) -> Self {
|
||||||
self.index = Some(index);
|
if let Some(current_index) = &mut self.index {
|
||||||
|
current_index.push(index);
|
||||||
|
} else {
|
||||||
|
self.index = Some(vec![index]);
|
||||||
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn into_context(self) -> Option<Arc<Self>> {
|
pub fn into_context(self) -> Option<Arc<Self>> {
|
||||||
@@ -346,12 +350,12 @@ impl OwnedContextImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Copy, dyn_any::DynAny)]
|
#[derive(Default, Clone, dyn_any::DynAny)]
|
||||||
pub struct ContextImpl<'a> {
|
pub struct ContextImpl<'a> {
|
||||||
pub(crate) footprint: Option<&'a Footprint>,
|
pub(crate) footprint: Option<&'a Footprint>,
|
||||||
varargs: Option<&'a [DynRef<'a>]>,
|
varargs: Option<&'a [DynRef<'a>]>,
|
||||||
// This could be converted into a single enum to save extra bytes
|
// This could be converted into a single enum to save extra bytes
|
||||||
index: Option<usize>,
|
index: Option<Vec<usize>>,
|
||||||
time: Option<f64>,
|
time: Option<f64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,6 +367,7 @@ impl<'a> ContextImpl<'a> {
|
|||||||
ContextImpl {
|
ContextImpl {
|
||||||
footprint: Some(new_footprint),
|
footprint: Some(new_footprint),
|
||||||
varargs: varargs.map(|x| x.borrow()),
|
varargs: varargs.map(|x| x.borrow()),
|
||||||
|
index: self.index.clone(),
|
||||||
..*self
|
..*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,12 +88,10 @@ 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) -> f64 {
|
async fn instance_index(ctx: impl Ctx + ExtractIndex, _primary: (), loop_level: u32) -> f64 {
|
||||||
match ctx.try_index() {
|
ctx.try_index()
|
||||||
Some(index) => return index as f64,
|
.and_then(|indexes| indexes.get(indexes.len().wrapping_sub(1).wrapping_sub(loop_level as usize)).copied())
|
||||||
None => warn!("Extracted value of incorrect type"),
|
.unwrap_or_default() as f64
|
||||||
}
|
|
||||||
0.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
Reference in New Issue
Block a user