Skip to content

Commit

Permalink
calculation of frame, frame in sequence, based on actual elapsed time
Browse files Browse the repository at this point in the history
  • Loading branch information
4sval committed Feb 13, 2023
1 parent 9b4c839 commit 144cf0e
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 40 deletions.
52 changes: 40 additions & 12 deletions FModel/Views/Snooper/Models/Animations/Animation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ public enum AnimSeparatorType
public class Animation : IDisposable
{
public float ElapsedTime;
public int Frame;
public int FrameInSequence;

public bool IsPaused;
public readonly int TotalFrames;
public readonly float TotalDuration;
public readonly int EndFrame;
public readonly float MaxElapsedTime;

public int CurrentSequence;
public readonly Sequence[] Sequences;
Expand All @@ -29,7 +33,8 @@ public Animation()

IsPaused = false;
TotalFrames = 0;
TotalDuration = 0.0f;
EndFrame = 0;
MaxElapsedTime = 0.0f;
Sequences = Array.Empty<Sequence>();
}

Expand All @@ -41,7 +46,8 @@ public Animation(Skeleton skeleton, CAnimSet anim, bool rotationOnly) : this()
Sequences[i] = new Sequence(anim.Sequences[i], skeleton, rotationOnly);

TotalFrames += Sequences[i].MaxFrame;
TotalDuration += Sequences[i].Duration;
MaxElapsedTime += anim.Sequences[i].NumFrames * Sequences[i].TimePerFrame;
EndFrame += (Sequences[i].Duration / Sequences[i].TimePerFrame).FloorToInt();
}

if (Sequences.Length > 0)
Expand All @@ -51,27 +57,48 @@ public Animation(Skeleton skeleton, CAnimSet anim, bool rotationOnly) : this()
public void Update(float deltaSeconds)
{
if (IsPaused) return;
if (Sequences[CurrentSequence].IsComplete)

ElapsedTime += deltaSeconds;
TimeCalculation();
}

private void TimeCalculation()
{
CurrentSequence = SequencesCount;
for (int i = 0; i < Sequences.Length; i++)
{
Sequences[CurrentSequence].Reset();
CurrentSequence++;
if (ElapsedTime < Sequences[i].EndTime)
{
CurrentSequence = i;
break;
}
}
if (CurrentSequence >= SequencesCount)
Reset();

ElapsedTime += Sequences[CurrentSequence].Update(deltaSeconds);
Frame = Math.Min((ElapsedTime / Sequences[CurrentSequence].TimePerFrame).FloorToInt(), TotalFrames);

var baseFrame = 0;
for (int s = 0; s < CurrentSequence; s++)
{
baseFrame += Sequences[s].MaxFrame;
}
FrameInSequence = Math.Min(Frame - baseFrame, Sequences[CurrentSequence].MaxFrame);
}


public Matrix4x4 InterpolateBoneTransform(int boneIndex)
{
// interpolate here
return Sequences[CurrentSequence].BonesTransform[boneIndex][Sequences[CurrentSequence].Frame].Matrix;
return Sequences[CurrentSequence].BonesTransform[boneIndex][FrameInSequence].Matrix;
}

private void Reset()
{
ElapsedTime = 0.0f;
Frame = 0;
FrameInSequence = 0;

CurrentSequence = 0;
}

Expand All @@ -92,7 +119,8 @@ public void ImGuiTimeline(ImFontPtr fontPtr)
if (IsPaused && ImGui.IsMouseDragging(ImGuiMouseButton.Left))
{
var mousePosCanvas = io.MousePos - canvasP0;
ElapsedTime = Math.Clamp(mousePosCanvas.X / canvasSize.X * TotalDuration, 0, TotalDuration);
ElapsedTime = Math.Clamp(mousePosCanvas.X / canvasSize.X * MaxElapsedTime, 0, MaxElapsedTime);
TimeCalculation();
}

drawList.AddRectFilled(canvasP0, canvasP1 with { Y = canvasP0.Y + _timeBarHeight }, 0xFF181818);
Expand All @@ -108,11 +136,11 @@ public void ImGuiTimeline(ImFontPtr fontPtr)

for (int i = 0; i < Sequences.Length; i++)
{
Sequences[i].DrawSequence(drawList, canvasP0, ratio, i);
Sequences[i].DrawSequence(drawList, canvasP0.X, canvasP0.Y + _timeBarHeight, ratio, i);
}

DrawSeparator(drawList, canvasP0, canvasP1, ElapsedTime * ratio.X, AnimSeparatorType.InBetween);
DrawSeparator(drawList, canvasP0, canvasP1, TotalDuration * ratio.X, AnimSeparatorType.End);
DrawSeparator(drawList, canvasP0, canvasP1, Frame * ratio.X, AnimSeparatorType.InBetween);
DrawSeparator(drawList, canvasP0, canvasP1, EndFrame * ratio.X, AnimSeparatorType.End);

// ImGui.Text($"{Sequences[CurrentSequence].Name} > {(CurrentSequence < SequencesCount - 1 ? Sequences[CurrentSequence + 1].Name : Sequences[0].Name)}");
// ImGui.Text($"Frame: {Sequences[CurrentSequence].Frame}/{Sequences[CurrentSequence].MaxFrame}");
Expand Down
40 changes: 12 additions & 28 deletions FModel/Views/Snooper/Models/Animations/Sequence.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
using System;
using System.Numerics;
using CUE4Parse_Conversion.Animations;
using CUE4Parse.Utils;
using ImGuiNET;

namespace FModel.Views.Snooper.Models.Animations;

public class Sequence : IDisposable
{
public int Frame;
public float ElapsedTime;
public readonly string Name;
public readonly int MaxFrame;
public readonly float TimePerFrame;
Expand All @@ -18,23 +15,24 @@ public class Sequence : IDisposable
public readonly float EndTime;
public readonly int LoopingCount;

public readonly Transform[][] BonesTransform;
private readonly float _start;
private readonly float _end;

public bool IsComplete => ElapsedTime > Duration;
// public bool IsComplete => Frame >= MaxFrame;
public readonly Transform[][] BonesTransform;

public Sequence(CAnimSequence sequence, Skeleton skeleton, bool rotationOnly)
{
Reset();

Name = sequence.Name;
MaxFrame = sequence.NumFrames - 1;
TimePerFrame = 1.0f / sequence.Rate;
StartTime = sequence.StartPos / TimePerFrame;
Duration = sequence.AnimEndTime / TimePerFrame;
StartTime = sequence.StartPos;
Duration = sequence.AnimEndTime;
EndTime = StartTime + Duration;
LoopingCount = sequence.LoopingCount;

_start = StartTime / TimePerFrame;
_end = EndTime / TimePerFrame;

BonesTransform = new Transform[skeleton.BonesTransformByIndex.Count][];
for (int trackIndex = 0; trackIndex < skeleton.UnrealSkeleton.ReferenceSkeleton.FinalRefBoneInfo.Length; trackIndex++)
{
Expand Down Expand Up @@ -83,27 +81,13 @@ public Sequence(CAnimSequence sequence, Skeleton skeleton, bool rotationOnly)
}
}

public float Update(float deltaSeconds)
{
var delta = deltaSeconds / TimePerFrame;
ElapsedTime += delta;
Frame = Math.Min(ElapsedTime.FloorToInt(), MaxFrame);
return delta;
}

public void Reset()
{
ElapsedTime = 0.0f;
Frame = 0;
}


private readonly float _height = 20.0f;
public void DrawSequence(ImDrawListPtr drawList, Vector2 origin, Vector2 ratio, int index)
public void DrawSequence(ImDrawListPtr drawList, float x, float y, Vector2 ratio, int index)
{
var height = _height * (index % 2) + _height;
var p1 = new Vector2(origin.X + StartTime * ratio.X, origin.Y + height);
var p2 = new Vector2(origin.X + EndTime * ratio.X, origin.Y + height + _height);
var height = _height * (index % 2);
var p1 = new Vector2(x + _start * ratio.X, y + height);
var p2 = new Vector2(x + _end * ratio.X, y + height + _height);
drawList.AddRectFilled(p1, p2, 0xFF175F17);
drawList.AddText(p1 with { X = p1.X + 2.5f }, 0xFF000000, Name);
}
Expand Down

0 comments on commit 144cf0e

Please sign in to comment.