Current State.

This commit is contained in:
Ottermandias 2026-02-05 16:46:38 +01:00
parent e8c6204c25
commit 0d4f7777f0
28 changed files with 557 additions and 557 deletions

@ -1 +1 @@
Subproject commit 5b6730d46f17bdd02a441e23e2141576cf7acf53 Subproject commit 51b3c72e91816af0002dd543d64944e777b246ba

View file

@ -1,32 +1,44 @@
using Glamourer.Api.Enums; using Glamourer.Api.Enums;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.GameData; using Glamourer.GameData;
using ImSharp;
using Luna.Generators;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
namespace Glamourer.Automation; namespace Glamourer.Automation;
[Flags] [Flags]
[TooltipEnum]
public enum ApplicationType : byte public enum ApplicationType : byte
{ {
Armor = 0x01, [Tooltip("Apply all armor piece changes that are enabled in this design and that are valid in a fixed design.")]
Customizations = 0x02, Armor = 0x01,
Weapons = 0x04,
[Tooltip(
"Apply all customization changes that are enabled in this design and that are valid in a fixed design and for the given race and gender.")]
Customizations = 0x02,
[Tooltip("Apply all weapon changes that are enabled in this design and that are valid with the current weapon worn.")]
Weapons = 0x04,
[Tooltip("Apply all dye and crest changes that are enabled in this design.")]
GearCustomization = 0x08, GearCustomization = 0x08,
Accessories = 0x10,
[Tooltip("Apply all accessory changes that are enabled in this design and that are valid in a fixed design.")]
Accessories = 0x10,
All = Armor | Accessories | Customizations | Weapons | GearCustomization, All = Armor | Accessories | Customizations | Weapons | GearCustomization,
} }
public static class ApplicationTypeExtensions public static partial class ApplicationTypeExtensions
{ {
public static readonly IReadOnlyList<(ApplicationType, string)> Types = public static readonly IReadOnlyList<(ApplicationType, StringU8)> Types =
[ [
(ApplicationType.Customizations, (ApplicationType.Customizations, ApplicationType.Customizations.Tooltip()),
"Apply all customization changes that are enabled in this design and that are valid in a fixed design and for the given race and gender."), (ApplicationType.Armor, ApplicationType.Armor.Tooltip()),
(ApplicationType.Armor, "Apply all armor piece changes that are enabled in this design and that are valid in a fixed design."), (ApplicationType.Accessories, ApplicationType.Accessories.Tooltip()),
(ApplicationType.Accessories, "Apply all accessory changes that are enabled in this design and that are valid in a fixed design."), (ApplicationType.GearCustomization, ApplicationType.GearCustomization.Tooltip()),
(ApplicationType.GearCustomization, "Apply all dye and crest changes that are enabled in this design."), (ApplicationType.Weapons, ApplicationType.Weapons.Tooltip()),
(ApplicationType.Weapons, "Apply all weapon changes that are enabled in this design and that are valid with the current weapon worn."),
]; ];
public static ApplicationCollection Collection(this ApplicationType type) public static ApplicationCollection Collection(this ApplicationType type)
@ -48,9 +60,10 @@ public static class ApplicationTypeExtensions
public static ApplicationCollection ApplyWhat(this ApplicationType type, IDesignStandIn designStandIn) public static ApplicationCollection ApplyWhat(this ApplicationType type, IDesignStandIn designStandIn)
{ {
if(designStandIn is not DesignBase design) if (designStandIn is not DesignBase design)
return type.Collection(); return type.Collection();
var ret = type.Collection().Restrict(design.Application);
var ret = type.Collection().Restrict(design.Application);
ret.CustomizeRaw = ret.CustomizeRaw.FixApplication(design.CustomizeSet); ret.CustomizeRaw = ret.CustomizeRaw.FixApplication(design.CustomizeSet);
return ret; return ret;
} }

View file

@ -37,8 +37,11 @@ public class Glamourer : IDalamudPlugin
_services = StaticServiceManager.CreateProvider(pluginInterface, Log, this); _services = StaticServiceManager.CreateProvider(pluginInterface, Log, this);
Messager = _services.GetService<MessageService>(); Messager = _services.GetService<MessageService>();
Dynamis = _services.GetService<DynamisIpc>(); Dynamis = _services.GetService<DynamisIpc>();
foreach (var _ in _services.GetServicesImplementing<IHookService>())
;
_ = _services.GetService<ImSharpDalamudContext>();
_services.EnsureRequiredServices(); _services.EnsureRequiredServices();
_services.GetService<VisorService>(); _services.GetService<VisorService>();
_services.GetService<WeaponService>(); _services.GetService<WeaponService>();
_services.GetService<ScalingService>(); _services.GetService<ScalingService>();

View file

@ -45,7 +45,7 @@ public partial class CustomizationDrawer
_ => Unknown, _ => Unknown,
}; };
if (ImEx.Icon.Button(icon, StringU8.Empty, icon != Unknown, _framedIconSize)) if (ImEx.Icon.Button(icon, StringU8.Empty, icon == Unknown, _framedIconSize))
Changed |= service.ChangeGender(ref _customize, icon == Male ? Gender.Female : Gender.Male); Changed |= service.ChangeGender(ref _customize, icon == Male ? Gender.Female : Gender.Male);
} }

View file

@ -46,7 +46,7 @@ public partial class CustomizationDrawer
} }
if (hasIcon) if (hasIcon)
Im.Tooltip.ImageOnHover(wrap!.Id, _iconSize); Im.Tooltip.ImageOnHover(wrap!.Id, wrap.Size);
Im.Line.Same(); Im.Line.Same();
using (Im.Group()) using (Im.Group())
@ -212,8 +212,8 @@ public partial class CustomizationDrawer
hasIcon = icon.TryGetWrap(out wrap, out _); hasIcon = icon.TryGetWrap(out wrap, out _);
} }
if (Im.Image.Button(wrap?.Id ?? icon.GetWrapOrEmpty().Id, _iconSize, Vector2.Zero, Vector2.One, Vector4.Zero, if (Im.Image.Button(wrap?.Id ?? icon.GetWrapOrEmpty().Id, _iconSize, Vector2.Zero, Vector2.One,
enabled ? Vector4.One : _redTint, enabled ? Vector4.One : _redTint, Vector4.Zero,
(int)Im.Style.FramePadding.X)) (int)Im.Style.FramePadding.X))
{ {
_customize.Set(featureIdx, enabled ? CustomizeValue.Zero : CustomizeValue.Max); _customize.Set(featureIdx, enabled ? CustomizeValue.Zero : CustomizeValue.Max);
@ -221,7 +221,7 @@ public partial class CustomizationDrawer
} }
if (hasIcon) if (hasIcon)
Im.Tooltip.ImageOnHover(wrap!.Id, _iconSize); Im.Tooltip.ImageOnHover(wrap!.Id, wrap.Size);
if (idx % 4 is not 3) if (idx % 4 is not 3)
Im.Line.Same(); Im.Line.Same();
} }

View file

@ -40,17 +40,19 @@ public partial class CustomizationDrawer
Span<byte> t = stackalloc byte[64]; Span<byte> t = stackalloc byte[64];
var ic = CultureInfo.InvariantCulture; var ic = CultureInfo.InvariantCulture;
int written;
if (config.HeightDisplayType switch if (config.HeightDisplayType switch
{ {
HeightDisplayType.Centimetre => Utf8.TryWrite(t, ic, $"({height * 100:F1} cm)", out _), HeightDisplayType.Centimetre => Utf8.TryWrite(t, ic, $"({height * 100:F1} cm)", out written),
HeightDisplayType.Metre => Utf8.TryWrite(t, ic, $"({height:F2} m)", out _), HeightDisplayType.Metre => Utf8.TryWrite(t, ic, $"({height:F2} m)", out written),
HeightDisplayType.Wrong => Utf8.TryWrite(t, ic, $"({height * 100 / 2.539:F1} in)", out _), HeightDisplayType.Wrong => Utf8.TryWrite(t, ic, $"({height * 100 / 2.539:F1} in)", out written),
HeightDisplayType.WrongFoot => Utf8.TryWrite(t, ic, $"({(int)(height * 3.2821)}'{(int)(height * 39.3856) % 12}'')", out _), HeightDisplayType.WrongFoot => Utf8.TryWrite(t, ic, $"({(int)(height * 3.2821)}'{(int)(height * 39.3856) % 12}'')",
HeightDisplayType.Corgi => Utf8.TryWrite(t, ic, $"({height * 100 / 40.0:F1} Corgis)", out _), out written),
HeightDisplayType.OlympicPool => Utf8.TryWrite(t, ic, $"({height / 3.0:F3} Pools)", out _), HeightDisplayType.Corgi => Utf8.TryWrite(t, ic, $"({height * 100 / 40.0:F1} Corgis)", out written),
_ => Utf8.TryWrite(t, ic, $"({height})", out _), HeightDisplayType.OlympicPool => Utf8.TryWrite(t, ic, $"({height / 3.0:F3} Pools)", out written),
_ => Utf8.TryWrite(t, ic, $"({height})", out written),
}) })
Im.Text(t); Im.Text(t[..written]);
} }
private void DrawPercentageSlider() private void DrawPercentageSlider()

View file

@ -15,6 +15,62 @@ using MouseWheelType = OtterGui.Widgets.MouseWheelType;
namespace Glamourer.Gui; namespace Glamourer.Gui;
//public abstract class DesignComboBase2 : ImSharp.FilterComboBase<DesignComboBase2.CacheItem>, IDisposable
//{
// protected readonly EphemeralConfig Config;
// protected readonly DesignChanged DesignChanged;
// protected readonly DesignColors DesignColors;
// protected readonly TabSelected TabSelected;
// protected IDesignStandIn? _currentDesign;
//
// private CacheItem CreateItem(IDesignStandIn design)
// {
//
// }
//
// public readonly struct CacheItem(IDesignStandIn design, Vector4 color)
// {
// public readonly IDesignStandIn Design = design;
// public readonly StringPair Name = new(design.ResolveName(false));
// public readonly StringPair Incognito = new(design.ResolveName(true));
// public readonly StringPair FullPath = StringPair.Empty;
// public readonly Vector4 Color = color;
// }
//
// public DesignComboBase2(EphemeralConfig config, DesignChanged designChanged, DesignColors designColors, TabSelected tabSelected)
// {
// Config = config;
// DesignChanged = designChanged;
// DesignColors = designColors;
// TabSelected = tabSelected;
//
// DesignChanged.Subscribe(OnDesignChanged, DesignChanged.Priority.DesignCombo);
// }
//
// private void OnDesignChanged(DesignChanged.Type type, Design? _1, ITransaction? _2 = null)
// {
// _isCurrentSelectionDirty = type switch
// {
// DesignChanged.Type.Created => true,
// DesignChanged.Type.Renamed => true,
// DesignChanged.Type.ChangedColor => true,
// DesignChanged.Type.Deleted => true,
// DesignChanged.Type.QuickDesignBar => true,
// _ => _isCurrentSelectionDirty,
// };
// }
//
// protected override bool DrawItem(in CacheItem item, int globalIndex, bool selected)
// {
//
// }
//
// public void Dispose()
// {
// DesignChanged.Unsubscribe(OnDesignChanged);
// }
//}
public abstract class DesignComboBase : FilterComboCache<Tuple<IDesignStandIn, string>>, IDisposable public abstract class DesignComboBase : FilterComboCache<Tuple<IDesignStandIn, string>>, IDisposable
{ {
protected readonly EphemeralConfig Config; protected readonly EphemeralConfig Config;

View file

@ -1,5 +1,4 @@
using Dalamud.Interface.Components; using Dalamud.Plugin.Services;
using Dalamud.Plugin.Services;
using Glamourer.Events; using Glamourer.Events;
using Glamourer.Gui.Materials; using Glamourer.Gui.Materials;
using Glamourer.Services; using Glamourer.Services;
@ -46,7 +45,7 @@ public class EquipmentDrawer
_advancedDyes = advancedDyes; _advancedDyes = advancedDyes;
_itemCopy = itemCopy; _itemCopy = itemCopy;
_stainData = items.Stains; _stainData = items.Stains;
_stainCombo = new GlamourerColorCombo(DefaultWidth - 20, _stainData, favorites); _stainCombo = new GlamourerColorCombo(_stainData, favorites);
_itemCombo = EquipSlotExtensions.EqdpSlots.Select(e => new ItemCombo(gameData, items, e, Glamourer.Log, favorites)).ToArray(); _itemCombo = EquipSlotExtensions.EqdpSlots.Select(e => new ItemCombo(gameData, items, e, Glamourer.Log, favorites)).ToArray();
_bonusItemCombo = BonusExtensions.AllFlags.Select(f => new BonusItemCombo(gameData, items, f, Glamourer.Log, favorites)).ToArray(); _bonusItemCombo = BonusExtensions.AllFlags.Select(f => new BonusItemCombo(gameData, items, f, Glamourer.Log, favorites)).ToArray();
_weaponCombo = new Dictionary<FullEquipType, WeaponCombo>(FullEquipTypeExtensions.WeaponTypes.Count * 2); _weaponCombo = new Dictionary<FullEquipType, WeaponCombo>(FullEquipTypeExtensions.WeaponTypes.Count * 2);
@ -159,13 +158,10 @@ public class EquipmentDrawer
public bool DrawAllStain(out StainIds ret, bool locked) public bool DrawAllStain(out StainIds ret, bool locked)
{ {
using var disabled = Im.Disabled(locked); using var disabled = Im.Disabled(locked);
var change = _stainCombo.Draw("Dye All Slots", Stain.None.RgbaColor, string.Empty, false, false, OtterGui.Widgets.MouseWheelType.None); var change = _stainCombo.Draw("Dye All Slots"u8, Stain.None, out var newAllStain, Im.Style.FrameHeight);
ret = StainIds.None; ret = StainIds.None;
if (change) if (change)
if (_stainData.TryGetValue(_stainCombo.CurrentSelection.Key, out var stain)) ret = newAllStain.RowIndex != Stain.None.RowIndex ? StainIds.All(newAllStain.RowIndex) : StainIds.None;
ret = StainIds.All(stain.RowIndex);
else if (_stainCombo.CurrentSelection.Key == Stain.None.RowIndex)
ret = StainIds.None;
if (!locked) if (!locked)
{ {
@ -390,15 +386,16 @@ public class EquipmentDrawer
private void DrawStain(in EquipDrawData data, bool small) private void DrawStain(in EquipDrawData data, bool small)
{ {
using var id = Im.Id.Push((uint)data.Slot);
using var disabled = Im.Disabled(data.Locked); using var disabled = Im.Disabled(data.Locked);
var width = (_comboLength - Im.Style.ItemInnerSpacing.X * (data.CurrentStains.Count - 1)) / data.CurrentStains.Count; var width = (_comboLength - Im.Style.ItemInnerSpacing.X * (data.CurrentStains.Count - 1)) / data.CurrentStains.Count;
foreach (var (index, stainId) in data.CurrentStains.Index()) foreach (var (index, stainId) in data.CurrentStains.Index())
{ {
using var id = Im.Id.Push(index); id.Push(index);
var found = _stainData.TryGetValue(stainId, out var stain); var found = _stainData.TryGetValue(stainId, out var stain);
var change = small var change = small
? _stainCombo.Draw($"##stain{data.Slot}", stain.RgbaColor, stain.Name, found, stain.Gloss) ? _stainCombo.Draw("##stain"u8, stain, out var newStain, Im.Style.FrameHeight)
: _stainCombo.Draw($"##stain{data.Slot}", stain.RgbaColor, stain.Name, found, stain.Gloss, width); : _stainCombo.Draw("##stain"u8, stain, out newStain, width);
_itemCopy.HandleCopyPaste(data, index); _itemCopy.HandleCopyPaste(data, index);
if (!change) if (!change)
@ -408,13 +405,11 @@ public class EquipmentDrawer
Im.Line.SameInner(); Im.Line.SameInner();
if (change) if (change)
if (_stainData.TryGetValue(_stainCombo.CurrentSelection.Key, out stain)) data.SetStains(data.CurrentStains.With(index, newStain.RowIndex));
data.SetStains(data.CurrentStains.With(index, stain.RowIndex));
else if (_stainCombo.CurrentSelection.Key == Stain.None.RowIndex)
data.SetStains(data.CurrentStains.With(index, Stain.None.RowIndex));
if (ResetOrClear(data.Locked, false, data.AllowRevert, true, stainId, data.GameStains[index], Stain.None.RowIndex, if (ResetOrClear(data.Locked, false, data.AllowRevert, true, stainId, data.GameStains[index], Stain.None.RowIndex,
out var newStain)) out var newStainId))
data.SetStains(data.CurrentStains.With(index, newStain)); data.SetStains(data.CurrentStains.With(index, newStainId));
id.Pop(index);
} }
} }

View file

@ -1,46 +1,70 @@
using Dalamud.Interface; using Glamourer.Unlocks;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Glamourer.Unlocks;
using Dalamud.Bindings.ImGui;
using ImSharp; using ImSharp;
using OtterGui.Widgets; using Luna;
using Penumbra.GameData.DataContainers; using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
using MouseWheelType = OtterGui.Widgets.MouseWheelType;
namespace Glamourer.Gui.Equipment; namespace Glamourer.Gui.Equipment;
public sealed class GlamourerColorCombo(float _comboWidth, DictStain _stains, FavoriteManager _favorites) public sealed class GlamourerColorCombo(DictStain stains, FavoriteManager favorites) : FilterComboColors
: FilterComboColors(_comboWidth, MouseWheelType.Control, CreateFunc(_stains, _favorites), Glamourer.Log)
{ {
protected override bool DrawSelectable(int globalIdx, bool selected) protected override float AdditionalSpace
{ => AwesomeIcon.Font.CalculateTextSize(LunaStyle.FavoriteIcon.Span).X + 4 * Im.Style.GlobalScale;
using (var _ = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGuiHelpers.ScaledVector2(4, 0)))
{
if (globalIdx == 0)
{
using var font = ImRaii.PushFont(UiBuilder.IconFont);
Im.Dummy(ImGui.CalcTextSize(FontAwesomeIcon.Star.ToIconString()));
}
else
{
UiHelpers.DrawFavoriteStar(_favorites, Items[globalIdx].Key);
}
Im.Line.Same(); protected override bool DrawItem(in Item item, int globalIndex, bool selected)
} {
if (globalIndex is 0)
Im.Dummy(AwesomeIcon.Font.CalculateTextSize(LunaStyle.FavoriteIcon.Span));
else
UiHelpers.DrawFavoriteStar(favorites, item.Id);
Im.Line.Same(0, 4 * Im.Style.GlobalScale);
var buttonWidth = Im.ContentRegion.Available.X; var buttonWidth = Im.ContentRegion.Available.X;
var totalWidth = ImGui.GetContentRegionMax().X; var totalWidth = Im.ContentRegion.Maximum.X;
using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(buttonWidth / 2 / totalWidth, 0.5f)); using var style = ImStyleDouble.ButtonTextAlign.PushX(buttonWidth / 2 / totalWidth);
return base.DrawItem(item, globalIndex, selected);
return base.DrawSelectable(globalIdx, selected);
} }
private static Func<IReadOnlyList<KeyValuePair<byte, (string Name, uint Color, bool Gloss)>>> CreateFunc(DictStain stains, protected override void PreDrawCombo(float width)
FavoriteManager favorites) {
=> () => stains.Select(kvp => (kvp, favorites.Contains(kvp.Key))).OrderBy(p => !p.Item2).Select(p => p.kvp) base.PreDrawCombo(width);
.Prepend(new KeyValuePair<StainId, Stain>(Stain.None.RowIndex, Stain.None)).Select(kvp Style.Push(ImGuiColor.Text, CurrentSelection.Color.ContrastColor(), !CurrentSelection.Color.IsTransparent);
=> new KeyValuePair<byte, (string, uint, bool)>(kvp.Key.Id, (kvp.Value.Name, kvp.Value.RgbaColor, kvp.Value.Gloss))).ToList(); }
protected override void PostDrawCombo(float width)
{
if (!CurrentSelection.Color.IsTransparent)
Style.PopColor();
base.PostDrawCombo(width);
}
public bool Draw(Utf8StringHandler<LabelStringHandlerBuffer> label, in Stain current, out Stain newStain, float width)
{
// Push the preview color.
using var color = ImGuiColor.FrameBackground.Push(current.RgbaColor, !current.RgbaColor.IsTransparent);
// Set the current selection only for the IsSelected and Gloss checks.
CurrentSelection = new Item(current.Name, current.RgbaColor, current.RowIndex.Id, current.Gloss);
// Skip the named preview if it does not fit.
var name = Im.Font.CalculateSize(current.Name).X <= width && !current.RgbaColor.IsTransparent ? current.Name : StringU8.Empty;
if (base.Draw(label, name, StringU8.Empty, width, out var newItem))
{
if (newItem.Id is 0)
newStain = Stain.None;
else if (!stains.TryGetValue(newItem.Id, out newStain))
return false;
return true;
}
newStain = current;
return false;
}
protected override IEnumerable<Item> GetItems()
=> stains.Select(kvp => (new Item(kvp.Value.Name, kvp.Value.RgbaColor, kvp.Key.Id, kvp.Value.Gloss), favorites.Contains(kvp.Key)))
.OrderBy(p => !p.Item2)
.Select(p => p.Item1)
.Prepend(None);
} }

View file

@ -1,18 +1,22 @@
using Dalamud.Game.ClientState.Objects.Enums; using Dalamud.Game.ClientState.Objects.Enums;
using Dalamud.Bindings.ImGui; using ImSharp;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.GameData.DataContainers; using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Gui; using Penumbra.GameData.Gui;
using Penumbra.GameData.Structs;
using Penumbra.String; using Penumbra.String;
namespace Glamourer.Gui.Tabs.AutomationTab; namespace Glamourer.Gui.Tabs.AutomationTab;
public class IdentifierDrawer public class IdentifierDrawer(
ActorManager actors,
DictWorld dictWorld,
DictModelChara dictModelChara,
DictBNpcNames bNpcNames,
DictBNpc bNpc,
HumanModelList humans)
{ {
private readonly WorldCombo _worldCombo; private readonly WorldCombo _worldCombo = new(dictWorld);
private readonly HumanNpcCombo _humanNpcCombo; private readonly HumanNpcCombo _humanNpcCombo = new("##npcs", dictModelChara, bNpcNames, bNpc, humans, Glamourer.Log);
private readonly ActorManager _actors;
private string _characterName = string.Empty; private string _characterName = string.Empty;
@ -22,18 +26,10 @@ public class IdentifierDrawer
public ActorIdentifier MannequinIdentifier { get; private set; } = ActorIdentifier.Invalid; public ActorIdentifier MannequinIdentifier { get; private set; } = ActorIdentifier.Invalid;
public ActorIdentifier OwnedIdentifier { get; private set; } = ActorIdentifier.Invalid; public ActorIdentifier OwnedIdentifier { get; private set; } = ActorIdentifier.Invalid;
public IdentifierDrawer(ActorManager actors, DictWorld dictWorld, DictModelChara dictModelChara, DictBNpcNames bNpcNames, DictBNpc bNpc,
HumanModelList humans)
{
_actors = actors;
_worldCombo = new WorldCombo(dictWorld);
_humanNpcCombo = new HumanNpcCombo("##npcs", dictModelChara, bNpcNames, bNpc, humans, Glamourer.Log);
}
public void DrawName(float width) public void DrawName(float width)
{ {
ImGui.SetNextItemWidth(width); Im.Item.SetNextWidth(width);
if (ImGui.InputTextWithHint("##Name", "Character Name...", ref _characterName, 32)) if (Im.Input.Text("##Name"u8, ref _characterName, "Character Name..."u8))
UpdateIdentifiers(); UpdateIdentifiers();
} }
@ -68,18 +64,19 @@ public class IdentifierDrawer
{ {
if (ByteString.FromString(_characterName, out var byteName)) if (ByteString.FromString(_characterName, out var byteName))
{ {
PlayerIdentifier = _actors.CreatePlayer(byteName, _worldCombo.Selected.Key); PlayerIdentifier = actors.CreatePlayer(byteName, _worldCombo.Selected.Key);
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.CurrentSelection.Kind is ObjectKind.EventNpc or ObjectKind.BattleNpc)
OwnedIdentifier = _actors.CreateOwned(byteName, _worldCombo.Selected.Key, _humanNpcCombo.CurrentSelection.Kind, _humanNpcCombo.CurrentSelection.Ids[0]); OwnedIdentifier = actors.CreateOwned(byteName, _worldCombo.Selected.Key, _humanNpcCombo.CurrentSelection.Kind,
_humanNpcCombo.CurrentSelection.Ids[0]);
else else
OwnedIdentifier = ActorIdentifier.Invalid; OwnedIdentifier = ActorIdentifier.Invalid;
} }
NpcIdentifier = _humanNpcCombo.CurrentSelection.Kind is ObjectKind.EventNpc or ObjectKind.BattleNpc NpcIdentifier = _humanNpcCombo.CurrentSelection.Kind is ObjectKind.EventNpc or ObjectKind.BattleNpc
? _actors.CreateNpc(_humanNpcCombo.CurrentSelection.Kind, _humanNpcCombo.CurrentSelection.Ids[0]) ? actors.CreateNpc(_humanNpcCombo.CurrentSelection.Kind, _humanNpcCombo.CurrentSelection.Ids[0])
: ActorIdentifier.Invalid; : ActorIdentifier.Invalid;
} }
} }

View file

@ -1,18 +1,11 @@
using Dalamud.Interface; using Glamourer.Automation;
using Dalamud.Interface.Utility;
using Glamourer.Automation;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Designs.Special; using Glamourer.Designs.Special;
using Glamourer.Interop; using Glamourer.Interop;
using Glamourer.Services; using Glamourer.Services;
using Glamourer.Unlocks; using Glamourer.Unlocks;
using Dalamud.Bindings.ImGui;
using ImSharp; using ImSharp;
using OtterGui; using Luna;
using OtterGui.Extensions;
using OtterGui.Log;
using OtterGui.Raii;
using OtterGui.Text;
using OtterGui.Widgets; using OtterGui.Widgets;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
@ -45,7 +38,7 @@ public class SetPanel(
public void Draw() public void Draw()
{ {
using var group = ImRaii.Group(); using var group = Im.Group();
DrawHeader(); DrawHeader();
DrawPanel(); DrawPanel();
} }
@ -55,59 +48,45 @@ public class SetPanel(
private void DrawPanel() private void DrawPanel()
{ {
using var child = ImUtf8.Child("##Panel"u8, -Vector2.One, true); using var child = Im.Child.Begin("##Panel"u8, Im.ContentRegion.Available, true);
if (!child || !selector.HasSelection) if (!child || !selector.HasSelection)
return; return;
var spacing = Im.Style.ItemInnerSpacing with { Y = Im.Style.ItemSpacing.Y }; using (Im.Group())
using (ImUtf8.Group())
{ {
using (ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing)) var enabled = Selection.Enabled;
{ if (Im.Checkbox("##Enabled"u8, ref enabled))
var enabled = Selection.Enabled; manager.SetState(selector.SelectionIndex, enabled);
if (ImUtf8.Checkbox("##Enabled"u8, ref enabled)) LunaStyle.DrawAlignedHelpMarkerLabel("Enabled"u8,
manager.SetState(selector.SelectionIndex, enabled); "Whether the designs in this set should be applied at all. Only one set can be enabled for a character at the same time."u8);
ImUtf8.LabeledHelpMarker("Enabled"u8,
"Whether the designs in this set should be applied at all. Only one set can be enabled for a character at the same time."u8);
}
using (ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing)) var useGame = selector.Selection!.BaseState is AutoDesignSet.Base.Game;
{ if (Im.Checkbox("##gameState"u8, ref useGame))
var useGame = selector.Selection!.BaseState is AutoDesignSet.Base.Game; manager.ChangeBaseState(selector.SelectionIndex, useGame ? AutoDesignSet.Base.Game : AutoDesignSet.Base.Current);
if (ImUtf8.Checkbox("##gameState"u8, ref useGame)) LunaStyle.DrawAlignedHelpMarkerLabel("Use Game State as Base"u8,
manager.ChangeBaseState(selector.SelectionIndex, useGame ? AutoDesignSet.Base.Game : AutoDesignSet.Base.Current); "When this is enabled, the designs matching conditions will be applied successively on top of what your character is supposed to look like for the game. "u8
ImUtf8.LabeledHelpMarker("Use Game State as Base"u8, + "Otherwise, they will be applied on top of the characters actual current look using Glamourer."u8);
"When this is enabled, the designs matching conditions will be applied successively on top of what your character is supposed to look like for the game. "u8
+ "Otherwise, they will be applied on top of the characters actual current look using Glamourer."u8);
}
} }
Im.Line.Same(); Im.Line.Same();
using (ImUtf8.Group()) using (Im.Group())
{ {
using (ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing)) var editing = config.ShowAutomationSetEditing;
if (Im.Checkbox("##Show Editing"u8, ref editing))
{ {
var editing = config.ShowAutomationSetEditing; config.ShowAutomationSetEditing = editing;
if (ImUtf8.Checkbox("##Show Editing"u8, ref editing)) config.Save();
{
config.ShowAutomationSetEditing = editing;
config.Save();
}
ImUtf8.LabeledHelpMarker("Show Editing"u8,
"Show options to change the name or the associated character or NPC of this design set."u8);
} }
using (ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing)) LunaStyle.DrawAlignedHelpMarkerLabel("Show Editing"u8,
{ "Show options to change the name or the associated character or NPC of this design set."u8);
var resetSettings = selector.Selection!.ResetTemporarySettings;
if (ImGui.Checkbox("##resetSettings", ref resetSettings))
manager.ChangeResetSettings(selector.SelectionIndex, resetSettings);
ImUtf8.LabeledHelpMarker("Reset Temporary Settings"u8, var resetSettings = selector.Selection!.ResetTemporarySettings;
"Always reset all temporary settings applied by Glamourer when this automation set is applied, regardless of active designs."u8); if (Im.Checkbox("##resetSettings"u8, ref resetSettings))
} manager.ChangeResetSettings(selector.SelectionIndex, resetSettings);
LunaStyle.DrawAlignedHelpMarkerLabel("Reset Temporary Settings"u8,
"Always reset all temporary settings applied by Glamourer when this automation set is applied, regardless of active designs."u8);
} }
if (config.ShowAutomationSetEditing) if (config.ShowAutomationSetEditing)
@ -118,11 +97,11 @@ public class SetPanel(
var name = _tempName ?? Selection.Name; var name = _tempName ?? Selection.Name;
var flags = selector.IncognitoMode ? InputTextFlags.ReadOnly | InputTextFlags.Password : InputTextFlags.None; var flags = selector.IncognitoMode ? InputTextFlags.ReadOnly | InputTextFlags.Password : InputTextFlags.None;
ImGui.SetNextItemWidth(330 * Im.Style.GlobalScale); Im.Item.SetNextWidthScaled(330);
if (Im.Input.Text("Rename Set##Name"u8, ref name, StringU8.Empty, flags)) if (Im.Input.Text("Rename Set##Name"u8, ref name, StringU8.Empty, flags))
_tempName = name; _tempName = name;
if (ImGui.IsItemDeactivated()) if (Im.Item.Deactivated)
{ {
manager.Rename(selector.SelectionIndex, name); manager.Rename(selector.SelectionIndex, name);
_tempName = null; _tempName = null;
@ -134,11 +113,11 @@ public class SetPanel(
Im.Dummy(Vector2.Zero); Im.Dummy(Vector2.Zero);
Im.Separator(); Im.Separator();
Im.Dummy(Vector2.Zero); Im.Dummy(Vector2.Zero);
DrawDesignTable(); DrawDesignTable();
randomDrawer.Draw(); randomDrawer.Draw();
} }
private void DrawDesignTable() private void DrawDesignTable()
{ {
var (numCheckboxes, numSpacing) = (config.ShowAllAutomatedApplicationRules, config.ShowUnlockedItemWarnings) switch var (numCheckboxes, numSpacing) = (config.ShowAllAutomatedApplicationRules, config.ShowUnlockedItemWarnings) switch
@ -177,17 +156,17 @@ public class SetPanel(
table.SetupColumn("Application"u8, TableColumnFlags.WidthFixed, table.SetupColumn("Application"u8, TableColumnFlags.WidthFixed,
6 * Im.Style.FrameHeight + 10 * Im.Style.GlobalScale); 6 * Im.Style.FrameHeight + 10 * Im.Style.GlobalScale);
else else
table.SetupColumn("Use"u8, TableColumnFlags.WidthFixed, ImGui.CalcTextSize("Use").X); table.SetupColumn("Use"u8, TableColumnFlags.WidthFixed, Im.Font.CalculateSize("Use"u8).X);
} }
else else
{ {
table.SetupColumn("Design / Job Restrictions"u8, TableColumnFlags.WidthFixed, table.SetupColumn("Design / Job Restrictions"u8, TableColumnFlags.WidthFixed,
250 * Im.Style.GlobalScale - (ImGui.GetScrollMaxY() > 0 ? Im.Style.ScrollbarSize : 0)); 250 * Im.Style.GlobalScale - (Im.Scroll.MaximumY > 0 ? Im.Style.ScrollbarSize : 0));
if (config.ShowAllAutomatedApplicationRules) if (config.ShowAllAutomatedApplicationRules)
table.SetupColumn("Application"u8, TableColumnFlags.WidthFixed, table.SetupColumn("Application"u8, TableColumnFlags.WidthFixed,
3 * Im.Style.FrameHeight + 4 * Im.Style.GlobalScale); 3 * Im.Style.FrameHeight + 4 * Im.Style.GlobalScale);
else else
table.SetupColumn("Use"u8, TableColumnFlags.WidthFixed, ImGui.CalcTextSize("Use").X); table.SetupColumn("Use"u8, TableColumnFlags.WidthFixed, Im.Font.CalculateSize("Use"u8).X);
} }
if (singleRow) if (singleRow)
@ -197,51 +176,48 @@ public class SetPanel(
table.SetupColumn(""u8, TableColumnFlags.WidthFixed, 2 * Im.Style.FrameHeight + 4 * Im.Style.GlobalScale); table.SetupColumn(""u8, TableColumnFlags.WidthFixed, 2 * Im.Style.FrameHeight + 4 * Im.Style.GlobalScale);
table.HeaderRow(); table.HeaderRow();
foreach (var (design, idx) in Selection.Designs.WithIndex()) foreach (var (idx, design) in Selection.Designs.Index())
{ {
using var id = ImUtf8.PushId(idx); using var id = Im.Id.Push(idx);
ImGui.TableNextColumn(); table.NextColumn();
var keyValid = config.DeleteDesignModifier.IsActive(); var keyValid = config.DeleteDesignModifier.IsActive();
var tt = keyValid if (ImEx.Icon.Button(LunaStyle.DeleteIcon, "Remove this design from the set."u8, !keyValid))
? "Remove this design from the set."
: $"Remove this design from the set.\nHold {config.DeleteDesignModifier} to remove.";
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), new Vector2(Im.Style.FrameHeight), tt, !keyValid, true))
_endAction = () => manager.DeleteDesign(Selection, idx); _endAction = () => manager.DeleteDesign(Selection, idx);
ImGui.TableNextColumn(); if(!keyValid)
Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} to remove.");
table.NextColumn();
DrawSelectable(idx, design.Design); DrawSelectable(idx, design.Design);
ImGui.TableNextColumn(); table.NextColumn();
DrawRandomEditing(Selection, design, idx); DrawRandomEditing(Selection, design, idx);
designCombo.Draw(Selection, design, idx); designCombo.Draw(Selection, design, idx);
DrawDragDrop(Selection, idx); DrawDragDrop(Selection, idx);
if (singleRow) if (singleRow)
{ {
ImGui.TableNextColumn(); table.NextColumn();
DrawApplicationTypeBoxes(Selection, design, idx, singleRow); DrawApplicationTypeBoxes(Selection, design, idx, singleRow);
ImGui.TableNextColumn(); table.NextColumn();
DrawConditions(design, idx); DrawConditions(design, idx);
} }
else else
{ {
DrawConditions(design, idx); DrawConditions(design, idx);
ImGui.TableNextColumn(); table.NextColumn();
DrawApplicationTypeBoxes(Selection, design, idx, singleRow); DrawApplicationTypeBoxes(Selection, design, idx, singleRow);
} }
if (config.ShowUnlockedItemWarnings) if (config.ShowUnlockedItemWarnings)
{ {
ImGui.TableNextColumn(); table.NextColumn();
DrawWarnings(design); DrawWarnings(design);
} }
} }
ImGui.TableNextColumn(); table.NextColumn();
ImGui.TableNextColumn(); table.DrawFrameColumn("New"u8);
ImUtf8.TextFrameAligned("New"u8); table.NextColumn();
ImGui.TableNextColumn();
designCombo.Draw(Selection, null, -1); designCombo.Draw(Selection, null, -1);
ImGui.TableNextRow(); table.NextRow();
_endAction?.Invoke(); _endAction?.Invoke();
_endAction = null; _endAction = null;
@ -250,7 +226,7 @@ public class SetPanel(
private void DrawSelectable(int idx, IDesignStandIn design) private void DrawSelectable(int idx, IDesignStandIn design)
{ {
var highlight = Rgba32.Transparent; var highlight = Rgba32.Transparent;
var sb = new StringBuilder(); var sb = new StringBuilder();
if (design is Design d) if (design is Design d)
{ {
var count = design.AllLinks(true).Count(); var count = design.AllLinks(true).Count();
@ -277,45 +253,31 @@ public class SetPanel(
using (ImGuiColor.Text.Push(highlight, highlight.IsTransparent)) using (ImGuiColor.Text.Push(highlight, highlight.IsTransparent))
{ {
ImUtf8.Selectable($"#{idx + 1:D2}"); Im.Selectable($"#{idx + 1:D2}");
} }
ImUtf8.HoverTooltip($"{sb}"); Im.Tooltip.OnHover($"{sb}");
DrawDragDrop(Selection, idx); DrawDragDrop(Selection, idx);
} }
private int _tmpGearset = int.MaxValue;
private int _whichIndex = -1;
private void DrawConditions(AutoDesign design, int idx) private void DrawConditions(AutoDesign design, int idx)
{ {
var usingGearset = design.GearsetIndex >= 0; var usingGearset = design.GearsetIndex >= 0;
if (ImUtf8.Button($"{(usingGearset ? "Gearset:" : "Jobs:")}##usingGearset")) if (Im.Button(usingGearset ? "Gearset:##usingGearset"u8 : "Jobs:##usingGearset"u8))
{ {
usingGearset = !usingGearset; usingGearset = !usingGearset;
manager.ChangeGearsetCondition(Selection, idx, (short)(usingGearset ? 0 : -1)); manager.ChangeGearsetCondition(Selection, idx, (short)(usingGearset ? 0 : -1));
} }
ImUtf8.HoverTooltip("Click to switch between Job and Gearset restrictions."u8); Im.Tooltip.OnHover("Click to switch between Job and Gearset restrictions."u8);
ImGui.SameLine(0, Im.Style.ItemInnerSpacing.X); Im.Line.SameInner();
if (usingGearset) if (usingGearset)
{ {
var set = 1 + (_tmpGearset == int.MaxValue || _whichIndex != idx ? design.GearsetIndex : _tmpGearset); Im.Item.SetNextWidthFull();
ImGui.SetNextItemWidth(Im.ContentRegion.Available.X); if (ImEx.InputOnDeactivation.Scalar("##whichGearset"u8, design.GearsetIndex + 1, out var newIndex))
if (ImUtf8.InputScalar("##whichGearset"u8, ref set)) manager.ChangeGearsetCondition(Selection, idx, (short)(Math.Clamp(newIndex, 1, 100) - 1));
{
_whichIndex = idx;
_tmpGearset = Math.Clamp(set, 1, 100);
}
if (ImGui.IsItemDeactivatedAfterEdit())
{
manager.ChangeGearsetCondition(Selection, idx, (short)(_tmpGearset - 1));
_tmpGearset = int.MaxValue;
_whichIndex = -1;
}
} }
else else
{ {
@ -329,7 +291,7 @@ public class SetPanel(
return; return;
randomDrawer.DrawButton(set, designIdx); randomDrawer.DrawButton(set, designIdx);
ImGui.SameLine(0, Im.Style.ItemInnerSpacing.X); Im.Line.SameInner();
} }
private void DrawWarnings(AutoDesign design) private void DrawWarnings(AutoDesign design)
@ -354,12 +316,12 @@ public class SetPanel(
sb.AppendLine($"{item.Name} in {slot.ToName()} slot is not unlocked. Consider obtaining it via gameplay means!"); sb.AppendLine($"{item.Name} in {slot.ToName()} slot is not unlocked. Consider obtaining it via gameplay means!");
} }
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, new Vector2(2 * Im.Style.GlobalScale, 0)); using var style = ImStyleDouble.ItemSpacing.Push(new Vector2(2 * Im.Style.GlobalScale, 0));
var tt = config.UnlockedItemMode var tt = config.UnlockedItemMode
? "\nThese items will be skipped when applied automatically.\n\nTo change this, disable the Obtained Item Mode setting." ? "\nThese items will be skipped when applied automatically.\n\nTo change this, disable the Obtained Item Mode setting."
: string.Empty; : string.Empty;
DrawWarning(sb, config.UnlockedItemMode ? 0xA03030F0 : 0x0, size, tt, "All equipment to be applied is unlocked."); DrawWarning(sb, config.UnlockedItemMode ? 0xA03030F0 : 0x0, size, tt, "All equipment to be applied is unlocked."u8);
sb.Clear(); sb.Clear();
var sb2 = new StringBuilder(); var sb2 = new StringBuilder();
@ -387,37 +349,36 @@ public class SetPanel(
tt = config.UnlockedItemMode tt = config.UnlockedItemMode
? "\nThese customizations will be skipped when applied automatically.\n\nTo change this, disable the Obtained Item Mode setting." ? "\nThese customizations will be skipped when applied automatically.\n\nTo change this, disable the Obtained Item Mode setting."
: string.Empty; : string.Empty;
DrawWarning(sb2, config.UnlockedItemMode ? 0xA03030F0 : 0x0, size, tt, "All customizations to be applied are unlocked."); DrawWarning(sb2, config.UnlockedItemMode ? 0xA03030F0 : 0x0, size, tt, "All customizations to be applied are unlocked."u8);
Im.Line.Same(); Im.Line.Same();
return; return;
static void DrawWarning(StringBuilder sb, uint color, Vector2 size, string suffix, string good) static void DrawWarning(StringBuilder sb, Rgba32 color, Vector2 size, string suffix, ReadOnlySpan<byte> good)
{ {
using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, Im.Style.GlobalScale); using var style = ImStyleSingle.FrameBorderThickness.Push(Im.Style.GlobalScale);
if (sb.Length > 0) if (sb.Length > 0)
{ {
sb.Append(suffix); sb.Append(suffix);
using (_ = ImRaii.PushFont(UiBuilder.IconFont)) using (AwesomeIcon.Font.Push())
{ {
ImGuiUtil.DrawTextButton(FontAwesomeIcon.ExclamationCircle.ToIconString(), size, color); ImEx.TextFramed(LunaStyle.WarningIcon.Span, size, color);
} }
ImUtf8.HoverTooltip($"{sb}"); Im.Tooltip.OnHover($"{sb}");
} }
else else
{ {
ImGuiUtil.DrawTextButton(string.Empty, size, 0); ImEx.TextFramed(StringU8.Empty, size, Rgba32.Transparent);
ImUtf8.HoverTooltip(good); Im.Tooltip.OnHover(good);
} }
} }
} }
private void DrawDragDrop(AutoDesignSet set, int index) private void DrawDragDrop(AutoDesignSet set, int index)
{ {
const string dragDropLabel = "DesignDragDrop"; using (var target = Im.DragDrop.Target())
using (var target = ImUtf8.DragDropTarget())
{ {
if (target.Success && ImGuiUtil.IsDropping(dragDropLabel)) if (target.IsDropping("DesignDragDrop"u8))
{ {
if (_dragIndex >= 0) if (_dragIndex >= 0)
{ {
@ -429,14 +390,14 @@ public class SetPanel(
} }
} }
using (var source = ImUtf8.DragDropSource()) using (var source = Im.DragDrop.Source())
{ {
if (source) if (source)
{ {
ImUtf8.Text($"Moving design #{index + 1:D2}..."); Im.Text($"Moving design #{index + 1:D2}...");
if (ImGui.SetDragDropPayload(dragDropLabel, null, 0)) if (source.SetPayload("DesignDragDrop"u8))
{ {
_dragIndex = index; _dragIndex = index;
selector.DragDesignIndex = index; selector.DragDesignIndex = index;
} }
} }
@ -445,26 +406,25 @@ public class SetPanel(
private void DrawApplicationTypeBoxes(AutoDesignSet set, AutoDesign design, int autoDesignIndex, bool singleLine) private void DrawApplicationTypeBoxes(AutoDesignSet set, AutoDesign design, int autoDesignIndex, bool singleLine)
{ {
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, new Vector2(2 * Im.Style.GlobalScale)); using var style = ImStyleDouble.ItemSpacing.Push(new Vector2(2 * Im.Style.GlobalScale));
var newType = design.Type; var newType = design.Type;
var newTypeInt = (uint)newType;
using (ImStyleBorder.Frame.Push(ColorId.FolderLine.Value())) using (ImStyleBorder.Frame.Push(ColorId.FolderLine.Value()))
{ {
if (ImGui.CheckboxFlags("##all", ref newTypeInt, (uint)ApplicationType.All)) Im.Checkbox("##all"u8, ref newType, ApplicationType.All);
newType = (ApplicationType)newTypeInt;
} }
style.Pop(); style.Pop();
ImUtf8.HoverTooltip("Toggle all application modes at once."u8); Im.Tooltip.OnHover("Toggle all application modes at once."u8);
if (config.ShowAllAutomatedApplicationRules) if (config.ShowAllAutomatedApplicationRules)
{ {
void Box(int idx) void Box(int idx)
{ {
var (type, description) = ApplicationTypeExtensions.Types[idx]; var (type, description) = ApplicationTypeExtensions.Types[idx];
var value = design.Type.HasFlag(type); using var id = Im.Id.Push((uint)type);
if (ImUtf8.Checkbox($"##{(byte)type}", ref value)) var value = design.Type.HasFlag(type);
if (Im.Checkbox(StringU8.Empty, ref value))
newType = value ? newType | type : newType & ~type; newType = value ? newType | type : newType & ~type;
ImUtf8.HoverTooltip(description); Im.Tooltip.OnHover(description);
} }
Im.Line.Same(); Im.Line.Same();
@ -486,29 +446,29 @@ public class SetPanel(
private void DrawIdentifierSelection(int setIndex) private void DrawIdentifierSelection(int setIndex)
{ {
using var id = ImUtf8.PushId("Identifiers"u8); using var id = Im.Id.Push("Identifiers"u8);
identifierDrawer.DrawWorld(130); identifierDrawer.DrawWorld(130);
Im.Line.Same(); Im.Line.Same();
identifierDrawer.DrawName(200 - Im.Style.ItemSpacing.X); identifierDrawer.DrawName(200 - Im.Style.ItemSpacing.X);
identifierDrawer.DrawNpcs(330); identifierDrawer.DrawNpcs(330);
var buttonWidth = new Vector2(165 * Im.Style.GlobalScale - Im.Style.ItemSpacing.X / 2, 0); var buttonWidth = new Vector2(165 * Im.Style.GlobalScale - Im.Style.ItemSpacing.X / 2, 0);
if (ImUtf8.ButtonEx("Set to Character"u8, string.Empty, buttonWidth, !identifierDrawer.CanSetPlayer)) if (ImEx.Button("Set to Character"u8, buttonWidth, StringU8.Empty, !identifierDrawer.CanSetPlayer))
manager.ChangeIdentifier(setIndex, identifierDrawer.PlayerIdentifier); manager.ChangeIdentifier(setIndex, identifierDrawer.PlayerIdentifier);
Im.Line.Same(); Im.Line.Same();
if (ImUtf8.ButtonEx("Set to NPC"u8, string.Empty, buttonWidth, !identifierDrawer.CanSetNpc)) if (ImEx.Button("Set to NPC"u8, buttonWidth, StringU8.Empty, !identifierDrawer.CanSetNpc))
manager.ChangeIdentifier(setIndex, identifierDrawer.NpcIdentifier); manager.ChangeIdentifier(setIndex, identifierDrawer.NpcIdentifier);
if (ImUtf8.ButtonEx("Set to Retainer"u8, string.Empty, buttonWidth, !identifierDrawer.CanSetRetainer)) if (ImEx.Button("Set to Retainer"u8, buttonWidth, StringU8.Empty, !identifierDrawer.CanSetRetainer))
manager.ChangeIdentifier(setIndex, identifierDrawer.RetainerIdentifier); manager.ChangeIdentifier(setIndex, identifierDrawer.RetainerIdentifier);
Im.Line.Same(); Im.Line.Same();
if (ImUtf8.ButtonEx("Set to Mannequin"u8, string.Empty, buttonWidth, !identifierDrawer.CanSetRetainer)) if (ImEx.Button("Set to Mannequin"u8, buttonWidth, StringU8.Empty, !identifierDrawer.CanSetRetainer))
manager.ChangeIdentifier(setIndex, identifierDrawer.MannequinIdentifier); manager.ChangeIdentifier(setIndex, identifierDrawer.MannequinIdentifier);
if (ImUtf8.ButtonEx("Set to Owned NPC"u8, string.Empty, buttonWidth, !identifierDrawer.CanSetOwned)) if (ImEx.Button("Set to Owned NPC"u8, buttonWidth, StringU8.Empty, !identifierDrawer.CanSetOwned))
manager.ChangeIdentifier(setIndex, identifierDrawer.OwnedIdentifier); manager.ChangeIdentifier(setIndex, identifierDrawer.OwnedIdentifier);
} }
private sealed class JobGroupCombo(AutoDesignManager manager, JobService jobs, Logger log) private sealed class JobGroupCombo(AutoDesignManager manager, JobService jobs, OtterGui.Log.Logger log)
: FilterComboCache<JobGroup>(() => jobs.JobGroups.Values.ToList(), MouseWheelType.None, log) : FilterComboCache<JobGroup>(() => jobs.JobGroups.Values.ToList(), MouseWheelType.None, log)
{ {
public void Draw(AutoDesignSet set, AutoDesign design, int autoDesignIndex) public void Draw(AutoDesignSet set, AutoDesign design, int autoDesignIndex)

View file

@ -6,7 +6,7 @@ using Luna;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public sealed class DatFilePanel : IGameDataDrawer public sealed class DatFilePanel(ImportService importService) : IGameDataDrawer
{ {
public ReadOnlySpan<byte> Label public ReadOnlySpan<byte> Label
=> "Character Dat File"u8; => "Character Dat File"u8;
@ -14,7 +14,7 @@ public sealed class DatFilePanel : IGameDataDrawer
public bool Disabled public bool Disabled
=> false; => false;
public sealed class Cache(ImportService importService) : BasicCache(TimeSpan.FromMinutes(10)), IService private sealed class Cache(ImportService importService) : BasicCache(TimeSpan.FromMinutes(10))
{ {
private string _datFilePath = string.Empty; private string _datFilePath = string.Empty;
private DatCharacterFile? _datFile; private DatCharacterFile? _datFile;
@ -48,7 +48,7 @@ public sealed class DatFilePanel : IGameDataDrawer
public void Draw() public void Draw()
{ {
var cache = CacheManager.Instance.GetOrCreateCache<Cache>(Im.Id.Current); var cache = CacheManager.Instance.GetOrCreateCache(Im.Id.Current, () => new Cache(importService));
cache.Draw(); cache.Draw();
} }
} }

View file

@ -32,7 +32,7 @@ public sealed class DebugTab(ServiceManager manager) : ITab<MainTabType>
return; return;
if (Im.Tree.Header("General"u8)) if (Im.Tree.Header("General"u8))
StartTimeTracker.Draw("Timers"u8); StartTimeTracker.Draw("Timers"u8, manager.GetService<StartTimeTracker>());
foreach (var header in _headers) foreach (var header in _headers)
header.Draw(); header.Draw();

View file

@ -7,7 +7,7 @@ using Penumbra.GameData.Gui.Debug;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public sealed class DesignConverterPanel : IGameDataDrawer public sealed class DesignConverterPanel(DesignConverter designConverter) : IGameDataDrawer
{ {
public ReadOnlySpan<byte> Label public ReadOnlySpan<byte> Label
=> "Design Converter"u8; => "Design Converter"u8;
@ -15,7 +15,7 @@ public sealed class DesignConverterPanel : IGameDataDrawer
public bool Disabled public bool Disabled
=> false; => false;
public sealed class Cache(DesignConverter designConverter) : BasicCache(TimeSpan.FromMinutes(10), IManagedCache.DirtyFlags.Clean), IService private sealed class Cache(DesignConverter designConverter) : BasicCache(TimeSpan.FromMinutes(10), IManagedCache.DirtyFlags.Clean), IService
{ {
private StringU8 _clipboardText = StringU8.Empty; private StringU8 _clipboardText = StringU8.Empty;
private StringU8 _clipboardData = StringU8.Empty; private StringU8 _clipboardData = StringU8.Empty;
@ -96,7 +96,7 @@ public sealed class DesignConverterPanel : IGameDataDrawer
public void Draw() public void Draw()
{ {
var cache = CacheManager.Instance.GetOrCreateCache<Cache>(Im.Id.Current); var cache = CacheManager.Instance.GetOrCreateCache(Im.Id.Current, () => new Cache(designConverter));
cache.Draw(); cache.Draw();
} }
} }

View file

@ -1,14 +1,8 @@
using Dalamud.Interface; using Dalamud.Plugin;
using Dalamud.Interface.Utility;
using Dalamud.Plugin;
using Glamourer.Api.Enums; using Glamourer.Api.Enums;
using Glamourer.Api.IpcSubscribers; using Glamourer.Api.IpcSubscribers;
using Dalamud.Bindings.ImGui;
using ImSharp; using ImSharp;
using Luna; using Luna;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Text;
namespace Glamourer.Gui.Tabs.DebugTab.IpcTester; namespace Glamourer.Gui.Tabs.DebugTab.IpcTester;
@ -21,104 +15,100 @@ public class DesignIpcTester(IDalamudPluginInterface pluginInterface) : IUiServi
private uint _key; private uint _key;
private ApplyFlag _flags = ApplyFlagEx.DesignDefault; private ApplyFlag _flags = ApplyFlagEx.DesignDefault;
private Guid? _design; private Guid? _design;
private string _designText = string.Empty;
private GlamourerApiEc _lastError; private GlamourerApiEc _lastError;
public void Draw() public void Draw()
{ {
using var tree = ImRaii.TreeNode("Designs"); using var tree = Im.Tree.Node("Designs"u8);
if (!tree) if (!tree)
return; return;
IpcTesterHelpers.IndexInput(ref _gameObjectIndex); IpcTesterHelpers.IndexInput(ref _gameObjectIndex);
IpcTesterHelpers.KeyInput(ref _key); IpcTesterHelpers.KeyInput(ref _key);
IpcTesterHelpers.NameInput(ref _gameObjectName); IpcTesterHelpers.NameInput(ref _gameObjectName);
ImUtf8.InputText("##designName"u8, ref _designName, "Design Name..."u8); Im.Input.Text("##designName"u8, ref _designName, "Design Name..."u8);
ImGuiUtil.GuidInput("##identifier", "Design Identifier...", string.Empty, ref _design, ref _designText, ImEx.GuidInput("##identifier"u8, ref _design, Im.ContentRegion.Available.X);
Im.ContentRegion.Available.X);
IpcTesterHelpers.DrawFlagInput(ref _flags); IpcTesterHelpers.DrawFlagInput(ref _flags);
using var table = Im.Table.Begin("##table"u8, 2, TableFlags.SizingFixedFit); using var table = Im.Table.Begin("##table"u8, 2, TableFlags.SizingFixedFit);
IpcTesterHelpers.DrawIntro("Last Error"); IpcTesterHelpers.DrawIntro("Last Error"u8);
ImGui.TextUnformatted(_lastError.ToString()); Im.Text($"{_lastError}");
IpcTesterHelpers.DrawIntro(GetDesignList.Label); IpcTesterHelpers.DrawIntro(GetDesignList.LabelU8);
DrawDesignsPopup(); DrawDesignsPopup();
if (ImGui.Button("Get##Designs")) if (Im.Button("Get##Designs"u8))
{ {
_designs = new GetDesignList(pluginInterface).Invoke(); _designs = new GetDesignList(pluginInterface).Invoke();
ImGui.OpenPopup("Designs"); Im.Popup.Open("Designs"u8);
} }
IpcTesterHelpers.DrawIntro(ApplyDesign.Label); IpcTesterHelpers.DrawIntro(ApplyDesign.LabelU8);
if (ImGuiUtil.DrawDisabledButton("Apply##Idx", Vector2.Zero, string.Empty, !_design.HasValue)) if (ImEx.Button("Apply##Idx"u8, Vector2.Zero, StringU8.Empty, !_design.HasValue))
_lastError = new ApplyDesign(pluginInterface).Invoke(_design!.Value, _gameObjectIndex, _key, _flags); _lastError = new ApplyDesign(pluginInterface).Invoke(_design!.Value, _gameObjectIndex, _key, _flags);
IpcTesterHelpers.DrawIntro(ApplyDesignName.Label); IpcTesterHelpers.DrawIntro(ApplyDesignName.LabelU8);
if (ImGuiUtil.DrawDisabledButton("Apply##Name", Vector2.Zero, string.Empty, !_design.HasValue)) if (ImEx.Button("Apply##Name"u8, Vector2.Zero, StringU8.Empty, !_design.HasValue))
_lastError = new ApplyDesignName(pluginInterface).Invoke(_design!.Value, _gameObjectName, _key, _flags); _lastError = new ApplyDesignName(pluginInterface).Invoke(_design!.Value, _gameObjectName, _key, _flags);
IpcTesterHelpers.DrawIntro(GetExtendedDesignData.Label); IpcTesterHelpers.DrawIntro(GetExtendedDesignData.LabelU8);
if (_design.HasValue) if (_design.HasValue)
{ {
var (display, path, color, draw) = new GetExtendedDesignData(pluginInterface).Invoke(_design.Value); var (display, path, color, draw) = new GetExtendedDesignData(pluginInterface).Invoke(_design.Value);
if (path.Length > 0) if (path.Length > 0)
ImUtf8.Text($"{display} ({path}){(draw ? " in QDB"u8 : ""u8)}", color); Im.Text($"{display} ({path}){(draw ? " in QDB"u8 : ""u8)}", color);
else else
ImUtf8.Text("No Data"u8); Im.Text("No Data"u8);
} }
else else
{ {
ImUtf8.Text("No Data"u8); Im.Text("No Data"u8);
} }
IpcTesterHelpers.DrawIntro(GetDesignBase64.Label); IpcTesterHelpers.DrawIntro(GetDesignBase64.LabelU8);
if (ImUtf8.Button("To Clipboard##Base64"u8) && _design.HasValue) if (Im.Button("To Clipboard##Base64"u8) && _design.HasValue)
{ {
var data = new GetDesignBase64(pluginInterface).Invoke(_design.Value); var data = new GetDesignBase64(pluginInterface).Invoke(_design.Value);
ImUtf8.SetClipboardText(data); if (data is not null)
Im.Clipboard.Set(data);
} }
IpcTesterHelpers.DrawIntro(AddDesign.Label); IpcTesterHelpers.DrawIntro(AddDesign.LabelU8);
if (ImUtf8.Button("Add from Clipboard"u8)) if (Im.Button("Add from Clipboard"u8))
try try
{ {
var data = ImUtf8.GetClipboardText(); var data = Im.Clipboard.GetUtf16();
_lastError = new AddDesign(pluginInterface).Invoke(data, _designName, out var newDesign); _lastError = new AddDesign(pluginInterface).Invoke(data, _designName, out var newDesign);
if (_lastError is GlamourerApiEc.Success) if (_lastError is GlamourerApiEc.Success)
{ _design = newDesign;
_design = newDesign;
_designText = newDesign.ToString();
}
} }
catch catch
{ {
_lastError = GlamourerApiEc.UnknownError; _lastError = GlamourerApiEc.UnknownError;
} }
IpcTesterHelpers.DrawIntro(DeleteDesign.Label); IpcTesterHelpers.DrawIntro(DeleteDesign.LabelU8);
if (ImUtf8.Button("Delete##Design"u8) && _design.HasValue) if (Im.Button("Delete##Design"u8) && _design.HasValue)
_lastError = new DeleteDesign(pluginInterface).Invoke(_design.Value); _lastError = new DeleteDesign(pluginInterface).Invoke(_design.Value);
} }
private void DrawDesignsPopup() private void DrawDesignsPopup()
{ {
ImGui.SetNextWindowSize(ImGuiHelpers.ScaledVector2(500, 500)); Im.Window.SetNextSize(ImEx.ScaledVector(500, 500));
using var p = ImRaii.Popup("Designs"); using var p = Im.Popup.Begin("Designs"u8);
if (!p) if (!p)
return; return;
using var table = Im.Table.Begin("Designs"u8, 2, TableFlags.SizingFixedFit); using var table = Im.Table.Begin("Designs"u8, 2, TableFlags.SizingFixedFit);
foreach (var (guid, name) in _designs) foreach (var (guid, name) in _designs)
{ {
ImGuiUtil.DrawTableColumn(name); table.DrawColumn(name);
using var f = Im.Font.PushMono(); using var f = Im.Font.PushMono();
ImGui.TableNextColumn(); table.NextColumn();
ImGuiUtil.CopyOnClickSelectable(guid.ToString()); ImEx.CopyOnClickSelectable($"{guid}");
} }
if (ImGui.Button("Close", -Vector2.UnitX) || !ImGui.IsWindowFocused()) if (Im.Button("Close"u8, Im.ContentRegion.Available with { Y = 0 }) || !Im.Window.Focused())
ImGui.CloseCurrentPopup(); Im.Popup.CloseCurrent();
} }
} }

View file

@ -1,5 +1,4 @@
using Glamourer.Api.Enums; using Glamourer.Api.Enums;
using Dalamud.Bindings.ImGui;
using ImSharp; using ImSharp;
namespace Glamourer.Gui.Tabs.DebugTab.IpcTester; namespace Glamourer.Gui.Tabs.DebugTab.IpcTester;
@ -8,51 +7,50 @@ public static class IpcTesterHelpers
{ {
public static void DrawFlagInput(ref ApplyFlag flags) public static void DrawFlagInput(ref ApplyFlag flags)
{ {
var value = (flags & ApplyFlag.Once) != 0; var value = (flags & ApplyFlag.Once) is not 0;
if (ImGui.Checkbox("Apply Once", ref value)) if (Im.Checkbox("Apply Once"u8, ref value))
flags = value ? flags | ApplyFlag.Once : flags & ~ApplyFlag.Once; flags = value ? flags | ApplyFlag.Once : flags & ~ApplyFlag.Once;
Im.Line.Same(); Im.Line.Same();
value = (flags & ApplyFlag.Equipment) != 0; value = (flags & ApplyFlag.Equipment) is not 0;
if (ImGui.Checkbox("Apply Equipment", ref value)) if (Im.Checkbox("Apply Equipment"u8, ref value))
flags = value ? flags | ApplyFlag.Equipment : flags & ~ApplyFlag.Equipment; flags = value ? flags | ApplyFlag.Equipment : flags & ~ApplyFlag.Equipment;
Im.Line.Same(); Im.Line.Same();
value = (flags & ApplyFlag.Customization) != 0; value = (flags & ApplyFlag.Customization) is not 0;
if (ImGui.Checkbox("Apply Customization", ref value)) if (Im.Checkbox("Apply Customization"u8, ref value))
flags = value ? flags | ApplyFlag.Customization : flags & ~ApplyFlag.Customization; flags = value ? flags | ApplyFlag.Customization : flags & ~ApplyFlag.Customization;
Im.Line.Same(); Im.Line.Same();
value = (flags & ApplyFlag.Lock) != 0; value = (flags & ApplyFlag.Lock) is not 0;
if (ImGui.Checkbox("Lock Actor", ref value)) if (Im.Checkbox("Lock Actor"u8, ref value))
flags = value ? flags | ApplyFlag.Lock : flags & ~ApplyFlag.Lock; flags = value ? flags | ApplyFlag.Lock : flags & ~ApplyFlag.Lock;
} }
public static void IndexInput(ref int index) public static void IndexInput(ref int index)
{ {
ImGui.SetNextItemWidth(Im.ContentRegion.Available.X / 2); Im.Item.SetNextWidth(Im.ContentRegion.Available.X / 2);
ImGui.InputInt("Game Object Index", ref index, 0, 0); Im.Input.Scalar("Game Object Index"u8, ref index);
} }
public static void KeyInput(ref uint key) public static void KeyInput(ref uint key)
{ {
ImGui.SetNextItemWidth(Im.ContentRegion.Available.X / 2); Im.Item.SetNextWidth(Im.ContentRegion.Available.X / 2);
var keyI = (int)key; var keyI = (int)key;
if (ImGui.InputInt("Key", ref keyI, 0, 0)) if (Im.Input.Scalar("Key"u8, ref keyI))
key = (uint)keyI; key = (uint)keyI;
} }
public static void NameInput(ref string name) public static void NameInput(ref string name)
{ {
ImGui.SetNextItemWidth(Im.ContentRegion.Available.X); Im.Item.SetNextWidthFull();
ImGui.InputTextWithHint("##gameObject", "Character Name...", ref name, 64); Im.Input.Text("##gameObject"u8, ref name, "Character Name..."u8);
} }
public static void DrawIntro(string intro) public static void DrawIntro(ReadOnlySpan<byte> intro)
{ {
ImGui.TableNextColumn(); Im.Table.NextColumn();
ImGui.AlignTextToFramePadding(); ImEx.TextFrameAligned(intro);
ImGui.TextUnformatted(intro); Im.Table.NextColumn();
ImGui.TableNextColumn();
} }
} }

View file

@ -1,7 +1,6 @@
using Dalamud.Plugin; using Dalamud.Plugin;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Glamourer.Api.IpcSubscribers; using Glamourer.Api.IpcSubscribers;
using Dalamud.Bindings.ImGui;
using ImSharp; using ImSharp;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
@ -29,15 +28,15 @@ public sealed class IpcTesterPanel(
{ {
_lastUpdate = framework.LastUpdateUTC.AddSeconds(1); _lastUpdate = framework.LastUpdateUTC.AddSeconds(1);
Subscribe(); Subscribe();
ImGui.TextUnformatted(ApiVersion.Label); Im.Text(ApiVersion.LabelU8);
var (major, minor) = new ApiVersion(pluginInterface).Invoke(); var (major, minor) = new ApiVersion(pluginInterface).Invoke();
Im.Line.Same(); Im.Line.Same();
ImGui.TextUnformatted($"({major}.{minor:D4})"); Im.Text($"({major}.{minor:D4})");
ImGui.TextUnformatted(AutoReloadGearEnabled.Label); Im.Text(AutoReloadGearEnabled.LabelU8);
var autoRedraw = new AutoReloadGearEnabled(pluginInterface).Invoke(); var autoRedraw = new AutoReloadGearEnabled(pluginInterface).Invoke();
Im.Line.Same(); Im.Line.Same();
ImGui.TextUnformatted(autoRedraw ? "Enabled" : "Disabled"); Im.Text(autoRedraw ? "Enabled"u8 : "Disabled"u8);
designs.Draw(); designs.Draw();
items.Draw(); items.Draw();

View file

@ -1,11 +1,8 @@
using Dalamud.Plugin; using Dalamud.Plugin;
using Glamourer.Api.Enums; using Glamourer.Api.Enums;
using Glamourer.Api.IpcSubscribers; using Glamourer.Api.IpcSubscribers;
using Dalamud.Bindings.ImGui;
using ImSharp; using ImSharp;
using Luna; using Luna;
using OtterGui;
using OtterGui.Raii;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Gui; using Penumbra.GameData.Gui;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
@ -26,7 +23,7 @@ public class ItemsIpcTester(IDalamudPluginInterface pluginInterface) : IUiServic
public void Draw() public void Draw()
{ {
using var tree = ImRaii.TreeNode("Items"); using var tree = Im.Tree.Node("Items"u8);
if (!tree) if (!tree)
return; return;
@ -37,26 +34,26 @@ public class ItemsIpcTester(IDalamudPluginInterface pluginInterface) : IUiServic
IpcTesterHelpers.DrawFlagInput(ref _flags); IpcTesterHelpers.DrawFlagInput(ref _flags);
using var table = Im.Table.Begin("##table"u8, 2, TableFlags.SizingFixedFit); using var table = Im.Table.Begin("##table"u8, 2, TableFlags.SizingFixedFit);
IpcTesterHelpers.DrawIntro("Last Error"); IpcTesterHelpers.DrawIntro("Last Error"u8);
ImGui.TextUnformatted(_lastError.ToString()); Im.Text($"{_lastError}");
IpcTesterHelpers.DrawIntro(SetItem.Label); IpcTesterHelpers.DrawIntro(SetItem.LabelU8);
if (ImGui.Button("Set##Idx")) if (Im.Button("Set##Idx"u8))
_lastError = new SetItem(pluginInterface).Invoke(_gameObjectIndex, (ApiEquipSlot)_slot, _customItemId.Id, [_stainId.Id], _key, _lastError = new SetItem(pluginInterface).Invoke(_gameObjectIndex, (ApiEquipSlot)_slot, _customItemId.Id, [_stainId.Id], _key,
_flags); _flags);
IpcTesterHelpers.DrawIntro(SetItemName.Label); IpcTesterHelpers.DrawIntro(SetItemName.LabelU8);
if (ImGui.Button("Set##Name")) if (Im.Button("Set##Name"u8))
_lastError = new SetItemName(pluginInterface).Invoke(_gameObjectName, (ApiEquipSlot)_slot, _customItemId.Id, [_stainId.Id], _key, _lastError = new SetItemName(pluginInterface).Invoke(_gameObjectName, (ApiEquipSlot)_slot, _customItemId.Id, [_stainId.Id], _key,
_flags); _flags);
IpcTesterHelpers.DrawIntro(SetBonusItem.Label); IpcTesterHelpers.DrawIntro(SetBonusItem.LabelU8);
if (ImGui.Button("Set##BonusIdx")) if (Im.Button("Set##BonusIdx"u8))
_lastError = new SetBonusItem(pluginInterface).Invoke(_gameObjectIndex, ToApi(_bonusSlot), _customItemId.Id, _key, _lastError = new SetBonusItem(pluginInterface).Invoke(_gameObjectIndex, ToApi(_bonusSlot), _customItemId.Id, _key,
_flags); _flags);
IpcTesterHelpers.DrawIntro(SetBonusItemName.Label); IpcTesterHelpers.DrawIntro(SetBonusItemName.LabelU8);
if (ImGui.Button("Set##BonusName")) if (Im.Button("Set##BonusName"u8))
_lastError = new SetBonusItemName(pluginInterface).Invoke(_gameObjectName, ToApi(_bonusSlot), _customItemId.Id, _key, _lastError = new SetBonusItemName(pluginInterface).Invoke(_gameObjectName, ToApi(_bonusSlot), _customItemId.Id, _key,
_flags); _flags);
} }
@ -65,14 +62,14 @@ public class ItemsIpcTester(IDalamudPluginInterface pluginInterface) : IUiServic
{ {
var tmp = _customItemId.Id; var tmp = _customItemId.Id;
var width = Im.ContentRegion.Available.X / 2; var width = Im.ContentRegion.Available.X / 2;
ImGui.SetNextItemWidth(width); Im.Item.SetNextWidth(width);
if (ImGuiUtil.InputUlong("Custom Item ID", ref tmp)) if (Im.Input.Scalar("Custom Item ID"u8, ref tmp))
_customItemId = tmp; _customItemId = tmp;
EquipSlotCombo.Draw("Equip Slot"u8, StringU8.Empty, ref _slot, width); EquipSlotCombo.Draw("Equip Slot"u8, StringU8.Empty, ref _slot, width);
BonusSlotCombo.Draw("Bonus Slot"u8, StringU8.Empty, ref _bonusSlot, width); BonusSlotCombo.Draw("Bonus Slot"u8, StringU8.Empty, ref _bonusSlot, width);
var value = (int)_stainId.Id; var value = (int)_stainId.Id;
ImGui.SetNextItemWidth(width); Im.Item.SetNextWidth(width);
if (ImGui.InputInt("Stain ID", ref value, 1, 3)) if (Im.Input.Scalar("Stain ID"u8, ref value, 1, 3))
{ {
value = Math.Clamp(value, 0, byte.MaxValue); value = Math.Clamp(value, 0, byte.MaxValue);
_stainId = (StainId)value; _stainId = (StainId)value;

View file

@ -1,7 +1,4 @@
using Dalamud.Bindings.ImGui; using Dalamud.Plugin;
using Dalamud.Interface;
using Dalamud.Interface.Utility;
using Dalamud.Plugin;
using Glamourer.Api.Enums; using Glamourer.Api.Enums;
using Glamourer.Api.Helpers; using Glamourer.Api.Helpers;
using Glamourer.Api.IpcSubscribers; using Glamourer.Api.IpcSubscribers;
@ -10,9 +7,6 @@ using ImSharp;
using Luna; using Luna;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Text;
using Penumbra.GameData.Interop; using Penumbra.GameData.Interop;
using Penumbra.String; using Penumbra.String;
@ -56,11 +50,11 @@ public class StateIpcTester : IUiService, IDisposable
public StateIpcTester(IDalamudPluginInterface pluginInterface) public StateIpcTester(IDalamudPluginInterface pluginInterface)
{ {
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;
AutoRedrawChanged = AutoReloadGearChanged.Subscriber(_pluginInterface, OnAutoRedrawChanged); AutoRedrawChanged = AutoReloadGearChanged.Subscriber(_pluginInterface, OnAutoRedrawChanged);
StateChanged = StateChangedWithType.Subscriber(_pluginInterface, OnStateChanged); StateChanged = StateChangedWithType.Subscriber(_pluginInterface, OnStateChanged);
StateFinalized = Api.IpcSubscribers.StateFinalized.Subscriber(_pluginInterface, OnStateFinalized); StateFinalized = Api.IpcSubscribers.StateFinalized.Subscriber(_pluginInterface, OnStateFinalized);
GPoseChanged = Api.IpcSubscribers.GPoseChanged.Subscriber(_pluginInterface, OnGPoseChange); GPoseChanged = Api.IpcSubscribers.GPoseChanged.Subscriber(_pluginInterface, OnGPoseChange);
AutoRedrawChanged.Disable(); AutoRedrawChanged.Disable();
StateChanged.Disable(); StateChanged.Disable();
StateFinalized.Disable(); StateFinalized.Disable();
@ -77,7 +71,7 @@ public class StateIpcTester : IUiService, IDisposable
public void Draw() public void Draw()
{ {
using var tree = ImRaii.TreeNode("State"); using var tree = Im.Tree.Node("State"u8);
if (!tree) if (!tree)
return; return;
@ -85,162 +79,156 @@ public class StateIpcTester : IUiService, IDisposable
IpcTesterHelpers.KeyInput(ref _key); IpcTesterHelpers.KeyInput(ref _key);
IpcTesterHelpers.NameInput(ref _gameObjectName); IpcTesterHelpers.NameInput(ref _gameObjectName);
IpcTesterHelpers.DrawFlagInput(ref _flags); IpcTesterHelpers.DrawFlagInput(ref _flags);
ImGui.SetNextItemWidth(Im.ContentRegion.Available.X); Im.Item.SetNextWidthFull();
ImGui.InputTextWithHint("##base64", "Base 64 State...", ref _base64State, 2000); Im.Input.Text("##base64"u8, ref _base64State, "Base 64 State..."u8);
using var table = Im.Table.Begin("##table"u8, 2, TableFlags.SizingFixedFit); using var table = Im.Table.Begin("##table"u8, 2, TableFlags.SizingFixedFit);
IpcTesterHelpers.DrawIntro("Last Error"); IpcTesterHelpers.DrawIntro("Last Error"u8);
ImGui.TextUnformatted(_lastError.ToString()); Im.Text($"{_lastError}");
IpcTesterHelpers.DrawIntro("Last Auto Redraw Change"); IpcTesterHelpers.DrawIntro("Last Auto Redraw Change"u8);
ImGui.TextUnformatted($"{_lastAutoRedrawChangeValue} at {_lastAutoRedrawChangeTime.ToLocalTime().TimeOfDay}"); Im.Text($"{_lastAutoRedrawChangeValue} at {_lastAutoRedrawChangeTime.ToLocalTime().TimeOfDay}");
IpcTesterHelpers.DrawIntro("Last State Change"); IpcTesterHelpers.DrawIntro("Last State Change"u8);
PrintChangeName(); PrintChangeName();
IpcTesterHelpers.DrawIntro("Last State Finalization"); IpcTesterHelpers.DrawIntro("Last State Finalization"u8);
PrintFinalizeName(); PrintFinalizeName();
IpcTesterHelpers.DrawIntro("Last GPose Change"); IpcTesterHelpers.DrawIntro("Last GPose Change"u8);
ImGui.TextUnformatted($"{_lastGPoseChangeValue} at {_lastGPoseChangeTime.ToLocalTime().TimeOfDay}"); Im.Text($"{_lastGPoseChangeValue} at {_lastGPoseChangeTime.ToLocalTime().TimeOfDay}");
IpcTesterHelpers.DrawIntro(GetState.Label); IpcTesterHelpers.DrawIntro(GetState.LabelU8);
DrawStatePopup(); DrawStatePopup();
if (ImUtf8.Button("Get##Idx"u8)) if (Im.Button("Get##Idx"u8))
{ {
(_lastError, _state) = new GetState(_pluginInterface).Invoke(_gameObjectIndex, _key); (_lastError, _state) = new GetState(_pluginInterface).Invoke(_gameObjectIndex, _key);
_stateString = _state?.ToString(Formatting.Indented) ?? "No State Available"; _stateString = _state?.ToString(Formatting.Indented) ?? "No State Available";
ImUtf8.OpenPopup("State"u8); Im.Popup.Open("State"u8);
} }
IpcTesterHelpers.DrawIntro(GetStateName.Label); IpcTesterHelpers.DrawIntro(GetStateName.LabelU8);
if (ImUtf8.Button("Get##Name"u8)) if (Im.Button("Get##Name"u8))
{ {
(_lastError, _state) = new GetStateName(_pluginInterface).Invoke(_gameObjectName, _key); (_lastError, _state) = new GetStateName(_pluginInterface).Invoke(_gameObjectName, _key);
_stateString = _state?.ToString(Formatting.Indented) ?? "No State Available"; _stateString = _state?.ToString(Formatting.Indented) ?? "No State Available";
ImUtf8.OpenPopup("State"u8); Im.Popup.Open("State"u8);
} }
IpcTesterHelpers.DrawIntro(GetStateBase64.Label); IpcTesterHelpers.DrawIntro(GetStateBase64.LabelU8);
if (ImUtf8.Button("Get##Base64Idx"u8)) if (Im.Button("Get##Base64Idx"u8))
{ {
(_lastError, _getStateString) = new GetStateBase64(_pluginInterface).Invoke(_gameObjectIndex, _key); (_lastError, _getStateString) = new GetStateBase64(_pluginInterface).Invoke(_gameObjectIndex, _key);
_stateString = _getStateString ?? "No State Available"; _stateString = _getStateString ?? "No State Available";
ImUtf8.OpenPopup("State"u8); Im.Popup.Open("State"u8);
} }
IpcTesterHelpers.DrawIntro(GetStateBase64Name.Label); IpcTesterHelpers.DrawIntro(GetStateBase64Name.LabelU8);
if (ImUtf8.Button("Get##Base64Idx"u8)) if (Im.Button("Get##Base64Idx"u8))
{ {
(_lastError, _getStateString) = new GetStateBase64Name(_pluginInterface).Invoke(_gameObjectName, _key); (_lastError, _getStateString) = new GetStateBase64Name(_pluginInterface).Invoke(_gameObjectName, _key);
_stateString = _getStateString ?? "No State Available"; _stateString = _getStateString ?? "No State Available";
ImUtf8.OpenPopup("State"u8); Im.Popup.Open("State"u8);
} }
IpcTesterHelpers.DrawIntro(ApplyState.Label); IpcTesterHelpers.DrawIntro(ApplyState.LabelU8);
if (ImGuiUtil.DrawDisabledButton("Apply Last##Idx", Vector2.Zero, string.Empty, _state == null)) if (ImEx.Button("Apply Last##Idx"u8, Vector2.Zero, StringU8.Empty, _state is null))
_lastError = new ApplyState(_pluginInterface).Invoke(_state!, _gameObjectIndex, _key, _flags); _lastError = new ApplyState(_pluginInterface).Invoke(_state!, _gameObjectIndex, _key, _flags);
Im.Line.Same(); Im.Line.Same();
if (ImUtf8.Button("Apply Base64##Idx"u8)) if (Im.Button("Apply Base64##Idx"u8))
_lastError = new ApplyState(_pluginInterface).Invoke(_base64State, _gameObjectIndex, _key, _flags); _lastError = new ApplyState(_pluginInterface).Invoke(_base64State, _gameObjectIndex, _key, _flags);
IpcTesterHelpers.DrawIntro(ApplyStateName.Label); IpcTesterHelpers.DrawIntro(ApplyStateName.LabelU8);
if (ImGuiUtil.DrawDisabledButton("Apply Last##Name", Vector2.Zero, string.Empty, _state == null)) if (ImEx.Button("Apply Last##Name"u8, Vector2.Zero, StringU8.Empty, _state is null))
_lastError = new ApplyStateName(_pluginInterface).Invoke(_state!, _gameObjectName, _key, _flags); _lastError = new ApplyStateName(_pluginInterface).Invoke(_state!, _gameObjectName, _key, _flags);
Im.Line.Same(); Im.Line.Same();
if (ImUtf8.Button("Apply Base64##Name"u8)) if (Im.Button("Apply Base64##Name"u8))
_lastError = new ApplyStateName(_pluginInterface).Invoke(_base64State, _gameObjectName, _key, _flags); _lastError = new ApplyStateName(_pluginInterface).Invoke(_base64State, _gameObjectName, _key, _flags);
IpcTesterHelpers.DrawIntro(ReapplyState.Label); IpcTesterHelpers.DrawIntro(ReapplyState.LabelU8);
if (ImUtf8.Button("Reapply##Idx"u8)) if (Im.Button("Reapply##Idx"u8))
_lastError = new ReapplyState(_pluginInterface).Invoke(_gameObjectIndex, _key, _flags); _lastError = new ReapplyState(_pluginInterface).Invoke(_gameObjectIndex, _key, _flags);
IpcTesterHelpers.DrawIntro(ReapplyStateName.Label); IpcTesterHelpers.DrawIntro(ReapplyStateName.LabelU8);
if (ImUtf8.Button("Reapply##Name"u8)) if (Im.Button("Reapply##Name"u8))
_lastError = new ReapplyStateName(_pluginInterface).Invoke(_gameObjectName, _key, _flags); _lastError = new ReapplyStateName(_pluginInterface).Invoke(_gameObjectName, _key, _flags);
IpcTesterHelpers.DrawIntro(RevertState.Label); IpcTesterHelpers.DrawIntro(RevertState.LabelU8);
if (ImUtf8.Button("Revert##Idx"u8)) if (Im.Button("Revert##Idx"u8))
_lastError = new RevertState(_pluginInterface).Invoke(_gameObjectIndex, _key, _flags); _lastError = new RevertState(_pluginInterface).Invoke(_gameObjectIndex, _key, _flags);
IpcTesterHelpers.DrawIntro(RevertStateName.Label); IpcTesterHelpers.DrawIntro(RevertStateName.LabelU8);
if (ImUtf8.Button("Revert##Name"u8)) if (Im.Button("Revert##Name"u8))
_lastError = new RevertStateName(_pluginInterface).Invoke(_gameObjectName, _key, _flags); _lastError = new RevertStateName(_pluginInterface).Invoke(_gameObjectName, _key, _flags);
IpcTesterHelpers.DrawIntro(UnlockState.Label); IpcTesterHelpers.DrawIntro(UnlockState.LabelU8);
if (ImUtf8.Button("Unlock##Idx"u8)) if (Im.Button("Unlock##Idx"u8))
_lastError = new UnlockState(_pluginInterface).Invoke(_gameObjectIndex, _key); _lastError = new UnlockState(_pluginInterface).Invoke(_gameObjectIndex, _key);
IpcTesterHelpers.DrawIntro(UnlockStateName.Label); IpcTesterHelpers.DrawIntro(UnlockStateName.LabelU8);
if (ImUtf8.Button("Unlock##Name"u8)) if (Im.Button("Unlock##Name"u8))
_lastError = new UnlockStateName(_pluginInterface).Invoke(_gameObjectName, _key); _lastError = new UnlockStateName(_pluginInterface).Invoke(_gameObjectName, _key);
IpcTesterHelpers.DrawIntro(UnlockAll.Label); IpcTesterHelpers.DrawIntro(UnlockAll.LabelU8);
if (ImUtf8.Button("Unlock##All"u8)) if (Im.Button("Unlock##All"u8))
_numUnlocked = new UnlockAll(_pluginInterface).Invoke(_key); _numUnlocked = new UnlockAll(_pluginInterface).Invoke(_key);
Im.Line.Same(); Im.Line.Same();
ImGui.TextUnformatted($"Unlocked {_numUnlocked}"); Im.Text($"Unlocked {_numUnlocked}");
IpcTesterHelpers.DrawIntro(RevertToAutomation.Label); IpcTesterHelpers.DrawIntro(RevertToAutomation.LabelU8);
if (ImUtf8.Button("Revert##AutomationIdx"u8)) if (Im.Button("Revert##AutomationIdx"u8))
_lastError = new RevertToAutomation(_pluginInterface).Invoke(_gameObjectIndex, _key, _flags); _lastError = new RevertToAutomation(_pluginInterface).Invoke(_gameObjectIndex, _key, _flags);
IpcTesterHelpers.DrawIntro(RevertToAutomationName.Label); IpcTesterHelpers.DrawIntro(RevertToAutomationName.LabelU8);
if (ImUtf8.Button("Revert##AutomationName"u8)) if (Im.Button("Revert##AutomationName"u8))
_lastError = new RevertToAutomationName(_pluginInterface).Invoke(_gameObjectName, _key, _flags); _lastError = new RevertToAutomationName(_pluginInterface).Invoke(_gameObjectName, _key, _flags);
} }
private void DrawStatePopup() private void DrawStatePopup()
{ {
ImGui.SetNextWindowSize(ImGuiHelpers.ScaledVector2(500, 500)); if (_stateString is null)
if (_stateString == null)
return; return;
using var p = ImUtf8.Popup("State"u8); Im.Window.SetNextSize(ImEx.ScaledVector(500, 500));
using var p = Im.Popup.Begin("State"u8);
if (!p) if (!p)
return; return;
if (ImUtf8.Button("Copy to Clipboard"u8)) if (Im.Button("Copy to Clipboard"u8))
ImUtf8.SetClipboardText(_stateString); Im.Clipboard.Set(_stateString);
if (_stateString[0] is '{') if (_stateString[0] is '{')
{ {
Im.Line.Same(); Im.Line.Same();
if (ImUtf8.Button("Copy as Base64"u8) && _state != null) if (Im.Button("Copy as Base64"u8) && _state is not null)
ImUtf8.SetClipboardText(DesignConverter.ToBase64(_state)); Im.Clipboard.Set(DesignConverter.ToBase64(_state));
} }
using var font = Im.Font.PushMono(); using var font = Im.Font.PushMono();
ImUtf8.TextWrapped(_stateString ?? string.Empty); Im.TextWrapped(_stateString ?? string.Empty);
if (ImUtf8.Button("Close"u8, -Vector2.UnitX) || !ImGui.IsWindowFocused()) if (Im.Button("Close"u8, Im.ContentRegion.Available with { Y = 0 }) || !Im.Window.Focused())
ImGui.CloseCurrentPopup(); Im.Popup.CloseCurrent();
} }
private unsafe void PrintChangeName() private unsafe void PrintChangeName()
{ {
ImUtf8.Text(_lastStateChangeName.Span); Im.Text(_lastStateChangeName.Span);
ImGui.SameLine(0, 0); Im.Line.NoSpacing();
ImUtf8.Text($" ({_lastStateChangeType})"); Im.Text($" ({_lastStateChangeType})");
Im.Line.Same(); Im.Line.Same();
using (Im.Font.PushMono()) Glamourer.Dynamis.DrawPointer(_lastStateChangeActor);
{
ImUtf8.CopyOnClickSelectable($"0x{_lastStateChangeActor:X}");
}
Im.Line.Same(); Im.Line.Same();
ImUtf8.Text($"at {_lastStateChangeTime.ToLocalTime().TimeOfDay}"); Im.Text($"at {_lastStateChangeTime.ToLocalTime().TimeOfDay}");
} }
private unsafe void PrintFinalizeName() private unsafe void PrintFinalizeName()
{ {
ImUtf8.Text(_lastStateFinalizeName.Span); Im.Text(_lastStateFinalizeName.Span);
ImGui.SameLine(0, 0); Im.Line.NoSpacing();
ImUtf8.Text($" ({_lastStateFinalizeType})"); Im.Text($" ({_lastStateFinalizeType})");
Im.Line.Same(); Im.Line.Same();
using (Im.Font.PushMono()) Glamourer.Dynamis.DrawPointer(_lastStateFinalizeActor);
{
ImUtf8.CopyOnClickSelectable($"0x{_lastStateFinalizeActor:X}");
}
Im.Line.Same(); Im.Line.Same();
ImUtf8.Text($"at {_lastStateFinalizeTime.ToLocalTime().TimeOfDay}"); Im.Text($"at {_lastStateFinalizeTime.ToLocalTime().TimeOfDay}");
} }
private void OnAutoRedrawChanged(bool value) private void OnAutoRedrawChanged(bool value)

View file

@ -41,7 +41,7 @@ public sealed class NpcAppearancePanel(
public readonly StringU8 ModelId = new($"{data.ModelId}"); public readonly StringU8 ModelId = new($"{data.ModelId}");
public readonly AwesomeIcon Visor = data.VisorToggled ? LunaStyle.TrueIcon : LunaStyle.FalseIcon; public readonly AwesomeIcon Visor = data.VisorToggled ? LunaStyle.TrueIcon : LunaStyle.FalseIcon;
public readonly StringU8 CustomizeData = new($"{data.Customize}"); public readonly StringU8 CustomizeData = new($"{data.Customize}");
public readonly StringU8 GearData = StringU8.Empty; //new(data.WriteGear()); public readonly StringU8 GearData = new(data.WriteGear());
} }
private sealed class Cache(NpcCustomizeSet npcData, NpcDataFilter filter) : BasicFilterCache<CacheItem>(filter) private sealed class Cache(NpcCustomizeSet npcData, NpcDataFilter filter) : BasicFilterCache<CacheItem>(filter)

View file

@ -1,13 +1,8 @@
using Dalamud.Interface.Utility; using Glamourer.Services;
using Glamourer.Services;
using Glamourer.Unlocks; using Glamourer.Unlocks;
using Dalamud.Bindings.ImGui;
using ImSharp; using ImSharp;
using OtterGui;
using OtterGui.Raii;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
using ImGuiClip = OtterGui.ImGuiClip;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
@ -34,32 +29,29 @@ public sealed class UnlockableItemsPanel(ItemUnlockManager itemUnlocks, ItemMana
table.SetupColumn("Unlock"u8, TableColumnFlags.WidthFixed, 120 * Im.Style.GlobalScale); table.SetupColumn("Unlock"u8, TableColumnFlags.WidthFixed, 120 * Im.Style.GlobalScale);
table.SetupColumn("Criteria"u8, TableColumnFlags.WidthStretch); table.SetupColumn("Criteria"u8, TableColumnFlags.WidthStretch);
ImGui.TableNextColumn(); using var clip = new Im.ListClipper(itemUnlocks.Unlockable.Count, Im.Style.TextHeightWithSpacing);
var skips = ImGuiClip.GetNecessarySkips(Im.Style.TextHeightWithSpacing); foreach (var (id, timestamp) in clip.Iterate(itemUnlocks.Unlockable))
ImGui.TableNextRow();
var remainder = ImGuiClip.ClippedDraw(itemUnlocks.Unlockable, skips, t =>
{ {
ImGuiUtil.DrawTableColumn(t.Key.ToString()); table.DrawColumn($"{id}");
if (items.ItemData.TryGetValue(t.Key, EquipSlot.MainHand, out var equip)) if (items.ItemData.TryGetValue(id, EquipSlot.MainHand, out var equip))
{ {
ImGuiUtil.DrawTableColumn(equip.Name); table.DrawColumn(equip.Name);
ImGuiUtil.DrawTableColumn(equip.Type.ToName()); table.DrawColumn(equip.Type.ToName());
ImGuiUtil.DrawTableColumn(equip.Weapon().ToString()); table.DrawColumn($"{equip.Weapon()}");
} }
else else
{ {
ImGui.TableNextColumn(); table.NextColumn();
ImGui.TableNextColumn(); table.NextColumn();
ImGui.TableNextColumn(); table.NextColumn();
} }
ImGuiUtil.DrawTableColumn(itemUnlocks.IsUnlocked(t.Key, out var time) table.DrawColumn(itemUnlocks.IsUnlocked(id, out var time)
? time == DateTimeOffset.MinValue ? time == DateTimeOffset.MinValue
? "Always" ? "Always"u8
: time.LocalDateTime.ToString("g") : $"{time.LocalDateTime:g}"
: "Never"); : "Never"u8);
ImGuiUtil.DrawTableColumn(t.Value.ToString()); table.DrawColumn($"{timestamp}");
}, itemUnlocks.Unlockable.Count); }
ImGuiClip.DrawEndDummy(remainder, Im.Style.TextHeight);
} }
} }

View file

@ -1,13 +1,9 @@
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Utility;
using Glamourer.Automation; using Glamourer.Automation;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Designs.Links; using Glamourer.Designs.Links;
using Dalamud.Bindings.ImGui;
using ImSharp; using ImSharp;
using Luna; using Luna;
using OtterGui;
using OtterGui.Raii;
namespace Glamourer.Gui.Tabs.DesignTab; namespace Glamourer.Gui.Tabs.DesignTab;
@ -29,10 +25,10 @@ public class DesignLinkDrawer(
if (!h.Alive) if (!h.Alive)
return; return;
ImGuiUtil.HoverTooltip( Im.Tooltip.OnHover(
"Design links are links to other designs that will be applied to characters or during automation according to the rules set.\n" "Design links are links to other designs that will be applied to characters or during automation according to the rules set.\n"u8
+ "They apply from top to bottom just like automated design sets, so anything set by an earlier design will not not be set again by later designs, and order is important.\n" + "They apply from top to bottom just like automated design sets, so anything set by an earlier design will not not be set again by later designs, and order is important.\n"u8
+ "If a linked design links to other designs, they will also be applied, so circular links are prohibited. "); + "If a linked design links to other designs, they will also be applied, so circular links are prohibited."u8);
if (!h) if (!h)
return; return;
@ -83,68 +79,67 @@ public class DesignLinkDrawer(
table.SetupColumn("Detail"u8, TableColumnFlags.WidthFixed, table.SetupColumn("Detail"u8, TableColumnFlags.WidthFixed,
6 * Im.Style.FrameHeight + 5 * Im.Style.ItemInnerSpacing.X); 6 * Im.Style.FrameHeight + 5 * Im.Style.ItemInnerSpacing.X);
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Im.Style.ItemInnerSpacing); using var style = ImStyleDouble.ItemSpacing.Push(Im.Style.ItemInnerSpacing);
DrawSubList(selector.Selected!.Links.Before, LinkOrder.Before); DrawSubList(table, selector.Selected!.Links.Before, LinkOrder.Before);
DrawSelf(); DrawSelf(table);
DrawSubList(selector.Selected!.Links.After, LinkOrder.After); DrawSubList(table, selector.Selected!.Links.After, LinkOrder.After);
DrawNew(); DrawNew(table);
MoveLink(); MoveLink();
} }
private void DrawSelf() private void DrawSelf(in Im.TableDisposable table)
{ {
using var id = Im.Id.Push((int)LinkOrder.Self); using var id = Im.Id.Push((int)LinkOrder.Self);
ImGui.TableNextColumn(); table.NextColumn();
var color = colorManager.GetColor(selector.Selected!); var color = colorManager.GetColor(selector.Selected!);
using (ImRaii.PushFont(UiBuilder.IconFont)) using (AwesomeIcon.Font.Push())
{ {
using var c = ImGuiColor.Text.Push(color); using var c = ImGuiColor.Text.Push(color);
ImGui.AlignTextToFramePadding(); Im.Cursor.FrameAlign();
ImGuiUtil.RightAlign(FontAwesomeIcon.ArrowRightLong.ToIconString()); ImEx.TextRightAligned(FontAwesomeIcon.ArrowRightLong.Icon().Span);
} }
ImGui.TableNextColumn(); table.NextColumn();
using (ImGuiColor.Text.Push(color)) using (ImGuiColor.Text.Push(color))
{ {
ImGui.AlignTextToFramePadding(); Im.Cursor.FrameAlign();
ImGui.Selectable(selector.IncognitoMode ? selector.Selected!.Incognito : selector.Selected!.Name.Text); Im.Selectable(selector.IncognitoMode ? selector.Selected!.Incognito : selector.Selected!.Name.Text);
} }
ImGuiUtil.HoverTooltip("Current Design"); Im.Tooltip.OnHover("Current Design"u8);
DrawDragDrop(selector.Selected!, LinkOrder.Self, 0); DrawDragDrop(selector.Selected!, LinkOrder.Self, 0);
ImGui.TableNextColumn(); table.NextColumn();
using (ImRaii.PushFont(UiBuilder.IconFont)) using (AwesomeIcon.Font.Push())
{ {
using var c = ImGuiColor.Text.Push(color); using var c = ImGuiColor.Text.Push(color);
ImGui.AlignTextToFramePadding(); Im.Cursor.FrameAlign();
ImGui.TextUnformatted(FontAwesomeIcon.ArrowLeftLong.ToIconString()); ImEx.TextRightAligned(FontAwesomeIcon.ArrowLeftLong.Icon().Span);
} }
} }
private void DrawSubList(IReadOnlyList<DesignLink> list, LinkOrder order) private void DrawSubList(in Im.TableDisposable table, IReadOnlyList<DesignLink> list, LinkOrder order)
{ {
using var id = Im.Id.Push((int)order); using var id = Im.Id.Push((int)order);
var buttonSize = new Vector2(Im.Style.FrameHeight);
for (var i = 0; i < list.Count; ++i) for (var i = 0; i < list.Count; ++i)
{ {
id.Push(i); id.Push(i);
ImGui.TableNextColumn(); table.NextColumn();
var delete = ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), buttonSize, "Delete this link.", false, true); var delete = ImEx.Icon.Button(LunaStyle.DeleteIcon, "Delete this link."u8);
var (design, flags) = list[i]; var (design, flags) = list[i];
ImGui.TableNextColumn(); table.NextColumn();
using (ImGuiColor.Text.Push(colorManager.GetColor(design))) using (ImGuiColor.Text.Push(colorManager.GetColor(design)))
{ {
ImGui.AlignTextToFramePadding(); Im.Cursor.FrameAlign();
ImGui.Selectable(selector.IncognitoMode ? design.Incognito : design.Name.Text); Im.Selectable(selector.IncognitoMode ? design.Incognito : design.Name.Text);
} }
DrawDragDrop(design, order, i); DrawDragDrop(design, order, i);
ImGui.TableNextColumn(); table.NextColumn();
ImGui.AlignTextToFramePadding(); Im.Cursor.FrameAlign();
DrawApplicationBoxes(i, order, flags); DrawApplicationBoxes(i, order, flags);
if (delete) if (delete)
@ -152,13 +147,12 @@ public class DesignLinkDrawer(
} }
} }
private void DrawNew() private void DrawNew(in Im.TableDisposable table)
{ {
var buttonSize = new Vector2(Im.Style.FrameHeight); table.NextColumn();
ImGui.TableNextColumn(); table.NextColumn();
ImGui.TableNextColumn();
combo.Draw(Im.ContentRegion.Available.X); combo.Draw(Im.ContentRegion.Available.X);
ImGui.TableNextColumn(); table.NextColumn();
string ttBefore, ttAfter; string ttBefore, ttAfter;
bool canAddBefore, canAddAfter; bool canAddBefore, canAddAfter;
var design = combo.Design as Design; var design = combo.Design as Design;
@ -179,35 +173,32 @@ public class DesignLinkDrawer(
: $"Can not add a link to {design.Name}:\n{error}"; : $"Can not add a link to {design.Name}:\n{error}";
} }
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.ArrowCircleUp.ToIconString(), buttonSize, ttBefore, !canAddBefore, true)) if (ImEx.Icon.Button(FontAwesomeIcon.ArrowCircleUp.Icon(), ttBefore, !canAddBefore))
{ {
linkManager.AddDesignLink(selector.Selected!, design!, LinkOrder.Before); linkManager.AddDesignLink(selector.Selected!, design!, LinkOrder.Before);
linkManager.MoveDesignLink(selector.Selected!, selector.Selected!.Links.Before.Count - 1, LinkOrder.Before, 0, LinkOrder.Before); linkManager.MoveDesignLink(selector.Selected!, selector.Selected!.Links.Before.Count - 1, LinkOrder.Before, 0, LinkOrder.Before);
} }
Im.Line.Same(); Im.Line.Same();
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.ArrowCircleDown.ToIconString(), buttonSize, ttAfter, !canAddAfter, true)) if (ImEx.Icon.Button(FontAwesomeIcon.ArrowCircleUp.Icon(), ttAfter, !canAddAfter))
linkManager.AddDesignLink(selector.Selected!, design!, LinkOrder.After); linkManager.AddDesignLink(selector.Selected!, design!, LinkOrder.After);
} }
private void DrawDragDrop(Design design, LinkOrder order, int index) private void DrawDragDrop(Design design, LinkOrder order, int index)
{ {
using (var source = ImRaii.DragDropSource()) using (var source = Im.DragDrop.Source())
{ {
if (source) if (source)
{ {
ImGui.SetDragDropPayload("DraggingLink", null, 0); source.SetPayload("DraggingLink"u8);
ImGui.TextUnformatted($"Reordering {design.Name}..."); Im.Text($"Reordering {design.Name}...");
_dragDropIndex = index; _dragDropIndex = index;
_dragDropOrder = order; _dragDropOrder = order;
} }
} }
using var target = ImRaii.DragDropTarget(); using var target = Im.DragDrop.Target();
if (!target) if (!target.IsDropping("DraggingLink"u8))
return;
if (!ImGuiUtil.IsDropping("DraggingLink"))
return; return;
_dragDropTargetIndex = index; _dragDropTargetIndex = index;
@ -216,15 +207,13 @@ public class DesignLinkDrawer(
private void DrawApplicationBoxes(int idx, LinkOrder order, ApplicationType current) private void DrawApplicationBoxes(int idx, LinkOrder order, ApplicationType current)
{ {
var newType = current; var newType = current;
var newTypeInt = (uint)newType;
using (ImStyleBorder.Frame.Push(ColorId.FolderLine.Value())) using (ImStyleBorder.Frame.Push(ColorId.FolderLine.Value()))
{ {
if (ImGui.CheckboxFlags("##all", ref newTypeInt, (uint)ApplicationType.All)) Im.Checkbox("##all"u8, ref newType, ApplicationType.All);
newType = (ApplicationType)newTypeInt;
} }
ImGuiUtil.HoverTooltip("Toggle all application modes at once."); Im.Tooltip.OnHover("Toggle all application modes at once."u8);
Im.Line.Same(); Im.Line.Same();
Box(0); Box(0);
@ -244,10 +233,11 @@ public class DesignLinkDrawer(
void Box(int i) void Box(int i)
{ {
var (applicationType, description) = ApplicationTypeExtensions.Types[i]; var (applicationType, description) = ApplicationTypeExtensions.Types[i];
var value = current.HasFlag(applicationType); using var id = Im.Id.Push((uint)applicationType);
if (ImGui.Checkbox($"##{(byte)applicationType}", ref value)) var value = current.HasFlag(applicationType);
if (Im.Checkbox(StringU8.Empty, ref value))
newType = value ? newType | applicationType : newType & ~applicationType; newType = value ? newType | applicationType : newType & ~applicationType;
ImGuiUtil.HoverTooltip(description); Im.Tooltip.OnHover(description);
} }
} }
} }

View file

@ -1,11 +1,8 @@
using Dalamud.Bindings.ImGui; using Dalamud.Interface;
using Dalamud.Interface;
using Glamourer.Interop.Penumbra; using Glamourer.Interop.Penumbra;
using Glamourer.Services; using Glamourer.Services;
using ImSharp; using ImSharp;
using Luna; using Luna;
using OtterGui;
using OtterGui.Raii;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.GameData.Interop; using Penumbra.GameData.Interop;
@ -26,10 +23,10 @@ public class CollectionOverrideDrawer(
public void Draw() public void Draw()
{ {
using var header = ImRaii.CollapsingHeader("Collection Overrides"); using var header = Im.Tree.HeaderId("Collection Overrides"u8);
ImGuiUtil.HoverTooltip( Im.Tooltip.OnHover(
"Here you can set up overrides for Penumbra collections that should have their settings changed when automatically applying mod settings from a design.\n" "Here you can set up overrides for Penumbra collections that should have their settings changed when automatically applying mod settings from a design.\n"u8
+ "Instead of the collection associated with the overridden character, the overridden collection will be manipulated."); + "Instead of the collection associated with the overridden character, the overridden collection will be manipulated."u8);
if (!header) if (!header)
return; return;
@ -37,46 +34,45 @@ public class CollectionOverrideDrawer(
if (!table) if (!table)
return; return;
var buttonSize = new Vector2(Im.Style.FrameHeight); table.SetupColumn("buttons"u8, TableColumnFlags.WidthFixed, Im.Style.FrameHeight);
table.SetupColumn("buttons"u8, TableColumnFlags.WidthFixed, buttonSize.X);
table.SetupColumn("identifiers"u8, TableColumnFlags.WidthStretch, 0.35f); table.SetupColumn("identifiers"u8, TableColumnFlags.WidthStretch, 0.35f);
table.SetupColumn("collections"u8, TableColumnFlags.WidthStretch, 0.4f); table.SetupColumn("collections"u8, TableColumnFlags.WidthStretch, 0.4f);
table.SetupColumn("name"u8, TableColumnFlags.WidthStretch, 0.25f); table.SetupColumn("name"u8, TableColumnFlags.WidthStretch, 0.25f);
for (var i = 0; i < collectionOverrides.Overrides.Count; ++i) for (var i = 0; i < collectionOverrides.Overrides.Count; ++i)
DrawCollectionRow(ref i, buttonSize); DrawCollectionRow(table, ref i);
DrawNewOverride(buttonSize); DrawNewOverride(table);
} }
private void DrawCollectionRow(ref int idx, Vector2 buttonSize) private void DrawCollectionRow(in Im.TableDisposable table, ref int idx)
{ {
using var id = Im.Id.Push(idx); using var id = Im.Id.Push(idx);
var (exists, actor, collection, name) = collectionOverrides.Fetch(idx); var (exists, actor, collection, name) = collectionOverrides.Fetch(idx);
ImGui.TableNextColumn(); table.NextColumn();
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), buttonSize, "Delete this override.", false, true)) if (ImEx.Icon.Button(LunaStyle.DeleteIcon, "Delete this override."u8))
collectionOverrides.DeleteOverride(idx--); collectionOverrides.DeleteOverride(idx--);
ImGui.TableNextColumn(); table.NextColumn();
DrawActorIdentifier(idx, actor); DrawActorIdentifier(idx, actor);
ImGui.TableNextColumn(); table.NextColumn();
if (combo.Draw("##collection", name, $"Select the overriding collection. Current GUID:", Im.ContentRegion.Available.X, if (combo.Draw("##collection", name, "Select the overriding collection. Current GUID:", Im.ContentRegion.Available.X,
Im.Style.TextHeight)) Im.Style.TextHeight))
{ {
var (guid, _, newName) = combo.CurrentSelection; var (guid, _, newName) = combo.CurrentSelection;
collectionOverrides.ChangeOverride(idx, guid, newName); collectionOverrides.ChangeOverride(idx, guid, newName);
} }
if (ImGui.IsItemHovered()) if (Im.Item.Hovered())
{ {
using var tt = ImRaii.Tooltip(); using var tt = Im.Tooltip.Begin();
using var font = Im.Font.PushMono(); using var font = Im.Font.PushMono();
ImGui.TextUnformatted($" {collection}"); Im.Text($" {collection}");
} }
ImGui.TableNextColumn(); table.NextColumn();
DrawCollectionName(exists, collection, name); DrawCollectionName(exists, collection, name);
} }
@ -84,64 +80,64 @@ public class CollectionOverrideDrawer(
{ {
if (!exists) if (!exists)
{ {
ImGui.TextUnformatted("<Does not Exist>"); Im.Text("<Does not Exist>"u8);
if (!ImGui.IsItemHovered()) if (!Im.Item.Hovered())
return; return;
using var tt1 = ImRaii.Tooltip(); using var tt1 = Im.Tooltip.Begin();
ImGui.TextUnformatted($"The design {name} with the GUID"); Im.Text($"The design {name} with the GUID");
using (Im.Font.PushMono()) using (Im.Font.PushMono())
{ {
ImGui.TextUnformatted($" {collection}"); Im.Text($" {collection}");
} }
ImGui.TextUnformatted("does not exist in Penumbra."); Im.Text("does not exist in Penumbra."u8);
return; return;
} }
ImGui.TextUnformatted(config.Ephemeral.IncognitoMode ? collection.ToString()[..8] : name); Im.Text(config.Ephemeral.IncognitoMode ? collection.ToString()[..8] : name);
if (!ImGui.IsItemHovered()) if (!Im.Item.Hovered())
return; return;
using var tt2 = ImRaii.Tooltip(); using var tt2 = Im.Tooltip.Begin();
using var f = Im.Font.PushMono(); using var f = Im.Font.PushMono();
ImGui.TextUnformatted(collection.ToString()); Im.Text($"{collection}");
} }
private void DrawActorIdentifier(int idx, ActorIdentifier actor) private void DrawActorIdentifier(int idx, ActorIdentifier actor)
{ {
ImGui.Selectable(config.Ephemeral.IncognitoMode ? actor.Incognito(null) : actor.ToString()); Im.Selectable(config.Ephemeral.IncognitoMode ? actor.Incognito(null) : actor.ToString());
using (var target = ImRaii.DragDropTarget()) using (var target = Im.DragDrop.Target())
{ {
if (target.Success && ImGuiUtil.IsDropping("DraggingOverride")) if (target.IsDropping("DraggingOverride"u8))
{ {
collectionOverrides.MoveOverride(_dragDropIndex, idx); collectionOverrides.MoveOverride(_dragDropIndex, idx);
_dragDropIndex = -1; _dragDropIndex = -1;
} }
} }
using (var source = ImRaii.DragDropSource()) using (var source = Im.DragDrop.Source())
{ {
if (source) if (source)
{ {
ImGui.SetDragDropPayload("DraggingOverride", null, 0); source.SetPayload("DraggingOverride"u8);
ImGui.TextUnformatted($"Reordering Override #{idx + 1}..."); Im.Text($"Reordering Override #{idx + 1}...");
_dragDropIndex = idx; _dragDropIndex = idx;
} }
} }
} }
private void DrawNewOverride(Vector2 buttonSize) private void DrawNewOverride(in Im.TableDisposable table)
{ {
var (currentId, currentName) = penumbra.CurrentCollection; var (currentId, currentName) = penumbra.CurrentCollection;
ImGui.TableNextColumn(); table.NextColumn();
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.PersonCirclePlus.ToIconString(), buttonSize, "Add override for current player.", if (ImEx.Icon.Button(FontAwesomeIcon.PersonCirclePlus.Icon(), "Add override for current player."u8,
!objects.Player.Valid && currentId != Guid.Empty, true)) !objects.Player.Valid && currentId != Guid.Empty))
collectionOverrides.AddOverride([objects.PlayerData.Identifier], currentId, currentName); collectionOverrides.AddOverride([objects.PlayerData.Identifier], currentId, currentName);
ImGui.TableNextColumn(); table.NextColumn();
ImGui.SetNextItemWidth(Im.ContentRegion.Available.X); Im.Item.SetNextWidthFull();
if (ImGui.InputTextWithHint("##newActor", "New Identifier...", ref _newIdentifier, 80)) if (Im.Input.Text("##newActor"u8, ref _newIdentifier, "New Identifier..."u8))
try try
{ {
_identifiers = actors.FromUserString(_newIdentifier, false); _identifiers = actors.FromUserString(_newIdentifier, false);
@ -154,22 +150,17 @@ public class CollectionOverrideDrawer(
var tt = _identifiers.Any(i => i.IsValid) var tt = _identifiers.Any(i => i.IsValid)
? $"Add a new override for {_identifiers.First(i => i.IsValid)}." ? $"Add a new override for {_identifiers.First(i => i.IsValid)}."
: _newIdentifier.Length == 0 : _newIdentifier.Length is 0
? "Please enter an identifier string first." ? "Please enter an identifier string first."
: $"The identifier string {_newIdentifier} does not result in a valid identifier{(_exception == null ? "." : $":\n\n{_exception?.Message}")}"; : $"The identifier string {_newIdentifier} does not result in a valid identifier{(_exception == null ? "." : $":\n\n{_exception?.Message}")}";
ImGui.TableNextColumn(); table.NextColumn();
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), buttonSize, tt, tt[0] is not 'A', true)) if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, tt, tt[0] is not 'A'))
collectionOverrides.AddOverride(_identifiers, currentId, currentName); collectionOverrides.AddOverride(_identifiers, currentId, currentName);
ImGui.SameLine(0, Im.Style.ItemInnerSpacing.X); Im.Line.SameInner();
using (ImRaii.PushFont(UiBuilder.IconFont)) ImEx.Icon.DrawAligned(LunaStyle.InfoIcon, ImGuiColor.TextDisabled.Get());
{ if (Im.Item.Hovered())
using var color = ImGuiColor.Text.Push(Im.Style[ImGuiColor.TextDisabled]);
ImGui.TextUnformatted(FontAwesomeIcon.InfoCircle.ToIconString());
}
if (ImGui.IsItemHovered())
ActorIdentifierFactory.WriteUserStringTooltip(false); ActorIdentifierFactory.WriteUserStringTooltip(false);
} }
} }

View file

@ -42,7 +42,7 @@ public static class UiHelpers
public static void DrawIcon(this EquipItem item, TextureService textures, Vector2 size, BonusItemFlag slot) public static void DrawIcon(this EquipItem item, TextureService textures, Vector2 size, BonusItemFlag slot)
{ {
var isEmpty = item.PrimaryId.Id == 0; var isEmpty = item.PrimaryId.Id is 0;
var (ptr, textureSize, empty) = textures.GetIcon(item, slot); var (ptr, textureSize, empty) = textures.GetIcon(item, slot);
if (empty) if (empty)
{ {

View file

@ -11,7 +11,7 @@ namespace Glamourer.Interop.Material;
public unsafe class DirectXService(IFramework framework) : IService public unsafe class DirectXService(IFramework framework) : IService
{ {
private readonly object _lock = new(); private readonly Lock _lock = new();
private readonly ConcurrentDictionary<nint, (DateTime Update, ColorTable.Table Table)> _textures = []; private readonly ConcurrentDictionary<nint, (DateTime Update, ColorTable.Table Table)> _textures = [];
/// <summary> Generate a color table the way the game does inside the original texture, and release the original. </summary> /// <summary> Generate a color table the way the game does inside the original texture, and release the original. </summary>

View file

@ -27,7 +27,6 @@ public sealed unsafe class PrepareColorSet
: base("Prepare Color Set ") : base("Prepare Color Set ")
{ {
_updateColorSets = updateColorSets; _updateColorSets = updateColorSets;
hooks.Provider.InitializeFromAttributes(this);
_task = hooks.CreateHook<Delegate>(Name, Sigs.PrepareColorSet, Detour, true); _task = hooks.CreateHook<Delegate>(Name, Sigs.PrepareColorSet, Detour, true);
} }
@ -36,6 +35,12 @@ public sealed unsafe class PrepareColorSet
public nint Address public nint Address
=> (nint)CharacterBase.MemberFunctionPointers.Destroy; => (nint)CharacterBase.MemberFunctionPointers.Destroy;
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
_task.Result.Dispose();
}
public void Enable() public void Enable()
=> _task.Result.Enable(); => _task.Result.Enable();

2
Luna

@ -1 +1 @@
Subproject commit 2cc9a03ba52a781f474d1b14d5b8c616fa719284 Subproject commit 6235cc8b4d0196c2545bf39834265fb4e0939b08

@ -1 +1 @@
Subproject commit 478febd4ed9af42055ce7396f69cec0334bc4140 Subproject commit bdbf134934238c7af53aa8625467bd5ad580d6f6