From 591a2d2336dee6074e4af8d2940ae8303d129bc2 Mon Sep 17 00:00:00 2001 From: 4sval Date: Tue, 21 Feb 2023 18:06:37 +0100 Subject: [PATCH] animate loaded model --- FModel/Views/Snooper/Animations/Animation.cs | 34 ++++++++++++++----- FModel/Views/Snooper/Animations/Sequence.cs | 16 ++++----- .../Views/Snooper/Animations/TimeTracker.cs | 12 +++++++ 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/FModel/Views/Snooper/Animations/Animation.cs b/FModel/Views/Snooper/Animations/Animation.cs index 037e8cd8..ae566716 100644 --- a/FModel/Views/Snooper/Animations/Animation.cs +++ b/FModel/Views/Snooper/Animations/Animation.cs @@ -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); diff --git a/FModel/Views/Snooper/Animations/Sequence.cs b/FModel/Views/Snooper/Animations/Sequence.cs index 9a7ea403..4c2f1474 100644 --- a/FModel/Views/Snooper/Animations/Sequence.cs +++ b/FModel/Views/Snooper/Animations/Sequence.cs @@ -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); } } diff --git a/FModel/Views/Snooper/Animations/TimeTracker.cs b/FModel/Views/Snooper/Animations/TimeTracker.cs index 636955b5..fcdba813 100644 --- a/FModel/Views/Snooper/Animations/TimeTracker.cs +++ b/FModel/Views/Snooper/Animations/TimeTracker.cs @@ -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: