Skip to content

Commit

Permalink
timeline
Browse files Browse the repository at this point in the history
  • Loading branch information
4sval committed Feb 21, 2023
1 parent 591a2d2 commit 4247dec
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 27 deletions.
4 changes: 2 additions & 2 deletions FModel/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ private async void OnLoaded(object sender, RoutedEventArgs e)
#if DEBUG
await _threadWorkerView.Begin(cancellationToken =>
_applicationView.CUE4Parse.Extract(cancellationToken,
"fortnitegame/Content/Characters/Player/Male/Medium/Bodies/M_Med_Soldier_04/Meshes/SK_M_Med_Soldier_04.uasset"));
"fortnitegame/Content/Characters/Player/Male/Medium/Bodies/M_MED_BlueGlaze/Meshes/M_MED_BlueGlaze.uasset"));
await _threadWorkerView.Begin(cancellationToken =>
_applicationView.CUE4Parse.Extract(cancellationToken,
"fortnitegame/Content/Animation/Game/MainPlayer/Emotes/Basketball_Tricks/Basketball_Tricks_Loop_CMM_M.uasset"));
"fortnitegame/Content/Animation/Game/MainPlayer/Emotes/Troops/Emote_Troops_CMM_M.uasset"));
#endif
}

Expand Down
45 changes: 25 additions & 20 deletions FModel/Views/Snooper/Animations/Animation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ namespace FModel.Views.Snooper.Animations;

public class Animation : IDisposable
{
public readonly UObject Export;
public readonly CAnimSet AnimSet;
private readonly UObject _export;
private readonly CAnimSet _animSet;

public readonly string Path;
public readonly string Name;
public readonly Sequence[] Sequences;
Expand All @@ -33,25 +34,25 @@ public class Animation : IDisposable

public Animation(UObject export)
{
Export = export;
Path = Export.GetPathName();
Name = Export.Name;
_export = export;
Path = _export.GetPathName();
Name = _export.Name;
Sequences = Array.Empty<Sequence>();
AttachedModels = new List<FGuid>();
}

public Animation(UObject export, CAnimSet animSet) : this(export)
{
AnimSet = animSet;
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)
Expand Down Expand Up @@ -95,37 +96,39 @@ public void Dispose()

public void ImGuiAnimation(Snooper s, Save saver, ImDrawListPtr drawList, Vector2 timelineP0, Vector2 treeP0, Vector2 treeP1, Vector2 timeStep, Vector2 timeRatio, float y, float t, int i)
{
var name = $"{Name}##{i}";
var p1 = new Vector2(timelineP0.X + StartTime * timeRatio.X + t, y + t);
var p2 = new Vector2(timelineP0.X + EndTime * timeRatio.X - t, y + timeStep.Y - t);

ImGui.SetCursorScreenPos(p1);
ImGui.InvisibleButton($"timeline_sequencetracker_{Name}##{i}", new Vector2(EndTime * timeRatio.X - t, timeStep.Y - t), ImGuiButtonFlags.MouseButtonLeft);
ImGui.InvisibleButton($"timeline_sequencetracker_{name}", 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))
{
s.Renderer.Options.SelectedAnimation = i;
s.Renderer.Options.SelectAnimation(i);
}
SnimGui.Popup(() =>
{
s.Renderer.Options.SelectedAnimation = i;
s.Renderer.Options.SelectAnimation(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)))
var selected = AttachedModels.Contains(guid);
if (ImGui.MenuItem(model.Name, null, selected, (model.HasSkeleton && !model.Skeleton.IsAnimated) || selected))
{
AttachedModels.Add(guid);
if (selected) AttachedModels.Remove(guid); else AttachedModels.Add(guid);
model.Skeleton.ResetAnimatedData(true);
model.Skeleton.Animate(AnimSet, s.Renderer.AnimateWithRotationOnly);
if (!selected) model.Skeleton.Animate(_animSet, s.Renderer.AnimateWithRotationOnly);
}
}
ImGui.EndMenu();
}
if (ImGui.Selectable("Save"))
{
s.WindowShouldFreeze(true);
saver.Value = s.Renderer.Options.TrySave(Export, out saver.Label, out saver.Path);
saver.Value = s.Renderer.Options.TrySave(_export, out saver.Label, out saver.Path);
s.WindowShouldFreeze(false);
}
ImGui.Separator();
Expand All @@ -138,8 +141,10 @@ public void ImGuiAnimation(Snooper s, Save saver, ImDrawListPtr drawList, Vector
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);
drawList.PopClipRect();
ImGui.SetCursorScreenPos(treeP0 with { Y = p1.Y });
if (ImGui.Selectable(name, s.Renderer.Options.SelectedAnimation == i, ImGuiSelectableFlags.SpanAllColumns, new Vector2(p1.X - treeP0.X, timeStep.Y - t - t)))
{
s.Renderer.Options.SelectAnimation(i);
}
}
}
21 changes: 17 additions & 4 deletions FModel/Views/Snooper/Animations/TimeTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,14 @@ public void ImGuiTimeline(Snooper s, Save saver, Dictionary<string, Texture> ico
}
}

ImGui.PushStyleVar(ImGuiStyleVar.SelectableTextAlign, new Vector2(0.0f, 0.5f));
for (int i = 0; i < animations.Count; i++)
{
var y = timelineP0.Y + _timeBarHeight + _timeStep.Y * i;
animations[i].ImGuiAnimation(s, saver, drawList, timelineP0, treeP0, treeP1, _timeStep, timeRatio, y, _thickness, i);
DrawSeparator(drawList, timelineP0, y + _timeStep.Y, animations[i].EndTime * timeRatio.X, ETrackerType.End);
}
ImGui.PopStyleVar();

for (int i = 0; i < animations.Count; i++)
{
Expand All @@ -165,7 +167,13 @@ public void ImGuiTimeline(Snooper s, Save saver, Dictionary<string, Texture> ico

private void DrawSeparator(ImDrawListPtr drawList, Vector2 origin, float y, float time, ETrackerType separatorType)
{
const int size = 5;
float size = separatorType switch
{
ETrackerType.Frame => 5,
ETrackerType.End => 5,
ETrackerType.InBetween => 7.5f,
_ => throw new ArgumentOutOfRangeException(nameof(separatorType), separatorType, null)
};

Vector2 p1 = separatorType switch
{
Expand All @@ -180,11 +188,10 @@ private void DrawSeparator(ImDrawListPtr drawList, Vector2 origin, float y, floa
{
ETrackerType.Frame => 0xFF6F6F6F,
ETrackerType.End => 0xFF2E3E82,
ETrackerType.InBetween => 0x50FFFFFF,
ETrackerType.InBetween => 0xA0FFFFFF,
_ => throw new ArgumentOutOfRangeException(nameof(separatorType), separatorType, null)
};

drawList.AddLine(p1, p2, color, 1f);
switch (separatorType)
{
case ETrackerType.Frame:
Expand All @@ -193,13 +200,19 @@ private void DrawSeparator(ImDrawListPtr drawList, Vector2 origin, float y, floa
var xr = p1.X + size;
var yb = origin.Y + _timeBarHeight - _timeHeight / 2.0f;

drawList.AddLine(p1, p2, color, 1f);
drawList.AddQuadFilled(origin with { X = xl }, origin with { X = xr }, new Vector2(xr, yb), new Vector2(xl, yb), color);
drawList.AddTriangleFilled(new Vector2(xl, yb), new Vector2(xr, yb), p1, color);
break;
case ETrackerType.End:
case ETrackerType.InBetween:
drawList.AddLine(p1, p2, color, 1f);
drawList.AddTriangleFilled(p1, p1 with { X = p1.X - size }, p1 with { Y = p1.Y + size }, color);
break;
case ETrackerType.InBetween:
p1.Y += _timeBarHeight;
drawList.AddLine(p1, p2, color, 1f);
drawList.AddTriangleFilled(p1, new Vector2(p1.X - size / 2.0f, p1.Y - size), new Vector2(p1.X + size / 2.0f, p1.Y - size), color);
break;
default:
throw new ArgumentOutOfRangeException(nameof(separatorType), separatorType, null);
}
Expand Down
7 changes: 6 additions & 1 deletion FModel/Views/Snooper/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class Options
public FGuid SelectedModel { get; private set; }
public int SelectedSection { get; private set; }
public int SelectedMorph { get; private set; }
public int SelectedAnimation{ get; set; }
public int SelectedAnimation{ get; private set; }

public readonly Dictionary<FGuid, Model> Models;
public readonly Dictionary<FGuid, Texture> Textures;
Expand Down Expand Up @@ -98,6 +98,11 @@ public void SelectModel(FGuid guid)
SelectedMorph = 0;
}

public void SelectAnimation(int animation)
{
SelectedAnimation = animation;
}

public void RemoveModel(FGuid guid)
{
if (!TryGetModel(guid, out var model)) return;
Expand Down

0 comments on commit 4247dec

Please sign in to comment.