mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Redesign Shpk tab.
This commit is contained in:
parent
7ae6d0a348
commit
e62b0155d4
8 changed files with 792 additions and 569 deletions
2
OtterGui
2
OtterGui
|
|
@ -1 +1 @@
|
|||
Subproject commit 2feb762d72c8717d8ece6a0bf72298776312b2c1
|
||||
Subproject commit 9e98cb9722bed3129134c7bc2fbe51268b2d6acd
|
||||
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Penumbra.GameData.Interop;
|
||||
using Penumbra.String;
|
||||
|
||||
namespace Penumbra.GameData.Data;
|
||||
|
||||
|
|
@ -96,26 +97,26 @@ public partial class DisassembledShader
|
|||
[GeneratedRegex(@"^\s*sample_\S*\s+[^.]+\.([wxyz]+),[^,]+,\s*t(\d+)\.([wxyz]+)", RegexOptions.NonBacktracking)]
|
||||
private static partial Regex Sm5TextureUsageRegex();
|
||||
|
||||
private static readonly char[] Digits = Enumerable.Range(0, 10).Select(c => (char) ('0' + c)).ToArray();
|
||||
private static readonly char[] Digits = Enumerable.Range(0, 10).Select(c => (char)('0' + c)).ToArray();
|
||||
|
||||
public readonly string RawDisassembly;
|
||||
public readonly uint ShaderModel;
|
||||
public readonly ShaderStage Stage;
|
||||
public readonly string BufferDefinitions;
|
||||
public readonly ResourceBinding[] ResourceBindings;
|
||||
public readonly InputOutput[] InputSignature;
|
||||
public readonly InputOutput[] OutputSignature;
|
||||
public readonly string[] Instructions;
|
||||
public readonly ByteString RawDisassembly;
|
||||
public readonly uint ShaderModel;
|
||||
public readonly ShaderStage Stage;
|
||||
public readonly string BufferDefinitions;
|
||||
public readonly ResourceBinding[] ResourceBindings;
|
||||
public readonly InputOutput[] InputSignature;
|
||||
public readonly InputOutput[] OutputSignature;
|
||||
public readonly IReadOnlyList<ByteString> Instructions;
|
||||
|
||||
public DisassembledShader(string rawDisassembly)
|
||||
public DisassembledShader(ByteString rawDisassembly)
|
||||
{
|
||||
RawDisassembly = rawDisassembly;
|
||||
var lines = rawDisassembly.Split('\n');
|
||||
Instructions = Array.FindAll(lines, ln => !ln.StartsWith("//") && ln.Length > 0);
|
||||
var shaderModel = Instructions[0].Trim().Split('_');
|
||||
Stage = (ShaderStage)(byte)char.ToUpper(shaderModel[0][0]);
|
||||
ShaderModel = (uint.Parse(shaderModel[1]) << 8) | uint.Parse(shaderModel[2]);
|
||||
var header = PreParseHeader(lines.AsSpan()[..Array.IndexOf(lines, Instructions[0])]);
|
||||
var lines = rawDisassembly.Split((byte) '\n');
|
||||
Instructions = lines.FindAll(ln => !ln.StartsWith("//"u8) && ln.Length > 0);
|
||||
var shaderModel = Instructions[0].Trim().Split((byte) '_');
|
||||
Stage = (ShaderStage)(byte)char.ToUpper((char) shaderModel[0][0]);
|
||||
ShaderModel = (uint.Parse(shaderModel[1].ToString()) << 8) | uint.Parse(shaderModel[2].ToString());
|
||||
var header = PreParseHeader(lines.Take(lines.IndexOf(Instructions[0])).Select(l => l.ToString()).ToArray());
|
||||
switch (ShaderModel >> 8)
|
||||
{
|
||||
case 3:
|
||||
|
|
@ -142,8 +143,8 @@ public partial class DisassembledShader
|
|||
private static void ParseSm3Header(Dictionary<string, string[]> header, out string bufferDefinitions,
|
||||
out ResourceBinding[] resourceBindings, out InputOutput[] inputSignature, out InputOutput[] outputSignature)
|
||||
{
|
||||
bufferDefinitions = header.TryGetValue("Parameters", out var rawParameters)
|
||||
? string.Join('\n', rawParameters)
|
||||
bufferDefinitions = header.TryGetValue("Parameters", out var rawParameters)
|
||||
? string.Join('\n', rawParameters)
|
||||
: string.Empty;
|
||||
if (header.TryGetValue("Registers", out var rawRegisters))
|
||||
{
|
||||
|
|
@ -176,7 +177,7 @@ public partial class DisassembledShader
|
|||
outputSignature = Array.Empty<InputOutput>();
|
||||
}
|
||||
|
||||
private static void ParseSm3ResourceUsage(string[] instructions, ResourceBinding[] resourceBindings)
|
||||
private static void ParseSm3ResourceUsage(IReadOnlyList<ByteString> instructions, ResourceBinding[] resourceBindings)
|
||||
{
|
||||
var cbIndices = new Dictionary<uint, int>();
|
||||
var tIndices = new Dictionary<uint, int>();
|
||||
|
|
@ -201,10 +202,11 @@ public partial class DisassembledShader
|
|||
foreach (var instruction in instructions)
|
||||
{
|
||||
var trimmed = instruction.Trim();
|
||||
if (trimmed.StartsWith("def") || trimmed.StartsWith("dcl"))
|
||||
if (trimmed.StartsWith("def"u8) || trimmed.StartsWith("dcl"u8))
|
||||
continue;
|
||||
|
||||
foreach (Match cbMatch in Sm3ConstantBufferUsageRegex().Matches(instruction))
|
||||
var instructionString = instruction.ToString();
|
||||
foreach (Match cbMatch in Sm3ConstantBufferUsageRegex().Matches(instructionString))
|
||||
{
|
||||
var buffer = uint.Parse(cbMatch.Groups[1].Value);
|
||||
if (cbIndices.TryGetValue(buffer, out var i))
|
||||
|
|
@ -217,7 +219,7 @@ public partial class DisassembledShader
|
|||
}
|
||||
}
|
||||
|
||||
var tMatch = Sm3TextureUsageRegex().Match(instruction);
|
||||
var tMatch = Sm3TextureUsageRegex().Match(instructionString);
|
||||
if (tMatch.Success)
|
||||
{
|
||||
var texture = uint.Parse(tMatch.Groups[1].Value);
|
||||
|
|
@ -307,7 +309,7 @@ public partial class DisassembledShader
|
|||
}
|
||||
}
|
||||
|
||||
private static void ParseSm5ResourceUsage(string[] instructions, ResourceBinding[] resourceBindings)
|
||||
private static void ParseSm5ResourceUsage(IReadOnlyList<ByteString> instructions, ResourceBinding[] resourceBindings)
|
||||
{
|
||||
var cbIndices = new Dictionary<uint, int>();
|
||||
var tIndices = new Dictionary<uint, int>();
|
||||
|
|
@ -331,10 +333,11 @@ public partial class DisassembledShader
|
|||
foreach (var instruction in instructions)
|
||||
{
|
||||
var trimmed = instruction.Trim();
|
||||
if (trimmed.StartsWith("def") || trimmed.StartsWith("dcl"))
|
||||
if (trimmed.StartsWith("def"u8) || trimmed.StartsWith("dcl"u8))
|
||||
continue;
|
||||
|
||||
foreach (Match cbMatch in Sm5ConstantBufferUsageRegex().Matches(instruction))
|
||||
var instructionString = instruction.ToString();
|
||||
foreach (Match cbMatch in Sm5ConstantBufferUsageRegex().Matches(instructionString))
|
||||
{
|
||||
var buffer = uint.Parse(cbMatch.Groups[1].Value);
|
||||
if (cbIndices.TryGetValue(buffer, out var i))
|
||||
|
|
@ -352,7 +355,7 @@ public partial class DisassembledShader
|
|||
}
|
||||
}
|
||||
|
||||
var tMatch = Sm5TextureUsageRegex().Match(instruction);
|
||||
var tMatch = Sm5TextureUsageRegex().Match(instructionString);
|
||||
if (tMatch.Success)
|
||||
{
|
||||
var texture = uint.Parse(tMatch.Groups[2].Value);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Penumbra.String;
|
||||
|
||||
namespace Penumbra.GameData.Interop;
|
||||
|
||||
|
|
@ -20,43 +21,41 @@ internal static class D3DCompiler
|
|||
[Flags]
|
||||
public enum DisassembleFlags : uint
|
||||
{
|
||||
EnableColorCode = 1,
|
||||
EnableDefaultValuePrints = 2,
|
||||
EnableColorCode = 1,
|
||||
EnableDefaultValuePrints = 2,
|
||||
EnableInstructionNumbering = 4,
|
||||
EnableInstructionCycle = 8,
|
||||
DisableDebugInfo = 16,
|
||||
EnableInstructionOffset = 32,
|
||||
InstructionOnly = 64,
|
||||
PrintHexLiterals = 128,
|
||||
EnableInstructionCycle = 8,
|
||||
DisableDebugInfo = 16,
|
||||
EnableInstructionOffset = 32,
|
||||
InstructionOnly = 64,
|
||||
PrintHexLiterals = 128,
|
||||
}
|
||||
|
||||
public static unsafe string Disassemble(ReadOnlySpan<byte> blob, DisassembleFlags flags = 0, string comments = "")
|
||||
public static unsafe ByteString Disassemble(ReadOnlySpan<byte> blob, DisassembleFlags flags = 0, string comments = "")
|
||||
{
|
||||
ID3DBlob? disassembly;
|
||||
int hr;
|
||||
fixed (byte* pSrcData = blob)
|
||||
ID3DBlob? disassembly = null;
|
||||
try
|
||||
{
|
||||
hr = D3DDisassemble(pSrcData, new UIntPtr((uint)blob.Length), (uint)flags, comments, out disassembly);
|
||||
fixed (byte* pSrcData = blob)
|
||||
{
|
||||
var hr = D3DDisassemble(pSrcData, new UIntPtr((uint)blob.Length), (uint)flags, comments, out disassembly);
|
||||
Marshal.ThrowExceptionForHR(hr);
|
||||
}
|
||||
|
||||
return disassembly == null
|
||||
? ByteString.Empty
|
||||
: new ByteString((byte*)disassembly.GetBufferPointer()).Clone();
|
||||
}
|
||||
Marshal.ThrowExceptionForHR(hr);
|
||||
var ret = Encoding.UTF8.GetString(BlobContents(disassembly));
|
||||
GC.KeepAlive(disassembly);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static unsafe ReadOnlySpan<byte> BlobContents(ID3DBlob? blob)
|
||||
{
|
||||
if (blob == null)
|
||||
finally
|
||||
{
|
||||
return ReadOnlySpan<byte>.Empty;
|
||||
if (disassembly != null)
|
||||
Marshal.FinalReleaseComObject(disassembly);
|
||||
}
|
||||
|
||||
return new ReadOnlySpan<byte>(blob.GetBufferPointer(), (int)blob.GetBufferSize().ToUInt32());
|
||||
}
|
||||
|
||||
[PreserveSig]
|
||||
[DllImport("D3DCompiler_47.dll")]
|
||||
private extern static unsafe int D3DDisassemble(
|
||||
private static extern unsafe int D3DDisassemble(
|
||||
[In] byte* pSrcData,
|
||||
[In] UIntPtr srcDataSize,
|
||||
uint flags,
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 3447fe0dc9cfc5f056e1595c6c2413de37db924a
|
||||
Subproject commit ce41e2b7da65edb25b5308ae41e4ca7d74d75e38
|
||||
|
|
@ -160,7 +160,7 @@ public partial class ModEditWindow
|
|||
{
|
||||
tab.NewKeyDefault = key.DefaultValue;
|
||||
tab.NewKeyId = key.Id;
|
||||
ret = true;
|
||||
ret = true;
|
||||
tab.UpdateShaderKeyLabels();
|
||||
}
|
||||
}
|
||||
|
|
@ -382,7 +382,9 @@ public partial class ModEditWindow
|
|||
var (label, filename) = tab.Samplers[ idx ];
|
||||
using var tree = ImRaii.TreeNode( label );
|
||||
if( !tree )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ImRaii.TreeNode( filename, ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
var ret = false;
|
||||
|
|
@ -398,7 +400,7 @@ public partial class ModEditWindow
|
|||
}
|
||||
|
||||
ImGui.SetNextItemWidth( ImGuiHelpers.GlobalScale * 150.0f );
|
||||
if( InputHexUInt16( "Texture Flags", ref tab.Mtrl.Textures[sampler.TextureIndex].Flags,
|
||||
if( InputHexUInt16( "Texture Flags", ref tab.Mtrl.Textures[ sampler.TextureIndex ].Flags,
|
||||
disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None ) )
|
||||
{
|
||||
ret = true;
|
||||
|
|
@ -409,22 +411,22 @@ public partial class ModEditWindow
|
|||
if( ImGui.InputInt( "Sampler Flags", ref samplerFlags, 0, 0,
|
||||
ImGuiInputTextFlags.CharsHexadecimal | ( disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None ) ) )
|
||||
{
|
||||
tab.Mtrl.ShaderPackage.Samplers[idx].Flags = ( uint )samplerFlags;
|
||||
ret = true;
|
||||
tab.Mtrl.ShaderPackage.Samplers[ idx ].Flags = ( uint )samplerFlags;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if( !disabled
|
||||
&& tab.OrphanedSamplers.Count == 0
|
||||
&& tab.AliasedSamplerCount == 0
|
||||
&& tab.AliasedSamplerCount == 0
|
||||
&& ImGui.Button( "Remove Sampler" ) )
|
||||
{
|
||||
tab.Mtrl.Textures = tab.Mtrl.Textures.RemoveItems( sampler.TextureIndex );
|
||||
tab.Mtrl.Textures = tab.Mtrl.Textures.RemoveItems( sampler.TextureIndex );
|
||||
tab.Mtrl.ShaderPackage.Samplers = tab.Mtrl.ShaderPackage.Samplers.RemoveItems( idx-- );
|
||||
for( var i = 0; i < tab.Mtrl.ShaderPackage.Samplers.Length; ++i )
|
||||
{
|
||||
if( tab.Mtrl.ShaderPackage.Samplers[i].TextureIndex >= sampler.TextureIndex )
|
||||
if( tab.Mtrl.ShaderPackage.Samplers[ i ].TextureIndex >= sampler.TextureIndex )
|
||||
{
|
||||
--tab.Mtrl.ShaderPackage.Samplers[i].TextureIndex;
|
||||
--tab.Mtrl.ShaderPackage.Samplers[ i ].TextureIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -438,7 +440,7 @@ public partial class ModEditWindow
|
|||
|
||||
private static bool DrawMaterialNewSampler( MtrlTab tab )
|
||||
{
|
||||
var (name, id) = tab.MissingSamplers[tab.NewSamplerIdx];
|
||||
var (name, id) = tab.MissingSamplers[ tab.NewSamplerIdx ];
|
||||
ImGui.SetNextItemWidth( ImGuiHelpers.GlobalScale * 450.0f );
|
||||
using( var c = ImRaii.Combo( "##NewSamplerId", $"{name} (ID: 0x{id:X8})" ) )
|
||||
{
|
||||
|
|
@ -475,14 +477,13 @@ public partial class ModEditWindow
|
|||
tab.UpdateSamplers();
|
||||
tab.UpdateTextureLabels();
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private static bool DrawMaterialSamplers( MtrlTab tab, bool disabled )
|
||||
{
|
||||
if( tab.Mtrl.ShaderPackage.Samplers.Length == 0
|
||||
&& tab.Mtrl.Textures.Length == 0
|
||||
&& ( disabled || (tab.AssociatedShpk?.Samplers.All( sampler => sampler.Slot != 2 ) ?? false ) ))
|
||||
&& ( disabled || ( tab.AssociatedShpk?.Samplers.All( sampler => sampler.Slot != 2 ) ?? false ) ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -493,7 +494,7 @@ public partial class ModEditWindow
|
|||
return false;
|
||||
}
|
||||
|
||||
var ret = false;
|
||||
var ret = false;
|
||||
for( var idx = 0; idx < tab.Mtrl.ShaderPackage.Samplers.Length; ++idx )
|
||||
{
|
||||
ret |= DrawMaterialSampler( tab, disabled, ref idx );
|
||||
|
|
@ -511,7 +512,7 @@ public partial class ModEditWindow
|
|||
}
|
||||
}
|
||||
}
|
||||
else if( !disabled && tab.MissingSamplers.Count > 0 && tab.AliasedSamplerCount == 0 && tab.Mtrl.Textures.Length < 255 )
|
||||
else if( !disabled && tab.MissingSamplers.Count > 0 && tab.AliasedSamplerCount == 0 && tab.Mtrl.Textures.Length < 255 )
|
||||
{
|
||||
ret |= DrawMaterialNewSampler( tab );
|
||||
}
|
||||
|
|
@ -592,7 +593,7 @@ public partial class ModEditWindow
|
|||
}
|
||||
|
||||
var sb = new StringBuilder( 128 );
|
||||
sb.Append( $"{prefix}[{firstVector}]{VectorSwizzle( firstComponent, 3 )}" );
|
||||
sb.Append( $"{prefix}[{firstVector}]{VectorSwizzle( firstComponent, 3 ).TrimEnd()}" );
|
||||
for( var i = firstVector + 1; i < lastVector; ++i )
|
||||
{
|
||||
sb.Append( $", [{i}]" );
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
188
Penumbra/UI/Classes/ModEditWindow.ShpkTab.cs
Normal file
188
Penumbra/UI/Classes/ModEditWindow.ShpkTab.cs
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Dalamud.Interface.ImGuiFileDialog;
|
||||
using Dalamud.Utility;
|
||||
using Lumina.Misc;
|
||||
using OtterGui;
|
||||
using Penumbra.GameData.Data;
|
||||
using Penumbra.GameData.Files;
|
||||
|
||||
namespace Penumbra.UI.Classes;
|
||||
|
||||
public partial class ModEditWindow
|
||||
{
|
||||
private class ShpkTab : IWritable
|
||||
{
|
||||
public readonly ShpkFile Shpk;
|
||||
|
||||
public string NewMaterialParamName = string.Empty;
|
||||
public uint NewMaterialParamId = Crc32.Get( string.Empty, 0xFFFFFFFFu );
|
||||
public short NewMaterialParamStart;
|
||||
public short NewMaterialParamEnd;
|
||||
|
||||
public readonly FileDialogManager FileDialog = ConfigWindow.SetupFileManager();
|
||||
|
||||
public readonly string Header;
|
||||
public readonly string Extension;
|
||||
|
||||
public ShpkTab( byte[] bytes )
|
||||
{
|
||||
Shpk = new ShpkFile( bytes, true );
|
||||
Header = $"Shader Package for DirectX {( int )Shpk.DirectXVersion}";
|
||||
Extension = Shpk.DirectXVersion switch
|
||||
{
|
||||
ShpkFile.DxVersion.DirectX9 => ".cso",
|
||||
ShpkFile.DxVersion.DirectX11 => ".dxbc",
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
Update();
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ColorType : byte
|
||||
{
|
||||
Unused = 0,
|
||||
Used = 1,
|
||||
Continuation = 2,
|
||||
}
|
||||
|
||||
public (string Name, string Tooltip, short Index, ColorType Color)[,] Matrix = null!;
|
||||
public readonly List< string > MalformedParameters = new();
|
||||
public readonly HashSet< uint > UsedIds = new(16);
|
||||
public readonly List< (string Name, short Index) > Orphans = new(16);
|
||||
|
||||
public void Update()
|
||||
{
|
||||
var materialParams = Shpk.GetConstantById( ShpkFile.MaterialParamsConstantId );
|
||||
var numParameters = ( ( Shpk.MaterialParamsSize + 0xFu ) & ~0xFu ) >> 4;
|
||||
Matrix = new (string Name, string Tooltip, short Index, ColorType Color)[numParameters, 4];
|
||||
|
||||
MalformedParameters.Clear();
|
||||
UsedIds.Clear();
|
||||
foreach( var (param, idx) in Shpk.MaterialParams.WithIndex() )
|
||||
{
|
||||
UsedIds.Add( param.Id );
|
||||
var iStart = param.ByteOffset >> 4;
|
||||
var jStart = ( param.ByteOffset >> 2 ) & 3;
|
||||
var iEnd = ( param.ByteOffset + param.ByteSize - 1 ) >> 4;
|
||||
var jEnd = ( ( param.ByteOffset + param.ByteSize - 1 ) >> 2 ) & 3;
|
||||
if( ( param.ByteOffset & 0x3 ) != 0 || ( param.ByteSize & 0x3 ) != 0 )
|
||||
{
|
||||
MalformedParameters.Add( $"ID: 0x{param.Id:X8}, offset: 0x{param.ByteOffset:X4}, size: 0x{param.ByteSize:X4}" );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( iEnd >= numParameters )
|
||||
{
|
||||
MalformedParameters.Add(
|
||||
$"{MaterialParamRangeName( materialParams?.Name ?? string.Empty, param.ByteOffset >> 2, param.ByteSize >> 2 )} (ID: 0x{param.Id:X8})" );
|
||||
continue;
|
||||
}
|
||||
|
||||
for( var i = iStart; i <= iEnd; ++i )
|
||||
{
|
||||
var end = i == iEnd ? jEnd : 3;
|
||||
for( var j = i == iStart ? jStart : 0; j <= end; ++j )
|
||||
{
|
||||
var tt = $"{MaterialParamRangeName( materialParams?.Name ?? string.Empty, param.ByteOffset >> 2, param.ByteSize >> 2 ).Item1} (ID: 0x{param.Id:X8})";
|
||||
Matrix[ i, j ] = ( $"0x{param.Id:X8}", tt, ( short )idx, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateOrphans( materialParams );
|
||||
UpdateColors( materialParams );
|
||||
}
|
||||
|
||||
public void UpdateOrphanStart( int orphanStart )
|
||||
{
|
||||
var oldEnd = Orphans.Count > 0 ? Orphans[ NewMaterialParamEnd ].Index : -1;
|
||||
UpdateOrphanStart( orphanStart, oldEnd );
|
||||
}
|
||||
|
||||
private void UpdateOrphanStart( int orphanStart, int oldEnd )
|
||||
{
|
||||
var count = Math.Min( NewMaterialParamEnd - NewMaterialParamStart + orphanStart + 1, Orphans.Count );
|
||||
NewMaterialParamStart = ( short )orphanStart;
|
||||
var current = Orphans[ NewMaterialParamStart ].Index;
|
||||
for( var i = NewMaterialParamStart; i < count; ++i )
|
||||
{
|
||||
var next = Orphans[ i ].Index;
|
||||
if( current++ != next )
|
||||
{
|
||||
NewMaterialParamEnd = ( short )( i - 1 );
|
||||
return;
|
||||
}
|
||||
|
||||
if( next == oldEnd )
|
||||
{
|
||||
NewMaterialParamEnd = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NewMaterialParamEnd = ( short )( count - 1 );
|
||||
}
|
||||
|
||||
private void UpdateOrphans( ShpkFile.Resource? materialParams )
|
||||
{
|
||||
var oldStart = Orphans.Count > 0 ? Orphans[ NewMaterialParamStart ].Index : -1;
|
||||
var oldEnd = Orphans.Count > 0 ? Orphans[ NewMaterialParamEnd ].Index : -1;
|
||||
|
||||
Orphans.Clear();
|
||||
short newMaterialParamStart = 0;
|
||||
for( var i = 0; i < Matrix.GetLength( 0 ); ++i )
|
||||
for( var j = 0; j < 4; ++j )
|
||||
{
|
||||
if( !Matrix[ i, j ].Name.IsNullOrEmpty() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Matrix[ i, j ] = ( "(none)", string.Empty, -1, 0 );
|
||||
var linear = ( short )( 4 * i + j );
|
||||
if( oldStart == linear )
|
||||
{
|
||||
newMaterialParamStart = ( short )Orphans.Count;
|
||||
}
|
||||
|
||||
Orphans.Add( ( $"{materialParams?.Name ?? string.Empty}{MaterialParamName( false, linear )}", linear ) );
|
||||
}
|
||||
|
||||
if( Orphans.Count == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateOrphanStart( newMaterialParamStart, oldEnd );
|
||||
}
|
||||
|
||||
private void UpdateColors( ShpkFile.Resource? materialParams )
|
||||
{
|
||||
var lastIndex = -1;
|
||||
for( var i = 0; i < Matrix.GetLength( 0 ); ++i )
|
||||
{
|
||||
var usedComponents = ( materialParams?.Used?[ i ] ?? DisassembledShader.VectorComponents.All ) | ( materialParams?.UsedDynamically ?? 0 );
|
||||
for( var j = 0; j < 4; ++j )
|
||||
{
|
||||
var color = ( ( byte )usedComponents & ( 1 << j ) ) != 0
|
||||
? ColorType.Used
|
||||
: 0;
|
||||
if( Matrix[ i, j ].Index == lastIndex || Matrix[ i, j ].Index < 0 )
|
||||
{
|
||||
color |= ColorType.Continuation;
|
||||
}
|
||||
|
||||
lastIndex = Matrix[ i, j ].Index;
|
||||
Matrix[ i, j ].Color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Valid
|
||||
=> Shpk.Valid;
|
||||
|
||||
public byte[] Write()
|
||||
=> Shpk.Write();
|
||||
}
|
||||
}
|
||||
|
|
@ -580,11 +580,11 @@ public partial class ModEditWindow : Window, IDisposable
|
|||
DrawModelPanel,
|
||||
() => _mod?.ModPath.FullName ?? string.Empty,
|
||||
null );
|
||||
_shaderPackageTab = new FileEditor< ShpkFile >( "Shader Packages", ".shpk",
|
||||
_shaderPackageTab = new FileEditor< ShpkTab >( "Shader Packages", ".shpk",
|
||||
() => _editor?.ShpkFiles ?? Array.Empty< Editor.FileRegistry >(),
|
||||
DrawShaderPackagePanel,
|
||||
() => _mod?.ModPath.FullName ?? string.Empty,
|
||||
bytes => new ShpkFile( bytes, true ) );
|
||||
bytes => new ShpkTab( bytes ) );
|
||||
_center = new CombinedTexture( _left, _right );
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue