From b3a993a2bc6c34fd3a9e531fc0c2b1958592aa84 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Fri, 11 Nov 2022 15:59:35 +0100 Subject: [PATCH] Further work on Dye Template previews --- OtterGui | 2 +- Penumbra.GameData/Files/StmFile.cs | 26 ++++++----- Penumbra/UI/Classes/ModEditWindow.FileEdit.cs | 46 ++++++++++++++++--- Penumbra/Util/StainManager.cs | 27 +++++++---- 4 files changed, 73 insertions(+), 28 deletions(-) diff --git a/OtterGui b/OtterGui index f2d99609..cbf21c63 160000 --- a/OtterGui +++ b/OtterGui @@ -1 +1 @@ -Subproject commit f2d996094058059b67b27a208303627c83b26d69 +Subproject commit cbf21c639f91d39422b2d4b7244bd8d8c5d5d4d7 diff --git a/Penumbra.GameData/Files/StmFile.cs b/Penumbra.GameData/Files/StmFile.cs index 38f0bc47..288c8600 100644 --- a/Penumbra.GameData/Files/StmFile.cs +++ b/Penumbra.GameData/Files/StmFile.cs @@ -2,6 +2,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.IO; +using System.Numerics; using Dalamud.Data; using Lumina.Extensions; using Penumbra.GameData.Structs; @@ -14,11 +15,11 @@ public partial class StmFile public record struct DyePack { - public uint Diffuse; - public uint Specular; - public uint Emissive; - public float SpecularPower; - public float Gloss; + public Vector3 Diffuse; + public Vector3 Specular; + public Vector3 Emissive; + public float SpecularPower; + public float Gloss; } public readonly struct StainingTemplateEntry @@ -31,9 +32,6 @@ public partial class StmFile public readonly IReadOnlyList SpecularPowerEntries; public readonly IReadOnlyList GlossEntries; - private static uint HalfToByte(Half value) - => (byte)((float)value * byte.MaxValue + 0.5f); - public DyePack this[StainId idx] => this[(int)idx.Value]; @@ -41,16 +39,20 @@ public partial class StmFile { get { + if (idx is <= 0 or > NumElements) + return default; + + --idx; var (dr, dg, db) = DiffuseEntries[idx]; var (sr, sg, sb) = SpecularEntries[idx]; var (er, eg, eb) = EmissiveEntries[idx]; var sp = SpecularPowerEntries[idx]; var g = GlossEntries[idx]; - return new DyePack() + return new DyePack { - Diffuse = 0xFF000000u | HalfToByte(dr) | (HalfToByte(dg) << 8) | (HalfToByte(db) << 16), - Emissive = 0xFF000000u | HalfToByte(sr) | (HalfToByte(sg) << 8) | (HalfToByte(sb) << 16), - Specular = 0xFF000000u | HalfToByte(er) | (HalfToByte(eg) << 8) | (HalfToByte(eb) << 16), + Diffuse = new Vector3((float)dr, (float)dg, (float)db), + Emissive = new Vector3((float)sr, (float)sg, (float)sb), + Specular = new Vector3((float)er, (float)eg, (float)eb), SpecularPower = (float)sp, Gloss = (float)g, }; diff --git a/Penumbra/UI/Classes/ModEditWindow.FileEdit.cs b/Penumbra/UI/Classes/ModEditWindow.FileEdit.cs index ed9ddd10..3f6ba35b 100644 --- a/Penumbra/UI/Classes/ModEditWindow.FileEdit.cs +++ b/Penumbra/UI/Classes/ModEditWindow.FileEdit.cs @@ -8,9 +8,12 @@ using System.Runtime.InteropServices; using Dalamud.Interface; using Dalamud.Interface.ImGuiFileDialog; using ImGuiNET; +using Lumina.Data.Parsing.Layer; using OtterGui; using OtterGui.Raii; +using OtterGui.Widgets; using Penumbra.GameData.Files; +using Penumbra.GameData.Structs; using Penumbra.Mods; using Penumbra.String.Classes; using Penumbra.String.Functions; @@ -326,7 +329,14 @@ public partial class ModEditWindow ColorSetCopyAllClipboardButton( file, 0 ); ImGui.SameLine(); var ret = ColorSetPasteAllClipboardButton( file, 0 ); - using var table = ImRaii.Table( "##ColorSets", 10, + ImGui.SameLine(); + ImGui.Dummy( ImGuiHelpers.ScaledVector2( 10, 0 ) ); + ImGui.SameLine(); + Penumbra.StainManager.StainCombo.Draw( "Preview Dye", Penumbra.StainManager.StainCombo.CurrentSelection.Value.Color, true ); + ImGui.SameLine(); + ImGui.Button( "Apply Preview Dyes." ); + + using var table = ImRaii.Table( "##ColorSets", 11, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersInnerV ); if( !table ) { @@ -353,6 +363,8 @@ public partial class ModEditWindow ImGui.TableHeader( "Skew" ); ImGui.TableNextColumn(); ImGui.TableHeader( "Dye" ); + ImGui.TableNextColumn(); + ImGui.TableHeader( "Dye Preview" ); for( var j = 0; j < file.ColorSets.Length; ++j ) { @@ -731,17 +743,37 @@ public partial class ModEditWindow ImGui.TableNextColumn(); if( hasDye ) { - tmpInt = dye.Template; - ImGui.SetNextItemWidth( intSize ); - if( ImGui.InputInt( "##DyeTemplate", ref tmpInt, 0, 0 ) - && tmpInt != dye.Template - && tmpInt is >= 0 and <= ushort.MaxValue ) + if( Penumbra.StainManager.TemplateCombo.Draw( "##dyeTemplate", dye.Template.ToString(), intSize + + ImGui.GetStyle().ScrollbarSize / 2, ImGui.GetTextLineHeightWithSpacing(), ImGuiComboFlags.NoArrowButton ) ) { - file.ColorDyeSets[ colorSetIdx ].Rows[ rowIdx ].Template = ( ushort )tmpInt; + file.ColorDyeSets[ colorSetIdx ].Rows[ rowIdx ].Template = Penumbra.StainManager.TemplateCombo.CurrentSelection; ret = true; } ImGuiUtil.HoverTooltip( "Dye Template", ImGuiHoveredFlags.AllowWhenDisabled ); + + ImGui.TableNextColumn(); + var stain = Penumbra.StainManager.StainCombo.CurrentSelection.Key; + if( stain != 0 && Penumbra.StainManager.StmFile.Entries.TryGetValue( dye.Template, out var entry ) ) + { + var values = entry[ ( int )stain ]; + using var _ = ImRaii.Disabled(); + ColorPicker( "##diffusePreview", string.Empty, values.Diffuse, c => { } ); + ImGui.SameLine(); + ColorPicker( "##specularPreview", string.Empty, values.Specular, c => { } ); + ImGui.SameLine(); + ColorPicker( "##emissivePreview", string.Empty, values.Emissive, c => { } ); + ImGui.SameLine(); + ImGui.SetNextItemWidth( floatSize ); + ImGui.DragFloat( "##specularStrength", ref values.SpecularPower ); + ImGui.SameLine(); + ImGui.SetNextItemWidth( floatSize ); + ImGui.DragFloat( "##gloss", ref values.Gloss ); + } + } + else + { + ImGui.TableNextColumn(); } diff --git a/Penumbra/Util/StainManager.cs b/Penumbra/Util/StainManager.cs index fc42e78e..91c9a731 100644 --- a/Penumbra/Util/StainManager.cs +++ b/Penumbra/Util/StainManager.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using Dalamud.Data; using Dalamud.Plugin; using OtterGui.Widgets; @@ -9,15 +11,24 @@ namespace Penumbra.Util; public class StainManager : IDisposable { - public readonly StainData StainData; - public readonly FilterComboColors Combo; - public readonly StmFile StmFile; - - public StainManager(DalamudPluginInterface pluginInterface, DataManager dataManager) + public sealed class StainTemplateCombo : FilterComboCache< ushort > { - StainData = new StainData( pluginInterface, dataManager, dataManager.Language ); - Combo = new FilterComboColors( 140, StainData.Data ); - StmFile = new StmFile( dataManager ); + public StainTemplateCombo( IEnumerable< ushort > items ) + : base( items ) + { } + } + + public readonly StainData StainData; + public readonly FilterComboColors StainCombo; + public readonly StmFile StmFile; + public readonly StainTemplateCombo TemplateCombo; + + public StainManager( DalamudPluginInterface pluginInterface, DataManager dataManager ) + { + StainData = new StainData( pluginInterface, dataManager, dataManager.Language ); + StainCombo = new FilterComboColors( 140, StainData.Data.Prepend( new KeyValuePair< byte, (string Name, uint Dye, bool Gloss) >( 0, ( "None", 0, false ) ) ) ); + StmFile = new StmFile( dataManager ); + TemplateCombo = new StainTemplateCombo( StmFile.Entries.Keys.Prepend( ( ushort )0 ) ); } public void Dispose()