diff --git a/CUE4Parse b/CUE4Parse
index 08709aee..d816fe61 160000
--- a/CUE4Parse
+++ b/CUE4Parse
@@ -1 +1 @@
-Subproject commit 08709aeedf2a1c0cada10f58a5aabb36cf89785e
+Subproject commit d816fe61ac8e5798d1584ea2f9871acfca0ca429
diff --git a/FModel/Settings/UserSettings.cs b/FModel/Settings/UserSettings.cs
index 0ef243fa..46f6e57a 100644
--- a/FModel/Settings/UserSettings.cs
+++ b/FModel/Settings/UserSettings.cs
@@ -424,6 +424,13 @@ namespace FModel.Settings
set => SetProperty(ref _saveMorphTargets, value);
}
+ private bool _saveMeshMaterials = true;
+ public bool SaveMeshMaterials
+ {
+ get => _saveMeshMaterials;
+ set => SetProperty(ref _saveMeshMaterials, value);
+ }
+
private bool _saveSkeletonAsMesh;
public bool SaveSkeletonAsMesh
{
diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs
index c9b00d73..e56c66ee 100644
--- a/FModel/ViewModels/CUE4ParseViewModel.cs
+++ b/FModel/ViewModels/CUE4ParseViewModel.cs
@@ -896,6 +896,7 @@ public class CUE4ParseViewModel : ViewModel
case UWorld when isNone && UserSettings.Default.PreviewWorlds:
case UStaticMesh when isNone && UserSettings.Default.PreviewStaticMeshes:
case USkeletalMesh when isNone && UserSettings.Default.PreviewSkeletalMeshes:
+ case USkeleton when isNone && UserSettings.Default.SaveSkeletonAsMesh:
case UMaterialInstance when isNone && UserSettings.Default.PreviewMaterials && !ModelIsOverwritingMaterial &&
!(Provider.InternalGameName.Equals("FortniteGame", StringComparison.OrdinalIgnoreCase) && export.Owner != null &&
(export.Owner.Name.EndsWith($"/MI_OfferImages/{export.Name}", StringComparison.OrdinalIgnoreCase) ||
@@ -984,7 +985,8 @@ public class CUE4ParseViewModel : ViewModel
TextureFormat = UserSettings.Default.TextureExportFormat,
SocketFormat = UserSettings.Default.SocketExportFormat,
Platform = UserSettings.Default.CurrentDir.TexturePlatform,
- ExportMorphTargets = UserSettings.Default.SaveMorphTargets
+ ExportMorphTargets = UserSettings.Default.SaveMorphTargets,
+ ExportMaterials = UserSettings.Default.SaveMeshMaterials
};
var toSave = new Exporter(export, exportOptions);
diff --git a/FModel/Views/SettingsView.xaml b/FModel/Views/SettingsView.xaml
index f546b1c7..f8176926 100644
--- a/FModel/Views/SettingsView.xaml
+++ b/FModel/Views/SettingsView.xaml
@@ -315,6 +315,7 @@
+
@@ -386,20 +387,25 @@
IsChecked="{Binding PreviewWorlds, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}"
Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" Margin="0 5 0 5"/>
-
+
+
+
+
-
-
+
-
+
-
-
+
@@ -408,8 +414,8 @@
-
-
+
diff --git a/FModel/Views/Snooper/Models/SkeletalModel.cs b/FModel/Views/Snooper/Models/SkeletalModel.cs
index 1e84d604..92ea0b80 100644
--- a/FModel/Views/Snooper/Models/SkeletalModel.cs
+++ b/FModel/Views/Snooper/Models/SkeletalModel.cs
@@ -1,7 +1,9 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using CUE4Parse_Conversion.Meshes.PSK;
using CUE4Parse.UE4.Assets.Exports.Animation;
using CUE4Parse.UE4.Assets.Exports.SkeletalMesh;
+using CUE4Parse.UE4.Objects.Core.Math;
using CUE4Parse.UE4.Objects.UObject;
using FModel.Views.Snooper.Animations;
using FModel.Views.Snooper.Buffers;
@@ -53,6 +55,26 @@ public class SkeletalModel : UModel
}
}
+ public SkeletalModel(USkeleton export, FBox box) : base(export)
+ {
+ Indices = Array.Empty();
+ Materials = Array.Empty();
+ Vertices = Array.Empty();
+ Sections = Array.Empty();
+ AddInstance(Transform.Identity);
+
+ Box = box * Constants.SCALE_DOWN_RATIO;
+ Morphs = new List();
+ Skeleton = new Skeleton(export.ReferenceSkeleton);
+ Skeleton.Name = export.Name;
+
+ for (int i = 0; i < export.Sockets.Length; i++)
+ {
+ if (export.Sockets[i].Load() is not { } socket) continue;
+ Sockets.Add(new Socket(socket));
+ }
+ }
+
public override void Setup(Options options)
{
base.Setup(options);
diff --git a/FModel/Views/Snooper/Models/UModel.cs b/FModel/Views/Snooper/Models/UModel.cs
index b73b0c84..fc4302be 100644
--- a/FModel/Views/Snooper/Models/UModel.cs
+++ b/FModel/Views/Snooper/Models/UModel.cs
@@ -365,7 +365,8 @@ public abstract class UModel : IRenderableModel
TextureFormat = UserSettings.Default.TextureExportFormat,
SocketFormat = UserSettings.Default.SocketExportFormat,
Platform = UserSettings.Default.CurrentDir.TexturePlatform,
- ExportMorphTargets = UserSettings.Default.SaveMorphTargets
+ ExportMorphTargets = UserSettings.Default.SaveMorphTargets,
+ ExportMaterials = UserSettings.Default.SaveMeshMaterials
};
var toSave = new Exporter(_export, exportOptions);
return toSave.TryWriteToDir(new DirectoryInfo(UserSettings.Default.ModelDirectory), out label, out savedFilePath);
diff --git a/FModel/Views/Snooper/Renderer.cs b/FModel/Views/Snooper/Renderer.cs
index 18a64aa3..b66ea124 100644
--- a/FModel/Views/Snooper/Renderer.cs
+++ b/FModel/Views/Snooper/Renderer.cs
@@ -87,6 +87,9 @@ public class Renderer : IDisposable
case USkeletalMesh sk:
LoadSkeletalMesh(sk);
break;
+ case USkeleton skel:
+ LoadSkeleton(skel);
+ break;
case UMaterialInstance mi:
LoadMaterialInstance(mi);
break;
@@ -349,6 +352,17 @@ public class Renderer : IDisposable
Options.SelectModel(guid);
}
+ private void LoadSkeleton(USkeleton original)
+ {
+ var guid = original.Guid;
+ if (Options.Models.ContainsKey(guid) || !original.TryConvert(out _, out var box)) return;
+
+ var fakeSkeletalModel = new SkeletalModel(original, box);
+ Options.Models[guid] = fakeSkeletalModel;
+ Options.SelectModel(guid);
+ IsSkeletonTreeOpen = true;
+ }
+
private void LoadMaterialInstance(UMaterialInstance original)
{
if (!Utils.TryLoadObject("Engine/Content/BasicShapes/Cube.Cube", out UStaticMesh editorCube))