Glamourer/Glamourer/Gui/Tabs/UnlocksTab/UnlockOverview.cs
Ottermandias f8e9cc8988 .
2023-07-07 20:24:44 +02:00

220 lines
8.4 KiB
C#

using System;
using System.Linq;
using System.Numerics;
using Dalamud.Interface;
using Glamourer.Customization;
using Glamourer.Services;
using Glamourer.Unlocks;
using ImGuiNET;
using OtterGui;
using OtterGui.Classes;
using OtterGui.Raii;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs;
namespace Glamourer.Gui.Tabs.UnlocksTab;
public class UnlockOverview
{
private readonly ItemManager _items;
private readonly ItemUnlockManager _itemUnlocks;
private readonly CustomizationService _customizations;
private readonly CustomizeUnlockManager _customizeUnlocks;
private readonly PenumbraChangedItemTooltip _tooltip;
private readonly TextureCache _textureCache;
private static readonly Vector4 UnavailableTint = new(0.3f, 0.3f, 0.3f, 1.0f);
private FullEquipType _selected1 = FullEquipType.Unknown;
private SubRace _selected2 = SubRace.Unknown;
private Gender _selected3 = Gender.Unknown;
private void DrawSelector()
{
using var child = ImRaii.Child("Selector", new Vector2(200 * ImGuiHelpers.GlobalScale, -1), true);
if (!child)
return;
foreach (var type in Enum.GetValues<FullEquipType>())
{
if (type.IsOffhandType() || !_items.ItemService.AwaitedService.TryGetValue(type, out var items) || items.Count == 0)
continue;
if (ImGui.Selectable(type.ToName(), _selected1 == type))
{
_selected1 = type;
_selected2 = SubRace.Unknown;
_selected3 = Gender.Unknown;
}
}
foreach (var clan in _customizations.AwaitedService.Clans)
{
foreach (var gender in _customizations.AwaitedService.Genders)
{
if (_customizations.AwaitedService.GetList(clan, gender).HairStyles.Count == 0)
continue;
if (ImGui.Selectable($"{(gender is Gender.Male ? '♂' : '♀')} {clan.ToShortName()} Hair & Paint",
_selected2 == clan && _selected3 == gender))
{
_selected1 = FullEquipType.Unknown;
_selected2 = clan;
_selected3 = gender;
}
}
}
}
public UnlockOverview(ItemManager items, CustomizationService customizations, ItemUnlockManager itemUnlocks,
CustomizeUnlockManager customizeUnlocks, PenumbraChangedItemTooltip tooltip, TextureCache textureCache)
{
_items = items;
_customizations = customizations;
_itemUnlocks = itemUnlocks;
_customizeUnlocks = customizeUnlocks;
_tooltip = tooltip;
_textureCache = textureCache;
}
public void Draw()
{
using var color = ImRaii.PushColor(ImGuiCol.Border, ImGui.GetColorU32(ImGuiCol.TableBorderStrong));
DrawSelector();
ImGui.SameLine();
DrawPanel();
}
private void DrawPanel()
{
using var child = ImRaii.Child("Panel", -Vector2.One, true);
if (!child)
return;
if (_selected1 is not FullEquipType.Unknown)
DrawItems();
else if (_selected2 is not SubRace.Unknown && _selected3 is not Gender.Unknown)
DrawCustomizations();
}
private void DrawCustomizations()
{
var set = _customizations.AwaitedService.GetList(_selected2, _selected3);
var spacing = IconSpacing;
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing);
var iconSize = ImGuiHelpers.ScaledVector2(128);
var iconsPerRow = IconsPerRow(iconSize.X, spacing.X);
var counter = 0;
foreach (var customize in set.HairStyles.Concat(set.FacePaints))
{
if (!_customizeUnlocks.Unlockable.TryGetValue(customize, out var unlockData))
continue;
var unlocked = _customizeUnlocks.IsUnlocked(customize, out var time);
var icon = _customizations.AwaitedService.GetIcon(customize.IconId);
ImGui.Image(icon.ImGuiHandle, iconSize, Vector2.Zero, Vector2.One, unlocked ? Vector4.One : UnavailableTint);
if (ImGui.IsItemHovered())
{
using var tt = ImRaii.Tooltip();
var size = new Vector2(icon.Width, icon.Height);
if (size.X >= iconSize.X && size.Y >= iconSize.Y)
ImGui.Image(icon.ImGuiHandle, size);
ImGui.TextUnformatted(unlockData.Name);
ImGui.TextUnformatted($"{customize.Index.ToDefaultName()} {customize.Value.Value}");
ImGui.TextUnformatted(unlocked ? $"Unlocked on {time:g}" : "Not unlocked.");
}
if (counter != iconsPerRow - 1)
{
ImGui.SameLine();
++counter;
}
else
{
counter = 0;
}
}
}
private void DrawItems()
{
if (!_items.ItemService.AwaitedService.TryGetValue(_selected1, out var items))
return;
var spacing = IconSpacing;
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing);
var iconSize = ImGuiHelpers.ScaledVector2(64);
var iconsPerRow = IconsPerRow(iconSize.X, spacing.X);
var numRows = (items.Count + iconsPerRow - 1) / iconsPerRow;
var numVisibleRows = (int)(Math.Ceiling(ImGui.GetContentRegionAvail().Y / (iconSize.Y + spacing.Y)) + 0.5f);
void DrawItem(EquipItem item)
{
var unlocked = _itemUnlocks.IsUnlocked(item.Id, out var time);
var iconHandle = _textureCache.LoadIcon(item.IconId);
if (!iconHandle.HasValue)
return;
var (icon, size) = iconHandle.Value.Value;
ImGui.Image(icon, iconSize, Vector2.Zero, Vector2.One, unlocked ? Vector4.One : UnavailableTint);
if (ImGui.IsItemClicked())
{
// TODO link
}
if (ImGui.IsItemClicked(ImGuiMouseButton.Right) && _tooltip.Player(out var state))
_tooltip.ApplyItem(state, item);
if (ImGui.IsItemHovered())
{
using var tt = ImRaii.Tooltip();
if (size.X >= iconSize.X && size.Y >= iconSize.Y)
ImGui.Image(icon, size);
ImGui.TextUnformatted(item.Name);
var slot = item.Type.ToSlot();
ImGui.TextUnformatted($"{item.Type.ToName()} ({slot.ToName()})");
if (item.Type.Offhand().IsOffhandType())
ImGui.TextUnformatted(
$"{item.Weapon()}{(_items.ItemService.AwaitedService.TryGetValue(item.Id, false, out var offhand) ? $" | {offhand.Weapon()}" : string.Empty)}");
else
ImGui.TextUnformatted(slot is EquipSlot.MainHand ? $"{item.Weapon()}" : $"{item.Armor()}");
ImGui.TextUnformatted(
unlocked ? time == DateTimeOffset.MinValue ? "Always Unlocked" : $"Unlocked on {time:g}" : "Not Unlocked.");
_tooltip.CreateTooltip(item, string.Empty, false);
}
}
var skips = ImGuiClip.GetNecessarySkips(iconSize.Y + spacing.Y);
var end = Math.Min(numVisibleRows * iconsPerRow + skips * iconsPerRow, items.Count);
var counter = 0;
for (var idx = skips * iconsPerRow; idx < end; ++idx)
{
DrawItem(items[idx]);
if (counter != iconsPerRow - 1)
{
ImGui.SameLine();
++counter;
}
else
{
counter = 0;
}
}
if (ImGui.GetCursorPosX() != 0)
ImGui.NewLine();
var remainder = numRows - numVisibleRows - skips;
if (remainder > 0)
ImGuiClip.DrawEndDummy(remainder, iconSize.Y + spacing.Y);
}
private static Vector2 IconSpacing
=> ImGuiHelpers.ScaledVector2(2);
private static int IconsPerRow(float iconWidth, float iconSpacing)
=> (int)(ImGui.GetContentRegionAvail().X / (iconWidth + iconSpacing));
}