diff --git a/Penumbra.GameData b/Penumbra.GameData index 635d4c72..862add38 160000 --- a/Penumbra.GameData +++ b/Penumbra.GameData @@ -1 +1 @@ -Subproject commit 635d4c72e84da65a20a2d22d758dd8061bd8babf +Subproject commit 862add38110116b9bb266b739489456a2dd699c0 diff --git a/Penumbra/Interop/MaterialPreview/LiveColorSetPreviewer.cs b/Penumbra/Interop/MaterialPreview/LiveColorTablePreviewer.cs similarity index 62% rename from Penumbra/Interop/MaterialPreview/LiveColorSetPreviewer.cs rename to Penumbra/Interop/MaterialPreview/LiveColorTablePreviewer.cs index f927aa43..c9505091 100644 --- a/Penumbra/Interop/MaterialPreview/LiveColorSetPreviewer.cs +++ b/Penumbra/Interop/MaterialPreview/LiveColorTablePreviewer.cs @@ -1,5 +1,4 @@ using System; -using System.Threading; using Dalamud.Game; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel; @@ -9,24 +8,24 @@ using Penumbra.Interop.SafeHandles; namespace Penumbra.Interop.MaterialPreview; -public sealed unsafe class LiveColorSetPreviewer : LiveMaterialPreviewerBase +public sealed unsafe class LiveColorTablePreviewer : LiveMaterialPreviewerBase { public const int TextureWidth = 4; - public const int TextureHeight = MtrlFile.ColorSet.RowArray.NumRows; + public const int TextureHeight = MtrlFile.ColorTable.NumRows; public const int TextureLength = TextureWidth * TextureHeight * 4; private readonly Framework _framework; - private readonly Texture** _colorSetTexture; - private readonly SafeTextureHandle _originalColorSetTexture; + private readonly Texture** _colorTableTexture; + private readonly SafeTextureHandle _originalColorTableTexture; - private Half[] _colorSet; + private Half[] _colorTable; private bool _updatePending; - public Half[] ColorSet - => _colorSet; + public Half[] ColorTable + => _colorTable; - public LiveColorSetPreviewer(IObjectTable objects, Framework framework, MaterialInfo materialInfo) + public LiveColorTablePreviewer(IObjectTable objects, Framework framework, MaterialInfo materialInfo) : base(objects, materialInfo) { _framework = framework; @@ -35,17 +34,17 @@ public sealed unsafe class LiveColorSetPreviewer : LiveMaterialPreviewerBase if (mtrlHandle == null) throw new InvalidOperationException("Material doesn't have a resource handle"); - var colorSetTextures = ((Structs.CharacterBaseExt*)DrawObject)->ColorSetTextures; + var colorSetTextures = ((Structs.CharacterBaseExt*)DrawObject)->ColorTableTextures; if (colorSetTextures == null) - throw new InvalidOperationException("Draw object doesn't have color set textures"); + throw new InvalidOperationException("Draw object doesn't have color table textures"); - _colorSetTexture = colorSetTextures + (MaterialInfo.ModelSlot * 4 + MaterialInfo.MaterialSlot); + _colorTableTexture = colorSetTextures + (MaterialInfo.ModelSlot * 4 + MaterialInfo.MaterialSlot); - _originalColorSetTexture = new SafeTextureHandle(*_colorSetTexture, true); - if (_originalColorSetTexture == null) - throw new InvalidOperationException("Material doesn't have a color set"); + _originalColorTableTexture = new SafeTextureHandle(*_colorTableTexture, true); + if (_originalColorTableTexture == null) + throw new InvalidOperationException("Material doesn't have a color table"); - _colorSet = new Half[TextureLength]; + _colorTable = new Half[TextureLength]; _updatePending = true; framework.Update += OnFrameworkUpdate; @@ -58,9 +57,9 @@ public sealed unsafe class LiveColorSetPreviewer : LiveMaterialPreviewerBase base.Clear(disposing, reset); if (reset) - _originalColorSetTexture.Exchange(ref *(nint*)_colorSetTexture); + _originalColorTableTexture.Exchange(ref *(nint*)_colorTableTexture); - _originalColorSetTexture.Dispose(); + _originalColorTableTexture.Dispose(); } public void ScheduleUpdate() @@ -87,16 +86,16 @@ public sealed unsafe class LiveColorSetPreviewer : LiveMaterialPreviewerBase return; bool success; - lock (_colorSet) + lock (_colorTable) { - fixed (Half* colorSet = _colorSet) + fixed (Half* colorTable = _colorTable) { - success = Structs.TextureUtility.InitializeContents(texture.Texture, colorSet); + success = Structs.TextureUtility.InitializeContents(texture.Texture, colorTable); } } if (success) - texture.Exchange(ref *(nint*)_colorSetTexture); + texture.Exchange(ref *(nint*)_colorTableTexture); } protected override bool IsStillValid() @@ -104,11 +103,11 @@ public sealed unsafe class LiveColorSetPreviewer : LiveMaterialPreviewerBase if (!base.IsStillValid()) return false; - var colorSetTextures = ((Structs.CharacterBaseExt*)DrawObject)->ColorSetTextures; + var colorSetTextures = ((Structs.CharacterBaseExt*)DrawObject)->ColorTableTextures; if (colorSetTextures == null) return false; - if (_colorSetTexture != colorSetTextures + (MaterialInfo.ModelSlot * 4 + MaterialInfo.MaterialSlot)) + if (_colorTableTexture != colorSetTextures + (MaterialInfo.ModelSlot * 4 + MaterialInfo.MaterialSlot)) return false; return true; diff --git a/Penumbra/Interop/Structs/CharacterBaseExt.cs b/Penumbra/Interop/Structs/CharacterBaseExt.cs index 3bbbeca9..1bc1c2f3 100644 --- a/Penumbra/Interop/Structs/CharacterBaseExt.cs +++ b/Penumbra/Interop/Structs/CharacterBaseExt.cs @@ -11,5 +11,5 @@ public unsafe struct CharacterBaseExt public CharacterBase CharacterBase; [FieldOffset( 0x258 )] - public Texture** ColorSetTextures; + public Texture** ColorTableTextures; } \ No newline at end of file diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.ColorSet.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.ColorTable.cs similarity index 65% rename from Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.ColorSet.cs rename to Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.ColorTable.cs index e1ba045d..2d868a42 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.ColorSet.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.ColorTable.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Numerics; using System.Runtime.InteropServices; using Dalamud.Interface; @@ -17,29 +16,28 @@ public partial class ModEditWindow private static readonly float HalfMaxValue = (float)Half.MaxValue; private static readonly float HalfEpsilon = (float)Half.Epsilon; - private bool DrawMaterialColorSetChange(MtrlTab tab, bool disabled) + private bool DrawMaterialColorTableChange(MtrlTab tab, bool disabled) { - if (!tab.SamplerIds.Contains(ShpkFile.TableSamplerId) || !tab.Mtrl.ColorSets.Any(c => c.HasRows)) + if (!tab.SamplerIds.Contains(ShpkFile.TableSamplerId) || !tab.Mtrl.HasTable) return false; ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); - if (!ImGui.CollapsingHeader("Color Set", ImGuiTreeNodeFlags.DefaultOpen)) + if (!ImGui.CollapsingHeader("Color Table", ImGuiTreeNodeFlags.DefaultOpen)) return false; - var hasAnyDye = tab.UseColorDyeSet; - - ColorSetCopyAllClipboardButton(tab.Mtrl, 0); + ColorTableCopyAllClipboardButton(tab.Mtrl); ImGui.SameLine(); - var ret = ColorSetPasteAllClipboardButton(tab, 0, disabled); + var ret = ColorTablePasteAllClipboardButton(tab, disabled); if (!disabled) { ImGui.SameLine(); ImGui.Dummy(ImGuiHelpers.ScaledVector2(20, 0)); ImGui.SameLine(); - ret |= ColorSetDyeableCheckbox(tab, ref hasAnyDye); + ret |= ColorTableDyeableCheckbox(tab); } - - if (hasAnyDye) + + var hasDyeTable = tab.Mtrl.HasDyeTable; + if (hasDyeTable) { ImGui.SameLine(); ImGui.Dummy(ImGuiHelpers.ScaledVector2(20, 0)); @@ -47,7 +45,7 @@ public partial class ModEditWindow ret |= DrawPreviewDye(tab, disabled); } - using var table = ImRaii.Table("##ColorSets", hasAnyDye ? 11 : 9, + using var table = ImRaii.Table("##ColorTable", hasDyeTable ? 11 : 9, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersInnerV); if (!table) return false; @@ -70,7 +68,7 @@ public partial class ModEditWindow ImGui.TableHeader("Repeat"); ImGui.TableNextColumn(); ImGui.TableHeader("Skew"); - if (hasAnyDye) + if (hasDyeTable) { ImGui.TableNextColumn(); ImGui.TableHeader("Dye"); @@ -78,29 +76,25 @@ public partial class ModEditWindow ImGui.TableHeader("Dye Preview"); } - for (var j = 0; j < tab.Mtrl.ColorSets.Length; ++j) + for (var i = 0; i < MtrlFile.ColorTable.NumRows; ++i) { - using var _ = ImRaii.PushId(j); - for (var i = 0; i < MtrlFile.ColorSet.RowArray.NumRows; ++i) - { - ret |= DrawColorSetRow(tab, j, i, disabled, hasAnyDye); - ImGui.TableNextRow(); - } + ret |= DrawColorTableRow(tab, i, disabled); + ImGui.TableNextRow(); } return ret; } - private static void ColorSetCopyAllClipboardButton(MtrlFile file, int colorSetIdx) + private static void ColorTableCopyAllClipboardButton(MtrlFile file) { if (!ImGui.Button("Export All Rows to Clipboard", ImGuiHelpers.ScaledVector2(200, 0))) return; try { - var data1 = file.ColorSets[colorSetIdx].Rows.AsBytes(); - var data2 = file.ColorDyeSets.Length > colorSetIdx ? file.ColorDyeSets[colorSetIdx].Rows.AsBytes() : ReadOnlySpan.Empty; + var data1 = file.Table.AsBytes(); + var data2 = file.HasDyeTable ? file.DyeTable.AsBytes() : ReadOnlySpan.Empty; var array = new byte[data1.Length + data2.Length]; data1.TryCopyTo(array); data2.TryCopyTo(array.AsSpan(data1.Length)); @@ -122,13 +116,13 @@ public partial class ModEditWindow if (ImGuiUtil.DrawDisabledButton("Apply Preview Dye", Vector2.Zero, tt, disabled || dyeId == 0)) { var ret = false; - for (var j = 0; j < tab.Mtrl.ColorDyeSets.Length; ++j) + if (tab.Mtrl.HasDyeTable) { - for (var i = 0; i < MtrlFile.ColorSet.RowArray.NumRows; ++i) - ret |= tab.Mtrl.ApplyDyeTemplate(_stainService.StmFile, j, i, dyeId); + for (var i = 0; i < MtrlFile.ColorTable.NumRows; ++i) + ret |= tab.Mtrl.ApplyDyeTemplate(_stainService.StmFile, i, dyeId); } - tab.UpdateColorSetPreview(); + tab.UpdateColorTablePreview(); return ret; } @@ -136,40 +130,40 @@ public partial class ModEditWindow ImGui.SameLine(); var label = dyeId == 0 ? "Preview Dye###previewDye" : $"{name} (Preview)###previewDye"; if (_stainService.StainCombo.Draw(label, dyeColor, string.Empty, true, gloss)) - tab.UpdateColorSetPreview(); + tab.UpdateColorTablePreview(); return false; } - private static unsafe bool ColorSetPasteAllClipboardButton(MtrlTab tab, int colorSetIdx, bool disabled) + private static unsafe bool ColorTablePasteAllClipboardButton(MtrlTab tab, bool disabled) { if (!ImGuiUtil.DrawDisabledButton("Import All Rows from Clipboard", ImGuiHelpers.ScaledVector2(200, 0), string.Empty, disabled) - || tab.Mtrl.ColorSets.Length <= colorSetIdx) + || !tab.Mtrl.HasTable) return false; try { var text = ImGui.GetClipboardText(); var data = Convert.FromBase64String(text); - if (data.Length < Marshal.SizeOf()) + if (data.Length < Marshal.SizeOf()) return false; - ref var rows = ref tab.Mtrl.ColorSets[colorSetIdx].Rows; + ref var rows = ref tab.Mtrl.Table; fixed (void* ptr = data, output = &rows) { - MemoryUtility.MemCpyUnchecked(output, ptr, Marshal.SizeOf()); - if (data.Length >= Marshal.SizeOf() + Marshal.SizeOf() - && tab.Mtrl.ColorDyeSets.Length > colorSetIdx) + MemoryUtility.MemCpyUnchecked(output, ptr, Marshal.SizeOf()); + if (data.Length >= Marshal.SizeOf() + Marshal.SizeOf() + && tab.Mtrl.HasDyeTable) { - ref var dyeRows = ref tab.Mtrl.ColorDyeSets[colorSetIdx].Rows; + ref var dyeRows = ref tab.Mtrl.DyeTable; fixed (void* output2 = &dyeRows) { - MemoryUtility.MemCpyUnchecked(output2, (byte*)ptr + Marshal.SizeOf(), - Marshal.SizeOf()); + MemoryUtility.MemCpyUnchecked(output2, (byte*)ptr + Marshal.SizeOf(), + Marshal.SizeOf()); } } } - tab.UpdateColorSetPreview(); + tab.UpdateColorTablePreview(); return true; } @@ -179,7 +173,7 @@ public partial class ModEditWindow } } - private static unsafe void ColorSetCopyClipboardButton(MtrlFile.ColorSet.Row row, MtrlFile.ColorDyeSet.Row dye) + private static unsafe void ColorTableCopyClipboardButton(MtrlFile.ColorTable.Row row, MtrlFile.ColorDyeTable.Row dye) { if (!ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Clipboard.ToIconString(), ImGui.GetFrameHeight() * Vector2.One, "Export this row to your clipboard.", false, true)) @@ -187,11 +181,11 @@ public partial class ModEditWindow try { - var data = new byte[MtrlFile.ColorSet.Row.Size + 2]; + var data = new byte[MtrlFile.ColorTable.Row.Size + 2]; fixed (byte* ptr = data) { - MemoryUtility.MemCpyUnchecked(ptr, &row, MtrlFile.ColorSet.Row.Size); - MemoryUtility.MemCpyUnchecked(ptr + MtrlFile.ColorSet.Row.Size, &dye, 2); + MemoryUtility.MemCpyUnchecked(ptr, &row, MtrlFile.ColorTable.Row.Size); + MemoryUtility.MemCpyUnchecked(ptr + MtrlFile.ColorTable.Row.Size, &dye, 2); } var text = Convert.ToBase64String(data); @@ -203,22 +197,21 @@ public partial class ModEditWindow } } - private static bool ColorSetDyeableCheckbox(MtrlTab tab, ref bool dyeable) - { - var ret = ImGui.Checkbox("Dyeable", ref dyeable); + private static bool ColorTableDyeableCheckbox(MtrlTab tab) + { + var dyeable = tab.Mtrl.HasDyeTable; + var ret = ImGui.Checkbox("Dyeable", ref dyeable); if (ret) { - tab.UseColorDyeSet = dyeable; - if (dyeable) - tab.Mtrl.FindOrAddColorDyeSet(); - tab.UpdateColorSetPreview(); + tab.Mtrl.HasDyeTable = dyeable; + tab.UpdateColorTablePreview(); } return ret; } - private static unsafe bool ColorSetPasteFromClipboardButton(MtrlTab tab, int colorSetIdx, int rowIdx, bool disabled) + private static unsafe bool ColorTablePasteFromClipboardButton(MtrlTab tab, int rowIdx, bool disabled) { if (!ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Paste.ToIconString(), ImGui.GetFrameHeight() * Vector2.One, "Import an exported row from your clipboard onto this row.", disabled, true)) @@ -228,18 +221,18 @@ public partial class ModEditWindow { var text = ImGui.GetClipboardText(); var data = Convert.FromBase64String(text); - if (data.Length != MtrlFile.ColorSet.Row.Size + 2 - || tab.Mtrl.ColorSets.Length <= colorSetIdx) + if (data.Length != MtrlFile.ColorTable.Row.Size + 2 + || !tab.Mtrl.HasTable) return false; fixed (byte* ptr = data) { - tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx] = *(MtrlFile.ColorSet.Row*)ptr; - if (colorSetIdx < tab.Mtrl.ColorDyeSets.Length) - tab.Mtrl.ColorDyeSets[colorSetIdx].Rows[rowIdx] = *(MtrlFile.ColorDyeSet.Row*)(ptr + MtrlFile.ColorSet.Row.Size); + tab.Mtrl.Table[rowIdx] = *(MtrlFile.ColorTable.Row*)ptr; + if (tab.Mtrl.HasDyeTable) + tab.Mtrl.DyeTable[rowIdx] = *(MtrlFile.ColorDyeTable.Row*)(ptr + MtrlFile.ColorTable.Row.Size); } - tab.UpdateColorSetRowPreview(rowIdx); + tab.UpdateColorTableRowPreview(rowIdx); return true; } @@ -249,18 +242,18 @@ public partial class ModEditWindow } } - private static void ColorSetHighlightButton(MtrlTab tab, int rowIdx, bool disabled) + private static void ColorTableHighlightButton(MtrlTab tab, int rowIdx, bool disabled) { ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Crosshairs.ToIconString(), ImGui.GetFrameHeight() * Vector2.One, - "Highlight this row on your character, if possible.", disabled || tab.ColorSetPreviewers.Count == 0, true); + "Highlight this row on your character, if possible.", disabled || tab.ColorTablePreviewers.Count == 0, true); if (ImGui.IsItemHovered()) - tab.HighlightColorSetRow(rowIdx); - else if (tab.HighlightedColorSetRow == rowIdx) - tab.CancelColorSetHighlight(); + tab.HighlightColorTableRow(rowIdx); + else if (tab.HighlightedColorTableRow == rowIdx) + tab.CancelColorTableHighlight(); } - private bool DrawColorSetRow(MtrlTab tab, int colorSetIdx, int rowIdx, bool disabled, bool hasAnyDye) + private bool DrawColorTableRow(MtrlTab tab, int rowIdx, bool disabled) { static bool FixFloat(ref float val, float current) { @@ -269,17 +262,17 @@ public partial class ModEditWindow } using var id = ImRaii.PushId(rowIdx); - var row = tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx]; - var hasDye = hasAnyDye && tab.Mtrl.ColorDyeSets.Length > colorSetIdx; - var dye = hasDye ? tab.Mtrl.ColorDyeSets[colorSetIdx].Rows[rowIdx] : new MtrlFile.ColorDyeSet.Row(); + ref var row = ref tab.Mtrl.Table[rowIdx]; + var hasDye = tab.Mtrl.HasDyeTable; + ref var dye = ref tab.Mtrl.DyeTable[rowIdx]; var floatSize = 70 * UiHelpers.Scale; var intSize = 45 * UiHelpers.Scale; ImGui.TableNextColumn(); - ColorSetCopyClipboardButton(row, dye); + ColorTableCopyClipboardButton(row, dye); ImGui.SameLine(); - var ret = ColorSetPasteFromClipboardButton(tab, colorSetIdx, rowIdx, disabled); + var ret = ColorTablePasteFromClipboardButton(tab, rowIdx, disabled); ImGui.SameLine(); - ColorSetHighlightButton(tab, rowIdx, disabled); + ColorTableHighlightButton(tab, rowIdx, disabled); ImGui.TableNextColumn(); ImGui.TextUnformatted($"#{rowIdx + 1:D2}"); @@ -288,8 +281,8 @@ public partial class ModEditWindow using var dis = ImRaii.Disabled(disabled); ret |= ColorPicker("##Diffuse", "Diffuse Color", row.Diffuse, c => { - tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].Diffuse = c; - tab.UpdateColorSetRowPreview(rowIdx); + tab.Mtrl.Table[rowIdx].Diffuse = c; + tab.UpdateColorTableRowPreview(rowIdx); }); if (hasDye) { @@ -297,25 +290,25 @@ public partial class ModEditWindow ret |= ImGuiUtil.Checkbox("##dyeDiffuse", "Apply Diffuse Color on Dye", dye.Diffuse, b => { - tab.Mtrl.ColorDyeSets[colorSetIdx].Rows[rowIdx].Diffuse = b; - tab.UpdateColorSetRowPreview(rowIdx); + tab.Mtrl.DyeTable[rowIdx].Diffuse = b; + tab.UpdateColorTableRowPreview(rowIdx); }, ImGuiHoveredFlags.AllowWhenDisabled); } ImGui.TableNextColumn(); ret |= ColorPicker("##Specular", "Specular Color", row.Specular, c => { - tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].Specular = c; - tab.UpdateColorSetRowPreview(rowIdx); + tab.Mtrl.Table[rowIdx].Specular = c; + tab.UpdateColorTableRowPreview(rowIdx); }); ImGui.SameLine(); var tmpFloat = row.SpecularStrength; ImGui.SetNextItemWidth(floatSize); - if (ImGui.DragFloat("##SpecularStrength", ref tmpFloat, 0.1f, 0f, HalfMaxValue, "%.2f") && FixFloat(ref tmpFloat, row.SpecularStrength)) + if (ImGui.DragFloat("##SpecularStrength", ref tmpFloat, 0.01f, 0f, HalfMaxValue, "%.2f") && FixFloat(ref tmpFloat, row.SpecularStrength)) { - tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].SpecularStrength = tmpFloat; - ret = true; - tab.UpdateColorSetRowPreview(rowIdx); + row.SpecularStrength = tmpFloat; + ret = true; + tab.UpdateColorTableRowPreview(rowIdx); } ImGuiUtil.HoverTooltip("Specular Strength", ImGuiHoveredFlags.AllowWhenDisabled); @@ -326,23 +319,23 @@ public partial class ModEditWindow ret |= ImGuiUtil.Checkbox("##dyeSpecular", "Apply Specular Color on Dye", dye.Specular, b => { - tab.Mtrl.ColorDyeSets[colorSetIdx].Rows[rowIdx].Specular = b; - tab.UpdateColorSetRowPreview(rowIdx); + tab.Mtrl.DyeTable[rowIdx].Specular = b; + tab.UpdateColorTableRowPreview(rowIdx); }, ImGuiHoveredFlags.AllowWhenDisabled); ImGui.SameLine(); ret |= ImGuiUtil.Checkbox("##dyeSpecularStrength", "Apply Specular Strength on Dye", dye.SpecularStrength, b => { - tab.Mtrl.ColorDyeSets[colorSetIdx].Rows[rowIdx].SpecularStrength = b; - tab.UpdateColorSetRowPreview(rowIdx); + tab.Mtrl.DyeTable[rowIdx].SpecularStrength = b; + tab.UpdateColorTableRowPreview(rowIdx); }, ImGuiHoveredFlags.AllowWhenDisabled); } ImGui.TableNextColumn(); ret |= ColorPicker("##Emissive", "Emissive Color", row.Emissive, c => { - tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].Emissive = c; - tab.UpdateColorSetRowPreview(rowIdx); + tab.Mtrl.Table[rowIdx].Emissive = c; + tab.UpdateColorTableRowPreview(rowIdx); }); if (hasDye) { @@ -350,8 +343,8 @@ public partial class ModEditWindow ret |= ImGuiUtil.Checkbox("##dyeEmissive", "Apply Emissive Color on Dye", dye.Emissive, b => { - tab.Mtrl.ColorDyeSets[colorSetIdx].Rows[rowIdx].Emissive = b; - tab.UpdateColorSetRowPreview(rowIdx); + tab.Mtrl.DyeTable[rowIdx].Emissive = b; + tab.UpdateColorTableRowPreview(rowIdx); }, ImGuiHoveredFlags.AllowWhenDisabled); } @@ -361,9 +354,9 @@ public partial class ModEditWindow if (ImGui.DragFloat("##GlossStrength", ref tmpFloat, Math.Max(0.1f, tmpFloat * 0.025f), HalfEpsilon, HalfMaxValue, "%.1f") && FixFloat(ref tmpFloat, row.GlossStrength)) { - tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].GlossStrength = Math.Max(tmpFloat, HalfEpsilon); - ret = true; - tab.UpdateColorSetRowPreview(rowIdx); + row.GlossStrength = Math.Max(tmpFloat, HalfEpsilon); + ret = true; + tab.UpdateColorTableRowPreview(rowIdx); } ImGuiUtil.HoverTooltip("Gloss Strength", ImGuiHoveredFlags.AllowWhenDisabled); @@ -373,8 +366,8 @@ public partial class ModEditWindow ret |= ImGuiUtil.Checkbox("##dyeGloss", "Apply Gloss Strength on Dye", dye.Gloss, b => { - tab.Mtrl.ColorDyeSets[colorSetIdx].Rows[rowIdx].Gloss = b; - tab.UpdateColorSetRowPreview(rowIdx); + tab.Mtrl.DyeTable[rowIdx].Gloss = b; + tab.UpdateColorTableRowPreview(rowIdx); }, ImGuiHoveredFlags.AllowWhenDisabled); } @@ -383,9 +376,9 @@ public partial class ModEditWindow ImGui.SetNextItemWidth(intSize); if (ImGui.DragInt("##TileSet", ref tmpInt, 0.25f, 0, 63) && tmpInt != row.TileSet && tmpInt is >= 0 and <= ushort.MaxValue) { - tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].TileSet = (ushort)Math.Clamp(tmpInt, 0, 63); - ret = true; - tab.UpdateColorSetRowPreview(rowIdx); + row.TileSet = (ushort)Math.Clamp(tmpInt, 0, 63); + ret = true; + tab.UpdateColorTableRowPreview(rowIdx); } ImGuiUtil.HoverTooltip("Tile Set", ImGuiHoveredFlags.AllowWhenDisabled); @@ -396,9 +389,9 @@ public partial class ModEditWindow if (ImGui.DragFloat("##RepeatX", ref tmpFloat, 0.1f, HalfMinValue, HalfMaxValue, "%.2f") && FixFloat(ref tmpFloat, row.MaterialRepeat.X)) { - tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].MaterialRepeat = row.MaterialRepeat with { X = tmpFloat }; - ret = true; - tab.UpdateColorSetRowPreview(rowIdx); + row.MaterialRepeat = row.MaterialRepeat with { X = tmpFloat }; + ret = true; + tab.UpdateColorTableRowPreview(rowIdx); } ImGuiUtil.HoverTooltip("Repeat X", ImGuiHoveredFlags.AllowWhenDisabled); @@ -408,9 +401,9 @@ public partial class ModEditWindow if (ImGui.DragFloat("##RepeatY", ref tmpFloat, 0.1f, HalfMinValue, HalfMaxValue, "%.2f") && FixFloat(ref tmpFloat, row.MaterialRepeat.Y)) { - tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].MaterialRepeat = row.MaterialRepeat with { Y = tmpFloat }; - ret = true; - tab.UpdateColorSetRowPreview(rowIdx); + row.MaterialRepeat = row.MaterialRepeat with { Y = tmpFloat }; + ret = true; + tab.UpdateColorTableRowPreview(rowIdx); } ImGuiUtil.HoverTooltip("Repeat Y", ImGuiHoveredFlags.AllowWhenDisabled); @@ -420,9 +413,9 @@ public partial class ModEditWindow ImGui.SetNextItemWidth(floatSize); if (ImGui.DragFloat("##SkewX", ref tmpFloat, 0.1f, HalfMinValue, HalfMaxValue, "%.2f") && FixFloat(ref tmpFloat, row.MaterialSkew.X)) { - tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].MaterialSkew = row.MaterialSkew with { X = tmpFloat }; - ret = true; - tab.UpdateColorSetRowPreview(rowIdx); + row.MaterialSkew = row.MaterialSkew with { X = tmpFloat }; + ret = true; + tab.UpdateColorTableRowPreview(rowIdx); } ImGuiUtil.HoverTooltip("Skew X", ImGuiHoveredFlags.AllowWhenDisabled); @@ -432,9 +425,9 @@ public partial class ModEditWindow ImGui.SetNextItemWidth(floatSize); if (ImGui.DragFloat("##SkewY", ref tmpFloat, 0.1f, HalfMinValue, HalfMaxValue, "%.2f") && FixFloat(ref tmpFloat, row.MaterialSkew.Y)) { - tab.Mtrl.ColorSets[colorSetIdx].Rows[rowIdx].MaterialSkew = row.MaterialSkew with { Y = tmpFloat }; - ret = true; - tab.UpdateColorSetRowPreview(rowIdx); + row.MaterialSkew = row.MaterialSkew with { Y = tmpFloat }; + ret = true; + tab.UpdateColorTableRowPreview(rowIdx); } ImGuiUtil.HoverTooltip("Skew Y", ImGuiHoveredFlags.AllowWhenDisabled); @@ -445,27 +438,22 @@ public partial class ModEditWindow if (_stainService.TemplateCombo.Draw("##dyeTemplate", dye.Template.ToString(), string.Empty, intSize + ImGui.GetStyle().ScrollbarSize / 2, ImGui.GetTextLineHeightWithSpacing(), ImGuiComboFlags.NoArrowButton)) { - tab.Mtrl.ColorDyeSets[colorSetIdx].Rows[rowIdx].Template = _stainService.TemplateCombo.CurrentSelection; - ret = true; - tab.UpdateColorSetRowPreview(rowIdx); + dye.Template = _stainService.TemplateCombo.CurrentSelection; + ret = true; + tab.UpdateColorTableRowPreview(rowIdx); } ImGuiUtil.HoverTooltip("Dye Template", ImGuiHoveredFlags.AllowWhenDisabled); ImGui.TableNextColumn(); - ret |= DrawDyePreview(tab, colorSetIdx, rowIdx, disabled, dye, floatSize); - } - else if (hasAnyDye) - { - ImGui.TableNextColumn(); - ImGui.TableNextColumn(); + ret |= DrawDyePreview(tab, rowIdx, disabled, dye, floatSize); } return ret; } - private bool DrawDyePreview(MtrlTab tab, int colorSetIdx, int rowIdx, bool disabled, MtrlFile.ColorDyeSet.Row dye, float floatSize) + private bool DrawDyePreview(MtrlTab tab, int rowIdx, bool disabled, MtrlFile.ColorDyeTable.Row dye, float floatSize) { var stain = _stainService.StainCombo.CurrentSelection.Key; if (stain == 0 || !_stainService.StmFile.Entries.TryGetValue(dye.Template, out var entry)) @@ -477,9 +465,9 @@ public partial class ModEditWindow var ret = ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.PaintBrush.ToIconString(), new Vector2(ImGui.GetFrameHeight()), "Apply the selected dye to this row.", disabled, true); - ret = ret && tab.Mtrl.ApplyDyeTemplate(_stainService.StmFile, colorSetIdx, rowIdx, stain); + ret = ret && tab.Mtrl.ApplyDyeTemplate(_stainService.StmFile, rowIdx, stain); if (ret) - tab.UpdateColorSetRowPreview(rowIdx); + tab.UpdateColorTableRowPreview(rowIdx); ImGui.SameLine(); ColorPicker("##diffusePreview", string.Empty, values.Diffuse, _ => { }, "D"); diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.MtrlTab.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.MtrlTab.cs index aff30fb0..12119742 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.MtrlTab.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.MtrlTab.cs @@ -67,7 +67,6 @@ public partial class ModEditWindow public readonly HashSet UnfoldedTextures = new(4); public readonly HashSet SamplerIds = new(16); public float TextureLabelWidth; - public bool UseColorDyeSet; // Material Constants public readonly @@ -75,10 +74,10 @@ public partial class ModEditWindow Constants)> Constants = new(16); // Live-Previewers - public readonly List MaterialPreviewers = new(4); - public readonly List ColorSetPreviewers = new(4); - public int HighlightedColorSetRow = -1; - public readonly Stopwatch HighlightTime = new(); + public readonly List MaterialPreviewers = new(4); + public readonly List ColorTablePreviewers = new(4); + public int HighlightedColorTableRow = -1; + public readonly Stopwatch HighlightTime = new(); public FullPath FindAssociatedShpk(out string defaultPath, out Utf8GamePath defaultGamePath) { @@ -286,7 +285,7 @@ public partial class ModEditWindow if (AssociatedShpk == null) { SamplerIds.UnionWith(Mtrl.ShaderPackage.Samplers.Select(sampler => sampler.SamplerId)); - if (Mtrl.ColorSets.Any(c => c.HasRows)) + if (Mtrl.HasTable) SamplerIds.Add(TableSamplerId); foreach (var (sampler, index) in Mtrl.ShaderPackage.Samplers.WithIndex()) @@ -301,7 +300,7 @@ public partial class ModEditWindow if (!ShadersKnown) { SamplerIds.UnionWith(Mtrl.ShaderPackage.Samplers.Select(sampler => sampler.SamplerId)); - if (Mtrl.ColorSets.Any(c => c.HasRows)) + if (Mtrl.HasTable) SamplerIds.Add(TableSamplerId); } @@ -320,7 +319,7 @@ public partial class ModEditWindow } if (SamplerIds.Contains(TableSamplerId)) - Mtrl.FindOrAddColorSet(); + Mtrl.HasTable = true; } Textures.Sort((x, y) => string.CompareOrdinal(x.Label, y.Label)); @@ -483,18 +482,16 @@ public partial class ModEditWindow } } - UpdateMaterialPreview(); - - var colorSet = Mtrl.ColorSets.FirstOrNull(colorSet => colorSet.HasRows); - - if (!colorSet.HasValue) + UpdateMaterialPreview(); + + if (!Mtrl.HasTable) return; foreach (var materialInfo in instances) { try { - ColorSetPreviewers.Add(new LiveColorSetPreviewer(_edit._dalamud.Objects, _edit._dalamud.Framework, materialInfo)); + ColorTablePreviewers.Add(new LiveColorTablePreviewer(_edit._dalamud.Objects, _edit._dalamud.Framework, materialInfo)); } catch (InvalidOperationException) { @@ -502,7 +499,7 @@ public partial class ModEditWindow } } - UpdateColorSetPreview(); + UpdateColorTablePreview(); } private void UnbindFromMaterialInstances() @@ -511,9 +508,9 @@ public partial class ModEditWindow previewer.Dispose(); MaterialPreviewers.Clear(); - foreach (var previewer in ColorSetPreviewers) + foreach (var previewer in ColorTablePreviewers) previewer.Dispose(); - ColorSetPreviewers.Clear(); + ColorTablePreviewers.Clear(); } private unsafe void UnbindFromDrawObjectMaterialInstances(nint characterBase) @@ -528,14 +525,14 @@ public partial class ModEditWindow MaterialPreviewers.RemoveAt(i); } - for (var i = ColorSetPreviewers.Count; i-- > 0;) + for (var i = ColorTablePreviewers.Count; i-- > 0;) { - var previewer = ColorSetPreviewers[i]; + var previewer = ColorTablePreviewers[i]; if ((nint)previewer.DrawObject != characterBase) continue; previewer.Dispose(); - ColorSetPreviewers.RemoveAt(i); + ColorTablePreviewers.RemoveAt(i); } } @@ -571,103 +568,94 @@ public partial class ModEditWindow SetSamplerFlags(sampler.SamplerId, sampler.Flags); } - public void HighlightColorSetRow(int rowIdx) + public void HighlightColorTableRow(int rowIdx) { - var oldRowIdx = HighlightedColorSetRow; + var oldRowIdx = HighlightedColorTableRow; - if (HighlightedColorSetRow != rowIdx) + if (HighlightedColorTableRow != rowIdx) { - HighlightedColorSetRow = rowIdx; + HighlightedColorTableRow = rowIdx; HighlightTime.Restart(); } if (oldRowIdx >= 0) - UpdateColorSetRowPreview(oldRowIdx); + UpdateColorTableRowPreview(oldRowIdx); if (rowIdx >= 0) - UpdateColorSetRowPreview(rowIdx); + UpdateColorTableRowPreview(rowIdx); } - public void CancelColorSetHighlight() + public void CancelColorTableHighlight() { - var rowIdx = HighlightedColorSetRow; + var rowIdx = HighlightedColorTableRow; - HighlightedColorSetRow = -1; + HighlightedColorTableRow = -1; HighlightTime.Reset(); if (rowIdx >= 0) - UpdateColorSetRowPreview(rowIdx); + UpdateColorTableRowPreview(rowIdx); } - public void UpdateColorSetRowPreview(int rowIdx) + public void UpdateColorTableRowPreview(int rowIdx) { - if (ColorSetPreviewers.Count == 0) + if (ColorTablePreviewers.Count == 0) + return; + + if (!Mtrl.HasTable) return; - var maybeColorSet = Mtrl.ColorSets.FirstOrNull(colorSet => colorSet.HasRows); - if (!maybeColorSet.HasValue) - return; - - var colorSet = maybeColorSet.Value; - var maybeColorDyeSet = Mtrl.ColorDyeSets.FirstOrNull(colorDyeSet => colorDyeSet.Index == colorSet.Index); - - var row = colorSet.Rows[rowIdx]; - if (maybeColorDyeSet.HasValue && UseColorDyeSet) + var row = Mtrl.Table[rowIdx]; + if (Mtrl.HasDyeTable) { var stm = _edit._stainService.StmFile; - var dye = maybeColorDyeSet.Value.Rows[rowIdx]; + var dye = Mtrl.DyeTable[rowIdx]; if (stm.TryGetValue(dye.Template, _edit._stainService.StainCombo.CurrentSelection.Key, out var dyes)) row.ApplyDyeTemplate(dye, dyes); } - if (HighlightedColorSetRow == rowIdx) + if (HighlightedColorTableRow == rowIdx) ApplyHighlight(ref row, (float)HighlightTime.Elapsed.TotalSeconds); - foreach (var previewer in ColorSetPreviewers) + foreach (var previewer in ColorTablePreviewers) { - row.AsHalves().CopyTo(previewer.ColorSet.AsSpan() - .Slice(LiveColorSetPreviewer.TextureWidth * 4 * rowIdx, LiveColorSetPreviewer.TextureWidth * 4)); + row.AsHalves().CopyTo(previewer.ColorTable.AsSpan() + .Slice(LiveColorTablePreviewer.TextureWidth * 4 * rowIdx, LiveColorTablePreviewer.TextureWidth * 4)); previewer.ScheduleUpdate(); } } - public void UpdateColorSetPreview() + public void UpdateColorTablePreview() { - if (ColorSetPreviewers.Count == 0) + if (ColorTablePreviewers.Count == 0) + return; + + if (!Mtrl.HasTable) return; - var maybeColorSet = Mtrl.ColorSets.FirstOrNull(colorSet => colorSet.HasRows); - if (!maybeColorSet.HasValue) - return; - - var colorSet = maybeColorSet.Value; - var maybeColorDyeSet = Mtrl.ColorDyeSets.FirstOrNull(colorDyeSet => colorDyeSet.Index == colorSet.Index); - - var rows = colorSet.Rows; - if (maybeColorDyeSet.HasValue && UseColorDyeSet) + var rows = Mtrl.Table; + if (Mtrl.HasDyeTable) { var stm = _edit._stainService.StmFile; var stainId = (StainId)_edit._stainService.StainCombo.CurrentSelection.Key; - var colorDyeSet = maybeColorDyeSet.Value; - for (var i = 0; i < MtrlFile.ColorSet.RowArray.NumRows; ++i) + for (var i = 0; i < MtrlFile.ColorTable.NumRows; ++i) { ref var row = ref rows[i]; - var dye = colorDyeSet.Rows[i]; + var dye = Mtrl.DyeTable[i]; if (stm.TryGetValue(dye.Template, stainId, out var dyes)) row.ApplyDyeTemplate(dye, dyes); } } - if (HighlightedColorSetRow >= 0) - ApplyHighlight(ref rows[HighlightedColorSetRow], (float)HighlightTime.Elapsed.TotalSeconds); + if (HighlightedColorTableRow >= 0) + ApplyHighlight(ref rows[HighlightedColorTableRow], (float)HighlightTime.Elapsed.TotalSeconds); - foreach (var previewer in ColorSetPreviewers) + foreach (var previewer in ColorTablePreviewers) { - rows.AsHalves().CopyTo(previewer.ColorSet); + rows.AsHalves().CopyTo(previewer.ColorTable); previewer.ScheduleUpdate(); } } - private static void ApplyHighlight(ref MtrlFile.ColorSet.Row row, float time) + private static void ApplyHighlight(ref MtrlFile.ColorTable.Row row, float time) { var level = (MathF.Sin(time * 2.0f * MathF.PI) + 2.0f) / 3.0f / 255.0f; var baseColor = ColorId.InGameHighlight.Value(); @@ -691,7 +679,6 @@ public partial class ModEditWindow Mtrl = file; FilePath = filePath; Writable = writable; - UseColorDyeSet = file.ColorDyeSets.Length > 0; AssociatedBaseDevkit = TryLoadShpkDevkit("_base", out LoadedBaseDevkitPathName); LoadShpk(FindAssociatedShpk(out _, out _)); if (writable) @@ -714,7 +701,7 @@ public partial class ModEditWindow public byte[] Write() { var output = Mtrl.Clone(); - output.GarbageCollect(AssociatedShpk, SamplerIds, UseColorDyeSet); + output.GarbageCollect(AssociatedShpk, SamplerIds); return output.Write(); } diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs index 102a6778..02845362 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs @@ -25,7 +25,7 @@ public partial class ModEditWindow ret |= DrawMaterialShader(tab, disabled); ret |= DrawMaterialTextureChange(tab, disabled); - ret |= DrawMaterialColorSetChange(tab, disabled); + ret |= DrawMaterialColorTableChange(tab, disabled); ret |= DrawMaterialConstants(tab, disabled); ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); @@ -42,7 +42,7 @@ public partial class ModEditWindow if (ImGui.Button("Reload live preview")) tab.BindToMaterialInstances(); - if (tab.MaterialPreviewers.Count != 0 || tab.ColorSetPreviewers.Count != 0) + if (tab.MaterialPreviewers.Count != 0 || tab.ColorTablePreviewers.Count != 0) return; ImGui.SameLine(); @@ -159,6 +159,13 @@ public partial class ModEditWindow ImRaii.TreeNode($"#{set.Index:D2} - {set.Name}", ImGuiTreeNodeFlags.Leaf).Dispose(); } + using (var sets = ImRaii.TreeNode("Color Sets", ImGuiTreeNodeFlags.DefaultOpen)) + { + if (sets) + foreach (var set in file.ColorSets) + ImRaii.TreeNode($"#{set.Index:D2} - {set.Name}", ImGuiTreeNodeFlags.Leaf).Dispose(); + } + if (file.AdditionalData.Length <= 0) return;