Spline ¶
Spline(a=None, mode='COPY', selector=None, attr_from=None, **attrs)
Curve spline domain.
Groups control points into splines and stores per-spline parameters (type, resolution, cyclic flags, and NURBS settings). Provides accessors to parametric functions and common evaluations.
Attributes:
Name | Type | Description |
---|---|---|
loop_start |
(S,) int
|
Starting control-point index of each spline. |
loop_total |
(S,) int
|
Control-point count per spline. |
material_index |
(S,) int, optional
|
Material index per spline. |
curve_type |
(S,) int
|
One of constants |
resolution |
(S,) int, optional
|
Evaluation resolution (samples per segment). |
cyclic |
(S,) bool, optional
|
Whether each spline is closed. |
order |
(S,) int, optional
|
NURBS order. |
bezierpoint, endpoint |
(S,) bool, optional
|
NURBS flags. |
Properties
has_bezier : bool
True if any spline is Bezier.
functions : list
List-like container of parametric spline functions (Bezier/Poly/NURBS).
length : list of float
Length of each spline (delegates to functions
).
Methods:
Name | Description |
---|---|
delete_splines |
Delete splines and their control points. |
add_splines |
Append new splines given control-point counts. |
tangent |
Evaluate tangents at parameter |
compute_attribute_on_points |
Broadcast per-spline attributes to control points. |
Examples:
Build functions and sample tangents:
funcs = splines.functions
tan = splines.tangent(0.25)
Append three splines with different sizes:
splines.add_splines([4, 6, 8], material_index=[0, 1, 1])
Note:
functions
relies on project spline implementations. Ensure control-point attributes (e.g., handles for Bezier, weights/order for NURBS) are present when required.Caution:
resolution
semantics differ for cyclic vs. non-cyclic splines (endpoints handling).
Initialize a domain array and its attribute schema.
Initializes the storage from an existing array/domain or creates an empty structure. Optionally merges attribute definitions/values from another domain and keyword-provided attributes.
Domains are never instancied directly but by owning geometries.
Actual Domains are Vertex
, [Faces
][npblender.Faces],
Corner
, Edge
,
ControlPoint
, Spline
and Point
.
Domains are initialized with their defaults attributes, for instance position
for
point domaines.
Use attributes can be freely added.
Note: user attributes are saved in Blender Mesh objects only, Blender Curve objects don't store user attributes.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
a
|
array - like or FieldArray or None
|
Source data used to initialize the domain. If |
None
|
mode
|
(COPY, CAPTURE, EMPTY)
|
Initialization mode. |
'COPY'
|
selector
|
Any
|
Optional row/element selector applied to |
None
|
attr_from
|
Domain or Mapping or None
|
Attribute schema (and possibly values) to merge into this domain. |
None
|
**attrs
|
Additional attribute name/value pairs to inject or override. |
{}
|
Notes
The effective attribute list results from _declare_attributes()
, then
attr_from
, then **attrs
(later entries take precedence).
Examples:
cube = Mesh.cube() # points, corners, faces and edges domains are created
# Adding named attribute to point domain
cube.points.new_float('age')
# Setting the age
cube.points.age = np.random.uniforme(10, 10, len(cube.points))
actual_names
property
¶
actual_names
Column names.
Returns the actual field names, excluding optional fields.
has_bezier
property
¶
has_bezier
Check if the domain contains any Bézier splines.
Evaluates the curve_type
attribute and returns True
if at least one
spline in the domain is of type BEZIER
.
Returns:
Type | Description |
---|---|
bool
|
|
Notes
- Useful for quickly testing whether Bézier-specific logic (e.g., handle attributes) must be considered.
- For mixed domains, the result is
True
as soon as one Bézier is present.
Examples:
if splines.has_bezier:
print("Domain contains Bézier curves.")
next_loop_start
property
¶
next_loop_start
Offset to use for the next appended item.
Returns:
Type | Description |
---|---|
int
|
|
See Also
[compute_loop_start
][npblender.FaceSplineDomain.compute_loop_start]
reversed_indices
property
¶
reversed_indices
Map each corner/control-point index back to its owning item.
Returns:
Type | Description |
---|---|
ndarray of shape ``(sum(loop_total),)``
|
For index |
transdom_names
property
¶
transdom_names
List the names of trans-domain attributes.
Returns:
Type | Description |
---|---|
list of str
|
Names of attributes flagged with |
Examples:
names = D.transdom_names()
add ¶
add(count, **fields)
Add count records
New records are set with default values or values provided by the user in fields dict.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
count
|
int
|
Number of records to add. |
required |
fields
|
dict
|
Keyword arguments mapping field names to values. |
{}
|
append ¶
append(**fields)
Append values to the structured array.
The number of records to append is determined by the number of fields provided in the fields dictionary. The values of the fields are copied to the new records.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
fields
|
dict
|
Keyword arguments mapping field names to values. |
{}
|
append_sizes ¶
append_sizes(sizes, **fields)
Append new items given their sizes.
If loop_start
is not provided in fields
, computes it from sizes
using [compute_loop_start
][npblender.FaceSplineDomain.compute_loop_start].
Parameters:
Name | Type | Description | Default |
---|---|---|---|
sizes
|
array-like of int or None
|
Number of corners/control-points for each new item. |
required |
**fields
|
Additional per-item attributes to append (e.g., |
{}
|
Returns:
Type | Description |
---|---|
Any
|
The value returned by |
Notes
Passing sizes=None
is a no-op and returns an empty list.
as_kwargs ¶
as_kwargs(selector=None, include=None, exclude=None)
Return a dictionary of field values formatted as kwargs.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
selector
|
slice, int, list, or mask
|
Optional selection of elements to extract. |
None
|
include
|
list[str]
|
List of field names (original or python names) to include. |
None
|
exclude
|
list[str]
|
List of field names (original or python names) to exclude. |
None
|
Returns:
Type | Description |
---|---|
dict
|
Mapping from python-safe field names to array values. |
check ¶
check(count, halt=True)
Validate loop counters against a reference element count.
Verifies that the sum of loop_total
equals count
(i.e., the total
number of referenced elements such as corners or control points).
Parameters:
Name | Type | Description | Default |
---|---|---|---|
count
|
int
|
Expected total number of elements referenced by all items. |
required |
halt
|
bool
|
If |
True
|
Returns:
Type | Description |
---|---|
bool
|
|
Raises:
Type | Description |
---|---|
RuntimeError
|
If |
Examples:
ok = fs.check(count=len(corners), halt=False)
if not ok:
# fix topology or sizes, then recompute
fs.update_loop_start()
compute_attribute_on_points ¶
compute_attribute_on_points(attr, points)
Expand spline attributes to control points.
Broadcasts attributes defined per-spline into per-point arrays by repeating each spline’s value over all its control points. This ensures compatibility when working in the control-point domain.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
attr
|
str or ndarray
|
Attribute to expand. If a string, it is looked up in this domain. If an array, it must have length equal to the number of splines. |
required |
points
|
ControlPoint
|
Control-point domain that receives the expanded attributes. The result
has length equal to |
required |
Returns:
Type | Description |
---|---|
ndarray
|
Array of shape |
Raises:
Type | Description |
---|---|
AttributeError
|
If the attribute is not found in this domain. |
ValueError
|
If the provided attribute array shape does not match the number of splines. |
Notes
- Expansion uses the
loop_start
andloop_total
arrays to map splines to their corresponding ranges of control points. - This is the inverse of aggregating per-point attributes back to splines.
Examples:
# Broadcast per-spline weights to all control points
w_points = splines.compute_attribute_on_points("weight", cpoints)
compute_loop_start ¶
compute_loop_start(loop_total=None)
Compute offsets for one or many new items to append.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
loop_total
|
int or array-like of int or None
|
Sizes of the items to add. If |
None
|
Returns:
Type | Description |
---|---|
int or ndarray or None
|
Offsets starting from
[ |
Examples:
# Prepare offsets for three faces of sizes 4, 5, 4
starts = fs.compute_loop_start([4, 5, 4])
fs.append(loop_start=starts, loop_total=[4, 5, 4])
copy_field ¶
copy_field(field_name, new_name, **infos)
Duplicate an existing field under a new name, with optional metadata overrides.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
field_name
|
str
|
The name of the existing field to copy. |
required |
new_name
|
str
|
The name of the new field to create. |
required |
infos
|
keyword arguments
|
Optional metadata (e.g. default, unit, description...) to override or supplement the original field's metadata. |
{}
|
Raises:
Type | Description |
---|---|
KeyError
|
If the source field does not exist. |
ValueError
|
If the target name already exists or is reserved. |
delete ¶
delete(selection)
Delete selected items and maintain consistent offsets.
After deleting items via super().delete(selection)
, recomputes
loop_start
with
[update_loop_start
][npblender.FaceSplineDomain.update_loop_start].
Parameters:
Name | Type | Description | Default |
---|---|---|---|
selection
|
Any
|
Boolean mask, integer index, slice, or array of indices. |
required |
Returns:
Type | Description |
---|---|
None
|
|
See Also
[update_loop_start
][npblender.FaceSplineDomain.update_loop_start]
delete_splines ¶
delete_splines(selection, cpoints)
Delete splines and their associated control points.
Removes the splines selected in this domain, and deletes the corresponding control points from the given control-point domain. Corner indices are retrieved first to ensure consistent cleanup.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
selection
|
array-like of bool or int
|
Indices or boolean mask selecting which splines to delete. |
required |
cpoints
|
ControlPoint
|
Control-point domain from which the corresponding points are removed. |
required |
Returns:
Type | Description |
---|---|
None
|
|
Raises:
Type | Description |
---|---|
IndexError
|
If any index in |
ValueError
|
If |
Notes
- This operation modifies both the spline domain and the control-point domain in place.
- Deletion preserves consistency between splines and their control points.
Examples:
# Delete the first spline and its control points
splines.delete_splines([0], cpoints)
dump ¶
dump(title='Dump', attributes=None, target='SCREEN')
Pretty-print or export domain content.
Formats attribute values and prints to screen or builds a tabular dump suitable for spreadsheets.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
title
|
str
|
Title displayed in the report. |
'Dump'
|
attributes
|
Sequence[str] or None
|
Subset of attribute names to include. If |
None
|
target
|
(SCREEN, ...)
|
Output target. |
'SCREEN'
|
Returns:
Type | Description |
---|---|
None
|
|
Examples:
Domain(points).dump(title="Vertices")
Note: Formatting adapts to the chosen
target
.
extend ¶
extend(other, join_fields=True)
Append multiple records from another array or FieldArray.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
other
|
FieldArray or structured np.ndarray
|
The array of records to append. Must have named fields matching a subset of the current array's fields. |
required |
filtered ¶
filtered(selector, *, copy=False)
Return a FieldArray containing only the selected records.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
selector
|
array‑like, slice or int
|
Any valid NumPy 1‑D index: boolean mask, integer index/array, or slice.
It is applied to the current valid part of the buffer
( |
required |
copy
|
bool
|
|
False
|
Returns:
Type | Description |
---|---|
FieldArray
|
A new instance holding exactly |
from_bl_attributes ¶
from_bl_attributes(bl_attributes)
Import attributes from a Blender attribute collection.
Reads geometry attributes from a Blender data-block and creates/updates the corresponding domain attributes, resizing the domain if needed.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
bl_attributes
|
Mapping[str, Any]
|
Blender attributes collection (name → attribute descriptor) providing
at least |
required |
Returns:
Type | Description |
---|---|
None
|
|
> ***Note:*** Only external (non-internal) Blender attributes matching this
|
|
domain are imported. Missing attributes are created with `transfer=True`.
|
|
from_dict
classmethod
¶
from_dict(data)
Build a FieldArray from a dictionary with field data and optional metadata.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data
|
dict[str, array - like or (array, dict)]
|
Mapping field names to arrays or (array, infos). Infos must include NAME. |
required |
copy
|
bool
|
Whether to copy the data. Default: True. |
required |
Returns:
Type | Description |
---|---|
FieldArray
|
|
get ¶
get(name, default=None, broadcast_shape=None)
Get attribute by name.
If name is not an actual field, return default value. Name can be an array.
pos = field_array.get("position", (0, 0, 1))
pos = field_array.get([[0, 0, 1], [0, 0, 0]])
get_corner_indices ¶
get_corner_indices()
Return the contiguous range of corner/control-point indices.
For each item, expands its [loop_start, loop_start + loop_total)
range
and concatenates the result for all items.
Returns:
Type | Description |
---|---|
ndarray of shape ``(sum(loop_total),)``
|
Absolute indices into the corner/control-point array. |
Notes
A fast Numba kernel is used for vectorized cases; the scalar case is handled directly.
join_attributes ¶
join_attributes(other)
Merge trans-domain attributes from another domain.
Copies or aligns attributes from other
into the current domain, excluding
any attributes not flagged as trans-domain in other
.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
other
|
Domain or None
|
Source domain. If |
required |
Returns:
Type | Description |
---|---|
Domain
|
The domain itself (for chaining). |
join_fields ¶
join_fields(other, exclude=[])
Add all missing fields from another FieldArray.
For every field in other
that is not present in self
, a new field is created
with the same dtype and shape, and initialized with its default value across all existing records.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
other
|
FieldArray
|
Another FieldArray instance whose fields will be checked for missing fields. |
required |
Returns:
Type | Description |
---|---|
self
|
|
load_bl_attributes ¶
load_bl_attributes(data)
Load spline attributes from a Blender object.
Reads attributes stored in a Blender data block and transfers those that belong to the spline domain into this domain. New attributes are created if they do not already exist.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data
|
ID or similar
|
Blender object or data block exposing an |
required |
Returns:
Type | Description |
---|---|
None
|
|
Raises:
Type | Description |
---|---|
Exception
|
If reading or assignment of an attribute fails. |
AssertionError
|
If Blender provides inconsistent attribute sizes. |
Notes
- Only attributes with a matching domain and not marked as internal are imported.
- If an attribute does not exist yet, it is created with the appropriate data type and marked as transferable.
- The domain is resized once to match the size of Blender attributes.
Examples:
import bpy
from npblender import Spline
curve = bpy.data.curves["MyCurve"]
splines = Spline()
splines.load_bl_attributes(curve)
make_buckets ¶
make_buckets(attr)
Group items into buckets by attribute value.
When a domain is to be considered as a collection of packets of various sizes, buckets mechanism groups pakets by size, allowing further operation with numpy vectorization.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
attr
|
array - like or str
|
Either an integer of shape |
required |
Returns:
Type | Description |
---|---|
list[ndarray(count, n)]
|
A list of int arrays (count, n): count is the number of buckets of length n. |
Examples:
buckets = mesh.make_buckets('material')
for bucket in buckets:
print(bucket.shape)
Note: The bucket attribute can be read with
attr[bucket[:, 0]]
.
multiply ¶
multiply(count)
Duplicate the current records count
times.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
count
|
int
|
Number of times to repeat the current records. |
required |
Notes
This duplicates the current valid records (up to self._length). If the array is empty or count <= 1, nothing happens.
Example:
If the array has 3 records and count == 4, the result will be:
[rec0, rec1, rec2, rec0, rec1, rec2, rec0, rec1, rec2, rec0, rec1, rec2]
new_attribute ¶
new_attribute(name, data_type, default, optional=False, transfer=True, transdom=True)
Register a new attribute in the domain schema.
Creates (or ensures) an attribute with a given name, logical data type, default value, and flags controlling Blender transfer and cross-domain propagation.
Note:
data_type
argument is a Blender data type not a python data type. The data type name is compatible with Blender internal storage.FLOAT
data type is implemented asnp.float32
and 'INT' asnp.int32
.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
Attribute name (Python identifier recommended). |
required |
data_type
|
(FLOAT, INT, BOOL, VECTOR, VECTOR2, COLOR, QUATERNION, MATRIX, STRING, ...)
|
Logical data type used by the domain. |
'FLOAT'
|
default
|
Any
|
Default value for newly allocated elements. |
required |
optional
|
bool
|
If |
False
|
transfer
|
bool
|
If |
True
|
transdom
|
bool
|
If |
True
|
See Also
new_float
, new_vector
, new_int
, new_bool
, new_color
, new_vector2
,
new_quaternion
, new_matrix
new_bool ¶
new_bool(name, default=False, optional=False, transfer=True, transdom=True)
Create or ensure a boolean attribute.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
Attribute name. |
required |
default
|
bool
|
Default value. |
False
|
optional
|
bool
|
|
False
|
transfer
|
bool
|
|
True
|
transdom
|
bool
|
|
True
|
new_color ¶
new_color(name, default=(0.5, 0.5, 0.5, 1.0), optional=False, transfer=True, transdom=True)
Create or ensure a color attribute.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
Attribute name. |
required |
default
|
array-like of shape (3,) or (4,)
|
Default color as RGB or RGBA. |
(0.5, 0.5, 0.5, 1.0)
|
optional
|
bool
|
|
False
|
transfer
|
bool
|
|
True
|
transdom
|
bool
|
|
True
|
new_field ¶
new_field(name, dtype, shape=None, default=0, optional=False, **infos)
Add a field to the structured array.
Arguments
- name (str) : field name
- dtype (type) : a valid numpy dtype
- shape (tuple = None) : the shape of the field
- default (any = 0) : default value
- optional (bool = False) : the field is created only when accessed
- infos (dict) : field infos
new_float ¶
new_float(name, default=0.0, optional=False, transfer=True, transdom=True)
Create or ensure a scalar float attribute.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
Attribute name. |
required |
default
|
float
|
Default value. |
0.0
|
optional
|
bool
|
|
False
|
transfer
|
bool
|
|
True
|
transdom
|
bool
|
|
True
|
new_int ¶
new_int(name, default=0, optional=False, transfer=True, transdom=True)
Create or ensure an integer attribute.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
Attribute name. |
required |
default
|
int
|
Default value. |
0
|
optional
|
bool
|
|
False
|
transfer
|
bool
|
|
True
|
transdom
|
bool
|
|
True
|
new_matrix ¶
new_matrix(name, default=np.eye(4), optional=False, transfer=True, transdom=True)
Create or ensure a matrix attribute.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
Attribute name. |
required |
default
|
array - like
|
Default matrix. By convention this is a square matrix per element
(e.g., |
np.eye(4)
|
optional
|
bool
|
|
False
|
transfer
|
bool
|
|
True
|
transdom
|
bool
|
|
True
|
order
|
|
required |
new_quaternion ¶
new_quaternion(name, default=(0.0, 0.0, 0.0, 1.0), optional=False, transfer=True, transdom=True)
Create or ensure a quaternion attribute.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
Attribute name. |
required |
default
|
array-like of shape (4,)
|
Default quaternion in |
(0.0, 0.0, 0.0, 1.0)
|
optional
|
bool
|
|
False
|
transfer
|
bool
|
|
True
|
transdom
|
bool
|
|
True
|
new_vector ¶
new_vector(name, default=(0.0, 0.0, 0.0), optional=False, transfer=True, transdom=True)
Create or ensure a 3D vector attribute.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
Attribute name. |
required |
default
|
array-like of shape (3,)
|
Default XYZ vector. |
(0.0, 0.0, 0.0)
|
optional
|
bool
|
|
False
|
transfer
|
bool
|
|
True
|
transdom
|
bool
|
|
True
|
new_vector2 ¶
new_vector2(name, default=(0.0, 0.0), optional=False, transfer=True, transdom=True)
Create or ensure a 2D vector attribute.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
Attribute name. |
required |
default
|
array-like of shape (2,)
|
Default XY vector. |
(0.0, 0.0)
|
optional
|
bool
|
|
False
|
transfer
|
bool
|
|
True
|
transdom
|
bool
|
|
True
|
per_size ¶
per_size()
Group items by their loop_total
(polygon/control-point count).
Returns a dictionary keyed by size (3
, 4
, …) where each entry
contains:
- 'start'
: array of loop_start
values for items of that size.
- 'indices'
: array mapping entry order back to item indices.
Returns:
Type | Description |
---|---|
dict[int, dict[str, ndarray]]
|
Grouped start offsets and reverse indices for each size present. |
Notes
Uses a Numba kernel to bucketize items efficiently.
to_bl_attributes ¶
to_bl_attributes(attributes, update=False)
Export attributes to a Blender attribute collection.
Writes eligible domain attributes to a Blender data-block, creating missing attributes and adjusting sizes as needed.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
attributes
|
Any
|
Blender attributes collection receiving the values. |
required |
update
|
bool
|
If |
False
|
Returns:
Type | Description |
---|---|
None
|
|
> ***Caution:*** Only attributes with `transfer=True` are exported. Optional
|
|
attributes are skipped.
|
|
> ***Caution:*** Curve domains user attributes are not saved.
|
|
to_dict ¶
to_dict(*, copy=True, with_infos=True)
Convert the array to a dictionary of fields or (field, infos) pairs.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
copy
|
bool
|
Whether to copy the arrays. |
True
|
with_infos
|
bool
|
If True, return (array, infos) for each field. |
True
|
Returns:
Type | Description |
---|---|
dict[str, array or (array, dict)]
|
|
to_object ¶
to_object(data, update=False)
Transfer spline attributes to a Blender object.
Writes this domain’s Blender attributes into the target Blender object or data block.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data
|
ID or similar
|
Blender object or data block exposing an |
required |
update
|
bool
|
If |
False
|
Returns:
Type | Description |
---|---|
None
|
|
Raises:
Type | Description |
---|---|
Exception
|
If attribute creation or assignment fails. |
Notes
- Only attributes flagged with
transfer=True
are exported. - String attributes are currently skipped.
Examples:
import bpy
from npblender import Spline
curve = bpy.data.curves["MyCurve"]
splines = Spline()
splines.to_object(curve, update=False)
Caution: Blender does not save user-defined attributes inside curve objects. Attributes written here may be lost when saving and reopening the file.
transfer_attributes ¶
transfer_attributes(other, shape=None, other_shape=None)
Transfer values of trans-domain attributes from another domain.
Copies values for each trans-domain attribute present in other
into the
corresponding attributes of self
, with optional reshaping for batched
assignments.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
other
|
Domain
|
Source domain providing attribute values. |
required |
shape
|
tuple of int or None
|
Target reshape for |
None
|
other_shape
|
tuple of int or None
|
Source reshape for |
None
|
Returns:
Type | Description |
---|---|
Domain
|
The domain itself (for chaining). |
> ***Note:*** Each attribute is reshaped as `shape + item_shape` on `self`
|
|
and `other_shape + item_shape` on `other` prior to assignment.
|
|
update_loop_start ¶
update_loop_start()
Recompute loop_start
from loop_total
(cumulative layout).
Sets loop_start
to a left-rolled cumulative sum of loop_total
,
so item i starts right after the end of item i-1.
Returns:
Type | Description |
---|---|
FaceSplineDomain
|
Self (for chaining). |
Notes
Call this after deletions / resizes to keep indices consistent.
See Also
[compute_loop_start
][npblender.FaceSplineDomain.compute_loop_start] :
Compute offsets for new items to be appended.