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