mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2026-02-22 23:47:45 +01:00
Remove Turn Human, update HumanNpcCombo
This commit is contained in:
parent
06e1fb2a3b
commit
bc5538dd9d
3 changed files with 105 additions and 62 deletions
|
|
@ -262,8 +262,6 @@ public sealed class ActorPanel : IPanel
|
||||||
private void DrawMonsterPanel()
|
private void DrawMonsterPanel()
|
||||||
{
|
{
|
||||||
var names = _modelChara[_selection.State!.ModelData.ModelId];
|
var names = _modelChara[_selection.State!.ModelData.ModelId];
|
||||||
var turnHuman = Im.Button("Turn Human"u8);
|
|
||||||
Im.Separator();
|
|
||||||
using (Im.ListBox.Begin("##MonsterList"u8, Im.ContentRegion.Available with { Y = 10 * Im.Style.TextHeightWithSpacing }))
|
using (Im.ListBox.Begin("##MonsterList"u8, Im.ContentRegion.Available with { Y = 10 * Im.Style.TextHeightWithSpacing }))
|
||||||
{
|
{
|
||||||
if (names.Count is 0)
|
if (names.Count is 0)
|
||||||
|
|
|
||||||
|
|
@ -1,103 +1,148 @@
|
||||||
using Dalamud.Game.ClientState.Objects.Enums;
|
using Dalamud.Game.ClientState.Objects.Enums;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using Dalamud.Bindings.ImGui;
|
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
using OtterGui;
|
using Luna;
|
||||||
using OtterGui.Extensions;
|
using Penumbra.GameData.Actors;
|
||||||
using OtterGui.Log;
|
|
||||||
using OtterGui.Widgets;
|
|
||||||
using Penumbra.GameData.DataContainers;
|
using Penumbra.GameData.DataContainers;
|
||||||
using OtterGui.Custom;
|
|
||||||
using MouseWheelType = OtterGui.Widgets.MouseWheelType;
|
|
||||||
|
|
||||||
namespace Glamourer.Gui.Tabs.AutomationTab;
|
namespace Glamourer.Gui.Tabs.AutomationTab;
|
||||||
|
|
||||||
public sealed class HumanNpcCombo(
|
public sealed class HumanNpcCombo(DictBNpcNames bNpcNames, DictModelChara modelCharaDict, HumanModelList humans, DictBNpc bNpcs)
|
||||||
string label,
|
: FilterComboBase<HumanNpcCombo.NpcCacheItem>(new NpcFilter())
|
||||||
DictModelChara modelCharaDict,
|
|
||||||
DictBNpcNames bNpcNames,
|
|
||||||
DictBNpc bNpcs,
|
|
||||||
HumanModelList humans,
|
|
||||||
Logger log)
|
|
||||||
: FilterComboCache<(string Name, ObjectKind Kind, uint[] Ids)>(() => CreateList(modelCharaDict, bNpcNames, bNpcs, humans), MouseWheelType.None, log)
|
|
||||||
{
|
{
|
||||||
protected override string ToString((string Name, ObjectKind Kind, uint[] Ids) obj)
|
private NpcCacheItem _selection = new(string.Empty, ObjectKind.None, new HashSet<uint>());
|
||||||
=> obj.Name;
|
|
||||||
|
|
||||||
protected override bool DrawSelectable(int globalIdx, bool selected)
|
public NpcCacheItem Selection
|
||||||
|
=> _selection;
|
||||||
|
|
||||||
|
public readonly struct NpcCacheItem(string name, ObjectKind kind, IReadOnlySet<uint> ids) : IComparable<NpcCacheItem>
|
||||||
{
|
{
|
||||||
var (name, kind, ids) = Items[globalIdx];
|
public readonly StringPair Name = new(name);
|
||||||
if (globalIdx > 0 && Items[globalIdx - 1].Name == name || globalIdx + 1 < Items.Count && Items[globalIdx + 1].Name == name)
|
public readonly ObjectKind Kind = kind;
|
||||||
name = $"{name} ({kind.ToName()})";
|
public readonly IReadOnlySet<uint> Ids = ids;
|
||||||
var ret = ImGui.Selectable(name, selected);
|
|
||||||
if (ImGui.IsItemHovered())
|
|
||||||
ImGui.SetTooltip(string.Join('\n', ids.Select(i => i.ToString())));
|
|
||||||
|
|
||||||
return ret;
|
/// <summary> Compare strings in a way that letters and numbers are sorted before any special symbols. </summary>
|
||||||
}
|
public int CompareTo(NpcCacheItem other)
|
||||||
|
|
||||||
public bool Draw(float width)
|
|
||||||
=> Draw(label, CurrentSelection.Name.IsNullOrEmpty() ? "Human Non-Player-Characters..." : CurrentSelection.Name, string.Empty, width,
|
|
||||||
Im.Style.TextHeightWithSpacing);
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary> Compare strings in a way that letters and numbers are sorted before any special symbols. </summary>
|
|
||||||
private class NameComparer : IComparer<(string, ObjectKind)>
|
|
||||||
{
|
|
||||||
public int Compare((string, ObjectKind) x, (string, ObjectKind) y)
|
|
||||||
{
|
{
|
||||||
if (x.Item1.IsNullOrWhitespace() || y.Item1.IsNullOrWhitespace())
|
if (Name.Utf16.IsNullOrWhitespace() || other.Name.Utf16.IsNullOrWhitespace())
|
||||||
return StringComparer.OrdinalIgnoreCase.Compare(x.Item1, y.Item1);
|
return StringComparer.OrdinalIgnoreCase.Compare(Name.Utf16, other.Name.Utf16);
|
||||||
|
|
||||||
var comp = (char.IsAsciiLetterOrDigit(x.Item1[0]), char.IsAsciiLetterOrDigit(y.Item1[0])) switch
|
var comp = (char.IsAsciiLetterOrDigit(Name.Utf16[0]), char.IsAsciiLetterOrDigit(other.Name.Utf16[0])) switch
|
||||||
{
|
{
|
||||||
(true, false) => -1,
|
(true, false) => -1,
|
||||||
(false, true) => 1,
|
(false, true) => 1,
|
||||||
_ => StringComparer.OrdinalIgnoreCase.Compare(x.Item1, y.Item1),
|
_ => StringComparer.OrdinalIgnoreCase.Compare(Name.Utf16, other.Name.Utf16),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (comp != 0)
|
if (comp is not 0)
|
||||||
return comp;
|
return comp;
|
||||||
|
|
||||||
return Comparer<ObjectKind>.Default.Compare(x.Item2, y.Item2);
|
return Comparer<ObjectKind>.Default.Compare(Kind, other.Kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IReadOnlyList<(string Name, ObjectKind Kind, uint[] Ids)> CreateList(DictModelChara modelCharaDict, DictBNpcNames bNpcNames,
|
private sealed class NpcFilter : TextFilterBase<NpcCacheItem>
|
||||||
DictBNpc bNpcs, HumanModelList humans)
|
|
||||||
{
|
{
|
||||||
var ret = new List<(string Name, ObjectKind Kind, uint Id)>(1024);
|
protected override string ToFilterString(in NpcCacheItem item, int globalIndex)
|
||||||
|
=> item.Name.Utf16;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IEnumerable<NpcCacheItem> GetItems()
|
||||||
|
{
|
||||||
|
var bNpcDict = new SetDictionary<string, uint>(1024);
|
||||||
|
var eNpcDict = new SetDictionary<string, uint>(1024);
|
||||||
|
var bothSet = new HashSet<string>(1024);
|
||||||
for (var modelChara = 0u; modelChara < modelCharaDict.Count; ++modelChara)
|
for (var modelChara = 0u; modelChara < modelCharaDict.Count; ++modelChara)
|
||||||
{
|
{
|
||||||
if (!humans.IsHuman(modelChara))
|
if (!humans.IsHuman(modelChara))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var list = modelCharaDict[modelChara];
|
var list = modelCharaDict[modelChara];
|
||||||
if (list.Count == 0)
|
if (list.Count is 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
foreach (var (name, kind, id) in list.Where(t => !t.Name.IsNullOrWhitespace()))
|
foreach (var (name, kind, id) in list.Where(t => !t.Name.IsNullOrWhitespace()))
|
||||||
{
|
{
|
||||||
|
string actualName;
|
||||||
switch (kind)
|
switch (kind)
|
||||||
{
|
{
|
||||||
case ObjectKind.BattleNpc:
|
case ObjectKind.BattleNpc:
|
||||||
if (!bNpcNames.TryGetValue(id, out var nameIds))
|
if (!bNpcNames.TryGetValue(id, out var nameIds))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret.AddRange(nameIds.SelectWhere(nameId => (bNpcs.TryGetValue(nameId, out var s), (s!, kind, nameId.Id))));
|
foreach (var nameId in nameIds)
|
||||||
|
{
|
||||||
|
if (!bNpcs.TryGetValue(nameId, out var s))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (bothSet.Contains(s))
|
||||||
|
{
|
||||||
|
actualName = $"{s} ({ObjectKind.BattleNpc.ToName()})";
|
||||||
|
}
|
||||||
|
else if (eNpcDict.Remove(s, out var values))
|
||||||
|
{
|
||||||
|
actualName = $"{s} ({ObjectKind.BattleNpc.ToName()})";
|
||||||
|
eNpcDict.TryAdd(actualName, values);
|
||||||
|
bothSet.Add(s);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
actualName = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
bNpcDict.TryAdd(actualName, nameId.Id);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ObjectKind.EventNpc:
|
case ObjectKind.EventNpc:
|
||||||
ret.Add((name, kind, id));
|
if (bothSet.Contains(name))
|
||||||
|
{
|
||||||
|
actualName = $"{name} ({ObjectKind.EventNpc.ToName()})";
|
||||||
|
}
|
||||||
|
else if (bNpcDict.Remove(name, out var values))
|
||||||
|
{
|
||||||
|
actualName = $"{name} ({ObjectKind.EventNpc.ToName()})";
|
||||||
|
bNpcDict.TryAdd(actualName, values);
|
||||||
|
bothSet.Add(name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
actualName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
eNpcDict.TryAdd(actualName, id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret.GroupBy(t => (t.Name, t.Kind))
|
return bNpcDict.Grouped.Select(p => new NpcCacheItem(p.Key, ObjectKind.BattleNpc, p.Value))
|
||||||
.OrderBy(g => g.Key, Comparer)
|
.Concat(eNpcDict.Grouped.Select(p => new NpcCacheItem(p.Key, ObjectKind.EventNpc, p.Value)))
|
||||||
.Select(g => (g.Key.Name, g.Key.Kind, g.Select(g => g.Id).Distinct().ToArray()))
|
.OrderBy(p => p);
|
||||||
.ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly NameComparer Comparer = new();
|
|
||||||
|
protected override float ItemHeight
|
||||||
|
=> Im.Style.TextHeightWithSpacing;
|
||||||
|
|
||||||
|
protected override bool DrawItem(in NpcCacheItem item, int globalIndex, bool selected)
|
||||||
|
{
|
||||||
|
var ret = Im.Selectable(item.Name.Utf8, selected);
|
||||||
|
if (Im.Item.Hovered())
|
||||||
|
{
|
||||||
|
using var style = Im.Style.PushDefault();
|
||||||
|
using var tt = Im.Tooltip.Begin();
|
||||||
|
foreach (var id in item.Ids)
|
||||||
|
Im.Text($"{id}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Draw(Utf8StringHandler<LabelStringHandlerBuffer> label, float width)
|
||||||
|
=> base.Draw(label, _selection.Kind is ObjectKind.None ? "Human Non-Player-Characters..."u8 : _selection.Name.Utf8, StringU8.Empty,
|
||||||
|
width, out _selection);
|
||||||
|
|
||||||
|
protected override bool IsSelected(NpcCacheItem item, int globalIndex)
|
||||||
|
=> item.Kind == _selection.Kind && item.Name.Utf16 == _selection.Name.Utf16;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ public class IdentifierDrawer(
|
||||||
HumanModelList humans)
|
HumanModelList humans)
|
||||||
{
|
{
|
||||||
private readonly WorldCombo _worldCombo = new(dictWorld);
|
private readonly WorldCombo _worldCombo = new(dictWorld);
|
||||||
private readonly HumanNpcCombo _humanNpcCombo = new("##npcs", dictModelChara, bNpcNames, bNpc, humans, Glamourer.Log);
|
private readonly HumanNpcCombo _humanNpcCombo = new(bNpcNames, dictModelChara, humans, bNpc);
|
||||||
|
|
||||||
private string _characterName = string.Empty;
|
private string _characterName = string.Empty;
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ public class IdentifierDrawer(
|
||||||
|
|
||||||
public void DrawNpcs(float width)
|
public void DrawNpcs(float width)
|
||||||
{
|
{
|
||||||
if (_humanNpcCombo.Draw(width))
|
if (_humanNpcCombo.Draw("##npcs"u8, width))
|
||||||
UpdateIdentifiers();
|
UpdateIdentifiers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,15 +68,15 @@ public class IdentifierDrawer(
|
||||||
RetainerIdentifier = actors.CreateRetainer(byteName, ActorIdentifier.RetainerType.Bell);
|
RetainerIdentifier = actors.CreateRetainer(byteName, ActorIdentifier.RetainerType.Bell);
|
||||||
MannequinIdentifier = actors.CreateRetainer(byteName, ActorIdentifier.RetainerType.Mannequin);
|
MannequinIdentifier = actors.CreateRetainer(byteName, ActorIdentifier.RetainerType.Mannequin);
|
||||||
|
|
||||||
if (_humanNpcCombo.CurrentSelection.Kind is ObjectKind.EventNpc or ObjectKind.BattleNpc)
|
if (_humanNpcCombo.Selection.Kind is ObjectKind.EventNpc or ObjectKind.BattleNpc)
|
||||||
OwnedIdentifier = actors.CreateOwned(byteName, _worldCombo.Selected.Key, _humanNpcCombo.CurrentSelection.Kind,
|
OwnedIdentifier = actors.CreateOwned(byteName, _worldCombo.Selected.Key, _humanNpcCombo.Selection.Kind,
|
||||||
_humanNpcCombo.CurrentSelection.Ids[0]);
|
_humanNpcCombo.Selection.Ids.First());
|
||||||
else
|
else
|
||||||
OwnedIdentifier = ActorIdentifier.Invalid;
|
OwnedIdentifier = ActorIdentifier.Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
NpcIdentifier = _humanNpcCombo.CurrentSelection.Kind is ObjectKind.EventNpc or ObjectKind.BattleNpc
|
NpcIdentifier = _humanNpcCombo.Selection.Kind is ObjectKind.EventNpc or ObjectKind.BattleNpc
|
||||||
? actors.CreateNpc(_humanNpcCombo.CurrentSelection.Kind, _humanNpcCombo.CurrentSelection.Ids[0])
|
? actors.CreateNpc(_humanNpcCombo.Selection.Kind, _humanNpcCombo.Selection.Ids.First())
|
||||||
: ActorIdentifier.Invalid;
|
: ActorIdentifier.Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue