mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-13 20:24:17 +01:00
Fix bug with weapon colorsets, add table buttons.
This commit is contained in:
parent
c85598acf4
commit
cdaabc05e9
4 changed files with 92 additions and 14 deletions
|
|
@ -26,6 +26,7 @@ public sealed unsafe class AdvancedDyePopup(
|
||||||
private ActorState _state = null!;
|
private ActorState _state = null!;
|
||||||
private Actor _actor;
|
private Actor _actor;
|
||||||
private byte _selectedMaterial = byte.MaxValue;
|
private byte _selectedMaterial = byte.MaxValue;
|
||||||
|
private bool _anyChanged = false;
|
||||||
|
|
||||||
private bool ShouldBeDrawn()
|
private bool ShouldBeDrawn()
|
||||||
{
|
{
|
||||||
|
|
@ -162,7 +163,7 @@ public sealed unsafe class AdvancedDyePopup(
|
||||||
}
|
}
|
||||||
|
|
||||||
var size = new Vector2(7 * ImGui.GetFrameHeight() + 3 * ImGui.GetStyle().ItemInnerSpacing.X + 300 * ImGuiHelpers.GlobalScale,
|
var size = new Vector2(7 * ImGui.GetFrameHeight() + 3 * ImGui.GetStyle().ItemInnerSpacing.X + 300 * ImGuiHelpers.GlobalScale,
|
||||||
17f * ImGui.GetFrameHeightWithSpacing() + ImGui.GetStyle().WindowPadding.Y);
|
18 * ImGui.GetFrameHeightWithSpacing() + ImGui.GetStyle().WindowPadding.Y + ImGui.GetStyle().ItemSpacing.Y);
|
||||||
ImGui.SetNextWindowSize(size);
|
ImGui.SetNextWindowSize(size);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -192,12 +193,57 @@ public sealed unsafe class AdvancedDyePopup(
|
||||||
private void DrawTable(MaterialValueIndex materialIndex, in MtrlFile.ColorTable table)
|
private void DrawTable(MaterialValueIndex materialIndex, in MtrlFile.ColorTable table)
|
||||||
{
|
{
|
||||||
using var disabled = ImRaii.Disabled(_state.IsLocked);
|
using var disabled = ImRaii.Disabled(_state.IsLocked);
|
||||||
|
_anyChanged = false;
|
||||||
for (byte i = 0; i < MtrlFile.ColorTable.NumRows; ++i)
|
for (byte i = 0; i < MtrlFile.ColorTable.NumRows; ++i)
|
||||||
{
|
{
|
||||||
var index = materialIndex with { RowIndex = i };
|
var index = materialIndex with { RowIndex = i };
|
||||||
ref var row = ref table[i];
|
ref var row = ref table[i];
|
||||||
DrawRow(ref row, index, table);
|
DrawRow(ref row, index, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
DrawAllRow(materialIndex, table);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawAllRow(MaterialValueIndex materialIndex, in MtrlFile.ColorTable table)
|
||||||
|
{
|
||||||
|
using var id = ImRaii.PushId(100);
|
||||||
|
var buttonSize = new Vector2(ImGui.GetFrameHeight());
|
||||||
|
ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Crosshairs.ToIconString(), buttonSize, "Highlight all affected colors on the character.",
|
||||||
|
false, true);
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
preview.OnHover(materialIndex with { RowIndex = byte.MaxValue }, _actor.Index, table);
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
using (ImRaii.PushFont(UiBuilder.MonoFont))
|
||||||
|
{
|
||||||
|
ImGui.TextUnformatted("All Color Rows");
|
||||||
|
}
|
||||||
|
|
||||||
|
var spacing = ImGui.GetStyle().ItemInnerSpacing.X;
|
||||||
|
ImGui.SameLine(ImGui.GetWindowSize().X - 3 * buttonSize.X - 3 * spacing);
|
||||||
|
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Clipboard.ToIconString(), buttonSize, "Export this table to your clipboard.", false,
|
||||||
|
true))
|
||||||
|
ColorRowClipboard.Table = table;
|
||||||
|
ImGui.SameLine(0, spacing);
|
||||||
|
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Paste.ToIconString(), buttonSize,
|
||||||
|
"Import an exported table from your clipboard onto this table.", !ColorRowClipboard.IsTableSet, true))
|
||||||
|
foreach (var (row, idx) in ColorRowClipboard.Table.WithIndex())
|
||||||
|
{
|
||||||
|
var internalRow = new ColorRow(row);
|
||||||
|
var slot = materialIndex.ToEquipSlot();
|
||||||
|
var weapon = slot is EquipSlot.MainHand or EquipSlot.OffHand
|
||||||
|
? _state.ModelData.Weapon(slot)
|
||||||
|
: _state.ModelData.Armor(slot).ToWeapon(0);
|
||||||
|
var value = new MaterialValueState(internalRow, internalRow, weapon, StateSource.Manual);
|
||||||
|
stateManager.ChangeMaterialValue(_state!, materialIndex with { RowIndex = (byte)idx }, value, ApplySettings.Manual);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SameLine(0, spacing);
|
||||||
|
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.UndoAlt.ToIconString(), buttonSize, "Reset this table to game state.", !_anyChanged,
|
||||||
|
true))
|
||||||
|
for (byte i = 0; i < MtrlFile.ColorTable.NumRows; ++i)
|
||||||
|
stateManager.ResetMaterialValue(_state, materialIndex with { RowIndex = (byte)i }, ApplySettings.Game);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawRow(ref MtrlFile.ColorTable.Row row, MaterialValueIndex index, in MtrlFile.ColorTable table)
|
private void DrawRow(ref MtrlFile.ColorTable.Row row, MaterialValueIndex index, in MtrlFile.ColorTable table)
|
||||||
|
|
@ -213,6 +259,10 @@ public sealed unsafe class AdvancedDyePopup(
|
||||||
: _state.ModelData.Armor(slot).ToWeapon(0);
|
: _state.ModelData.Armor(slot).ToWeapon(0);
|
||||||
value = new MaterialValueState(internalRow, internalRow, weapon, StateSource.Manual);
|
value = new MaterialValueState(internalRow, internalRow, weapon, StateSource.Manual);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_anyChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
var buttonSize = new Vector2(ImGui.GetFrameHeight());
|
var buttonSize = new Vector2(ImGui.GetFrameHeight());
|
||||||
ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Crosshairs.ToIconString(), buttonSize, "Highlight the affected colors on the character.",
|
ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Crosshairs.ToIconString(), buttonSize, "Highlight the affected colors on the character.",
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,27 @@
|
||||||
using Glamourer.Interop.Material;
|
using Glamourer.Interop.Material;
|
||||||
|
using Penumbra.GameData.Files;
|
||||||
|
|
||||||
namespace Glamourer.Gui.Materials;
|
namespace Glamourer.Gui.Materials;
|
||||||
|
|
||||||
public static class ColorRowClipboard
|
public static class ColorRowClipboard
|
||||||
{
|
{
|
||||||
private static ColorRow _row;
|
private static ColorRow _row;
|
||||||
|
private static MtrlFile.ColorTable _table;
|
||||||
|
|
||||||
public static bool IsSet { get; private set; }
|
public static bool IsSet { get; private set; }
|
||||||
|
|
||||||
|
public static bool IsTableSet { get; private set; }
|
||||||
|
|
||||||
|
public static MtrlFile.ColorTable Table
|
||||||
|
{
|
||||||
|
get => _table;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
IsTableSet = true;
|
||||||
|
_table = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static ColorRow Row
|
public static ColorRow Row
|
||||||
{
|
{
|
||||||
get => _row;
|
get => _row;
|
||||||
|
|
|
||||||
|
|
@ -29,21 +29,20 @@ public sealed unsafe class LiveColorTablePreviewer : IService, IDisposable
|
||||||
|
|
||||||
private void Reset()
|
private void Reset()
|
||||||
{
|
{
|
||||||
if (!LastValueIndex.Valid || _lastObjectIndex == ObjectIndex.AnyIndex)
|
if (LastValueIndex.DrawObject is MaterialValueIndex.DrawObjectType.Invalid || _lastObjectIndex == ObjectIndex.AnyIndex)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var actor = (Actor)_objects.GetObjectAddress(_lastObjectIndex.Index);
|
var actor = (Actor)_objects.GetObjectAddress(_lastObjectIndex.Index);
|
||||||
if (actor.IsCharacter && LastValueIndex.TryGetTexture(actor, out var texture))
|
if (actor.IsCharacter && LastValueIndex.TryGetTexture(actor, out var texture))
|
||||||
MaterialService.ReplaceColorTable(texture, LastOriginalColorTable);
|
MaterialService.ReplaceColorTable(texture, LastOriginalColorTable);
|
||||||
|
|
||||||
Glamourer.Log.Information($"Reset {_lastObjectIndex} {LastValueIndex}");
|
|
||||||
LastValueIndex = MaterialValueIndex.Invalid;
|
LastValueIndex = MaterialValueIndex.Invalid;
|
||||||
_lastObjectIndex = ObjectIndex.AnyIndex;
|
_lastObjectIndex = ObjectIndex.AnyIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnFramework(IFramework _)
|
private void OnFramework(IFramework _)
|
||||||
{
|
{
|
||||||
if (!_valueIndex.Valid || _objectIndex == ObjectIndex.AnyIndex)
|
if (_valueIndex.DrawObject is MaterialValueIndex.DrawObjectType.Invalid || _objectIndex == ObjectIndex.AnyIndex)
|
||||||
{
|
{
|
||||||
Reset();
|
Reset();
|
||||||
_valueIndex = MaterialValueIndex.Invalid;
|
_valueIndex = MaterialValueIndex.Invalid;
|
||||||
|
|
@ -69,10 +68,24 @@ public sealed unsafe class LiveColorTablePreviewer : IService, IDisposable
|
||||||
|
|
||||||
if (_valueIndex.TryGetTexture(actor, out var texture))
|
if (_valueIndex.TryGetTexture(actor, out var texture))
|
||||||
{
|
{
|
||||||
var diffuse = CalculateDiffuse();
|
var diffuse = CalculateDiffuse();
|
||||||
var table = LastOriginalColorTable;
|
var emissive = diffuse / 8;
|
||||||
table[_valueIndex.RowIndex].Diffuse = diffuse;
|
var table = LastOriginalColorTable;
|
||||||
table[_valueIndex.RowIndex].Emissive = diffuse / 8;
|
if (_valueIndex.RowIndex != byte.MaxValue)
|
||||||
|
{
|
||||||
|
table[_valueIndex.RowIndex].Diffuse = diffuse;
|
||||||
|
table[_valueIndex.RowIndex].Emissive = emissive;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
for (var i = 0; i < MtrlFile.ColorTable.NumRows; ++i)
|
||||||
|
{
|
||||||
|
table[i].Diffuse = diffuse;
|
||||||
|
table[i].Emissive = emissive;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MaterialService.ReplaceColorTable(texture, table);
|
MaterialService.ReplaceColorTable(texture, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,12 +95,12 @@ public sealed unsafe class LiveColorTablePreviewer : IService, IDisposable
|
||||||
|
|
||||||
public void OnHover(MaterialValueIndex index, ObjectIndex objectIndex, MtrlFile.ColorTable table)
|
public void OnHover(MaterialValueIndex index, ObjectIndex objectIndex, MtrlFile.ColorTable table)
|
||||||
{
|
{
|
||||||
if (_valueIndex.Valid)
|
if (_valueIndex.DrawObject is not MaterialValueIndex.DrawObjectType.Invalid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_valueIndex = index;
|
_valueIndex = index;
|
||||||
_objectIndex = objectIndex;
|
_objectIndex = objectIndex;
|
||||||
if (!LastValueIndex.Valid
|
if (LastValueIndex.DrawObject is MaterialValueIndex.DrawObjectType.Invalid
|
||||||
|| _lastObjectIndex == ObjectIndex.AnyIndex
|
|| _lastObjectIndex == ObjectIndex.AnyIndex
|
||||||
|| LastValueIndex.MaterialIndex != _valueIndex.MaterialIndex
|
|| LastValueIndex.MaterialIndex != _valueIndex.MaterialIndex
|
||||||
|| LastValueIndex.DrawObject != _valueIndex.DrawObject
|
|| LastValueIndex.DrawObject != _valueIndex.DrawObject
|
||||||
|
|
|
||||||
|
|
@ -74,15 +74,16 @@ public sealed unsafe class PrepareColorSet
|
||||||
public static bool TryGetColorTable(Actor actor, MaterialValueIndex index, out MtrlFile.ColorTable table)
|
public static bool TryGetColorTable(Actor actor, MaterialValueIndex index, out MtrlFile.ColorTable table)
|
||||||
{
|
{
|
||||||
var idx = index.SlotIndex * MaterialService.MaterialsPerModel + index.MaterialIndex;
|
var idx = index.SlotIndex * MaterialService.MaterialsPerModel + index.MaterialIndex;
|
||||||
var model = actor.Model.AsCharacterBase;
|
if (!index.TryGetModel(actor, out var model))
|
||||||
var handle = (MaterialResourceHandle*)model->Materials[idx];
|
return false;
|
||||||
|
var handle = (MaterialResourceHandle*)model.AsCharacterBase->Materials[idx];
|
||||||
if (handle == null)
|
if (handle == null)
|
||||||
{
|
{
|
||||||
table = default;
|
table = default;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TryGetColorTable(model, handle, GetStain(), out table);
|
return TryGetColorTable(model.AsCharacterBase, handle, GetStain(), out table);
|
||||||
|
|
||||||
StainId GetStain()
|
StainId GetStain()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue