Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public struct AuthoredMovementData
public int frameCount; // frames for this slot's transform
public float frameRate; // samples per second
public int loop; // 0 = one-shot, 1 = loop
public float sequenceSpeed; // playback rate multiplier (negative reverses)

// Captured rest pose (local space); motion composes as a delta from this.
public quaternion restRotation;
Expand Down Expand Up @@ -145,8 +146,18 @@ public void Execute(int index, TransformAccess transform)
if (m.frameCount <= 0) break;
float fr = m.frameRate > 1e-4f ? m.frameRate : 30f;
float length = m.frameCount / fr;
float pt = m.loop != 0 ? math.fmod(t, length) : math.min(math.max(t, 0f), length);
if (pt < 0f) pt += length; // fmod can return negative for negative t
float st = t * m.sequenceSpeed;
float pt;
if (m.loop != 0)
{
pt = math.fmod(st, length);
if (pt < 0f) pt += length; // fmod can return negative for negative t
}
else
{
// Reverse one-shot walks the playhead down from the end; forward holds at 0..length.
pt = math.clamp(m.sequenceSpeed < 0f ? length + st : st, 0f, length);
}

float frameF = pt * fr;
int f0 = (int)math.floor(frameF);
Expand Down Expand Up @@ -501,6 +512,7 @@ static Registration Build(BasisAuthoredMotion component)
d.frameCount = fc;
d.frameRate = clip.frameRate;
d.loop = mv.loop ? 1 : 0;
d.sequenceSpeed = mv.sequenceSpeed;
AddSlot(data, targets, movementEnabled, d, tf, mv.enabled);
}
break;
Expand Down
2 changes: 2 additions & 0 deletions Basis/Packages/com.basis.sdk/Localization/Languages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@
{ "key": "sdk.authoredMotion.field.keyframes.tooltip", "value": "Inline pose-delta timeline for short motion. Ignored when a Baked Clip is assigned." },
{ "key": "sdk.authoredMotion.field.loop.label", "value": "Loop" },
{ "key": "sdk.authoredMotion.field.loop.tooltip", "value": "Loop the sequence, or play it once." },
{ "key": "sdk.authoredMotion.field.sequenceSpeed.label", "value": "Speed" },
{ "key": "sdk.authoredMotion.field.sequenceSpeed.tooltip", "value": "Playback rate multiplier for the baked clip. 1 plays at authored speed, 2 plays twice as fast, 0.5 half speed; negative values play in reverse." },

{ "key": "sdk.buildReport.window.title", "value": "Basis Build Report Viewer" },
{ "key": "sdk.buildReport.window.tabTitle", "value": "Basis Bundle Report" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public enum Waveform { Sine, Triangle, Square, Pulse }
public Keyframe[] keyframes = Array.Empty<Keyframe>();
public BasisMotionClip bakedClip; // shared baked curves; null when using inline keyframes
public bool loop = true;
public float sequenceSpeed = 1f; // playback rate multiplier (1 = authored speed); negative plays in reverse

// Noise — simplex drift on `channel` about `axis`; reuses amplitude / chain / chainFalloff / seed; `noiseSpeed` = sample rate.
public float noiseSpeed = 0.5f;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ private void DrawMovementCard(SerializedProperty movements, int i,
Field(mv, "bakedClip", "bakedClip");
Field(mv, "sequenceRoot", "sequenceRoot");
Field(mv, "loop", "loop");
Field(mv, "sequenceSpeed", "sequenceSpeed");
break;
}

Expand Down
Loading