mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-01-02 13:53:42 +01:00
More Mtrl and ShPk editing (thanks @aers)
This commit is contained in:
parent
0c17892f03
commit
33231959b2
4 changed files with 648 additions and 247 deletions
|
|
@ -10,14 +10,13 @@ using Dalamud.Interface.ImGuiFileDialog;
|
|||
using Dalamud.Interface.Internal.Notifications;
|
||||
using ImGuiNET;
|
||||
using Lumina.Data.Parsing;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Files;
|
||||
using Penumbra.String.Classes;
|
||||
using Penumbra.String.Functions;
|
||||
using Penumbra.Util;
|
||||
using static OtterGui.Raii.ImRaii;
|
||||
using static Penumbra.GameData.Files.ShpkFile;
|
||||
|
||||
namespace Penumbra.UI.Classes;
|
||||
|
||||
|
|
@ -27,6 +26,7 @@ public partial class ModEditWindow
|
|||
|
||||
private readonly FileDialogManager _materialFileDialog = ConfigWindow.SetupFileManager();
|
||||
|
||||
private uint _materialNewKeyId = 0;
|
||||
private uint _materialNewConstantId = 0;
|
||||
private uint _materialNewSamplerId = 0;
|
||||
|
||||
|
|
@ -191,48 +191,165 @@ public partial class ModEditWindow
|
|||
ret = true;
|
||||
}
|
||||
ImRaii.TreeNode( $"Has associated ShPk file (for advanced editing): {( file.AssociatedShpk != null ? "Yes" : "No" )}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
if( !disabled && ImGui.Button( "Associate modded ShPk file" ) )
|
||||
if( !disabled )
|
||||
{
|
||||
_materialFileDialog.OpenFileDialog( $"Associate modded ShPk file...", ".shpk", ( success, name ) =>
|
||||
if( ImGui.Button( "Associate custom ShPk file" ) )
|
||||
{
|
||||
if( !success )
|
||||
_materialFileDialog.OpenFileDialog( $"Associate custom ShPk file...", ".shpk", ( success, name ) =>
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( !success )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
file.AssociatedShpk = new ShpkFile( File.ReadAllBytes( name ) );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
Penumbra.Log.Error( $"Could not load ShPk file {name}:\n{e}" );
|
||||
ChatUtil.NotificationMessage( $"Could not load {Path.GetFileName( name )}:\n{e.Message}", "Penumbra Advanced Editing", NotificationType.Error );
|
||||
return;
|
||||
}
|
||||
ChatUtil.NotificationMessage( $"Advanced Shader Resources for this material will now be based on the supplied {Path.GetFileName( name )}", "Penumbra Advanced Editing", NotificationType.Success );
|
||||
} );
|
||||
}
|
||||
ImGui.SameLine();
|
||||
if( ImGui.Button( "Associate default ShPk file" ) )
|
||||
{
|
||||
var shpk = LoadAssociatedShpk( file.ShaderPackage.Name );
|
||||
if( null != shpk )
|
||||
{
|
||||
file.AssociatedShpk = new ShpkFile( File.ReadAllBytes( name ) );
|
||||
file.AssociatedShpk = shpk;
|
||||
ChatUtil.NotificationMessage( $"Advanced Shader Resources for this material will now be based on the default {file.ShaderPackage.Name}", "Penumbra Advanced Editing", NotificationType.Success );
|
||||
}
|
||||
catch( Exception e )
|
||||
else
|
||||
{
|
||||
Penumbra.Log.Error( $"Could not load ShPk file {name}:\n{e}" );
|
||||
ChatUtil.NotificationMessage( $"Could not load {Path.GetFileName( name )}:\n{e.Message}", "Penumbra Advanced Editing", NotificationType.Error );
|
||||
return;
|
||||
ChatUtil.NotificationMessage( $"Could not load default {file.ShaderPackage.Name}", "Penumbra Advanced Editing", NotificationType.Error );
|
||||
}
|
||||
ChatUtil.NotificationMessage( $"Advanced Shader Resources for this material will now be based on the supplied {Path.GetFileName( name )}", "Penumbra Advanced Editing", NotificationType.Success );
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
if( file.ShaderPackage.ShaderKeys.Length > 0 )
|
||||
if( file.ShaderPackage.ShaderKeys.Length > 0 || !disabled && file.AssociatedShpk != null && file.AssociatedShpk.MaterialKeys.Length > 0 )
|
||||
{
|
||||
using var t = ImRaii.TreeNode( "Shader Keys" );
|
||||
if( t )
|
||||
{
|
||||
var definedKeys = new HashSet< uint >();
|
||||
|
||||
foreach( var (key, idx) in file.ShaderPackage.ShaderKeys.WithIndex() )
|
||||
{
|
||||
using var t2 = ImRaii.TreeNode( $"Shader Key #{idx}", file.ShaderPackage.ShaderKeys.Length == 1 ? ImGuiTreeNodeFlags.DefaultOpen : 0 );
|
||||
definedKeys.Add( key.Category );
|
||||
using var t2 = ImRaii.TreeNode( $"#{idx}: 0x{key.Category:X8} = 0x{key.Value:X8}###{idx}: 0x{key.Category:X8}", disabled ? ImGuiTreeNodeFlags.Leaf : 0 );
|
||||
if( t2 )
|
||||
{
|
||||
ImRaii.TreeNode( $"Category: 0x{key.Category:X8} ({key.Category})", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
ImRaii.TreeNode( $"Value: 0x{key.Value:X8} ({key.Value})", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
if( !disabled )
|
||||
{
|
||||
var shpkKey = file.AssociatedShpk?.GetMaterialKeyById( key.Category );
|
||||
if( shpkKey.HasValue )
|
||||
{
|
||||
ImGui.SetNextItemWidth( ImGuiHelpers.GlobalScale * 150.0f );
|
||||
using var c = ImRaii.Combo( "Value", $"0x{key.Value:X8}" );
|
||||
if( c )
|
||||
{
|
||||
foreach( var value in shpkKey.Value.Values )
|
||||
{
|
||||
if( ImGui.Selectable( $"0x{value:X8}", value == key.Value ) )
|
||||
{
|
||||
file.ShaderPackage.ShaderKeys[idx].Value = value;
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if( ImGui.Button( "Remove Key" ) )
|
||||
{
|
||||
ArrayRemove( ref file.ShaderPackage.ShaderKeys, idx );
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !disabled && file.AssociatedShpk != null )
|
||||
{
|
||||
var missingKeys = file.AssociatedShpk.MaterialKeys.Where( key => !definedKeys.Contains( key.Id ) ).ToArray();
|
||||
if( missingKeys.Length > 0 )
|
||||
{
|
||||
var selectedKey = Array.Find( missingKeys, key => key.Id == _materialNewKeyId );
|
||||
if( Array.IndexOf( missingKeys, selectedKey ) < 0 )
|
||||
{
|
||||
selectedKey = missingKeys[0];
|
||||
_materialNewKeyId = selectedKey.Id;
|
||||
}
|
||||
ImGui.SetNextItemWidth( ImGuiHelpers.GlobalScale * 150.0f );
|
||||
using( var c = ImRaii.Combo( "##NewConstantId", $"ID: 0x{selectedKey.Id:X8}" ) )
|
||||
{
|
||||
if( c )
|
||||
{
|
||||
foreach( var key in missingKeys )
|
||||
{
|
||||
if( ImGui.Selectable( $"ID: 0x{key.Id:X8}", key.Id == _materialNewKeyId ) )
|
||||
{
|
||||
selectedKey = key;
|
||||
_materialNewKeyId = key.Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui.SameLine();
|
||||
if( ImGui.Button( "Add Key" ) )
|
||||
{
|
||||
ArrayAdd( ref file.ShaderPackage.ShaderKeys, new ShaderKey
|
||||
{
|
||||
Category = selectedKey.Id,
|
||||
Value = selectedKey.DefaultValue,
|
||||
} );
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( file.AssociatedShpk != null )
|
||||
{
|
||||
var definedKeys = new Dictionary< uint, uint >();
|
||||
foreach( var key in file.ShaderPackage.ShaderKeys )
|
||||
{
|
||||
definedKeys[key.Category] = key.Value;
|
||||
}
|
||||
var materialKeys = Array.ConvertAll(file.AssociatedShpk.MaterialKeys, key =>
|
||||
{
|
||||
if( definedKeys.TryGetValue( key.Id, out var value ) )
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return key.DefaultValue;
|
||||
}
|
||||
} );
|
||||
var vertexShaders = new IndexSet( file.AssociatedShpk.VertexShaders.Length, false );
|
||||
var pixelShaders = new IndexSet( file.AssociatedShpk.PixelShaders.Length, false );
|
||||
foreach( var node in file.AssociatedShpk.Nodes )
|
||||
{
|
||||
if( node.MaterialKeys.WithIndex().All( key => key.Value == materialKeys[key.Index] ) )
|
||||
{
|
||||
foreach( var pass in node.Passes )
|
||||
{
|
||||
vertexShaders.Add( ( int )pass.VertexShader );
|
||||
pixelShaders.Add( ( int )pass.PixelShader );
|
||||
}
|
||||
}
|
||||
}
|
||||
ImRaii.TreeNode( $"Vertex Shaders: {( vertexShaders.Count > 0 ? string.Join( ", ", vertexShaders.Select( i => $"#{i}" ) ) : "???" )}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
ImRaii.TreeNode( $"Pixel Shaders: {( pixelShaders.Count > 0 ? string.Join( ", ", pixelShaders.Select( i => $"#{i}" ) ) : "???" )}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
}
|
||||
|
||||
if( file.ShaderPackage.Constants.Length > 0 || file.ShaderPackage.ShaderValues.Length > 0
|
||||
|| file.AssociatedShpk != null && file.AssociatedShpk.Constants.Length > 0 )
|
||||
|| !disabled && file.AssociatedShpk != null && file.AssociatedShpk.Constants.Length > 0 )
|
||||
{
|
||||
var materialParams = file.AssociatedShpk?.GetConstantById( ShpkFile.MaterialParamsConstantId );
|
||||
|
||||
|
|
@ -352,7 +469,7 @@ public partial class ModEditWindow
|
|||
foreach( var constant in missingConstants )
|
||||
{
|
||||
var (constantName, _) = MaterialParamRangeName( materialParams?.Name ?? "", constant.ByteOffset >> 2, constant.ByteSize >> 2 );
|
||||
if( ImGui.Selectable( $"{constantName} (ID: 0x{constant.Id:X8})" ) )
|
||||
if( ImGui.Selectable( $"{constantName} (ID: 0x{constant.Id:X8})", constant.Id == _materialNewConstantId ) )
|
||||
{
|
||||
selectedConstant = constant;
|
||||
_materialNewConstantId = constant.Id;
|
||||
|
|
@ -378,7 +495,7 @@ public partial class ModEditWindow
|
|||
}
|
||||
|
||||
if( file.ShaderPackage.Samplers.Length > 0 || file.Textures.Length > 0
|
||||
|| file.AssociatedShpk != null && file.AssociatedShpk.Samplers.Any( sampler => sampler.Slot == 2 ) )
|
||||
|| !disabled && file.AssociatedShpk != null && file.AssociatedShpk.Samplers.Any( sampler => sampler.Slot == 2 ) )
|
||||
{
|
||||
using var t = ImRaii.TreeNode( "Samplers" );
|
||||
if( t )
|
||||
|
|
@ -472,7 +589,7 @@ public partial class ModEditWindow
|
|||
{
|
||||
foreach( var sampler in missingSamplers )
|
||||
{
|
||||
if( ImGui.Selectable( $"{sampler.Name} (ID: 0x{sampler.Id:X8})" ) )
|
||||
if( ImGui.Selectable( $"{sampler.Name} (ID: 0x{sampler.Id:X8})", sampler.Id == _materialNewSamplerId ) )
|
||||
{
|
||||
selectedSampler = sampler;
|
||||
_materialNewSamplerId = sampler.Id;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ using Penumbra.GameData.Files;
|
|||
using Penumbra.Util;
|
||||
using Lumina.Data.Parsing;
|
||||
using static OtterGui.Raii.ImRaii;
|
||||
using static Penumbra.GameData.Files.ShpkFile;
|
||||
|
||||
namespace Penumbra.UI.Classes;
|
||||
|
||||
|
|
@ -76,7 +77,7 @@ public partial class ModEditWindow
|
|||
using var t = ImRaii.TreeNode( $"{objectName} #{idx}" );
|
||||
if( t )
|
||||
{
|
||||
if( ImGui.Button( $"Export Shader Blob ({shader.Blob.Length} bytes)" ) )
|
||||
if( ImGui.Button( $"Export Shader Program Blob ({shader.Blob.Length} bytes)" ) )
|
||||
{
|
||||
var extension = file.DirectXVersion switch
|
||||
{
|
||||
|
|
@ -86,7 +87,7 @@ public partial class ModEditWindow
|
|||
};
|
||||
var defaultName = new string( objectName.Where( char.IsUpper ).ToArray() ).ToLower() + idx.ToString();
|
||||
var blob = shader.Blob;
|
||||
_shaderPackageFileDialog.SaveFileDialog( $"Export {objectName} #{idx} Blob to...", extension, defaultName, extension, ( success, name ) =>
|
||||
_shaderPackageFileDialog.SaveFileDialog( $"Export {objectName} #{idx} Program Blob to...", extension, defaultName, extension, ( success, name ) =>
|
||||
{
|
||||
if( !success )
|
||||
{
|
||||
|
|
@ -103,15 +104,15 @@ public partial class ModEditWindow
|
|||
ChatUtil.NotificationMessage( $"Could not export {defaultName}{extension} to {Path.GetFileName( name )}:\n{e.Message}", "Penumbra Advanced Editing", NotificationType.Error );
|
||||
return;
|
||||
}
|
||||
ChatUtil.NotificationMessage( $"Shader Blob {defaultName}{extension} exported successfully to {Path.GetFileName( name )}", "Penumbra Advanced Editing", NotificationType.Success );
|
||||
ChatUtil.NotificationMessage( $"Shader Program Blob {defaultName}{extension} exported successfully to {Path.GetFileName( name )}", "Penumbra Advanced Editing", NotificationType.Success );
|
||||
} );
|
||||
}
|
||||
if( !disabled )
|
||||
{
|
||||
ImGui.SameLine();
|
||||
if( ImGui.Button( "Replace Shader Blob" ) )
|
||||
if( ImGui.Button( "Replace Shader Program Blob" ) )
|
||||
{
|
||||
_shaderPackageFileDialog.OpenFileDialog( $"Replace {objectName} #{idx} Blob...", "Shader Blobs{.o,.cso,.dxbc,.dxil}", ( success, name ) =>
|
||||
_shaderPackageFileDialog.OpenFileDialog( $"Replace {objectName} #{idx} Program Blob...", "Shader Program Blobs{.o,.cso,.dxbc,.dxil}", ( success, name ) =>
|
||||
{
|
||||
if( !success )
|
||||
{
|
||||
|
|
@ -146,10 +147,9 @@ public partial class ModEditWindow
|
|||
}
|
||||
}
|
||||
|
||||
ret |= DrawShaderPackageResourceArray( "Constant Buffers", "slot", true, shader.Constants, disabled );
|
||||
ret |= DrawShaderPackageResourceArray( "Samplers", "slot", false, shader.Samplers, disabled );
|
||||
ret |= DrawShaderPackageResourceArray( "Unknown Type X Resources", "slot", true, shader.UnknownX, disabled );
|
||||
ret |= DrawShaderPackageResourceArray( "Unknown Type Y Resources", "slot", true, shader.UnknownY, disabled );
|
||||
ret |= DrawShaderPackageResourceArray( "Constant Buffers", "slot", true, shader.Constants, true );
|
||||
ret |= DrawShaderPackageResourceArray( "Samplers", "slot", false, shader.Samplers, true );
|
||||
ret |= DrawShaderPackageResourceArray( "Unordered Access Views", "slot", true, shader.UAVs, true );
|
||||
|
||||
if( shader.AdditionalHeader.Length > 0 )
|
||||
{
|
||||
|
|
@ -160,7 +160,7 @@ public partial class ModEditWindow
|
|||
}
|
||||
}
|
||||
|
||||
using( var t2 = ImRaii.TreeNode( "Raw Disassembly" ) )
|
||||
using( var t2 = ImRaii.TreeNode( "Raw Program Disassembly" ) )
|
||||
{
|
||||
if( t2 )
|
||||
{
|
||||
|
|
@ -326,7 +326,7 @@ public partial class ModEditWindow
|
|||
foreach( var start in starts )
|
||||
{
|
||||
var name = MaterialParamName( false, start )!;
|
||||
if( ImGui.Selectable( $"{materialParams?.Name ?? ""}{name}" ) )
|
||||
if( ImGui.Selectable( $"{materialParams?.Name ?? ""}{name}", start == _shaderPackageNewMaterialParamStart ) )
|
||||
{
|
||||
_shaderPackageNewMaterialParamStart = ( ushort )start;
|
||||
}
|
||||
|
|
@ -352,7 +352,7 @@ public partial class ModEditWindow
|
|||
foreach( var end in ends )
|
||||
{
|
||||
var name = MaterialParamName( false, end )!;
|
||||
if( ImGui.Selectable( $"{materialParams?.Name ?? ""}{name}" ) )
|
||||
if( ImGui.Selectable( $"{materialParams?.Name ?? ""}{name}", end == _shaderPackageNewMaterialParamEnd ) )
|
||||
{
|
||||
_shaderPackageNewMaterialParamEnd = ( ushort )end;
|
||||
}
|
||||
|
|
@ -390,7 +390,7 @@ public partial class ModEditWindow
|
|||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawShaderPackageResourceArray( string arrayName, string slotLabel, bool withSize, ShpkFile.Resource[] resources, bool _ )
|
||||
private static bool DrawShaderPackageResourceArray( string arrayName, string slotLabel, bool withSize, ShpkFile.Resource[] resources, bool disabled )
|
||||
{
|
||||
if( resources.Length == 0 )
|
||||
{
|
||||
|
|
@ -407,65 +407,85 @@ public partial class ModEditWindow
|
|||
|
||||
foreach( var (buf, idx) in resources.WithIndex() )
|
||||
{
|
||||
using var t2 = ImRaii.TreeNode( $"#{idx}: {buf.Name} (ID: 0x{buf.Id:X8}), {slotLabel}: {buf.Slot}" + ( withSize ? $", size: {buf.Size} registers" : string.Empty ), ( buf.Used != null ) ? 0 : ImGuiTreeNodeFlags.Leaf );
|
||||
using var t2 = ImRaii.TreeNode( $"#{idx}: {buf.Name} (ID: 0x{buf.Id:X8}), {slotLabel}: {buf.Slot}" + ( withSize ? $", size: {buf.Size} registers###{idx}: {buf.Name} (ID: 0x{buf.Id:X8})" : string.Empty ), ( !disabled || buf.Used != null ) ? 0 : ImGuiTreeNodeFlags.Leaf );
|
||||
if( t2 )
|
||||
{
|
||||
var used = new List< string >();
|
||||
if( withSize )
|
||||
if( !disabled )
|
||||
{
|
||||
foreach( var (components, i) in ( buf.Used ?? Array.Empty<DisassembledShader.VectorComponents>() ).WithIndex() )
|
||||
// FIXME this probably doesn't belong here
|
||||
static unsafe bool InputUInt16( string label, ref ushort v, ImGuiInputTextFlags flags )
|
||||
{
|
||||
switch( components )
|
||||
fixed( ushort* v2 = &v )
|
||||
{
|
||||
return ImGui.InputScalar( label, ImGuiDataType.U16, new nint( v2 ), nint.Zero, nint.Zero, "%hu", flags );
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.SetNextItemWidth( ImGuiHelpers.GlobalScale * 150.0f );
|
||||
if( InputUInt16( $"{char.ToUpper( slotLabel[0] )}{slotLabel[1..].ToLower()}", ref resources[idx].Slot, ImGuiInputTextFlags.None ) )
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
if( buf.Used != null )
|
||||
{
|
||||
var used = new List<string>();
|
||||
if( withSize )
|
||||
{
|
||||
foreach( var (components, i) in ( buf.Used ?? Array.Empty<DisassembledShader.VectorComponents>() ).WithIndex() )
|
||||
{
|
||||
switch( components )
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case DisassembledShader.VectorComponents.All:
|
||||
used.Add( $"[{i}]" );
|
||||
break;
|
||||
default:
|
||||
used.Add( $"[{i}].{new string( components.ToString().Where( char.IsUpper ).ToArray() ).ToLower()}" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch( buf.UsedDynamically ?? 0 )
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case DisassembledShader.VectorComponents.All:
|
||||
used.Add( $"[{i}]" );
|
||||
used.Add( "[*]" );
|
||||
break;
|
||||
default:
|
||||
used.Add( $"[{i}].{new string( components.ToString().Where( char.IsUpper ).ToArray() ).ToLower()}" );
|
||||
used.Add( $"[*].{new string( buf.UsedDynamically!.Value.ToString().Where( char.IsUpper ).ToArray() ).ToLower()}" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch( buf.UsedDynamically ?? 0 )
|
||||
else
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case DisassembledShader.VectorComponents.All:
|
||||
used.Add( "[*]" );
|
||||
break;
|
||||
default:
|
||||
used.Add( $"[*].{new string( buf.UsedDynamically!.Value.ToString().Where( char.IsUpper ).ToArray() ).ToLower()}" );
|
||||
break;
|
||||
var components = ( ( buf.Used != null && buf.Used.Length > 0 ) ? buf.Used[0] : 0 ) | ( buf.UsedDynamically ?? 0 );
|
||||
if( ( components & DisassembledShader.VectorComponents.X ) != 0 )
|
||||
{
|
||||
used.Add( "Red" );
|
||||
}
|
||||
if( ( components & DisassembledShader.VectorComponents.Y ) != 0 )
|
||||
{
|
||||
used.Add( "Green" );
|
||||
}
|
||||
if( ( components & DisassembledShader.VectorComponents.Z ) != 0 )
|
||||
{
|
||||
used.Add( "Blue" );
|
||||
}
|
||||
if( ( components & DisassembledShader.VectorComponents.W ) != 0 )
|
||||
{
|
||||
used.Add( "Alpha" );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var components = ( ( buf.Used != null && buf.Used.Length > 0 ) ? buf.Used[0] : 0 ) | (buf.UsedDynamically ?? 0);
|
||||
if( ( components & DisassembledShader.VectorComponents.X ) != 0 )
|
||||
if( used.Count > 0 )
|
||||
{
|
||||
used.Add( "Red" );
|
||||
ImRaii.TreeNode( $"Used: {string.Join( ", ", used )}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
}
|
||||
if( ( components & DisassembledShader.VectorComponents.Y ) != 0 )
|
||||
else
|
||||
{
|
||||
used.Add( "Green" );
|
||||
ImRaii.TreeNode( "Unused", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
}
|
||||
if( ( components & DisassembledShader.VectorComponents.Z ) != 0 )
|
||||
{
|
||||
used.Add( "Blue" );
|
||||
}
|
||||
if( ( components & DisassembledShader.VectorComponents.W ) != 0 )
|
||||
{
|
||||
used.Add( "Alpha" );
|
||||
}
|
||||
}
|
||||
if( used.Count > 0 )
|
||||
{
|
||||
ImRaii.TreeNode( $"Used: {string.Join(", ", used)}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
ImRaii.TreeNode( "Unused", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -482,56 +502,91 @@ public partial class ModEditWindow
|
|||
return false;
|
||||
}
|
||||
|
||||
ImRaii.TreeNode( $"Version: 0x{file.Version:X8}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
|
||||
ret |= DrawShaderPackageResourceArray( "Constant Buffers", "type", true, file.Constants, disabled );
|
||||
ret |= DrawShaderPackageResourceArray( "Samplers", "type", false, file.Samplers, disabled );
|
||||
ret |= DrawShaderPackageResourceArray( "Unordered Access Views", "type", false, file.UAVs, disabled );
|
||||
|
||||
if( file.UnknownA.Length > 0 )
|
||||
static bool DrawKeyArray( string arrayName, bool withId, ShpkFile.Key[] keys, bool _ )
|
||||
{
|
||||
using var t = ImRaii.TreeNode( $"Unknown Type A Structures ({file.UnknownA.Length})" );
|
||||
if( keys.Length == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
using var t = ImRaii.TreeNode( arrayName );
|
||||
if( !t )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach( var (key, idx) in keys.WithIndex() )
|
||||
{
|
||||
using var t2 = ImRaii.TreeNode( withId ? $"#{idx}: ID: 0x{key.Id:X8}" : $"#{idx}" );
|
||||
if( t2 )
|
||||
{
|
||||
ImRaii.TreeNode( $"Default Value: 0x{key.DefaultValue:X8}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
ImRaii.TreeNode( $"Known Values: {string.Join( ", ", Array.ConvertAll( key.Values, value => $"0x{value:X8}" ) )}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ret |= DrawKeyArray( "System Keys", true, file.SystemKeys, disabled );
|
||||
ret |= DrawKeyArray( "Scene Keys", true, file.SceneKeys, disabled );
|
||||
ret |= DrawKeyArray( "Material Keys", true, file.MaterialKeys, disabled );
|
||||
ret |= DrawKeyArray( "Sub-View Keys", false, file.SubViewKeys, disabled );
|
||||
|
||||
if( file.Nodes.Length > 0 )
|
||||
{
|
||||
using var t = ImRaii.TreeNode( $"Nodes ({file.Nodes.Length})" );
|
||||
if( t )
|
||||
{
|
||||
foreach( var (unk, idx) in file.UnknownA.WithIndex() )
|
||||
foreach( var (node, idx) in file.Nodes.WithIndex() )
|
||||
{
|
||||
ImRaii.TreeNode( $"#{idx}: 0x{unk.Item1:X8}, 0x{unk.Item2:X8}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
using var t2 = ImRaii.TreeNode( $"#{idx}: ID: 0x{node.Id:X8}" );
|
||||
if( t2 )
|
||||
{
|
||||
foreach( var (key, keyIdx) in node.SystemKeys.WithIndex() )
|
||||
{
|
||||
ImRaii.TreeNode( $"System Key 0x{file.SystemKeys[keyIdx].Id:X8} = 0x{key:X8}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
}
|
||||
foreach( var (key, keyIdx) in node.SceneKeys.WithIndex() )
|
||||
{
|
||||
ImRaii.TreeNode( $"Scene Key 0x{file.SceneKeys[keyIdx].Id:X8} = 0x{key:X8}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
}
|
||||
foreach( var (key, keyIdx) in node.MaterialKeys.WithIndex() )
|
||||
{
|
||||
ImRaii.TreeNode( $"Material Key 0x{file.MaterialKeys[keyIdx].Id:X8} = 0x{key:X8}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
}
|
||||
foreach( var (key, keyIdx) in node.SubViewKeys.WithIndex() )
|
||||
{
|
||||
ImRaii.TreeNode( $"Sub-View Key #{keyIdx} = 0x{key:X8}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
}
|
||||
ImRaii.TreeNode( $"Pass Indices: {string.Join( ' ', node.PassIndices.Select( c => $"{c:X2}" ) )}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
foreach( var (pass, passIdx) in node.Passes.WithIndex() )
|
||||
{
|
||||
ImRaii.TreeNode( $"Pass #{passIdx}: ID: 0x{pass.Id:X8}, Vertex Shader #{pass.VertexShader}, Pixel Shader #{pass.PixelShader}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( file.UnknownB.Length > 0 )
|
||||
if( file.Items.Length > 0 )
|
||||
{
|
||||
using var t = ImRaii.TreeNode( $"Unknown Type B Structures ({file.UnknownB.Length})" );
|
||||
using var t = ImRaii.TreeNode( $"Items ({file.Items.Length})" );
|
||||
if( t )
|
||||
{
|
||||
foreach( var (unk, idx) in file.UnknownB.WithIndex() )
|
||||
foreach( var (item, idx) in file.Items.WithIndex() )
|
||||
{
|
||||
ImRaii.TreeNode( $"#{idx}: 0x{unk.Item1:X8}, 0x{unk.Item2:X8}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
ImRaii.TreeNode( $"#{idx}: ID: 0x{item.Id:X8}, node: {item.Node}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( file.UnknownC.Length > 0 )
|
||||
{
|
||||
using var t = ImRaii.TreeNode( $"Unknown Type C Structures ({file.UnknownC.Length})" );
|
||||
if( t )
|
||||
{
|
||||
foreach( var (unk, idx) in file.UnknownC.WithIndex() )
|
||||
{
|
||||
ImRaii.TreeNode( $"#{idx}: 0x{unk.Item1:X8}, 0x{unk.Item2:X8}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using( var t = ImRaii.TreeNode( $"Misc. Unknown Fields" ) )
|
||||
{
|
||||
if( t )
|
||||
{
|
||||
ImRaii.TreeNode( $"#1 (at 0x0004): 0x{file.Unknown1:X8}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
ImRaii.TreeNode( $"#2 (at 0x003C): 0x{file.Unknown2:X8}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
ImRaii.TreeNode( $"#3 (at 0x0040): 0x{file.Unknown3:X8}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
ImRaii.TreeNode( $"#4 (at 0x0044): 0x{file.Unknown4:X8}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
if( file.AdditionalData.Length > 0 )
|
||||
{
|
||||
using var t = ImRaii.TreeNode( $"Additional Data (Size: {file.AdditionalData.Length})###AdditionalData" );
|
||||
|
|
@ -541,17 +596,6 @@ public partial class ModEditWindow
|
|||
}
|
||||
}
|
||||
|
||||
using( var t = ImRaii.TreeNode( $"String Pool" ) )
|
||||
{
|
||||
if( t )
|
||||
{
|
||||
foreach( var offset in file.Strings.StartingOffsets )
|
||||
{
|
||||
ImGui.Text( file.Strings.GetNullTerminatedString( offset ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue