mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Auto-formatting and some cleanup.
This commit is contained in:
parent
ff01276869
commit
e5e555b981
8 changed files with 876 additions and 959 deletions
|
|
@ -17,65 +17,60 @@ public partial class ModEditWindow
|
|||
private static readonly float HalfMaxValue = (float)Half.MaxValue;
|
||||
private static readonly float HalfEpsilon = (float)Half.Epsilon;
|
||||
|
||||
private bool DrawMaterialColorSetChange( MtrlTab tab, bool disabled )
|
||||
private bool DrawMaterialColorSetChange(MtrlTab tab, bool disabled)
|
||||
{
|
||||
if( !tab.SamplerIds.Contains( ShpkFile.TableSamplerId ) || !tab.Mtrl.ColorSets.Any( c => c.HasRows ) )
|
||||
{
|
||||
if (!tab.SamplerIds.Contains(ShpkFile.TableSamplerId) || !tab.Mtrl.ColorSets.Any(c => c.HasRows))
|
||||
return false;
|
||||
}
|
||||
|
||||
ImGui.Dummy( new Vector2( ImGui.GetTextLineHeight() / 2 ) );
|
||||
if( !ImGui.CollapsingHeader( "Color Set", ImGuiTreeNodeFlags.DefaultOpen ) )
|
||||
{
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
if (!ImGui.CollapsingHeader("Color Set", ImGuiTreeNodeFlags.DefaultOpen))
|
||||
return false;
|
||||
}
|
||||
|
||||
var hasAnyDye = tab.UseColorDyeSet;
|
||||
|
||||
ColorSetCopyAllClipboardButton( tab.Mtrl, 0 );
|
||||
ColorSetCopyAllClipboardButton(tab.Mtrl, 0);
|
||||
ImGui.SameLine();
|
||||
var ret = ColorSetPasteAllClipboardButton( tab, 0, disabled );
|
||||
if( !disabled )
|
||||
var ret = ColorSetPasteAllClipboardButton(tab, 0, disabled);
|
||||
if (!disabled)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGui.Dummy( ImGuiHelpers.ScaledVector2( 20, 0 ) );
|
||||
ImGui.Dummy(ImGuiHelpers.ScaledVector2(20, 0));
|
||||
ImGui.SameLine();
|
||||
ret |= ColorSetDyeableCheckbox( tab, ref hasAnyDye );
|
||||
}
|
||||
if( hasAnyDye )
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGui.Dummy( ImGuiHelpers.ScaledVector2( 20, 0 ) );
|
||||
ImGui.SameLine();
|
||||
ret |= DrawPreviewDye( tab, disabled );
|
||||
ret |= ColorSetDyeableCheckbox(tab, ref hasAnyDye);
|
||||
}
|
||||
|
||||
using var table = ImRaii.Table( "##ColorSets", hasAnyDye ? 11 : 9,
|
||||
ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersInnerV );
|
||||
if( !table )
|
||||
if (hasAnyDye)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGui.Dummy(ImGuiHelpers.ScaledVector2(20, 0));
|
||||
ImGui.SameLine();
|
||||
ret |= DrawPreviewDye(tab, disabled);
|
||||
}
|
||||
|
||||
using var table = ImRaii.Table("##ColorSets", hasAnyDye ? 11 : 9,
|
||||
ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersInnerV);
|
||||
if (!table)
|
||||
return false;
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableHeader( string.Empty );
|
||||
ImGui.TableHeader(string.Empty);
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableHeader( "Row" );
|
||||
ImGui.TableHeader("Row");
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableHeader( "Diffuse" );
|
||||
ImGui.TableHeader("Diffuse");
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableHeader( "Specular" );
|
||||
ImGui.TableHeader("Specular");
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableHeader( "Emissive" );
|
||||
ImGui.TableHeader("Emissive");
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableHeader( "Gloss" );
|
||||
ImGui.TableHeader("Gloss");
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableHeader( "Tile" );
|
||||
ImGui.TableHeader("Tile");
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableHeader( "Repeat" );
|
||||
ImGui.TableHeader("Repeat");
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableHeader( "Skew" );
|
||||
if( hasAnyDye )
|
||||
ImGui.TableHeader("Skew");
|
||||
if (hasAnyDye)
|
||||
{
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableHeader("Dye");
|
||||
|
|
@ -83,12 +78,12 @@ public partial class ModEditWindow
|
|||
ImGui.TableHeader("Dye Preview");
|
||||
}
|
||||
|
||||
for( var j = 0; j < tab.Mtrl.ColorSets.Length; ++j )
|
||||
for (var j = 0; j < tab.Mtrl.ColorSets.Length; ++j)
|
||||
{
|
||||
using var _ = ImRaii.PushId( j );
|
||||
for( var i = 0; i < MtrlFile.ColorSet.RowArray.NumRows; ++i )
|
||||
using var _ = ImRaii.PushId(j);
|
||||
for (var i = 0; i < MtrlFile.ColorSet.RowArray.NumRows; ++i)
|
||||
{
|
||||
ret |= DrawColorSetRow( tab, j, i, disabled, hasAnyDye );
|
||||
ret |= DrawColorSetRow(tab, j, i, disabled, hasAnyDye);
|
||||
ImGui.TableNextRow();
|
||||
}
|
||||
}
|
||||
|
|
@ -97,22 +92,20 @@ public partial class ModEditWindow
|
|||
}
|
||||
|
||||
|
||||
private static void ColorSetCopyAllClipboardButton( MtrlFile file, int colorSetIdx )
|
||||
private static void ColorSetCopyAllClipboardButton(MtrlFile file, int colorSetIdx)
|
||||
{
|
||||
if( !ImGui.Button( "Export All Rows to Clipboard", ImGuiHelpers.ScaledVector2( 200, 0 ) ) )
|
||||
{
|
||||
if (!ImGui.Button("Export All Rows to Clipboard", ImGuiHelpers.ScaledVector2(200, 0)))
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var data1 = file.ColorSets[ colorSetIdx ].Rows.AsBytes();
|
||||
var data2 = file.ColorDyeSets.Length > colorSetIdx ? file.ColorDyeSets[ colorSetIdx ].Rows.AsBytes() : ReadOnlySpan< byte >.Empty;
|
||||
var data1 = file.ColorSets[colorSetIdx].Rows.AsBytes();
|
||||
var data2 = file.ColorDyeSets.Length > colorSetIdx ? file.ColorDyeSets[colorSetIdx].Rows.AsBytes() : ReadOnlySpan<byte>.Empty;
|
||||
var array = new byte[data1.Length + data2.Length];
|
||||
data1.TryCopyTo( array );
|
||||
data2.TryCopyTo( array.AsSpan( data1.Length ) );
|
||||
var text = Convert.ToBase64String( array );
|
||||
ImGui.SetClipboardText( text );
|
||||
data1.TryCopyTo(array);
|
||||
data2.TryCopyTo(array.AsSpan(data1.Length));
|
||||
var text = Convert.ToBase64String(array);
|
||||
ImGui.SetClipboardText(text);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
@ -120,19 +113,19 @@ public partial class ModEditWindow
|
|||
}
|
||||
}
|
||||
|
||||
private bool DrawPreviewDye( MtrlTab tab, bool disabled )
|
||||
private bool DrawPreviewDye(MtrlTab tab, bool disabled)
|
||||
{
|
||||
var (dyeId, (name, dyeColor, gloss)) = _stainService.StainCombo.CurrentSelection;
|
||||
var tt = dyeId == 0 ? "Select a preview dye first." : "Apply all preview values corresponding to the dye template and chosen dye where dyeing is enabled.";
|
||||
if( ImGuiUtil.DrawDisabledButton( "Apply Preview Dye", Vector2.Zero, tt, disabled || dyeId == 0 ) )
|
||||
var tt = dyeId == 0
|
||||
? "Select a preview dye first."
|
||||
: "Apply all preview values corresponding to the dye template and chosen dye where dyeing is enabled.";
|
||||
if (ImGuiUtil.DrawDisabledButton("Apply Preview Dye", Vector2.Zero, tt, disabled || dyeId == 0))
|
||||
{
|
||||
var ret = false;
|
||||
for( var j = 0; j < tab.Mtrl.ColorDyeSets.Length; ++j )
|
||||
for (var j = 0; j < tab.Mtrl.ColorDyeSets.Length; ++j)
|
||||
{
|
||||
for( var i = 0; i < MtrlFile.ColorSet.RowArray.NumRows; ++i )
|
||||
{
|
||||
ret |= tab.Mtrl.ApplyDyeTemplate( _stainService.StmFile, j, i, dyeId );
|
||||
}
|
||||
for (var i = 0; i < MtrlFile.ColorSet.RowArray.NumRows; ++i)
|
||||
ret |= tab.Mtrl.ApplyDyeTemplate(_stainService.StmFile, j, i, dyeId);
|
||||
}
|
||||
|
||||
tab.UpdateColorSetPreview();
|
||||
|
|
@ -147,33 +140,31 @@ public partial class ModEditWindow
|
|||
return false;
|
||||
}
|
||||
|
||||
private static unsafe bool ColorSetPasteAllClipboardButton( MtrlTab tab, int colorSetIdx, bool disabled )
|
||||
private static unsafe bool ColorSetPasteAllClipboardButton(MtrlTab tab, int colorSetIdx, bool disabled)
|
||||
{
|
||||
if( !ImGuiUtil.DrawDisabledButton( "Import All Rows from Clipboard", ImGuiHelpers.ScaledVector2( 200, 0 ), string.Empty, disabled ) || tab.Mtrl.ColorSets.Length <= colorSetIdx )
|
||||
{
|
||||
if (!ImGuiUtil.DrawDisabledButton("Import All Rows from Clipboard", ImGuiHelpers.ScaledVector2(200, 0), string.Empty, disabled)
|
||||
|| tab.Mtrl.ColorSets.Length <= colorSetIdx)
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var text = ImGui.GetClipboardText();
|
||||
var data = Convert.FromBase64String( text );
|
||||
if( data.Length < Marshal.SizeOf< MtrlFile.ColorSet.RowArray >() )
|
||||
{
|
||||
var data = Convert.FromBase64String(text);
|
||||
if (data.Length < Marshal.SizeOf<MtrlFile.ColorSet.RowArray>())
|
||||
return false;
|
||||
}
|
||||
|
||||
ref var rows = ref tab.Mtrl.ColorSets[ colorSetIdx ].Rows;
|
||||
fixed( void* ptr = data, output = &rows )
|
||||
ref var rows = ref tab.Mtrl.ColorSets[colorSetIdx].Rows;
|
||||
fixed (void* ptr = data, output = &rows)
|
||||
{
|
||||
MemoryUtility.MemCpyUnchecked( output, ptr, Marshal.SizeOf< MtrlFile.ColorSet.RowArray >() );
|
||||
if( data.Length >= Marshal.SizeOf< MtrlFile.ColorSet.RowArray >() + Marshal.SizeOf< MtrlFile.ColorDyeSet.RowArray >()
|
||||
&& tab.Mtrl.ColorDyeSets.Length > colorSetIdx )
|
||||
MemoryUtility.MemCpyUnchecked(output, ptr, Marshal.SizeOf<MtrlFile.ColorSet.RowArray>());
|
||||
if (data.Length >= Marshal.SizeOf<MtrlFile.ColorSet.RowArray>() + Marshal.SizeOf<MtrlFile.ColorDyeSet.RowArray>()
|
||||
&& tab.Mtrl.ColorDyeSets.Length > colorSetIdx)
|
||||
{
|
||||
ref var dyeRows = ref tab.Mtrl.ColorDyeSets[ colorSetIdx ].Rows;
|
||||
fixed( void* output2 = &dyeRows )
|
||||
ref var dyeRows = ref tab.Mtrl.ColorDyeSets[colorSetIdx].Rows;
|
||||
fixed (void* output2 = &dyeRows)
|
||||
{
|
||||
MemoryUtility.MemCpyUnchecked( output2, ( byte* )ptr + Marshal.SizeOf< MtrlFile.ColorSet.RowArray >(), Marshal.SizeOf< MtrlFile.ColorDyeSet.RowArray >() );
|
||||
MemoryUtility.MemCpyUnchecked(output2, (byte*)ptr + Marshal.SizeOf<MtrlFile.ColorSet.RowArray>(),
|
||||
Marshal.SizeOf<MtrlFile.ColorDyeSet.RowArray>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -188,38 +179,38 @@ public partial class ModEditWindow
|
|||
}
|
||||
}
|
||||
|
||||
private static unsafe void ColorSetCopyClipboardButton( MtrlFile.ColorSet.Row row, MtrlFile.ColorDyeSet.Row dye )
|
||||
private static unsafe void ColorSetCopyClipboardButton(MtrlFile.ColorSet.Row row, MtrlFile.ColorDyeSet.Row dye)
|
||||
{
|
||||
if( ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Clipboard.ToIconString(), ImGui.GetFrameHeight() * Vector2.One,
|
||||
"Export this row to your clipboard.", false, true ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = new byte[MtrlFile.ColorSet.Row.Size + 2];
|
||||
fixed( byte* ptr = data )
|
||||
{
|
||||
MemoryUtility.MemCpyUnchecked( ptr, &row, MtrlFile.ColorSet.Row.Size );
|
||||
MemoryUtility.MemCpyUnchecked( ptr + MtrlFile.ColorSet.Row.Size, &dye, 2 );
|
||||
}
|
||||
if (!ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Clipboard.ToIconString(), ImGui.GetFrameHeight() * Vector2.One,
|
||||
"Export this row to your clipboard.", false, true))
|
||||
return;
|
||||
|
||||
var text = Convert.ToBase64String( data );
|
||||
ImGui.SetClipboardText( text );
|
||||
}
|
||||
catch
|
||||
try
|
||||
{
|
||||
var data = new byte[MtrlFile.ColorSet.Row.Size + 2];
|
||||
fixed (byte* ptr = data)
|
||||
{
|
||||
// ignored
|
||||
MemoryUtility.MemCpyUnchecked(ptr, &row, MtrlFile.ColorSet.Row.Size);
|
||||
MemoryUtility.MemCpyUnchecked(ptr + MtrlFile.ColorSet.Row.Size, &dye, 2);
|
||||
}
|
||||
|
||||
var text = Convert.ToBase64String(data);
|
||||
ImGui.SetClipboardText(text);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ColorSetDyeableCheckbox( MtrlTab tab, ref bool dyeable )
|
||||
private static bool ColorSetDyeableCheckbox(MtrlTab tab, ref bool dyeable)
|
||||
{
|
||||
var ret = ImGui.Checkbox( "Dyeable", ref dyeable );
|
||||
var ret = ImGui.Checkbox("Dyeable", ref dyeable);
|
||||
|
||||
if( ret )
|
||||
if (ret)
|
||||
{
|
||||
tab.UseColorDyeSet = dyeable;
|
||||
if( dyeable )
|
||||
if (dyeable)
|
||||
tab.Mtrl.FindOrAddColorDyeSet();
|
||||
tab.UpdateColorSetPreview();
|
||||
}
|
||||
|
|
@ -227,215 +218,244 @@ public partial class ModEditWindow
|
|||
return ret;
|
||||
}
|
||||
|
||||
private static unsafe bool ColorSetPasteFromClipboardButton( MtrlTab tab, int colorSetIdx, int rowIdx, bool disabled )
|
||||
private static unsafe bool ColorSetPasteFromClipboardButton(MtrlTab tab, int colorSetIdx, int rowIdx, bool disabled)
|
||||
{
|
||||
if( ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Paste.ToIconString(), ImGui.GetFrameHeight() * Vector2.One,
|
||||
"Import an exported row from your clipboard onto this row.", disabled, true ) )
|
||||
if (!ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Paste.ToIconString(), ImGui.GetFrameHeight() * Vector2.One,
|
||||
"Import an exported row from your clipboard onto this row.", disabled, true))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
var text = ImGui.GetClipboardText();
|
||||
var data = Convert.FromBase64String(text);
|
||||
if (data.Length != MtrlFile.ColorSet.Row.Size + 2
|
||||
|| tab.Mtrl.ColorSets.Length <= colorSetIdx)
|
||||
return false;
|
||||
|
||||
fixed (byte* ptr = data)
|
||||
{
|
||||
var text = ImGui.GetClipboardText();
|
||||
var data = Convert.FromBase64String( text );
|
||||
if( data.Length != MtrlFile.ColorSet.Row.Size + 2
|
||||
|| tab.Mtrl.ColorSets.Length <= colorSetIdx )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
fixed( byte* ptr = data )
|
||||
{
|
||||
tab.Mtrl.ColorSets[ colorSetIdx ].Rows[ rowIdx ] = *( MtrlFile.ColorSet.Row* )ptr;
|
||||
if( colorSetIdx < tab.Mtrl.ColorDyeSets.Length )
|
||||
{
|
||||
tab.Mtrl.ColorDyeSets[ colorSetIdx ].Rows[ rowIdx ] = *( MtrlFile.ColorDyeSet.Row* )( ptr + MtrlFile.ColorSet.Row.Size );
|
||||
}
|
||||
}
|
||||
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx] = *(MtrlFile.ColorSet.Row*)ptr;
|
||||
if (colorSetIdx < tab.Mtrl.ColorDyeSets.Length)
|
||||
tab.Mtrl.ColorDyeSets[colorSetIdx].Rows[rowIdx] = *(MtrlFile.ColorDyeSet.Row*)(ptr + MtrlFile.ColorSet.Row.Size);
|
||||
}
|
||||
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void ColorSetHighlightButton( MtrlTab tab, int rowIdx, bool disabled )
|
||||
private static void ColorSetHighlightButton(MtrlTab tab, int rowIdx, bool disabled)
|
||||
{
|
||||
ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Crosshairs.ToIconString(), ImGui.GetFrameHeight() * Vector2.One,
|
||||
"Highlight this row on your character, if possible.", disabled || tab.ColorSetPreviewers.Count == 0, true );
|
||||
ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Crosshairs.ToIconString(), ImGui.GetFrameHeight() * Vector2.One,
|
||||
"Highlight this row on your character, if possible.", disabled || tab.ColorSetPreviewers.Count == 0, true);
|
||||
|
||||
if( ImGui.IsItemHovered() )
|
||||
tab.HighlightColorSetRow( rowIdx );
|
||||
else if( tab.HighlightedColorSetRow == rowIdx )
|
||||
if (ImGui.IsItemHovered())
|
||||
tab.HighlightColorSetRow(rowIdx);
|
||||
else if (tab.HighlightedColorSetRow == rowIdx)
|
||||
tab.CancelColorSetHighlight();
|
||||
}
|
||||
|
||||
private bool DrawColorSetRow( MtrlTab tab, int colorSetIdx, int rowIdx, bool disabled, bool hasAnyDye )
|
||||
private bool DrawColorSetRow(MtrlTab tab, int colorSetIdx, int rowIdx, bool disabled, bool hasAnyDye)
|
||||
{
|
||||
static bool FixFloat( ref float val, float current )
|
||||
static bool FixFloat(ref float val, float current)
|
||||
{
|
||||
val = ( float )( Half )val;
|
||||
val = (float)(Half)val;
|
||||
return val != current;
|
||||
}
|
||||
|
||||
using var id = ImRaii.PushId( rowIdx );
|
||||
var row = tab.Mtrl.ColorSets[ colorSetIdx ].Rows[ rowIdx ];
|
||||
using var id = ImRaii.PushId(rowIdx);
|
||||
var row = tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx];
|
||||
var hasDye = hasAnyDye && tab.Mtrl.ColorDyeSets.Length > colorSetIdx;
|
||||
var dye = hasDye ? tab.Mtrl.ColorDyeSets[ colorSetIdx ].Rows[ rowIdx ] : new MtrlFile.ColorDyeSet.Row();
|
||||
var dye = hasDye ? tab.Mtrl.ColorDyeSets[colorSetIdx].Rows[rowIdx] : new MtrlFile.ColorDyeSet.Row();
|
||||
var floatSize = 70 * UiHelpers.Scale;
|
||||
var intSize = 45 * UiHelpers.Scale;
|
||||
ImGui.TableNextColumn();
|
||||
ColorSetCopyClipboardButton( row, dye );
|
||||
ColorSetCopyClipboardButton(row, dye);
|
||||
ImGui.SameLine();
|
||||
var ret = ColorSetPasteFromClipboardButton( tab, colorSetIdx, rowIdx, disabled );
|
||||
var ret = ColorSetPasteFromClipboardButton(tab, colorSetIdx, rowIdx, disabled);
|
||||
ImGui.SameLine();
|
||||
ColorSetHighlightButton( tab, rowIdx, disabled );
|
||||
ColorSetHighlightButton(tab, rowIdx, disabled);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TextUnformatted( $"#{rowIdx + 1:D2}" );
|
||||
ImGui.TextUnformatted($"#{rowIdx + 1:D2}");
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
using var dis = ImRaii.Disabled( disabled );
|
||||
ret |= ColorPicker( "##Diffuse", "Diffuse Color", row.Diffuse, c => { tab.Mtrl.ColorSets[ colorSetIdx ].Rows[ rowIdx ].Diffuse = c; tab.UpdateColorSetRowPreview(rowIdx); } );
|
||||
if( hasDye )
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
ret |= ColorPicker("##Diffuse", "Diffuse Color", row.Diffuse, c =>
|
||||
{
|
||||
tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].Diffuse = c;
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
});
|
||||
if (hasDye)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ret |= ImGuiUtil.Checkbox( "##dyeDiffuse", "Apply Diffuse Color on Dye", dye.Diffuse,
|
||||
b => { tab.Mtrl.ColorDyeSets[ colorSetIdx ].Rows[ rowIdx ].Diffuse = b; tab.UpdateColorSetRowPreview(rowIdx); }, ImGuiHoveredFlags.AllowWhenDisabled );
|
||||
ret |= ImGuiUtil.Checkbox("##dyeDiffuse", "Apply Diffuse Color on Dye", dye.Diffuse,
|
||||
b =>
|
||||
{
|
||||
tab.Mtrl.ColorDyeSets[colorSetIdx].Rows[rowIdx].Diffuse = b;
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
}, ImGuiHoveredFlags.AllowWhenDisabled);
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ret |= ColorPicker( "##Specular", "Specular Color", row.Specular, c => { tab.Mtrl.ColorSets[ colorSetIdx ].Rows[ rowIdx ].Specular = c; tab.UpdateColorSetRowPreview(rowIdx); } );
|
||||
ret |= ColorPicker("##Specular", "Specular Color", row.Specular, c =>
|
||||
{
|
||||
tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].Specular = c;
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
});
|
||||
ImGui.SameLine();
|
||||
var tmpFloat = row.SpecularStrength;
|
||||
ImGui.SetNextItemWidth( floatSize );
|
||||
if( ImGui.DragFloat( "##SpecularStrength", ref tmpFloat, 0.1f, 0f, HalfMaxValue, "%.2f" ) && FixFloat( ref tmpFloat, row.SpecularStrength ) )
|
||||
ImGui.SetNextItemWidth(floatSize);
|
||||
if (ImGui.DragFloat("##SpecularStrength", ref tmpFloat, 0.1f, 0f, HalfMaxValue, "%.2f") && FixFloat(ref tmpFloat, row.SpecularStrength))
|
||||
{
|
||||
tab.Mtrl.ColorSets[ colorSetIdx ].Rows[ rowIdx ].SpecularStrength = tmpFloat;
|
||||
ret = true;
|
||||
tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].SpecularStrength = tmpFloat;
|
||||
ret = true;
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip( "Specular Strength", ImGuiHoveredFlags.AllowWhenDisabled );
|
||||
ImGuiUtil.HoverTooltip("Specular Strength", ImGuiHoveredFlags.AllowWhenDisabled);
|
||||
|
||||
if( hasDye )
|
||||
if (hasDye)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ret |= ImGuiUtil.Checkbox( "##dyeSpecular", "Apply Specular Color on Dye", dye.Specular,
|
||||
b => { tab.Mtrl.ColorDyeSets[ colorSetIdx ].Rows[ rowIdx ].Specular = b; tab.UpdateColorSetRowPreview(rowIdx); }, ImGuiHoveredFlags.AllowWhenDisabled );
|
||||
ret |= ImGuiUtil.Checkbox("##dyeSpecular", "Apply Specular Color on Dye", dye.Specular,
|
||||
b =>
|
||||
{
|
||||
tab.Mtrl.ColorDyeSets[colorSetIdx].Rows[rowIdx].Specular = b;
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
}, ImGuiHoveredFlags.AllowWhenDisabled);
|
||||
ImGui.SameLine();
|
||||
ret |= ImGuiUtil.Checkbox( "##dyeSpecularStrength", "Apply Specular Strength on Dye", dye.SpecularStrength,
|
||||
b => { tab.Mtrl.ColorDyeSets[ colorSetIdx ].Rows[ rowIdx ].SpecularStrength = b; tab.UpdateColorSetRowPreview(rowIdx); }, ImGuiHoveredFlags.AllowWhenDisabled );
|
||||
ret |= ImGuiUtil.Checkbox("##dyeSpecularStrength", "Apply Specular Strength on Dye", dye.SpecularStrength,
|
||||
b =>
|
||||
{
|
||||
tab.Mtrl.ColorDyeSets[colorSetIdx].Rows[rowIdx].SpecularStrength = b;
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
}, ImGuiHoveredFlags.AllowWhenDisabled);
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ret |= ColorPicker( "##Emissive", "Emissive Color", row.Emissive, c => { tab.Mtrl.ColorSets[ colorSetIdx ].Rows[ rowIdx ].Emissive = c; tab.UpdateColorSetRowPreview(rowIdx); } );
|
||||
if( hasDye )
|
||||
ret |= ColorPicker("##Emissive", "Emissive Color", row.Emissive, c =>
|
||||
{
|
||||
tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].Emissive = c;
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
});
|
||||
if (hasDye)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ret |= ImGuiUtil.Checkbox( "##dyeEmissive", "Apply Emissive Color on Dye", dye.Emissive,
|
||||
b => { tab.Mtrl.ColorDyeSets[ colorSetIdx ].Rows[ rowIdx ].Emissive = b; tab.UpdateColorSetRowPreview(rowIdx); }, ImGuiHoveredFlags.AllowWhenDisabled );
|
||||
ret |= ImGuiUtil.Checkbox("##dyeEmissive", "Apply Emissive Color on Dye", dye.Emissive,
|
||||
b =>
|
||||
{
|
||||
tab.Mtrl.ColorDyeSets[colorSetIdx].Rows[rowIdx].Emissive = b;
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
}, ImGuiHoveredFlags.AllowWhenDisabled);
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
tmpFloat = row.GlossStrength;
|
||||
ImGui.SetNextItemWidth( floatSize );
|
||||
if( ImGui.DragFloat( "##GlossStrength", ref tmpFloat, Math.Max( 0.1f, tmpFloat * 0.025f ), HalfEpsilon, HalfMaxValue, "%.1f" ) && FixFloat( ref tmpFloat, row.GlossStrength ) )
|
||||
ImGui.SetNextItemWidth(floatSize);
|
||||
if (ImGui.DragFloat("##GlossStrength", ref tmpFloat, Math.Max(0.1f, tmpFloat * 0.025f), HalfEpsilon, HalfMaxValue, "%.1f")
|
||||
&& FixFloat(ref tmpFloat, row.GlossStrength))
|
||||
{
|
||||
tab.Mtrl.ColorSets[ colorSetIdx ].Rows[ rowIdx ].GlossStrength = Math.Max(tmpFloat, HalfEpsilon);
|
||||
ret = true;
|
||||
tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].GlossStrength = Math.Max(tmpFloat, HalfEpsilon);
|
||||
ret = true;
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip( "Gloss Strength", ImGuiHoveredFlags.AllowWhenDisabled );
|
||||
if( hasDye )
|
||||
ImGuiUtil.HoverTooltip("Gloss Strength", ImGuiHoveredFlags.AllowWhenDisabled);
|
||||
if (hasDye)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ret |= ImGuiUtil.Checkbox( "##dyeGloss", "Apply Gloss Strength on Dye", dye.Gloss,
|
||||
b => { tab.Mtrl.ColorDyeSets[ colorSetIdx ].Rows[ rowIdx ].Gloss = b; tab.UpdateColorSetRowPreview(rowIdx); }, ImGuiHoveredFlags.AllowWhenDisabled );
|
||||
ret |= ImGuiUtil.Checkbox("##dyeGloss", "Apply Gloss Strength on Dye", dye.Gloss,
|
||||
b =>
|
||||
{
|
||||
tab.Mtrl.ColorDyeSets[colorSetIdx].Rows[rowIdx].Gloss = b;
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
}, ImGuiHoveredFlags.AllowWhenDisabled);
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
int tmpInt = row.TileSet;
|
||||
ImGui.SetNextItemWidth( intSize );
|
||||
if( ImGui.DragInt( "##TileSet", ref tmpInt, 0.25f, 0, 63 ) && tmpInt != row.TileSet && tmpInt is >= 0 and <= ushort.MaxValue )
|
||||
ImGui.SetNextItemWidth(intSize);
|
||||
if (ImGui.DragInt("##TileSet", ref tmpInt, 0.25f, 0, 63) && tmpInt != row.TileSet && tmpInt is >= 0 and <= ushort.MaxValue)
|
||||
{
|
||||
tab.Mtrl.ColorSets[ colorSetIdx ].Rows[ rowIdx ].TileSet = ( ushort )Math.Clamp(tmpInt, 0, 63);
|
||||
ret = true;
|
||||
tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].TileSet = (ushort)Math.Clamp(tmpInt, 0, 63);
|
||||
ret = true;
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip( "Tile Set", ImGuiHoveredFlags.AllowWhenDisabled );
|
||||
ImGuiUtil.HoverTooltip("Tile Set", ImGuiHoveredFlags.AllowWhenDisabled);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
tmpFloat = row.MaterialRepeat.X;
|
||||
ImGui.SetNextItemWidth( floatSize );
|
||||
if( ImGui.DragFloat( "##RepeatX", ref tmpFloat, 0.1f, HalfMinValue, HalfMaxValue, "%.2f" ) && FixFloat( ref tmpFloat, row.MaterialRepeat.X ) )
|
||||
ImGui.SetNextItemWidth(floatSize);
|
||||
if (ImGui.DragFloat("##RepeatX", ref tmpFloat, 0.1f, HalfMinValue, HalfMaxValue, "%.2f")
|
||||
&& FixFloat(ref tmpFloat, row.MaterialRepeat.X))
|
||||
{
|
||||
tab.Mtrl.ColorSets[ colorSetIdx ].Rows[ rowIdx ].MaterialRepeat = row.MaterialRepeat with { X = tmpFloat };
|
||||
ret = true;
|
||||
tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].MaterialRepeat = row.MaterialRepeat with { X = tmpFloat };
|
||||
ret = true;
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip( "Repeat X", ImGuiHoveredFlags.AllowWhenDisabled );
|
||||
ImGuiUtil.HoverTooltip("Repeat X", ImGuiHoveredFlags.AllowWhenDisabled);
|
||||
ImGui.SameLine();
|
||||
tmpFloat = row.MaterialRepeat.Y;
|
||||
ImGui.SetNextItemWidth( floatSize );
|
||||
if( ImGui.DragFloat( "##RepeatY", ref tmpFloat, 0.1f, HalfMinValue, HalfMaxValue, "%.2f" ) && FixFloat( ref tmpFloat, row.MaterialRepeat.Y ) )
|
||||
ImGui.SetNextItemWidth(floatSize);
|
||||
if (ImGui.DragFloat("##RepeatY", ref tmpFloat, 0.1f, HalfMinValue, HalfMaxValue, "%.2f")
|
||||
&& FixFloat(ref tmpFloat, row.MaterialRepeat.Y))
|
||||
{
|
||||
tab.Mtrl.ColorSets[ colorSetIdx ].Rows[ rowIdx ].MaterialRepeat = row.MaterialRepeat with { Y = tmpFloat };
|
||||
ret = true;
|
||||
tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].MaterialRepeat = row.MaterialRepeat with { Y = tmpFloat };
|
||||
ret = true;
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip( "Repeat Y", ImGuiHoveredFlags.AllowWhenDisabled );
|
||||
ImGuiUtil.HoverTooltip("Repeat Y", ImGuiHoveredFlags.AllowWhenDisabled);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
tmpFloat = row.MaterialSkew.X;
|
||||
ImGui.SetNextItemWidth( floatSize );
|
||||
if( ImGui.DragFloat( "##SkewX", ref tmpFloat, 0.1f, HalfMinValue, HalfMaxValue, "%.2f" ) && FixFloat( ref tmpFloat, row.MaterialSkew.X ) )
|
||||
ImGui.SetNextItemWidth(floatSize);
|
||||
if (ImGui.DragFloat("##SkewX", ref tmpFloat, 0.1f, HalfMinValue, HalfMaxValue, "%.2f") && FixFloat(ref tmpFloat, row.MaterialSkew.X))
|
||||
{
|
||||
tab.Mtrl.ColorSets[ colorSetIdx ].Rows[ rowIdx ].MaterialSkew = row.MaterialSkew with { X = tmpFloat };
|
||||
ret = true;
|
||||
tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].MaterialSkew = row.MaterialSkew with { X = tmpFloat };
|
||||
ret = true;
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip( "Skew X", ImGuiHoveredFlags.AllowWhenDisabled );
|
||||
ImGuiUtil.HoverTooltip("Skew X", ImGuiHoveredFlags.AllowWhenDisabled);
|
||||
|
||||
ImGui.SameLine();
|
||||
tmpFloat = row.MaterialSkew.Y;
|
||||
ImGui.SetNextItemWidth( floatSize );
|
||||
if( ImGui.DragFloat( "##SkewY", ref tmpFloat, 0.1f, HalfMinValue, HalfMaxValue, "%.2f" ) && FixFloat( ref tmpFloat, row.MaterialSkew.Y ) )
|
||||
ImGui.SetNextItemWidth(floatSize);
|
||||
if (ImGui.DragFloat("##SkewY", ref tmpFloat, 0.1f, HalfMinValue, HalfMaxValue, "%.2f") && FixFloat(ref tmpFloat, row.MaterialSkew.Y))
|
||||
{
|
||||
tab.Mtrl.ColorSets[ colorSetIdx ].Rows[ rowIdx ].MaterialSkew = row.MaterialSkew with { Y = tmpFloat };
|
||||
ret = true;
|
||||
tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].MaterialSkew = row.MaterialSkew with { Y = tmpFloat };
|
||||
ret = true;
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip( "Skew Y", ImGuiHoveredFlags.AllowWhenDisabled );
|
||||
ImGuiUtil.HoverTooltip("Skew Y", ImGuiHoveredFlags.AllowWhenDisabled);
|
||||
|
||||
if( hasDye )
|
||||
if (hasDye)
|
||||
{
|
||||
ImGui.TableNextColumn();
|
||||
if (_stainService.TemplateCombo.Draw( "##dyeTemplate", dye.Template.ToString(), string.Empty, intSize
|
||||
+ ImGui.GetStyle().ScrollbarSize / 2, ImGui.GetTextLineHeightWithSpacing(), ImGuiComboFlags.NoArrowButton ) )
|
||||
if (_stainService.TemplateCombo.Draw("##dyeTemplate", dye.Template.ToString(), string.Empty, intSize
|
||||
+ ImGui.GetStyle().ScrollbarSize / 2, ImGui.GetTextLineHeightWithSpacing(), ImGuiComboFlags.NoArrowButton))
|
||||
{
|
||||
tab.Mtrl.ColorDyeSets[ colorSetIdx ].Rows[ rowIdx ].Template = _stainService.TemplateCombo.CurrentSelection;
|
||||
ret = true;
|
||||
tab.Mtrl.ColorDyeSets[colorSetIdx].Rows[rowIdx].Template = _stainService.TemplateCombo.CurrentSelection;
|
||||
ret = true;
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip( "Dye Template", ImGuiHoveredFlags.AllowWhenDisabled );
|
||||
ImGuiUtil.HoverTooltip("Dye Template", ImGuiHoveredFlags.AllowWhenDisabled);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ret |= DrawDyePreview( tab, colorSetIdx, rowIdx, disabled, dye, floatSize );
|
||||
ret |= DrawDyePreview(tab, colorSetIdx, rowIdx, disabled, dye, floatSize);
|
||||
}
|
||||
else if ( hasAnyDye )
|
||||
else if (hasAnyDye)
|
||||
{
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableNextColumn();
|
||||
|
|
@ -445,63 +465,65 @@ public partial class ModEditWindow
|
|||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawDyePreview( MtrlTab tab, int colorSetIdx, int rowIdx, bool disabled, MtrlFile.ColorDyeSet.Row dye, float floatSize )
|
||||
private bool DrawDyePreview(MtrlTab tab, int colorSetIdx, int rowIdx, bool disabled, MtrlFile.ColorDyeSet.Row dye, float floatSize)
|
||||
{
|
||||
var stain = _stainService.StainCombo.CurrentSelection.Key;
|
||||
if( stain == 0 || !_stainService.StmFile.Entries.TryGetValue( dye.Template, out var entry ) )
|
||||
{
|
||||
if (stain == 0 || !_stainService.StmFile.Entries.TryGetValue(dye.Template, out var entry))
|
||||
return false;
|
||||
}
|
||||
|
||||
var values = entry[ ( int )stain ];
|
||||
using var style = ImRaii.PushStyle( ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemSpacing / 2 );
|
||||
var values = entry[(int)stain];
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemSpacing / 2);
|
||||
|
||||
var ret = ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.PaintBrush.ToIconString(), new Vector2( ImGui.GetFrameHeight() ),
|
||||
"Apply the selected dye to this row.", disabled, true );
|
||||
var ret = ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.PaintBrush.ToIconString(), new Vector2(ImGui.GetFrameHeight()),
|
||||
"Apply the selected dye to this row.", disabled, true);
|
||||
|
||||
ret = ret && tab.Mtrl.ApplyDyeTemplate(_stainService.StmFile, colorSetIdx, rowIdx, stain );
|
||||
ret = ret && tab.Mtrl.ApplyDyeTemplate(_stainService.StmFile, colorSetIdx, rowIdx, stain);
|
||||
if (ret)
|
||||
tab.UpdateColorSetRowPreview(rowIdx);
|
||||
|
||||
ImGui.SameLine();
|
||||
ColorPicker( "##diffusePreview", string.Empty, values.Diffuse, _ => { }, "D" );
|
||||
ColorPicker("##diffusePreview", string.Empty, values.Diffuse, _ => { }, "D");
|
||||
ImGui.SameLine();
|
||||
ColorPicker( "##specularPreview", string.Empty, values.Specular, _ => { }, "S" );
|
||||
ColorPicker("##specularPreview", string.Empty, values.Specular, _ => { }, "S");
|
||||
ImGui.SameLine();
|
||||
ColorPicker( "##emissivePreview", string.Empty, values.Emissive, _ => { }, "E" );
|
||||
ColorPicker("##emissivePreview", string.Empty, values.Emissive, _ => { }, "E");
|
||||
ImGui.SameLine();
|
||||
using var dis = ImRaii.Disabled();
|
||||
ImGui.SetNextItemWidth( floatSize );
|
||||
ImGui.DragFloat( "##gloss", ref values.Gloss, 0, values.Gloss, values.Gloss, "%.1f G" );
|
||||
ImGui.SetNextItemWidth(floatSize);
|
||||
ImGui.DragFloat("##gloss", ref values.Gloss, 0, values.Gloss, values.Gloss, "%.1f G");
|
||||
ImGui.SameLine();
|
||||
ImGui.SetNextItemWidth( floatSize );
|
||||
ImGui.DragFloat( "##specularStrength", ref values.SpecularPower, 0, values.SpecularPower, values.SpecularPower, "%.2f S" );
|
||||
ImGui.SetNextItemWidth(floatSize);
|
||||
ImGui.DragFloat("##specularStrength", ref values.SpecularPower, 0, values.SpecularPower, values.SpecularPower, "%.2f S");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool ColorPicker( string label, string tooltip, Vector3 input, Action< Vector3 > setter, string letter = "" )
|
||||
private static bool ColorPicker(string label, string tooltip, Vector3 input, Action<Vector3> setter, string letter = "")
|
||||
{
|
||||
var ret = false;
|
||||
var inputSqrt = PseudoSqrtRgb( input );
|
||||
var tmp = inputSqrt;
|
||||
if( ImGui.ColorEdit3( label, ref tmp,
|
||||
ImGuiColorEditFlags.NoInputs | ImGuiColorEditFlags.DisplayRGB | ImGuiColorEditFlags.InputRGB | ImGuiColorEditFlags.NoTooltip | ImGuiColorEditFlags.HDR )
|
||||
&& tmp != inputSqrt )
|
||||
var ret = false;
|
||||
var inputSqrt = PseudoSqrtRgb(input);
|
||||
var tmp = inputSqrt;
|
||||
if (ImGui.ColorEdit3(label, ref tmp,
|
||||
ImGuiColorEditFlags.NoInputs
|
||||
| ImGuiColorEditFlags.DisplayRGB
|
||||
| ImGuiColorEditFlags.InputRGB
|
||||
| ImGuiColorEditFlags.NoTooltip
|
||||
| ImGuiColorEditFlags.HDR)
|
||||
&& tmp != inputSqrt)
|
||||
{
|
||||
setter( PseudoSquareRgb( tmp ) );
|
||||
setter(PseudoSquareRgb(tmp));
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if( letter.Length > 0 && ImGui.IsItemVisible() )
|
||||
if (letter.Length > 0 && ImGui.IsItemVisible())
|
||||
{
|
||||
var textSize = ImGui.CalcTextSize( letter );
|
||||
var center = ImGui.GetItemRectMin() + ( ImGui.GetItemRectSize() - textSize ) / 2;
|
||||
var textSize = ImGui.CalcTextSize(letter);
|
||||
var center = ImGui.GetItemRectMin() + (ImGui.GetItemRectSize() - textSize) / 2;
|
||||
var textColor = input.LengthSquared() < 0.25f ? 0x80FFFFFFu : 0x80000000u;
|
||||
ImGui.GetWindowDrawList().AddText( center, textColor, letter );
|
||||
ImGui.GetWindowDrawList().AddText(center, textColor, letter);
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip( tooltip, ImGuiHoveredFlags.AllowWhenDisabled );
|
||||
ImGuiUtil.HoverTooltip(tooltip, ImGuiHoveredFlags.AllowWhenDisabled);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -509,7 +531,7 @@ public partial class ModEditWindow
|
|||
// Functions to deal with squared RGB values without making negatives useless.
|
||||
|
||||
private static float PseudoSquareRgb(float x)
|
||||
=> x < 0.0f ? -(x * x) : (x * x);
|
||||
=> x < 0.0f ? -(x * x) : x * x;
|
||||
|
||||
private static Vector3 PseudoSquareRgb(Vector3 vec)
|
||||
=> new(PseudoSquareRgb(vec.X), PseudoSquareRgb(vec.Y), PseudoSquareRgb(vec.Z));
|
||||
|
|
@ -525,4 +547,4 @@ public partial class ModEditWindow
|
|||
|
||||
private static Vector4 PseudoSqrtRgb(Vector4 vec)
|
||||
=> new(PseudoSqrtRgb(vec.X), PseudoSqrtRgb(vec.Y), PseudoSqrtRgb(vec.Z), vec.W);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Numerics;
|
||||
using ImGuiNET;
|
||||
using OtterGui.Raii;
|
||||
|
|
@ -27,7 +28,8 @@ public partial class ModEditWindow
|
|||
private readonly float _bias;
|
||||
private readonly string _format;
|
||||
|
||||
public FloatConstantEditor(float? minimum, float? maximum, float speed, float relativeSpeed, float factor, float bias, byte precision, string unit)
|
||||
public FloatConstantEditor(float? minimum, float? maximum, float speed, float relativeSpeed, float factor, float bias, byte precision,
|
||||
string unit)
|
||||
{
|
||||
_minimum = minimum;
|
||||
_maximum = maximum;
|
||||
|
|
@ -55,10 +57,13 @@ public partial class ModEditWindow
|
|||
|
||||
var value = (values[valueIdx] - _bias) / _factor;
|
||||
if (disabled)
|
||||
{
|
||||
ImGui.DragFloat($"##{valueIdx}", ref value, Math.Max(_speed, value * _relativeSpeed), value, value, _format);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui.DragFloat($"##{valueIdx}", ref value, Math.Max(_speed, value * _relativeSpeed), _minimum ?? 0.0f, _maximum ?? 0.0f, _format))
|
||||
if (ImGui.DragFloat($"##{valueIdx}", ref value, Math.Max(_speed, value * _relativeSpeed), _minimum ?? 0.0f,
|
||||
_maximum ?? 0.0f, _format))
|
||||
{
|
||||
values[valueIdx] = Clamp(value) * _factor + _bias;
|
||||
ret = true;
|
||||
|
|
@ -111,10 +116,13 @@ public partial class ModEditWindow
|
|||
|
||||
var value = (int)Math.Clamp(MathF.Round((values[valueIdx] - _bias) / _factor), int.MinValue, int.MaxValue);
|
||||
if (disabled)
|
||||
{
|
||||
ImGui.DragInt($"##{valueIdx}", ref value, Math.Max(_speed, value * _relativeSpeed), value, value, _format);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui.DragInt($"##{valueIdx}", ref value, Math.Max(_speed, value * _relativeSpeed), _minimum ?? 0, _maximum ?? 0, _format))
|
||||
if (ImGui.DragInt($"##{valueIdx}", ref value, Math.Max(_speed, value * _relativeSpeed), _minimum ?? 0, _maximum ?? 0,
|
||||
_format))
|
||||
{
|
||||
values[valueIdx] = Clamp(value) * _factor + _bias;
|
||||
ret = true;
|
||||
|
|
@ -142,14 +150,17 @@ public partial class ModEditWindow
|
|||
|
||||
public bool Draw(Span<float> values, bool disabled, float editorWidth)
|
||||
{
|
||||
if (values.Length == 3)
|
||||
switch (values.Length)
|
||||
{
|
||||
ImGui.SetNextItemWidth(editorWidth);
|
||||
var value = new Vector3(values);
|
||||
if (_squaredRgb)
|
||||
value = PseudoSqrtRgb(value);
|
||||
if (ImGui.ColorEdit3("##0", ref value, ImGuiColorEditFlags.Float | (_clamped ? 0 : ImGuiColorEditFlags.HDR)) && !disabled)
|
||||
case 3:
|
||||
{
|
||||
ImGui.SetNextItemWidth(editorWidth);
|
||||
var value = new Vector3(values);
|
||||
if (_squaredRgb)
|
||||
value = PseudoSqrtRgb(value);
|
||||
if (!ImGui.ColorEdit3("##0", ref value, ImGuiColorEditFlags.Float | (_clamped ? 0 : ImGuiColorEditFlags.HDR)) || disabled)
|
||||
return false;
|
||||
|
||||
if (_squaredRgb)
|
||||
value = PseudoSquareRgb(value);
|
||||
if (_clamped)
|
||||
|
|
@ -157,17 +168,17 @@ public partial class ModEditWindow
|
|||
value.CopyTo(values);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (values.Length == 4)
|
||||
{
|
||||
ImGui.SetNextItemWidth(editorWidth);
|
||||
var value = new Vector4(values);
|
||||
if (_squaredRgb)
|
||||
value = PseudoSqrtRgb(value);
|
||||
if (ImGui.ColorEdit4("##0", ref value, ImGuiColorEditFlags.Float | ImGuiColorEditFlags.AlphaPreviewHalf | (_clamped ? 0 : ImGuiColorEditFlags.HDR)) && !disabled)
|
||||
case 4:
|
||||
{
|
||||
ImGui.SetNextItemWidth(editorWidth);
|
||||
var value = new Vector4(values);
|
||||
if (_squaredRgb)
|
||||
value = PseudoSqrtRgb(value);
|
||||
if (!ImGui.ColorEdit4("##0", ref value,
|
||||
ImGuiColorEditFlags.Float | ImGuiColorEditFlags.AlphaPreviewHalf | (_clamped ? 0 : ImGuiColorEditFlags.HDR))
|
||||
|| disabled)
|
||||
return false;
|
||||
|
||||
if (_squaredRgb)
|
||||
value = PseudoSquareRgb(value);
|
||||
if (_clamped)
|
||||
|
|
@ -175,11 +186,8 @@ public partial class ModEditWindow
|
|||
value.CopyTo(values);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
default: return FloatConstantEditor.Default.Draw(values, disabled, editorWidth);
|
||||
}
|
||||
else
|
||||
return FloatConstantEditor.Default.Draw(values, disabled, editorWidth);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -188,9 +196,7 @@ public partial class ModEditWindow
|
|||
private readonly IReadOnlyList<(string Label, float Value, string Description)> _values;
|
||||
|
||||
public EnumConstantEditor(IReadOnlyList<(string Label, float Value, string Description)> values)
|
||||
{
|
||||
_values = values;
|
||||
}
|
||||
=> _values = values;
|
||||
|
||||
public bool Draw(Span<float> values, bool disabled, float editorWidth)
|
||||
{
|
||||
|
|
@ -200,33 +206,40 @@ public partial class ModEditWindow
|
|||
|
||||
for (var valueIdx = 0; valueIdx < values.Length; ++valueIdx)
|
||||
{
|
||||
using var id = ImRaii.PushId(valueIdx);
|
||||
if (valueIdx > 0)
|
||||
ImGui.SameLine();
|
||||
|
||||
ImGui.SetNextItemWidth(MathF.Round(fieldWidth * (valueIdx + 1)) - MathF.Round(fieldWidth * valueIdx));
|
||||
|
||||
var currentValue = values[valueIdx];
|
||||
var (currentLabel, _, currentDescription) = _values.FirstOrNull(v => v.Value == currentValue) ?? (currentValue.ToString(), currentValue, string.Empty);
|
||||
if (disabled)
|
||||
ImGui.InputText($"##{valueIdx}", ref currentLabel, (uint)currentLabel.Length, ImGuiInputTextFlags.ReadOnly);
|
||||
else
|
||||
{
|
||||
using var c = ImRaii.Combo($"##{valueIdx}", currentLabel);
|
||||
{
|
||||
if (c)
|
||||
foreach (var (valueLabel, value, valueDescription) in _values)
|
||||
{
|
||||
if (ImGui.Selectable(valueLabel, value == currentValue))
|
||||
{
|
||||
values[valueIdx] = value;
|
||||
ret = true;
|
||||
}
|
||||
var currentLabel = _values.FirstOrNull(v => v.Value == currentValue)?.Label
|
||||
?? currentValue.ToString(CultureInfo.CurrentCulture);
|
||||
ret = disabled
|
||||
? ImGui.InputText(string.Empty, ref currentLabel, (uint)currentLabel.Length, ImGuiInputTextFlags.ReadOnly)
|
||||
: DrawCombo(currentLabel, ref values[valueIdx]);
|
||||
}
|
||||
|
||||
if (valueDescription.Length > 0)
|
||||
ImGuiUtil.SelectableHelpMarker(valueDescription);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawCombo(string label, ref float currentValue)
|
||||
{
|
||||
using var c = ImRaii.Combo(string.Empty, label);
|
||||
if (!c)
|
||||
return false;
|
||||
|
||||
var ret = false;
|
||||
foreach (var (valueLabel, value, valueDescription) in _values)
|
||||
{
|
||||
if (ImGui.Selectable(valueLabel, value == currentValue))
|
||||
{
|
||||
currentValue = value;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (valueDescription.Length > 0)
|
||||
ImGuiUtil.SelectableHelpMarker(valueDescription);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using System.Linq;
|
|||
using System.Numerics;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Internal.Notifications;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using ImGuiNET;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
|
@ -17,10 +16,8 @@ using Penumbra.GameData;
|
|||
using Penumbra.GameData.Data;
|
||||
using Penumbra.GameData.Files;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Penumbra.Services;
|
||||
using Penumbra.String;
|
||||
using Penumbra.String.Classes;
|
||||
using Penumbra.Util;
|
||||
using static Penumbra.GameData.Files.ShpkFile;
|
||||
|
||||
namespace Penumbra.UI.AdvancedWindow;
|
||||
|
|
@ -48,28 +45,32 @@ public partial class ModEditWindow
|
|||
public ShpkFile? AssociatedShpk;
|
||||
public JObject? AssociatedShpkDevkit;
|
||||
|
||||
public readonly string LoadedBaseDevkitPathName = string.Empty;
|
||||
public readonly string LoadedBaseDevkitPathName;
|
||||
public readonly JObject? AssociatedBaseDevkit;
|
||||
|
||||
// Shader Key State
|
||||
public readonly List< (string Label, int Index, string Description, bool MonoFont, IReadOnlyList< (string Label, uint Value, string Description) > Values) > ShaderKeys = new(16);
|
||||
public readonly
|
||||
List<(string Label, int Index, string Description, bool MonoFont, IReadOnlyList<(string Label, uint Value, string Description)>
|
||||
Values)> ShaderKeys = new(16);
|
||||
|
||||
public readonly HashSet< int > VertexShaders = new(16);
|
||||
public readonly HashSet< int > PixelShaders = new(16);
|
||||
public bool ShadersKnown = false;
|
||||
public string VertexShadersString = "Vertex Shaders: ???";
|
||||
public string PixelShadersString = "Pixel Shaders: ???";
|
||||
public readonly HashSet<int> VertexShaders = new(16);
|
||||
public readonly HashSet<int> PixelShaders = new(16);
|
||||
public bool ShadersKnown;
|
||||
public string VertexShadersString = "Vertex Shaders: ???";
|
||||
public string PixelShadersString = "Pixel Shaders: ???";
|
||||
|
||||
// Textures & Samplers
|
||||
public readonly List< (string Label, int TextureIndex, int SamplerIndex, string Description, bool MonoFont) > Textures = new(4);
|
||||
public readonly List<(string Label, int TextureIndex, int SamplerIndex, string Description, bool MonoFont)> Textures = new(4);
|
||||
|
||||
public readonly HashSet< int > UnfoldedTextures = new(4);
|
||||
public readonly HashSet< uint > SamplerIds = new(16);
|
||||
public float TextureLabelWidth;
|
||||
public bool UseColorDyeSet;
|
||||
public readonly HashSet<int> UnfoldedTextures = new(4);
|
||||
public readonly HashSet<uint> SamplerIds = new(16);
|
||||
public float TextureLabelWidth;
|
||||
public bool UseColorDyeSet;
|
||||
|
||||
// Material Constants
|
||||
public readonly List< (string Header, List< (string Label, int ConstantIndex, Range Slice, string Description, bool MonoFont, IConstantEditor Editor) > Constants) > Constants = new(16);
|
||||
public readonly
|
||||
List<(string Header, List<(string Label, int ConstantIndex, Range Slice, string Description, bool MonoFont, IConstantEditor Editor)>
|
||||
Constants)> Constants = new(16);
|
||||
|
||||
// Live-Previewers
|
||||
public readonly List<LiveMaterialPreviewer> MaterialPreviewers = new(4);
|
||||
|
|
@ -77,15 +78,13 @@ public partial class ModEditWindow
|
|||
public int HighlightedColorSetRow = -1;
|
||||
public readonly Stopwatch HighlightTime = new();
|
||||
|
||||
public FullPath FindAssociatedShpk( out string defaultPath, out Utf8GamePath defaultGamePath )
|
||||
public FullPath FindAssociatedShpk(out string defaultPath, out Utf8GamePath defaultGamePath)
|
||||
{
|
||||
defaultPath = GamePaths.Shader.ShpkPath( Mtrl.ShaderPackage.Name );
|
||||
if( !Utf8GamePath.FromString( defaultPath, out defaultGamePath, true ) )
|
||||
{
|
||||
defaultPath = GamePaths.Shader.ShpkPath(Mtrl.ShaderPackage.Name);
|
||||
if (!Utf8GamePath.FromString(defaultPath, out defaultGamePath, true))
|
||||
return FullPath.Empty;
|
||||
}
|
||||
|
||||
return _edit.FindBestMatch( defaultGamePath );
|
||||
return _edit.FindBestMatch(defaultGamePath);
|
||||
}
|
||||
|
||||
public string[] GetShpkNames()
|
||||
|
|
@ -102,7 +101,7 @@ public partial class ModEditWindow
|
|||
return _shpkNames;
|
||||
}
|
||||
|
||||
public void LoadShpk( FullPath path )
|
||||
public void LoadShpk(FullPath path)
|
||||
{
|
||||
ShaderHeader = $"Shader ({Mtrl.ShaderPackage.Name})###Shader";
|
||||
|
||||
|
|
@ -110,26 +109,30 @@ public partial class ModEditWindow
|
|||
{
|
||||
LoadedShpkPath = path;
|
||||
var data = LoadedShpkPath.IsRooted
|
||||
? File.ReadAllBytes( LoadedShpkPath.FullName )
|
||||
: _edit._dalamud.GameData.GetFile( LoadedShpkPath.InternalName.ToString() )?.Data;
|
||||
AssociatedShpk = data?.Length > 0 ? new ShpkFile( data ) : throw new Exception( "Failure to load file data." );
|
||||
? File.ReadAllBytes(LoadedShpkPath.FullName)
|
||||
: _edit._dalamud.GameData.GetFile(LoadedShpkPath.InternalName.ToString())?.Data;
|
||||
AssociatedShpk = data?.Length > 0 ? new ShpkFile(data) : throw new Exception("Failure to load file data.");
|
||||
LoadedShpkPathName = path.ToPath();
|
||||
}
|
||||
catch( Exception e )
|
||||
catch (Exception e)
|
||||
{
|
||||
LoadedShpkPath = FullPath.Empty;
|
||||
LoadedShpkPathName = string.Empty;
|
||||
AssociatedShpk = null;
|
||||
Penumbra.Chat.NotificationMessage( $"Could not load {LoadedShpkPath.ToPath()}:\n{e}", "Penumbra Advanced Editing", NotificationType.Error );
|
||||
Penumbra.Chat.NotificationMessage($"Could not load {LoadedShpkPath.ToPath()}:\n{e}", "Penumbra Advanced Editing",
|
||||
NotificationType.Error);
|
||||
}
|
||||
|
||||
if( LoadedShpkPath.InternalName.IsEmpty )
|
||||
if (LoadedShpkPath.InternalName.IsEmpty)
|
||||
{
|
||||
AssociatedShpkDevkit = null;
|
||||
LoadedShpkDevkitPathName = string.Empty;
|
||||
}
|
||||
else
|
||||
AssociatedShpkDevkit = TryLoadShpkDevkit( Path.GetFileNameWithoutExtension( Mtrl.ShaderPackage.Name ), out LoadedShpkDevkitPathName );
|
||||
{
|
||||
AssociatedShpkDevkit =
|
||||
TryLoadShpkDevkit(Path.GetFileNameWithoutExtension(Mtrl.ShaderPackage.Name), out LoadedShpkDevkitPathName);
|
||||
}
|
||||
|
||||
UpdateShaderKeys();
|
||||
Update();
|
||||
|
|
@ -157,10 +160,8 @@ public partial class ModEditWindow
|
|||
}
|
||||
|
||||
private T? TryGetShpkDevkitData<T>(string category, uint? id, bool mayVary) where T : class
|
||||
{
|
||||
return TryGetShpkDevkitData<T>(AssociatedShpkDevkit, LoadedShpkDevkitPathName, category, id, mayVary)
|
||||
?? TryGetShpkDevkitData<T>(AssociatedBaseDevkit, LoadedBaseDevkitPathName, category, id, mayVary);
|
||||
}
|
||||
=> TryGetShpkDevkitData<T>(AssociatedShpkDevkit, LoadedShpkDevkitPathName, category, id, mayVary)
|
||||
?? TryGetShpkDevkitData<T>(AssociatedBaseDevkit, LoadedBaseDevkitPathName, category, id, mayVary);
|
||||
|
||||
private T? TryGetShpkDevkitData<T>(JObject? devkit, string devkitPathName, string category, uint? id, bool mayVary) where T : class
|
||||
{
|
||||
|
|
@ -175,7 +176,7 @@ public partial class ModEditWindow
|
|||
|
||||
if (mayVary && (data as JObject)?["Vary"] != null)
|
||||
{
|
||||
var selector = BuildSelector(data!["Vary"]!
|
||||
var selector = BuildSelector(data["Vary"]!
|
||||
.Select(key => (uint)key)
|
||||
.Select(key => Mtrl.GetShaderKey(key)?.Value ?? AssociatedShpk!.GetMaterialKeyById(key)!.Value.DefaultValue));
|
||||
var index = (int)data["Selectors"]![selector.ToString()]!;
|
||||
|
|
@ -192,14 +193,13 @@ public partial class ModEditWindow
|
|||
}
|
||||
}
|
||||
|
||||
public void UpdateShaderKeys()
|
||||
private void UpdateShaderKeys()
|
||||
{
|
||||
ShaderKeys.Clear();
|
||||
if (AssociatedShpk != null)
|
||||
{
|
||||
foreach (var key in AssociatedShpk.MaterialKeys)
|
||||
{
|
||||
var dkData = TryGetShpkDevkitData<DevkitShaderKey>("ShaderKeys", key.Id, false);
|
||||
var dkData = TryGetShpkDevkitData<DevkitShaderKey>("ShaderKeys", key.Id, false);
|
||||
var hasDkLabel = !string.IsNullOrEmpty(dkData?.Label);
|
||||
|
||||
var valueSet = new HashSet<uint>(key.Values);
|
||||
|
|
@ -211,8 +211,8 @@ public partial class ModEditWindow
|
|||
{
|
||||
if (dkData != null && dkData.Values.TryGetValue(value, out var dkValue))
|
||||
return (dkValue.Label.Length > 0 ? dkValue.Label : $"0x{value:X8}", value, dkValue.Description);
|
||||
else
|
||||
return ($"0x{value:X8}", value, string.Empty);
|
||||
|
||||
return ($"0x{value:X8}", value, string.Empty);
|
||||
}).ToArray();
|
||||
Array.Sort(values, (x, y) =>
|
||||
{
|
||||
|
|
@ -220,31 +220,33 @@ public partial class ModEditWindow
|
|||
return -1;
|
||||
if (y.Value == key.DefaultValue)
|
||||
return 1;
|
||||
return x.Label.CompareTo(y.Label);
|
||||
|
||||
return string.Compare(x.Label, y.Label, StringComparison.Ordinal);
|
||||
});
|
||||
ShaderKeys.Add((hasDkLabel ? dkData!.Label : $"0x{key.Id:X8}", mtrlKeyIndex, dkData?.Description ?? string.Empty, !hasDkLabel, values));
|
||||
ShaderKeys.Add((hasDkLabel ? dkData!.Label : $"0x{key.Id:X8}", mtrlKeyIndex, dkData?.Description ?? string.Empty,
|
||||
!hasDkLabel, values));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var (key, index) in Mtrl.ShaderPackage.ShaderKeys.WithIndex())
|
||||
ShaderKeys.Add(($"0x{key.Category:X8}", index, string.Empty, true, Array.Empty<(string, uint, string)>()));
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateShaders()
|
||||
private void UpdateShaders()
|
||||
{
|
||||
VertexShaders.Clear();
|
||||
PixelShaders.Clear();
|
||||
if (AssociatedShpk == null)
|
||||
{
|
||||
ShadersKnown = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShadersKnown = true;
|
||||
var systemKeySelectors = AllSelectors(AssociatedShpk.SystemKeys).ToArray();
|
||||
var sceneKeySelectors = AllSelectors(AssociatedShpk.SceneKeys).ToArray();
|
||||
var subViewKeySelectors = AllSelectors(AssociatedShpk.SubViewKeys).ToArray();
|
||||
var materialKeySelector = BuildSelector(AssociatedShpk.MaterialKeys.Select(key => Mtrl.GetOrAddShaderKey(key.Id, key.DefaultValue).Value));
|
||||
var materialKeySelector =
|
||||
BuildSelector(AssociatedShpk.MaterialKeys.Select(key => Mtrl.GetOrAddShaderKey(key.Id, key.DefaultValue).Value));
|
||||
foreach (var systemKeySelector in systemKeySelectors)
|
||||
{
|
||||
foreach (var sceneKeySelector in sceneKeySelectors)
|
||||
|
|
@ -252,15 +254,13 @@ public partial class ModEditWindow
|
|||
foreach (var subViewKeySelector in subViewKeySelectors)
|
||||
{
|
||||
var selector = BuildSelector(systemKeySelector, sceneKeySelector, materialKeySelector, subViewKeySelector);
|
||||
var node = AssociatedShpk.GetNodeBySelector(selector);
|
||||
var node = AssociatedShpk.GetNodeBySelector(selector);
|
||||
if (node.HasValue)
|
||||
{
|
||||
foreach (var pass in node.Value.Passes)
|
||||
{
|
||||
VertexShaders.Add((int)pass.VertexShader);
|
||||
PixelShaders.Add((int)pass.PixelShader);
|
||||
}
|
||||
}
|
||||
else
|
||||
ShadersKnown = false;
|
||||
}
|
||||
|
|
@ -272,12 +272,12 @@ public partial class ModEditWindow
|
|||
var pixelShaders = PixelShaders.OrderBy(i => i).Select(i => $"#{i}");
|
||||
|
||||
VertexShadersString = $"Vertex Shaders: {string.Join(", ", ShadersKnown ? vertexShaders : vertexShaders.Append("???"))}";
|
||||
PixelShadersString = $"Pixel Shaders: {string.Join(", ", ShadersKnown ? pixelShaders : pixelShaders.Append("???"))}";
|
||||
PixelShadersString = $"Pixel Shaders: {string.Join(", ", ShadersKnown ? pixelShaders : pixelShaders.Append("???"))}";
|
||||
|
||||
ShaderComment = TryGetShpkDevkitData<string>("Comment", null, true) ?? string.Empty;
|
||||
}
|
||||
|
||||
public void UpdateTextures()
|
||||
private void UpdateTextures()
|
||||
{
|
||||
Textures.Clear();
|
||||
SamplerIds.Clear();
|
||||
|
|
@ -302,50 +302,63 @@ public partial class ModEditWindow
|
|||
if (Mtrl.ColorSets.Any(c => c.HasRows))
|
||||
SamplerIds.Add(TableSamplerId);
|
||||
}
|
||||
|
||||
foreach (var samplerId in SamplerIds)
|
||||
{
|
||||
var shpkSampler = AssociatedShpk.GetSamplerById(samplerId);
|
||||
if (!shpkSampler.HasValue || shpkSampler.Value.Slot != 2)
|
||||
if (shpkSampler is not { Slot: 2 })
|
||||
continue;
|
||||
|
||||
var dkData = TryGetShpkDevkitData<DevkitSampler>("Samplers", samplerId, true);
|
||||
var dkData = TryGetShpkDevkitData<DevkitSampler>("Samplers", samplerId, true);
|
||||
var hasDkLabel = !string.IsNullOrEmpty(dkData?.Label);
|
||||
|
||||
var sampler = Mtrl.GetOrAddSampler(samplerId, dkData?.DefaultTexture ?? string.Empty, out var samplerIndex);
|
||||
Textures.Add((hasDkLabel ? dkData!.Label : shpkSampler.Value.Name, sampler.TextureIndex, samplerIndex, dkData?.Description ?? string.Empty, !hasDkLabel));
|
||||
Textures.Add((hasDkLabel ? dkData!.Label : shpkSampler.Value.Name, sampler.TextureIndex, samplerIndex,
|
||||
dkData?.Description ?? string.Empty, !hasDkLabel));
|
||||
}
|
||||
|
||||
if (SamplerIds.Contains(TableSamplerId))
|
||||
Mtrl.FindOrAddColorSet();
|
||||
}
|
||||
|
||||
Textures.Sort((x, y) => string.CompareOrdinal(x.Label, y.Label));
|
||||
|
||||
TextureLabelWidth = 50f * UiHelpers.Scale;
|
||||
|
||||
float helpWidth;
|
||||
using (var _ = ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
helpWidth = ImGui.GetStyle().ItemSpacing.X + ImGui.CalcTextSize(FontAwesomeIcon.InfoCircle.ToIconString()).X;
|
||||
}
|
||||
|
||||
foreach (var (label, _, _, description, monoFont) in Textures)
|
||||
{
|
||||
if (!monoFont)
|
||||
TextureLabelWidth = Math.Max(TextureLabelWidth, ImGui.CalcTextSize(label).X + (description.Length > 0 ? helpWidth : 0.0f));
|
||||
}
|
||||
|
||||
using (var _ = ImRaii.PushFont(UiBuilder.MonoFont))
|
||||
{
|
||||
foreach (var (label, _, _, description, monoFont) in Textures)
|
||||
{
|
||||
if (monoFont)
|
||||
TextureLabelWidth = Math.Max(TextureLabelWidth, ImGui.CalcTextSize(label).X + (description.Length > 0 ? helpWidth : 0.0f));
|
||||
TextureLabelWidth = Math.Max(TextureLabelWidth,
|
||||
ImGui.CalcTextSize(label).X + (description.Length > 0 ? helpWidth : 0.0f));
|
||||
}
|
||||
}
|
||||
|
||||
TextureLabelWidth = TextureLabelWidth / UiHelpers.Scale + 4;
|
||||
}
|
||||
|
||||
public void UpdateConstants()
|
||||
private void UpdateConstants()
|
||||
{
|
||||
static List<T> FindOrAddGroup<T>(List<(string, List<T>)> groups, string name)
|
||||
{
|
||||
foreach (var (groupName, group) in groups)
|
||||
{
|
||||
if (string.Equals(name, groupName, StringComparison.Ordinal))
|
||||
return group;
|
||||
}
|
||||
|
||||
var newGroup = new List<T>(16);
|
||||
groups.Add((name, newGroup));
|
||||
|
|
@ -360,7 +373,10 @@ public partial class ModEditWindow
|
|||
{
|
||||
var values = Mtrl.GetConstantValues(constant);
|
||||
for (var i = 0; i < values.Length; i += 4)
|
||||
fcGroup.Add(($"0x{constant.Id:X8}", index, i..Math.Min(i + 4, values.Length), string.Empty, true, FloatConstantEditor.Default));
|
||||
{
|
||||
fcGroup.Add(($"0x{constant.Id:X8}", index, i..Math.Min(i + 4, values.Length), string.Empty, true,
|
||||
FloatConstantEditor.Default));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -371,13 +387,12 @@ public partial class ModEditWindow
|
|||
if ((shpkConstant.ByteSize & 0x3) != 0)
|
||||
continue;
|
||||
|
||||
var constant = Mtrl.GetOrAddConstant(shpkConstant.Id, shpkConstant.ByteSize >> 2, out var constantIndex);
|
||||
var values = Mtrl.GetConstantValues(constant);
|
||||
var constant = Mtrl.GetOrAddConstant(shpkConstant.Id, shpkConstant.ByteSize >> 2, out var constantIndex);
|
||||
var values = Mtrl.GetConstantValues(constant);
|
||||
var handledElements = new IndexSet(values.Length, false);
|
||||
|
||||
var dkData = TryGetShpkDevkitData<DevkitConstant[]>("Constants", shpkConstant.Id, true);
|
||||
if (dkData != null)
|
||||
{
|
||||
foreach (var dkConstant in dkData)
|
||||
{
|
||||
var offset = (int)dkConstant.Offset;
|
||||
|
|
@ -386,13 +401,13 @@ public partial class ModEditWindow
|
|||
length = Math.Min(length, (int)dkConstant.Length.Value);
|
||||
if (length <= 0)
|
||||
continue;
|
||||
|
||||
var editor = dkConstant.CreateEditor();
|
||||
if (editor != null)
|
||||
FindOrAddGroup(Constants, dkConstant.Group.Length > 0 ? dkConstant.Group : "Further Constants")
|
||||
.Add((dkConstant.Label, constantIndex, offset..(offset + length), dkConstant.Description, false, editor));
|
||||
handledElements.AddRange(offset, length);
|
||||
}
|
||||
}
|
||||
|
||||
var fcGroup = FindOrAddGroup(Constants, "Further Constants");
|
||||
foreach (var (start, end) in handledElements.Ranges(true))
|
||||
|
|
@ -403,15 +418,20 @@ public partial class ModEditWindow
|
|||
for (int i = (start & ~0x3) - (offset & 0x3), j = offset >> 2; i < end; i += 4, ++j)
|
||||
{
|
||||
var rangeStart = Math.Max(i, start);
|
||||
var rangeEnd = Math.Min(i + 4, end);
|
||||
var rangeEnd = Math.Min(i + 4, end);
|
||||
if (rangeEnd > rangeStart)
|
||||
fcGroup.Add(($"{prefix}[{j:D2}]{VectorSwizzle((offset + rangeStart) & 0x3, (offset + rangeEnd - 1) & 0x3)} (0x{shpkConstant.Id:X8})", constantIndex, rangeStart..rangeEnd, string.Empty, true, FloatConstantEditor.Default));
|
||||
fcGroup.Add((
|
||||
$"{prefix}[{j:D2}]{VectorSwizzle((offset + rangeStart) & 0x3, (offset + rangeEnd - 1) & 0x3)} (0x{shpkConstant.Id:X8})",
|
||||
constantIndex, rangeStart..rangeEnd, string.Empty, true, FloatConstantEditor.Default));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = start; i < end; i += 4)
|
||||
fcGroup.Add(($"0x{shpkConstant.Id:X8}", constantIndex, i..Math.Min(i + 4, end), string.Empty, true, FloatConstantEditor.Default));
|
||||
{
|
||||
fcGroup.Add(($"0x{shpkConstant.Id:X8}", constantIndex, i..Math.Min(i + 4, end), string.Empty, true,
|
||||
FloatConstantEditor.Default));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -424,20 +444,23 @@ public partial class ModEditWindow
|
|||
return 1;
|
||||
if (string.Equals(y.Header, "Further Constants", StringComparison.Ordinal))
|
||||
return -1;
|
||||
|
||||
return string.Compare(x.Header, y.Header, StringComparison.Ordinal);
|
||||
});
|
||||
// HACK the Replace makes w appear after xyz, for the cbuffer-location-based naming scheme
|
||||
foreach (var (_, group) in Constants)
|
||||
{
|
||||
group.Sort((x, y) => string.CompareOrdinal(
|
||||
x.MonoFont ? x.Label.Replace("].w", "].{") : x.Label,
|
||||
y.MonoFont ? y.Label.Replace("].w", "].{") : y.Label));
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe void BindToMaterialInstances()
|
||||
{
|
||||
UnbindFromMaterialInstances();
|
||||
|
||||
var localPlayer = FindLocalPlayer(_edit._dalamud.Objects);
|
||||
var localPlayer = LocalPlayer(_edit._dalamud.Objects);
|
||||
if (null == localPlayer)
|
||||
return;
|
||||
|
||||
|
|
@ -449,7 +472,9 @@ public partial class ModEditWindow
|
|||
|
||||
var drawObjects = stackalloc CharacterBase*[4];
|
||||
drawObjects[0] = drawObject;
|
||||
|
||||
drawObjects[1] = *((CharacterBase**)&localPlayer->DrawData.MainHand + 1);
|
||||
drawObjects[2] = *((CharacterBase**)&localPlayer->DrawData.OffHand + 1);
|
||||
drawObjects[3] = *((CharacterBase**)&localPlayer->DrawData.UnkF0 + 1);
|
||||
for (var i = 0; i < 3; ++i)
|
||||
{
|
||||
var subActor = FindSubActor(localPlayer, i);
|
||||
|
|
@ -470,9 +495,11 @@ public partial class ModEditWindow
|
|||
var material = GetDrawObjectMaterial(drawObjects[subActorType + 1], modelSlot, materialSlot);
|
||||
if (foundMaterials.Contains((nint)material))
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
MaterialPreviewers.Add(new LiveMaterialPreviewer(_edit._dalamud.Objects, subActorType, childObjectIndex, modelSlot, materialSlot));
|
||||
MaterialPreviewers.Add(new LiveMaterialPreviewer(_edit._dalamud.Objects, subActorType, childObjectIndex, modelSlot,
|
||||
materialSlot));
|
||||
foundMaterials.Add((nint)material);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
|
|
@ -480,28 +507,31 @@ public partial class ModEditWindow
|
|||
// Carry on without that previewer.
|
||||
}
|
||||
}
|
||||
|
||||
UpdateMaterialPreview();
|
||||
|
||||
var colorSet = Mtrl.ColorSets.FirstOrNull(colorSet => colorSet.HasRows);
|
||||
|
||||
if (colorSet.HasValue)
|
||||
if (!colorSet.HasValue)
|
||||
return;
|
||||
|
||||
foreach (var (subActorType, childObjectIndex, modelSlot, materialSlot) in instances)
|
||||
{
|
||||
foreach (var (subActorType, childObjectIndex, modelSlot, materialSlot) in instances)
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
ColorSetPreviewers.Add(new LiveColorSetPreviewer(_edit._dalamud.Objects, _edit._dalamud.Framework, subActorType, childObjectIndex, modelSlot, materialSlot));
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// Carry on without that previewer.
|
||||
}
|
||||
ColorSetPreviewers.Add(new LiveColorSetPreviewer(_edit._dalamud.Objects, _edit._dalamud.Framework, subActorType,
|
||||
childObjectIndex, modelSlot, materialSlot));
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// Carry on without that previewer.
|
||||
}
|
||||
UpdateColorSetPreview();
|
||||
}
|
||||
|
||||
UpdateColorSetPreview();
|
||||
}
|
||||
|
||||
public void UnbindFromMaterialInstances()
|
||||
private void UnbindFromMaterialInstances()
|
||||
{
|
||||
foreach (var previewer in MaterialPreviewers)
|
||||
previewer.Dispose();
|
||||
|
|
@ -512,9 +542,9 @@ public partial class ModEditWindow
|
|||
ColorSetPreviewers.Clear();
|
||||
}
|
||||
|
||||
public unsafe void UnbindFromDrawObjectMaterialInstances(nint characterBase)
|
||||
private unsafe void UnbindFromDrawObjectMaterialInstances(nint characterBase)
|
||||
{
|
||||
for (var i = MaterialPreviewers.Count; i-- > 0; )
|
||||
for (var i = MaterialPreviewers.Count; i-- > 0;)
|
||||
{
|
||||
var previewer = MaterialPreviewers[i];
|
||||
if ((nint)previewer.DrawObject != characterBase)
|
||||
|
|
@ -553,7 +583,7 @@ public partial class ModEditWindow
|
|||
previewer.SetSamplerFlags(samplerCrc, samplerFlags);
|
||||
}
|
||||
|
||||
public void UpdateMaterialPreview()
|
||||
private void UpdateMaterialPreview()
|
||||
{
|
||||
SetShaderPackageFlags(Mtrl.ShaderPackage.Flags);
|
||||
foreach (var constant in Mtrl.ShaderPackage.Constants)
|
||||
|
|
@ -562,6 +592,7 @@ public partial class ModEditWindow
|
|||
if (values != null)
|
||||
SetMaterialParameter(constant.Id, 0, values);
|
||||
}
|
||||
|
||||
foreach (var sampler in Mtrl.ShaderPackage.Samplers)
|
||||
SetSamplerFlags(sampler.SamplerId, sampler.Flags);
|
||||
}
|
||||
|
|
@ -602,7 +633,7 @@ public partial class ModEditWindow
|
|||
if (!maybeColorSet.HasValue)
|
||||
return;
|
||||
|
||||
var colorSet = maybeColorSet.Value;
|
||||
var colorSet = maybeColorSet.Value;
|
||||
var maybeColorDyeSet = Mtrl.ColorDyeSets.FirstOrNull(colorDyeSet => colorDyeSet.Index == colorSet.Index);
|
||||
|
||||
var row = colorSet.Rows[rowIdx];
|
||||
|
|
@ -610,7 +641,7 @@ public partial class ModEditWindow
|
|||
{
|
||||
var stm = _edit._stainService.StmFile;
|
||||
var dye = maybeColorDyeSet.Value.Rows[rowIdx];
|
||||
if (stm.TryGetValue(dye.Template, (StainId)_edit._stainService.StainCombo.CurrentSelection.Key, out var dyes))
|
||||
if (stm.TryGetValue(dye.Template, _edit._stainService.StainCombo.CurrentSelection.Key, out var dyes))
|
||||
row.ApplyDyeTemplate(dye, dyes);
|
||||
}
|
||||
|
||||
|
|
@ -619,7 +650,8 @@ public partial class ModEditWindow
|
|||
|
||||
foreach (var previewer in ColorSetPreviewers)
|
||||
{
|
||||
row.AsHalves().CopyTo(previewer.ColorSet.AsSpan().Slice(LiveColorSetPreviewer.TextureWidth * 4 * rowIdx, LiveColorSetPreviewer.TextureWidth * 4));
|
||||
row.AsHalves().CopyTo(previewer.ColorSet.AsSpan()
|
||||
.Slice(LiveColorSetPreviewer.TextureWidth * 4 * rowIdx, LiveColorSetPreviewer.TextureWidth * 4));
|
||||
previewer.ScheduleUpdate();
|
||||
}
|
||||
}
|
||||
|
|
@ -633,19 +665,19 @@ public partial class ModEditWindow
|
|||
if (!maybeColorSet.HasValue)
|
||||
return;
|
||||
|
||||
var colorSet = maybeColorSet.Value;
|
||||
var colorSet = maybeColorSet.Value;
|
||||
var maybeColorDyeSet = Mtrl.ColorDyeSets.FirstOrNull(colorDyeSet => colorDyeSet.Index == colorSet.Index);
|
||||
|
||||
var rows = colorSet.Rows;
|
||||
if (maybeColorDyeSet.HasValue && UseColorDyeSet)
|
||||
{
|
||||
var stm = _edit._stainService.StmFile;
|
||||
var stainId = (StainId)_edit._stainService.StainCombo.CurrentSelection.Key;
|
||||
var stm = _edit._stainService.StmFile;
|
||||
var stainId = (StainId)_edit._stainService.StainCombo.CurrentSelection.Key;
|
||||
var colorDyeSet = maybeColorDyeSet.Value;
|
||||
for (var i = 0; i < MtrlFile.ColorSet.RowArray.NumRows; ++i)
|
||||
{
|
||||
ref var row = ref rows[i];
|
||||
var dye = colorDyeSet.Rows[i];
|
||||
var dye = colorDyeSet.Rows[i];
|
||||
if (stm.TryGetValue(dye.Template, stainId, out var dyes))
|
||||
row.ApplyDyeTemplate(dye, dyes);
|
||||
}
|
||||
|
|
@ -663,10 +695,10 @@ public partial class ModEditWindow
|
|||
|
||||
private static void ApplyHighlight(ref MtrlFile.ColorSet.Row row, float time)
|
||||
{
|
||||
var level = Math.Sin(time * 2.0 * Math.PI) * 0.25 + 0.5;
|
||||
var level = Math.Sin(time * 2.0 * Math.PI) * 0.25 + 0.5;
|
||||
var levelSq = (float)(level * level);
|
||||
|
||||
row.Diffuse = Vector3.Zero;
|
||||
row.Diffuse = Vector3.Zero;
|
||||
row.Specular = Vector3.Zero;
|
||||
row.Emissive = new Vector3(levelSq);
|
||||
}
|
||||
|
|
@ -678,15 +710,15 @@ public partial class ModEditWindow
|
|||
UpdateConstants();
|
||||
}
|
||||
|
||||
public MtrlTab( ModEditWindow edit, MtrlFile file, string filePath, bool writable )
|
||||
public MtrlTab(ModEditWindow edit, MtrlFile file, string filePath, bool writable)
|
||||
{
|
||||
_edit = edit;
|
||||
Mtrl = file;
|
||||
FilePath = filePath;
|
||||
Writable = writable;
|
||||
UseColorDyeSet = file.ColorDyeSets.Length > 0;
|
||||
AssociatedBaseDevkit = TryLoadShpkDevkit( "_base", out LoadedBaseDevkitPathName );
|
||||
LoadShpk( FindAssociatedShpk( out _, out _ ) );
|
||||
_edit = edit;
|
||||
Mtrl = file;
|
||||
FilePath = filePath;
|
||||
Writable = writable;
|
||||
UseColorDyeSet = file.ColorDyeSets.Length > 0;
|
||||
AssociatedBaseDevkit = TryLoadShpkDevkit("_base", out LoadedBaseDevkitPathName);
|
||||
LoadShpk(FindAssociatedShpk(out _, out _));
|
||||
if (writable)
|
||||
{
|
||||
_edit._gameEvents.CharacterBaseDestructor += UnbindFromDrawObjectMaterialInstances;
|
||||
|
|
@ -694,18 +726,7 @@ public partial class ModEditWindow
|
|||
}
|
||||
}
|
||||
|
||||
~MtrlTab()
|
||||
{
|
||||
DoDispose();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DoDispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void DoDispose()
|
||||
{
|
||||
UnbindFromMaterialInstances();
|
||||
if (Writable)
|
||||
|
|
@ -723,11 +744,7 @@ public partial class ModEditWindow
|
|||
return output.Write();
|
||||
}
|
||||
|
||||
private sealed class DevkitShaderKeyValue
|
||||
{
|
||||
public string Label = string.Empty;
|
||||
public string Description = string.Empty;
|
||||
}
|
||||
private sealed record DevkitShaderKeyValue(string Label = "", string Description = "");
|
||||
|
||||
private sealed class DevkitShaderKey
|
||||
{
|
||||
|
|
@ -736,12 +753,7 @@ public partial class ModEditWindow
|
|||
public Dictionary<uint, DevkitShaderKeyValue> Values = new();
|
||||
}
|
||||
|
||||
private sealed class DevkitSampler
|
||||
{
|
||||
public string Label = string.Empty;
|
||||
public string Description = string.Empty;
|
||||
public string DefaultTexture = string.Empty;
|
||||
}
|
||||
private sealed record DevkitSampler(string Label = "", string Description = "", string DefaultTexture = "");
|
||||
|
||||
private enum DevkitConstantType
|
||||
{
|
||||
|
|
@ -752,12 +764,7 @@ public partial class ModEditWindow
|
|||
Enum = 3,
|
||||
}
|
||||
|
||||
private sealed class DevkitConstantValue
|
||||
{
|
||||
public string Label = string.Empty;
|
||||
public string Description = string.Empty;
|
||||
public float Value = 0.0f;
|
||||
}
|
||||
private sealed record DevkitConstantValue(string Label = "", string Description = "", float Value = 0);
|
||||
|
||||
private sealed class DevkitConstant
|
||||
{
|
||||
|
|
@ -783,25 +790,20 @@ public partial class ModEditWindow
|
|||
public DevkitConstantValue[] Values = Array.Empty<DevkitConstantValue>();
|
||||
|
||||
public IConstantEditor? CreateEditor()
|
||||
{
|
||||
switch (Type)
|
||||
=> Type switch
|
||||
{
|
||||
case DevkitConstantType.Hidden:
|
||||
return null;
|
||||
case DevkitConstantType.Float:
|
||||
return new FloatConstantEditor(Minimum, Maximum, Speed ?? 0.1f, RelativeSpeed, Factor, Bias, Precision, Unit);
|
||||
case DevkitConstantType.Integer:
|
||||
return new IntConstantEditor(ToInteger(Minimum), ToInteger(Maximum), Speed ?? 0.25f, RelativeSpeed, Factor, Bias, Unit);
|
||||
case DevkitConstantType.Color:
|
||||
return new ColorConstantEditor(SquaredRgb, Clamped);
|
||||
case DevkitConstantType.Enum:
|
||||
return new EnumConstantEditor(Array.ConvertAll(Values, value => (value.Label, value.Value, value.Description)));
|
||||
default:
|
||||
return FloatConstantEditor.Default;
|
||||
}
|
||||
}
|
||||
DevkitConstantType.Hidden => null,
|
||||
DevkitConstantType.Float => new FloatConstantEditor(Minimum, Maximum, Speed ?? 0.1f, RelativeSpeed, Factor, Bias, Precision,
|
||||
Unit),
|
||||
DevkitConstantType.Integer => new IntConstantEditor(ToInteger(Minimum), ToInteger(Maximum), Speed ?? 0.25f, RelativeSpeed,
|
||||
Factor, Bias, Unit),
|
||||
DevkitConstantType.Color => new ColorConstantEditor(SquaredRgb, Clamped),
|
||||
DevkitConstantType.Enum => new EnumConstantEditor(Array.ConvertAll(Values,
|
||||
value => (value.Label, value.Value, value.Description))),
|
||||
_ => FloatConstantEditor.Default,
|
||||
};
|
||||
|
||||
private int? ToInteger(float? value)
|
||||
private static int? ToInteger(float? value)
|
||||
=> value.HasValue ? (int)Math.Clamp(MathF.Round(value.Value), int.MinValue, int.MaxValue) : null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.ImGuiFileDialog;
|
||||
using ImGuiNET;
|
||||
using Lumina.Data.Parsing;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData;
|
||||
using Penumbra.GameData.Files;
|
||||
using Penumbra.String.Classes;
|
||||
|
||||
namespace Penumbra.UI.AdvancedWindow;
|
||||
|
|
@ -25,7 +19,7 @@ public partial class ModEditWindow
|
|||
// Apricot shader packages are unlisted because
|
||||
// 1. they cause performance/memory issues when calculating the effective shader set
|
||||
// 2. they probably aren't intended for use with materials anyway
|
||||
private static readonly IReadOnlyList<string> StandardShaderPackages = new string[]
|
||||
private static readonly IReadOnlyList<string> StandardShaderPackages = new[]
|
||||
{
|
||||
"3dui.shpk",
|
||||
// "apricot_decal_dummy.shpk",
|
||||
|
|
@ -76,7 +70,7 @@ public partial class ModEditWindow
|
|||
Border = 3,
|
||||
}
|
||||
|
||||
private static readonly IReadOnlyList<string> TextureAddressModeTooltips = new string[]
|
||||
private static readonly IReadOnlyList<string> TextureAddressModeTooltips = new[]
|
||||
{
|
||||
"Tile the texture at every UV integer junction.\n\nFor example, for U values between 0 and 3, the texture is repeated three times.",
|
||||
"Flip the texture at every UV integer junction.\n\nFor U values between 0 and 1, for example, the texture is addressed normally; between 1 and 2, the texture is mirrored; between 2 and 3, the texture is normal again; and so on.",
|
||||
|
|
@ -113,18 +107,15 @@ public partial class ModEditWindow
|
|||
|
||||
private static bool DrawShaderFlagsInput(MtrlTab tab, bool disabled)
|
||||
{
|
||||
var ret = false;
|
||||
var shpkFlags = (int)tab.Mtrl.ShaderPackage.Flags;
|
||||
ImGui.SetNextItemWidth(UiHelpers.Scale * 250.0f);
|
||||
if (ImGui.InputInt("Shader Flags", ref shpkFlags, 0, 0,
|
||||
if (!ImGui.InputInt("Shader Flags", ref shpkFlags, 0, 0,
|
||||
ImGuiInputTextFlags.CharsHexadecimal | (disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None)))
|
||||
{
|
||||
tab.Mtrl.ShaderPackage.Flags = (uint)shpkFlags;
|
||||
ret = true;
|
||||
tab.SetShaderPackageFlags((uint)shpkFlags);
|
||||
}
|
||||
return false;
|
||||
|
||||
return ret;
|
||||
tab.Mtrl.ShaderPackage.Flags = (uint)shpkFlags;
|
||||
tab.SetShaderPackageFlags((uint)shpkFlags);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -6,34 +6,35 @@ using OtterGui;
|
|||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Files;
|
||||
using Penumbra.String.Classes;
|
||||
using Penumbra.UI.Classes;
|
||||
|
||||
namespace Penumbra.UI.AdvancedWindow;
|
||||
|
||||
public partial class ModEditWindow
|
||||
{
|
||||
private readonly FileEditor< MtrlTab > _materialTab;
|
||||
private readonly FileEditor<MtrlTab> _materialTab;
|
||||
|
||||
private bool DrawMaterialPanel( MtrlTab tab, bool disabled )
|
||||
private bool DrawMaterialPanel(MtrlTab tab, bool disabled)
|
||||
{
|
||||
DrawMaterialLivePreviewRebind( tab, disabled );
|
||||
DrawMaterialLivePreviewRebind(tab, disabled);
|
||||
|
||||
ImGui.Dummy( new Vector2( ImGui.GetTextLineHeight() / 2 ) );
|
||||
var ret = DrawBackFaceAndTransparency( tab, disabled );
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
var ret = DrawBackFaceAndTransparency(tab, disabled);
|
||||
|
||||
ImGui.Dummy( new Vector2( ImGui.GetTextLineHeight() / 2 ) );
|
||||
ret |= DrawMaterialShader( tab, disabled );
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
ret |= DrawMaterialShader(tab, disabled);
|
||||
|
||||
ret |= DrawMaterialTextureChange( tab, disabled );
|
||||
ret |= DrawMaterialColorSetChange( tab, disabled );
|
||||
ret |= DrawMaterialConstants( tab, disabled );
|
||||
ret |= DrawMaterialTextureChange(tab, disabled);
|
||||
ret |= DrawMaterialColorSetChange(tab, disabled);
|
||||
ret |= DrawMaterialConstants(tab, disabled);
|
||||
|
||||
ImGui.Dummy( new Vector2( ImGui.GetTextLineHeight() / 2 ) );
|
||||
DrawOtherMaterialDetails( tab.Mtrl, disabled );
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
DrawOtherMaterialDetails(tab.Mtrl, disabled);
|
||||
|
||||
return !disabled && ret;
|
||||
}
|
||||
|
||||
private static void DrawMaterialLivePreviewRebind( MtrlTab tab, bool disabled )
|
||||
private static void DrawMaterialLivePreviewRebind(MtrlTab tab, bool disabled)
|
||||
{
|
||||
if (disabled)
|
||||
return;
|
||||
|
|
@ -41,82 +42,74 @@ public partial class ModEditWindow
|
|||
if (ImGui.Button("Reload live preview"))
|
||||
tab.BindToMaterialInstances();
|
||||
|
||||
if (tab.MaterialPreviewers.Count == 0 && tab.ColorSetPreviewers.Count == 0)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
if (tab.MaterialPreviewers.Count != 0 || tab.ColorSetPreviewers.Count != 0)
|
||||
return;
|
||||
|
||||
var textColor = ImGui.GetColorU32(ImGuiCol.Text);
|
||||
var textColorWarning = (textColor & 0xFF000000u) | ((textColor & 0x00FEFEFE) >> 1) | 0x80u; // Half red
|
||||
|
||||
using var c = ImRaii.PushColor(ImGuiCol.Text, textColorWarning);
|
||||
|
||||
ImGui.TextUnformatted("The current material has not been found on your character. Please check the Import from Screen tab for more information.");
|
||||
}
|
||||
ImGui.SameLine();
|
||||
using var c = ImRaii.PushColor(ImGuiCol.Text, Colors.RegexWarningBorder);
|
||||
ImGui.TextUnformatted(
|
||||
"The current material has not been found on your character. Please check the Import from Screen tab for more information.");
|
||||
}
|
||||
|
||||
private static bool DrawMaterialTextureChange( MtrlTab tab, bool disabled )
|
||||
private static bool DrawMaterialTextureChange(MtrlTab tab, bool disabled)
|
||||
{
|
||||
if( tab.Textures.Count == 0 )
|
||||
{
|
||||
if (tab.Textures.Count == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
ImGui.Dummy( new Vector2( ImGui.GetTextLineHeight() / 2 ) );
|
||||
if( !ImGui.CollapsingHeader( "Textures and Samplers", ImGuiTreeNodeFlags.DefaultOpen ) )
|
||||
{
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
if (!ImGui.CollapsingHeader("Textures and Samplers", ImGuiTreeNodeFlags.DefaultOpen))
|
||||
return false;
|
||||
}
|
||||
|
||||
var frameHeight = ImGui.GetFrameHeight();
|
||||
var ret = false;
|
||||
using var table = ImRaii.Table( "##Textures", 3 );
|
||||
using var table = ImRaii.Table("##Textures", 3);
|
||||
|
||||
ImGui.TableSetupColumn( string.Empty, ImGuiTableColumnFlags.WidthFixed, frameHeight );
|
||||
ImGui.TableSetupColumn( "Path" , ImGuiTableColumnFlags.WidthStretch );
|
||||
ImGui.TableSetupColumn( "Name" , ImGuiTableColumnFlags.WidthFixed, tab.TextureLabelWidth * UiHelpers.Scale );
|
||||
for( var i = 0; i < tab.Textures.Count; ++i )
|
||||
ImGui.TableSetupColumn(string.Empty, ImGuiTableColumnFlags.WidthFixed, frameHeight);
|
||||
ImGui.TableSetupColumn("Path", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthFixed, tab.TextureLabelWidth * UiHelpers.Scale);
|
||||
foreach (var (label, textureI, samplerI, description, monoFont) in tab.Textures)
|
||||
{
|
||||
var (label, textureI, samplerI, description, monoFont) = tab.Textures[i];
|
||||
|
||||
using var _ = ImRaii.PushId( samplerI );
|
||||
var tmp = tab.Mtrl.Textures[ textureI ].Path;
|
||||
var unfolded = tab.UnfoldedTextures.Contains( samplerI );
|
||||
using var _ = ImRaii.PushId(samplerI);
|
||||
var tmp = tab.Mtrl.Textures[textureI].Path;
|
||||
var unfolded = tab.UnfoldedTextures.Contains(samplerI);
|
||||
ImGui.TableNextColumn();
|
||||
if( ImGuiUtil.DrawDisabledButton( ( unfolded ? FontAwesomeIcon.CaretDown : FontAwesomeIcon.CaretRight ).ToIconString(), new Vector2( frameHeight ),
|
||||
"Settings for this texture and the associated sampler", false, true ) )
|
||||
if (ImGuiUtil.DrawDisabledButton((unfolded ? FontAwesomeIcon.CaretDown : FontAwesomeIcon.CaretRight).ToIconString(),
|
||||
new Vector2(frameHeight),
|
||||
"Settings for this texture and the associated sampler", false, true))
|
||||
{
|
||||
unfolded = !unfolded;
|
||||
if( unfolded )
|
||||
tab.UnfoldedTextures.Add( samplerI );
|
||||
if (unfolded)
|
||||
tab.UnfoldedTextures.Add(samplerI);
|
||||
else
|
||||
tab.UnfoldedTextures.Remove( samplerI );
|
||||
}
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.SetNextItemWidth( ImGui.GetContentRegionAvail().X );
|
||||
if( ImGui.InputText( string.Empty, ref tmp, Utf8GamePath.MaxGamePathLength,
|
||||
disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None )
|
||||
&& tmp.Length > 0
|
||||
&& tmp != tab.Mtrl.Textures[ textureI ].Path )
|
||||
{
|
||||
ret = true;
|
||||
tab.Mtrl.Textures[ textureI ].Path = tmp;
|
||||
tab.UnfoldedTextures.Remove(samplerI);
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
using( var font = ImRaii.PushFont( UiBuilder.MonoFont, monoFont ) )
|
||||
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
|
||||
if (ImGui.InputText(string.Empty, ref tmp, Utf8GamePath.MaxGamePathLength,
|
||||
disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None)
|
||||
&& tmp.Length > 0
|
||||
&& tmp != tab.Mtrl.Textures[textureI].Path)
|
||||
{
|
||||
ret = true;
|
||||
tab.Mtrl.Textures[textureI].Path = tmp;
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
using (var font = ImRaii.PushFont(UiBuilder.MonoFont, monoFont))
|
||||
{
|
||||
ImGui.AlignTextToFramePadding();
|
||||
if( description.Length > 0 )
|
||||
ImGuiUtil.LabeledHelpMarker( label, description );
|
||||
if (description.Length > 0)
|
||||
ImGuiUtil.LabeledHelpMarker(label, description);
|
||||
else
|
||||
ImGui.TextUnformatted( label );
|
||||
ImGui.TextUnformatted(label);
|
||||
}
|
||||
|
||||
if( unfolded )
|
||||
if (unfolded)
|
||||
{
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableNextColumn();
|
||||
ret |= DrawMaterialSampler( tab, disabled, textureI, samplerI );
|
||||
ret |= DrawMaterialSampler(tab, disabled, textureI, samplerI);
|
||||
ImGui.TableNextColumn();
|
||||
}
|
||||
}
|
||||
|
|
@ -124,26 +117,27 @@ public partial class ModEditWindow
|
|||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawBackFaceAndTransparency( MtrlTab tab, bool disabled )
|
||||
private static bool DrawBackFaceAndTransparency(MtrlTab tab, bool disabled)
|
||||
{
|
||||
const uint transparencyBit = 0x10;
|
||||
const uint backfaceBit = 0x01;
|
||||
|
||||
var ret = false;
|
||||
|
||||
using var dis = ImRaii.Disabled( disabled );
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
|
||||
var tmp = ( tab.Mtrl.ShaderPackage.Flags & transparencyBit ) != 0;
|
||||
if( ImGui.Checkbox( "Enable Transparency", ref tmp ) )
|
||||
var tmp = (tab.Mtrl.ShaderPackage.Flags & transparencyBit) != 0;
|
||||
if (ImGui.Checkbox("Enable Transparency", ref tmp))
|
||||
{
|
||||
tab.Mtrl.ShaderPackage.Flags = tmp ? tab.Mtrl.ShaderPackage.Flags | transparencyBit : tab.Mtrl.ShaderPackage.Flags & ~transparencyBit;
|
||||
ret = true;
|
||||
tab.Mtrl.ShaderPackage.Flags =
|
||||
tmp ? tab.Mtrl.ShaderPackage.Flags | transparencyBit : tab.Mtrl.ShaderPackage.Flags & ~transparencyBit;
|
||||
ret = true;
|
||||
tab.SetShaderPackageFlags(tab.Mtrl.ShaderPackage.Flags);
|
||||
}
|
||||
|
||||
ImGui.SameLine( 200 * UiHelpers.Scale + ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X );
|
||||
tmp = ( tab.Mtrl.ShaderPackage.Flags & backfaceBit ) != 0;
|
||||
if( ImGui.Checkbox( "Hide Backfaces", ref tmp ) )
|
||||
ImGui.SameLine(200 * UiHelpers.Scale + ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X);
|
||||
tmp = (tab.Mtrl.ShaderPackage.Flags & backfaceBit) != 0;
|
||||
if (ImGui.Checkbox("Hide Backfaces", ref tmp))
|
||||
{
|
||||
tab.Mtrl.ShaderPackage.Flags = tmp ? tab.Mtrl.ShaderPackage.Flags | backfaceBit : tab.Mtrl.ShaderPackage.Flags & ~backfaceBit;
|
||||
ret = true;
|
||||
|
|
@ -153,106 +147,80 @@ public partial class ModEditWindow
|
|||
return ret;
|
||||
}
|
||||
|
||||
private static void DrawOtherMaterialDetails( MtrlFile file, bool _ )
|
||||
private static void DrawOtherMaterialDetails(MtrlFile file, bool _)
|
||||
{
|
||||
if( !ImGui.CollapsingHeader( "Further Content" ) )
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Further Content"))
|
||||
return;
|
||||
|
||||
using (var sets = ImRaii.TreeNode("UV Sets", ImGuiTreeNodeFlags.DefaultOpen))
|
||||
{
|
||||
if (sets)
|
||||
foreach (var set in file.UvSets)
|
||||
ImRaii.TreeNode($"#{set.Index:D2} - {set.Name}", ImGuiTreeNodeFlags.Leaf).Dispose();
|
||||
}
|
||||
|
||||
using( var sets = ImRaii.TreeNode( "UV Sets", ImGuiTreeNodeFlags.DefaultOpen ) )
|
||||
{
|
||||
if( sets )
|
||||
{
|
||||
foreach( var set in file.UvSets )
|
||||
{
|
||||
ImRaii.TreeNode( $"#{set.Index:D2} - {set.Name}", ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( file.AdditionalData.Length <= 0 )
|
||||
{
|
||||
if (file.AdditionalData.Length <= 0)
|
||||
return;
|
||||
}
|
||||
|
||||
using var t = ImRaii.TreeNode( $"Additional Data (Size: {file.AdditionalData.Length})###AdditionalData" );
|
||||
if( t )
|
||||
{
|
||||
ImGuiUtil.TextWrapped( string.Join( ' ', file.AdditionalData.Select( c => $"{c:X2}" ) ) );
|
||||
}
|
||||
using var t = ImRaii.TreeNode($"Additional Data (Size: {file.AdditionalData.Length})###AdditionalData");
|
||||
if (t)
|
||||
ImGuiUtil.TextWrapped(string.Join(' ', file.AdditionalData.Select(c => $"{c:X2}")));
|
||||
}
|
||||
|
||||
private void DrawMaterialReassignmentTab()
|
||||
{
|
||||
if( _editor.Files.Mdl.Count == 0 )
|
||||
{
|
||||
if (_editor.Files.Mdl.Count == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
using var tab = ImRaii.TabItem( "Material Reassignment" );
|
||||
if( !tab )
|
||||
{
|
||||
using var tab = ImRaii.TabItem("Material Reassignment");
|
||||
if (!tab)
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui.NewLine();
|
||||
MaterialSuffix.Draw( _editor, ImGuiHelpers.ScaledVector2( 175, 0 ) );
|
||||
MaterialSuffix.Draw(_editor, ImGuiHelpers.ScaledVector2(175, 0));
|
||||
|
||||
ImGui.NewLine();
|
||||
using var child = ImRaii.Child( "##mdlFiles", -Vector2.One, true );
|
||||
if( !child )
|
||||
{
|
||||
using var child = ImRaii.Child("##mdlFiles", -Vector2.One, true);
|
||||
if (!child)
|
||||
return;
|
||||
}
|
||||
|
||||
using var table = ImRaii.Table( "##files", 4, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit, -Vector2.One );
|
||||
if( !table )
|
||||
{
|
||||
using var table = ImRaii.Table("##files", 4, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit, -Vector2.One);
|
||||
if (!table)
|
||||
return;
|
||||
}
|
||||
|
||||
var iconSize = ImGui.GetFrameHeight() * Vector2.One;
|
||||
foreach( var (info, idx) in _editor.MdlMaterialEditor.ModelFiles.WithIndex() )
|
||||
foreach (var (info, idx) in _editor.MdlMaterialEditor.ModelFiles.WithIndex())
|
||||
{
|
||||
using var id = ImRaii.PushId( idx );
|
||||
using var id = ImRaii.PushId(idx);
|
||||
ImGui.TableNextColumn();
|
||||
if( ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Save.ToIconString(), iconSize,
|
||||
"Save the changed mdl file.\nUse at own risk!", !info.Changed, true ) )
|
||||
{
|
||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Save.ToIconString(), iconSize,
|
||||
"Save the changed mdl file.\nUse at own risk!", !info.Changed, true))
|
||||
info.Save();
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
if( ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Recycle.ToIconString(), iconSize,
|
||||
"Restore current changes to default.", !info.Changed, true ) )
|
||||
{
|
||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Recycle.ToIconString(), iconSize,
|
||||
"Restore current changes to default.", !info.Changed, true))
|
||||
info.Restore();
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TextUnformatted( info.Path.FullName[ ( _mod!.ModPath.FullName.Length + 1 ).. ] );
|
||||
ImGui.TextUnformatted(info.Path.FullName[(_mod!.ModPath.FullName.Length + 1)..]);
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.SetNextItemWidth( 400 * UiHelpers.Scale );
|
||||
var tmp = info.CurrentMaterials[ 0 ];
|
||||
if( ImGui.InputText( "##0", ref tmp, 64 ) )
|
||||
{
|
||||
info.SetMaterial( tmp, 0 );
|
||||
}
|
||||
ImGui.SetNextItemWidth(400 * UiHelpers.Scale);
|
||||
var tmp = info.CurrentMaterials[0];
|
||||
if (ImGui.InputText("##0", ref tmp, 64))
|
||||
info.SetMaterial(tmp, 0);
|
||||
|
||||
for( var i = 1; i < info.Count; ++i )
|
||||
for (var i = 1; i < info.Count; ++i)
|
||||
{
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.SetNextItemWidth( 400 * UiHelpers.Scale );
|
||||
tmp = info.CurrentMaterials[ i ];
|
||||
if( ImGui.InputText( $"##{i}", ref tmp, 64 ) )
|
||||
{
|
||||
info.SetMaterial( tmp, i );
|
||||
}
|
||||
ImGui.SetNextItemWidth(400 * UiHelpers.Scale);
|
||||
tmp = info.CurrentMaterials[i];
|
||||
if (ImGui.InputText($"##{i}", ref tmp, 64))
|
||||
info.SetMaterial(tmp, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using Penumbra.GameData.Files;
|
|||
using Penumbra.String.Classes;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Penumbra.UI.AdvancedWindow;
|
||||
|
||||
namespace Penumbra.UI.AdvancedWindow;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,32 +20,32 @@ namespace Penumbra.UI.AdvancedWindow;
|
|||
|
||||
public partial class ModEditWindow
|
||||
{
|
||||
private static readonly ByteString DisassemblyLabel = ByteString.FromSpanUnsafe( "##disassembly"u8, true, true, true );
|
||||
private static readonly ByteString DisassemblyLabel = ByteString.FromSpanUnsafe("##disassembly"u8, true, true, true);
|
||||
|
||||
private readonly FileEditor< ShpkTab > _shaderPackageTab;
|
||||
private readonly FileEditor<ShpkTab> _shaderPackageTab;
|
||||
|
||||
private static bool DrawShaderPackagePanel( ShpkTab file, bool disabled )
|
||||
private static bool DrawShaderPackagePanel(ShpkTab file, bool disabled)
|
||||
{
|
||||
DrawShaderPackageSummary( file );
|
||||
DrawShaderPackageSummary(file);
|
||||
|
||||
var ret = false;
|
||||
ImGui.Dummy( new Vector2( ImGui.GetTextLineHeight() / 2 ) );
|
||||
ret |= DrawShaderPackageShaderArray( file, "Vertex Shader", file.Shpk.VertexShaders, disabled );
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
ret |= DrawShaderPackageShaderArray(file, "Vertex Shader", file.Shpk.VertexShaders, disabled);
|
||||
|
||||
ImGui.Dummy( new Vector2( ImGui.GetTextLineHeight() / 2 ) );
|
||||
ret |= DrawShaderPackageShaderArray( file, "Pixel Shader", file.Shpk.PixelShaders, disabled );
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
ret |= DrawShaderPackageShaderArray(file, "Pixel Shader", file.Shpk.PixelShaders, disabled);
|
||||
|
||||
ImGui.Dummy( new Vector2( ImGui.GetTextLineHeight() / 2 ) );
|
||||
ret |= DrawShaderPackageMaterialParamLayout( file, disabled );
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
ret |= DrawShaderPackageMaterialParamLayout(file, disabled);
|
||||
|
||||
ImGui.Dummy( new Vector2( ImGui.GetTextLineHeight() / 2 ) );
|
||||
ret |= DrawShaderPackageResources( file, disabled );
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
ret |= DrawShaderPackageResources(file, disabled);
|
||||
|
||||
ImGui.Dummy( new Vector2( ImGui.GetTextLineHeight() / 2 ) );
|
||||
DrawShaderPackageSelection( file );
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
DrawShaderPackageSelection(file);
|
||||
|
||||
ImGui.Dummy( new Vector2( ImGui.GetTextLineHeight() / 2 ) );
|
||||
DrawOtherShaderPackageDetails( file );
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
DrawOtherShaderPackageDetails(file);
|
||||
|
||||
file.FileDialog.Draw();
|
||||
|
||||
|
|
@ -54,28 +54,26 @@ public partial class ModEditWindow
|
|||
return !disabled && ret;
|
||||
}
|
||||
|
||||
private static void DrawShaderPackageSummary( ShpkTab tab )
|
||||
private static void DrawShaderPackageSummary(ShpkTab tab)
|
||||
{
|
||||
ImGui.TextUnformatted( tab.Header );
|
||||
if( !tab.Shpk.Disassembled )
|
||||
ImGui.TextUnformatted(tab.Header);
|
||||
if (!tab.Shpk.Disassembled)
|
||||
{
|
||||
var textColor = ImGui.GetColorU32( ImGuiCol.Text );
|
||||
var textColorWarning = ( textColor & 0xFF000000u ) | ( ( textColor & 0x00FEFEFE ) >> 1 ) | 0x80u; // Half red
|
||||
var textColor = ImGui.GetColorU32(ImGuiCol.Text);
|
||||
var textColorWarning = (textColor & 0xFF000000u) | ((textColor & 0x00FEFEFE) >> 1) | 0x80u; // Half red
|
||||
|
||||
using var c = ImRaii.PushColor( ImGuiCol.Text, textColorWarning );
|
||||
using var c = ImRaii.PushColor(ImGuiCol.Text, textColorWarning);
|
||||
|
||||
ImGui.TextUnformatted( "Your system doesn't support disassembling shaders. Some functionality will be missing." );
|
||||
ImGui.TextUnformatted("Your system doesn't support disassembling shaders. Some functionality will be missing.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawShaderExportButton( ShpkTab tab, string objectName, Shader shader, int idx )
|
||||
private static void DrawShaderExportButton(ShpkTab tab, string objectName, Shader shader, int idx)
|
||||
{
|
||||
if( !ImGui.Button( $"Export Shader Program Blob ({shader.Blob.Length} bytes)" ) )
|
||||
{
|
||||
if (!ImGui.Button($"Export Shader Program Blob ({shader.Blob.Length} bytes)"))
|
||||
return;
|
||||
}
|
||||
|
||||
var defaultName = objectName[ 0 ] switch
|
||||
var defaultName = objectName[0] switch
|
||||
{
|
||||
'V' => $"vs{idx}",
|
||||
'P' => $"ps{idx}",
|
||||
|
|
@ -83,247 +81,225 @@ public partial class ModEditWindow
|
|||
};
|
||||
|
||||
var blob = shader.Blob;
|
||||
tab.FileDialog.OpenSavePicker( $"Export {objectName} #{idx} Program Blob to...", tab.Extension, defaultName, tab.Extension, ( success, name ) =>
|
||||
{
|
||||
if( !success )
|
||||
tab.FileDialog.OpenSavePicker($"Export {objectName} #{idx} Program Blob to...", tab.Extension, defaultName, tab.Extension,
|
||||
(success, name) =>
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!success)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
File.WriteAllBytes( name, blob );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
Penumbra.Chat.NotificationMessage( $"Could not export {defaultName}{tab.Extension} to {name}:\n{e.Message}", "Penumbra Advanced Editing",
|
||||
NotificationType.Error );
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
File.WriteAllBytes(name, blob);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Penumbra.Chat.NotificationMessage($"Could not export {defaultName}{tab.Extension} to {name}:\n{e.Message}",
|
||||
"Penumbra Advanced Editing",
|
||||
NotificationType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
Penumbra.Chat.NotificationMessage( $"Shader Program Blob {defaultName}{tab.Extension} exported successfully to {Path.GetFileName( name )}",
|
||||
"Penumbra Advanced Editing", NotificationType.Success );
|
||||
}, null, false );
|
||||
Penumbra.Chat.NotificationMessage(
|
||||
$"Shader Program Blob {defaultName}{tab.Extension} exported successfully to {Path.GetFileName(name)}",
|
||||
"Penumbra Advanced Editing", NotificationType.Success);
|
||||
}, null, false);
|
||||
}
|
||||
|
||||
private static void DrawShaderImportButton( ShpkTab tab, string objectName, Shader[] shaders, int idx )
|
||||
private static void DrawShaderImportButton(ShpkTab tab, string objectName, Shader[] shaders, int idx)
|
||||
{
|
||||
if( !ImGui.Button( "Replace Shader Program Blob" ) )
|
||||
{
|
||||
if (!ImGui.Button("Replace Shader Program Blob"))
|
||||
return;
|
||||
}
|
||||
|
||||
tab.FileDialog.OpenFilePicker( $"Replace {objectName} #{idx} Program Blob...", "Shader Program Blobs{.o,.cso,.dxbc,.dxil}", ( success, name ) =>
|
||||
{
|
||||
if( !success )
|
||||
tab.FileDialog.OpenFilePicker($"Replace {objectName} #{idx} Program Blob...", "Shader Program Blobs{.o,.cso,.dxbc,.dxil}",
|
||||
(success, name) =>
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!success)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
shaders[ idx ].Blob = File.ReadAllBytes(name[0] );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
Penumbra.Chat.NotificationMessage( $"Could not import {name}:\n{e.Message}", "Penumbra Advanced Editing", NotificationType.Error );
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
shaders[idx].Blob = File.ReadAllBytes(name[0]);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Penumbra.Chat.NotificationMessage($"Could not import {name}:\n{e.Message}", "Penumbra Advanced Editing",
|
||||
NotificationType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
shaders[ idx ].UpdateResources( tab.Shpk );
|
||||
tab.Shpk.UpdateResources();
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
tab.Shpk.SetInvalid();
|
||||
Penumbra.Chat.NotificationMessage( $"Failed to update resources after importing {name}:\n{e.Message}", "Penumbra Advanced Editing",
|
||||
NotificationType.Error );
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
shaders[idx].UpdateResources(tab.Shpk);
|
||||
tab.Shpk.UpdateResources();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
tab.Shpk.SetInvalid();
|
||||
Penumbra.Chat.NotificationMessage($"Failed to update resources after importing {name}:\n{e.Message}",
|
||||
"Penumbra Advanced Editing",
|
||||
NotificationType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
tab.Shpk.SetChanged();
|
||||
}, 1, null, false );
|
||||
tab.Shpk.SetChanged();
|
||||
}, 1, null, false);
|
||||
}
|
||||
|
||||
private static unsafe void DrawRawDisassembly( Shader shader )
|
||||
private static unsafe void DrawRawDisassembly(Shader shader)
|
||||
{
|
||||
using var t2 = ImRaii.TreeNode( "Raw Program Disassembly" );
|
||||
if( !t2 )
|
||||
{
|
||||
using var t2 = ImRaii.TreeNode("Raw Program Disassembly");
|
||||
if (!t2)
|
||||
return;
|
||||
}
|
||||
|
||||
using var font = ImRaii.PushFont( UiBuilder.MonoFont );
|
||||
var size = new Vector2( ImGui.GetContentRegionAvail().X, ImGui.GetTextLineHeight() * 20 );
|
||||
ImGuiNative.igInputTextMultiline( DisassemblyLabel.Path, shader.Disassembly!.RawDisassembly.Path, ( uint )shader.Disassembly!.RawDisassembly.Length + 1, size,
|
||||
ImGuiInputTextFlags.ReadOnly, null, null );
|
||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||
var size = new Vector2(ImGui.GetContentRegionAvail().X, ImGui.GetTextLineHeight() * 20);
|
||||
ImGuiNative.igInputTextMultiline(DisassemblyLabel.Path, shader.Disassembly!.RawDisassembly.Path,
|
||||
(uint)shader.Disassembly!.RawDisassembly.Length + 1, size,
|
||||
ImGuiInputTextFlags.ReadOnly, null, null);
|
||||
}
|
||||
|
||||
private static bool DrawShaderPackageShaderArray( ShpkTab tab, string objectName, Shader[] shaders, bool disabled )
|
||||
private static bool DrawShaderPackageShaderArray(ShpkTab tab, string objectName, Shader[] shaders, bool disabled)
|
||||
{
|
||||
if( shaders.Length == 0 || !ImGui.CollapsingHeader( $"{objectName}s" ) )
|
||||
{
|
||||
if (shaders.Length == 0 || !ImGui.CollapsingHeader($"{objectName}s"))
|
||||
return false;
|
||||
}
|
||||
|
||||
var ret = false;
|
||||
for( var idx = 0; idx < shaders.Length; ++idx )
|
||||
for (var idx = 0; idx < shaders.Length; ++idx)
|
||||
{
|
||||
var shader = shaders[ idx ];
|
||||
using var t = ImRaii.TreeNode( $"{objectName} #{idx}" );
|
||||
if( !t )
|
||||
{
|
||||
var shader = shaders[idx];
|
||||
using var t = ImRaii.TreeNode($"{objectName} #{idx}");
|
||||
if (!t)
|
||||
continue;
|
||||
}
|
||||
|
||||
DrawShaderExportButton( tab, objectName, shader, idx );
|
||||
if( !disabled && tab.Shpk.Disassembled )
|
||||
DrawShaderExportButton(tab, objectName, shader, idx);
|
||||
if (!disabled && tab.Shpk.Disassembled)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
DrawShaderImportButton( tab, objectName, shaders, idx );
|
||||
DrawShaderImportButton(tab, objectName, shaders, idx);
|
||||
}
|
||||
|
||||
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 );
|
||||
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 )
|
||||
if (shader.AdditionalHeader.Length > 0)
|
||||
{
|
||||
using var t2 = ImRaii.TreeNode( $"Additional Header (Size: {shader.AdditionalHeader.Length})###AdditionalHeader" );
|
||||
if( t2 )
|
||||
{
|
||||
ImGuiUtil.TextWrapped( string.Join( ' ', shader.AdditionalHeader.Select( c => $"{c:X2}" ) ) );
|
||||
}
|
||||
using var t2 = ImRaii.TreeNode($"Additional Header (Size: {shader.AdditionalHeader.Length})###AdditionalHeader");
|
||||
if (t2)
|
||||
ImGuiUtil.TextWrapped(string.Join(' ', shader.AdditionalHeader.Select(c => $"{c:X2}")));
|
||||
}
|
||||
|
||||
if( tab.Shpk.Disassembled )
|
||||
DrawRawDisassembly( shader );
|
||||
if (tab.Shpk.Disassembled)
|
||||
DrawRawDisassembly(shader);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawShaderPackageResource( string slotLabel, bool withSize, ref Resource resource, bool disabled )
|
||||
private static bool DrawShaderPackageResource(string slotLabel, bool withSize, ref Resource resource, bool disabled)
|
||||
{
|
||||
var ret = false;
|
||||
if( !disabled )
|
||||
if (!disabled)
|
||||
{
|
||||
ImGui.SetNextItemWidth( UiHelpers.Scale * 150.0f );
|
||||
if( ImGuiUtil.InputUInt16( $"{char.ToUpper( slotLabel[ 0 ] )}{slotLabel[ 1.. ].ToLower()}", ref resource.Slot, ImGuiInputTextFlags.None ) )
|
||||
{
|
||||
ImGui.SetNextItemWidth(UiHelpers.Scale * 150.0f);
|
||||
if (ImGuiUtil.InputUInt16($"{char.ToUpper(slotLabel[0])}{slotLabel[1..].ToLower()}", ref resource.Slot, ImGuiInputTextFlags.None))
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( resource.Used == null )
|
||||
{
|
||||
if (resource.Used == null)
|
||||
return ret;
|
||||
}
|
||||
|
||||
var usedString = UsedComponentString( withSize, resource );
|
||||
if( usedString.Length > 0 )
|
||||
{
|
||||
ImRaii.TreeNode( $"Used: {usedString}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet ).Dispose();
|
||||
}
|
||||
var usedString = UsedComponentString(withSize, resource);
|
||||
if (usedString.Length > 0)
|
||||
ImRaii.TreeNode($"Used: {usedString}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
else
|
||||
{
|
||||
ImRaii.TreeNode( "Unused", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet ).Dispose();
|
||||
}
|
||||
ImRaii.TreeNode("Unused", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawShaderPackageResourceArray( string arrayName, string slotLabel, bool withSize, Resource[] resources, bool disabled )
|
||||
private static bool DrawShaderPackageResourceArray(string arrayName, string slotLabel, bool withSize, Resource[] resources, bool disabled)
|
||||
{
|
||||
if( resources.Length == 0 )
|
||||
{
|
||||
if (resources.Length == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
using var t = ImRaii.TreeNode( arrayName );
|
||||
if( !t )
|
||||
{
|
||||
using var t = ImRaii.TreeNode(arrayName);
|
||||
if (!t)
|
||||
return false;
|
||||
}
|
||||
|
||||
var ret = false;
|
||||
for( var idx = 0; idx < resources.Length; ++idx )
|
||||
for (var idx = 0; idx < resources.Length; ++idx)
|
||||
{
|
||||
ref var buf = ref resources[ idx ];
|
||||
ref var buf = ref resources[idx];
|
||||
var name = $"#{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 );
|
||||
using var font = ImRaii.PushFont( UiBuilder.MonoFont );
|
||||
using var t2 = ImRaii.TreeNode( name, !disabled || buf.Used != null ? 0 : ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet );
|
||||
+ (withSize ? $", size: {buf.Size} registers###{idx}: {buf.Name} (ID: 0x{buf.Id:X8})" : string.Empty);
|
||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||
using var t2 = ImRaii.TreeNode(name, !disabled || buf.Used != null ? 0 : ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet);
|
||||
font.Dispose();
|
||||
if( t2 )
|
||||
{
|
||||
ret |= DrawShaderPackageResource( slotLabel, withSize, ref buf, disabled );
|
||||
}
|
||||
if (t2)
|
||||
ret |= DrawShaderPackageResource(slotLabel, withSize, ref buf, disabled);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawMaterialParamLayoutHeader( string label )
|
||||
private static bool DrawMaterialParamLayoutHeader(string label)
|
||||
{
|
||||
using var font = ImRaii.PushFont( UiBuilder.MonoFont );
|
||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||
var pos = ImGui.GetCursorScreenPos()
|
||||
+ new Vector2( ImGui.CalcTextSize( label ).X + 3 * ImGui.GetStyle().ItemInnerSpacing.X + ImGui.GetFrameHeight(), ImGui.GetStyle().FramePadding.Y );
|
||||
+ new Vector2(ImGui.CalcTextSize(label).X + 3 * ImGui.GetStyle().ItemInnerSpacing.X + ImGui.GetFrameHeight(),
|
||||
ImGui.GetStyle().FramePadding.Y);
|
||||
|
||||
var ret = ImGui.CollapsingHeader( label );
|
||||
ImGui.GetWindowDrawList().AddText( UiBuilder.DefaultFont, UiBuilder.DefaultFont.FontSize, pos, ImGui.GetColorU32( ImGuiCol.Text ), "Layout" );
|
||||
var ret = ImGui.CollapsingHeader(label);
|
||||
ImGui.GetWindowDrawList()
|
||||
.AddText(UiBuilder.DefaultFont, UiBuilder.DefaultFont.FontSize, pos, ImGui.GetColorU32(ImGuiCol.Text), "Layout");
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawMaterialParamLayoutBufferSize( ShpkFile file, Resource? materialParams )
|
||||
private static bool DrawMaterialParamLayoutBufferSize(ShpkFile file, Resource? materialParams)
|
||||
{
|
||||
var isSizeWellDefined = ( file.MaterialParamsSize & 0xF ) == 0 && ( !materialParams.HasValue || file.MaterialParamsSize == materialParams.Value.Size << 4 );
|
||||
if( isSizeWellDefined )
|
||||
{
|
||||
var isSizeWellDefined = (file.MaterialParamsSize & 0xF) == 0
|
||||
&& (!materialParams.HasValue || file.MaterialParamsSize == materialParams.Value.Size << 4);
|
||||
if (isSizeWellDefined)
|
||||
return true;
|
||||
}
|
||||
|
||||
ImGui.TextUnformatted( materialParams.HasValue
|
||||
ImGui.TextUnformatted(materialParams.HasValue
|
||||
? $"Buffer size mismatch: {file.MaterialParamsSize} bytes ≠ {materialParams.Value.Size} registers ({materialParams.Value.Size << 4} bytes)"
|
||||
: $"Buffer size mismatch: {file.MaterialParamsSize} bytes, not a multiple of 16" );
|
||||
: $"Buffer size mismatch: {file.MaterialParamsSize} bytes, not a multiple of 16");
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool DrawShaderPackageMaterialMatrix( ShpkTab tab, bool disabled )
|
||||
private static bool DrawShaderPackageMaterialMatrix(ShpkTab tab, bool disabled)
|
||||
{
|
||||
ImGui.TextUnformatted( tab.Shpk.Disassembled
|
||||
ImGui.TextUnformatted(tab.Shpk.Disassembled
|
||||
? "Parameter positions (continuations are grayed out, unused values are red):"
|
||||
: "Parameter positions (continuations are grayed out):" );
|
||||
: "Parameter positions (continuations are grayed out):");
|
||||
|
||||
using var table = ImRaii.Table( "##MaterialParamLayout", 5,
|
||||
ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg );
|
||||
if( !table )
|
||||
{
|
||||
using var table = ImRaii.Table("##MaterialParamLayout", 5,
|
||||
ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg);
|
||||
if (!table)
|
||||
return false;
|
||||
}
|
||||
|
||||
ImGui.TableSetupColumn( string.Empty, ImGuiTableColumnFlags.WidthFixed, 25 * UiHelpers.Scale );
|
||||
ImGui.TableSetupColumn( "x", ImGuiTableColumnFlags.WidthFixed, 100 * UiHelpers.Scale );
|
||||
ImGui.TableSetupColumn( "y", ImGuiTableColumnFlags.WidthFixed, 100 * UiHelpers.Scale );
|
||||
ImGui.TableSetupColumn( "z", ImGuiTableColumnFlags.WidthFixed, 100 * UiHelpers.Scale );
|
||||
ImGui.TableSetupColumn( "w", ImGuiTableColumnFlags.WidthFixed, 100 * UiHelpers.Scale );
|
||||
ImGui.TableSetupColumn(string.Empty, ImGuiTableColumnFlags.WidthFixed, 25 * UiHelpers.Scale);
|
||||
ImGui.TableSetupColumn("x", ImGuiTableColumnFlags.WidthFixed, 100 * UiHelpers.Scale);
|
||||
ImGui.TableSetupColumn("y", ImGuiTableColumnFlags.WidthFixed, 100 * UiHelpers.Scale);
|
||||
ImGui.TableSetupColumn("z", ImGuiTableColumnFlags.WidthFixed, 100 * UiHelpers.Scale);
|
||||
ImGui.TableSetupColumn("w", ImGuiTableColumnFlags.WidthFixed, 100 * UiHelpers.Scale);
|
||||
ImGui.TableHeadersRow();
|
||||
|
||||
var textColorStart = ImGui.GetColorU32( ImGuiCol.Text );
|
||||
var textColorCont = ( textColorStart & 0x00FFFFFFu ) | ( ( textColorStart & 0xFE000000u ) >> 1 ); // Half opacity
|
||||
var textColorUnusedStart = ( textColorStart & 0xFF000000u ) | ( ( textColorStart & 0x00FEFEFE ) >> 1 ) | 0x80u; // Half red
|
||||
var textColorUnusedCont = ( textColorUnusedStart & 0x00FFFFFFu ) | ( ( textColorUnusedStart & 0xFE000000u ) >> 1 );
|
||||
var textColorStart = ImGui.GetColorU32(ImGuiCol.Text);
|
||||
var textColorCont = (textColorStart & 0x00FFFFFFu) | ((textColorStart & 0xFE000000u) >> 1); // Half opacity
|
||||
var textColorUnusedStart = (textColorStart & 0xFF000000u) | ((textColorStart & 0x00FEFEFE) >> 1) | 0x80u; // Half red
|
||||
var textColorUnusedCont = (textColorUnusedStart & 0x00FFFFFFu) | ((textColorUnusedStart & 0xFE000000u) >> 1);
|
||||
|
||||
var ret = false;
|
||||
for( var i = 0; i < tab.Matrix.GetLength( 0 ); ++i )
|
||||
for (var i = 0; i < tab.Matrix.GetLength(0); ++i)
|
||||
{
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableHeader( $" [{i}]" );
|
||||
for( var j = 0; j < 4; ++j )
|
||||
ImGui.TableHeader($" [{i}]");
|
||||
for (var j = 0; j < 4; ++j)
|
||||
{
|
||||
var (name, tooltip, idx, colorType) = tab.Matrix[ i, j ];
|
||||
var (name, tooltip, idx, colorType) = tab.Matrix[i, j];
|
||||
var color = colorType switch
|
||||
{
|
||||
ShpkTab.ColorType.Unused => textColorUnusedStart,
|
||||
|
|
@ -332,367 +308,307 @@ public partial class ModEditWindow
|
|||
ShpkTab.ColorType.Continuation | ShpkTab.ColorType.Used => textColorCont,
|
||||
_ => textColorStart,
|
||||
};
|
||||
using var _ = ImRaii.PushId( i * 4 + j );
|
||||
using var _ = ImRaii.PushId(i * 4 + j);
|
||||
var deletable = !disabled && idx >= 0;
|
||||
using( var font = ImRaii.PushFont( UiBuilder.MonoFont, tooltip.Length > 0 ) )
|
||||
using (var font = ImRaii.PushFont(UiBuilder.MonoFont, tooltip.Length > 0))
|
||||
{
|
||||
using( var c = ImRaii.PushColor( ImGuiCol.Text, color ) )
|
||||
using (var c = ImRaii.PushColor(ImGuiCol.Text, color))
|
||||
{
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.Selectable( name );
|
||||
if( deletable && ImGui.IsItemClicked( ImGuiMouseButton.Right ) && ImGui.GetIO().KeyCtrl )
|
||||
ImGui.Selectable(name);
|
||||
if (deletable && ImGui.IsItemClicked(ImGuiMouseButton.Right) && ImGui.GetIO().KeyCtrl)
|
||||
{
|
||||
tab.Shpk.MaterialParams = tab.Shpk.MaterialParams.RemoveItems( idx );
|
||||
tab.Shpk.MaterialParams = tab.Shpk.MaterialParams.RemoveItems(idx);
|
||||
ret = true;
|
||||
tab.Update();
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip( tooltip );
|
||||
ImGuiUtil.HoverTooltip(tooltip);
|
||||
}
|
||||
|
||||
if( deletable )
|
||||
{
|
||||
ImGuiUtil.HoverTooltip( "\nControl + Right-Click to remove." );
|
||||
}
|
||||
if (deletable)
|
||||
ImGuiUtil.HoverTooltip("\nControl + Right-Click to remove.");
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static void DrawShaderPackageMisalignedParameters( ShpkTab tab )
|
||||
private static void DrawShaderPackageMisalignedParameters(ShpkTab tab)
|
||||
{
|
||||
using var t = ImRaii.TreeNode( "Misaligned / Overflowing Parameters" );
|
||||
if( !t )
|
||||
{
|
||||
using var t = ImRaii.TreeNode("Misaligned / Overflowing Parameters");
|
||||
if (!t)
|
||||
return;
|
||||
}
|
||||
|
||||
using var _ = ImRaii.PushFont( UiBuilder.MonoFont );
|
||||
foreach( var name in tab.MalformedParameters )
|
||||
{
|
||||
ImRaii.TreeNode( name, ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet ).Dispose();
|
||||
}
|
||||
using var _ = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||
foreach (var name in tab.MalformedParameters)
|
||||
ImRaii.TreeNode(name, ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
}
|
||||
|
||||
private static void DrawShaderPackageStartCombo( ShpkTab tab )
|
||||
private static void DrawShaderPackageStartCombo(ShpkTab tab)
|
||||
{
|
||||
using var s = ImRaii.PushStyle( ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemInnerSpacing );
|
||||
using( var _ = ImRaii.PushFont( UiBuilder.MonoFont ) )
|
||||
using var s = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemInnerSpacing);
|
||||
using (var _ = ImRaii.PushFont(UiBuilder.MonoFont))
|
||||
{
|
||||
ImGui.SetNextItemWidth( UiHelpers.Scale * 400 );
|
||||
using var c = ImRaii.Combo( "##Start", tab.Orphans[ tab.NewMaterialParamStart ].Name );
|
||||
if( c )
|
||||
{
|
||||
foreach( var (start, idx) in tab.Orphans.WithIndex() )
|
||||
ImGui.SetNextItemWidth(UiHelpers.Scale * 400);
|
||||
using var c = ImRaii.Combo("##Start", tab.Orphans[tab.NewMaterialParamStart].Name);
|
||||
if (c)
|
||||
foreach (var (start, idx) in tab.Orphans.WithIndex())
|
||||
{
|
||||
if( ImGui.Selectable( start.Name, idx == tab.NewMaterialParamStart ) )
|
||||
{
|
||||
tab.UpdateOrphanStart( idx );
|
||||
}
|
||||
if (ImGui.Selectable(start.Name, idx == tab.NewMaterialParamStart))
|
||||
tab.UpdateOrphanStart(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted( "Start" );
|
||||
ImGui.TextUnformatted("Start");
|
||||
}
|
||||
|
||||
private static void DrawShaderPackageEndCombo( ShpkTab tab )
|
||||
private static void DrawShaderPackageEndCombo(ShpkTab tab)
|
||||
{
|
||||
using var s = ImRaii.PushStyle( ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemInnerSpacing );
|
||||
using( var _ = ImRaii.PushFont( UiBuilder.MonoFont ) )
|
||||
using var s = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemInnerSpacing);
|
||||
using (var _ = ImRaii.PushFont(UiBuilder.MonoFont))
|
||||
{
|
||||
ImGui.SetNextItemWidth( UiHelpers.Scale * 400 );
|
||||
using var c = ImRaii.Combo( "##End", tab.Orphans[ tab.NewMaterialParamEnd ].Name );
|
||||
if( c )
|
||||
ImGui.SetNextItemWidth(UiHelpers.Scale * 400);
|
||||
using var c = ImRaii.Combo("##End", tab.Orphans[tab.NewMaterialParamEnd].Name);
|
||||
if (c)
|
||||
{
|
||||
var current = tab.Orphans[ tab.NewMaterialParamStart ].Index;
|
||||
for( var i = tab.NewMaterialParamStart; i < tab.Orphans.Count; ++i )
|
||||
var current = tab.Orphans[tab.NewMaterialParamStart].Index;
|
||||
for (var i = tab.NewMaterialParamStart; i < tab.Orphans.Count; ++i)
|
||||
{
|
||||
var next = tab.Orphans[ i ];
|
||||
if( current++ != next.Index )
|
||||
{
|
||||
var next = tab.Orphans[i];
|
||||
if (current++ != next.Index)
|
||||
break;
|
||||
}
|
||||
|
||||
if( ImGui.Selectable( next.Name, i == tab.NewMaterialParamEnd ) )
|
||||
{
|
||||
if (ImGui.Selectable(next.Name, i == tab.NewMaterialParamEnd))
|
||||
tab.NewMaterialParamEnd = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted( "End" );
|
||||
ImGui.TextUnformatted("End");
|
||||
}
|
||||
|
||||
private static bool DrawShaderPackageNewParameter( ShpkTab tab )
|
||||
private static bool DrawShaderPackageNewParameter(ShpkTab tab)
|
||||
{
|
||||
if( tab.Orphans.Count == 0 )
|
||||
{
|
||||
if (tab.Orphans.Count == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
DrawShaderPackageStartCombo( tab );
|
||||
DrawShaderPackageEndCombo( tab );
|
||||
DrawShaderPackageStartCombo(tab);
|
||||
DrawShaderPackageEndCombo(tab);
|
||||
|
||||
ImGui.SetNextItemWidth( UiHelpers.Scale * 400 );
|
||||
if( ImGui.InputText( "Name", ref tab.NewMaterialParamName, 63 ) )
|
||||
{
|
||||
tab.NewMaterialParamId = Crc32.Get( tab.NewMaterialParamName, 0xFFFFFFFFu );
|
||||
}
|
||||
ImGui.SetNextItemWidth(UiHelpers.Scale * 400);
|
||||
if (ImGui.InputText("Name", ref tab.NewMaterialParamName, 63))
|
||||
tab.NewMaterialParamId = Crc32.Get(tab.NewMaterialParamName, 0xFFFFFFFFu);
|
||||
|
||||
var tooltip = tab.UsedIds.Contains( tab.NewMaterialParamId )
|
||||
var tooltip = tab.UsedIds.Contains(tab.NewMaterialParamId)
|
||||
? "The ID is already in use. Please choose a different name."
|
||||
: string.Empty;
|
||||
if( !ImGuiUtil.DrawDisabledButton( $"Add ID 0x{tab.NewMaterialParamId:X8}", new Vector2( 400 * UiHelpers.Scale, ImGui.GetFrameHeight() ), tooltip,
|
||||
tooltip.Length > 0 ) )
|
||||
{
|
||||
if (!ImGuiUtil.DrawDisabledButton($"Add ID 0x{tab.NewMaterialParamId:X8}", new Vector2(400 * UiHelpers.Scale, ImGui.GetFrameHeight()),
|
||||
tooltip,
|
||||
tooltip.Length > 0))
|
||||
return false;
|
||||
}
|
||||
|
||||
tab.Shpk.MaterialParams = tab.Shpk.MaterialParams.AddItem( new MaterialParam
|
||||
tab.Shpk.MaterialParams = tab.Shpk.MaterialParams.AddItem(new MaterialParam
|
||||
{
|
||||
Id = tab.NewMaterialParamId,
|
||||
ByteOffset = ( ushort )( tab.Orphans[ tab.NewMaterialParamStart ].Index << 2 ),
|
||||
ByteSize = ( ushort )( ( tab.NewMaterialParamEnd - tab.NewMaterialParamStart + 1 ) << 2 ),
|
||||
} );
|
||||
ByteOffset = (ushort)(tab.Orphans[tab.NewMaterialParamStart].Index << 2),
|
||||
ByteSize = (ushort)((tab.NewMaterialParamEnd - tab.NewMaterialParamStart + 1) << 2),
|
||||
});
|
||||
tab.Update();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool DrawShaderPackageMaterialParamLayout( ShpkTab tab, bool disabled )
|
||||
private static bool DrawShaderPackageMaterialParamLayout(ShpkTab tab, bool disabled)
|
||||
{
|
||||
var ret = false;
|
||||
|
||||
var materialParams = tab.Shpk.GetConstantById( MaterialParamsConstantId );
|
||||
if( !DrawMaterialParamLayoutHeader( materialParams?.Name ?? "Material Parameter" ) )
|
||||
{
|
||||
var materialParams = tab.Shpk.GetConstantById(MaterialParamsConstantId);
|
||||
if (!DrawMaterialParamLayoutHeader(materialParams?.Name ?? "Material Parameter"))
|
||||
return false;
|
||||
}
|
||||
|
||||
var sizeWellDefined = DrawMaterialParamLayoutBufferSize( tab.Shpk, materialParams );
|
||||
var sizeWellDefined = DrawMaterialParamLayoutBufferSize(tab.Shpk, materialParams);
|
||||
|
||||
ret |= DrawShaderPackageMaterialMatrix( tab, disabled );
|
||||
ret |= DrawShaderPackageMaterialMatrix(tab, disabled);
|
||||
|
||||
if( tab.MalformedParameters.Count > 0 )
|
||||
{
|
||||
DrawShaderPackageMisalignedParameters( tab );
|
||||
}
|
||||
else if( !disabled && sizeWellDefined )
|
||||
{
|
||||
ret |= DrawShaderPackageNewParameter( tab );
|
||||
}
|
||||
if (tab.MalformedParameters.Count > 0)
|
||||
DrawShaderPackageMisalignedParameters(tab);
|
||||
else if (!disabled && sizeWellDefined)
|
||||
ret |= DrawShaderPackageNewParameter(tab);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawShaderPackageResources( ShpkTab tab, bool disabled )
|
||||
private static bool DrawShaderPackageResources(ShpkTab tab, bool disabled)
|
||||
{
|
||||
var ret = false;
|
||||
|
||||
if( !ImGui.CollapsingHeader( "Shader Resources" ) )
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Shader Resources"))
|
||||
return false;
|
||||
}
|
||||
|
||||
ret |= DrawShaderPackageResourceArray( "Constant Buffers", "type", true, tab.Shpk.Constants, disabled );
|
||||
ret |= DrawShaderPackageResourceArray( "Samplers", "type", false, tab.Shpk.Samplers, disabled );
|
||||
ret |= DrawShaderPackageResourceArray( "Unordered Access Views", "type", false, tab.Shpk.Uavs, disabled );
|
||||
ret |= DrawShaderPackageResourceArray("Constant Buffers", "type", true, tab.Shpk.Constants, disabled);
|
||||
ret |= DrawShaderPackageResourceArray("Samplers", "type", false, tab.Shpk.Samplers, disabled);
|
||||
ret |= DrawShaderPackageResourceArray("Unordered Access Views", "type", false, tab.Shpk.Uavs, disabled);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static void DrawKeyArray( string arrayName, bool withId, IReadOnlyCollection< Key > keys )
|
||||
private static void DrawKeyArray(string arrayName, bool withId, IReadOnlyCollection<Key> keys)
|
||||
{
|
||||
if( keys.Count == 0 )
|
||||
{
|
||||
if (keys.Count == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
using var t = ImRaii.TreeNode( arrayName );
|
||||
if( !t )
|
||||
{
|
||||
using var t = ImRaii.TreeNode(arrayName);
|
||||
if (!t)
|
||||
return;
|
||||
}
|
||||
|
||||
using var font = ImRaii.PushFont( UiBuilder.MonoFont );
|
||||
foreach( var (key, idx) in keys.WithIndex() )
|
||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||
foreach (var (key, idx) in keys.WithIndex())
|
||||
{
|
||||
using var t2 = ImRaii.TreeNode( withId ? $"#{idx}: ID: 0x{key.Id:X8}" : $"#{idx}" );
|
||||
if( t2 )
|
||||
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 | ImGuiTreeNodeFlags.Bullet ).Dispose();
|
||||
ImRaii.TreeNode( $"Known Values: {string.Join( ", ", Array.ConvertAll( key.Values, value => $"0x{value:X8}" ) )}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet ).Dispose();
|
||||
ImRaii.TreeNode($"Default Value: 0x{key.DefaultValue:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
ImRaii.TreeNode($"Known Values: {string.Join(", ", Array.ConvertAll(key.Values, value => $"0x{value:X8}"))}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawShaderPackageNodes( ShpkTab tab )
|
||||
private static void DrawShaderPackageNodes(ShpkTab tab)
|
||||
{
|
||||
if( tab.Shpk.Nodes.Length <= 0 )
|
||||
{
|
||||
if (tab.Shpk.Nodes.Length <= 0)
|
||||
return;
|
||||
}
|
||||
|
||||
using var t = ImRaii.TreeNode( $"Nodes ({tab.Shpk.Nodes.Length})###Nodes" );
|
||||
if( !t )
|
||||
{
|
||||
using var t = ImRaii.TreeNode($"Nodes ({tab.Shpk.Nodes.Length})###Nodes");
|
||||
if (!t)
|
||||
return;
|
||||
}
|
||||
|
||||
foreach( var (node, idx) in tab.Shpk.Nodes.WithIndex() )
|
||||
foreach (var (node, idx) in tab.Shpk.Nodes.WithIndex())
|
||||
{
|
||||
using var font = ImRaii.PushFont( UiBuilder.MonoFont );
|
||||
using var t2 = ImRaii.TreeNode( $"#{idx:D4}: Selector: 0x{node.Selector:X8}" );
|
||||
if( !t2 )
|
||||
{
|
||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||
using var t2 = ImRaii.TreeNode($"#{idx:D4}: Selector: 0x{node.Selector:X8}");
|
||||
if (!t2)
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach( var (key, keyIdx) in node.SystemKeys.WithIndex() )
|
||||
{
|
||||
ImRaii.TreeNode( $"System Key 0x{tab.Shpk.SystemKeys[ keyIdx ].Id:X8} = 0x{key:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet ).Dispose();
|
||||
}
|
||||
foreach (var (key, keyIdx) in node.SystemKeys.WithIndex())
|
||||
ImRaii.TreeNode($"System Key 0x{tab.Shpk.SystemKeys[keyIdx].Id:X8} = 0x{key:X8}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
|
||||
foreach( var (key, keyIdx) in node.SceneKeys.WithIndex() )
|
||||
{
|
||||
ImRaii.TreeNode( $"Scene Key 0x{tab.Shpk.SceneKeys[ keyIdx ].Id:X8} = 0x{key:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet ).Dispose();
|
||||
}
|
||||
foreach (var (key, keyIdx) in node.SceneKeys.WithIndex())
|
||||
ImRaii.TreeNode($"Scene Key 0x{tab.Shpk.SceneKeys[keyIdx].Id:X8} = 0x{key:X8}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
|
||||
foreach( var (key, keyIdx) in node.MaterialKeys.WithIndex() )
|
||||
{
|
||||
ImRaii.TreeNode( $"Material Key 0x{tab.Shpk.MaterialKeys[ keyIdx ].Id:X8} = 0x{key:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet ).Dispose();
|
||||
}
|
||||
foreach (var (key, keyIdx) in node.MaterialKeys.WithIndex())
|
||||
ImRaii.TreeNode($"Material Key 0x{tab.Shpk.MaterialKeys[keyIdx].Id:X8} = 0x{key:X8}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
|
||||
foreach( var (key, keyIdx) in node.SubViewKeys.WithIndex() )
|
||||
{
|
||||
ImRaii.TreeNode( $"Sub-View Key #{keyIdx} = 0x{key:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet ).Dispose();
|
||||
}
|
||||
foreach (var (key, keyIdx) in node.SubViewKeys.WithIndex())
|
||||
ImRaii.TreeNode($"Sub-View Key #{keyIdx} = 0x{key:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
|
||||
ImRaii.TreeNode( $"Pass Indices: {string.Join( ' ', node.PassIndices.Select( c => $"{c:X2}" ) )}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet ).Dispose();
|
||||
foreach( var (pass, passIdx) in node.Passes.WithIndex() )
|
||||
ImRaii.TreeNode($"Pass Indices: {string.Join(' ', node.PassIndices.Select(c => $"{c:X2}"))}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).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 | ImGuiTreeNodeFlags.Bullet )
|
||||
.Dispose();
|
||||
ImRaii.TreeNode($"Pass #{passIdx}: ID: 0x{pass.Id:X8}, Vertex Shader #{pass.VertexShader}, Pixel Shader #{pass.PixelShader}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet)
|
||||
.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawShaderPackageSelection( ShpkTab tab )
|
||||
private static void DrawShaderPackageSelection(ShpkTab tab)
|
||||
{
|
||||
if( !ImGui.CollapsingHeader( "Shader Selection" ) )
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Shader Selection"))
|
||||
return;
|
||||
}
|
||||
|
||||
DrawKeyArray( "System Keys", true, tab.Shpk.SystemKeys );
|
||||
DrawKeyArray( "Scene Keys", true, tab.Shpk.SceneKeys );
|
||||
DrawKeyArray( "Material Keys", true, tab.Shpk.MaterialKeys );
|
||||
DrawKeyArray( "Sub-View Keys", false, tab.Shpk.SubViewKeys );
|
||||
DrawKeyArray("System Keys", true, tab.Shpk.SystemKeys);
|
||||
DrawKeyArray("Scene Keys", true, tab.Shpk.SceneKeys);
|
||||
DrawKeyArray("Material Keys", true, tab.Shpk.MaterialKeys);
|
||||
DrawKeyArray("Sub-View Keys", false, tab.Shpk.SubViewKeys);
|
||||
|
||||
DrawShaderPackageNodes( tab );
|
||||
using var t = ImRaii.TreeNode( $"Node Selectors ({tab.Shpk.NodeSelectors.Count})###NodeSelectors" );
|
||||
if( t )
|
||||
DrawShaderPackageNodes(tab);
|
||||
using var t = ImRaii.TreeNode($"Node Selectors ({tab.Shpk.NodeSelectors.Count})###NodeSelectors");
|
||||
if (t)
|
||||
{
|
||||
using var font = ImRaii.PushFont( UiBuilder.MonoFont );
|
||||
foreach( var selector in tab.Shpk.NodeSelectors )
|
||||
{
|
||||
ImRaii.TreeNode( $"#{selector.Value:D4}: Selector: 0x{selector.Key:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet ).Dispose();
|
||||
}
|
||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||
foreach (var selector in tab.Shpk.NodeSelectors)
|
||||
ImRaii.TreeNode($"#{selector.Value:D4}: Selector: 0x{selector.Key:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet)
|
||||
.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawOtherShaderPackageDetails( ShpkTab tab )
|
||||
private static void DrawOtherShaderPackageDetails(ShpkTab tab)
|
||||
{
|
||||
if( !ImGui.CollapsingHeader( "Further Content" ) )
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Further Content"))
|
||||
return;
|
||||
}
|
||||
|
||||
ImRaii.TreeNode( $"Version: 0x{tab.Shpk.Version:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet ).Dispose();
|
||||
ImRaii.TreeNode($"Version: 0x{tab.Shpk.Version:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
|
||||
if( tab.Shpk.AdditionalData.Length > 0 )
|
||||
if (tab.Shpk.AdditionalData.Length > 0)
|
||||
{
|
||||
using var t = ImRaii.TreeNode( $"Additional Data (Size: {tab.Shpk.AdditionalData.Length})###AdditionalData" );
|
||||
if( t )
|
||||
{
|
||||
ImGuiUtil.TextWrapped( string.Join( ' ', tab.Shpk.AdditionalData.Select( c => $"{c:X2}" ) ) );
|
||||
}
|
||||
using var t = ImRaii.TreeNode($"Additional Data (Size: {tab.Shpk.AdditionalData.Length})###AdditionalData");
|
||||
if (t)
|
||||
ImGuiUtil.TextWrapped(string.Join(' ', tab.Shpk.AdditionalData.Select(c => $"{c:X2}")));
|
||||
}
|
||||
}
|
||||
|
||||
private static string UsedComponentString( bool withSize, in Resource resource )
|
||||
private static string UsedComponentString(bool withSize, in Resource resource)
|
||||
{
|
||||
var sb = new StringBuilder( 256 );
|
||||
if( withSize )
|
||||
var sb = new StringBuilder(256);
|
||||
if (withSize)
|
||||
{
|
||||
foreach( var (components, i) in ( resource.Used ?? Array.Empty< DisassembledShader.VectorComponents >() ).WithIndex() )
|
||||
foreach (var (components, i) in (resource.Used ?? Array.Empty<DisassembledShader.VectorComponents>()).WithIndex())
|
||||
{
|
||||
switch( components )
|
||||
switch (components)
|
||||
{
|
||||
case 0: break;
|
||||
case DisassembledShader.VectorComponents.All:
|
||||
sb.Append( $"[{i}], " );
|
||||
sb.Append($"[{i}], ");
|
||||
break;
|
||||
default:
|
||||
sb.Append( $"[{i}]." );
|
||||
foreach( var c in components.ToString().Where( char.IsUpper ) )
|
||||
{
|
||||
sb.Append( char.ToLower( c ) );
|
||||
}
|
||||
sb.Append($"[{i}].");
|
||||
foreach (var c in components.ToString().Where(char.IsUpper))
|
||||
sb.Append(char.ToLower(c));
|
||||
|
||||
sb.Append( ", " );
|
||||
sb.Append(", ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch( resource.UsedDynamically ?? 0 )
|
||||
switch (resource.UsedDynamically ?? 0)
|
||||
{
|
||||
case 0: break;
|
||||
case DisassembledShader.VectorComponents.All:
|
||||
sb.Append( "[*], " );
|
||||
sb.Append("[*], ");
|
||||
break;
|
||||
default:
|
||||
sb.Append( "[*]." );
|
||||
foreach( var c in resource.UsedDynamically!.Value.ToString().Where( char.IsUpper ) )
|
||||
{
|
||||
sb.Append( char.ToLower( c ) );
|
||||
}
|
||||
sb.Append("[*].");
|
||||
foreach (var c in resource.UsedDynamically!.Value.ToString().Where(char.IsUpper))
|
||||
sb.Append(char.ToLower(c));
|
||||
|
||||
sb.Append( ", " );
|
||||
sb.Append(", ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var components = ( resource.Used is { Length: > 0 } ? resource.Used[ 0 ] : 0 ) | ( resource.UsedDynamically ?? 0 );
|
||||
if( ( components & DisassembledShader.VectorComponents.X ) != 0 )
|
||||
{
|
||||
sb.Append( "Red, " );
|
||||
}
|
||||
var components = (resource.Used is { Length: > 0 } ? resource.Used[0] : 0) | (resource.UsedDynamically ?? 0);
|
||||
if ((components & DisassembledShader.VectorComponents.X) != 0)
|
||||
sb.Append("Red, ");
|
||||
|
||||
if( ( components & DisassembledShader.VectorComponents.Y ) != 0 )
|
||||
{
|
||||
sb.Append( "Green, " );
|
||||
}
|
||||
if ((components & DisassembledShader.VectorComponents.Y) != 0)
|
||||
sb.Append("Green, ");
|
||||
|
||||
if( ( components & DisassembledShader.VectorComponents.Z ) != 0 )
|
||||
{
|
||||
sb.Append( "Blue, " );
|
||||
}
|
||||
if ((components & DisassembledShader.VectorComponents.Z) != 0)
|
||||
sb.Append("Blue, ");
|
||||
|
||||
if( ( components & DisassembledShader.VectorComponents.W ) != 0 )
|
||||
{
|
||||
sb.Append( "Alpha, " );
|
||||
}
|
||||
if ((components & DisassembledShader.VectorComponents.W) != 0)
|
||||
sb.Append("Alpha, ");
|
||||
}
|
||||
|
||||
return sb.Length == 0 ? string.Empty : sb.ToString( 0, sb.Length - 2 );
|
||||
return sb.Length == 0 ? string.Empty : sb.ToString(0, sb.Length - 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -533,14 +533,20 @@ public partial class ModEditWindow : Window, IDisposable
|
|||
var ret = new HashSet<Utf8GamePath>();
|
||||
|
||||
foreach (var path in _activeCollections.Current.ResolvedFiles.Keys)
|
||||
{
|
||||
if (path.Path.StartsWith(prefix))
|
||||
ret.Add(path);
|
||||
}
|
||||
|
||||
if (_mod != null)
|
||||
foreach (var option in _mod.Groups.SelectMany(g => g).Append(_mod.Default))
|
||||
{
|
||||
foreach (var path in option.Files.Keys)
|
||||
{
|
||||
if (path.Path.StartsWith(prefix))
|
||||
ret.Add(path);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue