mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Auto-formatting, generous application of ImUtf8, minor cleanups.
This commit is contained in:
parent
c8e859ae05
commit
f8b034c42d
13 changed files with 647 additions and 517 deletions
|
|
@ -13,7 +13,7 @@ public partial class MtrlTab
|
|||
{
|
||||
private const float ColorTableScalarSize = 65.0f;
|
||||
|
||||
private int _colorTableSelectedPair = 0;
|
||||
private int _colorTableSelectedPair;
|
||||
|
||||
private bool DrawColorTable(ColorTable table, ColorDyeTable? dyeTable, bool disabled)
|
||||
{
|
||||
|
|
@ -23,25 +23,27 @@ public partial class MtrlTab
|
|||
|
||||
private void DrawColorTablePairSelector(ColorTable table, bool disabled)
|
||||
{
|
||||
var style = ImGui.GetStyle();
|
||||
var itemSpacing = style.ItemSpacing.X;
|
||||
var itemInnerSpacing = style.ItemInnerSpacing.X;
|
||||
var framePadding = style.FramePadding;
|
||||
var buttonWidth = (ImGui.GetContentRegionAvail().X - itemSpacing * 7.0f) * 0.125f;
|
||||
var frameHeight = ImGui.GetFrameHeight();
|
||||
var highlighterSize = ImUtf8.CalcIconSize(FontAwesomeIcon.Crosshairs) + framePadding * 2.0f;
|
||||
var spaceWidth = ImUtf8.CalcTextSize(" "u8).X;
|
||||
var spacePadding = (int)MathF.Ceiling((highlighterSize.X + framePadding.X + itemInnerSpacing) / spaceWidth);
|
||||
|
||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||
using var alignment = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f));
|
||||
var style = ImGui.GetStyle();
|
||||
var itemSpacing = style.ItemSpacing.X;
|
||||
var itemInnerSpacing = style.ItemInnerSpacing.X;
|
||||
var framePadding = style.FramePadding;
|
||||
var buttonWidth = (ImGui.GetContentRegionAvail().X - itemSpacing * 7.0f) * 0.125f;
|
||||
var frameHeight = ImGui.GetFrameHeight();
|
||||
var highlighterSize = ImUtf8.CalcIconSize(FontAwesomeIcon.Crosshairs) + framePadding * 2.0f;
|
||||
var spaceWidth = ImUtf8.CalcTextSize(" "u8).X;
|
||||
var spacePadding = (int)MathF.Ceiling((highlighterSize.X + framePadding.X + itemInnerSpacing) / spaceWidth);
|
||||
for (var i = 0; i < ColorTable.NumRows >> 1; i += 8)
|
||||
{
|
||||
for (var j = 0; j < 8; ++j)
|
||||
{
|
||||
var pairIndex = i + j;
|
||||
using (var color = ImRaii.PushColor(ImGuiCol.Button, ImGui.GetColorU32(ImGuiCol.ButtonActive), pairIndex == _colorTableSelectedPair))
|
||||
using (ImRaii.PushColor(ImGuiCol.Button, ImGui.GetColorU32(ImGuiCol.ButtonActive), pairIndex == _colorTableSelectedPair))
|
||||
{
|
||||
if (ImUtf8.Button($"#{pairIndex + 1}".PadLeft(3 + spacePadding), new Vector2(buttonWidth, ImGui.GetFrameHeightWithSpacing() + frameHeight)))
|
||||
if (ImUtf8.Button($"#{pairIndex + 1}".PadLeft(3 + spacePadding),
|
||||
new Vector2(buttonWidth, ImGui.GetFrameHeightWithSpacing() + frameHeight)))
|
||||
_colorTableSelectedPair = pairIndex;
|
||||
}
|
||||
|
||||
|
|
@ -79,12 +81,10 @@ public partial class MtrlTab
|
|||
|
||||
private bool DrawColorTablePairEditor(ColorTable table, ColorDyeTable? dyeTable, bool disabled)
|
||||
{
|
||||
var retA = false;
|
||||
var retB = false;
|
||||
ref var rowA = ref table[_colorTableSelectedPair << 1];
|
||||
ref var rowB = ref table[(_colorTableSelectedPair << 1) | 1];
|
||||
var dyeA = dyeTable != null ? dyeTable[_colorTableSelectedPair << 1] : default;
|
||||
var dyeB = dyeTable != null ? dyeTable[(_colorTableSelectedPair << 1) | 1] : default;
|
||||
var retA = false;
|
||||
var retB = false;
|
||||
var dyeA = dyeTable?[_colorTableSelectedPair << 1] ?? default;
|
||||
var dyeB = dyeTable?[(_colorTableSelectedPair << 1) | 1] ?? default;
|
||||
var previewDyeA = _stainService.GetStainCombo(dyeA.Channel).CurrentSelection.Key;
|
||||
var previewDyeB = _stainService.GetStainCombo(dyeB.Channel).CurrentSelection.Key;
|
||||
var dyePackA = _stainService.GudStmFile.GetValueOrNull(dyeA.Template, previewDyeA);
|
||||
|
|
@ -108,68 +108,96 @@ public partial class MtrlTab
|
|||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||
{
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
using (var id = ImUtf8.PushId("ColorsA"u8))
|
||||
using (ImUtf8.PushId("ColorsA"u8))
|
||||
{
|
||||
retA |= DrawColors(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||
}
|
||||
|
||||
columns.Next();
|
||||
using (var id = ImUtf8.PushId("ColorsB"u8))
|
||||
using (ImUtf8.PushId("ColorsB"u8))
|
||||
{
|
||||
retB |= DrawColors(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||
}
|
||||
}
|
||||
|
||||
DrawHeader(" Physical Parameters"u8);
|
||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||
{
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
using (var id = ImUtf8.PushId("PbrA"u8))
|
||||
using (ImUtf8.PushId("PbrA"u8))
|
||||
{
|
||||
retA |= DrawPbr(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||
}
|
||||
|
||||
columns.Next();
|
||||
using (var id = ImUtf8.PushId("PbrB"u8))
|
||||
using (ImUtf8.PushId("PbrB"u8))
|
||||
{
|
||||
retB |= DrawPbr(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||
}
|
||||
}
|
||||
|
||||
DrawHeader(" Sheen Layer Parameters"u8);
|
||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||
{
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
using (var id = ImUtf8.PushId("SheenA"u8))
|
||||
using (ImUtf8.PushId("SheenA"u8))
|
||||
{
|
||||
retA |= DrawSheen(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||
}
|
||||
|
||||
columns.Next();
|
||||
using (var id = ImUtf8.PushId("SheenB"u8))
|
||||
using (ImUtf8.PushId("SheenB"u8))
|
||||
{
|
||||
retB |= DrawSheen(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||
}
|
||||
}
|
||||
|
||||
DrawHeader(" Pair Blending"u8);
|
||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||
{
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
using (var id = ImUtf8.PushId("BlendingA"u8))
|
||||
using (ImUtf8.PushId("BlendingA"u8))
|
||||
{
|
||||
retA |= DrawBlending(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||
}
|
||||
|
||||
columns.Next();
|
||||
using (var id = ImUtf8.PushId("BlendingB"u8))
|
||||
using (ImUtf8.PushId("BlendingB"u8))
|
||||
{
|
||||
retB |= DrawBlending(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||
}
|
||||
}
|
||||
|
||||
DrawHeader(" Material Template"u8);
|
||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||
{
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
using (var id = ImUtf8.PushId("TemplateA"u8))
|
||||
using (ImUtf8.PushId("TemplateA"u8))
|
||||
{
|
||||
retA |= DrawTemplate(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||
}
|
||||
|
||||
columns.Next();
|
||||
using (var id = ImUtf8.PushId("TemplateB"u8))
|
||||
using (ImUtf8.PushId("TemplateB"u8))
|
||||
{
|
||||
retB |= DrawTemplate(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (dyeTable != null)
|
||||
{
|
||||
DrawHeader(" Dye Properties"u8);
|
||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||
using var columns = ImUtf8.Columns(2, "ColorTable"u8);
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
using (ImUtf8.PushId("DyeA"u8))
|
||||
{
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
using (var id = ImUtf8.PushId("DyeA"u8))
|
||||
retA |= DrawDye(dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||
columns.Next();
|
||||
using (var id = ImUtf8.PushId("DyeB"u8))
|
||||
retB |= DrawDye(dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||
retA |= DrawDye(dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||
}
|
||||
|
||||
columns.Next();
|
||||
using (ImUtf8.PushId("DyeB"u8))
|
||||
{
|
||||
retB |= DrawDye(dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -177,11 +205,16 @@ public partial class MtrlTab
|
|||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||
{
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
using (var id = ImUtf8.PushId("FurtherA"u8))
|
||||
using (ImUtf8.PushId("FurtherA"u8))
|
||||
{
|
||||
retA |= DrawFurther(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||
}
|
||||
|
||||
columns.Next();
|
||||
using (var id = ImUtf8.PushId("FurtherB"u8))
|
||||
using (ImUtf8.PushId("FurtherB"u8))
|
||||
{
|
||||
retB |= DrawFurther(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (retA)
|
||||
|
|
@ -195,18 +228,21 @@ public partial class MtrlTab
|
|||
/// <remarks> Padding styles do not seem to apply to this component. It is recommended to prepend two spaces. </remarks>
|
||||
private static void DrawHeader(ReadOnlySpan<byte> label)
|
||||
{
|
||||
var headerColor = ImGui.GetColorU32(ImGuiCol.Header);
|
||||
using var _ = ImRaii.PushColor(ImGuiCol.HeaderHovered, headerColor).Push(ImGuiCol.HeaderActive, headerColor);
|
||||
var headerColor = ImGui.GetColorU32(ImGuiCol.Header);
|
||||
using var _ = ImRaii.PushColor(ImGuiCol.HeaderHovered, headerColor).Push(ImGuiCol.HeaderActive, headerColor);
|
||||
ImUtf8.CollapsingHeader(label, ImGuiTreeNodeFlags.Leaf);
|
||||
}
|
||||
|
||||
private static bool DrawColors(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
||||
{
|
||||
var dyeOffset = ImGui.GetContentRegionAvail().X + ImGui.GetStyle().ItemSpacing.X - ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight() * 2.0f;
|
||||
var dyeOffset = ImGui.GetContentRegionAvail().X
|
||||
+ ImGui.GetStyle().ItemSpacing.X
|
||||
- ImGui.GetStyle().ItemInnerSpacing.X
|
||||
- ImGui.GetFrameHeight() * 2.0f;
|
||||
|
||||
var ret = false;
|
||||
var ret = false;
|
||||
ref var row = ref table[rowIdx];
|
||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
||||
var dye = dyeTable?[rowIdx] ?? default;
|
||||
|
||||
ret |= CtColorPicker("Diffuse Color"u8, default, row.DiffuseColor,
|
||||
c => table[rowIdx].DiffuseColor = c);
|
||||
|
|
@ -247,13 +283,17 @@ public partial class MtrlTab
|
|||
private static bool DrawBlending(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
||||
{
|
||||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
||||
var dyeOffset = ImGui.GetContentRegionAvail().X + ImGui.GetStyle().ItemSpacing.X - ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight() - scalarSize;
|
||||
var dyeOffset = ImGui.GetContentRegionAvail().X
|
||||
+ ImGui.GetStyle().ItemSpacing.X
|
||||
- ImGui.GetStyle().ItemInnerSpacing.X
|
||||
- ImGui.GetFrameHeight()
|
||||
- scalarSize;
|
||||
|
||||
var isRowB = (rowIdx & 1) != 0;
|
||||
|
||||
var ret = false;
|
||||
var ret = false;
|
||||
ref var row = ref table[rowIdx];
|
||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
||||
var dye = dyeTable?[rowIdx] ?? default;
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragHalf(isRowB ? "Field #19"u8 : "Anisotropy Degree"u8, default, row.Anisotropy, "%.2f"u8, 0.0f, HalfMaxValue, 0.1f,
|
||||
|
|
@ -261,11 +301,13 @@ public partial class MtrlTab
|
|||
if (dyeTable != null)
|
||||
{
|
||||
ImGui.SameLine(dyeOffset);
|
||||
ret |= CtApplyStainCheckbox("##dyeAnisotropy"u8, isRowB ? "Apply Field #19 on Dye"u8 : "Apply Anisotropy Degree on Dye"u8, dye.Anisotropy,
|
||||
ret |= CtApplyStainCheckbox("##dyeAnisotropy"u8, isRowB ? "Apply Field #19 on Dye"u8 : "Apply Anisotropy Degree on Dye"u8,
|
||||
dye.Anisotropy,
|
||||
b => dyeTable[rowIdx].Anisotropy = b);
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
CtDragHalf("##dyePreviewAnisotropy"u8, isRowB ? "Dye Preview for Field #19"u8 : "Dye Preview for Anisotropy Degree"u8, dyePack?.Anisotropy, "%.2f"u8);
|
||||
CtDragHalf("##dyePreviewAnisotropy"u8, isRowB ? "Dye Preview for Field #19"u8 : "Dye Preview for Anisotropy Degree"u8,
|
||||
dyePack?.Anisotropy, "%.2f"u8);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -276,11 +318,11 @@ public partial class MtrlTab
|
|||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
||||
var itemSpacing = ImGui.GetStyle().ItemSpacing.X;
|
||||
var dyeOffset = ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight() - scalarSize - 64.0f;
|
||||
var subcolWidth = CalculateSubcolumnWidth(2);
|
||||
var subColWidth = CalculateSubColumnWidth(2);
|
||||
|
||||
var ret = false;
|
||||
var ret = false;
|
||||
ref var row = ref table[rowIdx];
|
||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
||||
var dye = dyeTable?[rowIdx] ?? default;
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragScalar("Shader ID"u8, default, row.ShaderId, "%d"u8, (ushort)0, (ushort)255, 0.25f,
|
||||
|
|
@ -306,13 +348,15 @@ public partial class MtrlTab
|
|||
ImGui.SetCursorScreenPos(ImGui.GetCursorScreenPos() with { Y = cursor.Y });
|
||||
ImGui.SetNextItemWidth(scalarSize + itemSpacing + 64.0f);
|
||||
using var dis = ImRaii.Disabled();
|
||||
CtSphereMapIndexPicker("###SphereMapIndexDye"u8, "Dye Preview for Sphere Map"u8, dyePack?.SphereMapIndex ?? ushort.MaxValue, false, Nop);
|
||||
CtSphereMapIndexPicker("###SphereMapIndexDye"u8, "Dye Preview for Sphere Map"u8, dyePack?.SphereMapIndex ?? ushort.MaxValue, false,
|
||||
Nop);
|
||||
}
|
||||
|
||||
ImGui.Dummy(new Vector2(64.0f, 0.0f));
|
||||
ImGui.SameLine();
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragScalar("Sphere Map Intensity"u8, default, (float)row.SphereMapMask * 100.0f, "%.0f%%"u8, HalfMinValue * 100.0f, HalfMaxValue * 100.0f, 1.0f,
|
||||
ret |= CtDragScalar("Sphere Map Intensity"u8, default, (float)row.SphereMapMask * 100.0f, "%.0f%%"u8, HalfMinValue * 100.0f,
|
||||
HalfMaxValue * 100.0f, 1.0f,
|
||||
v => table[rowIdx].SphereMapMask = (Half)(v * 0.01f));
|
||||
if (dyeTable != null)
|
||||
{
|
||||
|
|
@ -326,10 +370,10 @@ public partial class MtrlTab
|
|||
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
|
||||
var leftLineHeight = 64.0f + ImGui.GetStyle().FramePadding.Y * 2.0f;
|
||||
var leftLineHeight = 64.0f + ImGui.GetStyle().FramePadding.Y * 2.0f;
|
||||
var rightLineHeight = 3.0f * ImGui.GetFrameHeight() + 2.0f * ImGui.GetStyle().ItemSpacing.Y;
|
||||
var lineHeight = Math.Max(leftLineHeight, rightLineHeight);
|
||||
var cursorPos = ImGui.GetCursorScreenPos();
|
||||
var lineHeight = Math.Max(leftLineHeight, rightLineHeight);
|
||||
var cursorPos = ImGui.GetCursorScreenPos();
|
||||
ImGui.SetCursorScreenPos(cursorPos + new Vector2(0.0f, (lineHeight - leftLineHeight) * 0.5f));
|
||||
ImGui.SetNextItemWidth(scalarSize + (itemSpacing + 64.0f) * 2.0f);
|
||||
ret |= CtTileIndexPicker("###TileIndex"u8, default, row.TileIndex, false,
|
||||
|
|
@ -337,9 +381,10 @@ public partial class MtrlTab
|
|||
ImUtf8.SameLineInner();
|
||||
ImUtf8.Text("Tile"u8);
|
||||
|
||||
ImGui.SameLine(subcolWidth);
|
||||
ImGui.SetCursorScreenPos(ImGui.GetCursorScreenPos() with { Y = cursorPos.Y + (lineHeight - rightLineHeight) * 0.5f, });
|
||||
using (var cld = ImUtf8.Child("###TileProperties"u8, new(ImGui.GetContentRegionAvail().X, float.Lerp(rightLineHeight, lineHeight, 0.5f)), false))
|
||||
ImGui.SameLine(subColWidth);
|
||||
ImGui.SetCursorScreenPos(ImGui.GetCursorScreenPos() with { Y = cursorPos.Y + (lineHeight - rightLineHeight) * 0.5f });
|
||||
using (ImUtf8.Child("###TileProperties"u8,
|
||||
new Vector2(ImGui.GetContentRegionAvail().X, float.Lerp(rightLineHeight, lineHeight, 0.5f))))
|
||||
{
|
||||
ImGui.Dummy(new Vector2(scalarSize, 0.0f));
|
||||
ImUtf8.SameLineInner();
|
||||
|
|
@ -350,7 +395,8 @@ public partial class MtrlTab
|
|||
ret |= CtTileTransformMatrix(row.TileTransform, scalarSize, true,
|
||||
m => table[rowIdx].TileTransform = m);
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetCursorScreenPos(ImGui.GetCursorScreenPos() - new Vector2(0.0f, (ImGui.GetFrameHeight() + ImGui.GetStyle().ItemSpacing.Y) * 0.5f));
|
||||
ImGui.SetCursorScreenPos(ImGui.GetCursorScreenPos()
|
||||
- new Vector2(0.0f, (ImGui.GetFrameHeight() + ImGui.GetStyle().ItemSpacing.Y) * 0.5f));
|
||||
ImUtf8.Text("Tile Transform"u8);
|
||||
}
|
||||
|
||||
|
|
@ -360,15 +406,20 @@ public partial class MtrlTab
|
|||
private static bool DrawPbr(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
||||
{
|
||||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
||||
var subcolWidth = CalculateSubcolumnWidth(2) + ImGui.GetStyle().ItemSpacing.X;
|
||||
var dyeOffset = subcolWidth - ImGui.GetStyle().ItemSpacing.X * 2.0f - ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight() - scalarSize;
|
||||
var subColWidth = CalculateSubColumnWidth(2) + ImGui.GetStyle().ItemSpacing.X;
|
||||
var dyeOffset = subColWidth
|
||||
- ImGui.GetStyle().ItemSpacing.X * 2.0f
|
||||
- ImGui.GetStyle().ItemInnerSpacing.X
|
||||
- ImGui.GetFrameHeight()
|
||||
- scalarSize;
|
||||
|
||||
var ret = false;
|
||||
var ret = false;
|
||||
ref var row = ref table[rowIdx];
|
||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
||||
var dye = dyeTable?[rowIdx] ?? default;
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragScalar("Roughness"u8, default, (float)row.Roughness * 100.0f, "%.0f%%"u8, HalfMinValue * 100.0f, HalfMaxValue * 100.0f, 1.0f,
|
||||
ret |= CtDragScalar("Roughness"u8, default, (float)row.Roughness * 100.0f, "%.0f%%"u8, HalfMinValue * 100.0f, HalfMaxValue * 100.0f,
|
||||
1.0f,
|
||||
v => table[rowIdx].Roughness = (Half)(v * 0.01f));
|
||||
if (dyeTable != null)
|
||||
{
|
||||
|
|
@ -380,13 +431,14 @@ public partial class MtrlTab
|
|||
CtDragScalar("##dyePreviewRoughness"u8, "Dye Preview for Roughness"u8, (float?)dyePack?.Roughness * 100.0f, "%.0f%%"u8);
|
||||
}
|
||||
|
||||
ImGui.SameLine(subcolWidth);
|
||||
ImGui.SameLine(subColWidth);
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragScalar("Metalness"u8, default, (float)row.Metalness * 100.0f, "%.0f%%"u8, HalfMinValue * 100.0f, HalfMaxValue * 100.0f, 1.0f,
|
||||
ret |= CtDragScalar("Metalness"u8, default, (float)row.Metalness * 100.0f, "%.0f%%"u8, HalfMinValue * 100.0f, HalfMaxValue * 100.0f,
|
||||
1.0f,
|
||||
v => table[rowIdx].Metalness = (Half)(v * 0.01f));
|
||||
if (dyeTable != null)
|
||||
{
|
||||
ImGui.SameLine(subcolWidth + dyeOffset);
|
||||
ImGui.SameLine(subColWidth + dyeOffset);
|
||||
ret |= CtApplyStainCheckbox("##dyeMetalness"u8, "Apply Metalness on Dye"u8, dye.Metalness,
|
||||
b => dyeTable[rowIdx].Metalness = b);
|
||||
ImUtf8.SameLineInner();
|
||||
|
|
@ -400,12 +452,16 @@ public partial class MtrlTab
|
|||
private static bool DrawSheen(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
||||
{
|
||||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
||||
var subcolWidth = CalculateSubcolumnWidth(2) + ImGui.GetStyle().ItemSpacing.X;
|
||||
var dyeOffset = subcolWidth - ImGui.GetStyle().ItemSpacing.X * 2.0f - ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight() - scalarSize;
|
||||
var subColWidth = CalculateSubColumnWidth(2) + ImGui.GetStyle().ItemSpacing.X;
|
||||
var dyeOffset = subColWidth
|
||||
- ImGui.GetStyle().ItemSpacing.X * 2.0f
|
||||
- ImGui.GetStyle().ItemInnerSpacing.X
|
||||
- ImGui.GetFrameHeight()
|
||||
- scalarSize;
|
||||
|
||||
var ret = false;
|
||||
var ret = false;
|
||||
ref var row = ref table[rowIdx];
|
||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
||||
var dye = dyeTable?[rowIdx] ?? default;
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragScalar("Sheen"u8, default, (float)row.SheenRate * 100.0f, "%.0f%%"u8, HalfMinValue * 100.0f, HalfMaxValue * 100.0f, 1.0f,
|
||||
|
|
@ -420,13 +476,14 @@ public partial class MtrlTab
|
|||
CtDragScalar("##dyePreviewSheenRate"u8, "Dye Preview for Sheen"u8, (float?)dyePack?.SheenRate * 100.0f, "%.0f%%"u8);
|
||||
}
|
||||
|
||||
ImGui.SameLine(subcolWidth);
|
||||
ImGui.SameLine(subColWidth);
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragScalar("Sheen Tint"u8, default, (float)row.SheenTintRate * 100.0f, "%.0f%%"u8, HalfMinValue * 100.0f, HalfMaxValue * 100.0f, 1.0f,
|
||||
ret |= CtDragScalar("Sheen Tint"u8, default, (float)row.SheenTintRate * 100.0f, "%.0f%%"u8, HalfMinValue * 100.0f,
|
||||
HalfMaxValue * 100.0f, 1.0f,
|
||||
v => table[rowIdx].SheenTintRate = (Half)(v * 0.01f));
|
||||
if (dyeTable != null)
|
||||
{
|
||||
ImGui.SameLine(subcolWidth + dyeOffset);
|
||||
ImGui.SameLine(subColWidth + dyeOffset);
|
||||
ret |= CtApplyStainCheckbox("##dyeSheenTintRate"u8, "Apply Sheen Tint on Dye"u8, dye.SheenTintRate,
|
||||
b => dyeTable[rowIdx].SheenTintRate = b);
|
||||
ImUtf8.SameLineInner();
|
||||
|
|
@ -435,7 +492,8 @@ public partial class MtrlTab
|
|||
}
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragScalar("Sheen Roughness"u8, default, 100.0f / (float)row.SheenAperture, "%.0f%%"u8, 100.0f / HalfMaxValue, 100.0f / HalfEpsilon, 1.0f,
|
||||
ret |= CtDragScalar("Sheen Roughness"u8, default, 100.0f / (float)row.SheenAperture, "%.0f%%"u8, 100.0f / HalfMaxValue,
|
||||
100.0f / HalfEpsilon, 1.0f,
|
||||
v => table[rowIdx].SheenAperture = (Half)(100.0f / v));
|
||||
if (dyeTable != null)
|
||||
{
|
||||
|
|
@ -444,7 +502,8 @@ public partial class MtrlTab
|
|||
b => dyeTable[rowIdx].SheenAperture = b);
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
CtDragScalar("##dyePreviewSheenRoughness"u8, "Dye Preview for Sheen Roughness"u8, 100.0f / (float?)dyePack?.SheenAperture, "%.0f%%"u8);
|
||||
CtDragScalar("##dyePreviewSheenRoughness"u8, "Dye Preview for Sheen Roughness"u8, 100.0f / (float?)dyePack?.SheenAperture,
|
||||
"%.0f%%"u8);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -453,12 +512,16 @@ public partial class MtrlTab
|
|||
private static bool DrawFurther(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
||||
{
|
||||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
||||
var subcolWidth = CalculateSubcolumnWidth(2) + ImGui.GetStyle().ItemSpacing.X;
|
||||
var dyeOffset = subcolWidth - ImGui.GetStyle().ItemSpacing.X * 2.0f - ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight() - scalarSize;
|
||||
var subColWidth = CalculateSubColumnWidth(2) + ImGui.GetStyle().ItemSpacing.X;
|
||||
var dyeOffset = subColWidth
|
||||
- ImGui.GetStyle().ItemSpacing.X * 2.0f
|
||||
- ImGui.GetStyle().ItemInnerSpacing.X
|
||||
- ImGui.GetFrameHeight()
|
||||
- scalarSize;
|
||||
|
||||
var ret = false;
|
||||
var ret = false;
|
||||
ref var row = ref table[rowIdx];
|
||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
||||
var dye = dyeTable?[rowIdx] ?? default;
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragHalf("Field #11"u8, default, row.Scalar11, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||
|
|
@ -479,7 +542,7 @@ public partial class MtrlTab
|
|||
ret |= CtDragHalf("Field #3"u8, default, row.Scalar3, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||
v => table[rowIdx].Scalar3 = v);
|
||||
|
||||
ImGui.SameLine(subcolWidth);
|
||||
ImGui.SameLine(subColWidth);
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragHalf("Field #7"u8, default, row.Scalar7, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||
v => table[rowIdx].Scalar7 = v);
|
||||
|
|
@ -488,7 +551,7 @@ public partial class MtrlTab
|
|||
ret |= CtDragHalf("Field #15"u8, default, row.Scalar15, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||
v => table[rowIdx].Scalar15 = v);
|
||||
|
||||
ImGui.SameLine(subcolWidth);
|
||||
ImGui.SameLine(subColWidth);
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragHalf("Field #17"u8, default, row.Scalar17, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||
v => table[rowIdx].Scalar17 = v);
|
||||
|
|
@ -497,7 +560,7 @@ public partial class MtrlTab
|
|||
ret |= CtDragHalf("Field #20"u8, default, row.Scalar20, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||
v => table[rowIdx].Scalar20 = v);
|
||||
|
||||
ImGui.SameLine(subcolWidth);
|
||||
ImGui.SameLine(subColWidth);
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragHalf("Field #22"u8, default, row.Scalar22, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||
v => table[rowIdx].Scalar22 = v);
|
||||
|
|
@ -513,33 +576,32 @@ public partial class MtrlTab
|
|||
{
|
||||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
||||
var applyButtonWidth = ImUtf8.CalcTextSize("Apply Preview Dye"u8).X + ImGui.GetStyle().FramePadding.X * 2.0f;
|
||||
var subcolWidth = CalculateSubcolumnWidth(2, applyButtonWidth);
|
||||
|
||||
var ret = false;
|
||||
var subColWidth = CalculateSubColumnWidth(2, applyButtonWidth);
|
||||
|
||||
var ret = false;
|
||||
ref var dye = ref dyeTable[rowIdx];
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragScalar("Dye Channel"u8, default, dye.Channel + 1, "%d"u8, 1, StainService.ChannelCount, 0.1f,
|
||||
value => dyeTable[rowIdx].Channel = (byte)(Math.Clamp(value, 1, StainService.ChannelCount) - 1));
|
||||
ImGui.SameLine(subcolWidth);
|
||||
ImGui.SameLine(subColWidth);
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
if (_stainService.GudTemplateCombo.Draw("##dyeTemplate", dye.Template.ToString(), string.Empty,
|
||||
scalarSize + ImGui.GetStyle().ScrollbarSize / 2, ImGui.GetTextLineHeightWithSpacing(), ImGuiComboFlags.NoArrowButton))
|
||||
scalarSize + ImGui.GetStyle().ScrollbarSize / 2, ImGui.GetTextLineHeightWithSpacing(), ImGuiComboFlags.NoArrowButton))
|
||||
{
|
||||
dye.Template = _stainService.LegacyTemplateCombo.CurrentSelection;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
ImUtf8.SameLineInner();
|
||||
ImUtf8.Text("Dye Template"u8);
|
||||
ImGui.SameLine(ImGui.GetContentRegionAvail().X - applyButtonWidth + ImGui.GetStyle().ItemSpacing.X);
|
||||
using var dis = ImRaii.Disabled(!dyePack.HasValue);
|
||||
if (ImUtf8.Button("Apply Preview Dye"u8))
|
||||
{
|
||||
ret |= Mtrl.ApplyDyeToRow(_stainService.GudStmFile, [
|
||||
_stainService.StainCombo1.CurrentSelection.Key,
|
||||
_stainService.StainCombo2.CurrentSelection.Key,
|
||||
], rowIdx);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -554,9 +616,9 @@ public partial class MtrlTab
|
|||
ImGui.TextUnformatted(text);
|
||||
}
|
||||
|
||||
private static float CalculateSubcolumnWidth(int numSubcolumns, float reservedSpace = 0.0f)
|
||||
private static float CalculateSubColumnWidth(int numSubColumns, float reservedSpace = 0.0f)
|
||||
{
|
||||
var itemSpacing = ImGui.GetStyle().ItemSpacing.X;
|
||||
return (ImGui.GetContentRegionAvail().X - reservedSpace - itemSpacing * (numSubcolumns - 1)) / numSubcolumns + itemSpacing;
|
||||
return (ImGui.GetContentRegionAvail().X - reservedSpace - itemSpacing * (numSubColumns - 1)) / numSubColumns + itemSpacing;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ namespace Penumbra.UI.AdvancedWindow.Materials;
|
|||
|
||||
public partial class MtrlTab
|
||||
{
|
||||
private static readonly float HalfMinValue = (float)Half.MinValue;
|
||||
private static readonly float HalfMaxValue = (float)Half.MaxValue;
|
||||
private static readonly float HalfEpsilon = (float)Half.Epsilon;
|
||||
private static readonly float HalfMinValue = (float)Half.MinValue;
|
||||
private static readonly float HalfMaxValue = (float)Half.MaxValue;
|
||||
private static readonly float HalfEpsilon = (float)Half.Epsilon;
|
||||
|
||||
private static readonly FontAwesomeCheckbox ApplyStainCheckbox = new(FontAwesomeIcon.FillDrip);
|
||||
|
||||
|
|
@ -22,11 +22,11 @@ public partial class MtrlTab
|
|||
|
||||
private bool DrawColorTableSection(bool disabled)
|
||||
{
|
||||
if ((!ShpkLoading && !SamplerIds.Contains(ShpkFile.TableSamplerId)) || Mtrl.Table == null)
|
||||
if (!_shpkLoading && !SamplerIds.Contains(ShpkFile.TableSamplerId) || Mtrl.Table == null)
|
||||
return false;
|
||||
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
if (!ImGui.CollapsingHeader("Color Table", ImGuiTreeNodeFlags.DefaultOpen))
|
||||
if (!ImUtf8.CollapsingHeader("Color Table"u8, ImGuiTreeNodeFlags.DefaultOpen))
|
||||
return false;
|
||||
|
||||
ColorTableCopyAllClipboardButton();
|
||||
|
|
@ -35,7 +35,7 @@ public partial class MtrlTab
|
|||
if (!disabled)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGui.Dummy(ImGuiHelpers.ScaledVector2(20, 0));
|
||||
ImUtf8.IconDummy();
|
||||
ImGui.SameLine();
|
||||
ret |= ColorTableDyeableCheckbox();
|
||||
}
|
||||
|
|
@ -43,17 +43,18 @@ public partial class MtrlTab
|
|||
if (Mtrl.DyeTable != null)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGui.Dummy(ImGuiHelpers.ScaledVector2(20, 0));
|
||||
ImUtf8.IconDummy();
|
||||
ImGui.SameLine();
|
||||
ret |= DrawPreviewDye(disabled);
|
||||
}
|
||||
|
||||
ret |= Mtrl.Table switch
|
||||
{
|
||||
LegacyColorTable legacyTable => DrawLegacyColorTable(legacyTable, Mtrl.DyeTable as LegacyColorDyeTable, disabled),
|
||||
ColorTable table when Mtrl.ShaderPackage.Name is "characterlegacy.shpk" => DrawLegacyColorTable(table, Mtrl.DyeTable as ColorDyeTable, disabled),
|
||||
ColorTable table => DrawColorTable(table, Mtrl.DyeTable as ColorDyeTable, disabled),
|
||||
_ => false,
|
||||
LegacyColorTable legacyTable => DrawLegacyColorTable(legacyTable, Mtrl.DyeTable as LegacyColorDyeTable, disabled),
|
||||
ColorTable table when Mtrl.ShaderPackage.Name is "characterlegacy.shpk" => DrawLegacyColorTable(table,
|
||||
Mtrl.DyeTable as ColorDyeTable, disabled),
|
||||
ColorTable table => DrawColorTable(table, Mtrl.DyeTable as ColorDyeTable, disabled),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
return ret;
|
||||
|
|
@ -64,7 +65,7 @@ public partial class MtrlTab
|
|||
if (Mtrl.Table == null)
|
||||
return;
|
||||
|
||||
if (!ImGui.Button("Export All Rows to Clipboard", ImGuiHelpers.ScaledVector2(200, 0)))
|
||||
if (!ImUtf8.Button("Export All Rows to Clipboard"u8, ImGuiHelpers.ScaledVector2(200, 0)))
|
||||
return;
|
||||
|
||||
try
|
||||
|
|
@ -178,16 +179,18 @@ public partial class MtrlTab
|
|||
private bool ColorTableDyeableCheckbox()
|
||||
{
|
||||
var dyeable = Mtrl.DyeTable != null;
|
||||
var ret = ImGui.Checkbox("Dyeable", ref dyeable);
|
||||
var ret = ImUtf8.Checkbox("Dyeable"u8, ref dyeable);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
Mtrl.DyeTable = dyeable ? Mtrl.Table switch
|
||||
{
|
||||
ColorTable => new ColorDyeTable(),
|
||||
LegacyColorTable => new LegacyColorDyeTable(),
|
||||
_ => null,
|
||||
} : null;
|
||||
Mtrl.DyeTable = dyeable
|
||||
? Mtrl.Table switch
|
||||
{
|
||||
ColorTable => new ColorDyeTable(),
|
||||
LegacyColorTable => new LegacyColorDyeTable(),
|
||||
_ => null,
|
||||
}
|
||||
: null;
|
||||
UpdateColorTablePreview();
|
||||
}
|
||||
|
||||
|
|
@ -227,24 +230,27 @@ public partial class MtrlTab
|
|||
|
||||
private void ColorTableHighlightButton(int pairIdx, bool disabled)
|
||||
{
|
||||
ImUtf8.IconButton(FontAwesomeIcon.Crosshairs, "Highlight this pair of rows on your character, if possible.\n\nHighlight colors can be configured in Penumbra's settings."u8,
|
||||
ImGui.GetFrameHeight() * Vector2.One, disabled || ColorTablePreviewers.Count == 0);
|
||||
ImUtf8.IconButton(FontAwesomeIcon.Crosshairs,
|
||||
"Highlight this pair of rows on your character, if possible.\n\nHighlight colors can be configured in Penumbra's settings."u8,
|
||||
ImGui.GetFrameHeight() * Vector2.One, disabled || _colorTablePreviewers.Count == 0);
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
HighlightColorTablePair(pairIdx);
|
||||
else if (HighlightedColorTablePair == pairIdx)
|
||||
else if (_highlightedColorTablePair == pairIdx)
|
||||
CancelColorTableHighlight();
|
||||
}
|
||||
|
||||
private static void CtBlendRect(Vector2 rcMin, Vector2 rcMax, uint topColor, uint bottomColor)
|
||||
{
|
||||
var style = ImGui.GetStyle();
|
||||
var frameRounding = style.FrameRounding;
|
||||
var style = ImGui.GetStyle();
|
||||
var frameRounding = style.FrameRounding;
|
||||
var frameThickness = style.FrameBorderSize;
|
||||
var borderColor = ImGui.GetColorU32(ImGuiCol.Border);
|
||||
var drawList = ImGui.GetWindowDrawList();
|
||||
var borderColor = ImGui.GetColorU32(ImGuiCol.Border);
|
||||
var drawList = ImGui.GetWindowDrawList();
|
||||
if (topColor == bottomColor)
|
||||
{
|
||||
drawList.AddRectFilled(rcMin, rcMax, topColor, frameRounding, ImDrawFlags.RoundCornersDefault);
|
||||
}
|
||||
else
|
||||
{
|
||||
drawList.AddRectFilled(
|
||||
|
|
@ -258,10 +264,12 @@ public partial class MtrlTab
|
|||
rcMin with { Y = float.Lerp(rcMin.Y, rcMax.Y, 2.0f / 3) }, rcMax,
|
||||
bottomColor, frameRounding, ImDrawFlags.RoundCornersBottomLeft | ImDrawFlags.RoundCornersBottomRight);
|
||||
}
|
||||
|
||||
drawList.AddRect(rcMin, rcMax, borderColor, frameRounding, ImDrawFlags.RoundCornersDefault, frameThickness);
|
||||
}
|
||||
|
||||
private static bool CtColorPicker(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, HalfColor current, Action<HalfColor> setter, ReadOnlySpan<byte> letter = default)
|
||||
private static bool CtColorPicker(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, HalfColor current, Action<HalfColor> setter,
|
||||
ReadOnlySpan<byte> letter = default)
|
||||
{
|
||||
var ret = false;
|
||||
var inputSqrt = PseudoSqrtRgb((Vector3)current);
|
||||
|
|
@ -291,10 +299,13 @@ public partial class MtrlTab
|
|||
return ret;
|
||||
}
|
||||
|
||||
private static void CtColorPicker(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, HalfColor? current, ReadOnlySpan<byte> letter = default)
|
||||
private static void CtColorPicker(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, HalfColor? current,
|
||||
ReadOnlySpan<byte> letter = default)
|
||||
{
|
||||
if (current.HasValue)
|
||||
{
|
||||
CtColorPicker(label, description, current.Value, Nop, letter);
|
||||
}
|
||||
else
|
||||
{
|
||||
var tmp = Vector4.Zero;
|
||||
|
|
@ -308,8 +319,8 @@ public partial class MtrlTab
|
|||
|
||||
if (letter.Length > 0 && ImGui.IsItemVisible())
|
||||
{
|
||||
var textSize = ImUtf8.CalcTextSize(letter);
|
||||
var center = ImGui.GetItemRectMin() + (ImGui.GetItemRectSize() - textSize) / 2;
|
||||
var textSize = ImUtf8.CalcTextSize(letter);
|
||||
var center = ImGui.GetItemRectMin() + (ImGui.GetItemRectSize() - textSize) / 2;
|
||||
ImGui.GetWindowDrawList().AddText(letter, center, 0x80000000u);
|
||||
}
|
||||
|
||||
|
|
@ -319,7 +330,7 @@ public partial class MtrlTab
|
|||
|
||||
private static bool CtApplyStainCheckbox(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, bool current, Action<bool> setter)
|
||||
{
|
||||
var tmp = current;
|
||||
var tmp = current;
|
||||
var result = ApplyStainCheckbox.Draw(label, ref tmp);
|
||||
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, description);
|
||||
if (!result || tmp == current)
|
||||
|
|
@ -329,68 +340,79 @@ public partial class MtrlTab
|
|||
return true;
|
||||
}
|
||||
|
||||
private static bool CtDragHalf(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, Half value, ReadOnlySpan<byte> format, float min, float max, float speed, Action<Half> setter)
|
||||
private static bool CtDragHalf(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, Half value, ReadOnlySpan<byte> format, float min,
|
||||
float max, float speed, Action<Half> setter)
|
||||
{
|
||||
var tmp = (float)value;
|
||||
var tmp = (float)value;
|
||||
var result = ImUtf8.DragScalar(label, ref tmp, format, min, max, speed);
|
||||
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, description);
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
var newValue = (Half)tmp;
|
||||
if (newValue == value)
|
||||
return false;
|
||||
|
||||
setter(newValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool CtDragHalf(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, ref Half value, ReadOnlySpan<byte> format, float min, float max, float speed)
|
||||
private static bool CtDragHalf(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, ref Half value, ReadOnlySpan<byte> format,
|
||||
float min, float max, float speed)
|
||||
{
|
||||
var tmp = (float)value;
|
||||
var tmp = (float)value;
|
||||
var result = ImUtf8.DragScalar(label, ref tmp, format, min, max, speed);
|
||||
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, description);
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
var newValue = (Half)tmp;
|
||||
if (newValue == value)
|
||||
return false;
|
||||
|
||||
value = newValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void CtDragHalf(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, Half? value, ReadOnlySpan<byte> format)
|
||||
{
|
||||
using var _ = ImRaii.Disabled();
|
||||
var valueOrDefault = value ?? Half.Zero;
|
||||
var floatValue = (float)valueOrDefault;
|
||||
using var _ = ImRaii.Disabled();
|
||||
var valueOrDefault = value ?? Half.Zero;
|
||||
var floatValue = (float)valueOrDefault;
|
||||
CtDragHalf(label, description, valueOrDefault, value.HasValue ? format : "-"u8, floatValue, floatValue, 0.0f, Nop);
|
||||
}
|
||||
|
||||
private static bool CtDragScalar<T>(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, T value, ReadOnlySpan<byte> format, T min, T max, float speed, Action<T> setter) where T : unmanaged, INumber<T>
|
||||
private static bool CtDragScalar<T>(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, T value, ReadOnlySpan<byte> format, T min,
|
||||
T max, float speed, Action<T> setter) where T : unmanaged, INumber<T>
|
||||
{
|
||||
var tmp = value;
|
||||
var tmp = value;
|
||||
var result = ImUtf8.DragScalar(label, ref tmp, format, min, max, speed);
|
||||
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, description);
|
||||
if (!result || tmp == value)
|
||||
return false;
|
||||
|
||||
setter(tmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool CtDragScalar<T>(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, ref T value, ReadOnlySpan<byte> format, T min, T max, float speed) where T : unmanaged, INumber<T>
|
||||
private static bool CtDragScalar<T>(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, ref T value, ReadOnlySpan<byte> format, T min,
|
||||
T max, float speed) where T : unmanaged, INumber<T>
|
||||
{
|
||||
var tmp = value;
|
||||
var tmp = value;
|
||||
var result = ImUtf8.DragScalar(label, ref tmp, format, min, max, speed);
|
||||
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, description);
|
||||
if (!result || tmp == value)
|
||||
return false;
|
||||
|
||||
value = tmp;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void CtDragScalar<T>(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, T? value, ReadOnlySpan<byte> format) where T : unmanaged, INumber<T>
|
||||
private static void CtDragScalar<T>(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, T? value, ReadOnlySpan<byte> format)
|
||||
where T : unmanaged, INumber<T>
|
||||
{
|
||||
using var _ = ImRaii.Disabled();
|
||||
var valueOrDefault = value ?? T.Zero;
|
||||
using var _ = ImRaii.Disabled();
|
||||
var valueOrDefault = value ?? T.Zero;
|
||||
CtDragScalar(label, description, valueOrDefault, value.HasValue ? format : "-"u8, valueOrDefault, valueOrDefault, 0.0f, Nop);
|
||||
}
|
||||
|
||||
|
|
@ -398,14 +420,17 @@ public partial class MtrlTab
|
|||
{
|
||||
if (!_materialTemplatePickers.DrawTileIndexPicker(label, description, ref value, compact))
|
||||
return false;
|
||||
|
||||
setter(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool CtSphereMapIndexPicker(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, ushort value, bool compact, Action<ushort> setter)
|
||||
private bool CtSphereMapIndexPicker(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, ushort value, bool compact,
|
||||
Action<ushort> setter)
|
||||
{
|
||||
if (!_materialTemplatePickers.DrawSphereMapIndexPicker(label, description, ref value, compact))
|
||||
return false;
|
||||
|
||||
setter(value);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -430,33 +455,34 @@ public partial class MtrlTab
|
|||
ret |= CtDragHalf("##TileTransformVU"u8, "Tile Skew V"u8, ref tmp.VU, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f);
|
||||
if (!ret || tmp == value)
|
||||
return false;
|
||||
|
||||
setter(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
value.Decompose(out var scale, out var rotation, out var shear);
|
||||
rotation *= 180.0f / MathF.PI;
|
||||
shear *= 180.0f / MathF.PI;
|
||||
shear *= 180.0f / MathF.PI;
|
||||
ImGui.SetNextItemWidth(floatSize);
|
||||
var scaleXChanged = CtDragScalar("##TileScaleU"u8, "Tile Scale U"u8, ref scale.X, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f);
|
||||
var activated = ImGui.IsItemActivated();
|
||||
var deactivated = ImGui.IsItemDeactivated();
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetNextItemWidth(floatSize);
|
||||
var scaleYChanged = CtDragScalar("##TileScaleV"u8, "Tile Scale V"u8, ref scale.Y, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f);
|
||||
activated |= ImGui.IsItemActivated();
|
||||
deactivated |= ImGui.IsItemDeactivated();
|
||||
var scaleYChanged = CtDragScalar("##TileScaleV"u8, "Tile Scale V"u8, ref scale.Y, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f);
|
||||
activated |= ImGui.IsItemActivated();
|
||||
deactivated |= ImGui.IsItemDeactivated();
|
||||
if (!twoRowLayout)
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetNextItemWidth(floatSize);
|
||||
var rotationChanged = CtDragScalar("##TileRotation"u8, "Tile Rotation"u8, ref rotation, "%.0f°"u8, -180.0f, 180.0f, 1.0f);
|
||||
activated |= ImGui.IsItemActivated();
|
||||
deactivated |= ImGui.IsItemDeactivated();
|
||||
var rotationChanged = CtDragScalar("##TileRotation"u8, "Tile Rotation"u8, ref rotation, "%.0f°"u8, -180.0f, 180.0f, 1.0f);
|
||||
activated |= ImGui.IsItemActivated();
|
||||
deactivated |= ImGui.IsItemDeactivated();
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetNextItemWidth(floatSize);
|
||||
var shearChanged = CtDragScalar("##TileShear"u8, "Tile Shear"u8, ref shear, "%.0f°"u8, -90.0f, 90.0f, 1.0f);
|
||||
activated |= ImGui.IsItemActivated();
|
||||
deactivated |= ImGui.IsItemDeactivated();
|
||||
var shearChanged = CtDragScalar("##TileShear"u8, "Tile Shear"u8, ref shear, "%.0f°"u8, -90.0f, 90.0f, 1.0f);
|
||||
activated |= ImGui.IsItemActivated();
|
||||
deactivated |= ImGui.IsItemDeactivated();
|
||||
if (deactivated)
|
||||
_pinnedTileTransform = null;
|
||||
else if (activated)
|
||||
|
|
@ -464,6 +490,7 @@ public partial class MtrlTab
|
|||
ret = scaleXChanged | scaleYChanged | rotationChanged | shearChanged;
|
||||
if (!ret)
|
||||
return false;
|
||||
|
||||
if (_pinnedTileTransform.HasValue)
|
||||
{
|
||||
var (pinScale, pinRotation, pinShear) = _pinnedTileTransform.Value;
|
||||
|
|
@ -476,11 +503,14 @@ public partial class MtrlTab
|
|||
if (!shearChanged)
|
||||
shear = pinShear;
|
||||
}
|
||||
|
||||
var newValue = HalfMatrix2x2.Compose(scale, rotation * MathF.PI / 180.0f, shear * MathF.PI / 180.0f);
|
||||
if (newValue == value)
|
||||
return false;
|
||||
|
||||
setter(newValue);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ public partial class MtrlTab
|
|||
|
||||
Constants.Clear();
|
||||
string mpPrefix;
|
||||
if (AssociatedShpk == null)
|
||||
if (_associatedShpk == null)
|
||||
{
|
||||
mpPrefix = MaterialParamsConstantName.Value!;
|
||||
var fcGroup = FindOrAddGroup(Constants, "Further Constants");
|
||||
|
|
@ -51,12 +51,12 @@ public partial class MtrlTab
|
|||
}
|
||||
else
|
||||
{
|
||||
mpPrefix = AssociatedShpk.GetConstantById(MaterialParamsConstantId)?.Name ?? MaterialParamsConstantName.Value!;
|
||||
mpPrefix = _associatedShpk.GetConstantById(MaterialParamsConstantId)?.Name ?? MaterialParamsConstantName.Value!;
|
||||
var autoNameMaxLength = Math.Max(Names.LongestKnownNameLength, mpPrefix.Length + 8);
|
||||
foreach (var shpkConstant in AssociatedShpk.MaterialParams)
|
||||
foreach (var shpkConstant in _associatedShpk.MaterialParams)
|
||||
{
|
||||
var name = Names.KnownNames.TryResolve(shpkConstant.Id);
|
||||
var constant = Mtrl.GetOrAddConstant(shpkConstant.Id, AssociatedShpk, out var constantIndex);
|
||||
var constant = Mtrl.GetOrAddConstant(shpkConstant.Id, _associatedShpk, out var constantIndex);
|
||||
var values = Mtrl.GetConstantValue<byte>(constant);
|
||||
var handledElements = new IndexSet(values.Length, false);
|
||||
|
||||
|
|
@ -64,8 +64,8 @@ public partial class MtrlTab
|
|||
if (dkData != null)
|
||||
foreach (var dkConstant in dkData)
|
||||
{
|
||||
var offset = (int)dkConstant.EffectiveByteOffset;
|
||||
var length = values.Length - offset;
|
||||
var offset = (int)dkConstant.EffectiveByteOffset;
|
||||
var length = values.Length - offset;
|
||||
var constantSize = dkConstant.EffectiveByteSize;
|
||||
if (constantSize.HasValue)
|
||||
length = Math.Min(length, (int)constantSize.Value);
|
||||
|
|
@ -86,7 +86,6 @@ public partial class MtrlTab
|
|||
foreach (var (start, end) in handledElements.Ranges(complement: true))
|
||||
{
|
||||
if (start == 0 && end == values.Length && end - start <= 16)
|
||||
{
|
||||
if (name.Value != null)
|
||||
{
|
||||
fcGroup.Add((
|
||||
|
|
@ -94,7 +93,6 @@ public partial class MtrlTab
|
|||
constantIndex, 0..values.Length, string.Empty, true, DefaultConstantEditorFor(name)));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((shpkConstant.ByteOffset & 0x3) == 0 && (shpkConstant.ByteSize & 0x3) == 0)
|
||||
{
|
||||
|
|
@ -105,7 +103,8 @@ public partial class MtrlTab
|
|||
var rangeEnd = Math.Min(i + 16, end);
|
||||
if (rangeEnd > rangeStart)
|
||||
{
|
||||
var autoName = $"{mpPrefix}[{j,2:D}]{VectorSwizzle(((offset + rangeStart) & 0xF) >> 2, ((offset + rangeEnd - 1) & 0xF) >> 2)}";
|
||||
var autoName =
|
||||
$"{mpPrefix}[{j,2:D}]{VectorSwizzle(((offset + rangeStart) & 0xF) >> 2, ((offset + rangeEnd - 1) & 0xF) >> 2)}";
|
||||
fcGroup.Add((
|
||||
$"{autoName.PadRight(autoNameMaxLength)} (0x{shpkConstant.Id:X8})",
|
||||
constantIndex, rangeStart..rangeEnd, string.Empty, true, DefaultConstantEditorFor(name)));
|
||||
|
|
@ -116,7 +115,8 @@ public partial class MtrlTab
|
|||
{
|
||||
for (var i = start; i < end; i += 16)
|
||||
{
|
||||
fcGroup.Add(($"{"???".PadRight(autoNameMaxLength)} (0x{shpkConstant.Id:X8})", constantIndex, i..Math.Min(i + 16, end), string.Empty, true,
|
||||
fcGroup.Add(($"{"???".PadRight(autoNameMaxLength)} (0x{shpkConstant.Id:X8})", constantIndex,
|
||||
i..Math.Min(i + 16, end), string.Empty, true,
|
||||
DefaultConstantEditorFor(name)));
|
||||
}
|
||||
}
|
||||
|
|
@ -178,15 +178,16 @@ public partial class MtrlTab
|
|||
ret = true;
|
||||
SetMaterialParameter(constant.Id, slice.Start, buffer[slice]);
|
||||
}
|
||||
var shpkConstant = AssociatedShpk?.GetMaterialParamById(constant.Id);
|
||||
var defaultConstantValue = shpkConstant.HasValue ? AssociatedShpk!.GetMaterialParamDefault<byte>(shpkConstant.Value) : [];
|
||||
|
||||
var shpkConstant = _associatedShpk?.GetMaterialParamById(constant.Id);
|
||||
var defaultConstantValue = shpkConstant.HasValue ? _associatedShpk!.GetMaterialParamDefault<byte>(shpkConstant.Value) : [];
|
||||
var defaultValue = IsValid(slice, defaultConstantValue.Length) ? defaultConstantValue[slice] : [];
|
||||
var canReset = AssociatedShpk?.MaterialParamsDefaults != null
|
||||
var canReset = _associatedShpk?.MaterialParamsDefaults != null
|
||||
? defaultValue.Length > 0 && !defaultValue.SequenceEqual(buffer[slice])
|
||||
: buffer[slice].ContainsAnyExcept((byte)0);
|
||||
ImUtf8.SameLineInner();
|
||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Backspace.ToIconString(), ImGui.GetFrameHeight() * Vector2.One,
|
||||
"Reset this constant to its default value.\n\nHold Ctrl to unlock.", !ImGui.GetIO().KeyCtrl || !canReset, true))
|
||||
"Reset this constant to its default value.\n\nHold Ctrl to unlock.", !ImGui.GetIO().KeyCtrl || !canReset, true))
|
||||
{
|
||||
ret = true;
|
||||
if (defaultValue.Length > 0)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OtterGui.Text.Widget.Editors;
|
||||
using Penumbra.String.Classes;
|
||||
|
|
@ -29,8 +30,8 @@ public partial class MtrlTab
|
|||
}
|
||||
|
||||
private T? TryGetShpkDevkitData<T>(string category, uint? id, bool mayVary) where T : class
|
||||
=> 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
|
||||
{
|
||||
|
|
@ -47,7 +48,7 @@ public partial class MtrlTab
|
|||
{
|
||||
var selector = BuildSelector(data!["Vary"]!
|
||||
.Select(key => (uint)key)
|
||||
.Select(key => Mtrl.GetShaderKey(key)?.Value ?? AssociatedShpk!.GetMaterialKeyById(key)!.Value.DefaultValue));
|
||||
.Select(key => Mtrl.GetShaderKey(key)?.Value ?? _associatedShpk!.GetMaterialKeyById(key)!.Value.DefaultValue));
|
||||
var index = (int)data["Selectors"]![selector.ToString()]!;
|
||||
data = data["Items"]![index];
|
||||
}
|
||||
|
|
@ -62,12 +63,14 @@ public partial class MtrlTab
|
|||
}
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
private sealed class DevkitShaderKeyValue
|
||||
{
|
||||
public string Label = string.Empty;
|
||||
public string Description = string.Empty;
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
private sealed class DevkitShaderKey
|
||||
{
|
||||
public string Label = string.Empty;
|
||||
|
|
@ -75,6 +78,7 @@ public partial class MtrlTab
|
|||
public Dictionary<uint, DevkitShaderKeyValue> Values = [];
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
private sealed class DevkitSampler
|
||||
{
|
||||
public string Label = string.Empty;
|
||||
|
|
@ -84,14 +88,16 @@ public partial class MtrlTab
|
|||
|
||||
private enum DevkitConstantType
|
||||
{
|
||||
Hidden = -1,
|
||||
Float = 0,
|
||||
Hidden = -1,
|
||||
Float = 0,
|
||||
|
||||
/// <summary> Integer encoded as a float. </summary>
|
||||
Integer = 1,
|
||||
Color = 2,
|
||||
Enum = 3,
|
||||
Integer = 1,
|
||||
Color = 2,
|
||||
Enum = 3,
|
||||
|
||||
/// <summary> Native integer. </summary>
|
||||
Int32 = 4,
|
||||
Int32 = 4,
|
||||
Int32Enum = 5,
|
||||
Int8 = 6,
|
||||
Int8Enum = 7,
|
||||
|
|
@ -105,6 +111,7 @@ public partial class MtrlTab
|
|||
SphereMapIndex = 15,
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
private sealed class DevkitConstantValue
|
||||
{
|
||||
public string Label = string.Empty;
|
||||
|
|
@ -112,6 +119,7 @@ public partial class MtrlTab
|
|||
public double Value = 0;
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
private sealed class DevkitConstant
|
||||
{
|
||||
public uint Offset = 0;
|
||||
|
|
@ -147,7 +155,7 @@ public partial class MtrlTab
|
|||
=> ByteOffset ?? Offset * ValueSize;
|
||||
|
||||
public uint? EffectiveByteSize
|
||||
=> ByteSize ?? (Length * ValueSize);
|
||||
=> ByteSize ?? Length * ValueSize;
|
||||
|
||||
public unsafe uint ValueSize
|
||||
=> Type switch
|
||||
|
|
@ -198,19 +206,23 @@ public partial class MtrlTab
|
|||
private IEditor<T> CreateIntegerEditor<T>()
|
||||
where T : unmanaged, INumber<T>
|
||||
=> ((Drag || Slider) && !Hex
|
||||
? (Drag
|
||||
? (IEditor<T>)DragEditor<T>.CreateInteger(ToInteger<T>(Minimum), ToInteger<T>(Maximum), Speed ?? 0.25f, RelativeSpeed, Unit, 0)
|
||||
: SliderEditor<T>.CreateInteger(ToInteger<T>(Minimum) ?? default, ToInteger<T>(Maximum) ?? default, Unit, 0))
|
||||
: InputEditor<T>.CreateInteger(ToInteger<T>(Minimum), ToInteger<T>(Maximum), ToInteger<T>(Step), ToInteger<T>(StepFast), Hex, Unit, 0))
|
||||
? Drag
|
||||
? (IEditor<T>)DragEditor<T>.CreateInteger(ToInteger<T>(Minimum), ToInteger<T>(Maximum), Speed ?? 0.25f, RelativeSpeed,
|
||||
Unit, 0)
|
||||
: SliderEditor<T>.CreateInteger(ToInteger<T>(Minimum) ?? default, ToInteger<T>(Maximum) ?? default, Unit, 0)
|
||||
: InputEditor<T>.CreateInteger(ToInteger<T>(Minimum), ToInteger<T>(Maximum), ToInteger<T>(Step), ToInteger<T>(StepFast),
|
||||
Hex, Unit, 0))
|
||||
.WithFactorAndBias(ToInteger<T>(Factor), ToInteger<T>(Bias));
|
||||
|
||||
private IEditor<T> CreateFloatEditor<T>()
|
||||
where T : unmanaged, INumber<T>, IPowerFunctions<T>
|
||||
=> ((Drag || Slider)
|
||||
? (Drag
|
||||
? (IEditor<T>)DragEditor<T>.CreateFloat(ToFloat<T>(Minimum), ToFloat<T>(Maximum), Speed ?? 0.1f, RelativeSpeed, Precision, Unit, 0)
|
||||
: SliderEditor<T>.CreateFloat(ToFloat<T>(Minimum) ?? default, ToFloat<T>(Maximum) ?? default, Precision, Unit, 0))
|
||||
: InputEditor<T>.CreateFloat(ToFloat<T>(Minimum), ToFloat<T>(Maximum), T.CreateSaturating(Step), T.CreateSaturating(StepFast), Precision, Unit, 0))
|
||||
=> (Drag || Slider
|
||||
? Drag
|
||||
? (IEditor<T>)DragEditor<T>.CreateFloat(ToFloat<T>(Minimum), ToFloat<T>(Maximum), Speed ?? 0.1f, RelativeSpeed,
|
||||
Precision, Unit, 0)
|
||||
: SliderEditor<T>.CreateFloat(ToFloat<T>(Minimum) ?? default, ToFloat<T>(Maximum) ?? default, Precision, Unit, 0)
|
||||
: InputEditor<T>.CreateFloat(ToFloat<T>(Minimum), ToFloat<T>(Maximum), T.CreateSaturating(Step),
|
||||
T.CreateSaturating(StepFast), Precision, Unit, 0))
|
||||
.WithExponent(T.CreateSaturating(Exponent))
|
||||
.WithFactorAndBias(T.CreateSaturating(Factor), T.CreateSaturating(Bias));
|
||||
|
||||
|
|
|
|||
|
|
@ -110,9 +110,9 @@ public partial class MtrlTab
|
|||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
using (ImRaii.PushFont(UiBuilder.MonoFont))
|
||||
{
|
||||
ImUtf8.Text($"{(rowIdx >> 1) + 1,2:D}{"AB"[rowIdx & 1]}");
|
||||
using (ImRaii.PushFont(UiBuilder.MonoFont))
|
||||
{
|
||||
ImUtf8.Text($"{(rowIdx >> 1) + 1,2:D}{"AB"[rowIdx & 1]}");
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
|
|
|
|||
|
|
@ -12,20 +12,20 @@ namespace Penumbra.UI.AdvancedWindow.Materials;
|
|||
|
||||
public partial class MtrlTab
|
||||
{
|
||||
public readonly List<LiveMaterialPreviewer> MaterialPreviewers = new(4);
|
||||
public readonly List<LiveColorTablePreviewer> ColorTablePreviewers = new(4);
|
||||
public int HighlightedColorTablePair = -1;
|
||||
public readonly Stopwatch HighlightTime = new();
|
||||
private readonly List<LiveMaterialPreviewer> _materialPreviewers = new(4);
|
||||
private readonly List<LiveColorTablePreviewer> _colorTablePreviewers = new(4);
|
||||
private int _highlightedColorTablePair = -1;
|
||||
private readonly Stopwatch _highlightTime = new();
|
||||
|
||||
private void DrawMaterialLivePreviewRebind(bool disabled)
|
||||
{
|
||||
if (disabled)
|
||||
return;
|
||||
|
||||
if (ImGui.Button("Reload live preview"))
|
||||
if (ImUtf8.Button("Reload live preview"u8))
|
||||
BindToMaterialInstances();
|
||||
|
||||
if (MaterialPreviewers.Count != 0 || ColorTablePreviewers.Count != 0)
|
||||
if (_materialPreviewers.Count != 0 || _colorTablePreviewers.Count != 0)
|
||||
return;
|
||||
|
||||
ImGui.SameLine();
|
||||
|
|
@ -34,7 +34,7 @@ public partial class MtrlTab
|
|||
"The current material has not been found on your character. Please check the Import from Screen tab for more information."u8);
|
||||
}
|
||||
|
||||
public unsafe void BindToMaterialInstances()
|
||||
private unsafe void BindToMaterialInstances()
|
||||
{
|
||||
UnbindFromMaterialInstances();
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ public partial class MtrlTab
|
|||
|
||||
try
|
||||
{
|
||||
MaterialPreviewers.Add(new LiveMaterialPreviewer(_objects, materialInfo));
|
||||
_materialPreviewers.Add(new LiveMaterialPreviewer(_objects, materialInfo));
|
||||
foundMaterials.Add((nint)material);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
|
|
@ -68,7 +68,7 @@ public partial class MtrlTab
|
|||
{
|
||||
try
|
||||
{
|
||||
ColorTablePreviewers.Add(new LiveColorTablePreviewer(_objects, _framework, materialInfo));
|
||||
_colorTablePreviewers.Add(new LiveColorTablePreviewer(_objects, _framework, materialInfo));
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
|
|
@ -81,53 +81,53 @@ public partial class MtrlTab
|
|||
|
||||
private void UnbindFromMaterialInstances()
|
||||
{
|
||||
foreach (var previewer in MaterialPreviewers)
|
||||
foreach (var previewer in _materialPreviewers)
|
||||
previewer.Dispose();
|
||||
MaterialPreviewers.Clear();
|
||||
_materialPreviewers.Clear();
|
||||
|
||||
foreach (var previewer in ColorTablePreviewers)
|
||||
foreach (var previewer in _colorTablePreviewers)
|
||||
previewer.Dispose();
|
||||
ColorTablePreviewers.Clear();
|
||||
_colorTablePreviewers.Clear();
|
||||
}
|
||||
|
||||
private unsafe void UnbindFromDrawObjectMaterialInstances(CharacterBase* characterBase)
|
||||
{
|
||||
for (var i = MaterialPreviewers.Count; i-- > 0;)
|
||||
for (var i = _materialPreviewers.Count; i-- > 0;)
|
||||
{
|
||||
var previewer = MaterialPreviewers[i];
|
||||
var previewer = _materialPreviewers[i];
|
||||
if (previewer.DrawObject != characterBase)
|
||||
continue;
|
||||
|
||||
previewer.Dispose();
|
||||
MaterialPreviewers.RemoveAt(i);
|
||||
_materialPreviewers.RemoveAt(i);
|
||||
}
|
||||
|
||||
for (var i = ColorTablePreviewers.Count; i-- > 0;)
|
||||
for (var i = _colorTablePreviewers.Count; i-- > 0;)
|
||||
{
|
||||
var previewer = ColorTablePreviewers[i];
|
||||
var previewer = _colorTablePreviewers[i];
|
||||
if (previewer.DrawObject != characterBase)
|
||||
continue;
|
||||
|
||||
previewer.Dispose();
|
||||
ColorTablePreviewers.RemoveAt(i);
|
||||
_colorTablePreviewers.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetShaderPackageFlags(uint shPkFlags)
|
||||
private void SetShaderPackageFlags(uint shPkFlags)
|
||||
{
|
||||
foreach (var previewer in MaterialPreviewers)
|
||||
foreach (var previewer in _materialPreviewers)
|
||||
previewer.SetShaderPackageFlags(shPkFlags);
|
||||
}
|
||||
|
||||
public void SetMaterialParameter(uint parameterCrc, Index offset, Span<byte> value)
|
||||
private void SetMaterialParameter(uint parameterCrc, Index offset, Span<byte> value)
|
||||
{
|
||||
foreach (var previewer in MaterialPreviewers)
|
||||
foreach (var previewer in _materialPreviewers)
|
||||
previewer.SetMaterialParameter(parameterCrc, offset, value);
|
||||
}
|
||||
|
||||
public void SetSamplerFlags(uint samplerCrc, uint samplerFlags)
|
||||
private void SetSamplerFlags(uint samplerCrc, uint samplerFlags)
|
||||
{
|
||||
foreach (var previewer in MaterialPreviewers)
|
||||
foreach (var previewer in _materialPreviewers)
|
||||
previewer.SetSamplerFlags(samplerCrc, samplerFlags);
|
||||
}
|
||||
|
||||
|
|
@ -145,14 +145,14 @@ public partial class MtrlTab
|
|||
SetSamplerFlags(sampler.SamplerId, sampler.Flags);
|
||||
}
|
||||
|
||||
public void HighlightColorTablePair(int pairIdx)
|
||||
private void HighlightColorTablePair(int pairIdx)
|
||||
{
|
||||
var oldPairIdx = HighlightedColorTablePair;
|
||||
var oldPairIdx = _highlightedColorTablePair;
|
||||
|
||||
if (HighlightedColorTablePair != pairIdx)
|
||||
if (_highlightedColorTablePair != pairIdx)
|
||||
{
|
||||
HighlightedColorTablePair = pairIdx;
|
||||
HighlightTime.Restart();
|
||||
_highlightedColorTablePair = pairIdx;
|
||||
_highlightTime.Restart();
|
||||
}
|
||||
|
||||
if (oldPairIdx >= 0)
|
||||
|
|
@ -160,19 +160,6 @@ public partial class MtrlTab
|
|||
UpdateColorTableRowPreview(oldPairIdx << 1);
|
||||
UpdateColorTableRowPreview((oldPairIdx << 1) | 1);
|
||||
}
|
||||
if (pairIdx >= 0)
|
||||
{
|
||||
UpdateColorTableRowPreview(pairIdx << 1);
|
||||
UpdateColorTableRowPreview((pairIdx << 1) | 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelColorTableHighlight()
|
||||
{
|
||||
var pairIdx = HighlightedColorTablePair;
|
||||
|
||||
HighlightedColorTablePair = -1;
|
||||
HighlightTime.Reset();
|
||||
|
||||
if (pairIdx >= 0)
|
||||
{
|
||||
|
|
@ -181,9 +168,23 @@ public partial class MtrlTab
|
|||
}
|
||||
}
|
||||
|
||||
public void UpdateColorTableRowPreview(int rowIdx)
|
||||
private void CancelColorTableHighlight()
|
||||
{
|
||||
if (ColorTablePreviewers.Count == 0)
|
||||
var pairIdx = _highlightedColorTablePair;
|
||||
|
||||
_highlightedColorTablePair = -1;
|
||||
_highlightTime.Reset();
|
||||
|
||||
if (pairIdx >= 0)
|
||||
{
|
||||
UpdateColorTableRowPreview(pairIdx << 1);
|
||||
UpdateColorTableRowPreview((pairIdx << 1) | 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateColorTableRowPreview(int rowIdx)
|
||||
{
|
||||
if (_colorTablePreviewers.Count == 0)
|
||||
return;
|
||||
|
||||
if (Mtrl.Table == null)
|
||||
|
|
@ -192,7 +193,7 @@ public partial class MtrlTab
|
|||
var row = Mtrl.Table switch
|
||||
{
|
||||
LegacyColorTable legacyTable => new ColorTableRow(legacyTable[rowIdx]),
|
||||
ColorTable table => table[rowIdx],
|
||||
ColorTable table => table[rowIdx],
|
||||
_ => throw new InvalidOperationException($"Unsupported color table type {Mtrl.Table.GetType()}"),
|
||||
};
|
||||
if (Mtrl.DyeTable != null)
|
||||
|
|
@ -200,8 +201,8 @@ public partial class MtrlTab
|
|||
var dyeRow = Mtrl.DyeTable switch
|
||||
{
|
||||
LegacyColorDyeTable legacyDyeTable => new ColorDyeTableRow(legacyDyeTable[rowIdx]),
|
||||
ColorDyeTable dyeTable => dyeTable[rowIdx],
|
||||
_ => throw new InvalidOperationException($"Unsupported color dye table type {Mtrl.DyeTable.GetType()}"),
|
||||
ColorDyeTable dyeTable => dyeTable[rowIdx],
|
||||
_ => throw new InvalidOperationException($"Unsupported color dye table type {Mtrl.DyeTable.GetType()}"),
|
||||
};
|
||||
if (dyeRow.Channel < StainService.ChannelCount)
|
||||
{
|
||||
|
|
@ -213,21 +214,21 @@ public partial class MtrlTab
|
|||
}
|
||||
}
|
||||
|
||||
if (HighlightedColorTablePair << 1 == rowIdx)
|
||||
ApplyHighlight(ref row, ColorId.InGameHighlight, (float)HighlightTime.Elapsed.TotalSeconds);
|
||||
else if (((HighlightedColorTablePair << 1) | 1) == rowIdx)
|
||||
ApplyHighlight(ref row, ColorId.InGameHighlight2, (float)HighlightTime.Elapsed.TotalSeconds);
|
||||
if (_highlightedColorTablePair << 1 == rowIdx)
|
||||
ApplyHighlight(ref row, ColorId.InGameHighlight, (float)_highlightTime.Elapsed.TotalSeconds);
|
||||
else if (((_highlightedColorTablePair << 1) | 1) == rowIdx)
|
||||
ApplyHighlight(ref row, ColorId.InGameHighlight2, (float)_highlightTime.Elapsed.TotalSeconds);
|
||||
|
||||
foreach (var previewer in ColorTablePreviewers)
|
||||
foreach (var previewer in _colorTablePreviewers)
|
||||
{
|
||||
row[..].CopyTo(previewer.GetColorRow(rowIdx));
|
||||
previewer.ScheduleUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateColorTablePreview()
|
||||
private void UpdateColorTablePreview()
|
||||
{
|
||||
if (ColorTablePreviewers.Count == 0)
|
||||
if (_colorTablePreviewers.Count == 0)
|
||||
return;
|
||||
|
||||
if (Mtrl.Table == null)
|
||||
|
|
@ -237,7 +238,8 @@ public partial class MtrlTab
|
|||
var dyeRows = Mtrl.DyeTable != null ? ColorDyeTable.CastOrConvert(Mtrl.DyeTable) : null;
|
||||
if (dyeRows != null)
|
||||
{
|
||||
ReadOnlySpan<StainId> stainIds = [
|
||||
ReadOnlySpan<StainId> stainIds =
|
||||
[
|
||||
_stainService.StainCombo1.CurrentSelection.Key,
|
||||
_stainService.StainCombo2.CurrentSelection.Key,
|
||||
];
|
||||
|
|
@ -245,13 +247,14 @@ public partial class MtrlTab
|
|||
rows.ApplyDye(_stainService.GudStmFile, stainIds, dyeRows);
|
||||
}
|
||||
|
||||
if (HighlightedColorTablePair >= 0)
|
||||
if (_highlightedColorTablePair >= 0)
|
||||
{
|
||||
ApplyHighlight(ref rows[HighlightedColorTablePair << 1], ColorId.InGameHighlight, (float)HighlightTime.Elapsed.TotalSeconds);
|
||||
ApplyHighlight(ref rows[(HighlightedColorTablePair << 1) | 1], ColorId.InGameHighlight2, (float)HighlightTime.Elapsed.TotalSeconds);
|
||||
ApplyHighlight(ref rows[_highlightedColorTablePair << 1], ColorId.InGameHighlight, (float)_highlightTime.Elapsed.TotalSeconds);
|
||||
ApplyHighlight(ref rows[(_highlightedColorTablePair << 1) | 1], ColorId.InGameHighlight2,
|
||||
(float)_highlightTime.Elapsed.TotalSeconds);
|
||||
}
|
||||
|
||||
foreach (var previewer in ColorTablePreviewers)
|
||||
foreach (var previewer in _colorTablePreviewers)
|
||||
{
|
||||
rows.AsHalves().CopyTo(previewer.ColorTable);
|
||||
previewer.ScheduleUpdate();
|
||||
|
|
@ -260,11 +263,11 @@ public partial class MtrlTab
|
|||
|
||||
private static void ApplyHighlight(ref ColorTableRow row, ColorId colorId, float time)
|
||||
{
|
||||
var level = (MathF.Sin(time * 2.0f * MathF.PI) + 2.0f) / 3.0f / 255.0f;
|
||||
var baseColor = colorId.Value();
|
||||
var level = (MathF.Sin(time * 2.0f * MathF.PI) + 2.0f) / 3.0f / 255.0f;
|
||||
var baseColor = colorId.Value();
|
||||
var color = level * new Vector3(baseColor & 0xFF, (baseColor >> 8) & 0xFF, (baseColor >> 16) & 0xFF);
|
||||
var halfColor = (HalfColor)(color * color);
|
||||
|
||||
|
||||
row.DiffuseColor = halfColor;
|
||||
row.SpecularColor = halfColor;
|
||||
row.EmissiveColor = halfColor;
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ public partial class MtrlTab
|
|||
// Apricot shader packages are unlisted because
|
||||
// 1. they cause severe performance/memory issues when calculating the effective shader set
|
||||
// 2. they probably aren't intended for use with materials anyway
|
||||
internal static readonly IReadOnlyList<string> StandardShaderPackages = new[]
|
||||
{
|
||||
private static readonly IReadOnlyList<string> StandardShaderPackages =
|
||||
[
|
||||
"3dui.shpk",
|
||||
// "apricot_decal_dummy.shpk",
|
||||
// "apricot_decal_ring.shpk",
|
||||
|
|
@ -80,35 +80,35 @@ public partial class MtrlTab
|
|||
"verticalfog.shpk",
|
||||
"water.shpk",
|
||||
"weather.shpk",
|
||||
};
|
||||
];
|
||||
|
||||
private static readonly byte[] UnknownShadersString = Encoding.UTF8.GetBytes("Vertex Shaders: ???\nPixel Shaders: ???");
|
||||
private static readonly byte[] UnknownShadersString = "Vertex Shaders: ???\nPixel Shaders: ???"u8.ToArray();
|
||||
|
||||
private string[]? _shpkNames;
|
||||
|
||||
public string ShaderHeader = "Shader###Shader";
|
||||
public FullPath LoadedShpkPath = FullPath.Empty;
|
||||
public string LoadedShpkPathName = string.Empty;
|
||||
public string LoadedShpkDevkitPathName = string.Empty;
|
||||
public string ShaderComment = string.Empty;
|
||||
public ShpkFile? AssociatedShpk;
|
||||
public bool ShpkLoading;
|
||||
public JObject? AssociatedShpkDevkit;
|
||||
private string _shaderHeader = "Shader###Shader";
|
||||
private FullPath _loadedShpkPath = FullPath.Empty;
|
||||
private string _loadedShpkPathName = string.Empty;
|
||||
private string _loadedShpkDevkitPathName = string.Empty;
|
||||
private string _shaderComment = string.Empty;
|
||||
private ShpkFile? _associatedShpk;
|
||||
private bool _shpkLoading;
|
||||
private JObject? _associatedShpkDevkit;
|
||||
|
||||
public readonly string LoadedBaseDevkitPathName;
|
||||
public readonly JObject? AssociatedBaseDevkit;
|
||||
private readonly string _loadedBaseDevkitPathName;
|
||||
private readonly JObject? _associatedBaseDevkit;
|
||||
|
||||
// Shader Key State
|
||||
public readonly
|
||||
private readonly
|
||||
List<(string Label, int Index, string Description, bool MonoFont, IReadOnlyList<(string Label, uint Value, string Description)>
|
||||
Values)> ShaderKeys = new(16);
|
||||
Values)> _shaderKeys = new(16);
|
||||
|
||||
public readonly HashSet<int> VertexShaders = new(16);
|
||||
public readonly HashSet<int> PixelShaders = new(16);
|
||||
public bool ShadersKnown;
|
||||
public ReadOnlyMemory<byte> ShadersString = UnknownShadersString;
|
||||
private readonly HashSet<int> _vertexShaders = new(16);
|
||||
private readonly HashSet<int> _pixelShaders = new(16);
|
||||
private bool _shadersKnown;
|
||||
private ReadOnlyMemory<byte> _shadersString = UnknownShadersString;
|
||||
|
||||
public string[] GetShpkNames()
|
||||
private string[] GetShpkNames()
|
||||
{
|
||||
if (null != _shpkNames)
|
||||
return _shpkNames;
|
||||
|
|
@ -122,7 +122,7 @@ public partial class MtrlTab
|
|||
return _shpkNames;
|
||||
}
|
||||
|
||||
public FullPath FindAssociatedShpk(out string defaultPath, out Utf8GamePath defaultGamePath)
|
||||
private FullPath FindAssociatedShpk(out string defaultPath, out Utf8GamePath defaultGamePath)
|
||||
{
|
||||
defaultPath = GamePaths.Shader.ShpkPath(Mtrl.ShaderPackage.Name);
|
||||
if (!Utf8GamePath.FromString(defaultPath, out defaultGamePath))
|
||||
|
|
@ -131,45 +131,45 @@ public partial class MtrlTab
|
|||
return _edit.FindBestMatch(defaultGamePath);
|
||||
}
|
||||
|
||||
public void LoadShpk(FullPath path)
|
||||
private void LoadShpk(FullPath path)
|
||||
=> Task.Run(() => DoLoadShpk(path));
|
||||
|
||||
private async Task DoLoadShpk(FullPath path)
|
||||
{
|
||||
ShadersKnown = false;
|
||||
ShaderHeader = $"Shader ({Mtrl.ShaderPackage.Name})###Shader";
|
||||
ShpkLoading = true;
|
||||
_shadersKnown = false;
|
||||
_shaderHeader = $"Shader ({Mtrl.ShaderPackage.Name})###Shader";
|
||||
_shpkLoading = true;
|
||||
|
||||
try
|
||||
{
|
||||
var data = path.IsRooted
|
||||
? await File.ReadAllBytesAsync(path.FullName)
|
||||
: _gameData.GetFile(path.InternalName.ToString())?.Data;
|
||||
LoadedShpkPath = path;
|
||||
AssociatedShpk = data?.Length > 0 ? new ShpkFile(data) : throw new Exception("Failure to load file data.");
|
||||
LoadedShpkPathName = path.ToPath();
|
||||
_loadedShpkPath = path;
|
||||
_associatedShpk = data?.Length > 0 ? new ShpkFile(data) : throw new Exception("Failure to load file data.");
|
||||
_loadedShpkPathName = path.ToPath();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LoadedShpkPath = FullPath.Empty;
|
||||
LoadedShpkPathName = string.Empty;
|
||||
AssociatedShpk = null;
|
||||
Penumbra.Messager.NotificationMessage(e, $"Could not load {LoadedShpkPath.ToPath()}.", NotificationType.Error, false);
|
||||
_loadedShpkPath = FullPath.Empty;
|
||||
_loadedShpkPathName = string.Empty;
|
||||
_associatedShpk = null;
|
||||
Penumbra.Messager.NotificationMessage(e, $"Could not load {_loadedShpkPath.ToPath()}.", NotificationType.Error, false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ShpkLoading = false;
|
||||
_shpkLoading = false;
|
||||
}
|
||||
|
||||
if (LoadedShpkPath.InternalName.IsEmpty)
|
||||
if (_loadedShpkPath.InternalName.IsEmpty)
|
||||
{
|
||||
AssociatedShpkDevkit = null;
|
||||
LoadedShpkDevkitPathName = string.Empty;
|
||||
_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();
|
||||
|
|
@ -178,9 +178,9 @@ public partial class MtrlTab
|
|||
|
||||
private void UpdateShaderKeys()
|
||||
{
|
||||
ShaderKeys.Clear();
|
||||
if (AssociatedShpk != null)
|
||||
foreach (var key in AssociatedShpk.MaterialKeys)
|
||||
_shaderKeys.Clear();
|
||||
if (_associatedShpk != null)
|
||||
foreach (var key in _associatedShpk.MaterialKeys)
|
||||
{
|
||||
var keyName = Names.KnownNames.TryResolve(key.Id);
|
||||
var dkData = TryGetShpkDevkitData<DevkitShaderKey>("ShaderKeys", key.Id, false);
|
||||
|
|
@ -210,7 +210,7 @@ public partial class MtrlTab
|
|||
|
||||
return string.Compare(x.Label, y.Label, StringComparison.Ordinal);
|
||||
});
|
||||
ShaderKeys.Add((hasDkLabel ? dkData!.Label : keyName.ToString(), mtrlKeyIndex, dkData?.Description ?? string.Empty,
|
||||
_shaderKeys.Add((hasDkLabel ? dkData!.Label : keyName.ToString(), mtrlKeyIndex, dkData?.Description ?? string.Empty,
|
||||
!hasDkLabel, values));
|
||||
}
|
||||
else
|
||||
|
|
@ -218,7 +218,7 @@ public partial class MtrlTab
|
|||
{
|
||||
var keyName = Names.KnownNames.TryResolve(key.Category);
|
||||
var valueName = keyName.WithKnownSuffixes().TryResolve(Names.KnownNames, key.Value);
|
||||
ShaderKeys.Add((keyName.ToString(), index, string.Empty, true, [(valueName.ToString(), key.Value, string.Empty)]));
|
||||
_shaderKeys.Add((keyName.ToString(), index, string.Empty, true, [(valueName.ToString(), key.Value, string.Empty)]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -232,27 +232,28 @@ public partial class MtrlTab
|
|||
passSet = [];
|
||||
byPassSets.Add(passId, passSet);
|
||||
}
|
||||
|
||||
passSet.Add(shaderIndex);
|
||||
}
|
||||
|
||||
VertexShaders.Clear();
|
||||
PixelShaders.Clear();
|
||||
_vertexShaders.Clear();
|
||||
_pixelShaders.Clear();
|
||||
|
||||
var vertexShadersByPass = new Dictionary<uint, HashSet<int>>();
|
||||
var pixelShadersByPass = new Dictionary<uint, HashSet<int>>();
|
||||
|
||||
if (AssociatedShpk == null || !AssociatedShpk.IsExhaustiveNodeAnalysisFeasible())
|
||||
if (_associatedShpk == null || !_associatedShpk.IsExhaustiveNodeAnalysisFeasible())
|
||||
{
|
||||
ShadersKnown = false;
|
||||
_shadersKnown = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShadersKnown = true;
|
||||
var systemKeySelectors = AllSelectors(AssociatedShpk.SystemKeys).ToArray();
|
||||
var sceneKeySelectors = AllSelectors(AssociatedShpk.SceneKeys).ToArray();
|
||||
var subViewKeySelectors = AllSelectors(AssociatedShpk.SubViewKeys).ToArray();
|
||||
_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));
|
||||
BuildSelector(_associatedShpk.MaterialKeys.Select(key => Mtrl.GetOrAddShaderKey(key.Id, key.DefaultValue).Value));
|
||||
|
||||
foreach (var systemKeySelector in systemKeySelectors)
|
||||
{
|
||||
|
|
@ -261,38 +262,39 @@ public partial class MtrlTab
|
|||
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)
|
||||
{
|
||||
AddShader(VertexShaders, vertexShadersByPass, pass.Id, (int)pass.VertexShader);
|
||||
AddShader(PixelShaders, pixelShadersByPass, pass.Id, (int)pass.PixelShader);
|
||||
AddShader(_vertexShaders, vertexShadersByPass, pass.Id, (int)pass.VertexShader);
|
||||
AddShader(_pixelShaders, pixelShadersByPass, pass.Id, (int)pass.PixelShader);
|
||||
}
|
||||
else
|
||||
ShadersKnown = false;
|
||||
_shadersKnown = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ShadersKnown)
|
||||
if (_shadersKnown)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
foreach (var (passId, passVS) in vertexShadersByPass)
|
||||
foreach (var (passId, passVertexShader) in vertexShadersByPass)
|
||||
{
|
||||
if (builder.Length > 0)
|
||||
builder.Append("\n\n");
|
||||
|
||||
var passName = Names.KnownNames.TryResolve(passId);
|
||||
var shaders = passVS.OrderBy(i => i).Select(i => $"#{i}");
|
||||
var shaders = passVertexShader.OrderBy(i => i).Select(i => $"#{i}");
|
||||
builder.Append($"Vertex Shaders ({passName}): {string.Join(", ", shaders)}");
|
||||
if (pixelShadersByPass.TryGetValue(passId, out var passPS))
|
||||
if (pixelShadersByPass.TryGetValue(passId, out var passPixelShader))
|
||||
{
|
||||
shaders = passPS.OrderBy(i => i).Select(i => $"#{i}");
|
||||
shaders = passPixelShader.OrderBy(i => i).Select(i => $"#{i}");
|
||||
builder.Append($"\nPixel Shaders ({passName}): {string.Join(", ", shaders)}");
|
||||
}
|
||||
}
|
||||
foreach (var (passId, passPS) in pixelShadersByPass)
|
||||
|
||||
foreach (var (passId, passPixelShader) in pixelShadersByPass)
|
||||
{
|
||||
if (vertexShadersByPass.ContainsKey(passId))
|
||||
continue;
|
||||
|
|
@ -301,22 +303,24 @@ public partial class MtrlTab
|
|||
builder.Append("\n\n");
|
||||
|
||||
var passName = Names.KnownNames.TryResolve(passId);
|
||||
var shaders = passPS.OrderBy(i => i).Select(i => $"#{i}");
|
||||
var shaders = passPixelShader.OrderBy(i => i).Select(i => $"#{i}");
|
||||
builder.Append($"Pixel Shaders ({passName}): {string.Join(", ", shaders)}");
|
||||
}
|
||||
|
||||
ShadersString = Encoding.UTF8.GetBytes(builder.ToString());
|
||||
_shadersString = Encoding.UTF8.GetBytes(builder.ToString());
|
||||
}
|
||||
else
|
||||
ShadersString = UnknownShadersString;
|
||||
{
|
||||
_shadersString = UnknownShadersString;
|
||||
}
|
||||
|
||||
ShaderComment = TryGetShpkDevkitData<string>("Comment", null, true) ?? string.Empty;
|
||||
_shaderComment = TryGetShpkDevkitData<string>("Comment", null, true) ?? string.Empty;
|
||||
}
|
||||
|
||||
private bool DrawShaderSection(bool disabled)
|
||||
{
|
||||
var ret = false;
|
||||
if (ImGui.CollapsingHeader(ShaderHeader))
|
||||
if (ImGui.CollapsingHeader(_shaderHeader))
|
||||
{
|
||||
ret |= DrawPackageNameInput(disabled);
|
||||
ret |= DrawShaderFlagsInput(disabled);
|
||||
|
|
@ -325,20 +329,17 @@ public partial class MtrlTab
|
|||
DrawMaterialShaders();
|
||||
}
|
||||
|
||||
if (!ShpkLoading && (AssociatedShpk == null || AssociatedShpkDevkit == null))
|
||||
if (!_shpkLoading && (_associatedShpk == null || _associatedShpkDevkit == null))
|
||||
{
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
|
||||
if (AssociatedShpk == null)
|
||||
{
|
||||
if (_associatedShpk == null)
|
||||
ImUtf8.Text("Unable to find a suitable shader (.shpk) file for cross-references. Some functionality will be missing."u8,
|
||||
ImGuiUtil.HalfBlendText(0x80u)); // Half red
|
||||
}
|
||||
else
|
||||
{
|
||||
ImUtf8.Text("No dev-kit file found for this material's shaders. Please install one for optimal editing experience, such as actual constant names instead of hexadecimal identifiers."u8,
|
||||
ImUtf8.Text(
|
||||
"No dev-kit file found for this material's shaders. Please install one for optimal editing experience, such as actual constant names instead of hexadecimal identifiers."u8,
|
||||
ImGuiUtil.HalfBlendText(0x8080u)); // Half yellow
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -358,14 +359,14 @@ public partial class MtrlTab
|
|||
if (c)
|
||||
foreach (var value in GetShpkNames())
|
||||
{
|
||||
if (ImGui.Selectable(value, value == Mtrl.ShaderPackage.Name))
|
||||
{
|
||||
Mtrl.ShaderPackage.Name = value;
|
||||
ret = true;
|
||||
AssociatedShpk = null;
|
||||
LoadedShpkPath = FullPath.Empty;
|
||||
LoadShpk(FindAssociatedShpk(out _, out _));
|
||||
}
|
||||
if (!ImGui.Selectable(value, value == Mtrl.ShaderPackage.Name))
|
||||
continue;
|
||||
|
||||
Mtrl.ShaderPackage.Name = value;
|
||||
ret = true;
|
||||
_associatedShpk = null;
|
||||
_loadedShpkPath = FullPath.Empty;
|
||||
LoadShpk(FindAssociatedShpk(out _, out _));
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -391,23 +392,23 @@ public partial class MtrlTab
|
|||
private void DrawCustomAssociations()
|
||||
{
|
||||
const string tooltip = "Click to copy file path to clipboard.";
|
||||
var text = AssociatedShpk == null
|
||||
var text = _associatedShpk == null
|
||||
? "Associated .shpk file: None"
|
||||
: $"Associated .shpk file: {LoadedShpkPathName}";
|
||||
var devkitText = AssociatedShpkDevkit == null
|
||||
: $"Associated .shpk file: {_loadedShpkPathName}";
|
||||
var devkitText = _associatedShpkDevkit == null
|
||||
? "Associated dev-kit file: None"
|
||||
: $"Associated dev-kit file: {LoadedShpkDevkitPathName}";
|
||||
var baseDevkitText = AssociatedBaseDevkit == null
|
||||
: $"Associated dev-kit file: {_loadedShpkDevkitPathName}";
|
||||
var baseDevkitText = _associatedBaseDevkit == null
|
||||
? "Base dev-kit file: None"
|
||||
: $"Base dev-kit file: {LoadedBaseDevkitPathName}";
|
||||
: $"Base dev-kit file: {_loadedBaseDevkitPathName}";
|
||||
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
|
||||
ImGuiUtil.CopyOnClickSelectable(text, LoadedShpkPathName, tooltip);
|
||||
ImGuiUtil.CopyOnClickSelectable(devkitText, LoadedShpkDevkitPathName, tooltip);
|
||||
ImGuiUtil.CopyOnClickSelectable(baseDevkitText, LoadedBaseDevkitPathName, tooltip);
|
||||
ImUtf8.CopyOnClickSelectable(text, _loadedShpkPathName, tooltip);
|
||||
ImUtf8.CopyOnClickSelectable(devkitText, _loadedShpkDevkitPathName, tooltip);
|
||||
ImUtf8.CopyOnClickSelectable(baseDevkitText, _loadedBaseDevkitPathName, tooltip);
|
||||
|
||||
if (ImGui.Button("Associate Custom .shpk File"))
|
||||
if (ImUtf8.Button("Associate Custom .shpk File"u8))
|
||||
_fileDialog.OpenFilePicker("Associate Custom .shpk File...", ".shpk", (success, name) =>
|
||||
{
|
||||
if (success)
|
||||
|
|
@ -416,15 +417,15 @@ public partial class MtrlTab
|
|||
|
||||
var moddedPath = FindAssociatedShpk(out var defaultPath, out var gamePath);
|
||||
ImGui.SameLine();
|
||||
if (ImGuiUtil.DrawDisabledButton("Associate Default .shpk File", Vector2.Zero, moddedPath.ToPath(),
|
||||
moddedPath.Equals(LoadedShpkPath)))
|
||||
if (ImUtf8.ButtonEx("Associate Default .shpk File"u8, moddedPath.ToPath(), Vector2.Zero,
|
||||
moddedPath.Equals(_loadedShpkPath)))
|
||||
LoadShpk(moddedPath);
|
||||
|
||||
if (!gamePath.Path.Equals(moddedPath.InternalName))
|
||||
{
|
||||
ImGui.SameLine();
|
||||
if (ImGuiUtil.DrawDisabledButton("Associate Unmodded .shpk File", Vector2.Zero, defaultPath,
|
||||
gamePath.Path.Equals(LoadedShpkPath.InternalName)))
|
||||
if (ImUtf8.ButtonEx("Associate Unmodded .shpk File", defaultPath, Vector2.Zero,
|
||||
gamePath.Path.Equals(_loadedShpkPath.InternalName)))
|
||||
LoadShpk(new FullPath(gamePath));
|
||||
}
|
||||
|
||||
|
|
@ -433,22 +434,23 @@ public partial class MtrlTab
|
|||
|
||||
private bool DrawMaterialShaderKeys(bool disabled)
|
||||
{
|
||||
if (ShaderKeys.Count == 0)
|
||||
if (_shaderKeys.Count == 0)
|
||||
return false;
|
||||
|
||||
var ret = false;
|
||||
foreach (var (label, index, description, monoFont, values) in ShaderKeys)
|
||||
foreach (var (label, index, description, monoFont, values) in _shaderKeys)
|
||||
{
|
||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont, monoFont);
|
||||
ref var key = ref Mtrl.ShaderPackage.ShaderKeys[index];
|
||||
var shpkKey = AssociatedShpk?.GetMaterialKeyById(key.Category);
|
||||
using var id = ImUtf8.PushId((int)key.Category);
|
||||
var shpkKey = _associatedShpk?.GetMaterialKeyById(key.Category);
|
||||
var currentValue = key.Value;
|
||||
var (currentLabel, _, currentDescription) =
|
||||
values.FirstOrNull(v => v.Value == currentValue) ?? ($"0x{currentValue:X8}", currentValue, string.Empty);
|
||||
if (!disabled && shpkKey.HasValue)
|
||||
{
|
||||
ImGui.SetNextItemWidth(UiHelpers.Scale * 250.0f);
|
||||
using (var c = ImRaii.Combo($"##{key.Category:X8}", currentLabel))
|
||||
using (var c = ImUtf8.Combo(""u8, currentLabel))
|
||||
{
|
||||
if (c)
|
||||
foreach (var (valueLabel, value, valueDescription) in values)
|
||||
|
|
@ -469,16 +471,16 @@ public partial class MtrlTab
|
|||
if (description.Length > 0)
|
||||
ImGuiUtil.LabeledHelpMarker(label, description);
|
||||
else
|
||||
ImGui.TextUnformatted(label);
|
||||
ImUtf8.Text(label);
|
||||
}
|
||||
else if (description.Length > 0 || currentDescription.Length > 0)
|
||||
{
|
||||
ImGuiUtil.LabeledHelpMarker($"{label}: {currentLabel}",
|
||||
ImUtf8.LabeledHelpMarker($"{label}: {currentLabel}",
|
||||
description + (description.Length > 0 && currentDescription.Length > 0 ? "\n\n" : string.Empty) + currentDescription);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.TextUnformatted($"{label}: {currentLabel}");
|
||||
ImUtf8.Text($"{label}: {currentLabel}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -487,19 +489,19 @@ public partial class MtrlTab
|
|||
|
||||
private void DrawMaterialShaders()
|
||||
{
|
||||
if (AssociatedShpk == null)
|
||||
if (_associatedShpk == null)
|
||||
return;
|
||||
|
||||
using (var node = ImUtf8.TreeNode("Candidate Shaders"u8))
|
||||
{
|
||||
if (node)
|
||||
ImUtf8.Text(ShadersString.Span);
|
||||
ImUtf8.Text(_shadersString.Span);
|
||||
}
|
||||
|
||||
if (ShaderComment.Length > 0)
|
||||
if (_shaderComment.Length > 0)
|
||||
{
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
ImGui.TextUnformatted(ShaderComment);
|
||||
ImUtf8.Text(_shaderComment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ public partial class MtrlTab
|
|||
{
|
||||
Textures.Clear();
|
||||
SamplerIds.Clear();
|
||||
if (AssociatedShpk == null)
|
||||
if (_associatedShpk == null)
|
||||
{
|
||||
SamplerIds.UnionWith(Mtrl.ShaderPackage.Samplers.Select(sampler => sampler.SamplerId));
|
||||
if (Mtrl.Table != null)
|
||||
|
|
@ -34,11 +34,11 @@ public partial class MtrlTab
|
|||
}
|
||||
else
|
||||
{
|
||||
foreach (var index in VertexShaders)
|
||||
SamplerIds.UnionWith(AssociatedShpk.VertexShaders[index].Samplers.Select(sampler => sampler.Id));
|
||||
foreach (var index in PixelShaders)
|
||||
SamplerIds.UnionWith(AssociatedShpk.PixelShaders[index].Samplers.Select(sampler => sampler.Id));
|
||||
if (!ShadersKnown)
|
||||
foreach (var index in _vertexShaders)
|
||||
SamplerIds.UnionWith(_associatedShpk.VertexShaders[index].Samplers.Select(sampler => sampler.Id));
|
||||
foreach (var index in _pixelShaders)
|
||||
SamplerIds.UnionWith(_associatedShpk.PixelShaders[index].Samplers.Select(sampler => sampler.Id));
|
||||
if (!_shadersKnown)
|
||||
{
|
||||
SamplerIds.UnionWith(Mtrl.ShaderPackage.Samplers.Select(sampler => sampler.SamplerId));
|
||||
if (Mtrl.Table != null)
|
||||
|
|
@ -47,11 +47,11 @@ public partial class MtrlTab
|
|||
|
||||
foreach (var samplerId in SamplerIds)
|
||||
{
|
||||
var shpkSampler = AssociatedShpk.GetSamplerById(samplerId);
|
||||
var shpkSampler = _associatedShpk.GetSamplerById(samplerId);
|
||||
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);
|
||||
|
|
@ -95,9 +95,12 @@ public partial class MtrlTab
|
|||
private static ReadOnlySpan<byte> TextureAddressModeTooltip(TextureAddressMode addressMode)
|
||||
=> addressMode switch
|
||||
{
|
||||
TextureAddressMode.Wrap => "Tile the texture at every UV integer junction.\n\nFor example, for U values between 0 and 3, the texture is repeated three times."u8,
|
||||
TextureAddressMode.Mirror => "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."u8,
|
||||
TextureAddressMode.Clamp => "Texture coordinates outside the range [0.0, 1.0] are set to the texture color at 0.0 or 1.0, respectively."u8,
|
||||
TextureAddressMode.Wrap =>
|
||||
"Tile the texture at every UV integer junction.\n\nFor example, for U values between 0 and 3, the texture is repeated three times."u8,
|
||||
TextureAddressMode.Mirror =>
|
||||
"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."u8,
|
||||
TextureAddressMode.Clamp =>
|
||||
"Texture coordinates outside the range [0.0, 1.0] are set to the texture color at 0.0 or 1.0, respectively."u8,
|
||||
TextureAddressMode.Border => "Texture coordinates outside the range [0.0, 1.0] are set to the border color (generally black)."u8,
|
||||
_ => ""u8,
|
||||
};
|
||||
|
|
@ -167,7 +170,7 @@ public partial class MtrlTab
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
private static bool ComboTextureAddressMode(ReadOnlySpan<byte> label, ref TextureAddressMode value)
|
||||
{
|
||||
using var c = ImUtf8.Combo(label, value.ToString());
|
||||
|
|
@ -202,7 +205,7 @@ public partial class MtrlTab
|
|||
ret = true;
|
||||
}
|
||||
|
||||
ref var samplerFlags = ref SamplerFlags.Wrap(ref sampler.Flags);
|
||||
ref var samplerFlags = ref Wrap(ref sampler.Flags);
|
||||
|
||||
ImGui.SetNextItemWidth(UiHelpers.Scale * 100.0f);
|
||||
var addressMode = samplerFlags.UAddressMode;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ using OtterGui;
|
|||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
using OtterGui.Widgets;
|
||||
using Penumbra.GameData;
|
||||
using Penumbra.GameData.Files;
|
||||
using Penumbra.GameData.Files.MaterialStructs;
|
||||
using Penumbra.GameData.Interop;
|
||||
|
|
@ -21,7 +20,7 @@ public sealed partial class MtrlTab : IWritable, IDisposable
|
|||
private const int ShpkPrefixLength = 16;
|
||||
|
||||
private static readonly CiByteString ShpkPrefix = CiByteString.FromSpanUnsafe("shader/sm5/shpk/"u8, true, true, true);
|
||||
|
||||
|
||||
private readonly IDataManager _gameData;
|
||||
private readonly IFramework _framework;
|
||||
private readonly ObjectManager _objects;
|
||||
|
|
@ -40,7 +39,8 @@ public sealed partial class MtrlTab : IWritable, IDisposable
|
|||
private bool _updateOnNextFrame;
|
||||
|
||||
public unsafe MtrlTab(IDataManager gameData, IFramework framework, ObjectManager objects, CharacterBaseDestructor characterBaseDestructor,
|
||||
StainService stainService, ResourceTreeFactory resourceTreeFactory, FileDialogService fileDialog, MaterialTemplatePickers materialTemplatePickers,
|
||||
StainService stainService, ResourceTreeFactory resourceTreeFactory, FileDialogService fileDialog,
|
||||
MaterialTemplatePickers materialTemplatePickers,
|
||||
Configuration config, ModEditWindow edit, MtrlFile file, string filePath, bool writable)
|
||||
{
|
||||
_gameData = gameData;
|
||||
|
|
@ -53,11 +53,11 @@ public sealed partial class MtrlTab : IWritable, IDisposable
|
|||
_materialTemplatePickers = materialTemplatePickers;
|
||||
_config = config;
|
||||
|
||||
_edit = edit;
|
||||
Mtrl = file;
|
||||
FilePath = filePath;
|
||||
Writable = writable;
|
||||
AssociatedBaseDevkit = TryLoadShpkDevkit("_base", out LoadedBaseDevkitPathName);
|
||||
_edit = edit;
|
||||
Mtrl = file;
|
||||
FilePath = filePath;
|
||||
Writable = writable;
|
||||
_associatedBaseDevkit = TryLoadShpkDevkit("_base", out _loadedBaseDevkitPathName);
|
||||
Update();
|
||||
LoadShpk(FindAssociatedShpk(out _, out _));
|
||||
if (writable)
|
||||
|
|
@ -118,7 +118,7 @@ public sealed partial class MtrlTab : IWritable, IDisposable
|
|||
using var dis = ImRaii.Disabled(disabled);
|
||||
|
||||
var tmp = shaderFlags.EnableTransparency;
|
||||
if (ImGui.Checkbox("Enable Transparency", ref tmp))
|
||||
if (ImUtf8.Checkbox("Enable Transparency"u8, ref tmp))
|
||||
{
|
||||
shaderFlags.EnableTransparency = tmp;
|
||||
ret = true;
|
||||
|
|
@ -127,14 +127,14 @@ public sealed partial class MtrlTab : IWritable, IDisposable
|
|||
|
||||
ImGui.SameLine(200 * UiHelpers.Scale + ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X);
|
||||
tmp = shaderFlags.HideBackfaces;
|
||||
if (ImGui.Checkbox("Hide Backfaces", ref tmp))
|
||||
if (ImUtf8.Checkbox("Hide Backfaces"u8, ref tmp))
|
||||
{
|
||||
shaderFlags.HideBackfaces = tmp;
|
||||
ret = true;
|
||||
SetShaderPackageFlags(Mtrl.ShaderPackage.Flags);
|
||||
}
|
||||
|
||||
if (ShpkLoading)
|
||||
if (_shpkLoading)
|
||||
{
|
||||
ImGui.SameLine(400 * UiHelpers.Scale + 2 * ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X);
|
||||
|
||||
|
|
@ -147,32 +147,32 @@ public sealed partial class MtrlTab : IWritable, IDisposable
|
|||
|
||||
private void DrawOtherMaterialDetails(bool _)
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Further Content"))
|
||||
if (!ImUtf8.CollapsingHeader("Further Content"u8))
|
||||
return;
|
||||
|
||||
using (var sets = ImRaii.TreeNode("UV Sets", ImGuiTreeNodeFlags.DefaultOpen))
|
||||
using (var sets = ImUtf8.TreeNode("UV Sets"u8, ImGuiTreeNodeFlags.DefaultOpen))
|
||||
{
|
||||
if (sets)
|
||||
foreach (var set in Mtrl.UvSets)
|
||||
ImRaii.TreeNode($"#{set.Index:D2} - {set.Name}", ImGuiTreeNodeFlags.Leaf).Dispose();
|
||||
ImUtf8.TreeNode($"#{set.Index:D2} - {set.Name}", ImGuiTreeNodeFlags.Leaf).Dispose();
|
||||
}
|
||||
|
||||
using (var sets = ImRaii.TreeNode("Color Sets", ImGuiTreeNodeFlags.DefaultOpen))
|
||||
using (var sets = ImUtf8.TreeNode("Color Sets"u8, ImGuiTreeNodeFlags.DefaultOpen))
|
||||
{
|
||||
if (sets)
|
||||
foreach (var set in Mtrl.ColorSets)
|
||||
ImRaii.TreeNode($"#{set.Index:D2} - {set.Name}", ImGuiTreeNodeFlags.Leaf).Dispose();
|
||||
ImUtf8.TreeNode($"#{set.Index:D2} - {set.Name}", ImGuiTreeNodeFlags.Leaf).Dispose();
|
||||
}
|
||||
|
||||
if (Mtrl.AdditionalData.Length <= 0)
|
||||
return;
|
||||
|
||||
using var t = ImRaii.TreeNode($"Additional Data (Size: {Mtrl.AdditionalData.Length})###AdditionalData");
|
||||
using var t = ImUtf8.TreeNode($"Additional Data (Size: {Mtrl.AdditionalData.Length})###AdditionalData");
|
||||
if (t)
|
||||
Widget.DrawHexViewer(Mtrl.AdditionalData);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
private void Update()
|
||||
{
|
||||
UpdateShaders();
|
||||
UpdateTextures();
|
||||
|
|
@ -187,12 +187,12 @@ public sealed partial class MtrlTab : IWritable, IDisposable
|
|||
}
|
||||
|
||||
public bool Valid
|
||||
=> ShadersKnown && Mtrl.Valid;
|
||||
=> _shadersKnown && Mtrl.Valid;
|
||||
|
||||
public byte[] Write()
|
||||
{
|
||||
var output = Mtrl.Clone();
|
||||
output.GarbageCollect(AssociatedShpk, SamplerIds);
|
||||
output.GarbageCollect(_associatedShpk, SamplerIds);
|
||||
|
||||
return output.Write();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,16 @@ using Penumbra.Services;
|
|||
|
||||
namespace Penumbra.UI.AdvancedWindow.Materials;
|
||||
|
||||
public sealed class MtrlTabFactory(IDataManager gameData, IFramework framework, ObjectManager objects,
|
||||
CharacterBaseDestructor characterBaseDestructor, StainService stainService, ResourceTreeFactory resourceTreeFactory,
|
||||
FileDialogService fileDialog, MaterialTemplatePickers materialTemplatePickers, Configuration config) : IUiService
|
||||
public sealed class MtrlTabFactory(
|
||||
IDataManager gameData,
|
||||
IFramework framework,
|
||||
ObjectManager objects,
|
||||
CharacterBaseDestructor characterBaseDestructor,
|
||||
StainService stainService,
|
||||
ResourceTreeFactory resourceTreeFactory,
|
||||
FileDialogService fileDialog,
|
||||
MaterialTemplatePickers materialTemplatePickers,
|
||||
Configuration config) : IUiService
|
||||
{
|
||||
public MtrlTab Create(ModEditWindow edit, MtrlFile file, string filePath, bool writable)
|
||||
=> new(gameData, framework, objects, characterBaseDestructor, stainService, resourceTreeFactory, fileDialog,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using Dalamud.Interface.Utility;
|
|||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
using Penumbra.UI.AdvancedWindow.Materials;
|
||||
|
||||
namespace Penumbra.UI.AdvancedWindow;
|
||||
|
|
@ -24,7 +25,7 @@ public partial class ModEditWindow
|
|||
if (_editor.Files.Mdl.Count == 0)
|
||||
return;
|
||||
|
||||
using var tab = ImRaii.TabItem("Material Reassignment");
|
||||
using var tab = ImUtf8.TabItem("Material Reassignment"u8);
|
||||
if (!tab)
|
||||
return;
|
||||
|
||||
|
|
@ -32,45 +33,43 @@ public partial class ModEditWindow
|
|||
MaterialSuffix.Draw(_editor, ImGuiHelpers.ScaledVector2(175, 0));
|
||||
|
||||
ImGui.NewLine();
|
||||
using var child = ImRaii.Child("##mdlFiles", -Vector2.One, true);
|
||||
using var child = ImUtf8.Child("##mdlFiles"u8, -Vector2.One, true);
|
||||
if (!child)
|
||||
return;
|
||||
|
||||
using var table = ImRaii.Table("##files", 4, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit, -Vector2.One);
|
||||
using var table = ImUtf8.Table("##files"u8, 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())
|
||||
{
|
||||
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 (ImUtf8.IconButton(FontAwesomeIcon.Save, "Save the changed mdl file.\nUse at own risk!"u8, disabled: !info.Changed))
|
||||
info.Save(_editor.Compactor);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Recycle.ToIconString(), iconSize,
|
||||
"Restore current changes to default.", !info.Changed, true))
|
||||
if (ImUtf8.IconButton(FontAwesomeIcon.Recycle, "Restore current changes to default."u8, disabled: !info.Changed))
|
||||
info.Restore();
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TextUnformatted(info.Path.FullName[(Mod!.ModPath.FullName.Length + 1)..]);
|
||||
ImUtf8.Text(info.Path.InternalName.Span[(Mod!.ModPath.FullName.Length + 1)..]);
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.SetNextItemWidth(400 * UiHelpers.Scale);
|
||||
var tmp = info.CurrentMaterials[0];
|
||||
if (ImGui.InputText("##0", ref tmp, 64))
|
||||
if (ImUtf8.InputText("##0"u8, ref tmp))
|
||||
info.SetMaterial(tmp, 0);
|
||||
|
||||
for (var i = 1; i < info.Count; ++i)
|
||||
{
|
||||
using var id2 = ImUtf8.PushId(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))
|
||||
if (ImUtf8.InputText(""u8, ref tmp))
|
||||
info.SetMaterial(tmp, i);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ using Penumbra.GameData.Interop;
|
|||
using Penumbra.String;
|
||||
using static Penumbra.GameData.Files.ShpkFile;
|
||||
using OtterGui.Widgets;
|
||||
using Penumbra.GameData.Files.ShaderStructs;
|
||||
using OtterGui.Text;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
|
|
@ -56,21 +55,17 @@ public partial class ModEditWindow
|
|||
private static void DrawShaderPackageSummary(ShpkTab tab)
|
||||
{
|
||||
if (tab.Shpk.IsLegacy)
|
||||
{
|
||||
ImUtf8.Text("This legacy shader package will not work in the current version of the game. Do not attempt to load it.",
|
||||
ImGuiUtil.HalfBlendText(0x80u)); // Half red
|
||||
}
|
||||
ImGui.TextUnformatted(tab.Header);
|
||||
ImUtf8.Text(tab.Header);
|
||||
if (!tab.Shpk.Disassembled)
|
||||
{
|
||||
ImUtf8.Text("Your system doesn't support disassembling shaders. Some functionality will be missing.",
|
||||
ImGuiUtil.HalfBlendText(0x80u)); // Half red
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawShaderExportButton(ShpkTab tab, string objectName, Shader shader, int idx)
|
||||
{
|
||||
if (!ImGui.Button($"Export Shader Program Blob ({shader.Blob.Length} bytes)"))
|
||||
if (!ImUtf8.Button($"Export Shader Program Blob ({shader.Blob.Length} bytes)"))
|
||||
return;
|
||||
|
||||
var defaultName = objectName[0] switch
|
||||
|
|
@ -106,7 +101,7 @@ public partial class ModEditWindow
|
|||
|
||||
private static void DrawShaderImportButton(ShpkTab tab, string objectName, Shader[] shaders, int idx)
|
||||
{
|
||||
if (!ImGui.Button("Replace Shader Program Blob"))
|
||||
if (!ImUtf8.Button("Replace Shader Program Blob"u8))
|
||||
return;
|
||||
|
||||
tab.FileDialog.OpenFilePicker($"Replace {objectName} #{idx} Program Blob...", "Shader Program Blobs{.o,.cso,.dxbc,.dxil}",
|
||||
|
|
@ -145,8 +140,8 @@ public partial class ModEditWindow
|
|||
|
||||
private static unsafe void DrawRawDisassembly(Shader shader)
|
||||
{
|
||||
using var t2 = ImRaii.TreeNode("Raw Program Disassembly");
|
||||
if (!t2)
|
||||
using var tree = ImUtf8.TreeNode("Raw Program Disassembly"u8);
|
||||
if (!tree)
|
||||
return;
|
||||
|
||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||
|
|
@ -164,31 +159,34 @@ public partial class ModEditWindow
|
|||
{
|
||||
foreach (var (key, keyIdx) in shader.SystemValues!.WithIndex())
|
||||
{
|
||||
ImRaii.TreeNode($"Used with System Key {tab.TryResolveName(tab.Shpk.SystemKeys[keyIdx].Id)} \u2208 {{ {tab.NameSetToString(key)} }}",
|
||||
ImUtf8.TreeNode(
|
||||
$"Used with System Key {tab.TryResolveName(tab.Shpk.SystemKeys[keyIdx].Id)} \u2208 {{ {tab.NameSetToString(key)} }}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
}
|
||||
|
||||
foreach (var (key, keyIdx) in shader.SceneValues!.WithIndex())
|
||||
{
|
||||
ImRaii.TreeNode($"Used with Scene Key {tab.TryResolveName(tab.Shpk.SceneKeys[keyIdx].Id)} \u2208 {{ {tab.NameSetToString(key)} }}",
|
||||
ImUtf8.TreeNode(
|
||||
$"Used with Scene Key {tab.TryResolveName(tab.Shpk.SceneKeys[keyIdx].Id)} \u2208 {{ {tab.NameSetToString(key)} }}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
}
|
||||
|
||||
foreach (var (key, keyIdx) in shader.MaterialValues!.WithIndex())
|
||||
{
|
||||
ImRaii.TreeNode($"Used with Material Key {tab.TryResolveName(tab.Shpk.MaterialKeys[keyIdx].Id)} \u2208 {{ {tab.NameSetToString(key)} }}",
|
||||
ImUtf8.TreeNode(
|
||||
$"Used with Material Key {tab.TryResolveName(tab.Shpk.MaterialKeys[keyIdx].Id)} \u2208 {{ {tab.NameSetToString(key)} }}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
}
|
||||
|
||||
foreach (var (key, keyIdx) in shader.SubViewValues!.WithIndex())
|
||||
{
|
||||
ImRaii.TreeNode($"Used with Sub-View Key #{keyIdx} \u2208 {{ {tab.NameSetToString(key)} }}",
|
||||
ImUtf8.TreeNode($"Used with Sub-View Key #{keyIdx} \u2208 {{ {tab.NameSetToString(key)} }}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImRaii.TreeNode($"Used in Passes: {tab.NameSetToString(shader.Passes)}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
ImUtf8.TreeNode($"Used in Passes: {tab.NameSetToString(shader.Passes)}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
}
|
||||
|
||||
private static void DrawShaderPackageFilterSection(ShpkTab tab)
|
||||
|
|
@ -215,19 +213,20 @@ public partial class ModEditWindow
|
|||
{
|
||||
if (values.PossibleValues == null)
|
||||
{
|
||||
ImRaii.TreeNode(label, ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
ImUtf8.TreeNode(label, ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
using var node = ImRaii.TreeNode(label);
|
||||
using var node = ImUtf8.TreeNode(label);
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
foreach (var value in values.PossibleValues)
|
||||
{
|
||||
var contains = values.Contains(value);
|
||||
if (!ImGui.Checkbox($"{tab.TryResolveName(value)}", ref contains))
|
||||
if (!ImUtf8.Checkbox($"{tab.TryResolveName(value)}", ref contains))
|
||||
continue;
|
||||
|
||||
if (contains)
|
||||
{
|
||||
if (values.AddExisting(value))
|
||||
|
|
@ -249,7 +248,7 @@ public partial class ModEditWindow
|
|||
|
||||
private static bool DrawShaderPackageShaderArray(ShpkTab tab, string objectName, Shader[] shaders, bool disabled)
|
||||
{
|
||||
if (shaders.Length == 0 || !ImGui.CollapsingHeader($"{objectName}s"))
|
||||
if (shaders.Length == 0 || !ImUtf8.CollapsingHeader($"{objectName}s"))
|
||||
return false;
|
||||
|
||||
var ret = false;
|
||||
|
|
@ -259,7 +258,7 @@ public partial class ModEditWindow
|
|||
if (!tab.IsFilterMatch(shader))
|
||||
continue;
|
||||
|
||||
using var t = ImRaii.TreeNode($"{objectName} #{idx}");
|
||||
using var t = ImUtf8.TreeNode($"{objectName} #{idx}");
|
||||
if (!t)
|
||||
continue;
|
||||
|
||||
|
|
@ -270,20 +269,20 @@ public partial class ModEditWindow
|
|||
DrawShaderImportButton(tab, objectName, shaders, idx);
|
||||
}
|
||||
|
||||
ret |= DrawShaderPackageResourceArray("Constant Buffers", "slot", true, shader.Constants, false, true);
|
||||
ret |= DrawShaderPackageResourceArray("Samplers", "slot", false, shader.Samplers, false, true);
|
||||
ret |= DrawShaderPackageResourceArray("Constant Buffers", "slot", true, shader.Constants, false, true);
|
||||
ret |= DrawShaderPackageResourceArray("Samplers", "slot", false, shader.Samplers, false, true);
|
||||
if (!tab.Shpk.IsLegacy)
|
||||
ret |= DrawShaderPackageResourceArray("Textures", "slot", false, shader.Textures, false, true);
|
||||
ret |= DrawShaderPackageResourceArray("Unordered Access Views", "slot", true, shader.Uavs, false, true);
|
||||
ret |= DrawShaderPackageResourceArray("Textures", "slot", false, shader.Textures, false, true);
|
||||
ret |= DrawShaderPackageResourceArray("Unordered Access Views", "slot", true, shader.Uavs, false, true);
|
||||
|
||||
if (shader.DeclaredInputs != 0)
|
||||
ImRaii.TreeNode($"Declared Inputs: {shader.DeclaredInputs}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
ImUtf8.TreeNode($"Declared Inputs: {shader.DeclaredInputs}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
if (shader.UsedInputs != 0)
|
||||
ImRaii.TreeNode($"Used Inputs: {shader.UsedInputs}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
ImUtf8.TreeNode($"Used Inputs: {shader.UsedInputs}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
|
||||
if (shader.AdditionalHeader.Length > 8)
|
||||
{
|
||||
using var t2 = ImRaii.TreeNode($"Additional Header (Size: {shader.AdditionalHeader.Length})###AdditionalHeader");
|
||||
using var t2 = ImUtf8.TreeNode($"Additional Header (Size: {shader.AdditionalHeader.Length})###AdditionalHeader");
|
||||
if (t2)
|
||||
Widget.DrawHexViewer(shader.AdditionalHeader);
|
||||
}
|
||||
|
|
@ -313,23 +312,28 @@ public partial class ModEditWindow
|
|||
var usedString = UsedComponentString(withSize, false, resource);
|
||||
if (usedString.Length > 0)
|
||||
{
|
||||
ImRaii.TreeNode(hasFilter ? $"Globally Used: {usedString}" : $"Used: {usedString}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
ImUtf8.TreeNode(hasFilter ? $"Globally Used: {usedString}" : $"Used: {usedString}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
if (hasFilter)
|
||||
{
|
||||
var filteredUsedString = UsedComponentString(withSize, true, resource);
|
||||
if (filteredUsedString.Length > 0)
|
||||
ImRaii.TreeNode($"Used within Filters: {filteredUsedString}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
ImUtf8.TreeNode($"Used within Filters: {filteredUsedString}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet)
|
||||
.Dispose();
|
||||
else
|
||||
ImRaii.TreeNode("Unused within Filters", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
ImUtf8.TreeNode("Unused within Filters"u8, ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
}
|
||||
}
|
||||
else
|
||||
ImRaii.TreeNode(hasFilter ? "Globally Unused" : "Unused", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
{
|
||||
ImUtf8.TreeNode(hasFilter ? "Globally Unused"u8 : "Unused"u8, ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawShaderPackageResourceArray(string arrayName, string slotLabel, bool withSize, Resource[] resources, bool hasFilter, bool disabled)
|
||||
private static bool DrawShaderPackageResourceArray(string arrayName, string slotLabel, bool withSize, Resource[] resources, bool hasFilter,
|
||||
bool disabled)
|
||||
{
|
||||
if (resources.Length == 0)
|
||||
return false;
|
||||
|
|
@ -345,8 +349,8 @@ public partial class ModEditWindow
|
|||
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);
|
||||
font.Dispose();
|
||||
using var t2 = ImUtf8.TreeNode(name, !disabled || buf.Used != null ? 0 : ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet);
|
||||
font.Pop();
|
||||
if (t2)
|
||||
ret |= DrawShaderPackageResource(slotLabel, withSize, ref buf, hasFilter, disabled);
|
||||
}
|
||||
|
|
@ -361,7 +365,7 @@ public partial class ModEditWindow
|
|||
+ new Vector2(ImGui.CalcTextSize(label).X + 3 * ImGui.GetStyle().ItemInnerSpacing.X + ImGui.GetFrameHeight(),
|
||||
ImGui.GetStyle().FramePadding.Y);
|
||||
|
||||
var ret = ImGui.CollapsingHeader(label);
|
||||
var ret = ImUtf8.CollapsingHeader(label);
|
||||
ImGui.GetWindowDrawList()
|
||||
.AddText(UiBuilder.DefaultFont, UiBuilder.DefaultFont.FontSize, pos, ImGui.GetColorU32(ImGuiCol.Text), "Layout");
|
||||
return ret;
|
||||
|
|
@ -374,7 +378,7 @@ public partial class ModEditWindow
|
|||
if (isSizeWellDefined)
|
||||
return true;
|
||||
|
||||
ImGui.TextUnformatted(materialParams.HasValue
|
||||
ImUtf8.Text(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");
|
||||
return false;
|
||||
|
|
@ -382,7 +386,7 @@ public partial class ModEditWindow
|
|||
|
||||
private static bool DrawShaderPackageMaterialMatrix(ShpkTab tab, bool disabled)
|
||||
{
|
||||
ImGui.TextUnformatted(tab.Shpk.Disassembled
|
||||
ImUtf8.Text(tab.Shpk.Disassembled
|
||||
? "Parameter positions (continuations are grayed out, globally unused values are red, unused values within filters are yellow):"
|
||||
: "Parameter positions (continuations are grayed out):");
|
||||
|
||||
|
|
@ -398,10 +402,7 @@ public partial class ModEditWindow
|
|||
ImGui.TableSetupColumn("w", ImGuiTableColumnFlags.WidthFixed, 250 * UiHelpers.Scale);
|
||||
ImGui.TableHeadersRow();
|
||||
|
||||
var textColorStart = ImGui.GetColorU32(ImGuiCol.Text);
|
||||
var textColorCont = ImGuiUtil.HalfTransparent(textColorStart); // Half opacity
|
||||
var textColorUnusedStart = ImGuiUtil.HalfBlend(textColorStart, 0x80u); // Half red
|
||||
var textColorUnusedCont = ImGuiUtil.HalfTransparent(textColorUnusedStart);
|
||||
var textColorStart = ImGui.GetColorU32(ImGuiCol.Text);
|
||||
|
||||
var ret = false;
|
||||
for (var i = 0; i < tab.Matrix.GetLength(0); ++i)
|
||||
|
|
@ -420,12 +421,12 @@ public partial class ModEditWindow
|
|||
color = ImGuiUtil.HalfTransparent(color); // Half opacity
|
||||
using var _ = ImRaii.PushId(i * 4 + j);
|
||||
var deletable = !disabled && idx >= 0;
|
||||
using (var font = ImRaii.PushFont(UiBuilder.MonoFont, tooltip.Length > 0))
|
||||
using (ImRaii.PushFont(UiBuilder.MonoFont, tooltip.Length > 0))
|
||||
{
|
||||
using (var c = ImRaii.PushColor(ImGuiCol.Text, color))
|
||||
using (ImRaii.PushColor(ImGuiCol.Text, color))
|
||||
{
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.Selectable(name);
|
||||
ImUtf8.Selectable(name);
|
||||
if (deletable && ImGui.IsItemClicked(ImGuiMouseButton.Right) && ImGui.GetIO().KeyCtrl)
|
||||
{
|
||||
tab.Shpk.MaterialParams = tab.Shpk.MaterialParams.RemoveItems(idx);
|
||||
|
|
@ -434,11 +435,11 @@ public partial class ModEditWindow
|
|||
}
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip(tooltip);
|
||||
ImUtf8.HoverTooltip(tooltip);
|
||||
}
|
||||
|
||||
if (deletable)
|
||||
ImGuiUtil.HoverTooltip("\nControl + Right-Click to remove.");
|
||||
ImUtf8.HoverTooltip("\nControl + Right-Click to remove."u8);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -450,7 +451,9 @@ public partial class ModEditWindow
|
|||
if (!ImUtf8.Button("Export globally unused parameters as material dev-kit file"u8))
|
||||
return;
|
||||
|
||||
tab.FileDialog.OpenSavePicker("Export material dev-kit file", ".json", $"{Path.GetFileNameWithoutExtension(tab.FilePath)}.json", ".json", DoSave, null, false);
|
||||
tab.FileDialog.OpenSavePicker("Export material dev-kit file", ".json", $"{Path.GetFileNameWithoutExtension(tab.FilePath)}.json",
|
||||
".json", DoSave, null, false);
|
||||
return;
|
||||
|
||||
void DoSave(bool success, string path)
|
||||
{
|
||||
|
|
@ -476,22 +479,22 @@ public partial class ModEditWindow
|
|||
|
||||
private static void DrawShaderPackageMisalignedParameters(ShpkTab tab)
|
||||
{
|
||||
using var t = ImRaii.TreeNode("Misaligned / Overflowing Parameters");
|
||||
using var t = ImUtf8.TreeNode("Misaligned / Overflowing Parameters"u8);
|
||||
if (!t)
|
||||
return;
|
||||
|
||||
using var _ = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||
foreach (var name in tab.MalformedParameters)
|
||||
ImRaii.TreeNode(name, ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
ImUtf8.TreeNode(name, ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
}
|
||||
|
||||
private static void DrawShaderPackageStartCombo(ShpkTab tab)
|
||||
{
|
||||
using var s = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemInnerSpacing);
|
||||
using (var _ = ImRaii.PushFont(UiBuilder.MonoFont))
|
||||
using (ImRaii.PushFont(UiBuilder.MonoFont))
|
||||
{
|
||||
ImGui.SetNextItemWidth(UiHelpers.Scale * 400);
|
||||
using var c = ImRaii.Combo("##Start", tab.Orphans[tab.NewMaterialParamStart].Name);
|
||||
using var c = ImUtf8.Combo("##Start", tab.Orphans[tab.NewMaterialParamStart].Name);
|
||||
if (c)
|
||||
foreach (var (start, idx) in tab.Orphans.WithIndex())
|
||||
{
|
||||
|
|
@ -501,7 +504,7 @@ public partial class ModEditWindow
|
|||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted("Start");
|
||||
ImUtf8.Text("Start"u8);
|
||||
}
|
||||
|
||||
private static void DrawShaderPackageEndCombo(ShpkTab tab)
|
||||
|
|
@ -510,7 +513,7 @@ public partial class ModEditWindow
|
|||
using (var _ = ImRaii.PushFont(UiBuilder.MonoFont))
|
||||
{
|
||||
ImGui.SetNextItemWidth(UiHelpers.Scale * 400);
|
||||
using var c = ImRaii.Combo("##End", tab.Orphans[tab.NewMaterialParamEnd].Name);
|
||||
using var c = ImUtf8.Combo("##End", tab.Orphans[tab.NewMaterialParamEnd].Name);
|
||||
if (c)
|
||||
{
|
||||
var current = tab.Orphans[tab.NewMaterialParamStart].Index;
|
||||
|
|
@ -527,7 +530,7 @@ public partial class ModEditWindow
|
|||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted("End");
|
||||
ImUtf8.Text("End"u8);
|
||||
}
|
||||
|
||||
private static bool DrawShaderPackageNewParameter(ShpkTab tab)
|
||||
|
|
@ -540,15 +543,14 @@ public partial class ModEditWindow
|
|||
|
||||
ImGui.SetNextItemWidth(UiHelpers.Scale * 400);
|
||||
var newName = tab.NewMaterialParamName.Value!;
|
||||
if (ImGui.InputText("Name", ref newName, 63))
|
||||
if (ImUtf8.InputText("Name", ref newName))
|
||||
tab.NewMaterialParamName = newName;
|
||||
|
||||
var tooltip = tab.UsedIds.Contains(tab.NewMaterialParamName.Crc32)
|
||||
? "The ID is already in use. Please choose a different name."
|
||||
: string.Empty;
|
||||
if (!ImGuiUtil.DrawDisabledButton($"Add {tab.NewMaterialParamName} (0x{tab.NewMaterialParamName.Crc32:X8})", new Vector2(400 * UiHelpers.Scale, ImGui.GetFrameHeight()),
|
||||
tooltip,
|
||||
tooltip.Length > 0))
|
||||
? "The ID is already in use. Please choose a different name."u8
|
||||
: ""u8;
|
||||
if (!ImUtf8.ButtonEx($"Add {tab.NewMaterialParamName} (0x{tab.NewMaterialParamName.Crc32:X8})", tooltip,
|
||||
new Vector2(400 * UiHelpers.Scale, ImGui.GetFrameHeight()), tooltip.Length > 0))
|
||||
return false;
|
||||
|
||||
tab.Shpk.MaterialParams = tab.Shpk.MaterialParams.AddItem(new MaterialParam
|
||||
|
|
@ -589,15 +591,15 @@ public partial class ModEditWindow
|
|||
{
|
||||
var ret = false;
|
||||
|
||||
if (!ImGui.CollapsingHeader("Shader Resources"))
|
||||
if (!ImUtf8.CollapsingHeader("Shader Resources"u8))
|
||||
return false;
|
||||
|
||||
var hasFilters = tab.FilterPopCount != tab.FilterMaximumPopCount;
|
||||
ret |= DrawShaderPackageResourceArray("Constant Buffers", "type", true, tab.Shpk.Constants, hasFilters, disabled);
|
||||
ret |= DrawShaderPackageResourceArray("Samplers", "type", false, tab.Shpk.Samplers, hasFilters, disabled);
|
||||
ret |= DrawShaderPackageResourceArray("Constant Buffers", "type", true, tab.Shpk.Constants, hasFilters, disabled);
|
||||
ret |= DrawShaderPackageResourceArray("Samplers", "type", false, tab.Shpk.Samplers, hasFilters, disabled);
|
||||
if (!tab.Shpk.IsLegacy)
|
||||
ret |= DrawShaderPackageResourceArray("Textures", "type", false, tab.Shpk.Textures, hasFilters, disabled);
|
||||
ret |= DrawShaderPackageResourceArray("Unordered Access Views", "type", false, tab.Shpk.Uavs, hasFilters, disabled);
|
||||
ret |= DrawShaderPackageResourceArray("Textures", "type", false, tab.Shpk.Textures, hasFilters, disabled);
|
||||
ret |= DrawShaderPackageResourceArray("Unordered Access Views", "type", false, tab.Shpk.Uavs, hasFilters, disabled);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -607,18 +609,20 @@ public partial class ModEditWindow
|
|||
if (keys.Count == 0)
|
||||
return;
|
||||
|
||||
using var t = ImRaii.TreeNode(arrayName);
|
||||
using var t = ImUtf8.TreeNode(arrayName);
|
||||
if (!t)
|
||||
return;
|
||||
|
||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||
foreach (var (key, idx) in keys.WithIndex())
|
||||
{
|
||||
using var t2 = ImRaii.TreeNode(withId ? $"#{idx}: {tab.TryResolveName(key.Id)} (0x{key.Id:X8})" : $"#{idx}");
|
||||
using var t2 = ImUtf8.TreeNode(withId ? $"#{idx}: {tab.TryResolveName(key.Id)} (0x{key.Id:X8})" : $"#{idx}");
|
||||
if (t2)
|
||||
{
|
||||
ImRaii.TreeNode($"Default Value: {tab.TryResolveName(key.DefaultValue)} (0x{key.DefaultValue:X8})", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
ImRaii.TreeNode($"Known Values: {tab.NameSetToString(key.Values, true)}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
ImUtf8.TreeNode($"Default Value: {tab.TryResolveName(key.DefaultValue)} (0x{key.DefaultValue:X8})",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
ImUtf8.TreeNode($"Known Values: {tab.NameSetToString(key.Values, true)}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet)
|
||||
.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -628,7 +632,7 @@ public partial class ModEditWindow
|
|||
if (tab.Shpk.Nodes.Length <= 0)
|
||||
return;
|
||||
|
||||
using var t = ImRaii.TreeNode($"Nodes ({tab.Shpk.Nodes.Length})###Nodes");
|
||||
using var t = ImUtf8.TreeNode($"Nodes ({tab.Shpk.Nodes.Length})###Nodes");
|
||||
if (!t)
|
||||
return;
|
||||
|
||||
|
|
@ -639,39 +643,44 @@ public partial class ModEditWindow
|
|||
if (!tab.IsFilterMatch(node))
|
||||
continue;
|
||||
|
||||
using var t2 = ImRaii.TreeNode($"#{idx:D4}: Selector: 0x{node.Selector:X8}");
|
||||
using var t2 = ImUtf8.TreeNode($"#{idx:D4}: Selector: 0x{node.Selector:X8}");
|
||||
if (!t2)
|
||||
continue;
|
||||
|
||||
foreach (var (key, keyIdx) in node.SystemKeys.WithIndex())
|
||||
{
|
||||
ImRaii.TreeNode($"System Key {tab.TryResolveName(tab.Shpk.SystemKeys[keyIdx].Id)} = {tab.TryResolveName(key)} / \u2208 {{ {tab.NameSetToString(node.SystemValues![keyIdx])} }}",
|
||||
ImUtf8.TreeNode(
|
||||
$"System Key {tab.TryResolveName(tab.Shpk.SystemKeys[keyIdx].Id)} = {tab.TryResolveName(key)} / \u2208 {{ {tab.NameSetToString(node.SystemValues![keyIdx])} }}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
}
|
||||
|
||||
foreach (var (key, keyIdx) in node.SceneKeys.WithIndex())
|
||||
{
|
||||
ImRaii.TreeNode($"Scene Key {tab.TryResolveName(tab.Shpk.SceneKeys[keyIdx].Id)} = {tab.TryResolveName(key)} / \u2208 {{ {tab.NameSetToString(node.SceneValues![keyIdx])} }}",
|
||||
ImUtf8.TreeNode(
|
||||
$"Scene Key {tab.TryResolveName(tab.Shpk.SceneKeys[keyIdx].Id)} = {tab.TryResolveName(key)} / \u2208 {{ {tab.NameSetToString(node.SceneValues![keyIdx])} }}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
}
|
||||
|
||||
foreach (var (key, keyIdx) in node.MaterialKeys.WithIndex())
|
||||
{
|
||||
ImRaii.TreeNode($"Material Key {tab.TryResolveName(tab.Shpk.MaterialKeys[keyIdx].Id)} = {tab.TryResolveName(key)} / \u2208 {{ {tab.NameSetToString(node.MaterialValues![keyIdx])} }}",
|
||||
ImUtf8.TreeNode(
|
||||
$"Material Key {tab.TryResolveName(tab.Shpk.MaterialKeys[keyIdx].Id)} = {tab.TryResolveName(key)} / \u2208 {{ {tab.NameSetToString(node.MaterialValues![keyIdx])} }}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
}
|
||||
|
||||
foreach (var (key, keyIdx) in node.SubViewKeys.WithIndex())
|
||||
{
|
||||
ImRaii.TreeNode($"Sub-View Key #{keyIdx} = {tab.TryResolveName(key)} / \u2208 {{ {tab.NameSetToString(node.SubViewValues![keyIdx])} }}",
|
||||
ImUtf8.TreeNode(
|
||||
$"Sub-View Key #{keyIdx} = {tab.TryResolveName(key)} / \u2208 {{ {tab.NameSetToString(node.SubViewValues![keyIdx])} }}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
}
|
||||
|
||||
ImRaii.TreeNode($"Pass Indices: {string.Join(' ', node.PassIndices.Select(c => $"{c:X2}"))}",
|
||||
ImUtf8.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: {tab.TryResolveName(pass.Id)}, Vertex Shader #{pass.VertexShader}, Pixel Shader #{pass.PixelShader}",
|
||||
ImUtf8.TreeNode(
|
||||
$"Pass #{passIdx}: ID: {tab.TryResolveName(pass.Id)}, Vertex Shader #{pass.VertexShader}, Pixel Shader #{pass.PixelShader}",
|
||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet)
|
||||
.Dispose();
|
||||
}
|
||||
|
|
@ -680,7 +689,7 @@ public partial class ModEditWindow
|
|||
|
||||
private static void DrawShaderPackageSelection(ShpkTab tab)
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Shader Selection"))
|
||||
if (!ImUtf8.CollapsingHeader("Shader Selection"u8))
|
||||
return;
|
||||
|
||||
DrawKeyArray(tab, "System Keys", true, tab.Shpk.SystemKeys);
|
||||
|
|
@ -689,13 +698,13 @@ public partial class ModEditWindow
|
|||
DrawKeyArray(tab, "Sub-View Keys", false, tab.Shpk.SubViewKeys);
|
||||
|
||||
DrawShaderPackageNodes(tab);
|
||||
using var t = ImRaii.TreeNode($"Node Selectors ({tab.Shpk.NodeSelectors.Count})###NodeSelectors");
|
||||
using var t = ImUtf8.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)
|
||||
ImUtf8.TreeNode($"#{selector.Value:D4}: Selector: 0x{selector.Key:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet)
|
||||
.Dispose();
|
||||
}
|
||||
}
|
||||
|
|
@ -703,14 +712,14 @@ public partial class ModEditWindow
|
|||
|
||||
private static void DrawOtherShaderPackageDetails(ShpkTab tab)
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Further Content"))
|
||||
if (!ImUtf8.CollapsingHeader("Further Content"u8))
|
||||
return;
|
||||
|
||||
ImRaii.TreeNode($"Version: 0x{tab.Shpk.Version:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
ImUtf8.TreeNode($"Version: 0x{tab.Shpk.Version:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||
|
||||
if (tab.Shpk.AdditionalData.Length > 0)
|
||||
{
|
||||
using var t = ImRaii.TreeNode($"Additional Data (Size: {tab.Shpk.AdditionalData.Length})###AdditionalData");
|
||||
using var t = ImUtf8.TreeNode($"Additional Data (Size: {tab.Shpk.AdditionalData.Length})###AdditionalData");
|
||||
if (t)
|
||||
Widget.DrawHexViewer(tab.Shpk.AdditionalData);
|
||||
}
|
||||
|
|
@ -718,9 +727,9 @@ public partial class ModEditWindow
|
|||
|
||||
private static string UsedComponentString(bool withSize, bool filtered, in Resource resource)
|
||||
{
|
||||
var used = filtered ? resource.FilteredUsed : resource.Used;
|
||||
var used = filtered ? resource.FilteredUsed : resource.Used;
|
||||
var usedDynamically = filtered ? resource.FilteredUsedDynamically : resource.UsedDynamically;
|
||||
var sb = new StringBuilder(256);
|
||||
var sb = new StringBuilder(256);
|
||||
if (withSize)
|
||||
{
|
||||
foreach (var (components, i) in (used ?? Array.Empty<DisassembledShader.VectorComponents>()).WithIndex())
|
||||
|
|
|
|||
|
|
@ -21,11 +21,11 @@ public partial class ModEditWindow
|
|||
public short NewMaterialParamStart;
|
||||
public short NewMaterialParamEnd;
|
||||
|
||||
public SharedSet<uint, uint>[] FilterSystemValues;
|
||||
public SharedSet<uint, uint>[] FilterSceneValues;
|
||||
public SharedSet<uint, uint>[] FilterMaterialValues;
|
||||
public SharedSet<uint, uint>[] FilterSubViewValues;
|
||||
public SharedSet<uint, uint> FilterPasses;
|
||||
public readonly SharedSet<uint, uint>[] FilterSystemValues;
|
||||
public readonly SharedSet<uint, uint>[] FilterSceneValues;
|
||||
public readonly SharedSet<uint, uint>[] FilterMaterialValues;
|
||||
public readonly SharedSet<uint, uint>[] FilterSubViewValues;
|
||||
public SharedSet<uint, uint> FilterPasses;
|
||||
|
||||
public readonly int FilterMaximumPopCount;
|
||||
public int FilterPopCount;
|
||||
|
|
@ -46,6 +46,7 @@ public partial class ModEditWindow
|
|||
{
|
||||
Shpk = new ShpkFile(bytes, false);
|
||||
}
|
||||
|
||||
FilePath = filePath;
|
||||
|
||||
Header = $"Shader Package for DirectX {(int)Shpk.DirectXVersion}";
|
||||
|
|
@ -105,13 +106,21 @@ public partial class ModEditWindow
|
|||
_nameSetWithIdsCache.Clear();
|
||||
}
|
||||
|
||||
public void UpdateNameCache()
|
||||
private void UpdateNameCache()
|
||||
{
|
||||
static void CollectResourceNames(Dictionary<uint, Name> nameCache, ShpkFile.Resource[] resources)
|
||||
{
|
||||
foreach (var resource in resources)
|
||||
nameCache.TryAdd(resource.Id, resource.Name);
|
||||
}
|
||||
CollectResourceNames(_nameCache, Shpk.Constants);
|
||||
CollectResourceNames(_nameCache, Shpk.Samplers);
|
||||
CollectResourceNames(_nameCache, Shpk.Textures);
|
||||
CollectResourceNames(_nameCache, Shpk.Uavs);
|
||||
|
||||
CollectKeyNames(_nameCache, Shpk.SystemKeys);
|
||||
CollectKeyNames(_nameCache, Shpk.SceneKeys);
|
||||
CollectKeyNames(_nameCache, Shpk.MaterialKeys);
|
||||
CollectKeyNames(_nameCache, Shpk.SubViewKeys);
|
||||
|
||||
_nameSetCache.Clear();
|
||||
_nameSetWithIdsCache.Clear();
|
||||
return;
|
||||
|
||||
static void CollectKeyNames(Dictionary<uint, Name> nameCache, ShpkFile.Key[] keys)
|
||||
{
|
||||
|
|
@ -128,18 +137,11 @@ public partial class ModEditWindow
|
|||
}
|
||||
}
|
||||
|
||||
CollectResourceNames(_nameCache, Shpk.Constants);
|
||||
CollectResourceNames(_nameCache, Shpk.Samplers);
|
||||
CollectResourceNames(_nameCache, Shpk.Textures);
|
||||
CollectResourceNames(_nameCache, Shpk.Uavs);
|
||||
|
||||
CollectKeyNames(_nameCache, Shpk.SystemKeys);
|
||||
CollectKeyNames(_nameCache, Shpk.SceneKeys);
|
||||
CollectKeyNames(_nameCache, Shpk.MaterialKeys);
|
||||
CollectKeyNames(_nameCache, Shpk.SubViewKeys);
|
||||
|
||||
_nameSetCache.Clear();
|
||||
_nameSetWithIdsCache.Clear();
|
||||
static void CollectResourceNames(Dictionary<uint, Name> nameCache, ShpkFile.Resource[] resources)
|
||||
{
|
||||
foreach (var resource in resources)
|
||||
nameCache.TryAdd(resource.Id, resource.Name);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
|
@ -151,6 +153,7 @@ public partial class ModEditWindow
|
|||
var cache = withIds ? _nameSetWithIdsCache : _nameSetCache;
|
||||
if (cache.TryGetValue(nameSet, out var nameSetStr))
|
||||
return nameSetStr;
|
||||
|
||||
if (withIds)
|
||||
nameSetStr = string.Join(", ", nameSet.Select(id => $"{TryResolveName(id)} (0x{id:X8})"));
|
||||
else
|
||||
|
|
@ -186,7 +189,8 @@ public partial class ModEditWindow
|
|||
var jEnd = ((param.ByteOffset + param.ByteSize - 1) >> 2) & 3;
|
||||
if ((param.ByteOffset & 0x3) != 0 || (param.ByteSize & 0x3) != 0)
|
||||
{
|
||||
MalformedParameters.Add($"ID: {TryResolveName(param.Id)} (0x{param.Id:X8}), offset: 0x{param.ByteOffset:X4}, size: 0x{param.ByteSize:X4}");
|
||||
MalformedParameters.Add(
|
||||
$"ID: {TryResolveName(param.Id)} (0x{param.Id:X8}), offset: 0x{param.ByteOffset:X4}, size: 0x{param.ByteSize:X4}");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -206,7 +210,8 @@ public partial class ModEditWindow
|
|||
var tt =
|
||||
$"{MtrlTab.MaterialParamRangeName(materialParams?.Name ?? string.Empty, param.ByteOffset >> 2, param.ByteSize >> 2).Item1} ({TryResolveName(param.Id)}, 0x{param.Id:X8})";
|
||||
if (component < defaultFloats.Length)
|
||||
tt += $"\n\nDefault value: {defaultFloats[component]} ({defaults[component << 2]:X2} {defaults[(component << 2) | 1]:X2} {defaults[(component << 2) | 2]:X2} {defaults[(component << 2) | 3]:X2})";
|
||||
tt +=
|
||||
$"\n\nDefault value: {defaultFloats[component]} ({defaults[component << 2]:X2} {defaults[(component << 2) | 1]:X2} {defaults[(component << 2) | 2]:X2} {defaults[(component << 2) | 3]:X2})";
|
||||
Matrix[i, j] = (TryResolveName(param.Id).ToString(), tt, (short)idx, 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -265,7 +270,8 @@ public partial class ModEditWindow
|
|||
if (oldStart == linear)
|
||||
newMaterialParamStart = (short)Orphans.Count;
|
||||
|
||||
Orphans.Add(($"{materialParams?.Name ?? ShpkFile.MaterialParamsConstantName}{MtrlTab.MaterialParamName(false, linear)}", linear));
|
||||
Orphans.Add(($"{materialParams?.Name ?? ShpkFile.MaterialParamsConstantName}{MtrlTab.MaterialParamName(false, linear)}",
|
||||
linear));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -407,7 +413,6 @@ public partial class ModEditWindow
|
|||
var unusedSlices = new JArray();
|
||||
|
||||
if (materialParameterUsage.Indices(start, length).Any())
|
||||
{
|
||||
foreach (var (rgStart, rgEnd) in materialParameterUsage.Ranges(start, length, true))
|
||||
{
|
||||
unusedSlices.Add(new JObject
|
||||
|
|
@ -417,14 +422,11 @@ public partial class ModEditWindow
|
|||
["Length"] = rgEnd - rgStart,
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unusedSlices.Add(new JObject
|
||||
{
|
||||
["Type"] = "Hidden",
|
||||
});
|
||||
}
|
||||
|
||||
dkConstants[param.Id.ToString()] = unusedSlices;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue