Fix issue with shapes/attributes not checking the groups correctly.

This commit is contained in:
Ottermandias 2025-05-23 11:29:52 +02:00
parent 1bdbfe22c1
commit 08c9124858
2 changed files with 45 additions and 36 deletions

View file

@ -21,43 +21,39 @@ public sealed class ShapeAttributeHashSet : Dictionary<(HumanSlot Slot, PrimaryI
private readonly BitArray _allIds = new((ShapeAttributeManager.ModelSlotSize + 1) * GenderRaceValues.Count); private readonly BitArray _allIds = new((ShapeAttributeManager.ModelSlotSize + 1) * GenderRaceValues.Count);
public bool this[HumanSlot slot] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
=> slot is HumanSlot.Unknown ? All : _allIds[(int)slot * GenderRaceIndices.Count]; private bool CheckGroups(HumanSlot slot, GenderRace genderRace)
public bool this[GenderRace genderRace]
=> GenderRaceIndices.TryGetValue(genderRace, out var index)
&& _allIds[ShapeAttributeManager.ModelSlotSize * GenderRaceIndices.Count + index];
public bool this[HumanSlot slot, GenderRace genderRace]
{ {
get if (All || this[slot])
{ return true;
if (!GenderRaceIndices.TryGetValue(genderRace, out var index))
return false;
if (_allIds[ShapeAttributeManager.ModelSlotSize * GenderRaceIndices.Count + index]) if (!GenderRaceIndices.TryGetValue(genderRace, out var index))
return true; return false;
return _allIds[(int)slot * GenderRaceIndices.Count + index]; if (_allIds[ToIndex(HumanSlot.Unknown, index)])
} return true;
set
{
if (!GenderRaceIndices.TryGetValue(genderRace, out var index))
return;
var genderRaceCount = GenderRaceValues.Count; return _allIds[ToIndex(slot, index)];
if (slot is HumanSlot.Unknown)
_allIds[ShapeAttributeManager.ModelSlotSize * genderRaceCount + index] = value;
else
_allIds[(int)slot * genderRaceCount + index] = value;
}
} }
public bool this[HumanSlot slot]
=> _allIds[ToIndex(slot, 0)];
public bool this[GenderRace genderRace]
=> ToIndex(HumanSlot.Unknown, genderRace, out var index) && _allIds[index];
public bool this[HumanSlot slot, GenderRace genderRace]
=> ToIndex(slot, genderRace, out var index) && _allIds[index];
public bool All public bool All
=> _allIds[ShapeAttributeManager.ModelSlotSize * GenderRaceIndices.Count]; => _allIds[AllIndex];
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static int ToIndex(HumanSlot slot, int genderRaceIndex)
=> slot is HumanSlot.Unknown ? genderRaceIndex + AllIndex : genderRaceIndex + (int)slot * GenderRaceValues.Count;
public bool Contains(HumanSlot slot, PrimaryId id, GenderRace genderRace) public bool Contains(HumanSlot slot, PrimaryId id, GenderRace genderRace)
=> All || this[slot, genderRace] || ContainsEntry(slot, id, genderRace); => CheckGroups(slot, genderRace) || ContainsEntry(slot, id, genderRace);
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private bool ContainsEntry(HumanSlot slot, PrimaryId id, GenderRace genderRace) private bool ContainsEntry(HumanSlot slot, PrimaryId id, GenderRace genderRace)
@ -72,9 +68,9 @@ public sealed class ShapeAttributeHashSet : Dictionary<(HumanSlot Slot, PrimaryI
if (!id.HasValue) if (!id.HasValue)
{ {
var slotIndex = slot is HumanSlot.Unknown ? ShapeAttributeManager.ModelSlotSize : (int)slot; var slotIndex = ToIndex(slot, index);
var old = _allIds[slotIndex * GenderRaceIndices.Count + index]; var old = _allIds[slotIndex];
_allIds[slotIndex * GenderRaceIndices.Count + index] = value; _allIds[slotIndex] = value;
return old != value; return old != value;
} }
@ -120,4 +116,16 @@ public sealed class ShapeAttributeHashSet : Dictionary<(HumanSlot Slot, PrimaryI
public bool IsEmpty public bool IsEmpty
=> !_allIds.HasAnySet() && Count is 0; => !_allIds.HasAnySet() && Count is 0;
private static readonly int AllIndex = ShapeAttributeManager.ModelSlotSize * GenderRaceValues.Count;
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static bool ToIndex(HumanSlot slot, GenderRace genderRace, out int index)
{
if (!GenderRaceIndices.TryGetValue(genderRace, out index))
return false;
index = ToIndex(slot, index);
return true;
}
} }

View file

@ -1,6 +1,7 @@
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Utility.Raii;
using ImGuiNET; using ImGuiNET;
using OtterGui.Extensions;
using OtterGui.Services; using OtterGui.Services;
using OtterGui.Text; using OtterGui.Text;
using Penumbra.Collections.Cache; using Penumbra.Collections.Cache;
@ -167,7 +168,7 @@ public class ShapeInspector(ObjectManager objects, CollectionResolver resolver)
ImUtf8.TableSetupColumn("Slot"u8, ImGuiTableColumnFlags.WidthFixed, 150 * ImUtf8.GlobalScale); ImUtf8.TableSetupColumn("Slot"u8, ImGuiTableColumnFlags.WidthFixed, 150 * ImUtf8.GlobalScale);
ImUtf8.TableSetupColumn("Address"u8, ImGuiTableColumnFlags.WidthFixed, UiBuilder.MonoFont.GetCharAdvance('0') * 14); ImUtf8.TableSetupColumn("Address"u8, ImGuiTableColumnFlags.WidthFixed, UiBuilder.MonoFont.GetCharAdvance('0') * 14);
ImUtf8.TableSetupColumn("Mask"u8, ImGuiTableColumnFlags.WidthFixed, UiBuilder.MonoFont.GetCharAdvance('0') * 8); ImUtf8.TableSetupColumn("Mask"u8, ImGuiTableColumnFlags.WidthFixed, UiBuilder.MonoFont.GetCharAdvance('0') * 8);
ImUtf8.TableSetupColumn("Count"u8, ImGuiTableColumnFlags.WidthFixed, 30 * ImUtf8.GlobalScale); ImUtf8.TableSetupColumn("Count"u8, ImGuiTableColumnFlags.WidthFixed, 30 * ImUtf8.GlobalScale);
ImUtf8.TableSetupColumn("Shapes"u8, ImGuiTableColumnFlags.WidthStretch); ImUtf8.TableSetupColumn("Shapes"u8, ImGuiTableColumnFlags.WidthStretch);
ImGui.TableHeadersRow(); ImGui.TableHeadersRow();
@ -187,9 +188,9 @@ public class ShapeInspector(ObjectManager objects, CollectionResolver resolver)
ImUtf8.DrawTableColumn($"{mask:X8}"); ImUtf8.DrawTableColumn($"{mask:X8}");
ImUtf8.DrawTableColumn($"{model->ModelResourceHandle->Shapes.Count}"); ImUtf8.DrawTableColumn($"{model->ModelResourceHandle->Shapes.Count}");
ImGui.TableNextColumn(); ImGui.TableNextColumn();
foreach (var (shape, idx) in model->ModelResourceHandle->Shapes) foreach (var ((shape, flag), idx) in model->ModelResourceHandle->Shapes.WithIndex())
{ {
var disabled = (mask & (1u << idx)) is 0; var disabled = (mask & (1u << flag)) is 0;
using var color = ImRaii.PushColor(ImGuiCol.Text, disabledColor, disabled); using var color = ImRaii.PushColor(ImGuiCol.Text, disabledColor, disabled);
ImUtf8.Text(shape.AsSpan()); ImUtf8.Text(shape.AsSpan());
ImGui.SameLine(0, 0); ImGui.SameLine(0, 0);
@ -241,9 +242,9 @@ public class ShapeInspector(ObjectManager objects, CollectionResolver resolver)
ImUtf8.DrawTableColumn($"{mask:X8}"); ImUtf8.DrawTableColumn($"{mask:X8}");
ImUtf8.DrawTableColumn($"{model->ModelResourceHandle->Attributes.Count}"); ImUtf8.DrawTableColumn($"{model->ModelResourceHandle->Attributes.Count}");
ImGui.TableNextColumn(); ImGui.TableNextColumn();
foreach (var (attribute, idx) in model->ModelResourceHandle->Attributes) foreach (var ((attribute, flag), idx) in model->ModelResourceHandle->Attributes.WithIndex())
{ {
var disabled = (mask & (1u << idx)) is 0; var disabled = (mask & (1u << flag)) is 0;
using var color = ImRaii.PushColor(ImGuiCol.Text, disabledColor, disabled); using var color = ImRaii.PushColor(ImGuiCol.Text, disabledColor, disabled);
ImUtf8.Text(attribute.AsSpan()); ImUtf8.Text(attribute.AsSpan());
ImGui.SameLine(0, 0); ImGui.SameLine(0, 0);