mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 10:17:23 +01:00
Add favorite option to items.
This commit is contained in:
parent
00883943cd
commit
ea4fb49c0f
11 changed files with 211 additions and 31 deletions
|
|
@ -22,6 +22,7 @@ public sealed class ObjectUnlocked : EventWrapper<Action<ObjectUnlocked.Type, ui
|
|||
public enum Priority
|
||||
{
|
||||
/// <seealso cref="Gui.Tabs.UnlocksTab.UnlockTable.OnObjectUnlock"/>
|
||||
/// <remarks> Currently used as a hack to make the unlock table dirty in it. If anything else starts using this, rework. </remarks>
|
||||
UnlockTable = 0,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ public enum ColorId
|
|||
AutomationActorAvailable,
|
||||
AutomationActorUnavailable,
|
||||
HeaderButtons,
|
||||
FavoriteStarOn,
|
||||
FavoriteStarHovered,
|
||||
FavoriteStarOff,
|
||||
}
|
||||
|
||||
public static class Colors
|
||||
|
|
@ -40,6 +43,9 @@ public static class Colors
|
|||
ColorId.AutomationActorAvailable => (0xFFFFFFFF, "Automation Actor Available", "A character associated with the given automated design set is currently visible." ),
|
||||
ColorId.AutomationActorUnavailable => (0xFF808080, "Automation Actor Unavailable", "No character associated with the given automated design set is currently visible." ),
|
||||
ColorId.HeaderButtons => (0xFFFFF0C0, "Header Buttons", "The text and border color of buttons in the header, like the Incognito toggle." ),
|
||||
ColorId.FavoriteStarOn => (0xFF40D0D0, "Favored Item", "The color of the star for favored items and of the border in the unlock overview tab." ),
|
||||
ColorId.FavoriteStarHovered => (0xFFD040D0, "Favorite Star Hovered", "The color of the star for favored items when it is hovered." ),
|
||||
ColorId.FavoriteStarOff => (0x20808080, "Favorite Star Outline", "The color of the star for items that are not favored when it is not hovered." ),
|
||||
_ => (0x00000000, string.Empty, string.Empty ),
|
||||
// @formatter:on
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using Glamourer.Designs;
|
|||
using Glamourer.Events;
|
||||
using Glamourer.Services;
|
||||
using Glamourer.Structs;
|
||||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
|
|
@ -37,7 +38,8 @@ public class EquipmentDrawer
|
|||
private float _requiredComboWidthUnscaled;
|
||||
private float _requiredComboWidth;
|
||||
|
||||
public EquipmentDrawer(IDataManager gameData, ItemManager items, CodeService codes, TextureService textures, Configuration config,
|
||||
public EquipmentDrawer(FavoriteManager favorites, IDataManager gameData, ItemManager items, CodeService codes, TextureService textures,
|
||||
Configuration config,
|
||||
GPoseService gPose)
|
||||
{
|
||||
_items = items;
|
||||
|
|
@ -48,7 +50,7 @@ public class EquipmentDrawer
|
|||
_stainData = items.Stains;
|
||||
_stainCombo = new FilterComboColors(DefaultWidth - 20,
|
||||
_stainData.Data.Prepend(new KeyValuePair<byte, (string Name, uint Dye, bool Gloss)>(0, ("None", 0, false))), Glamourer.Log);
|
||||
_itemCombo = EquipSlotExtensions.EqdpSlots.Select(e => new ItemCombo(gameData, items, e, Glamourer.Log)).ToArray();
|
||||
_itemCombo = EquipSlotExtensions.EqdpSlots.Select(e => new ItemCombo(gameData, items, e, Glamourer.Log, favorites)).ToArray();
|
||||
_weaponCombo = new Dictionary<FullEquipType, WeaponCombo>(FullEquipTypeExtensions.WeaponTypes.Count * 2);
|
||||
foreach (var type in Enum.GetValues<FullEquipType>())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
using System.Linq;
|
||||
using Dalamud.Plugin.Services;
|
||||
using Glamourer.Services;
|
||||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using OtterGui;
|
||||
|
|
@ -16,13 +17,15 @@ namespace Glamourer.Gui.Equipment;
|
|||
|
||||
public sealed class ItemCombo : FilterComboCache<EquipItem>
|
||||
{
|
||||
public readonly string Label;
|
||||
private ItemId _currentItem;
|
||||
private float _innerWidth;
|
||||
private readonly FavoriteManager _favorites;
|
||||
public readonly string Label;
|
||||
private ItemId _currentItem;
|
||||
private float _innerWidth;
|
||||
|
||||
public ItemCombo(IDataManager gameData, ItemManager items, EquipSlot slot, Logger log)
|
||||
: base(() => GetItems(items, slot), log)
|
||||
public ItemCombo(IDataManager gameData, ItemManager items, EquipSlot slot, Logger log, FavoriteManager favorites)
|
||||
: base(() => GetItems(favorites, items, slot), log)
|
||||
{
|
||||
_favorites = favorites;
|
||||
Label = GetLabel(gameData, slot);
|
||||
_currentItem = ItemManager.NothingId(slot);
|
||||
SearchByParts = true;
|
||||
|
|
@ -59,7 +62,15 @@ public sealed class ItemCombo : FilterComboCache<EquipItem>
|
|||
{
|
||||
var obj = Items[globalIdx];
|
||||
var name = ToString(obj);
|
||||
var ret = ImGui.Selectable(name, selected);
|
||||
if (UiHelpers.DrawFavoriteStar(_favorites, obj) && CurrentSelectionIdx == globalIdx)
|
||||
{
|
||||
CurrentSelectionIdx = -1;
|
||||
_currentItem = obj.ItemId;
|
||||
CurrentSelection = default;
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
var ret = ImGui.Selectable(name, selected);
|
||||
ImGui.SameLine();
|
||||
using var color = ImRaii.PushColor(ImGuiCol.Text, 0xFF808080);
|
||||
ImGuiUtil.RightAlign($"({obj.ModelString})");
|
||||
|
|
@ -92,7 +103,7 @@ public sealed class ItemCombo : FilterComboCache<EquipItem>
|
|||
};
|
||||
}
|
||||
|
||||
private static IReadOnlyList<EquipItem> GetItems(ItemManager items, EquipSlot slot)
|
||||
private static IReadOnlyList<EquipItem> GetItems(FavoriteManager favorites, ItemManager items, EquipSlot slot)
|
||||
{
|
||||
var nothing = ItemManager.NothingItem(slot);
|
||||
if (!items.ItemService.AwaitedService.TryGetValue(slot.ToEquipType(), out var list))
|
||||
|
|
@ -104,6 +115,6 @@ public sealed class ItemCombo : FilterComboCache<EquipItem>
|
|||
var enumerable = list.AsEnumerable();
|
||||
if (slot.IsEquipment())
|
||||
enumerable = enumerable.Append(ItemManager.SmallClothesItem(slot));
|
||||
return enumerable.OrderBy(i => i.Name).Prepend(nothing).ToList();
|
||||
return enumerable.OrderByDescending(favorites.Contains).ThenBy(i => i.Name).Prepend(nothing).ToList();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Interop;
|
||||
|
|
@ -24,6 +25,7 @@ public class UnlockOverview
|
|||
private readonly TextureService _textures;
|
||||
private readonly CodeService _codes;
|
||||
private readonly JobService _jobs;
|
||||
private readonly FavoriteManager _favorites;
|
||||
|
||||
private static readonly Vector4 UnavailableTint = new(0.3f, 0.3f, 0.3f, 1.0f);
|
||||
|
||||
|
|
@ -70,7 +72,7 @@ public class UnlockOverview
|
|||
|
||||
public UnlockOverview(ItemManager items, CustomizationService customizations, ItemUnlockManager itemUnlocks,
|
||||
CustomizeUnlockManager customizeUnlocks, PenumbraChangedItemTooltip tooltip, TextureService textures, CodeService codes,
|
||||
JobService jobs)
|
||||
JobService jobs, FavoriteManager favorites)
|
||||
{
|
||||
_items = items;
|
||||
_customizations = customizations;
|
||||
|
|
@ -80,6 +82,7 @@ public class UnlockOverview
|
|||
_textures = textures;
|
||||
_codes = codes;
|
||||
_jobs = jobs;
|
||||
_favorites = favorites;
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
|
|
@ -166,10 +169,12 @@ public class UnlockOverview
|
|||
var (icon, size) = (iconHandle.ImGuiHandle, new Vector2(iconHandle.Width, iconHandle.Height));
|
||||
|
||||
ImGui.Image(icon, iconSize, Vector2.Zero, Vector2.One, unlocked || _codes.EnabledShirts ? Vector4.One : UnavailableTint);
|
||||
if (_favorites.Contains(item))
|
||||
ImGui.GetWindowDrawList().AddRect(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), ColorId.FavoriteStarOn.Value(),
|
||||
2 * ImGuiHelpers.GlobalScale, ImDrawFlags.RoundCornersAll, 4 * ImGuiHelpers.GlobalScale);
|
||||
|
||||
if (ImGui.IsItemClicked())
|
||||
{
|
||||
// TODO link
|
||||
}
|
||||
Glamourer.Messager.Chat.Print(new SeStringBuilder().AddItemLink(item.ItemId.Id, false).BuiltString);
|
||||
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right) && _tooltip.Player(out var state))
|
||||
_tooltip.ApplyItem(state, item);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using System.Collections;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Glamourer.Events;
|
||||
|
|
@ -24,19 +25,20 @@ public class UnlockTable : Table<EquipItem>, IDisposable
|
|||
private readonly ObjectUnlocked _event;
|
||||
|
||||
public UnlockTable(ItemManager items, TextureService textures, ItemUnlockManager itemUnlocks,
|
||||
PenumbraChangedItemTooltip tooltip, ObjectUnlocked @event, JobService jobs)
|
||||
PenumbraChangedItemTooltip tooltip, ObjectUnlocked @event, JobService jobs, FavoriteManager favorites)
|
||||
: base("ItemUnlockTable", new ItemList(items),
|
||||
new NameColumn(textures, tooltip) { Label = "Item Name..." },
|
||||
new SlotColumn() { Label = "Equip Slot" },
|
||||
new TypeColumn() { Label = "Item Type..." },
|
||||
new UnlockDateColumn(itemUnlocks) { Label = "Unlocked" },
|
||||
new ItemIdColumn() { Label = "Item Id..." },
|
||||
new ModelDataColumn(items) { Label = "Model Data..." },
|
||||
new JobColumn(jobs) { Label = "Jobs" },
|
||||
new LevelColumn() { Label = "Level..." },
|
||||
new DyableColumn() { Label = "Dye" },
|
||||
new CrestColumn() { Label = "Crest" },
|
||||
new TradableColumn() { Label = "Trade" }
|
||||
new FavoriteColumn(favorites, @event) { Label = "F" },
|
||||
new NameColumn(textures, tooltip) { Label = "Item Name..." },
|
||||
new SlotColumn() { Label = "Equip Slot" },
|
||||
new TypeColumn() { Label = "Item Type..." },
|
||||
new UnlockDateColumn(itemUnlocks) { Label = "Unlocked" },
|
||||
new ItemIdColumn() { Label = "Item Id..." },
|
||||
new ModelDataColumn(items) { Label = "Model Data..." },
|
||||
new JobColumn(jobs) { Label = "Jobs" },
|
||||
new LevelColumn() { Label = "Level..." },
|
||||
new DyableColumn() { Label = "Dye" },
|
||||
new CrestColumn() { Label = "Crest" },
|
||||
new TradableColumn() { Label = "Trade" }
|
||||
)
|
||||
{
|
||||
_event = @event;
|
||||
|
|
@ -48,6 +50,37 @@ public class UnlockTable : Table<EquipItem>, IDisposable
|
|||
public void Dispose()
|
||||
=> _event.Unsubscribe(OnObjectUnlock);
|
||||
|
||||
private sealed class FavoriteColumn : YesNoColumn
|
||||
{
|
||||
public override float Width
|
||||
=> ImGui.GetFrameHeightWithSpacing();
|
||||
|
||||
private readonly FavoriteManager _favorites;
|
||||
private readonly ObjectUnlocked _hackEvent; // used to trigger the table dirty.
|
||||
|
||||
public FavoriteColumn(FavoriteManager favorites, ObjectUnlocked hackEvent)
|
||||
{
|
||||
_favorites = favorites;
|
||||
_hackEvent = hackEvent;
|
||||
}
|
||||
|
||||
protected override bool GetValue(EquipItem item)
|
||||
=> _favorites.Contains(item);
|
||||
|
||||
public override void DrawColumn(EquipItem item, int idx)
|
||||
{
|
||||
ImGui.AlignTextToFramePadding();
|
||||
if (UiHelpers.DrawFavoriteStar(_favorites, item))
|
||||
_hackEvent.Invoke(ObjectUnlocked.Type.Customization, 0, DateTimeOffset.Now);
|
||||
}
|
||||
|
||||
public override bool FilterFunc(EquipItem item)
|
||||
=> FilterValue.HasFlag(_favorites.Contains(item) ? YesNoFlag.Yes : YesNoFlag.No);
|
||||
|
||||
public override int Compare(EquipItem lhs, EquipItem rhs)
|
||||
=> _favorites.Contains(rhs).CompareTo(_favorites.Contains(lhs));
|
||||
}
|
||||
|
||||
private sealed class NameColumn : ColumnString<EquipItem>
|
||||
{
|
||||
private readonly TextureService _textures;
|
||||
|
|
@ -75,9 +108,7 @@ public class UnlockTable : Table<EquipItem>, IDisposable
|
|||
ImGui.SameLine();
|
||||
ImGui.AlignTextToFramePadding();
|
||||
if (ImGui.Selectable(item.Name))
|
||||
{
|
||||
// TODO link
|
||||
}
|
||||
Glamourer.Messager.Chat.Print(new SeStringBuilder().AddItemLink(item.ItemId.Id, false).BuiltString);
|
||||
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right) && _tooltip.Player(out var state))
|
||||
_tooltip.ApplyItem(state, item);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Services;
|
||||
using Glamourer.Structs;
|
||||
using Glamourer.Unlocks;
|
||||
using ImGuiNET;
|
||||
using Lumina.Misc;
|
||||
using OtterGui;
|
||||
|
|
@ -119,4 +121,26 @@ public static class UiHelpers
|
|||
(true, false) => (true, false),
|
||||
(false, true) => (false, true),
|
||||
};
|
||||
}
|
||||
|
||||
public static bool DrawFavoriteStar(FavoriteManager favorites, EquipItem item)
|
||||
{
|
||||
var favorite = favorites.Contains(item);
|
||||
var hovering = ImGui.IsMouseHoveringRect(ImGui.GetCursorScreenPos(),
|
||||
ImGui.GetCursorScreenPos() + new Vector2(ImGui.GetTextLineHeight()));
|
||||
|
||||
using var font = ImRaii.PushFont(UiBuilder.IconFont);
|
||||
using var c = ImRaii.PushColor(ImGuiCol.Text,
|
||||
hovering ? ColorId.FavoriteStarHovered.Value() : favorite ? ColorId.FavoriteStarOn.Value() : ColorId.FavoriteStarOff.Value());
|
||||
ImGui.TextUnformatted(FontAwesomeIcon.Star.ToIconString());
|
||||
if (ImGui.IsItemClicked())
|
||||
{
|
||||
if (favorite)
|
||||
favorites.Remove(item);
|
||||
else
|
||||
favorites.TryAdd(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ public class BackupService
|
|||
new(fileNames.AutomationFile),
|
||||
new(fileNames.UnlockFileCustomize),
|
||||
new(fileNames.UnlockFileItems),
|
||||
new(fileNames.FavoriteFile),
|
||||
};
|
||||
|
||||
list.AddRange(fileNames.Designs());
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ public class FilenameService
|
|||
public readonly string AutomationFile;
|
||||
public readonly string UnlockFileCustomize;
|
||||
public readonly string UnlockFileItems;
|
||||
public readonly string FavoriteFile;
|
||||
|
||||
public FilenameService(DalamudPluginInterface pi)
|
||||
{
|
||||
|
|
@ -26,6 +27,7 @@ public class FilenameService
|
|||
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");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ public static class ServiceManager
|
|||
.AddSingleton<CodeService>()
|
||||
.AddSingleton<ConfigMigrationService>()
|
||||
.AddSingleton<Configuration>()
|
||||
.AddSingleton<TextureService>();
|
||||
.AddSingleton<TextureService>()
|
||||
.AddSingleton<FavoriteManager>();
|
||||
|
||||
private static IServiceCollection AddEvents(this IServiceCollection services)
|
||||
=> services.AddSingleton<VisorStateChanged>()
|
||||
|
|
|
|||
96
Glamourer/Unlocks/FavoriteManager.cs
Normal file
96
Glamourer/Unlocks/FavoriteManager.cs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Dalamud.Interface.Internal.Notifications;
|
||||
using Glamourer.Services;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OtterGui.Classes;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Unlocks;
|
||||
|
||||
public class FavoriteManager : ISavable
|
||||
{
|
||||
private readonly SaveService _saveService;
|
||||
private readonly HashSet<ItemId> _favorites = new();
|
||||
|
||||
public FavoriteManager(SaveService saveService)
|
||||
{
|
||||
_saveService = saveService;
|
||||
Load();
|
||||
}
|
||||
|
||||
private void Load()
|
||||
{
|
||||
var file = _saveService.FileNames.FavoriteFile;
|
||||
if (!File.Exists(file))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var text = File.ReadAllText(file);
|
||||
var array = JsonConvert.DeserializeObject<uint[]>(text) ?? Array.Empty<uint>();
|
||||
_favorites.UnionWith(array.Select(i => (ItemId)i));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Glamourer.Messager.NotificationMessage(ex, "Could not read Favorite file.", NotificationType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
public string ToFilename(FilenameService fileNames)
|
||||
=> fileNames.FavoriteFile;
|
||||
|
||||
private void Save()
|
||||
=> _saveService.DelaySave(this);
|
||||
|
||||
public void Save(StreamWriter writer)
|
||||
{
|
||||
using var j = new JsonTextWriter(writer)
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
};
|
||||
j.WriteStartArray();
|
||||
foreach (var item in _favorites)
|
||||
j.WriteValue(item.Id);
|
||||
j.WriteEndArray();
|
||||
}
|
||||
|
||||
public bool TryAdd(EquipItem item)
|
||||
=> TryAdd(item.ItemId);
|
||||
|
||||
public bool TryAdd(ItemId item)
|
||||
{
|
||||
if (item.Id == 0 || !_favorites.Add(item))
|
||||
return false;
|
||||
|
||||
Save();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Remove(EquipItem item)
|
||||
=> Remove(item.ItemId);
|
||||
|
||||
public bool Remove(ItemId item)
|
||||
{
|
||||
if (!_favorites.Remove(item))
|
||||
return false;
|
||||
|
||||
Save();
|
||||
return true;
|
||||
}
|
||||
|
||||
public IEnumerator<ItemId> GetEnumerator()
|
||||
=> _favorites.GetEnumerator();
|
||||
|
||||
public int Count
|
||||
=> _favorites.Count;
|
||||
|
||||
public bool Contains(EquipItem item)
|
||||
=> _favorites.Contains(item.ItemId);
|
||||
|
||||
public bool Contains(ItemId item)
|
||||
=> _favorites.Contains(item);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue