diff --git a/CUE4Parse b/CUE4Parse index 699dbd44..822dc9bf 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 699dbd44389e3543e7c09875e0a1b518b0dd05da +Subproject commit 822dc9bf39d793a4005c2eb9ba53721c10b791da diff --git a/FModel/Creator/CreatorPackage.cs b/FModel/Creator/CreatorPackage.cs index ee169896..7c2b154b 100644 --- a/FModel/Creator/CreatorPackage.cs +++ b/FModel/Creator/CreatorPackage.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using CUE4Parse.UE4.Assets.Exports; using FModel.Creator.Bases; @@ -30,7 +31,7 @@ public class CreatorPackage : IDisposable } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryConstructCreator(out UCreator creator) + public bool TryConstructCreator([MaybeNullWhen(false)] out UCreator creator) { switch (_exportType) { diff --git a/FModel/Extensions/CUE4ParseExtensions.cs b/FModel/Extensions/CUE4ParseExtensions.cs index 7254564e..463a668e 100644 --- a/FModel/Extensions/CUE4ParseExtensions.cs +++ b/FModel/Extensions/CUE4ParseExtensions.cs @@ -2,6 +2,8 @@ using CUE4Parse.FileProvider; using CUE4Parse.FileProvider.Objects; using CUE4Parse.UE4.Assets; +using CUE4Parse.UE4.Objects.UObject; +using FModel.Settings; namespace FModel.Extensions; @@ -9,35 +11,57 @@ public static class CUE4ParseExtensions { public class LoadPackageResult { + // more than 1 export per page currently break the inner package navigation feature + // if you have 1k exports per page, at page 2, you click on export index 932 + // it will find the export index 932 in the current page, which would realistically be 1932 + // fix would be to use InclusiveStart and ExclusiveEnd to determine the page the export index is in + // giving the document access to this would fix the issue and we could re-use Package instead of reloading it but it's quite a bit of work atm + private const int PaginationThreshold = 5000; private const int MaxExportPerPage = 1; public IPackage Package; + public int RequestedIndex; + public bool IsPaginated => Package.ExportMapLength >= PaginationThreshold; - public int InclusiveStart; + /// + /// index of the first export on the current page + /// this index is the starting point for additional data preview + /// + /// it can be >0 even if is false if we want to focus data preview on a specific export + /// in this case, we will display all exports but only the focused one will be checked for data preview + /// + public int InclusiveStart => Math.Max(0, RequestedIndex - RequestedIndex % MaxExportPerPage); + /// + /// last exclusive export index of the current page + /// public int ExclusiveEnd => IsPaginated ? Math.Min(InclusiveStart + MaxExportPerPage, Package.ExportMapLength) : Package.ExportMapLength; + public int PageSize => ExclusiveEnd - InclusiveStart; - private int CurrentPage => (InclusiveStart + 1) / MaxExportPerPage; - private int LastPage => Math.Max(1, (Package.ExportMapLength + MaxExportPerPage - 1) / MaxExportPerPage); - private int PageSize => ExclusiveEnd - InclusiveStart; + public string TabTitleExtra => IsPaginated ? $"Export{(PageSize > 1 ? "s" : "")} {InclusiveStart}{(PageSize > 1 ? $"-{ExclusiveEnd - 1}" : "")} of {Package.ExportMapLength - 1}" : null; - public string TabTitleExtra => IsPaginated ? $"Page {CurrentPage}/{LastPage}" : null; - - public object GetDisplayData(bool save = false) => !save ? Package.GetExports(InclusiveStart, PageSize) : Package.GetExports(); + /// + /// display all exports unless paginated + /// + /// if we save the data we will display all exports even if is true + /// + public object GetDisplayData(bool save = false) => !save && IsPaginated + ? Package.GetExports(InclusiveStart, PageSize) + : Package.GetExports(); } public static LoadPackageResult GetLoadPackageResult(this IFileProvider provider, GameFile file, string objectName = null) { var result = new LoadPackageResult { Package = provider.LoadPackage(file) }; - if (result.IsPaginated) + if (result.IsPaginated || (result.Package.HasFlags(EPackageFlags.PKG_ContainsMap) && UserSettings.Default.PreviewWorlds)) // focus on UWorld if it's a map we want to preview { - result.InclusiveStart = result.Package.GetExportIndex(file.NameWithoutExtension); + result.RequestedIndex = result.Package.GetExportIndex(file.NameWithoutExtension); if (objectName != null) { - result.InclusiveStart = int.TryParse(objectName, out var index) ? index : result.Package.GetExportIndex(objectName); + result.RequestedIndex = int.TryParse(objectName, out var index) ? index : result.Package.GetExportIndex(objectName); } } diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs index 23cdc2d2..4597519a 100644 --- a/FModel/MainWindow.xaml.cs +++ b/FModel/MainWindow.xaml.cs @@ -83,9 +83,9 @@ public partial class MainWindow ).ConfigureAwait(false); #if DEBUG - await _threadWorkerView.Begin(cancellationToken => - _applicationView.CUE4Parse.Extract(cancellationToken, - _applicationView.CUE4Parse.Provider["FortniteGame/Plugins/GameFeatures/BRMapCh6/Content/Maps/Hermes_Terrain.umap"])); + // await _threadWorkerView.Begin(cancellationToken => + // _applicationView.CUE4Parse.Extract(cancellationToken, + // _applicationView.CUE4Parse.Provider["FortniteGame/Plugins/GameFeatures/MeshCosmetics/Content/Jumpsuit/F_MED_Jumpsuit_Scrap/CO/CO_F_MED_Jumpsuit_Scrap.uasset"])); // await _threadWorkerView.Begin(cancellationToken => // _applicationView.CUE4Parse.Extract(cancellationToken, // "RED/Content/Chara/ABA/Costume01/Animation/Charaselect/body/stand_body01.uasset")); diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index eed30718..4a820a62 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -138,12 +138,12 @@ public class CUE4ParseViewModel : ViewModel { case Constants._FN_LIVE_TRIGGER: { - Provider = new StreamedFileProvider("FortniteLive", true, versionContainer); + Provider = new StreamedFileProvider("FortniteLive", versionContainer); break; } case Constants._VAL_LIVE_TRIGGER: { - Provider = new StreamedFileProvider("ValorantLive", true, versionContainer); + Provider = new StreamedFileProvider("ValorantLive", versionContainer); break; } default: @@ -155,12 +155,12 @@ public class CUE4ParseViewModel : ViewModel [ new(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\StateOfDecay2\\Saved\\Paks"), new(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\StateOfDecay2\\Saved\\DisabledPaks") - ], SearchOption.AllDirectories, true, versionContainer), + ], SearchOption.AllDirectories, versionContainer), "eFootball" => new DefaultFileProvider(new DirectoryInfo(gameDirectory), [ new(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\KONAMI\\eFootball\\ST\\Download") - ], SearchOption.AllDirectories, true, versionContainer), - _ => new DefaultFileProvider(gameDirectory, SearchOption.AllDirectories, true, versionContainer) + ], SearchOption.AllDirectories, versionContainer), + _ => new DefaultFileProvider(gameDirectory, SearchOption.AllDirectories, versionContainer) }; break; diff --git a/FModel/Views/Resources/Controls/Aed/GamePathVisualLineText.cs b/FModel/Views/Resources/Controls/Aed/GamePathVisualLineText.cs index d642a47e..ea19954c 100644 --- a/FModel/Views/Resources/Controls/Aed/GamePathVisualLineText.cs +++ b/FModel/Views/Resources/Controls/Aed/GamePathVisualLineText.cs @@ -70,7 +70,7 @@ public class GamePathVisualLineText : VisualLineText { var obj = gamePath.SubstringAfterLast('.'); var package = gamePath.SubstringBeforeLast('.'); - var fullPath = _applicationView.CUE4Parse.Provider.FixPath(package, StringComparison.Ordinal); + var fullPath = _applicationView.CUE4Parse.Provider.FixPath(package); var firstLine = a.ParentVisualLine.Document.GetLineByNumber(2); if (a.ParentVisualLine.Document.FileName.Equals(fullPath.SubstringBeforeLast('.'), StringComparison.OrdinalIgnoreCase) && diff --git a/FModel/Views/Resources/Controls/ImagePopout.xaml b/FModel/Views/Resources/Controls/ImagePopout.xaml index 31bf8301..b28330aa 100644 --- a/FModel/Views/Resources/Controls/ImagePopout.xaml +++ b/FModel/Views/Resources/Controls/ImagePopout.xaml @@ -15,7 +15,9 @@ - - + + + + diff --git a/FModel/Views/Snooper/Shading/Material.cs b/FModel/Views/Snooper/Shading/Material.cs index 05d7e354..a3e58d49 100644 --- a/FModel/Views/Snooper/Shading/Material.cs +++ b/FModel/Views/Snooper/Shading/Material.cs @@ -80,7 +80,7 @@ public class Material : IDisposable Normals = [new Texture(new FLinearColor(0.5f, 0.5f, 1f, 1f))]; SpecularMasks = [new Texture(new FLinearColor(1f, 0.5f, 0.5f, 1f))]; Emissive = new Texture[1]; - DiffuseColor = [Vector4.One]; + DiffuseColor = FillColors(1, Diffuse, CMaterialParams2.DiffuseColors, Vector4.One); EmissiveColor = [Vector4.One]; } else