From 26e92238bac939b5291ecf95e3ce9f84868f6be3 Mon Sep 17 00:00:00 2001 From: 4sval Date: Tue, 14 Mar 2023 00:51:23 +0100 Subject: [PATCH] cleaned skeleton and bones --- CUE4Parse | 2 +- FModel/MainWindow.xaml.cs | 19 +-- FModel/ViewModels/CUE4ParseViewModel.cs | 2 - .../Commands/RightClickMenuCommand.cs | 7 + FModel/ViewModels/TabControlViewModel.cs | 2 - FModel/Views/Snooper/Animations/Bone.cs | 25 +++ FModel/Views/Snooper/Animations/BoneIndice.cs | 19 --- FModel/Views/Snooper/Animations/Skeleton.cs | 159 +++++++----------- FModel/Views/Snooper/Models/Model.cs | 4 +- FModel/Views/Snooper/SnimGui.cs | 1 + FModel/Views/Snooper/Snooper.cs | 6 + 11 files changed, 111 insertions(+), 135 deletions(-) create mode 100644 FModel/Views/Snooper/Animations/Bone.cs delete mode 100644 FModel/Views/Snooper/Animations/BoneIndice.cs diff --git a/CUE4Parse b/CUE4Parse index 04239c2e..d0a84960 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 04239c2e1f7fd257c6671a0bb52a7896c0232930 +Subproject commit d0a849608247dbdcb14b9b6e6851addd761f3c73 diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs index 0c9d1b43..12e09244 100644 --- a/FModel/MainWindow.xaml.cs +++ b/FModel/MainWindow.xaml.cs @@ -76,19 +76,12 @@ public partial class MainWindow _discordHandler.Initialize(_applicationView.CUE4Parse.Provider.GameName); #if DEBUG - // await _threadWorkerView.Begin(cancellationToken => - // _applicationView.CUE4Parse.Extract(cancellationToken, - // "ShooterGame/Content/Characters/_Core/3P/Models/TP_Core_NewMale_Skelmesh.uasset")); - // await _threadWorkerView.Begin(cancellationToken => - // _applicationView.CUE4Parse.Extract(cancellationToken, - // "Game/Characters/_Core/3P/Anims/TP_Core_SprintAddN_UB.uasset")); - // - // await _threadWorkerView.Begin(cancellationToken => - // _applicationView.CUE4Parse.Extract(cancellationToken, - // "ShooterGame/Content/Characters/Guide/S0/1P/Models/FP_Guide_S0_Skelmesh.uasset")); - // await _threadWorkerView.Begin(cancellationToken => - // _applicationView.CUE4Parse.Extract(cancellationToken, - // "/Game/Equippables/Guns/SniperRifles/Boltsniper/S0/1P/Anims/FP_Core_Boltsniper_S0_Fire.uasset")); + await _threadWorkerView.Begin(cancellationToken => + _applicationView.CUE4Parse.Extract(cancellationToken, + "ShooterGame/Content/Characters/BountyHunter/S0/Ability_4/1P/Models/AB_BountyHunter_S0_4_TrailCreature_Skelmesh.uasset")); + await _threadWorkerView.Begin(cancellationToken => + _applicationView.CUE4Parse.Extract(cancellationToken, + "ShooterGame/Content/Characters/BountyHunter/S0/Ability_4/1P/Anims/FP_BountyHunter_S0_4_Aim_S.uasset")); #endif } diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index b566634a..c5bcaea6 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -6,7 +6,6 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows; -using System.Windows.Forms; using AdonisUI.Controls; using CUE4Parse.Encryption.Aes; using CUE4Parse.FileProvider; @@ -41,7 +40,6 @@ using FModel.Settings; using FModel.Views; using FModel.Views.Resources.Controls; using FModel.Views.Snooper; -using ImGuiNET; using Newtonsoft.Json; using Ookii.Dialogs.Wpf; using OpenTK.Windowing.Common; diff --git a/FModel/ViewModels/Commands/RightClickMenuCommand.cs b/FModel/ViewModels/Commands/RightClickMenuCommand.cs index 821cf32b..1da8395e 100644 --- a/FModel/ViewModels/Commands/RightClickMenuCommand.cs +++ b/FModel/ViewModels/Commands/RightClickMenuCommand.cs @@ -1,5 +1,6 @@ using System.Collections; using System.Linq; +using System.Threading; using FModel.Framework; using FModel.Services; @@ -28,6 +29,7 @@ public class RightClickMenuCommand : ViewModelCommand case "Assets_Extract_New_Tab": foreach (var asset in assetItems) { + Thread.Sleep(10); cancellationToken.ThrowIfCancellationRequested(); contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, true); } @@ -35,6 +37,7 @@ public class RightClickMenuCommand : ViewModelCommand case "Assets_Export_Data": foreach (var asset in assetItems) { + Thread.Sleep(10); cancellationToken.ThrowIfCancellationRequested(); contextViewModel.CUE4Parse.ExportData(asset.FullPath); } @@ -42,6 +45,7 @@ public class RightClickMenuCommand : ViewModelCommand case "Assets_Save_Properties": foreach (var asset in assetItems) { + Thread.Sleep(10); cancellationToken.ThrowIfCancellationRequested(); contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, false, EBulkType.Properties); } @@ -49,6 +53,7 @@ public class RightClickMenuCommand : ViewModelCommand case "Assets_Save_Textures": foreach (var asset in assetItems) { + Thread.Sleep(10); cancellationToken.ThrowIfCancellationRequested(); contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, false, EBulkType.Textures); } @@ -56,6 +61,7 @@ public class RightClickMenuCommand : ViewModelCommand case "Assets_Save_Models": foreach (var asset in assetItems) { + Thread.Sleep(10); cancellationToken.ThrowIfCancellationRequested(); contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, false, EBulkType.Meshes | EBulkType.Auto); } @@ -63,6 +69,7 @@ public class RightClickMenuCommand : ViewModelCommand case "Assets_Save_Animations": foreach (var asset in assetItems) { + Thread.Sleep(10); cancellationToken.ThrowIfCancellationRequested(); contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, false, EBulkType.Animations | EBulkType.Auto); } diff --git a/FModel/ViewModels/TabControlViewModel.cs b/FModel/ViewModels/TabControlViewModel.cs index c5a7bca2..82701d3e 100644 --- a/FModel/ViewModels/TabControlViewModel.cs +++ b/FModel/ViewModels/TabControlViewModel.cs @@ -6,7 +6,6 @@ using FModel.ViewModels.Commands; using FModel.Views.Resources.Controls; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Highlighting; -using Microsoft.Win32; using Serilog; using SkiaSharp; using System.Collections.Generic; @@ -17,7 +16,6 @@ using System.Windows; using System.Windows.Media.Imaging; using CUE4Parse.UE4.Assets.Exports.Texture; using CUE4Parse_Conversion.Textures; -using Ookii.Dialogs.Wpf; namespace FModel.ViewModels; diff --git a/FModel/Views/Snooper/Animations/Bone.cs b/FModel/Views/Snooper/Animations/Bone.cs new file mode 100644 index 00000000..50268a1d --- /dev/null +++ b/FModel/Views/Snooper/Animations/Bone.cs @@ -0,0 +1,25 @@ +namespace FModel.Views.Snooper.Animations; + +public class Bone +{ + public readonly int Index; + public readonly int ParentIndex; + public readonly Transform Rest; + public string LoweredParentName; + + public int SkeletonIndex = -1; + public bool[] IsAnimated; + + public Bone(int i, int p, Transform t) + { + Index = i; + ParentIndex = p; + Rest = t; + } + + public bool IsRoot => Index == 0 && ParentIndex == -1 && string.IsNullOrEmpty(LoweredParentName); + public bool IsMapped => SkeletonIndex > -1; + public bool IsNative => Index == SkeletonIndex; + + public override string ToString() => $"Mesh Ref '{Index}' is Skel Ref '{SkeletonIndex}' ({IsNative})"; +} diff --git a/FModel/Views/Snooper/Animations/BoneIndice.cs b/FModel/Views/Snooper/Animations/BoneIndice.cs deleted file mode 100644 index e206ac4d..00000000 --- a/FModel/Views/Snooper/Animations/BoneIndice.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace FModel.Views.Snooper.Animations; - -public class BoneIndice -{ - public int BoneIndex = -1; - public int ParentBoneIndex = -1; - public string LoweredParentBoneName; - public bool IsRoot => BoneIndex == 0 && ParentBoneIndex == -1 && string.IsNullOrEmpty(LoweredParentBoneName); - - public int TrackedBoneIndex = -1; - public int TrackedParentBoneIndex = -1; // bone index of the first tracked parent bone - public bool IsTracked => TrackedBoneIndex > -1; - public bool IsParentTracked => TrackedParentBoneIndex > -1; - - public bool IsNative => BoneIndex == TrackedBoneIndex; - public bool IsParentNative => ParentBoneIndex == TrackedParentBoneIndex; // always true? - - public override string ToString() => $"Mesh Ref '{BoneIndex}' is Skel Ref '{TrackedBoneIndex}' ({IsNative}, {IsParentNative})"; -} diff --git a/FModel/Views/Snooper/Animations/Skeleton.cs b/FModel/Views/Snooper/Animations/Skeleton.cs index 29d75f52..33cf1681 100644 --- a/FModel/Views/Snooper/Animations/Skeleton.cs +++ b/FModel/Views/Snooper/Animations/Skeleton.cs @@ -16,8 +16,7 @@ public class Skeleton : IDisposable private BufferObject _ssbo; public string Name; - public readonly Dictionary BonesIndicesByLoweredName; - public readonly Dictionary BonesTransformByIndex; + public readonly Dictionary BonesByLoweredName; private int _previousAnimationSequence; private int _previousSequenceFrame; @@ -28,48 +27,36 @@ public class Skeleton : IDisposable public Skeleton() { - BonesIndicesByLoweredName = new Dictionary(); - BonesTransformByIndex = new Dictionary(); + BonesByLoweredName = new Dictionary(); _animatedBonesTransform = Array.Empty(); _invertedBonesMatrix = Array.Empty(); } public Skeleton(FReferenceSkeleton referenceSkeleton) : this() { - for (int boneIndex = 0; boneIndex < referenceSkeleton.FinalRefBoneInfo.Length; boneIndex++) + _invertedBonesMatrix = new Matrix4x4[referenceSkeleton.FinalRefBoneInfo.Length]; + for (int boneIndex = 0; boneIndex < _invertedBonesMatrix.Length; boneIndex++) { var info = referenceSkeleton.FinalRefBoneInfo[boneIndex]; - - var boneIndices = new BoneIndice { BoneIndex = boneIndex, ParentBoneIndex = info.ParentIndex }; - if (!boneIndices.IsRoot) - boneIndices.LoweredParentBoneName = - referenceSkeleton.FinalRefBoneInfo[boneIndices.ParentBoneIndex].Name.Text.ToLower(); - - BonesIndicesByLoweredName[info.Name.Text.ToLower()] = boneIndices; - } - - _invertedBonesMatrix = new Matrix4x4[BonesIndicesByLoweredName.Count]; - foreach (var boneIndices in BonesIndicesByLoweredName.Values) - { - var bone = referenceSkeleton.FinalRefBonePose[boneIndices.BoneIndex]; - if (!BonesTransformByIndex.TryGetValue(boneIndices.BoneIndex, out var boneTransform)) + var boneTransform = new Transform { - boneTransform = new Transform - { - Rotation = bone.Rotation, - Position = bone.Translation * Constants.SCALE_DOWN_RATIO, - Scale = bone.Scale3D - }; + Rotation = referenceSkeleton.FinalRefBonePose[boneIndex].Rotation, + Position = referenceSkeleton.FinalRefBonePose[boneIndex].Translation * Constants.SCALE_DOWN_RATIO, + Scale = referenceSkeleton.FinalRefBonePose[boneIndex].Scale3D + }; + + var bone = new Bone(boneIndex, info.ParentIndex, boneTransform); + if (!bone.IsRoot) + { + bone.LoweredParentName = + referenceSkeleton.FinalRefBoneInfo[bone.ParentIndex].Name.Text.ToLower(); + bone.Rest.Relation = BonesByLoweredName[bone.LoweredParentName].Rest.Matrix; } - if (!BonesTransformByIndex.TryGetValue(boneIndices.ParentBoneIndex, out var parentTransform)) - parentTransform = new Transform { Relation = Matrix4x4.Identity }; + BonesByLoweredName[info.Name.Text.ToLower()] = bone; - boneTransform.Relation = parentTransform.Matrix; Matrix4x4.Invert(boneTransform.Matrix, out var inverted); - - BonesTransformByIndex[boneIndices.BoneIndex] = boneTransform; - _invertedBonesMatrix[boneIndices.BoneIndex] = inverted; + _invertedBonesMatrix[bone.Index] = inverted; } } @@ -82,48 +69,47 @@ public class Skeleton : IDisposable { var sequence = anim.Sequences[s]; _animatedBonesTransform[s] = new Transform[BoneCount][]; - foreach (var boneIndices in BonesIndicesByLoweredName.Values) + foreach (var bone in BonesByLoweredName.Values) { - var originalTransform = BonesTransformByIndex[boneIndices.BoneIndex]; - _animatedBonesTransform[s][boneIndices.BoneIndex] = new Transform[sequence.NumFrames]; + _animatedBonesTransform[s][bone.Index] = new Transform[sequence.NumFrames]; - var trackedBoneIndex = boneIndices.TrackedBoneIndex; - if (sequence.OriginalSequence.FindTrackForBoneIndex(trackedBoneIndex) < 0) + var skeletonBoneIndex = bone.SkeletonIndex; + bone.IsAnimated[s] = sequence.OriginalSequence.FindTrackForBoneIndex(skeletonBoneIndex) >= 0; + if (!bone.IsAnimated[s]) { - for (int frame = 0; frame < _animatedBonesTransform[s][boneIndices.BoneIndex].Length; frame++) + for (int frame = 0; frame < _animatedBonesTransform[s][bone.Index].Length; frame++) { - _animatedBonesTransform[s][boneIndices.BoneIndex][frame] = new Transform + _animatedBonesTransform[s][bone.Index][frame] = new Transform { - Relation = boneIndices.IsParentTracked ? - originalTransform.LocalMatrix * _animatedBonesTransform[s][boneIndices.TrackedParentBoneIndex][frame].Matrix : - originalTransform.Relation + Relation = bone.IsRoot ? bone.Rest.Relation : + bone.Rest.LocalMatrix * _animatedBonesTransform[s][bone.ParentIndex][frame].Matrix }; } } else { - for (int frame = 0; frame < _animatedBonesTransform[s][boneIndices.BoneIndex].Length; frame++) + for (int frame = 0; frame < _animatedBonesTransform[s][bone.Index].Length; frame++) { - var boneOrientation = originalTransform.Rotation; - var bonePosition = originalTransform.Position; - var boneScale = originalTransform.Scale; + var boneOrientation = bone.Rest.Rotation; + var bonePosition = bone.Rest.Position; + var boneScale = bone.Rest.Scale; - sequence.Tracks[trackedBoneIndex].GetBoneTransform(frame, sequence.NumFrames, ref boneOrientation, ref bonePosition, ref boneScale); + sequence.Tracks[skeletonBoneIndex].GetBoneTransform(frame, sequence.NumFrames, ref boneOrientation, ref bonePosition, ref boneScale); - switch (anim.Skeleton.BoneTree[trackedBoneIndex]) + switch (anim.Skeleton.BoneTree[skeletonBoneIndex]) { case EBoneTranslationRetargetingMode.Skeleton when !rotationOnly: { - var targetTransform = sequence.RetargetBasePose?[trackedBoneIndex] ?? anim.Skeleton.ReferenceSkeleton.FinalRefBonePose[trackedBoneIndex]; + var targetTransform = sequence.RetargetBasePose?[skeletonBoneIndex] ?? anim.Skeleton.ReferenceSkeleton.FinalRefBonePose[skeletonBoneIndex]; bonePosition = targetTransform.Translation; break; } case EBoneTranslationRetargetingMode.AnimationScaled when !rotationOnly: { - var sourceTranslationLength = (originalTransform.Position / Constants.SCALE_DOWN_RATIO).Size(); + var sourceTranslationLength = (bone.Rest.Position / Constants.SCALE_DOWN_RATIO).Size(); if (sourceTranslationLength > UnrealMath.KindaSmallNumber) { - var targetTranslationLength = sequence.RetargetBasePose?[trackedBoneIndex].Translation.Size() ?? anim.Skeleton.ReferenceSkeleton.FinalRefBonePose[trackedBoneIndex].Translation.Size(); + var targetTranslationLength = sequence.RetargetBasePose?[skeletonBoneIndex].Translation.Size() ?? anim.Skeleton.ReferenceSkeleton.FinalRefBonePose[skeletonBoneIndex].Translation.Size(); bonePosition.Scale(targetTranslationLength / sourceTranslationLength); } break; @@ -131,19 +117,19 @@ public class Skeleton : IDisposable case EBoneTranslationRetargetingMode.AnimationRelative when !rotationOnly: { // can't tell if it's working or not - var sourceSkelTrans = originalTransform.Position / Constants.SCALE_DOWN_RATIO; - var refPoseTransform = sequence.RetargetBasePose?[trackedBoneIndex] ?? anim.Skeleton.ReferenceSkeleton.FinalRefBonePose[trackedBoneIndex]; + var sourceSkelTrans = bone.Rest.Position / Constants.SCALE_DOWN_RATIO; + var refPoseTransform = sequence.RetargetBasePose?[skeletonBoneIndex] ?? anim.Skeleton.ReferenceSkeleton.FinalRefBonePose[skeletonBoneIndex]; - boneOrientation = boneOrientation * FQuat.Conjugate(originalTransform.Rotation) * refPoseTransform.Rotation; + boneOrientation = boneOrientation * FQuat.Conjugate(bone.Rest.Rotation) * refPoseTransform.Rotation; bonePosition += refPoseTransform.Translation - sourceSkelTrans; - boneScale *= refPoseTransform.Scale3D * originalTransform.Scale; + boneScale *= refPoseTransform.Scale3D * bone.Rest.Scale; boneOrientation.Normalize(); break; } case EBoneTranslationRetargetingMode.OrientAndScale when !rotationOnly: { - var sourceSkelTrans = originalTransform.Position / Constants.SCALE_DOWN_RATIO; - var targetSkelTrans = sequence.RetargetBasePose?[trackedBoneIndex].Translation ?? anim.Skeleton.ReferenceSkeleton.FinalRefBonePose[trackedBoneIndex].Translation; + var sourceSkelTrans = bone.Rest.Position / Constants.SCALE_DOWN_RATIO; + var targetSkelTrans = sequence.RetargetBasePose?[skeletonBoneIndex].Translation ?? anim.Skeleton.ReferenceSkeleton.FinalRefBonePose[skeletonBoneIndex].Translation; if (!sourceSkelTrans.Equals(targetSkelTrans)) { @@ -163,11 +149,11 @@ public class Skeleton : IDisposable } } - _animatedBonesTransform[s][boneIndices.BoneIndex][frame] = new Transform + _animatedBonesTransform[s][bone.Index][frame] = new Transform { - Relation = boneIndices.IsParentTracked ? _animatedBonesTransform[s][boneIndices.TrackedParentBoneIndex][frame].Matrix : originalTransform.Relation, + Relation = bone.IsRoot ? bone.Rest.Relation : _animatedBonesTransform[s][bone.ParentIndex][frame].Matrix, Rotation = boneOrientation, - Position = rotationOnly ? originalTransform.Position : bonePosition * Constants.SCALE_DOWN_RATIO, + Position = rotationOnly ? bone.Rest.Position : bonePosition * Constants.SCALE_DOWN_RATIO, Scale = boneScale }; } @@ -180,53 +166,35 @@ public class Skeleton : IDisposable { ResetAnimatedData(); - // tracked bones - for (int trackIndex = 0; trackIndex < anim.Skeleton.BoneCount; trackIndex++) + // map bones + for (int boneIndex = 0; boneIndex < anim.Skeleton.BoneCount; boneIndex++) { - var info = anim.Skeleton.ReferenceSkeleton.FinalRefBoneInfo[trackIndex]; - if (!BonesIndicesByLoweredName.TryGetValue(info.Name.Text.ToLower(), out var boneIndices)) + var info = anim.Skeleton.ReferenceSkeleton.FinalRefBoneInfo[boneIndex]; + if (!BonesByLoweredName.TryGetValue(info.Name.Text.ToLower(), out var bone)) continue; - boneIndices.TrackedBoneIndex = trackIndex; - var parentTrackIndex = info.ParentIndex; - - do - { - if (parentTrackIndex < 0) break; - info = anim.Skeleton.ReferenceSkeleton.FinalRefBoneInfo[parentTrackIndex]; - if (boneIndices.LoweredParentBoneName.Equals(info.Name.Text, StringComparison.OrdinalIgnoreCase) && // same parent (name based) - BonesIndicesByLoweredName.TryGetValue(info.Name.Text.ToLower(), out var parentBoneIndices) && parentBoneIndices.IsTracked) - boneIndices.TrackedParentBoneIndex = parentBoneIndices.BoneIndex; - else parentTrackIndex = info.ParentIndex; - } while (!boneIndices.IsParentTracked); + bone.SkeletonIndex = boneIndex; } - // fix parent of untracked bones - foreach ((var boneName, var boneIndices) in BonesIndicesByLoweredName) + var seqCount = anim.Sequences.Count; + foreach ((var boneName, var bone) in BonesByLoweredName) { - if (boneIndices.IsRoot || boneIndices.IsTracked && boneIndices.IsParentTracked) // assuming root bone always has a track + bone.IsAnimated = new bool[seqCount]; +#if DEBUG + if (bone.IsRoot || bone.IsMapped) // assuming root bone always is mapped continue; -#if DEBUG - Log.Warning($"{Name} Bone Mismatch: {boneName} ({boneIndices.BoneIndex}) was not present in the anim's target skeleton"); + Log.Warning($"{Name} Bone Mismatch: {boneName} ({bone.Index}) was not present in the anim's target skeleton"); #endif - - var loweredParentBoneName = boneIndices.LoweredParentBoneName; - do - { - var parentBoneIndices = BonesIndicesByLoweredName[loweredParentBoneName]; - if (parentBoneIndices.IsParentTracked || parentBoneIndices.IsRoot) boneIndices.TrackedParentBoneIndex = parentBoneIndices.BoneIndex; - else loweredParentBoneName = parentBoneIndices.LoweredParentBoneName; - } while (!boneIndices.IsParentTracked); } } public void ResetAnimatedData(bool full = false) { - foreach (var boneIndices in BonesIndicesByLoweredName.Values) + foreach (var bone in BonesByLoweredName.Values) { - boneIndices.TrackedBoneIndex = -1; - boneIndices.TrackedParentBoneIndex = -1; + bone.SkeletonIndex = -1; + bone.IsAnimated = null; } if (!full) return; @@ -256,11 +224,11 @@ public class Skeleton : IDisposable _ssbo.Unbind(); } - public Matrix4x4 GetBoneMatrix(BoneIndice boneIndices) + public Matrix4x4 GetBoneMatrix(Bone bone) { return IsAnimated - ? _animatedBonesTransform[_previousAnimationSequence][boneIndices.BoneIndex][_previousSequenceFrame].Matrix - : BonesTransformByIndex[boneIndices.BoneIndex].Matrix; + ? _animatedBonesTransform[_previousAnimationSequence][bone.Index][_previousSequenceFrame].Matrix + : bone.Rest.Matrix; } public void Render() @@ -270,8 +238,7 @@ public class Skeleton : IDisposable public void Dispose() { - BonesIndicesByLoweredName.Clear(); - BonesTransformByIndex.Clear(); + BonesByLoweredName.Clear(); _ssbo?.Dispose(); GL.DeleteProgram(_handle); diff --git a/FModel/Views/Snooper/Models/Model.cs b/FModel/Views/Snooper/Models/Model.cs index 81312284..fd04527b 100644 --- a/FModel/Views/Snooper/Models/Model.cs +++ b/FModel/Views/Snooper/Models/Model.cs @@ -256,8 +256,8 @@ public class Model : IDisposable foreach (var socket in Sockets) { var boneMatrix = Matrix4x4.Identity; - if (HasSkeleton && Skeleton.BonesIndicesByLoweredName.TryGetValue(socket.BoneName.Text.ToLower(), out var boneIndices)) - boneMatrix = Skeleton.GetBoneMatrix(boneIndices); + if (HasSkeleton && Skeleton.BonesByLoweredName.TryGetValue(socket.BoneName.Text.ToLower(), out var bone)) + boneMatrix = Skeleton.GetBoneMatrix(bone); var socketRelation = boneMatrix * worldMatrix; foreach (var info in socket.AttachedModels) diff --git a/FModel/Views/Snooper/SnimGui.cs b/FModel/Views/Snooper/SnimGui.cs index 99c3db51..6fcff481 100644 --- a/FModel/Views/Snooper/SnimGui.cs +++ b/FModel/Views/Snooper/SnimGui.cs @@ -295,6 +295,7 @@ public class SnimGui - WASD to move around - Shift to move faster - XC to zoom + - Z to animate selected model - Left Mouse Button pressed to look around - Right Click to select a model in the world diff --git a/FModel/Views/Snooper/Snooper.cs b/FModel/Views/Snooper/Snooper.cs index ea1545c9..23e7b188 100644 --- a/FModel/Views/Snooper/Snooper.cs +++ b/FModel/Views/Snooper/Snooper.cs @@ -159,6 +159,12 @@ public class Snooper : GameWindow var delta = (float) e.Time; Renderer.CameraOp.Modify(KeyboardState, delta); + if (KeyboardState.IsKeyPressed(Keys.Z)) + { + Renderer.Options.RemoveAnimations(); + Renderer.Options.AnimateMesh(true); + WindowShouldClose(true, false); + } if (KeyboardState.IsKeyPressed(Keys.Space)) Renderer.Options.Tracker.IsPaused = !Renderer.Options.Tracker.IsPaused; if (KeyboardState.IsKeyPressed(Keys.Delete))