diff --git a/FModel/Views/Snooper/Models/Animations/Animation.cs b/FModel/Views/Snooper/Models/Animations/Animation.cs index 6cd4ee78..69391705 100644 --- a/FModel/Views/Snooper/Models/Animations/Animation.cs +++ b/FModel/Views/Snooper/Models/Animations/Animation.cs @@ -58,6 +58,6 @@ public class Animation : IDisposable public void Dispose() { - throw new NotImplementedException(); + } } diff --git a/FModel/Views/Snooper/Models/Animations/Skeleton.cs b/FModel/Views/Snooper/Models/Animations/Skeleton.cs index 1e0162a1..f37601c7 100644 --- a/FModel/Views/Snooper/Models/Animations/Skeleton.cs +++ b/FModel/Views/Snooper/Models/Animations/Skeleton.cs @@ -11,6 +11,7 @@ namespace FModel.Views.Snooper.Models.Animations; public class Skeleton : IDisposable { public readonly USkeleton UnrealSkeleton; + public readonly FReferenceSkeleton ReferenceSkeleton; public readonly Dictionary BonesIndexByName; public readonly Dictionary BonesTransformByIndex; public readonly bool IsLoaded; @@ -23,15 +24,15 @@ public class Skeleton : IDisposable BonesTransformByIndex = new Dictionary(); } - public Skeleton(FPackageIndex package, Transform transform) : this() + public Skeleton(FPackageIndex package, FReferenceSkeleton referenceSkeleton, Transform transform) : this() { UnrealSkeleton = package.Load(); if (UnrealSkeleton == null) return; - BonesIndexByName = UnrealSkeleton.ReferenceSkeleton.FinalNameToIndexMap; + ReferenceSkeleton = referenceSkeleton ?? UnrealSkeleton.ReferenceSkeleton; + BonesIndexByName = ReferenceSkeleton.FinalNameToIndexMap; BonesTransformByIndex = new Dictionary(); UpdateBoneMatrices(transform.Matrix); - IsLoaded = true; } @@ -44,8 +45,8 @@ public class Skeleton : IDisposable { foreach (var boneIndex in BonesIndexByName.Values) { - var bone = UnrealSkeleton.ReferenceSkeleton.FinalRefBonePose[boneIndex]; - var parentIndex = UnrealSkeleton.ReferenceSkeleton.FinalRefBoneInfo[boneIndex].ParentIndex; + var bone = ReferenceSkeleton.FinalRefBonePose[boneIndex]; + var parentIndex = ReferenceSkeleton.FinalRefBoneInfo[boneIndex].ParentIndex; if (!BonesTransformByIndex.TryGetValue(boneIndex, out var boneTransform)) { @@ -76,6 +77,8 @@ public class Skeleton : IDisposable public void Dispose() { - throw new NotImplementedException(); + BonesIndexByName.Clear(); + BonesTransformByIndex.Clear(); + Anim?.Dispose(); } } diff --git a/FModel/Views/Snooper/Models/Model.cs b/FModel/Views/Snooper/Models/Model.cs index a6d470d5..88ce1137 100644 --- a/FModel/Views/Snooper/Models/Model.cs +++ b/FModel/Views/Snooper/Models/Model.cs @@ -13,7 +13,6 @@ using CUE4Parse.UE4.Assets.Exports.SkeletalMesh; using CUE4Parse.UE4.Assets.Exports.StaticMesh; using CUE4Parse.UE4.Objects.Core.Math; using FModel.Extensions; -using FModel.Services; using FModel.Settings; using FModel.Views.Snooper.Buffers; using FModel.Views.Snooper.Models.Animations; @@ -25,6 +24,7 @@ namespace FModel.Views.Snooper.Models; public class Model : IDisposable { private int _handle; + private const int _LOD_INDEX = 0; private BufferObject _ebo; private BufferObject _vbo; @@ -40,7 +40,6 @@ public class Model : IDisposable public readonly string Name; public readonly string Type; public readonly bool HasVertexColors; - public readonly bool HasMorphTargets; public readonly int UvCount; public readonly FBox Box; public uint[] Indices; @@ -55,6 +54,9 @@ public class Model : IDisposable public bool HasSockets => Sockets.Length > 0; public readonly Socket[] Sockets; + public bool HasMorphTargets => Morphs.Length > 0; + public readonly Morph[] Morphs; + private string _attachedTo = string.Empty; private readonly List _attachedFor = new (); public bool IsAttached => _attachedTo.Length > 0; @@ -66,8 +68,6 @@ public class Model : IDisposable public readonly List Transforms; private Matrix4x4 _previousMatrix; - public readonly Morph[] Morphs; - public bool Show; public bool Wireframe; public bool IsSetup { get; private set; } @@ -87,7 +87,7 @@ public class Model : IDisposable } public Model(UStaticMesh export, CStaticMesh staticMesh) : this(export, staticMesh, Transform.Identity) {} - public Model(UStaticMesh export, CStaticMesh staticMesh, Transform transform) : this(export, export.Materials, null, staticMesh.LODs.Count, staticMesh.LODs[0], staticMesh.LODs[0].Verts, transform) + public Model(UStaticMesh export, CStaticMesh staticMesh, Transform transform) : this(export, export.Materials, staticMesh.LODs, transform) { Box = staticMesh.BoundingBox * Constants.SCALE_DOWN_RATIO; @@ -97,10 +97,16 @@ public class Model : IDisposable if (export.Sockets[i].Load() is not { } socket) continue; Sockets[i] = new Socket(socket, Transforms[0]); } + + Morphs = Array.Empty(); } - private Model(USkeletalMesh export, CSkeletalMesh skeletalMesh, Transform transform) : this(export, export.Materials, export.Skeleton, skeletalMesh.LODs.Count, skeletalMesh.LODs[0], skeletalMesh.LODs[0].Verts, transform) + + public Model(USkeletalMesh export, CSkeletalMesh skeletalMesh) : this(export, skeletalMesh, Transform.Identity) {} + private Model(USkeletalMesh export, CSkeletalMesh skeletalMesh, Transform transform) : this(export, export.Materials, skeletalMesh.LODs, transform) { + var t = Transforms[0]; Box = skeletalMesh.BoundingBox * Constants.SCALE_DOWN_RATIO; + Skeleton = new Skeleton(export.Skeleton, export.ReferenceSkeleton, t); var sockets = new List(); sockets.AddRange(export.Sockets); @@ -113,37 +119,29 @@ public class Model : IDisposable if (!Skeleton.BonesIndexByName.TryGetValue(socket.BoneName.Text, out var boneIndex) || !Skeleton.BonesTransformByIndex.TryGetValue(boneIndex, out var boneTransform)) - boneTransform = Transforms[0]; + boneTransform = t; Sockets[i] = new Socket(socket, boneTransform); } - } - public Model(USkeletalMesh export, CSkeletalMesh skeletalMesh) : this(export, skeletalMesh, Transform.Identity) - { - var morphTargets = export.MorphTargets; - if (morphTargets is not { Length: > 0 }) - return; - var length = morphTargets.Length; - - HasMorphTargets = true; - Morphs = new Morph[length]; + Morphs = new Morph[export.MorphTargets.Length]; for (var i = 0; i < Morphs.Length; i++) { - Morphs[i] = new Morph(Vertices, VertexSize, morphTargets[i].Load()); - ApplicationService.ApplicationView.Status.UpdateStatusLabel($"{Morphs[i].Name} ... {i}/{length}"); + Morphs[i] = new Morph(Vertices, VertexSize, export.MorphTargets[i].Load()); } - ApplicationService.ApplicationView.Status.UpdateStatusLabel(""); } - private Model(UObject export, ResolvedObject[] materials, FPackageIndex skeleton, int numLods, CBaseMeshLod lod, CMeshVertex[] vertices, Transform transform = null) : this(export) + private Model(UObject export, IReadOnlyList materials, IReadOnlyList lods, Transform transform = null) + : this(export, materials, lods[_LOD_INDEX], lods[_LOD_INDEX].Verts, lods.Count, transform) {} + private Model(UObject export, IReadOnlyList materials, IReadOnlyList lods, Transform transform = null) + : this(export, materials, lods[_LOD_INDEX], lods[_LOD_INDEX].Verts, lods.Count, transform) {} + private Model(UObject export, IReadOnlyList materials, CBaseMeshLod lod, IReadOnlyList vertices, int numLods, Transform transform = null) : this(export) { - var t = transform ?? Transform.Identity; var hasCustomUvs = lod.ExtraUV.IsValueCreated; UvCount = hasCustomUvs ? Math.Max(lod.NumTexCoords, numLods) : lod.NumTexCoords; TwoSided = lod.IsTwoSided; - Materials = new Material[materials.Length]; + Materials = new Material[materials.Count]; for (int m = 0; m < Materials.Length; m++) { if ((materials[m]?.TryLoad(out var material) ?? false) && material is UMaterialInterface unrealMaterial) @@ -156,9 +154,8 @@ public class Model : IDisposable VertexSize += 4; // + Color } - if (skeleton != null) + if (vertices is CSkelMeshVertex[]) { - Skeleton = new Skeleton(skeleton, t); VertexSize += 8; // + BoneIds + BoneWeights } @@ -169,7 +166,7 @@ public class Model : IDisposable } Vertices = new float[lod.NumVerts * VertexSize]; - for (int i = 0; i < vertices.Length; i++) + for (int i = 0; i < vertices.Count; i++) { var count = 0; var baseIndex = i * VertexSize; @@ -197,9 +194,8 @@ public class Model : IDisposable Vertices[baseIndex + count++] = color.A; } - if (HasSkeleton) + if (vert is CSkelMeshVertex skelVert) { - var skelVert = (CSkelMeshVertex) vert; var weightsHash = skelVert.UnpackWeights(); Vertices[baseIndex + count++] = skelVert.Bone[0]; Vertices[baseIndex + count++] = skelVert.Bone[1]; @@ -220,6 +216,7 @@ public class Model : IDisposable if (section.IsValid) Sections[s].SetupMaterial(Materials[section.MaterialIndex]); } + var t = transform ?? Transform.Identity; _previousMatrix = t.Matrix; AddInstance(t); } @@ -425,13 +422,15 @@ public class Model : IDisposable _vbo.Dispose(); _matrixVbo.Dispose(); _vao.Dispose(); - if (HasMorphTargets) + Skeleton?.Dispose(); + for (int socket = 0; socket < Sockets.Length; socket++) { - _morphVbo.Dispose(); - for (var morph = 0; morph < Morphs.Length; morph++) - { - Morphs[morph].Dispose(); - } + Sockets[socket]?.Dispose(); + } + if (HasMorphTargets) _morphVbo.Dispose(); + for (var morph = 0; morph < Morphs.Length; morph++) + { + Morphs[morph]?.Dispose(); } GL.DeleteProgram(_handle); diff --git a/FModel/Views/Snooper/Models/Socket.cs b/FModel/Views/Snooper/Models/Socket.cs index 0a76057e..6a0db823 100644 --- a/FModel/Views/Snooper/Models/Socket.cs +++ b/FModel/Views/Snooper/Models/Socket.cs @@ -48,6 +48,6 @@ public class Socket : IDisposable public void Dispose() { - throw new NotImplementedException(); + AttachedModels.Clear(); } }