saving this before refactoring

This commit is contained in:
4sval 2023-02-16 16:55:48 +01:00
parent ad7dc46a0a
commit 8438591839
5 changed files with 82 additions and 26 deletions

View File

@ -11,6 +11,4 @@ public class BoneIndice
public int ParentTrackIndex = -1; // bone index of the first tracked parent bone
public bool HasTrack => TrackIndex > -1;
public bool HasParentTrack => ParentTrackIndex > -1;
public override string ToString() => $"{ParentBoneIndex} -> {BoneIndex}{(HasTrack ? $" ({ParentTrackIndex} -> {TrackIndex})" : "")}";
}

View File

@ -83,8 +83,8 @@ public class Model : IDisposable
public bool HasSkeleton => Skeleton != null;
public readonly Skeleton Skeleton;
public bool HasSockets => Sockets.Length > 0;
public readonly Socket[] Sockets;
public bool HasSockets => Sockets.Count > 0;
public readonly List<Socket> Sockets;
public bool HasMorphTargets => Morphs.Length > 0;
public readonly Morph[] Morphs;
@ -115,7 +115,7 @@ public class Model : IDisposable
Type = export.ExportType;
UvCount = 1;
Box = new FBox(new FVector(-2f), new FVector(2f));
Sockets = Array.Empty<Socket>();
Sockets = new List<Socket>();
Morphs = Array.Empty<Morph>();
Transforms = new List<Transform>();
}
@ -125,11 +125,10 @@ public class Model : IDisposable
{
Box = staticMesh.BoundingBox * Constants.SCALE_DOWN_RATIO;
Sockets = new Socket[export.Sockets.Length];
for (int i = 0; i < Sockets.Length; i++)
for (int i = 0; i < export.Sockets.Length; i++)
{
if (export.Sockets[i].Load<UStaticMeshSocket>() is not { } socket) continue;
Sockets[i] = new Socket(socket);
Sockets.Add(new Socket(socket));
}
}
@ -147,11 +146,10 @@ public class Model : IDisposable
sockets.AddRange(skeleton.Sockets);
}
Sockets = new Socket[sockets.Count];
for (int i = 0; i < Sockets.Length; i++)
for (int i = 0; i < sockets.Count; i++)
{
if (sockets[i].Load<USkeletalMeshSocket>() is not { } socket) continue;
Sockets[i] = new Socket(socket);
Sockets.Add(new Socket(socket));
}
Morphs = new Morph[export.MorphTargets.Length];
@ -453,10 +451,11 @@ public class Model : IDisposable
_matrixVbo.Dispose();
_vao.Dispose();
Skeleton?.Dispose();
for (int socket = 0; socket < Sockets.Length; socket++)
for (int socket = 0; socket < Sockets.Count; socket++)
{
Sockets[socket]?.Dispose();
}
Sockets.Clear();
if (HasMorphTargets) _morphVbo.Dispose();
for (var morph = 0; morph < Morphs.Length; morph++)
{

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using CUE4Parse.UE4.Assets.Exports.SkeletalMesh;
using CUE4Parse.UE4.Assets.Exports.StaticMesh;
@ -21,6 +21,13 @@ public class Socket : IDisposable
AttachedModels = new List<FGuid>();
}
public Socket(string name, FName boneName, Transform transform) : this()
{
Name = name;
BoneName = boneName;
Transform = transform;
}
public Socket(UStaticMeshSocket socket) : this()
{
Name = socket.SocketName.Text;

View File

@ -93,16 +93,60 @@ public class Renderer : IDisposable
public void Animate(UObject anim)
{
if (!Options.TryGetModel(out var model) || !model.HasSkeleton)
if (!Options.TryGetModel(out var model))
return;
Animate(anim, model);
}
private void Animate(UObject anim, Model model)
{
if (!model.HasSkeleton) return;
switch (anim)
{
case UAnimSequence animSequence when animSequence.Skeleton.TryLoad(out USkeleton skeleton):
model.Skeleton.SetAnimation(skeleton.ConvertAnims(animSequence), AnimateWithRotationOnly);
break;
case UAnimMontage animMontage when animMontage.Skeleton.TryLoad(out USkeleton skeleton):
// for (int i = 0; i < skeleton.Sockets.Length; i++)
// {
// if (skeleton.Sockets[i].Load<USkeletalMeshSocket>() is not { } socket) continue;
// model.Sockets.Add(new Socket(socket));
// }
model.Skeleton.SetAnimation(skeleton.ConvertAnims(animMontage), AnimateWithRotationOnly);
foreach (var notifyEvent in animMontage.Notifies)
{
if (!notifyEvent.NotifyStateClass.TryLoad(out UObject notifyClass) ||
!notifyClass.TryGetValue(out FPackageIndex meshProp, "SkeletalMeshProp", "StaticMeshProp", "Mesh") ||
!meshProp.TryLoad(out UObject export)) continue;
FGuid guid = export switch
{
UStaticMesh st => LoadStaticMesh(st, false),
USkeletalMesh sk => LoadSkeletalMesh(sk, false),
_ => throw new ArgumentException()
};
if (!Options.TryGetModel(guid, out var addedModel))
continue;
if (notifyClass.TryGetValue(out UObject skeletalMeshPropAnimation, "SkeletalMeshPropAnimation"))
Animate(skeletalMeshPropAnimation, addedModel);
if (notifyClass.TryGetValue(out FName socketName, "SocketName"))
{
var t = Transform.Identity;
if (notifyClass.TryGetValue(out FVector location, "Location"))
t.Position = location * Constants.SCALE_DOWN_RATIO;
if (notifyClass.TryGetValue(out FRotator rotation, "RotationOffset", "Rotation"))
t.Rotation = rotation.Quaternion();
if (notifyClass.TryGetValue(out FVector scale, "Scale"))
t.Scale = scale;
var s = new Socket("hello", socketName, t);
model.Sockets.Add(s);
s.AttachedModels.Add(guid);
addedModel.AttachModel(model, s);
}
}
break;
case UAnimComposite animComposite when animComposite.Skeleton.TryLoad(out USkeleton skeleton):
model.Skeleton.SetAnimation(skeleton.ConvertAnims(animComposite), AnimateWithRotationOnly);
@ -168,32 +212,40 @@ public class Renderer : IDisposable
Picking.Render(viewMatrix, projMatrix, Options.Models);
}
private void LoadStaticMesh(UStaticMesh original)
private FGuid LoadStaticMesh(UStaticMesh original, bool select = true)
{
var guid = original.LightingGuid;
if (Options.TryGetModel(guid, out var model))
{
model.AddInstance(Transform.Identity);
Application.Current.Dispatcher.Invoke(() => model.SetupInstances());
return;
return guid;
}
if (!original.TryConvert(out var mesh))
return;
return guid;
Options.Models[guid] = new Model(original, mesh);
Options.SelectModel(guid);
SetupCamera(Options.Models[guid].Box);
if (select)
{
Options.SelectModel(guid);
SetupCamera(Options.Models[guid].Box);
}
return guid;
}
private void LoadSkeletalMesh(USkeletalMesh original)
private FGuid LoadSkeletalMesh(USkeletalMesh original, bool select = true)
{
var guid = new FGuid((uint) original.GetFullName().GetHashCode());
if (Options.Models.ContainsKey(guid) || !original.TryConvert(out var mesh)) return;
if (Options.Models.ContainsKey(guid) || !original.TryConvert(out var mesh)) return guid;
Options.Models[guid] = new Model(original, mesh);
Options.SelectModel(guid);
SetupCamera(Options.Models[guid].Box);
if (select)
{
Options.SelectModel(guid);
SetupCamera(Options.Models[guid].Box);
}
return guid;
}
private void LoadMaterialInstance(UMaterialInstance original)

View File

@ -411,7 +411,7 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio
foreach (var model in s.Renderer.Options.Models.Values)
{
if (!model.HasSockets || model.IsSelected) continue;
if (ImGui.TreeNode($"{model.Name} [{model.Sockets.Length}]"))
if (ImGui.TreeNode($"{model.Name} [{model.Sockets.Count}]"))
{
var i = 0;
foreach (var socket in model.Sockets)
@ -460,7 +460,7 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio
{
Layout("Two Sided");ImGui.Text($" : {model.TwoSided}");
}
Layout("Sockets");ImGui.Text($" : x{model.Sockets.Length}");
Layout("Sockets");ImGui.Text($" : x{model.Sockets.Count}");
ImGui.EndTable();
});