diff --git a/Penumbra.GameData b/Penumbra.GameData index 2946073a..6c02858d 160000 --- a/Penumbra.GameData +++ b/Penumbra.GameData @@ -1 +1 @@ -Subproject commit 2946073ad67f2d9ddac4ef6135660f7607542300 +Subproject commit 6c02858d5a3d20100377dd127d1b85dbe82a4c44 diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs index f211c1fe..7b5ba868 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs @@ -456,8 +456,8 @@ public partial class MtrlTab var dye = 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, + ret |= CtDragScalar("Roughness"u8, default, (float)row.Roughness * 100.0f, "%.0f%%"u8, 0.0f, 100.0f, + 0.25f, v => table[rowIdx].Roughness = (Half)(v * 0.01f)); if (dyeTable != null) { @@ -471,8 +471,8 @@ public partial class MtrlTab 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, + ret |= CtDragScalar("Metalness"u8, default, (float)row.Metalness * 100.0f, "%.0f%%"u8, 0.0f, 100.0f, + 0.25f, v => table[rowIdx].Metalness = (Half)(v * 0.01f)); if (dyeTable != null) { diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs index f3ca43b9..cf788143 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs @@ -9,6 +9,8 @@ namespace Penumbra.UI.AdvancedWindow.Materials; public partial class MtrlTab { + private static readonly float EffectiveMaxShininess = (float)LegacyColorTableRow.EffectiveMaxShininess; + private bool DrawLegacyColorTable(IColorTable table, IColorDyeTable? dyeTable, bool disabled, MtrlTabUiState uiState) where TRow : unmanaged, ILegacyColorRow where TDyeRow : unmanaged, ILegacyColorDyeRow { @@ -147,7 +149,7 @@ public partial class MtrlTab ImGui.SameLine(subColWidth); ImGui.SetNextItemWidth(scalarSize); var shininessMin = ImGui.GetIO().KeyCtrl ? 0.0f : HalfEpsilon; - ret |= CtDragHalf("Gloss"u8, default, row.Shininess, "%.1f"u8, shininessMin, HalfMaxValue, + ret |= CtDragHalf("Gloss"u8, default, row.Shininess, "%.1f"u8, shininessMin, EffectiveMaxShininess, Math.Max(0.1f, (float)row.Shininess * 0.025f), v => table[rowIdx].Shininess = v); if (dyeTable != null) diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ShaderPackage.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ShaderPackage.cs index ae57a122..c86001b0 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ShaderPackage.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ShaderPackage.cs @@ -1,5 +1,6 @@ using Dalamud.Interface; using Dalamud.Interface.ImGuiNotification; +using FFXIVClientStructs.FFXIV.Common.Lua; using ImGuiNET; using Newtonsoft.Json.Linq; using OtterGui; @@ -9,6 +10,7 @@ using OtterGui.Text; using Penumbra.GameData; using Penumbra.GameData.Data; using Penumbra.GameData.Files; +using Penumbra.GameData.Files.MaterialStructs; using Penumbra.GameData.Files.ShaderStructs; using Penumbra.String.Classes; using static Penumbra.GameData.Files.ShpkFile; @@ -327,6 +329,7 @@ public partial class MtrlTab DrawCustomAssociations(); ret |= DrawMaterialShaderKeys(disabled); DrawMaterialShaders(); + ret |= DrawShaderQuickActions(disabled); } if (!_shpkLoading && (_associatedShpk == null || _associatedShpkDevkit == null)) @@ -362,16 +365,21 @@ public partial class MtrlTab if (!ImGui.Selectable(value, value == Mtrl.ShaderPackage.Name)) continue; - Mtrl.ShaderPackage.Name = value; - ret = true; - _associatedShpk = null; - _loadedShpkPath = FullPath.Empty; - LoadShpk(FindAssociatedShpk(out _, out _)); + ret = true; + SwitchToShaderPackage(value); } return ret; } + private void SwitchToShaderPackage(string shPkName) + { + Mtrl.ShaderPackage.Name = shPkName; + _associatedShpk = null; + _loadedShpkPath = FullPath.Empty; + LoadShpk(FindAssociatedShpk(out _, out _)); + } + private bool DrawShaderFlagsInput(bool disabled) { var shpkFlags = (int)Mtrl.ShaderPackage.Flags; @@ -504,4 +512,35 @@ public partial class MtrlTab ImUtf8.Text(_shaderComment); } } + + private bool DrawShaderQuickActions(bool disabled) + { + if (disabled) + return false; + + var ret = false; + if (Mtrl.ShaderPackage.Name is "characterlegacy.shpk") + { + using var _ = ImRaii.Disabled(!ImGui.GetIO().KeyCtrl); + if (ImUtf8.Button("[Experimental] Convert to New character.shpk"u8)) + ret |= ConvertToNewCharacterShader(); + ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, "This operation will switch this material to character.shpk and convert its color table accordingly.\nThis conversion is experimental and will require further manual edits to this material, and may also require edits to the model and/or textures.\n\nHold Ctrl to unlock."u8); + } + + return ret; + } + + private bool ConvertToNewCharacterShader() + { + if (Mtrl.ShaderPackage.Name is not "characterlegacy.shpk") + return false; + + SwitchToShaderPackage("character.shpk"); + if (Mtrl.Table is ColorTable colorTable) + colorTable.ConvertFromCharacterLegacy(); + if (Mtrl.DyeTable is ColorDyeTable colorDyeTable) + colorDyeTable.ConvertFromCharacterLegacy(); + + return true; + } }