mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 10:17:23 +01:00
Add overrides to associated collections.
This commit is contained in:
parent
02dff90dd0
commit
a194f88903
10 changed files with 322 additions and 30 deletions
|
|
@ -9,6 +9,7 @@ using Glamourer.Gui.Tabs.AutomationTab;
|
|||
using Glamourer.Gui.Tabs.DebugTab;
|
||||
using Glamourer.Gui.Tabs.DesignTab;
|
||||
using Glamourer.Gui.Tabs.NpcTab;
|
||||
using Glamourer.Gui.Tabs.SettingsTab;
|
||||
using Glamourer.Gui.Tabs.UnlocksTab;
|
||||
using ImGuiNET;
|
||||
using OtterGui.Custom;
|
||||
|
|
|
|||
122
Glamourer/Gui/Tabs/SettingsTab/CollectionOverrideDrawer.cs
Normal file
122
Glamourer/Gui/Tabs/SettingsTab/CollectionOverrideDrawer.cs
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Components;
|
||||
using Dalamud.Interface.Style;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.Services;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.GameData.Actors;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.SettingsTab;
|
||||
|
||||
public class CollectionOverrideDrawer(
|
||||
CollectionOverrideService collectionOverrides,
|
||||
Configuration config,
|
||||
ObjectManager objects,
|
||||
ActorManager actors) : IService
|
||||
{
|
||||
private string _newIdentifier = string.Empty;
|
||||
private ActorIdentifier[] _identifiers = [];
|
||||
private int _dragDropIndex = -1;
|
||||
private Exception? _exception;
|
||||
private string _collection = string.Empty;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
using var header = ImRaii.CollapsingHeader("Collection Overrides");
|
||||
ImGuiUtil.HoverTooltip(
|
||||
"Here you can set up overrides for Penumbra collections that should have their settings changed when automatically applying mod settings from a design.\n"
|
||||
+ "Instead of the collection associated with the overridden character, the overridden collection will be manipulated.");
|
||||
if (!header)
|
||||
return;
|
||||
|
||||
using var table = ImRaii.Table("table", 3, ImGuiTableFlags.RowBg);
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
var buttonSize = new Vector2(ImGui.GetFrameHeight());
|
||||
ImGui.TableSetupColumn("buttons", ImGuiTableColumnFlags.WidthFixed, buttonSize.X);
|
||||
ImGui.TableSetupColumn("identifiers", ImGuiTableColumnFlags.WidthStretch, 0.6f);
|
||||
ImGui.TableSetupColumn("collections", ImGuiTableColumnFlags.WidthStretch, 0.4f);
|
||||
|
||||
for (var i = 0; i < collectionOverrides.Overrides.Count; ++i)
|
||||
{
|
||||
var (identifier, collection) = collectionOverrides.Overrides[i];
|
||||
using var id = ImRaii.PushId(i);
|
||||
ImGui.TableNextColumn();
|
||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), buttonSize, "Delete this override.", false, true))
|
||||
collectionOverrides.DeleteOverride(i--);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.Selectable(config.Ephemeral.IncognitoMode ? identifier.Incognito(null) : identifier.ToString());
|
||||
|
||||
using (var target = ImRaii.DragDropTarget())
|
||||
{
|
||||
if (target.Success && ImGuiUtil.IsDropping("DraggingOverride"))
|
||||
{
|
||||
collectionOverrides.MoveOverride(_dragDropIndex, i);
|
||||
_dragDropIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
using (var source = ImRaii.DragDropSource())
|
||||
{
|
||||
if (source)
|
||||
{
|
||||
ImGui.SetDragDropPayload("DraggingOverride", nint.Zero, 0);
|
||||
ImGui.TextUnformatted($"Reordering Override #{i + 1}...");
|
||||
_dragDropIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
|
||||
if (ImGui.InputText("##input", ref collection, 64) && collection.Length > 0)
|
||||
collectionOverrides.ChangeOverride(i, collection);
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.PersonCirclePlus.ToIconString(), buttonSize, "Add override for current player.",
|
||||
!objects.Player.Valid, true))
|
||||
collectionOverrides.AddOverride([objects.PlayerData.Identifier], _collection.Length > 0 ? _collection : "TempCollection");
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemInnerSpacing.X - buttonSize.X * 2);
|
||||
if (ImGui.InputTextWithHint("##newActor", "New Identifier...", ref _newIdentifier, 80))
|
||||
try
|
||||
{
|
||||
_identifiers = actors.FromUserString(_newIdentifier, false);
|
||||
}
|
||||
catch (ActorIdentifierFactory.IdentifierParseError e)
|
||||
{
|
||||
_exception = e;
|
||||
_identifiers = [];
|
||||
}
|
||||
|
||||
var tt = _identifiers.Any(i => i.IsValid)
|
||||
? $"Add a new override for {_identifiers.First(i => i.IsValid)}."
|
||||
: _newIdentifier.Length == 0
|
||||
? "Please enter an identifier string first."
|
||||
: $"The identifier string {_newIdentifier} does not result in a valid identifier{(_exception == null ? "." : $":\n\n{_exception?.Message}")}";
|
||||
|
||||
ImGui.SameLine(0, ImGui.GetStyle().ItemInnerSpacing.X);
|
||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), buttonSize, tt, tt[0] is 'T', true))
|
||||
collectionOverrides.AddOverride(_identifiers, _collection.Length > 0 ? _collection : "TempCollection");
|
||||
|
||||
ImGui.SameLine(0, ImGui.GetStyle().ItemInnerSpacing.X);
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
using var color = ImRaii.PushColor(ImGuiCol.Text, ImGui.GetColorU32(ImGuiCol.TextDisabled));
|
||||
ImGui.TextUnformatted(FontAwesomeIcon.InfoCircle.ToIconString());
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
ActorIdentifierFactory.WriteUserStringTooltip(false);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
|
||||
ImGui.InputTextWithHint("##collection", "Enter Collection...", ref _collection, 80);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ using OtterGui;
|
|||
using OtterGui.Raii;
|
||||
using OtterGui.Widgets;
|
||||
|
||||
namespace Glamourer.Gui.Tabs;
|
||||
namespace Glamourer.Gui.Tabs.SettingsTab;
|
||||
|
||||
public class SettingsTab(
|
||||
Configuration config,
|
||||
|
|
@ -29,7 +29,8 @@ public class SettingsTab(
|
|||
IKeyState keys,
|
||||
DesignColorUi designColorUi,
|
||||
PaletteImport paletteImport,
|
||||
PalettePlusChecker paletteChecker)
|
||||
PalettePlusChecker paletteChecker,
|
||||
CollectionOverrideDrawer overrides)
|
||||
: ITab
|
||||
{
|
||||
private readonly VirtualKey[] _validKeys = keys.GetValidVirtualKeys().Prepend(VirtualKey.NO_KEY).ToArray();
|
||||
|
|
@ -57,6 +58,7 @@ public class SettingsTab(
|
|||
DrawBehaviorSettings();
|
||||
DrawInterfaceSettings();
|
||||
DrawColorSettings();
|
||||
overrides.Draw();
|
||||
DrawCodes();
|
||||
}
|
||||
|
||||
|
|
@ -90,6 +92,9 @@ public class SettingsTab(
|
|||
"Enable the display and editing of advanced customization options like arbitrary colors.",
|
||||
config.UseAdvancedParameters, paletteChecker.SetAdvancedParameters);
|
||||
PaletteImportButton();
|
||||
Checkbox("Enable Advanced Dye Options",
|
||||
"Enable the display and editing of advanced dyes (color sets) for all equipment",
|
||||
config.UseAdvancedDyes, v => config.UseAdvancedDyes = v);
|
||||
Checkbox("Always Apply Associated Mods",
|
||||
"Whenever a design is applied to a character (including via automation), Glamourer will try to apply its associated mod settings to the collection currently associated with that character, if it is available.\n\n"
|
||||
+ "Glamourer will NOT revert these applied settings automatically. This may mess up your collection and configuration.\n\n"
|
||||
|
|
@ -189,6 +194,7 @@ public class SettingsTab(
|
|||
ImGui.NewLine();
|
||||
}
|
||||
|
||||
|
||||
private void PaletteImportButton()
|
||||
{
|
||||
if (!config.UseAdvancedParameters || !config.ShowPalettePlusImport)
|
||||
|
|
@ -1,11 +1,13 @@
|
|||
using Glamourer.Designs.Links;
|
||||
using Glamourer.Interop.Structs;
|
||||
using Glamourer.Services;
|
||||
using Glamourer.State;
|
||||
using OtterGui.Services;
|
||||
|
||||
namespace Glamourer.Interop.Penumbra;
|
||||
|
||||
public class ModSettingApplier(PenumbraService penumbra, Configuration config, ObjectManager objects) : IService
|
||||
public class ModSettingApplier(PenumbraService penumbra, Configuration config, ObjectManager objects, CollectionOverrideService overrides)
|
||||
: IService
|
||||
{
|
||||
public void HandleStateApplication(ActorState state, MergedDesign design)
|
||||
{
|
||||
|
|
@ -24,7 +26,7 @@ public class ModSettingApplier(PenumbraService penumbra, Configuration config, O
|
|||
|
||||
foreach (var actor in data.Objects)
|
||||
{
|
||||
var collection = penumbra.GetActorCollection(actor);
|
||||
var (collection, overridden) = overrides.GetCollection(actor, state.Identifier);
|
||||
if (collection.Length == 0)
|
||||
{
|
||||
Glamourer.Log.Verbose($"[Mod Applier] Could not obtain associated collection for {actor.Utf8Name}.");
|
||||
|
|
@ -40,16 +42,17 @@ public class ModSettingApplier(PenumbraService penumbra, Configuration config, O
|
|||
if (message.Length > 0)
|
||||
Glamourer.Log.Verbose($"[Mod Applier] Error applying mod settings: {message}");
|
||||
else
|
||||
Glamourer.Log.Verbose($"[Mod Applier] Set mod settings for {mod.DirectoryName} in {collection}.");
|
||||
Glamourer.Log.Verbose(
|
||||
$"[Mod Applier] Set mod settings for {mod.DirectoryName} in {collection}{(overridden ? " (overridden by settings)" : string.Empty)}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public (List<string> Messages, int Applied, string Collection) ApplyModSettings(IReadOnlyDictionary<Mod, ModSettings> settings, Actor actor)
|
||||
public (List<string> Messages, int Applied, string Collection, bool Overridden) ApplyModSettings(IReadOnlyDictionary<Mod, ModSettings> settings, Actor actor)
|
||||
{
|
||||
var collection = penumbra.GetActorCollection(actor);
|
||||
var (collection, overridden) = overrides.GetCollection(actor);
|
||||
if (collection.Length <= 0)
|
||||
return ([$"Could not obtain associated collection for {actor.Utf8Name}."], 0, string.Empty);
|
||||
return ([$"Could not obtain associated collection for {actor.Utf8Name}."], 0, string.Empty, false);
|
||||
|
||||
var messages = new List<string>();
|
||||
var appliedMods = 0;
|
||||
|
|
@ -62,6 +65,6 @@ public class ModSettingApplier(PenumbraService penumbra, Configuration config, O
|
|||
++appliedMods;
|
||||
}
|
||||
|
||||
return (messages, appliedMods, collection);
|
||||
return (messages, appliedMods, collection, overridden);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
160
Glamourer/Services/CollectionOverrideService.cs
Normal file
160
Glamourer/Services/CollectionOverrideService.cs
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
using Glamourer.Interop.Penumbra;
|
||||
using Glamourer.Interop.Structs;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OtterGui;
|
||||
using OtterGui.Filesystem;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.GameData.Actors;
|
||||
|
||||
namespace Glamourer.Services;
|
||||
|
||||
public sealed class CollectionOverrideService : IService, ISavable
|
||||
{
|
||||
public const int Version = 1;
|
||||
private readonly SaveService _saveService;
|
||||
private readonly ActorManager _actors;
|
||||
private readonly PenumbraService _penumbra;
|
||||
|
||||
public CollectionOverrideService(SaveService saveService, ActorManager actors, PenumbraService penumbra)
|
||||
{
|
||||
_saveService = saveService;
|
||||
_actors = actors;
|
||||
_penumbra = penumbra;
|
||||
Load();
|
||||
}
|
||||
|
||||
public unsafe (string Collection, bool Overriden) GetCollection(Actor actor, ActorIdentifier identifier = default)
|
||||
{
|
||||
if (!identifier.IsValid)
|
||||
identifier = _actors.FromObject(actor.AsObject, out _, true, true, true);
|
||||
|
||||
return _overrides.FindFirst(p => p.Actor.Matches(identifier), out var ret)
|
||||
? (ret.Collection, true)
|
||||
: (_penumbra.GetActorCollection(actor), false);
|
||||
}
|
||||
|
||||
private readonly List<(ActorIdentifier Actor, string Collection)> _overrides = [];
|
||||
|
||||
public IReadOnlyList<(ActorIdentifier Actor, string Collection)> Overrides
|
||||
=> _overrides;
|
||||
|
||||
public string ToFilename(FilenameService fileNames)
|
||||
=> fileNames.CollectionOverrideFile;
|
||||
|
||||
public void AddOverride(IEnumerable<ActorIdentifier> identifiers, string collection)
|
||||
{
|
||||
if (collection.Length == 0)
|
||||
return;
|
||||
|
||||
foreach (var id in identifiers.Where(i => i.IsValid))
|
||||
{
|
||||
_overrides.Add((id, collection));
|
||||
Glamourer.Log.Debug($"Added collection override {id.Incognito(null)} -> {collection}.");
|
||||
_saveService.QueueSave(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeOverride(int idx, string newCollection)
|
||||
{
|
||||
if (idx < 0 || idx >= _overrides.Count || newCollection.Length == 0)
|
||||
return;
|
||||
|
||||
var current = _overrides[idx];
|
||||
if (current.Collection == newCollection)
|
||||
return;
|
||||
|
||||
_overrides[idx] = current with { Collection = newCollection };
|
||||
Glamourer.Log.Debug($"Changed collection override {idx + 1} from {current.Collection} to {newCollection}.");
|
||||
_saveService.QueueSave(this);
|
||||
}
|
||||
|
||||
public void DeleteOverride(int idx)
|
||||
{
|
||||
if (idx < 0 || idx >= _overrides.Count)
|
||||
return;
|
||||
|
||||
_overrides.RemoveAt(idx);
|
||||
Glamourer.Log.Debug($"Removed collection override {idx + 1}.");
|
||||
_saveService.QueueSave(this);
|
||||
}
|
||||
|
||||
public void MoveOverride(int idxFrom, int idxTo)
|
||||
{
|
||||
if (!_overrides.Move(idxFrom, idxTo))
|
||||
return;
|
||||
|
||||
Glamourer.Log.Debug($"Moved collection override {idxFrom + 1} to {idxTo + 1}.");
|
||||
_saveService.QueueSave(this);
|
||||
}
|
||||
|
||||
private void Load()
|
||||
{
|
||||
var file = _saveService.FileNames.CollectionOverrideFile;
|
||||
if (!File.Exists(file))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var text = File.ReadAllText(file);
|
||||
var jObj = JObject.Parse(text);
|
||||
var version = jObj["Version"]?.ToObject<int>() ?? 0;
|
||||
switch (version)
|
||||
{
|
||||
case 1:
|
||||
if (jObj["Overrides"] is not JArray array)
|
||||
{
|
||||
Glamourer.Log.Error($"Invalid format of collection override file, ignored.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var token in array.OfType<JObject>())
|
||||
{
|
||||
var collection = token["Collection"]?.ToObject<string>() ?? string.Empty;
|
||||
var identifier = _actors.FromJson(token);
|
||||
if (!identifier.IsValid)
|
||||
Glamourer.Log.Warning($"Invalid identifier for collection override with collection [{collection}], skipped.");
|
||||
else if (collection.Length == 0)
|
||||
Glamourer.Log.Warning($"Empty collection override for identifier {identifier.Incognito(null)}, skipped.");
|
||||
else
|
||||
_overrides.Add((identifier, collection));
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
Glamourer.Log.Error($"Invalid version {version} of collection override file, ignored.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Glamourer.Log.Error($"Error loading collection override file:\n{ex}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Save(StreamWriter writer)
|
||||
{
|
||||
var jObj = new JObject()
|
||||
{
|
||||
["Version"] = Version,
|
||||
["Overrides"] = SerializeOverrides(),
|
||||
};
|
||||
using var j = new JsonTextWriter(writer);
|
||||
j.Formatting = Formatting.Indented;
|
||||
jObj.WriteTo(j);
|
||||
return;
|
||||
|
||||
JArray SerializeOverrides()
|
||||
{
|
||||
var jArray = new JArray();
|
||||
foreach (var (actor, collection) in _overrides)
|
||||
{
|
||||
var obj = actor.ToJson();
|
||||
obj["Collection"] = collection;
|
||||
jArray.Add(obj);
|
||||
}
|
||||
|
||||
return jArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -440,13 +440,13 @@ public class CommandService : IDisposable
|
|||
if (!applyMods || design is not Design d)
|
||||
return;
|
||||
|
||||
var (messages, appliedMods, collection) = _modApplier.ApplyModSettings(d.AssociatedMods, actor);
|
||||
var (messages, appliedMods, collection, overridden) = _modApplier.ApplyModSettings(d.AssociatedMods, actor);
|
||||
|
||||
foreach (var message in messages)
|
||||
Glamourer.Messager.Chat.Print($"Error applying mod settings: {message}");
|
||||
|
||||
if (appliedMods > 0)
|
||||
Glamourer.Messager.Chat.Print($"Applied {appliedMods} mod settings to {collection}.");
|
||||
Glamourer.Messager.Chat.Print($"Applied {appliedMods} mod settings to {collection}{(overridden ? " (overridden by settings)" : string.Empty)}.");
|
||||
}
|
||||
|
||||
private bool Delete(string argument)
|
||||
|
|
|
|||
|
|
@ -17,21 +17,23 @@ public class FilenameService
|
|||
public readonly string DesignColorFile;
|
||||
public readonly string EphemeralConfigFile;
|
||||
public readonly string NpcAppearanceFile;
|
||||
public readonly string CollectionOverrideFile;
|
||||
|
||||
public FilenameService(DalamudPluginInterface pi)
|
||||
{
|
||||
ConfigDirectory = pi.ConfigDirectory.FullName;
|
||||
ConfigFile = pi.ConfigFile.FullName;
|
||||
AutomationFile = Path.Combine(ConfigDirectory, "automation.json");
|
||||
DesignFileSystem = Path.Combine(ConfigDirectory, "sort_order.json");
|
||||
MigrationDesignFile = Path.Combine(ConfigDirectory, "Designs.json");
|
||||
UnlockFileCustomize = Path.Combine(ConfigDirectory, "unlocks_customize.json");
|
||||
UnlockFileItems = Path.Combine(ConfigDirectory, "unlocks_items.json");
|
||||
DesignDirectory = Path.Combine(ConfigDirectory, "designs");
|
||||
FavoriteFile = Path.Combine(ConfigDirectory, "favorites.json");
|
||||
DesignColorFile = Path.Combine(ConfigDirectory, "design_colors.json");
|
||||
EphemeralConfigFile = Path.Combine(ConfigDirectory, "ephemeral_config.json");
|
||||
NpcAppearanceFile = Path.Combine(ConfigDirectory, "npc_appearance_data.json");
|
||||
ConfigDirectory = pi.ConfigDirectory.FullName;
|
||||
ConfigFile = pi.ConfigFile.FullName;
|
||||
AutomationFile = Path.Combine(ConfigDirectory, "automation.json");
|
||||
DesignFileSystem = Path.Combine(ConfigDirectory, "sort_order.json");
|
||||
MigrationDesignFile = Path.Combine(ConfigDirectory, "Designs.json");
|
||||
UnlockFileCustomize = Path.Combine(ConfigDirectory, "unlocks_customize.json");
|
||||
UnlockFileItems = Path.Combine(ConfigDirectory, "unlocks_items.json");
|
||||
DesignDirectory = Path.Combine(ConfigDirectory, "designs");
|
||||
FavoriteFile = Path.Combine(ConfigDirectory, "favorites.json");
|
||||
DesignColorFile = Path.Combine(ConfigDirectory, "design_colors.json");
|
||||
EphemeralConfigFile = Path.Combine(ConfigDirectory, "ephemeral_config.json");
|
||||
NpcAppearanceFile = Path.Combine(ConfigDirectory, "npc_appearance_data.json");
|
||||
CollectionOverrideFile = Path.Combine(ConfigDirectory, "collection_overrides.json");
|
||||
}
|
||||
|
||||
public IEnumerable<FileInfo> Designs()
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ using Glamourer.Gui.Tabs.AutomationTab;
|
|||
using Glamourer.Gui.Tabs.DebugTab;
|
||||
using Glamourer.Gui.Tabs.DesignTab;
|
||||
using Glamourer.Gui.Tabs.NpcTab;
|
||||
using Glamourer.Gui.Tabs.SettingsTab;
|
||||
using Glamourer.Gui.Tabs.UnlocksTab;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.Interop.Penumbra;
|
||||
|
|
|
|||
|
|
@ -7,13 +7,10 @@ using Penumbra.GameData.Structs;
|
|||
|
||||
namespace Glamourer.Services;
|
||||
|
||||
public sealed class TextureService : TextureCache, IDisposable
|
||||
public sealed class TextureService(UiBuilder uiBuilder, IDataManager dataManager, ITextureProvider textureProvider)
|
||||
: TextureCache(dataManager, textureProvider), IDisposable
|
||||
{
|
||||
public TextureService(UiBuilder uiBuilder, IDataManager dataManager, ITextureProvider textureProvider)
|
||||
: base(dataManager, textureProvider)
|
||||
=> _slotIcons = CreateSlotIcons(uiBuilder);
|
||||
|
||||
private readonly IDalamudTextureWrap?[] _slotIcons;
|
||||
private readonly IDalamudTextureWrap?[] _slotIcons = CreateSlotIcons(uiBuilder);
|
||||
|
||||
public (nint, Vector2, bool) GetIcon(EquipItem item, EquipSlot slot)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 3a7f6d86c9975a4892f58be3c629b7664e6c3733
|
||||
Subproject commit 5825bafb0602cf8a252581f21291c0d27e5561f0
|
||||
Loading…
Add table
Add a link
Reference in a new issue