MtrlTab UI improvements and code deduplication

This commit is contained in:
Exter-N 2024-08-17 04:34:09 +02:00
parent 1da095be99
commit 5a241e3dbb
9 changed files with 99 additions and 176 deletions

@ -1 +1 @@
Subproject commit b7fdfe9d19f7e3229834480db446478b0bf6acee Subproject commit 0784569ab59c96b2058730cdb4cefd61c96b5f1a

View file

@ -107,7 +107,9 @@ public class Configuration : IPluginConfiguration, ISavable, IService
public bool AlwaysOpenDefaultImport { get; set; } = false; public bool AlwaysOpenDefaultImport { get; set; } = false;
public bool KeepDefaultMetaChanges { get; set; } = false; public bool KeepDefaultMetaChanges { get; set; } = false;
public string DefaultModAuthor { get; set; } = DefaultTexToolsData.Author; public string DefaultModAuthor { get; set; } = DefaultTexToolsData.Author;
public bool EditRawTileTransforms { get; set; } = false; public bool EditRawTileTransforms { get; set; } = false;
public bool WholePairSelectorAlwaysHighlights { get; set; } = false;
public Dictionary<ColorId, uint> Colors { get; set; } public Dictionary<ColorId, uint> Colors { get; set; }
= Enum.GetValues<ColorId>().ToDictionary(c => c, c => c.Data().DefaultColor); = Enum.GetValues<ColorId>().ToDictionary(c => c, c => c.Data().DefaultColor);

View file

@ -13,15 +13,13 @@ public partial class MtrlTab
{ {
private const float ColorTableScalarSize = 65.0f; private const float ColorTableScalarSize = 65.0f;
private int _colorTableSelectedPair; private bool DrawColorTable(ColorTable table, ColorDyeTable? dyeTable, bool disabled, MtrlTabUiState uiState)
private bool DrawColorTable(ColorTable table, ColorDyeTable? dyeTable, bool disabled)
{ {
DrawColorTablePairSelector(table, disabled); DrawColorTablePairSelector(table, disabled, uiState);
return DrawColorTablePairEditor(table, dyeTable, disabled); return DrawColorTablePairEditor(table, dyeTable, disabled, uiState);
} }
private void DrawColorTablePairSelector(ColorTable table, bool disabled) private void DrawColorTablePairSelector<TRow>(IColorTable<TRow> table, bool disabled, MtrlTabUiState uiState) where TRow : unmanaged, IColorRow
{ {
var style = ImGui.GetStyle(); var style = ImGui.GetStyle();
var itemSpacing = style.ItemSpacing.X; var itemSpacing = style.ItemSpacing.X;
@ -38,16 +36,17 @@ public partial class MtrlTab
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);
for (var i = 0; i < ColorTable.NumRows >> 1; i += 8) for (var i = 0; i < table.Height >> 1; i += 8)
{ {
for (var j = 0; j < 8; ++j) var numPairsInRow = Math.Min(8, (table.Height >> 1) - i);
for (var j = 0; j < numPairsInRow; ++j)
{ {
var pairIndex = i + j; var pairIndex = i + j;
using (ImRaii.PushColor(ImGuiCol.Button, ImGui.GetColorU32(ImGuiCol.ButtonActive), pairIndex == _colorTableSelectedPair)) using (ImRaii.PushColor(ImGuiCol.Button, ImGui.GetColorU32(ImGuiCol.ButtonActive), pairIndex == uiState.ColorTableSelectedPair))
{ {
if (ImUtf8.Button($"#{pairIndex + 1}".PadLeft(3 + spacePadding), if (ImUtf8.Button($"#{pairIndex + 1}".PadLeft(3 + spacePadding),
new Vector2(buttonWidth, ImGui.GetFrameHeightWithSpacing() + frameHeight))) new Vector2(buttonWidth, ImGui.GetFrameHeightWithSpacing() + frameHeight)))
_colorTableSelectedPair = pairIndex; uiState.ColorTableSelectedPair = pairIndex;
} }
var rcMin = ImGui.GetItemRectMin() + framePadding; var rcMin = ImGui.GetItemRectMin() + framePadding;
@ -69,7 +68,7 @@ public partial class MtrlTab
ImGuiUtil.ColorConvertFloat3ToU32(PseudoSqrtRgb((Vector3)table[pairIndex << 1].EmissiveColor)), ImGuiUtil.ColorConvertFloat3ToU32(PseudoSqrtRgb((Vector3)table[pairIndex << 1].EmissiveColor)),
ImGuiUtil.ColorConvertFloat3ToU32(PseudoSqrtRgb((Vector3)table[(pairIndex << 1) | 1].EmissiveColor)) ImGuiUtil.ColorConvertFloat3ToU32(PseudoSqrtRgb((Vector3)table[(pairIndex << 1) | 1].EmissiveColor))
); );
if (j < 7) if (j + 1 < numPairsInRow)
ImGui.SameLine(); ImGui.SameLine();
var cursor = ImGui.GetCursorScreenPos(); var cursor = ImGui.GetCursorScreenPos();
@ -82,14 +81,14 @@ public partial class MtrlTab
} }
} }
private bool DrawColorTablePairEditor(ColorTable table, ColorDyeTable? dyeTable, bool disabled) private bool DrawColorTablePairEditor(ColorTable table, ColorDyeTable? dyeTable, bool disabled, MtrlTabUiState uiState)
{ {
var retA = false; var retA = false;
var retB = false; var retB = false;
var rowAIdx = _colorTableSelectedPair << 1; var rowAIdx = uiState.ColorTableSelectedPair << 1;
var rowBIdx = rowAIdx | 1; var rowBIdx = rowAIdx | 1;
var dyeA = dyeTable?[_colorTableSelectedPair << 1] ?? default; var dyeA = dyeTable?[uiState.ColorTableSelectedPair << 1] ?? default;
var dyeB = dyeTable?[(_colorTableSelectedPair << 1) | 1] ?? default; var dyeB = dyeTable?[(uiState.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);
@ -335,7 +334,6 @@ 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 ret = false; var ret = false;
ref var row = ref table[rowIdx]; ref var row = ref table[rowIdx];
@ -387,6 +385,20 @@ public partial class MtrlTab
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
ret |= DrawTemplateTile(table, rowIdx);
return ret;
}
private bool DrawTemplateTile<TRow>(IColorTable<TRow> table, int rowIdx) where TRow : unmanaged, IColorRow
{
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
var itemSpacing = ImGui.GetStyle().ItemSpacing.X;
var subColWidth = CalculateSubColumnWidth(2);
var ret = false;
ref var row = ref table[rowIdx];
var leftLineHeight = 64.0f + ImGui.GetStyle().FramePadding.Y * 2.0f; var leftLineHeight = 64.0f + ImGui.GetStyle().FramePadding.Y * 2.0f;
var rightLineHeight = 3.0f * ImGui.GetFrameHeight() + 2.0f * ImGui.GetStyle().ItemSpacing.Y; var rightLineHeight = 3.0f * ImGui.GetFrameHeight() + 2.0f * ImGui.GetStyle().ItemSpacing.Y;
var lineHeight = Math.Max(leftLineHeight, rightLineHeight); var lineHeight = Math.Max(leftLineHeight, rightLineHeight);
@ -406,8 +418,13 @@ public partial class MtrlTab
ImGui.Dummy(new Vector2(scalarSize, 0.0f)); ImGui.Dummy(new Vector2(scalarSize, 0.0f));
ImUtf8.SameLineInner(); ImUtf8.SameLineInner();
ImGui.SetNextItemWidth(scalarSize); ImGui.SetNextItemWidth(scalarSize);
if (table is ColorTable rwTable)
{
ret |= CtDragScalar("Tile Opacity"u8, default, (float)row.TileAlpha * 100.0f, "%.0f%%"u8, 0.0f, HalfMaxValue * 100.0f, 1.0f, ret |= CtDragScalar("Tile Opacity"u8, default, (float)row.TileAlpha * 100.0f, "%.0f%%"u8, 0.0f, HalfMaxValue * 100.0f, 1.0f,
v => table[rowIdx].TileAlpha = (Half)(v * 0.01f)); v => rwTable[rowIdx].TileAlpha = (Half)(v * 0.01f));
}
else
CtDragScalar<float>("Tile Opacity"u8, default, (float)row.TileAlpha * 100.0f, "%.0f%%"u8);
ret |= CtTileTransformMatrix(row.TileTransform, scalarSize, true, ret |= CtTileTransformMatrix(row.TileTransform, scalarSize, true,
m => table[rowIdx].TileTransform = m); m => table[rowIdx].TileTransform = m);

View file

@ -20,7 +20,7 @@ public partial class MtrlTab
private static (Vector2 Scale, float Rotation, float Shear)? _pinnedTileTransform; private static (Vector2 Scale, float Rotation, float Shear)? _pinnedTileTransform;
private bool DrawColorTableSection(bool disabled) private bool DrawColorTableSection(bool disabled, MtrlTabUiState uiState)
{ {
if (!_shpkLoading && !SamplerIds.Contains(ShpkFile.TableSamplerId) || Mtrl.Table == null) if (!_shpkLoading && !SamplerIds.Contains(ShpkFile.TableSamplerId) || Mtrl.Table == null)
return false; return false;
@ -53,7 +53,7 @@ public partial class MtrlTab
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, ColorTable table when Mtrl.ShaderPackage.Name is "characterlegacy.shpk" => DrawLegacyColorTable(table,
Mtrl.DyeTable as ColorDyeTable, disabled), Mtrl.DyeTable as ColorDyeTable, disabled),
ColorTable table => DrawColorTable(table, Mtrl.DyeTable as ColorDyeTable, disabled), ColorTable table => DrawColorTable(table, Mtrl.DyeTable as ColorDyeTable, disabled, uiState),
_ => false, _ => false,
}; };
@ -230,11 +230,13 @@ public partial class MtrlTab
private void ColorTablePairHighlightButton(int pairIdx, bool disabled) private void ColorTablePairHighlightButton(int pairIdx, bool disabled)
{ {
var wholePairSelectorHighlight = (_config.WholePairSelectorAlwaysHighlights || ImGui.GetIO().KeyCtrl) && ImGui.IsItemHovered();
ImUtf8.IconButton(FontAwesomeIcon.Crosshairs, 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, "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); ImGui.GetFrameHeight() * Vector2.One, disabled || _colorTablePreviewers.Count == 0);
if (ImGui.IsItemHovered()) if (wholePairSelectorHighlight || ImGui.IsItemHovered())
HighlightColorTablePair(pairIdx); HighlightColorTablePair(pairIdx);
else if (_highlightedColorTablePair == pairIdx) else if (_highlightedColorTablePair == pairIdx)
CancelColorTableHighlight(); CancelColorTableHighlight();
@ -266,14 +268,14 @@ public partial class MtrlTab
else else
{ {
drawList.AddRectFilled( drawList.AddRectFilled(
rcMin, rcMax with { Y = float.Lerp(rcMin.Y, rcMax.Y, 1.0f / 3) }, rcMin, rcMax with { Y = MathF.Floor(float.Lerp(rcMin.Y, rcMax.Y, 1.0f / 3)) },
topColor, frameRounding, ImDrawFlags.RoundCornersTopLeft | ImDrawFlags.RoundCornersTopRight); topColor, frameRounding, ImDrawFlags.RoundCornersTopLeft | ImDrawFlags.RoundCornersTopRight);
drawList.AddRectFilledMultiColor( drawList.AddRectFilledMultiColor(
rcMin with { Y = float.Lerp(rcMin.Y, rcMax.Y, 1.0f / 3) }, rcMin with { Y = MathF.Floor(float.Lerp(rcMin.Y, rcMax.Y, 1.0f / 3)) },
rcMax with { Y = float.Lerp(rcMin.Y, rcMax.Y, 2.0f / 3) }, rcMax with { Y = MathF.Ceiling(float.Lerp(rcMin.Y, rcMax.Y, 2.0f / 3)) },
topColor, topColor, bottomColor, bottomColor); topColor, topColor, bottomColor, bottomColor);
drawList.AddRectFilled( drawList.AddRectFilled(
rcMin with { Y = float.Lerp(rcMin.Y, rcMax.Y, 2.0f / 3) }, rcMax, rcMin with { Y = MathF.Ceiling(float.Lerp(rcMin.Y, rcMax.Y, 2.0f / 3)) }, rcMax,
bottomColor, frameRounding, ImDrawFlags.RoundCornersBottomLeft | ImDrawFlags.RoundCornersBottomRight); bottomColor, frameRounding, ImDrawFlags.RoundCornersBottomLeft | ImDrawFlags.RoundCornersBottomRight);
} }

View file

@ -16,31 +16,8 @@ public partial class MtrlTab
private const float LegacyColorTableIntegerSize = 40.0f; private const float LegacyColorTableIntegerSize = 40.0f;
private const float LegacyColorTableByteSize = 25.0f; private const float LegacyColorTableByteSize = 25.0f;
private bool DrawLegacyColorTable(LegacyColorTable table, LegacyColorDyeTable? dyeTable, bool disabled) private bool DrawLegacyColorTable<TRow, TDyeRow>(IColorTable<TRow> table, IColorDyeTable<TDyeRow>? dyeTable, bool disabled)
{ where TRow : unmanaged, ILegacyColorRow where TDyeRow : unmanaged, ILegacyColorDyeRow
using var imTable = ImUtf8.Table("##ColorTable"u8, dyeTable != null ? 10 : 8,
ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersInnerV);
if (!imTable)
return false;
DrawLegacyColorTableHeader(dyeTable != null);
var ret = false;
for (var i = 0; i < LegacyColorTable.NumRows; ++i)
{
if (DrawLegacyColorTableRow(table, dyeTable, i, disabled))
{
UpdateColorTableRowPreview(i);
ret = true;
}
ImGui.TableNextRow();
}
return ret;
}
private bool DrawLegacyColorTable(ColorTable table, ColorDyeTable? dyeTable, bool disabled)
{ {
using var imTable = ImUtf8.Table("##ColorTable"u8, dyeTable != null ? 10 : 8, using var imTable = ImUtf8.Table("##ColorTable"u8, dyeTable != null ? 10 : 8,
ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersInnerV); ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersInnerV);
@ -91,113 +68,8 @@ public partial class MtrlTab
} }
} }
private bool DrawLegacyColorTableRow(LegacyColorTable table, LegacyColorDyeTable? dyeTable, int rowIdx, bool disabled) private bool DrawLegacyColorTableRow<TRow, TDyeRow>(IColorTable<TRow> table, IColorDyeTable<TDyeRow>? dyeTable, int rowIdx, bool disabled)
{ where TRow : unmanaged, ILegacyColorRow where TDyeRow : unmanaged, ILegacyColorDyeRow
using var id = ImRaii.PushId(rowIdx);
ref var row = ref table[rowIdx];
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
var floatSize = LegacyColorTableFloatSize * UiHelpers.Scale;
var pctSize = LegacyColorTablePercentageSize * UiHelpers.Scale;
var intSize = LegacyColorTableIntegerSize * UiHelpers.Scale;
ImGui.TableNextColumn();
ColorTableCopyClipboardButton(rowIdx);
ImUtf8.SameLineInner();
var ret = ColorTablePasteFromClipboardButton(rowIdx, disabled);
ImUtf8.SameLineInner();
ColorTableRowHighlightButton(rowIdx, disabled);
ImGui.TableNextColumn();
using (ImRaii.PushFont(UiBuilder.MonoFont))
{
ImUtf8.Text($"{(rowIdx >> 1) + 1,2:D}{"AB"[rowIdx & 1]}");
}
ImGui.TableNextColumn();
using var dis = ImRaii.Disabled(disabled);
ret |= CtColorPicker("##Diffuse"u8, "Diffuse Color"u8, row.DiffuseColor,
c => table[rowIdx].DiffuseColor = c);
if (dyeTable != null)
{
ImUtf8.SameLineInner();
ret |= CtApplyStainCheckbox("##dyeDiffuse"u8, "Apply Diffuse Color on Dye"u8, dye.DiffuseColor,
b => dyeTable[rowIdx].DiffuseColor = b);
}
ImGui.TableNextColumn();
ret |= CtColorPicker("##Specular"u8, "Specular Color"u8, row.SpecularColor,
c => table[rowIdx].SpecularColor = c);
if (dyeTable != null)
{
ImUtf8.SameLineInner();
ret |= CtApplyStainCheckbox("##dyeSpecular"u8, "Apply Specular Color on Dye"u8, dye.SpecularColor,
b => dyeTable[rowIdx].SpecularColor = b);
}
ImGui.SameLine();
ImGui.SetNextItemWidth(pctSize);
ret |= CtDragScalar("##SpecularMask"u8, "Specular Strength"u8, (float)row.SpecularMask * 100.0f, "%.0f%%"u8, 0f, HalfMaxValue * 100.0f,
1.0f,
v => table[rowIdx].SpecularMask = (Half)(v * 0.01f));
if (dyeTable != null)
{
ImUtf8.SameLineInner();
ret |= CtApplyStainCheckbox("##dyeSpecularMask"u8, "Apply Specular Strength on Dye"u8, dye.SpecularMask,
b => dyeTable[rowIdx].SpecularMask = b);
}
ImGui.TableNextColumn();
ret |= CtColorPicker("##Emissive"u8, "Emissive Color"u8, row.EmissiveColor,
c => table[rowIdx].EmissiveColor = c);
if (dyeTable != null)
{
ImUtf8.SameLineInner();
ret |= CtApplyStainCheckbox("##dyeEmissive"u8, "Apply Emissive Color on Dye"u8, dye.EmissiveColor,
b => dyeTable[rowIdx].EmissiveColor = b);
}
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(floatSize);
var glossStrengthMin = ImGui.GetIO().KeyCtrl ? 0.0f : HalfEpsilon;
ret |= CtDragHalf("##Shininess"u8, "Gloss Strength"u8, row.Shininess, "%.1f"u8, glossStrengthMin, HalfMaxValue,
Math.Max(0.1f, (float)row.Shininess * 0.025f),
v => table[rowIdx].Shininess = v);
if (dyeTable != null)
{
ImUtf8.SameLineInner();
ret |= CtApplyStainCheckbox("##dyeShininess"u8, "Apply Gloss Strength on Dye"u8, dye.Shininess,
b => dyeTable[rowIdx].Shininess = b);
}
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(intSize);
ret |= CtTileIndexPicker("##TileIndex"u8, "Tile Index"u8, row.TileIndex, true,
value => table[rowIdx].TileIndex = value);
ImGui.TableNextColumn();
ret |= CtTileTransformMatrix(row.TileTransform, floatSize, false,
m => table[rowIdx].TileTransform = m);
if (dyeTable != null)
{
ImGui.TableNextColumn();
if (_stainService.LegacyTemplateCombo.Draw("##dyeTemplate", dye.Template.ToString(), string.Empty, intSize
+ ImGui.GetStyle().ScrollbarSize / 2, ImGui.GetTextLineHeightWithSpacing(), ImGuiComboFlags.NoArrowButton))
{
dyeTable[rowIdx].Template = _stainService.LegacyTemplateCombo.CurrentSelection;
ret = true;
}
ImGuiUtil.HoverTooltip("Dye Template", ImGuiHoveredFlags.AllowWhenDisabled);
ImGui.TableNextColumn();
ret |= DrawLegacyDyePreview(rowIdx, disabled, dye, floatSize);
}
return ret;
}
private bool DrawLegacyColorTableRow(ColorTable table, ColorDyeTable? dyeTable, int rowIdx, bool disabled)
{ {
using var id = ImRaii.PushId(rowIdx); using var id = ImRaii.PushId(rowIdx);
ref var row = ref table[rowIdx]; ref var row = ref table[rowIdx];
@ -242,13 +114,13 @@ public partial class MtrlTab
ImGui.SameLine(); ImGui.SameLine();
ImGui.SetNextItemWidth(pctSize); ImGui.SetNextItemWidth(pctSize);
ret |= CtDragScalar("##SpecularMask"u8, "Specular Strength"u8, (float)row.Scalar7 * 100.0f, "%.0f%%"u8, 0f, HalfMaxValue * 100.0f, 1.0f, ret |= CtDragScalar("##SpecularMask"u8, "Specular Strength"u8, (float)row.SpecularMask * 100.0f, "%.0f%%"u8, 0f, HalfMaxValue * 100.0f, 1.0f,
v => table[rowIdx].Scalar7 = (Half)(v * 0.01f)); v => table[rowIdx].SpecularMask = (Half)(v * 0.01f));
if (dyeTable != null) if (dyeTable != null)
{ {
ImUtf8.SameLineInner(); ImUtf8.SameLineInner();
ret |= CtApplyStainCheckbox("##dyeSpecularMask"u8, "Apply Specular Strength on Dye"u8, dye.Metalness, ret |= CtApplyStainCheckbox("##dyeSpecularMask"u8, "Apply Specular Strength on Dye"u8, dye.SpecularMask,
b => dyeTable[rowIdx].Metalness = b); b => dyeTable[rowIdx].SpecularMask = b);
} }
ImGui.TableNextColumn(); ImGui.TableNextColumn();
@ -264,15 +136,15 @@ public partial class MtrlTab
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGui.SetNextItemWidth(floatSize); ImGui.SetNextItemWidth(floatSize);
var glossStrengthMin = ImGui.GetIO().KeyCtrl ? 0.0f : HalfEpsilon; var glossStrengthMin = ImGui.GetIO().KeyCtrl ? 0.0f : HalfEpsilon;
ret |= CtDragHalf("##Shininess"u8, "Gloss Strength"u8, row.Scalar3, "%.1f"u8, glossStrengthMin, HalfMaxValue, ret |= CtDragHalf("##Shininess"u8, "Gloss Strength"u8, row.Shininess, "%.1f"u8, glossStrengthMin, HalfMaxValue,
Math.Max(0.1f, (float)row.Scalar3 * 0.025f), Math.Max(0.1f, (float)row.Shininess * 0.025f),
v => table[rowIdx].Scalar3 = v); v => table[rowIdx].Shininess = v);
if (dyeTable != null) if (dyeTable != null)
{ {
ImUtf8.SameLineInner(); ImUtf8.SameLineInner();
ret |= CtApplyStainCheckbox("##dyeShininess"u8, "Apply Gloss Strength on Dye"u8, dye.Scalar3, ret |= CtApplyStainCheckbox("##dyeShininess"u8, "Apply Gloss Strength on Dye"u8, dye.Shininess,
b => dyeTable[rowIdx].Scalar3 = b); b => dyeTable[rowIdx].Shininess = b);
} }
ImGui.TableNextColumn(); ImGui.TableNextColumn();
@ -281,8 +153,13 @@ public partial class MtrlTab
value => table[rowIdx].TileIndex = value); value => table[rowIdx].TileIndex = value);
ImUtf8.SameLineInner(); ImUtf8.SameLineInner();
ImGui.SetNextItemWidth(pctSize); ImGui.SetNextItemWidth(pctSize);
if (table is ColorTable rwTable)
{
ret |= CtDragScalar("##TileAlpha"u8, "Tile Opacity"u8, (float)row.TileAlpha * 100.0f, "%.0f%%"u8, 0f, HalfMaxValue * 100.0f, 1.0f, ret |= CtDragScalar("##TileAlpha"u8, "Tile Opacity"u8, (float)row.TileAlpha * 100.0f, "%.0f%%"u8, 0f, HalfMaxValue * 100.0f, 1.0f,
v => table[rowIdx].TileAlpha = (Half)(v * 0.01f)); v => rwTable[rowIdx].TileAlpha = (Half)(v * 0.01f));
}
else
CtDragScalar<float>("##TileAlpha"u8, "Tile Opacity"u8, (float)row.TileAlpha * 100.0f, "%.0f%%"u8);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ret |= CtTileTransformMatrix(row.TileTransform, floatSize, false, ret |= CtTileTransformMatrix(row.TileTransform, floatSize, false,
@ -292,8 +169,13 @@ public partial class MtrlTab
{ {
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGui.SetNextItemWidth(byteSize); ImGui.SetNextItemWidth(byteSize);
ret |= CtDragScalar("##DyeChannel"u8, "Dye Channel"u8, dye.Channel + 1, "%hhd"u8, 1, StainService.ChannelCount, 0.25f, if (dyeTable is ColorDyeTable rwDyeTable)
value => dyeTable[rowIdx].Channel = (byte)(Math.Clamp(value, 1, StainService.ChannelCount) - 1)); {
ret |= CtDragScalar("##DyeChannel"u8, "Dye Channel"u8, dye.Channel + 1, "%d"u8, 1, StainService.ChannelCount, 0.25f,
value => rwDyeTable[rowIdx].Channel = (byte)(Math.Clamp(value, 1, StainService.ChannelCount) - 1));
}
else
CtDragScalar<int>("##DyeChannel"u8, "Dye Channel"u8, dye.Channel + 1, "%d"u8);
ImUtf8.SameLineInner(); ImUtf8.SameLineInner();
_stainService.LegacyTemplateCombo.CurrentDyeChannel = dye.Channel; _stainService.LegacyTemplateCombo.CurrentDyeChannel = dye.Channel;
if (_stainService.LegacyTemplateCombo.Draw("##dyeTemplate", dye.Template.ToString(), string.Empty, intSize if (_stainService.LegacyTemplateCombo.Draw("##dyeTemplate", dye.Template.ToString(), string.Empty, intSize
@ -312,7 +194,8 @@ public partial class MtrlTab
return ret; return ret;
} }
private bool DrawLegacyDyePreview(int rowIdx, bool disabled, LegacyColorDyeTableRow dye, float floatSize) private bool DrawLegacyDyePreview<TDyeRow>(int rowIdx, bool disabled, TDyeRow dye, float floatSize)
where TDyeRow : unmanaged, ILegacyColorDyeRow
{ {
var stain = _stainService.StainCombo1.CurrentSelection.Key; var stain = _stainService.StainCombo1.CurrentSelection.Key;
if (stain == 0 || !_stainService.LegacyStmFile.TryGetValue(dye.Template, stain, out var values)) if (stain == 0 || !_stainService.LegacyStmFile.TryGetValue(dye.Template, stain, out var values))

View file

@ -83,7 +83,7 @@ public sealed partial class MtrlTab : IWritable, IDisposable
return true; return true;
} }
public bool DrawPanel(bool disabled) public bool DrawPanel(bool disabled, MtrlTabUiState uiState)
{ {
if (_updateOnNextFrame) if (_updateOnNextFrame)
{ {
@ -100,7 +100,7 @@ public sealed partial class MtrlTab : IWritable, IDisposable
ret |= DrawShaderSection(disabled); ret |= DrawShaderSection(disabled);
ret |= DrawTextureSection(disabled); ret |= DrawTextureSection(disabled);
ret |= DrawColorTableSection(disabled); ret |= DrawColorTableSection(disabled, uiState);
ret |= DrawConstantsSection(disabled); ret |= DrawConstantsSection(disabled);
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));

View file

@ -0,0 +1,9 @@
namespace Penumbra.UI.AdvancedWindow.Materials;
/// <summary>
/// This class contains UI state that shall be preserved across <see cref="MtrlTab"/> instances.
/// </summary>
public sealed class MtrlTabUiState
{
public int ColorTableSelectedPair = 0;
}

View file

@ -12,12 +12,18 @@ public partial class ModEditWindow
{ {
private readonly FileEditor<MtrlTab> _materialTab; private readonly FileEditor<MtrlTab> _materialTab;
private readonly MtrlTabUiState _materialTabRwUiState = new();
private readonly MtrlTabUiState _materialTabRoUiState = new();
private bool DrawMaterialPanel(MtrlTab tab, bool disabled) private bool DrawMaterialPanel(MtrlTab tab, bool disabled)
{ {
// This depends on the current inner workings of FileEditor<T>.
var uiState = disabled ? _materialTabRoUiState : _materialTabRwUiState;
if (tab.DrawVersionUpdate(disabled)) if (tab.DrawVersionUpdate(disabled))
_materialTab.SaveFile(); _materialTab.SaveFile();
return tab.DrawPanel(disabled); return tab.DrawPanel(disabled, uiState);
} }
private void DrawMaterialReassignmentTab() private void DrawMaterialReassignmentTab()

View file

@ -733,6 +733,10 @@ public class SettingsTab : ITab, IUiService
Checkbox("Advanced Editing: Edit Raw Tile UV Transforms", Checkbox("Advanced Editing: Edit Raw Tile UV Transforms",
"Edit the raw matrix components of tile UV transforms, instead of having them decomposed into scale, rotation and shear.", "Edit the raw matrix components of tile UV transforms, instead of having them decomposed into scale, rotation and shear.",
_config.EditRawTileTransforms, v => _config.EditRawTileTransforms = v); _config.EditRawTileTransforms, v => _config.EditRawTileTransforms = v);
Checkbox("Advanced Editing: Always Highlight Color Row Pair when Hovering Selection Button",
"Make the whole color row pair selection button highlight the pair in game, instead of just the crosshair, even without holding Ctrl.",
_config.WholePairSelectorAlwaysHighlights, v => _config.WholePairSelectorAlwaysHighlights = v);
} }
#endregion #endregion