mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-14 04:34:19 +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 const float ColorTableScalarSize = 65.0f;
|
||||||
|
|
||||||
private int _colorTableSelectedPair = 0;
|
private int _colorTableSelectedPair;
|
||||||
|
|
||||||
private bool DrawColorTable(ColorTable table, ColorDyeTable? dyeTable, bool disabled)
|
private bool DrawColorTable(ColorTable table, ColorDyeTable? dyeTable, bool disabled)
|
||||||
{
|
{
|
||||||
|
|
@ -23,8 +23,6 @@ public partial class MtrlTab
|
||||||
|
|
||||||
private void DrawColorTablePairSelector(ColorTable table, bool disabled)
|
private void DrawColorTablePairSelector(ColorTable table, bool disabled)
|
||||||
{
|
{
|
||||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
|
||||||
using var alignment = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f));
|
|
||||||
var style = ImGui.GetStyle();
|
var style = ImGui.GetStyle();
|
||||||
var itemSpacing = style.ItemSpacing.X;
|
var itemSpacing = style.ItemSpacing.X;
|
||||||
var itemInnerSpacing = style.ItemInnerSpacing.X;
|
var itemInnerSpacing = style.ItemInnerSpacing.X;
|
||||||
|
|
@ -34,14 +32,18 @@ public partial class MtrlTab
|
||||||
var highlighterSize = ImUtf8.CalcIconSize(FontAwesomeIcon.Crosshairs) + framePadding * 2.0f;
|
var highlighterSize = ImUtf8.CalcIconSize(FontAwesomeIcon.Crosshairs) + framePadding * 2.0f;
|
||||||
var spaceWidth = ImUtf8.CalcTextSize(" "u8).X;
|
var spaceWidth = ImUtf8.CalcTextSize(" "u8).X;
|
||||||
var spacePadding = (int)MathF.Ceiling((highlighterSize.X + framePadding.X + itemInnerSpacing) / spaceWidth);
|
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));
|
||||||
for (var i = 0; i < ColorTable.NumRows >> 1; i += 8)
|
for (var i = 0; i < ColorTable.NumRows >> 1; i += 8)
|
||||||
{
|
{
|
||||||
for (var j = 0; j < 8; ++j)
|
for (var j = 0; j < 8; ++j)
|
||||||
{
|
{
|
||||||
var pairIndex = i + 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;
|
_colorTableSelectedPair = pairIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,10 +83,8 @@ public partial class MtrlTab
|
||||||
{
|
{
|
||||||
var retA = false;
|
var retA = false;
|
||||||
var retB = false;
|
var retB = false;
|
||||||
ref var rowA = ref table[_colorTableSelectedPair << 1];
|
var dyeA = dyeTable?[_colorTableSelectedPair << 1] ?? default;
|
||||||
ref var rowB = ref table[(_colorTableSelectedPair << 1) | 1];
|
var dyeB = dyeTable?[(_colorTableSelectedPair << 1) | 1] ?? default;
|
||||||
var dyeA = dyeTable != null ? dyeTable[_colorTableSelectedPair << 1] : default;
|
|
||||||
var dyeB = dyeTable != null ? dyeTable[(_colorTableSelectedPair << 1) | 1] : default;
|
|
||||||
var previewDyeA = _stainService.GetStainCombo(dyeA.Channel).CurrentSelection.Key;
|
var previewDyeA = _stainService.GetStainCombo(dyeA.Channel).CurrentSelection.Key;
|
||||||
var previewDyeB = _stainService.GetStainCombo(dyeB.Channel).CurrentSelection.Key;
|
var previewDyeB = _stainService.GetStainCombo(dyeB.Channel).CurrentSelection.Key;
|
||||||
var dyePackA = _stainService.GudStmFile.GetValueOrNull(dyeA.Template, previewDyeA);
|
var dyePackA = _stainService.GudStmFile.GetValueOrNull(dyeA.Template, previewDyeA);
|
||||||
|
|
@ -108,67 +108,95 @@ public partial class MtrlTab
|
||||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||||
{
|
{
|
||||||
using var dis = ImRaii.Disabled(disabled);
|
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);
|
retA |= DrawColors(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||||
|
}
|
||||||
|
|
||||||
columns.Next();
|
columns.Next();
|
||||||
using (var id = ImUtf8.PushId("ColorsB"u8))
|
using (ImUtf8.PushId("ColorsB"u8))
|
||||||
|
{
|
||||||
retB |= DrawColors(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
retB |= DrawColors(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DrawHeader(" Physical Parameters"u8);
|
DrawHeader(" Physical Parameters"u8);
|
||||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||||
{
|
{
|
||||||
using var dis = ImRaii.Disabled(disabled);
|
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);
|
retA |= DrawPbr(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||||
|
}
|
||||||
|
|
||||||
columns.Next();
|
columns.Next();
|
||||||
using (var id = ImUtf8.PushId("PbrB"u8))
|
using (ImUtf8.PushId("PbrB"u8))
|
||||||
|
{
|
||||||
retB |= DrawPbr(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
retB |= DrawPbr(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DrawHeader(" Sheen Layer Parameters"u8);
|
DrawHeader(" Sheen Layer Parameters"u8);
|
||||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||||
{
|
{
|
||||||
using var dis = ImRaii.Disabled(disabled);
|
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);
|
retA |= DrawSheen(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||||
|
}
|
||||||
|
|
||||||
columns.Next();
|
columns.Next();
|
||||||
using (var id = ImUtf8.PushId("SheenB"u8))
|
using (ImUtf8.PushId("SheenB"u8))
|
||||||
|
{
|
||||||
retB |= DrawSheen(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
retB |= DrawSheen(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DrawHeader(" Pair Blending"u8);
|
DrawHeader(" Pair Blending"u8);
|
||||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||||
{
|
{
|
||||||
using var dis = ImRaii.Disabled(disabled);
|
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);
|
retA |= DrawBlending(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||||
|
}
|
||||||
|
|
||||||
columns.Next();
|
columns.Next();
|
||||||
using (var id = ImUtf8.PushId("BlendingB"u8))
|
using (ImUtf8.PushId("BlendingB"u8))
|
||||||
|
{
|
||||||
retB |= DrawBlending(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
retB |= DrawBlending(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DrawHeader(" Material Template"u8);
|
DrawHeader(" Material Template"u8);
|
||||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||||
{
|
{
|
||||||
using var dis = ImRaii.Disabled(disabled);
|
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);
|
retA |= DrawTemplate(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||||
|
}
|
||||||
|
|
||||||
columns.Next();
|
columns.Next();
|
||||||
using (var id = ImUtf8.PushId("TemplateB"u8))
|
using (ImUtf8.PushId("TemplateB"u8))
|
||||||
|
{
|
||||||
retB |= DrawTemplate(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
retB |= DrawTemplate(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (dyeTable != null)
|
if (dyeTable != null)
|
||||||
{
|
{
|
||||||
DrawHeader(" Dye Properties"u8);
|
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 var dis = ImRaii.Disabled(disabled);
|
||||||
using (var id = ImUtf8.PushId("DyeA"u8))
|
using (ImUtf8.PushId("DyeA"u8))
|
||||||
|
{
|
||||||
retA |= DrawDye(dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
retA |= DrawDye(dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||||
|
}
|
||||||
|
|
||||||
columns.Next();
|
columns.Next();
|
||||||
using (var id = ImUtf8.PushId("DyeB"u8))
|
using (ImUtf8.PushId("DyeB"u8))
|
||||||
|
{
|
||||||
retB |= DrawDye(dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
retB |= DrawDye(dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -177,12 +205,17 @@ public partial class MtrlTab
|
||||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||||
{
|
{
|
||||||
using var dis = ImRaii.Disabled(disabled);
|
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);
|
retA |= DrawFurther(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||||
|
}
|
||||||
|
|
||||||
columns.Next();
|
columns.Next();
|
||||||
using (var id = ImUtf8.PushId("FurtherB"u8))
|
using (ImUtf8.PushId("FurtherB"u8))
|
||||||
|
{
|
||||||
retB |= DrawFurther(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
retB |= DrawFurther(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (retA)
|
if (retA)
|
||||||
UpdateColorTableRowPreview(_colorTableSelectedPair << 1);
|
UpdateColorTableRowPreview(_colorTableSelectedPair << 1);
|
||||||
|
|
@ -202,11 +235,14 @@ public partial class MtrlTab
|
||||||
|
|
||||||
private static bool DrawColors(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
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];
|
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,
|
ret |= CtColorPicker("Diffuse Color"u8, default, row.DiffuseColor,
|
||||||
c => table[rowIdx].DiffuseColor = c);
|
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)
|
private static bool DrawBlending(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
||||||
{
|
{
|
||||||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
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 isRowB = (rowIdx & 1) != 0;
|
||||||
|
|
||||||
var ret = false;
|
var ret = false;
|
||||||
ref var row = ref table[rowIdx];
|
ref var row = ref table[rowIdx];
|
||||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
var dye = dyeTable?[rowIdx] ?? default;
|
||||||
|
|
||||||
ImGui.SetNextItemWidth(scalarSize);
|
ImGui.SetNextItemWidth(scalarSize);
|
||||||
ret |= CtDragHalf(isRowB ? "Field #19"u8 : "Anisotropy Degree"u8, default, row.Anisotropy, "%.2f"u8, 0.0f, HalfMaxValue, 0.1f,
|
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)
|
if (dyeTable != null)
|
||||||
{
|
{
|
||||||
ImGui.SameLine(dyeOffset);
|
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);
|
b => dyeTable[rowIdx].Anisotropy = b);
|
||||||
ImUtf8.SameLineInner();
|
ImUtf8.SameLineInner();
|
||||||
ImGui.SetNextItemWidth(scalarSize);
|
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;
|
return ret;
|
||||||
|
|
@ -276,11 +318,11 @@ public partial class MtrlTab
|
||||||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
||||||
var itemSpacing = ImGui.GetStyle().ItemSpacing.X;
|
var itemSpacing = ImGui.GetStyle().ItemSpacing.X;
|
||||||
var dyeOffset = ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight() - scalarSize - 64.0f;
|
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];
|
ref var row = ref table[rowIdx];
|
||||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
var dye = dyeTable?[rowIdx] ?? default;
|
||||||
|
|
||||||
ImGui.SetNextItemWidth(scalarSize);
|
ImGui.SetNextItemWidth(scalarSize);
|
||||||
ret |= CtDragScalar("Shader ID"u8, default, row.ShaderId, "%d"u8, (ushort)0, (ushort)255, 0.25f,
|
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.SetCursorScreenPos(ImGui.GetCursorScreenPos() with { Y = cursor.Y });
|
||||||
ImGui.SetNextItemWidth(scalarSize + itemSpacing + 64.0f);
|
ImGui.SetNextItemWidth(scalarSize + itemSpacing + 64.0f);
|
||||||
using var dis = ImRaii.Disabled();
|
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.Dummy(new Vector2(64.0f, 0.0f));
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.SetNextItemWidth(scalarSize);
|
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));
|
v => table[rowIdx].SphereMapMask = (Half)(v * 0.01f));
|
||||||
if (dyeTable != null)
|
if (dyeTable != null)
|
||||||
{
|
{
|
||||||
|
|
@ -337,9 +381,10 @@ public partial class MtrlTab
|
||||||
ImUtf8.SameLineInner();
|
ImUtf8.SameLineInner();
|
||||||
ImUtf8.Text("Tile"u8);
|
ImUtf8.Text("Tile"u8);
|
||||||
|
|
||||||
ImGui.SameLine(subcolWidth);
|
ImGui.SameLine(subColWidth);
|
||||||
ImGui.SetCursorScreenPos(ImGui.GetCursorScreenPos() with { Y = cursorPos.Y + (lineHeight - rightLineHeight) * 0.5f, });
|
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))
|
using (ImUtf8.Child("###TileProperties"u8,
|
||||||
|
new Vector2(ImGui.GetContentRegionAvail().X, float.Lerp(rightLineHeight, lineHeight, 0.5f))))
|
||||||
{
|
{
|
||||||
ImGui.Dummy(new Vector2(scalarSize, 0.0f));
|
ImGui.Dummy(new Vector2(scalarSize, 0.0f));
|
||||||
ImUtf8.SameLineInner();
|
ImUtf8.SameLineInner();
|
||||||
|
|
@ -350,7 +395,8 @@ public partial class MtrlTab
|
||||||
ret |= CtTileTransformMatrix(row.TileTransform, scalarSize, true,
|
ret |= CtTileTransformMatrix(row.TileTransform, scalarSize, true,
|
||||||
m => table[rowIdx].TileTransform = m);
|
m => table[rowIdx].TileTransform = m);
|
||||||
ImUtf8.SameLineInner();
|
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);
|
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)
|
private static bool DrawPbr(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
||||||
{
|
{
|
||||||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
||||||
var subcolWidth = CalculateSubcolumnWidth(2) + ImGui.GetStyle().ItemSpacing.X;
|
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 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];
|
ref var row = ref table[rowIdx];
|
||||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
var dye = dyeTable?[rowIdx] ?? default;
|
||||||
|
|
||||||
ImGui.SetNextItemWidth(scalarSize);
|
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));
|
v => table[rowIdx].Roughness = (Half)(v * 0.01f));
|
||||||
if (dyeTable != null)
|
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);
|
CtDragScalar("##dyePreviewRoughness"u8, "Dye Preview for Roughness"u8, (float?)dyePack?.Roughness * 100.0f, "%.0f%%"u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.SameLine(subcolWidth);
|
ImGui.SameLine(subColWidth);
|
||||||
ImGui.SetNextItemWidth(scalarSize);
|
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));
|
v => table[rowIdx].Metalness = (Half)(v * 0.01f));
|
||||||
if (dyeTable != null)
|
if (dyeTable != null)
|
||||||
{
|
{
|
||||||
ImGui.SameLine(subcolWidth + dyeOffset);
|
ImGui.SameLine(subColWidth + dyeOffset);
|
||||||
ret |= CtApplyStainCheckbox("##dyeMetalness"u8, "Apply Metalness on Dye"u8, dye.Metalness,
|
ret |= CtApplyStainCheckbox("##dyeMetalness"u8, "Apply Metalness on Dye"u8, dye.Metalness,
|
||||||
b => dyeTable[rowIdx].Metalness = b);
|
b => dyeTable[rowIdx].Metalness = b);
|
||||||
ImUtf8.SameLineInner();
|
ImUtf8.SameLineInner();
|
||||||
|
|
@ -400,12 +452,16 @@ public partial class MtrlTab
|
||||||
private static bool DrawSheen(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
private static bool DrawSheen(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
||||||
{
|
{
|
||||||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
||||||
var subcolWidth = CalculateSubcolumnWidth(2) + ImGui.GetStyle().ItemSpacing.X;
|
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 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];
|
ref var row = ref table[rowIdx];
|
||||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
var dye = dyeTable?[rowIdx] ?? default;
|
||||||
|
|
||||||
ImGui.SetNextItemWidth(scalarSize);
|
ImGui.SetNextItemWidth(scalarSize);
|
||||||
ret |= CtDragScalar("Sheen"u8, default, (float)row.SheenRate * 100.0f, "%.0f%%"u8, HalfMinValue * 100.0f, HalfMaxValue * 100.0f, 1.0f,
|
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);
|
CtDragScalar("##dyePreviewSheenRate"u8, "Dye Preview for Sheen"u8, (float?)dyePack?.SheenRate * 100.0f, "%.0f%%"u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.SameLine(subcolWidth);
|
ImGui.SameLine(subColWidth);
|
||||||
ImGui.SetNextItemWidth(scalarSize);
|
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));
|
v => table[rowIdx].SheenTintRate = (Half)(v * 0.01f));
|
||||||
if (dyeTable != null)
|
if (dyeTable != null)
|
||||||
{
|
{
|
||||||
ImGui.SameLine(subcolWidth + dyeOffset);
|
ImGui.SameLine(subColWidth + dyeOffset);
|
||||||
ret |= CtApplyStainCheckbox("##dyeSheenTintRate"u8, "Apply Sheen Tint on Dye"u8, dye.SheenTintRate,
|
ret |= CtApplyStainCheckbox("##dyeSheenTintRate"u8, "Apply Sheen Tint on Dye"u8, dye.SheenTintRate,
|
||||||
b => dyeTable[rowIdx].SheenTintRate = b);
|
b => dyeTable[rowIdx].SheenTintRate = b);
|
||||||
ImUtf8.SameLineInner();
|
ImUtf8.SameLineInner();
|
||||||
|
|
@ -435,7 +492,8 @@ public partial class MtrlTab
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.SetNextItemWidth(scalarSize);
|
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));
|
v => table[rowIdx].SheenAperture = (Half)(100.0f / v));
|
||||||
if (dyeTable != null)
|
if (dyeTable != null)
|
||||||
{
|
{
|
||||||
|
|
@ -444,7 +502,8 @@ public partial class MtrlTab
|
||||||
b => dyeTable[rowIdx].SheenAperture = b);
|
b => dyeTable[rowIdx].SheenAperture = b);
|
||||||
ImUtf8.SameLineInner();
|
ImUtf8.SameLineInner();
|
||||||
ImGui.SetNextItemWidth(scalarSize);
|
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;
|
return ret;
|
||||||
|
|
@ -453,12 +512,16 @@ public partial class MtrlTab
|
||||||
private static bool DrawFurther(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
private static bool DrawFurther(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
||||||
{
|
{
|
||||||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
||||||
var subcolWidth = CalculateSubcolumnWidth(2) + ImGui.GetStyle().ItemSpacing.X;
|
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 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];
|
ref var row = ref table[rowIdx];
|
||||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
var dye = dyeTable?[rowIdx] ?? default;
|
||||||
|
|
||||||
ImGui.SetNextItemWidth(scalarSize);
|
ImGui.SetNextItemWidth(scalarSize);
|
||||||
ret |= CtDragHalf("Field #11"u8, default, row.Scalar11, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
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,
|
ret |= CtDragHalf("Field #3"u8, default, row.Scalar3, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||||
v => table[rowIdx].Scalar3 = v);
|
v => table[rowIdx].Scalar3 = v);
|
||||||
|
|
||||||
ImGui.SameLine(subcolWidth);
|
ImGui.SameLine(subColWidth);
|
||||||
ImGui.SetNextItemWidth(scalarSize);
|
ImGui.SetNextItemWidth(scalarSize);
|
||||||
ret |= CtDragHalf("Field #7"u8, default, row.Scalar7, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
ret |= CtDragHalf("Field #7"u8, default, row.Scalar7, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||||
v => table[rowIdx].Scalar7 = v);
|
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,
|
ret |= CtDragHalf("Field #15"u8, default, row.Scalar15, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||||
v => table[rowIdx].Scalar15 = v);
|
v => table[rowIdx].Scalar15 = v);
|
||||||
|
|
||||||
ImGui.SameLine(subcolWidth);
|
ImGui.SameLine(subColWidth);
|
||||||
ImGui.SetNextItemWidth(scalarSize);
|
ImGui.SetNextItemWidth(scalarSize);
|
||||||
ret |= CtDragHalf("Field #17"u8, default, row.Scalar17, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
ret |= CtDragHalf("Field #17"u8, default, row.Scalar17, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||||
v => table[rowIdx].Scalar17 = v);
|
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,
|
ret |= CtDragHalf("Field #20"u8, default, row.Scalar20, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||||
v => table[rowIdx].Scalar20 = v);
|
v => table[rowIdx].Scalar20 = v);
|
||||||
|
|
||||||
ImGui.SameLine(subcolWidth);
|
ImGui.SameLine(subColWidth);
|
||||||
ImGui.SetNextItemWidth(scalarSize);
|
ImGui.SetNextItemWidth(scalarSize);
|
||||||
ret |= CtDragHalf("Field #22"u8, default, row.Scalar22, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
ret |= CtDragHalf("Field #22"u8, default, row.Scalar22, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||||
v => table[rowIdx].Scalar22 = v);
|
v => table[rowIdx].Scalar22 = v);
|
||||||
|
|
@ -513,7 +576,7 @@ public partial class MtrlTab
|
||||||
{
|
{
|
||||||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
||||||
var applyButtonWidth = ImUtf8.CalcTextSize("Apply Preview Dye"u8).X + ImGui.GetStyle().FramePadding.X * 2.0f;
|
var applyButtonWidth = ImUtf8.CalcTextSize("Apply Preview Dye"u8).X + ImGui.GetStyle().FramePadding.X * 2.0f;
|
||||||
var subcolWidth = CalculateSubcolumnWidth(2, applyButtonWidth);
|
var subColWidth = CalculateSubColumnWidth(2, applyButtonWidth);
|
||||||
|
|
||||||
var ret = false;
|
var ret = false;
|
||||||
ref var dye = ref dyeTable[rowIdx];
|
ref var dye = ref dyeTable[rowIdx];
|
||||||
|
|
@ -521,7 +584,7 @@ public partial class MtrlTab
|
||||||
ImGui.SetNextItemWidth(scalarSize);
|
ImGui.SetNextItemWidth(scalarSize);
|
||||||
ret |= CtDragScalar("Dye Channel"u8, default, dye.Channel + 1, "%d"u8, 1, StainService.ChannelCount, 0.1f,
|
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));
|
value => dyeTable[rowIdx].Channel = (byte)(Math.Clamp(value, 1, StainService.ChannelCount) - 1));
|
||||||
ImGui.SameLine(subcolWidth);
|
ImGui.SameLine(subColWidth);
|
||||||
ImGui.SetNextItemWidth(scalarSize);
|
ImGui.SetNextItemWidth(scalarSize);
|
||||||
if (_stainService.GudTemplateCombo.Draw("##dyeTemplate", dye.Template.ToString(), string.Empty,
|
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))
|
||||||
|
|
@ -529,17 +592,16 @@ public partial class MtrlTab
|
||||||
dye.Template = _stainService.LegacyTemplateCombo.CurrentSelection;
|
dye.Template = _stainService.LegacyTemplateCombo.CurrentSelection;
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImUtf8.SameLineInner();
|
ImUtf8.SameLineInner();
|
||||||
ImUtf8.Text("Dye Template"u8);
|
ImUtf8.Text("Dye Template"u8);
|
||||||
ImGui.SameLine(ImGui.GetContentRegionAvail().X - applyButtonWidth + ImGui.GetStyle().ItemSpacing.X);
|
ImGui.SameLine(ImGui.GetContentRegionAvail().X - applyButtonWidth + ImGui.GetStyle().ItemSpacing.X);
|
||||||
using var dis = ImRaii.Disabled(!dyePack.HasValue);
|
using var dis = ImRaii.Disabled(!dyePack.HasValue);
|
||||||
if (ImUtf8.Button("Apply Preview Dye"u8))
|
if (ImUtf8.Button("Apply Preview Dye"u8))
|
||||||
{
|
|
||||||
ret |= Mtrl.ApplyDyeToRow(_stainService.GudStmFile, [
|
ret |= Mtrl.ApplyDyeToRow(_stainService.GudStmFile, [
|
||||||
_stainService.StainCombo1.CurrentSelection.Key,
|
_stainService.StainCombo1.CurrentSelection.Key,
|
||||||
_stainService.StainCombo2.CurrentSelection.Key,
|
_stainService.StainCombo2.CurrentSelection.Key,
|
||||||
], rowIdx);
|
], rowIdx);
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -554,9 +616,9 @@ public partial class MtrlTab
|
||||||
ImGui.TextUnformatted(text);
|
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;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,11 @@ public partial class MtrlTab
|
||||||
|
|
||||||
private bool DrawColorTableSection(bool disabled)
|
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;
|
return false;
|
||||||
|
|
||||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||||
if (!ImGui.CollapsingHeader("Color Table", ImGuiTreeNodeFlags.DefaultOpen))
|
if (!ImUtf8.CollapsingHeader("Color Table"u8, ImGuiTreeNodeFlags.DefaultOpen))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ColorTableCopyAllClipboardButton();
|
ColorTableCopyAllClipboardButton();
|
||||||
|
|
@ -35,7 +35,7 @@ public partial class MtrlTab
|
||||||
if (!disabled)
|
if (!disabled)
|
||||||
{
|
{
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.Dummy(ImGuiHelpers.ScaledVector2(20, 0));
|
ImUtf8.IconDummy();
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ret |= ColorTableDyeableCheckbox();
|
ret |= ColorTableDyeableCheckbox();
|
||||||
}
|
}
|
||||||
|
|
@ -43,7 +43,7 @@ public partial class MtrlTab
|
||||||
if (Mtrl.DyeTable != null)
|
if (Mtrl.DyeTable != null)
|
||||||
{
|
{
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.Dummy(ImGuiHelpers.ScaledVector2(20, 0));
|
ImUtf8.IconDummy();
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ret |= DrawPreviewDye(disabled);
|
ret |= DrawPreviewDye(disabled);
|
||||||
}
|
}
|
||||||
|
|
@ -51,7 +51,8 @@ public partial class MtrlTab
|
||||||
ret |= Mtrl.Table switch
|
ret |= Mtrl.Table switch
|
||||||
{
|
{
|
||||||
LegacyColorTable legacyTable => DrawLegacyColorTable(legacyTable, Mtrl.DyeTable as LegacyColorDyeTable, disabled),
|
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 when Mtrl.ShaderPackage.Name is "characterlegacy.shpk" => DrawLegacyColorTable(table,
|
||||||
|
Mtrl.DyeTable as ColorDyeTable, disabled),
|
||||||
ColorTable table => DrawColorTable(table, Mtrl.DyeTable as ColorDyeTable, disabled),
|
ColorTable table => DrawColorTable(table, Mtrl.DyeTable as ColorDyeTable, disabled),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
@ -64,7 +65,7 @@ public partial class MtrlTab
|
||||||
if (Mtrl.Table == null)
|
if (Mtrl.Table == null)
|
||||||
return;
|
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;
|
return;
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -178,16 +179,18 @@ public partial class MtrlTab
|
||||||
private bool ColorTableDyeableCheckbox()
|
private bool ColorTableDyeableCheckbox()
|
||||||
{
|
{
|
||||||
var dyeable = Mtrl.DyeTable != null;
|
var dyeable = Mtrl.DyeTable != null;
|
||||||
var ret = ImGui.Checkbox("Dyeable", ref dyeable);
|
var ret = ImUtf8.Checkbox("Dyeable"u8, ref dyeable);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
Mtrl.DyeTable = dyeable ? Mtrl.Table switch
|
Mtrl.DyeTable = dyeable
|
||||||
|
? Mtrl.Table switch
|
||||||
{
|
{
|
||||||
ColorTable => new ColorDyeTable(),
|
ColorTable => new ColorDyeTable(),
|
||||||
LegacyColorTable => new LegacyColorDyeTable(),
|
LegacyColorTable => new LegacyColorDyeTable(),
|
||||||
_ => null,
|
_ => null,
|
||||||
} : null;
|
}
|
||||||
|
: null;
|
||||||
UpdateColorTablePreview();
|
UpdateColorTablePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -227,12 +230,13 @@ public partial class MtrlTab
|
||||||
|
|
||||||
private void ColorTableHighlightButton(int pairIdx, bool disabled)
|
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,
|
ImUtf8.IconButton(FontAwesomeIcon.Crosshairs,
|
||||||
ImGui.GetFrameHeight() * Vector2.One, disabled || ColorTablePreviewers.Count == 0);
|
"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())
|
if (ImGui.IsItemHovered())
|
||||||
HighlightColorTablePair(pairIdx);
|
HighlightColorTablePair(pairIdx);
|
||||||
else if (HighlightedColorTablePair == pairIdx)
|
else if (_highlightedColorTablePair == pairIdx)
|
||||||
CancelColorTableHighlight();
|
CancelColorTableHighlight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -244,7 +248,9 @@ public partial class MtrlTab
|
||||||
var borderColor = ImGui.GetColorU32(ImGuiCol.Border);
|
var borderColor = ImGui.GetColorU32(ImGuiCol.Border);
|
||||||
var drawList = ImGui.GetWindowDrawList();
|
var drawList = ImGui.GetWindowDrawList();
|
||||||
if (topColor == bottomColor)
|
if (topColor == bottomColor)
|
||||||
|
{
|
||||||
drawList.AddRectFilled(rcMin, rcMax, topColor, frameRounding, ImDrawFlags.RoundCornersDefault);
|
drawList.AddRectFilled(rcMin, rcMax, topColor, frameRounding, ImDrawFlags.RoundCornersDefault);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
drawList.AddRectFilled(
|
drawList.AddRectFilled(
|
||||||
|
|
@ -258,10 +264,12 @@ public partial class MtrlTab
|
||||||
rcMin with { Y = float.Lerp(rcMin.Y, rcMax.Y, 2.0f / 3) }, rcMax,
|
rcMin with { Y = float.Lerp(rcMin.Y, rcMax.Y, 2.0f / 3) }, rcMax,
|
||||||
bottomColor, frameRounding, ImDrawFlags.RoundCornersBottomLeft | ImDrawFlags.RoundCornersBottomRight);
|
bottomColor, frameRounding, ImDrawFlags.RoundCornersBottomLeft | ImDrawFlags.RoundCornersBottomRight);
|
||||||
}
|
}
|
||||||
|
|
||||||
drawList.AddRect(rcMin, rcMax, borderColor, frameRounding, ImDrawFlags.RoundCornersDefault, frameThickness);
|
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 ret = false;
|
||||||
var inputSqrt = PseudoSqrtRgb((Vector3)current);
|
var inputSqrt = PseudoSqrtRgb((Vector3)current);
|
||||||
|
|
@ -291,10 +299,13 @@ public partial class MtrlTab
|
||||||
return ret;
|
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)
|
if (current.HasValue)
|
||||||
|
{
|
||||||
CtColorPicker(label, description, current.Value, Nop, letter);
|
CtColorPicker(label, description, current.Value, Nop, letter);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var tmp = Vector4.Zero;
|
var tmp = Vector4.Zero;
|
||||||
|
|
@ -329,30 +340,36 @@ public partial class MtrlTab
|
||||||
return true;
|
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);
|
var result = ImUtf8.DragScalar(label, ref tmp, format, min, max, speed);
|
||||||
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, description);
|
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, description);
|
||||||
if (!result)
|
if (!result)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var newValue = (Half)tmp;
|
var newValue = (Half)tmp;
|
||||||
if (newValue == value)
|
if (newValue == value)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
setter(newValue);
|
setter(newValue);
|
||||||
return true;
|
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);
|
var result = ImUtf8.DragScalar(label, ref tmp, format, min, max, speed);
|
||||||
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, description);
|
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, description);
|
||||||
if (!result)
|
if (!result)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var newValue = (Half)tmp;
|
var newValue = (Half)tmp;
|
||||||
if (newValue == value)
|
if (newValue == value)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
value = newValue;
|
value = newValue;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -365,29 +382,34 @@ public partial class MtrlTab
|
||||||
CtDragHalf(label, description, valueOrDefault, value.HasValue ? format : "-"u8, floatValue, floatValue, 0.0f, Nop);
|
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);
|
var result = ImUtf8.DragScalar(label, ref tmp, format, min, max, speed);
|
||||||
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, description);
|
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, description);
|
||||||
if (!result || tmp == value)
|
if (!result || tmp == value)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
setter(tmp);
|
setter(tmp);
|
||||||
return true;
|
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);
|
var result = ImUtf8.DragScalar(label, ref tmp, format, min, max, speed);
|
||||||
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, description);
|
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, description);
|
||||||
if (!result || tmp == value)
|
if (!result || tmp == value)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
value = tmp;
|
value = tmp;
|
||||||
return true;
|
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();
|
using var _ = ImRaii.Disabled();
|
||||||
var valueOrDefault = value ?? T.Zero;
|
var valueOrDefault = value ?? T.Zero;
|
||||||
|
|
@ -398,14 +420,17 @@ public partial class MtrlTab
|
||||||
{
|
{
|
||||||
if (!_materialTemplatePickers.DrawTileIndexPicker(label, description, ref value, compact))
|
if (!_materialTemplatePickers.DrawTileIndexPicker(label, description, ref value, compact))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
setter(value);
|
setter(value);
|
||||||
return true;
|
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))
|
if (!_materialTemplatePickers.DrawSphereMapIndexPicker(label, description, ref value, compact))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
setter(value);
|
setter(value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -430,6 +455,7 @@ public partial class MtrlTab
|
||||||
ret |= CtDragHalf("##TileTransformVU"u8, "Tile Skew V"u8, ref tmp.VU, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f);
|
ret |= CtDragHalf("##TileTransformVU"u8, "Tile Skew V"u8, ref tmp.VU, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f);
|
||||||
if (!ret || tmp == value)
|
if (!ret || tmp == value)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
setter(tmp);
|
setter(tmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -464,6 +490,7 @@ public partial class MtrlTab
|
||||||
ret = scaleXChanged | scaleYChanged | rotationChanged | shearChanged;
|
ret = scaleXChanged | scaleYChanged | rotationChanged | shearChanged;
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (_pinnedTileTransform.HasValue)
|
if (_pinnedTileTransform.HasValue)
|
||||||
{
|
{
|
||||||
var (pinScale, pinRotation, pinShear) = _pinnedTileTransform.Value;
|
var (pinScale, pinRotation, pinShear) = _pinnedTileTransform.Value;
|
||||||
|
|
@ -476,11 +503,14 @@ public partial class MtrlTab
|
||||||
if (!shearChanged)
|
if (!shearChanged)
|
||||||
shear = pinShear;
|
shear = pinShear;
|
||||||
}
|
}
|
||||||
|
|
||||||
var newValue = HalfMatrix2x2.Compose(scale, rotation * MathF.PI / 180.0f, shear * MathF.PI / 180.0f);
|
var newValue = HalfMatrix2x2.Compose(scale, rotation * MathF.PI / 180.0f, shear * MathF.PI / 180.0f);
|
||||||
if (newValue == value)
|
if (newValue == value)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
setter(newValue);
|
setter(newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ public partial class MtrlTab
|
||||||
|
|
||||||
Constants.Clear();
|
Constants.Clear();
|
||||||
string mpPrefix;
|
string mpPrefix;
|
||||||
if (AssociatedShpk == null)
|
if (_associatedShpk == null)
|
||||||
{
|
{
|
||||||
mpPrefix = MaterialParamsConstantName.Value!;
|
mpPrefix = MaterialParamsConstantName.Value!;
|
||||||
var fcGroup = FindOrAddGroup(Constants, "Further Constants");
|
var fcGroup = FindOrAddGroup(Constants, "Further Constants");
|
||||||
|
|
@ -51,12 +51,12 @@ public partial class MtrlTab
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mpPrefix = AssociatedShpk.GetConstantById(MaterialParamsConstantId)?.Name ?? MaterialParamsConstantName.Value!;
|
mpPrefix = _associatedShpk.GetConstantById(MaterialParamsConstantId)?.Name ?? MaterialParamsConstantName.Value!;
|
||||||
var autoNameMaxLength = Math.Max(Names.LongestKnownNameLength, mpPrefix.Length + 8);
|
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 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 values = Mtrl.GetConstantValue<byte>(constant);
|
||||||
var handledElements = new IndexSet(values.Length, false);
|
var handledElements = new IndexSet(values.Length, false);
|
||||||
|
|
||||||
|
|
@ -86,7 +86,6 @@ public partial class MtrlTab
|
||||||
foreach (var (start, end) in handledElements.Ranges(complement: true))
|
foreach (var (start, end) in handledElements.Ranges(complement: true))
|
||||||
{
|
{
|
||||||
if (start == 0 && end == values.Length && end - start <= 16)
|
if (start == 0 && end == values.Length && end - start <= 16)
|
||||||
{
|
|
||||||
if (name.Value != null)
|
if (name.Value != null)
|
||||||
{
|
{
|
||||||
fcGroup.Add((
|
fcGroup.Add((
|
||||||
|
|
@ -94,7 +93,6 @@ public partial class MtrlTab
|
||||||
constantIndex, 0..values.Length, string.Empty, true, DefaultConstantEditorFor(name)));
|
constantIndex, 0..values.Length, string.Empty, true, DefaultConstantEditorFor(name)));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ((shpkConstant.ByteOffset & 0x3) == 0 && (shpkConstant.ByteSize & 0x3) == 0)
|
if ((shpkConstant.ByteOffset & 0x3) == 0 && (shpkConstant.ByteSize & 0x3) == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -105,7 +103,8 @@ public partial class MtrlTab
|
||||||
var rangeEnd = Math.Min(i + 16, end);
|
var rangeEnd = Math.Min(i + 16, end);
|
||||||
if (rangeEnd > rangeStart)
|
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((
|
fcGroup.Add((
|
||||||
$"{autoName.PadRight(autoNameMaxLength)} (0x{shpkConstant.Id:X8})",
|
$"{autoName.PadRight(autoNameMaxLength)} (0x{shpkConstant.Id:X8})",
|
||||||
constantIndex, rangeStart..rangeEnd, string.Empty, true, DefaultConstantEditorFor(name)));
|
constantIndex, rangeStart..rangeEnd, string.Empty, true, DefaultConstantEditorFor(name)));
|
||||||
|
|
@ -116,7 +115,8 @@ public partial class MtrlTab
|
||||||
{
|
{
|
||||||
for (var i = start; i < end; i += 16)
|
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)));
|
DefaultConstantEditorFor(name)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -178,10 +178,11 @@ public partial class MtrlTab
|
||||||
ret = true;
|
ret = true;
|
||||||
SetMaterialParameter(constant.Id, slice.Start, buffer[slice]);
|
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 defaultValue = IsValid(slice, defaultConstantValue.Length) ? defaultConstantValue[slice] : [];
|
||||||
var canReset = AssociatedShpk?.MaterialParamsDefaults != null
|
var canReset = _associatedShpk?.MaterialParamsDefaults != null
|
||||||
? defaultValue.Length > 0 && !defaultValue.SequenceEqual(buffer[slice])
|
? defaultValue.Length > 0 && !defaultValue.SequenceEqual(buffer[slice])
|
||||||
: buffer[slice].ContainsAnyExcept((byte)0);
|
: buffer[slice].ContainsAnyExcept((byte)0);
|
||||||
ImUtf8.SameLineInner();
|
ImUtf8.SameLineInner();
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using JetBrains.Annotations;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using OtterGui.Text.Widget.Editors;
|
using OtterGui.Text.Widget.Editors;
|
||||||
using Penumbra.String.Classes;
|
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
|
private T? TryGetShpkDevkitData<T>(string category, uint? id, bool mayVary) where T : class
|
||||||
=> TryGetShpkDevkitData<T>(AssociatedShpkDevkit, LoadedShpkDevkitPathName, category, id, mayVary)
|
=> TryGetShpkDevkitData<T>(_associatedShpkDevkit, _loadedShpkDevkitPathName, category, id, mayVary)
|
||||||
?? TryGetShpkDevkitData<T>(AssociatedBaseDevkit, LoadedBaseDevkitPathName, 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
|
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"]!
|
var selector = BuildSelector(data!["Vary"]!
|
||||||
.Select(key => (uint)key)
|
.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()]!;
|
var index = (int)data["Selectors"]![selector.ToString()]!;
|
||||||
data = data["Items"]![index];
|
data = data["Items"]![index];
|
||||||
}
|
}
|
||||||
|
|
@ -62,12 +63,14 @@ public partial class MtrlTab
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
private sealed class DevkitShaderKeyValue
|
private sealed class DevkitShaderKeyValue
|
||||||
{
|
{
|
||||||
public string Label = string.Empty;
|
public string Label = string.Empty;
|
||||||
public string Description = string.Empty;
|
public string Description = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
private sealed class DevkitShaderKey
|
private sealed class DevkitShaderKey
|
||||||
{
|
{
|
||||||
public string Label = string.Empty;
|
public string Label = string.Empty;
|
||||||
|
|
@ -75,6 +78,7 @@ public partial class MtrlTab
|
||||||
public Dictionary<uint, DevkitShaderKeyValue> Values = [];
|
public Dictionary<uint, DevkitShaderKeyValue> Values = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
private sealed class DevkitSampler
|
private sealed class DevkitSampler
|
||||||
{
|
{
|
||||||
public string Label = string.Empty;
|
public string Label = string.Empty;
|
||||||
|
|
@ -86,10 +90,12 @@ public partial class MtrlTab
|
||||||
{
|
{
|
||||||
Hidden = -1,
|
Hidden = -1,
|
||||||
Float = 0,
|
Float = 0,
|
||||||
|
|
||||||
/// <summary> Integer encoded as a float. </summary>
|
/// <summary> Integer encoded as a float. </summary>
|
||||||
Integer = 1,
|
Integer = 1,
|
||||||
Color = 2,
|
Color = 2,
|
||||||
Enum = 3,
|
Enum = 3,
|
||||||
|
|
||||||
/// <summary> Native integer. </summary>
|
/// <summary> Native integer. </summary>
|
||||||
Int32 = 4,
|
Int32 = 4,
|
||||||
Int32Enum = 5,
|
Int32Enum = 5,
|
||||||
|
|
@ -105,6 +111,7 @@ public partial class MtrlTab
|
||||||
SphereMapIndex = 15,
|
SphereMapIndex = 15,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
private sealed class DevkitConstantValue
|
private sealed class DevkitConstantValue
|
||||||
{
|
{
|
||||||
public string Label = string.Empty;
|
public string Label = string.Empty;
|
||||||
|
|
@ -112,6 +119,7 @@ public partial class MtrlTab
|
||||||
public double Value = 0;
|
public double Value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
private sealed class DevkitConstant
|
private sealed class DevkitConstant
|
||||||
{
|
{
|
||||||
public uint Offset = 0;
|
public uint Offset = 0;
|
||||||
|
|
@ -147,7 +155,7 @@ public partial class MtrlTab
|
||||||
=> ByteOffset ?? Offset * ValueSize;
|
=> ByteOffset ?? Offset * ValueSize;
|
||||||
|
|
||||||
public uint? EffectiveByteSize
|
public uint? EffectiveByteSize
|
||||||
=> ByteSize ?? (Length * ValueSize);
|
=> ByteSize ?? Length * ValueSize;
|
||||||
|
|
||||||
public unsafe uint ValueSize
|
public unsafe uint ValueSize
|
||||||
=> Type switch
|
=> Type switch
|
||||||
|
|
@ -198,19 +206,23 @@ public partial class MtrlTab
|
||||||
private IEditor<T> CreateIntegerEditor<T>()
|
private IEditor<T> CreateIntegerEditor<T>()
|
||||||
where T : unmanaged, INumber<T>
|
where T : unmanaged, INumber<T>
|
||||||
=> ((Drag || Slider) && !Hex
|
=> ((Drag || Slider) && !Hex
|
||||||
? (Drag
|
? Drag
|
||||||
? (IEditor<T>)DragEditor<T>.CreateInteger(ToInteger<T>(Minimum), ToInteger<T>(Maximum), Speed ?? 0.25f, RelativeSpeed, Unit, 0)
|
? (IEditor<T>)DragEditor<T>.CreateInteger(ToInteger<T>(Minimum), ToInteger<T>(Maximum), Speed ?? 0.25f, RelativeSpeed,
|
||||||
: SliderEditor<T>.CreateInteger(ToInteger<T>(Minimum) ?? default, ToInteger<T>(Maximum) ?? default, Unit, 0))
|
Unit, 0)
|
||||||
: InputEditor<T>.CreateInteger(ToInteger<T>(Minimum), ToInteger<T>(Maximum), ToInteger<T>(Step), ToInteger<T>(StepFast), Hex, 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));
|
.WithFactorAndBias(ToInteger<T>(Factor), ToInteger<T>(Bias));
|
||||||
|
|
||||||
private IEditor<T> CreateFloatEditor<T>()
|
private IEditor<T> CreateFloatEditor<T>()
|
||||||
where T : unmanaged, INumber<T>, IPowerFunctions<T>
|
where T : unmanaged, INumber<T>, IPowerFunctions<T>
|
||||||
=> ((Drag || Slider)
|
=> (Drag || Slider
|
||||||
? (Drag
|
? Drag
|
||||||
? (IEditor<T>)DragEditor<T>.CreateFloat(ToFloat<T>(Minimum), ToFloat<T>(Maximum), Speed ?? 0.1f, RelativeSpeed, Precision, Unit, 0)
|
? (IEditor<T>)DragEditor<T>.CreateFloat(ToFloat<T>(Minimum), ToFloat<T>(Maximum), Speed ?? 0.1f, RelativeSpeed,
|
||||||
: SliderEditor<T>.CreateFloat(ToFloat<T>(Minimum) ?? default, ToFloat<T>(Maximum) ?? default, Precision, Unit, 0))
|
Precision, Unit, 0)
|
||||||
: InputEditor<T>.CreateFloat(ToFloat<T>(Minimum), ToFloat<T>(Maximum), T.CreateSaturating(Step), T.CreateSaturating(StepFast), 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))
|
.WithExponent(T.CreateSaturating(Exponent))
|
||||||
.WithFactorAndBias(T.CreateSaturating(Factor), T.CreateSaturating(Bias));
|
.WithFactorAndBias(T.CreateSaturating(Factor), T.CreateSaturating(Bias));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,20 +12,20 @@ namespace Penumbra.UI.AdvancedWindow.Materials;
|
||||||
|
|
||||||
public partial class MtrlTab
|
public partial class MtrlTab
|
||||||
{
|
{
|
||||||
public readonly List<LiveMaterialPreviewer> MaterialPreviewers = new(4);
|
private readonly List<LiveMaterialPreviewer> _materialPreviewers = new(4);
|
||||||
public readonly List<LiveColorTablePreviewer> ColorTablePreviewers = new(4);
|
private readonly List<LiveColorTablePreviewer> _colorTablePreviewers = new(4);
|
||||||
public int HighlightedColorTablePair = -1;
|
private int _highlightedColorTablePair = -1;
|
||||||
public readonly Stopwatch HighlightTime = new();
|
private readonly Stopwatch _highlightTime = new();
|
||||||
|
|
||||||
private void DrawMaterialLivePreviewRebind(bool disabled)
|
private void DrawMaterialLivePreviewRebind(bool disabled)
|
||||||
{
|
{
|
||||||
if (disabled)
|
if (disabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ImGui.Button("Reload live preview"))
|
if (ImUtf8.Button("Reload live preview"u8))
|
||||||
BindToMaterialInstances();
|
BindToMaterialInstances();
|
||||||
|
|
||||||
if (MaterialPreviewers.Count != 0 || ColorTablePreviewers.Count != 0)
|
if (_materialPreviewers.Count != 0 || _colorTablePreviewers.Count != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ImGui.SameLine();
|
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);
|
"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();
|
UnbindFromMaterialInstances();
|
||||||
|
|
||||||
|
|
@ -50,7 +50,7 @@ public partial class MtrlTab
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
MaterialPreviewers.Add(new LiveMaterialPreviewer(_objects, materialInfo));
|
_materialPreviewers.Add(new LiveMaterialPreviewer(_objects, materialInfo));
|
||||||
foundMaterials.Add((nint)material);
|
foundMaterials.Add((nint)material);
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException)
|
catch (InvalidOperationException)
|
||||||
|
|
@ -68,7 +68,7 @@ public partial class MtrlTab
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ColorTablePreviewers.Add(new LiveColorTablePreviewer(_objects, _framework, materialInfo));
|
_colorTablePreviewers.Add(new LiveColorTablePreviewer(_objects, _framework, materialInfo));
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException)
|
catch (InvalidOperationException)
|
||||||
{
|
{
|
||||||
|
|
@ -81,53 +81,53 @@ public partial class MtrlTab
|
||||||
|
|
||||||
private void UnbindFromMaterialInstances()
|
private void UnbindFromMaterialInstances()
|
||||||
{
|
{
|
||||||
foreach (var previewer in MaterialPreviewers)
|
foreach (var previewer in _materialPreviewers)
|
||||||
previewer.Dispose();
|
previewer.Dispose();
|
||||||
MaterialPreviewers.Clear();
|
_materialPreviewers.Clear();
|
||||||
|
|
||||||
foreach (var previewer in ColorTablePreviewers)
|
foreach (var previewer in _colorTablePreviewers)
|
||||||
previewer.Dispose();
|
previewer.Dispose();
|
||||||
ColorTablePreviewers.Clear();
|
_colorTablePreviewers.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void UnbindFromDrawObjectMaterialInstances(CharacterBase* characterBase)
|
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)
|
if (previewer.DrawObject != characterBase)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
previewer.Dispose();
|
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)
|
if (previewer.DrawObject != characterBase)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
previewer.Dispose();
|
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);
|
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);
|
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);
|
previewer.SetSamplerFlags(samplerCrc, samplerFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,14 +145,14 @@ public partial class MtrlTab
|
||||||
SetSamplerFlags(sampler.SamplerId, sampler.Flags);
|
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;
|
_highlightedColorTablePair = pairIdx;
|
||||||
HighlightTime.Restart();
|
_highlightTime.Restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldPairIdx >= 0)
|
if (oldPairIdx >= 0)
|
||||||
|
|
@ -160,19 +160,6 @@ public partial class MtrlTab
|
||||||
UpdateColorTableRowPreview(oldPairIdx << 1);
|
UpdateColorTableRowPreview(oldPairIdx << 1);
|
||||||
UpdateColorTableRowPreview((oldPairIdx << 1) | 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)
|
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;
|
return;
|
||||||
|
|
||||||
if (Mtrl.Table == null)
|
if (Mtrl.Table == null)
|
||||||
|
|
@ -213,21 +214,21 @@ public partial class MtrlTab
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HighlightedColorTablePair << 1 == rowIdx)
|
if (_highlightedColorTablePair << 1 == rowIdx)
|
||||||
ApplyHighlight(ref row, ColorId.InGameHighlight, (float)HighlightTime.Elapsed.TotalSeconds);
|
ApplyHighlight(ref row, ColorId.InGameHighlight, (float)_highlightTime.Elapsed.TotalSeconds);
|
||||||
else if (((HighlightedColorTablePair << 1) | 1) == rowIdx)
|
else if (((_highlightedColorTablePair << 1) | 1) == rowIdx)
|
||||||
ApplyHighlight(ref row, ColorId.InGameHighlight2, (float)HighlightTime.Elapsed.TotalSeconds);
|
ApplyHighlight(ref row, ColorId.InGameHighlight2, (float)_highlightTime.Elapsed.TotalSeconds);
|
||||||
|
|
||||||
foreach (var previewer in ColorTablePreviewers)
|
foreach (var previewer in _colorTablePreviewers)
|
||||||
{
|
{
|
||||||
row[..].CopyTo(previewer.GetColorRow(rowIdx));
|
row[..].CopyTo(previewer.GetColorRow(rowIdx));
|
||||||
previewer.ScheduleUpdate();
|
previewer.ScheduleUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateColorTablePreview()
|
private void UpdateColorTablePreview()
|
||||||
{
|
{
|
||||||
if (ColorTablePreviewers.Count == 0)
|
if (_colorTablePreviewers.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (Mtrl.Table == null)
|
if (Mtrl.Table == null)
|
||||||
|
|
@ -237,7 +238,8 @@ public partial class MtrlTab
|
||||||
var dyeRows = Mtrl.DyeTable != null ? ColorDyeTable.CastOrConvert(Mtrl.DyeTable) : null;
|
var dyeRows = Mtrl.DyeTable != null ? ColorDyeTable.CastOrConvert(Mtrl.DyeTable) : null;
|
||||||
if (dyeRows != null)
|
if (dyeRows != null)
|
||||||
{
|
{
|
||||||
ReadOnlySpan<StainId> stainIds = [
|
ReadOnlySpan<StainId> stainIds =
|
||||||
|
[
|
||||||
_stainService.StainCombo1.CurrentSelection.Key,
|
_stainService.StainCombo1.CurrentSelection.Key,
|
||||||
_stainService.StainCombo2.CurrentSelection.Key,
|
_stainService.StainCombo2.CurrentSelection.Key,
|
||||||
];
|
];
|
||||||
|
|
@ -245,13 +247,14 @@ public partial class MtrlTab
|
||||||
rows.ApplyDye(_stainService.GudStmFile, stainIds, dyeRows);
|
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], ColorId.InGameHighlight, (float)_highlightTime.Elapsed.TotalSeconds);
|
||||||
ApplyHighlight(ref rows[(HighlightedColorTablePair << 1) | 1], ColorId.InGameHighlight2, (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);
|
rows.AsHalves().CopyTo(previewer.ColorTable);
|
||||||
previewer.ScheduleUpdate();
|
previewer.ScheduleUpdate();
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@ public partial class MtrlTab
|
||||||
// Apricot shader packages are unlisted because
|
// Apricot shader packages are unlisted because
|
||||||
// 1. they cause severe performance/memory issues when calculating the effective shader set
|
// 1. they cause severe performance/memory issues when calculating the effective shader set
|
||||||
// 2. they probably aren't intended for use with materials anyway
|
// 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",
|
"3dui.shpk",
|
||||||
// "apricot_decal_dummy.shpk",
|
// "apricot_decal_dummy.shpk",
|
||||||
// "apricot_decal_ring.shpk",
|
// "apricot_decal_ring.shpk",
|
||||||
|
|
@ -80,35 +80,35 @@ public partial class MtrlTab
|
||||||
"verticalfog.shpk",
|
"verticalfog.shpk",
|
||||||
"water.shpk",
|
"water.shpk",
|
||||||
"weather.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;
|
private string[]? _shpkNames;
|
||||||
|
|
||||||
public string ShaderHeader = "Shader###Shader";
|
private string _shaderHeader = "Shader###Shader";
|
||||||
public FullPath LoadedShpkPath = FullPath.Empty;
|
private FullPath _loadedShpkPath = FullPath.Empty;
|
||||||
public string LoadedShpkPathName = string.Empty;
|
private string _loadedShpkPathName = string.Empty;
|
||||||
public string LoadedShpkDevkitPathName = string.Empty;
|
private string _loadedShpkDevkitPathName = string.Empty;
|
||||||
public string ShaderComment = string.Empty;
|
private string _shaderComment = string.Empty;
|
||||||
public ShpkFile? AssociatedShpk;
|
private ShpkFile? _associatedShpk;
|
||||||
public bool ShpkLoading;
|
private bool _shpkLoading;
|
||||||
public JObject? AssociatedShpkDevkit;
|
private JObject? _associatedShpkDevkit;
|
||||||
|
|
||||||
public readonly string LoadedBaseDevkitPathName;
|
private readonly string _loadedBaseDevkitPathName;
|
||||||
public readonly JObject? AssociatedBaseDevkit;
|
private readonly JObject? _associatedBaseDevkit;
|
||||||
|
|
||||||
// Shader Key State
|
// Shader Key State
|
||||||
public readonly
|
private readonly
|
||||||
List<(string Label, int Index, string Description, bool MonoFont, IReadOnlyList<(string Label, uint Value, string Description)>
|
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);
|
private readonly HashSet<int> _vertexShaders = new(16);
|
||||||
public readonly HashSet<int> PixelShaders = new(16);
|
private readonly HashSet<int> _pixelShaders = new(16);
|
||||||
public bool ShadersKnown;
|
private bool _shadersKnown;
|
||||||
public ReadOnlyMemory<byte> ShadersString = UnknownShadersString;
|
private ReadOnlyMemory<byte> _shadersString = UnknownShadersString;
|
||||||
|
|
||||||
public string[] GetShpkNames()
|
private string[] GetShpkNames()
|
||||||
{
|
{
|
||||||
if (null != _shpkNames)
|
if (null != _shpkNames)
|
||||||
return _shpkNames;
|
return _shpkNames;
|
||||||
|
|
@ -122,7 +122,7 @@ public partial class MtrlTab
|
||||||
return _shpkNames;
|
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);
|
defaultPath = GamePaths.Shader.ShpkPath(Mtrl.ShaderPackage.Name);
|
||||||
if (!Utf8GamePath.FromString(defaultPath, out defaultGamePath))
|
if (!Utf8GamePath.FromString(defaultPath, out defaultGamePath))
|
||||||
|
|
@ -131,45 +131,45 @@ public partial class MtrlTab
|
||||||
return _edit.FindBestMatch(defaultGamePath);
|
return _edit.FindBestMatch(defaultGamePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadShpk(FullPath path)
|
private void LoadShpk(FullPath path)
|
||||||
=> Task.Run(() => DoLoadShpk(path));
|
=> Task.Run(() => DoLoadShpk(path));
|
||||||
|
|
||||||
private async Task DoLoadShpk(FullPath path)
|
private async Task DoLoadShpk(FullPath path)
|
||||||
{
|
{
|
||||||
ShadersKnown = false;
|
_shadersKnown = false;
|
||||||
ShaderHeader = $"Shader ({Mtrl.ShaderPackage.Name})###Shader";
|
_shaderHeader = $"Shader ({Mtrl.ShaderPackage.Name})###Shader";
|
||||||
ShpkLoading = true;
|
_shpkLoading = true;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var data = path.IsRooted
|
var data = path.IsRooted
|
||||||
? await File.ReadAllBytesAsync(path.FullName)
|
? await File.ReadAllBytesAsync(path.FullName)
|
||||||
: _gameData.GetFile(path.InternalName.ToString())?.Data;
|
: _gameData.GetFile(path.InternalName.ToString())?.Data;
|
||||||
LoadedShpkPath = path;
|
_loadedShpkPath = path;
|
||||||
AssociatedShpk = data?.Length > 0 ? new ShpkFile(data) : throw new Exception("Failure to load file data.");
|
_associatedShpk = data?.Length > 0 ? new ShpkFile(data) : throw new Exception("Failure to load file data.");
|
||||||
LoadedShpkPathName = path.ToPath();
|
_loadedShpkPathName = path.ToPath();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
LoadedShpkPath = FullPath.Empty;
|
_loadedShpkPath = FullPath.Empty;
|
||||||
LoadedShpkPathName = string.Empty;
|
_loadedShpkPathName = string.Empty;
|
||||||
AssociatedShpk = null;
|
_associatedShpk = null;
|
||||||
Penumbra.Messager.NotificationMessage(e, $"Could not load {LoadedShpkPath.ToPath()}.", NotificationType.Error, false);
|
Penumbra.Messager.NotificationMessage(e, $"Could not load {_loadedShpkPath.ToPath()}.", NotificationType.Error, false);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
ShpkLoading = false;
|
_shpkLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LoadedShpkPath.InternalName.IsEmpty)
|
if (_loadedShpkPath.InternalName.IsEmpty)
|
||||||
{
|
{
|
||||||
AssociatedShpkDevkit = null;
|
_associatedShpkDevkit = null;
|
||||||
LoadedShpkDevkitPathName = string.Empty;
|
_loadedShpkDevkitPathName = string.Empty;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AssociatedShpkDevkit =
|
_associatedShpkDevkit =
|
||||||
TryLoadShpkDevkit(Path.GetFileNameWithoutExtension(Mtrl.ShaderPackage.Name), out LoadedShpkDevkitPathName);
|
TryLoadShpkDevkit(Path.GetFileNameWithoutExtension(Mtrl.ShaderPackage.Name), out _loadedShpkDevkitPathName);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateShaderKeys();
|
UpdateShaderKeys();
|
||||||
|
|
@ -178,9 +178,9 @@ public partial class MtrlTab
|
||||||
|
|
||||||
private void UpdateShaderKeys()
|
private void UpdateShaderKeys()
|
||||||
{
|
{
|
||||||
ShaderKeys.Clear();
|
_shaderKeys.Clear();
|
||||||
if (AssociatedShpk != null)
|
if (_associatedShpk != null)
|
||||||
foreach (var key in AssociatedShpk.MaterialKeys)
|
foreach (var key in _associatedShpk.MaterialKeys)
|
||||||
{
|
{
|
||||||
var keyName = Names.KnownNames.TryResolve(key.Id);
|
var keyName = Names.KnownNames.TryResolve(key.Id);
|
||||||
var dkData = TryGetShpkDevkitData<DevkitShaderKey>("ShaderKeys", key.Id, false);
|
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);
|
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));
|
!hasDkLabel, values));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -218,7 +218,7 @@ public partial class MtrlTab
|
||||||
{
|
{
|
||||||
var keyName = Names.KnownNames.TryResolve(key.Category);
|
var keyName = Names.KnownNames.TryResolve(key.Category);
|
||||||
var valueName = keyName.WithKnownSuffixes().TryResolve(Names.KnownNames, key.Value);
|
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 = [];
|
passSet = [];
|
||||||
byPassSets.Add(passId, passSet);
|
byPassSets.Add(passId, passSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
passSet.Add(shaderIndex);
|
passSet.Add(shaderIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
VertexShaders.Clear();
|
_vertexShaders.Clear();
|
||||||
PixelShaders.Clear();
|
_pixelShaders.Clear();
|
||||||
|
|
||||||
var vertexShadersByPass = new Dictionary<uint, HashSet<int>>();
|
var vertexShadersByPass = new Dictionary<uint, HashSet<int>>();
|
||||||
var pixelShadersByPass = 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
|
else
|
||||||
{
|
{
|
||||||
ShadersKnown = true;
|
_shadersKnown = true;
|
||||||
var systemKeySelectors = AllSelectors(AssociatedShpk.SystemKeys).ToArray();
|
var systemKeySelectors = AllSelectors(_associatedShpk.SystemKeys).ToArray();
|
||||||
var sceneKeySelectors = AllSelectors(AssociatedShpk.SceneKeys).ToArray();
|
var sceneKeySelectors = AllSelectors(_associatedShpk.SceneKeys).ToArray();
|
||||||
var subViewKeySelectors = AllSelectors(AssociatedShpk.SubViewKeys).ToArray();
|
var subViewKeySelectors = AllSelectors(_associatedShpk.SubViewKeys).ToArray();
|
||||||
var materialKeySelector =
|
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)
|
foreach (var systemKeySelector in systemKeySelectors)
|
||||||
{
|
{
|
||||||
|
|
@ -261,38 +262,39 @@ public partial class MtrlTab
|
||||||
foreach (var subViewKeySelector in subViewKeySelectors)
|
foreach (var subViewKeySelector in subViewKeySelectors)
|
||||||
{
|
{
|
||||||
var selector = BuildSelector(systemKeySelector, sceneKeySelector, materialKeySelector, subViewKeySelector);
|
var selector = BuildSelector(systemKeySelector, sceneKeySelector, materialKeySelector, subViewKeySelector);
|
||||||
var node = AssociatedShpk.GetNodeBySelector(selector);
|
var node = _associatedShpk.GetNodeBySelector(selector);
|
||||||
if (node.HasValue)
|
if (node.HasValue)
|
||||||
foreach (var pass in node.Value.Passes)
|
foreach (var pass in node.Value.Passes)
|
||||||
{
|
{
|
||||||
AddShader(VertexShaders, vertexShadersByPass, pass.Id, (int)pass.VertexShader);
|
AddShader(_vertexShaders, vertexShadersByPass, pass.Id, (int)pass.VertexShader);
|
||||||
AddShader(PixelShaders, pixelShadersByPass, pass.Id, (int)pass.PixelShader);
|
AddShader(_pixelShaders, pixelShadersByPass, pass.Id, (int)pass.PixelShader);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ShadersKnown = false;
|
_shadersKnown = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShadersKnown)
|
if (_shadersKnown)
|
||||||
{
|
{
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
foreach (var (passId, passVS) in vertexShadersByPass)
|
foreach (var (passId, passVertexShader) in vertexShadersByPass)
|
||||||
{
|
{
|
||||||
if (builder.Length > 0)
|
if (builder.Length > 0)
|
||||||
builder.Append("\n\n");
|
builder.Append("\n\n");
|
||||||
|
|
||||||
var passName = Names.KnownNames.TryResolve(passId);
|
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)}");
|
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)}");
|
builder.Append($"\nPixel Shaders ({passName}): {string.Join(", ", shaders)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (var (passId, passPS) in pixelShadersByPass)
|
|
||||||
|
foreach (var (passId, passPixelShader) in pixelShadersByPass)
|
||||||
{
|
{
|
||||||
if (vertexShadersByPass.ContainsKey(passId))
|
if (vertexShadersByPass.ContainsKey(passId))
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -301,22 +303,24 @@ public partial class MtrlTab
|
||||||
builder.Append("\n\n");
|
builder.Append("\n\n");
|
||||||
|
|
||||||
var passName = Names.KnownNames.TryResolve(passId);
|
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)}");
|
builder.Append($"Pixel Shaders ({passName}): {string.Join(", ", shaders)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
ShadersString = Encoding.UTF8.GetBytes(builder.ToString());
|
_shadersString = Encoding.UTF8.GetBytes(builder.ToString());
|
||||||
}
|
}
|
||||||
else
|
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)
|
private bool DrawShaderSection(bool disabled)
|
||||||
{
|
{
|
||||||
var ret = false;
|
var ret = false;
|
||||||
if (ImGui.CollapsingHeader(ShaderHeader))
|
if (ImGui.CollapsingHeader(_shaderHeader))
|
||||||
{
|
{
|
||||||
ret |= DrawPackageNameInput(disabled);
|
ret |= DrawPackageNameInput(disabled);
|
||||||
ret |= DrawShaderFlagsInput(disabled);
|
ret |= DrawShaderFlagsInput(disabled);
|
||||||
|
|
@ -325,21 +329,18 @@ public partial class MtrlTab
|
||||||
DrawMaterialShaders();
|
DrawMaterialShaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ShpkLoading && (AssociatedShpk == null || AssociatedShpkDevkit == null))
|
if (!_shpkLoading && (_associatedShpk == null || _associatedShpkDevkit == null))
|
||||||
{
|
{
|
||||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
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,
|
ImUtf8.Text("Unable to find a suitable shader (.shpk) file for cross-references. Some functionality will be missing."u8,
|
||||||
ImGuiUtil.HalfBlendText(0x80u)); // Half red
|
ImGuiUtil.HalfBlendText(0x80u)); // Half red
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
ImUtf8.Text(
|
||||||
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,
|
"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
|
ImGuiUtil.HalfBlendText(0x8080u)); // Half yellow
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -358,15 +359,15 @@ public partial class MtrlTab
|
||||||
if (c)
|
if (c)
|
||||||
foreach (var value in GetShpkNames())
|
foreach (var value in GetShpkNames())
|
||||||
{
|
{
|
||||||
if (ImGui.Selectable(value, value == Mtrl.ShaderPackage.Name))
|
if (!ImGui.Selectable(value, value == Mtrl.ShaderPackage.Name))
|
||||||
{
|
continue;
|
||||||
|
|
||||||
Mtrl.ShaderPackage.Name = value;
|
Mtrl.ShaderPackage.Name = value;
|
||||||
ret = true;
|
ret = true;
|
||||||
AssociatedShpk = null;
|
_associatedShpk = null;
|
||||||
LoadedShpkPath = FullPath.Empty;
|
_loadedShpkPath = FullPath.Empty;
|
||||||
LoadShpk(FindAssociatedShpk(out _, out _));
|
LoadShpk(FindAssociatedShpk(out _, out _));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -391,23 +392,23 @@ public partial class MtrlTab
|
||||||
private void DrawCustomAssociations()
|
private void DrawCustomAssociations()
|
||||||
{
|
{
|
||||||
const string tooltip = "Click to copy file path to clipboard.";
|
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: None"
|
||||||
: $"Associated .shpk file: {LoadedShpkPathName}";
|
: $"Associated .shpk file: {_loadedShpkPathName}";
|
||||||
var devkitText = AssociatedShpkDevkit == null
|
var devkitText = _associatedShpkDevkit == null
|
||||||
? "Associated dev-kit file: None"
|
? "Associated dev-kit file: None"
|
||||||
: $"Associated dev-kit file: {LoadedShpkDevkitPathName}";
|
: $"Associated dev-kit file: {_loadedShpkDevkitPathName}";
|
||||||
var baseDevkitText = AssociatedBaseDevkit == null
|
var baseDevkitText = _associatedBaseDevkit == null
|
||||||
? "Base dev-kit file: None"
|
? "Base dev-kit file: None"
|
||||||
: $"Base dev-kit file: {LoadedBaseDevkitPathName}";
|
: $"Base dev-kit file: {_loadedBaseDevkitPathName}";
|
||||||
|
|
||||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||||
|
|
||||||
ImGuiUtil.CopyOnClickSelectable(text, LoadedShpkPathName, tooltip);
|
ImUtf8.CopyOnClickSelectable(text, _loadedShpkPathName, tooltip);
|
||||||
ImGuiUtil.CopyOnClickSelectable(devkitText, LoadedShpkDevkitPathName, tooltip);
|
ImUtf8.CopyOnClickSelectable(devkitText, _loadedShpkDevkitPathName, tooltip);
|
||||||
ImGuiUtil.CopyOnClickSelectable(baseDevkitText, LoadedBaseDevkitPathName, 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) =>
|
_fileDialog.OpenFilePicker("Associate Custom .shpk File...", ".shpk", (success, name) =>
|
||||||
{
|
{
|
||||||
if (success)
|
if (success)
|
||||||
|
|
@ -416,15 +417,15 @@ public partial class MtrlTab
|
||||||
|
|
||||||
var moddedPath = FindAssociatedShpk(out var defaultPath, out var gamePath);
|
var moddedPath = FindAssociatedShpk(out var defaultPath, out var gamePath);
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
if (ImGuiUtil.DrawDisabledButton("Associate Default .shpk File", Vector2.Zero, moddedPath.ToPath(),
|
if (ImUtf8.ButtonEx("Associate Default .shpk File"u8, moddedPath.ToPath(), Vector2.Zero,
|
||||||
moddedPath.Equals(LoadedShpkPath)))
|
moddedPath.Equals(_loadedShpkPath)))
|
||||||
LoadShpk(moddedPath);
|
LoadShpk(moddedPath);
|
||||||
|
|
||||||
if (!gamePath.Path.Equals(moddedPath.InternalName))
|
if (!gamePath.Path.Equals(moddedPath.InternalName))
|
||||||
{
|
{
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
if (ImGuiUtil.DrawDisabledButton("Associate Unmodded .shpk File", Vector2.Zero, defaultPath,
|
if (ImUtf8.ButtonEx("Associate Unmodded .shpk File", defaultPath, Vector2.Zero,
|
||||||
gamePath.Path.Equals(LoadedShpkPath.InternalName)))
|
gamePath.Path.Equals(_loadedShpkPath.InternalName)))
|
||||||
LoadShpk(new FullPath(gamePath));
|
LoadShpk(new FullPath(gamePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -433,22 +434,23 @@ public partial class MtrlTab
|
||||||
|
|
||||||
private bool DrawMaterialShaderKeys(bool disabled)
|
private bool DrawMaterialShaderKeys(bool disabled)
|
||||||
{
|
{
|
||||||
if (ShaderKeys.Count == 0)
|
if (_shaderKeys.Count == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var ret = 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);
|
using var font = ImRaii.PushFont(UiBuilder.MonoFont, monoFont);
|
||||||
ref var key = ref Mtrl.ShaderPackage.ShaderKeys[index];
|
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 currentValue = key.Value;
|
||||||
var (currentLabel, _, currentDescription) =
|
var (currentLabel, _, currentDescription) =
|
||||||
values.FirstOrNull(v => v.Value == currentValue) ?? ($"0x{currentValue:X8}", currentValue, string.Empty);
|
values.FirstOrNull(v => v.Value == currentValue) ?? ($"0x{currentValue:X8}", currentValue, string.Empty);
|
||||||
if (!disabled && shpkKey.HasValue)
|
if (!disabled && shpkKey.HasValue)
|
||||||
{
|
{
|
||||||
ImGui.SetNextItemWidth(UiHelpers.Scale * 250.0f);
|
ImGui.SetNextItemWidth(UiHelpers.Scale * 250.0f);
|
||||||
using (var c = ImRaii.Combo($"##{key.Category:X8}", currentLabel))
|
using (var c = ImUtf8.Combo(""u8, currentLabel))
|
||||||
{
|
{
|
||||||
if (c)
|
if (c)
|
||||||
foreach (var (valueLabel, value, valueDescription) in values)
|
foreach (var (valueLabel, value, valueDescription) in values)
|
||||||
|
|
@ -469,16 +471,16 @@ public partial class MtrlTab
|
||||||
if (description.Length > 0)
|
if (description.Length > 0)
|
||||||
ImGuiUtil.LabeledHelpMarker(label, description);
|
ImGuiUtil.LabeledHelpMarker(label, description);
|
||||||
else
|
else
|
||||||
ImGui.TextUnformatted(label);
|
ImUtf8.Text(label);
|
||||||
}
|
}
|
||||||
else if (description.Length > 0 || currentDescription.Length > 0)
|
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);
|
description + (description.Length > 0 && currentDescription.Length > 0 ? "\n\n" : string.Empty) + currentDescription);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ImGui.TextUnformatted($"{label}: {currentLabel}");
|
ImUtf8.Text($"{label}: {currentLabel}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -487,19 +489,19 @@ public partial class MtrlTab
|
||||||
|
|
||||||
private void DrawMaterialShaders()
|
private void DrawMaterialShaders()
|
||||||
{
|
{
|
||||||
if (AssociatedShpk == null)
|
if (_associatedShpk == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using (var node = ImUtf8.TreeNode("Candidate Shaders"u8))
|
using (var node = ImUtf8.TreeNode("Candidate Shaders"u8))
|
||||||
{
|
{
|
||||||
if (node)
|
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.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||||
ImGui.TextUnformatted(ShaderComment);
|
ImUtf8.Text(_shaderComment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ public partial class MtrlTab
|
||||||
{
|
{
|
||||||
Textures.Clear();
|
Textures.Clear();
|
||||||
SamplerIds.Clear();
|
SamplerIds.Clear();
|
||||||
if (AssociatedShpk == null)
|
if (_associatedShpk == null)
|
||||||
{
|
{
|
||||||
SamplerIds.UnionWith(Mtrl.ShaderPackage.Samplers.Select(sampler => sampler.SamplerId));
|
SamplerIds.UnionWith(Mtrl.ShaderPackage.Samplers.Select(sampler => sampler.SamplerId));
|
||||||
if (Mtrl.Table != null)
|
if (Mtrl.Table != null)
|
||||||
|
|
@ -34,11 +34,11 @@ public partial class MtrlTab
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (var index in VertexShaders)
|
foreach (var index in _vertexShaders)
|
||||||
SamplerIds.UnionWith(AssociatedShpk.VertexShaders[index].Samplers.Select(sampler => sampler.Id));
|
SamplerIds.UnionWith(_associatedShpk.VertexShaders[index].Samplers.Select(sampler => sampler.Id));
|
||||||
foreach (var index in PixelShaders)
|
foreach (var index in _pixelShaders)
|
||||||
SamplerIds.UnionWith(AssociatedShpk.PixelShaders[index].Samplers.Select(sampler => sampler.Id));
|
SamplerIds.UnionWith(_associatedShpk.PixelShaders[index].Samplers.Select(sampler => sampler.Id));
|
||||||
if (!ShadersKnown)
|
if (!_shadersKnown)
|
||||||
{
|
{
|
||||||
SamplerIds.UnionWith(Mtrl.ShaderPackage.Samplers.Select(sampler => sampler.SamplerId));
|
SamplerIds.UnionWith(Mtrl.ShaderPackage.Samplers.Select(sampler => sampler.SamplerId));
|
||||||
if (Mtrl.Table != null)
|
if (Mtrl.Table != null)
|
||||||
|
|
@ -47,7 +47,7 @@ public partial class MtrlTab
|
||||||
|
|
||||||
foreach (var samplerId in SamplerIds)
|
foreach (var samplerId in SamplerIds)
|
||||||
{
|
{
|
||||||
var shpkSampler = AssociatedShpk.GetSamplerById(samplerId);
|
var shpkSampler = _associatedShpk.GetSamplerById(samplerId);
|
||||||
if (shpkSampler is not { Slot: 2 })
|
if (shpkSampler is not { Slot: 2 })
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -95,9 +95,12 @@ public partial class MtrlTab
|
||||||
private static ReadOnlySpan<byte> TextureAddressModeTooltip(TextureAddressMode addressMode)
|
private static ReadOnlySpan<byte> TextureAddressModeTooltip(TextureAddressMode addressMode)
|
||||||
=> addressMode switch
|
=> 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.Wrap =>
|
||||||
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,
|
"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.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.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,
|
TextureAddressMode.Border => "Texture coordinates outside the range [0.0, 1.0] are set to the border color (generally black)."u8,
|
||||||
_ => ""u8,
|
_ => ""u8,
|
||||||
};
|
};
|
||||||
|
|
@ -202,7 +205,7 @@ public partial class MtrlTab
|
||||||
ret = true;
|
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);
|
ImGui.SetNextItemWidth(UiHelpers.Scale * 100.0f);
|
||||||
var addressMode = samplerFlags.UAddressMode;
|
var addressMode = samplerFlags.UAddressMode;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ using OtterGui;
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
using OtterGui.Text;
|
using OtterGui.Text;
|
||||||
using OtterGui.Widgets;
|
using OtterGui.Widgets;
|
||||||
using Penumbra.GameData;
|
|
||||||
using Penumbra.GameData.Files;
|
using Penumbra.GameData.Files;
|
||||||
using Penumbra.GameData.Files.MaterialStructs;
|
using Penumbra.GameData.Files.MaterialStructs;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
|
@ -40,7 +39,8 @@ public sealed partial class MtrlTab : IWritable, IDisposable
|
||||||
private bool _updateOnNextFrame;
|
private bool _updateOnNextFrame;
|
||||||
|
|
||||||
public unsafe MtrlTab(IDataManager gameData, IFramework framework, ObjectManager objects, CharacterBaseDestructor characterBaseDestructor,
|
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)
|
Configuration config, ModEditWindow edit, MtrlFile file, string filePath, bool writable)
|
||||||
{
|
{
|
||||||
_gameData = gameData;
|
_gameData = gameData;
|
||||||
|
|
@ -57,7 +57,7 @@ public sealed partial class MtrlTab : IWritable, IDisposable
|
||||||
Mtrl = file;
|
Mtrl = file;
|
||||||
FilePath = filePath;
|
FilePath = filePath;
|
||||||
Writable = writable;
|
Writable = writable;
|
||||||
AssociatedBaseDevkit = TryLoadShpkDevkit("_base", out LoadedBaseDevkitPathName);
|
_associatedBaseDevkit = TryLoadShpkDevkit("_base", out _loadedBaseDevkitPathName);
|
||||||
Update();
|
Update();
|
||||||
LoadShpk(FindAssociatedShpk(out _, out _));
|
LoadShpk(FindAssociatedShpk(out _, out _));
|
||||||
if (writable)
|
if (writable)
|
||||||
|
|
@ -118,7 +118,7 @@ public sealed partial class MtrlTab : IWritable, IDisposable
|
||||||
using var dis = ImRaii.Disabled(disabled);
|
using var dis = ImRaii.Disabled(disabled);
|
||||||
|
|
||||||
var tmp = shaderFlags.EnableTransparency;
|
var tmp = shaderFlags.EnableTransparency;
|
||||||
if (ImGui.Checkbox("Enable Transparency", ref tmp))
|
if (ImUtf8.Checkbox("Enable Transparency"u8, ref tmp))
|
||||||
{
|
{
|
||||||
shaderFlags.EnableTransparency = tmp;
|
shaderFlags.EnableTransparency = tmp;
|
||||||
ret = true;
|
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);
|
ImGui.SameLine(200 * UiHelpers.Scale + ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X);
|
||||||
tmp = shaderFlags.HideBackfaces;
|
tmp = shaderFlags.HideBackfaces;
|
||||||
if (ImGui.Checkbox("Hide Backfaces", ref tmp))
|
if (ImUtf8.Checkbox("Hide Backfaces"u8, ref tmp))
|
||||||
{
|
{
|
||||||
shaderFlags.HideBackfaces = tmp;
|
shaderFlags.HideBackfaces = tmp;
|
||||||
ret = true;
|
ret = true;
|
||||||
SetShaderPackageFlags(Mtrl.ShaderPackage.Flags);
|
SetShaderPackageFlags(Mtrl.ShaderPackage.Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShpkLoading)
|
if (_shpkLoading)
|
||||||
{
|
{
|
||||||
ImGui.SameLine(400 * UiHelpers.Scale + 2 * ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X);
|
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 _)
|
private void DrawOtherMaterialDetails(bool _)
|
||||||
{
|
{
|
||||||
if (!ImGui.CollapsingHeader("Further Content"))
|
if (!ImUtf8.CollapsingHeader("Further Content"u8))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using (var sets = ImRaii.TreeNode("UV Sets", ImGuiTreeNodeFlags.DefaultOpen))
|
using (var sets = ImUtf8.TreeNode("UV Sets"u8, ImGuiTreeNodeFlags.DefaultOpen))
|
||||||
{
|
{
|
||||||
if (sets)
|
if (sets)
|
||||||
foreach (var set in Mtrl.UvSets)
|
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)
|
if (sets)
|
||||||
foreach (var set in Mtrl.ColorSets)
|
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)
|
if (Mtrl.AdditionalData.Length <= 0)
|
||||||
return;
|
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)
|
if (t)
|
||||||
Widget.DrawHexViewer(Mtrl.AdditionalData);
|
Widget.DrawHexViewer(Mtrl.AdditionalData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
UpdateShaders();
|
UpdateShaders();
|
||||||
UpdateTextures();
|
UpdateTextures();
|
||||||
|
|
@ -187,12 +187,12 @@ public sealed partial class MtrlTab : IWritable, IDisposable
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Valid
|
public bool Valid
|
||||||
=> ShadersKnown && Mtrl.Valid;
|
=> _shadersKnown && Mtrl.Valid;
|
||||||
|
|
||||||
public byte[] Write()
|
public byte[] Write()
|
||||||
{
|
{
|
||||||
var output = Mtrl.Clone();
|
var output = Mtrl.Clone();
|
||||||
output.GarbageCollect(AssociatedShpk, SamplerIds);
|
output.GarbageCollect(_associatedShpk, SamplerIds);
|
||||||
|
|
||||||
return output.Write();
|
return output.Write();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,16 @@ using Penumbra.Services;
|
||||||
|
|
||||||
namespace Penumbra.UI.AdvancedWindow.Materials;
|
namespace Penumbra.UI.AdvancedWindow.Materials;
|
||||||
|
|
||||||
public sealed class MtrlTabFactory(IDataManager gameData, IFramework framework, ObjectManager objects,
|
public sealed class MtrlTabFactory(
|
||||||
CharacterBaseDestructor characterBaseDestructor, StainService stainService, ResourceTreeFactory resourceTreeFactory,
|
IDataManager gameData,
|
||||||
FileDialogService fileDialog, MaterialTemplatePickers materialTemplatePickers, Configuration config) : IUiService
|
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)
|
public MtrlTab Create(ModEditWindow edit, MtrlFile file, string filePath, bool writable)
|
||||||
=> new(gameData, framework, objects, characterBaseDestructor, stainService, resourceTreeFactory, fileDialog,
|
=> new(gameData, framework, objects, characterBaseDestructor, stainService, resourceTreeFactory, fileDialog,
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using Dalamud.Interface.Utility;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
|
using OtterGui.Text;
|
||||||
using Penumbra.UI.AdvancedWindow.Materials;
|
using Penumbra.UI.AdvancedWindow.Materials;
|
||||||
|
|
||||||
namespace Penumbra.UI.AdvancedWindow;
|
namespace Penumbra.UI.AdvancedWindow;
|
||||||
|
|
@ -24,7 +25,7 @@ public partial class ModEditWindow
|
||||||
if (_editor.Files.Mdl.Count == 0)
|
if (_editor.Files.Mdl.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using var tab = ImRaii.TabItem("Material Reassignment");
|
using var tab = ImUtf8.TabItem("Material Reassignment"u8);
|
||||||
if (!tab)
|
if (!tab)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -32,45 +33,43 @@ public partial class ModEditWindow
|
||||||
MaterialSuffix.Draw(_editor, ImGuiHelpers.ScaledVector2(175, 0));
|
MaterialSuffix.Draw(_editor, ImGuiHelpers.ScaledVector2(175, 0));
|
||||||
|
|
||||||
ImGui.NewLine();
|
ImGui.NewLine();
|
||||||
using var child = ImRaii.Child("##mdlFiles", -Vector2.One, true);
|
using var child = ImUtf8.Child("##mdlFiles"u8, -Vector2.One, true);
|
||||||
if (!child)
|
if (!child)
|
||||||
return;
|
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)
|
if (!table)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var iconSize = ImGui.GetFrameHeight() * Vector2.One;
|
|
||||||
foreach (var (info, idx) in _editor.MdlMaterialEditor.ModelFiles.WithIndex())
|
foreach (var (info, idx) in _editor.MdlMaterialEditor.ModelFiles.WithIndex())
|
||||||
{
|
{
|
||||||
using var id = ImRaii.PushId(idx);
|
using var id = ImRaii.PushId(idx);
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Save.ToIconString(), iconSize,
|
if (ImUtf8.IconButton(FontAwesomeIcon.Save, "Save the changed mdl file.\nUse at own risk!"u8, disabled: !info.Changed))
|
||||||
"Save the changed mdl file.\nUse at own risk!", !info.Changed, true))
|
|
||||||
info.Save(_editor.Compactor);
|
info.Save(_editor.Compactor);
|
||||||
|
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Recycle.ToIconString(), iconSize,
|
if (ImUtf8.IconButton(FontAwesomeIcon.Recycle, "Restore current changes to default."u8, disabled: !info.Changed))
|
||||||
"Restore current changes to default.", !info.Changed, true))
|
|
||||||
info.Restore();
|
info.Restore();
|
||||||
|
|
||||||
ImGui.TableNextColumn();
|
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.TableNextColumn();
|
||||||
ImGui.SetNextItemWidth(400 * UiHelpers.Scale);
|
ImGui.SetNextItemWidth(400 * UiHelpers.Scale);
|
||||||
var tmp = info.CurrentMaterials[0];
|
var tmp = info.CurrentMaterials[0];
|
||||||
if (ImGui.InputText("##0", ref tmp, 64))
|
if (ImUtf8.InputText("##0"u8, ref tmp))
|
||||||
info.SetMaterial(tmp, 0);
|
info.SetMaterial(tmp, 0);
|
||||||
|
|
||||||
for (var i = 1; i < info.Count; ++i)
|
for (var i = 1; i < info.Count; ++i)
|
||||||
{
|
{
|
||||||
|
using var id2 = ImUtf8.PushId(i);
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.SetNextItemWidth(400 * UiHelpers.Scale);
|
ImGui.SetNextItemWidth(400 * UiHelpers.Scale);
|
||||||
tmp = info.CurrentMaterials[i];
|
tmp = info.CurrentMaterials[i];
|
||||||
if (ImGui.InputText($"##{i}", ref tmp, 64))
|
if (ImUtf8.InputText(""u8, ref tmp))
|
||||||
info.SetMaterial(tmp, i);
|
info.SetMaterial(tmp, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ using Penumbra.GameData.Interop;
|
||||||
using Penumbra.String;
|
using Penumbra.String;
|
||||||
using static Penumbra.GameData.Files.ShpkFile;
|
using static Penumbra.GameData.Files.ShpkFile;
|
||||||
using OtterGui.Widgets;
|
using OtterGui.Widgets;
|
||||||
using Penumbra.GameData.Files.ShaderStructs;
|
|
||||||
using OtterGui.Text;
|
using OtterGui.Text;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
|
|
@ -56,21 +55,17 @@ public partial class ModEditWindow
|
||||||
private static void DrawShaderPackageSummary(ShpkTab tab)
|
private static void DrawShaderPackageSummary(ShpkTab tab)
|
||||||
{
|
{
|
||||||
if (tab.Shpk.IsLegacy)
|
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.",
|
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
|
ImGuiUtil.HalfBlendText(0x80u)); // Half red
|
||||||
}
|
ImUtf8.Text(tab.Header);
|
||||||
ImGui.TextUnformatted(tab.Header);
|
|
||||||
if (!tab.Shpk.Disassembled)
|
if (!tab.Shpk.Disassembled)
|
||||||
{
|
|
||||||
ImUtf8.Text("Your system doesn't support disassembling shaders. Some functionality will be missing.",
|
ImUtf8.Text("Your system doesn't support disassembling shaders. Some functionality will be missing.",
|
||||||
ImGuiUtil.HalfBlendText(0x80u)); // Half red
|
ImGuiUtil.HalfBlendText(0x80u)); // Half red
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static void DrawShaderExportButton(ShpkTab tab, string objectName, Shader shader, int idx)
|
private static void DrawShaderExportButton(ShpkTab tab, string objectName, Shader shader, int idx)
|
||||||
{
|
{
|
||||||
if (!ImGui.Button($"Export Shader Program Blob ({shader.Blob.Length} bytes)"))
|
if (!ImUtf8.Button($"Export Shader Program Blob ({shader.Blob.Length} bytes)"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var defaultName = objectName[0] switch
|
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)
|
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;
|
return;
|
||||||
|
|
||||||
tab.FileDialog.OpenFilePicker($"Replace {objectName} #{idx} Program Blob...", "Shader Program Blobs{.o,.cso,.dxbc,.dxil}",
|
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)
|
private static unsafe void DrawRawDisassembly(Shader shader)
|
||||||
{
|
{
|
||||||
using var t2 = ImRaii.TreeNode("Raw Program Disassembly");
|
using var tree = ImUtf8.TreeNode("Raw Program Disassembly"u8);
|
||||||
if (!t2)
|
if (!tree)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||||
|
|
@ -164,31 +159,34 @@ public partial class ModEditWindow
|
||||||
{
|
{
|
||||||
foreach (var (key, keyIdx) in shader.SystemValues!.WithIndex())
|
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();
|
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (key, keyIdx) in shader.SceneValues!.WithIndex())
|
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();
|
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (key, keyIdx) in shader.MaterialValues!.WithIndex())
|
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();
|
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (key, keyIdx) in shader.SubViewValues!.WithIndex())
|
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();
|
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)
|
private static void DrawShaderPackageFilterSection(ShpkTab tab)
|
||||||
|
|
@ -215,19 +213,20 @@ public partial class ModEditWindow
|
||||||
{
|
{
|
||||||
if (values.PossibleValues == null)
|
if (values.PossibleValues == null)
|
||||||
{
|
{
|
||||||
ImRaii.TreeNode(label, ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
ImUtf8.TreeNode(label, ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using var node = ImRaii.TreeNode(label);
|
using var node = ImUtf8.TreeNode(label);
|
||||||
if (!node)
|
if (!node)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var value in values.PossibleValues)
|
foreach (var value in values.PossibleValues)
|
||||||
{
|
{
|
||||||
var contains = values.Contains(value);
|
var contains = values.Contains(value);
|
||||||
if (!ImGui.Checkbox($"{tab.TryResolveName(value)}", ref contains))
|
if (!ImUtf8.Checkbox($"{tab.TryResolveName(value)}", ref contains))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (contains)
|
if (contains)
|
||||||
{
|
{
|
||||||
if (values.AddExisting(value))
|
if (values.AddExisting(value))
|
||||||
|
|
@ -249,7 +248,7 @@ public partial class ModEditWindow
|
||||||
|
|
||||||
private static bool DrawShaderPackageShaderArray(ShpkTab tab, string objectName, Shader[] shaders, bool disabled)
|
private static bool DrawShaderPackageShaderArray(ShpkTab tab, string objectName, Shader[] shaders, bool disabled)
|
||||||
{
|
{
|
||||||
if (shaders.Length == 0 || !ImGui.CollapsingHeader($"{objectName}s"))
|
if (shaders.Length == 0 || !ImUtf8.CollapsingHeader($"{objectName}s"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var ret = false;
|
var ret = false;
|
||||||
|
|
@ -259,7 +258,7 @@ public partial class ModEditWindow
|
||||||
if (!tab.IsFilterMatch(shader))
|
if (!tab.IsFilterMatch(shader))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
using var t = ImRaii.TreeNode($"{objectName} #{idx}");
|
using var t = ImUtf8.TreeNode($"{objectName} #{idx}");
|
||||||
if (!t)
|
if (!t)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -277,13 +276,13 @@ public partial class ModEditWindow
|
||||||
ret |= DrawShaderPackageResourceArray("Unordered Access Views", "slot", true, shader.Uavs, false, true);
|
ret |= DrawShaderPackageResourceArray("Unordered Access Views", "slot", true, shader.Uavs, false, true);
|
||||||
|
|
||||||
if (shader.DeclaredInputs != 0)
|
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)
|
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)
|
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)
|
if (t2)
|
||||||
Widget.DrawHexViewer(shader.AdditionalHeader);
|
Widget.DrawHexViewer(shader.AdditionalHeader);
|
||||||
}
|
}
|
||||||
|
|
@ -313,23 +312,28 @@ public partial class ModEditWindow
|
||||||
var usedString = UsedComponentString(withSize, false, resource);
|
var usedString = UsedComponentString(withSize, false, resource);
|
||||||
if (usedString.Length > 0)
|
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)
|
if (hasFilter)
|
||||||
{
|
{
|
||||||
var filteredUsedString = UsedComponentString(withSize, true, resource);
|
var filteredUsedString = UsedComponentString(withSize, true, resource);
|
||||||
if (filteredUsedString.Length > 0)
|
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
|
else
|
||||||
ImRaii.TreeNode("Unused within Filters", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
ImUtf8.TreeNode("Unused within Filters"u8, ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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;
|
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)
|
if (resources.Length == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -345,8 +349,8 @@ public partial class ModEditWindow
|
||||||
var name = $"#{idx}: {buf.Name} (ID: 0x{buf.Id:X8}), {slotLabel}: {buf.Slot}"
|
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);
|
+ (withSize ? $", size: {buf.Size} registers###{idx}: {buf.Name} (ID: 0x{buf.Id:X8})" : string.Empty);
|
||||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||||
using var t2 = ImRaii.TreeNode(name, !disabled || buf.Used != null ? 0 : ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet);
|
using var t2 = ImUtf8.TreeNode(name, !disabled || buf.Used != null ? 0 : ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet);
|
||||||
font.Dispose();
|
font.Pop();
|
||||||
if (t2)
|
if (t2)
|
||||||
ret |= DrawShaderPackageResource(slotLabel, withSize, ref buf, hasFilter, disabled);
|
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(),
|
+ new Vector2(ImGui.CalcTextSize(label).X + 3 * ImGui.GetStyle().ItemInnerSpacing.X + ImGui.GetFrameHeight(),
|
||||||
ImGui.GetStyle().FramePadding.Y);
|
ImGui.GetStyle().FramePadding.Y);
|
||||||
|
|
||||||
var ret = ImGui.CollapsingHeader(label);
|
var ret = ImUtf8.CollapsingHeader(label);
|
||||||
ImGui.GetWindowDrawList()
|
ImGui.GetWindowDrawList()
|
||||||
.AddText(UiBuilder.DefaultFont, UiBuilder.DefaultFont.FontSize, pos, ImGui.GetColorU32(ImGuiCol.Text), "Layout");
|
.AddText(UiBuilder.DefaultFont, UiBuilder.DefaultFont.FontSize, pos, ImGui.GetColorU32(ImGuiCol.Text), "Layout");
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -374,7 +378,7 @@ public partial class ModEditWindow
|
||||||
if (isSizeWellDefined)
|
if (isSizeWellDefined)
|
||||||
return true;
|
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 ≠ {materialParams.Value.Size} registers ({materialParams.Value.Size << 4} bytes)"
|
||||||
: $"Buffer size mismatch: {file.MaterialParamsSize} bytes, not a multiple of 16");
|
: $"Buffer size mismatch: {file.MaterialParamsSize} bytes, not a multiple of 16");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -382,7 +386,7 @@ public partial class ModEditWindow
|
||||||
|
|
||||||
private static bool DrawShaderPackageMaterialMatrix(ShpkTab tab, bool disabled)
|
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, globally unused values are red, unused values within filters are yellow):"
|
||||||
: "Parameter positions (continuations are grayed out):");
|
: "Parameter positions (continuations are grayed out):");
|
||||||
|
|
||||||
|
|
@ -399,9 +403,6 @@ public partial class ModEditWindow
|
||||||
ImGui.TableHeadersRow();
|
ImGui.TableHeadersRow();
|
||||||
|
|
||||||
var textColorStart = ImGui.GetColorU32(ImGuiCol.Text);
|
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 ret = false;
|
var ret = false;
|
||||||
for (var i = 0; i < tab.Matrix.GetLength(0); ++i)
|
for (var i = 0; i < tab.Matrix.GetLength(0); ++i)
|
||||||
|
|
@ -420,12 +421,12 @@ public partial class ModEditWindow
|
||||||
color = ImGuiUtil.HalfTransparent(color); // Half opacity
|
color = ImGuiUtil.HalfTransparent(color); // Half opacity
|
||||||
using var _ = ImRaii.PushId(i * 4 + j);
|
using var _ = ImRaii.PushId(i * 4 + j);
|
||||||
var deletable = !disabled && idx >= 0;
|
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.TableNextColumn();
|
||||||
ImGui.Selectable(name);
|
ImUtf8.Selectable(name);
|
||||||
if (deletable && ImGui.IsItemClicked(ImGuiMouseButton.Right) && ImGui.GetIO().KeyCtrl)
|
if (deletable && ImGui.IsItemClicked(ImGuiMouseButton.Right) && ImGui.GetIO().KeyCtrl)
|
||||||
{
|
{
|
||||||
tab.Shpk.MaterialParams = tab.Shpk.MaterialParams.RemoveItems(idx);
|
tab.Shpk.MaterialParams = tab.Shpk.MaterialParams.RemoveItems(idx);
|
||||||
|
|
@ -434,11 +435,11 @@ public partial class ModEditWindow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGuiUtil.HoverTooltip(tooltip);
|
ImUtf8.HoverTooltip(tooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deletable)
|
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))
|
if (!ImUtf8.Button("Export globally unused parameters as material dev-kit file"u8))
|
||||||
return;
|
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)
|
void DoSave(bool success, string path)
|
||||||
{
|
{
|
||||||
|
|
@ -476,22 +479,22 @@ public partial class ModEditWindow
|
||||||
|
|
||||||
private static void DrawShaderPackageMisalignedParameters(ShpkTab tab)
|
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)
|
if (!t)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using var _ = ImRaii.PushFont(UiBuilder.MonoFont);
|
using var _ = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||||
foreach (var name in tab.MalformedParameters)
|
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)
|
private static void DrawShaderPackageStartCombo(ShpkTab tab)
|
||||||
{
|
{
|
||||||
using var s = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemInnerSpacing);
|
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);
|
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)
|
if (c)
|
||||||
foreach (var (start, idx) in tab.Orphans.WithIndex())
|
foreach (var (start, idx) in tab.Orphans.WithIndex())
|
||||||
{
|
{
|
||||||
|
|
@ -501,7 +504,7 @@ public partial class ModEditWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.TextUnformatted("Start");
|
ImUtf8.Text("Start"u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DrawShaderPackageEndCombo(ShpkTab tab)
|
private static void DrawShaderPackageEndCombo(ShpkTab tab)
|
||||||
|
|
@ -510,7 +513,7 @@ public partial class ModEditWindow
|
||||||
using (var _ = ImRaii.PushFont(UiBuilder.MonoFont))
|
using (var _ = ImRaii.PushFont(UiBuilder.MonoFont))
|
||||||
{
|
{
|
||||||
ImGui.SetNextItemWidth(UiHelpers.Scale * 400);
|
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)
|
if (c)
|
||||||
{
|
{
|
||||||
var current = tab.Orphans[tab.NewMaterialParamStart].Index;
|
var current = tab.Orphans[tab.NewMaterialParamStart].Index;
|
||||||
|
|
@ -527,7 +530,7 @@ public partial class ModEditWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.TextUnformatted("End");
|
ImUtf8.Text("End"u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool DrawShaderPackageNewParameter(ShpkTab tab)
|
private static bool DrawShaderPackageNewParameter(ShpkTab tab)
|
||||||
|
|
@ -540,15 +543,14 @@ public partial class ModEditWindow
|
||||||
|
|
||||||
ImGui.SetNextItemWidth(UiHelpers.Scale * 400);
|
ImGui.SetNextItemWidth(UiHelpers.Scale * 400);
|
||||||
var newName = tab.NewMaterialParamName.Value!;
|
var newName = tab.NewMaterialParamName.Value!;
|
||||||
if (ImGui.InputText("Name", ref newName, 63))
|
if (ImUtf8.InputText("Name", ref newName))
|
||||||
tab.NewMaterialParamName = newName;
|
tab.NewMaterialParamName = newName;
|
||||||
|
|
||||||
var tooltip = tab.UsedIds.Contains(tab.NewMaterialParamName.Crc32)
|
var tooltip = tab.UsedIds.Contains(tab.NewMaterialParamName.Crc32)
|
||||||
? "The ID is already in use. Please choose a different name."
|
? "The ID is already in use. Please choose a different name."u8
|
||||||
: string.Empty;
|
: ""u8;
|
||||||
if (!ImGuiUtil.DrawDisabledButton($"Add {tab.NewMaterialParamName} (0x{tab.NewMaterialParamName.Crc32:X8})", new Vector2(400 * UiHelpers.Scale, ImGui.GetFrameHeight()),
|
if (!ImUtf8.ButtonEx($"Add {tab.NewMaterialParamName} (0x{tab.NewMaterialParamName.Crc32:X8})", tooltip,
|
||||||
tooltip,
|
new Vector2(400 * UiHelpers.Scale, ImGui.GetFrameHeight()), tooltip.Length > 0))
|
||||||
tooltip.Length > 0))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
tab.Shpk.MaterialParams = tab.Shpk.MaterialParams.AddItem(new MaterialParam
|
tab.Shpk.MaterialParams = tab.Shpk.MaterialParams.AddItem(new MaterialParam
|
||||||
|
|
@ -589,7 +591,7 @@ public partial class ModEditWindow
|
||||||
{
|
{
|
||||||
var ret = false;
|
var ret = false;
|
||||||
|
|
||||||
if (!ImGui.CollapsingHeader("Shader Resources"))
|
if (!ImUtf8.CollapsingHeader("Shader Resources"u8))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var hasFilters = tab.FilterPopCount != tab.FilterMaximumPopCount;
|
var hasFilters = tab.FilterPopCount != tab.FilterMaximumPopCount;
|
||||||
|
|
@ -607,18 +609,20 @@ public partial class ModEditWindow
|
||||||
if (keys.Count == 0)
|
if (keys.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using var t = ImRaii.TreeNode(arrayName);
|
using var t = ImUtf8.TreeNode(arrayName);
|
||||||
if (!t)
|
if (!t)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||||
foreach (var (key, idx) in keys.WithIndex())
|
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)
|
if (t2)
|
||||||
{
|
{
|
||||||
ImRaii.TreeNode($"Default Value: {tab.TryResolveName(key.DefaultValue)} (0x{key.DefaultValue:X8})", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
ImUtf8.TreeNode($"Default Value: {tab.TryResolveName(key.DefaultValue)} (0x{key.DefaultValue:X8})",
|
||||||
ImRaii.TreeNode($"Known Values: {tab.NameSetToString(key.Values, true)}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
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)
|
if (tab.Shpk.Nodes.Length <= 0)
|
||||||
return;
|
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)
|
if (!t)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -639,39 +643,44 @@ public partial class ModEditWindow
|
||||||
if (!tab.IsFilterMatch(node))
|
if (!tab.IsFilterMatch(node))
|
||||||
continue;
|
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)
|
if (!t2)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
foreach (var (key, keyIdx) in node.SystemKeys.WithIndex())
|
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();
|
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (key, keyIdx) in node.SceneKeys.WithIndex())
|
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();
|
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (key, keyIdx) in node.MaterialKeys.WithIndex())
|
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();
|
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (key, keyIdx) in node.SubViewKeys.WithIndex())
|
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();
|
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();
|
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||||
foreach (var (pass, passIdx) in node.Passes.WithIndex())
|
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)
|
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet)
|
||||||
.Dispose();
|
.Dispose();
|
||||||
}
|
}
|
||||||
|
|
@ -680,7 +689,7 @@ public partial class ModEditWindow
|
||||||
|
|
||||||
private static void DrawShaderPackageSelection(ShpkTab tab)
|
private static void DrawShaderPackageSelection(ShpkTab tab)
|
||||||
{
|
{
|
||||||
if (!ImGui.CollapsingHeader("Shader Selection"))
|
if (!ImUtf8.CollapsingHeader("Shader Selection"u8))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DrawKeyArray(tab, "System Keys", true, tab.Shpk.SystemKeys);
|
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);
|
DrawKeyArray(tab, "Sub-View Keys", false, tab.Shpk.SubViewKeys);
|
||||||
|
|
||||||
DrawShaderPackageNodes(tab);
|
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)
|
if (t)
|
||||||
{
|
{
|
||||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||||
foreach (var selector in tab.Shpk.NodeSelectors)
|
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();
|
.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -703,14 +712,14 @@ public partial class ModEditWindow
|
||||||
|
|
||||||
private static void DrawOtherShaderPackageDetails(ShpkTab tab)
|
private static void DrawOtherShaderPackageDetails(ShpkTab tab)
|
||||||
{
|
{
|
||||||
if (!ImGui.CollapsingHeader("Further Content"))
|
if (!ImUtf8.CollapsingHeader("Further Content"u8))
|
||||||
return;
|
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)
|
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)
|
if (t)
|
||||||
Widget.DrawHexViewer(tab.Shpk.AdditionalData);
|
Widget.DrawHexViewer(tab.Shpk.AdditionalData);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,10 @@ public partial class ModEditWindow
|
||||||
public short NewMaterialParamStart;
|
public short NewMaterialParamStart;
|
||||||
public short NewMaterialParamEnd;
|
public short NewMaterialParamEnd;
|
||||||
|
|
||||||
public SharedSet<uint, uint>[] FilterSystemValues;
|
public readonly SharedSet<uint, uint>[] FilterSystemValues;
|
||||||
public SharedSet<uint, uint>[] FilterSceneValues;
|
public readonly SharedSet<uint, uint>[] FilterSceneValues;
|
||||||
public SharedSet<uint, uint>[] FilterMaterialValues;
|
public readonly SharedSet<uint, uint>[] FilterMaterialValues;
|
||||||
public SharedSet<uint, uint>[] FilterSubViewValues;
|
public readonly SharedSet<uint, uint>[] FilterSubViewValues;
|
||||||
public SharedSet<uint, uint> FilterPasses;
|
public SharedSet<uint, uint> FilterPasses;
|
||||||
|
|
||||||
public readonly int FilterMaximumPopCount;
|
public readonly int FilterMaximumPopCount;
|
||||||
|
|
@ -46,6 +46,7 @@ public partial class ModEditWindow
|
||||||
{
|
{
|
||||||
Shpk = new ShpkFile(bytes, false);
|
Shpk = new ShpkFile(bytes, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath = filePath;
|
FilePath = filePath;
|
||||||
|
|
||||||
Header = $"Shader Package for DirectX {(int)Shpk.DirectXVersion}";
|
Header = $"Shader Package for DirectX {(int)Shpk.DirectXVersion}";
|
||||||
|
|
@ -105,13 +106,21 @@ public partial class ModEditWindow
|
||||||
_nameSetWithIdsCache.Clear();
|
_nameSetWithIdsCache.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateNameCache()
|
private void UpdateNameCache()
|
||||||
{
|
{
|
||||||
static void CollectResourceNames(Dictionary<uint, Name> nameCache, ShpkFile.Resource[] resources)
|
CollectResourceNames(_nameCache, Shpk.Constants);
|
||||||
{
|
CollectResourceNames(_nameCache, Shpk.Samplers);
|
||||||
foreach (var resource in resources)
|
CollectResourceNames(_nameCache, Shpk.Textures);
|
||||||
nameCache.TryAdd(resource.Id, resource.Name);
|
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)
|
static void CollectKeyNames(Dictionary<uint, Name> nameCache, ShpkFile.Key[] keys)
|
||||||
{
|
{
|
||||||
|
|
@ -128,18 +137,11 @@ public partial class ModEditWindow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectResourceNames(_nameCache, Shpk.Constants);
|
static void CollectResourceNames(Dictionary<uint, Name> nameCache, ShpkFile.Resource[] resources)
|
||||||
CollectResourceNames(_nameCache, Shpk.Samplers);
|
{
|
||||||
CollectResourceNames(_nameCache, Shpk.Textures);
|
foreach (var resource in resources)
|
||||||
CollectResourceNames(_nameCache, Shpk.Uavs);
|
nameCache.TryAdd(resource.Id, resource.Name);
|
||||||
|
}
|
||||||
CollectKeyNames(_nameCache, Shpk.SystemKeys);
|
|
||||||
CollectKeyNames(_nameCache, Shpk.SceneKeys);
|
|
||||||
CollectKeyNames(_nameCache, Shpk.MaterialKeys);
|
|
||||||
CollectKeyNames(_nameCache, Shpk.SubViewKeys);
|
|
||||||
|
|
||||||
_nameSetCache.Clear();
|
|
||||||
_nameSetWithIdsCache.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
|
@ -151,6 +153,7 @@ public partial class ModEditWindow
|
||||||
var cache = withIds ? _nameSetWithIdsCache : _nameSetCache;
|
var cache = withIds ? _nameSetWithIdsCache : _nameSetCache;
|
||||||
if (cache.TryGetValue(nameSet, out var nameSetStr))
|
if (cache.TryGetValue(nameSet, out var nameSetStr))
|
||||||
return nameSetStr;
|
return nameSetStr;
|
||||||
|
|
||||||
if (withIds)
|
if (withIds)
|
||||||
nameSetStr = string.Join(", ", nameSet.Select(id => $"{TryResolveName(id)} (0x{id:X8})"));
|
nameSetStr = string.Join(", ", nameSet.Select(id => $"{TryResolveName(id)} (0x{id:X8})"));
|
||||||
else
|
else
|
||||||
|
|
@ -186,7 +189,8 @@ public partial class ModEditWindow
|
||||||
var jEnd = ((param.ByteOffset + param.ByteSize - 1) >> 2) & 3;
|
var jEnd = ((param.ByteOffset + param.ByteSize - 1) >> 2) & 3;
|
||||||
if ((param.ByteOffset & 0x3) != 0 || (param.ByteSize & 0x3) != 0)
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -206,7 +210,8 @@ public partial class ModEditWindow
|
||||||
var tt =
|
var tt =
|
||||||
$"{MtrlTab.MaterialParamRangeName(materialParams?.Name ?? string.Empty, param.ByteOffset >> 2, param.ByteSize >> 2).Item1} ({TryResolveName(param.Id)}, 0x{param.Id:X8})";
|
$"{MtrlTab.MaterialParamRangeName(materialParams?.Name ?? string.Empty, param.ByteOffset >> 2, param.ByteSize >> 2).Item1} ({TryResolveName(param.Id)}, 0x{param.Id:X8})";
|
||||||
if (component < defaultFloats.Length)
|
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);
|
Matrix[i, j] = (TryResolveName(param.Id).ToString(), tt, (short)idx, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -265,7 +270,8 @@ public partial class ModEditWindow
|
||||||
if (oldStart == linear)
|
if (oldStart == linear)
|
||||||
newMaterialParamStart = (short)Orphans.Count;
|
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();
|
var unusedSlices = new JArray();
|
||||||
|
|
||||||
if (materialParameterUsage.Indices(start, length).Any())
|
if (materialParameterUsage.Indices(start, length).Any())
|
||||||
{
|
|
||||||
foreach (var (rgStart, rgEnd) in materialParameterUsage.Ranges(start, length, true))
|
foreach (var (rgStart, rgEnd) in materialParameterUsage.Ranges(start, length, true))
|
||||||
{
|
{
|
||||||
unusedSlices.Add(new JObject
|
unusedSlices.Add(new JObject
|
||||||
|
|
@ -417,14 +422,11 @@ public partial class ModEditWindow
|
||||||
["Length"] = rgEnd - rgStart,
|
["Length"] = rgEnd - rgStart,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
unusedSlices.Add(new JObject
|
unusedSlices.Add(new JObject
|
||||||
{
|
{
|
||||||
["Type"] = "Hidden",
|
["Type"] = "Hidden",
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
dkConstants[param.Id.ToString()] = unusedSlices;
|
dkConstants[param.Id.ToString()] = unusedSlices;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue