From 1aa45b1b8894952799d8a1f241e4da9cd036b7ce Mon Sep 17 00:00:00 2001 From: Asval Date: Thu, 17 Aug 2023 01:06:36 +0200 Subject: [PATCH] mock-up bone hierarchy --- FModel/Views/Snooper/Animations/Bone.cs | 1 + FModel/Views/Snooper/Animations/Skeleton.cs | 58 +++++++++++++++++---- FModel/Views/Snooper/SnimGui.cs | 17 ++++-- 3 files changed, 61 insertions(+), 15 deletions(-) diff --git a/FModel/Views/Snooper/Animations/Bone.cs b/FModel/Views/Snooper/Animations/Bone.cs index 337c5bbc..dc78c982 100644 --- a/FModel/Views/Snooper/Animations/Bone.cs +++ b/FModel/Views/Snooper/Animations/Bone.cs @@ -31,6 +31,7 @@ public class Bone public bool IsMapped => SkeletonIndex > -1; public bool IsAnimated => AnimatedBySequences.Count > 0; public bool IsNative => Index == SkeletonIndex; + public uint Color => !IsMapped || !IsAnimated ? 0xFFA0A0A0 : 0xFF48B048; public override string ToString() => $"Mesh Ref '{Index}' is Skel Ref '{SkeletonIndex}'"; } diff --git a/FModel/Views/Snooper/Animations/Skeleton.cs b/FModel/Views/Snooper/Animations/Skeleton.cs index d039b802..487fc336 100644 --- a/FModel/Views/Snooper/Animations/Skeleton.cs +++ b/FModel/Views/Snooper/Animations/Skeleton.cs @@ -18,14 +18,14 @@ public class Skeleton : IDisposable private BufferObject _rest; private BufferObject _ssbo; private Matrix4x4[] _boneMatriceAtFrame; + private readonly List _breadcrumb; public string Name; - public readonly string RootBoneName; public readonly Dictionary BonesByLoweredName; public readonly int BoneCount; - public int AdditionalBoneCount; - public int TotalBoneCount => BoneCount + AdditionalBoneCount; + private int _additionalBoneCount; + private int TotalBoneCount => BoneCount + _additionalBoneCount; public bool IsAnimated { get; private set; } public string SelectedBone; @@ -33,6 +33,7 @@ public class Skeleton : IDisposable public Skeleton() { BonesByLoweredName = new Dictionary(); + _breadcrumb = new List(); } public Skeleton(FReferenceSkeleton referenceSkeleton) : this() @@ -58,7 +59,7 @@ public class Skeleton : IDisposable parentBone.LoweredChildNames.Add(boneName); } - if (boneIndex == 0) RootBoneName = boneName; + if (boneIndex == 0) SelectedBone = boneName; BonesByLoweredName[boneName] = bone; } _boneMatriceAtFrame = new Matrix4x4[BoneCount]; @@ -73,7 +74,7 @@ public class Skeleton : IDisposable if (!BonesByLoweredName.TryGetValue(boneName, out var bone)) { - bone = new Bone(BoneCount + AdditionalBoneCount, info.ParentIndex, new Transform + bone = new Bone(BoneCount + _additionalBoneCount, info.ParentIndex, new Transform { Rotation = referenceSkeleton.FinalRefBonePose[boneIndex].Rotation, Position = referenceSkeleton.FinalRefBonePose[boneIndex].Translation * Constants.SCALE_DOWN_RATIO, @@ -90,10 +91,10 @@ public class Skeleton : IDisposable } BonesByLoweredName[boneName] = bone; - AdditionalBoneCount++; + _additionalBoneCount++; } } - _boneMatriceAtFrame = new Matrix4x4[BoneCount + AdditionalBoneCount]; + _boneMatriceAtFrame = new Matrix4x4[TotalBoneCount]; } public void Setup() @@ -135,7 +136,7 @@ public class Skeleton : IDisposable { bone.AnimatedBySequences.Add(s); } - sequence.Retarget(animation.Skeleton); + sequence.RetargetTracks(animation.Skeleton); } #if DEBUG @@ -238,22 +239,56 @@ public class Skeleton : IDisposable _rest.BindBufferBase(2); } + public void ImGuiBoneBreadcrumb() + { + for (int i = _breadcrumb.Count - 1; i >= 0; i--) + { + var boneName = _breadcrumb[i]; + ImGui.SameLine(); + var clicked = ImGui.SmallButton(boneName); + ImGui.SameLine(); + ImGui.Text(">"); + + if (clicked) + { + SelectedBone = boneName; + _breadcrumb.RemoveRange(0, i + 1); + break; + } + } + } + public void ImGuiBoneHierarchy() { - DrawBoneTree(RootBoneName, BonesByLoweredName[RootBoneName]); + DrawBoneTree(SelectedBone, BonesByLoweredName[SelectedBone]); } private void DrawBoneTree(string boneName, Bone bone) { - var flags = ImGuiTreeNodeFlags.OpenOnArrow | ImGuiTreeNodeFlags.OpenOnDoubleClick | ImGuiTreeNodeFlags.SpanAvailWidth; + ImGui.PushID(bone.Index); + ImGui.TableNextRow(); + ImGui.TableNextColumn(); + + var flags = ImGuiTreeNodeFlags.OpenOnArrow | ImGuiTreeNodeFlags.SpanFullWidth; if (boneName == SelectedBone) flags |= ImGuiTreeNodeFlags.Selected; if (bone.IsVirtual) flags |= ImGuiTreeNodeFlags.Leaf; else if (!bone.IsDaron) flags |= ImGuiTreeNodeFlags.Bullet; - ImGui.SetNextItemOpen(bone.LoweredChildNames.Count <= 1, ImGuiCond.Appearing); + ImGui.SetNextItemOpen(bone.LoweredChildNames.Count <= 1 || flags.HasFlag(ImGuiTreeNodeFlags.Selected), ImGuiCond.Appearing); var open = ImGui.TreeNodeEx(boneName, flags); if (ImGui.IsItemClicked() && !ImGui.IsItemToggledOpen()) + { SelectedBone = boneName; + _breadcrumb.Clear(); + do + { + _breadcrumb.Add(boneName); + boneName = BonesByLoweredName[boneName].LoweredParentName; + } while (boneName != null); + } + + ImGui.TableNextColumn(); + ImGui.TextColored(ImGui.ColorConvertU32ToFloat4(bone.Color), bone.SkeletonIndex.ToString()); if (open) { @@ -263,6 +298,7 @@ public class Skeleton : IDisposable } ImGui.TreePop(); } + ImGui.PopID(); } public void Dispose() diff --git a/FModel/Views/Snooper/SnimGui.cs b/FModel/Views/Snooper/SnimGui.cs index 954fef74..770f1a1f 100644 --- a/FModel/Views/Snooper/SnimGui.cs +++ b/FModel/Views/Snooper/SnimGui.cs @@ -104,10 +104,11 @@ public class SnimGui Draw3DViewport(s); DrawNavbar(); - DrawModals(s); - if (_ti_open) DrawTextureInspector(s); if (_bh_open) DrawBoneHierarchy(s); + + DrawModals(s); + Controller.Render(); } @@ -722,11 +723,19 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio private void DrawBoneHierarchy(Snooper s) { + ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero); if (ImGui.Begin("Bone Hierarchy", ref _bh_open, ImGuiWindowFlags.NoScrollbar) && s.Renderer.Options.TryGetModel(out var model)) { - model.Skeleton.ImGuiBoneHierarchy(); + model.Skeleton.ImGuiBoneBreadcrumb(); + if (ImGui.BeginTable("bone_hierarchy", 2, ImGuiTableFlags.NoSavedSettings | ImGuiTableFlags.RowBg, ImGui.GetContentRegionAvail(), ImGui.GetWindowWidth())) + { + ImGui.TableSetupColumn("Bone", ImGuiTableColumnFlags.WidthStretch); + ImGui.TableSetupColumn("", ImGuiTableColumnFlags.NoHeaderWidth | ImGuiTableColumnFlags.WidthFixed, _tableWidth); + model.Skeleton.ImGuiBoneHierarchy(); + ImGui.EndTable(); + } } - ImGui.End(); // if window is collapsed + ImGui.PopStyleVar(); } private void Draw3DViewport(Snooper s)