diff --git a/CUE4Parse b/CUE4Parse
index cebbff90..35f6d437 160000
--- a/CUE4Parse
+++ b/CUE4Parse
@@ -1 +1 @@
-Subproject commit cebbff9035b292e81493f8b94c19d39394be2618
+Subproject commit 35f6d437eb0f03855d30265a6214794810868e6a
diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj
index c311a842..ef487add 100644
--- a/FModel/FModel.csproj
+++ b/FModel/FModel.csproj
@@ -101,8 +101,8 @@
-
-
+
+
@@ -120,8 +120,8 @@
-
-
+
+
@@ -132,7 +132,6 @@
-
@@ -238,4 +237,10 @@
+
+
+ Always
+
+
+
diff --git a/FModel/Resources/imgui.frag b/FModel/Resources/imgui.frag
deleted file mode 100644
index 5a705b23..00000000
--- a/FModel/Resources/imgui.frag
+++ /dev/null
@@ -1,13 +0,0 @@
-#version 330
-
-layout (location = 0) out vec4 Out_Color;
-
-in vec2 Frag_UV;
-in vec4 Frag_Color;
-
-uniform sampler2D Texture;
-
-void main()
-{
- Out_Color = Frag_Color * texture(Texture, Frag_UV.st);
-}
diff --git a/FModel/Resources/imgui.vert b/FModel/Resources/imgui.vert
deleted file mode 100644
index 284ed1a5..00000000
--- a/FModel/Resources/imgui.vert
+++ /dev/null
@@ -1,17 +0,0 @@
-#version 330
-
-layout (location = 0) in vec2 Position;
-layout (location = 1) in vec2 UV;
-layout (location = 2) in vec4 Color;
-
-uniform mat4 ProjMtx;
-
-out vec2 Frag_UV;
-out vec4 Frag_Color;
-
-void main()
-{
- Frag_UV = UV;
- Frag_Color = Color;
- gl_Position = ProjMtx * vec4(Position.xy,0,1);
-}
diff --git a/FModel/Resources/outline.frag b/FModel/Resources/outline.frag
new file mode 100644
index 00000000..26817aa5
--- /dev/null
+++ b/FModel/Resources/outline.frag
@@ -0,0 +1,8 @@
+#version 330
+
+out vec4 FragColor;
+
+void main()
+{
+ FragColor = vec4(0.929, 0.588, 0.196, 0.2);
+}
diff --git a/FModel/Resources/outline.vert b/FModel/Resources/outline.vert
new file mode 100644
index 00000000..0d2d8acc
--- /dev/null
+++ b/FModel/Resources/outline.vert
@@ -0,0 +1,15 @@
+#version 330 core
+
+layout (location = 0) in vec3 vPos;
+layout (location = 1) in vec3 vNormal;
+layout (location = 6) in mat4 vInstanceMatrix;
+
+uniform mat4 uView;
+uniform mat4 uProjection;
+
+void main()
+{
+ float scaleFactor = 0.005;
+ vec3 scaleVertex = vPos + vNormal * scaleFactor;
+ gl_Position = uProjection * uView * vInstanceMatrix * vec4(scaleVertex, 1.0);
+}
diff --git a/FModel/ViewModels/ApplicationViewModel.cs b/FModel/ViewModels/ApplicationViewModel.cs
index 9564f56c..7438c6a6 100644
--- a/FModel/ViewModels/ApplicationViewModel.cs
+++ b/FModel/ViewModels/ApplicationViewModel.cs
@@ -72,7 +72,6 @@ public class ApplicationViewModel : ViewModel
public AesManagerViewModel AesManager { get; }
public AudioPlayerViewModel AudioPlayer { get; }
public MapViewerViewModel MapViewer { get; }
- public ModelViewerViewModel ModelViewer { get; }
private OodleCompressor _oodle;
public ApplicationViewModel()
@@ -94,7 +93,6 @@ public class ApplicationViewModel : ViewModel
AesManager = new AesManagerViewModel(CUE4Parse);
MapViewer = new MapViewerViewModel(CUE4Parse);
AudioPlayer = new AudioPlayerViewModel();
- ModelViewer = new ModelViewerViewModel(CUE4Parse.Game);
Status = EStatusKind.Ready;
}
diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs
index 1e2dc2f9..7586ab9f 100644
--- a/FModel/ViewModels/CUE4ParseViewModel.cs
+++ b/FModel/ViewModels/CUE4ParseViewModel.cs
@@ -763,12 +763,7 @@ public class CUE4ParseViewModel : ViewModel
}
case UMaterialInstance m when ModelIsOverwritingMaterial:
{
- Application.Current.Dispatcher.Invoke(delegate
- {
- var modelViewer = Helper.GetWindow("Model Viewer", () => new ModelViewer().Show());
- modelViewer.Overwrite(m);
- });
- return true;
+ throw new NotImplementedException();
}
case UStaticMesh when UserSettings.Default.SaveStaticMeshes:
case USkeletalMesh when UserSettings.Default.SaveSkeletalMeshes:
diff --git a/FModel/ViewModels/ModelViewerViewModel.cs b/FModel/ViewModels/ModelViewerViewModel.cs
deleted file mode 100644
index 34018f77..00000000
--- a/FModel/ViewModels/ModelViewerViewModel.cs
+++ /dev/null
@@ -1,767 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.ComponentModel;
-using System.IO;
-using System.Linq;
-using System.Numerics;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Data;
-using System.Windows.Media.Media3D;
-using CUE4Parse_Conversion;
-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.Utils;
-using CUE4Parse_Conversion.Materials;
-using CUE4Parse_Conversion.Meshes;
-using CUE4Parse_Conversion.Meshes.glTF;
-using CUE4Parse_Conversion.Meshes.PSK;
-using CUE4Parse_Conversion.Textures;
-using FModel.Framework;
-using FModel.Services;
-using FModel.Settings;
-using FModel.Views.Resources.Controls;
-using HelixToolkit.SharpDX.Core;
-using HelixToolkit.Wpf.SharpDX;
-using Ookii.Dialogs.Wpf;
-using Serilog;
-using SharpDX;
-using SharpGLTF.Geometry;
-using SharpGLTF.Geometry.VertexTypes;
-using SharpGLTF.Scenes;
-using SharpGLTF.Schema2;
-using SharpGLTF.Transforms;
-using SkiaSharp;
-using Camera = HelixToolkit.Wpf.SharpDX.Camera;
-using Exporter = CUE4Parse_Conversion.Exporter;
-using Geometry3D = HelixToolkit.SharpDX.Core.Geometry3D;
-using PerspectiveCamera = HelixToolkit.Wpf.SharpDX.PerspectiveCamera;
-using Vector2 = SharpDX.Vector2;
-using Vector3 = SharpDX.Vector3;
-using VERTEX = SharpGLTF.Geometry.VertexTypes.VertexPositionNormalTangent;
-
-namespace FModel.ViewModels;
-
-public class ModelViewerViewModel : ViewModel
-{
- private ThreadWorkerViewModel _threadWorkerView => ApplicationService.ThreadWorkerView;
-
- private EffectsManager _effectManager;
- public EffectsManager EffectManager
- {
- get => _effectManager;
- set => SetProperty(ref _effectManager, value);
- }
-
- private Camera _cam;
- public Camera Cam
- {
- get => _cam;
- set => SetProperty(ref _cam, value);
- }
-
- private ModelAndCam _selectedModel; // selected mesh
- public ModelAndCam SelectedModel
- {
- get => _selectedModel;
- set => SetProperty(ref _selectedModel, value);
- }
-
- private readonly ObservableCollection _loadedModels; // mesh list
- public ICollectionView LoadedModelsView { get; }
-
- private bool _appendMode;
- public bool AppendMode
- {
- get => _appendMode;
- set => SetProperty(ref _appendMode, value);
- }
-
- public bool CanAppend => SelectedModel != null;
-
- public TextureModel HDRi { get; private set; }
-
- private readonly FGame _game;
- private readonly int[] _facesIndex = { 1, 0, 2 };
-
- public ModelViewerViewModel(FGame game)
- {
- _game = game;
- _loadedModels = new ObservableCollection();
-
- EffectManager = new DefaultEffectsManager();
- LoadedModelsView = new ListCollectionView(_loadedModels);
- Cam = new PerspectiveCamera { NearPlaneDistance = 0.1, FarPlaneDistance = double.PositiveInfinity, FieldOfView = 90 };
- LoadHDRi();
- }
-
- private void LoadHDRi()
- {
- var cubeMap = Application.GetResourceStream(new Uri("/FModel;component/Resources/approaching_storm_cubemap.dds", UriKind.Relative));
- HDRi = TextureModel.Create(cubeMap?.Stream);
- }
-
- public void LoadExport(UObject export)
- {
-#if DEBUG
- LoadHDRi();
-#endif
-
- ModelAndCam p;
- if (AppendMode && CanAppend)
- {
- p = SelectedModel;
- _loadedModels.Add(new ModelAndCam(export) { IsVisible = false });
- }
- else
- {
- p = new ModelAndCam(export);
- _loadedModels.Add(p);
- }
-
- switch (export)
- {
- case UStaticMesh st:
- LoadStaticMesh(st, p);
- break;
- case USkeletalMesh sk:
- LoadSkeletalMesh(sk, p);
- break;
- case UMaterialInstance mi:
- LoadMaterialInstance(mi, p);
- break;
- default:
- throw new ArgumentOutOfRangeException(nameof(export));
- }
-
- if (AppendMode && CanAppend) return;
- SelectedModel = p;
- Cam.UpDirection = new Vector3D(0, 1, 0);
- Cam.Position = p.Position;
- Cam.LookDirection = p.LookDirection;
- }
-
- #region PUBLIC METHODS
-
- public void RenderingToggle()
- {
- if (SelectedModel == null) return;
- SelectedModel.RenderingToggle = !SelectedModel.RenderingToggle;
- }
-
- public void WirefreameToggle()
- {
- if (SelectedModel == null) return;
- SelectedModel.WireframeToggle = !SelectedModel.WireframeToggle;
- }
-
- public void MaterialColorToggle()
- {
- if (SelectedModel == null) return;
- SelectedModel.ShowMaterialColor = !SelectedModel.ShowMaterialColor;
- }
-
- public void DiffuseOnlyToggle()
- {
- if (SelectedModel == null) return;
- SelectedModel.DiffuseOnlyToggle = !SelectedModel.DiffuseOnlyToggle;
- }
-
- public void FocusOnSelectedMesh()
- {
- Cam.AnimateTo(SelectedModel.Position, SelectedModel.LookDirection, new Vector3D(0, 1, 0), 500);
- }
-
- public async Task SaveLoadedModels()
- {
- if (_loadedModels.Count < 1) return;
-
- var folderBrowser = new VistaFolderBrowserDialog { ShowNewFolderButton = true };
- if (folderBrowser.ShowDialog() == false) return;
-
- await _threadWorkerView.Begin(_ =>
- {
- var exportOptions = new ExporterOptions
- {
- TextureFormat = UserSettings.Default.TextureExportFormat,
- LodFormat = UserSettings.Default.LodExportFormat,
- MeshFormat = UserSettings.Default.MeshExportFormat,
- Platform = UserSettings.Default.OverridedPlatform,
- ExportMorphTargets = UserSettings.Default.SaveMorphTargets
- };
- foreach (var model in _loadedModels)
- {
- var toSave = new Exporter(model.Export, exportOptions);
- if (toSave.TryWriteToDir(new DirectoryInfo(folderBrowser.SelectedPath), out var savedFileName))
- {
- Log.Information("Successfully saved {FileName}", savedFileName);
- FLogger.AppendInformation();
- FLogger.AppendText($"Successfully saved {savedFileName}", Constants.WHITE, true);
- }
- else
- {
- Log.Error("{FileName} could not be saved", savedFileName);
- FLogger.AppendError();
- FLogger.AppendText($"Could not save '{savedFileName}'", Constants.WHITE, true);
- }
- }
- });
- }
-
- public void SaveAsScene()
- {
- if (_loadedModels.Count < 1) return;
-
- var fileBrowser = new VistaSaveFileDialog
- {
- Title = "Save Loaded Models As...",
- DefaultExt = ".glb",
- Filter = "glTF Binary File (*.glb)|*.glb|glTF ASCII File (*.gltf)|*.gltf|All Files(*.*)|*.*",
- AddExtension = true,
- OverwritePrompt = true,
- CheckPathExists = true
- };
-
- if (fileBrowser.ShowDialog() == false || string.IsNullOrEmpty(fileBrowser.FileName)) return;
-
- var sceneBuilder = new SceneBuilder();
- var materialExports = new List();
- foreach (var model in _loadedModels)
- {
- switch (model.Export)
- {
- case UStaticMesh sm:
- {
- var mesh = new MeshBuilder(sm.Name);
- if (sm.TryConvert(out var convertedMesh) && convertedMesh.LODs.Count > 0)
- {
- var lod = convertedMesh.LODs.First();
- for (var i = 0; i < lod.Sections.Value.Length; i++)
- {
- Gltf.ExportStaticMeshSections(i, lod, lod.Sections.Value[i], materialExports, mesh);
- }
-
- sceneBuilder.AddRigidMesh(mesh, AffineTransform.Identity);
- }
-
- break;
- }
- case USkeletalMesh sk:
- {
- var mesh = new MeshBuilder(sk.Name);
-
- if (sk.TryConvert(out var convertedMesh) && convertedMesh.LODs.Count > 0)
- {
- var lod = convertedMesh.LODs.First();
- for (var i = 0; i < lod.Sections.Value.Length; i++)
- {
- Gltf.ExportSkelMeshSections(i, lod, lod.Sections.Value[i], materialExports, mesh);
- }
-
- var armatureNodeBuilder = new NodeBuilder(sk.Name + ".ao");
- var armature = Gltf.CreateGltfSkeleton(convertedMesh.RefSkeleton, armatureNodeBuilder);
- sceneBuilder.AddSkinnedMesh(mesh, Matrix4x4.Identity, armature);
- }
-
- break;
- }
- }
- }
-
- var scene = sceneBuilder.ToGltf2();
- var fileName = fileBrowser.FileName;
- if (fileName.EndsWith(".glb", StringComparison.OrdinalIgnoreCase))
- scene.SaveGLB(fileName);
- else if (fileName.EndsWith(".gltf", StringComparison.OrdinalIgnoreCase))
- scene.SaveGLTF(fileName);
- else if (fileName.EndsWith(".obj", StringComparison.OrdinalIgnoreCase))
- scene.SaveAsWavefront(fileName);
- else
- throw new ArgumentOutOfRangeException(nameof(fileName), $@"Unknown file format {fileName.SubstringAfterWithLast('.')}");
-
- if (!CheckIfSaved(fileName)) return;
- foreach (var materialExport in materialExports)
- {
- materialExport.TryWriteToDir(new DirectoryInfo(StringUtils.SubstringBeforeWithLast(fileName, '\\')), out _);
- }
- }
-
- public void CopySelectedMaterialName()
- {
- if (SelectedModel is not { } m || m.SelectedGeometry is null)
- return;
-
- Clipboard.SetText(m.SelectedGeometry.DisplayName.TrimEnd());
- }
-
- #endregion
-
- public bool TryOverwriteMaterial(UMaterialInstance materialInstance)
- {
- if (SelectedModel?.SelectedGeometry == null || _loadedModels.Count < 1) return false;
-
- var (m, _, _) = LoadMaterial(materialInstance);
-
- var obj = new ResolvedLoadedObject(materialInstance);
- switch (_loadedModels[SelectedModel.SelectedGeometry.ExportIndex].Export)
- {
- case UStaticMesh { Materials: { } } st:
- st.Materials[SelectedModel.SelectedGeometry.MaterialIndex] = obj;
- break;
- case USkeletalMesh sk:
- sk.Materials[SelectedModel.SelectedGeometry.MaterialIndex].Material = obj;
- break;
- case UMaterialInstance:
- SelectedModel.SwapExport(materialInstance);
- break;
- }
-
- SelectedModel.SelectedGeometry.Material = m;
- return m != null;
- }
-
- private void LoadMaterialInstance(UMaterialInstance materialInstance, ModelAndCam cam)
- {
- var builder = new MeshBuilder();
- builder.AddBox(Vector3.Zero, 10, 10, 10);
- cam.TriangleCount = 12; // no need to count
-
- SetupCameraAndAxis(new FBox(new FVector(-8), new FVector(8)), cam);
- var (m, isRendering, isTransparent) = LoadMaterial(materialInstance);
-
- cam.Group3d.Add(new CustomMeshGeometryModel3D
- {
- Transform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 1, 0), -45)),
- DisplayName = materialInstance.Name, Geometry = builder.ToMeshGeometry3D(), MaterialIndex = 0,
- Material = m, IsTransparent = isTransparent, IsRendering = isRendering, ExportIndex = _loadedModels.Count - 1
- });
- }
-
- private void LoadStaticMesh(UStaticMesh mesh, ModelAndCam cam)
- {
- if (!mesh.TryConvert(out var convertedMesh) || convertedMesh.LODs.Count <= 0)
- {
- return;
- }
-
- SetupCameraAndAxis(convertedMesh.BoundingBox, cam);
- foreach (var lod in convertedMesh.LODs.Where(lod => !lod.SkipLod))
- {
- PushLod(lod.Sections.Value, lod.Verts, lod.Indices.Value, cam);
- break;
- }
- }
-
- private void LoadSkeletalMesh(USkeletalMesh mesh, ModelAndCam cam)
- {
- if (!mesh.TryConvert(out var convertedMesh) || convertedMesh.LODs.Count <= 0)
- {
- return;
- }
-
- SetupCameraAndAxis(convertedMesh.BoundingBox, cam);
- foreach (var lod in convertedMesh.LODs.Where(lod => !lod.SkipLod))
- {
- PushLod(lod.Sections.Value, lod.Verts, lod.Indices.Value, cam);
- break;
- }
- }
-
- private void PushLod(CMeshSection[] sections, CMeshVertex[] verts, FRawStaticIndexBuffer indices, ModelAndCam cam)
- {
- for (var i = 0; i < sections.Length; i++) // each section is a mesh part with its own material
- {
- var section = sections[i];
- var builder = new MeshBuilder();
- cam.TriangleCount += section.NumFaces; // NumFaces * 3 (triangle) = next section FirstIndex
-
- for (var j = 0; j < section.NumFaces; j++) // draw a triangle for each face
- {
- foreach (var t in _facesIndex) // triangle face 1 then 0 then 2
- {
- var id = section.FirstIndex + j * 3 + t;
- var vert = verts[indices[id]];
- var p = new Vector3(vert.Position.X, vert.Position.Z, vert.Position.Y); // up direction is Y
- var n = new Vector3(vert.Normal.X, vert.Normal.Z, vert.Normal.Y);
- n.Normalize();
-
- builder.AddNode(p, n, new Vector2(vert.UV.U, vert.UV.V));
- builder.TriangleIndices.Add(j * 3 + t); // one mesh part is "j * 3 + t" use "id" if you're building the full mesh
- }
- }
-
- if (section.Material == null || !section.Material.TryLoad(out var o) || o is not UMaterialInterface material)
- {
- cam.Group3d.Add(new CustomMeshGeometryModel3D
- {
- DisplayName = section.Material?.Name.ToString() ?? $"material_{section.MaterialIndex}", MaterialIndex = section.MaterialIndex,
- Geometry = builder.ToMeshGeometry3D(), Material = new PBRMaterial(), IsTransparent = false,
- IsRendering = true, ExportIndex = _loadedModels.Count - 1
- });
- }
- else
- {
- var (m, isRendering, isTransparent) = LoadMaterial(material);
- cam.Group3d.Add(new CustomMeshGeometryModel3D
- {
- DisplayName = material.Name, MaterialIndex = section.MaterialIndex,
- Geometry = builder.ToMeshGeometry3D(), Material = m, IsTransparent = isTransparent,
- IsRendering = isRendering, ExportIndex = _loadedModels.Count - 1
- });
- }
- }
- }
-
- private (PBRMaterial material, bool isRendering, bool isTransparent) LoadMaterial(UMaterialInterface unrealMaterial)
- {
- var m = new PBRMaterial { RenderShadowMap = true, EnableAutoTangent = true, RenderEnvironmentMap = true };
- var parameters = new CMaterialParams();
- unrealMaterial.GetParams(parameters);
-
- var isRendering = !parameters.IsNull;
- if (isRendering)
- {
- if (!parameters.HasTopDiffuseTexture && parameters.DiffuseColor is { A: > 0 } diffuseColor)
- {
- m.AlbedoColor = new Color4(diffuseColor.R, diffuseColor.G, diffuseColor.B, diffuseColor.A);
- }
- else if (parameters.Diffuse is UTexture2D diffuse)
- {
- m.AlbedoMap = new TextureModel(diffuse.Decode(UserSettings.Default.OverridedPlatform)?.Encode(SKEncodedImageFormat.Png, 100).AsStream());
- }
-
- if (parameters.Normal is UTexture2D normal)
- {
- m.NormalMap = new TextureModel(normal.Decode(UserSettings.Default.OverridedPlatform)?.Encode(SKEncodedImageFormat.Png, 100).AsStream());
- }
-
- if (parameters.Specular is UTexture2D specular)
- {
- var mip = specular.GetFirstMip();
- var platform = UserSettings.Default.OverridedPlatform;
- TextureDecoder.DecodeTexture(mip, specular.Format, specular.isNormalMap, platform, out var data, out var colorType);
-
- switch (_game)
- {
- case FGame.FortniteGame:
- {
- // Fortnite's Specular Texture Channels
- // R Specular
- // G Metallic
- // B Roughness
- unsafe
- {
- var offset = 0;
- fixed (byte* d = data)
- {
- for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
- {
- d[offset] = 0;
- (d[offset + 1], d[offset + 2]) = (d[offset + 2], d[offset + 1]); // swap G and B
- offset += 4;
- }
- }
- }
-
- parameters.RoughnessValue = 1;
- parameters.MetallicValue = 1;
- break;
- }
- case FGame.ShooterGame:
- {
- var packedPBRType = specular.Name[(specular.Name.LastIndexOf('_') + 1)..];
- switch (packedPBRType)
- {
- case "MRAE": // R: Metallic, G: AO (0-127) & Emissive (128-255), B: Roughness (Character PBR)
- unsafe
- {
- var offset = 0;
- fixed (byte* d = data)
- {
- for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
- {
- (d[offset], d[offset + 2]) = (d[offset + 2], d[offset]); // swap R and B
- (d[offset], d[offset + 1]) = (d[offset + 1], d[offset]); // swap R and G
- offset += 4;
- }
- }
- }
-
- break;
- case "MRAS": // R: Metallic, B: Roughness, B: AO, A: Specular (Legacy PBR)
- case "MRA": // R: Metallic, B: Roughness, B: AO (Environment PBR)
- case "MRS": // R: Metallic, G: Roughness, B: Specular (Weapon PBR)
- unsafe
- {
- var offset = 0;
- fixed (byte* d = data)
- {
- for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
- {
- (d[offset], d[offset + 2]) = (d[offset + 2], d[offset]); // swap R and B
- offset += 4;
- }
- }
- }
-
- break;
- }
-
- parameters.RoughnessValue = 1;
- parameters.MetallicValue = 1;
- break;
- }
- case FGame.Gameface:
- {
- // GTA's Specular Texture Channels
- // R Metallic
- // G Roughness
- // B Specular
- unsafe
- {
- var offset = 0;
- fixed (byte* d = data)
- {
- for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
- {
- (d[offset], d[offset + 2]) = (d[offset + 2], d[offset]); // swap R and B
- offset += 4;
- }
- }
- }
-
- break;
- }
- }
-
- using var bitmap = new SKBitmap(new SKImageInfo(mip.SizeX, mip.SizeY, colorType, SKAlphaType.Unpremul));
- unsafe
- {
- fixed (byte* p = data)
- {
- bitmap.SetPixels(new IntPtr(p));
- }
- }
-
- // R -> AO G -> Roughness B -> Metallic
- m.RoughnessMetallicMap = new TextureModel(bitmap.Encode(SKEncodedImageFormat.Png, 100).AsStream());
- m.RoughnessFactor = parameters.RoughnessValue;
- m.MetallicFactor = parameters.MetallicValue;
- m.RenderAmbientOcclusionMap = parameters.SpecularValue > 0;
- }
-
- if (parameters.HasTopEmissiveTexture && parameters.Emissive is UTexture2D emissive && parameters.EmissiveColor is { A: > 0 } emissiveColor)
- {
- m.EmissiveColor = new Color4(emissiveColor.R, emissiveColor.G, emissiveColor.B, emissiveColor.A);
- m.EmissiveMap = new TextureModel(emissive.Decode(UserSettings.Default.OverridedPlatform)?.Encode(SKEncodedImageFormat.Png, 100).AsStream());
- }
- }
- else
- {
- m.AlbedoColor = new Color4(1, 0, 0, 1);
- }
-
- return (m, isRendering, parameters.IsTransparent);
- }
-
- private void SetupCameraAndAxis(FBox box, ModelAndCam cam)
- {
- if (AppendMode && CanAppend) return;
- var center = box.GetCenter();
-
- var lineBuilder = new LineBuilder();
- lineBuilder.AddLine(new Vector3(box.Min.X, center.Z, center.Y), new Vector3(box.Max.X, center.Z, center.Y));
- cam.XAxis = lineBuilder.ToLineGeometry3D();
- lineBuilder = new LineBuilder();
- lineBuilder.AddLine(new Vector3(center.X, box.Min.Z, center.Y), new Vector3(center.X, box.Max.Z, center.Y));
- cam.YAxis = lineBuilder.ToLineGeometry3D();
- lineBuilder = new LineBuilder();
- lineBuilder.AddLine(new Vector3(center.X, center.Z, box.Min.Y), new Vector3(center.X, center.Z, box.Max.Y));
- cam.ZAxis = lineBuilder.ToLineGeometry3D();
-
- cam.Position = new Point3D(box.Max.X + center.X * 2, center.Z, box.Min.Y + center.Y * 2);
- cam.LookDirection = new Vector3D(-cam.Position.X + center.X, 0, -cam.Position.Z + center.Y);
- }
-
- private bool CheckIfSaved(string path)
- {
- if (File.Exists(path))
- {
- Log.Information("Successfully saved {FileName}", path);
- FLogger.AppendInformation();
- FLogger.AppendText($"Successfully saved {path}", Constants.WHITE, true);
- return true;
- }
-
- Log.Error("{FileName} could not be saved", path);
- FLogger.AppendError();
- FLogger.AppendText($"Could not save '{path}'", Constants.WHITE, true);
- return false;
- }
-
- public void Clear()
- {
- foreach (var g in _loadedModels.ToList())
- {
- g.Dispose();
- _loadedModels.Remove(g);
- }
- }
-}
-
-public class ModelAndCam : ViewModel
-{
- public UObject Export { get; private set; }
- public Point3D Position { get; set; }
- public Vector3D LookDirection { get; set; }
- public Geometry3D XAxis { get; set; }
- public Geometry3D YAxis { get; set; }
- public Geometry3D ZAxis { get; set; }
- public int TriangleCount { get; set; }
-
- private bool _isVisible = true;
- public bool IsVisible
- {
- get => _isVisible;
- set => SetProperty(ref _isVisible, value);
- }
-
- private bool _renderingToggle;
- public bool RenderingToggle
- {
- get => _renderingToggle;
- set
- {
- SetProperty(ref _renderingToggle, value);
- foreach (var g in Group3d)
- {
- if (g is not CustomMeshGeometryModel3D geometryModel)
- continue;
-
- geometryModel.IsRendering = !geometryModel.IsRendering;
- }
- }
- }
-
- private bool _wireframeToggle;
- public bool WireframeToggle
- {
- get => _wireframeToggle;
- set
- {
- SetProperty(ref _wireframeToggle, value);
- foreach (var g in Group3d)
- {
- if (g is not CustomMeshGeometryModel3D geometryModel)
- continue;
-
- geometryModel.RenderWireframe = !geometryModel.RenderWireframe;
- }
- }
- }
-
- private bool _showMaterialColor;
- public bool ShowMaterialColor
- {
- get => _showMaterialColor;
- set
- {
- SetProperty(ref _showMaterialColor, value);
- for (var i = 0; i < Group3d.Count; i++)
- {
- if (Group3d[i] is not CustomMeshGeometryModel3D { Material: PBRMaterial material } m)
- continue;
-
- var index = B(i);
- material.RenderAlbedoMap = !_showMaterialColor;
-
- if (_showMaterialColor)
- {
- m.Tag = material.AlbedoColor;
- material.AlbedoColor = new Color4(_table[C(index)] / 255, _table[C(index >> 1)] / 255, _table[C(index >> 2)] / 255, 1);
- }
- else material.AlbedoColor = (Color4) m.Tag;
- }
- }
- }
-
- private bool _diffuseOnlyToggle;
- public bool DiffuseOnlyToggle
- {
- get => _diffuseOnlyToggle;
- set
- {
- SetProperty(ref _diffuseOnlyToggle, value);
- foreach (var g in Group3d)
- {
- if (g is not CustomMeshGeometryModel3D { Material: PBRMaterial material })
- continue;
-
- material.RenderAmbientOcclusionMap = !material.RenderAmbientOcclusionMap;
- material.RenderDisplacementMap = !material.RenderDisplacementMap;
- // material.RenderEmissiveMap = !material.RenderEmissiveMap;
- // material.RenderEnvironmentMap = !material.RenderEnvironmentMap;
- material.RenderIrradianceMap = !material.RenderIrradianceMap;
- material.RenderRoughnessMetallicMap = !material.RenderRoughnessMetallicMap;
- material.RenderShadowMap = !material.RenderShadowMap;
- material.RenderNormalMap = !material.RenderNormalMap;
- }
- }
- }
-
- private CustomMeshGeometryModel3D _selectedGeometry; // selected material
- public CustomMeshGeometryModel3D SelectedGeometry
- {
- get => _selectedGeometry;
- set => SetProperty(ref _selectedGeometry, value);
- }
-
- private ObservableElement3DCollection _group3d; // material list
- public ObservableElement3DCollection Group3d
- {
- get => _group3d;
- set => SetProperty(ref _group3d, value);
- }
-
- private readonly float[] _table = { 255 * 0.9f, 25 * 3.0f, 255 * 0.6f, 255 * 0.0f };
- private readonly int[] _table2 = { 0, 1, 2, 4, 7, 3, 5, 6 };
-
- public ModelAndCam(UObject export)
- {
- Export = export;
- TriangleCount = 0;
- Group3d = new ObservableElement3DCollection();
- }
-
- 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;
- SelectedGeometry = null;
- foreach (var g in Group3d.ToList())
- {
- g.Dispose();
- Group3d.Remove(g);
- }
- }
-}
-
-public class CustomMeshGeometryModel3D : MeshGeometryModel3D
-{
- public string DisplayName { get; set; }
- public int MaterialIndex { get; set; }
- public int ExportIndex { get; set; }
-}
diff --git a/FModel/Views/ModelViewer.xaml b/FModel/Views/ModelViewer.xaml
deleted file mode 100644
index 66edcd2a..00000000
--- a/FModel/Views/ModelViewer.xaml
+++ /dev/null
@@ -1,135 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/FModel/Views/ModelViewer.xaml.cs b/FModel/Views/ModelViewer.xaml.cs
deleted file mode 100644
index 07d6a2bd..00000000
--- a/FModel/Views/ModelViewer.xaml.cs
+++ /dev/null
@@ -1,115 +0,0 @@
-using System.ComponentModel;
-using System.Windows;
-using System.Windows.Input;
-using AdonisUI.Controls;
-using CUE4Parse.UE4.Assets.Exports;
-using CUE4Parse.UE4.Assets.Exports.Material;
-using FModel.Services;
-using FModel.ViewModels;
-using HelixToolkit.Wpf.SharpDX;
-using MessageBox = AdonisUI.Controls.MessageBox;
-using MessageBoxImage = AdonisUI.Controls.MessageBoxImage;
-
-namespace FModel.Views;
-
-public partial class ModelViewer
-{
- private bool _messageShown;
- private ApplicationViewModel _applicationView => ApplicationService.ApplicationView;
-
- public ModelViewer()
- {
- DataContext = _applicationView;
- InitializeComponent();
- }
-
- public void Load(UObject export) => _applicationView.ModelViewer.LoadExport(export);
- public void Overwrite(UMaterialInstance materialInstance)
- {
- if (_applicationView.ModelViewer.TryOverwriteMaterial(materialInstance))
- {
- _applicationView.CUE4Parse.ModelIsOverwritingMaterial = false;
- }
- else
- {
- MessageBox.Show(new MessageBoxModel
- {
- Text = "An attempt to load a material failed.",
- Caption = "Error",
- Icon = MessageBoxImage.Error,
- Buttons = MessageBoxButtons.OkCancel(),
- IsSoundEnabled = false
- });
- }
- }
-
- private void OnClosing(object sender, CancelEventArgs e)
- {
- _applicationView.ModelViewer.Clear();
- _applicationView.ModelViewer.AppendMode = false;
- _applicationView.CUE4Parse.ModelIsOverwritingMaterial = false;
- MyAntiCrashGroup.ItemsSource = null; // <3
- }
-
- private async void OnWindowKeyDown(object sender, KeyEventArgs e)
- {
- switch (e.Key)
- {
- case Key.W:
- _applicationView.ModelViewer.WirefreameToggle();
- break;
- case Key.H:
- _applicationView.ModelViewer.RenderingToggle();
- break;
- case Key.D:
- _applicationView.ModelViewer.DiffuseOnlyToggle();
- break;
- case Key.M:
- _applicationView.ModelViewer.MaterialColorToggle();
- break;
- case Key.Decimal:
- _applicationView.ModelViewer.FocusOnSelectedMesh();
- break;
- case Key.S when Keyboard.Modifiers.HasFlag(ModifierKeys.Control) && Keyboard.Modifiers.HasFlag(ModifierKeys.Shift):
- _applicationView.ModelViewer.SaveAsScene();
- break;
- case Key.S when Keyboard.Modifiers.HasFlag(ModifierKeys.Control):
- await _applicationView.ModelViewer.SaveLoadedModels();
- break;
- }
- }
-
- private void OnMouse3DDown(object sender, MouseDown3DEventArgs e)
- {
- if (!Keyboard.Modifiers.HasFlag(ModifierKeys.Shift) || e.HitTestResult.ModelHit is not CustomMeshGeometryModel3D m) return;
- _applicationView.ModelViewer.SelectedModel.SelectedGeometry = m;
- MaterialsListName.ScrollIntoView(m);
- }
-
- private void OnFocusClick(object sender, RoutedEventArgs e)
- => _applicationView.ModelViewer.FocusOnSelectedMesh();
-
- private void OnCopyClick(object sender, RoutedEventArgs e)
- => _applicationView.ModelViewer.CopySelectedMaterialName();
-
- private async void Save(object sender, RoutedEventArgs e)
- => await _applicationView.ModelViewer.SaveLoadedModels();
-
- private void OnOverwriteMaterialClick(object sender, RoutedEventArgs e)
- {
- _applicationView.CUE4Parse.ModelIsOverwritingMaterial = true;
- if (!_messageShown)
- {
- MessageBox.Show(new MessageBoxModel
- {
- Text = "Simply extract a material once FModel will be brought to the foreground. This message will be shown once per Model Viewer's lifetime, close it to begin.",
- Caption = "How To Overwrite Material?",
- Icon = MessageBoxImage.Information,
- IsSoundEnabled = false
- });
- _messageShown = true;
- }
-
- MainWindow.YesWeCats.Activate();
- }
-}
\ No newline at end of file
diff --git a/FModel/Views/Resources/Converters/BoolToFillModeConverter.cs b/FModel/Views/Resources/Converters/BoolToFillModeConverter.cs
deleted file mode 100644
index 3a85a8c7..00000000
--- a/FModel/Views/Resources/Converters/BoolToFillModeConverter.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System;
-using System.Globalization;
-using System.Windows.Data;
-using SharpDX.Direct3D11;
-
-namespace FModel.Views.Resources.Converters;
-
-public class BoolToFillModeConverter : IValueConverter
-{
- public static readonly BoolToFillModeConverter Instance = new();
-
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- return value switch
- {
- FillMode.Solid => true,
- _ => false
- };
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- return value switch
- {
- true => FillMode.Solid,
- _ => FillMode.Wireframe
- };
- }
-}
\ No newline at end of file
diff --git a/FModel/Views/Resources/Converters/DateTimeToStringConverter.cs b/FModel/Views/Resources/Converters/DateTimeToStringConverter.cs
deleted file mode 100644
index 1d525940..00000000
--- a/FModel/Views/Resources/Converters/DateTimeToStringConverter.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System;
-using System.Globalization;
-using System.Windows.Data;
-
-namespace FModel.Views.Resources.Converters;
-
-public class DateTimeToStringConverter : IValueConverter
-{
- public static readonly DateTimeToStringConverter Instance = new();
-
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- return value is not DateTime dateTime ? value : $"{dateTime.ToLongDateString()}, {dateTime.ToShortTimeString()}";
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- throw new NotImplementedException();
- }
-}
\ No newline at end of file
diff --git a/FModel/Views/Resources/Converters/TagToColorConverter.cs b/FModel/Views/Resources/Converters/TagToColorConverter.cs
deleted file mode 100644
index ae0d4cfd..00000000
--- a/FModel/Views/Resources/Converters/TagToColorConverter.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System;
-using System.Globalization;
-using System.Windows.Data;
-using System.Windows.Media;
-using HelixToolkit.Wpf.SharpDX;
-
-namespace FModel.Views.Resources.Converters;
-
-public class TagToColorConverter : IValueConverter
-{
- public static readonly TagToColorConverter Instance = new();
-
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- if (value is not PBRMaterial material)
- return new SolidColorBrush(Colors.Red);
-
- return new SolidColorBrush(Color.FromScRgb(
- material.AlbedoColor.Alpha, material.AlbedoColor.Red,
- material.AlbedoColor.Green, material.AlbedoColor.Blue));
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- throw new NotImplementedException();
- }
-}
\ No newline at end of file
diff --git a/FModel/Views/Resources/Resources.xaml b/FModel/Views/Resources/Resources.xaml
index 984f2454..3dd838e2 100644
--- a/FModel/Views/Resources/Resources.xaml
+++ b/FModel/Views/Resources/Resources.xaml
@@ -4,7 +4,6 @@
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:controls="clr-namespace:FModel.Views.Resources.Controls"
xmlns:soundOut="clr-namespace:CSCore.SoundOut;assembly=CSCore"
- xmlns:sharpDx="clr-namespace:SharpDX.Direct3D11;assembly=SharpDX.Direct3D11"
xmlns:audioControls="clr-namespace:FModel.Views.Resources.Controls.Aup"
xmlns:converters="clr-namespace:FModel.Views.Resources.Converters"
xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit"
@@ -638,91 +637,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-