Skip to content

Tracking Issue: Instances tables #1834

Open
@Keavon

Description

@Keavon
  • 1. Write the Instances<T> struct. Wrap VectorData to become Instances<VectorData>, ImageFrame to become Instances<ImageFrame>, GraphicGroup to become Instances<GraphicGroup>, which lets us leave transform/alpha_blending alone for now. Places that read the single piece of data now read from a "getter" function that calls .next().expect("...") and write to a "setter" function that loops through each row (but there's just 1 presently).
    (Instance tables refactor part 1: wrap graphical data in the new Instances<T> struct #2230)
  • 2. Move the transform/alpha_blending up a level, which removes those fields from VectorData, ImageFrame, and GraphicGroup.
    (Instance tables refactor part 2: move the transform and alpha_blending fields up a level #2249)
  • 3. Since the ImageFrame<P> struct now has only one field left (pub image: Image<P>), delete this redundant struct and replace its usage in Instances<ImageFrame<P>> with Instances<Image<P>>.
    (Instance tables refactor part 3: flatten ImageFrame<P> in lieu of Image<P> #2256)
  • 4. Wrap ArtboardGroup to become Instances<ArtboardGroup>. Since the ArtboardGroup struct now has only one field (artboards: Vec<(Artboard, Option<NodeId>)>), delete this redundant struct and replace its usage with Instances<Artboard>. Move the Option<NodeId> to be an attribute called source_node_id in Instances<T>.
    (Instance tables refactor part 4: replace ArtboardGroups with multi-row Instances<Artboard> #2265)
  • 5. Since the GraphicGroup struct now has only one field left (elements: Vec<(GraphicElement, Option<NodeId>)>), delete this redundant struct and replace its usage in Instances<GraphicGroup> with Instances<GraphicElement>. Move the Option<NodeId> to the source_node_id attribute in Instances<T>. At this point, we have multi-row tables for group data but single-row image and vector data tables.
    (Instance tables refactor part 5: unwrap GraphicGroup as multi-row Instance<GraphicElement> tables and move up transforms #2363)
  • 6. Remove all usages of .one_instance_ref() and .one_instance_mut() by replacing their usages with loops or fold/reduce as needed in the nodes that currently expect one value but now need to work on multiple rows of values. Once this is done, nodes won't panic when we have a zero-row table. So we can replace usages of the form VectorDataTable::new(VectorData::empty()) with an actual empty table. Now, we have nodes that can accept table data of any row counts, and will often map N rows to N rows, but we don't have any nodes that actually produce more than 1 row as output yet unless given more than 1 row. But the repeat style nodes all currently output groups, not multi-rows of vector or raster, which we change in the next step. (db34ac3, 2cee9e2, Instance table refactor part 6: remove usage of one_instance_* functions #2672)
  • 7. Change the Repeat/Circular Repeat/Copy to Points node to no longer create a level of grouping, so they map from Instances<T> to Instances<T>, not from Instances<T> to Instances<GraphicElement>, now that we have (in the previous step) ensured all other nodes are able to work correctly with multiple instances instead of assuming a single instance. Investigate also doing this for the Merge node, making it generic over its input types, so we can have homogenous layer stacks to keep the data entropy down.
  • 8. Get the renderer to not wrap every leaf layer in a <g></g> which has the transform and alpha blending. (It's possibly helpful to reference this prior attempt.)
  • 9. Add an origin: DVec2 field to Image<P> where (0, 0) is its top left and (1, 1) is its bottom right. Update the nodes like Copy to Points which don't use the origin, and instead currently use the bounding box center, to behave in the more intended fashion by using origins. Manually update demo art which relies on Copy to Points to use the appropriate origin point.

Once done, #1929 becomes unblocked.


Initial

type GraphicElement = VectorData | GraphicGroup;

struct VectorData {
    transform: DAffine2,
}

struct GraphicGroup {
    transform: DAffine2,
    elements: Vec<GraphicElement>,
}

Wrapped in table

type GraphicElement = VectorDataTable | GraphicGroupTable;

struct VectorData {
    // transform has been moved to the table
}
type VectorDataTable = struct Instances<VectorData> {
    transform: Vec<DAffine2>, // count = 1
    instance: Vec<VectorData>, // count = 1
}

struct GraphicGroup {
    // transform has been moved to the table, but not up to the parent group
    elements: Vec<GraphicElement>,
}
type GraphicGroupTable = struct Instances<GraphicGroup> {
    transform: Vec<DAffine2>, // count = 1, parent to all in self.instance[0].elements
    instance: Vec<GraphicGroup>, // count = 1
}

(Inlined GraphicGroup)

type GraphicElement = VectorDataTable | GraphicGroupTable;

struct VectorData {
    // transform has been moved to the table
}
type VectorDataTable = struct Instances<VectorData> {
    transform: Vec<DAffine2>, // count = 1
    instance: Vec<VectorData>, // count = 1
}

type GraphicGroupTable = struct Instances<Vec<GraphicElement>> {
    transform: Vec<DAffine2>, // count = 1, parent to all in self.instance[0]
    instance: Vec<Vec<GraphicElement>>, // count = 1
}
// Document root
// ├─ Top folder
// │  ├─ Inner vector 1
// │  └─ Inner vector 2
// └─ Top vector

// Document root
GraphicGroupTable {
    transform: vec![ // count = 1
        DAffine2::IDENTITY,
    ],
    instance: vec![ // count = 1
        vec![
            // Top folder
            GraphicGroupTable {
                transform: vec![ // count = 1
                    DAffine2::TOP_FOLDER,
                ],
                instance: vec![ // count = 1
                    vec![
                        // Inner vector 1
                        VectorDataTable {
                            transform: vec![ // count = 1
                                DAffine2::INNER_VECTOR_1,
                            ],
                            instance: vec![ // count = 1
                                VectorData {},
                            ],
                        },
                        // Inner vector 2
                        VectorDataTable {
                            transform: vec![ // count = 1
                                DAffine2::INNER_VECTOR_2,
                            ],
                            instance: vec![ // count = 1
                                VectorData {},
                            ],
                        },
                    ],
                ],
            },
            // Top vector
            VectorDataTable {
                transform: vec![ // count = 1
                    DAffine2::TOP_VECTOR,
                ],
                instance: vec![ // count = 1
                    VectorData {},
                ],
            },
        ],
    ],
}

Flattened GraphicGroup with transform moved to parent

type GraphicElement = VectorDataTable | GraphicGroupTable;

struct VectorData {
    // transform has been moved to the table
}
type VectorDataTable = struct Instances<VectorData> {
    transform: Vec<DAffine2>, // count = 1
    instance: Vec<VectorData>, // count = 1
}

type GraphicGroupTable = struct Instances<GraphicElement> {
    transform: Vec<DAffine2>, // parent to its corresponding element in self.instance
    instance: Vec<GraphicElement>,
}
// Document root
// ├─ Top folder
// │  ├─ Inner vector 1
// │  └─ Inner vector 2
// └─ Top vector

// Document root
GraphicGroupTable {
    transform: vec![
        DAffine2::TOP_FOLDER,
        DAffine2::TOP_VECTOR,
    ],
    instance: vec![
        // Top folder
        GraphicGroupTable {
            transform: vec![
                DAffine2::IDENTITY, // from the Merge layer node
                DAffine2::IDENTITY, // from the Merge layer node
            ],
            instance: vec![
                // Inner vector 1
                VectorDataTable {
                    transform: vec![ // count = 1
                        DAffine2::INNER_VECTOR_1,
                    ],
                    instance: vec![ // count = 1
                        VectorData {},
                    ],
                },
                // Inner vector 2
                VectorDataTable {
                    transform: vec![ // count = 1
                        DAffine2::INNER_VECTOR_2,
                    ],
                    instance: vec![ // count = 1
                        VectorData {},
                    ],
                },
            ],
        },
        // Top vector
        VectorDataTable {
            transform: vec![ // count = 1
                DAffine2::IDENTITY,
            ],
            instance: vec![ // count = 1
                VectorData {},
            ],
        },
    ],
}

Metadata

Metadata

Assignees

Labels

ArchitectureInvolves architecture or engineering work or discussion

Projects

Status

Ongoing Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions