From 4be7d4c3fb40aa00b3779c4fc5a56384bd7fbe92 Mon Sep 17 00:00:00 2001 From: Marlon Date: Thu, 4 Apr 2024 06:18:49 +0200 Subject: [PATCH 1/6] small rework removed DotNetZip make use of Oodle.NET & Zlib-ng.NET updated EpicManifestParser minor optimizations --- CUE4Parse | 2 +- FModel/FModel.csproj | 12 +- FModel/FModel.sln | 6 - FModel/Helper.cs | 44 ++++---- FModel/MainWindow.xaml.cs | 2 + .../ApiEndpoints/EpicApiEndpoint.cs | 8 +- .../ApiEndpoints/ValorantApiEndpoint.cs | 33 +++--- FModel/ViewModels/ApplicationViewModel.cs | 28 +++-- FModel/ViewModels/CUE4ParseViewModel.cs | 103 +++++++++++++----- 9 files changed, 150 insertions(+), 88 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 909fae9a..de075f49 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 909fae9ad24f8c9b0216af824b3c021dd39f1956 +Subproject commit de075f490ce4dc838a5175b78801d45c7bda1588 diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 27458409..19873095 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -140,28 +140,28 @@ - + - - + + + - + - + - diff --git a/FModel/FModel.sln b/FModel/FModel.sln index 52492681..238d1b59 100644 --- a/FModel/FModel.sln +++ b/FModel/FModel.sln @@ -9,8 +9,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUE4Parse", "..\CUE4Parse\C EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUE4Parse-Conversion", "..\CUE4Parse\CUE4Parse-Conversion\CUE4Parse-Conversion.csproj", "{D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EpicManifestParser", "..\EpicManifestParser\src\EpicManifestParser\EpicManifestParser.csproj", "{D4958A8B-815B-421D-A988-2A4E8E2B582D}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -29,10 +27,6 @@ Global {D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Debug|Any CPU.Build.0 = Debug|Any CPU {D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Release|Any CPU.ActiveCfg = Release|Any CPU {D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Release|Any CPU.Build.0 = Release|Any CPU - {D4958A8B-815B-421D-A988-2A4E8E2B582D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D4958A8B-815B-421D-A988-2A4E8E2B582D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D4958A8B-815B-421D-A988-2A4E8E2B582D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D4958A8B-815B-421D-A988-2A4E8E2B582D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/FModel/Helper.cs b/FModel/Helper.cs index 67cd659f..c7a43c50 100644 --- a/FModel/Helper.cs +++ b/FModel/Helper.cs @@ -1,30 +1,32 @@ -using System; +using System; using System.Linq; -using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; using System.Windows; namespace FModel; public static class Helper { - [StructLayout(LayoutKind.Explicit)] - private struct NanUnion - { - [FieldOffset(0)] - internal double DoubleValue; - [FieldOffset(0)] - internal readonly ulong UlongValue; - } - public static string FixKey(string key) { if (string.IsNullOrEmpty(key)) return string.Empty; - if (key.StartsWith("0x")) - key = key[2..]; + var keySpan = key.AsSpan().Trim(); + if (keySpan.Length > sizeof(char) * (2 /* 0x */ + 32 /* FAES = 256 bit */)) // maybe strictly check for length? + return string.Empty; // bullshit key - return "0x" + key.ToUpper().Trim(); + Span resultSpan = stackalloc char[keySpan.Length + 2 /* pad for 0x */]; + keySpan.ToUpperInvariant(resultSpan[2..]); + + if (resultSpan[2..].StartsWith("0X")) + resultSpan = resultSpan[2..]; + else + resultSpan[0] = '0'; + + resultSpan[1] = 'x'; + + return new string(resultSpan); } public static void OpenWindow(string windowName, Action action) where T : Window @@ -74,9 +76,9 @@ public static class Helper public static bool IsNaN(double value) { - var t = new NanUnion { DoubleValue = value }; - var exp = t.UlongValue & 0xfff0000000000000; - var man = t.UlongValue & 0x000fffffffffffff; + var ulongValue = Unsafe.As(ref value); + var exp = ulongValue & 0xfff0000000000000; + var man = ulongValue & 0x000fffffffffffff; return exp is 0x7ff0000000000000 or 0xfff0000000000000 && man != 0; } @@ -96,13 +98,17 @@ public static class Helper return -d < n && d > n; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float DegreesToRadians(float degrees) { - return MathF.PI / 180f * degrees; + const float ratio = MathF.PI / 180f; + return ratio * degrees; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float RadiansToDegrees(float radians) { - return radians* 180f / MathF.PI; + const float ratio = 180f / MathF.PI; + return radians * ratio; } } diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs index 86212096..24d66a1a 100644 --- a/FModel/MainWindow.xaml.cs +++ b/FModel/MainWindow.xaml.cs @@ -61,6 +61,8 @@ public partial class MainWindow break; } + await _applicationView.CUE4Parse.InitOodle(); + await _applicationView.CUE4Parse.InitZlib(); await _applicationView.CUE4Parse.Initialize(); await _applicationView.AesManager.InitAes(); await _applicationView.UpdateProvider(true); diff --git a/FModel/ViewModels/ApiEndpoints/EpicApiEndpoint.cs b/FModel/ViewModels/ApiEndpoints/EpicApiEndpoint.cs index 386762ce..6b1eeea2 100644 --- a/FModel/ViewModels/ApiEndpoints/EpicApiEndpoint.cs +++ b/FModel/ViewModels/ApiEndpoints/EpicApiEndpoint.cs @@ -1,10 +1,14 @@ using System.Threading; using System.Threading.Tasks; -using EpicManifestParser.Objects; + +using EpicManifestParser.Api; + using FModel.Framework; using FModel.Settings; using FModel.ViewModels.ApiEndpoints.Models; + using RestSharp; + using Serilog; namespace FModel.ViewModels.ApiEndpoints; @@ -25,7 +29,7 @@ public class EpicApiEndpoint : AbstractApiProvider request.AddHeader("Authorization", $"bearer {UserSettings.Default.LastAuthResponse.AccessToken}"); var response = await _client.ExecuteAsync(request, token).ConfigureAwait(false); Log.Information("[{Method}] [{Status}({StatusCode})] '{Resource}'", request.Method, response.StatusDescription, (int) response.StatusCode, response.ResponseUri?.OriginalString); - return response.IsSuccessful ? new ManifestInfo(response.Content) : null; + return response.IsSuccessful ? ManifestInfo.Deserialize(response.RawBytes) : null; } public ManifestInfo GetManifest(CancellationToken token) diff --git a/FModel/ViewModels/ApiEndpoints/ValorantApiEndpoint.cs b/FModel/ViewModels/ApiEndpoints/ValorantApiEndpoint.cs index 67c51f96..8c827867 100644 --- a/FModel/ViewModels/ApiEndpoints/ValorantApiEndpoint.cs +++ b/FModel/ViewModels/ApiEndpoints/ValorantApiEndpoint.cs @@ -1,8 +1,3 @@ -using CUE4Parse.UE4.Exceptions; -using CUE4Parse.UE4.Readers; -using FModel.Settings; -using Ionic.Zlib; -using RestSharp; using System; using System.Collections.Generic; using System.IO; @@ -13,7 +8,15 @@ using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; + +using CUE4Parse.Compression; +using CUE4Parse.UE4.Exceptions; +using CUE4Parse.UE4.Readers; + using FModel.Framework; +using FModel.Settings; + +using RestSharp; namespace FModel.ViewModels.ApiEndpoints; @@ -40,26 +43,22 @@ public class VManifest public readonly VChunk[] Chunks; public readonly VPak[] Paks; - public VManifest(byte[] data) : this(new FByteArchive("CompressedValorantManifest", data)) - { - } - + public VManifest(byte[] data) : this(new FByteArchive("CompressedValorantManifest", data)) { } private VManifest(FArchive Ar) { using (Ar) { Header = new VHeader(Ar); var compressedBuffer = Ar.ReadBytes((int) Header.CompressedSize); - var uncompressedBuffer = ZlibStream.UncompressBuffer(compressedBuffer); - if (uncompressedBuffer.Length != Header.UncompressedSize) - throw new ParserException(Ar, $"Decompression failed, {uncompressedBuffer.Length} != {Header.UncompressedSize}"); + var uncompressedBuffer = new byte[(int)Header.UncompressedSize]; + ZlibHelper.Decompress(compressedBuffer, 0, compressedBuffer.Length, uncompressedBuffer, 0, uncompressedBuffer.Length); - using var manifest = new FByteArchive("UncompressedValorantManifest", uncompressedBuffer); - Chunks = manifest.ReadArray((int) Header.ChunkCount); - Paks = manifest.ReadArray((int) Header.PakCount, () => new VPak(manifest)); + var manifestAr = new FByteArchive("UncompressedValorantManifest", uncompressedBuffer); + Chunks = manifestAr.ReadArray((int) Header.ChunkCount); + Paks = manifestAr.ReadArray((int) Header.PakCount, () => new VPak(manifestAr)); - if (manifest.Position != manifest.Length) - throw new ParserException(manifest, $"Parsing failed, {manifest.Position} != {manifest.Length}"); + if (manifestAr.Position != manifestAr.Length) + throw new ParserException(manifestAr, $"Parsing failed, {manifestAr.Position} != {manifestAr.Length}"); } _client = new HttpClient(new HttpClientHandler diff --git a/FModel/ViewModels/ApplicationViewModel.cs b/FModel/ViewModels/ApplicationViewModel.cs index 6398f37a..fcfa725b 100644 --- a/FModel/ViewModels/ApplicationViewModel.cs +++ b/FModel/ViewModels/ApplicationViewModel.cs @@ -1,3 +1,10 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.Threading.Tasks; +using System.Windows; + using FModel.Extensions; using FModel.Framework; using FModel.Services; @@ -5,12 +12,7 @@ using FModel.Settings; using FModel.ViewModels.Commands; using FModel.Views; using FModel.Views.Resources.Controls; -using Ionic.Zip; -using System; -using System.Diagnostics; -using System.IO; -using System.Threading.Tasks; -using System.Windows; + using MessageBox = AdonisUI.Controls.MessageBox; using MessageBoxButton = AdonisUI.Controls.MessageBoxButton; using MessageBoxImage = AdonisUI.Controls.MessageBoxImage; @@ -168,9 +170,17 @@ public class ApplicationViewModel : ViewModel await ApplicationService.ApiEndpointView.DownloadFileAsync("https://github.com/vgmstream/vgmstream/releases/latest/download/vgmstream-win.zip", vgmZipFilePath); if (new FileInfo(vgmZipFilePath).Length > 0) { - var zip = ZipFile.Read(vgmZipFilePath); - var zipDir = vgmZipFilePath.SubstringBeforeLast("\\"); - foreach (var e in zip) e.Extract(zipDir, ExtractExistingFileAction.OverwriteSilently); + var zipDir = Path.GetDirectoryName(vgmZipFilePath)!; + await using var zipFs = File.OpenRead(vgmZipFilePath); + using var zip = new ZipArchive(zipFs, ZipArchiveMode.Read); + + foreach (var entry in zip.Entries) + { + var entryPath = Path.Combine(zipDir, entry.FullName); + await using var entryFs = File.OpenRead(entryPath); + await using var entryStream = entry.Open(); + await entryStream.CopyToAsync(entryFs); + } } else { diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 977e83ba..90008f9d 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Net.Http.Headers; @@ -7,7 +8,9 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows; + using AdonisUI.Controls; +using CUE4Parse.Compression; using CUE4Parse.Encryption.Aes; using CUE4Parse.FileProvider; using CUE4Parse.FileProvider.Vfs; @@ -17,23 +20,26 @@ using CUE4Parse.UE4.Assets.Exports; using CUE4Parse.UE4.Assets.Exports.Animation; using CUE4Parse.UE4.Assets.Exports.Material; using CUE4Parse.UE4.Assets.Exports.SkeletalMesh; -using CUE4Parse.UE4.Assets.Exports.Verse; using CUE4Parse.UE4.Assets.Exports.Sound; using CUE4Parse.UE4.Assets.Exports.StaticMesh; using CUE4Parse.UE4.Assets.Exports.Texture; +using CUE4Parse.UE4.Assets.Exports.Verse; using CUE4Parse.UE4.Assets.Exports.Wwise; using CUE4Parse.UE4.IO; using CUE4Parse.UE4.Localization; +using CUE4Parse.UE4.Objects.Core.Serialization; using CUE4Parse.UE4.Objects.Engine; using CUE4Parse.UE4.Oodle.Objects; using CUE4Parse.UE4.Readers; using CUE4Parse.UE4.Shaders; using CUE4Parse.UE4.Versions; using CUE4Parse.UE4.Wwise; + using CUE4Parse_Conversion; using CUE4Parse_Conversion.Sounds; -using CUE4Parse.UE4.Objects.Core.Serialization; -using EpicManifestParser.Objects; + +using EpicManifestParser; + using FModel.Creator; using FModel.Extensions; using FModel.Framework; @@ -42,13 +48,20 @@ using FModel.Settings; using FModel.Views; using FModel.Views.Resources.Controls; using FModel.Views.Snooper; + using Newtonsoft.Json; + using Ookii.Dialogs.Wpf; + using OpenTK.Windowing.Common; using OpenTK.Windowing.Desktop; + using Serilog; + using SkiaSharp; + using UE4Config.Parsing; + using Application = System.Windows.Application; namespace FModel.ViewModels; @@ -190,45 +203,41 @@ public class CUE4ParseViewModel : ViewModel case "FortniteLive": { var manifestInfo = _apiEndpointView.EpicApi.GetManifest(cancellationToken); - if (manifestInfo == null) + if (manifestInfo is null) { - throw new Exception("Could not load latest Fortnite manifest, you may have to switch to your local installation."); + throw new FileLoadException("Could not load latest Fortnite manifest, you may have to switch to your local installation."); } - byte[] manifestData; - var chunksDir = Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, ".data")); - var manifestPath = Path.Combine(chunksDir.FullName, manifestInfo.FileName); - if (File.Exists(manifestPath)) + var cacheDir = Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, ".data")).FullName; + var manifestOptions = new ManifestParseOptions { - manifestData = File.ReadAllBytes(manifestPath); - } - else - { - manifestData = manifestInfo.DownloadManifestData(); - File.WriteAllBytes(manifestPath, manifestData); - } + ChunkCacheDirectory = cacheDir, + ManifestCacheDirectory = cacheDir, + ChunkBaseUrl = "http://epicgames-download1.akamaized.net/Builds/Fortnite/CloudDir/", + Zlibng = ZlibHelper.Instance + }; - var manifest = new Manifest(manifestData, new ManifestOptions - { - ChunkBaseUri = new Uri("http://epicgames-download1.akamaized.net/Builds/Fortnite/CloudDir/ChunksV4/", UriKind.Absolute), - ChunkCacheDirectory = chunksDir - }); + var startTs = Stopwatch.GetTimestamp(); + var (manifest, _) = manifestInfo.DownloadAndParseAsync(manifestOptions, + cancellationToken: cancellationToken).GetAwaiter().GetResult(); + var parseTime = Stopwatch.GetElapsedTime(startTs); + const bool cacheChunksAsIs = false; - foreach (var fileManifest in manifest.FileManifests) + foreach (var fileManifest in manifest.FileManifestList) { - if (fileManifest.Name.Equals("Cloud/IoStoreOnDemand.ini", StringComparison.OrdinalIgnoreCase)) + if (fileManifest.FileName.Equals("Cloud/IoStoreOnDemand.ini", StringComparison.OrdinalIgnoreCase)) { - IoStoreOnDemand.Read(new StreamReader(fileManifest.GetStream())); + IoStoreOnDemand.Read(new StreamReader(fileManifest.GetStream(cacheChunksAsIs))); continue; } - if (!_fnLive.IsMatch(fileManifest.Name)) continue; + if (!_fnLive.IsMatch(fileManifest.FileName)) continue; - p.RegisterVfs(fileManifest.Name, new Stream[] { fileManifest.GetStream() } - , it => new FStreamArchive(it, manifest.FileManifests.First(x => x.Name.Equals(it)).GetStream(), p.Versions)); + p.RegisterVfs(fileManifest.FileName, [ fileManifest.GetStream(cacheChunksAsIs) ] + , it => new FStreamArchive(it, manifest.FileManifestList.First(x => x.FileName.Equals(it)).GetStream(cacheChunksAsIs), p.Versions)); } FLogger.Append(ELog.Information, () => - FLogger.Text($"Fortnite has been loaded successfully in {manifest.ParseTime.TotalMilliseconds}ms", Constants.WHITE, true)); + FLogger.Text($"Fortnite [LIVE] has been loaded successfully in {parseTime.TotalMilliseconds}ms", Constants.WHITE, true)); break; } case "ValorantLive": @@ -351,6 +360,44 @@ public class CUE4ParseViewModel : ViewModel }); } + public async Task InitOodle() + { + var dataDir = Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, ".data")).FullName; + var oodlePath = Path.Combine(dataDir, OodleHelper.OODLE_DLL_NAME); + bool result; + if (File.Exists(OodleHelper.OODLE_DLL_NAME)) + { + File.Move(OodleHelper.OODLE_DLL_NAME, oodlePath, true); + result = true; + } + else + { + result = await OodleHelper.DownloadOodleDllAsync(oodlePath); + } + + OodleHelper.Initialize(oodlePath); + return result; + } + + public async Task InitZlib() + { + var dataDir = Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, ".data")).FullName; + var zlibPath = Path.Combine(dataDir, ZlibHelper.DLL_NAME); + bool result; + if (File.Exists(ZlibHelper.DLL_NAME)) + { + File.Move(ZlibHelper.DLL_NAME, zlibPath, true); + result = true; + } + else + { + result = await ZlibHelper.DownloadDllAsync(zlibPath); + } + + ZlibHelper.Initialize(zlibPath); + return result; + } + public Task InitMappings(bool force = false) { if (!UserSettings.IsEndpointValid(EEndpointType.Mapping, out var endpoint)) From 158bf9d6c71bf58f4e11566396cc00d465b4810c Mon Sep 17 00:00:00 2001 From: Marlon Date: Thu, 4 Apr 2024 14:36:12 +0200 Subject: [PATCH 2/6] minor changes --- FModel/ViewModels/CUE4ParseViewModel.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 90008f9d..a858aa92 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -232,7 +232,7 @@ public class CUE4ParseViewModel : ViewModel } if (!_fnLive.IsMatch(fileManifest.FileName)) continue; - p.RegisterVfs(fileManifest.FileName, [ fileManifest.GetStream(cacheChunksAsIs) ] + p.RegisterVfs(fileManifest.FileName, [fileManifest.GetStream(cacheChunksAsIs)] , it => new FStreamArchive(it, manifest.FileManifestList.First(x => x.FileName.Equals(it)).GetStream(cacheChunksAsIs), p.Versions)); } @@ -250,7 +250,7 @@ public class CUE4ParseViewModel : ViewModel for (var i = 0; i < manifestInfo.Paks.Length; i++) { - p.RegisterVfs(manifestInfo.Paks[i].GetFullName(), new[] { manifestInfo.GetPakStream(i) }); + p.RegisterVfs(manifestInfo.Paks[i].GetFullName(), [manifestInfo.GetPakStream(i)]); } FLogger.Append(ELog.Information, () => @@ -261,9 +261,14 @@ public class CUE4ParseViewModel : ViewModel break; case DefaultFileProvider: - var ioStoreOnDemandPath = Path.Combine(UserSettings.Default.GameDirectory, "..\\..\\..\\Cloud\\IoStoreOnDemand.ini"); - if (File.Exists(ioStoreOnDemandPath)) IoStoreOnDemand.Read(new StringReader(File.ReadAllText(ioStoreOnDemandPath))); + { + var ioStoreOnDemandPath = Path.Combine(UserSettings.Default.GameDirectory, + "..\\..\\..\\Cloud\\IoStoreOnDemand.ini"); + using var tr = File.OpenText(ioStoreOnDemandPath); + if (File.Exists(ioStoreOnDemandPath)) + IoStoreOnDemand.Read(tr); break; + } } Provider.Initialize(); From bc15757db0f2d26bc137bf6ddef7d39862d6ce94 Mon Sep 17 00:00:00 2001 From: Marlon Date: Thu, 4 Apr 2024 14:36:24 +0200 Subject: [PATCH 3/6] nuget updates --- CUE4Parse | 2 +- FModel/FModel.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index de075f49..7ea875e5 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit de075f490ce4dc838a5175b78801d45c7bda1588 +Subproject commit 7ea875e520ce683f03ca46c688e9bee1aad32fa4 diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 19873095..51f3260a 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -144,7 +144,7 @@ - + From 1852eb1b7d85f9a1612307ba9532193d92b8e75e Mon Sep 17 00:00:00 2001 From: Marlon Date: Fri, 5 Apr 2024 06:39:34 +0200 Subject: [PATCH 4/6] removed submodule --- .gitmodules | 3 --- EpicManifestParser | 1 - 2 files changed, 4 deletions(-) delete mode 160000 EpicManifestParser diff --git a/.gitmodules b/.gitmodules index 959570f6..2221fc41 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "CUE4Parse"] path = CUE4Parse url = https://github.com/FabianFG/CUE4Parse -[submodule "EpicManifestParser"] - path = EpicManifestParser - url = https://github.com/FModel/EpicManifestParser \ No newline at end of file diff --git a/EpicManifestParser b/EpicManifestParser deleted file mode 160000 index 21df8a55..00000000 --- a/EpicManifestParser +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 21df8a55d474f14148a35bc943e06f3fdc20c997 From eb9983bb189cfe60785b7b1892d20cae70b14141 Mon Sep 17 00:00:00 2001 From: Asval Date: Sat, 6 Apr 2024 20:38:45 +0200 Subject: [PATCH 5/6] improvements - custom imgui settings directory - viewport icons (not finished) - can read ue version project name, number of archives, number of aes from logs - bug fixes --- CUE4Parse | 2 +- FModel/FModel.csproj | 14 +- FModel/Framework/ImGuiController.cs | 192 +++++++++------------- FModel/MainWindow.xaml.cs | 9 +- FModel/Resources/cube.png | Bin 0 -> 831 bytes FModel/Resources/cube_off.png | Bin 0 -> 1094 bytes FModel/Resources/light.png | Bin 0 -> 1234 bytes FModel/Resources/light_off.png | Bin 0 -> 1567 bytes FModel/Resources/square.png | Bin 0 -> 1239 bytes FModel/Resources/square_off.png | Bin 0 -> 1299 bytes FModel/ViewModels/ApplicationViewModel.cs | 43 ++++- FModel/ViewModels/CUE4ParseViewModel.cs | 52 ++---- FModel/Views/Snooper/Options.cs | 6 + FModel/Views/Snooper/SnimGui.cs | 48 ++++-- 14 files changed, 186 insertions(+), 180 deletions(-) create mode 100644 FModel/Resources/cube.png create mode 100644 FModel/Resources/cube_off.png create mode 100644 FModel/Resources/light.png create mode 100644 FModel/Resources/light_off.png create mode 100644 FModel/Resources/square.png create mode 100644 FModel/Resources/square_off.png diff --git a/CUE4Parse b/CUE4Parse index 7ea875e5..50d5e06d 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 7ea875e520ce683f03ca46c688e9bee1aad32fa4 +Subproject commit 50d5e06d421e2935cc4107df6352b36c341ec7c0 diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 51f3260a..3822bf06 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -45,6 +45,12 @@ + + + + + + @@ -145,7 +151,7 @@ - + @@ -181,6 +187,12 @@ + + + + + + diff --git a/FModel/Framework/ImGuiController.cs b/FModel/Framework/ImGuiController.cs index 9077553b..8e1e2c91 100644 --- a/FModel/Framework/ImGuiController.cs +++ b/FModel/Framework/ImGuiController.cs @@ -1,10 +1,13 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Numerics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Windows; using System.Windows.Forms; +using FModel.Settings; using ImGuiNET; using OpenTK.Graphics.OpenGL4; using OpenTK.Windowing.Desktop; @@ -34,7 +37,6 @@ public class ImGuiController : IDisposable private int _windowWidth; private int _windowHeight; - // private string _iniPath; public ImFontPtr FontNormal; public ImFontPtr FontBold; @@ -49,7 +51,6 @@ public class ImGuiController : IDisposable { _windowWidth = width; _windowHeight = height; - // _iniPath = Path.Combine(UserSettings.Default.OutputDirectory, ".data", "imgui.ini"); int major = GL.GetInteger(GetPName.MajorVersion); int minor = GL.GetInteger(GetPName.MinorVersion); @@ -58,9 +59,13 @@ public class ImGuiController : IDisposable IntPtr context = ImGui.CreateContext(); ImGui.SetCurrentContext(context); - // ImGui.LoadIniSettingsFromDisk(_iniPath); var io = ImGui.GetIO(); + unsafe + { + var iniFileNamePtr = Marshal.StringToCoTaskMemUTF8(Path.Combine(UserSettings.Default.OutputDirectory, ".data", "imgui.ini")); + io.NativePtr->IniFilename = (byte*)iniFileNamePtr; + } FontNormal = io.Fonts.AddFontFromFileTTF("C:\\Windows\\Fonts\\segoeui.ttf", 16 * DpiScale); FontBold = io.Fonts.AddFontFromFileTTF("C:\\Windows\\Fonts\\segoeuib.ttf", 16 * DpiScale); FontSemiBold = io.Fonts.AddFontFromFileTTF("C:\\Windows\\Fonts\\seguisb.ttf", 16 * DpiScale); @@ -71,7 +76,6 @@ public class ImGuiController : IDisposable io.Fonts.Flags |= ImFontAtlasFlags.NoBakedLines; CreateDeviceResources(); - SetKeyMappings(); SetPerFrameImGuiData(1f / 60f); @@ -271,8 +275,8 @@ outputColor = color * texture(in_fontTexture, texCoord); foreach (Keys key in Enum.GetValues(typeof(Keys))) { - if (key == Keys.Unknown || io.KeyMap[(int) key] == -1) continue; - io.AddKeyEvent((ImGuiKey) io.KeyMap[(int) key], kState.IsKeyDown(key)); + if (key == Keys.Unknown) continue; + io.AddKeyEvent(TranslateKey(key), kState.IsKeyDown(key)); } foreach (var c in PressedChars) @@ -292,115 +296,6 @@ outputColor = color * texture(in_fontTexture, texCoord); PressedChars.Add(keyChar); } - private static void SetKeyMappings() - { - ImGuiIOPtr io = ImGui.GetIO(); - io.KeyMap[(int)ImGuiKey.LeftShift] = (int)Keys.LeftShift; - io.KeyMap[(int)ImGuiKey.RightShift] = (int)Keys.RightShift; - io.KeyMap[(int)ImGuiKey.LeftCtrl] = (int)Keys.LeftControl; - io.KeyMap[(int)ImGuiKey.RightCtrl] = (int)Keys.RightControl; - io.KeyMap[(int)ImGuiKey.LeftAlt] = (int)Keys.LeftAlt; - io.KeyMap[(int)ImGuiKey.RightAlt] = (int)Keys.RightAlt; - io.KeyMap[(int)ImGuiKey.LeftSuper] = (int)Keys.LeftSuper; - io.KeyMap[(int)ImGuiKey.RightSuper] = (int)Keys.RightSuper; - io.KeyMap[(int)ImGuiKey.Menu] = (int)Keys.Menu; - io.KeyMap[(int)ImGuiKey.UpArrow] = (int)Keys.Up; - io.KeyMap[(int)ImGuiKey.DownArrow] = (int)Keys.Down; - io.KeyMap[(int)ImGuiKey.LeftArrow] = (int)Keys.Left; - io.KeyMap[(int)ImGuiKey.RightArrow] = (int)Keys.Right; - io.KeyMap[(int)ImGuiKey.Enter] = (int)Keys.Enter; - io.KeyMap[(int)ImGuiKey.Escape] = (int)Keys.Escape; - io.KeyMap[(int)ImGuiKey.Space] = (int)Keys.Space; - io.KeyMap[(int)ImGuiKey.Tab] = (int)Keys.Tab; - io.KeyMap[(int)ImGuiKey.Backspace] = (int)Keys.Backspace; - io.KeyMap[(int)ImGuiKey.Insert] = (int)Keys.Insert; - io.KeyMap[(int)ImGuiKey.Delete] = (int)Keys.Delete; - io.KeyMap[(int)ImGuiKey.PageUp] = (int)Keys.PageUp; - io.KeyMap[(int)ImGuiKey.PageDown] = (int)Keys.PageDown; - io.KeyMap[(int)ImGuiKey.Home] = (int)Keys.Home; - io.KeyMap[(int)ImGuiKey.End] = (int)Keys.End; - io.KeyMap[(int)ImGuiKey.CapsLock] = (int)Keys.CapsLock; - io.KeyMap[(int)ImGuiKey.ScrollLock] = (int)Keys.ScrollLock; - io.KeyMap[(int)ImGuiKey.PrintScreen] = (int)Keys.PrintScreen; - io.KeyMap[(int)ImGuiKey.Pause] = (int)Keys.Pause; - io.KeyMap[(int)ImGuiKey.NumLock] = (int)Keys.NumLock; - io.KeyMap[(int)ImGuiKey.KeypadDivide] = (int)Keys.KeyPadDivide; - io.KeyMap[(int)ImGuiKey.KeypadMultiply] = (int)Keys.KeyPadMultiply; - io.KeyMap[(int)ImGuiKey.KeypadSubtract] = (int)Keys.KeyPadSubtract; - io.KeyMap[(int)ImGuiKey.KeypadAdd] = (int)Keys.KeyPadAdd; - io.KeyMap[(int)ImGuiKey.KeypadDecimal] = (int)Keys.KeyPadDecimal; - io.KeyMap[(int)ImGuiKey.KeypadEnter] = (int)Keys.KeyPadEnter; - io.KeyMap[(int)ImGuiKey.GraveAccent] = (int)Keys.GraveAccent; - io.KeyMap[(int)ImGuiKey.Minus] = (int)Keys.Minus; - io.KeyMap[(int)ImGuiKey.Equal] = (int)Keys.Equal; - io.KeyMap[(int)ImGuiKey.LeftBracket] = (int)Keys.LeftBracket; - io.KeyMap[(int)ImGuiKey.RightBracket] = (int)Keys.RightBracket; - io.KeyMap[(int)ImGuiKey.Semicolon] = (int)Keys.Semicolon; - io.KeyMap[(int)ImGuiKey.Apostrophe] = (int)Keys.Apostrophe; - io.KeyMap[(int)ImGuiKey.Comma] = (int)Keys.Comma; - io.KeyMap[(int)ImGuiKey.Period] = (int)Keys.Period; - io.KeyMap[(int)ImGuiKey.Slash] = (int)Keys.Slash; - io.KeyMap[(int)ImGuiKey.Backslash] = (int)Keys.Backslash; - io.KeyMap[(int)ImGuiKey.F1] = (int)Keys.F1; - io.KeyMap[(int)ImGuiKey.F2] = (int)Keys.F2; - io.KeyMap[(int)ImGuiKey.F3] = (int)Keys.F3; - io.KeyMap[(int)ImGuiKey.F4] = (int)Keys.F4; - io.KeyMap[(int)ImGuiKey.F5] = (int)Keys.F5; - io.KeyMap[(int)ImGuiKey.F6] = (int)Keys.F6; - io.KeyMap[(int)ImGuiKey.F7] = (int)Keys.F7; - io.KeyMap[(int)ImGuiKey.F8] = (int)Keys.F8; - io.KeyMap[(int)ImGuiKey.F9] = (int)Keys.F9; - io.KeyMap[(int)ImGuiKey.F10] = (int)Keys.F10; - io.KeyMap[(int)ImGuiKey.F11] = (int)Keys.F11; - io.KeyMap[(int)ImGuiKey.F12] = (int)Keys.F12; - io.KeyMap[(int)ImGuiKey.Keypad0] = (int)Keys.KeyPad0; - io.KeyMap[(int)ImGuiKey.Keypad1] = (int)Keys.KeyPad1; - io.KeyMap[(int)ImGuiKey.Keypad2] = (int)Keys.KeyPad2; - io.KeyMap[(int)ImGuiKey.Keypad3] = (int)Keys.KeyPad3; - io.KeyMap[(int)ImGuiKey.Keypad4] = (int)Keys.KeyPad4; - io.KeyMap[(int)ImGuiKey.Keypad5] = (int)Keys.KeyPad5; - io.KeyMap[(int)ImGuiKey.Keypad6] = (int)Keys.KeyPad6; - io.KeyMap[(int)ImGuiKey.Keypad7] = (int)Keys.KeyPad7; - io.KeyMap[(int)ImGuiKey.Keypad8] = (int)Keys.KeyPad8; - io.KeyMap[(int)ImGuiKey.Keypad9] = (int)Keys.KeyPad9; - io.KeyMap[(int)ImGuiKey._0] = (int)Keys.D0; - io.KeyMap[(int)ImGuiKey._1] = (int)Keys.D1; - io.KeyMap[(int)ImGuiKey._2] = (int)Keys.D2; - io.KeyMap[(int)ImGuiKey._3] = (int)Keys.D3; - io.KeyMap[(int)ImGuiKey._4] = (int)Keys.D4; - io.KeyMap[(int)ImGuiKey._5] = (int)Keys.D5; - io.KeyMap[(int)ImGuiKey._6] = (int)Keys.D6; - io.KeyMap[(int)ImGuiKey._7] = (int)Keys.D7; - io.KeyMap[(int)ImGuiKey._8] = (int)Keys.D8; - io.KeyMap[(int)ImGuiKey._9] = (int)Keys.D9; - io.KeyMap[(int)ImGuiKey.A] = (int)Keys.A; - io.KeyMap[(int)ImGuiKey.B] = (int)Keys.B; - io.KeyMap[(int)ImGuiKey.C] = (int)Keys.C; - io.KeyMap[(int)ImGuiKey.D] = (int)Keys.D; - io.KeyMap[(int)ImGuiKey.E] = (int)Keys.E; - io.KeyMap[(int)ImGuiKey.F] = (int)Keys.F; - io.KeyMap[(int)ImGuiKey.G] = (int)Keys.G; - io.KeyMap[(int)ImGuiKey.H] = (int)Keys.H; - io.KeyMap[(int)ImGuiKey.I] = (int)Keys.I; - io.KeyMap[(int)ImGuiKey.J] = (int)Keys.J; - io.KeyMap[(int)ImGuiKey.K] = (int)Keys.K; - io.KeyMap[(int)ImGuiKey.L] = (int)Keys.L; - io.KeyMap[(int)ImGuiKey.M] = (int)Keys.M; - io.KeyMap[(int)ImGuiKey.N] = (int)Keys.N; - io.KeyMap[(int)ImGuiKey.O] = (int)Keys.O; - io.KeyMap[(int)ImGuiKey.P] = (int)Keys.P; - io.KeyMap[(int)ImGuiKey.Q] = (int)Keys.Q; - io.KeyMap[(int)ImGuiKey.R] = (int)Keys.R; - io.KeyMap[(int)ImGuiKey.S] = (int)Keys.S; - io.KeyMap[(int)ImGuiKey.T] = (int)Keys.T; - io.KeyMap[(int)ImGuiKey.U] = (int)Keys.U; - io.KeyMap[(int)ImGuiKey.V] = (int)Keys.V; - io.KeyMap[(int)ImGuiKey.W] = (int)Keys.W; - io.KeyMap[(int)ImGuiKey.X] = (int)Keys.X; - io.KeyMap[(int)ImGuiKey.Y] = (int)Keys.Y; - io.KeyMap[(int)ImGuiKey.Z] = (int)Keys.Z; - } - private void RenderImDrawData(ImDrawDataPtr draw_data) { if (draw_data.CmdListsCount == 0) @@ -643,4 +538,71 @@ outputColor = color * texture(in_fontTexture, texCoord); { return Math.Max((float)(Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth), (float)(Screen.PrimaryScreen.Bounds.Height / SystemParameters.PrimaryScreenHeight)); } + + public static ImGuiKey TranslateKey(Keys key) + { + if (key is >= Keys.D0 and <= Keys.D9) + return key - Keys.D0 + ImGuiKey._0; + + if (key is >= Keys.A and <= Keys.Z) + return key - Keys.A + ImGuiKey.A; + + if (key is >= Keys.KeyPad0 and <= Keys.KeyPad9) + return key - Keys.KeyPad0 + ImGuiKey.Keypad0; + + if (key is >= Keys.F1 and <= Keys.F24) + return key - Keys.F1 + ImGuiKey.F24; + + return key switch + { + Keys.Tab => ImGuiKey.Tab, + Keys.Left => ImGuiKey.LeftArrow, + Keys.Right => ImGuiKey.RightArrow, + Keys.Up => ImGuiKey.UpArrow, + Keys.Down => ImGuiKey.DownArrow, + Keys.PageUp => ImGuiKey.PageUp, + Keys.PageDown => ImGuiKey.PageDown, + Keys.Home => ImGuiKey.Home, + Keys.End => ImGuiKey.End, + Keys.Insert => ImGuiKey.Insert, + Keys.Delete => ImGuiKey.Delete, + Keys.Backspace => ImGuiKey.Backspace, + Keys.Space => ImGuiKey.Space, + Keys.Enter => ImGuiKey.Enter, + Keys.Escape => ImGuiKey.Escape, + Keys.Apostrophe => ImGuiKey.Apostrophe, + Keys.Comma => ImGuiKey.Comma, + Keys.Minus => ImGuiKey.Minus, + Keys.Period => ImGuiKey.Period, + Keys.Slash => ImGuiKey.Slash, + Keys.Semicolon => ImGuiKey.Semicolon, + Keys.Equal => ImGuiKey.Equal, + Keys.LeftBracket => ImGuiKey.LeftBracket, + Keys.Backslash => ImGuiKey.Backslash, + Keys.RightBracket => ImGuiKey.RightBracket, + Keys.GraveAccent => ImGuiKey.GraveAccent, + Keys.CapsLock => ImGuiKey.CapsLock, + Keys.ScrollLock => ImGuiKey.ScrollLock, + Keys.NumLock => ImGuiKey.NumLock, + Keys.PrintScreen => ImGuiKey.PrintScreen, + Keys.Pause => ImGuiKey.Pause, + Keys.KeyPadDecimal => ImGuiKey.KeypadDecimal, + Keys.KeyPadDivide => ImGuiKey.KeypadDivide, + Keys.KeyPadMultiply => ImGuiKey.KeypadMultiply, + Keys.KeyPadSubtract => ImGuiKey.KeypadSubtract, + Keys.KeyPadAdd => ImGuiKey.KeypadAdd, + Keys.KeyPadEnter => ImGuiKey.KeypadEnter, + Keys.KeyPadEqual => ImGuiKey.KeypadEqual, + Keys.LeftShift => ImGuiKey.LeftShift, + Keys.LeftControl => ImGuiKey.LeftCtrl, + Keys.LeftAlt => ImGuiKey.LeftAlt, + Keys.LeftSuper => ImGuiKey.LeftSuper, + Keys.RightShift => ImGuiKey.RightShift, + Keys.RightControl => ImGuiKey.RightCtrl, + Keys.RightAlt => ImGuiKey.RightAlt, + Keys.RightSuper => ImGuiKey.RightSuper, + Keys.Menu => ImGuiKey.Menu, + _ => ImGuiKey.None + }; + } } diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs index 24d66a1a..a79f953a 100644 --- a/FModel/MainWindow.xaml.cs +++ b/FModel/MainWindow.xaml.cs @@ -61,8 +61,8 @@ public partial class MainWindow break; } - await _applicationView.CUE4Parse.InitOodle(); - await _applicationView.CUE4Parse.InitZlib(); + await _applicationView.InitOodle(); + await _applicationView.InitZlib(); await _applicationView.CUE4Parse.Initialize(); await _applicationView.AesManager.InitAes(); await _applicationView.UpdateProvider(true); @@ -85,10 +85,7 @@ public partial class MainWindow #if DEBUG await _threadWorkerView.Begin(cancellationToken => _applicationView.CUE4Parse.Extract(cancellationToken, - "fortnitegame/Content/Characters/Player/Female/Medium/Bodies/F_Med_Soldier_01/Meshes/F_Med_Soldier_01.uasset")); - await _threadWorkerView.Begin(cancellationToken => - _applicationView.CUE4Parse.Extract(cancellationToken, - "fortnitegame/Content/Animation/Game/MainPlayer/Emotes/Cowbell/Cowbell_CMM_Loop_M.uasset")); + "ShooterGame/Content/Characters/Smonk/S0/3P/Models/TP_Smonk_S0_Skelmesh.uasset")); #endif } diff --git a/FModel/Resources/cube.png b/FModel/Resources/cube.png new file mode 100644 index 0000000000000000000000000000000000000000..007668747cecd4b2a48fcbade28c85698db24078 GIT binary patch literal 831 zcmV-F1Hk-=P)(vPss7o1LAi_dHBy zn5AcjL=zu0G~KVi?^X4yt`;-nZbm#hdE=u!7Ul%?0vHH@z^DMBW@4|4<5-Nmors(q z<_uHq=Hb;yo$&JU6aY6Ai|S4{RU_60{71x-2}i143y)2wJ-ZYKZzoDq$Iepub;)SeOjsT@U4K$BQlcM z(JZp3c7vWR2`+8>$JZ|gcCH(h6w+kIo0|wT!#SZ<zi9FcQ;wP@FyZr)N8njzKsu71tO5ALNK^|O}W}r zT6M=_BO*(UEXzm|;ljl$EO&oqW&IK%D2;lR$T`f0MNAcpMGQM5PlcfH`?hlBFXNt0 zO7eG)Z@ZgxSAV15AJC{*iKD0lo+&sWa!}2NQ?#`c^W(|}E30cPwVTY>vO~e6n7xuG zrY>@jL`D)v6!jW$9L)sZmf*kxvpzg`LU6nBzY02c3TkGxl0Zy8H2H74o0;ML;J~%9 zz?pki%$*Q8^KZeXO072cL8HC&P)T4IVw@IpM@8jn;JaIadp|%mkXPqU7wyiYjb{6~ zG)ccN2_{33kHzFcF?kVKot6O9tHFP^Am*;m022*Hmt5A7lW#N?ew z-F;&63h)!q1A3;~OVV_?*;;(2*Na4Mrr^6002ov JPDHLkV1kXfhBp8J literal 0 HcmV?d00001 diff --git a/FModel/Resources/cube_off.png b/FModel/Resources/cube_off.png new file mode 100644 index 0000000000000000000000000000000000000000..eae850fadca338df2e4dc0fe707527d9acf2c82c GIT binary patch literal 1094 zcmV-M1iAZ(P)R@PS2*2MCKozQ#qAr0IBJz<^>NTzP7lvVc zUY)4-RVo!s)1qo zp8|V;uYqrqBO|+j4}i6c*FRjRwf5<3xY|FZBRj=T(_Qhmx~9cG#Y6M_bRI?`S)F7CViuq zK`^>==W2I#XxJ62+d<-v=0v>hQXb_J_=o3h}I23MFg!ij^j|N zRJd~G3KJ6(l|&-ZSb^61R-sUc6pKafMIzkavj>!-`N9PvLqq6NiJQB3b3YPk2pkH9 z5D})Prf^-CTrP)U821)!5rAb`hzR*oiRrdBO53-yR)p4z7imu>5z}Ngk)Y7oi4zV3 zaQ*sqT-PO=%>ob(hf)7t`9?tXMp%}G=XqS~>f&#p=fMNo$H!?ua|X-jW1*>uOg_)V zgm?B(^$GPh`{||stR4j|Tu^8FjUjEAG*_g}m;^oU!w8ri3=5|X9Qg^t| z26!Yf3}&KHuEpb6hCwWwWos&h65;m^8<=Zq;_=OTCIEnE7|gV_@!Q6Yh*I=qGHgw! zQNVaC#%xQ=69JK@g_N~sy0eo9mIWg8WV38erxB%?=MiumoCwi&)0l4z?%mTzNNK(Ln)Pf>Pk$LYpYf<7LSvPMzM=U zUP-0qSNr|1))HT$qj7v-;DCr61$yfP+P01Bx@0mLg2CWJNV$yZdAu+?d+xxgQ-3zk z&3y*^@T88`pyLArZ;QzLz=nE2Hk-xg^C2Px0)eFCILAIbdh`s?155ymJKBj8Cu(0r zy&g4_cSYo|ZQC8L>oPq(O*kA*heDxGg2CYNY9;kLa^%Qk6+9>X1F*@zGKCcMZ~y=R M07*qoM6N<$f(XzGqW}N^ literal 0 HcmV?d00001 diff --git a/FModel/Resources/light.png b/FModel/Resources/light.png new file mode 100644 index 0000000000000000000000000000000000000000..cdce6934222e408f6fc9e99781f497df144dbc66 GIT binary patch literal 1234 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 R`E>vQ002ovPDHLkV1g$l`}6<+ literal 0 HcmV?d00001 diff --git a/FModel/Resources/square.png b/FModel/Resources/square.png new file mode 100644 index 0000000000000000000000000000000000000000..1edb68e8c1f78610a98ea12150bf19fa48b6d42b GIT binary patch literal 1239 zcmV;|1StE7P)#IWyCHOMxJA5h-F-P*PEdiHZq{ z8ZQqHGmQc0vTz!^fEJ@na<^$ zy|)iDZCXkj{F9ZP?6cPYpSAW{OW5BZ1=xbss{ny;-bdJt$Q=9o9^`bPjkuFxB9u)S z&&hF5^Cu`L2PQn`y8>QD$W8d^%8lFDiOfi&Yn~nOTL_8bgydHOiPf7Z4?z1{74t8G z;hBS}yO*T=ruwk_-vS|EBn=6Ov64mdLDL@&gu81bzly2i5>ffSS=E0*k}| zVhdI$u{v4xM0x(;LsA`vLc4_xW*v#=QG0B)<=Xykw+jtII6I`&Ie*Db46 z*>wa%)jS$Hu|_F`zY!;+5Z>x+c~&Cq=eEXF>WPTVlhd`^ln90in}IpN!fF;Bz^xXs z)VJ z!=)+cc>T=iiRq$;GoggrLQ~{5GdiVbcIiMarU8fZ!-zEZ;SxIU%-u5MlaCT z0U#_3NMQi32dGi09^Z!OE6qS&5_JS{0C#d~iv%YYv@zX=e1qtfKLb*Qj*D5q|b^0;j7bn5C`SA6OSxmd4G4E6WT9b)f4&_#w>H z!|2}mtzr*&O>L-#E=+I}kd*};qhfJNCi0KA4tbrJS2htmXYjJa7Lf(|%PkyEt-xC6 zKK$k`a%W*~Cp0dH zKRa=4azR8E7xek9hnk%89~&#b1O6B(RAqMo!P^M+1u8rnID<7K9XPs+#txlTAPkG@ zzF#`n|G8XP)MD5V|>{$EIT?AYPhwk@@_wE&!3wTjzg z#=z*&Q^YXN*9HRJ{|B%k95w&}?2HGJ5t?h(Fs8Yg>z2i>l9I#m@^YFY5gTX)jshov z)4P5{S5uFpPKg{QQH7($cLu zd<4AYev1Jw@KYcd>~NJH2ENU>@oO|%luRa{v~Bx<*XteRrZhG-;_-M8k?~5YlUgG2 z)|~nCF91t`7lAI5Ha22Iy>0365pODRRl z>#YKQ2fhLJ0j0p}zEMEMfuIpdr=jY?~dhf;K@ePjSEYq`^sMF=uq)V(7 z@B<2%1uOvif!)9bU{Lq@e7;XbWVvA&%Pq^=YN9Uu-&aDOF%7T{}OKTr(3 z2D}VZ!9RQN$6KTpK-cxw+}vDD(?lPz<_z$3);vkN_J1TD`#Em7bYMGhIeW8G>M57s z5D~my?;tBq0G_5uB)c3e-~jMF>6{e1;i>~_TxA)mcB65}RWwM!MVD6$`0oJ6f$xC5 zKpC(Icm)`qS)^%NjizZG8E^(@2e|6;5m{qMC)y%?T*7v zi2Si@=gxd(+jm7|kb)~NuL2G-n3BLD;2!BD&q8F;&FRxunq6IG*E}9_a&v1;(>&%l z&NIMWO+*k$pLZg1$>r5UfM=+mbmBJydyX1jml0qN0LSDmBV5jHQNQ zklhE=1_FOZo0|HSQqMg?0ZoxeN{`1AczA!(X)PM%D>px}0YGFdYG z)G2!E>+wyT$gr6+>4jYY5(Md-pK$5VzJosQ>RX4kA zF`A~eI*t%cTkG)=o0i^ZNOC@8?^^9_0chzO}vig-MZ zrfK)9@c~1##=DhL@94UI#qalb15u^a48Pxx<2Wd#h6MOG`Wp`% FLogger.Text("Could not download ImGui settings", Constants.WHITE, true)); } } + + public async Task InitOodle() + { + var oodlePath = Path.Combine(UserSettings.Default.OutputDirectory, ".data", OodleHelper.OODLE_DLL_NAME); + if (File.Exists(OodleHelper.OODLE_DLL_NAME)) + { + File.Move(OodleHelper.OODLE_DLL_NAME, oodlePath, true); + } + else if (!File.Exists(oodlePath)) + { + await OodleHelper.DownloadOodleDllAsync(oodlePath); + } + + OodleHelper.Initialize(oodlePath); + } + + public async Task InitZlib() + { + var zlibPath = Path.Combine(UserSettings.Default.OutputDirectory, ".data", ZlibHelper.DLL_NAME); + if (File.Exists(ZlibHelper.DLL_NAME)) + { + File.Move(ZlibHelper.DLL_NAME, zlibPath, true); + } + else if (!File.Exists(zlibPath)) + { + await ZlibHelper.DownloadDllAsync(zlibPath); + } + + ZlibHelper.Initialize(zlibPath); + } } diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index a858aa92..409b0d12 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -262,16 +262,18 @@ public class CUE4ParseViewModel : ViewModel break; case DefaultFileProvider: { - var ioStoreOnDemandPath = Path.Combine(UserSettings.Default.GameDirectory, - "..\\..\\..\\Cloud\\IoStoreOnDemand.ini"); - using var tr = File.OpenText(ioStoreOnDemandPath); + var ioStoreOnDemandPath = Path.Combine(UserSettings.Default.GameDirectory, "..\\..\\..\\Cloud\\IoStoreOnDemand.ini"); if (File.Exists(ioStoreOnDemandPath)) - IoStoreOnDemand.Read(tr); + { + using var s = new StreamReader(ioStoreOnDemandPath); + IoStoreOnDemand.Read(s); + } break; } } Provider.Initialize(); + Log.Information($"{Provider.Versions.Game} ({Provider.Versions.Platform}) | Archives: x{Provider.UnloadedVfs.Count} | AES: x{Provider.RequiredKeys.Count}"); foreach (var vfs in Provider.UnloadedVfs) // push files from the provider to the ui { @@ -319,6 +321,10 @@ public class CUE4ParseViewModel : ViewModel } InternalGameName = Provider.InternalGameName; + + var aesMax = Provider.RequiredKeys.Count + Provider.Keys.Count; + var archiveMax = Provider.UnloadedVfs.Count + Provider.MountedVfs.Count; + Log.Information($"Project: {InternalGameName} | Mounted: {Provider.MountedVfs.Count}/{archiveMax} | AES: {Provider.Keys.Count}/{aesMax}"); } public void ClearProvider() @@ -365,44 +371,6 @@ public class CUE4ParseViewModel : ViewModel }); } - public async Task InitOodle() - { - var dataDir = Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, ".data")).FullName; - var oodlePath = Path.Combine(dataDir, OodleHelper.OODLE_DLL_NAME); - bool result; - if (File.Exists(OodleHelper.OODLE_DLL_NAME)) - { - File.Move(OodleHelper.OODLE_DLL_NAME, oodlePath, true); - result = true; - } - else - { - result = await OodleHelper.DownloadOodleDllAsync(oodlePath); - } - - OodleHelper.Initialize(oodlePath); - return result; - } - - public async Task InitZlib() - { - var dataDir = Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, ".data")).FullName; - var zlibPath = Path.Combine(dataDir, ZlibHelper.DLL_NAME); - bool result; - if (File.Exists(ZlibHelper.DLL_NAME)) - { - File.Move(ZlibHelper.DLL_NAME, zlibPath, true); - result = true; - } - else - { - result = await ZlibHelper.DownloadDllAsync(zlibPath); - } - - ZlibHelper.Initialize(zlibPath); - return result; - } - public Task InitMappings(bool force = false) { if (!UserSettings.IsEndpointValid(EEndpointType.Mapping, out var endpoint)) diff --git a/FModel/Views/Snooper/Options.cs b/FModel/Views/Snooper/Options.cs index aab519e0..0493fcbd 100644 --- a/FModel/Views/Snooper/Options.cs +++ b/FModel/Views/Snooper/Options.cs @@ -42,6 +42,12 @@ public class Options Icons = new Dictionary { ["material"] = new ("materialicon"), + ["square"] = new ("square"), + ["square_off"] = new ("square_off"), + ["cube"] = new ("cube"), + ["cube_off"] = new ("cube_off"), + ["light"] = new ("light"), + ["light_off"] = new ("light_off"), ["noimage"] = new ("T_Placeholder_Item_Image"), ["checker"] = new ("checker"), ["pointlight"] = new ("pointlight"), diff --git a/FModel/Views/Snooper/SnimGui.cs b/FModel/Views/Snooper/SnimGui.cs index e774c83f..ff28a65a 100644 --- a/FModel/Views/Snooper/SnimGui.cs +++ b/FModel/Views/Snooper/SnimGui.cs @@ -215,15 +215,9 @@ public class SnimGui ImGui.SeparatorText("Editor"); if (ImGui.BeginTable("world_editor", 2)) { - Layout("Skybox");ImGui.PushID(1); - ImGui.Checkbox("", ref s.Renderer.ShowSkybox); - ImGui.PopID();Layout("Grid");ImGui.PushID(2); - ImGui.Checkbox("", ref s.Renderer.ShowGrid); - ImGui.PopID();Layout("Lights");ImGui.PushID(3); - ImGui.Checkbox("", ref s.Renderer.ShowLights); - ImGui.PopID();Layout("Animate With Rotation Only");ImGui.PushID(4); + Layout("Animate With Rotation Only");ImGui.PushID(1); ImGui.Checkbox("", ref s.Renderer.AnimateWithRotationOnly); - ImGui.PopID();Layout("Vertex Colors");ImGui.PushID(5); + ImGui.PopID();Layout("Vertex Colors");ImGui.PushID(2); var c = (int) s.Renderer.Color; ImGui.Combo("vertex_colors", ref c, "Default\0Sections\0Colors\0Normals\0Texture Coordinates\0"); @@ -783,13 +777,36 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio s.CursorState = CursorState.Normal; } + const float margin = 7.5f; + var buttonWidth = 14.0f * ImGui.GetWindowDpiScale(); + var basePos = new Vector2( size.X - buttonWidth - margin * 2, ImGui.GetFrameHeight() + margin); + ImGui.SetCursorPos(basePos); + ImGui.PushStyleColor(ImGuiCol.Button, Vector4.Zero); + ImGui.PushStyleColor(ImGuiCol.ButtonHovered, new Vector4(0.2f)); + ImGui.ImageButton("skybox_btn", s.Renderer.Options.Icons[s.Renderer.ShowSkybox ? "cube" : "cube_off"].GetPointer(), new Vector2(buttonWidth)); + TooltipCheckbox("Skybox", ref s.Renderer.ShowSkybox); + + basePos.X -= buttonWidth + margin; + ImGui.SetCursorPos(basePos); + ImGui.ImageButton("grid_btn", s.Renderer.Options.Icons[s.Renderer.ShowGrid ? "square" : "square_off"].GetPointer(), new Vector2(buttonWidth)); + TooltipCheckbox("Grid", ref s.Renderer.ShowGrid); + + basePos.X -= buttonWidth + margin; + ImGui.SetCursorPos(basePos); + ImGui.ImageButton("lights_btn", s.Renderer.Options.Icons[s.Renderer.ShowLights ? "light" : "light_off"].GetPointer(), new Vector2(buttonWidth)); + TooltipCheckbox("Lights", ref s.Renderer.ShowLights); + + ImGui.PopStyleColor(); + + float framerate = ImGui.GetIO().Framerate; - ImGui.SetCursorPos(size with { X = 7.5f }); + ImGui.SetCursorPos(size with { X = margin }); ImGui.Text($"FPS: {framerate:0} ({1000.0f / framerate:0.##} ms)"); const string label = "Previewed content may differ from final version saved or used in-game."; - ImGui.SetCursorPos(size with { X = size.X - ImGui.CalcTextSize(label).X - 7.5f }); + ImGui.SetCursorPos(size with { X = size.X - ImGui.CalcTextSize(label).X - margin }); ImGui.TextColored(new Vector4(0.50f, 0.50f, 0.50f, 1.00f), label); + }, false); ImGui.PopStyleVar(); } @@ -906,6 +923,17 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio if (ImGui.IsItemClicked()) ImGui.SetClipboardText(text ?? label); } + private static void TooltipCheckbox(string tooltip, ref bool value) + { + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.Text($"{tooltip}: {value}"); + ImGui.EndTooltip(); + } + if (ImGui.IsItemClicked()) value = !value; + } + private void Theme() { var style = ImGui.GetStyle(); From a6eb13c0ab60ec72327a1cc16cc4e39362eb67e8 Mon Sep 17 00:00:00 2001 From: Marlon Date: Wed, 10 Apr 2024 10:27:50 +0200 Subject: [PATCH 6/6] updated faulty epicmanifestparser --- CUE4Parse | 2 +- FModel/FModel.csproj | 2 +- FModel/MainWindow.xaml.cs | 8 ++++---- FModel/ViewModels/ApplicationViewModel.cs | 14 +++++--------- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 50d5e06d..08a5553d 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 50d5e06d421e2935cc4107df6352b36c341ec7c0 +Subproject commit 08a5553ddec50aa6064278b424620e95aabf4048 diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 3822bf06..0a192513 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -150,7 +150,7 @@ - + diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs index a79f953a..3c69be80 100644 --- a/FModel/MainWindow.xaml.cs +++ b/FModel/MainWindow.xaml.cs @@ -61,8 +61,8 @@ public partial class MainWindow break; } - await _applicationView.InitOodle(); - await _applicationView.InitZlib(); + await ApplicationViewModel.InitOodle(); + await ApplicationViewModel.InitZlib(); await _applicationView.CUE4Parse.Initialize(); await _applicationView.AesManager.InitAes(); await _applicationView.UpdateProvider(true); @@ -73,8 +73,8 @@ public partial class MainWindow _applicationView.CUE4Parse.VerifyConsoleVariables(), _applicationView.CUE4Parse.VerifyOnDemandArchives(), _applicationView.CUE4Parse.InitMappings(), - _applicationView.InitVgmStream(), - _applicationView.InitImGuiSettings(newOrUpdated), + ApplicationViewModel.InitVgmStream(), + ApplicationViewModel.InitImGuiSettings(newOrUpdated), Task.Run(() => { if (UserSettings.Default.DiscordRpc == EDiscordRpc.Always) diff --git a/FModel/ViewModels/ApplicationViewModel.cs b/FModel/ViewModels/ApplicationViewModel.cs index 444885f7..86929360 100644 --- a/FModel/ViewModels/ApplicationViewModel.cs +++ b/FModel/ViewModels/ApplicationViewModel.cs @@ -162,7 +162,7 @@ public class ApplicationViewModel : ViewModel RaisePropertyChanged(nameof(GameDisplayName)); } - public async Task InitVgmStream() + public static async Task InitVgmStream() { var vgmZipFilePath = Path.Combine(UserSettings.Default.OutputDirectory, ".data", "vgmstream-win.zip"); if (File.Exists(vgmZipFilePath)) return; @@ -188,7 +188,7 @@ public class ApplicationViewModel : ViewModel } } - public async Task InitImGuiSettings(bool forceDownload) + public static async Task InitImGuiSettings(bool forceDownload) { var imgui = "imgui.ini"; var imguiPath = Path.Combine(UserSettings.Default.OutputDirectory, ".data", imgui); @@ -203,7 +203,7 @@ public class ApplicationViewModel : ViewModel } } - public async Task InitOodle() + public static async ValueTask InitOodle() { var oodlePath = Path.Combine(UserSettings.Default.OutputDirectory, ".data", OodleHelper.OODLE_DLL_NAME); if (File.Exists(OodleHelper.OODLE_DLL_NAME)) @@ -218,14 +218,10 @@ public class ApplicationViewModel : ViewModel OodleHelper.Initialize(oodlePath); } - public async Task InitZlib() + public static async ValueTask InitZlib() { var zlibPath = Path.Combine(UserSettings.Default.OutputDirectory, ".data", ZlibHelper.DLL_NAME); - if (File.Exists(ZlibHelper.DLL_NAME)) - { - File.Move(ZlibHelper.DLL_NAME, zlibPath, true); - } - else if (!File.Exists(zlibPath)) + if (!File.Exists(zlibPath)) { await ZlibHelper.DownloadDllAsync(zlibPath); }