animate loaded model

This commit is contained in:
4sval 2023-02-21 18:06:37 +01:00
parent d78df4a953
commit 591a2d2336
3 changed files with 45 additions and 17 deletions

View File

@ -12,6 +12,7 @@ namespace FModel.Views.Snooper.Animations;
public class Animation : IDisposable
{
public readonly UObject Export;
public readonly CAnimSet AnimSet;
public readonly string Path;
public readonly string Name;
public readonly Sequence[] Sequences;
@ -23,6 +24,8 @@ public class Animation : IDisposable
public int CurrentSequence;
public int FrameInSequence; // Current Sequence's Frame to Display
public string Label =>
$"Retarget: {TargetSkeleton}\nSequences: {CurrentSequence + 1}/{Sequences.Length}\nFrames: {FrameInSequence}/{Sequences[CurrentSequence].EndFrame}";
public bool IsActive;
public bool IsSelected;
@ -39,15 +42,16 @@ public class Animation : IDisposable
public Animation(UObject export, CAnimSet animSet) : this(export)
{
TargetSkeleton = animSet.OriginalAnim.Name;
AnimSet = animSet;
TargetSkeleton = AnimSet.OriginalAnim.Name;
Sequences = new Sequence[animSet.Sequences.Count];
Sequences = new Sequence[AnimSet.Sequences.Count];
for (int i = 0; i < Sequences.Length; i++)
{
Sequences[i] = new Sequence(animSet.Sequences[i]);
Sequences[i] = new Sequence(AnimSet.Sequences[i]);
EndTime = Sequences[i].EndTime;
TotalElapsedTime += animSet.Sequences[i].NumFrames * Sequences[i].TimePerFrame;
TotalElapsedTime += AnimSet.Sequences[i].NumFrames * Sequences[i].TimePerFrame;
}
if (Sequences.Length > 0)
@ -95,7 +99,7 @@ public class Animation : IDisposable
var p2 = new Vector2(timelineP0.X + EndTime * timeRatio.X - t, y + timeStep.Y - t);
ImGui.SetCursorScreenPos(p1);
ImGui.InvisibleButton($"timeline_sequencetracker_{Name}", new Vector2(EndTime * timeRatio.X - t, timeStep.Y - t), ImGuiButtonFlags.MouseButtonLeft);
ImGui.InvisibleButton($"timeline_sequencetracker_{Name}##{i}", new Vector2(EndTime * timeRatio.X - t, timeStep.Y - t), ImGuiButtonFlags.MouseButtonLeft);
IsActive = ImGui.IsItemActive();
IsSelected = s.Renderer.Options.SelectedAnimation == i;
if (ImGui.IsItemClicked(ImGuiMouseButton.Left))
@ -105,6 +109,19 @@ public class Animation : IDisposable
SnimGui.Popup(() =>
{
s.Renderer.Options.SelectedAnimation = i;
if (ImGui.BeginMenu("Animate"))
{
foreach ((var guid, var model) in s.Renderer.Options.Models)
{
if (ImGui.MenuItem(model.Name, model.HasSkeleton && !AttachedModels.Contains(guid)))
{
AttachedModels.Add(guid);
model.Skeleton.ResetAnimatedData(true);
model.Skeleton.Animate(AnimSet, s.Renderer.AnimateWithRotationOnly);
}
}
ImGui.EndMenu();
}
if (ImGui.Selectable("Save"))
{
s.WindowShouldFreeze(true);
@ -116,9 +133,10 @@ public class Animation : IDisposable
});
drawList.AddRectFilled(p1, p2, IsSelected ? 0xFF48B048 : 0xFF175F17, 5.0f, ImDrawFlags.RoundCornersTop);
drawList.PushClipRect(p1, p2, true);
drawList.AddText(p1, 0xFF000000, $"{TargetSkeleton} - {CurrentSequence + 1}/{Sequences.Length} - {FrameInSequence}/{Sequences[CurrentSequence].EndFrame}");
drawList.PopClipRect();
for (int j = 0; j < Sequences.Length; j++)
{
Sequences[j].DrawSequence(drawList, timelineP0.X, p2, timeStep, timeRatio, t);
}
drawList.PushClipRect(treeP0 with { Y = p1.Y }, treeP1 with { Y = p2.Y }, true);
drawList.AddText(treeP0 with { Y = y + timeStep.Y / 4.0f }, 0xFFFFFFFF, Name);

View File

@ -28,15 +28,13 @@ public class Sequence
IsAdditive = sequence.bAdditive;
}
private readonly float _height = 20.0f;
public void DrawSequence(ImDrawListPtr drawList, float x, float y, Vector2 ratio, int index, uint col)
public void DrawSequence(ImDrawListPtr drawList, float x, Vector2 p2, Vector2 timeStep, Vector2 timeRatio, float t)
{
var height = _height * (index % 2);
var p1 = new Vector2(x + StartTime * ratio.X, y + height);
var p2 = new Vector2(x + EndTime * ratio.X, y + height + _height);
drawList.PushClipRect(p1, p2, true);
drawList.AddRectFilled(p1, p2, col);
drawList.AddText(p1 with { X = p1.X + 2.5f }, 0xFF000000, Name);
drawList.PopClipRect();
var q1 = new Vector2(x + StartTime * timeRatio.X + t, p2.Y - timeStep.Y / 2.0f);
var q2 = p2 with { X = x + EndTime * timeRatio.X - t - t };
drawList.AddLine(new Vector2(q1.X, q2.Y), q1, 0x50FFFFFF, 1.0f);
drawList.AddLine(q1, new Vector2(q2.X, q1.Y), 0x50FFFFFF, 1.0f);
drawList.AddLine(new Vector2(q2.X, q1.Y), q2, 0x50FFFFFF, 1.0f);
}
}

View File

@ -148,6 +148,15 @@ public class TimeTracker : IDisposable
DrawSeparator(drawList, timelineP0, y + _timeStep.Y, animations[i].EndTime * timeRatio.X, ETrackerType.End);
}
for (int i = 0; i < animations.Count; i++)
{
var y = timelineP0.Y + _timeBarHeight + _timeStep.Y * i;
for (int j = 0; j < animations[i].Sequences.Length - 1; j++)
{
DrawSeparator(drawList, timelineP0, y + _timeStep.Y - _thickness, animations[i].Sequences[j].EndTime * timeRatio.X - 1.0f, ETrackerType.InBetween);
}
}
DrawSeparator(drawList, timelineP0, timelineP1.Y, ElapsedTime * timeRatio.X, ETrackerType.Frame);
drawList.PopClipRect();
@ -162,6 +171,7 @@ public class TimeTracker : IDisposable
{
ETrackerType.Frame => new Vector2(origin.X + time, origin.Y + _timeBarHeight),
ETrackerType.End => origin with { X = origin.X + time },
ETrackerType.InBetween => origin with { X = origin.X + time },
_ => throw new ArgumentOutOfRangeException(nameof(separatorType), separatorType, null)
};
var p2 = p1 with { Y = y };
@ -170,6 +180,7 @@ public class TimeTracker : IDisposable
{
ETrackerType.Frame => 0xFF6F6F6F,
ETrackerType.End => 0xFF2E3E82,
ETrackerType.InBetween => 0x50FFFFFF,
_ => throw new ArgumentOutOfRangeException(nameof(separatorType), separatorType, null)
};
@ -186,6 +197,7 @@ public class TimeTracker : IDisposable
drawList.AddTriangleFilled(new Vector2(xl, yb), new Vector2(xr, yb), p1, color);
break;
case ETrackerType.End:
case ETrackerType.InBetween:
drawList.AddTriangleFilled(p1, p1 with { X = p1.X - size }, p1 with { Y = p1.Y + size }, color);
break;
default: