Replace all occurences of ImGuiCol.

This commit is contained in:
Ottermandias 2025-10-20 22:41:29 +02:00
parent a4302c9145
commit 74d35870e2
46 changed files with 1586 additions and 1475 deletions

2
Luna

@ -1 +1 @@
Subproject commit 1ffa8c5de118f94b609f7d6352e3b63de463398c Subproject commit ec5cc05211c5083f276e32816d8c3eb8c09d04b4

@ -1 +1 @@
Subproject commit 3a9406bc634228cc0815ddb6fe5e20419cafb864 Subproject commit 182cca56a49411430233d73d7a8a6bb3d983f8f0

View file

@ -54,8 +54,8 @@ public static class FeatureChecker
const int numButtons = 5; const int numButtons = 5;
var innerSpacing = ImGui.GetStyle().ItemInnerSpacing; var innerSpacing = ImGui.GetStyle().ItemInnerSpacing;
var size = new Vector2((width - (numButtons - 1) * innerSpacing.X) / numButtons, 0); var size = new Vector2((width - (numButtons - 1) * innerSpacing.X) / numButtons, 0);
var buttonColor = ImGui.GetColorU32(ImGuiCol.FrameBg); var buttonColor = Im.Style[ImGuiColor.FrameBackground];
var textColor = ImGui.GetColorU32(ImGuiCol.TextDisabled); var textColor = Im.Style[ImGuiColor.TextDisabled];
using (var style = ImStyleBorder.Frame.Push(ColorId.FolderLine.Value(), 0) using (var style = ImStyleBorder.Frame.Push(ColorId.FolderLine.Value(), 0)
.Push(ImStyleDouble.ItemSpacing, innerSpacing) .Push(ImStyleDouble.ItemSpacing, innerSpacing)
.Push(ImGuiColor.Button, buttonColor) .Push(ImGuiColor.Button, buttonColor)

View file

@ -7,6 +7,103 @@ using FileSystemChangeType = OtterGui.Filesystem.FileSystemChangeType;
namespace Penumbra.Mods.Manager; namespace Penumbra.Mods.Manager;
//public sealed class ModFileSystem2 : BaseFileSystem
//{
// private readonly Configuration _config;
// private readonly SaveService _saveService;
// public ModFileSystem2(FileSystemChanged @event, DataNodePathChange dataChangeEvent, Configuration config, SaveService saveService, IComparer<ReadOnlySpan<char>>? comparer = null)
// : base(@event, dataChangeEvent, comparer)
// {
// _config = config;
// _saveService = saveService;
// }
//
// public void Dispose()
// {
// _communicator.ModPathChanged.Unsubscribe(OnModPathChange);
// _communicator.ModDiscoveryFinished.Unsubscribe(Reload);
// _communicator.ModDataChanged.Unsubscribe(OnModDataChange);
// }
//
// // Save the filesystem on every filesystem change except full reloading.
// private void OnChange(FileSystemChangeType type, IPath _1, IPath? _2, IPath? _3)
// {
// if (type != FileSystemChangeType.Reload)
// _saveService.DelaySave(this);
// }
//
// // Update sort order when defaulted mod names change.
// private void OnModDataChange(in ModDataChanged.Arguments arguments)
// {
// if (!arguments.Type.HasFlag(ModDataChangeType.Name) || arguments.OldName == null || !TryGetValue(arguments.Mod, out var leaf))
// return;
//
// var old = Extensions.FixName(arguments.OldName);
// if (old == leaf.Name || Extensions.IsDuplicateName(leaf.Name, out var baseName, out _) && baseName == old)
// RenameWithDuplicates(leaf, arguments.Mod.Name);
// }
//
// // Update the filesystem if a mod has been added or removed.
// // Save it, if the mod directory has been moved, since this will change the save format.
// private void OnModPathChange(in ModPathChanged.Arguments arguments)
// {
// switch (arguments.Type)
// {
// case ModPathChangeType.Added:
// var parent = Root;
// if (_config.DefaultImportFolder.Length != 0)
// try
// {
// parent = FindOrCreateAllFolders(_config.DefaultImportFolder);
// }
// catch (Exception e)
// {
// Penumbra.Messager.NotificationMessage(e,
// $"Could not move newly imported mod {arguments.Mod.Name} to default import folder {_config.DefaultImportFolder}.",
// NotificationType.Warning);
// }
//
// CreateDuplicateLeaf(parent, arguments.Mod.Name, arguments.Mod);
// break;
// case ModPathChangeType.Deleted:
// if (arguments.Mod.Node is not null)
// Delete(arguments.Mod.Node);
// break;
// case ModPathChangeType.Moved:
// _saveService.DelaySave(this);
// break;
// case ModPathChangeType.Reloaded:
// // Nothing
// break;
// }
// }
//
// public struct ImportDate : ISortMode
// {
// public ReadOnlySpan<byte> Name
// => "Import Date (Older First)"u8;
//
// public ReadOnlySpan<byte> Description
// => "In each folder, sort all subfolders lexicographically, then sort all leaves using their import date."u8;
//
// public IEnumerable<IFileSystemNode> GetChildren(IFileSystemFolder f)
// => f.GetSubFolders().Cast<IFileSystemNode>().Concat(f.GetLeaves().OfType<IFileSystemData<Mod>>().OrderBy(l => l.Value.ImportDate));
// }
//
// public struct InverseImportDate : ISortMode
// {
// public ReadOnlySpan<byte> Name
// => "Import Date (Newer First)"u8;
//
// public ReadOnlySpan<byte> Description
// => "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse import date."u8;
//
// public IEnumerable<IFileSystemNode> GetChildren(IFileSystemFolder f)
// => f.GetSubFolders().Cast<IFileSystemNode>().Concat(f.GetLeaves().OfType<IFileSystemData<Mod>>().OrderByDescending(l => l.Value.ImportDate));
// }
//
//}
public sealed class ModFileSystem : FileSystem<Mod>, IDisposable, ISavable, IService public sealed class ModFileSystem : FileSystem<Mod>, IDisposable, ISavable, IService
{ {
private readonly ModManager _modManager; private readonly ModManager _modManager;

View file

@ -20,7 +20,7 @@ public enum FeatureFlags : ulong
Invalid = 1ul << 62, Invalid = 1ul << 62,
} }
public sealed class Mod : IMod public sealed class Mod : IMod, IFileSystemValue<Mod>
{ {
public static readonly TemporaryMod ForcedFiles = new() public static readonly TemporaryMod ForcedFiles = new()
{ {
@ -69,6 +69,7 @@ public sealed class Mod : IMod
// Local Data // Local Data
public string FullPath { get; set; } = string.Empty;
public long ImportDate { get; internal set; } = DateTimeOffset.UnixEpoch.ToUnixTimeMilliseconds(); public long ImportDate { get; internal set; } = DateTimeOffset.UnixEpoch.ToUnixTimeMilliseconds();
public IReadOnlyList<string> LocalTags { get; internal set; } = []; public IReadOnlyList<string> LocalTags { get; internal set; } = [];
public string Note { get; internal set; } = string.Empty; public string Note { get; internal set; } = string.Empty;
@ -130,14 +131,15 @@ public sealed class Mod : IMod
} }
// Cache // Cache
public IFileSystemData<Mod>? Node { get; set; }
public readonly SortedList<string, IIdentifiedObjectData> ChangedItems = new(); public readonly SortedList<string, IIdentifiedObjectData> ChangedItems = new();
public string LowerChangedItemsString { get; internal set; } = string.Empty; public string LowerChangedItemsString { get; internal set; } = string.Empty;
public string AllTagsLower { get; internal set; } = string.Empty; public string AllTagsLower { get; internal set; } = string.Empty;
public int TotalFileCount { get; internal set; } public int TotalFileCount { get; internal set; }
public int TotalSwapCount { get; internal set; } public int TotalSwapCount { get; internal set; }
public int TotalManipulations { get; internal set; } public int TotalManipulations { get; internal set; }
public ushort LastChangedItemsUpdate { get; internal set; } public ushort LastChangedItemsUpdate { get; internal set; }
public bool HasOptions { get; internal set; } public bool HasOptions { get; internal set; }
} }

View file

@ -1,131 +1,139 @@
using Newtonsoft.Json; using Luna;
using Newtonsoft.Json.Linq; using Newtonsoft.Json;
using Penumbra.GameData.Structs; using Newtonsoft.Json.Linq;
using Penumbra.Mods.Manager; using Penumbra.GameData.Structs;
using Penumbra.Services; using Penumbra.Mods.Manager;
using Penumbra.Services;
namespace Penumbra.Mods;
namespace Penumbra.Mods;
public readonly struct ModLocalData(Mod mod) : ISavable
{ public readonly struct ModLocalData(Mod mod) : ISavable
public const int FileVersion = 3; {
public const int FileVersion = 3;
public string ToFilePath(FilenameService fileNames)
=> fileNames.LocalDataFile(mod); public string ToFilePath(FilenameService fileNames)
=> fileNames.LocalDataFile(mod);
public void Save(StreamWriter writer)
{ public void Save(StreamWriter writer)
var jObject = new JObject {
{ var jObject = new JObject
{ nameof(FileVersion), JToken.FromObject(FileVersion) }, {
{ nameof(Mod.ImportDate), JToken.FromObject(mod.ImportDate) }, { nameof(FileVersion), JToken.FromObject(FileVersion) },
{ nameof(Mod.LocalTags), JToken.FromObject(mod.LocalTags) }, { nameof(Mod.ImportDate), JToken.FromObject(mod.ImportDate) },
{ nameof(Mod.Note), JToken.FromObject(mod.Note) }, { nameof(Mod.LocalTags), JToken.FromObject(mod.LocalTags) },
{ nameof(Mod.Favorite), JToken.FromObject(mod.Favorite) }, { nameof(Mod.Note), JToken.FromObject(mod.Note) },
{ nameof(Mod.PreferredChangedItems), JToken.FromObject(mod.PreferredChangedItems) }, { nameof(Mod.Favorite), JToken.FromObject(mod.Favorite) },
}; { nameof(Mod.PreferredChangedItems), JToken.FromObject(mod.PreferredChangedItems) },
using var jWriter = new JsonTextWriter(writer); };
jWriter.Formatting = Formatting.Indented;
jObject.WriteTo(jWriter); if (mod.FullPath.Length > 0)
} {
var baseName = mod.FullPath.GetBaseName(mod.Name, out var folder);
public static ModDataChangeType Load(ModDataEditor editor, Mod mod) jObject[nameof(Mod.FullPath)] = folder.Length > 0 ? $"{folder}/{baseName}" : baseName.ToString();
{ }
var dataFile = editor.SaveService.FileNames.LocalDataFile(mod);
using var jWriter = new JsonTextWriter(writer);
var importDate = 0L; jWriter.Formatting = Formatting.Indented;
var localTags = Enumerable.Empty<string>(); jObject.WriteTo(jWriter);
var favorite = false; }
var note = string.Empty;
public static ModDataChangeType Load(ModDataEditor editor, Mod mod)
HashSet<CustomItemId> preferredChangedItems = []; {
var dataFile = editor.SaveService.FileNames.LocalDataFile(mod);
var save = true;
if (File.Exists(dataFile)) var importDate = 0L;
try var localTags = Enumerable.Empty<string>();
{ var favorite = false;
var text = File.ReadAllText(dataFile); var note = string.Empty;
var json = JObject.Parse(text);
HashSet<CustomItemId> preferredChangedItems = [];
importDate = json[nameof(Mod.ImportDate)]?.Value<long>() ?? importDate;
favorite = json[nameof(Mod.Favorite)]?.Value<bool>() ?? favorite; var save = true;
note = json[nameof(Mod.Note)]?.Value<string>() ?? note; if (File.Exists(dataFile))
localTags = (json[nameof(Mod.LocalTags)] as JArray)?.Values<string>().OfType<string>() ?? localTags; try
preferredChangedItems = (json[nameof(Mod.PreferredChangedItems)] as JArray)?.Values<ulong>().Select(i => (CustomItemId) i).ToHashSet() ?? mod.DefaultPreferredItems; {
save = false; var text = File.ReadAllText(dataFile);
} var json = JObject.Parse(text);
catch (Exception e)
{ importDate = json[nameof(Mod.ImportDate)]?.Value<long>() ?? importDate;
Penumbra.Log.Error($"Could not load local mod data:\n{e}"); favorite = json[nameof(Mod.Favorite)]?.Value<bool>() ?? favorite;
} note = json[nameof(Mod.Note)]?.Value<string>() ?? note;
else localTags = (json[nameof(Mod.LocalTags)] as JArray)?.Values<string>().OfType<string>() ?? localTags;
{ preferredChangedItems =
preferredChangedItems = mod.DefaultPreferredItems; (json[nameof(Mod.PreferredChangedItems)] as JArray)?.Values<ulong>().Select(i => (CustomItemId)i).ToHashSet()
} ?? mod.DefaultPreferredItems;
save = false;
if (importDate == 0) }
importDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); catch (Exception e)
{
ModDataChangeType changes = 0; Penumbra.Log.Error($"Could not load local mod data:\n{e}");
if (mod.ImportDate != importDate) }
{ else
mod.ImportDate = importDate; preferredChangedItems = mod.DefaultPreferredItems;
changes |= ModDataChangeType.ImportDate;
} if (importDate == 0)
importDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
changes |= UpdateTags(mod, null, localTags);
ModDataChangeType changes = 0;
if (mod.Favorite != favorite) if (mod.ImportDate != importDate)
{ {
mod.Favorite = favorite; mod.ImportDate = importDate;
changes |= ModDataChangeType.Favorite; changes |= ModDataChangeType.ImportDate;
} }
if (mod.Note != note) changes |= UpdateTags(mod, null, localTags);
{
mod.Note = note; if (mod.Favorite != favorite)
changes |= ModDataChangeType.Note; {
} mod.Favorite = favorite;
changes |= ModDataChangeType.Favorite;
if (!preferredChangedItems.SetEquals(mod.PreferredChangedItems)) }
{
mod.PreferredChangedItems = preferredChangedItems; if (mod.Note != note)
changes |= ModDataChangeType.PreferredChangedItems; {
} mod.Note = note;
changes |= ModDataChangeType.Note;
if (save) }
editor.SaveService.QueueSave(new ModLocalData(mod));
if (!preferredChangedItems.SetEquals(mod.PreferredChangedItems))
return changes; {
} mod.PreferredChangedItems = preferredChangedItems;
changes |= ModDataChangeType.PreferredChangedItems;
internal static ModDataChangeType UpdateTags(Mod mod, IEnumerable<string>? newModTags, IEnumerable<string>? newLocalTags) }
{
if (newModTags == null && newLocalTags == null) if (save)
return 0; editor.SaveService.QueueSave(new ModLocalData(mod));
ModDataChangeType type = 0; return changes;
if (newModTags != null) }
{
var modTags = newModTags.Where(t => t.Length > 0).Distinct().ToArray(); internal static ModDataChangeType UpdateTags(Mod mod, IEnumerable<string>? newModTags, IEnumerable<string>? newLocalTags)
if (!modTags.SequenceEqual(mod.ModTags)) {
{ if (newModTags == null && newLocalTags == null)
newLocalTags ??= mod.LocalTags; return 0;
mod.ModTags = modTags;
type |= ModDataChangeType.ModTags; ModDataChangeType type = 0;
} if (newModTags != null)
} {
var modTags = newModTags.Where(t => t.Length > 0).Distinct().ToArray();
if (newLocalTags != null) if (!modTags.SequenceEqual(mod.ModTags))
{ {
var localTags = newLocalTags!.Where(t => t.Length > 0 && !mod.ModTags.Contains(t)).Distinct().ToArray(); newLocalTags ??= mod.LocalTags;
if (!localTags.SequenceEqual(mod.LocalTags)) mod.ModTags = modTags;
{ type |= ModDataChangeType.ModTags;
mod.LocalTags = localTags; }
type |= ModDataChangeType.LocalTags; }
}
} if (newLocalTags != null)
{
return type; var localTags = newLocalTags!.Where(t => t.Length > 0 && !mod.ModTags.Contains(t)).Distinct().ToArray();
} if (!localTags.SequenceEqual(mod.LocalTags))
} {
mod.LocalTags = localTags;
type |= ModDataChangeType.LocalTags;
}
}
return type;
}
}

View file

@ -22,7 +22,7 @@ public static class StaticServiceManager
{ {
public static ServiceManager CreateProvider(Penumbra penumbra, IDalamudPluginInterface pi, Logger log) public static ServiceManager CreateProvider(Penumbra penumbra, IDalamudPluginInterface pi, Logger log)
{ {
var services = new ServiceManager(log) var services = new ServiceManager(log, Logger.GlobalPluginName)
.AddDalamudServices(pi) .AddDalamudServices(pi)
.AddExistingService(log) .AddExistingService(log)
.AddExistingService(penumbra); .AddExistingService(penumbra);

View file

@ -44,7 +44,7 @@ public partial class MtrlTab
for (var j = 0; j < 8; ++j) for (var j = 0; j < 8; ++j)
{ {
var pairIndex = i + j; var pairIndex = i + j;
using (ImRaii.PushColor(ImGuiCol.Button, ImGui.GetColorU32(ImGuiCol.ButtonActive), pairIndex == _colorTableSelectedPair)) using (ImGuiColor.Button.Push(Im.Style[ImGuiColor.ButtonActive], pairIndex == _colorTableSelectedPair))
{ {
if (ImUtf8.Button($"#{pairIndex + 1}".PadLeft(3 + spacePadding), if (ImUtf8.Button($"#{pairIndex + 1}".PadLeft(3 + spacePadding),
new Vector2(buttonWidth, ImGui.GetFrameHeightWithSpacing() + frameHeight))) new Vector2(buttonWidth, ImGui.GetFrameHeightWithSpacing() + frameHeight)))
@ -101,6 +101,7 @@ public partial class MtrlTab
{ {
retA |= DrawRowHeader(rowAIdx, disabled); retA |= DrawRowHeader(rowAIdx, disabled);
} }
columns.Next(); columns.Next();
using (ImUtf8.PushId("RowHeaderB"u8)) using (ImUtf8.PushId("RowHeaderB"u8))
{ {
@ -232,8 +233,8 @@ public partial class MtrlTab
/// <remarks> Padding styles do not seem to apply to this component. It is recommended to prepend two spaces. </remarks> /// <remarks> Padding styles do not seem to apply to this component. It is recommended to prepend two spaces. </remarks>
private static void DrawHeader(ReadOnlySpan<byte> label) private static void DrawHeader(ReadOnlySpan<byte> label)
{ {
var headerColor = ImGui.GetColorU32(ImGuiCol.Header); var headerColor = Im.Style[ImGuiColor.Header];
using var _ = ImRaii.PushColor(ImGuiCol.HeaderHovered, headerColor).Push(ImGuiCol.HeaderActive, headerColor); using var _ = ImGuiColor.HeaderHovered.Push(headerColor).Push(ImGuiColor.HeaderActive, headerColor);
ImUtf8.CollapsingHeader(label, ImGuiTreeNodeFlags.Leaf); ImUtf8.CollapsingHeader(label, ImGuiTreeNodeFlags.Leaf);
} }

View file

@ -308,7 +308,7 @@ public partial class MtrlTab
var style = ImGui.GetStyle(); var style = ImGui.GetStyle();
var frameRounding = style.FrameRounding; var frameRounding = style.FrameRounding;
var frameThickness = style.FrameBorderSize; var frameThickness = style.FrameBorderSize;
var borderColor = ImGui.GetColorU32(ImGuiCol.Border); var borderColor = ImGuiColor.Border.Get();
var drawList = ImGui.GetWindowDrawList(); var drawList = ImGui.GetWindowDrawList();
if (topColor == bottomColor) if (topColor == bottomColor)
{ {
@ -328,7 +328,7 @@ public partial class MtrlTab
bottomColor, frameRounding, ImDrawFlags.RoundCornersBottomLeft | ImDrawFlags.RoundCornersBottomRight); bottomColor, frameRounding, ImDrawFlags.RoundCornersBottomLeft | ImDrawFlags.RoundCornersBottomRight);
} }
drawList.AddRect(rcMin, rcMax, borderColor, frameRounding, ImDrawFlags.RoundCornersDefault, frameThickness); drawList.AddRect(rcMin, rcMax, borderColor.Color, frameRounding, ImDrawFlags.RoundCornersDefault, frameThickness);
} }
private static bool CtColorPicker(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, HalfColor current, Action<HalfColor> setter, private static bool CtColorPicker(ReadOnlySpan<byte> label, ReadOnlySpan<byte> description, HalfColor current, Action<HalfColor> setter,

View file

@ -24,16 +24,15 @@ public partial class MtrlTab
if (disabled) if (disabled)
return; return;
if (ImUtf8.Button("Reload live preview"u8)) if (Im.Button("Reload live preview"u8))
BindToMaterialInstances(); BindToMaterialInstances();
if (_materialPreviewers.Count != 0 || _colorTablePreviewers.Count != 0) if (_materialPreviewers.Count != 0 || _colorTablePreviewers.Count != 0)
return; return;
Im.Line.Same(); Im.Line.Same();
using var c = ImRaii.PushColor(ImGuiCol.Text, Colors.RegexWarningBorder); Im.Text("The current material has not been found on your character. Please check the Import from Screen tab for more information."u8,
ImUtf8.Text( Colors.RegexWarningBorder);
"The current material has not been found on your character. Please check the Import from Screen tab for more information."u8);
} }
private unsafe void BindToMaterialInstances() private unsafe void BindToMaterialInstances()
@ -292,7 +291,7 @@ public partial class MtrlTab
{ {
var level = (MathF.Sin(time * 2.0f * MathF.PI) + 2.0f) / 3.0f / 255.0f; var level = (MathF.Sin(time * 2.0f * MathF.PI) + 2.0f) / 3.0f / 255.0f;
var baseColor = colorId.Value(); var baseColor = colorId.Value();
var color = level * new Vector3(baseColor & 0xFF, (baseColor >> 8) & 0xFF, (baseColor >> 16) & 0xFF); var color = level * new Vector3(baseColor.R, baseColor.G, baseColor.B);
var halfColor = (HalfColor)(color * color); var halfColor = (HalfColor)(color * color);
row.DiffuseColor = halfColor; row.DiffuseColor = halfColor;

View file

@ -1,273 +1,274 @@
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Newtonsoft.Json.Linq; using ImSharp;
using OtterGui.Raii; using Newtonsoft.Json.Linq;
using OtterGui.Text; using OtterGui.Raii;
using Penumbra.Collections.Cache; using OtterGui.Text;
using Penumbra.GameData.Enums; using Penumbra.Collections.Cache;
using Penumbra.GameData.Structs; using Penumbra.GameData.Enums;
using Penumbra.Meta; using Penumbra.GameData.Structs;
using Penumbra.Meta.Files; using Penumbra.Meta;
using Penumbra.Meta.Manipulations; using Penumbra.Meta.Files;
using Penumbra.Mods.Editor; using Penumbra.Meta.Manipulations;
using Penumbra.UI.Classes; using Penumbra.Mods.Editor;
using Penumbra.UI.Classes;
namespace Penumbra.UI.AdvancedWindow.Meta;
namespace Penumbra.UI.AdvancedWindow.Meta;
public sealed class AtrMetaDrawer(ModMetaEditor editor, MetaFileManager metaFiles)
: MetaDrawer<AtrIdentifier, AtrEntry>(editor, metaFiles), Luna.IService public sealed class AtrMetaDrawer(ModMetaEditor editor, MetaFileManager metaFiles)
{ : MetaDrawer<AtrIdentifier, AtrEntry>(editor, metaFiles), Luna.IService
public override ReadOnlySpan<byte> Label {
=> "Attributes(ATR)###ATR"u8; public override ReadOnlySpan<byte> Label
=> "Attributes(ATR)###ATR"u8;
private ShapeAttributeString _buffer = ShapeAttributeString.TryRead("atrx_"u8, out var s) ? s : ShapeAttributeString.Empty;
private bool _identifierValid; private ShapeAttributeString _buffer = ShapeAttributeString.TryRead("atrx_"u8, out var s) ? s : ShapeAttributeString.Empty;
private bool _identifierValid;
public override int NumColumns
=> 7; public override int NumColumns
=> 7;
public override float ColumnHeight
=> ImUtf8.FrameHeightSpacing; public override float ColumnHeight
=> ImUtf8.FrameHeightSpacing;
protected override void Initialize()
{ protected override void Initialize()
Identifier = new AtrIdentifier(HumanSlot.Unknown, null, ShapeAttributeString.Empty, GenderRace.Unknown); {
Entry = AtrEntry.True; Identifier = new AtrIdentifier(HumanSlot.Unknown, null, ShapeAttributeString.Empty, GenderRace.Unknown);
} Entry = AtrEntry.True;
}
protected override void DrawNew()
{ protected override void DrawNew()
ImGui.TableNextColumn(); {
CopyToClipboardButton("Copy all current ATR manipulations to clipboard."u8, ImGui.TableNextColumn();
new Lazy<JToken?>(() => MetaDictionary.SerializeTo([], Editor.Atr))); CopyToClipboardButton("Copy all current ATR manipulations to clipboard."u8,
new Lazy<JToken?>(() => MetaDictionary.SerializeTo([], Editor.Atr)));
ImGui.TableNextColumn();
var canAdd = !Editor.Contains(Identifier) && _identifierValid; ImGui.TableNextColumn();
var tt = canAdd var canAdd = !Editor.Contains(Identifier) && _identifierValid;
? "Stage this edit."u8 var tt = canAdd
: _identifierValid ? "Stage this edit."u8
? "This entry does not contain a valid attribute."u8 : _identifierValid
: "This entry is already edited."u8; ? "This entry does not contain a valid attribute."u8
if (ImUtf8.IconButton(FontAwesomeIcon.Plus, tt, disabled: !canAdd)) : "This entry is already edited."u8;
Editor.Changes |= Editor.TryAdd(Identifier, AtrEntry.False); if (ImUtf8.IconButton(FontAwesomeIcon.Plus, tt, disabled: !canAdd))
Editor.Changes |= Editor.TryAdd(Identifier, AtrEntry.False);
DrawIdentifierInput(ref Identifier);
DrawEntry(ref Entry, true); DrawIdentifierInput(ref Identifier);
} DrawEntry(ref Entry, true);
}
protected override void DrawEntry(AtrIdentifier identifier, AtrEntry entry)
{ protected override void DrawEntry(AtrIdentifier identifier, AtrEntry entry)
DrawMetaButtons(identifier, entry); {
DrawIdentifier(identifier); DrawMetaButtons(identifier, entry);
DrawIdentifier(identifier);
if (DrawEntry(ref entry, false))
Editor.Changes |= Editor.Update(identifier, entry); if (DrawEntry(ref entry, false))
} Editor.Changes |= Editor.Update(identifier, entry);
}
protected override IEnumerable<(AtrIdentifier, AtrEntry)> Enumerate()
=> Editor.Atr protected override IEnumerable<(AtrIdentifier, AtrEntry)> Enumerate()
.OrderBy(kvp => kvp.Key.Attribute) => Editor.Atr
.ThenBy(kvp => kvp.Key.Slot) .OrderBy(kvp => kvp.Key.Attribute)
.ThenBy(kvp => kvp.Key.Id) .ThenBy(kvp => kvp.Key.Slot)
.Select(kvp => (kvp.Key, kvp.Value)); .ThenBy(kvp => kvp.Key.Id)
.Select(kvp => (kvp.Key, kvp.Value));
protected override int Count
=> Editor.Atr.Count; protected override int Count
=> Editor.Atr.Count;
private bool DrawIdentifierInput(ref AtrIdentifier identifier)
{ private bool DrawIdentifierInput(ref AtrIdentifier identifier)
ImGui.TableNextColumn(); {
var changes = DrawHumanSlot(ref identifier); ImGui.TableNextColumn();
var changes = DrawHumanSlot(ref identifier);
ImGui.TableNextColumn();
changes |= DrawGenderRaceConditionInput(ref identifier); ImGui.TableNextColumn();
changes |= DrawGenderRaceConditionInput(ref identifier);
ImGui.TableNextColumn();
changes |= DrawPrimaryId(ref identifier); ImGui.TableNextColumn();
changes |= DrawPrimaryId(ref identifier);
ImGui.TableNextColumn();
changes |= DrawAttributeKeyInput(ref identifier, ref _buffer, ref _identifierValid); ImGui.TableNextColumn();
return changes; changes |= DrawAttributeKeyInput(ref identifier, ref _buffer, ref _identifierValid);
} return changes;
}
private static void DrawIdentifier(AtrIdentifier identifier)
{ private static void DrawIdentifier(AtrIdentifier identifier)
ImGui.TableNextColumn(); {
ImGui.TableNextColumn();
ImUtf8.TextFramed(ShpMetaDrawer.SlotName(identifier.Slot), FrameColor);
ImUtf8.HoverTooltip("Model Slot"u8); ImUtf8.TextFramed(ShpMetaDrawer.SlotName(identifier.Slot), FrameColor);
ImUtf8.HoverTooltip("Model Slot"u8);
ImGui.TableNextColumn();
if (identifier.GenderRaceCondition is not GenderRace.Unknown) ImGui.TableNextColumn();
{ if (identifier.GenderRaceCondition is not GenderRace.Unknown)
ImUtf8.TextFramed($"{identifier.GenderRaceCondition.ToName()} ({identifier.GenderRaceCondition.ToRaceCode()})", FrameColor); {
ImUtf8.HoverTooltip("Gender & Race Code for this attribute to be set."); ImUtf8.TextFramed($"{identifier.GenderRaceCondition.ToName()} ({identifier.GenderRaceCondition.ToRaceCode()})", FrameColor);
} ImUtf8.HoverTooltip("Gender & Race Code for this attribute to be set.");
else }
{ else
ImUtf8.TextFramed("Any Gender & Race"u8, FrameColor); {
} ImUtf8.TextFramed("Any Gender & Race"u8, FrameColor);
}
ImGui.TableNextColumn();
if (identifier.Id.HasValue) ImGui.TableNextColumn();
ImUtf8.TextFramed($"{identifier.Id.Value.Id}", FrameColor); if (identifier.Id.HasValue)
else ImUtf8.TextFramed($"{identifier.Id.Value.Id}", FrameColor);
ImUtf8.TextFramed("All IDs"u8, FrameColor); else
ImUtf8.HoverTooltip("Primary ID"u8); ImUtf8.TextFramed("All IDs"u8, FrameColor);
ImUtf8.HoverTooltip("Primary ID"u8);
ImGui.TableNextColumn();
ImUtf8.TextFramed(identifier.Attribute.AsSpan, FrameColor); ImGui.TableNextColumn();
} ImUtf8.TextFramed(identifier.Attribute.AsSpan, FrameColor);
}
private static bool DrawEntry(ref AtrEntry entry, bool disabled)
{ private static bool DrawEntry(ref AtrEntry entry, bool disabled)
using var dis = ImRaii.Disabled(disabled); {
ImGui.TableNextColumn(); using var dis = ImRaii.Disabled(disabled);
var value = entry.Value; ImGui.TableNextColumn();
var changes = ImUtf8.Checkbox("##atrEntry"u8, ref value); var value = entry.Value;
if (changes) var changes = ImUtf8.Checkbox("##atrEntry"u8, ref value);
entry = new AtrEntry(value); if (changes)
ImUtf8.HoverTooltip("Whether to enable or disable this attribute for the selected items."); entry = new AtrEntry(value);
return changes; ImUtf8.HoverTooltip("Whether to enable or disable this attribute for the selected items.");
} return changes;
}
public static bool DrawPrimaryId(ref AtrIdentifier identifier, float unscaledWidth = 100)
{ public static bool DrawPrimaryId(ref AtrIdentifier identifier, float unscaledWidth = 100)
var allSlots = identifier.Slot is HumanSlot.Unknown; {
var all = !identifier.Id.HasValue; var allSlots = identifier.Slot is HumanSlot.Unknown;
var ret = false; var all = !identifier.Id.HasValue;
using (ImRaii.Disabled(allSlots)) var ret = false;
{ using (ImRaii.Disabled(allSlots))
if (ImUtf8.Checkbox("##atrAll"u8, ref all)) {
{ if (ImUtf8.Checkbox("##atrAll"u8, ref all))
identifier = identifier with { Id = all ? null : 0 }; {
ret = true; identifier = identifier with { Id = all ? null : 0 };
} ret = true;
} }
}
ImUtf8.HoverTooltip(allSlots
? "When using all slots, you also need to use all IDs."u8 ImUtf8.HoverTooltip(allSlots
: "Enable this attribute for all model IDs."u8); ? "When using all slots, you also need to use all IDs."u8
: "Enable this attribute for all model IDs."u8);
ImGui.SameLine(0, ImGui.GetStyle().ItemInnerSpacing.X);
if (all) ImGui.SameLine(0, ImGui.GetStyle().ItemInnerSpacing.X);
{ if (all)
using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0.05f, 0.5f)); {
ImUtf8.TextFramed("All IDs"u8, ImGui.GetColorU32(ImGuiCol.FrameBg, all || allSlots ? ImGui.GetStyle().DisabledAlpha : 1f), using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0.05f, 0.5f));
new Vector2(unscaledWidth, 0), ImGui.GetColorU32(ImGuiCol.TextDisabled)); ImUtf8.TextFramed("All IDs"u8, ImGuiColor.FrameBackground.Get(all || allSlots ? ImGui.GetStyle().DisabledAlpha : 1f).Color,
} new Vector2(unscaledWidth, 0), ImGuiColor.TextDisabled.Get().Color);
else }
{ else
var max = identifier.Slot.ToSpecificEnum() is BodySlot ? byte.MaxValue : ExpandedEqpGmpBase.Count - 1; {
if (IdInput("##atrPrimaryId"u8, unscaledWidth, identifier.Id.GetValueOrDefault(0).Id, out var setId, 0, max, false)) var max = identifier.Slot.ToSpecificEnum() is BodySlot ? byte.MaxValue : ExpandedEqpGmpBase.Count - 1;
{ if (IdInput("##atrPrimaryId"u8, unscaledWidth, identifier.Id.GetValueOrDefault(0).Id, out var setId, 0, max, false))
identifier = identifier with { Id = setId }; {
ret = true; identifier = identifier with { Id = setId };
} ret = true;
} }
}
ImUtf8.HoverTooltip("Primary ID - You can usually find this as the 'e####' part of an item path or similar for customizations."u8);
ImUtf8.HoverTooltip("Primary ID - You can usually find this as the 'e####' part of an item path or similar for customizations."u8);
return ret;
} return ret;
}
public bool DrawHumanSlot(ref AtrIdentifier identifier, float unscaledWidth = 150)
{ public bool DrawHumanSlot(ref AtrIdentifier identifier, float unscaledWidth = 150)
var ret = false; {
ImGui.SetNextItemWidth(unscaledWidth * ImUtf8.GlobalScale); var ret = false;
using (var combo = ImUtf8.Combo("##atrSlot"u8, ShpMetaDrawer.SlotName(identifier.Slot))) ImGui.SetNextItemWidth(unscaledWidth * ImUtf8.GlobalScale);
{ using (var combo = ImUtf8.Combo("##atrSlot"u8, ShpMetaDrawer.SlotName(identifier.Slot)))
if (combo) {
foreach (var slot in ShpMetaDrawer.AvailableSlots) if (combo)
{ foreach (var slot in ShpMetaDrawer.AvailableSlots)
if (!ImUtf8.Selectable(ShpMetaDrawer.SlotName(slot), slot == identifier.Slot) || slot == identifier.Slot) {
continue; if (!ImUtf8.Selectable(ShpMetaDrawer.SlotName(slot), slot == identifier.Slot) || slot == identifier.Slot)
continue;
ret = true;
if (slot is HumanSlot.Unknown) ret = true;
{ if (slot is HumanSlot.Unknown)
identifier = identifier with {
{ identifier = identifier with
Id = null, {
Slot = slot, Id = null,
}; Slot = slot,
} };
else }
{ else
identifier = identifier with {
{ identifier = identifier with
Id = identifier.Id.HasValue {
? (PrimaryId)Math.Clamp(identifier.Id.Value.Id, 0, Id = identifier.Id.HasValue
slot.ToSpecificEnum() is BodySlot ? byte.MaxValue : ExpandedEqpGmpBase.Count - 1) ? (PrimaryId)Math.Clamp(identifier.Id.Value.Id, 0,
: null, slot.ToSpecificEnum() is BodySlot ? byte.MaxValue : ExpandedEqpGmpBase.Count - 1)
Slot = slot, : null,
}; Slot = slot,
ret = true; };
} ret = true;
} }
} }
}
ImUtf8.HoverTooltip("Model Slot"u8);
return ret; ImUtf8.HoverTooltip("Model Slot"u8);
} return ret;
}
private static bool DrawGenderRaceConditionInput(ref AtrIdentifier identifier, float unscaledWidth = 250)
{ private static bool DrawGenderRaceConditionInput(ref AtrIdentifier identifier, float unscaledWidth = 250)
var ret = false; {
ImGui.SetNextItemWidth(unscaledWidth * ImUtf8.GlobalScale); var ret = false;
ImGui.SetNextItemWidth(unscaledWidth * ImUtf8.GlobalScale);
using (var combo = ImUtf8.Combo("##shpGenderRace"u8,
identifier.GenderRaceCondition is GenderRace.Unknown using (var combo = ImUtf8.Combo("##shpGenderRace"u8,
? "Any Gender & Race" identifier.GenderRaceCondition is GenderRace.Unknown
: $"{identifier.GenderRaceCondition.ToName()} ({identifier.GenderRaceCondition.ToRaceCode()})")) ? "Any Gender & Race"
{ : $"{identifier.GenderRaceCondition.ToName()} ({identifier.GenderRaceCondition.ToRaceCode()})"))
if (combo) {
{ if (combo)
if (ImUtf8.Selectable("Any Gender & Race"u8, identifier.GenderRaceCondition is GenderRace.Unknown) {
&& identifier.GenderRaceCondition is not GenderRace.Unknown) if (ImUtf8.Selectable("Any Gender & Race"u8, identifier.GenderRaceCondition is GenderRace.Unknown)
{ && identifier.GenderRaceCondition is not GenderRace.Unknown)
identifier = identifier with { GenderRaceCondition = GenderRace.Unknown }; {
ret = true; identifier = identifier with { GenderRaceCondition = GenderRace.Unknown };
} ret = true;
}
foreach (var gr in ShapeAttributeHashSet.GenderRaceValues.Skip(1))
{ foreach (var gr in ShapeAttributeHashSet.GenderRaceValues.Skip(1))
if (ImUtf8.Selectable($"{gr.ToName()} ({gr.ToRaceCode()})", identifier.GenderRaceCondition == gr) {
&& identifier.GenderRaceCondition != gr) if (ImUtf8.Selectable($"{gr.ToName()} ({gr.ToRaceCode()})", identifier.GenderRaceCondition == gr)
{ && identifier.GenderRaceCondition != gr)
identifier = identifier with { GenderRaceCondition = gr }; {
ret = true; identifier = identifier with { GenderRaceCondition = gr };
} ret = true;
} }
} }
} }
}
ImUtf8.HoverTooltip(
"Only activate this attribute for this gender & race code."u8); ImUtf8.HoverTooltip(
"Only activate this attribute for this gender & race code."u8);
return ret;
} return ret;
}
public static unsafe bool DrawAttributeKeyInput(ref AtrIdentifier identifier, ref ShapeAttributeString buffer, ref bool valid,
float unscaledWidth = 150) public static unsafe bool DrawAttributeKeyInput(ref AtrIdentifier identifier, ref ShapeAttributeString buffer, ref bool valid,
{ float unscaledWidth = 150)
var ret = false; {
var ptr = Unsafe.AsPointer(ref buffer); var ret = false;
var span = new Span<byte>(ptr, ShapeAttributeString.MaxLength + 1); var ptr = Unsafe.AsPointer(ref buffer);
using (new ImRaii.ColorStyle().Push(ImGuiCol.Border, Colors.RegexWarningBorder, !valid).Push(ImGuiStyleVar.FrameBorderSize, 1f, !valid)) var span = new Span<byte>(ptr, ShapeAttributeString.MaxLength + 1);
{ using (ImStyleBorder.Frame.Push(Colors.RegexWarningBorder, Im.Style.GlobalScale, !valid))
ImGui.SetNextItemWidth(unscaledWidth * ImUtf8.GlobalScale); {
if (ImUtf8.InputText("##atrAttribute"u8, span, out int newLength, "Attribute..."u8)) ImGui.SetNextItemWidth(unscaledWidth * ImUtf8.GlobalScale);
{ if (ImUtf8.InputText("##atrAttribute"u8, span, out int newLength, "Attribute..."u8))
buffer.ForceLength((byte)newLength); {
valid = buffer.ValidateCustomAttributeString(); buffer.ForceLength((byte)newLength);
if (valid) valid = buffer.ValidateCustomAttributeString();
identifier = identifier with { Attribute = buffer }; if (valid)
ret = true; identifier = identifier with { Attribute = buffer };
} ret = true;
} }
}
ImUtf8.HoverTooltip("Supported attribute need to have the format `atrx_*` and a maximum length of 30 characters."u8);
return ret; ImUtf8.HoverTooltip("Supported attribute need to have the format `atrx_*` and a maximum length of 30 characters."u8);
} return ret;
} }
}

View file

@ -1,165 +1,163 @@
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Newtonsoft.Json.Linq; using ImSharp;
using OtterGui; using Newtonsoft.Json.Linq;
using OtterGui.Raii; using OtterGui;
using OtterGui.Text; using OtterGui.Raii;
using Penumbra.Api.Api; using OtterGui.Text;
using Penumbra.Meta; using Penumbra.Api.Api;
using Penumbra.Meta.Manipulations; using Penumbra.Meta;
using Penumbra.Mods.Editor; using Penumbra.Meta.Manipulations;
using Penumbra.UI.Classes; using Penumbra.Mods.Editor;
using Penumbra.UI.Classes;
namespace Penumbra.UI.AdvancedWindow.Meta;
namespace Penumbra.UI.AdvancedWindow.Meta;
public interface IMetaDrawer
{ public interface IMetaDrawer
public ReadOnlySpan<byte> Label { get; } {
public int NumColumns { get; } public ReadOnlySpan<byte> Label { get; }
public float ColumnHeight { get; } public int NumColumns { get; }
public void Draw(); public float ColumnHeight { get; }
} public void Draw();
}
public abstract class MetaDrawer<TIdentifier, TEntry>(ModMetaEditor editor, MetaFileManager metaFiles) : IMetaDrawer
where TIdentifier : unmanaged, IMetaIdentifier public abstract class MetaDrawer<TIdentifier, TEntry>(ModMetaEditor editor, MetaFileManager metaFiles) : IMetaDrawer
where TEntry : unmanaged where TIdentifier : unmanaged, IMetaIdentifier
{ where TEntry : unmanaged
protected const uint FrameColor = 0; {
protected const uint FrameColor = 0;
protected readonly ModMetaEditor Editor = editor;
protected readonly MetaFileManager MetaFiles = metaFiles; protected readonly ModMetaEditor Editor = editor;
protected TIdentifier Identifier; protected readonly MetaFileManager MetaFiles = metaFiles;
protected TEntry Entry; protected TIdentifier Identifier;
private bool _initialized; protected TEntry Entry;
private bool _initialized;
public void Draw()
{ public void Draw()
if (!_initialized) {
{ if (!_initialized)
Initialize(); {
_initialized = true; Initialize();
} _initialized = true;
}
using var id = ImUtf8.PushId((int)Identifier.Type);
DrawNew(); using var id = ImUtf8.PushId((int)Identifier.Type);
DrawNew();
var height = ColumnHeight;
var skips = ImGuiClip.GetNecessarySkipsAtPos(height, ImGui.GetCursorPosY(), Count); var height = ColumnHeight;
if (skips < Count) var skips = ImGuiClip.GetNecessarySkipsAtPos(height, ImGui.GetCursorPosY(), Count);
{ if (skips < Count)
var remainder = ImGuiClip.ClippedTableDraw(Enumerate(), skips, DrawLine, Count); {
if (remainder > 0) var remainder = ImGuiClip.ClippedTableDraw(Enumerate(), skips, DrawLine, Count);
ImGuiClip.DrawEndDummy(remainder, height); if (remainder > 0)
} ImGuiClip.DrawEndDummy(remainder, height);
}
void DrawLine((TIdentifier Identifier, TEntry Value) pair)
=> DrawEntry(pair.Identifier, pair.Value); void DrawLine((TIdentifier Identifier, TEntry Value) pair)
} => DrawEntry(pair.Identifier, pair.Value);
}
public abstract ReadOnlySpan<byte> Label { get; }
public abstract int NumColumns { get; } public abstract ReadOnlySpan<byte> Label { get; }
public abstract int NumColumns { get; }
public virtual float ColumnHeight
=> ImUtf8.FrameHeightSpacing; public virtual float ColumnHeight
=> ImUtf8.FrameHeightSpacing;
protected abstract void DrawNew();
protected abstract void Initialize(); protected abstract void DrawNew();
protected abstract void DrawEntry(TIdentifier identifier, TEntry entry); protected abstract void Initialize();
protected abstract void DrawEntry(TIdentifier identifier, TEntry entry);
protected abstract IEnumerable<(TIdentifier, TEntry)> Enumerate();
protected abstract int Count { get; } protected abstract IEnumerable<(TIdentifier, TEntry)> Enumerate();
protected abstract int Count { get; }
/// <summary>
/// A number input for ids with an optional max id of given width. /// <summary>
/// Returns true if newId changed against currentId. /// A number input for ids with an optional max id of given width.
/// </summary> /// Returns true if newId changed against currentId.
protected static bool IdInput(ReadOnlySpan<byte> label, float unscaledWidth, ushort currentId, out ushort newId, int minId, int maxId, /// </summary>
bool border) protected static bool IdInput(ReadOnlySpan<byte> label, float unscaledWidth, ushort currentId, out ushort newId, int minId, int maxId,
{ bool border)
int tmp = currentId; {
ImGui.SetNextItemWidth(unscaledWidth * ImUtf8.GlobalScale); int tmp = currentId;
using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, UiHelpers.Scale, border); ImGui.SetNextItemWidth(unscaledWidth * ImUtf8.GlobalScale);
using var color = ImRaii.PushColor(ImGuiCol.Border, Colors.RegexWarningBorder, border); using var style = ImStyleBorder.Frame.Push(Colors.RegexWarningBorder, Im.Style.GlobalScale, border);
if (ImUtf8.InputScalar(label, ref tmp)) if (ImUtf8.InputScalar(label, ref tmp))
tmp = Math.Clamp(tmp, minId, maxId); tmp = Math.Clamp(tmp, minId, maxId);
newId = (ushort)tmp; newId = (ushort)tmp;
return newId != currentId; return newId != currentId;
} }
/// <summary> /// <summary>
/// A dragging int input of given width that compares against a default value, shows a tooltip and clamps against min and max. /// A dragging int input of given width that compares against a default value, shows a tooltip and clamps against min and max.
/// Returns true if newValue changed against currentValue. /// Returns true if newValue changed against currentValue.
/// </summary> /// </summary>
protected static bool DragInput<T>(ReadOnlySpan<byte> label, ReadOnlySpan<byte> tooltip, float width, T currentValue, T defaultValue, protected static bool DragInput<T>(ReadOnlySpan<byte> label, ReadOnlySpan<byte> tooltip, float width, T currentValue, T defaultValue,
out T newValue, T minValue, T maxValue, float speed, bool addDefault) where T : unmanaged, INumber<T> out T newValue, T minValue, T maxValue, float speed, bool addDefault) where T : unmanaged, INumber<T>
{ {
newValue = currentValue; newValue = currentValue;
using var color = ImRaii.PushColor(ImGuiCol.FrameBg, var c = defaultValue > currentValue ? ColorId.DecreasedMetaValue.Value() : ColorId.IncreasedMetaValue.Value();
defaultValue > currentValue ? ColorId.DecreasedMetaValue.Value() : ColorId.IncreasedMetaValue.Value(), using var color = ImGuiColor.FrameBackground.Push(c, defaultValue != currentValue);
defaultValue != currentValue); ImGui.SetNextItemWidth(width);
ImGui.SetNextItemWidth(width); if (ImUtf8.DragScalar(label, ref newValue, minValue, maxValue, speed))
if (ImUtf8.DragScalar(label, ref newValue, minValue, maxValue, speed)) newValue = newValue <= minValue ? minValue : newValue >= maxValue ? maxValue : newValue;
newValue = newValue <= minValue ? minValue : newValue >= maxValue ? maxValue : newValue;
if (addDefault)
if (addDefault) ImUtf8.HoverTooltip($"{tooltip}\nDefault Value: {defaultValue}");
ImUtf8.HoverTooltip($"{tooltip}\nDefault Value: {defaultValue}"); else
else ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, tooltip);
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, tooltip);
return newValue != currentValue;
return newValue != currentValue; }
}
/// <summary>
/// <summary> /// A checkmark that compares against a default value and shows a tooltip.
/// A checkmark that compares against a default value and shows a tooltip. /// Returns true if newValue is changed against currentValue.
/// Returns true if newValue is changed against currentValue. /// </summary>
/// </summary> protected static bool Checkmark(ReadOnlySpan<byte> label, ReadOnlySpan<byte> tooltip, bool currentValue, bool defaultValue,
protected static bool Checkmark(ReadOnlySpan<byte> label, ReadOnlySpan<byte> tooltip, bool currentValue, bool defaultValue, out bool newValue)
out bool newValue) {
{ var c = defaultValue ? ColorId.DecreasedMetaValue.Value() : ColorId.IncreasedMetaValue.Value();
using var color = ImRaii.PushColor(ImGuiCol.FrameBg, using var color = ImGuiColor.FrameBackground.Push(c, defaultValue != currentValue);
defaultValue ? ColorId.DecreasedMetaValue.Value() : ColorId.IncreasedMetaValue.Value(), newValue = currentValue;
defaultValue != currentValue); ImUtf8.Checkbox(label, ref newValue);
newValue = currentValue; ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, tooltip);
ImUtf8.Checkbox(label, ref newValue); return newValue != currentValue;
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, tooltip); }
return newValue != currentValue;
} /// <summary>
/// A checkmark that compares against a default value and shows a tooltip.
/// <summary> /// Returns true if newValue is changed against currentValue.
/// A checkmark that compares against a default value and shows a tooltip. /// </summary>
/// Returns true if newValue is changed against currentValue. protected static bool Checkmark(ReadOnlySpan<byte> label, ReadOnlySpan<char> tooltip, bool currentValue, bool defaultValue,
/// </summary> out bool newValue)
protected static bool Checkmark(ReadOnlySpan<byte> label, ReadOnlySpan<char> tooltip, bool currentValue, bool defaultValue, {
out bool newValue) var c = defaultValue != currentValue ? ColorId.DecreasedMetaValue.Value() : ColorId.IncreasedMetaValue.Value();
{ using var color = ImGuiColor.FrameBackground.Push(c, defaultValue != currentValue);
using var color = ImRaii.PushColor(ImGuiCol.FrameBg, newValue = currentValue;
defaultValue ? ColorId.DecreasedMetaValue.Value() : ColorId.IncreasedMetaValue.Value(), ImUtf8.Checkbox(label, ref newValue);
defaultValue != currentValue); ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, tooltip);
newValue = currentValue; return newValue != currentValue;
ImUtf8.Checkbox(label, ref newValue); }
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, tooltip);
return newValue != currentValue; protected void DrawMetaButtons(TIdentifier identifier, TEntry entry)
} {
ImGui.TableNextColumn();
protected void DrawMetaButtons(TIdentifier identifier, TEntry entry) CopyToClipboardButton("Copy this manipulation to clipboard."u8,
{ new Lazy<JToken?>(() => new JArray { MetaDictionary.Serialize(identifier, entry)! }));
ImGui.TableNextColumn();
CopyToClipboardButton("Copy this manipulation to clipboard."u8, new Lazy<JToken?>(() => new JArray { MetaDictionary.Serialize(identifier, entry)! })); ImGui.TableNextColumn();
if (ImUtf8.IconButton(FontAwesomeIcon.Trash, "Delete this meta manipulation."u8))
ImGui.TableNextColumn(); Editor.Changes |= Editor.Remove(identifier);
if (ImUtf8.IconButton(FontAwesomeIcon.Trash, "Delete this meta manipulation."u8)) }
Editor.Changes |= Editor.Remove(identifier);
} protected void CopyToClipboardButton(ReadOnlySpan<byte> tooltip, Lazy<JToken?> manipulations)
{
protected void CopyToClipboardButton(ReadOnlySpan<byte> tooltip, Lazy<JToken?> manipulations) if (!ImUtf8.IconButton(FontAwesomeIcon.Clipboard, tooltip))
{ return;
if (!ImUtf8.IconButton(FontAwesomeIcon.Clipboard, tooltip))
return; var text = Functions.ToCompressedBase64(manipulations.Value, 0);
if (text.Length > 0)
var text = Functions.ToCompressedBase64(manipulations.Value, 0); ImGui.SetClipboardText(text);
if (text.Length > 0) }
ImGui.SetClipboardText(text); }
}
}

