From b478d4398724d46b10970624c424770d2729eede Mon Sep 17 00:00:00 2001 From: Asval Date: Sat, 28 Oct 2023 19:52:07 +0200 Subject: [PATCH 01/85] yes --- CUE4Parse | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CUE4Parse b/CUE4Parse index d816fe61..b80d888b 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit d816fe61ac8e5798d1584ea2f9871acfca0ca429 +Subproject commit b80d888be74a1bb3f85b06925f035598874e6c80 From 422f892af8ebde483b8fc8f1db19664577204a37 Mon Sep 17 00:00:00 2001 From: Zain / Kaiser M <106357974+KaiserM21@users.noreply.github.com> Date: Mon, 30 Oct 2023 18:52:40 +0100 Subject: [PATCH 02/85] Fix Overwrite Material Index --- FModel/Views/Snooper/Renderer.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/FModel/Views/Snooper/Renderer.cs b/FModel/Views/Snooper/Renderer.cs index b66ea124..5f2b8e22 100644 --- a/FModel/Views/Snooper/Renderer.cs +++ b/FModel/Views/Snooper/Renderer.cs @@ -517,13 +517,11 @@ public class Renderer : IDisposable if (staticMeshComp.TryGetValue(out FPackageIndex[] overrideMaterials, "OverrideMaterials")) { - var max = model.Sections.Length - 1; - for (var j = 0; j < overrideMaterials.Length; j++) + for (var j = 0; j < overrideMaterials.Length && j < model.Sections.Length; j++) { - if (j > max) break; - if (!model.Materials[model.Sections[j].MaterialIndex].IsUsed || - overrideMaterials[j].Load() is not UMaterialInterface unrealMaterial) continue; - model.Materials[model.Sections[j].MaterialIndex].SwapMaterial(unrealMaterial); + var matIndex = model.Sections[j].MaterialIndex; + if (!(model.Materials[matIndex].IsUsed && overrideMaterials[matIndex].Load() is UMaterialInterface unrealMaterial)) continue; + model.Materials[matIndex].SwapMaterial(unrealMaterial); } } From 5e5051628d71cbd466a9843845a9bf5269a2a68e Mon Sep 17 00:00:00 2001 From: GMatrixGames Date: Thu, 2 Nov 2023 20:52:27 -0400 Subject: [PATCH 03/85] CUE4Parse-up --- CUE4Parse | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CUE4Parse b/CUE4Parse index b80d888b..94b08d60 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit b80d888be74a1bb3f85b06925f035598874e6c80 +Subproject commit 94b08d6022a8577732e805e5140931d318204c82 From ef94d35ca276b12cb0193cfc9b1a38457cbf6c61 Mon Sep 17 00:00:00 2001 From: Asval Date: Sat, 4 Nov 2023 18:09:07 +0100 Subject: [PATCH 04/85] qa testing test --- CUE4Parse | 2 +- FModel/Enums.cs | 4 ++- FModel/MainWindow.xaml.cs | 2 +- FModel/Settings/UserSettings.cs | 9 ++++++ .../ApiEndpoints/FModelApiEndpoint.cs | 31 ++++++++++++++----- FModel/ViewModels/ApplicationViewModel.cs | 2 +- FModel/ViewModels/GameSelectorViewModel.cs | 4 +-- FModel/Views/ImageMerger.xaml.cs | 2 +- 8 files changed, 42 insertions(+), 14 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 94b08d60..3ff8c179 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 94b08d6022a8577732e805e5140931d318204c82 +Subproject commit 3ff8c179dfbe817f22e9672dab9c2901a58b9db7 diff --git a/FModel/Enums.cs b/FModel/Enums.cs index 77c81c0e..ae52dfeb 100644 --- a/FModel/Enums.cs +++ b/FModel/Enums.cs @@ -71,7 +71,9 @@ public enum EUpdateMode [Description("Stable")] Stable, [Description("Beta")] - Beta + Beta, + [Description("QA Testing")] + Qa } public enum ECompressedAudio diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs index 449f04a0..9cc995ef 100644 --- a/FModel/MainWindow.xaml.cs +++ b/FModel/MainWindow.xaml.cs @@ -47,7 +47,7 @@ public partial class MainWindow { var newOrUpdated = UserSettings.Default.ShowChangelog; #if !DEBUG - ApplicationService.ApiEndpointView.FModelApi.CheckForUpdates(UserSettings.Default.UpdateMode); + ApplicationService.ApiEndpointView.FModelApi.CheckForUpdates(UserSettings.Default.UpdateMode, true); #endif switch (UserSettings.Default.AesReload) diff --git a/FModel/Settings/UserSettings.cs b/FModel/Settings/UserSettings.cs index 5dc4eb85..03c3b7cf 100644 --- a/FModel/Settings/UserSettings.cs +++ b/FModel/Settings/UserSettings.cs @@ -159,6 +159,13 @@ namespace FModel.Settings set => SetProperty(ref _updateMode, value); } + private string _commitId = Constants.APP_VERSION; + public string CommitId + { + get => _commitId; + set => SetProperty(ref _commitId, value); + } + private bool _keepDirectoryStructure = true; public bool KeepDirectoryStructure { @@ -231,6 +238,8 @@ namespace FModel.Settings [JsonIgnore] public DirectorySettings CurrentDir { get; set; } + [JsonIgnore] + public string ShortCommitId => CommitId[..7]; /// /// TO DELETEEEEEEEEEEEEE diff --git a/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs b/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs index 0e1b1f85..fb803341 100644 --- a/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs +++ b/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs @@ -116,10 +116,13 @@ public class FModelApiEndpoint : AbstractApiProvider return communityDesign; } - public void CheckForUpdates(EUpdateMode updateMode) + public void CheckForUpdates(EUpdateMode updateMode, bool launch = false) { - AutoUpdater.ParseUpdateInfoEvent += ParseUpdateInfoEvent; - AutoUpdater.CheckForUpdateEvent += CheckForUpdateEvent; + if (launch) + { + AutoUpdater.ParseUpdateInfoEvent += ParseUpdateInfoEvent; + AutoUpdater.CheckForUpdateEvent += CheckForUpdateEvent; + } AutoUpdater.Start($"https://api.fmodel.app/v1/infos/{updateMode}"); } @@ -130,9 +133,14 @@ public class FModelApiEndpoint : AbstractApiProvider { args.UpdateInfo = new UpdateInfoEventArgs { - CurrentVersion = _infos.Version, + CurrentVersion = _infos.Version.SubstringBefore('-'), ChangelogURL = _infos.ChangelogUrl, - DownloadURL = _infos.DownloadUrl + DownloadURL = _infos.DownloadUrl, + Mandatory = new CustomMandatory + { + Value = UserSettings.Default.UpdateMode == EUpdateMode.Qa, + CommitId = _infos.Version.SubstringAfter('+') + } }; } } @@ -141,8 +149,10 @@ public class FModelApiEndpoint : AbstractApiProvider { if (args is { CurrentVersion: { } }) { + var qa = (CustomMandatory) args.Mandatory; var currentVersion = new System.Version(args.CurrentVersion); - if (currentVersion == args.InstalledVersion) + if ((qa.Value && qa.CommitId == UserSettings.Default.CommitId) || // qa branch : same commit id + (!qa.Value && currentVersion == args.InstalledVersion && args.CurrentVersion == UserSettings.Default.CommitId)) // stable - beta branch : same version + commit id = version { if (UserSettings.Default.ShowChangelog) ShowChangelog(args); @@ -152,7 +162,7 @@ public class FModelApiEndpoint : AbstractApiProvider var downgrade = currentVersion < args.InstalledVersion; var messageBox = new MessageBoxModel { - Text = $"The latest version of FModel {UserSettings.Default.UpdateMode} is {args.CurrentVersion}. You are using version {args.InstalledVersion}. Do you want to {(downgrade ? "downgrade" : "update")} the application now?", + Text = $"The latest version of FModel {UserSettings.Default.UpdateMode.GetDescription()} is {(qa.Value ? qa.ShortCommitId : args.CurrentVersion)}. You are using version {(qa.Value ? UserSettings.Default.ShortCommitId : args.InstalledVersion)}. Do you want to {(downgrade ? "downgrade" : "update")} the application now?", Caption = $"{(downgrade ? "Downgrade" : "Update")} Available", Icon = MessageBoxImage.Question, Buttons = MessageBoxButtons.YesNo(), @@ -167,6 +177,7 @@ public class FModelApiEndpoint : AbstractApiProvider if (AutoUpdater.DownloadUpdate(args)) { UserSettings.Default.ShowChangelog = true; + UserSettings.Default.CommitId = qa.CommitId; Application.Current.Shutdown(); } } @@ -196,3 +207,9 @@ public class FModelApiEndpoint : AbstractApiProvider UserSettings.Default.ShowChangelog = false; } } + +public class CustomMandatory : Mandatory +{ + public string CommitId { get; set; } + public string ShortCommitId => CommitId[..7]; +} diff --git a/FModel/ViewModels/ApplicationViewModel.cs b/FModel/ViewModels/ApplicationViewModel.cs index dd044e67..9ef32ce0 100644 --- a/FModel/ViewModels/ApplicationViewModel.cs +++ b/FModel/ViewModels/ApplicationViewModel.cs @@ -46,7 +46,7 @@ public class ApplicationViewModel : ViewModel public CopyCommand CopyCommand => _copyCommand ??= new CopyCommand(this); private CopyCommand _copyCommand; - public string InitialWindowTitle => $"FModel {UserSettings.Default.UpdateMode}"; + public string InitialWindowTitle => $"FModel {UserSettings.Default.UpdateMode.GetDescription()}"; public string GameDisplayName => CUE4Parse.Provider.GameDisplayName ?? "Unknown"; public string TitleExtra => $"({UserSettings.Default.CurrentDir.UeVersion}){(Build != EBuildKind.Release ? $" ({Build})" : "")}"; diff --git a/FModel/ViewModels/GameSelectorViewModel.cs b/FModel/ViewModels/GameSelectorViewModel.cs index f1d40228..45f6c35a 100644 --- a/FModel/ViewModels/GameSelectorViewModel.cs +++ b/FModel/ViewModels/GameSelectorViewModel.cs @@ -87,8 +87,8 @@ public class GameSelectorViewModel : ViewModel .OrderBy(value => (int)value == ((int)value & ~0xF)); private IEnumerable EnumerateDetectedGames() { - yield return GetUnrealEngineGame("Fortnite", "\\FortniteGame\\Content\\Paks", EGame.GAME_UE5_3); - yield return DirectorySettings.Default("Fortnite [LIVE]", Constants._FN_LIVE_TRIGGER, ue: EGame.GAME_UE5_3); + yield return GetUnrealEngineGame("Fortnite", "\\FortniteGame\\Content\\Paks", EGame.GAME_UE5_4); + yield return DirectorySettings.Default("Fortnite [LIVE]", Constants._FN_LIVE_TRIGGER, ue: EGame.GAME_UE5_4); yield return GetUnrealEngineGame("Pewee", "\\RogueCompany\\Content\\Paks", EGame.GAME_RogueCompany); yield return GetUnrealEngineGame("Rosemallow", "\\Indiana\\Content\\Paks", EGame.GAME_UE4_21); yield return GetUnrealEngineGame("Catnip", "\\OakGame\\Content\\Paks", EGame.GAME_Borderlands3); diff --git a/FModel/Views/ImageMerger.xaml.cs b/FModel/Views/ImageMerger.xaml.cs index a8cc6a99..6190973d 100644 --- a/FModel/Views/ImageMerger.xaml.cs +++ b/FModel/Views/ImageMerger.xaml.cs @@ -142,7 +142,7 @@ public partial class ImageMerger var fileBrowser = new OpenFileDialog { Title = "Add image(s)", - InitialDirectory = $"{UserSettings.Default.OutputDirectory}\\Exports", + InitialDirectory = Path.Combine(UserSettings.Default.OutputDirectory, "Exports"), Multiselect = true, Filter = "Image Files (*.png,*.bmp,*.jpg,*.jpeg,*.jfif,*.jpe,*.tiff,*.tif)|*.png;*.bmp;*.jpg;*.jpeg;*.jfif;*.jpe;*.tiff;*.tif|All Files (*.*)|*.*" }; From af10998e3156840f490f3211619fdd119ccf7ed5 Mon Sep 17 00:00:00 2001 From: Asval Date: Sat, 4 Nov 2023 18:40:26 +0100 Subject: [PATCH 05/85] hello --- FModel/Settings/UserSettings.cs | 10 +++++----- .../ViewModels/ApiEndpoints/FModelApiEndpoint.cs | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/FModel/Settings/UserSettings.cs b/FModel/Settings/UserSettings.cs index 03c3b7cf..cdbbaae4 100644 --- a/FModel/Settings/UserSettings.cs +++ b/FModel/Settings/UserSettings.cs @@ -159,11 +159,11 @@ namespace FModel.Settings set => SetProperty(ref _updateMode, value); } - private string _commitId = Constants.APP_VERSION; - public string CommitId + private string _commitHash = Constants.APP_VERSION; + public string CommitHash { - get => _commitId; - set => SetProperty(ref _commitId, value); + get => _commitHash; + set => SetProperty(ref _commitHash, value); } private bool _keepDirectoryStructure = true; @@ -239,7 +239,7 @@ namespace FModel.Settings [JsonIgnore] public DirectorySettings CurrentDir { get; set; } [JsonIgnore] - public string ShortCommitId => CommitId[..7]; + public string ShortCommitHash => CommitHash[..7]; /// /// TO DELETEEEEEEEEEEEEE diff --git a/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs b/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs index fb803341..1e9e889d 100644 --- a/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs +++ b/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs @@ -139,7 +139,7 @@ public class FModelApiEndpoint : AbstractApiProvider Mandatory = new CustomMandatory { Value = UserSettings.Default.UpdateMode == EUpdateMode.Qa, - CommitId = _infos.Version.SubstringAfter('+') + CommitHash = _infos.Version.SubstringAfter('+') } }; } @@ -151,8 +151,8 @@ public class FModelApiEndpoint : AbstractApiProvider { var qa = (CustomMandatory) args.Mandatory; var currentVersion = new System.Version(args.CurrentVersion); - if ((qa.Value && qa.CommitId == UserSettings.Default.CommitId) || // qa branch : same commit id - (!qa.Value && currentVersion == args.InstalledVersion && args.CurrentVersion == UserSettings.Default.CommitId)) // stable - beta branch : same version + commit id = version + if ((qa.Value && qa.CommitHash == UserSettings.Default.CommitHash) || // qa branch : same commit id + (!qa.Value && currentVersion == args.InstalledVersion && args.CurrentVersion == UserSettings.Default.CommitHash)) // stable - beta branch : same version + commit id = version { if (UserSettings.Default.ShowChangelog) ShowChangelog(args); @@ -162,7 +162,7 @@ public class FModelApiEndpoint : AbstractApiProvider var downgrade = currentVersion < args.InstalledVersion; var messageBox = new MessageBoxModel { - Text = $"The latest version of FModel {UserSettings.Default.UpdateMode.GetDescription()} is {(qa.Value ? qa.ShortCommitId : args.CurrentVersion)}. You are using version {(qa.Value ? UserSettings.Default.ShortCommitId : args.InstalledVersion)}. Do you want to {(downgrade ? "downgrade" : "update")} the application now?", + Text = $"The latest version of FModel {UserSettings.Default.UpdateMode.GetDescription()} is {(qa.Value ? qa.ShortCommitHash : args.CurrentVersion)}. You are using version {(qa.Value ? UserSettings.Default.ShortCommitHash : args.InstalledVersion)}. Do you want to {(downgrade ? "downgrade" : "update")} the application now?", Caption = $"{(downgrade ? "Downgrade" : "Update")} Available", Icon = MessageBoxImage.Question, Buttons = MessageBoxButtons.YesNo(), @@ -177,7 +177,7 @@ public class FModelApiEndpoint : AbstractApiProvider if (AutoUpdater.DownloadUpdate(args)) { UserSettings.Default.ShowChangelog = true; - UserSettings.Default.CommitId = qa.CommitId; + UserSettings.Default.CommitHash = qa.CommitHash; Application.Current.Shutdown(); } } @@ -210,6 +210,6 @@ public class FModelApiEndpoint : AbstractApiProvider public class CustomMandatory : Mandatory { - public string CommitId { get; set; } - public string ShortCommitId => CommitId[..7]; + public string CommitHash { get; set; } + public string ShortCommitHash => CommitHash[..7]; } From 3cab5e6a27d98d4f81047ae1e74bfc88d3788297 Mon Sep 17 00:00:00 2001 From: Valentin Date: Sat, 4 Nov 2023 18:47:02 +0100 Subject: [PATCH 06/85] Create qa.yml --- .github/workflows/qa.yml | 44 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .github/workflows/qa.yml diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml new file mode 100644 index 00000000..90dd3fa8 --- /dev/null +++ b/.github/workflows/qa.yml @@ -0,0 +1,44 @@ +name: FModel QA Builder + +on: + push: + branches: [ dev ] + pull_request: + branches: [ dev ] + +jobs: + build: + runs-on: windows-latest + + steps: + - name: GIT Checkout + uses: actions/checkout@v2 + with: + submodules: 'true' + + - name: Fetch Submodules Recursively + run: git submodule update --init --recursive + + - name: .NET 6 Setup + uses: actions/setup-dotnet@v2 + with: + dotnet-version: '6.0.x' + + - name: .NET Restore + run: dotnet restore FModel + + - name: .NET Publish + run: dotnet publish FModel -c Release --no-self-contained -r win-x64 -f net6.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false + + - name: ZIP File + uses: papeloto/action-zip@v1 + with: + files: ./FModel/bin/Publish/FModel.exe + dest: ${{ github.sha }}.zip # will end up in working directory not the Publish folder + + - name: Edit QA Artifact + uses: irongut/EditRelease@v1.2.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + id: qa + files: ${{ github.sha }}.zip From 5f2fea6828943551a7d074b2fcc3b2d3533c8d96 Mon Sep 17 00:00:00 2001 From: Valentin Date: Sat, 4 Nov 2023 18:54:02 +0100 Subject: [PATCH 07/85] Update qa.yml --- .github/workflows/qa.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 90dd3fa8..434dc9ae 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -36,9 +36,13 @@ jobs: files: ./FModel/bin/Publish/FModel.exe dest: ${{ github.sha }}.zip # will end up in working directory not the Publish folder + deploy: + runs-on: ubuntu-latest + + steps: - name: Edit QA Artifact uses: irongut/EditRelease@v1.2.0 with: token: ${{ secrets.GITHUB_TOKEN }} - id: qa + id: 127997284 files: ${{ github.sha }}.zip From 3afb34018d538e574e13fce25459391e2838d8bc Mon Sep 17 00:00:00 2001 From: Valentin Date: Sat, 4 Nov 2023 19:04:10 +0100 Subject: [PATCH 08/85] Update qa.yml --- .github/workflows/qa.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 434dc9ae..743a90fb 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -36,13 +36,11 @@ jobs: files: ./FModel/bin/Publish/FModel.exe dest: ${{ github.sha }}.zip # will end up in working directory not the Publish folder - deploy: - runs-on: ubuntu-latest - - steps: - name: Edit QA Artifact - uses: irongut/EditRelease@v1.2.0 + uses: johnwbyrd/update-release@v1 with: token: ${{ secrets.GITHUB_TOKEN }} - id: 127997284 + release: FModel QA Testing + tag: qa + prerelease: true files: ${{ github.sha }}.zip From 33e311c4578cf394bc4cc5d6bdf907e4feff492f Mon Sep 17 00:00:00 2001 From: Valentin Date: Sat, 4 Nov 2023 19:05:58 +0100 Subject: [PATCH 09/85] Update qa.yml --- .github/workflows/qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 743a90fb..51dd7dcb 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -37,7 +37,7 @@ jobs: dest: ${{ github.sha }}.zip # will end up in working directory not the Publish folder - name: Edit QA Artifact - uses: johnwbyrd/update-release@v1 + uses: johnwbyrd/update-release@v1.0.0 with: token: ${{ secrets.GITHUB_TOKEN }} release: FModel QA Testing From 3b2a0fb044b4801aa85b55635969917e710696a2 Mon Sep 17 00:00:00 2001 From: Valentin Date: Sat, 4 Nov 2023 19:42:41 +0100 Subject: [PATCH 10/85] Update qa.yml --- .github/workflows/qa.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 51dd7dcb..d28478ed 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -27,6 +27,12 @@ jobs: - name: .NET Restore run: dotnet restore FModel + - name: Get Version + id: package_version + uses: KageKirin/get-csproj-version@v1.0.0 + with: + file: FModel/FModel.csproj + - name: .NET Publish run: dotnet publish FModel -c Release --no-self-contained -r win-x64 -f net6.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false @@ -37,6 +43,7 @@ jobs: dest: ${{ github.sha }}.zip # will end up in working directory not the Publish folder - name: Edit QA Artifact + id: edited_release uses: johnwbyrd/update-release@v1.0.0 with: token: ${{ secrets.GITHUB_TOKEN }} @@ -44,3 +51,18 @@ jobs: tag: qa prerelease: true files: ${{ github.sha }}.zip + + - name: FModel Auth + id: fmodel_auth + uses: fjogeleit/http-request-action@v1.14.1 + with: + url: "https://api.fmodel.app/v1/oauth/token" + data: '{"username": "${{ secrets.API_USERNAME }}", "password": "${{ secrets.API_PASSWORD }}"}' + + - name: FModel Deploy Build + uses: fjogeleit/http-request-action@v1.14.1 + with: + url: "https://api.fmodel.app/v1/infos/${{ secrets.QA_ID }}" + method: "PATCH" + bearerToken: ${{ fromJson(steps.fmodel_auth.outputs.response).accessToken }} + data: '{"version": "${{ steps.test.package_version.version }}-dev+${{ github.sha }}", "downloadUrl": "${{ steps.edited_release.outputs.files }}"}' From 88e3ab1a714ae2efeffcbe48e36ae490c587195a Mon Sep 17 00:00:00 2001 From: Valentin Date: Sat, 4 Nov 2023 19:51:21 +0100 Subject: [PATCH 11/85] Update qa.yml --- .github/workflows/qa.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index d28478ed..32a492d8 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -32,6 +32,7 @@ jobs: uses: KageKirin/get-csproj-version@v1.0.0 with: file: FModel/FModel.csproj + regex: '^(?[0-9])\.(?[0-9])\.(?[0-9])\.(?[0-9])$' - name: .NET Publish run: dotnet publish FModel -c Release --no-self-contained -r win-x64 -f net6.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false From 0f7bd1833a4033c3a569cd4b6c2509c575481991 Mon Sep 17 00:00:00 2001 From: Valentin Date: Sat, 4 Nov 2023 19:59:12 +0100 Subject: [PATCH 12/85] Update qa.yml --- .github/workflows/qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 32a492d8..956f9dce 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -66,4 +66,4 @@ jobs: url: "https://api.fmodel.app/v1/infos/${{ secrets.QA_ID }}" method: "PATCH" bearerToken: ${{ fromJson(steps.fmodel_auth.outputs.response).accessToken }} - data: '{"version": "${{ steps.test.package_version.version }}-dev+${{ github.sha }}", "downloadUrl": "${{ steps.edited_release.outputs.files }}"}' + data: '{"version": "${{ steps.test.package_version.version }}-dev+${{ github.sha }}", "downloadUrl": "${{ join(steps.edited_release.outputs.files.*, ",") }}"}' From 1e9f7e73552ce82011cb3ca90f67c08947920af2 Mon Sep 17 00:00:00 2001 From: Valentin Date: Sat, 4 Nov 2023 20:03:55 +0100 Subject: [PATCH 13/85] Update qa.yml --- .github/workflows/qa.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 956f9dce..91717ab2 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -53,6 +53,9 @@ jobs: prerelease: true files: ${{ github.sha }}.zip + - name: Show Response + run: echo ${{ steps.edited_release.outputs.files.* }} + - name: FModel Auth id: fmodel_auth uses: fjogeleit/http-request-action@v1.14.1 @@ -66,4 +69,4 @@ jobs: url: "https://api.fmodel.app/v1/infos/${{ secrets.QA_ID }}" method: "PATCH" bearerToken: ${{ fromJson(steps.fmodel_auth.outputs.response).accessToken }} - data: '{"version": "${{ steps.test.package_version.version }}-dev+${{ github.sha }}", "downloadUrl": "${{ join(steps.edited_release.outputs.files.*, ",") }}"}' + data: '{"version": "${{ steps.test.package_version.version }}-dev+${{ github.sha }}"}' From 26a0dfcde85d4d7c6eb73a1e8275fd80fbaf27f0 Mon Sep 17 00:00:00 2001 From: Valentin Date: Sat, 4 Nov 2023 20:08:53 +0100 Subject: [PATCH 14/85] Update qa.yml --- .github/workflows/qa.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 91717ab2..eb7dd25c 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -54,7 +54,9 @@ jobs: files: ${{ github.sha }}.zip - name: Show Response - run: echo ${{ steps.edited_release.outputs.files.* }} + run: | + echo ${{ steps.package_version.outputs.version }} + echo ${{ join(steps.edited_release.outputs.files.*, ",") }} - name: FModel Auth id: fmodel_auth @@ -69,4 +71,4 @@ jobs: url: "https://api.fmodel.app/v1/infos/${{ secrets.QA_ID }}" method: "PATCH" bearerToken: ${{ fromJson(steps.fmodel_auth.outputs.response).accessToken }} - data: '{"version": "${{ steps.test.package_version.version }}-dev+${{ github.sha }}"}' + data: '{"version": "${{ steps.package_version.outputs.version }}-dev+${{ github.sha }}"}' From f510ca0a0c3e3c10c4612e401481741621b36eab Mon Sep 17 00:00:00 2001 From: Valentin Date: Sat, 4 Nov 2023 20:10:15 +0100 Subject: [PATCH 15/85] Update qa.yml --- .github/workflows/qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index eb7dd25c..16c42c07 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -56,7 +56,7 @@ jobs: - name: Show Response run: | echo ${{ steps.package_version.outputs.version }} - echo ${{ join(steps.edited_release.outputs.files.*, ",") }} + echo ${{ join(steps.edited_release.outputs.files.*, ';') }} - name: FModel Auth id: fmodel_auth From e81259b298700379052a737b49415349258be574 Mon Sep 17 00:00:00 2001 From: Valentin Date: Sat, 4 Nov 2023 20:14:18 +0100 Subject: [PATCH 16/85] Update qa.yml --- .github/workflows/qa.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 16c42c07..9f785f37 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -54,9 +54,7 @@ jobs: files: ${{ github.sha }}.zip - name: Show Response - run: | - echo ${{ steps.package_version.outputs.version }} - echo ${{ join(steps.edited_release.outputs.files.*, ';') }} + run: echo ${{ join(steps.edited_release.outputs.files.*, ';') }} - name: FModel Auth id: fmodel_auth From b5a3b1c65558ef985f7c7ae9015fffcbeda0a02e Mon Sep 17 00:00:00 2001 From: Valentin Date: Sat, 4 Nov 2023 20:18:11 +0100 Subject: [PATCH 17/85] Update qa.yml --- .github/workflows/qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 9f785f37..3eab0b80 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -54,7 +54,7 @@ jobs: files: ${{ github.sha }}.zip - name: Show Response - run: echo ${{ join(steps.edited_release.outputs.files.*, ';') }} + run: echo ${{ join(steps.edited_release.outputs.files, ';') }} - name: FModel Auth id: fmodel_auth From 5ef205c14229a5f83fd1191b632e73a4c2a9b0e2 Mon Sep 17 00:00:00 2001 From: Valentin Date: Sat, 4 Nov 2023 20:23:37 +0100 Subject: [PATCH 18/85] Update qa.yml --- .github/workflows/qa.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 3eab0b80..b3e00a8d 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -53,9 +53,6 @@ jobs: prerelease: true files: ${{ github.sha }}.zip - - name: Show Response - run: echo ${{ join(steps.edited_release.outputs.files, ';') }} - - name: FModel Auth id: fmodel_auth uses: fjogeleit/http-request-action@v1.14.1 @@ -69,4 +66,4 @@ jobs: url: "https://api.fmodel.app/v1/infos/${{ secrets.QA_ID }}" method: "PATCH" bearerToken: ${{ fromJson(steps.fmodel_auth.outputs.response).accessToken }} - data: '{"version": "${{ steps.package_version.outputs.version }}-dev+${{ github.sha }}"}' + data: '{"version": "${{ steps.package_version.outputs.version }}-dev+${{ github.sha }}", "downloadUrl": "https://github.com/4sval/FModel/releases/download/qa/${{ github.sha }}.zip"}' From 88adcd03be3cff593298b50b732e80188fd75217 Mon Sep 17 00:00:00 2001 From: Asval Date: Wed, 8 Nov 2023 22:15:04 +0100 Subject: [PATCH 19/85] load ondemand archives --- .github/workflows/qa.yml | 2 - CUE4Parse | 2 +- FModel/MainWindow.xaml.cs | 3 +- .../ApiEndpoints/EpicApiEndpoint.cs | 34 ++----- FModel/ViewModels/CUE4ParseViewModel.cs | 98 +++++-------------- 5 files changed, 32 insertions(+), 107 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index b3e00a8d..70f2f7ae 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -3,8 +3,6 @@ name: FModel QA Builder on: push: branches: [ dev ] - pull_request: - branches: [ dev ] jobs: build: diff --git a/CUE4Parse b/CUE4Parse index 3ff8c179..5107809d 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 3ff8c179dfbe817f22e9672dab9c2901a58b9db7 +Subproject commit 5107809d35e3c43121c717b3b3aa732aa08e77fb diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs index 9cc995ef..0d0ccca8 100644 --- a/FModel/MainWindow.xaml.cs +++ b/FModel/MainWindow.xaml.cs @@ -69,8 +69,7 @@ public partial class MainWindow #endif await Task.WhenAll( _applicationView.CUE4Parse.VerifyConsoleVariables(), - _applicationView.CUE4Parse.VerifyVirtualCache(), - _applicationView.CUE4Parse.VerifyContentBuildManifest(), + _applicationView.CUE4Parse.VerifyOnDemandArchives(), _applicationView.CUE4Parse.InitMappings(), _applicationView.InitImGuiSettings(newOrUpdated), _applicationView.InitVgmStream(), diff --git a/FModel/ViewModels/ApiEndpoints/EpicApiEndpoint.cs b/FModel/ViewModels/ApiEndpoints/EpicApiEndpoint.cs index e09390a2..386762ce 100644 --- a/FModel/ViewModels/ApiEndpoints/EpicApiEndpoint.cs +++ b/FModel/ViewModels/ApiEndpoints/EpicApiEndpoint.cs @@ -14,20 +14,12 @@ public class EpicApiEndpoint : AbstractApiProvider private const string _OAUTH_URL = "https://account-public-service-prod03.ol.epicgames.com/account/api/oauth/token"; private const string _BASIC_TOKEN = "basic MzQ0NmNkNzI2OTRjNGE0NDg1ZDgxYjc3YWRiYjIxNDE6OTIwOWQ0YTVlMjVhNDU3ZmI5YjA3NDg5ZDMxM2I0MWE="; private const string _APP_URL = "https://launcher-public-service-prod06.ol.epicgames.com/launcher/api/public/assets/v2/platform/Windows/namespace/fn/catalogItem/4fe75bbc5a674f4f9b356b5c90567da5/app/Fortnite/label/Live"; - private const string _CBM_URL = "https://launcher-public-service-prod06.ol.epicgames.com/launcher/api/public/assets/Windows/5cb97847cee34581afdbc445400e2f77/FortniteContentBuilds"; public EpicApiEndpoint(RestClient client) : base(client) { } public async Task GetManifestAsync(CancellationToken token) { - if (await IsExpired().ConfigureAwait(false)) - { - var auth = await GetAuthAsync(token).ConfigureAwait(false); - if (auth != null) - { - UserSettings.Default.LastAuthResponse = auth; - } - } + await VerifyAuth(token).ConfigureAwait(false); var request = new FRestRequest(_APP_URL); request.AddHeader("Authorization", $"bearer {UserSettings.Default.LastAuthResponse.AccessToken}"); @@ -36,7 +28,12 @@ public class EpicApiEndpoint : AbstractApiProvider return response.IsSuccessful ? new ManifestInfo(response.Content) : null; } - public async Task GetContentBuildManifestAsync(CancellationToken token, string label) + public ManifestInfo GetManifest(CancellationToken token) + { + return GetManifestAsync(token).GetAwaiter().GetResult(); + } + + public async Task VerifyAuth(CancellationToken token) { if (await IsExpired().ConfigureAwait(false)) { @@ -46,23 +43,6 @@ public class EpicApiEndpoint : AbstractApiProvider UserSettings.Default.LastAuthResponse = auth; } } - - var request = new FRestRequest(_CBM_URL); - request.AddHeader("Authorization", $"bearer {UserSettings.Default.LastAuthResponse.AccessToken}"); - request.AddQueryParameter("label", label); - 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 ContentBuildManifestInfo(response.Content) : null; - } - - public ManifestInfo GetManifest(CancellationToken token) - { - return GetManifestAsync(token).GetAwaiter().GetResult(); - } - - public ContentBuildManifestInfo GetContentBuildManifest(CancellationToken token, string label) - { - return GetContentBuildManifestAsync(token, label).GetAwaiter().GetResult(); } private async Task GetAuthAsync(CancellationToken token) diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 473ad1fb..21de8fec 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net.Http.Headers; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -31,7 +32,6 @@ using CUE4Parse.UE4.Versions; using CUE4Parse.UE4.Wwise; using CUE4Parse_Conversion; using CUE4Parse_Conversion.Sounds; -using CUE4Parse.FileProvider.Objects; using CUE4Parse.UE4.Objects.Core.Serialization; using EpicManifestParser.Objects; using FModel.Creator; @@ -121,7 +121,7 @@ public class CUE4ParseViewModel : ViewModel public AssetsFolderViewModel AssetsFolder { get; } public SearchViewModel SearchVm { get; } public TabControlViewModel TabControl { get; } - public ConfigIni BuildInfo { get; } + public ConfigIni IoStoreOnDemand { get; } public CUE4ParseViewModel() { @@ -175,7 +175,7 @@ public class CUE4ParseViewModel : ViewModel AssetsFolder = new AssetsFolderViewModel(); SearchVm = new SearchViewModel(); TabControl = new TabControlViewModel(); - BuildInfo = new ConfigIni(nameof(BuildInfo)); + IoStoreOnDemand = new ConfigIni(nameof(IoStoreOnDemand)); } public async Task Initialize() @@ -216,9 +216,9 @@ public class CUE4ParseViewModel : ViewModel foreach (var fileManifest in manifest.FileManifests) { - if (fileManifest.Name.Equals("Cloud/BuildInfo.ini", StringComparison.OrdinalIgnoreCase)) + if (fileManifest.Name.Equals("Cloud/IoStoreOnDemand.ini", StringComparison.OrdinalIgnoreCase)) { - BuildInfo.Read(new StreamReader(fileManifest.GetStream())); + IoStoreOnDemand.Read(new StreamReader(fileManifest.GetStream())); continue; } if (!_fnLive.IsMatch(fileManifest.Name)) continue; @@ -252,8 +252,8 @@ public class CUE4ParseViewModel : ViewModel break; case DefaultFileProvider: - var buildInfoPath = Path.Combine(UserSettings.Default.GameDirectory, "..\\..\\..\\Cloud\\BuildInfo.ini"); - if (File.Exists(buildInfoPath)) BuildInfo.Read(new StringReader(File.ReadAllText(buildInfoPath))); + var ioStoreOnDemandPath = Path.Combine(UserSettings.Default.GameDirectory, "..\\..\\..\\Cloud\\IoStoreOnDemand.ini"); + if (File.Exists(ioStoreOnDemandPath)) IoStoreOnDemand.Read(new StringReader(File.ReadAllText(ioStoreOnDemandPath))); break; } @@ -294,7 +294,7 @@ public class CUE4ParseViewModel : ViewModel if (Provider.MountedVfs.FirstOrDefault(x => x.Name == file.Name) is not { } vfs) { if (Provider.UnloadedVfs.FirstOrDefault(x => x.Name == file.Name) is IoStoreReader store) - file.FileCount = (int) store.Info.TocEntryCount - 1; + file.FileCount = (int) store.TocResource.Header.TocEntryCount - 1; continue; } @@ -436,87 +436,35 @@ public class CUE4ParseViewModel : ViewModel }); } - private int _vfcCount { get; set; } - public Task VerifyVirtualCache() - { - if (Provider is StreamedFileProvider { LiveGame: "FortniteLive" } || _vfcCount > 0) - return Task.CompletedTask; - - return Task.Run(() => - { - _vfcCount = Provider.LoadVirtualCache(); - if (_vfcCount > 0) - FLogger.Append(ELog.Information, - () => FLogger.Text($"{_vfcCount} cached packages loaded", Constants.WHITE, true)); - }); - } - - public Task VerifyContentBuildManifest() + public Task VerifyOnDemandArchives() { + // only local fortnite if (Provider is not DefaultFileProvider || !Provider.InternalGameName.Equals("FortniteGame", StringComparison.OrdinalIgnoreCase)) return Task.CompletedTask; + // scuffed but working var persistentDownloadDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "FortniteGame/Saved/PersistentDownloadDir"); - var vfcMetadata = Path.Combine(persistentDownloadDir, "VFC", "vfc.meta"); - if (!File.Exists(vfcMetadata)) + var iasFileInfo = new FileInfo(Path.Combine(persistentDownloadDir, "ias", "ias.cache.0")); + if (!iasFileInfo.Exists || iasFileInfo.Length == 0) return Task.CompletedTask; - // load if local fortnite with ondemand disabled - // VFC folder is created at launch if ondemand - // VFC folder is deleted at launch if not ondemand anymore - return Task.Run(() => + return Task.Run(async () => { var inst = new List(); - BuildInfo.FindPropertyInstructions("Content", "Label", inst); + IoStoreOnDemand.FindPropertyInstructions("Endpoint", "TocPath", inst); if (inst.Count <= 0) return; - var manifestInfo = _apiEndpointView.EpicApi.GetContentBuildManifest(default, inst[0].Value); - var manifestDir = new DirectoryInfo(Path.Combine(persistentDownloadDir, "ManifestCache")); - var manifestPath = Path.Combine(manifestDir.FullName, manifestInfo?.FileName ?? ""); + var ioStoreOnDemandPath = Path.Combine(UserSettings.Default.GameDirectory, "..\\..\\..\\Cloud", inst[0].Value.SubstringAfterLast("/").SubstringBefore("\"")); + if (!File.Exists(ioStoreOnDemandPath)) return; - byte[] manifestData; - if (File.Exists(manifestPath)) + await _apiEndpointView.EpicApi.VerifyAuth(default); + await Provider.RegisterVfs(new IoChunkToc(ioStoreOnDemandPath), new IoStoreOnDemandOptions { - manifestData = File.ReadAllBytes(manifestPath); - } - else if (manifestInfo != null) - { - manifestData = manifestInfo.DownloadManifestData(); - File.WriteAllBytes(manifestPath, manifestData); - } - else if (manifestDir.Exists && manifestDir.GetFiles("*.manifest") is { Length: > 0} cachedManifests) - { - manifestData = File.ReadAllBytes(cachedManifests[0].FullName); - } - else return; - - var manifest = new Manifest(manifestData, new ManifestOptions - { - ChunkBaseUri = new Uri("http://epicgames-download1.akamaized.net/Builds/Fortnite/Content/CloudDir/ChunksV4/", UriKind.Absolute), - ChunkCacheDirectory = Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, ".data")) + ChunkBaseUri = new Uri("https://download.epicgames.com/ias/fortnite/", UriKind.Absolute), + ChunkCacheDirectory = Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, ".data")), + Authorization = new AuthenticationHeaderValue("Bearer", UserSettings.Default.LastAuthResponse.AccessToken) }); - - var onDemandFiles = new Dictionary(); - foreach (var fileManifest in manifest.FileManifests) - { - if (Provider.Files.TryGetValue(fileManifest.Name, out _)) continue; - - var onDemandFile = new StreamedGameFile(fileManifest.Name, fileManifest.GetStream(), Provider.Versions); - if (Provider.IsCaseInsensitive) onDemandFiles[onDemandFile.Path.ToLowerInvariant()] = onDemandFile; - else onDemandFiles[onDemandFile.Path] = onDemandFile; - } - - (Provider.Files as FileProviderDictionary)?.AddFiles(onDemandFiles); - if (onDemandFiles.Count > 0) - FLogger.Append(ELog.Information, - () => FLogger.Text($"{onDemandFiles.Count} streamed packages loaded", Constants.WHITE, true)); -#if DEBUG - - var missing = manifest.FileManifests.Count - onDemandFiles.Count; - if (missing > 0) - FLogger.Append(ELog.Debug, - () => FLogger.Text($"{missing} packages were already loaded by regular archives", Constants.WHITE, true)); -#endif + await Provider.MountAsync(); }); } From b525796f7903c28954c1170ca8363d1863ccb831 Mon Sep 17 00:00:00 2001 From: Asval Date: Thu, 9 Nov 2023 20:34:58 +0100 Subject: [PATCH 20/85] acl track skipping workaround --- CUE4Parse | 2 +- FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs | 2 +- FModel/Views/Snooper/Animations/Skeleton.cs | 2 +- FModel/Views/Snooper/Models/Section.cs | 4 ++-- FModel/Views/Snooper/Shading/Material.cs | 12 ++++++------ 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 5107809d..27580a04 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 5107809d35e3c43121c717b3b3aa732aa08e77fb +Subproject commit 27580a04fd5a32572300c2a8f1d4d821a6634843 diff --git a/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs b/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs index 1e9e889d..498ae089 100644 --- a/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs +++ b/FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs @@ -176,7 +176,7 @@ public class FModelApiEndpoint : AbstractApiProvider { if (AutoUpdater.DownloadUpdate(args)) { - UserSettings.Default.ShowChangelog = true; + UserSettings.Default.ShowChangelog = !qa.Value; UserSettings.Default.CommitHash = qa.CommitHash; Application.Current.Shutdown(); } diff --git a/FModel/Views/Snooper/Animations/Skeleton.cs b/FModel/Views/Snooper/Animations/Skeleton.cs index ff01318d..ce1a0dcc 100644 --- a/FModel/Views/Snooper/Animations/Skeleton.cs +++ b/FModel/Views/Snooper/Animations/Skeleton.cs @@ -201,7 +201,7 @@ public class Skeleton : IDisposable sequence.Tracks[bone.SkeletonIndex].GetBoneTransform(f, sequence.NumFrames, ref boneOrientation, ref bonePosition, ref boneScale); if (!bone.IsRoot) boneMatrix = _boneMatriceAtFrame[bone.ParentIndex]; - bonePosition = rotationOnly ? bone.Rest.Position : bonePosition * Constants.SCALE_DOWN_RATIO; + bonePosition = rotationOnly || bonePosition.IsZero() ? bone.Rest.Position : bonePosition * Constants.SCALE_DOWN_RATIO; boneMatrix = new Transform { diff --git a/FModel/Views/Snooper/Models/Section.cs b/FModel/Views/Snooper/Models/Section.cs index 0c96ed90..4a4ced53 100644 --- a/FModel/Views/Snooper/Models/Section.cs +++ b/FModel/Views/Snooper/Models/Section.cs @@ -16,11 +16,11 @@ public class Section public Section(int index, int facesCount, int firstFaceIndex) { - MaterialIndex = index; + MaterialIndex = Math.Max(0, index); FacesCount = facesCount; FirstFaceIndex = firstFaceIndex; FirstFaceIndexPtr = new IntPtr(FirstFaceIndex * sizeof(uint)); - Color = Constants.COLOR_PALETTE[index % Constants.PALETTE_LENGTH]; + Color = Constants.COLOR_PALETTE[MaterialIndex % Constants.PALETTE_LENGTH]; Show = true; } diff --git a/FModel/Views/Snooper/Shading/Material.cs b/FModel/Views/Snooper/Shading/Material.cs index 7c1d6296..2aabe66f 100644 --- a/FModel/Views/Snooper/Shading/Material.cs +++ b/FModel/Views/Snooper/Shading/Material.cs @@ -329,12 +329,12 @@ public class Material : IDisposable switch (SelectedTexture) { - case 0: + case 0 when DiffuseColor.Length > 0: SnimGui.Layout("Color");ImGui.PushID(3); ImGui.ColorEdit4("", ref DiffuseColor[SelectedChannel], ImGuiColorEditFlags.NoAlpha); ImGui.PopID(); break; - case 4: + case 4 when EmissiveColor.Length > 0: SnimGui.Layout("Color");ImGui.PushID(3); ImGui.ColorEdit4("", ref EmissiveColor[SelectedChannel], ImGuiColorEditFlags.NoAlpha); ImGui.PopID();SnimGui.Layout("Region");ImGui.PushID(4); @@ -357,11 +357,11 @@ public class Material : IDisposable { return SelectedTexture switch { - 0 => Diffuse[SelectedChannel], - 1 => Normals[SelectedChannel], - 2 => SpecularMasks[SelectedChannel], + 0 when Diffuse.Length > 0 => Diffuse[SelectedChannel], + 1 when Normals.Length > 0 => Normals[SelectedChannel], + 2 when SpecularMasks.Length > 0 => SpecularMasks[SelectedChannel], 3 => Ao.Texture, - 4 => Emissive[SelectedChannel], + 4 when Emissive.Length > 0 => Emissive[SelectedChannel], _ => null }; } From d6af826097c0f8d77c29a3b217c9834482a1cd4a Mon Sep 17 00:00:00 2001 From: Asval Date: Thu, 16 Nov 2023 20:39:01 +0100 Subject: [PATCH 21/85] instanced SMs in umap --- CUE4Parse | 2 +- FModel/FModel.csproj | 14 +++--- FModel/Framework/ImGuiController.cs | 4 +- FModel/Views/Snooper/Renderer.cs | 76 +++++++++++++++++++++-------- 4 files changed, 66 insertions(+), 30 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 27580a04..b6dfd4cd 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 27580a04fd5a32572300c2a8f1d4d821a6634843 +Subproject commit b6dfd4cd53a99b48850e0b2f9f00321816643f99 diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index e8971df2..3bf68654 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -140,22 +140,22 @@ - + - - + + - + - + - - + + diff --git a/FModel/Framework/ImGuiController.cs b/FModel/Framework/ImGuiController.cs index 3c099c7b..9077553b 100644 --- a/FModel/Framework/ImGuiController.cs +++ b/FModel/Framework/ImGuiController.cs @@ -440,7 +440,7 @@ outputColor = color * texture(in_fontTexture, texCoord); GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBuffer); for (int i = 0; i < draw_data.CmdListsCount; i++) { - ImDrawListPtr cmd_list = draw_data.CmdListsRange[i]; + ImDrawListPtr cmd_list = draw_data.CmdLists[i]; int vertexSize = cmd_list.VtxBuffer.Size * Unsafe.SizeOf(); if (vertexSize > _vertexBufferSize) @@ -490,7 +490,7 @@ outputColor = color * texture(in_fontTexture, texCoord); // Render command lists for (int n = 0; n < draw_data.CmdListsCount; n++) { - ImDrawListPtr cmd_list = draw_data.CmdListsRange[n]; + ImDrawListPtr cmd_list = draw_data.CmdLists[n]; GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero, cmd_list.VtxBuffer.Size * Unsafe.SizeOf(), cmd_list.VtxBuffer.Data); CheckGLError($"Data Vert {n}"); diff --git a/FModel/Views/Snooper/Renderer.cs b/FModel/Views/Snooper/Renderer.cs index 5f2b8e22..568cf9f2 100644 --- a/FModel/Views/Snooper/Renderer.cs +++ b/FModel/Views/Snooper/Renderer.cs @@ -454,34 +454,57 @@ public class Renderer : IDisposable private void WorldMesh(UObject actor, Transform transform) { - if (!actor.TryGetValue(out FPackageIndex staticMeshComponent, "StaticMeshComponent", "StaticMesh", "Mesh", "LightMesh") || - !staticMeshComponent.TryLoad(out UStaticMeshComponent staticMeshComp) || - !staticMeshComp.GetStaticMesh().TryLoad(out UStaticMesh m) || m.Materials.Length < 1) - return; - - var guid = m.LightingGuid; - var t = new Transform + if (actor.TryGetValue(out FPackageIndex[] instanceComponents, "InstanceComponents")) { - Relation = transform.Matrix, - Position = staticMeshComp.GetOrDefault("RelativeLocation", FVector.ZeroVector) * Constants.SCALE_DOWN_RATIO, - Rotation = staticMeshComp.GetOrDefault("RelativeRotation", FRotator.ZeroRotator).Quaternion(), - Scale = staticMeshComp.GetOrDefault("RelativeScale3D", FVector.OneVector) - }; + foreach (var component in instanceComponents) + { + if (!component.TryLoad(out UInstancedStaticMeshComponent staticMeshComp) || + !staticMeshComp.GetStaticMesh().TryLoad(out UStaticMesh m) || m.Materials.Length < 1) + continue; + + if (staticMeshComp.PerInstanceSMData is { Length: > 0 }) + { + + var relation = CalculateTransform(staticMeshComp, transform); + foreach (var perInstanceData in staticMeshComp.PerInstanceSMData) + { + ProcessMesh(actor, staticMeshComp, m, new Transform + { + Relation = relation.Matrix, + Position = perInstanceData.TransformData.Translation * Constants.SCALE_DOWN_RATIO, + Rotation = perInstanceData.TransformData.Rotation, + Scale = perInstanceData.TransformData.Scale3D + }); + } + } + else ProcessMesh(actor, staticMeshComp, m, CalculateTransform(staticMeshComp, transform)); + } + } + else if (actor.TryGetValue(out FPackageIndex staticMeshComponent, "StaticMeshComponent", "StaticMesh", "Mesh", "LightMesh") && + staticMeshComponent.TryLoad(out UStaticMeshComponent staticMeshComp) && + staticMeshComp.GetStaticMesh().TryLoad(out UStaticMesh m) && m.Materials.Length > 0) + { + ProcessMesh(actor, staticMeshComp, m, CalculateTransform(staticMeshComp, transform)); + } + } + + private void ProcessMesh(UObject actor, UStaticMeshComponent staticMeshComp, UStaticMesh m, Transform transform) + { + var guid = m.LightingGuid; OverrideVertexColors(staticMeshComp, m); if (Options.TryGetModel(guid, out var model)) { - model.AddInstance(t); + model.AddInstance(transform); } else if (m.TryConvert(out var mesh)) { - model = new StaticModel(m, mesh, t); + model = new StaticModel(m, mesh, transform); model.IsTwoSided = actor.GetOrDefault("bMirrored", staticMeshComp.GetOrDefault("bDisallowMeshPaintPerInstance", model.IsTwoSided)); - if (actor.TryGetValue(out FPackageIndex baseMaterial, "BaseMaterial") && - actor.TryGetAllValues(out FPackageIndex[] textureData, "TextureData")) + if (actor.TryGetAllValues(out FPackageIndex[] textureData, "TextureData")) { - var material = model.Materials.FirstOrDefault(x => x.Name == baseMaterial.Name); + var material = model.Materials.FirstOrDefault(); if (material is { IsUsed: true }) { for (int j = 0; j < textureData.Length; j++) @@ -520,7 +543,9 @@ public class Renderer : IDisposable for (var j = 0; j < overrideMaterials.Length && j < model.Sections.Length; j++) { var matIndex = model.Sections[j].MaterialIndex; - if (!(model.Materials[matIndex].IsUsed && overrideMaterials[matIndex].Load() is UMaterialInterface unrealMaterial)) continue; + if (matIndex < 0 || matIndex >= model.Materials.Length || matIndex >= overrideMaterials.Length || + overrideMaterials[matIndex].Load() is not UMaterialInterface unrealMaterial) continue; + model.Materials[matIndex].SwapMaterial(unrealMaterial); } } @@ -531,15 +556,26 @@ public class Renderer : IDisposable if (actor.TryGetValue(out FPackageIndex treasureLight, "PointLight", "TreasureLight") && treasureLight.TryLoad(out var pl1) && pl1.Template.TryLoad(out var pl2)) { - Options.Lights.Add(new PointLight(guid, Options.Icons["pointlight"], pl1, pl2, t)); + Options.Lights.Add(new PointLight(guid, Options.Icons["pointlight"], pl1, pl2, transform)); } if (actor.TryGetValue(out FPackageIndex spotLight, "SpotLight") && spotLight.TryLoad(out var sl1) && sl1.Template.TryLoad(out var sl2)) { - Options.Lights.Add(new SpotLight(guid, Options.Icons["spotlight"], sl1, sl2, t)); + Options.Lights.Add(new SpotLight(guid, Options.Icons["spotlight"], sl1, sl2, transform)); } } + private Transform CalculateTransform(UStaticMeshComponent staticMeshComp, Transform relation) + { + return new Transform + { + Relation = relation.Matrix, + Position = staticMeshComp.GetOrDefault("RelativeLocation", FVector.ZeroVector) * Constants.SCALE_DOWN_RATIO, + Rotation = staticMeshComp.GetOrDefault("RelativeRotation", FRotator.ZeroRotator).Quaternion(), + Scale = staticMeshComp.GetOrDefault("RelativeScale3D", FVector.OneVector) + }; + } + private void OverrideVertexColors(UStaticMeshComponent staticMeshComp, UStaticMesh staticMesh) { if (staticMeshComp.LODData is not { Length: > 0 } || staticMesh.RenderData is not { LODs.Length: > 0 }) From 8a790321ddd453a5d2355a71c113c3f3abea7461 Mon Sep 17 00:00:00 2001 From: Asval Date: Thu, 16 Nov 2023 22:50:41 +0100 Subject: [PATCH 22/85] if you have, you have --- CUE4Parse | 2 +- FModel/ViewModels/AudioPlayerViewModel.cs | 57 +++++++++++++++++++---- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index b6dfd4cd..93067506 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit b6dfd4cd53a99b48850e0b2f9f00321816643f99 +Subproject commit 93067506661ec535ba6d443ee29b5cc336f018dc diff --git a/FModel/ViewModels/AudioPlayerViewModel.cs b/FModel/ViewModels/AudioPlayerViewModel.cs index 4aedde73..e6c099db 100644 --- a/FModel/ViewModels/AudioPlayerViewModel.cs +++ b/FModel/ViewModels/AudioPlayerViewModel.cs @@ -552,14 +552,26 @@ public class AudioPlayerViewModel : ViewModel, ISource, IDisposable case "opus": case "wem": case "at9": + case "raw": { - if (TryConvert(out var wavFilePath) && !string.IsNullOrEmpty(wavFilePath)) + if (TryConvert(out var wavFilePath)) { var newAudio = new AudioFile(SelectedAudioFile.Id, new FileInfo(wavFilePath)); Replace(newAudio); return true; } + return false; + } + case "binka": + { + if (TryDecode(out var rawFilePath)) + { + var newAudio = new AudioFile(SelectedAudioFile.Id, new FileInfo(rawFilePath)); + Replace(newAudio); + return true; + } + return false; } } @@ -567,7 +579,8 @@ public class AudioPlayerViewModel : ViewModel, ISource, IDisposable return true; } - private bool TryConvert(out string wavFilePath) + private bool TryConvert(out string wavFilePath) => TryConvert(SelectedAudioFile.FilePath, SelectedAudioFile.Data, out wavFilePath); + private bool TryConvert(string inputFilePath, byte[] inputFileData, out string wavFilePath) { wavFilePath = string.Empty; var vgmFilePath = Path.Combine(UserSettings.Default.OutputDirectory, ".data", "test.exe"); @@ -577,22 +590,46 @@ public class AudioPlayerViewModel : ViewModel, ISource, IDisposable if (!File.Exists(vgmFilePath)) return false; } - Directory.CreateDirectory(SelectedAudioFile.FilePath.SubstringBeforeLast("/")); - File.WriteAllBytes(SelectedAudioFile.FilePath, SelectedAudioFile.Data); + Directory.CreateDirectory(inputFilePath.SubstringBeforeLast("/")); + File.WriteAllBytes(inputFilePath, inputFileData); - wavFilePath = Path.ChangeExtension(SelectedAudioFile.FilePath, ".wav"); + wavFilePath = Path.ChangeExtension(inputFilePath, ".wav"); var vgmProcess = Process.Start(new ProcessStartInfo { FileName = vgmFilePath, - Arguments = $"-o \"{wavFilePath}\" \"{SelectedAudioFile.FilePath}\"", + Arguments = $"-o \"{wavFilePath}\" \"{inputFilePath}\"", UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, CreateNoWindow = true }); - vgmProcess?.WaitForExit(); + vgmProcess?.WaitForExit(5000); - File.Delete(SelectedAudioFile.FilePath); + File.Delete(inputFilePath); return vgmProcess?.ExitCode == 0 && File.Exists(wavFilePath); } + + private bool TryDecode(out string rawFilePath) + { + rawFilePath = string.Empty; + var binkadecPath = Path.Combine(UserSettings.Default.OutputDirectory, ".data", "binkadec.exe"); + if (!File.Exists(binkadecPath)) + { + return false; + } + + Directory.CreateDirectory(SelectedAudioFile.FilePath.SubstringBeforeLast("/")); + File.WriteAllBytes(SelectedAudioFile.FilePath, SelectedAudioFile.Data); + + rawFilePath = Path.ChangeExtension(SelectedAudioFile.FilePath, ".wav"); + var binkadecProcess = Process.Start(new ProcessStartInfo + { + FileName = binkadecPath, + Arguments = $"-i \"{SelectedAudioFile.FilePath}\" -o \"{rawFilePath}\"", + UseShellExecute = false, + CreateNoWindow = true + }); + binkadecProcess?.WaitForExit(5000); + + File.Delete(SelectedAudioFile.FilePath); + return binkadecProcess?.ExitCode == 0 && File.Exists(rawFilePath); + } } From 0551bc3731cab3bde8c600f8ed292365a356063f Mon Sep 17 00:00:00 2001 From: Asval Date: Fri, 17 Nov 2023 23:08:34 +0100 Subject: [PATCH 23/85] .NET 8 --- .github/workflows/main.yml | 6 +++--- .github/workflows/qa.yml | 6 +++--- CUE4Parse | 2 +- FModel/FModel.csproj | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8e6f8404..b80429a5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,16 +21,16 @@ jobs: - name: Fetch Submodules Recursively run: git submodule update --init --recursive - - name: .NET 6 Setup + - name: .NET 8 Setup uses: actions/setup-dotnet@v2 with: - dotnet-version: '6.0.x' + dotnet-version: '8.0.x' - name: .NET Restore run: dotnet restore FModel - name: .NET Publish - run: dotnet publish FModel -c Release --no-self-contained -r win-x64 -f net6.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false -p:AssemblyVersion=${{ github.event.inputs.appVersion }} -p:FileVersion=${{ github.event.inputs.appVersion }} + run: dotnet publish FModel -c Release --no-self-contained -r win-x64 -f net8.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false -p:AssemblyVersion=${{ github.event.inputs.appVersion }} -p:FileVersion=${{ github.event.inputs.appVersion }} - name: ZIP File uses: papeloto/action-zip@v1 diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 70f2f7ae..d8e487e5 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -17,10 +17,10 @@ jobs: - name: Fetch Submodules Recursively run: git submodule update --init --recursive - - name: .NET 6 Setup + - name: .NET 8 Setup uses: actions/setup-dotnet@v2 with: - dotnet-version: '6.0.x' + dotnet-version: '8.0.x' - name: .NET Restore run: dotnet restore FModel @@ -33,7 +33,7 @@ jobs: regex: '^(?[0-9])\.(?[0-9])\.(?[0-9])\.(?[0-9])$' - name: .NET Publish - run: dotnet publish FModel -c Release --no-self-contained -r win-x64 -f net6.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false + run: dotnet publish FModel -c Release --no-self-contained -r win-x64 -f net8.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false - name: ZIP File uses: papeloto/action-zip@v1 diff --git a/CUE4Parse b/CUE4Parse index 93067506..18e624a3 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 93067506661ec535ba6d443ee29b5cc336f018dc +Subproject commit 18e624a38c82efaf94161ee9e2982fa6a9de9d21 diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 3bf68654..9fcc3f7c 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -2,7 +2,7 @@ WinExe - net6.0-windows + net8.0-windows true FModel.ico 4.4.3.4 From a80379c3b982f63ef543d58cf89bf70e7dfeb43b Mon Sep 17 00:00:00 2001 From: Asval Date: Sat, 25 Nov 2023 05:36:08 +0100 Subject: [PATCH 24/85] bind pose stripped anim export + cubemap to panorama Co-authored-by: Zain / Kaiser M <106357974+KaiserM21@users.noreply.github.com> --- CUE4Parse | 2 +- FModel/ViewModels/CUE4ParseViewModel.cs | 4 +++- FModel/ViewModels/TabControlViewModel.cs | 10 +++++++++- FModel/Views/Snooper/Animations/Skeleton.cs | 2 +- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 18e624a3..6a1df768 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 18e624a38c82efaf94161ee9e2982fa6a9de9d21 +Subproject commit 6a1df768876bb7216e8f39a0d0f5ae176644aa8a diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 21de8fec..5e2a6551 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -464,7 +464,9 @@ public class CUE4ParseViewModel : ViewModel ChunkCacheDirectory = Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, ".data")), Authorization = new AuthenticationHeaderValue("Bearer", UserSettings.Default.LastAuthResponse.AccessToken) }); - await Provider.MountAsync(); + var onDemandCount = await Provider.MountAsync(); + FLogger.Append(ELog.Information, () => + FLogger.Text($"{onDemandCount} on-demand archive{(onDemandCount > 1 ? "s" : "")} streamed via epicgames.com", Constants.WHITE, true)); }); } diff --git a/FModel/ViewModels/TabControlViewModel.cs b/FModel/ViewModels/TabControlViewModel.cs index 461dd34e..8d081946 100644 --- a/FModel/ViewModels/TabControlViewModel.cs +++ b/FModel/ViewModels/TabControlViewModel.cs @@ -229,7 +229,15 @@ public class TabItem : ViewModel } public void AddImage(UTexture texture, bool save, bool updateUi) - => AddImage(texture.Name, texture.RenderNearestNeighbor, texture.Decode(UserSettings.Default.CurrentDir.TexturePlatform), save, updateUi); + { + var img = texture.Decode(UserSettings.Default.CurrentDir.TexturePlatform); + if (texture is UTextureCube) + { + img = img?.ToPanorama(); + } + + AddImage(texture.Name, texture.RenderNearestNeighbor, img, save, updateUi); + } public void AddImage(string name, bool rnn, SKBitmap[] img, bool save, bool updateUi) { diff --git a/FModel/Views/Snooper/Animations/Skeleton.cs b/FModel/Views/Snooper/Animations/Skeleton.cs index ce1a0dcc..ff01318d 100644 --- a/FModel/Views/Snooper/Animations/Skeleton.cs +++ b/FModel/Views/Snooper/Animations/Skeleton.cs @@ -201,7 +201,7 @@ public class Skeleton : IDisposable sequence.Tracks[bone.SkeletonIndex].GetBoneTransform(f, sequence.NumFrames, ref boneOrientation, ref bonePosition, ref boneScale); if (!bone.IsRoot) boneMatrix = _boneMatriceAtFrame[bone.ParentIndex]; - bonePosition = rotationOnly || bonePosition.IsZero() ? bone.Rest.Position : bonePosition * Constants.SCALE_DOWN_RATIO; + bonePosition = rotationOnly ? bone.Rest.Position : bonePosition * Constants.SCALE_DOWN_RATIO; boneMatrix = new Transform { From 1461a6e52551e1aab5ee95781c40e90dee7f22a2 Mon Sep 17 00:00:00 2001 From: GMatrixGames Date: Mon, 4 Dec 2023 15:56:33 -0500 Subject: [PATCH 25/85] Force QA build --- CUE4Parse | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CUE4Parse b/CUE4Parse index 6a1df768..53dcd66f 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 6a1df768876bb7216e8f39a0d0f5ae176644aa8a +Subproject commit 53dcd66fc069ad574f0ecf9f722f60f3c712a6d2 From 3721d7cd17be8e7107ef1c69e1460b9d7365ba83 Mon Sep 17 00:00:00 2001 From: Asval Date: Thu, 7 Dec 2023 18:05:47 +0100 Subject: [PATCH 26/85] fixes --- FModel/Creator/Bases/FN/BaseIcon.cs | 1 + FModel/Creator/Bases/FN/BaseMtxOffer.cs | 7 ++--- .../Creator/Bases/FN/BaseOfferDisplayData.cs | 13 +++++--- FModel/Creator/CreatorPackage.cs | 24 ++++++++++++-- FModel/FModel.csproj | 1 - FModel/MainWindow.xaml.cs | 3 +- FModel/ViewModels/ApplicationViewModel.cs | 31 ------------------- FModel/ViewModels/CUE4ParseViewModel.cs | 5 +-- FModel/Views/Snooper/Models/Section.cs | 1 - 9 files changed, 38 insertions(+), 48 deletions(-) diff --git a/FModel/Creator/Bases/FN/BaseIcon.cs b/FModel/Creator/Bases/FN/BaseIcon.cs index b47109e8..5b1e3f42 100644 --- a/FModel/Creator/Bases/FN/BaseIcon.cs +++ b/FModel/Creator/Bases/FN/BaseIcon.cs @@ -200,6 +200,7 @@ public class BaseIcon : UCreator 1 => 10, 2 => 8, 3 => 4, + 4 => 5, _ => 10 }; diff --git a/FModel/Creator/Bases/FN/BaseMtxOffer.cs b/FModel/Creator/Bases/FN/BaseMtxOffer.cs index 68e64762..7f62c89e 100644 --- a/FModel/Creator/Bases/FN/BaseMtxOffer.cs +++ b/FModel/Creator/Bases/FN/BaseMtxOffer.cs @@ -17,10 +17,9 @@ public class BaseMtxOffer : UCreator public override void ParseForInfo() { - if (Object.TryGetValue(out FStructFallback typeImage, "DetailsImage", "TileImage") && - typeImage.TryGetValue(out FPackageIndex resource, "ResourceObject")) + if (Object.TryGetValue(out FSoftObjectPath image, "SoftDetailsImage", "SoftTileImage")) { - Preview = Utils.GetBitmap(resource); + Preview = Utils.GetBitmap(image); } if (Object.TryGetValue(out FStructFallback gradient, "Gradient") && @@ -81,4 +80,4 @@ public class BaseMtxOffer : UCreator return new[] { ret }; } -} \ No newline at end of file +} diff --git a/FModel/Creator/Bases/FN/BaseOfferDisplayData.cs b/FModel/Creator/Bases/FN/BaseOfferDisplayData.cs index b1a1808e..250a6ab3 100644 --- a/FModel/Creator/Bases/FN/BaseOfferDisplayData.cs +++ b/FModel/Creator/Bases/FN/BaseOfferDisplayData.cs @@ -1,5 +1,7 @@ using CUE4Parse.UE4.Assets.Exports; using CUE4Parse.UE4.Assets.Exports.Material; +using CUE4Parse.UE4.Assets.Objects; +using CUE4Parse.UE4.Objects.UObject; using SkiaSharp; namespace FModel.Creator.Bases.FN; @@ -14,13 +16,16 @@ public class BaseOfferDisplayData : UCreator public override void ParseForInfo() { - if (!Object.TryGetValue(out UMaterialInterface[] presentations, "Presentations")) + if (!Object.TryGetValue(out FStructFallback[] contextualPresentations, "ContextualPresentations")) return; - _offerImages = new BaseMaterialInstance[presentations.Length]; + _offerImages = new BaseMaterialInstance[contextualPresentations.Length]; for (var i = 0; i < _offerImages.Length; i++) { - var offerImage = new BaseMaterialInstance(presentations[i], Style); + if (!contextualPresentations[i].TryGetValue(out FSoftObjectPath material, "Material") || + !material.TryLoad(out UMaterialInterface presentation)) continue; + + var offerImage = new BaseMaterialInstance(presentation, Style); offerImage.ParseForInfo(); _offerImages[i] = offerImage; } @@ -36,4 +41,4 @@ public class BaseOfferDisplayData : UCreator return ret; } -} \ No newline at end of file +} diff --git a/FModel/Creator/CreatorPackage.cs b/FModel/Creator/CreatorPackage.cs index 1ff20af0..fd2cea3f 100644 --- a/FModel/Creator/CreatorPackage.cs +++ b/FModel/Creator/CreatorPackage.cs @@ -64,13 +64,18 @@ public class CreatorPackage : IDisposable case "FortAmmoItemDefinition": case "FortEmoteItemDefinition": case "FortBadgeItemDefinition": + case "SparksMicItemDefinition": case "FortAwardItemDefinition": + case "SparksAuraItemDefinition": + case "SparksDrumItemDefinition": + case "SparksBassItemDefinition": case "FortGadgetItemDefinition": case "AthenaCharmItemDefinition": case "FortPlaysetItemDefinition": case "FortGiftBoxItemDefinition": case "FortOutpostItemDefinition": case "FortVehicleItemDefinition": + case "SparksGuitarItemDefinition": case "FortCardPackItemDefinition": case "FortDefenderItemDefinition": case "FortCurrencyItemDefinition": @@ -80,27 +85,36 @@ public class CreatorPackage : IDisposable case "FortWeaponModItemDefinition": case "FortCodeTokenItemDefinition": case "FortSchematicItemDefinition": + case "SparksKeyboardItemDefinition": case "FortWorldMultiItemDefinition": case "FortAlterationItemDefinition": case "FortExpeditionItemDefinition": case "FortIngredientItemDefinition": + case "StWFortAccoladeItemDefinition": case "FortAccountBuffItemDefinition": case "FortWeaponMeleeItemDefinition": case "FortPlayerPerksItemDefinition": case "FortPlaysetPropItemDefinition": + case "JunoRecipeBundleItemDefinition": case "FortHomebaseNodeItemDefinition": case "FortNeverPersistItemDefinition": case "FortPlayerAugmentItemDefinition": + case "FortSmartBuildingItemDefinition": + case "FortWeaponModItemDefinitionOptic": case "RadioContentSourceItemDefinition": case "FortPlaysetGrenadeItemDefinition": + case "JunoWeaponCreatureItemDefinition": case "FortPersonalVehicleItemDefinition": case "FortGameplayModifierItemDefinition": case "FortHardcoreModifierItemDefinition": + case "FortWeaponModItemDefinitionMagazine": case "FortConsumableAccountItemDefinition": case "FortConversionControlItemDefinition": case "FortAccountBuffCreditItemDefinition": + case "JunoBuildInstructionsItemDefinition": case "FortEventCurrencyItemDefinitionRedir": case "FortPersistentResourceItemDefinition": + case "FortWeaponMeleeOffhandItemDefinition": case "FortHomebaseBannerIconItemDefinition": case "FortCampaignHeroLoadoutItemDefinition": case "FortConditionalResourceItemDefinition": @@ -108,10 +122,14 @@ public class CreatorPackage : IDisposable case "FortWeaponMeleeDualWieldItemDefinition": case "FortDailyRewardScheduleTokenDefinition": case "FortCreativeWeaponRangedItemDefinition": + case "FortVehicleCosmeticsItemDefinition_Body": + case "FortVehicleCosmeticsItemDefinition_Skin": + case "FortVehicleCosmeticsItemDefinition_Wheel": case "FortCreativeRealEstatePlotItemDefinition": + case "FortVehicleCosmeticsItemDefinition_Booster": case "AthenaDanceItemDefinition_AdHocSquadsJoin_C": - case "StWFortAccoladeItemDefinition": - case "FortSmartBuildingItemDefinition": + case "FortVehicleCosmeticsItemDefinition_DriftSmoke": + case "FortVehicleCosmeticsItemDefinition_EngineAudio": creator = _style switch { EIconStyle.Cataba => new BaseCommunity(_object, _style, "Cataba"), @@ -134,7 +152,7 @@ public class CreatorPackage : IDisposable return true; case "MaterialInstanceConstant" when _object.Owner != null && - (_object.Owner.Name.EndsWith($"/MI_OfferImages/{_object.Name}", StringComparison.OrdinalIgnoreCase) || + (_object.Owner.Name.Contains("/MI_OfferImages/", StringComparison.OrdinalIgnoreCase) || _object.Owner.Name.EndsWith($"/RenderSwitch_Materials/{_object.Name}", StringComparison.OrdinalIgnoreCase) || _object.Owner.Name.EndsWith($"/MI_BPTile/{_object.Name}", StringComparison.OrdinalIgnoreCase)): creator = new BaseMaterialInstance(_object, _style); diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 9fcc3f7c..3ba25ad9 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -148,7 +148,6 @@ - diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs index 0d0ccca8..86212096 100644 --- a/FModel/MainWindow.xaml.cs +++ b/FModel/MainWindow.xaml.cs @@ -71,9 +71,8 @@ public partial class MainWindow _applicationView.CUE4Parse.VerifyConsoleVariables(), _applicationView.CUE4Parse.VerifyOnDemandArchives(), _applicationView.CUE4Parse.InitMappings(), - _applicationView.InitImGuiSettings(newOrUpdated), _applicationView.InitVgmStream(), - _applicationView.InitOodle(), + _applicationView.InitImGuiSettings(newOrUpdated), Task.Run(() => { if (UserSettings.Default.DiscordRpc == EDiscordRpc.Always) diff --git a/FModel/ViewModels/ApplicationViewModel.cs b/FModel/ViewModels/ApplicationViewModel.cs index 9ef32ce0..6398f37a 100644 --- a/FModel/ViewModels/ApplicationViewModel.cs +++ b/FModel/ViewModels/ApplicationViewModel.cs @@ -6,7 +6,6 @@ using FModel.ViewModels.Commands; using FModel.Views; using FModel.Views.Resources.Controls; using Ionic.Zip; -using Oodle.NET; using System; using System.Diagnostics; using System.IO; @@ -15,7 +14,6 @@ using System.Windows; using MessageBox = AdonisUI.Controls.MessageBox; using MessageBoxButton = AdonisUI.Controls.MessageBoxButton; using MessageBoxImage = AdonisUI.Controls.MessageBoxImage; -using OodleCUE4 = CUE4Parse.Compression.Oodle; namespace FModel.ViewModels; @@ -56,7 +54,6 @@ public class ApplicationViewModel : ViewModel public SettingsViewModel SettingsView { get; } public AesManagerViewModel AesManager { get; } public AudioPlayerViewModel AudioPlayer { get; } - private OodleCompressor _oodle; public ApplicationViewModel() { @@ -181,34 +178,6 @@ public class ApplicationViewModel : ViewModel } } - public async Task InitOodle() - { - var dataDir = Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, ".data")); - var oodlePath = Path.Combine(dataDir.FullName, OodleCUE4.OODLE_DLL_NAME); - - if (File.Exists(OodleCUE4.OODLE_DLL_NAME)) - { - File.Move(OodleCUE4.OODLE_DLL_NAME, oodlePath, true); - } - else if (!File.Exists(oodlePath)) - { - var result = await OodleCUE4.DownloadOodleDll(oodlePath); - if (!result) return; - } - - if (File.Exists("oo2core_8_win64.dll")) - File.Delete("oo2core_8_win64.dll"); - - _oodle = new OodleCompressor(oodlePath); - - unsafe - { - OodleCUE4.DecompressFunc = (bufferPtr, bufferSize, outputPtr, outputSize, a, b, c, d, e, f, g, h, i, threadModule) => - _oodle.Decompress(new IntPtr(bufferPtr), bufferSize, new IntPtr(outputPtr), outputSize, - (OodleLZ_FuzzSafe) a, (OodleLZ_CheckCRC) b, (OodleLZ_Verbosity) c, d, e, f, g, h, i, (OodleLZ_Decode_ThreadPhase) threadModule); - } - } - public async Task InitImGuiSettings(bool forceDownload) { var imgui = Path.Combine(/*UserSettings.Default.OutputDirectory, ".data", */"imgui.ini"); diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 5e2a6551..3ef1204e 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -462,7 +462,8 @@ public class CUE4ParseViewModel : ViewModel { ChunkBaseUri = new Uri("https://download.epicgames.com/ias/fortnite/", UriKind.Absolute), ChunkCacheDirectory = Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, ".data")), - Authorization = new AuthenticationHeaderValue("Bearer", UserSettings.Default.LastAuthResponse.AccessToken) + Authorization = new AuthenticationHeaderValue("Bearer", UserSettings.Default.LastAuthResponse.AccessToken), + Timeout = TimeSpan.FromSeconds(15) }); var onDemandCount = await Provider.MountAsync(); FLogger.Append(ELog.Information, () => @@ -849,7 +850,7 @@ public class CUE4ParseViewModel : ViewModel 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) || + (export.Owner.Name.Contains("/MI_OfferImages/", StringComparison.OrdinalIgnoreCase) || export.Owner.Name.EndsWith($"/RenderSwitch_Materials/{export.Name}", StringComparison.OrdinalIgnoreCase) || export.Owner.Name.EndsWith($"/MI_BPTile/{export.Name}", StringComparison.OrdinalIgnoreCase))): { diff --git a/FModel/Views/Snooper/Models/Section.cs b/FModel/Views/Snooper/Models/Section.cs index 4a4ced53..6720e167 100644 --- a/FModel/Views/Snooper/Models/Section.cs +++ b/FModel/Views/Snooper/Models/Section.cs @@ -21,7 +21,6 @@ public class Section FirstFaceIndex = firstFaceIndex; FirstFaceIndexPtr = new IntPtr(FirstFaceIndex * sizeof(uint)); Color = Constants.COLOR_PALETTE[MaterialIndex % Constants.PALETTE_LENGTH]; - Show = true; } public void SetupMaterial(Material material) From 0160abf630d8ae51b1b8ba8cf9f411b5dfec88cc Mon Sep 17 00:00:00 2001 From: Asval Date: Sun, 7 Jan 2024 13:18:23 +0100 Subject: [PATCH 27/85] FModel v4.4.3.5 --- CUE4Parse | 2 +- FModel/Enums.cs | 2 -- FModel/FModel.csproj | 6 +++--- FModel/ViewModels/CUE4ParseViewModel.cs | 2 +- FModel/ViewModels/Commands/LoadCommand.cs | 1 - FModel/Views/Resources/Controls/AvalonEditor.xaml.cs | 3 +-- FModel/Views/Resources/Resources.xaml | 3 --- 7 files changed, 6 insertions(+), 13 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 53dcd66f..e581c54a 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 53dcd66fc069ad574f0ecf9f722f60f3c712a6d2 +Subproject commit e581c54af3b9c6f5fea7947a990057be0b636d56 diff --git a/FModel/Enums.cs b/FModel/Enums.cs index ae52dfeb..8231f7b6 100644 --- a/FModel/Enums.cs +++ b/FModel/Enums.cs @@ -54,8 +54,6 @@ public enum EDiscordRpc public enum ELoadingMode { - [Description("Single")] - Single, [Description("Multiple")] Multiple, [Description("All")] diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 3ba25ad9..ea1bfd12 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -5,9 +5,9 @@ net8.0-windows true FModel.ico - 4.4.3.4 - 4.4.3.4 - 4.4.3.4 + 4.4.3.5 + 4.4.3.5 + 4.4.3.5 false true win-x64 diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 3ef1204e..977e83ba 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -463,7 +463,7 @@ public class CUE4ParseViewModel : ViewModel ChunkBaseUri = new Uri("https://download.epicgames.com/ias/fortnite/", UriKind.Absolute), ChunkCacheDirectory = Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, ".data")), Authorization = new AuthenticationHeaderValue("Bearer", UserSettings.Default.LastAuthResponse.AccessToken), - Timeout = TimeSpan.FromSeconds(15) + Timeout = TimeSpan.FromSeconds(30) }); var onDemandCount = await Provider.MountAsync(); FLogger.Append(ELog.Information, () => diff --git a/FModel/ViewModels/Commands/LoadCommand.cs b/FModel/ViewModels/Commands/LoadCommand.cs index f11c9e4a..9d838476 100644 --- a/FModel/ViewModels/Commands/LoadCommand.cs +++ b/FModel/ViewModels/Commands/LoadCommand.cs @@ -61,7 +61,6 @@ public class LoadCommand : ViewModelCommand // filter what to show switch (UserSettings.Default.LoadingMode) { - case ELoadingMode.Single: case ELoadingMode.Multiple: { var l = (IList) parameter; diff --git a/FModel/Views/Resources/Controls/AvalonEditor.xaml.cs b/FModel/Views/Resources/Controls/AvalonEditor.xaml.cs index 04e5ed5e..c145a849 100644 --- a/FModel/Views/Resources/Controls/AvalonEditor.xaml.cs +++ b/FModel/Views/Resources/Controls/AvalonEditor.xaml.cs @@ -223,10 +223,9 @@ public partial class AvalonEditor private void OnTabClose(object sender, EventArgs eventArgs) { - if (eventArgs is not TabControlViewModel.TabEventArgs e || e.TabToRemove.Document == null) + if (eventArgs is not TabControlViewModel.TabEventArgs e || e.TabToRemove.Document?.FileName is not { } fileName) return; - var fileName = e.TabToRemove.Document.FileName; if (_savedCarets.ContainsKey(fileName)) _savedCarets.Remove(fileName); } diff --git a/FModel/Views/Resources/Resources.xaml b/FModel/Views/Resources/Resources.xaml index 61f071b9..92225133 100644 --- a/FModel/Views/Resources/Resources.xaml +++ b/FModel/Views/Resources/Resources.xaml @@ -183,9 +183,6 @@ - - - From fa11884936c2d50e263a3ce8f758c42351b74ec4 Mon Sep 17 00:00:00 2001 From: Asval Date: Tue, 9 Jan 2024 17:26:27 +0100 Subject: [PATCH 28/85] bump acl --- CUE4Parse | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CUE4Parse b/CUE4Parse index e581c54a..64451497 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit e581c54af3b9c6f5fea7947a990057be0b636d56 +Subproject commit 6445149747051286a9d8d1e3038cbdbb8e8ad59e From 69b18039e68e34a97441b9c6a5880e97af6e87e8 Mon Sep 17 00:00:00 2001 From: Asval Date: Tue, 9 Jan 2024 23:47:07 +0100 Subject: [PATCH 29/85] bump --- CUE4Parse | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CUE4Parse b/CUE4Parse index 64451497..ae4906d2 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 6445149747051286a9d8d1e3038cbdbb8e8ad59e +Subproject commit ae4906d24b23957e61513c53f808db28cdef59ca From b2f6223958b20684762b6ce0b538a3b210010723 Mon Sep 17 00:00:00 2001 From: GMatrixGames Date: Thu, 25 Jan 2024 18:24:29 -0500 Subject: [PATCH 30/85] parse update --- CUE4Parse | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CUE4Parse b/CUE4Parse index ae4906d2..1cb082d1 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit ae4906d24b23957e61513c53f808db28cdef59ca +Subproject commit 1cb082d145bc70f76cf7a0cefbff890ae9f82c47 From eb546602eae74942d13989b86f85c801cdb42ee0 Mon Sep 17 00:00:00 2001 From: Asval Date: Sun, 28 Jan 2024 15:53:32 +0100 Subject: [PATCH 31/85] quest fix + juno icons --- CUE4Parse | 2 +- FModel/Creator/Bases/FN/BaseJuno.cs | 42 ++++++++++++++++++++++++++ FModel/Creator/Bases/FN/BaseQuest.cs | 27 ++++++++++++----- FModel/Creator/Bases/FN/Reward.cs | 44 ++++++++++++++-------------- FModel/Creator/CreatorPackage.cs | 3 ++ 5 files changed, 88 insertions(+), 30 deletions(-) create mode 100644 FModel/Creator/Bases/FN/BaseJuno.cs diff --git a/CUE4Parse b/CUE4Parse index 1cb082d1..20662a92 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 1cb082d145bc70f76cf7a0cefbff890ae9f82c47 +Subproject commit 20662a924df0c494b3576888fa5c3ae2ef38594d diff --git a/FModel/Creator/Bases/FN/BaseJuno.cs b/FModel/Creator/Bases/FN/BaseJuno.cs new file mode 100644 index 00000000..af1bbeb7 --- /dev/null +++ b/FModel/Creator/Bases/FN/BaseJuno.cs @@ -0,0 +1,42 @@ +using CUE4Parse.UE4.Assets.Exports; +using CUE4Parse.UE4.Assets.Objects; +using CUE4Parse.UE4.Objects.UObject; +using SkiaSharp; + +namespace FModel.Creator.Bases.FN; + +public class BaseJuno : BaseIcon +{ + private BaseIcon _character; + + public BaseJuno(UObject uObject, EIconStyle style) : base(uObject, style) + { + + } + + public override void ParseForInfo() + { + if (Object.TryGetValue(out FSoftObjectPath baseCid, "BaseAthenaCharacterItemDefinition") && + Utils.TryLoadObject(baseCid.AssetPathName.Text, out UObject cid)) + { + _character = new BaseIcon(cid, Style); + _character.ParseForInfo(); + + if (Object.TryGetValue(out FSoftObjectPath assembledMeshSchema, "AssembledMeshSchema") && + Utils.TryLoadObject(assembledMeshSchema.AssetPathName.Text, out UObject meshSchema) && + meshSchema.TryGetValue(out FInstancedStruct[] additionalData, "AdditionalData")) + { + foreach (var data in additionalData) + { + if (data.NonConstStruct?.TryGetValue(out FSoftObjectPath largePreview, "LargePreviewImage", "SmallPreviewImage") ?? false) + { + _character.Preview = Utils.GetBitmap(largePreview); + break; + } + } + } + } + } + + public override SKBitmap[] Draw() => _character.Draw(); +} diff --git a/FModel/Creator/Bases/FN/BaseQuest.cs b/FModel/Creator/Bases/FN/BaseQuest.cs index 4c0364b2..fd0c862b 100644 --- a/FModel/Creator/Bases/FN/BaseQuest.cs +++ b/FModel/Creator/Bases/FN/BaseQuest.cs @@ -69,13 +69,19 @@ public class BaseQuest : BaseIcon } else { - Description = ShortDescription; - if (Object.TryGetValue(out FText completionText, "CompletionText")) - Description += "\n" + completionText.Text; - if (Object.TryGetValue(out FSoftObjectPath tandemCharacterData, "TandemCharacterData") && + if (!string.IsNullOrEmpty(ShortDescription)) + Description = ShortDescription; + if (string.IsNullOrEmpty(DisplayName) && !string.IsNullOrEmpty(Description)) + DisplayName = Description; + if (DisplayName == Description) + Description = string.Empty; + + if ((Object.TryGetValue(out FSoftObjectPath icon, "QuestGiverWidgetIcon", "NotificationIconOverride") && + Utils.TryLoadObject(icon.AssetPathName.Text, out UObject iconObject)) || + (Object.TryGetValue(out FSoftObjectPath tandemCharacterData, "TandemCharacterData") && Utils.TryLoadObject(tandemCharacterData.AssetPathName.Text, out UObject uObject) && uObject.TryGetValue(out FSoftObjectPath tandemIcon, "EntryListIcon", "ToastIcon") && - Utils.TryLoadObject(tandemIcon.AssetPathName.Text, out UObject iconObject)) + Utils.TryLoadObject(tandemIcon.AssetPathName.Text, out iconObject))) { Preview = iconObject switch { @@ -127,9 +133,16 @@ public class BaseQuest : BaseIcon } } - if (_reward == null && Object.TryGetValue(out UDataTable rewardsTable, "RewardsTable")) + if (_reward == null) { - if (rewardsTable.TryGetDataTableRow("Default", StringComparison.InvariantCulture, out var row)) + FName rowName = null; + if (Object.TryGetValue(out UDataTable rewardsTable, "RewardsTable")) + rowName = new FName("Default"); + else if (Object.TryGetValue(out FStructFallback[] rewardTableRows, "IndividualRewardTableRows") && + rewardTableRows.Length > 0 && rewardTableRows[0].TryGetValue(out rowName, "RowName") && + rewardTableRows[0].TryGetValue(out rewardsTable, "DataTable")) {} + + if (rewardsTable != null && rowName != null && rewardsTable.TryGetDataTableRow(rowName.Text, StringComparison.InvariantCulture, out var row)) { if (row.TryGetValue(out FName templateId, "TemplateId") && row.TryGetValue(out int quantity, "Quantity")) diff --git a/FModel/Creator/Bases/FN/Reward.cs b/FModel/Creator/Bases/FN/Reward.cs index 0e5aad43..fe650617 100644 --- a/FModel/Creator/Bases/FN/Reward.cs +++ b/FModel/Creator/Bases/FN/Reward.cs @@ -64,7 +64,7 @@ public class Reward _rewardPaint.TextSize = 50; if (HasReward()) { - c.DrawBitmap(_theReward.Preview.Resize((int) rect.Height), new SKPoint(rect.Left, rect.Top), _rewardPaint); + c.DrawBitmap((_theReward.Preview ?? _theReward.DefaultPreview).Resize((int) rect.Height), new SKPoint(rect.Left, rect.Top), _rewardPaint); _rewardPaint.Color = _theReward.Border[0]; _rewardPaint.Typeface = _rewardQuantity.StartsWith("x") ? Utils.Typefaces.BundleNumber : Utils.Typefaces.Bundle; @@ -88,7 +88,7 @@ public class Reward public void DrawSeasonWin(SKCanvas c, int size) { if (!HasReward()) return; - c.DrawBitmap(_theReward.Preview.Resize(size), new SKPoint(0, 0), _rewardPaint); + c.DrawBitmap((_theReward.Preview ?? _theReward.DefaultPreview).Resize(size), new SKPoint(0, 0), _rewardPaint); } public void DrawSeason(SKCanvas c, int x, int y, int areaSize) @@ -115,33 +115,33 @@ public class Reward { switch (trigger.ToLower()) { - case "athenabattlestar": - _theReward = new BaseIcon(null, EIconStyle.Default); - _theReward.Border[0] = SKColor.Parse("FFDB67"); - _theReward.Background[0] = SKColor.Parse("8F4A20"); - _theReward.Preview = Utils.GetBitmap("FortniteGame/Content/Athena/UI/Frontend/Art/T_UI_BP_BattleStar_L.T_UI_BP_BattleStar_L"); - break; - case "athenaseasonalxp": - _theReward = new BaseIcon(null, EIconStyle.Default); - _theReward.Border[0] = SKColor.Parse("E6FDB1"); - _theReward.Background[0] = SKColor.Parse("51830F"); - _theReward.Preview = Utils.GetBitmap("FortniteGame/Content/UI/Foundation/Textures/Icons/Items/T-FNBR-XPUncommon-L.T-FNBR-XPUncommon-L"); - break; - case "mtxgiveaway": - _theReward = new BaseIcon(null, EIconStyle.Default); - _theReward.Border[0] = SKColor.Parse("DCE6FF"); - _theReward.Background[0] = SKColor.Parse("64A0AF"); - _theReward.Preview = Utils.GetBitmap("FortniteGame/Content/UI/Foundation/Textures/Icons/Items/T-Items-MTX.T-Items-MTX"); - break; + // case "athenabattlestar": + // _theReward = new BaseIcon(null, EIconStyle.Default); + // _theReward.Border[0] = SKColor.Parse("FFDB67"); + // _theReward.Background[0] = SKColor.Parse("8F4A20"); + // _theReward.Preview = Utils.GetBitmap("FortniteGame/Content/Athena/UI/Frontend/Art/T_UI_BP_BattleStar_L.T_UI_BP_BattleStar_L"); + // break; + // case "athenaseasonalxp": + // _theReward = new BaseIcon(null, EIconStyle.Default); + // _theReward.Border[0] = SKColor.Parse("E6FDB1"); + // _theReward.Background[0] = SKColor.Parse("51830F"); + // _theReward.Preview = Utils.GetBitmap("FortniteGame/Content/UI/Foundation/Textures/Icons/Items/T-FNBR-XPUncommon-L.T-FNBR-XPUncommon-L"); + // break; + // case "mtxgiveaway": + // _theReward = new BaseIcon(null, EIconStyle.Default); + // _theReward.Border[0] = SKColor.Parse("DCE6FF"); + // _theReward.Background[0] = SKColor.Parse("64A0AF"); + // _theReward.Preview = Utils.GetBitmap("FortniteGame/Content/UI/Foundation/Textures/Icons/Items/T-Items-MTX.T-Items-MTX"); + // break; default: { - var path = Utils.GetFullPath($"FortniteGame/Content/Athena/.*?/{trigger}.*"); // path has no objectname and its needed so we push the trigger again as the objectname + var path = Utils.GetFullPath($"FortniteGame/(?:Content/Athena|Content/Items|Plugins/GameFeatures)/.*?/{trigger}.uasset"); // path has no objectname and its needed so we push the trigger again as the objectname if (!string.IsNullOrWhiteSpace(path) && Utils.TryLoadObject(path.Replace("uasset", trigger), out UObject d)) { _theReward = new BaseIcon(d, EIconStyle.Default); _theReward.ParseForReward(false); _theReward.Border[0] = SKColors.White; - _rewardQuantity = _theReward.DisplayName; + _rewardQuantity = $"{_theReward.DisplayName} ({_rewardQuantity})"; } break; diff --git a/FModel/Creator/CreatorPackage.cs b/FModel/Creator/CreatorPackage.cs index fd2cea3f..6342482a 100644 --- a/FModel/Creator/CreatorPackage.cs +++ b/FModel/Creator/CreatorPackage.cs @@ -136,6 +136,9 @@ public class CreatorPackage : IDisposable _ => new BaseIcon(_object, _style) }; return true; + case "JunoAthenaCharacterItemOverrideDefinition": + creator = new BaseJuno(_object, _style); + return true; case "FortTandemCharacterData": creator = new BaseTandem(_object, _style); return true; From ea279b67851eaa2b165e3517a07543d4b3166a12 Mon Sep 17 00:00:00 2001 From: GMatrixGames Date: Wed, 7 Feb 2024 09:50:22 -0500 Subject: [PATCH 32/85] 28.20 property name change --- FModel/Creator/Bases/FN/BaseIcon.cs | 4 +- .../Creator/Bases/FN/BaseItemAccessToken.cs | 4 +- FModel/Creator/Bases/FN/BaseSeason.cs | 2 +- FModel/Creator/CreatorPackage.cs | 478 +++++++++--------- 4 files changed, 244 insertions(+), 244 deletions(-) diff --git a/FModel/Creator/Bases/FN/BaseIcon.cs b/FModel/Creator/Bases/FN/BaseIcon.cs index 5b1e3f42..be3316c4 100644 --- a/FModel/Creator/Bases/FN/BaseIcon.cs +++ b/FModel/Creator/Bases/FN/BaseIcon.cs @@ -50,9 +50,9 @@ public class BaseIcon : UCreator Preview = Utils.GetBitmap(res); // text - if (Object.TryGetValue(out FText displayName, "DisplayName", "DefaultHeaderText", "UIDisplayName", "EntryName", "EventCalloutTitle")) + if (Object.TryGetValue(out FText displayName, "DisplayName", "ItemName", "DefaultHeaderText", "UIDisplayName", "EntryName", "EventCalloutTitle")) DisplayName = displayName.Text; - if (Object.TryGetValue(out FText description, "Description", "GeneralDescription", "DefaultBodyText", "UIDescription", "UIDisplayDescription", "EntryDescription", "EventCalloutDescription")) + if (Object.TryGetValue(out FText description, "Description", "ItemDescription", "GeneralDescription", "DefaultBodyText", "UIDescription", "UIDisplayDescription", "EntryDescription", "EventCalloutDescription")) Description = description.Text; else if (Object.TryGetValue(out FText[] descriptions, "Description")) Description = string.Join('\n', descriptions.Select(x => x.Text)); diff --git a/FModel/Creator/Bases/FN/BaseItemAccessToken.cs b/FModel/Creator/Bases/FN/BaseItemAccessToken.cs index 3df2e490..455a1fc5 100644 --- a/FModel/Creator/Bases/FN/BaseItemAccessToken.cs +++ b/FModel/Creator/Bases/FN/BaseItemAccessToken.cs @@ -29,12 +29,12 @@ public class BaseItemAccessToken : UCreator _icon.ParseForReward(false); } - if (Object.TryGetValue(out FText displayName, "DisplayName") && displayName.Text != "TBD") + if (Object.TryGetValue(out FText displayName, "DisplayName", "ItemName") && displayName.Text != "TBD") DisplayName = displayName.Text; else DisplayName = _icon?.DisplayName; - Description = Object.TryGetValue(out FText description, "Description") ? description.Text : _icon?.Description; + Description = Object.TryGetValue(out FText description, "Description", "ItemDescription") ? description.Text : _icon?.Description; if (Object.TryGetValue(out FText unlockDescription, "UnlockDescription")) _unlockedDescription = unlockDescription.Text; } diff --git a/FModel/Creator/Bases/FN/BaseSeason.cs b/FModel/Creator/Bases/FN/BaseSeason.cs index c97163b5..1ee32067 100644 --- a/FModel/Creator/Bases/FN/BaseSeason.cs +++ b/FModel/Creator/Bases/FN/BaseSeason.cs @@ -36,7 +36,7 @@ public class BaseSeason : UCreator { _bookXpSchedule = Array.Empty(); - if (Object.TryGetValue(out FText displayName, "DisplayName")) + if (Object.TryGetValue(out FText displayName, "DisplayName", "ItemName")) DisplayName = displayName.Text.ToUpperInvariant(); if (Object.TryGetValue(out FStructFallback seasonFirstWinRewards, "SeasonFirstWinRewards") && diff --git a/FModel/Creator/CreatorPackage.cs b/FModel/Creator/CreatorPackage.cs index 6342482a..c2849e9d 100644 --- a/FModel/Creator/CreatorPackage.cs +++ b/FModel/Creator/CreatorPackage.cs @@ -1,239 +1,239 @@ -using System; -using System.Runtime.CompilerServices; -using CUE4Parse.UE4.Assets.Exports; -using FModel.Creator.Bases; -using FModel.Creator.Bases.BB; -using FModel.Creator.Bases.FN; -using FModel.Creator.Bases.MV; -using FModel.Creator.Bases.SB; - -namespace FModel.Creator; - -public class CreatorPackage : IDisposable -{ - private UObject _object; - private EIconStyle _style; - - public CreatorPackage(UObject uObject, EIconStyle style) - { - _object = uObject; - _style = style; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public UCreator ConstructCreator() - { - TryConstructCreator(out var creator); - return creator; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryConstructCreator(out UCreator creator) - { - switch (_object.ExportType) - { - // Fortnite - case "FortCreativeWeaponMeleeItemDefinition": - case "AthenaConsumableEmoteItemDefinition": - case "AthenaSkyDiveContrailItemDefinition": - case "AthenaLoadingScreenItemDefinition": - case "AthenaVictoryPoseItemDefinition": - case "AthenaPetCarrierItemDefinition": - case "AthenaMusicPackItemDefinition": - case "AthenaBattleBusItemDefinition": - case "AthenaCharacterItemDefinition": - case "AthenaMapMarkerItemDefinition": - case "AthenaBackpackItemDefinition": - case "AthenaPickaxeItemDefinition": - case "AthenaGadgetItemDefinition": - case "AthenaGliderItemDefinition": - case "AthenaSprayItemDefinition": - case "AthenaDanceItemDefinition": - case "AthenaEmojiItemDefinition": - case "AthenaItemWrapDefinition": - case "AthenaToyItemDefinition": - case "FortHeroType": - case "FortTokenType": - case "FortAbilityKit": - case "FortWorkerType": - case "RewardGraphToken": - case "FortBannerTokenType": - case "FortVariantTokenType": - case "FortDecoItemDefinition": - case "FortStatItemDefinition": - case "FortAmmoItemDefinition": - case "FortEmoteItemDefinition": - case "FortBadgeItemDefinition": - case "SparksMicItemDefinition": - case "FortAwardItemDefinition": - case "SparksAuraItemDefinition": - case "SparksDrumItemDefinition": - case "SparksBassItemDefinition": - case "FortGadgetItemDefinition": - case "AthenaCharmItemDefinition": - case "FortPlaysetItemDefinition": - case "FortGiftBoxItemDefinition": - case "FortOutpostItemDefinition": - case "FortVehicleItemDefinition": - case "SparksGuitarItemDefinition": - case "FortCardPackItemDefinition": - case "FortDefenderItemDefinition": - case "FortCurrencyItemDefinition": - case "FortResourceItemDefinition": - case "FortBackpackItemDefinition": - case "FortEventQuestMapDataAsset": - case "FortWeaponModItemDefinition": - case "FortCodeTokenItemDefinition": - case "FortSchematicItemDefinition": - case "SparksKeyboardItemDefinition": - case "FortWorldMultiItemDefinition": - case "FortAlterationItemDefinition": - case "FortExpeditionItemDefinition": - case "FortIngredientItemDefinition": - case "StWFortAccoladeItemDefinition": - case "FortAccountBuffItemDefinition": - case "FortWeaponMeleeItemDefinition": - case "FortPlayerPerksItemDefinition": - case "FortPlaysetPropItemDefinition": - case "JunoRecipeBundleItemDefinition": - case "FortHomebaseNodeItemDefinition": - case "FortNeverPersistItemDefinition": - case "FortPlayerAugmentItemDefinition": - case "FortSmartBuildingItemDefinition": - case "FortWeaponModItemDefinitionOptic": - case "RadioContentSourceItemDefinition": - case "FortPlaysetGrenadeItemDefinition": - case "JunoWeaponCreatureItemDefinition": - case "FortPersonalVehicleItemDefinition": - case "FortGameplayModifierItemDefinition": - case "FortHardcoreModifierItemDefinition": - case "FortWeaponModItemDefinitionMagazine": - case "FortConsumableAccountItemDefinition": - case "FortConversionControlItemDefinition": - case "FortAccountBuffCreditItemDefinition": - case "JunoBuildInstructionsItemDefinition": - case "FortEventCurrencyItemDefinitionRedir": - case "FortPersistentResourceItemDefinition": - case "FortWeaponMeleeOffhandItemDefinition": - case "FortHomebaseBannerIconItemDefinition": - case "FortCampaignHeroLoadoutItemDefinition": - case "FortConditionalResourceItemDefinition": - case "FortChallengeBundleScheduleDefinition": - case "FortWeaponMeleeDualWieldItemDefinition": - case "FortDailyRewardScheduleTokenDefinition": - case "FortCreativeWeaponRangedItemDefinition": - case "FortVehicleCosmeticsItemDefinition_Body": - case "FortVehicleCosmeticsItemDefinition_Skin": - case "FortVehicleCosmeticsItemDefinition_Wheel": - case "FortCreativeRealEstatePlotItemDefinition": - case "FortVehicleCosmeticsItemDefinition_Booster": - case "AthenaDanceItemDefinition_AdHocSquadsJoin_C": - case "FortVehicleCosmeticsItemDefinition_DriftSmoke": - case "FortVehicleCosmeticsItemDefinition_EngineAudio": - creator = _style switch - { - EIconStyle.Cataba => new BaseCommunity(_object, _style, "Cataba"), - _ => new BaseIcon(_object, _style) - }; - return true; - case "JunoAthenaCharacterItemOverrideDefinition": - creator = new BaseJuno(_object, _style); - return true; - case "FortTandemCharacterData": - creator = new BaseTandem(_object, _style); - return true; - case "FortTrapItemDefinition": - case "FortSpyTechItemDefinition": - case "FortAccoladeItemDefinition": - case "FortContextTrapItemDefinition": - case "FortWeaponRangedItemDefinition": - case "Daybreak_LevelExitVehicle_PartItemDefinition_C": - creator = new BaseIconStats(_object, _style); - return true; - case "FortItemSeriesDefinition": - creator = new BaseSeries(_object, _style); - return true; - case "MaterialInstanceConstant" - when _object.Owner != null && - (_object.Owner.Name.Contains("/MI_OfferImages/", StringComparison.OrdinalIgnoreCase) || - _object.Owner.Name.EndsWith($"/RenderSwitch_Materials/{_object.Name}", StringComparison.OrdinalIgnoreCase) || - _object.Owner.Name.EndsWith($"/MI_BPTile/{_object.Name}", StringComparison.OrdinalIgnoreCase)): - creator = new BaseMaterialInstance(_object, _style); - return true; - case "AthenaItemShopOfferDisplayData": - creator = new BaseOfferDisplayData(_object, _style); - return true; - case "FortMtxOfferData": - creator = new BaseMtxOffer(_object, _style); - return true; - case "FortPlaylistAthena": - creator = new BasePlaylist(_object, _style); - return true; - case "FortFeatItemDefinition": - case "FortQuestItemDefinition": - case "FortQuestItemDefinition_Athena": - case "FortQuestItemDefinition_Campaign": - case "AthenaDailyQuestDefinition": - case "FortUrgentQuestItemDefinition": - creator = new Bases.FN.BaseQuest(_object, _style); - return true; - case "FortCompendiumItemDefinition": - case "FortChallengeBundleItemDefinition": - creator = new BaseBundle(_object, _style); - return true; - // case "AthenaSeasonItemDefinition": - // creator = new BaseSeason(_object, _style); - // return true; - case "FortItemAccessTokenType": - creator = new BaseItemAccessToken(_object, _style); - return true; - case "FortCreativeOption": - case "PlaylistUserOptionEnum": - case "PlaylistUserOptionBool": - case "PlaylistUserOptionString": - case "PlaylistUserOptionIntEnum": - case "PlaylistUserOptionIntRange": - case "PlaylistUserOptionColorEnum": - case "PlaylistUserOptionFloatEnum": - case "PlaylistUserOptionFloatRange": - case "PlaylistUserTintedIconIntEnum": - case "PlaylistUserOptionPrimaryAsset": - case "PlaylistUserOptionCollisionProfileEnum": - creator = new BaseUserControl(_object, _style); - return true; - // PandaGame - case "CharacterData": - creator = new BaseFighter(_object, _style); - return true; - case "PerkGroup": - creator = new BasePerkGroup(_object, _style); - return true; - case "StatTrackingBundleData": - case "HydraSyncedDataAsset": - case "AnnouncerPackData": - case "CharacterGiftData": - case "ProfileIconData": - case "RingOutVfxData": - case "BannerData": - case "EmoteData": - case "TauntData": - case "SkinData": - case "PerkData": - creator = new BasePandaIcon(_object, _style); - return true; - case "QuestData": - creator = new Bases.MV.BaseQuest(_object, _style); - return true; - default: - creator = null; - return false; - } - } - - public override string ToString() => $"{_object.ExportType} | {_style}"; - - public void Dispose() - { - _object = null; - } -} +using System; +using System.Runtime.CompilerServices; +using CUE4Parse.UE4.Assets.Exports; +using FModel.Creator.Bases; +using FModel.Creator.Bases.BB; +using FModel.Creator.Bases.FN; +using FModel.Creator.Bases.MV; +using FModel.Creator.Bases.SB; + +namespace FModel.Creator; + +public class CreatorPackage : IDisposable +{ + private UObject _object; + private EIconStyle _style; + + public CreatorPackage(UObject uObject, EIconStyle style) + { + _object = uObject; + _style = style; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public UCreator ConstructCreator() + { + TryConstructCreator(out var creator); + return creator; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool TryConstructCreator(out UCreator creator) + { + switch (_object.ExportType) + { + // Fortnite + case "FortCreativeWeaponMeleeItemDefinition": + case "AthenaConsumableEmoteItemDefinition": + case "AthenaSkyDiveContrailItemDefinition": + case "AthenaLoadingScreenItemDefinition": + case "AthenaVictoryPoseItemDefinition": + case "AthenaPetCarrierItemDefinition": + case "AthenaMusicPackItemDefinition": + case "AthenaBattleBusItemDefinition": + case "AthenaCharacterItemDefinition": + case "AthenaMapMarkerItemDefinition": + case "AthenaBackpackItemDefinition": + case "AthenaPickaxeItemDefinition": + case "AthenaGadgetItemDefinition": + case "AthenaGliderItemDefinition": + case "AthenaSprayItemDefinition": + case "AthenaDanceItemDefinition": + case "AthenaEmojiItemDefinition": + case "AthenaItemWrapDefinition": + case "AthenaToyItemDefinition": + case "FortHeroType": + case "FortTokenType": + case "FortAbilityKit": + case "FortWorkerType": + case "RewardGraphToken": + case "FortBannerTokenType": + case "FortVariantTokenType": + case "FortDecoItemDefinition": + case "FortStatItemDefinition": + case "FortAmmoItemDefinition": + case "FortEmoteItemDefinition": + case "FortBadgeItemDefinition": + case "SparksMicItemDefinition": + case "FortAwardItemDefinition": + case "SparksAuraItemDefinition": + case "SparksDrumItemDefinition": + case "SparksBassItemDefinition": + case "FortGadgetItemDefinition": + case "AthenaCharmItemDefinition": + case "FortPlaysetItemDefinition": + case "FortGiftBoxItemDefinition": + case "FortOutpostItemDefinition": + case "FortVehicleItemDefinition": + case "SparksGuitarItemDefinition": + case "FortCardPackItemDefinition": + case "FortDefenderItemDefinition": + case "FortCurrencyItemDefinition": + case "FortResourceItemDefinition": + case "FortBackpackItemDefinition": + case "FortEventQuestMapDataAsset": + case "FortWeaponModItemDefinition": + case "FortCodeTokenItemDefinition": + case "FortSchematicItemDefinition": + case "SparksKeyboardItemDefinition": + case "FortWorldMultiItemDefinition": + case "FortAlterationItemDefinition": + case "FortExpeditionItemDefinition": + case "FortIngredientItemDefinition": + case "StWFortAccoladeItemDefinition": + case "FortAccountBuffItemDefinition": + case "FortWeaponMeleeItemDefinition": + case "FortPlayerPerksItemDefinition": + case "FortPlaysetPropItemDefinition": + case "JunoRecipeBundleItemDefinition": + case "FortHomebaseNodeItemDefinition": + case "FortNeverPersistItemDefinition": + case "FortPlayerAugmentItemDefinition": + case "FortSmartBuildingItemDefinition": + case "FortWeaponModItemDefinitionOptic": + case "RadioContentSourceItemDefinition": + case "FortPlaysetGrenadeItemDefinition": + case "JunoWeaponCreatureItemDefinition": + case "FortPersonalVehicleItemDefinition": + case "FortGameplayModifierItemDefinition": + case "FortHardcoreModifierItemDefinition": + case "FortWeaponModItemDefinitionMagazine": + case "FortConsumableAccountItemDefinition": + case "FortConversionControlItemDefinition": + case "FortAccountBuffCreditItemDefinition": + case "JunoBuildInstructionsItemDefinition": + case "FortEventCurrencyItemDefinitionRedir": + case "FortPersistentResourceItemDefinition": + case "FortWeaponMeleeOffhandItemDefinition": + case "FortHomebaseBannerIconItemDefinition": + case "FortCampaignHeroLoadoutItemDefinition": + case "FortConditionalResourceItemDefinition": + case "FortChallengeBundleScheduleDefinition": + case "FortWeaponMeleeDualWieldItemDefinition": + case "FortDailyRewardScheduleTokenDefinition": + case "FortCreativeWeaponRangedItemDefinition": + case "FortVehicleCosmeticsItemDefinition_Body": + case "FortVehicleCosmeticsItemDefinition_Skin": + case "FortVehicleCosmeticsItemDefinition_Wheel": + case "FortCreativeRealEstatePlotItemDefinition": + case "FortVehicleCosmeticsItemDefinition_Booster": + case "AthenaDanceItemDefinition_AdHocSquadsJoin_C": + case "FortVehicleCosmeticsItemDefinition_DriftSmoke": + case "FortVehicleCosmeticsItemDefinition_EngineAudio": + creator = _style switch + { + EIconStyle.Cataba => new BaseCommunity(_object, _style, "Cataba"), + _ => new BaseIcon(_object, _style) + }; + return true; + case "JunoAthenaCharacterItemOverrideDefinition": + creator = new BaseJuno(_object, _style); + return true; + case "FortTandemCharacterData": + creator = new BaseTandem(_object, _style); + return true; + case "FortTrapItemDefinition": + case "FortSpyTechItemDefinition": + case "FortAccoladeItemDefinition": + case "FortContextTrapItemDefinition": + case "FortWeaponRangedItemDefinition": + case "Daybreak_LevelExitVehicle_PartItemDefinition_C": + creator = new BaseIconStats(_object, _style); + return true; + case "FortItemSeriesDefinition": + creator = new BaseSeries(_object, _style); + return true; + case "MaterialInstanceConstant" + when _object.Owner != null && + (_object.Owner.Name.Contains("/MI_OfferImages/", StringComparison.OrdinalIgnoreCase) || + _object.Owner.Name.EndsWith($"/RenderSwitch_Materials/{_object.Name}", StringComparison.OrdinalIgnoreCase) || + _object.Owner.Name.EndsWith($"/MI_BPTile/{_object.Name}", StringComparison.OrdinalIgnoreCase)): + creator = new BaseMaterialInstance(_object, _style); + return true; + case "AthenaItemShopOfferDisplayData": + creator = new BaseOfferDisplayData(_object, _style); + return true; + case "FortMtxOfferData": + creator = new BaseMtxOffer(_object, _style); + return true; + case "FortPlaylistAthena": + creator = new BasePlaylist(_object, _style); + return true; + case "FortFeatItemDefinition": + case "FortQuestItemDefinition": + case "FortQuestItemDefinition_Athena": + case "FortQuestItemDefinition_Campaign": + case "AthenaDailyQuestDefinition": + case "FortUrgentQuestItemDefinition": + creator = new Bases.FN.BaseQuest(_object, _style); + return true; + case "FortCompendiumItemDefinition": + case "FortChallengeBundleItemDefinition": + creator = new BaseBundle(_object, _style); + return true; + // case "AthenaSeasonItemDefinition": + // creator = new BaseSeason(_object, _style); + // return true; + case "FortItemAccessTokenType": + creator = new BaseItemAccessToken(_object, _style); + return true; + case "FortCreativeOption": + case "PlaylistUserOptionEnum": + case "PlaylistUserOptionBool": + case "PlaylistUserOptionString": + case "PlaylistUserOptionIntEnum": + case "PlaylistUserOptionIntRange": + case "PlaylistUserOptionColorEnum": + case "PlaylistUserOptionFloatEnum": + case "PlaylistUserOptionFloatRange": + case "PlaylistUserTintedIconIntEnum": + case "PlaylistUserOptionPrimaryAsset": + case "PlaylistUserOptionCollisionProfileEnum": + creator = new BaseUserControl(_object, _style); + return true; + // PandaGame + case "CharacterData": + creator = new BaseFighter(_object, _style); + return true; + case "PerkGroup": + creator = new BasePerkGroup(_object, _style); + return true; + case "StatTrackingBundleData": + case "HydraSyncedDataAsset": + case "AnnouncerPackData": + case "CharacterGiftData": + case "ProfileIconData": + case "RingOutVfxData": + case "BannerData": + case "EmoteData": + case "TauntData": + case "SkinData": + case "PerkData": + creator = new BasePandaIcon(_object, _style); + return true; + case "QuestData": + creator = new Bases.MV.BaseQuest(_object, _style); + return true; + default: + creator = null; + return false; + } + } + + public override string ToString() => $"{_object.ExportType} | {_style}"; + + public void Dispose() + { + _object = null; + } +} From bb0741af389097400d428a3b480ac63b370c4763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=85=E1=B4=8A=CA=9F=E1=B4=8F=CA=803x=E1=B4=A2?= =?UTF-8?q?=E1=B4=8F?= Date: Wed, 7 Feb 2024 16:14:42 +0100 Subject: [PATCH 33/85] QuestsBundle property change (DisplayName->ItemName) --- FModel/Creator/Bases/FN/BaseBundle.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FModel/Creator/Bases/FN/BaseBundle.cs b/FModel/Creator/Bases/FN/BaseBundle.cs index ea5114e8..9f4df8ce 100644 --- a/FModel/Creator/Bases/FN/BaseBundle.cs +++ b/FModel/Creator/Bases/FN/BaseBundle.cs @@ -26,7 +26,7 @@ public class BaseBundle : UCreator { _quests = new List(); - if (Object.TryGetValue(out FText displayName, "DisplayName")) + if (Object.TryGetValue(out FText displayName, "DisplayName", "ItemName")) DisplayName = displayName.Text.ToUpperInvariant(); if (Object.TryGetValue(out FStructFallback[] quests, "QuestInfos")) // prout :) From 44f704258cf173454d60c886310f0ca481be1d0f Mon Sep 17 00:00:00 2001 From: GhostScissors <79089473+GhostScissors@users.noreply.github.com> Date: Thu, 8 Feb 2024 16:29:08 +0530 Subject: [PATCH 34/85] Update BaseJuno.cs Some JIDO use "LowDetailsAssembledMeshSchema" proeprty instead of "AssembledMeshSchema" --- FModel/Creator/Bases/FN/BaseJuno.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FModel/Creator/Bases/FN/BaseJuno.cs b/FModel/Creator/Bases/FN/BaseJuno.cs index af1bbeb7..0fdc6b77 100644 --- a/FModel/Creator/Bases/FN/BaseJuno.cs +++ b/FModel/Creator/Bases/FN/BaseJuno.cs @@ -16,7 +16,7 @@ public class BaseJuno : BaseIcon public override void ParseForInfo() { - if (Object.TryGetValue(out FSoftObjectPath baseCid, "BaseAthenaCharacterItemDefinition") && + if (Object.TryGetValue(out FSoftObjectPath baseCid, "BaseAthenaCharacterItemDefinition", "LowDetailsAssembledMeshSchema") && Utils.TryLoadObject(baseCid.AssetPathName.Text, out UObject cid)) { _character = new BaseIcon(cid, Style); From 033009ef8278c3c89eb4b7c216f6a07e9c6b93a7 Mon Sep 17 00:00:00 2001 From: GhostScissors <79089473+GhostScissors@users.noreply.github.com> Date: Thu, 8 Feb 2024 19:23:37 +0530 Subject: [PATCH 35/85] Update BaseJuno.cs Hmm not doing this anymore --- FModel/Creator/Bases/FN/BaseJuno.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FModel/Creator/Bases/FN/BaseJuno.cs b/FModel/Creator/Bases/FN/BaseJuno.cs index 0fdc6b77..5c5f82bf 100644 --- a/FModel/Creator/Bases/FN/BaseJuno.cs +++ b/FModel/Creator/Bases/FN/BaseJuno.cs @@ -16,13 +16,13 @@ public class BaseJuno : BaseIcon public override void ParseForInfo() { - if (Object.TryGetValue(out FSoftObjectPath baseCid, "BaseAthenaCharacterItemDefinition", "LowDetailsAssembledMeshSchema") && + if (Object.TryGetValue(out FSoftObjectPath baseCid, "BaseAthenaCharacterItemDefinition") && Utils.TryLoadObject(baseCid.AssetPathName.Text, out UObject cid)) { _character = new BaseIcon(cid, Style); _character.ParseForInfo(); - if (Object.TryGetValue(out FSoftObjectPath assembledMeshSchema, "AssembledMeshSchema") && + if (Object.TryGetValue(out FSoftObjectPath assembledMeshSchema, "AssembledMeshSchema", "LowDetailsAssembledMeshSchema") && Utils.TryLoadObject(assembledMeshSchema.AssetPathName.Text, out UObject meshSchema) && meshSchema.TryGetValue(out FInstancedStruct[] additionalData, "AdditionalData")) { From 3e8b155d4aec553741f7e2cb19b76b707c36a9a0 Mon Sep 17 00:00:00 2001 From: GMatrixGames Date: Sat, 10 Feb 2024 15:50:44 -0500 Subject: [PATCH 36/85] parse --- CUE4Parse | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CUE4Parse b/CUE4Parse index 20662a92..aad58828 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 20662a924df0c494b3576888fa5c3ae2ef38594d +Subproject commit aad588289ae725cdf916862064991a986256a502 From 8cbb9503fdd4fb03300aac054454f0abadf4adef Mon Sep 17 00:00:00 2001 From: GMatrixGames Date: Thu, 15 Feb 2024 19:38:44 -0500 Subject: [PATCH 37/85] hm --- CUE4Parse | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CUE4Parse b/CUE4Parse index aad58828..40caf44c 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit aad588289ae725cdf916862064991a986256a502 +Subproject commit 40caf44c1db66e5f0e1edf87c35515ef9a91369f From 5e6765f4b0a337c96205cecabc69df000f8defba Mon Sep 17 00:00:00 2001 From: GMatrixGames Date: Thu, 22 Feb 2024 05:09:25 -0500 Subject: [PATCH 38/85] version bump so you dont have to pull --- CUE4Parse | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CUE4Parse b/CUE4Parse index 40caf44c..be3999f3 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 40caf44c1db66e5f0e1edf87c35515ef9a91369f +Subproject commit be3999f3889bd050c1ccd50781a8b941b7ba08c0 From 53bb6e1f90236b367f18038a30743699d63ad787 Mon Sep 17 00:00:00 2001 From: FireMonkey <38590471+iFireMonkey@users.noreply.github.com> Date: Thu, 22 Feb 2024 16:06:30 -0500 Subject: [PATCH 39/85] LEGO Fortnite JIDO Emote Support (#455) * LEGO Fortnite JIDO Emote Support * LEGO Fortnite JIDO Emote Support Might be a better way of doing this but if it fits it sits. --- FModel/Creator/Bases/FN/BaseJuno.cs | 9 ++++++++- FModel/Creator/CreatorPackage.cs | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/FModel/Creator/Bases/FN/BaseJuno.cs b/FModel/Creator/Bases/FN/BaseJuno.cs index 5c5f82bf..bcabb7bf 100644 --- a/FModel/Creator/Bases/FN/BaseJuno.cs +++ b/FModel/Creator/Bases/FN/BaseJuno.cs @@ -1,4 +1,4 @@ -using CUE4Parse.UE4.Assets.Exports; +using CUE4Parse.UE4.Assets.Exports; using CUE4Parse.UE4.Assets.Objects; using CUE4Parse.UE4.Objects.UObject; using SkiaSharp; @@ -36,6 +36,13 @@ public class BaseJuno : BaseIcon } } } + + if (Object.TryGetValue(out FSoftObjectPath baseEid, "BaseAthenaDanceItemDefinition") && + Utils.TryLoadObject(baseEid.AssetPathName.Text, out UObject eid)) + { + _character = new BaseIcon(eid, Style); + _character.ParseForInfo(); + } } public override SKBitmap[] Draw() => _character.Draw(); diff --git a/FModel/Creator/CreatorPackage.cs b/FModel/Creator/CreatorPackage.cs index c2849e9d..07530d7f 100644 --- a/FModel/Creator/CreatorPackage.cs +++ b/FModel/Creator/CreatorPackage.cs @@ -137,6 +137,7 @@ public class CreatorPackage : IDisposable }; return true; case "JunoAthenaCharacterItemOverrideDefinition": + case "JunoAthenaDanceItemOverrideDefinition": creator = new BaseJuno(_object, _style); return true; case "FortTandemCharacterData": From f64151b0eea4914bb8268f74835bec41435f856e Mon Sep 17 00:00:00 2001 From: Lyndsey Winter <51070189+lyndseyy@users.noreply.github.com> Date: Thu, 22 Feb 2024 17:18:01 -0400 Subject: [PATCH 40/85] add support for ComponentContainer (#454) --- FModel/Creator/Bases/FN/BaseIcon.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/FModel/Creator/Bases/FN/BaseIcon.cs b/FModel/Creator/Bases/FN/BaseIcon.cs index be3316c4..884050c3 100644 --- a/FModel/Creator/Bases/FN/BaseIcon.cs +++ b/FModel/Creator/Bases/FN/BaseIcon.cs @@ -31,6 +31,7 @@ public class BaseIcon : UCreator { // rarity if (Object.TryGetValue(out FPackageIndex series, "Series")) GetSeries(series); + else if (Object.TryGetValue(out FStructFallback componentContainer, "ComponentContainer")) GetSeries(componentContainer); else GetRarity(Object.GetOrDefault("Rarity", EFortRarity.Uncommon)); // default is uncommon // preview @@ -127,6 +128,21 @@ public class BaseIcon : UCreator GetSeries(export); } + private void GetSeries(FStructFallback s) + { + if (!s.TryGetValue(out FPackageIndex[] components, "Components")) return; + + foreach (var component in components) + { + if (!component.TryLoad(out var componentObj) || + !componentObj!.TryGetValue(out UObject componentSeriesDef, "Series")) + continue; + + GetSeries(componentSeriesDef); + break; + } + } + protected void GetSeries(UObject uObject) { if (uObject is UTexture2D texture2D) From eabe4690aa0a22884352bc6f583c44f2d60aa741 Mon Sep 17 00:00:00 2001 From: Asval Date: Fri, 8 Mar 2024 16:57:08 +0100 Subject: [PATCH 41/85] bump --- CUE4Parse | 2 +- FModel/FModel.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index be3999f3..909fae9a 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit be3999f3889bd050c1ccd50781a8b941b7ba08c0 +Subproject commit 909fae9ad24f8c9b0216af824b3c021dd39f1956 diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index ea1bfd12..27458409 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -153,7 +153,7 @@ - + From 4be7d4c3fb40aa00b3779c4fc5a56384bd7fbe92 Mon Sep 17 00:00:00 2001 From: Marlon Date: Thu, 4 Apr 2024 06:18:49 +0200 Subject: [PATCH 42/85] 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 43/85] 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 44/85] 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 45/85] 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 46/85] 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 zcmV;@1TFiCP)1t;YHG-WLY;|1lfW`MvxRi7z~C;SYtuBVkC_yj5&@+$1~2%an3n&JnOf1@r^V# z;fz5Kd^az=|KIccpFi&>T-W9QEQQ}Uj6IbVsFWZ(2(}8QB_o$N;18`N5SokT(~%^w zEhrUI6!X7eRzE}2j^ei=T?d`B;N7h#H|7hliu2F|U(9axCz_P&}vD7JnUG=7|jX^j8m(On| zeR3M6wE{yM0T||3fbBx5P){(_!StEn3xLu9p*oOt5E3{x7&$0hfYKFEgV1~nXw_#( z4|Wm0`nCrc&Wr^(4p`MMnAYZ_rV)ZOz!wEq@od2X4DdyuW(s6aLH~=6RP#K0`5cI~!J&VrFx*lK( zXzjk6`g%{CHV`)mo7@U+1*D8;*U$-X@qT}U2bkP9s(axjC1B1#jRR9*yd(q2Gr&0k zYAwjVkuwz!P?H_)4_HPFe{CCjJrEsV9K2MCFi2^TG;nS20~8$fZ*d{ObQX|^>iD8~ z8=qha|A?sLg{)e&J%A*8hr!@TwzG?fOadhU7=SiG0AQEFwZIZk%$)#G&P;j@*A*mF zL)3)hH4B^fKS=n1t#O8`l;aulydTQPA$JOLL(tco!OT8|zom;n*#lfIR9s!t-uG+r%5%LbURnJ-y0)9mAAXMQ ztYi6OQ$bCEYk)0-Z9+8%+YgxI-2ZKLAsRWrMl&%&qtWIn(fFq7#J01AsP85xQK0Qh_65H6_ zll1GFO1WA=mSwumC0Q`{PMYcx?B0I>*SVkP8p`M8frERY=2skX1W61a%b;qYI3PJ= z!~vuuhYn|_v`l6&lf!jfils8PV{>UBP3xpaZfy>I{QYmKhYR|gISBJ*^uQi8eE>!E z{%Yftw0gsf;f|kvOL*rb)o3v+uycZx0{;V_S1r`&qc-Yj=XMH@&*$!N$g> w;!7_qH@9uyd9|zO>?e_MBvZ07*qoM6N<$f=aR7i=nm0xHa*A>QpcmC|`%bj0B%k@V9_`aXAZF?}A%?{@C`HMrt z!|wvznxC)U6G9+_s2Lvv&HzV&-Q(A;eK!~kE+&)7&QK^+GYEj=IFw2y%H=Y;uG8Gy zOgtX{)zvFkCILLpt5Q^{RBFa|0p9?kz)!7cG#uaB`lY^qKdPz{3WW%TLddd=5CY%# zu`G*BCPT4UL{(Kx)5P<IYR7OJWejYi4ka_<7i zm6v2%0v7JQ_14c@pFX8|X$kG-O@wJ82ZPYj0XxYx3LDwT-EVr*<| zAW0I6qBH?0xm@mL2RN$Q?!Edd@}4~q3c=hQOih8R!oUFR+gFbSz%)%ZHZ}+Z0w_vV z`87E!I|;7i+SRLOK!|-tLj!>W2f#F;Qh{5y;QDnC0^WQR+S=+)gb-+&RxeE7_o=B< zsd=hFlB8Z;*R^0Uh)`AN>Vm;RkY%`e6F&N=O4qSt(B5AEPgPZX->=t+w^Im8P1ALH z9OwIyNCZ_?@jS1Z+`c{t2Ep@Se!fbVEW?o_Rl0U)aU7@qa?7&r0Vo|E9d+XipL`N- zv+W=5L_)DxBoc{Kso1|CjvueCXJ=tz0vxBFc-yuq7K=!dL_VJ$=qX5RwEfEmf($cmbb%1}iIM^Lf71 zG^}8dXV0G_gy;>2!<&2e?nNFM84-m-;gw7#^ZUbx5C3d!ZB3e-oTRmey?Zo&{Bb%p zJ^j9sPX7zgsdfdFhK7bWJkL8;E|&pVU0r2xaF9eI!R5=BIdkR=U0q!~dh`g#amZvc z*tVUoR4VsXRo(Pbsi*P9#pdwl=C^@2fC?}UECVQ}X`WtLS!R!W>XRo=W&(l0Z6U;`L&L+*cf_Xv-vI`JL%@%y&Xwxn!ootjr>BPp z4<29`2E}3#&+~Zp>=~(4ic~7~yT!%D8v_FafBV6qLwUXq7q|mhfDHT*sP`Y~#EBEp z+1Xiodwa|4>+AKT27^K7=H@2u+`04KZ_b~;)!ozc-;CE#2L29Q2LAlj1I0AWKb<>w zu3uHvK!1Nf)6>&LA`$N1y*snIx_a6$jP0?D7wPNkV`*uLP$*Py3AJ&%^X>Y+zvTNq zhG7t^IfzE19|$45vuDqKFPTghhKGlpOP4O?9zJ~dhgdB3BA?HHb!Pw1_%~v{Z%~5> 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 47/85] 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); } From c52df06e7ab349c8a5cb5e9466cc7d20b68e012d Mon Sep 17 00:00:00 2001 From: Marlon Date: Sat, 27 Apr 2024 11:22:59 +0200 Subject: [PATCH 48/85] sync cue4parse --- CUE4Parse | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CUE4Parse b/CUE4Parse index 08a5553d..e05d309a 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 08a5553ddec50aa6064278b424620e95aabf4048 +Subproject commit e05d309a9352cf8e6b6d1a78bfb9e009c5f41323 From 049a4434c9e90ecff7379fb2c52fd35d62927297 Mon Sep 17 00:00:00 2001 From: Marlon Date: Sat, 27 Apr 2024 12:07:00 +0200 Subject: [PATCH 49/85] updated qa qorkflow --- .github/workflows/qa.yml | 46 +++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index d8e487e5..441a9d8a 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -10,56 +10,54 @@ jobs: steps: - name: GIT Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: - submodules: 'true' - - - name: Fetch Submodules Recursively - run: git submodule update --init --recursive + submodules: 'recursive' - name: .NET 8 Setup - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@v4 with: dotnet-version: '8.0.x' - name: .NET Restore run: dotnet restore FModel - - name: Get Version - id: package_version - uses: KageKirin/get-csproj-version@v1.0.0 - with: - file: FModel/FModel.csproj - regex: '^(?[0-9])\.(?[0-9])\.(?[0-9])\.(?[0-9])$' - - name: .NET Publish - run: dotnet publish FModel -c Release --no-self-contained -r win-x64 -f net8.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false + run: dotnet publish FModel -c Release --no-restore --no-self-contained -r win-x64 -f net8.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false - name: ZIP File - uses: papeloto/action-zip@v1 + - uses: thedoctor0/zip-release@v0.7.6 with: - files: ./FModel/bin/Publish/FModel.exe - dest: ${{ github.sha }}.zip # will end up in working directory not the Publish folder + type: 7z + filename: ${{ github.sha }}.7z # will end up in working directory not the Publish folder + path: ./FModel/bin/Publish/FModel.exe - name: Edit QA Artifact - id: edited_release - uses: johnwbyrd/update-release@v1.0.0 + - uses: ncipollo/release-action@v1.14.0 with: token: ${{ secrets.GITHUB_TOKEN }} - release: FModel QA Testing - tag: qa + name: 'FModel QA Testing' + body: 'Dev builds' + tag: 'qa' + artifacts: ${{ github.sha }}.zip prerelease: true - files: ${{ github.sha }}.zip + allowUpdates: true + + - name: Get Version + id: package_version + uses: kzrnm/get-net-sdk-project-versions-action@v2 + with: + proj-path: ./FModel/FModel.csproj - name: FModel Auth id: fmodel_auth - uses: fjogeleit/http-request-action@v1.14.1 + uses: fjogeleit/http-request-action@v1.15.5 with: url: "https://api.fmodel.app/v1/oauth/token" data: '{"username": "${{ secrets.API_USERNAME }}", "password": "${{ secrets.API_PASSWORD }}"}' - name: FModel Deploy Build - uses: fjogeleit/http-request-action@v1.14.1 + uses: fjogeleit/http-request-action@v1.15.5 with: url: "https://api.fmodel.app/v1/infos/${{ secrets.QA_ID }}" method: "PATCH" From 5965cb7e7ffb1041f0b130b4db60894c6980db0f Mon Sep 17 00:00:00 2001 From: Marlon Date: Sat, 27 Apr 2024 12:09:30 +0200 Subject: [PATCH 50/85] fix --- .github/workflows/qa.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 441a9d8a..877c530a 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -26,14 +26,14 @@ jobs: run: dotnet publish FModel -c Release --no-restore --no-self-contained -r win-x64 -f net8.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false - name: ZIP File - - uses: thedoctor0/zip-release@v0.7.6 + uses: thedoctor0/zip-release@v0.7.6 with: type: 7z filename: ${{ github.sha }}.7z # will end up in working directory not the Publish folder path: ./FModel/bin/Publish/FModel.exe - name: Edit QA Artifact - - uses: ncipollo/release-action@v1.14.0 + uses: ncipollo/release-action@v1.14.0 with: token: ${{ secrets.GITHUB_TOKEN }} name: 'FModel QA Testing' From 2d87dcf83c301300b50fcf3d7d616c8d962bc054 Mon Sep 17 00:00:00 2001 From: Marlon Date: Sat, 27 Apr 2024 12:10:24 +0200 Subject: [PATCH 51/85] grr --- .github/workflows/qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 877c530a..bbf8a387 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -26,7 +26,7 @@ jobs: run: dotnet publish FModel -c Release --no-restore --no-self-contained -r win-x64 -f net8.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false - name: ZIP File - uses: thedoctor0/zip-release@v0.7.6 + uses: thedoctor0/zip-release@0.7.6 with: type: 7z filename: ${{ github.sha }}.7z # will end up in working directory not the Publish folder From 81be2dacecfe6ba2aa16d458ff028d128a386c57 Mon Sep 17 00:00:00 2001 From: Marlon Date: Sat, 27 Apr 2024 12:14:28 +0200 Subject: [PATCH 52/85] 7z --- .github/workflows/qa.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index bbf8a387..4d473c7c 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -39,7 +39,7 @@ jobs: name: 'FModel QA Testing' body: 'Dev builds' tag: 'qa' - artifacts: ${{ github.sha }}.zip + artifacts: ${{ github.sha }}.7z prerelease: true allowUpdates: true @@ -62,4 +62,4 @@ jobs: url: "https://api.fmodel.app/v1/infos/${{ secrets.QA_ID }}" method: "PATCH" bearerToken: ${{ fromJson(steps.fmodel_auth.outputs.response).accessToken }} - data: '{"version": "${{ steps.package_version.outputs.version }}-dev+${{ github.sha }}", "downloadUrl": "https://github.com/4sval/FModel/releases/download/qa/${{ github.sha }}.zip"}' + data: '{"version": "${{ steps.package_version.outputs.version }}-dev+${{ github.sha }}", "downloadUrl": "https://github.com/4sval/FModel/releases/download/qa/${{ github.sha }}.7z"}' From 547dadbfc2797886c23d36f53dc16f34666fe7d2 Mon Sep 17 00:00:00 2001 From: Marlon Date: Sat, 27 Apr 2024 12:33:47 +0200 Subject: [PATCH 53/85] nuget updates --- CUE4Parse | 2 +- FModel/FModel.csproj | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index e05d309a..462e5efd 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit e05d309a9352cf8e6b6d1a78bfb9e009c5f41323 +Subproject commit 462e5efd764e97256d123685f37be621f5787fcc diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 0a192513..9e1e1f6f 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -160,8 +160,8 @@ - - + + From 0f20b543ca64203686062d563605c3a296990f3d Mon Sep 17 00:00:00 2001 From: Marlon Date: Sat, 27 Apr 2024 12:33:58 +0200 Subject: [PATCH 54/85] use zip --- .github/workflows/qa.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 4d473c7c..ead5c624 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -23,13 +23,13 @@ jobs: run: dotnet restore FModel - name: .NET Publish - run: dotnet publish FModel -c Release --no-restore --no-self-contained -r win-x64 -f net8.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false + run: dotnet publish "./FModel/FModel.csproj" -c Release --no-restore --no-self-contained -r win-x64 -f net8.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false - name: ZIP File uses: thedoctor0/zip-release@0.7.6 with: - type: 7z - filename: ${{ github.sha }}.7z # will end up in working directory not the Publish folder + type: zip + filename: ${{ github.sha }}.zip # will end up in working directory not the Publish folder path: ./FModel/bin/Publish/FModel.exe - name: Edit QA Artifact @@ -39,7 +39,7 @@ jobs: name: 'FModel QA Testing' body: 'Dev builds' tag: 'qa' - artifacts: ${{ github.sha }}.7z + artifacts: ${{ github.sha }}.zip prerelease: true allowUpdates: true @@ -62,4 +62,4 @@ jobs: url: "https://api.fmodel.app/v1/infos/${{ secrets.QA_ID }}" method: "PATCH" bearerToken: ${{ fromJson(steps.fmodel_auth.outputs.response).accessToken }} - data: '{"version": "${{ steps.package_version.outputs.version }}-dev+${{ github.sha }}", "downloadUrl": "https://github.com/4sval/FModel/releases/download/qa/${{ github.sha }}.7z"}' + data: '{"version": "${{ steps.package_version.outputs.version }}-dev+${{ github.sha }}", "downloadUrl": "https://github.com/4sval/FModel/releases/download/qa/${{ github.sha }}.zip"}' From 21cfa0781f6cda69e8eda444bbef0762ebfb48ee Mon Sep 17 00:00:00 2001 From: Asval Date: Sat, 27 Apr 2024 12:35:13 +0200 Subject: [PATCH 55/85] bye bye --- FModel/MainWindow.xaml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/FModel/MainWindow.xaml b/FModel/MainWindow.xaml index b9952ffd..d2243583 100644 --- a/FModel/MainWindow.xaml +++ b/FModel/MainWindow.xaml @@ -321,16 +321,16 @@ - - - - - - - - - - + + + + + + + + + + From 071d32b2da55ce1b2922aa14becd40ac467e2220 Mon Sep 17 00:00:00 2001 From: Asval Date: Tue, 30 Apr 2024 02:54:40 +0200 Subject: [PATCH 56/85] 8 bone influence --- CUE4Parse | 2 +- FModel/Resources/default.frag | 4 +- FModel/Resources/default.vert | 50 ++++++++++++------ FModel/Resources/outline.vert | 29 +++++++---- FModel/Resources/picking.vert | 24 ++++++--- .../Snooper/Buffers/VertexArrayObject.cs | 3 +- FModel/Views/Snooper/Models/UModel.cs | 52 +++++++++---------- 7 files changed, 103 insertions(+), 61 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 462e5efd..39ba4c7f 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 462e5efd764e97256d123685f37be621f5787fcc +Subproject commit 39ba4c7fcd9e058dbe33d8fec7cddb00763ace33 diff --git a/FModel/Resources/default.frag b/FModel/Resources/default.frag index 29b9f84d..34a2225c 100644 --- a/FModel/Resources/default.frag +++ b/FModel/Resources/default.frag @@ -8,7 +8,7 @@ in vec3 fPos; in vec3 fNormal; in vec3 fTangent; in vec2 fTexCoords; -in float fTexLayer; +flat in int fTexLayer; in vec4 fColor; struct Texture @@ -98,7 +98,7 @@ out vec4 FragColor; int LayerToIndex() { - return clamp(int(fTexLayer), 0, uUvCount - 1); + return clamp(fTexLayer, 0, uUvCount - 1); } vec4 SamplerToVector(sampler2D s, vec2 coords) diff --git a/FModel/Resources/default.vert b/FModel/Resources/default.vert index 3d530a5b..97e564c7 100644 --- a/FModel/Resources/default.vert +++ b/FModel/Resources/default.vert @@ -4,10 +4,10 @@ layout (location = 1) in vec3 vPos; layout (location = 2) in vec3 vNormal; layout (location = 3) in vec3 vTangent; layout (location = 4) in vec2 vTexCoords; -layout (location = 5) in float vTexLayer; -layout (location = 6) in vec4 vColor; -layout (location = 7) in vec4 vBoneIds; -layout (location = 8) in vec4 vBoneWeights; +layout (location = 5) in int vTexLayer; +layout (location = 6) in float vColor; +layout (location = 7) in vec4 vBoneInfluence; +layout (location = 8) in vec4 vBoneInfluenceExtra; layout (location = 9) in mat4 vInstanceMatrix; layout (location = 13) in vec3 vMorphTargetPos; layout (location = 14) in vec3 vMorphTargetTangent; @@ -30,9 +30,23 @@ out vec3 fPos; out vec3 fNormal; out vec3 fTangent; out vec2 fTexCoords; -out float fTexLayer; +flat out int fTexLayer; out vec4 fColor; +vec4 unpackARGB(int color) +{ + float a = float((color >> 24) & 0xFF); + float r = float((color >> 16) & 0xFF); + float g = float((color >> 8) & 0xFF); + float b = float((color >> 0) & 0xFF); + return vec4(r, g, b, a); +} + +vec2 unpackBoneIDsAndWeights(int packedData) +{ + return vec2(float((packedData >> 16) & 0xFFFF), float(packedData & 0xFFFF)); +} + void main() { vec4 bindPos = vec4(mix(vPos, vMorphTargetPos, uMorphTime), 1.0); @@ -44,18 +58,24 @@ void main() vec4 finalTangent = vec4(0.0); if (uIsAnimated) { - for(int i = 0 ; i < 4; i++) + vec4 boneInfluences[2]; + boneInfluences[0] = vBoneInfluence; + boneInfluences[1] = vBoneInfluenceExtra; + for (int i = 0; i < 2; i++) { - int boneIndex = int(vBoneIds[i]); - if(boneIndex < 0) break; + for(int j = 0 ; j < 4; j++) + { + vec2 boneInfluence = unpackBoneIDsAndWeights(int(boneInfluences[i][j])); + int boneIndex = int(boneInfluence.x); + float weight = boneInfluence.y; - mat4 boneMatrix = uFinalBonesMatrix[boneIndex] * inverse(uRestBonesMatrix[boneIndex]); - mat4 inverseBoneMatrix = transpose(inverse(boneMatrix)); - float weight = vBoneWeights[i]; + mat4 boneMatrix = uFinalBonesMatrix[boneIndex] * inverse(uRestBonesMatrix[boneIndex]); + mat4 inverseBoneMatrix = transpose(inverse(boneMatrix)); - finalPos += boneMatrix * bindPos * weight; - finalNormal += inverseBoneMatrix * bindNormal * weight; - finalTangent += inverseBoneMatrix * bindTangent * weight; + finalPos += boneMatrix * bindPos * weight; + finalNormal += inverseBoneMatrix * bindNormal * weight; + finalTangent += inverseBoneMatrix * bindTangent * weight; + } } } else @@ -72,5 +92,5 @@ void main() fTangent = vec3(transpose(inverse(vInstanceMatrix)) * finalTangent); fTexCoords = vTexCoords; fTexLayer = vTexLayer; - fColor = vColor; + fColor = unpackARGB(int(vColor)); } diff --git a/FModel/Resources/outline.vert b/FModel/Resources/outline.vert index ffb85c6c..a7049e5e 100644 --- a/FModel/Resources/outline.vert +++ b/FModel/Resources/outline.vert @@ -2,8 +2,8 @@ layout (location = 1) in vec3 vPos; layout (location = 2) in vec3 vNormal; -layout (location = 7) in vec4 vBoneIds; -layout (location = 8) in vec4 vBoneWeights; +layout (location = 7) in vec4 vBoneInfluence; +layout (location = 8) in vec4 vBoneInfluenceExtra; layout (location = 9) in mat4 vInstanceMatrix; layout (location = 13) in vec3 vMorphTargetPos; @@ -22,6 +22,11 @@ uniform mat4 uProjection; uniform float uMorphTime; uniform bool uIsAnimated; +vec2 unpackBoneIDsAndWeights(int packedData) +{ + return vec2(float((packedData >> 16) & 0xFFFF), float(packedData & 0xFFFF)); +} + void main() { vec4 bindPos = vec4(mix(vPos, vMorphTargetPos, uMorphTime), 1.0); @@ -31,16 +36,22 @@ void main() vec4 finalNormal = vec4(0.0); if (uIsAnimated) { - for(int i = 0 ; i < 4; i++) + vec4 boneInfluences[2]; + boneInfluences[0] = vBoneInfluence; + boneInfluences[1] = vBoneInfluenceExtra; + for(int i = 0 ; i < 2; i++) { - int boneIndex = int(vBoneIds[i]); - if(boneIndex < 0) break; + for(int j = 0; j < 4; j++) + { + vec2 boneInfluence = unpackBoneIDsAndWeights(int(boneInfluences[i][j])); + int boneIndex = int(boneInfluence.x); + float weight = boneInfluence.y; - mat4 boneMatrix = uFinalBonesMatrix[boneIndex] * inverse(uRestBonesMatrix[boneIndex]); - float weight = vBoneWeights[i]; + mat4 boneMatrix = uFinalBonesMatrix[boneIndex] * inverse(uRestBonesMatrix[boneIndex]); - finalPos += boneMatrix * bindPos * weight; - finalNormal += transpose(inverse(boneMatrix)) * bindNormal * weight; + finalPos += boneMatrix * bindPos * weight; + finalNormal += transpose(inverse(boneMatrix)) * bindNormal * weight; + } } } else diff --git a/FModel/Resources/picking.vert b/FModel/Resources/picking.vert index 7d267c0c..15194254 100644 --- a/FModel/Resources/picking.vert +++ b/FModel/Resources/picking.vert @@ -1,8 +1,8 @@ #version 460 core layout (location = 1) in vec3 vPos; -layout (location = 7) in vec4 vBoneIds; -layout (location = 8) in vec4 vBoneWeights; +layout (location = 7) in vec4 vBoneInfluence; +layout (location = 8) in vec4 vBoneInfluenceExtra; layout (location = 9) in mat4 vInstanceMatrix; layout (location = 13) in vec3 vMorphTargetPos; @@ -20,6 +20,11 @@ uniform mat4 uProjection; uniform float uMorphTime; uniform bool uIsAnimated; +vec2 unpackBoneIDsAndWeights(int packedData) +{ + return vec2(float((packedData >> 16) & 0xFFFF), float(packedData & 0xFFFF)); +} + void main() { vec4 bindPos = vec4(mix(vPos, vMorphTargetPos, uMorphTime), 1.0); @@ -27,12 +32,19 @@ void main() vec4 finalPos = vec4(0.0); if (uIsAnimated) { - for(int i = 0 ; i < 4; i++) + vec4 boneInfluences[2]; + boneInfluences[0] = vBoneInfluence; + boneInfluences[1] = vBoneInfluenceExtra; + for(int i = 0 ; i < 2; i++) { - int boneIndex = int(vBoneIds[i]); - if(boneIndex < 0) break; + for(int j = 0; j < 4; j++) + { + vec2 boneInfluence = unpackBoneIDsAndWeights(int(boneInfluences[i][j])); + int boneIndex = int(boneInfluence.x); + float weight = boneInfluence.y; - finalPos += uFinalBonesMatrix[boneIndex] * inverse(uRestBonesMatrix[boneIndex]) * bindPos * vBoneWeights[i]; + finalPos += uFinalBonesMatrix[boneIndex] * inverse(uRestBonesMatrix[boneIndex]) * bindPos * weight; + } } } else finalPos = bindPos; diff --git a/FModel/Views/Snooper/Buffers/VertexArrayObject.cs b/FModel/Views/Snooper/Buffers/VertexArrayObject.cs index 820d1885..6bf24c12 100644 --- a/FModel/Views/Snooper/Buffers/VertexArrayObject.cs +++ b/FModel/Views/Snooper/Buffers/VertexArrayObject.cs @@ -26,7 +26,8 @@ public class VertexArrayObject : IDisposable where TVer switch (type) { case VertexAttribPointerType.Int: - GL.VertexAttribIPointer(index, count, VertexAttribIntegerType.Int, vertexSize * _sizeOfVertex, (IntPtr) (offset * _sizeOfVertex)); + case VertexAttribPointerType.UnsignedInt: + GL.VertexAttribIPointer(index, count, (VertexAttribIntegerType) type, vertexSize * _sizeOfVertex, offset * _sizeOfVertex); break; default: GL.VertexAttribPointer(index, count, type, false, vertexSize * _sizeOfVertex, offset * _sizeOfVertex); diff --git a/FModel/Views/Snooper/Models/UModel.cs b/FModel/Views/Snooper/Models/UModel.cs index 6bff5537..8e6fa3d1 100644 --- a/FModel/Views/Snooper/Models/UModel.cs +++ b/FModel/Views/Snooper/Models/UModel.cs @@ -20,6 +20,7 @@ namespace FModel.Views.Snooper.Models; public class VertexAttribute { public int Size; + public VertexAttribPointerType Type; public bool Enabled; } @@ -28,18 +29,18 @@ public abstract class UModel : IRenderableModel protected const int LodLevel = 0; private readonly UObject _export; - private readonly List _vertexAttributes = new() - { - new VertexAttribute { Size = 1, Enabled = false }, // VertexIndex - new VertexAttribute { Size = 3, Enabled = true }, // Position - new VertexAttribute { Size = 3, Enabled = false }, // Normal - new VertexAttribute { Size = 3, Enabled = false }, // Tangent - new VertexAttribute { Size = 2, Enabled = false }, // UV - new VertexAttribute { Size = 1, Enabled = false }, // TextureLayer - new VertexAttribute { Size = 4, Enabled = false }, // Colors - new VertexAttribute { Size = 4, Enabled = false }, // BoneIds - new VertexAttribute { Size = 4, Enabled = false } // BoneWeights - }; + private readonly List _vertexAttributes = + [ + new VertexAttribute { Size = 1, Type = VertexAttribPointerType.Int, Enabled = false }, // VertexIndex + new VertexAttribute { Size = 3, Type = VertexAttribPointerType.Float, Enabled = true }, // Position + new VertexAttribute { Size = 3, Type = VertexAttribPointerType.Float, Enabled = false }, // Normal + new VertexAttribute { Size = 3, Type = VertexAttribPointerType.Float, Enabled = false }, // Tangent + new VertexAttribute { Size = 2, Type = VertexAttribPointerType.Float, Enabled = false }, // UV + new VertexAttribute { Size = 1, Type = VertexAttribPointerType.Float, Enabled = false }, // TextureLayer + new VertexAttribute { Size = 1, Type = VertexAttribPointerType.Float, Enabled = false }, // Colors + new VertexAttribute { Size = 4, Type = VertexAttribPointerType.Float, Enabled = false }, // BoneIds + new VertexAttribute { Size = 4, Type = VertexAttribPointerType.Float, Enabled = false } // BoneWeights + ]; public int Handle { get; set; } public BufferObject Ebo { get; set; } @@ -149,24 +150,20 @@ public abstract class UModel : IRenderableModel if (HasVertexColors) { - var color = lod.VertexColors[i]; - Vertices[baseIndex + count++] = color.R; - Vertices[baseIndex + count++] = color.G; - Vertices[baseIndex + count++] = color.B; - Vertices[baseIndex + count++] = color.A; + Vertices[baseIndex + count++] = lod.VertexColors[i].ToPackedARGB(); } if (vert is CSkelMeshVertex skelVert) { - var weightsHash = skelVert.UnpackWeights(); - Vertices[baseIndex + count++] = skelVert.Bone[0]; - Vertices[baseIndex + count++] = skelVert.Bone[1]; - Vertices[baseIndex + count++] = skelVert.Bone[2]; - Vertices[baseIndex + count++] = skelVert.Bone[3]; - Vertices[baseIndex + count++] = weightsHash[0]; - Vertices[baseIndex + count++] = weightsHash[1]; - Vertices[baseIndex + count++] = weightsHash[2]; - Vertices[baseIndex + count++] = weightsHash[3]; + int max = skelVert.Influences.Count; + for (int j = 0; j < 8; j++) + { + var boneID = j < max ? skelVert.Influences[j].Bone : (short) 0; + var weight = j < max ? skelVert.Influences[j].RawWeight : (byte) 0; + + // Pack bone ID and weight + Vertices[baseIndex + count++] = (boneID << 16) | weight; + } } } @@ -197,8 +194,9 @@ public abstract class UModel : IRenderableModel if (i != 5 || !broken) { - Vao.VertexAttributePointer((uint) i, attribute.Size, i == 0 ? VertexAttribPointerType.Int : VertexAttribPointerType.Float, VertexSize, offset); + Vao.VertexAttributePointer((uint) i, attribute.Size, attribute.Type, VertexSize, offset); } + offset += attribute.Size; } From 3714f1e125ce98df17440aeb1f41529afa96ae25 Mon Sep 17 00:00:00 2001 From: Marlon Date: Tue, 30 Apr 2024 10:46:23 +0200 Subject: [PATCH 57/85] cue4p sync --- CUE4Parse | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CUE4Parse b/CUE4Parse index 39ba4c7f..75bf52ca 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 39ba4c7fcd9e058dbe33d8fec7cddb00763ace33 +Subproject commit 75bf52cafb31d8d90b1b8c517aeb36c6b0ee89e6 From c3e4e7d404ceee3a2b5f8e825b0ba0f4bbebf2ba Mon Sep 17 00:00:00 2001 From: Marlon Date: Tue, 30 Apr 2024 10:46:33 +0200 Subject: [PATCH 58/85] obsolete fix? --- FModel/ViewModels/CUE4ParseViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 409b0d12..0ec33ce2 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -112,7 +112,7 @@ public class CUE4ParseViewModel : ViewModel new GameWindowSettings { UpdateFrequency = htz }, new NativeWindowSettings { - Size = new OpenTK.Mathematics.Vector2i( + ClientSize = new OpenTK.Mathematics.Vector2i( Convert.ToInt32(SystemParameters.MaximizedPrimaryScreenWidth * .75 * scale), Convert.ToInt32(SystemParameters.MaximizedPrimaryScreenHeight * .85 * scale)), NumberOfSamples = Constants.SAMPLES_COUNT, From 2df24242ac3e3b02af6e905bf1ed0c14601eef25 Mon Sep 17 00:00:00 2001 From: GMatrixGames Date: Thu, 2 May 2024 14:30:54 -0400 Subject: [PATCH 59/85] Undawn custom encryption handling --- CUE4Parse | 2 +- FModel/ViewModels/CUE4ParseViewModel.cs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CUE4Parse b/CUE4Parse index 75bf52ca..8edb3a46 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 75bf52cafb31d8d90b1b8c517aeb36c6b0ee89e6 +Subproject commit 8edb3a46c989889aed56ebb2cf910bbcf8fa5bed diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 0ec33ce2..ae06ad8d 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -38,6 +38,7 @@ using CUE4Parse.UE4.Wwise; using CUE4Parse_Conversion; using CUE4Parse_Conversion.Sounds; +using CUE4Parse.GameTypes.UDWN.Encryption.Aes; using EpicManifestParser; using FModel.Creator; @@ -183,6 +184,11 @@ public class CUE4ParseViewModel : ViewModel } } Provider.ReadScriptData = UserSettings.Default.ReadScriptData; + Provider.CustomEncryption = Provider.Versions.Game switch + { + EGame.GAME_Undawn => ToaaAes.ToaaDecrypt, + _ => Provider.CustomEncryption + }; GameDirectory = new GameDirectoryViewModel(); AssetsFolder = new AssetsFolderViewModel(); From 9a9eb02f05fe7acf80f29ddb7e18f8ede89dc249 Mon Sep 17 00:00:00 2001 From: LongerWarrior Date: Fri, 3 May 2024 23:40:00 +0300 Subject: [PATCH 60/85] DbD custom encryption handling --- CUE4Parse | 2 +- FModel/ViewModels/CUE4ParseViewModel.cs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CUE4Parse b/CUE4Parse index 8edb3a46..38be1267 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 8edb3a46c989889aed56ebb2cf910bbcf8fa5bed +Subproject commit 38be126747f52c4a72f98d09de2d8073c4af750e diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index ae06ad8d..0ee837ad 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -39,6 +39,7 @@ using CUE4Parse_Conversion; using CUE4Parse_Conversion.Sounds; using CUE4Parse.GameTypes.UDWN.Encryption.Aes; +using CUE4Parse.GameTypes.DBD.Encryption.Aes; using EpicManifestParser; using FModel.Creator; @@ -187,6 +188,7 @@ public class CUE4ParseViewModel : ViewModel Provider.CustomEncryption = Provider.Versions.Game switch { EGame.GAME_Undawn => ToaaAes.ToaaDecrypt, + EGame.GAME_DeadbyDaylight => DbDAes.DbDDecrypt, _ => Provider.CustomEncryption }; From 2a733b9d9a5d3b97a69e9f762c092a91f8322ce9 Mon Sep 17 00:00:00 2001 From: LongerWarrior Date: Fri, 3 May 2024 23:40:00 +0300 Subject: [PATCH 61/85] compression settings --- FModel/Settings/UserSettings.cs | 8 +++ FModel/ViewModels/CUE4ParseViewModel.cs | 8 +++ FModel/ViewModels/SettingsViewModel.cs | 26 +++++++- FModel/Views/SettingsView.xaml | 79 ++++++++++++++----------- 4 files changed, 86 insertions(+), 35 deletions(-) diff --git a/FModel/Settings/UserSettings.cs b/FModel/Settings/UserSettings.cs index cdbbaae4..8945c772 100644 --- a/FModel/Settings/UserSettings.cs +++ b/FModel/Settings/UserSettings.cs @@ -6,6 +6,7 @@ using System.Windows.Input; using CUE4Parse.UE4.Versions; using CUE4Parse_Conversion.Meshes; using CUE4Parse_Conversion.Textures; +using CUE4Parse_Conversion.UEFormat.Enums; using CUE4Parse.UE4.Assets.Exports.Material; using FModel.Framework; using FModel.ViewModels; @@ -356,6 +357,13 @@ namespace FModel.Settings set => SetProperty(ref _socketExportFormat, value); } + private EFileCompressionFormat _compressionFormat = EFileCompressionFormat.ZSTD; + public EFileCompressionFormat CompressionFormat + { + get => _compressionFormat; + set => SetProperty(ref _compressionFormat, value); + } + private ELodFormat _lodExportFormat = ELodFormat.FirstLod; public ELodFormat LodExportFormat { diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 0ee837ad..3a043223 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -36,6 +36,8 @@ using CUE4Parse.UE4.Versions; using CUE4Parse.UE4.Wwise; using CUE4Parse_Conversion; +using CUE4Parse_Conversion.Animations; +using CUE4Parse_Conversion.Meshes; using CUE4Parse_Conversion.Sounds; using CUE4Parse.GameTypes.UDWN.Encryption.Aes; @@ -960,9 +962,15 @@ public class CUE4ParseViewModel : ViewModel { LodFormat = UserSettings.Default.LodExportFormat, MeshFormat = UserSettings.Default.MeshExportFormat, + AnimFormat = UserSettings.Default.MeshExportFormat switch + { + EMeshFormat.ActorX => EAnimFormat.ActorX, + _ => EAnimFormat.UEFormat // i think we said ueformat default is okay + }, MaterialFormat = UserSettings.Default.MaterialExportFormat, TextureFormat = UserSettings.Default.TextureExportFormat, SocketFormat = UserSettings.Default.SocketExportFormat, + CompressionFormat = UserSettings.Default.CompressionFormat, Platform = UserSettings.Default.CurrentDir.TexturePlatform, ExportMorphTargets = UserSettings.Default.SaveMorphTargets, ExportMaterials = UserSettings.Default.SaveEmbeddedMaterials diff --git a/FModel/ViewModels/SettingsViewModel.cs b/FModel/ViewModels/SettingsViewModel.cs index 4d5f2aa4..b75ebf5b 100644 --- a/FModel/ViewModels/SettingsViewModel.cs +++ b/FModel/ViewModels/SettingsViewModel.cs @@ -2,11 +2,13 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; +using System.Windows; using CUE4Parse.UE4.Assets.Exports.Texture; using CUE4Parse.UE4.Objects.Core.Serialization; using CUE4Parse.UE4.Versions; using CUE4Parse_Conversion.Meshes; using CUE4Parse_Conversion.Textures; +using CUE4Parse_Conversion.UEFormat.Enums; using CUE4Parse.UE4.Assets.Exports.Material; using FModel.Framework; using FModel.Services; @@ -120,7 +122,12 @@ public class SettingsViewModel : ViewModel public EMeshFormat SelectedMeshExportFormat { get => _selectedMeshExportFormat; - set => SetProperty(ref _selectedMeshExportFormat, value); + set + { + SetProperty(ref _selectedMeshExportFormat, value); + RaisePropertyChanged(nameof(SocketSettingsEnabled)); + RaisePropertyChanged(nameof(CompressionSettingsEnabled)); + } } private ESocketFormat _selectedSocketExportFormat; @@ -130,6 +137,13 @@ public class SettingsViewModel : ViewModel set => SetProperty(ref _selectedSocketExportFormat, value); } + private EFileCompressionFormat _selectedCompressionFormat; + public EFileCompressionFormat SelectedCompressionFormat + { + get => _selectedCompressionFormat; + set => SetProperty(ref _selectedCompressionFormat, value); + } + private ELodFormat _selectedLodExportFormat; public ELodFormat SelectedLodExportFormat { @@ -151,6 +165,9 @@ public class SettingsViewModel : ViewModel set => SetProperty(ref _selectedTextureExportFormat, value); } + public bool SocketSettingsEnabled => SelectedMeshExportFormat == EMeshFormat.ActorX; + public bool CompressionSettingsEnabled => SelectedMeshExportFormat == EMeshFormat.UEFormat; + public ReadOnlyObservableCollection UpdateModes { get; private set; } public ReadOnlyObservableCollection UeGames { get; private set; } public ReadOnlyObservableCollection AssetLanguages { get; private set; } @@ -160,6 +177,7 @@ public class SettingsViewModel : ViewModel public ReadOnlyObservableCollection CosmeticStyles { get; private set; } public ReadOnlyObservableCollection MeshExportFormats { get; private set; } public ReadOnlyObservableCollection SocketExportFormats { get; private set; } + public ReadOnlyObservableCollection CompressionFormats { get; private set; } public ReadOnlyObservableCollection LodExportFormats { get; private set; } public ReadOnlyObservableCollection MaterialExportFormats { get; private set; } public ReadOnlyObservableCollection TextureExportFormats { get; private set; } @@ -183,6 +201,7 @@ public class SettingsViewModel : ViewModel private EIconStyle _cosmeticStyleSnapshot; private EMeshFormat _meshExportFormatSnapshot; private ESocketFormat _socketExportFormatSnapshot; + private EFileCompressionFormat _compressionFormatSnapshot; private ELodFormat _lodExportFormatSnapshot; private EMaterialFormat _materialExportFormatSnapshot; private ETextureFormat _textureExportFormatSnapshot; @@ -223,6 +242,7 @@ public class SettingsViewModel : ViewModel _cosmeticStyleSnapshot = UserSettings.Default.CosmeticStyle; _meshExportFormatSnapshot = UserSettings.Default.MeshExportFormat; _socketExportFormatSnapshot = UserSettings.Default.SocketExportFormat; + _compressionFormatSnapshot = UserSettings.Default.CompressionFormat; _lodExportFormatSnapshot = UserSettings.Default.LodExportFormat; _materialExportFormatSnapshot = UserSettings.Default.MaterialExportFormat; _textureExportFormatSnapshot = UserSettings.Default.TextureExportFormat; @@ -238,6 +258,7 @@ public class SettingsViewModel : ViewModel SelectedCosmeticStyle = _cosmeticStyleSnapshot; SelectedMeshExportFormat = _meshExportFormatSnapshot; SelectedSocketExportFormat = _socketExportFormatSnapshot; + SelectedCompressionFormat = _selectedCompressionFormat; SelectedLodExportFormat = _lodExportFormatSnapshot; SelectedMaterialExportFormat = _materialExportFormatSnapshot; SelectedTextureExportFormat = _textureExportFormatSnapshot; @@ -253,6 +274,7 @@ public class SettingsViewModel : ViewModel CosmeticStyles = new ReadOnlyObservableCollection(new ObservableCollection(EnumerateCosmeticStyles())); MeshExportFormats = new ReadOnlyObservableCollection(new ObservableCollection(EnumerateMeshExportFormat())); SocketExportFormats = new ReadOnlyObservableCollection(new ObservableCollection(EnumerateSocketExportFormat())); + CompressionFormats = new ReadOnlyObservableCollection(new ObservableCollection(EnumerateCompressionFormat())); LodExportFormats = new ReadOnlyObservableCollection(new ObservableCollection(EnumerateLodExportFormat())); MaterialExportFormats = new ReadOnlyObservableCollection(new ObservableCollection(EnumerateMaterialExportFormat())); TextureExportFormats = new ReadOnlyObservableCollection(new ObservableCollection(EnumerateTextureExportFormat())); @@ -295,6 +317,7 @@ public class SettingsViewModel : ViewModel UserSettings.Default.CosmeticStyle = SelectedCosmeticStyle; UserSettings.Default.MeshExportFormat = SelectedMeshExportFormat; UserSettings.Default.SocketExportFormat = SelectedSocketExportFormat; + UserSettings.Default.CompressionFormat = SelectedCompressionFormat; UserSettings.Default.LodExportFormat = SelectedLodExportFormat; UserSettings.Default.MaterialExportFormat = SelectedMaterialExportFormat; UserSettings.Default.TextureExportFormat = SelectedTextureExportFormat; @@ -320,6 +343,7 @@ public class SettingsViewModel : ViewModel private IEnumerable EnumerateCosmeticStyles() => Enum.GetValues(); private IEnumerable EnumerateMeshExportFormat() => Enum.GetValues(); private IEnumerable EnumerateSocketExportFormat() => Enum.GetValues(); + private IEnumerable EnumerateCompressionFormat() => Enum.GetValues(); private IEnumerable EnumerateLodExportFormat() => Enum.GetValues(); private IEnumerable EnumerateMaterialExportFormat() => Enum.GetValues(); private IEnumerable EnumerateTextureExportFormat() => Enum.GetValues(); diff --git a/FModel/Views/SettingsView.xaml b/FModel/Views/SettingsView.xaml index f5373a08..1b331007 100644 --- a/FModel/Views/SettingsView.xaml +++ b/FModel/Views/SettingsView.xaml @@ -316,6 +316,7 @@ + @@ -330,7 +331,7 @@ + + diff --git a/FModel/Views/DirectorySelector.xaml.cs b/FModel/Views/DirectorySelector.xaml.cs index 8b51717f..9605352f 100644 --- a/FModel/Views/DirectorySelector.xaml.cs +++ b/FModel/Views/DirectorySelector.xaml.cs @@ -1,6 +1,7 @@ using FModel.ViewModels; using Ookii.Dialogs.Wpf; using System.Windows; +using CUE4Parse.Utils; namespace FModel.Views; @@ -38,6 +39,7 @@ public partial class DirectorySelector var folderBrowser = new VistaFolderBrowserDialog {ShowNewFolderButton = false}; if (folderBrowser.ShowDialog() == true) { + HelloMyNameIsGame.Text = folderBrowser.SelectedPath.SubstringAfterLast('\\'); HelloGameMyNameIsDirectory.Text = folderBrowser.SelectedPath; } } From ba31c630739d280f48218fe4f9dea06666637f48 Mon Sep 17 00:00:00 2001 From: GMatrixGames Date: Tue, 21 May 2024 16:34:33 -0400 Subject: [PATCH 79/85] Fix exception when deleting saved games. --- CUE4Parse | 2 +- FModel/ViewModels/GameSelectorViewModel.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index d11401ea..61042149 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit d11401ea0ac61ca6dd32343b64e93095334e9689 +Subproject commit 61042149e8e2a4ea2bd34300b4f276cf6cec6ab8 diff --git a/FModel/ViewModels/GameSelectorViewModel.cs b/FModel/ViewModels/GameSelectorViewModel.cs index 1b18776f..af6653b9 100644 --- a/FModel/ViewModels/GameSelectorViewModel.cs +++ b/FModel/ViewModels/GameSelectorViewModel.cs @@ -47,7 +47,7 @@ public class GameSelectorViewModel : ViewModel set { SetProperty(ref _selectedDirectory, value); - UseCustomEGames = EnumerateUeGames().ElementAt(1).Contains(_selectedDirectory.UeVersion); + if (_selectedDirectory != null) UseCustomEGames = EnumerateUeGames().ElementAt(1).Contains(_selectedDirectory.UeVersion); } } From eb49b3c8533dd53d7d102ab6ec064d0c6a9e7312 Mon Sep 17 00:00:00 2001 From: Asval Date: Fri, 24 May 2024 16:42:15 +0200 Subject: [PATCH 80/85] HighlightedCheckBox --- CUE4Parse | 2 +- FModel/Settings/CustomDirectory.cs | 6 +-- FModel/ViewModels/CUE4ParseViewModel.cs | 2 + FModel/ViewModels/GameSelectorViewModel.cs | 4 +- FModel/Views/DirectorySelector.xaml | 3 +- FModel/Views/Resources/Resources.xaml | 25 +++++++++++ FModel/Views/SettingsView.xaml | 3 +- FModel/Views/Snooper/Renderer.cs | 48 ++++++++++++++++++++++ 8 files changed, 85 insertions(+), 8 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 61042149..52292cb8 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 61042149e8e2a4ea2bd34300b4f276cf6cec6ab8 +Subproject commit 52292cb88d4de990fbcf6e07fac883e3a8d13d4f diff --git a/FModel/Settings/CustomDirectory.cs b/FModel/Settings/CustomDirectory.cs index 471cb93f..14b4a388 100644 --- a/FModel/Settings/CustomDirectory.cs +++ b/FModel/Settings/CustomDirectory.cs @@ -13,9 +13,9 @@ public class CustomDirectory : ViewModel case "Fortnite [LIVE]": return new List { - new("Cosmetics", "FortniteGame/Content/Athena/Items/Cosmetics/"), - new("Emotes [AUDIO]", "FortniteGame/Content/Athena/Sounds/Emotes/"), - new("Music Packs [AUDIO]", "FortniteGame/Content/Athena/Sounds/MusicPacks/"), + new("Cosmetics", "FortniteGame/Plugins/GameFeatures/BRCosmetics/Content/Athena/Items/Cosmetics/"), + new("Emotes [AUDIO]", "FortniteGame/Plugins/GameFeatures/BRCosmetics/Content/Athena/Sounds/Emotes/"), + new("Music Packs [AUDIO]", "FortniteGame/Plugins/GameFeatures/BRCosmetics/Content/Athena/Sounds/MusicPacks/"), new("Weapons", "FortniteGame/Content/Athena/Items/Weapons/"), new("Strings", "FortniteGame/Content/Localization/") }; diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 11eac187..0eac6eea 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -42,6 +42,7 @@ using CUE4Parse.GameTypes.DBD.Encryption.Aes; using CUE4Parse.GameTypes.PAXDEI.Encryption.Aes; using CUE4Parse.GameTypes.NetEase.MAR.Encryption.Aes; using CUE4Parse.GameTypes.FSR.Encryption.Aes; +using CUE4Parse.UE4.Assets.Exports.Atom; using EpicManifestParser; using FModel.Creator; using FModel.Extensions; @@ -854,6 +855,7 @@ public class CUE4ParseViewModel : ViewModel return false; } case UWorld when isNone && UserSettings.Default.PreviewWorlds: + case UAtomModel when isNone && UserSettings.Default.PreviewStaticMeshes: case UStaticMesh when isNone && UserSettings.Default.PreviewStaticMeshes: case USkeletalMesh when isNone && UserSettings.Default.PreviewSkeletalMeshes: case USkeleton when isNone && UserSettings.Default.SaveSkeletonAsMesh: diff --git a/FModel/ViewModels/GameSelectorViewModel.cs b/FModel/ViewModels/GameSelectorViewModel.cs index af6653b9..273248b2 100644 --- a/FModel/ViewModels/GameSelectorViewModel.cs +++ b/FModel/ViewModels/GameSelectorViewModel.cs @@ -101,8 +101,8 @@ public class GameSelectorViewModel : ViewModel .GroupBy(value => (int)value == ((int)value & ~0xF)); private IEnumerable EnumerateDetectedGames() { - yield return GetUnrealEngineGame("Fortnite", "\\FortniteGame\\Content\\Paks", EGame.GAME_UE5_4); - yield return DirectorySettings.Default("Fortnite [LIVE]", Constants._FN_LIVE_TRIGGER, ue: EGame.GAME_UE5_4); + yield return GetUnrealEngineGame("Fortnite", "\\FortniteGame\\Content\\Paks", EGame.GAME_UE5_5); + yield return DirectorySettings.Default("Fortnite [LIVE]", Constants._FN_LIVE_TRIGGER, ue: EGame.GAME_UE5_5); yield return GetUnrealEngineGame("Pewee", "\\RogueCompany\\Content\\Paks", EGame.GAME_RogueCompany); yield return GetUnrealEngineGame("Rosemallow", "\\Indiana\\Content\\Paks", EGame.GAME_UE4_21); yield return GetUnrealEngineGame("Catnip", "\\OakGame\\Content\\Paks", EGame.GAME_Borderlands3); diff --git a/FModel/Views/DirectorySelector.xaml b/FModel/Views/DirectorySelector.xaml index a4fa8eff..badcfc23 100644 --- a/FModel/Views/DirectorySelector.xaml +++ b/FModel/Views/DirectorySelector.xaml @@ -80,7 +80,8 @@ + IsChecked="{Binding UseCustomEGames, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" + BorderBrush="White" Style="{StaticResource HighlightedCheckBox}" /> diff --git a/FModel/Views/Resources/Resources.xaml b/FModel/Views/Resources/Resources.xaml index a8516833..4cd0164e 100644 --- a/FModel/Views/Resources/Resources.xaml +++ b/FModel/Views/Resources/Resources.xaml @@ -80,6 +80,31 @@ + +