mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
DT material editor, new color tables
This commit is contained in:
parent
36ab9573ae
commit
f4fe3605f0
2 changed files with 563 additions and 0 deletions
562
Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs
Normal file
562
Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs
Normal file
|
|
@ -0,0 +1,562 @@
|
|||
using Dalamud.Interface;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
using Penumbra.GameData.Files.MaterialStructs;
|
||||
using Penumbra.GameData.Files.StainMapStructs;
|
||||
using Penumbra.Services;
|
||||
|
||||
namespace Penumbra.UI.AdvancedWindow.Materials;
|
||||
|
||||
public partial class MtrlTab
|
||||
{
|
||||
private const float ColorTableScalarSize = 65.0f;
|
||||
|
||||
private int _colorTableSelectedPair = 0;
|
||||
|
||||
private bool DrawColorTable(ColorTable table, ColorDyeTable? dyeTable, bool disabled)
|
||||
{
|
||||
DrawColorTablePairSelector(table, disabled);
|
||||
return DrawColorTablePairEditor(table, dyeTable, disabled);
|
||||
}
|
||||
|
||||
private void DrawColorTablePairSelector(ColorTable table, bool disabled)
|
||||
{
|
||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||
using var alignment = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f));
|
||||
var style = ImGui.GetStyle();
|
||||
var itemSpacing = style.ItemSpacing.X;
|
||||
var itemInnerSpacing = style.ItemInnerSpacing.X;
|
||||
var framePadding = style.FramePadding;
|
||||
var buttonWidth = (ImGui.GetContentRegionAvail().X - itemSpacing * 7.0f) * 0.125f;
|
||||
var frameHeight = ImGui.GetFrameHeight();
|
||||
var highlighterSize = ImUtf8.CalcIconSize(FontAwesomeIcon.Crosshairs) + framePadding * 2.0f;
|
||||
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 j = 0; j < 8; ++j)
|
||||
{
|
||||
var pairIndex = i + j;
|
||||
using (var color = ImRaii.PushColor(ImGuiCol.Button, ImGui.GetColorU32(ImGuiCol.ButtonActive), pairIndex == _colorTableSelectedPair))
|
||||
{
|
||||
if (ImUtf8.Button($"#{pairIndex + 1}".PadLeft(3 + spacePadding), new Vector2(buttonWidth, ImGui.GetFrameHeightWithSpacing() + frameHeight)))
|
||||
_colorTableSelectedPair = pairIndex;
|
||||
}
|
||||
|
||||
var rcMin = ImGui.GetItemRectMin() + framePadding;
|
||||
var rcMax = ImGui.GetItemRectMax() - framePadding;
|
||||
CtBlendRect(
|
||||
rcMin with { X = rcMax.X - frameHeight * 3 - itemInnerSpacing * 2 },
|
||||
rcMax with { X = rcMax.X - (frameHeight + itemInnerSpacing) * 2 },
|
||||
ImGuiUtil.ColorConvertFloat3ToU32(PseudoSqrtRgb((Vector3)table[pairIndex << 1].DiffuseColor)),
|
||||
ImGuiUtil.ColorConvertFloat3ToU32(PseudoSqrtRgb((Vector3)table[(pairIndex << 1) | 1].DiffuseColor))
|
||||
);
|
||||
CtBlendRect(
|
||||
rcMin with { X = rcMax.X - frameHeight * 2 - itemInnerSpacing },
|
||||
rcMax with { X = rcMax.X - frameHeight - itemInnerSpacing },
|
||||
ImGuiUtil.ColorConvertFloat3ToU32(PseudoSqrtRgb((Vector3)table[pairIndex << 1].SpecularColor)),
|
||||
ImGuiUtil.ColorConvertFloat3ToU32(PseudoSqrtRgb((Vector3)table[(pairIndex << 1) | 1].SpecularColor))
|
||||
);
|
||||
CtBlendRect(
|
||||
rcMin with { X = rcMax.X - frameHeight }, rcMax,
|
||||
ImGuiUtil.ColorConvertFloat3ToU32(PseudoSqrtRgb((Vector3)table[pairIndex << 1].EmissiveColor)),
|
||||
ImGuiUtil.ColorConvertFloat3ToU32(PseudoSqrtRgb((Vector3)table[(pairIndex << 1) | 1].EmissiveColor))
|
||||
);
|
||||
if (j < 7)
|
||||
ImGui.SameLine();
|
||||
|
||||
var cursor = ImGui.GetCursorScreenPos();
|
||||
ImGui.SetCursorScreenPos(rcMin with { Y = float.Lerp(rcMin.Y, rcMax.Y, 0.5f) - highlighterSize.Y * 0.5f });
|
||||
font.Pop();
|
||||
ColorTableHighlightButton(pairIndex, disabled);
|
||||
font.Push(UiBuilder.MonoFont);
|
||||
ImGui.SetCursorScreenPos(cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool DrawColorTablePairEditor(ColorTable table, ColorDyeTable? dyeTable, bool disabled)
|
||||
{
|
||||
var retA = false;
|
||||
var retB = false;
|
||||
ref var rowA = ref table[_colorTableSelectedPair << 1];
|
||||
ref var rowB = ref table[(_colorTableSelectedPair << 1) | 1];
|
||||
var dyeA = dyeTable != null ? dyeTable[_colorTableSelectedPair << 1] : default;
|
||||
var dyeB = dyeTable != null ? dyeTable[(_colorTableSelectedPair << 1) | 1] : default;
|
||||
var previewDyeA = _stainService.GetStainCombo(dyeA.Channel).CurrentSelection.Key;
|
||||
var previewDyeB = _stainService.GetStainCombo(dyeB.Channel).CurrentSelection.Key;
|
||||
var dyePackA = _stainService.GudStmFile.GetValueOrNull(dyeA.Template, previewDyeA);
|
||||
var dyePackB = _stainService.GudStmFile.GetValueOrNull(dyeB.Template, previewDyeB);
|
||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||
{
|
||||
ColorTableCopyClipboardButton(_colorTableSelectedPair << 1);
|
||||
ImUtf8.SameLineInner();
|
||||
retA |= ColorTablePasteFromClipboardButton(_colorTableSelectedPair << 1, disabled);
|
||||
ImGui.SameLine();
|
||||
CenteredTextInRest($"Row {_colorTableSelectedPair + 1}A");
|
||||
columns.Next();
|
||||
ColorTableCopyClipboardButton((_colorTableSelectedPair << 1) | 1);
|
||||
ImUtf8.SameLineInner();
|
||||
retB |= ColorTablePasteFromClipboardButton((_colorTableSelectedPair << 1) | 1, disabled);
|
||||
ImGui.SameLine();
|
||||
CenteredTextInRest($"Row {_colorTableSelectedPair + 1}B");
|
||||
}
|
||||
|
||||
DrawHeader(" Colors"u8);
|
||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||
{
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
using (var id = ImUtf8.PushId("ColorsA"u8))
|
||||
retA |= DrawColors(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||
columns.Next();
|
||||
using (var id = ImUtf8.PushId("ColorsB"u8))
|
||||
retB |= DrawColors(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||
}
|
||||
|
||||
DrawHeader(" Physical Parameters"u8);
|
||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||
{
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
using (var id = ImUtf8.PushId("PbrA"u8))
|
||||
retA |= DrawPbr(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||
columns.Next();
|
||||
using (var id = ImUtf8.PushId("PbrB"u8))
|
||||
retB |= DrawPbr(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||
}
|
||||
|
||||
DrawHeader(" Sheen Layer Parameters"u8);
|
||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||
{
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
using (var id = ImUtf8.PushId("SheenA"u8))
|
||||
retA |= DrawSheen(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||
columns.Next();
|
||||
using (var id = ImUtf8.PushId("SheenB"u8))
|
||||
retB |= DrawSheen(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||
}
|
||||
|
||||
DrawHeader(" Pair Blending"u8);
|
||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||
{
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
using (var id = ImUtf8.PushId("BlendingA"u8))
|
||||
retA |= DrawBlending(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||
columns.Next();
|
||||
using (var id = ImUtf8.PushId("BlendingB"u8))
|
||||
retB |= DrawBlending(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||
}
|
||||
|
||||
DrawHeader(" Material Template"u8);
|
||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||
{
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
using (var id = ImUtf8.PushId("TemplateA"u8))
|
||||
retA |= DrawTemplate(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||
columns.Next();
|
||||
using (var id = ImUtf8.PushId("TemplateB"u8))
|
||||
retB |= DrawTemplate(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||
}
|
||||
|
||||
if (dyeTable != null)
|
||||
{
|
||||
DrawHeader(" Dye Properties"u8);
|
||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||
{
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
using (var id = ImUtf8.PushId("DyeA"u8))
|
||||
retA |= DrawDye(dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||
columns.Next();
|
||||
using (var id = ImUtf8.PushId("DyeB"u8))
|
||||
retB |= DrawDye(dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||
}
|
||||
}
|
||||
|
||||
DrawHeader(" Further Content"u8);
|
||||
using (var columns = ImUtf8.Columns(2, "ColorTable"u8))
|
||||
{
|
||||
using var dis = ImRaii.Disabled(disabled);
|
||||
using (var id = ImUtf8.PushId("FurtherA"u8))
|
||||
retA |= DrawFurther(table, dyeTable, dyePackA, _colorTableSelectedPair << 1);
|
||||
columns.Next();
|
||||
using (var id = ImUtf8.PushId("FurtherB"u8))
|
||||
retB |= DrawFurther(table, dyeTable, dyePackB, (_colorTableSelectedPair << 1) | 1);
|
||||
}
|
||||
|
||||
if (retA)
|
||||
UpdateColorTableRowPreview(_colorTableSelectedPair << 1);
|
||||
if (retB)
|
||||
UpdateColorTableRowPreview((_colorTableSelectedPair << 1) | 1);
|
||||
|
||||
return retA | retB;
|
||||
}
|
||||
|
||||
/// <remarks> Padding styles do not seem to apply to this component. It is recommended to prepend two spaces. </remarks>
|
||||
private static void DrawHeader(ReadOnlySpan<byte> label)
|
||||
{
|
||||
var headerColor = ImGui.GetColorU32(ImGuiCol.Header);
|
||||
using var _ = ImRaii.PushColor(ImGuiCol.HeaderHovered, headerColor).Push(ImGuiCol.HeaderActive, headerColor);
|
||||
ImUtf8.CollapsingHeader(label, ImGuiTreeNodeFlags.Leaf);
|
||||
}
|
||||
|
||||
private static bool DrawColors(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
||||
{
|
||||
var dyeOffset = ImGui.GetContentRegionAvail().X + ImGui.GetStyle().ItemSpacing.X - ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight() * 2.0f;
|
||||
|
||||
var ret = false;
|
||||
ref var row = ref table[rowIdx];
|
||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
||||
|
||||
ret |= CtColorPicker("Diffuse Color"u8, default, row.DiffuseColor,
|
||||
c => table[rowIdx].DiffuseColor = c);
|
||||
if (dyeTable != null)
|
||||
{
|
||||
ImGui.SameLine(dyeOffset);
|
||||
ret |= CtApplyStainCheckbox("##dyeDiffuseColor"u8, "Apply Diffuse Color on Dye"u8, dye.DiffuseColor,
|
||||
b => dyeTable[rowIdx].DiffuseColor = b);
|
||||
ImUtf8.SameLineInner();
|
||||
CtColorPicker("##dyePreviewDiffuseColor"u8, "Dye Preview for Diffuse Color"u8, dyePack?.DiffuseColor);
|
||||
}
|
||||
|
||||
ret |= CtColorPicker("Specular Color"u8, default, row.SpecularColor,
|
||||
c => table[rowIdx].SpecularColor = c);
|
||||
if (dyeTable != null)
|
||||
{
|
||||
ImGui.SameLine(dyeOffset);
|
||||
ret |= CtApplyStainCheckbox("##dyeSpecularColor"u8, "Apply Specular Color on Dye"u8, dye.SpecularColor,
|
||||
b => dyeTable[rowIdx].SpecularColor = b);
|
||||
ImUtf8.SameLineInner();
|
||||
CtColorPicker("##dyePreviewSpecularColor"u8, "Dye Preview for Specular Color"u8, dyePack?.SpecularColor);
|
||||
}
|
||||
|
||||
ret |= CtColorPicker("Emissive Color"u8, default, row.EmissiveColor,
|
||||
c => table[rowIdx].EmissiveColor = c);
|
||||
if (dyeTable != null)
|
||||
{
|
||||
ImGui.SameLine(dyeOffset);
|
||||
ret |= CtApplyStainCheckbox("##dyeEmissiveColor"u8, "Apply Emissive Color on Dye"u8, dye.EmissiveColor,
|
||||
b => dyeTable[rowIdx].EmissiveColor = b);
|
||||
ImUtf8.SameLineInner();
|
||||
CtColorPicker("##dyePreviewEmissiveColor"u8, "Dye Preview for Emissive Color"u8, dyePack?.EmissiveColor);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawBlending(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
||||
{
|
||||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
||||
var dyeOffset = ImGui.GetContentRegionAvail().X + ImGui.GetStyle().ItemSpacing.X - ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight() - scalarSize;
|
||||
|
||||
var isRowB = (rowIdx & 1) != 0;
|
||||
|
||||
var ret = false;
|
||||
ref var row = ref table[rowIdx];
|
||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragHalf(isRowB ? "Field #19"u8 : "Anisotropy Degree"u8, default, row.Anisotropy, "%.2f"u8, 0.0f, HalfMaxValue, 0.1f,
|
||||
v => table[rowIdx].Anisotropy = v);
|
||||
if (dyeTable != null)
|
||||
{
|
||||
ImGui.SameLine(dyeOffset);
|
||||
ret |= CtApplyStainCheckbox("##dyeAnisotropy"u8, isRowB ? "Apply Field #19 on Dye"u8 : "Apply Anisotropy Degree on Dye"u8, dye.Anisotropy,
|
||||
b => dyeTable[rowIdx].Anisotropy = b);
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
CtDragHalf("##dyePreviewAnisotropy"u8, isRowB ? "Dye Preview for Field #19"u8 : "Dye Preview for Anisotropy Degree"u8, dyePack?.Anisotropy, "%.2f"u8);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawTemplate(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
||||
{
|
||||
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];
|
||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragScalar("Shader ID"u8, default, row.ShaderId, "%d"u8, (ushort)0, (ushort)255, 0.25f,
|
||||
v => table[rowIdx].ShaderId = v);
|
||||
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize + itemSpacing + 64.0f);
|
||||
ret |= CtSphereMapIndexPicker("###SphereMapIndex"u8, default, row.SphereMapIndex, false,
|
||||
v => table[rowIdx].SphereMapIndex = v);
|
||||
ImUtf8.SameLineInner();
|
||||
ImUtf8.Text("Sphere Map"u8);
|
||||
if (dyeTable != null)
|
||||
{
|
||||
var textRectMin = ImGui.GetItemRectMin();
|
||||
var textRectMax = ImGui.GetItemRectMax();
|
||||
ImGui.SameLine(dyeOffset);
|
||||
var cursor = ImGui.GetCursorScreenPos();
|
||||
ImGui.SetCursorScreenPos(cursor with { Y = float.Lerp(textRectMin.Y, textRectMax.Y, 0.5f) - ImGui.GetFrameHeight() * 0.5f });
|
||||
ret |= CtApplyStainCheckbox("##dyeSphereMapIndex"u8, "Apply Sphere Map on Dye"u8, dye.SphereMapIndex,
|
||||
b => dyeTable[rowIdx].SphereMapIndex = b);
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetCursorScreenPos(ImGui.GetCursorScreenPos() with { Y = cursor.Y });
|
||||
ImGui.SetNextItemWidth(scalarSize + itemSpacing + 64.0f);
|
||||
using var dis = ImRaii.Disabled();
|
||||
CtSphereMapIndexPicker("###SphereMapIndexDye"u8, "Dye Preview for Sphere Map"u8, dyePack?.SphereMapIndex ?? ushort.MaxValue, false, Nop);
|
||||
}
|
||||
|
||||
ImGui.Dummy(new Vector2(64.0f, 0.0f));
|
||||
ImGui.SameLine();
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragScalar("Sphere Map Intensity"u8, default, (float)row.SphereMapMask * 100.0f, "%.0f%%"u8, HalfMinValue * 100.0f, HalfMaxValue * 100.0f, 1.0f,
|
||||
v => table[rowIdx].SphereMapMask = (Half)(v * 0.01f));
|
||||
if (dyeTable != null)
|
||||
{
|
||||
ImGui.SameLine(dyeOffset);
|
||||
ret |= CtApplyStainCheckbox("##dyeSphereMapMask"u8, "Apply Sphere Map Intensity on Dye"u8, dye.SphereMapMask,
|
||||
b => dyeTable[rowIdx].SphereMapMask = b);
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
CtDragScalar("##dyeSphereMapMask"u8, "Dye Preview for Sphere Map Intensity"u8, (float?)dyePack?.SphereMapMask * 100.0f, "%.0f%%"u8);
|
||||
}
|
||||
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
|
||||
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);
|
||||
var cursorPos = ImGui.GetCursorScreenPos();
|
||||
ImGui.SetCursorScreenPos(cursorPos + new Vector2(0.0f, (lineHeight - leftLineHeight) * 0.5f));
|
||||
ImGui.SetNextItemWidth(scalarSize + (itemSpacing + 64.0f) * 2.0f);
|
||||
ret |= CtTileIndexPicker("###TileIndex"u8, default, row.TileIndex, false,
|
||||
v => table[rowIdx].TileIndex = v);
|
||||
ImUtf8.SameLineInner();
|
||||
ImUtf8.Text("Tile"u8);
|
||||
|
||||
ImGui.SameLine(subcolWidth);
|
||||
ImGui.SetCursorScreenPos(ImGui.GetCursorScreenPos() with { Y = cursorPos.Y + (lineHeight - rightLineHeight) * 0.5f, });
|
||||
using (var cld = ImUtf8.Child("###TileProperties"u8, new(ImGui.GetContentRegionAvail().X, float.Lerp(rightLineHeight, lineHeight, 0.5f)), false))
|
||||
{
|
||||
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));
|
||||
|
||||
ret |= CtTileTransformMatrix(row.TileTransform, scalarSize, true,
|
||||
m => table[rowIdx].TileTransform = m);
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetCursorScreenPos(ImGui.GetCursorScreenPos() - new Vector2(0.0f, (ImGui.GetFrameHeight() + ImGui.GetStyle().ItemSpacing.Y) * 0.5f));
|
||||
ImUtf8.Text("Tile Transform"u8);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawPbr(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
||||
{
|
||||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
||||
var subcolWidth = CalculateSubcolumnWidth(2) + ImGui.GetStyle().ItemSpacing.X;
|
||||
var dyeOffset = subcolWidth - ImGui.GetStyle().ItemSpacing.X * 2.0f - ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight() - scalarSize;
|
||||
|
||||
var ret = false;
|
||||
ref var row = ref table[rowIdx];
|
||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragScalar("Roughness"u8, default, (float)row.Roughness * 100.0f, "%.0f%%"u8, HalfMinValue * 100.0f, HalfMaxValue * 100.0f, 1.0f,
|
||||
v => table[rowIdx].Roughness = (Half)(v * 0.01f));
|
||||
if (dyeTable != null)
|
||||
{
|
||||
ImGui.SameLine(dyeOffset);
|
||||
ret |= CtApplyStainCheckbox("##dyeRoughness"u8, "Apply Roughness on Dye"u8, dye.Roughness,
|
||||
b => dyeTable[rowIdx].Roughness = b);
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
CtDragScalar("##dyePreviewRoughness"u8, "Dye Preview for Roughness"u8, (float?)dyePack?.Roughness * 100.0f, "%.0f%%"u8);
|
||||
}
|
||||
|
||||
ImGui.SameLine(subcolWidth);
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragScalar("Metalness"u8, default, (float)row.Metalness * 100.0f, "%.0f%%"u8, HalfMinValue * 100.0f, HalfMaxValue * 100.0f, 1.0f,
|
||||
v => table[rowIdx].Metalness = (Half)(v * 0.01f));
|
||||
if (dyeTable != null)
|
||||
{
|
||||
ImGui.SameLine(subcolWidth + dyeOffset);
|
||||
ret |= CtApplyStainCheckbox("##dyeMetalness"u8, "Apply Metalness on Dye"u8, dye.Metalness,
|
||||
b => dyeTable[rowIdx].Metalness = b);
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
CtDragScalar("##dyePreviewMetalness"u8, "Dye Preview for Metalness"u8, (float?)dyePack?.Metalness * 100.0f, "%.0f%%"u8);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawSheen(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
||||
{
|
||||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
||||
var subcolWidth = CalculateSubcolumnWidth(2) + ImGui.GetStyle().ItemSpacing.X;
|
||||
var dyeOffset = subcolWidth - ImGui.GetStyle().ItemSpacing.X * 2.0f - ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight() - scalarSize;
|
||||
|
||||
var ret = false;
|
||||
ref var row = ref table[rowIdx];
|
||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragScalar("Sheen"u8, default, (float)row.SheenRate * 100.0f, "%.0f%%"u8, HalfMinValue * 100.0f, HalfMaxValue * 100.0f, 1.0f,
|
||||
v => table[rowIdx].SheenRate = (Half)(v * 0.01f));
|
||||
if (dyeTable != null)
|
||||
{
|
||||
ImGui.SameLine(dyeOffset);
|
||||
ret |= CtApplyStainCheckbox("##dyeSheenRate"u8, "Apply Sheen on Dye"u8, dye.SheenRate,
|
||||
b => dyeTable[rowIdx].SheenRate = b);
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
CtDragScalar("##dyePreviewSheenRate"u8, "Dye Preview for Sheen"u8, (float?)dyePack?.SheenRate * 100.0f, "%.0f%%"u8);
|
||||
}
|
||||
|
||||
ImGui.SameLine(subcolWidth);
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragScalar("Sheen Tint"u8, default, (float)row.SheenTintRate * 100.0f, "%.0f%%"u8, HalfMinValue * 100.0f, HalfMaxValue * 100.0f, 1.0f,
|
||||
v => table[rowIdx].SheenTintRate = (Half)(v * 0.01f));
|
||||
if (dyeTable != null)
|
||||
{
|
||||
ImGui.SameLine(subcolWidth + dyeOffset);
|
||||
ret |= CtApplyStainCheckbox("##dyeSheenTintRate"u8, "Apply Sheen Tint on Dye"u8, dye.SheenTintRate,
|
||||
b => dyeTable[rowIdx].SheenTintRate = b);
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
CtDragScalar("##dyePreviewSheenTintRate"u8, "Dye Preview for Sheen Tint"u8, (float?)dyePack?.SheenTintRate * 100.0f, "%.0f%%"u8);
|
||||
}
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragScalar("Sheen Roughness"u8, default, 100.0f / (float)row.SheenAperture, "%.0f%%"u8, 100.0f / HalfMaxValue, 100.0f / HalfEpsilon, 1.0f,
|
||||
v => table[rowIdx].SheenAperture = (Half)(100.0f / v));
|
||||
if (dyeTable != null)
|
||||
{
|
||||
ImGui.SameLine(dyeOffset);
|
||||
ret |= CtApplyStainCheckbox("##dyeSheenRoughness"u8, "Apply Sheen Roughness on Dye"u8, dye.SheenAperture,
|
||||
b => dyeTable[rowIdx].SheenAperture = b);
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
CtDragScalar("##dyePreviewSheenRoughness"u8, "Dye Preview for Sheen Roughness"u8, 100.0f / (float?)dyePack?.SheenAperture, "%.0f%%"u8);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawFurther(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx)
|
||||
{
|
||||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
||||
var subcolWidth = CalculateSubcolumnWidth(2) + ImGui.GetStyle().ItemSpacing.X;
|
||||
var dyeOffset = subcolWidth - ImGui.GetStyle().ItemSpacing.X * 2.0f - ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight() - scalarSize;
|
||||
|
||||
var ret = false;
|
||||
ref var row = ref table[rowIdx];
|
||||
var dye = dyeTable != null ? dyeTable[rowIdx] : default;
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragHalf("Field #11"u8, default, row.Scalar11, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||
v => table[rowIdx].Scalar11 = v);
|
||||
if (dyeTable != null)
|
||||
{
|
||||
ImGui.SameLine(dyeOffset);
|
||||
ret |= CtApplyStainCheckbox("##dyeScalar11"u8, "Apply Field #11 on Dye"u8, dye.Scalar3,
|
||||
b => dyeTable[rowIdx].Scalar3 = b);
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
CtDragHalf("##dyePreviewScalar11"u8, "Dye Preview for Field #11"u8, dyePack?.Scalar3, "%.2f"u8);
|
||||
}
|
||||
|
||||
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragHalf("Field #3"u8, default, row.Scalar3, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||
v => table[rowIdx].Scalar3 = v);
|
||||
|
||||
ImGui.SameLine(subcolWidth);
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragHalf("Field #7"u8, default, row.Scalar7, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||
v => table[rowIdx].Scalar7 = v);
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragHalf("Field #15"u8, default, row.Scalar15, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||
v => table[rowIdx].Scalar15 = v);
|
||||
|
||||
ImGui.SameLine(subcolWidth);
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragHalf("Field #17"u8, default, row.Scalar17, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||
v => table[rowIdx].Scalar17 = v);
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragHalf("Field #20"u8, default, row.Scalar20, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||
v => table[rowIdx].Scalar20 = v);
|
||||
|
||||
ImGui.SameLine(subcolWidth);
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragHalf("Field #22"u8, default, row.Scalar22, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||
v => table[rowIdx].Scalar22 = v);
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragHalf("Field #23"u8, default, row.Scalar23, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f,
|
||||
v => table[rowIdx].Scalar23 = v);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawDye(ColorDyeTable dyeTable, DyePack? dyePack, int rowIdx)
|
||||
{
|
||||
var scalarSize = ColorTableScalarSize * UiHelpers.Scale;
|
||||
var applyButtonWidth = ImUtf8.CalcTextSize("Apply Preview Dye"u8).X + ImGui.GetStyle().FramePadding.X * 2.0f;
|
||||
var subcolWidth = CalculateSubcolumnWidth(2, applyButtonWidth);
|
||||
|
||||
var ret = false;
|
||||
ref var dye = ref dyeTable[rowIdx];
|
||||
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
ret |= CtDragScalar("Dye Channel"u8, default, dye.Channel + 1, "%d"u8, 1, StainService.ChannelCount, 0.1f,
|
||||
value => dyeTable[rowIdx].Channel = (byte)(Math.Clamp(value, 1, StainService.ChannelCount) - 1));
|
||||
ImGui.SameLine(subcolWidth);
|
||||
ImGui.SetNextItemWidth(scalarSize);
|
||||
if (_stainService.GudTemplateCombo.Draw("##dyeTemplate", dye.Template.ToString(), string.Empty,
|
||||
scalarSize + ImGui.GetStyle().ScrollbarSize / 2, ImGui.GetTextLineHeightWithSpacing(), ImGuiComboFlags.NoArrowButton))
|
||||
{
|
||||
dye.Template = _stainService.LegacyTemplateCombo.CurrentSelection;
|
||||
ret = true;
|
||||
}
|
||||
ImUtf8.SameLineInner();
|
||||
ImUtf8.Text("Dye Template"u8);
|
||||
ImGui.SameLine(ImGui.GetContentRegionAvail().X - applyButtonWidth + ImGui.GetStyle().ItemSpacing.X);
|
||||
using var dis = ImRaii.Disabled(!dyePack.HasValue);
|
||||
if (ImUtf8.Button("Apply Preview Dye"u8))
|
||||
{
|
||||
ret |= Mtrl.ApplyDyeToRow(_stainService.GudStmFile, [
|
||||
_stainService.StainCombo1.CurrentSelection.Key,
|
||||
_stainService.StainCombo2.CurrentSelection.Key,
|
||||
], rowIdx);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static void CenteredTextInRest(string text)
|
||||
=> AlignedTextInRest(text, 0.5f);
|
||||
|
||||
private static void AlignedTextInRest(string text, float alignment)
|
||||
{
|
||||
var width = ImGui.CalcTextSize(text).X;
|
||||
ImGui.SetCursorScreenPos(ImGui.GetCursorScreenPos() + new Vector2((ImGui.GetContentRegionAvail().X - width) * alignment, 0.0f));
|
||||
ImGui.TextUnformatted(text);
|
||||
}
|
||||
|
||||
private static float CalculateSubcolumnWidth(int numSubcolumns, float reservedSpace = 0.0f)
|
||||
{
|
||||
var itemSpacing = ImGui.GetStyle().ItemSpacing.X;
|
||||
return (ImGui.GetContentRegionAvail().X - reservedSpace - itemSpacing * (numSubcolumns - 1)) / numSubcolumns + itemSpacing;
|
||||
}
|
||||
}
|
||||
|
|
@ -52,6 +52,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),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue