Advanced Concepts

This page explains how the Curvy Generator updates and processes data. Understanding these concepts helps you build more efficient graphs and write your own modules.

Modules fall into three groups based on how and when they compute their output.

Normal modules refresh during the standard pass of the CurvyGenerator.Refresh() method (automatically called when Auto Refresh is set to true). When the generator refreshes, it iterates through all modules in dependency order — upstream modules first — and calls Refresh() on each dirty module.

Example modules: Shape Extrusion, Deform Mesh.

On-request modules implement the IOnRequestProcessing interface. Their Refresh method is never called. Instead, they compute data only when a downstream module asks for it. The downstream module calls OnSlotDataRequest() on the upstream module, passing request parameters that describe exactly what data is needed (e.g. rasterization resolution, start/end range).

On-request modules cache their last result. The output slot stores the request parameters from the last call. If a downstream module makes the same request again (identical parameters), the cached data is returned without recalculation.

In the graph editor, links to on-request modules are shown with double lines instead of single lines. The output slots of an on-request module can connect only to:

Example modules: Input Spline Path, Conform Path.

No-processing modules implement the INoProcessing marker interface. Their Refresh method is never called. They exist in the graph for utility purposes only and do not produce or consume data through links.

Example module: the Note module.

The generator does not recalculate everything on every update. It uses a dirtying mechanism:

  • When a module changes (e.g. its settings are edited), it marks itself dirty.
  • This dirty state propagates to all downstream modules (modules connected to its outputs).

A dirtied normal module will recalculate at the next refresh. A dirtied on-request module will clear its cache.

Modules exchange data in the form of instances of CGData (see also Data Types). CGData instances usually contain arrays of data (positions, vertices, triangles). Creating new arrays on every refresh would generate garbage and hurt performance.

To avoid this, Curvy uses a pooling system based on the SubArray<T> structure. Large arrays are allocated from pools and returned when no longer needed. The arrays are returned when the CGData instance that owns them is disposed.

Whether a CGData instance should be disposed by its consumer after use depends on how it was produced:

  • Disposable — Data that was copied (cloned) when passed between modules. This happens when a slot's ModifiesData value is set to true, or when the data comes from an on-request module. The receiving module owns this copy and should dispose it when done, returning the underlying arrays to the pool.
  • Non-disposable — Data that is a direct reference to a module's internal output. Modules consuming it should not dispose it.

All this is transparent to you as a user.