diff --git a/CUE4Parse b/CUE4Parse
index 1fc543a0..3dbe09d4 160000
--- a/CUE4Parse
+++ b/CUE4Parse
@@ -1 +1 @@
-Subproject commit 1fc543a0434c8a2aa020443a377659fd4a908895
+Subproject commit 3dbe09d4a83b9b3628a2a340394628c39a954eb9
diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj
index e5bc0c2f..a2f525c0 100644
--- a/FModel/FModel.csproj
+++ b/FModel/FModel.csproj
@@ -110,12 +110,12 @@
-
+
-
+
diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs
index fb8c18d2..13f296f4 100644
--- a/FModel/ViewModels/CUE4ParseViewModel.cs
+++ b/FModel/ViewModels/CUE4ParseViewModel.cs
@@ -59,11 +59,11 @@ namespace FModel.ViewModels
set => SetProperty(ref _game, value);
}
- private bool _modelIsSwappingMaterial;
- public bool ModelIsSwappingMaterial
+ private bool _modelIsOverwritingMaterial;
+ public bool ModelIsOverwritingMaterial
{
- get => _modelIsSwappingMaterial;
- set => SetProperty(ref _modelIsSwappingMaterial, value);
+ get => _modelIsOverwritingMaterial;
+ set => SetProperty(ref _modelIsOverwritingMaterial, value);
}
public AbstractVfsFileProvider Provider { get; }
@@ -675,7 +675,7 @@ namespace FModel.ViewModels
}
case UStaticMesh when UserSettings.Default.PreviewStaticMeshes:
case USkeletalMesh when UserSettings.Default.PreviewSkeletalMeshes:
- case UMaterialInstance when UserSettings.Default.PreviewMaterials && !ModelIsSwappingMaterial &&
+ case UMaterialInstance when UserSettings.Default.PreviewMaterials && !ModelIsOverwritingMaterial &&
!(Game == FGame.FortniteGame && export.Owner != null && (export.Owner.Name.EndsWith($"/MI_OfferImages/{export.Name}", StringComparison.OrdinalIgnoreCase) ||
export.Owner.Name.EndsWith($"/RenderSwitch_Materials/{export.Name}", StringComparison.OrdinalIgnoreCase) ||
export.Owner.Name.EndsWith($"/MI_BPTile/{export.Name}", StringComparison.OrdinalIgnoreCase))):
@@ -687,12 +687,12 @@ namespace FModel.ViewModels
});
return true;
}
- case UMaterialInstance m when ModelIsSwappingMaterial:
+ case UMaterialInstance m when ModelIsOverwritingMaterial:
{
Application.Current.Dispatcher.InvokeAsync(() =>
{
var modelViewer = Helper.GetWindow("Model Viewer", () => new ModelViewer().Show());
- modelViewer.Swap(m);
+ modelViewer.Overwrite(m);
});
return true;
}
diff --git a/FModel/ViewModels/ModelViewerViewModel.cs b/FModel/ViewModels/ModelViewerViewModel.cs
index 1e8739cd..e2b19d43 100644
--- a/FModel/ViewModels/ModelViewerViewModel.cs
+++ b/FModel/ViewModels/ModelViewerViewModel.cs
@@ -9,12 +9,14 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media.Media3D;
+using CUE4Parse.UE4.Assets;
using CUE4Parse.UE4.Assets.Exports;
using CUE4Parse.UE4.Assets.Exports.Material;
using CUE4Parse.UE4.Assets.Exports.SkeletalMesh;
using CUE4Parse.UE4.Assets.Exports.StaticMesh;
using CUE4Parse.UE4.Assets.Exports.Texture;
using CUE4Parse.UE4.Objects.Core.Math;
+using CUE4Parse.UE4.Objects.UObject;
using CUE4Parse.Utils;
using CUE4Parse_Conversion.Materials;
using CUE4Parse_Conversion.Meshes;
@@ -284,9 +286,9 @@ namespace FModel.ViewModels
Clipboard.SetText(m.SelectedGeometry.DisplayName.TrimEnd());
}
- public async Task TryChangeSelectedMaterial(UMaterialInstance materialInstance)
+ public async Task TryOverwriteMaterial(UMaterialInstance materialInstance)
{
- if (SelectedModel is not { } model || model.SelectedGeometry is null)
+ if (SelectedModel is not { SelectedGeometry: {} geometry } model)
return false;
PBRMaterial m = null;
@@ -297,7 +299,22 @@ namespace FModel.ViewModels
});
if (m == null) return false;
- model.SelectedGeometry.Material = m;
+
+ var index = geometry.MaterialIndex;
+ var obj = new ResolvedLoadedObject(materialInstance);
+ switch (model.Export)
+ {
+ case UStaticMesh { Materials: { } } st:
+ st.Materials[index] = obj;
+ break;
+ case USkeletalMesh sk:
+ sk.Materials[index].Material = obj;
+ break;
+ case UMaterialInstance:
+ model.SwapExport(materialInstance);
+ break;
+ }
+ geometry.Material = m;
return true;
}
#endregion
@@ -317,7 +334,7 @@ namespace FModel.ViewModels
cam.Group3d.Add(new CustomMeshGeometryModel3D
{
Transform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(1,0,0), -90)),
- DisplayName = s, Geometry = builder.ToMeshGeometry3D(),
+ DisplayName = s, Geometry = builder.ToMeshGeometry3D(), MaterialIndex = 0,
Material = m, IsTransparent = isTransparent, IsRendering = isRendering
});
});
@@ -378,15 +395,15 @@ namespace FModel.ViewModels
}
}
- if (section.Material == null || !section.Material.TryLoad(out var unrealMaterial))
+ if (section.Material == null || !section.Material.TryLoad(out var o) || o is not UMaterialInterface material)
continue;
- var (m, isRendering, isTransparent) = LoadMaterial(unrealMaterial);
+ var (m, isRendering, isTransparent) = LoadMaterial(material);
Application.Current.Dispatcher.Invoke(() =>
{
cam.Group3d.Add(new CustomMeshGeometryModel3D
{
- DisplayName = FixName(section.MaterialName ?? unrealMaterial.Name),
+ DisplayName = FixName(section.MaterialName ?? material.Name), MaterialIndex = i,
Geometry = builder.ToMeshGeometry3D(), Material = m, IsTransparent = isTransparent,
IsRendering = isRendering
});
@@ -618,7 +635,7 @@ namespace FModel.ViewModels
public class ModelAndCam : ViewModel
{
- public UObject Export { get; }
+ public UObject Export { get; private set; }
public Point3D Position { get; set; }
public Vector3D LookDirection { get; set; }
public Geometry3D XAxis { get; set; }
@@ -743,6 +760,11 @@ namespace FModel.ViewModels
private int B(int x) => (x & 0xFFF8) | _table2[x & 7] ^ 7;
private int C(int x) => (x & 1) | ((x >> 2) & 2);
+ public void SwapExport(UObject e)
+ {
+ Export = e;
+ }
+
public void Dispose()
{
TriangleCount = 0;
@@ -758,5 +780,6 @@ namespace FModel.ViewModels
public class CustomMeshGeometryModel3D : MeshGeometryModel3D
{
public string DisplayName { get; set; }
+ public int MaterialIndex { get; set; }
}
}
diff --git a/FModel/Views/ModelViewer.xaml b/FModel/Views/ModelViewer.xaml
index 7d51f26e..bcf3ce38 100644
--- a/FModel/Views/ModelViewer.xaml
+++ b/FModel/Views/ModelViewer.xaml
@@ -90,11 +90,11 @@
-