Change handling of associated shpk for material.

This commit is contained in:
Ottermandias 2023-02-23 15:20:51 +01:00
parent a2b62a8b6a
commit 7e56858bc6
3 changed files with 53 additions and 37 deletions

View file

@ -94,7 +94,7 @@ public partial class MtrlFile : IWritable
return samplers;
}
public MtrlFile(byte[] data, Func<string, ShpkFile?>? 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)
{

View file

@ -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;
/// <summary> Load the material with an associated shader package if it can be found. See <seealso cref="FindBestMatch"/>. </summary>
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 );

View file

@ -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<T>( string gamePath, Func< byte[], T? > parse )
/// <summary>
/// Find the best matching associated file for a given path.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
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,