Curve
A cubic Y-from-X function with tangents and a sampling cache.
Curve stores (X, Y) points and tangent slopes dy/dx. Sample evaluates the original curve; SampleBaked uses a uniform cache with linear interpolation. This is not a Curve2D/Curve3D path. Sampling coordinates use domain units; the default domain is 0…1.
Use Linear for a straight transition: default zero Free tangents produce a smooth cubic curve. Complete example:
using Reckfell;
public static class UnitRamp
{
public static Curve Create()
{
var curve = new Curve { BakeResolution = 128 };
curve.AddPoint(Vector2.Zero,
leftMode: Curve.TangentMode.Linear, rightMode: Curve.TangentMode.Linear);
curve.AddPoint(Vector2.One,
leftMode: Curve.TangentMode.Linear, rightMode: Curve.TangentMode.Linear);
return curve;
}
}AddPoint clamps the position to bounds, SetPointValue does not clamp Y, and SetPointOffset re-clamps both coordinates and returns a new index. Do not treat indices as permanent identifiers. Value bounds do not clamp cubic overshoot.
BakeResolution changes cache accuracy but does not emit Changed. Call EmitChanged() after editing it if a connected CurveTexture must refresh. Resolution 1 produces a constant cache equal to the last Y.
Known current-version defect: CleanDupes also removes points with distinct X values. Do not call it on working data. This checked helper preserves distinct positions and removes the right point only when adjacent X values are exactly equal; it neither merges nearby values nor fixes the native method:
using System;
using Reckfell;
public static class CurveTools
{
// Removes the right-hand point only when adjacent X values are exactly equal.
public static int RemoveExactDuplicateOffsets(Curve curve)
{
ArgumentNullException.ThrowIfNull(curve);
int removed = 0;
for (int i = curve.GetPointCount() - 1; i > 0; i--)
{
if (curve.GetPointPosition(i).X == curve.GetPointPosition(i - 1).X)
{
curve.RemovePoint(i);
removed++;
}
}
return removed;
}
}Declarations checked against C# SDK 1.0.0. Expand a name to see declarations and documentation.
Constructors1
CurveConstructor
public Curve();Creates an empty curve with domain and value range 0…1 and BakeResolution=100.
Properties8
BakeResolutionProperty
public int BakeResolution { get; set; }Baked cache sample count, 1…1000, initially 100. Use at least 2 for a varying value. The setter invalidates the cache but does not emit Changed: call EmitChanged() to refresh a connected CurveTexture after this edit.
MaxDomainProperty
public float MaxDomain { get; set; }Upper X bound, initially 1. The setter preserves the last point and at least a 0.01 gap to MinDomain; it does not scale points. Invalidates the cache and emits Changed and DomainChanged.
MaxValueProperty
public float MaxValue { get; set; }Upper bound for newly added Y values, initially 1. The setter preserves existing point maxima and at least a 0.01 gap to MinValue. Tangents can produce samples above this bound; emits RangeChanged without Changed.
MinDomainProperty
public float MinDomain { get; set; }Lower X bound, initially 0. The setter preserves the first point and at least a 0.01 gap to MaxDomain; it does not move points. Invalidates the cache and emits Changed and DomainChanged.
MinValueProperty
public float MinValue { get; set; }Lower bound for newly added Y values, initially 0. The setter preserves existing point minima and at least a 0.01 gap to MaxValue. It does not clamp cubic interpolation output; emits RangeChanged without Changed.
PointCountProperty
public int PointCount { get; set; }Point count, initially 0. Shrinking discards trailing points. Growing does not space X evenly: new X values are domain-clamped zero for an empty curve, otherwise MaxDomain. Use AddPoint for deliberate point placement.
_DataProperty
public Reckfell.Collections.Array _Data { get; set; }Internal serialization property: five elements per point — Vector2, left/right tangents and left/right modes. The getter returns an independent container. The setter neither sorts nor clamps positions; use point methods in application code rather than editing storage format.
_LimitsProperty
public Reckfell.Collections.Array _Limits { get; set; }Internal serialization property: [MinValue, MaxValue, MinDomain, MaxDomain]. The getter returns an independent container. Its loading setter bypasses public constraints and notifications; change bounds through public properties.
Methods32
AddPointint
public int AddPoint(Vector2 position, float leftTangent = 0f, float rightTangent = 0f, Curve.TangentMode leftMode = Curve.TangentMode.Free, Curve.TangentMode rightMode = Curve.TangentMode.Free);Clamps X to the domain and Y to the value range, then inserts in X order. Returns the current index. Default zero Free tangents produce a smooth cubic transition rather than a straight line; set both sides to Linear for a straight segment.
| Name | Type | Default |
|---|---|---|
position | Vector2 | — |
leftTangent | float | 0f |
rightTangent | float | 0f |
leftMode | Curve.TangentMode | Curve.TangentMode.Free |
rightMode | Curve.TangentMode | Curve.TangentMode.Free |
positionFinite X and Y; AddPoint clamps them to current bounds.
leftTangentLeft tangent slope dy/dx; defaults to 0.
rightTangentRight tangent slope dy/dx; defaults to 0.
leftModeFree or Linear for the left side.
rightModeFree or Linear for the right side.
intThe point’s new insertion index; other indices can change.
Bakevoid
public void Bake();Rebuilds the uniform cache over the current domain using BakeResolution. SampleBaked also rebuilds a dirty cache on demand; Sample uses the original curve.
CleanDupesvoid
public void CleanDupes();Do not use in the current version: a check with three distinct X values retained only one point. The native comparison also removes distinct adjacent positions. The engine defect is not fixed; RemoveExactDuplicateOffsets in the class example removes only exactly equal X values.
ClearPointsvoid
public void ClearPoints();Removes all points. Sample and SampleBaked return 0 after clearing.
GetBakeResolutionint
public int GetBakeResolution();Baked cache sample count, 1…1000, initially 100. Use at least 2 for a varying value. The setter invalidates the cache but does not emit Changed: call EmitChanged() to refresh a connected CurveTexture after this edit.
intBaked cache sample count, 1…1000, initially 100. Use at least 2 for a varying value. The setter invalidates the cache but does not emit Changed: call EmitChanged() to refresh a connected CurveTexture after this edit.
GetDomainRangefloat
public float GetDomainRange();Returns MaxDomain − MinDomain in X-coordinate units.
floatReturns MaxDomain − MinDomain in X-coordinate units.
GetMaxDomainfloat
public float GetMaxDomain();Upper X bound, initially 1. The setter preserves the last point and at least a 0.01 gap to MinDomain; it does not scale points. Invalidates the cache and emits Changed and DomainChanged.
floatUpper X bound, initially 1. The setter preserves the last point and at least a 0.01 gap to MinDomain; it does not scale points. Invalidates the cache and emits Changed and DomainChanged.
GetMaxValuefloat
public float GetMaxValue();Upper bound for newly added Y values, initially 1. The setter preserves existing point maxima and at least a 0.01 gap to MinValue. Tangents can produce samples above this bound; emits RangeChanged without Changed.
floatUpper bound for newly added Y values, initially 1. The setter preserves existing point maxima and at least a 0.01 gap to MinValue. Tangents can produce samples above this bound; emits RangeChanged without Changed.
GetMinDomainfloat
public float GetMinDomain();Lower X bound, initially 0. The setter preserves the first point and at least a 0.01 gap to MaxDomain; it does not move points. Invalidates the cache and emits Changed and DomainChanged.
floatLower X bound, initially 0. The setter preserves the first point and at least a 0.01 gap to MaxDomain; it does not move points. Invalidates the cache and emits Changed and DomainChanged.
GetMinValuefloat
public float GetMinValue();Lower bound for newly added Y values, initially 0. The setter preserves existing point minima and at least a 0.01 gap to MaxValue. It does not clamp cubic interpolation output; emits RangeChanged without Changed.
floatLower bound for newly added Y values, initially 0. The setter preserves existing point minima and at least a 0.01 gap to MaxValue. It does not clamp cubic interpolation output; emits RangeChanged without Changed.
GetPointCountint
public int GetPointCount();Point count, initially 0. Shrinking discards trailing points. Growing does not space X evenly: new X values are domain-clamped zero for an empty curve, otherwise MaxDomain. Use AddPoint for deliberate point placement.
intPoint count, initially 0. Shrinking discards trailing points. Growing does not space X evenly: new X values are domain-clamped zero for an empty curve, otherwise MaxDomain. Use AddPoint for deliberate point placement.
GetPointLeftModeCurve.TangentMode
public Curve.TangentMode GetPointLeftMode(int index);Returns an existing point’s tangent mode: Free or Linear.
| Name | Type | Default |
|---|---|---|
index | int | — |
indexAn existing point index: 0 ≤ index < PointCount.
Curve.TangentModeReturns an existing point’s tangent mode: Free or Linear.
GetPointLeftTangentfloat
public float GetPointLeftTangent(int index);Returns an existing point’s tangent slope dy/dx, not an angle in degrees.
| Name | Type | Default |
|---|---|---|
index | int | — |
indexAn existing point index: 0 ≤ index < PointCount.
floatReturns an existing point’s tangent slope dy/dx, not an angle in degrees.
GetPointPositionVector2
public Vector2 GetPointPosition(int index);Returns an existing point’s (X, Y). Insertion, removal and SetPointOffset can change indices.
| Name | Type | Default |
|---|---|---|
index | int | — |
indexAn existing point index: 0 ≤ index < PointCount.
Vector2Returns an existing point’s (X, Y). Insertion, removal and SetPointOffset can change indices.
GetPointRightModeCurve.TangentMode
public Curve.TangentMode GetPointRightMode(int index);Returns an existing point’s tangent mode: Free or Linear.
| Name | Type | Default |
|---|---|---|
index | int | — |
indexAn existing point index: 0 ≤ index < PointCount.
Curve.TangentModeReturns an existing point’s tangent mode: Free or Linear.
GetPointRightTangentfloat
public float GetPointRightTangent(int index);Returns an existing point’s tangent slope dy/dx, not an angle in degrees.
| Name | Type | Default |
|---|---|---|
index | int | — |
indexAn existing point index: 0 ≤ index < PointCount.
floatReturns an existing point’s tangent slope dy/dx, not an angle in degrees.
GetValueRangefloat
public float GetValueRange();Returns MaxValue − MinValue; this is not the actual interpolated curve amplitude.
floatReturns MaxValue − MinValue; this is not the actual interpolated curve amplitude.
RemovePointvoid
public void RemovePoint(int index);Removes an existing point by index and updates neighboring automatic tangents. Removing the last point is allowed.
| Name | Type | Default |
|---|---|---|
index | int | — |
indexAn existing point index: 0 ≤ index < PointCount.
Samplefloat
public float Sample(float offset);Evaluates the cubic curve at a finite domain coordinate, not necessarily 0…1. Before/after the endpoints it returns the endpoint Y; an empty curve returns 0 and a single point its constant Y. Tangents can exceed MinValue/MaxValue.
| Name | Type | Default |
|---|---|---|
offset | float | — |
offsetA finite X coordinate in domain units.
floatEvaluates the cubic curve at a finite domain coordinate, not necessarily 0…1. Before/after the endpoints it returns the endpoint Y; an empty curve returns 0 and a single point its constant Y. Tangents can exceed MinValue/MaxValue.
SampleBakedfloat
public float SampleBaked(float offset);Bakes a dirty cache on demand and linearly interpolates cached samples in domain coordinates. This approximates Sample. With BakeResolution=1 the entire cache equals the last Y; use at least 2 for a varying curve.
| Name | Type | Default |
|---|---|---|
offset | float | — |
offsetA finite X coordinate in domain units.
floatBakes a dirty cache on demand and linearly interpolates cached samples in domain coordinates. This approximates Sample. With BakeResolution=1 the entire cache equals the last Y; use at least 2 for a varying curve.
SetBakeResolutionvoid
public void SetBakeResolution(int resolution);Baked cache sample count, 1…1000, initially 100. Use at least 2 for a varying value. The setter invalidates the cache but does not emit Changed: call EmitChanged() to refresh a connected CurveTexture after this edit.
| Name | Type | Default |
|---|---|---|
resolution | int | — |
resolutionSample count 1…1000; at least 2 for a varying curve.
SetMaxDomainvoid
public void SetMaxDomain(float max);Upper X bound, initially 1. The setter preserves the last point and at least a 0.01 gap to MinDomain; it does not scale points. Invalidates the cache and emits Changed and DomainChanged.
| Name | Type | Default |
|---|---|---|
max | float | — |
maxRequested finite upper bound; the setter preserves existing points and the minimum gap.
SetMaxValuevoid
public void SetMaxValue(float max);Upper bound for newly added Y values, initially 1. The setter preserves existing point maxima and at least a 0.01 gap to MinValue. Tangents can produce samples above this bound; emits RangeChanged without Changed.
| Name | Type | Default |
|---|---|---|
max | float | — |
maxRequested finite upper bound; the setter preserves existing points and the minimum gap.
SetMinDomainvoid
public void SetMinDomain(float min);Lower X bound, initially 0. The setter preserves the first point and at least a 0.01 gap to MaxDomain; it does not move points. Invalidates the cache and emits Changed and DomainChanged.
| Name | Type | Default |
|---|---|---|
min | float | — |
minRequested finite lower bound; the setter preserves existing points and the minimum gap.
SetMinValuevoid
public void SetMinValue(float min);Lower bound for newly added Y values, initially 0. The setter preserves existing point minima and at least a 0.01 gap to MaxValue. It does not clamp cubic interpolation output; emits RangeChanged without Changed.
| Name | Type | Default |
|---|---|---|
min | float | — |
minRequested finite lower bound; the setter preserves existing points and the minimum gap.
SetPointCountvoid
public void SetPointCount(int count);Point count, initially 0. Shrinking discards trailing points. Growing does not space X evenly: new X values are domain-clamped zero for an empty curve, otherwise MaxDomain. Use AddPoint for deliberate point placement.
| Name | Type | Default |
|---|---|---|
count | int | — |
countNew nonnegative point count; growing does not space X evenly.
SetPointLeftModevoid
public void SetPointLeftMode(int index, Curve.TangentMode mode);Changes the left tangent: Free uses the assigned slope, Linear computes a slope from the neighboring point. ModeCount is a sentinel, not a mode.
| Name | Type | Default |
|---|---|---|
index | int | — |
mode | Curve.TangentMode | — |
indexAn existing point index: 0 ≤ index < PointCount.
modeFree or Linear; not ModeCount.
SetPointLeftTangentvoid
public void SetPointLeftTangent(int index, float tangent);Sets the left tangent as dy/dx and switches it to Free. A steep slope can produce Y outside the value range.
| Name | Type | Default |
|---|---|---|
index | int | — |
tangent | float | — |
indexAn existing point index: 0 ≤ index < PointCount.
tangentA finite slope dy/dx, not an angle.
SetPointOffsetint
public int SetPointOffset(int index, float offset);Reinserts a point with a new X, clamps X to the domain and also re-clamps its Y to the value range. Returns the new index; the old index is not a stable identifier.
| Name | Type | Default |
|---|---|---|
index | int | — |
offset | float | — |
indexAn existing point index: 0 ≤ index < PointCount.
offsetA finite X coordinate in domain units.
intThe point’s new insertion index; other indices can change.
SetPointRightModevoid
public void SetPointRightMode(int index, Curve.TangentMode mode);Changes the right tangent: Free uses the assigned slope, Linear computes a slope from the neighboring point. ModeCount is a sentinel, not a mode.
| Name | Type | Default |
|---|---|---|
index | int | — |
mode | Curve.TangentMode | — |
indexAn existing point index: 0 ≤ index < PointCount.
modeFree or Linear; not ModeCount.
SetPointRightTangentvoid
public void SetPointRightTangent(int index, float tangent);Sets the right tangent as dy/dx and switches it to Free. A steep slope can produce Y outside the value range.
| Name | Type | Default |
|---|---|---|
index | int | — |
tangent | float | — |
indexAn existing point index: 0 ≤ index < PointCount.
tangentA finite slope dy/dx, not an angle.
SetPointValuevoid
public void SetPointValue(int index, float y);Replaces an existing point’s Y without clamping to MinValue/MaxValue and updates automatic tangents. Later reinsertion through SetPointOffset clamps Y again.
| Name | Type | Default |
|---|---|---|
index | int | — |
y | float | — |
indexAn existing point index: 0 ≤ index < PointCount.
yA finite Y value; this setter does not clamp it to the value range.
Signals and events2
DomainChangedEvent
public event Action DomainChanged;Notification from domain-bound setters; accompanied by Changed and cache rebuilding on subsequent sampling. It does not mean points were moved.
RangeChangedEvent
public event Action RangeChanged;Notification from value-bound setters. By itself it does not emit Changed or refresh connected textures.
Curve.TangentMode
| Value | Description |
|---|---|
Free = 0 | The tangent on this side of the point is user-defined. |
Linear = 1 | The curve calculates the tangent on this side of the point as the slope halfway towards the adjacent point. |
ModeCount = 2 | The total number of available tangent modes. |