From 7e56858bc6439a0a8499e71433c4416454da3a8c Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Thu, 23 Feb 2023 15:20:51 +0100 Subject: [PATCH] Change handling of associated shpk for material. --- Penumbra.GameData/Files/MtrlFile.cs | 4 +- .../UI/Classes/ModEditWindow.Materials.cs | 31 ++++++++++- Penumbra/UI/Classes/ModEditWindow.cs | 55 ++++++++----------- 3 files changed, 53 insertions(+), 37 deletions(-) diff --git a/Penumbra.GameData/Files/MtrlFile.cs b/Penumbra.GameData/Files/MtrlFile.cs index 6a51a39b..f890f539 100644 --- a/Penumbra.GameData/Files/MtrlFile.cs +++ b/Penumbra.GameData/Files/MtrlFile.cs @@ -94,7 +94,7 @@ public partial class MtrlFile : IWritable return samplers; } - public MtrlFile(byte[] data, Func? loadAssociatedShpk = null) + public MtrlFile(byte[] data) { using var stream = new MemoryStream(data); using var r = new BinaryReader(stream); @@ -133,8 +133,6 @@ public partial class MtrlFile : IWritable ShaderPackage.Name = UseOffset(strings, shaderPackageNameOffset); - AssociatedShpk = loadAssociatedShpk?.Invoke(ShaderPackage.Name); - AdditionalData = r.ReadBytes(additionalDataSize); for (var i = 0; i < ColorSets.Length; ++i) { diff --git a/Penumbra/UI/Classes/ModEditWindow.Materials.cs b/Penumbra/UI/Classes/ModEditWindow.Materials.cs index d9354807..f88fa5cf 100644 --- a/Penumbra/UI/Classes/ModEditWindow.Materials.cs +++ b/Penumbra/UI/Classes/ModEditWindow.Materials.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; using System.Numerics; @@ -17,7 +16,6 @@ using Penumbra.GameData.Files; using Penumbra.String.Classes; using Penumbra.String.Functions; using Penumbra.Util; -using static Penumbra.GameData.Files.ShpkFile; namespace Penumbra.UI.Classes; @@ -31,6 +29,35 @@ public partial class ModEditWindow private uint _materialNewConstantId = 0; private uint _materialNewSamplerId = 0; + /// Load the material with an associated shader package if it can be found. See . + private MtrlFile LoadMtrl( byte[] bytes ) + { + var mtrl = new MtrlFile( bytes ); + if( !Utf8GamePath.FromString( $"shader/sm5/shpk/{mtrl.ShaderPackage.Name}", out var shpkPath, true ) ) + { + return mtrl; + } + + try + { + var shpkFilePath = FindBestMatch( shpkPath ); + var data = shpkFilePath.IsRooted + ? File.ReadAllBytes( shpkFilePath.FullName ) + : Dalamud.GameData.GetFile( shpkFilePath.FullName )?.Data; + if( data?.Length > 0 ) + { + mtrl.AssociatedShpk = new ShpkFile( data ); + } + } + catch( Exception e ) + { + Penumbra.Log.Debug( $"Could not parse associated file {shpkPath} to Shpk:\n{e}" ); + mtrl.AssociatedShpk = null; + } + + return mtrl; + } + private bool DrawMaterialPanel( MtrlFile file, bool disabled ) { var ret = DrawMaterialTextureChange( file, disabled ); diff --git a/Penumbra/UI/Classes/ModEditWindow.cs b/Penumbra/UI/Classes/ModEditWindow.cs index 5e5c514e..a3de3c34 100644 --- a/Penumbra/UI/Classes/ModEditWindow.cs +++ b/Penumbra/UI/Classes/ModEditWindow.cs @@ -535,45 +535,36 @@ public partial class ModEditWindow : Window, IDisposable ImGui.InputTextWithHint( "##swapValue", "... instead of this file.", ref _newSwapKey, Utf8GamePath.MaxGamePathLength ); } - // FIXME this probably doesn't belong here - private T? LoadAssociatedFile( string gamePath, Func< byte[], T? > parse ) + /// + /// Find the best matching associated file for a given path. + /// + /// + /// Tries to resolve from the current collection first and chooses the currently resolved file if any exists. + /// If none exists, goes through all options in the currently selected mod (if any) in order of priority and resolves in them. + /// If no redirection is found in either of those options, returns the original path. + /// + private FullPath FindBestMatch( Utf8GamePath path ) { - var defaultFiles = _mod?.Default?.Files; - if( defaultFiles != null ) + var currentFile = Penumbra.CollectionManager.Current.ResolvePath( path ); + if( currentFile != null ) { - if( Utf8GamePath.FromString( gamePath, out var utf8Path, true ) ) + return currentFile.Value; + } + + if( _mod != null ) + { + foreach( var option in _mod.Groups.OrderByDescending( g => g.Priority ) + .SelectMany( g => g.WithIndex().OrderByDescending( o => g.OptionPriority( o.Index ) ).Select( g => g.Value ) ) + .Append( _mod.Default ) ) { - try + if( option.Files.TryGetValue( path, out var value ) || option.FileSwaps.TryGetValue( path, out value ) ) { - if (defaultFiles.TryGetValue( utf8Path, out var fsPath )) - { - return parse( File.ReadAllBytes( fsPath.FullName ) ); - } - } - finally - { - utf8Path.Dispose(); + return value; } } } - var file = Dalamud.GameData.GetFile( gamePath )?.Data; - return file == null ? default : parse( file ); - } - - // FIXME neither does this - private ShpkFile? LoadAssociatedShpk( string shaderName ) - { - var path = $"shader/sm5/shpk/{shaderName}"; - try - { - return LoadAssociatedFile( path, file => new ShpkFile( file ) ); - } - catch( Exception e ) - { - Penumbra.Log.Debug( $"Could not parse associated file {path} to Shpk:\n{e}" ); - return null; - } + return new FullPath( path ); } public ModEditWindow() @@ -583,7 +574,7 @@ public partial class ModEditWindow : Window, IDisposable () => _editor?.MtrlFiles ?? Array.Empty< Editor.FileRegistry >(), DrawMaterialPanel, () => _mod?.ModPath.FullName ?? string.Empty, - bytes => new MtrlFile( bytes, LoadAssociatedShpk ) ); + LoadMtrl ); _modelTab = new FileEditor< MdlFile >( "Models", ".mdl", () => _editor?.MdlFiles ?? Array.Empty< Editor.FileRegistry >(), DrawModelPanel,