View file

@ -1,5 +1,6 @@
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using ImSharp;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Text; using OtterGui.Text;
@ -161,8 +162,8 @@ public sealed class ShpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile
if (all) if (all)
{ {
using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0.05f, 0.5f)); using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0.05f, 0.5f));
ImUtf8.TextFramed("All IDs"u8, ImGui.GetColorU32(ImGuiCol.FrameBg, all || allSlots ? ImGui.GetStyle().DisabledAlpha : 1f), ImUtf8.TextFramed("All IDs"u8, ImGuiColor.FrameBackground.Get(all || allSlots ? ImGui.GetStyle().DisabledAlpha : 1f).Color,
new Vector2(unscaledWidth, 0), ImGui.GetColorU32(ImGuiCol.TextDisabled)); new Vector2(unscaledWidth, 0), ImGuiColor.TextDisabled.Get().Color);
} }
else else
{ {
@ -232,7 +233,7 @@ public sealed class ShpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile
var ret = false; var ret = false;
var ptr = Unsafe.AsPointer(ref buffer); var ptr = Unsafe.AsPointer(ref buffer);
var span = new Span<byte>(ptr, ShapeAttributeString.MaxLength + 1); var span = new Span<byte>(ptr, ShapeAttributeString.MaxLength + 1);
using (new ImRaii.ColorStyle().Push(ImGuiCol.Border, Colors.RegexWarningBorder, !valid).Push(ImGuiStyleVar.FrameBorderSize, 1f, !valid)) using (ImStyleBorder.Frame.Push(Colors.RegexWarningBorder, Im.Style.GlobalScale, !valid))
{ {
ImGui.SetNextItemWidth(unscaledWidth * ImUtf8.GlobalScale); ImGui.SetNextItemWidth(unscaledWidth * ImUtf8.GlobalScale);
if (ImUtf8.InputText("##shpShape"u8, span, out int newLength, "Shape Key..."u8)) if (ImUtf8.InputText("##shpShape"u8, span, out int newLength, "Shape Key..."u8))

View file

@ -53,7 +53,7 @@ public partial class ModEditWindow
continue; continue;
using var id = ImUtf8.PushId(index); using var id = ImUtf8.PushId(index);
using var color = ImRaii.PushColor(ImGuiCol.Text, ImGui.GetColorU32(ImGuiCol.TextDisabled), deformer.RacialDeformer.IsEmpty); using var color = ImGuiColor.Text.Push(Im.Style[ImGuiColor.TextDisabled], deformer.RacialDeformer.IsEmpty);
if (ImUtf8.Selectable(name, deformer.GenderRace == _pbdData.SelectedRaceCode)) if (ImUtf8.Selectable(name, deformer.GenderRace == _pbdData.SelectedRaceCode))
{ {
_pbdData.SelectedRaceCode = deformer.GenderRace; _pbdData.SelectedRaceCode = deformer.GenderRace;
@ -61,7 +61,7 @@ public partial class ModEditWindow
} }
Im.Line.Same(); Im.Line.Same();
color.Push(ImGuiCol.Text, metaColor); color.Push(ImGuiColor.Text, metaColor);
ImUtf8.TextRightAligned(raceCode); ImUtf8.TextRightAligned(raceCode);
} }
} }
@ -142,7 +142,7 @@ public partial class ModEditWindow
var ret = false; var ret = false;
ImUtf8.TextFrameAligned("Copy the values of the bone "u8); ImUtf8.TextFrameAligned("Copy the values of the bone "u8);
ImGui.SameLine(0, 0); ImGui.SameLine(0, 0);
using (ImRaii.PushColor(ImGuiCol.Text, ColorId.NewMod.Value())) using (ImGuiColor.Text.Push(ColorId.NewMod.Value()))
{ {
ImUtf8.TextFrameAligned(_pbdData.SelectedBone); ImUtf8.TextFrameAligned(_pbdData.SelectedBone);
} }

View file

@ -182,7 +182,7 @@ public partial class ModEditWindow
var selected = _selectedFiles.Contains(registry); var selected = _selectedFiles.Contains(registry);
var color = registry.SubModUsage.Count == 0 ? ColorId.ConflictingMod : var color = registry.SubModUsage.Count == 0 ? ColorId.ConflictingMod :
registry.CurrentUsage == registry.SubModUsage.Count ? ColorId.NewMod : ColorId.InheritedMod; registry.CurrentUsage == registry.SubModUsage.Count ? ColorId.NewMod : ColorId.InheritedMod;
using (ImRaii.PushColor(ImGuiCol.Text, color.Value())) using (ImGuiColor.Text.Push(color.Value()))
{ {
if (Im.Selectable(registry.RelPath.Path.Span, selected)) if (Im.Selectable(registry.RelPath.Path.Span, selected))
{ {
@ -290,9 +290,9 @@ public partial class ModEditWindow
{ {
Im.Line.Same(); Im.Line.Same();
ImGui.SetCursorPosX(pos); ImGui.SetCursorPosX(pos);
using (ImRaii.PushFont(UiBuilder.IconFont)) using (ImRaii.PushFont(UiBuilder.IconFont))
{ {
ImGuiUtil.TextColored(0xFF00B0B0, FontAwesomeIcon.ExclamationCircle.ToIconString()); ImGuiUtil.TextColored(0xFF00B0B0, FontAwesomeIcon.ExclamationCircle.ToIconString());
} }
ImUtf8.HoverTooltip("The game path and the file do not have the same extension."u8); ImUtf8.HoverTooltip("The game path and the file do not have the same extension."u8);
@ -333,9 +333,9 @@ public partial class ModEditWindow
{ {
Im.Line.Same(); Im.Line.Same();
ImGui.SetCursorPosX(pos); ImGui.SetCursorPosX(pos);
using (ImRaii.PushFont(UiBuilder.IconFont)) using (ImRaii.PushFont(UiBuilder.IconFont))
{ {
ImGuiUtil.TextColored(0xFF00B0B0, FontAwesomeIcon.ExclamationCircle.ToIconString()); ImGuiUtil.TextColored(0xFF00B0B0, FontAwesomeIcon.ExclamationCircle.ToIconString());
} }
ImUtf8.HoverTooltip("The game path and the file do not have the same extension."u8); ImUtf8.HoverTooltip("The game path and the file do not have the same extension."u8);

View file

@ -143,7 +143,7 @@ public partial class ModEditWindow
var text = $"{otherOptionData.TotalCount} Edits in other Options"; var text = $"{otherOptionData.TotalCount} Edits in other Options";
var size = ImGui.CalcTextSize(text).X; var size = ImGui.CalcTextSize(text).X;
ImGui.SetCursorPos(new Vector2(ImGui.GetContentRegionAvail().X - size, oldPos + ImGui.GetStyle().FramePadding.Y)); ImGui.SetCursorPos(new Vector2(ImGui.GetContentRegionAvail().X - size, oldPos + ImGui.GetStyle().FramePadding.Y));
ImGuiUtil.TextColored(ColorId.RedundantAssignment.Value() | 0xFF000000, text); Im.Text(text, ColorId.RedundantAssignment.Value().FullAlpha());
if (ImGui.IsItemHovered()) if (ImGui.IsItemHovered())
{ {
using var tt = ImUtf8.Tooltip(); using var tt = ImUtf8.Tooltip();

View file

@ -275,9 +275,9 @@ public partial class ModEditWindow
if (tab.GamePaths!.Count == 1) if (tab.GamePaths!.Count == 1)
{ {
using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f)); using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f));
using var color = ImRaii.PushColor(ImGuiCol.Button, ImGui.GetColorU32(ImGuiCol.FrameBg)) using var color = ImGuiColor.Button.Push(Im.Style[ImGuiColor.FrameBackground])
.Push(ImGuiCol.ButtonHovered, ImGui.GetColorU32(ImGuiCol.FrameBgHovered)) .Push(ImGuiColor.ButtonHovered, Im.Style[ImGuiColor.FrameBackgroundHovered])
.Push(ImGuiCol.ButtonActive, ImGui.GetColorU32(ImGuiCol.FrameBgActive)); .Push(ImGuiColor.ButtonActive, Im.Style[ImGuiColor.FrameBackgroundActive]);
using var group = ImRaii.Group(); using var group = ImRaii.Group();
ImGui.Button(preview, new Vector2(buttonWidth, 0)); ImGui.Button(preview, new Vector2(buttonWidth, 0));
ImGui.SameLine(0, ImGui.GetStyle().ItemInnerSpacing.X); ImGui.SameLine(0, ImGui.GetStyle().ItemInnerSpacing.X);
@ -310,7 +310,7 @@ public partial class ModEditWindow
var width = ImGui.CalcTextSize(text).X + framePadding.X * 2; var width = ImGui.CalcTextSize(text).X + framePadding.X * 2;
// Draw the link button. We set the background colour to transparent to mimic the look of a link. // Draw the link button. We set the background colour to transparent to mimic the look of a link.
using var color = ImRaii.PushColor(ImGuiCol.Button, 0x00000000); using var color = ImGuiColor.Button.Push(Vector4.Zero);
SupportButton.Link(Penumbra.Messager, text, address, width, ""u8); SupportButton.Link(Penumbra.Messager, text, address, width, ""u8);
// Draw an underline for the text. // Draw an underline for the text.

View file

@ -368,7 +368,7 @@ public partial class ModEditWindow
var ret = ImUtf8.CollapsingHeader(label); var ret = ImUtf8.CollapsingHeader(label);
ImGui.GetWindowDrawList() ImGui.GetWindowDrawList()
.AddText(UiBuilder.DefaultFont, UiBuilder.DefaultFont.FontSize, pos, ImGui.GetColorU32(ImGuiCol.Text), "Layout"); .AddText(UiBuilder.DefaultFont, UiBuilder.DefaultFont.FontSize, pos, ImGuiColor.Text.Get().Color, "Layout");
return ret; return ret;
} }
@ -403,7 +403,7 @@ public partial class ModEditWindow
ImGui.TableSetupColumn("w", ImGuiTableColumnFlags.WidthFixed, 250 * UiHelpers.Scale); ImGui.TableSetupColumn("w", ImGuiTableColumnFlags.WidthFixed, 250 * UiHelpers.Scale);
ImGui.TableHeadersRow(); ImGui.TableHeadersRow();
var textColorStart = ImGui.GetColorU32(ImGuiCol.Text); var textColorStart = ImGuiColor.Text.Get().Color;
var ret = false; var ret = false;
for (var i = 0; i < tab.Matrix.GetLength(0); ++i) for (var i = 0; i < tab.Matrix.GetLength(0); ++i)
@ -424,7 +424,7 @@ public partial class ModEditWindow
var deletable = !disabled && idx >= 0; var deletable = !disabled && idx >= 0;
using (ImRaii.PushFont(UiBuilder.MonoFont, tooltip.Length > 0)) using (ImRaii.PushFont(UiBuilder.MonoFont, tooltip.Length > 0))
{ {
using (ImRaii.PushColor(ImGuiCol.Text, color)) using (ImGuiColor.Text.Push(color))
{ {
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImUtf8.Selectable(name); ImUtf8.Selectable(name);

View file

@ -49,7 +49,7 @@ public partial class ModEditWindow
return; return;
using var id = ImRaii.PushId(label); using var id = ImRaii.PushId(label);
ImGuiUtil.DrawTextButton(label, new Vector2(-1, 0), ImGui.GetColorU32(ImGuiCol.FrameBg)); ImEx.TextFramed(label, new Vector2(-1, 0), ImGuiColor.FrameBackground.Get());
ImGui.NewLine(); ImGui.NewLine();
using (ImRaii.Disabled(!_center.SaveTask.IsCompleted)) using (ImRaii.Disabled(!_center.SaveTask.IsCompleted))
@ -206,7 +206,7 @@ public partial class ModEditWindow
case TaskStatus.Faulted: case TaskStatus.Faulted:
{ {
ImGui.TextUnformatted("Could not save file:"); ImGui.TextUnformatted("Could not save file:");
using var color = ImRaii.PushColor(ImGuiCol.Text, 0xFF0000FF); using var color = ImGuiColor.Text.Push(new Vector4(1, 0, 0, 1));
ImGuiUtil.TextWrapped(_center.SaveTask.Exception?.ToString() ?? "Unknown Error"); ImGuiUtil.TextWrapped(_center.SaveTask.Exception?.ToString() ?? "Unknown Error");
break; break;
} }

View file

@ -205,7 +205,7 @@ public partial class ModEditWindow : Window, IDisposable, Luna.IUiService
var offsetX = ImGui.GetContentRegionAvail().X / 2 - radius; var offsetX = ImGui.GetContentRegionAvail().X / 2 - radius;
var offsetY = ImGui.GetContentRegionAvail().Y / 2 - radius; var offsetY = ImGui.GetContentRegionAvail().Y / 2 - radius;
ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(offsetX, offsetY)); ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(offsetX, offsetY));
ImUtf8.Spinner("##spinner"u8, radius, thickness, ImGui.GetColorU32(ImGuiCol.Text)); ImEx.Spinner("##spinner"u8, radius, thickness, ImGuiColor.Text.Get());
return; return;
} }
@ -501,7 +501,7 @@ public partial class ModEditWindow : Window, IDisposable, Luna.IUiService
{ {
Im.Line.Same(); Im.Line.Same();
ImGuiUtil.DrawTextButton($"There are {otherSwaps} file swaps configured in other options.", Vector2.Zero, ImGuiUtil.DrawTextButton($"There are {otherSwaps} file swaps configured in other options.", Vector2.Zero,
ColorId.RedundantAssignment.Value()); ColorId.RedundantAssignment.Value().Color);
} }
using var child = ImRaii.Child("##swaps", -Vector2.One, true); using var child = ImRaii.Child("##swaps", -Vector2.One, true);

View file

@ -82,7 +82,7 @@ public class ModMergeTab(ModMerger modMerger) : Luna.IUiService
var color = group != null || modMerger.OptionGroupName.Length == 0 && modMerger.OptionName.Length == 0 var color = group != null || modMerger.OptionGroupName.Length == 0 && modMerger.OptionName.Length == 0
? Colors.PressEnterWarningBg ? Colors.PressEnterWarningBg
: Colors.DiscordColor; : Colors.DiscordColor;
using var c = ImRaii.PushColor(ImGuiCol.Border, color); using var c = ImGuiColor.Border.Push(color);
ImGui.SetNextItemWidth(buttonWidth); ImGui.SetNextItemWidth(buttonWidth);
ImGui.InputTextWithHint("##optionGroupInput", "Target Option Group", ref modMerger.OptionGroupName, 64); ImGui.InputTextWithHint("##optionGroupInput", "Target Option Group", ref modMerger.OptionGroupName, 64);
ImGuiUtil.HoverTooltip( ImGuiUtil.HoverTooltip(
@ -96,7 +96,7 @@ public class ModMergeTab(ModMerger modMerger) : Luna.IUiService
: group == null || group.Options.Any(o => o.Name == modMerger.OptionName) : group == null || group.Options.Any(o => o.Name == modMerger.OptionName)
? Colors.PressEnterWarningBg ? Colors.PressEnterWarningBg
: Colors.DiscordColor; : Colors.DiscordColor;
c.Push(ImGuiCol.Border, color); c.Push(ImGuiColor.Border, color);
ImGui.SetNextItemWidth(buttonWidth); ImGui.SetNextItemWidth(buttonWidth);
ImGui.InputTextWithHint("##optionInput", "Target Option Name", ref modMerger.OptionName, 64); ImGui.InputTextWithHint("##optionInput", "Target Option Name", ref modMerger.OptionName, 64);
ImGuiUtil.HoverTooltip( ImGuiUtil.HoverTooltip(
@ -249,7 +249,7 @@ public class ModMergeTab(ModMerger modMerger) : Luna.IUiService
ImGui.Separator(); ImGui.Separator();
ImGui.Dummy(Vector2.One); ImGui.Dummy(Vector2.One);
using var color = ImRaii.PushColor(ImGuiCol.Text, Colors.TutorialBorder); using var color = ImGuiColor.Text.Push(Colors.TutorialBorder);
foreach (var warning in modMerger.Warnings.SkipLast(1)) foreach (var warning in modMerger.Warnings.SkipLast(1))
{ {
ImGuiUtil.TextWrapped(warning); ImGuiUtil.TextWrapped(warning);
@ -266,7 +266,7 @@ public class ModMergeTab(ModMerger modMerger) : Luna.IUiService
ImGui.Separator(); ImGui.Separator();
ImGui.Dummy(Vector2.One); ImGui.Dummy(Vector2.One);
using var color = ImRaii.PushColor(ImGuiCol.Text, Colors.RegexWarningBorder); using var color = ImGuiColor.Text.Push(Colors.RegexWarningBorder);
ImGuiUtil.TextWrapped(modMerger.Error.ToString()); ImGuiUtil.TextWrapped(modMerger.Error.ToString());
} }
} }

View file

@ -1,9 +1,10 @@
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using OtterGui.Raii; using ImSharp;
using OtterGui.Text; using OtterGui.Text;
using OtterGui.Widgets; using OtterGui.Widgets;
using Penumbra.Mods.Editor; using Penumbra.Mods.Editor;
using Penumbra.UI.Classes; using Penumbra.UI.Classes;
using MouseWheelType = OtterGui.Widgets.MouseWheelType;
namespace Penumbra.UI.AdvancedWindow; namespace Penumbra.UI.AdvancedWindow;
@ -11,12 +12,12 @@ public sealed class OptionSelectCombo(ModEditor editor, ModEditWindow window)
: FilterComboCache<(string FullName, (int Group, int Data) Index)>( : FilterComboCache<(string FullName, (int Group, int Data) Index)>(
() => window.Mod!.AllDataContainers.Select(c => (c.GetFullName(), c.GetDataIndices())).ToList(), MouseWheelType.Control, Penumbra.Log) () => window.Mod!.AllDataContainers.Select(c => (c.GetFullName(), c.GetDataIndices())).ToList(), MouseWheelType.Control, Penumbra.Log)
{ {
private ImRaii.ColorStyle _border; private readonly Im.ColorStyleDisposable _border = new();
protected override void DrawCombo(string label, string preview, string tooltip, int currentSelected, float previewWidth, float itemHeight, protected override void DrawCombo(string label, string preview, string tooltip, int currentSelected, float previewWidth, float itemHeight,
ImGuiComboFlags flags) ImGuiComboFlags flags)
{ {
_border = ImRaii.PushFrameBorder(ImUtf8.GlobalScale, ColorId.FolderLine.Value()); _border.PushBorder(ImStyleBorder.Frame, ColorId.FolderLine.Value());
base.DrawCombo(label, preview, tooltip, currentSelected, previewWidth, itemHeight, flags); base.DrawCombo(label, preview, tooltip, currentSelected, previewWidth, itemHeight, flags);
_border.Dispose(); _border.Dispose();
} }

View file

@ -70,7 +70,7 @@ public class ResourceTreeViewer(
else if (_task.Exception != null) else if (_task.Exception != null)
{ {
ImGui.NewLine(); ImGui.NewLine();
using var color = ImRaii.PushColor(ImGuiCol.Text, Colors.RegexWarningBorder); using var color = ImGuiColor.Text.Push(Colors.RegexWarningBorder);
ImGui.TextUnformatted($"Error during calculation of character list:\n\n{_task.Exception}"); ImGui.TextUnformatted($"Error during calculation of character list:\n\n{_task.Exception}");
} }
else if (_task.IsCompletedSuccessfully) else if (_task.IsCompletedSuccessfully)
@ -82,7 +82,7 @@ public class ResourceTreeViewer(
if (!_categoryFilter.HasFlag(category) || !tree.Name.Contains(_nameFilter, StringComparison.OrdinalIgnoreCase)) if (!_categoryFilter.HasFlag(category) || !tree.Name.Contains(_nameFilter, StringComparison.OrdinalIgnoreCase))
continue; continue;
using (var c = ImRaii.PushColor(ImGuiCol.Text, CategoryColor(category).Value())) using (ImGuiColor.Text.Push(CategoryColor(category).Value()))
{ {
var isOpen = ImGui.CollapsingHeader($"{(incognito.IncognitoMode ? tree.AnonymizedName : tree.Name)}###{index}", var isOpen = ImGui.CollapsingHeader($"{(incognito.IncognitoMode ? tree.AnonymizedName : tree.Name)}###{index}",
index == 0 ? ImGuiTreeNodeFlags.DefaultOpen : 0); index == 0 ? ImGuiTreeNodeFlags.DefaultOpen : 0);
@ -164,7 +164,7 @@ public class ResourceTreeViewer(
if (!gameData.HasModifiedGameDataFiles) if (!gameData.HasModifiedGameDataFiles)
return; return;
using var style = ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudOrange); using var style = ImGuiColor.Text.Push(ImGuiColors.DalamudOrange);
ImUtf8.TextWrapped( ImUtf8.TextWrapped(
"Dalamud is reporting your FFXIV installation has modified game files. Any mods installed through TexTools will produce this message."u8); "Dalamud is reporting your FFXIV installation has modified game files. Any mods installed through TexTools will produce this message."u8);
@ -189,18 +189,18 @@ public class ResourceTreeViewer(
var checkPadding = 10 * ImGuiHelpers.GlobalScale + ImGui.GetStyle().ItemSpacing.X; var checkPadding = 10 * ImGuiHelpers.GlobalScale + ImGui.GetStyle().ItemSpacing.X;
ImGui.SameLine(0, checkPadding); ImGui.SameLine(0, checkPadding);
using (var id = ImRaii.PushId("TreeCategoryFilter")) using (ImRaii.PushId("TreeCategoryFilter"))
{ {
var categoryFilter = (uint)_categoryFilter; var categoryFilter = (uint)_categoryFilter;
foreach (var category in Enum.GetValues<TreeCategory>()) foreach (var category in Enum.GetValues<TreeCategory>())
{ {
using var c = ImRaii.PushColor(ImGuiCol.CheckMark, CategoryColor(category).Value()); using var c = ImGuiColor.CheckMark.Push(CategoryColor(category).Value());
ImGui.CheckboxFlags($"##{category}", ref categoryFilter, (uint)category); ImGui.CheckboxFlags($"##{category}", ref categoryFilter, (uint)category);
ImGuiUtil.HoverTooltip(CategoryFilterDescription(category)); ImGuiUtil.HoverTooltip(CategoryFilterDescription(category));
ImGui.SameLine(0.0f, checkSpacing); ImGui.SameLine(0.0f, checkSpacing);
} }
_categoryFilter = (TreeCategory)categoryFilter; _categoryFilter = (TreeCategory)categoryFilter;
} }
ImGui.SameLine(0, checkPadding); ImGui.SameLine(0, checkPadding);
@ -257,7 +257,7 @@ public class ResourceTreeViewer(
if (visibility == NodeVisibility.Hidden) if (visibility == NodeVisibility.Hidden)
continue; continue;
using var mutedColor = ImRaii.PushColor(ImGuiCol.Text, ImGuiUtil.HalfTransparentText(), resourceNode.Internal); using var mutedColor = ImGuiColor.Text.Push(ImGuiUtil.HalfTransparentText(), resourceNode.Internal);
var filterIcon = resourceNode.IconFlag != 0 ? resourceNode.IconFlag : parentFilterIconFlag; var filterIcon = resourceNode.IconFlag != 0 ? resourceNode.IconFlag : parentFilterIconFlag;
@ -335,7 +335,7 @@ public class ResourceTreeViewer(
var modName = $"[{(hasMod ? mod!.Name : resourceNode.ModName)}]"; var modName = $"[{(hasMod ? mod!.Name : resourceNode.ModName)}]";
var textPos = ImGui.GetCursorPosX() + ImUtf8.CalcTextSize(modName).X + ImGui.GetStyle().ItemInnerSpacing.X; var textPos = ImGui.GetCursorPosX() + ImUtf8.CalcTextSize(modName).X + ImGui.GetStyle().ItemInnerSpacing.X;
using var group = ImUtf8.Group(); using var group = ImUtf8.Group();
using (var color = ImRaii.PushColor(ImGuiCol.Text, (hasMod ? ColorId.NewMod : ColorId.DisabledMod).Value())) using (ImGuiColor.Text.Push((hasMod ? ColorId.NewMod : ColorId.DisabledMod).Value()))
{ {
ImUtf8.Selectable(modName, false, ImGuiSelectableFlags.AllowItemOverlap, ImUtf8.Selectable(modName, false, ImGuiSelectableFlags.AllowItemOverlap,
new Vector2(ImGui.GetContentRegionAvail().X, frameHeight)); new Vector2(ImGui.GetContentRegionAvail().X, frameHeight));

View file

@ -144,7 +144,7 @@ public class ChangedItemDrawer : IDisposable, IUiService
Im.Line.Same(); Im.Line.Same();
using var color = ImGuiColor.Text.Push(ColorId.ItemId.Value()); using var color = ImGuiColor.Text.Push(ColorId.ItemId.Value());
Im.Cursor.Y += height - Im.Style.TextHeight / 2; Im.Cursor.Y += (height - Im.Style.TextHeight) / 2;
ImEx.TextRightAligned(additionalData, Im.Style.ItemInnerSpacing.X); ImEx.TextRightAligned(additionalData, Im.Style.ItemInnerSpacing.X);
} }
@ -156,7 +156,7 @@ public class ChangedItemDrawer : IDisposable, IUiService
Im.Line.Same(); Im.Line.Same();
using var color = ImGuiColor.Text.Push(ColorId.ItemId.Value()); using var color = ImGuiColor.Text.Push(ColorId.ItemId.Value());
Im.Cursor.Y += height - Im.Style.TextHeight / 2; Im.Cursor.Y += (height - Im.Style.TextHeight) / 2;
ImEx.TextRightAligned(text, Im.Style.ItemInnerSpacing.X); ImEx.TextRightAligned(text, Im.Style.ItemInnerSpacing.X);
} }

View file

@ -136,7 +136,7 @@ public class MigrationSectionDrawer(MigrationManager migrationManager, Configura
return; return;
Im.Line.Same(); Im.Line.Same();
ImUtf8.Spinner("Spinner"u8, ImGui.GetTextLineHeight() / 2, 2, ImGui.GetColorU32(ImGuiCol.Text)); ImEx.Spinner("Spinner"u8, ImGui.GetTextLineHeight() / 2, 2, ImGuiColor.Text.Get());
} }
private void DrawCancelButton(MigrationManager.TaskType task, ReadOnlySpan<byte> tooltip) private void DrawCancelButton(MigrationManager.TaskType task, ReadOnlySpan<byte> tooltip)

View file

@ -283,7 +283,7 @@ public sealed class CollectionPanel(
if (!context) if (!context)
return; return;
using (var color = ImRaii.PushColor(ImGuiCol.Text, Colors.DiscordColor)) using (var color = ImGuiColor.Text.Push(Colors.DiscordColor))
{ {
if (ImGui.MenuItem("Use no mods.")) if (ImGui.MenuItem("Use no mods."))
_active.SetCollection(ModCollection.Empty, type, _active.Individuals.GetGroup(identifier)); _active.SetCollection(ModCollection.Empty, type, _active.Individuals.GetGroup(identifier));
@ -291,7 +291,7 @@ public sealed class CollectionPanel(
if (collection != null && type.CanBeRemoved()) if (collection != null && type.CanBeRemoved())
{ {
using var color = ImRaii.PushColor(ImGuiCol.Text, Colors.RegexWarningBorder); using var color = ImGuiColor.Text.Push(Colors.RegexWarningBorder);
if (ImGui.MenuItem("Remove this assignment.")) if (ImGui.MenuItem("Remove this assignment."))
_active.SetCollection(null, type, _active.Individuals.GetGroup(identifier)); _active.SetCollection(null, type, _active.Individuals.GetGroup(identifier));
} }
@ -303,15 +303,15 @@ public sealed class CollectionPanel(
} }
} }
private bool DrawButton(string text, CollectionType type, Vector2 width, uint borderColor, ActorIdentifier id, char suffix, private bool DrawButton(string text, CollectionType type, Vector2 width, Rgba32 borderColor, ActorIdentifier id, char suffix,
ModCollection? collection = null) ModCollection? collection = null)
{ {
using var group = ImRaii.Group(); using var group = ImRaii.Group();
var invalid = type == CollectionType.Individual && !id.IsValid; var invalid = type == CollectionType.Individual && !id.IsValid;
var redundancy = _active.RedundancyCheck(type, id); var redundancy = _active.RedundancyCheck(type, id);
collection ??= _active.ByType(type, id); collection ??= _active.ByType(type, id);
using var color = ImRaii.PushColor(ImGuiCol.Button, using var color = ImGuiColor.Button.Push(
collection == null collection is null
? ColorId.NoAssignment.Value() ? ColorId.NoAssignment.Value()
: redundancy.Length > 0 : redundancy.Length > 0
? ColorId.RedundantAssignment.Value() ? ColorId.RedundantAssignment.Value()
@ -319,8 +319,8 @@ public sealed class CollectionPanel(
? ColorId.SelectedCollection.Value() ? ColorId.SelectedCollection.Value()
: collection == ModCollection.Empty : collection == ModCollection.Empty
? ColorId.NoModsAssignment.Value() ? ColorId.NoModsAssignment.Value()
: ImGui.GetColorU32(ImGuiCol.Button), !invalid) : ImGuiColor.Button.Get(), !invalid)
.Push(ImGuiCol.Border, borderColor == 0 ? ImGui.GetColorU32(ImGuiCol.TextDisabled) : borderColor); .Push(ImGuiColor.Border, borderColor == 0 ? ImGuiColor.TextDisabled.Get().Color : borderColor);
using var disabled = ImRaii.Disabled(invalid); using var disabled = ImRaii.Disabled(invalid);
var button = ImGui.Button(text, width) || ImGui.IsItemClicked(ImGuiMouseButton.Right); var button = ImGui.Button(text, width) || ImGui.IsItemClicked(ImGuiMouseButton.Right);
var hovered = redundancy.Length > 0 && ImGui.IsItemHovered(); var hovered = redundancy.Length > 0 && ImGui.IsItemHovered();
@ -332,7 +332,7 @@ public sealed class CollectionPanel(
var name = Name(collection); var name = Name(collection);
var size = ImGui.CalcTextSize(name); var size = ImGui.CalcTextSize(name);
var textPos = ImGui.GetItemRectMax() - size - ImGui.GetStyle().FramePadding; var textPos = ImGui.GetItemRectMax() - size - ImGui.GetStyle().FramePadding;
ImGui.GetWindowDrawList().AddText(textPos, ImGui.GetColorU32(ImGuiCol.Text), name); ImGui.GetWindowDrawList().AddText(textPos, ImGuiColor.Text.Get().Color, name);
DrawContext(button, collection, type, id, text, suffix); DrawContext(button, collection, type, id, text, suffix);
} }
@ -484,7 +484,7 @@ public sealed class CollectionPanel(
private void DrawCollectionName(ModCollection collection) private void DrawCollectionName(ModCollection collection)
{ {
ImGui.Dummy(Vector2.One); ImGui.Dummy(Vector2.One);
using var color = ImRaii.PushColor(ImGuiCol.Border, Colors.MetaInfoText); using var color = ImGuiColor.Border.Push(Colors.MetaInfoText);
using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, 2 * UiHelpers.Scale); using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, 2 * UiHelpers.Scale);
using var f = _nameFont.Push(); using var f = _nameFont.Push();
var name = Name(collection); var name = Name(collection);
@ -574,7 +574,7 @@ public sealed class CollectionPanel(
using var f = _nameFont.Push(); using var f = _nameFont.Push();
using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, ImGuiHelpers.GlobalScale); using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, ImGuiHelpers.GlobalScale);
using var color = ImRaii.PushColor(ImGuiCol.Border, Colors.MetaInfoText); using var color = ImGuiColor.Border.Push(Colors.MetaInfoText);
ImGuiUtil.DrawTextButton(Name(collection.Inheritance.DirectlyInheritedBy[0]), Vector2.Zero, 0); ImGuiUtil.DrawTextButton(Name(collection.Inheritance.DirectlyInheritedBy[0]), Vector2.Zero, 0);
var constOffset = (ImGui.GetStyle().FramePadding.X + ImGuiHelpers.GlobalScale) * 2 var constOffset = (ImGui.GetStyle().FramePadding.X + ImGuiHelpers.GlobalScale) * 2
+ ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().ItemSpacing.X

View file

@ -1,4 +1,5 @@
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using ImSharp;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.Collections; using Penumbra.Collections;
@ -75,7 +76,7 @@ public sealed class CollectionSelector : ItemSelector<ModCollection>, IDisposabl
protected override bool OnDraw(int idx) protected override bool OnDraw(int idx)
{ {
using var color = ImRaii.PushColor(ImGuiCol.Header, ColorId.SelectedCollection.Value()); using var color = ImGuiColor.Header.Push(ColorId.SelectedCollection.Value());
var ret = ImGui.Selectable(Name(Items[idx]), idx == CurrentIdx); var ret = ImGui.Selectable(Name(Items[idx]), idx == CurrentIdx);
using var source = ImRaii.DragDropSource(); using var source = ImRaii.DragDropSource();

View file

@ -24,7 +24,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService
{ {
using var id = ImRaii.PushId("##Inheritance"); using var id = ImRaii.PushId("##Inheritance");
ImGuiUtil.DrawColoredText(($"The {TutorialService.SelectedCollection} ", 0), ImGuiUtil.DrawColoredText(($"The {TutorialService.SelectedCollection} ", 0),
(Name(_active.Current), ColorId.SelectedCollection.Value() | 0xFF000000), (" inherits from:", 0)); (Name(_active.Current), ColorId.SelectedCollection.Value().FullAlpha().Color), (" inherits from:", 0));
ImGui.Dummy(Vector2.One); ImGui.Dummy(Vector2.One);
DrawCurrentCollectionInheritance(); DrawCurrentCollectionInheritance();
@ -111,7 +111,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService
foreach (var inheritance in collection.Inheritance.FlatHierarchy.Skip(1)) foreach (var inheritance in collection.Inheritance.FlatHierarchy.Skip(1))
{ {
// Draw the child, already seen collections are colored as conflicts. // Draw the child, already seen collections are colored as conflicts.
using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.HandledConflictMod.Value(), using var color = ImGuiColor.Text.Push(ColorId.HandledConflictMod.Value(),
_seenInheritedCollections.Contains(inheritance)); _seenInheritedCollections.Contains(inheritance));
_seenInheritedCollections.Add(inheritance); _seenInheritedCollections.Add(inheritance);
@ -138,7 +138,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService
/// <summary> Draw a single primary inherited collection. </summary> /// <summary> Draw a single primary inherited collection. </summary>
private void DrawInheritance(ModCollection collection) private void DrawInheritance(ModCollection collection)
{ {
using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.HandledConflictMod.Value(), using var color = ImGuiColor.Text.Push(ColorId.HandledConflictMod.Value(),
_seenInheritedCollections.Contains(collection)); _seenInheritedCollections.Contains(collection));
_seenInheritedCollections.Add(collection); _seenInheritedCollections.Add(collection);
using var tree = ImRaii.TreeNode($"{Name(collection)}###{collection.Identity.Name}", ImGuiTreeNodeFlags.NoTreePushOnOpen); using var tree = ImRaii.TreeNode($"{Name(collection)}###{collection.Identity.Name}", ImGuiTreeNodeFlags.NoTreePushOnOpen);
@ -172,10 +172,10 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService
private void DrawInheritanceTrashButton() private void DrawInheritanceTrashButton()
{ {
var size = UiHelpers.IconButtonSize with { Y = ImGui.GetTextLineHeightWithSpacing() * InheritedCollectionHeight }; var size = UiHelpers.IconButtonSize with { Y = ImGui.GetTextLineHeightWithSpacing() * InheritedCollectionHeight };
var buttonColor = ImGui.GetColorU32(ImGuiCol.Button); var buttonColor = Im.Style[ImGuiColor.Button];
// Prevent hovering from highlighting the button. // Prevent hovering from highlighting the button.
using var color = ImRaii.PushColor(ImGuiCol.ButtonActive, buttonColor) using var color = ImGuiColor.ButtonActive.Push(buttonColor)
.Push(ImGuiCol.ButtonHovered, buttonColor); .Push(ImGuiColor.ButtonHovered, buttonColor);
ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), size, ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), size,
"Drag primary inheritance here to remove it from the list.", false, true); "Drag primary inheritance here to remove it from the list.", false, true);

View file

@ -140,7 +140,7 @@ public sealed class ConfigWindow : Window, Luna.IUiService
private void DrawProblemWindow(string text) private void DrawProblemWindow(string text)
{ {
using var color = ImRaii.PushColor(ImGuiCol.Text, Colors.RegexWarningBorder); using var color = ImGuiColor.Text.Push(Colors.RegexWarningBorder);
ImGui.NewLine(); ImGui.NewLine();
ImGui.NewLine(); ImGui.NewLine();
ImUtf8.TextWrapped(text); ImUtf8.TextWrapped(text);

View file

@ -23,7 +23,7 @@ public readonly struct ImcModGroupEditDrawer(ModGroupEditDrawer editor, ImcModGr
var changes = false; var changes = false;
var width = editor.AvailableWidth.X - 3 * ImUtf8.ItemInnerSpacing.X - ImUtf8.ItemSpacing.X - ImUtf8.CalcTextSize("All Variants"u8).X - ImUtf8.CalcTextSize("Only Attributes"u8).X - 2 * ImUtf8.FrameHeight; var width = editor.AvailableWidth.X - 3 * ImUtf8.ItemInnerSpacing.X - ImUtf8.ItemSpacing.X - ImUtf8.CalcTextSize("All Variants"u8).X - ImUtf8.CalcTextSize("Only Attributes"u8).X - 2 * ImUtf8.FrameHeight;
ImUtf8.TextFramed(identifier.ToString(), 0, new Vector2(width, 0), borderColor: ImGui.GetColorU32(ImGuiCol.Border)); ImEx.TextFramed(identifier.ToString(), new Vector2(width, 0), Rgba32.Transparent);
ImUtf8.SameLineInner(); ImUtf8.SameLineInner();
var allVariants = group.AllVariants; var allVariants = group.AllVariants;
@ -175,7 +175,7 @@ public readonly struct ImcModGroupEditDrawer(ModGroupEditDrawer editor, ImcModGr
protected override void RenderSymbol(bool value, Vector2 position, float size) protected override void RenderSymbol(bool value, Vector2 position, float size)
{ {
if (value) if (value)
SymbolHelpers.RenderCross(ImGui.GetWindowDrawList(), position, ImGui.GetColorU32(ImGuiCol.CheckMark), size); SymbolHelpers.RenderCross(ImGui.GetWindowDrawList(), position, ImGuiColor.CheckMark.Get().Color, size);
} }
protected override bool NextValue(bool value) protected override bool NextValue(bool value)

View file

@ -836,7 +836,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
ImGui.SetCursorPos(comboPos); ImGui.SetCursorPos(comboPos);
// Draw combo button // Draw combo button
using var color = ImRaii.PushColor(ImGuiCol.Button, Colors.FilterActive, !everything); using var color = ImGuiColor.Button.Push(Colors.FilterActive, !everything);
var rightClick = DrawFilterCombo(ref everything); var rightClick = DrawFilterCombo(ref everything);
_tutorial.OpenTutorial(BasicTutorialSteps.ModFilters); _tutorial.OpenTutorial(BasicTutorialSteps.ModFilters);
if (rightClick) if (rightClick)

View file

@ -1,347 +1,356 @@
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Utility.Raii;
using OtterGui; using ImSharp;
using OtterGui.Services; using Luna;
using OtterGui.Text; using OtterGui;
using OtterGui.Widgets; using OtterGui.Services;
using Penumbra.GameData.Data; using OtterGui.Text;
using Penumbra.GameData.Enums; using OtterGui.Widgets;
using Penumbra.GameData.Structs; using Penumbra.GameData.Data;
using Penumbra.Mods; using Penumbra.GameData.Enums;
using Penumbra.Mods.Manager; using Penumbra.GameData.Structs;
using Penumbra.String; using Penumbra.Mods;
using Penumbra.UI.Classes; using Penumbra.Mods.Manager;
using Penumbra.String;
namespace Penumbra.UI.ModsTab; using Penumbra.UI.Classes;
public class ModPanelChangedItemsTab( namespace Penumbra.UI.ModsTab;
ModFileSystemSelector selector,
ChangedItemDrawer drawer, public class ModPanelChangedItemsTab(
ImGuiCacheService cacheService, ModFileSystemSelector selector,
Configuration config, ChangedItemDrawer drawer,
ModDataEditor dataEditor) ImGuiCacheService cacheService,
: ITab, Luna.IUiService Configuration config,
{ ModDataEditor dataEditor)
private readonly ImGuiCacheService.CacheId _cacheId = cacheService.GetNewId(); : ITab, Luna.IUiService
{
private class ChangedItemsCache private readonly ImGuiCacheService.CacheId _cacheId = cacheService.GetNewId();
{
private Mod? _lastSelected; private class ChangedItemsCache
private ushort _lastUpdate; {
private ChangedItemIconFlag _filter = ChangedItemFlagExtensions.DefaultFlags; private Mod? _lastSelected;
private ChangedItemMode _lastMode; private ushort _lastUpdate;
private bool _reset; private ChangedItemIconFlag _filter = ChangedItemFlagExtensions.DefaultFlags;
public readonly List<Container> Data = []; private ChangedItemMode _lastMode;
public bool AnyExpandable { get; private set; } private bool _reset;
public readonly List<Container> Data = [];
public record struct Container public bool AnyExpandable { get; private set; }
{
public IIdentifiedObjectData Data; public record struct Container
public ByteString Text; {
public ByteString ModelData; public IIdentifiedObjectData Data;
public uint Id; public ByteString Text;
public int Children; public ByteString ModelData;
public ChangedItemIconFlag Icon; public uint Id;
public bool Expandable; public int Children;
public bool Expanded; public ChangedItemIconFlag Icon;
public bool Child; public bool Expandable;
public bool Expanded;
public static Container Single(string text, IIdentifiedObjectData data) public bool Child;
=> new()
{ public static Container Single(string text, IIdentifiedObjectData data)
Child = false, => new()
Text = ByteString.FromStringUnsafe(data.ToName(text), false), {
ModelData = ByteString.FromStringUnsafe(data.AdditionalData, false), Child = false,
Icon = data.GetIcon().ToFlag(), Text = ByteString.FromStringUnsafe(data.ToName(text), false),
Expandable = false, ModelData = ByteString.FromStringUnsafe(data.AdditionalData, false),
Expanded = false, Icon = data.GetIcon().ToFlag(),
Data = data, Expandable = false,
Id = 0, Expanded = false,
Children = 0, Data = data,
}; Id = 0,
Children = 0,
public static Container Parent(string text, IIdentifiedObjectData data, uint id, int children, bool expanded) };
=> new()
{ public static Container Parent(string text, IIdentifiedObjectData data, uint id, int children, bool expanded)
Child = false, => new()
Text = ByteString.FromStringUnsafe(data.ToName(text), false), {
ModelData = ByteString.FromStringUnsafe(data.AdditionalData, false), Child = false,
Icon = data.GetIcon().ToFlag(), Text = ByteString.FromStringUnsafe(data.ToName(text), false),
Expandable = true, ModelData = ByteString.FromStringUnsafe(data.AdditionalData, false),
Expanded = expanded, Icon = data.GetIcon().ToFlag(),
Data = data, Expandable = true,
Id = id, Expanded = expanded,
Children = children, Data = data,
}; Id = id,
Children = children,
public static Container Indent(string text, IIdentifiedObjectData data) };
=> new()
{ public static Container Indent(string text, IIdentifiedObjectData data)
Child = true, => new()
Text = ByteString.FromStringUnsafe(data.ToName(text), false), {
ModelData = ByteString.FromStringUnsafe(data.AdditionalData, false), Child = true,
Icon = data.GetIcon().ToFlag(), Text = ByteString.FromStringUnsafe(data.ToName(text), false),
Expandable = false, ModelData = ByteString.FromStringUnsafe(data.AdditionalData, false),
Expanded = false, Icon = data.GetIcon().ToFlag(),
Data = data, Expandable = false,
Id = 0, Expanded = false,
Children = 0, Data = data,
}; Id = 0,
} Children = 0,
};
public void Reset() }
=> _reset = true;
public void Reset()
public void Update(Mod? mod, ChangedItemDrawer drawer, ChangedItemIconFlag filter, ChangedItemMode mode) => _reset = true;
{
if (mod == _lastSelected public void Update(Mod? mod, ChangedItemDrawer drawer, ChangedItemIconFlag filter, ChangedItemMode mode)
&& _lastSelected!.LastChangedItemsUpdate == _lastUpdate {
&& _filter == filter if (mod == _lastSelected
&& !_reset && _lastSelected!.LastChangedItemsUpdate == _lastUpdate
&& _lastMode == mode) && _filter == filter
return; && !_reset
&& _lastMode == mode)
_reset = false; return;
Data.Clear();
AnyExpandable = false; _reset = false;
_lastSelected = mod; Data.Clear();
_filter = filter; AnyExpandable = false;
_lastMode = mode; _lastSelected = mod;
if (_lastSelected == null) _filter = filter;
return; _lastMode = mode;
if (_lastSelected == null)
_lastUpdate = _lastSelected.LastChangedItemsUpdate; return;
if (mode is ChangedItemMode.Alphabetical) _lastUpdate = _lastSelected.LastChangedItemsUpdate;
{
foreach (var (s, i) in _lastSelected.ChangedItems) if (mode is ChangedItemMode.Alphabetical)
{ {
if (drawer.FilterChangedItem(s, i, string.Empty)) foreach (var (s, i) in _lastSelected.ChangedItems)
Data.Add(Container.Single(s, i)); {
} if (drawer.FilterChangedItem(s, i, string.Empty))
Data.Add(Container.Single(s, i));
return; }
}
return;
var tmp = new Dictionary<(PrimaryId, FullEquipType), List<IdentifiedItem>>(); }
var defaultExpansion = _lastMode is ChangedItemMode.GroupedExpanded;
foreach (var (s, i) in _lastSelected.ChangedItems) var tmp = new Dictionary<(PrimaryId, FullEquipType), List<IdentifiedItem>>();
{ var defaultExpansion = _lastMode is ChangedItemMode.GroupedExpanded;
if (i is not IdentifiedItem item) foreach (var (s, i) in _lastSelected.ChangedItems)
continue; {
if (i is not IdentifiedItem item)
if (!drawer.FilterChangedItem(s, item, string.Empty)) continue;
continue;
if (!drawer.FilterChangedItem(s, item, string.Empty))
if (tmp.TryGetValue((item.Item.PrimaryId, item.Item.Type), out var p)) continue;
p.Add(item);
else if (tmp.TryGetValue((item.Item.PrimaryId, item.Item.Type), out var p))
tmp[(item.Item.PrimaryId, item.Item.Type)] = [item]; p.Add(item);
} else
tmp[(item.Item.PrimaryId, item.Item.Type)] = [item];
foreach (var list in tmp.Values) }
{
list.Sort((i1, i2) => foreach (var list in tmp.Values)
{ {
// reversed list.Sort((i1, i2) =>
var preferred = _lastSelected.PreferredChangedItems.Contains(i2.Item.Id) {
.CompareTo(_lastSelected.PreferredChangedItems.Contains(i1.Item.Id)); // reversed
if (preferred != 0) var preferred = _lastSelected.PreferredChangedItems.Contains(i2.Item.Id)
return preferred; .CompareTo(_lastSelected.PreferredChangedItems.Contains(i1.Item.Id));
if (preferred != 0)
// reversed return preferred;
var count = i2.Count.CompareTo(i1.Count);
if (count != 0) // reversed
return count; var count = i2.Count.CompareTo(i1.Count);
if (count != 0)
return string.Compare(i1.Item.Name, i2.Item.Name, StringComparison.Ordinal); return count;
});
} return string.Compare(i1.Item.Name, i2.Item.Name, StringComparison.Ordinal);
});
var sortedTmp = tmp.Values.OrderBy(s => s[0].Item.Name).ToArray(); }
var sortedTmpIdx = 0; var sortedTmp = tmp.Values.OrderBy(s => s[0].Item.Name).ToArray();
foreach (var (s, i) in _lastSelected.ChangedItems)
{ var sortedTmpIdx = 0;
if (i is IdentifiedItem) foreach (var (s, i) in _lastSelected.ChangedItems)
continue; {
if (i is IdentifiedItem)
if (!drawer.FilterChangedItem(s, i, string.Empty)) continue;
continue;
if (!drawer.FilterChangedItem(s, i, string.Empty))
while (sortedTmpIdx < sortedTmp.Length continue;
&& string.Compare(sortedTmp[sortedTmpIdx][0].Item.Name, s, StringComparison.Ordinal) <= 0)
AddList(sortedTmp[sortedTmpIdx++]); while (sortedTmpIdx < sortedTmp.Length
&& string.Compare(sortedTmp[sortedTmpIdx][0].Item.Name, s, StringComparison.Ordinal) <= 0)
Data.Add(Container.Single(s, i)); AddList(sortedTmp[sortedTmpIdx++]);
}
Data.Add(Container.Single(s, i));
for (; sortedTmpIdx < sortedTmp.Length; ++sortedTmpIdx) }
AddList(sortedTmp[sortedTmpIdx]);
return; for (; sortedTmpIdx < sortedTmp.Length; ++sortedTmpIdx)
AddList(sortedTmp[sortedTmpIdx]);
void AddList(List<IdentifiedItem> list) return;
{
var mainItem = list[0]; void AddList(List<IdentifiedItem> list)
if (list.Count == 1) {
{ var mainItem = list[0];
Data.Add(Container.Single(mainItem.Item.Name, mainItem)); if (list.Count == 1)
} {
else Data.Add(Container.Single(mainItem.Item.Name, mainItem));
{ }
var id = ImUtf8.GetId($"{mainItem.Item.PrimaryId}{(int)mainItem.Item.Type}"); else
var expanded = ImGui.GetStateStorage().GetBool(id, defaultExpansion); {
Data.Add(Container.Parent(mainItem.Item.Name, mainItem, id, list.Count - 1, expanded)); var id = ImUtf8.GetId($"{mainItem.Item.PrimaryId}{(int)mainItem.Item.Type}");
AnyExpandable = true; var expanded = ImGui.GetStateStorage().GetBool(id, defaultExpansion);
if (!expanded) Data.Add(Container.Parent(mainItem.Item.Name, mainItem, id, list.Count - 1, expanded));
return; AnyExpandable = true;
if (!expanded)
foreach (var item in list.Skip(1)) return;
Data.Add(Container.Indent(item.Item.Name, item));
} foreach (var item in list.Skip(1))
} Data.Add(Container.Indent(item.Item.Name, item));
} }
} }
}
public ReadOnlySpan<byte> Label }
=> "Changed Items"u8;
public ReadOnlySpan<byte> Label
public bool IsVisible => "Changed Items"u8;
=> selector.Selected!.ChangedItems.Count > 0;
public bool IsVisible
private ImGuiStoragePtr _stateStorage; => selector.Selected!.ChangedItems.Count > 0;
private Vector2 _buttonSize; private ImGuiStoragePtr _stateStorage;
private uint _starColor;
private Vector2 _buttonSize;
public void DrawContent() private Rgba32 _starColor;
{
if (cacheService.Cache(_cacheId, () => (new ChangedItemsCache(), "ModPanelChangedItemsCache")) is not { } cache) public void DrawContent()
return; {
if (cacheService.Cache(_cacheId, () => (new ChangedItemsCache(), "ModPanelChangedItemsCache")) is not { } cache)
drawer.DrawTypeFilter(); return;
_stateStorage = ImGui.GetStateStorage(); drawer.DrawTypeFilter();
cache.Update(selector.Selected, drawer, config.Ephemeral.ChangedItemFilter, config.ChangedItemDisplay);
ImGui.Separator(); _stateStorage = ImGui.GetStateStorage();
_buttonSize = new Vector2(ImGui.GetStyle().ItemSpacing.Y + ImGui.GetFrameHeight()); cache.Update(selector.Selected, drawer, config.Ephemeral.ChangedItemFilter, config.ChangedItemDisplay);
using var style = ImRaii.PushStyle(ImGuiStyleVar.CellPadding, Vector2.Zero) ImGui.Separator();
.Push(ImGuiStyleVar.ItemSpacing, Vector2.Zero) _buttonSize = new Vector2(ImGui.GetStyle().ItemSpacing.Y + ImGui.GetFrameHeight());
.Push(ImGuiStyleVar.FramePadding, Vector2.Zero) using var style = ImRaii.PushStyle(ImGuiStyleVar.CellPadding, Vector2.Zero)
.Push(ImGuiStyleVar.SelectableTextAlign, new Vector2(0.01f, 0.5f)); .Push(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
using var color = ImRaii.PushColor(ImGuiCol.Button, 0); .Push(ImGuiStyleVar.FramePadding, Vector2.Zero)
.Push(ImGuiStyleVar.SelectableTextAlign, new Vector2(0.01f, 0.5f));
using var table = ImUtf8.Table("##changedItems"u8, cache.AnyExpandable ? 2 : 1, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY, using var color = ImGuiColor.Button.Push(Rgba32.Transparent)
new Vector2(ImGui.GetContentRegionAvail().X, -1)); .Push(ImGuiColor.ButtonActive, Rgba32.Transparent)
if (!table) .Push(ImGuiColor.ButtonHovered, Rgba32.Transparent);
return;
using var table = ImUtf8.Table("##changedItems"u8, cache.AnyExpandable ? 2 : 1, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY,
_starColor = ColorId.ChangedItemPreferenceStar.Value(); new Vector2(ImGui.GetContentRegionAvail().X, -1));
if (cache.AnyExpandable) if (!table)
{ return;
ImUtf8.TableSetupColumn("##exp"u8, ImGuiTableColumnFlags.WidthFixed, _buttonSize.Y);
ImUtf8.TableSetupColumn("##text"u8, ImGuiTableColumnFlags.WidthStretch); _starColor = ColorId.ChangedItemPreferenceStar.Value();
ImGuiClip.ClippedDraw(cache.Data, DrawContainerExpandable, _buttonSize.Y); if (cache.AnyExpandable)
} {
else ImUtf8.TableSetupColumn("##exp"u8, ImGuiTableColumnFlags.WidthFixed, _buttonSize.Y);
{ ImUtf8.TableSetupColumn("##text"u8, ImGuiTableColumnFlags.WidthStretch);
ImGuiClip.ClippedDraw(cache.Data, DrawContainer, _buttonSize.Y); ImGuiClip.ClippedDraw(cache.Data, DrawContainerExpandable, _buttonSize.Y);
} }
} else
{
private void DrawContainerExpandable(ChangedItemsCache.Container obj, int idx) ImGuiClip.ClippedDraw(cache.Data, DrawContainer, _buttonSize.Y);
{ }
using var id = ImUtf8.PushId(idx); }
ImGui.TableNextColumn();
if (obj.Expandable) private void DrawContainerExpandable(ChangedItemsCache.Container obj, int idx)
{ {
if (ImUtf8.IconButton(obj.Expanded ? FontAwesomeIcon.CaretDown : FontAwesomeIcon.CaretRight, using var id = ImUtf8.PushId(idx);
obj.Expanded ? "Hide the other items using the same model." : ImGui.TableNextColumn();
obj.Children > 1 ? $"Show {obj.Children} other items using the same model." : if (obj.Expandable)
"Show one other item using the same model.", {
_buttonSize)) if (ImUtf8.IconButton(obj.Expanded ? FontAwesomeIcon.CaretDown : FontAwesomeIcon.CaretRight,
{ obj.Expanded ? "Hide the other items using the same model." :
_stateStorage.SetBool(obj.Id, !obj.Expanded); obj.Children > 1 ? $"Show {obj.Children} other items using the same model." :
if (cacheService.TryGetCache<ChangedItemsCache>(_cacheId, out var cache)) "Show one other item using the same model.",
cache.Reset(); _buttonSize))
} {
} _stateStorage.SetBool(obj.Id, !obj.Expanded);
else if (obj is { Child: true, Data: IdentifiedItem item }) if (cacheService.TryGetCache<ChangedItemsCache>(_cacheId, out var cache))
{ cache.Reset();
DrawPreferredButton(item, idx); }
} }
else else if (obj is { Child: true, Data: IdentifiedItem item })
{ {
ImGui.Dummy(_buttonSize); DrawPreferredButton(item, idx);
} }
else
DrawBaseContainer(obj, idx); {
} ImGui.Dummy(_buttonSize);
}
private void DrawContainer(ChangedItemsCache.Container obj, int idx)
{ DrawBaseContainer(obj, idx);
using var id = ImUtf8.PushId(idx); }
DrawBaseContainer(obj, idx);
} private void DrawContainer(ChangedItemsCache.Container obj, int idx)
{
private void DrawPreferredButton(IdentifiedItem item, int idx) using var id = ImUtf8.PushId(idx);
{ DrawBaseContainer(obj, idx);
if (ImUtf8.IconButton(FontAwesomeIcon.Star, "Prefer displaying this item instead of the current primary item.\n\nRight-click for more options."u8, _buttonSize, }
false, _starColor))
dataEditor.AddPreferredItem(selector.Selected!, item.Item.Id, false, true); private void DrawPreferredButton(IdentifiedItem item, int idx)
using var context = ImUtf8.PopupContextItem("StarContext"u8); {
if (!context) var textColor = Im.Mouse.IsHoveringRectangle(Rectangle.FromSize(Im.Cursor.ScreenPosition, _buttonSize))
return; ? LunaStyle.FavoriteColor
: _starColor;
if (cacheService.TryGetCache<ChangedItemsCache>(_cacheId, out var cache))
for (--idx; idx >= 0; --idx) if (ImEx.Icon.Button(LunaStyle.FavoriteIcon,
{ "Prefer displaying this item instead of the current primary item.\n\nRight-click for more options."u8,
if (!cache.Data[idx].Expanded) textColor: textColor, size: _buttonSize))
continue; dataEditor.AddPreferredItem(selector.Selected!, item.Item.Id, false, true);
using var context = ImUtf8.PopupContextItem("StarContext"u8);
if (cache.Data[idx].Data is IdentifiedItem it) if (!context)
{ return;
if (selector.Selected!.PreferredChangedItems.Contains(it.Item.Id)
&& ImUtf8.MenuItem("Remove Parent from Local Preferred Items"u8)) if (cacheService.TryGetCache<ChangedItemsCache>(_cacheId, out var cache))
dataEditor.RemovePreferredItem(selector.Selected!, it.Item.Id, false); for (--idx; idx >= 0; --idx)
if (selector.Selected!.DefaultPreferredItems.Contains(it.Item.Id) {
&& ImUtf8.MenuItem("Remove Parent from Default Preferred Items"u8)) if (!cache.Data[idx].Expanded)
dataEditor.RemovePreferredItem(selector.Selected!, it.Item.Id, true); continue;
}
if (cache.Data[idx].Data is IdentifiedItem it)
break; {
} if (selector.Selected!.PreferredChangedItems.Contains(it.Item.Id)
&& ImUtf8.MenuItem("Remove Parent from Local Preferred Items"u8))
var enabled = !selector.Selected!.DefaultPreferredItems.Contains(item.Item.Id); dataEditor.RemovePreferredItem(selector.Selected!, it.Item.Id, false);
if (enabled) if (selector.Selected!.DefaultPreferredItems.Contains(it.Item.Id)
{ && ImUtf8.MenuItem("Remove Parent from Default Preferred Items"u8))
if (ImUtf8.MenuItem("Add to Local and Default Preferred Changed Items"u8)) dataEditor.RemovePreferredItem(selector.Selected!, it.Item.Id, true);
dataEditor.AddPreferredItem(selector.Selected!, item.Item.Id, true, true); }
}
else break;
{ }
if (ImUtf8.MenuItem("Remove from Default Preferred Changed Items"u8))
dataEditor.RemovePreferredItem(selector.Selected!, item.Item.Id, true); var enabled = !selector.Selected!.DefaultPreferredItems.Contains(item.Item.Id);
} if (enabled)
{
if (ImUtf8.MenuItem("Reset Local Preferred Items to Default"u8)) if (ImUtf8.MenuItem("Add to Local and Default Preferred Changed Items"u8))
dataEditor.ResetPreferredItems(selector.Selected!); dataEditor.AddPreferredItem(selector.Selected!, item.Item.Id, true, true);
}
if (ImUtf8.MenuItem("Clear Local and Default Preferred Items not Changed by the Mod"u8)) else
dataEditor.ClearInvalidPreferredItems(selector.Selected!); {
} if (ImUtf8.MenuItem("Remove from Default Preferred Changed Items"u8))
dataEditor.RemovePreferredItem(selector.Selected!, item.Item.Id, true);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DrawBaseContainer(in ChangedItemsCache.Container obj, int _) if (ImUtf8.MenuItem("Reset Local Preferred Items to Default"u8))
{ dataEditor.ResetPreferredItems(selector.Selected!);
ImGui.TableNextColumn();
using var indent = ImRaii.PushIndent(1, obj.Child); if (ImUtf8.MenuItem("Clear Local and Default Preferred Items not Changed by the Mod"u8))
drawer.DrawCategoryIcon(obj.Icon, _buttonSize.Y); dataEditor.ClearInvalidPreferredItems(selector.Selected!);
ImGui.SameLine(0, 0); }
var clicked = ImUtf8.Selectable(obj.Text.Span, false, ImGuiSelectableFlags.None, _buttonSize with { X = 0 });
drawer.ChangedItemHandling(obj.Data, clicked);
ChangedItemDrawer.DrawModelData(obj.ModelData.Span, _buttonSize.Y); [MethodImpl(MethodImplOptions.AggressiveInlining)]
} private void DrawBaseContainer(in ChangedItemsCache.Container obj, int _)
} {
ImGui.TableNextColumn();
using var indent = ImRaii.PushIndent(1, obj.Child);
drawer.DrawCategoryIcon(obj.Icon, _buttonSize.Y);
ImGui.SameLine(0, 0);
var clicked = ImUtf8.Selectable(obj.Text.Span, false, ImGuiSelectableFlags.None, _buttonSize with { X = 0 });
drawer.ChangedItemHandling(obj.Data, clicked);
ChangedItemDrawer.DrawModelData(obj.ModelData.Span, _buttonSize.Y);
}
}

View file

@ -1,206 +1,205 @@
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Utility; using Dalamud.Interface.Utility;
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using ImSharp; using ImSharp;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Text; using OtterGui.Text;
using OtterGui.Widgets; using OtterGui.Widgets;
using Penumbra.Collections.Cache; using Penumbra.Collections.Cache;
using Penumbra.Collections.Manager; using Penumbra.Collections.Manager;
using Penumbra.Meta.Manipulations; using Penumbra.Meta.Manipulations;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.Mods.Editor; using Penumbra.Mods.Editor;
using Penumbra.Mods.Settings; using Penumbra.Mods.Settings;
using Penumbra.String.Classes; using Penumbra.String.Classes;
using Penumbra.UI.Classes; using Penumbra.UI.Classes;
namespace Penumbra.UI.ModsTab; namespace Penumbra.UI.ModsTab;
public class ModPanelConflictsTab(CollectionManager collectionManager, ModFileSystemSelector selector) : ITab, Luna.IUiService public class ModPanelConflictsTab(CollectionManager collectionManager, ModFileSystemSelector selector) : ITab, Luna.IUiService
{ {
private int? _currentPriority; private int? _currentPriority;
public ReadOnlySpan<byte> Label public ReadOnlySpan<byte> Label
=> "Conflicts"u8; => "Conflicts"u8;
public bool IsVisible public bool IsVisible
=> collectionManager.Active.Current.Conflicts(selector.Selected!).Any(c => !GetPriority(c).IsHidden); => collectionManager.Active.Current.Conflicts(selector.Selected!).Any(c => !GetPriority(c).IsHidden);
private readonly ConditionalWeakTable<IMod, object> _expandedMods = []; private readonly ConditionalWeakTable<IMod, object> _expandedMods = [];
private ModPriority GetPriority(ModConflicts conflicts) private ModPriority GetPriority(ModConflicts conflicts)
{ {
if (conflicts.Mod2.Index < 0) if (conflicts.Mod2.Index < 0)
return conflicts.Mod2.Priority; return conflicts.Mod2.Priority;
return collectionManager.Active.Current.GetActualSettings(conflicts.Mod2.Index).Settings?.Priority ?? ModPriority.Default; return collectionManager.Active.Current.GetActualSettings(conflicts.Mod2.Index).Settings?.Priority ?? ModPriority.Default;
} }
public void DrawContent() public void DrawContent()
{ {
using var table = ImRaii.Table("conflicts", 3, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY, ImGui.GetContentRegionAvail()); using var table = ImRaii.Table("conflicts", 3, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY, ImGui.GetContentRegionAvail());
if (!table) if (!table)
return; return;
var buttonSize = new Vector2(ImGui.GetFrameHeight()); var buttonSize = new Vector2(ImGui.GetFrameHeight());
var spacing = ImGui.GetStyle().ItemInnerSpacing with { Y = ImGui.GetStyle().ItemSpacing.Y }; var spacing = ImGui.GetStyle().ItemInnerSpacing with { Y = ImGui.GetStyle().ItemSpacing.Y };
var priorityRowWidth = ImGui.CalcTextSize("Priority").X + 20 * ImGuiHelpers.GlobalScale + 2 * buttonSize.X; var priorityRowWidth = ImGui.CalcTextSize("Priority").X + 20 * ImGuiHelpers.GlobalScale + 2 * buttonSize.X;
var priorityWidth = priorityRowWidth - 2 * (buttonSize.X + spacing.X); var priorityWidth = priorityRowWidth - 2 * (buttonSize.X + spacing.X);
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing); using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing);
ImGui.TableSetupColumn("Conflicting Mod", ImGuiTableColumnFlags.WidthStretch); ImGui.TableSetupColumn("Conflicting Mod", ImGuiTableColumnFlags.WidthStretch);
ImGui.TableSetupColumn("Priority", ImGuiTableColumnFlags.WidthFixed, priorityRowWidth); ImGui.TableSetupColumn("Priority", ImGuiTableColumnFlags.WidthFixed, priorityRowWidth);
ImGui.TableSetupColumn("Files", ImGuiTableColumnFlags.WidthFixed, ImGui.CalcTextSize("Files").X + spacing.X); ImGui.TableSetupColumn("Files", ImGuiTableColumnFlags.WidthFixed, ImGui.CalcTextSize("Files").X + spacing.X);
ImGui.TableSetupScrollFreeze(2, 2); ImGui.TableSetupScrollFreeze(2, 2);
ImGui.TableHeadersRow(); ImGui.TableHeadersRow();
DrawCurrentRow(priorityWidth); DrawCurrentRow(priorityWidth);
// Can not be null because otherwise the tab bar is never drawn. // Can not be null because otherwise the tab bar is never drawn.
var mod = selector.Selected!; var mod = selector.Selected!;
foreach (var (index, conflict) in collectionManager.Active.Current.Conflicts(mod).Where(c => !c.Mod2.Priority.IsHidden) foreach (var (index, conflict) in collectionManager.Active.Current.Conflicts(mod).Where(c => !c.Mod2.Priority.IsHidden)
.OrderByDescending(GetPriority) .OrderByDescending(GetPriority)
.ThenBy(c => c.Mod2.Name, StringComparer.OrdinalIgnoreCase).Index()) .ThenBy(c => c.Mod2.Name, StringComparer.OrdinalIgnoreCase).Index())
{ {
using var id = ImRaii.PushId(index); using var id = ImRaii.PushId(index);
DrawConflictRow(conflict, priorityWidth, buttonSize); DrawConflictRow(conflict, priorityWidth, buttonSize);
} }
} }
private void DrawCurrentRow(float priorityWidth) private void DrawCurrentRow(float priorityWidth)
{ {
ImGui.TableNextColumn(); ImGui.TableNextColumn();
using var c = ImRaii.PushColor(ImGuiCol.Text, ColorId.FolderLine.Value()); using var c = ImGuiColor.Text.Push(ColorId.FolderLine.Value());
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(selector.Selected!.Name); ImGui.TextUnformatted(selector.Selected!.Name);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
var actualSettings = collectionManager.Active.Current.GetActualSettings(selector.Selected!.Index).Settings!; var actualSettings = collectionManager.Active.Current.GetActualSettings(selector.Selected!.Index).Settings!;
var priority = actualSettings.Priority.Value; var priority = actualSettings.Priority.Value;
// TODO // TODO
using (ImRaii.Disabled(actualSettings is TemporaryModSettings)) using (ImRaii.Disabled(actualSettings is TemporaryModSettings))
{ {
ImGui.SetNextItemWidth(priorityWidth); ImGui.SetNextItemWidth(priorityWidth);
if (ImGui.InputInt("##priority", ref priority, 0, 0, flags: ImGuiInputTextFlags.EnterReturnsTrue)) if (ImGui.InputInt("##priority", ref priority, 0, 0, flags: ImGuiInputTextFlags.EnterReturnsTrue))
_currentPriority = priority; _currentPriority = priority;
if (ImGui.IsItemDeactivatedAfterEdit() && _currentPriority.HasValue) if (ImGui.IsItemDeactivatedAfterEdit() && _currentPriority.HasValue)
{ {
if (_currentPriority != actualSettings.Priority.Value) if (_currentPriority != actualSettings.Priority.Value)
collectionManager.Editor.SetModPriority(collectionManager.Active.Current, selector.Selected!, collectionManager.Editor.SetModPriority(collectionManager.Active.Current, selector.Selected!,
new ModPriority(_currentPriority.Value)); new ModPriority(_currentPriority.Value));
_currentPriority = null; _currentPriority = null;
} }
else if (ImGui.IsItemDeactivated()) else if (ImGui.IsItemDeactivated())
{ {
_currentPriority = null; _currentPriority = null;
} }
} }
ImGui.TableNextColumn(); ImGui.TableNextColumn();
} }
private void DrawConflictSelectable(ModConflicts conflict) private void DrawConflictSelectable(ModConflicts conflict)
{ {
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
if (ImGui.Selectable(conflict.Mod2.Name) && conflict.Mod2 is Mod otherMod) if (ImGui.Selectable(conflict.Mod2.Name) && conflict.Mod2 is Mod otherMod)
selector.SelectByValue(otherMod); selector.SelectByValue(otherMod);
var hovered = ImGui.IsItemHovered(); var hovered = ImGui.IsItemHovered();
var rightClicked = ImGui.IsItemClicked(ImGuiMouseButton.Right); var rightClicked = ImGui.IsItemClicked(ImGuiMouseButton.Right);
if (conflict.Mod2 is Mod otherMod2) if (conflict.Mod2 is Mod otherMod2)
{ {
if (hovered) if (hovered)
ImGui.SetTooltip("Click to jump to mod, Control + Right-Click to disable mod."); ImGui.SetTooltip("Click to jump to mod, Control + Right-Click to disable mod.");
if (rightClicked && ImGui.GetIO().KeyCtrl) if (rightClicked && ImGui.GetIO().KeyCtrl)
collectionManager.Editor.SetModState(collectionManager.Active.Current, otherMod2, false); collectionManager.Editor.SetModState(collectionManager.Active.Current, otherMod2, false);
} }
} }
private bool DrawExpandedFiles(ModConflicts conflict) private bool DrawExpandedFiles(ModConflicts conflict)
{ {
if (!_expandedMods.TryGetValue(conflict.Mod2, out _)) if (!_expandedMods.TryGetValue(conflict.Mod2, out _))
return false; return false;
using var indent = ImRaii.PushIndent(30f); using var indent = ImRaii.PushIndent(30f);
foreach (var data in conflict.Conflicts) foreach (var data in conflict.Conflicts)
{ {
_ = data switch _ = data switch
{ {
Utf8GamePath p => ImUtf8.Selectable(p.Path.Span, false), Utf8GamePath p => ImUtf8.Selectable(p.Path.Span, false),
IMetaIdentifier m => ImUtf8.Selectable(m.ToString(), false), IMetaIdentifier m => ImUtf8.Selectable(m.ToString(), false),
_ => false, _ => false,
}; };
} }
return true; return true;
} }
private void DrawConflictRow(ModConflicts conflict, float priorityWidth, Vector2 buttonSize) private void DrawConflictRow(ModConflicts conflict, float priorityWidth, Vector2 buttonSize)
{ {
ImGui.TableNextColumn(); ImGui.TableNextColumn();
DrawConflictSelectable(conflict); DrawConflictSelectable(conflict);
var expanded = DrawExpandedFiles(conflict); var expanded = DrawExpandedFiles(conflict);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
var conflictPriority = DrawPriorityInput(conflict, priorityWidth); var conflictPriority = DrawPriorityInput(conflict, priorityWidth);
Im.Line.Same(); Im.Line.Same();
var selectedPriority = collectionManager.Active.Current.GetActualSettings(selector.Selected!.Index).Settings!.Priority.Value; var selectedPriority = collectionManager.Active.Current.GetActualSettings(selector.Selected!.Index).Settings!.Priority.Value;
DrawPriorityButtons(conflict.Mod2 as Mod, conflictPriority, selectedPriority, buttonSize); DrawPriorityButtons(conflict.Mod2 as Mod, conflictPriority, selectedPriority, buttonSize);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
DrawExpandButton(conflict.Mod2, expanded, buttonSize); DrawExpandButton(conflict.Mod2, expanded, buttonSize);
} }
private void DrawExpandButton(IMod mod, bool expanded, Vector2 buttonSize) private void DrawExpandButton(IMod mod, bool expanded, Vector2 buttonSize)
{ {
var (icon, tt) = expanded var (icon, tt) = expanded
? (FontAwesomeIcon.CaretUp.ToIconString(), "Hide the conflicting files for this mod.") ? (FontAwesomeIcon.CaretUp.ToIconString(), "Hide the conflicting files for this mod.")
: (FontAwesomeIcon.CaretDown.ToIconString(), "Show the conflicting files for this mod."); : (FontAwesomeIcon.CaretDown.ToIconString(), "Show the conflicting files for this mod.");
if (ImGuiUtil.DrawDisabledButton(icon, buttonSize, tt, false, true)) if (ImGuiUtil.DrawDisabledButton(icon, buttonSize, tt, false, true))
{ {
if (expanded) if (expanded)
_expandedMods.Remove(mod); _expandedMods.Remove(mod);
else else
_expandedMods.Add(mod, new object()); _expandedMods.Add(mod, new object());
} }
} }
private int DrawPriorityInput(ModConflicts conflict, float priorityWidth) private int DrawPriorityInput(ModConflicts conflict, float priorityWidth)
{ {
using var color = ImRaii.PushColor(ImGuiCol.Text, using var color = ImGuiColor.Text.Push(conflict.HasPriority ? ColorId.HandledConflictMod.Value() : ColorId.ConflictingMod.Value());
conflict.HasPriority ? ColorId.HandledConflictMod.Value() : ColorId.ConflictingMod.Value()); using var disabled = ImRaii.Disabled(conflict.Mod2.Index < 0);
using var disabled = ImRaii.Disabled(conflict.Mod2.Index < 0); var priority = _currentPriority ?? GetPriority(conflict).Value;
var priority = _currentPriority ?? GetPriority(conflict).Value;
ImGui.SetNextItemWidth(priorityWidth);
ImGui.SetNextItemWidth(priorityWidth); if (ImGui.InputInt("##priority", ref priority, 0, 0, flags: ImGuiInputTextFlags.EnterReturnsTrue))
if (ImGui.InputInt("##priority", ref priority, 0, 0, flags: ImGuiInputTextFlags.EnterReturnsTrue)) _currentPriority = priority;
_currentPriority = priority;
if (ImGui.IsItemDeactivatedAfterEdit() && _currentPriority.HasValue)
if (ImGui.IsItemDeactivatedAfterEdit() && _currentPriority.HasValue) {
{ if (_currentPriority != GetPriority(conflict).Value)
if (_currentPriority != GetPriority(conflict).Value) collectionManager.Editor.SetModPriority(collectionManager.Active.Current, (Mod)conflict.Mod2,
collectionManager.Editor.SetModPriority(collectionManager.Active.Current, (Mod)conflict.Mod2, new ModPriority(_currentPriority.Value));
new ModPriority(_currentPriority.Value));
_currentPriority = null;
_currentPriority = null; }
} else if (ImGui.IsItemDeactivated())
else if (ImGui.IsItemDeactivated()) {
{ _currentPriority = null;
_currentPriority = null; }
}
return priority;
return priority; }
}
private void DrawPriorityButtons(Mod? conflict, int conflictPriority, int selectedPriority, Vector2 buttonSize)
private void DrawPriorityButtons(Mod? conflict, int conflictPriority, int selectedPriority, Vector2 buttonSize) {
{ if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.SortNumericUpAlt.ToIconString(), buttonSize,
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.SortNumericUpAlt.ToIconString(), buttonSize, $"Set the priority of the currently selected mod to this mods priority plus one. ({selectedPriority} -> {conflictPriority + 1})",
$"Set the priority of the currently selected mod to this mods priority plus one. ({selectedPriority} -> {conflictPriority + 1})", selectedPriority > conflictPriority, true))
selectedPriority > conflictPriority, true)) collectionManager.Editor.SetModPriority(collectionManager.Active.Current, selector.Selected!,
collectionManager.Editor.SetModPriority(collectionManager.Active.Current, selector.Selected!, new ModPriority(conflictPriority + 1));
new ModPriority(conflictPriority + 1)); Im.Line.Same();
Im.Line.Same(); if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.SortNumericDownAlt.ToIconString(), buttonSize,
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.SortNumericDownAlt.ToIconString(), buttonSize, $"Set the priority of this mod to the currently selected mods priority minus one. ({conflictPriority} -> {selectedPriority - 1})",
$"Set the priority of this mod to the currently selected mods priority minus one. ({conflictPriority} -> {selectedPriority - 1})", selectedPriority > conflictPriority || conflict == null, true))
selectedPriority > conflictPriority || conflict == null, true)) collectionManager.Editor.SetModPriority(collectionManager.Active.Current, conflict!, new ModPriority(selectedPriority - 1));
collectionManager.Editor.SetModPriority(collectionManager.Active.Current, conflict!, new ModPriority(selectedPriority - 1)); }
} }
}

View file

@ -208,8 +208,8 @@ public class ModPanelEditTab(
private void DrawImportDate() private void DrawImportDate()
{ {
ImUtf8.TextFramed($"{DateTimeOffset.FromUnixTimeMilliseconds(_mod.ImportDate).ToLocalTime():yyyy/MM/dd HH:mm}", ImEx.TextFramed($"{DateTimeOffset.FromUnixTimeMilliseconds(_mod.ImportDate).ToLocalTime():yyyy/MM/dd HH:mm}",
ImGui.GetColorU32(ImGuiCol.FrameBg, 0.5f), new Vector2(UiHelpers.InputTextMinusButton3, 0)); new Vector2(UiHelpers.InputTextMinusButton3, 0), ImGuiColor.FrameBackground.Get(0.5f));
ImGui.SameLine(0, 3 * ImUtf8.GlobalScale); ImGui.SameLine(0, 3 * ImUtf8.GlobalScale);
var canRefresh = config.DeleteModModifier.IsActive(); var canRefresh = config.DeleteModModifier.IsActive();

View file

@ -149,8 +149,7 @@ public class ModPanelHeader : IDisposable
ImGui.SetCursorPosX(offset); ImGui.SetCursorPosX(offset);
} }
using var color = ImRaii.PushColor(ImGuiCol.Border, Colors.MetaInfoText); using var style = ImStyleBorder.Frame.Push(Colors.MetaInfoText, 2 * Im.Style.GlobalScale);
using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, 2 * UiHelpers.Scale);
using var f = _nameFont.Push(); using var f = _nameFont.Push();
ImGuiUtil.DrawTextButton(_modName, Vector2.Zero, 0); ImGuiUtil.DrawTextButton(_modName, Vector2.Zero, 0);
_nameWidth = ImGui.GetItemRectSize().X; _nameWidth = ImGui.GetItemRectSize().X;

View file

@ -92,7 +92,7 @@ public class ModPanelSettingsTab(
if (!_inherited) if (!_inherited)
return; return;
using var color = ImRaii.PushColor(ImGuiCol.Button, Colors.PressEnterWarningBg); using var color = ImGuiColor.Button.Push(Colors.PressEnterWarningBg);
var width = new Vector2(ImGui.GetContentRegionAvail().X, 0); var width = new Vector2(ImGui.GetContentRegionAvail().X, 0);
if (ImUtf8.ButtonEx($"These settings are inherited from {selection.Collection.Identity.Name}.", width, _locked)) if (ImUtf8.ButtonEx($"These settings are inherited from {selection.Collection.Identity.Name}.", width, _locked))
{ {

View file

@ -1,158 +1,158 @@
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Dalamud.Interface; using Dalamud.Interface;
using OtterGui; using ImSharp;
using OtterGui.Raii; using Luna;
using OtterGui.Widgets; using OtterGui;
using Penumbra.Mods; using OtterGui.Raii;
using Penumbra.Mods.Manager; using OtterGui.Widgets;
using Penumbra.UI.AdvancedWindow; using Penumbra.Mods;
using Penumbra.Mods.Manager;
namespace Penumbra.UI.ModsTab; using Penumbra.UI.AdvancedWindow;
using ImGuiColor = ImSharp.ImGuiColor;
public class ModPanelTabBar : Luna.IUiService
{ namespace Penumbra.UI.ModsTab;
private enum ModPanelTabType
{ public class ModPanelTabBar : IUiService
Description, {
Settings, private enum ModPanelTabType
ChangedItems, {
Conflicts, Description,
Collections, Settings,
Edit, ChangedItems,
}; Conflicts,
Collections,
public readonly ModPanelSettingsTab Settings; Edit,
public readonly ModPanelDescriptionTab Description; };
public readonly ModPanelCollectionsTab Collections;
public readonly ModPanelConflictsTab Conflicts; public readonly ModPanelSettingsTab Settings;
public readonly ModPanelChangedItemsTab ChangedItems; public readonly ModPanelDescriptionTab Description;
public readonly ModPanelEditTab Edit; public readonly ModPanelCollectionsTab Collections;
private readonly ModEditWindow _modEditWindow; public readonly ModPanelConflictsTab Conflicts;
private readonly ModManager _modManager; public readonly ModPanelChangedItemsTab ChangedItems;
private readonly TutorialService _tutorial; public readonly ModPanelEditTab Edit;
private readonly ModEditWindow _modEditWindow;
public readonly ITab[] Tabs; private readonly ModManager _modManager;
private ModPanelTabType _preferredTab = ModPanelTabType.Settings; private readonly TutorialService _tutorial;
private Mod? _lastMod;
public readonly ITab[] Tabs;
public ModPanelTabBar(ModEditWindow modEditWindow, ModPanelSettingsTab settings, ModPanelDescriptionTab description, private ModPanelTabType _preferredTab = ModPanelTabType.Settings;
ModPanelConflictsTab conflicts, ModPanelChangedItemsTab changedItems, ModPanelEditTab edit, ModManager modManager, private Mod? _lastMod;
TutorialService tutorial, ModPanelCollectionsTab collections)
{ public ModPanelTabBar(ModEditWindow modEditWindow, ModPanelSettingsTab settings, ModPanelDescriptionTab description,
_modEditWindow = modEditWindow; ModPanelConflictsTab conflicts, ModPanelChangedItemsTab changedItems, ModPanelEditTab edit, ModManager modManager,
Settings = settings; TutorialService tutorial, ModPanelCollectionsTab collections)
Description = description; {
Conflicts = conflicts; _modEditWindow = modEditWindow;
ChangedItems = changedItems; Settings = settings;
Edit = edit; Description = description;
_modManager = modManager; Conflicts = conflicts;
_tutorial = tutorial; ChangedItems = changedItems;
Collections = collections; Edit = edit;
_modManager = modManager;
Tabs = _tutorial = tutorial;
[ Collections = collections;
Settings,
Description, Tabs =
Conflicts, [
ChangedItems, Settings,
Collections, Description,
Edit, Conflicts,
]; ChangedItems,
} Collections,
Edit,
public void Draw(Mod mod) ];
{ }
var tabBarHeight = ImGui.GetCursorPosY();
if (_lastMod != mod) public void Draw(Mod mod)
{ {
_lastMod = mod; var tabBarHeight = ImGui.GetCursorPosY();
TabBar.Draw(string.Empty, ImGuiTabBarFlags.NoTooltip, ToLabel(_preferredTab), out _, () => DrawAdvancedEditingButton(mod), Tabs); if (_lastMod != mod)
} {
else _lastMod = mod;
{ TabBar.Draw(string.Empty, ImGuiTabBarFlags.NoTooltip, ToLabel(_preferredTab), out _, () => DrawAdvancedEditingButton(mod), Tabs);
TabBar.Draw(string.Empty, ImGuiTabBarFlags.NoTooltip, ReadOnlySpan<byte>.Empty, out var label, () => DrawAdvancedEditingButton(mod), }
Tabs); else
_preferredTab = ToType(label); {
} TabBar.Draw(string.Empty, ImGuiTabBarFlags.NoTooltip, ReadOnlySpan<byte>.Empty, out var label, () => DrawAdvancedEditingButton(mod),
Tabs);
DrawFavoriteButton(mod, tabBarHeight); _preferredTab = ToType(label);
} }
private ReadOnlySpan<byte> ToLabel(ModPanelTabType type) DrawFavoriteButton(mod, tabBarHeight);
=> type switch }
{
ModPanelTabType.Description => Description.Label, private ReadOnlySpan<byte> ToLabel(ModPanelTabType type)
ModPanelTabType.Settings => Settings.Label, => type switch
ModPanelTabType.ChangedItems => ChangedItems.Label, {
ModPanelTabType.Conflicts => Conflicts.Label, ModPanelTabType.Description => Description.Label,
ModPanelTabType.Collections => Collections.Label, ModPanelTabType.Settings => Settings.Label,
ModPanelTabType.Edit => Edit.Label, ModPanelTabType.ChangedItems => ChangedItems.Label,
_ => ReadOnlySpan<byte>.Empty, ModPanelTabType.Conflicts => Conflicts.Label,
}; ModPanelTabType.Collections => Collections.Label,
ModPanelTabType.Edit => Edit.Label,
private ModPanelTabType ToType(ReadOnlySpan<byte> label) _ => ReadOnlySpan<byte>.Empty,
{ };
if (label == Description.Label)
return ModPanelTabType.Description; private ModPanelTabType ToType(ReadOnlySpan<byte> label)
if (label == Settings.Label) {
return ModPanelTabType.Settings; if (label == Description.Label)
if (label == ChangedItems.Label) return ModPanelTabType.Description;
return ModPanelTabType.ChangedItems; if (label == Settings.Label)
if (label == Conflicts.Label) return ModPanelTabType.Settings;
return ModPanelTabType.Conflicts; if (label == ChangedItems.Label)
if (label == Collections.Label) return ModPanelTabType.ChangedItems;
return ModPanelTabType.Collections; if (label == Conflicts.Label)
if (label == Edit.Label) return ModPanelTabType.Conflicts;
return ModPanelTabType.Edit; if (label == Collections.Label)
return ModPanelTabType.Collections;
return 0; if (label == Edit.Label)
} return ModPanelTabType.Edit;
private void DrawAdvancedEditingButton(Mod mod) return 0;
{ }
if (ImGui.TabItemButton("Advanced Editing", ImGuiTabItemFlags.Trailing | ImGuiTabItemFlags.NoTooltip))
{ private void DrawAdvancedEditingButton(Mod mod)
_modEditWindow.ChangeMod(mod); {
_modEditWindow.ChangeOption(mod.Default); if (ImGui.TabItemButton("Advanced Editing", ImGuiTabItemFlags.Trailing | ImGuiTabItemFlags.NoTooltip))
_modEditWindow.IsOpen = true; {
} _modEditWindow.ChangeMod(mod);
_modEditWindow.ChangeOption(mod.Default);
ImGuiUtil.HoverTooltip( _modEditWindow.IsOpen = true;
"Clicking this will open a new window in which you can\nedit the following things per option for this mod:\n\n" }
+ "\t\t- file redirections\n"
+ "\t\t- file swaps\n" ImGuiUtil.HoverTooltip(
+ "\t\t- metadata manipulations\n" "Clicking this will open a new window in which you can\nedit the following things per option for this mod:\n\n"
+ "\t\t- model materials\n" + "\t\t- file redirections\n"
+ "\t\t- duplicates\n" + "\t\t- file swaps\n"
+ "\t\t- textures"); + "\t\t- metadata manipulations\n"
} + "\t\t- model materials\n"
+ "\t\t- duplicates\n"
private void DrawFavoriteButton(Mod mod, float height) + "\t\t- textures");
{ }
using (var font = ImRaii.PushFont(UiBuilder.IconFont))
{ private void DrawFavoriteButton(Mod mod, float height)
var size = ImGui.CalcTextSize(FontAwesomeIcon.Star.ToIconString()) + ImGui.GetStyle().FramePadding * 2; {
var newPos = new Vector2(ImGui.GetWindowWidth() - size.X - ImGui.GetStyle().ItemSpacing.X, height); var size = ImEx.Icon.CalculateSize(LunaStyle.FavoriteIcon) + ImGui.GetStyle().FramePadding * 2;
if (ImGui.GetScrollMaxX() > 0) var newPos = new Vector2(ImGui.GetWindowWidth() - size.X - ImGui.GetStyle().ItemSpacing.X, height);
newPos.X += ImGui.GetScrollX(); if (ImGui.GetScrollMaxX() > 0)
newPos.X += ImGui.GetScrollX();
var rectUpper = ImGui.GetWindowPos() + newPos;
var color = ImGui.IsMouseHoveringRect(rectUpper, rectUpper + size) ? ImGui.GetColorU32(ImGuiCol.Text) : var rectUpper = ImGui.GetWindowPos() + newPos;
mod.Favorite ? 0xFF00FFFF : ImGui.GetColorU32(ImGuiCol.TextDisabled); var color = ImGui.IsMouseHoveringRect(rectUpper, rectUpper + size) ? Im.Style[ImGuiColor.Text] :
using var c = ImRaii.PushColor(ImGuiCol.Text, color) mod.Favorite ? LunaStyle.FavoriteColor : Im.Style[ImGuiColor.TextDisabled];
.Push(ImGuiCol.Button, 0) using var c = ImGuiColor.Text.Push(color)
.Push(ImGuiCol.ButtonHovered, 0) .Push(ImGuiColor.Button, Vector4.Zero)
.Push(ImGuiCol.ButtonActive, 0); .Push(ImGuiColor.ButtonHovered, Vector4.Zero)
.Push(ImGuiColor.ButtonActive, Vector4.Zero);
ImGui.SetCursorPos(newPos);
if (ImGui.Button(FontAwesomeIcon.Star.ToIconString())) ImGui.SetCursorPos(newPos);
_modManager.DataEditor.ChangeModFavorite(mod, !mod.Favorite); if (ImEx.Icon.Button(LunaStyle.FavoriteIcon))
} _modManager.DataEditor.ChangeModFavorite(mod, !mod.Favorite);
var hovered = ImGui.IsItemHovered(); var hovered = ImGui.IsItemHovered();
_tutorial.OpenTutorial(BasicTutorialSteps.Favorites); _tutorial.OpenTutorial(BasicTutorialSteps.Favorites);
if (hovered) if (hovered)
ImGui.SetTooltip("Favorite"); ImGui.SetTooltip("Favorite");
} }
} }

View file

@ -21,8 +21,8 @@ public sealed class PredefinedTagManager : ISavable, IReadOnlyList<string>, ISer
private readonly SaveService _saveService; private readonly SaveService _saveService;
private bool _isListOpen; private bool _isListOpen;
private uint _enabledColor; private Rgba32 _enabledColor;
private uint _disabledColor; private Rgba32 _disabledColor;
private readonly SortedList<string, TagData> _predefinedTags = []; private readonly SortedList<string, TagData> _predefinedTags = [];

View file

@ -1,5 +1,6 @@
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Dalamud.Interface; using Dalamud.Interface;
using ImSharp;
using Luna; using Luna;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
@ -336,17 +337,13 @@ internal sealed class ResourceWatcherTable : Table<Record>
$"Successfully loaded ({(byte)item.LoadState})."), $"Successfully loaded ({(byte)item.LoadState})."),
LoadState.FailedSubResource => (FontAwesomeIcon.ExclamationCircle, ColorId.DecreasedMetaValue.Value(), LoadState.FailedSubResource => (FontAwesomeIcon.ExclamationCircle, ColorId.DecreasedMetaValue.Value(),
$"Dependencies failed to load ({(byte)item.LoadState})."), $"Dependencies failed to load ({(byte)item.LoadState})."),
<= LoadState.Constructed => (FontAwesomeIcon.QuestionCircle, ColorId.UndefinedMod.Value(), $"Not yet loaded ({(byte)item.LoadState})."), <= LoadState.Constructed => (FontAwesomeIcon.QuestionCircle, ColorId.UndefinedMod.Value(),
$"Not yet loaded ({(byte)item.LoadState})."),
< LoadState.Success => (FontAwesomeIcon.Clock, ColorId.FolderLine.Value(), $"Loading asynchronously ({(byte)item.LoadState})."), < LoadState.Success => (FontAwesomeIcon.Clock, ColorId.FolderLine.Value(), $"Loading asynchronously ({(byte)item.LoadState})."),
> LoadState.Success => (FontAwesomeIcon.Times, ColorId.DecreasedMetaValue.Value(), > LoadState.Success => (FontAwesomeIcon.Times, ColorId.DecreasedMetaValue.Value(),
$"Failed to load ({(byte)item.LoadState})."), $"Failed to load ({(byte)item.LoadState})."),
}; };
using (var font = ImRaii.PushFont(UiBuilder.IconFont)) ImEx.Icon.Draw(icon.Icon(), color);
{
using var c = ImRaii.PushColor(ImGuiCol.Text, color);
ImGui.TextUnformatted(icon.ToIconString());
}
ImGuiUtil.HoverTooltip(tt); ImGuiUtil.HoverTooltip(tt);
} }

View file

@ -86,29 +86,30 @@ public sealed class CollectionsTab : IDisposable, ITab, Luna.IUiService
using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameRounding, 0).Push(ImGuiStyleVar.ItemSpacing, Vector2.Zero); using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameRounding, 0).Push(ImGuiStyleVar.ItemSpacing, Vector2.Zero);
var buttonSize = new Vector2((ImGui.GetContentRegionAvail().X - withSpacing) / 4f, ImGui.GetFrameHeight()); var buttonSize = new Vector2((ImGui.GetContentRegionAvail().X - withSpacing) / 4f, ImGui.GetFrameHeight());
using var _ = ImRaii.Group(); using var _ = ImRaii.Group();
using var color = ImRaii.PushColor(ImGuiCol.Button, ImGui.GetColorU32(ImGuiCol.TabActive), Mode is PanelMode.SimpleAssignment); var tabSelectedColor = Im.Style[ImGuiColor.TabSelected];
using var color = ImGuiColor.Button.Push(tabSelectedColor, Mode is PanelMode.SimpleAssignment);
if (ImGui.Button("Simple Assignments", buttonSize)) if (ImGui.Button("Simple Assignments", buttonSize))
Mode = PanelMode.SimpleAssignment; Mode = PanelMode.SimpleAssignment;
color.Pop(); color.Pop();
_tutorial.OpenTutorial(BasicTutorialSteps.SimpleAssignments); _tutorial.OpenTutorial(BasicTutorialSteps.SimpleAssignments);
Im.Line.Same(); Im.Line.Same();
color.Push(ImGuiCol.Button, ImGui.GetColorU32(ImGuiCol.TabActive), Mode is PanelMode.IndividualAssignment); color.Push(ImGuiColor.Button, tabSelectedColor, Mode is PanelMode.IndividualAssignment);
if (ImGui.Button("Individual Assignments", buttonSize)) if (ImGui.Button("Individual Assignments", buttonSize))
Mode = PanelMode.IndividualAssignment; Mode = PanelMode.IndividualAssignment;
color.Pop(); color.Pop();
_tutorial.OpenTutorial(BasicTutorialSteps.IndividualAssignments); _tutorial.OpenTutorial(BasicTutorialSteps.IndividualAssignments);
Im.Line.Same(); Im.Line.Same();
color.Push(ImGuiCol.Button, ImGui.GetColorU32(ImGuiCol.TabActive), Mode is PanelMode.GroupAssignment); color.Push(ImGuiColor.Button, tabSelectedColor, Mode is PanelMode.GroupAssignment);
if (ImGui.Button("Group Assignments", buttonSize)) if (ImGui.Button("Group Assignments", buttonSize))
Mode = PanelMode.GroupAssignment; Mode = PanelMode.GroupAssignment;
color.Pop(); color.Pop();
_tutorial.OpenTutorial(BasicTutorialSteps.GroupAssignments); _tutorial.OpenTutorial(BasicTutorialSteps.GroupAssignments);
Im.Line.Same(); Im.Line.Same();
color.Push(ImGuiCol.Button, ImGui.GetColorU32(ImGuiCol.TabActive), Mode is PanelMode.Details); color.Push(ImGuiColor.Button, tabSelectedColor, Mode is PanelMode.Details);
if (ImGui.Button("Collection Details", buttonSize)) if (ImGui.Button("Collection Details", buttonSize))
Mode = PanelMode.Details; Mode = PanelMode.Details;
color.Pop(); color.Pop();

View file

@ -31,7 +31,6 @@ using Penumbra.Mods.Manager;
using Penumbra.Services; using Penumbra.Services;
using Penumbra.String; using Penumbra.String;
using Penumbra.UI.Classes; using Penumbra.UI.Classes;
using static OtterGui.Raii.ImRaii;
using CharacterBase = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.CharacterBase; using CharacterBase = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.CharacterBase;
using ImGuiClip = OtterGui.ImGuiClip; using ImGuiClip = OtterGui.ImGuiClip;
using Penumbra.Api.IpcTester; using Penumbra.Api.IpcTester;
@ -68,7 +67,7 @@ public class Diagnostics(ServiceManager provider) : IUiService
} }
} }
public class DebugTab : Window, ITab, IUiService public class DebugTab : Window, ITab
{ {
private readonly Configuration _config; private readonly Configuration _config;
private readonly CollectionManager _collectionManager; private readonly CollectionManager _collectionManager;
@ -180,7 +179,7 @@ public class DebugTab : Window, ITab, IUiService
public void DrawContent() public void DrawContent()
{ {
using var child = Child("##DebugTab", -Vector2.One); using var child = Im.Child.Begin("##DebugTab"u8, -Vector2.One);
if (!child) if (!child)
return; return;
@ -218,9 +217,9 @@ public class DebugTab : Window, ITab, IUiService
{ {
if (collection.HasCache) if (collection.HasCache)
{ {
using var color = PushColor(ImGuiCol.Text, ColorId.FolderExpanded.Value()); using var color = ImGuiColor.Text.Push(ColorId.FolderExpanded.Value());
using var node = using var node =
TreeNode($"{collection.Identity.Name} (Change Counter {collection.Counters.Change})###{collection.Identity.Name}"); Im.Tree.Node($"{collection.Identity.Name} (Change Counter {collection.Counters.Change})###{collection.Identity.Name}");
if (!node) if (!node)
continue; continue;
@ -272,24 +271,24 @@ public class DebugTab : Window, ITab, IUiService
if (modNode) if (modNode)
foreach (var (mod, paths, manips) in collection._cache!.ModData.Data.OrderBy(t => t.Item1.Name)) foreach (var (mod, paths, manips) in collection._cache!.ModData.Data.OrderBy(t => t.Item1.Name))
{ {
using var id = mod is TemporaryMod t ? PushId(t.Priority.Value) : PushId(((Mod)mod).ModPath.Name); using var id = mod is TemporaryMod t ? Im.Id.Push(t.Priority.Value) : Im.Id.Push(((Mod)mod).ModPath.Name);
using var node2 = TreeNode(mod.Name); using var node2 = Im.Tree.Node(mod.Name);
if (!node2) if (!node2)
continue; continue;
foreach (var path in paths) foreach (var path in paths)
TreeNode(path.ToString(), ImGuiTreeNodeFlags.Bullet | ImGuiTreeNodeFlags.Leaf).Dispose(); Im.Tree.Node(path.Path.Span, TreeNodeFlags.Bullet | TreeNodeFlags.Leaf).Dispose();
foreach (var manip in manips) foreach (var manip in manips)
TreeNode(manip.ToString(), ImGuiTreeNodeFlags.Bullet | ImGuiTreeNodeFlags.Leaf).Dispose(); Im.Tree.Node($"{manip}", TreeNodeFlags.Bullet | TreeNodeFlags.Leaf).Dispose();
} }
} }
else else
{ {
using var color = PushColor(ImGuiCol.Text, ColorId.UndefinedMod.Value()); using var color = ImGuiColor.Text.Push(ColorId.UndefinedMod.Value());
TreeNode($"{collection.Identity.Name} (Change Counter {collection.Counters.Change})", Im.Tree.Node($"{collection.Identity.Name} (Change Counter {collection.Counters.Change})",
ImGuiTreeNodeFlags.Bullet | ImGuiTreeNodeFlags.Leaf).Dispose(); TreeNodeFlags.Bullet | TreeNodeFlags.Leaf).Dispose();
} }
} }
} }
@ -308,7 +307,7 @@ public class DebugTab : Window, ITab, IUiService
_config.Ephemeral.Save(); _config.Ephemeral.Save();
} }
using (var table = Table("##DebugGeneralTable", 2, ImGuiTableFlags.SizingFixedFit)) using (var table = Im.Table.Begin("##DebugGeneralTable"u8, 2, TableFlags.SizingFixedFit))
{ {
if (table) if (table)
{ {
@ -329,11 +328,11 @@ public class DebugTab : Window, ITab, IUiService
var issues = _modManager.Index().Count(p => p.Index != p.Item.Index); var issues = _modManager.Index().Count(p => p.Index != p.Item.Index);
using (var tree = TreeNode($"Mods ({issues} Issues)###Mods")) using (var tree = Im.Tree.Node($"Mods ({issues} Issues)###Mods"))
{ {
if (tree) if (tree)
{ {
using var table = Table("##DebugModsTable", 3, ImGuiTableFlags.SizingFixedFit); using var table = Im.Table.Begin("##DebugModsTable"u8, 3, TableFlags.SizingFixedFit);
if (table) if (table)
{ {
var lastIndex = -1; var lastIndex = -1;
@ -350,11 +349,11 @@ public class DebugTab : Window, ITab, IUiService
} }
} }
using (var tree = TreeNode("Mod Import")) using (var tree = Im.Tree.Node("Mod Import"u8))
{ {
if (tree) if (tree)
{ {
using var table = Table("##DebugModImport", 2, ImGuiTableFlags.SizingFixedFit); using var table = Im.Table.Begin("##DebugModImport"u8, 2, TableFlags.SizingFixedFit);
if (table) if (table)
{ {
var importing = _modImporter.IsImporting(out var importer); var importing = _modImporter.IsImporting(out var importer);
@ -384,11 +383,11 @@ public class DebugTab : Window, ITab, IUiService
} }
} }
using (var tree = TreeNode("Framework")) using (var tree = Im.Tree.Node("Framework"u8))
{ {
if (tree) if (tree)
{ {
using var table = Table("##DebugFramework", 2, ImGuiTableFlags.SizingFixedFit); using var table = Im.Table.Begin("##DebugFramework"u8, 2, TableFlags.SizingFixedFit);
if (table) if (table)
{ {
foreach (var important in _framework.Important) foreach (var important in _framework.Important)
@ -406,11 +405,11 @@ public class DebugTab : Window, ITab, IUiService
} }
} }
using (var tree = TreeNode($"Texture Manager {_textureManager.Tasks.Count}###Texture Manager")) using (var tree = Im.Tree.Node($"Texture Manager {_textureManager.Tasks.Count}###Texture Manager"))
{ {
if (tree) if (tree)
{ {
using var table = Table("##Tasks", 2, ImGuiTableFlags.RowBg); using var table = Im.Table.Begin("##Tasks"u8, 2, TableFlags.RowBackground);
if (table) if (table)
foreach (var task in _textureManager.Tasks) foreach (var task in _textureManager.Tasks)
{ {
@ -420,11 +419,11 @@ public class DebugTab : Window, ITab, IUiService
} }
} }
using (var tree = TreeNode("Redraw Service")) using (var tree = Im.Tree.Node("Redraw Service"u8))
{ {
if (tree) if (tree)
{ {
using var table = Table("##redraws", 3, ImGuiTableFlags.RowBg); using var table = Im.Table.Begin("##redraws"u8, 3, TableFlags.RowBackground);
if (table) if (table)
{ {
ImGuiUtil.DrawTableColumn("In GPose"); ImGuiUtil.DrawTableColumn("In GPose");
@ -494,7 +493,7 @@ public class DebugTab : Window, ITab, IUiService
if (!ImGui.CollapsingHeader("Performance")) if (!ImGui.CollapsingHeader("Performance"))
return; return;
using (var start = TreeNode("Startup Performance", ImGuiTreeNodeFlags.DefaultOpen)) using (var start = Im.Tree.Node("Startup Performance"u8, TreeNodeFlags.DefaultOpen))
{ {
if (start) if (start)
ImGui.NewLine(); ImGui.NewLine();
@ -512,7 +511,7 @@ public class DebugTab : Window, ITab, IUiService
{ {
_objects.DrawDebug(); _objects.DrawDebug();
using var table = Table("##actors", 8, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit, using var table = Im.Table.Begin("##actors"u8, 8, TableFlags.RowBackground | TableFlags.SizingFixedFit,
-Vector2.UnitX); -Vector2.UnitX);
if (!table) if (!table)
return; return;
@ -581,11 +580,11 @@ public class DebugTab : Window, ITab, IUiService
ImGui.TextUnformatted( ImGui.TextUnformatted(
$"Last Game Object: 0x{_collectionResolver.IdentifyLastGameObjectCollection(true).AssociatedGameObject:X} ({_collectionResolver.IdentifyLastGameObjectCollection(true).ModCollection.Identity.Name})"); $"Last Game Object: 0x{_collectionResolver.IdentifyLastGameObjectCollection(true).AssociatedGameObject:X} ({_collectionResolver.IdentifyLastGameObjectCollection(true).ModCollection.Identity.Name})");
using (var drawTree = TreeNode("Draw Object to Object")) using (var drawTree = Im.Tree.Node("Draw Object to Object"u8))
{ {
if (drawTree) if (drawTree)
{ {
using var table = Table("###DrawObjectResolverTable", 8, ImGuiTableFlags.SizingFixedFit); using var table = Im.Table.Begin("###DrawObjectResolverTable"u8, 8, TableFlags.SizingFixedFit);
if (table) if (table)
foreach (var (drawObject, (gameObjectPtr, idx, child)) in _drawObjectState foreach (var (drawObject, (gameObjectPtr, idx, child)) in _drawObjectState
.OrderBy(kvp => kvp.Value.Item2.Index) .OrderBy(kvp => kvp.Value.Item2.Index)
@ -595,7 +594,7 @@ public class DebugTab : Window, ITab, IUiService
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImUtf8.CopyOnClickSelectable($"{drawObject}"); ImUtf8.CopyOnClickSelectable($"{drawObject}");
ImUtf8.DrawTableColumn($"{gameObjectPtr.Index}"); ImUtf8.DrawTableColumn($"{gameObjectPtr.Index}");
using (ImRaii.PushColor(ImGuiCol.Text, 0xFF0000FF, gameObjectPtr.Index != idx)) using (ImGuiColor.Text.Push(new Vector4(1, 0, 0, 1), gameObjectPtr.Index != idx))
{ {
ImUtf8.DrawTableColumn($"{idx}"); ImUtf8.DrawTableColumn($"{idx}");
} }
@ -603,7 +602,7 @@ public class DebugTab : Window, ITab, IUiService
ImUtf8.DrawTableColumn(child ? "Child"u8 : "Main"u8); ImUtf8.DrawTableColumn(child ? "Child"u8 : "Main"u8);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImUtf8.CopyOnClickSelectable($"{gameObjectPtr}"); ImUtf8.CopyOnClickSelectable($"{gameObjectPtr}");
using (ImRaii.PushColor(ImGuiCol.Text, 0xFF0000FF, _objects[idx] != gameObjectPtr)) using (ImGuiColor.Text.Push(new Vector4(1, 0, 0, 1), _objects[idx] != gameObjectPtr))
{ {
ImUtf8.DrawTableColumn($"{_objects[idx]}"); ImUtf8.DrawTableColumn($"{_objects[idx]}");
} }
@ -615,11 +614,11 @@ public class DebugTab : Window, ITab, IUiService
} }
} }
using (var pathTree = TreeNode("Path Collections")) using (var pathTree = Im.Tree.Node("Path Collections"u8))
{ {
if (pathTree) if (pathTree)
{ {
using var table = Table("###PathCollectionResolverTable", 2, ImGuiTableFlags.SizingFixedFit); using var table = Im.Table.Begin("###PathCollectionResolverTable"u8, 2, TableFlags.SizingFixedFit);
if (table) if (table)
foreach (var data in _pathState.CurrentData) foreach (var data in _pathState.CurrentData)
{ {
@ -631,11 +630,11 @@ public class DebugTab : Window, ITab, IUiService
} }
} }
using (var resourceTree = TreeNode("Subfile Collections")) using (var resourceTree = Im.Tree.Node("Subfile Collections"u8))
{ {
if (resourceTree) if (resourceTree)
{ {
using var table = Table("###ResourceCollectionResolverTable", 4, ImGuiTableFlags.SizingFixedFit); using var table = Im.Table.Begin("###ResourceCollectionResolverTable"u8, 4, TableFlags.SizingFixedFit);
if (table) if (table)
{ {
ImGuiUtil.DrawTableColumn("Current Mtrl Data"); ImGuiUtil.DrawTableColumn("Current Mtrl Data");
@ -664,11 +663,11 @@ public class DebugTab : Window, ITab, IUiService
} }
} }
using (var identifiedTree = TreeNode("Identified Collections")) using (var identifiedTree = Im.Tree.Node("Identified Collections"u8))
{ {
if (identifiedTree) if (identifiedTree)
{ {
using var table = Table("##PathCollectionsIdentifiedTable", 4, ImGuiTableFlags.SizingFixedFit); using var table = Im.Table.Begin("##PathCollectionsIdentifiedTable"u8, 4, TableFlags.SizingFixedFit);
if (table) if (table)
foreach (var (address, identifier, collection) in _identifiedCollectionCache foreach (var (address, identifier, collection) in _identifiedCollectionCache
.OrderBy(kvp => ((GameObject*)kvp.Address)->ObjectIndex)) .OrderBy(kvp => ((GameObject*)kvp.Address)->ObjectIndex))
@ -681,11 +680,11 @@ public class DebugTab : Window, ITab, IUiService
} }
} }
using (var cutsceneTree = TreeNode("Cutscene Actors")) using (var cutsceneTree = Im.Tree.Node("Cutscene Actors"u8))
{ {
if (cutsceneTree) if (cutsceneTree)
{ {
using var table = Table("###PCutsceneResolverTable", 2, ImGuiTableFlags.SizingFixedFit); using var table = Im.Table.Begin("###PCutsceneResolverTable"u8, 2, TableFlags.SizingFixedFit);
if (table) if (table)
foreach (var (idx, actor) in _cutsceneService.Actors) foreach (var (idx, actor) in _cutsceneService.Actors)
{ {
@ -695,11 +694,11 @@ public class DebugTab : Window, ITab, IUiService
} }
} }
using (var groupTree = TreeNode("Group")) using (var groupTree = Im.Tree.Node("Group"u8))
{ {
if (groupTree) if (groupTree)
{ {
using var table = Table("###PGroupTable", 2, ImGuiTableFlags.SizingFixedFit); using var table = Im.Table.Begin("###PGroupTable"u8, 2, TableFlags.SizingFixedFit);
if (table) if (table)
{ {
ImGuiUtil.DrawTableColumn("Group Members"); ImGuiUtil.DrawTableColumn("Group Members");
@ -714,7 +713,7 @@ public class DebugTab : Window, ITab, IUiService
} }
} }
using (var bannerTree = TreeNode("Party Banner")) using (var bannerTree = Im.Tree.Node("Party Banner"u8))
{ {
if (bannerTree) if (bannerTree)
{ {
@ -727,7 +726,7 @@ public class DebugTab : Window, ITab, IUiService
Penumbra.Dynamis.DrawPointer((nint)agent); Penumbra.Dynamis.DrawPointer((nint)agent);
if (agent->Data != null) if (agent->Data != null)
{ {
using var table = Table("###PBannerTable", 2, ImGuiTableFlags.SizingFixedFit); using var table = Im.Table.Begin("###PBannerTable"u8, 2, TableFlags.SizingFixedFit);
if (table) if (table)
for (var i = 0; i < 8; ++i) for (var i = 0; i < 8; ++i)
{ {
@ -744,11 +743,11 @@ public class DebugTab : Window, ITab, IUiService
} }
} }
using (var tmbCache = TreeNode("TMB Cache")) using (var tmbCache = Im.Tree.Node("TMB Cache"u8))
{ {
if (tmbCache) if (tmbCache)
{ {
using var table = Table("###TmbTable", 2, ImGuiTableFlags.SizingFixedFit); using var table = Im.Table.Begin("###TmbTable"u8, 2, TableFlags.SizingFixedFit);
if (table) if (table)
foreach (var (id, name) in _schedulerService.ListedTmbs.OrderBy(kvp => kvp.Key)) foreach (var (id, name) in _schedulerService.ListedTmbs.OrderBy(kvp => kvp.Key))
{ {
@ -777,7 +776,7 @@ public class DebugTab : Window, ITab, IUiService
private void DrawFileTest() private void DrawFileTest()
{ {
using var node = TreeNode("Game File Test"); using var node = Im.Tree.Node("Game File Test"u8);
if (!node) if (!node)
return; return;
@ -803,7 +802,7 @@ public class DebugTab : Window, ITab, IUiService
private void DrawChangedItemTest() private void DrawChangedItemTest()
{ {
using var node = TreeNode("Changed Item Test"); using var node = Im.Tree.Node("Changed Item Test"u8);
if (!node) if (!node)
return; return;
@ -855,13 +854,13 @@ public class DebugTab : Window, ITab, IUiService
private void DrawEmotes() private void DrawEmotes()
{ {
using var mainTree = TreeNode("Emotes"); using var mainTree = Im.Tree.Node("Emotes"u8);
if (!mainTree) if (!mainTree)
return; return;
ImGui.InputText("File Name", ref _emoteSearchFile, 256); ImGui.InputText("File Name", ref _emoteSearchFile, 256);
ImGui.InputText("Emote Name", ref _emoteSearchName, 256); ImGui.InputText("Emote Name", ref _emoteSearchName, 256);
using var table = Table("##table", 2, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY | ImGuiTableFlags.SizingFixedFit, using var table = Im.Table.Begin("##table"u8, 2, TableFlags.RowBackground | TableFlags.ScrollY | TableFlags.SizingFixedFit,
new Vector2(-1, 12 * ImGui.GetTextLineHeightWithSpacing())); new Vector2(-1, 12 * ImGui.GetTextLineHeightWithSpacing()));
if (!table) if (!table)
return; return;
@ -886,13 +885,13 @@ public class DebugTab : Window, ITab, IUiService
private void DrawActionTmbs() private void DrawActionTmbs()
{ {
using var mainTree = TreeNode("Action TMBs"); using var mainTree = Im.Tree.Node("Action TMBs"u8);
if (!mainTree) if (!mainTree)
return; return;
if (ImGui.InputText("Key", ref _tmbKeyFilter, 256)) if (ImGui.InputText("Key", ref _tmbKeyFilter, 256))
_tmbKeyFilterU8 = CiByteString.FromString(_tmbKeyFilter, out var r, MetaDataComputation.All) ? r : CiByteString.Empty; _tmbKeyFilterU8 = CiByteString.FromString(_tmbKeyFilter, out var r, MetaDataComputation.All) ? r : CiByteString.Empty;
using var table = Table("##table", 2, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY | ImGuiTableFlags.SizingFixedFit, using var table = Im.Table.Begin("##table"u8, 2, TableFlags.RowBackground | TableFlags.ScrollY | TableFlags.SizingFixedFit,
new Vector2(-1, 12 * ImGui.GetTextLineHeightWithSpacing())); new Vector2(-1, 12 * ImGui.GetTextLineHeightWithSpacing()));
if (!table) if (!table)
return; return;
@ -910,17 +909,17 @@ public class DebugTab : Window, ITab, IUiService
private void DrawStainTemplates() private void DrawStainTemplates()
{ {
using var mainTree = TreeNode("Staining Templates"); using var mainTree = Im.Tree.Node("Staining Templates"u8);
if (!mainTree) if (!mainTree)
return; return;
using (var legacyTree = TreeNode("stainingtemplate.stm")) using (var legacyTree = Im.Tree.Node("stainingtemplate.stm"u8))
{ {
if (legacyTree) if (legacyTree)
DrawStainTemplatesFile(_stains.LegacyStmFile); DrawStainTemplatesFile(_stains.LegacyStmFile);
} }
using (var gudTree = TreeNode("stainingtemplate_gud.stm")) using (var gudTree = Im.Tree.Node("stainingtemplate_gud.stm"u8))
{ {
if (gudTree) if (gudTree)
DrawStainTemplatesFile(_stains.GudStmFile); DrawStainTemplatesFile(_stains.GudStmFile);
@ -931,12 +930,12 @@ public class DebugTab : Window, ITab, IUiService
{ {
foreach (var (key, data) in stmFile.Entries) foreach (var (key, data) in stmFile.Entries)
{ {
using var tree = TreeNode($"Template {key}"); using var tree = Im.Tree.Node($"Template {key}");
if (!tree) if (!tree)
continue; continue;
using var table = Table("##table", data.Colors.Length + data.Scalars.Length, using var table = Im.Table.Begin("##table"u8, data.Colors.Length + data.Scalars.Length,
ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg); TableFlags.SizingFixedFit | TableFlags.RowBackground);
if (!table) if (!table)
continue; continue;
@ -974,7 +973,7 @@ public class DebugTab : Window, ITab, IUiService
if (!enableShaderReplacementFixer) if (!enableShaderReplacementFixer)
return; return;
using var table = Table("##ShaderReplacementFixer", 3, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit, using var table = Im.Table.Begin("##ShaderReplacementFixer"u8, 3, TableFlags.RowBackground | TableFlags.SizingFixedFit,
-Vector2.UnitX); -Vector2.UnitX);
if (!table) if (!table)
return; return;
@ -1066,7 +1065,7 @@ public class DebugTab : Window, ITab, IUiService
DrawCopyableAddress("CharacterBase"u8, model); DrawCopyableAddress("CharacterBase"u8, model);
using (var t1 = Table("##table", 2, ImGuiTableFlags.SizingFixedFit)) using (var t1 = Im.Table.Begin("##table"u8, 2, TableFlags.SizingFixedFit))
{ {
if (t1) if (t1)
{ {
@ -1079,7 +1078,7 @@ public class DebugTab : Window, ITab, IUiService
} }
} }
using var table = Table($"##{name}DrawTable", 5, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit); using var table = Im.Table.Begin($"##{name}DrawTable", 5, TableFlags.RowBackground | TableFlags.SizingFixedFit);
if (!table) if (!table)
return; return;
@ -1120,7 +1119,7 @@ public class DebugTab : Window, ITab, IUiService
private string _crcInput = string.Empty; private string _crcInput = string.Empty;
private FullPath _crcPath = FullPath.Empty; private FullPath _crcPath = FullPath.Empty;
private unsafe void DrawCrcCache() private void DrawCrcCache()
{ {
var header = ImUtf8.CollapsingHeader("CRC Cache"u8); var header = ImUtf8.CollapsingHeader("CRC Cache"u8);
if (!header) if (!header)
@ -1188,7 +1187,7 @@ public class DebugTab : Window, ITab, IUiService
if (!header) if (!header)
return; return;
using var table = Table("##ProblemsTable", 6, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit); using var table = Im.Table.Begin("##ProblemsTable"u8, 6, TableFlags.RowBackground | TableFlags.SizingFixedFit);
if (!table) if (!table)
return; return;
@ -1240,10 +1239,7 @@ public class DebugTab : Window, ITab, IUiService
ImUtf8.Text($"Is Cloud Synced? {_cloudTesterReturn}"); ImUtf8.Text($"Is Cloud Synced? {_cloudTesterReturn}");
if (_cloudTesterError is not null) if (_cloudTesterError is not null)
{ Im.Text($"{_cloudTesterError}", ImGuiColors.DalamudRed);
using var color = ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudRed);
ImUtf8.Text($"{_cloudTesterError}");
}
} }

View file

@ -84,7 +84,7 @@ public class RenderTargetDrawer(RenderTargetHdrEnabler renderTargetHdrEnabler, D
+ record.Offset); + record.Offset);
if (texture != null) if (texture != null)
{ {
using var color = Dalamud.Interface.Utility.Raii.ImRaii.PushColor(ImGuiCol.Text, ImGuiUtil.HalfBlendText(0xFF), using var color = ImGuiColor.Text.Push(ImGuiUtil.HalfBlendText(0xFF),
texture->TextureFormat != record.OriginalTextureFormat); texture->TextureFormat != record.OriginalTextureFormat);
ImUtf8.Text($"{texture->TextureFormat}"); ImUtf8.Text($"{texture->TextureFormat}");
} }

View file

@ -1,6 +1,7 @@
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Utility.Raii;
using ImSharp;
using OtterGui.Text; using OtterGui.Text;
using Penumbra.Collections.Cache; using Penumbra.Collections.Cache;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
@ -90,10 +91,10 @@ public class ShapeInspector(ObjectManager objects, CollectionResolver resolver)
private static void DrawValues(in ShapeAttributeString shapeAttribute, ShapeAttributeHashSet set) private static void DrawValues(in ShapeAttributeString shapeAttribute, ShapeAttributeHashSet set)
{ {
ImGui.TableNextColumn(); ImGui.TableNextColumn();
var disabledColor = Im.Style[ImGuiColor.TextDisabled];
if (set.All is { } value) if (set.All is { } value)
{ {
using var color = ImRaii.PushColor(ImGuiCol.Text, ImGui.GetColorU32(ImGuiCol.TextDisabled), !value); using var color = ImGuiColor.Text.Push(disabledColor, !value);
ImUtf8.Text("All, "u8); ImUtf8.Text("All, "u8);
ImGui.SameLine(0, 0); ImGui.SameLine(0, 0);
} }
@ -103,7 +104,7 @@ public class ShapeInspector(ObjectManager objects, CollectionResolver resolver)
if (set[slot] is not { } value2) if (set[slot] is not { } value2)
continue; continue;
using var color = ImRaii.PushColor(ImGuiCol.Text, ImGui.GetColorU32(ImGuiCol.TextDisabled), !value2); using var color = ImGuiColor.Text.Push(disabledColor, !value2);
ImUtf8.Text($"All {slot.ToName()}, "); ImUtf8.Text($"All {slot.ToName()}, ");
ImGui.SameLine(0, 0); ImGui.SameLine(0, 0);
} }
@ -112,7 +113,7 @@ public class ShapeInspector(ObjectManager objects, CollectionResolver resolver)
{ {
if (set[gr] is { } value3) if (set[gr] is { } value3)
{ {
using var color = ImRaii.PushColor(ImGuiCol.Text, ImGui.GetColorU32(ImGuiCol.TextDisabled), !value3); using var color = ImGuiColor.Text.Push(disabledColor, !value3);
ImUtf8.Text($"All {gr.ToName()}, "); ImUtf8.Text($"All {gr.ToName()}, ");
ImGui.SameLine(0, 0); ImGui.SameLine(0, 0);
} }
@ -123,7 +124,7 @@ public class ShapeInspector(ObjectManager objects, CollectionResolver resolver)
if (set[slot, gr] is not { } value4) if (set[slot, gr] is not { } value4)
continue; continue;
using var color = ImRaii.PushColor(ImGuiCol.Text, ImGui.GetColorU32(ImGuiCol.TextDisabled), !value4); using var color = ImGuiColor.Text.Push(disabledColor, !value4);
ImUtf8.Text($"All {gr.ToName()} {slot.ToName()}, "); ImUtf8.Text($"All {gr.ToName()} {slot.ToName()}, ");
ImGui.SameLine(0, 0); ImGui.SameLine(0, 0);
} }
@ -138,7 +139,7 @@ public class ShapeInspector(ObjectManager objects, CollectionResolver resolver)
if (set[slot, GenderRace.Unknown] != enabled) if (set[slot, GenderRace.Unknown] != enabled)
{ {
using var color = ImRaii.PushColor(ImGuiCol.Text, ImGui.GetColorU32(ImGuiCol.TextDisabled), !enabled); using var color = ImGuiColor.Text.Push(disabledColor, !enabled);
ImUtf8.Text($"{slot.ToName()} {id.Id:D4}, "); ImUtf8.Text($"{slot.ToName()} {id.Id:D4}, ");
ImGui.SameLine(0, 0); ImGui.SameLine(0, 0);
} }
@ -153,7 +154,7 @@ public class ShapeInspector(ObjectManager objects, CollectionResolver resolver)
var gr = ShapeAttributeHashSet.GenderRaceValues[currentIndex]; var gr = ShapeAttributeHashSet.GenderRaceValues[currentIndex];
if (set[slot, gr] != enabled) if (set[slot, gr] != enabled)
{ {
using var color = ImRaii.PushColor(ImGuiCol.Text, ImGui.GetColorU32(ImGuiCol.TextDisabled), !enabled); using var color = ImGuiColor.Text.Push(disabledColor, !enabled);
ImUtf8.Text($"{gr.ToName()} {slot.ToName()} #{id.Id:D4}, "); ImUtf8.Text($"{gr.ToName()} {slot.ToName()} #{id.Id:D4}, ");
ImGui.SameLine(0, 0); ImGui.SameLine(0, 0);
} }
@ -186,7 +187,7 @@ public class ShapeInspector(ObjectManager objects, CollectionResolver resolver)
ImGui.TableHeadersRow(); ImGui.TableHeadersRow();
var disabledColor = ImGui.GetColorU32(ImGuiCol.TextDisabled); var disabledColor = Im.Style[ImGuiColor.TextDisabled];
for (var i = 0; i < human.AsHuman->SlotCount; ++i) for (var i = 0; i < human.AsHuman->SlotCount; ++i)
{ {
ImUtf8.DrawTableColumn($"{(uint)i:D2}"); ImUtf8.DrawTableColumn($"{(uint)i:D2}");
@ -205,7 +206,7 @@ public class ShapeInspector(ObjectManager objects, CollectionResolver resolver)
foreach (var (idx, (shape, flag)) in model->ModelResourceHandle->Shapes.Index()) foreach (var (idx, (shape, flag)) in model->ModelResourceHandle->Shapes.Index())
{ {
var disabled = (mask & (1u << flag)) is 0; var disabled = (mask & (1u << flag)) is 0;
using var color = ImRaii.PushColor(ImGuiCol.Text, disabledColor, disabled); using var color = ImGuiColor.Text.Push(disabledColor, disabled);
ImUtf8.Text(shape.AsSpan()); ImUtf8.Text(shape.AsSpan());
ImGui.SameLine(0, 0); ImGui.SameLine(0, 0);
ImUtf8.Text(", "u8); ImUtf8.Text(", "u8);
@ -243,7 +244,7 @@ public class ShapeInspector(ObjectManager objects, CollectionResolver resolver)
ImGui.TableHeadersRow(); ImGui.TableHeadersRow();
var disabledColor = ImGui.GetColorU32(ImGuiCol.TextDisabled); var disabledColor = Im.Style[ImGuiColor.TextDisabled];
for (var i = 0; i < human.AsHuman->SlotCount; ++i) for (var i = 0; i < human.AsHuman->SlotCount; ++i)
{ {
ImUtf8.DrawTableColumn($"{(uint)i:D2}"); ImUtf8.DrawTableColumn($"{(uint)i:D2}");
@ -262,7 +263,7 @@ public class ShapeInspector(ObjectManager objects, CollectionResolver resolver)
foreach (var (idx, (attribute, flag)) in model->ModelResourceHandle->Attributes.Index()) foreach (var (idx, (attribute, flag)) in model->ModelResourceHandle->Attributes.Index())
{ {
var disabled = (mask & (1u << flag)) is 0; var disabled = (mask & (1u << flag)) is 0;
using var color = ImRaii.PushColor(ImGuiCol.Text, disabledColor, disabled); using var color = ImGuiColor.Text.Push(disabledColor, disabled);
ImUtf8.Text(attribute.AsSpan()); ImUtf8.Text(attribute.AsSpan());
ImGui.SameLine(0, 0); ImGui.SameLine(0, 0);
ImUtf8.Text(", "u8); ImUtf8.Text(", "u8);

View file

@ -1,6 +1,7 @@
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Dalamud.Interface.DragDrop; using Dalamud.Interface.DragDrop;
using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Utility.Raii;
using ImSharp;
using Lumina.Data.Files; using Lumina.Data.Files;
using OtterGui.Text; using OtterGui.Text;
using Penumbra.UI.Classes; using Penumbra.UI.Classes;
@ -47,7 +48,7 @@ public class TexHeaderDrawer(IDragDropManager dragDrop) : Luna.IUiService
if (_exception != null) if (_exception != null)
{ {
using var color = ImRaii.PushColor(ImGuiCol.Text, Colors.RegexWarningBorder); using var color = ImGuiColor.Text.Push(Colors.RegexWarningBorder);
ImUtf8.TextWrapped($"Failure to load file:\n{_exception}"); ImUtf8.TextWrapped($"Failure to load file:\n{_exception}");
} }
else if (_tex != null) else if (_tex != null)

View file

@ -95,7 +95,7 @@ public class ModsTab(
} }
var frameHeight = new Vector2(0, ImGui.GetFrameHeight()); var frameHeight = new Vector2(0, ImGui.GetFrameHeight());
var frameColor = ImGui.GetColorU32(ImGuiCol.FrameBg); var frameColor = ImGuiColor.FrameBackground.Get().Color;
using (var _ = ImRaii.Group()) using (var _ = ImRaii.Group())
{ {
using (ImRaii.PushFont(UiBuilder.IconFont)) using (ImRaii.PushFont(UiBuilder.IconFont))

View file

@ -242,7 +242,7 @@ public class SettingsTab : ITab, IUiService
/// </summary> /// </summary>
private bool DrawPressEnterWarning(string newName, string old, float width, bool saved, bool selected) private bool DrawPressEnterWarning(string newName, string old, float width, bool saved, bool selected)
{ {
using var color = ImRaii.PushColor(ImGuiCol.Button, Colors.PressEnterWarningBg); using var color = ImGuiColor.Button.Push(Colors.PressEnterWarningBg);
var w = new Vector2(width, 0); var w = new Vector2(width, 0);
var (text, valid) = CheckRootDirectoryPath(newName, old, selected); var (text, valid) = CheckRootDirectoryPath(newName, old, selected);
@ -339,10 +339,9 @@ public class SettingsTab : ITab, IUiService
using (ImRaii.Group()) using (ImRaii.Group())
{ {
ImGui.SetNextItemWidth(UiHelpers.InputTextMinusButton3); ImGui.SetNextItemWidth(UiHelpers.InputTextMinusButton3);
using (ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, ImGuiHelpers.GlobalScale, !_modManager.Valid)) using (var color = ImStyleBorder.Frame.Push(Colors.RegexWarningBorder, Im.Style.GlobalScale, !_modManager.Valid))
{ {
using var color = ImRaii.PushColor(ImGuiCol.Border, Colors.RegexWarningBorder) color.Push(ImGuiColor.TextDisabled, Colors.RegexWarningBorder, !_modManager.Valid);
.Push(ImGuiCol.TextDisabled, Colors.RegexWarningBorder, !_modManager.Valid);
save = ImGui.InputTextWithHint("##rootDirectory", "Enter Root Directory here (MANDATORY)...", ref _newModDirectory, save = ImGui.InputTextWithHint("##rootDirectory", "Enter Root Directory here (MANDATORY)...", ref _newModDirectory,
RootDirectoryMaxLength, ImGuiInputTextFlags.EnterReturnsTrue); RootDirectoryMaxLength, ImGuiInputTextFlags.EnterReturnsTrue);
} }