mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
Add some valid options for material values.
This commit is contained in:
parent
ef2d9ba207
commit
0bc9fc872e
3 changed files with 52 additions and 18 deletions
|
|
@ -57,7 +57,7 @@ public class GlamourerChangelog
|
|||
.RegisterEntry(
|
||||
"This was a considerable backend change on both automation sets and design application. I may have messed up and introduced bugs. Please let me know if something does not work right anymore.",
|
||||
1)
|
||||
.RegisterHighlight("Added advanced dye options for equipment. You can now runtime-edit the color sets of your gear.")
|
||||
.RegisterHighlight("Added advanced dye options for equipment. You can now live-edit the color sets of your gear.")
|
||||
.RegisterEntry(
|
||||
"The logic for this is very complicated and may interfere with other options or not update correctly, it will need a lot of testing.",
|
||||
1)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using System.Reflection.Metadata.Ecma335;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Utility;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
||||
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
|
||||
using FFXIVClientStructs.Interop;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Interop.Material;
|
||||
|
|
@ -13,6 +13,7 @@ using OtterGui.Raii;
|
|||
using OtterGui.Services;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Files;
|
||||
using Penumbra.String;
|
||||
|
||||
namespace Glamourer.Gui.Materials;
|
||||
|
||||
|
|
@ -68,6 +69,20 @@ public sealed unsafe class AdvancedDyePopup(
|
|||
ImGuiUtil.HoverTooltip("Open advanced dyes for this slot.");
|
||||
}
|
||||
|
||||
private (string Path, string GamePath) ResourceName(MaterialValueIndex index)
|
||||
{
|
||||
var materialHandle = (MaterialResourceHandle*)_actor.Model.AsCharacterBase->MaterialsSpan[
|
||||
index.MaterialIndex + index.SlotIndex * MaterialService.MaterialsPerModel].Value;
|
||||
var model = _actor.Model.AsCharacterBase->ModelsSpan[index.SlotIndex].Value;
|
||||
var modelHandle = model == null ? null : model->ModelResourceHandle;
|
||||
var path = materialHandle == null
|
||||
? string.Empty
|
||||
: ByteString.FromSpanUnsafe(materialHandle->ResourceHandle.FileName.AsSpan(), true).ToString();
|
||||
var gamePath = modelHandle == null
|
||||
? string.Empty
|
||||
: modelHandle->GetMaterialFileNameBySlotAsString(index.MaterialIndex);
|
||||
return (path, gamePath);
|
||||
}
|
||||
|
||||
private void DrawTabBar(ReadOnlySpan<Pointer<Texture>> textures, ref bool firstAvailable)
|
||||
{
|
||||
|
|
@ -79,6 +94,7 @@ public sealed unsafe class AdvancedDyePopup(
|
|||
{
|
||||
var index = _drawIndex!.Value with { MaterialIndex = i };
|
||||
var available = index.TryGetTexture(textures, out var texture) && index.TryGetColorTable(texture, out var table);
|
||||
|
||||
if (index == preview.LastValueIndex with { RowIndex = 0 })
|
||||
table = preview.LastOriginalColorTable;
|
||||
|
||||
|
|
@ -91,11 +107,16 @@ public sealed unsafe class AdvancedDyePopup(
|
|||
firstAvailable = false;
|
||||
|
||||
using var tab = _label.TabItem(i, select);
|
||||
if (!available)
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
||||
{
|
||||
using var disabled = ImRaii.Enabled();
|
||||
ImGuiUtil.HoverTooltip("This material does not exist or does not have an associated color set.",
|
||||
ImGuiHoveredFlags.AllowWhenDisabled);
|
||||
using var enabled = ImRaii.Enabled();
|
||||
var (path, gamePath) = ResourceName(index);
|
||||
if (gamePath.Length == 0 || path.Length == 0)
|
||||
ImGui.SetTooltip("This material does not exist.");
|
||||
else if (!available)
|
||||
ImGui.SetTooltip($"This material does not have an associated color set.\n\n{gamePath}\n{path}");
|
||||
else
|
||||
ImGui.SetTooltip($"{gamePath}\n{path}");
|
||||
}
|
||||
|
||||
if ((tab.Success || select is ImGuiTabItemFlags.SetSelected) && available)
|
||||
|
|
@ -186,7 +207,7 @@ public sealed unsafe class AdvancedDyePopup(
|
|||
if (!changed)
|
||||
{
|
||||
var internalRow = new ColorRow(row);
|
||||
var slot = index.ToSlot();
|
||||
var slot = index.ToEquipSlot();
|
||||
var weapon = slot is EquipSlot.MainHand or EquipSlot.OffHand
|
||||
? _state.ModelData.Weapon(slot)
|
||||
: _state.ModelData.Armor(slot).ToWeapon(0);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public readonly record struct MaterialValueIndex(
|
|||
=> ToKey(DrawObject, SlotIndex, MaterialIndex, RowIndex);
|
||||
|
||||
public bool Valid
|
||||
=> Validate(DrawObject) && ValidateSlot(SlotIndex) && ValidateMaterial(MaterialIndex) && ValidateRow(RowIndex);
|
||||
=> Validate(DrawObject) && ValidateSlot(DrawObject, SlotIndex) && ValidateMaterial(MaterialIndex) && ValidateRow(RowIndex);
|
||||
|
||||
public static bool FromKey(uint key, out MaterialValueIndex index)
|
||||
{
|
||||
|
|
@ -42,7 +42,7 @@ public readonly record struct MaterialValueIndex(
|
|||
return Invalid;
|
||||
}
|
||||
|
||||
public EquipSlot ToSlot()
|
||||
public EquipSlot ToEquipSlot()
|
||||
=> DrawObject switch
|
||||
{
|
||||
DrawObjectType.Human when SlotIndex < 10 => ((uint)SlotIndex).ToEquipSlot(),
|
||||
|
|
@ -155,8 +155,14 @@ public readonly record struct MaterialValueIndex(
|
|||
public static bool Validate(DrawObjectType type)
|
||||
=> type is not DrawObjectType.Invalid && Enum.IsDefined(type);
|
||||
|
||||
public static bool ValidateSlot(byte slotIndex)
|
||||
=> slotIndex < 10;
|
||||
public static bool ValidateSlot(DrawObjectType type, byte slotIndex)
|
||||
=> type switch
|
||||
{
|
||||
DrawObjectType.Human => slotIndex < 14,
|
||||
DrawObjectType.Mainhand => slotIndex == 0,
|
||||
DrawObjectType.Offhand => slotIndex == 0,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
public static bool ValidateMaterial(byte materialIndex)
|
||||
=> materialIndex < MaterialService.MaterialsPerModel;
|
||||
|
|
@ -178,12 +184,19 @@ public readonly record struct MaterialValueIndex(
|
|||
{ }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var slot = ToSlot();
|
||||
return slot is EquipSlot.Unknown
|
||||
? $"{DrawObject} Slot {SlotIndex} Material #{MaterialIndex + 1} Row #{RowIndex + 1}"
|
||||
: $"{slot.ToName()} Material #{MaterialIndex + 1} Row #{RowIndex + 1}";
|
||||
}
|
||||
=> DrawObject switch
|
||||
{
|
||||
DrawObjectType.Invalid => "Invalid",
|
||||
DrawObjectType.Human when SlotIndex < 10 =>
|
||||
$"{((uint)SlotIndex).ToEquipSlot().ToName()} Material #{MaterialIndex + 1} Row #{RowIndex + 1}",
|
||||
DrawObjectType.Human when SlotIndex == 10 => $"BodySlot.Hair.ToString() Material #{MaterialIndex + 1} Row #{RowIndex + 1}",
|
||||
DrawObjectType.Human when SlotIndex == 11 => $"BodySlot.Face.ToString() Material #{MaterialIndex + 1} Row #{RowIndex + 1}",
|
||||
DrawObjectType.Human when SlotIndex == 12 => $"{BodySlot.Tail} / {BodySlot.Ear} Material #{MaterialIndex + 1} Row #{RowIndex + 1}",
|
||||
DrawObjectType.Human when SlotIndex == 13 => $"Connectors Material #{MaterialIndex + 1} Row #{RowIndex + 1}",
|
||||
DrawObjectType.Mainhand when SlotIndex == 0 => $"{EquipSlot.MainHand.ToName()} Material #{MaterialIndex + 1} Row #{RowIndex + 1}",
|
||||
DrawObjectType.Offhand when SlotIndex == 0 => $"{EquipSlot.OffHand.ToName()} Material #{MaterialIndex + 1} Row #{RowIndex + 1}",
|
||||
_ => $"{DrawObject} Slot {SlotIndex} Material #{MaterialIndex + 1} Row #{RowIndex + 1}",
|
||||
};
|
||||
|
||||
private class Converter : JsonConverter<MaterialValueIndex>
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue