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))