evaluate method

Object evaluate(
  1. Duration t
)

The hold rule: before the first key its value, after the last the last, and between neighbours a lerp shaped by the ARRIVING key's curve. Pure in t — backwards seek needs no history.

Implementation

Object evaluate(Duration t) {
  // Blocks: the leading clip's time at this moment, as seconds — the
  // whole answer is [blendAt]; this is the one number a track reads as.
  if (clips.isNotEmpty) return blendAt(t).time;
  if (keys.isEmpty) {
    throw StateError(
      'an empty track has no value — it contributes '
      'nothing and should not be evaluated',
    );
  }
  if (t <= keys.first.at) return keys.first.value;
  if (t >= keys.last.at) return keys.last.value;
  for (var i = 1; i < keys.length; i++) {
    if (t <= keys[i].at) {
      var a = keys[i - 1], b = keys[i];
      var u = (t - a.at).inMicroseconds / (b.at - a.at).inMicroseconds;
      var shaped = (b.curve ?? SceneCurves.linear).transform(u);
      return switch (kind) {
        TrackKind.number =>
          (a.value as double) +
              ((b.value as double) - (a.value as double)) * shaped,
        TrackKind.color => SceneColor.lerp(
          a.value as SceneColor,
          b.value as SceneColor,
          shaped,
        ),
      };
    }
  }
  return keys.last.value;
}