diff --git a/Penumbra.GameData b/Penumbra.GameData index b7fdfe9d..0784569a 160000 --- a/Penumbra.GameData +++ b/Penumbra.GameData @@ -1 +1 @@ -Subproject commit b7fdfe9d19f7e3229834480db446478b0bf6acee +Subproject commit 0784569ab59c96b2058730cdb4cefd61c96b5f1a diff --git a/Penumbra/Configuration.cs b/Penumbra/Configuration.cs index 50426b38..31dc2d82 100644 --- a/Penumbra/Configuration.cs +++ b/Penumbra/Configuration.cs @@ -107,7 +107,9 @@ public class Configuration : IPluginConfiguration, ISavable, IService public bool AlwaysOpenDefaultImport { get; set; } = false; public bool KeepDefaultMetaChanges { get; set; } = false; 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 Colors { get; set; } = Enum.GetValues().ToDictionary(c => c, c => c.Data().DefaultColor); diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs index ab93dc5f..2c2dde5b 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs @@ -13,15 +13,13 @@ public partial class MtrlTab { private const float ColorTableScalarSize = 65.0f; - private int _colorTableSelectedPair; - - private bool DrawColorTable(ColorTable table, ColorDyeTable? dyeTable, bool disabled) + private bool DrawColorTable(ColorTable table, ColorDyeTable? dyeTable, bool disabled, MtrlTabUiState uiState) { - DrawColorTablePairSelector(table, disabled); - return DrawColorTablePairEditor(table, dyeTable, disabled); + DrawColorTablePairSelector(table, disabled, uiState); + return DrawColorTablePairEditor(table, dyeTable, disabled, uiState); } - private void DrawColorTablePairSelector(ColorTable table, bool disabled) + private void DrawColorTablePairSelector(IColorTable table, bool disabled, MtrlTabUiState uiState) where TRow : unmanaged, IColorRow { var style = ImGui.GetStyle(); var itemSpacing = style.ItemSpacing.X; @@ -38,16 +36,17 @@ public partial class MtrlTab var spaceWidth = ImUtf8.CalcTextSize(" "u8).X; var spacePadding = (int)MathF.Ceiling((highlighterSize.X + framePadding.X + itemInnerSpacing) / spaceWidth); - for (var i = 0; i < ColorTable.NumRows >> 1; i += 8) + for (var 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; - 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), new Vector2(buttonWidth, ImGui.GetFrameHeightWithSpacing() + frameHeight))) - _colorTableSelectedPair = pairIndex; + uiState.ColorTableSelectedPair = pairIndex; } 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) | 1].EmissiveColor)) ); - if (j < 7) + if (j + 1 < numPairsInRow) ImGui.SameLine(); 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 retB = false; - var rowAIdx = _colorTableSelectedPair << 1; + var rowAIdx = uiState.ColorTableSelectedPair << 1; var rowBIdx = rowAIdx | 1; - var dyeA = dyeTable?[_colorTableSelectedPair << 1] ?? default; - var dyeB = dyeTable?[(_colorTableSelectedPair << 1) | 1] ?? default; + var dyeA = dyeTable?[uiState.ColorTableSelectedPair << 1] ?? default; + var dyeB = dyeTable?[(uiState.ColorTableSelectedPair << 1) | 1] ?? default; var previewDyeA = _stainService.GetStainCombo(dyeA.Channel).CurrentSelection.Key; var previewDyeB = _stainService.GetStainCombo(dyeB.Channel).CurrentSelection.Key; var dyePackA = _stainService.GudStmFile.GetValueOrNull(dyeA.Template, previewDyeA); @@ -335,7 +334,6 @@ public partial class MtrlTab var scalarSize = ColorTableScalarSize * UiHelpers.Scale; var itemSpacing = ImGui.GetStyle().ItemSpacing.X; var dyeOffset = ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight() - scalarSize - 64.0f; - var subColWidth = CalculateSubColumnWidth(2); var ret = false; ref var row = ref table[rowIdx]; @@ -387,6 +385,20 @@ public partial class MtrlTab ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ret |= DrawTemplateTile(table, rowIdx); + + return ret; + } + + private bool DrawTemplateTile(IColorTable 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 rightLineHeight = 3.0f * ImGui.GetFrameHeight() + 2.0f * ImGui.GetStyle().ItemSpacing.Y; var lineHeight = Math.Max(leftLineHeight, rightLineHeight); @@ -406,8 +418,13 @@ public partial class MtrlTab ImGui.Dummy(new Vector2(scalarSize, 0.0f)); ImUtf8.SameLineInner(); ImGui.SetNextItemWidth(scalarSize); - 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)); + 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, + v => rwTable[rowIdx].TileAlpha = (Half)(v * 0.01f)); + } + else + CtDragScalar("Tile Opacity"u8, default, (float)row.TileAlpha * 100.0f, "%.0f%%"u8); ret |= CtTileTransformMatrix(row.TileTransform, scalarSize, true, m => table[rowIdx].TileTransform = m); diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.CommonColorTable.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.CommonColorTable.cs index 38f02100..7d8e2cf2 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.CommonColorTable.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.CommonColorTable.cs @@ -20,7 +20,7 @@ public partial class MtrlTab 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) return false; @@ -53,7 +53,7 @@ public partial class MtrlTab LegacyColorTable legacyTable => DrawLegacyColorTable(legacyTable, Mtrl.DyeTable as LegacyColorDyeTable, disabled), ColorTable table when Mtrl.ShaderPackage.Name is "characterlegacy.shpk" => DrawLegacyColorTable(table, Mtrl.DyeTable as ColorDyeTable, disabled), - ColorTable table => DrawColorTable(table, Mtrl.DyeTable as ColorDyeTable, disabled), + ColorTable table => DrawColorTable(table, Mtrl.DyeTable as ColorDyeTable, disabled, uiState), _ => false, }; @@ -230,11 +230,13 @@ public partial class MtrlTab private void ColorTablePairHighlightButton(int pairIdx, bool disabled) { + var wholePairSelectorHighlight = (_config.WholePairSelectorAlwaysHighlights || ImGui.GetIO().KeyCtrl) && ImGui.IsItemHovered(); + ImUtf8.IconButton(FontAwesomeIcon.Crosshairs, "Highlight this pair of rows on your character, if possible.\n\nHighlight colors can be configured in Penumbra's settings."u8, ImGui.GetFrameHeight() * Vector2.One, disabled || _colorTablePreviewers.Count == 0); - if (ImGui.IsItemHovered()) + if (wholePairSelectorHighlight || ImGui.IsItemHovered()) HighlightColorTablePair(pairIdx); else if (_highlightedColorTablePair == pairIdx) CancelColorTableHighlight(); @@ -266,14 +268,14 @@ public partial class MtrlTab else { 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); drawList.AddRectFilledMultiColor( - rcMin with { Y = float.Lerp(rcMin.Y, rcMax.Y, 1.0f / 3) }, - rcMax with { Y = float.Lerp(rcMin.Y, rcMax.Y, 2.0f / 3) }, + rcMin with { Y = MathF.Floor(float.Lerp(rcMin.Y, rcMax.Y, 1.0f / 3)) }, + rcMax with { Y = MathF.Ceiling(float.Lerp(rcMin.Y, rcMax.Y, 2.0f / 3)) }, topColor, topColor, bottomColor, bottomColor); 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); } diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs index f21d86a9..52280487 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs @@ -16,31 +16,8 @@ public partial class MtrlTab private const float LegacyColorTableIntegerSize = 40.0f; private const float LegacyColorTableByteSize = 25.0f; - private bool DrawLegacyColorTable(LegacyColorTable table, LegacyColorDyeTable? dyeTable, bool disabled) - { - 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) + private bool DrawLegacyColorTable(IColorTable table, IColorDyeTable? 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); @@ -91,113 +68,8 @@ public partial class MtrlTab } } - private bool DrawLegacyColorTableRow(LegacyColorTable table, LegacyColorDyeTable? dyeTable, int rowIdx, bool disabled) - { - 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) + private bool DrawLegacyColorTableRow(IColorTable table, IColorDyeTable? 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]; @@ -242,13 +114,13 @@ public partial class MtrlTab ImGui.SameLine(); ImGui.SetNextItemWidth(pctSize); - ret |= CtDragScalar("##SpecularMask"u8, "Specular Strength"u8, (float)row.Scalar7 * 100.0f, "%.0f%%"u8, 0f, HalfMaxValue * 100.0f, 1.0f, - v => table[rowIdx].Scalar7 = (Half)(v * 0.01f)); + 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.Metalness, - b => dyeTable[rowIdx].Metalness = b); + ret |= CtApplyStainCheckbox("##dyeSpecularMask"u8, "Apply Specular Strength on Dye"u8, dye.SpecularMask, + b => dyeTable[rowIdx].SpecularMask = b); } ImGui.TableNextColumn(); @@ -264,15 +136,15 @@ public partial class MtrlTab ImGui.TableNextColumn(); ImGui.SetNextItemWidth(floatSize); var glossStrengthMin = ImGui.GetIO().KeyCtrl ? 0.0f : HalfEpsilon; - ret |= CtDragHalf("##Shininess"u8, "Gloss Strength"u8, row.Scalar3, "%.1f"u8, glossStrengthMin, HalfMaxValue, - Math.Max(0.1f, (float)row.Scalar3 * 0.025f), - v => table[rowIdx].Scalar3 = v); + 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.Scalar3, - b => dyeTable[rowIdx].Scalar3 = b); + ret |= CtApplyStainCheckbox("##dyeShininess"u8, "Apply Gloss Strength on Dye"u8, dye.Shininess, + b => dyeTable[rowIdx].Shininess = b); } ImGui.TableNextColumn(); @@ -281,8 +153,13 @@ public partial class MtrlTab value => table[rowIdx].TileIndex = value); ImUtf8.SameLineInner(); ImGui.SetNextItemWidth(pctSize); - 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)); + 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, + v => rwTable[rowIdx].TileAlpha = (Half)(v * 0.01f)); + } + else + CtDragScalar("##TileAlpha"u8, "Tile Opacity"u8, (float)row.TileAlpha * 100.0f, "%.0f%%"u8); ImGui.TableNextColumn(); ret |= CtTileTransformMatrix(row.TileTransform, floatSize, false, @@ -292,8 +169,13 @@ public partial class MtrlTab { ImGui.TableNextColumn(); ImGui.SetNextItemWidth(byteSize); - ret |= CtDragScalar("##DyeChannel"u8, "Dye Channel"u8, dye.Channel + 1, "%hhd"u8, 1, StainService.ChannelCount, 0.25f, - value => dyeTable[rowIdx].Channel = (byte)(Math.Clamp(value, 1, StainService.ChannelCount) - 1)); + if (dyeTable is ColorDyeTable rwDyeTable) + { + 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("##DyeChannel"u8, "Dye Channel"u8, dye.Channel + 1, "%d"u8); ImUtf8.SameLineInner(); _stainService.LegacyTemplateCombo.CurrentDyeChannel = dye.Channel; if (_stainService.LegacyTemplateCombo.Draw("##dyeTemplate", dye.Template.ToString(), string.Empty, intSize @@ -312,7 +194,8 @@ public partial class MtrlTab return ret; } - private bool DrawLegacyDyePreview(int rowIdx, bool disabled, LegacyColorDyeTableRow dye, float floatSize) + private bool DrawLegacyDyePreview(int rowIdx, bool disabled, TDyeRow dye, float floatSize) + where TDyeRow : unmanaged, ILegacyColorDyeRow { var stain = _stainService.StainCombo1.CurrentSelection.Key; if (stain == 0 || !_stainService.LegacyStmFile.TryGetValue(dye.Template, stain, out var values)) diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.cs index 6e16de99..0c9d15e5 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.cs @@ -83,7 +83,7 @@ public sealed partial class MtrlTab : IWritable, IDisposable return true; } - public bool DrawPanel(bool disabled) + public bool DrawPanel(bool disabled, MtrlTabUiState uiState) { if (_updateOnNextFrame) { @@ -100,7 +100,7 @@ public sealed partial class MtrlTab : IWritable, IDisposable ret |= DrawShaderSection(disabled); ret |= DrawTextureSection(disabled); - ret |= DrawColorTableSection(disabled); + ret |= DrawColorTableSection(disabled, uiState); ret |= DrawConstantsSection(disabled); ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTabUiState.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTabUiState.cs new file mode 100644 index 00000000..7d87f8cd --- /dev/null +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTabUiState.cs @@ -0,0 +1,9 @@ +namespace Penumbra.UI.AdvancedWindow.Materials; + +/// +/// This class contains UI state that shall be preserved across instances. +/// +public sealed class MtrlTabUiState +{ + public int ColorTableSelectedPair = 0; +} diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs index 59b38465..eb4af9af 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs @@ -12,12 +12,18 @@ public partial class ModEditWindow { private readonly FileEditor _materialTab; + private readonly MtrlTabUiState _materialTabRwUiState = new(); + private readonly MtrlTabUiState _materialTabRoUiState = new(); + private bool DrawMaterialPanel(MtrlTab tab, bool disabled) { + // This depends on the current inner workings of FileEditor. + var uiState = disabled ? _materialTabRoUiState : _materialTabRwUiState; + if (tab.DrawVersionUpdate(disabled)) _materialTab.SaveFile(); - return tab.DrawPanel(disabled); + return tab.DrawPanel(disabled, uiState); } private void DrawMaterialReassignmentTab() diff --git a/Penumbra/UI/Tabs/SettingsTab.cs b/Penumbra/UI/Tabs/SettingsTab.cs index 27c7f2ed..66b76406 100644 --- a/Penumbra/UI/Tabs/SettingsTab.cs +++ b/Penumbra/UI/Tabs/SettingsTab.cs @@ -733,6 +733,10 @@ public class SettingsTab : ITab, IUiService 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.", _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