Move some services to Luna, move config files. Add and use UiConfig.

This commit is contained in:
Ottermandias 2026-02-18 18:04:58 +01:00
parent 98178ae289
commit 6b7039f743
83 changed files with 643 additions and 540 deletions

View file

@ -3,7 +3,7 @@ using Luna;
namespace Glamourer.Api; namespace Glamourer.Api;
public class GlamourerApi(Configuration config, DesignsApi designs, StateApi state, ItemsApi items) : IGlamourerApi, IApiService public class GlamourerApi(Configuration.Configuration config, DesignsApi designs, StateApi state, ItemsApi items) : IGlamourerApi, IApiService
{ {
public const int CurrentApiVersionMajor = 1; public const int CurrentApiVersionMajor = 1;
public const int CurrentApiVersionMinor = 7; public const int CurrentApiVersionMinor = 7;

View file

@ -16,7 +16,7 @@ namespace Glamourer.Automation;
public sealed class AutoDesignApplier : IDisposable public sealed class AutoDesignApplier : IDisposable
{ {
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly AutoDesignManager _manager; private readonly AutoDesignManager _manager;
private readonly StateManager _state; private readonly StateManager _state;
private readonly JobService _jobs; private readonly JobService _jobs;
@ -31,7 +31,7 @@ public sealed class AutoDesignApplier : IDisposable
private readonly JobChangeState _jobChangeState; private readonly JobChangeState _jobChangeState;
public AutoDesignApplier(Configuration config, AutoDesignManager manager, StateManager state, JobService jobs, ActorManager actors, public AutoDesignApplier(Configuration.Configuration config, AutoDesignManager manager, StateManager state, JobService jobs, ActorManager actors,
AutomationChanged @event, ActorObjectManager objects, WeaponLoading weapons, HumanModelList humans, IClientState clientState, AutomationChanged @event, ActorObjectManager objects, WeaponLoading weapons, HumanModelList humans, IClientState clientState,
EquippedGearset equippedGearset, DesignMerger designMerger, JobChangeState jobChangeState) EquippedGearset equippedGearset, DesignMerger designMerger, JobChangeState jobChangeState)
{ {

View file

@ -381,7 +381,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
_event.Invoke(AutomationChanged.Type.ChangedData, set, (which, data)); _event.Invoke(AutomationChanged.Type.ChangedData, set, (which, data));
} }
public string ToFilename(FilenameService fileNames) public string ToFilePath(FilenameService fileNames)
=> fileNames.AutomationFile; => fileNames.AutomationFile;
public void Save(StreamWriter writer) public void Save(StreamWriter writer)

View file

@ -6,53 +6,21 @@ using Glamourer.Gui;
using Glamourer.Gui.Tabs.DesignTab; using Glamourer.Gui.Tabs.DesignTab;
using Glamourer.Services; using Glamourer.Services;
using ImSharp; using ImSharp;
using Luna;
using Newtonsoft.Json; using Newtonsoft.Json;
using OtterGui.Filesystem; using OtterGui.Filesystem;
using Luna;
using Luna.Generators;
using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs; using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
namespace Glamourer; namespace Glamourer.Configuration;
[TooltipEnum]
public enum HeightDisplayType
{
[Tooltip("Do Not Display")]
None,
[Tooltip("Centimetres (000.0 cm)")]
Centimetre,
[Tooltip("Metres (0.00 m)")]
Metre,
[Tooltip("Inches (00.0 in)")]
Wrong,
[Tooltip("Feet (0'00'')")]
WrongFoot,
[Tooltip("Corgis (0.0 Corgis)")]
Corgi,
[Tooltip("Olympic-size swimming Pools (0.000 Pools)")]
OlympicPool,
}
public class DefaultDesignSettings
{
public bool AlwaysForceRedrawing = false;
public bool ResetAdvancedDyes = false;
public bool ShowQuickDesignBar = true;
public bool ResetTemporarySettings = false;
public bool Locked = false;
}
public class Configuration : IPluginConfiguration, ISavable public class Configuration : IPluginConfiguration, ISavable
{ {
[JsonIgnore] [JsonIgnore]
public readonly EphemeralConfig Ephemeral; public readonly EphemeralConfig Ephemeral;
[JsonIgnore]
public readonly UiConfig Ui;
public bool AttachToPcp { get; set; } = true; public bool AttachToPcp { get; set; } = true;
public bool UseRestrictedGearProtection { get; set; } = false; public bool UseRestrictedGearProtection { get; set; } = false;
public bool OpenFoldersByDefault { get; set; } = false; public bool OpenFoldersByDefault { get; set; } = false;
@ -120,10 +88,11 @@ public class Configuration : IPluginConfiguration, ISavable
[JsonIgnore] [JsonIgnore]
private readonly SaveService _saveService; private readonly SaveService _saveService;
public Configuration(SaveService saveService, ConfigMigrationService migrator, EphemeralConfig ephemeral) public Configuration(SaveService saveService, ConfigMigrationService migrator, EphemeralConfig ephemeral, UiConfig ui)
{ {
_saveService = saveService; _saveService = saveService;
Ephemeral = ephemeral; Ephemeral = ephemeral;
Ui = ui;
Load(migrator); Load(migrator);
} }
@ -132,13 +101,13 @@ public class Configuration : IPluginConfiguration, ISavable
private void Load(ConfigMigrationService migrator) private void Load(ConfigMigrationService migrator)
{ {
if (!File.Exists(_saveService.FileNames.ConfigFile)) if (!File.Exists(_saveService.FileNames.ConfigurationFile))
return; return;
if (File.Exists(_saveService.FileNames.ConfigFile)) if (File.Exists(_saveService.FileNames.ConfigurationFile))
try try
{ {
var text = File.ReadAllText(_saveService.FileNames.ConfigFile); var text = File.ReadAllText(_saveService.FileNames.ConfigurationFile);
JsonConvert.PopulateObject(text, this, new JsonSerializerSettings JsonConvert.PopulateObject(text, this, new JsonSerializerSettings
{ {
Error = HandleDeserializationError, Error = HandleDeserializationError,
@ -162,8 +131,8 @@ public class Configuration : IPluginConfiguration, ISavable
} }
} }
public string ToFilename(FilenameService fileNames) public string ToFilePath(FilenameService fileNames)
=> fileNames.ConfigFile; => fileNames.ConfigurationFile;
public void Save(StreamWriter writer) public void Save(StreamWriter writer)
{ {

View file

@ -0,0 +1,10 @@
namespace Glamourer.Configuration;
public class DefaultDesignSettings
{
public bool AlwaysForceRedrawing = false;
public bool ResetAdvancedDyes = false;
public bool ShowQuickDesignBar = true;
public bool ResetTemporarySettings = false;
public bool Locked = false;
}

View file

@ -1,7 +1,7 @@
using Luna.Generators; using ImSharp;
using ImSharp; using Luna.Generators;
namespace Glamourer; namespace Glamourer.Configuration;
[Flags] [Flags]
[NamedEnum(Utf16: false)] [NamedEnum(Utf16: false)]
@ -42,7 +42,7 @@ public static partial class DesignPanelFlagExtensions
{ {
private static readonly StringU8 Expand = new("Expand"u8); private static readonly StringU8 Expand = new("Expand"u8);
public static Im.HeaderDisposable Header(this DesignPanelFlag flag, Configuration config) public static Im.HeaderDisposable Header(this DesignPanelFlag flag, global::Glamourer.Configuration.Configuration config)
{ {
if (config.HideDesignPanel.HasFlag(flag)) if (config.HideDesignPanel.HasFlag(flag))
return default; return default;
@ -55,7 +55,6 @@ public static partial class DesignPanelFlagExtensions
Action<DesignPanelFlag> setterExpand) Action<DesignPanelFlag> setterExpand)
{ {
var checkBoxWidth = Math.Max(Im.Style.FrameHeight, Expand.CalculateSize().X); var checkBoxWidth = Math.Max(Im.Style.FrameHeight, Expand.CalculateSize().X);
var test = DesignPanelFlag.AdvancedCustomizations.ToNameU8();
var textWidth = AdvancedCustomizations_Name__GenU8.CalculateSize().X; var textWidth = AdvancedCustomizations_Name__GenU8.CalculateSize().X;
var tableSize = 2 * (textWidth + 2 * checkBoxWidth) var tableSize = 2 * (textWidth + 2 * checkBoxWidth)
+ 10 * Im.Style.CellPadding.X + 10 * Im.Style.CellPadding.X

View file

@ -6,7 +6,7 @@ using Luna.Generators;
using Newtonsoft.Json; using Newtonsoft.Json;
using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs; using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
namespace Glamourer; namespace Glamourer.Configuration;
public partial class EphemeralConfig : ISavable public partial class EphemeralConfig : ISavable
{ {
@ -69,7 +69,7 @@ public partial class EphemeralConfig : ISavable
} }
} }
public string ToFilename(FilenameService fileNames) public string ToFilePath(FilenameService fileNames)
=> fileNames.EphemeralConfigFile; => fileNames.EphemeralConfigFile;
public void Save(StreamWriter writer) public void Save(StreamWriter writer)

View file

@ -0,0 +1,28 @@
using Luna.Generators;
namespace Glamourer.Configuration;
[TooltipEnum]
public enum HeightDisplayType
{
[Tooltip("Do Not Display")]
None,
[Tooltip("Centimetres (000.0 cm)")]
Centimetre,
[Tooltip("Metres (0.00 m)")]
Metre,
[Tooltip("Inches (00.0 in)")]
Wrong,
[Tooltip("Feet (0'00'')")]
WrongFoot,
[Tooltip("Corgis (0.0 Corgis)")]
Corgi,
[Tooltip("Olympic-size swimming Pools (0.000 Pools)")]
OlympicPool,
}

View file

@ -0,0 +1,50 @@
using Glamourer.Services;
using Luna;
using Luna.Generators;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Glamourer.Configuration;
public sealed partial class UiConfig : ConfigurationFile<FilenameService>
{
public UiConfig(SaveService saveService, MessageService messageService)
: base(saveService, messageService)
{
Load();
}
[ConfigProperty]
private TwoPanelWidth _actorsTabScale = new(250, ScalingMode.Absolute);
[ConfigProperty]
private TwoPanelWidth _designsTabScale = new(0.3f, ScalingMode.Percentage);
[ConfigProperty]
private TwoPanelWidth _automationTabScale = new(0.3f, ScalingMode.Percentage);
[ConfigProperty]
private TwoPanelWidth _npcTabScale = new(250, ScalingMode.Absolute);
public override int CurrentVersion
=> 1;
protected override void AddData(JsonTextWriter j)
{
ActorsTabScale.WriteJson(j, "ActorsTab");
DesignsTabScale.WriteJson(j, "DesignsTab");
AutomationTabScale.WriteJson(j, "AutomationTab");
NpcTabScale.WriteJson(j, "NpcTab");
}
protected override void LoadData(JObject j)
{
_actorsTabScale = TwoPanelWidth.ReadJson(j, "ActorsTab", new TwoPanelWidth(250, ScalingMode.Absolute));
_designsTabScale = TwoPanelWidth.ReadJson(j, "DesignsTab", new TwoPanelWidth(0.3f, ScalingMode.Percentage));
_automationTabScale = TwoPanelWidth.ReadJson(j, "AutomationTab", new TwoPanelWidth(0.3f, ScalingMode.Percentage));
_npcTabScale = TwoPanelWidth.ReadJson(j, "NpcTab", new TwoPanelWidth(250, ScalingMode.Absolute));
}
public override string ToFilePath(FilenameService fileNames)
=> fileNames.UiConfiguration;
}

View file

@ -11,7 +11,6 @@ using OtterGui.Classes;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
using Luna; using Luna;
using Notification = Luna.Notification; using Notification = Luna.Notification;
using SaveType = OtterGui.Classes.SaveType;
namespace Glamourer.Designs; namespace Glamourer.Designs;
@ -232,7 +231,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
Glamourer.Messager.AddMessage(new Notification( Glamourer.Messager.AddMessage(new Notification(
$"Swapped Gloss and Specular Strength in {materialDesignData.Values.Count} Rows in design {design.Incognito} {reason}", $"Swapped Gloss and Specular Strength in {materialDesignData.Values.Count} Rows in design {design.Incognito} {reason}",
NotificationType.Info)); NotificationType.Info));
saveService.Save(SaveType.ImmediateSync, design); saveService.Save(Luna.SaveType.ImmediateSync, design);
} }
} }
@ -329,15 +328,13 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
#region ISavable #region ISavable
public string ToFilename(FilenameService fileNames) public string ToFilePath(FilenameService fileNames)
=> fileNames.DesignFile(this); => fileNames.DesignFile(this);
public void Save(StreamWriter writer) public void Save(StreamWriter writer)
{ {
using var j = new JsonTextWriter(writer) using var j = new JsonTextWriter(writer);
{ j.Formatting = Formatting.Indented;
Formatting = Formatting.Indented,
};
var obj = JsonSerialize(); var obj = JsonSerialize();
obj.WriteTo(j); obj.WriteTo(j);
} }

View file

@ -8,7 +8,7 @@ using Newtonsoft.Json.Linq;
namespace Glamourer.Designs; namespace Glamourer.Designs;
public class DesignColorUi(DesignColors colors, Configuration config) public class DesignColorUi(DesignColors colors, Configuration.Configuration config)
{ {
private string _newName = string.Empty; private string _newName = string.Empty;
@ -183,7 +183,7 @@ public class DesignColors : ISavable, IReadOnlyDictionary<string, Rgba32>
SaveAndInvoke(); SaveAndInvoke();
} }
public string ToFilename(FilenameService fileNames) public string ToFilePath(FilenameService fileNames)
=> fileNames.DesignColorFile; => fileNames.DesignColorFile;
public void Save(StreamWriter writer) public void Save(StreamWriter writer)

View file

@ -16,14 +16,14 @@ public class DesignEditor(
DesignChanged designChanged, DesignChanged designChanged,
CustomizeService customizations, CustomizeService customizations,
ItemManager items, ItemManager items,
Configuration config) Configuration.Configuration config)
: IDesignEditor : IDesignEditor
{ {
protected readonly DesignChanged DesignChanged = designChanged; protected readonly DesignChanged DesignChanged = designChanged;
protected readonly SaveService SaveService = saveService; protected readonly SaveService SaveService = saveService;
protected readonly ItemManager Items = items; protected readonly ItemManager Items = items;
protected readonly CustomizeService Customizations = customizations; protected readonly CustomizeService Customizations = customizations;
protected readonly Configuration Config = config; protected readonly Configuration.Configuration Config = config;
protected readonly Dictionary<Guid, DesignData> UndoStore = []; protected readonly Dictionary<Guid, DesignData> UndoStore = [];
private bool _forceFullItemOff; private bool _forceFullItemOff;

View file

@ -187,7 +187,7 @@ public sealed class DesignFileSystem : OtterGui.Filesystem.FileSystem<Design>, I
} }
} }
public string ToFilename(FilenameService fileNames) public string ToFilePath(FilenameService fileNames)
=> fileNames.DesignFileSystem; => fileNames.DesignFileSystem;
public void Save(StreamWriter writer) public void Save(StreamWriter writer)

View file

@ -21,7 +21,7 @@ public sealed class DesignManager : DesignEditor
private readonly HumanModelList _humans; private readonly HumanModelList _humans;
public DesignManager(SaveService saveService, ItemManager items, CustomizeService customizations, public DesignManager(SaveService saveService, ItemManager items, CustomizeService customizations,
DesignChanged @event, HumanModelList humans, DesignStorage storage, DesignLinkLoader designLinkLoader, Configuration config) DesignChanged @event, HumanModelList humans, DesignStorage storage, DesignLinkLoader designLinkLoader, Configuration.Configuration config)
: base(saveService, @event, customizations, items, config) : base(saveService, @event, customizations, items, config)
{ {
Designs = storage; Designs = storage;

View file

@ -15,7 +15,7 @@ namespace Glamourer.Designs.Links;
public class DesignMerger( public class DesignMerger(
DesignManager designManager, DesignManager designManager,
CustomizeService customizeService, CustomizeService customizeService,
Configuration config, Configuration.Configuration config,
ItemUnlockManager itemUnlocks, ItemUnlockManager itemUnlocks,
CustomizeUnlockManager customizeUnlocks) : IService CustomizeUnlockManager customizeUnlocks) : IService
{ {

View file

@ -3,7 +3,7 @@ using Luna;
namespace Glamourer.Designs.Special; namespace Glamourer.Designs.Special;
public class RandomDesignGenerator(DesignStorage designs, DesignFileSystem fileSystem, Configuration config) : IService public class RandomDesignGenerator(DesignStorage designs, DesignFileSystem fileSystem, Configuration.Configuration config) : IService
{ {
private readonly Random _rng = new(); private readonly Random _rng = new();
private readonly WeakReference<Design> _lastDesign = new(null!, false); private readonly WeakReference<Design> _lastDesign = new(null!, false);

View file

@ -61,7 +61,7 @@ public class Glamourer : IDalamudPlugin
public string GatherSupportInformation() public string GatherSupportInformation()
{ {
var sb = new StringBuilder(10240); var sb = new StringBuilder(10240);
var config = _services.GetService<Configuration>(); var config = _services.GetService<Configuration.Configuration>();
sb.AppendLine("**Settings**"); sb.AppendLine("**Settings**");
sb.Append($"> **`Plugin Version: `** {Version}\n"); sb.Append($"> **`Plugin Version: `** {Version}\n");
sb.Append($"> **`Commit Hash: `** {CommitHash}\n"); sb.Append($"> **`Commit Hash: `** {CommitHash}\n");

View file

@ -83,6 +83,6 @@ public static class Colors
=> _colors.TryGetValue(color, out var value) ? value : color.Data().DefaultColor; => _colors.TryGetValue(color, out var value) ? value : color.Data().DefaultColor;
/// <summary> Set the configurable colors dictionary to a value. </summary> /// <summary> Set the configurable colors dictionary to a value. </summary>
public static void SetColors(Configuration config) public static void SetColors(Configuration.Configuration config)
=> _colors = config.Colors; => _colors = config.Colors;
} }

View file

@ -1,4 +1,5 @@
using System.Text.Unicode; using System.Text.Unicode;
using Glamourer.Configuration;
using ImSharp; using ImSharp;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;

View file

@ -14,7 +14,7 @@ namespace Glamourer.Gui.Customization;
public partial class CustomizationDrawer( public partial class CustomizationDrawer(
ITextureProvider textures, ITextureProvider textures,
CustomizeService service, CustomizeService service,
Configuration config, Configuration.Configuration config,
FavoriteManager favorites, FavoriteManager favorites,
HeightService heightService) HeightService heightService)
: IDisposable : IDisposable

View file

@ -7,7 +7,7 @@ using Luna;
namespace Glamourer.Gui.Customization; namespace Glamourer.Gui.Customization;
public class CustomizeParameterDrawer(Configuration config, PaletteImport import) : IService public class CustomizeParameterDrawer(Configuration.Configuration config, PaletteImport import) : IService
{ {
private readonly Dictionary<Design, CustomizeParameterData> _lastData = []; private readonly Dictionary<Design, CustomizeParameterData> _lastData = [];
private StringU8 _paletteName = StringU8.Empty; private StringU8 _paletteName = StringU8.Empty;

View file

@ -9,7 +9,7 @@ using Luna;
namespace Glamourer.Gui; namespace Glamourer.Gui;
public abstract class DesignComboBase( public abstract class DesignComboBase(
EphemeralConfig config, Configuration.EphemeralConfig config,
DesignManager designs, DesignManager designs,
DesignChanged designChanged, DesignChanged designChanged,
DesignColors designColors, DesignColors designColors,
@ -17,7 +17,7 @@ public abstract class DesignComboBase(
DesignFileSystem designFileSystem) DesignFileSystem designFileSystem)
: FilterComboBase<DesignComboBase.CacheItem>(new DesignFilter(), ConfigData.Default with { ComputeWidth = true }) : FilterComboBase<DesignComboBase.CacheItem>(new DesignFilter(), ConfigData.Default with { ComputeWidth = true })
{ {
protected readonly EphemeralConfig Config = config; protected readonly Configuration.EphemeralConfig Config = config;
protected readonly DesignChanged DesignChanged = designChanged; protected readonly DesignChanged DesignChanged = designChanged;
protected readonly DesignColors DesignColors = designColors; protected readonly DesignColors DesignColors = designColors;
protected readonly DesignFileSystem DesignFileSystem = designFileSystem; protected readonly DesignFileSystem DesignFileSystem = designFileSystem;
@ -203,7 +203,7 @@ public sealed class QuickDesignCombo : DesignComboBase, IDisposable, IUiService
} }
public QuickDesignCombo(EphemeralConfig config, DesignChanged designChanged, DesignColors designColors, TabSelected tabSelected, public QuickDesignCombo(Configuration.EphemeralConfig config, DesignChanged designChanged, DesignColors designColors, TabSelected tabSelected,
DesignFileSystem designFileSystem, DesignManager designs) DesignFileSystem designFileSystem, DesignManager designs)
: base(config, designs, designChanged, designColors, tabSelected, designFileSystem) : base(config, designs, designChanged, designColors, tabSelected, designFileSystem)
{ {
@ -264,7 +264,7 @@ public sealed class LinkDesignCombo : DesignComboBase, IUiService, IDisposable
{ {
public Design? NewSelection { get; private set; } public Design? NewSelection { get; private set; }
public LinkDesignCombo(EphemeralConfig config, DesignChanged designChanged, DesignColors designColors, TabSelected tabSelected, public LinkDesignCombo(Configuration.EphemeralConfig config, DesignChanged designChanged, DesignColors designColors, TabSelected tabSelected,
DesignFileSystem designFileSystem, DesignManager designs) DesignFileSystem designFileSystem, DesignManager designs)
: base(config, designs, designChanged, designColors, tabSelected, designFileSystem) : base(config, designs, designChanged, designColors, tabSelected, designFileSystem)
{ {
@ -295,7 +295,7 @@ public sealed class LinkDesignCombo : DesignComboBase, IUiService, IDisposable
} }
public sealed class RandomDesignCombo( public sealed class RandomDesignCombo(
EphemeralConfig config, Configuration.EphemeralConfig config,
DesignManager designs, DesignManager designs,
DesignChanged designChanged, DesignChanged designChanged,
DesignColors designColors, DesignColors designColors,
@ -346,7 +346,7 @@ public sealed class SpecialDesignCombo : DesignComboBase, IUiService
private readonly CacheItem _revert; private readonly CacheItem _revert;
private readonly CacheItem _quick; private readonly CacheItem _quick;
public SpecialDesignCombo(EphemeralConfig config, public SpecialDesignCombo(Configuration.EphemeralConfig config,
DesignManager designs, DesignManager designs,
DesignChanged designChanged, DesignChanged designChanged,
DesignColors designColors, DesignColors designColors,

View file

@ -33,7 +33,7 @@ public sealed class DesignQuickBar : Window, IDisposable
? WindowFlags.NoDecoration | WindowFlags.NoDocking | WindowFlags.NoFocusOnAppearing | WindowFlags.NoMove ? WindowFlags.NoDecoration | WindowFlags.NoDocking | WindowFlags.NoFocusOnAppearing | WindowFlags.NoMove
: WindowFlags.NoDecoration | WindowFlags.NoDocking | WindowFlags.NoFocusOnAppearing; : WindowFlags.NoDecoration | WindowFlags.NoDocking | WindowFlags.NoFocusOnAppearing;
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly QuickDesignCombo _designCombo; private readonly QuickDesignCombo _designCombo;
private readonly StateManager _stateManager; private readonly StateManager _stateManager;
private readonly AutoDesignApplier _autoDesignApplier; private readonly AutoDesignApplier _autoDesignApplier;
@ -45,7 +45,7 @@ public sealed class DesignQuickBar : Window, IDisposable
private int _numButtons; private int _numButtons;
private readonly StringBuilder _tooltipBuilder = new(512); private readonly StringBuilder _tooltipBuilder = new(512);
public DesignQuickBar(Configuration config, QuickDesignCombo designCombo, StateManager stateManager, IKeyState keyState, public DesignQuickBar(Configuration.Configuration config, QuickDesignCombo designCombo, StateManager stateManager, IKeyState keyState,
ActorObjectManager objects, AutoDesignApplier autoDesignApplier, PenumbraService penumbra) ActorObjectManager objects, AutoDesignApplier autoDesignApplier, PenumbraService penumbra)
: base("Glamourer Quick Bar", WindowFlags.NoDecoration | WindowFlags.NoDocking) : base("Glamourer Quick Bar", WindowFlags.NoDecoration | WindowFlags.NoDocking)
{ {

View file

@ -22,7 +22,7 @@ public class EquipmentDrawer
private readonly BonusItemCombo[] _bonusItemCombo; private readonly BonusItemCombo[] _bonusItemCombo;
private readonly Dictionary<FullEquipType, WeaponCombo> _weaponCombo; private readonly Dictionary<FullEquipType, WeaponCombo> _weaponCombo;
private readonly TextureService _textures; private readonly TextureService _textures;
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly GPoseService _gPose; private readonly GPoseService _gPose;
private readonly AdvancedDyePopup _advancedDyes; private readonly AdvancedDyePopup _advancedDyes;
private readonly ItemCopyService _itemCopy; private readonly ItemCopyService _itemCopy;
@ -32,7 +32,7 @@ public class EquipmentDrawer
private EquipSlot _dragTarget; private EquipSlot _dragTarget;
public EquipmentDrawer(FavoriteManager favorites, IDataManager gameData, ItemManager items, TextureService textures, public EquipmentDrawer(FavoriteManager favorites, IDataManager gameData, ItemManager items, TextureService textures,
Configuration config, GPoseService gPose, AdvancedDyePopup advancedDyes, ItemCopyService itemCopy) Configuration.Configuration config, GPoseService gPose, AdvancedDyePopup advancedDyes, ItemCopyService itemCopy)
{ {
_items = items; _items = items;
_textures = textures; _textures = textures;

View file

@ -6,12 +6,12 @@ namespace Glamourer.Gui;
public class GenericPopupWindow : Luna.Window public class GenericPopupWindow : Luna.Window
{ {
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly ICondition _condition; private readonly ICondition _condition;
private readonly IClientState _state; private readonly IClientState _state;
public bool OpenFestivalPopup { get; internal set; } public bool OpenFestivalPopup { get; internal set; }
public GenericPopupWindow(Configuration config, IClientState state, ICondition condition) public GenericPopupWindow(Configuration.Configuration config, IClientState state, ICondition condition)
: base("Glamourer Popups", : base("Glamourer Popups",
WindowFlags.NoBringToFrontOnFocus WindowFlags.NoBringToFrontOnFocus
| WindowFlags.NoDecoration | WindowFlags.NoDecoration

View file

@ -6,10 +6,10 @@ namespace Glamourer.Gui;
public class GlamourerChangelog public class GlamourerChangelog
{ {
public const int LastChangelogVersion = 0; public const int LastChangelogVersion = 0;
private readonly Configuration _config; private readonly Configuration.Configuration _config;
public readonly Changelog Changelog; public readonly Changelog Changelog;
public GlamourerChangelog(Configuration config) public GlamourerChangelog(Configuration.Configuration config)
{ {
_config = config; _config = config;
Changelog = new Changelog("Glamourer Changelog", ConfigData, Save); Changelog = new Changelog("Glamourer Changelog", ConfigData, Save);

View file

@ -11,7 +11,7 @@ public class GlamourerWindowSystem : IDisposable
private readonly MainWindow _ui; private readonly MainWindow _ui;
public GlamourerWindowSystem(IUiBuilder uiBuilder, MainWindow ui, GenericPopupWindow popups, public GlamourerWindowSystem(IUiBuilder uiBuilder, MainWindow ui, GenericPopupWindow popups,
Configuration config, UnlocksTab unlocksTab, GlamourerChangelog changelog, DesignQuickBar quick) Configuration.Configuration config, UnlocksTab unlocksTab, GlamourerChangelog changelog, DesignQuickBar quick)
{ {
_uiBuilder = uiBuilder; _uiBuilder = uiBuilder;
_ui = ui; _ui = ui;

View file

@ -14,11 +14,11 @@ namespace Glamourer.Gui;
public sealed class MainTabBar : TabBar<MainTabType> public sealed class MainTabBar : TabBar<MainTabType>
{ {
private readonly EphemeralConfig _config; private readonly Configuration.EphemeralConfig _config;
public readonly TabSelected Event; public readonly TabSelected Event;
public readonly SettingsTab Settings; public readonly SettingsTab Settings;
public MainTabBar(Logger log, EphemeralConfig config, SettingsTab settings, ActorTab actors, DesignTab designs, public MainTabBar(Logger log, Configuration.EphemeralConfig config, SettingsTab settings, ActorTab actors, DesignTab designs,
AutomationTab automation, UnlocksTab unlocks, NpcTab npcs, MessagesTab messages, DebugTab debug, TabSelected @event) AutomationTab automation, UnlocksTab unlocks, NpcTab npcs, MessagesTab messages, DebugTab debug, TabSelected @event)
: base("MainTabBar", log, settings, actors, designs, automation, unlocks, npcs, messages, debug) : base("MainTabBar", log, settings, actors, designs, automation, unlocks, npcs, messages, debug)
{ {

View file

@ -8,13 +8,13 @@ namespace Glamourer.Gui;
public sealed class MainWindow : Window, IDisposable public sealed class MainWindow : Window, IDisposable
{ {
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly PenumbraService _penumbra; private readonly PenumbraService _penumbra;
private readonly DesignQuickBar _quickBar; private readonly DesignQuickBar _quickBar;
private readonly MainTabBar _mainTabBar; private readonly MainTabBar _mainTabBar;
private bool _ignorePenumbra; private bool _ignorePenumbra;
public MainWindow(IDalamudPluginInterface pi, Configuration config, PenumbraService penumbra, public MainWindow(IDalamudPluginInterface pi, Configuration.Configuration config, PenumbraService penumbra,
MainTabBar mainTabBar, DesignQuickBar quickBar) MainTabBar mainTabBar, DesignQuickBar quickBar)
: base("GlamourerMainWindow") : base("GlamourerMainWindow")
{ {

View file

@ -2,6 +2,7 @@
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel; using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
using FFXIVClientStructs.FFXIV.Client.Graphics.Render; using FFXIVClientStructs.FFXIV.Client.Graphics.Render;
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle; using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
using Glamourer.Configuration;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Interop.Material; using Glamourer.Interop.Material;
using Glamourer.State; using Glamourer.State;
@ -16,7 +17,7 @@ using Notification = Luna.Notification;
namespace Glamourer.Gui.Materials; namespace Glamourer.Gui.Materials;
public sealed unsafe class AdvancedDyePopup( public sealed unsafe class AdvancedDyePopup(
Configuration config, Configuration.Configuration config,
StateManager stateManager, StateManager stateManager,
LiveColorTablePreviewer preview, LiveColorTablePreviewer preview,
DirectXService directX) : IService DirectXService directX) : IService

View file

@ -7,7 +7,7 @@ using Penumbra.GameData.Files.MaterialStructs;
namespace Glamourer.Gui.Materials; namespace Glamourer.Gui.Materials;
public class MaterialDrawer(DesignManager designManager, Configuration config) : IService public class MaterialDrawer(DesignManager designManager, Configuration.Configuration config) : IService
{ {
public const float GlossWidth = 100; public const float GlossWidth = 100;
public const float SpecularStrengthWidth = 125; public const float SpecularStrengthWidth = 125;

View file

@ -1,6 +1,7 @@
using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ImGuiNotification;
using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game;
using Glamourer.Automation; using Glamourer.Automation;
using Glamourer.Configuration;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Designs.History; using Glamourer.Designs.History;
using Glamourer.Gui.Customization; using Glamourer.Gui.Customization;
@ -24,7 +25,7 @@ public sealed class ActorPanel : IPanel
private readonly CustomizationDrawer _customizationDrawer; private readonly CustomizationDrawer _customizationDrawer;
private readonly EquipmentDrawer _equipmentDrawer; private readonly EquipmentDrawer _equipmentDrawer;
private readonly AutoDesignApplier _autoDesignApplier; private readonly AutoDesignApplier _autoDesignApplier;
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly DesignConverter _converter; private readonly DesignConverter _converter;
private readonly ActorObjectManager _objects; private readonly ActorObjectManager _objects;
private readonly ImportService _importService; private readonly ImportService _importService;
@ -36,7 +37,7 @@ public sealed class ActorPanel : IPanel
CustomizationDrawer customizationDrawer, CustomizationDrawer customizationDrawer,
EquipmentDrawer equipmentDrawer, EquipmentDrawer equipmentDrawer,
AutoDesignApplier autoDesignApplier, AutoDesignApplier autoDesignApplier,
Configuration config, Configuration.Configuration config,
DesignConverter converter, DesignConverter converter,
ActorObjectManager objects, ActorObjectManager objects,
DesignManager designManager, DesignManager designManager,

View file

@ -14,7 +14,7 @@ public readonly struct ActorCacheItem(ActorIdentifier identifier, ActorData data
public readonly StringU8 IncognitoText = new(identifier.Incognito(data.Label)); public readonly StringU8 IncognitoText = new(identifier.Incognito(data.Label));
} }
public sealed class ActorSelector(ActorSelection selection, ActorObjectManager objects, ActorFilter filter, PenumbraService penumbra, EphemeralConfig config) : IPanel public sealed class ActorSelector(ActorSelection selection, ActorObjectManager objects, ActorFilter filter, PenumbraService penumbra, Configuration.EphemeralConfig config) : IPanel
{ {
public ReadOnlySpan<byte> Id public ReadOnlySpan<byte> Id
=> "ActorSelector"u8; => "ActorSelector"u8;

View file

@ -1,4 +1,5 @@
using ImSharp; using Glamourer.Configuration;
using ImSharp;
using Luna; using Luna;
namespace Glamourer.Gui.Tabs.ActorTab; namespace Glamourer.Gui.Tabs.ActorTab;
@ -6,11 +7,13 @@ namespace Glamourer.Gui.Tabs.ActorTab;
public sealed class ActorTab : TwoPanelLayout, ITab<MainTabType> public sealed class ActorTab : TwoPanelLayout, ITab<MainTabType>
{ {
private readonly ActorSelection _selection; private readonly ActorSelection _selection;
private readonly UiConfig _uiConfig;
public ActorTab(ActorSelector selector, ActorPanel panel, ActorFilter filter, SelectPlayerButton selectPlayer, public ActorTab(ActorSelector selector, ActorPanel panel, ActorFilter filter, SelectPlayerButton selectPlayer,
SelectTargetButton selectTarget, ActorsHeader header, ActorSelection selection) SelectTargetButton selectTarget, ActorsHeader header, ActorSelection selection, UiConfig uiConfig)
{ {
_selection = selection; _selection = selection;
_uiConfig = uiConfig;
LeftPanel = selector; LeftPanel = selector;
LeftHeader = new FilterHeader<ActorCacheItem>(filter, new StringU8("Filter..."u8)); LeftHeader = new FilterHeader<ActorCacheItem>(filter, new StringU8("Filter..."u8));
var footer = new ButtonFooter(); var footer = new ButtonFooter();
@ -29,9 +32,18 @@ public sealed class ActorTab : TwoPanelLayout, ITab<MainTabType>
public void DrawContent() public void DrawContent()
{ {
_selection.Update(); _selection.Update();
Draw(TwoPanelWidth.IndeterminateRelative); Draw(_uiConfig.ActorsTabScale);
} }
protected override void SetWidth(float width, ScalingMode mode)
=> _uiConfig.ActorsTabScale = new TwoPanelWidth(width, mode);
protected override float MinimumWidth
=> LeftHeader.MinimumWidth;
protected override float MaximumWidth
=> Im.Window.Width - 500 * Im.Style.GlobalScale;
public MainTabType Identifier public MainTabType Identifier
=> MainTabType.Actors; => MainTabType.Actors;
} }

View file

@ -6,10 +6,10 @@ namespace Glamourer.Gui.Tabs.ActorTab;
public sealed class ActorsHeader : SplitButtonHeader public sealed class ActorsHeader : SplitButtonHeader
{ {
private readonly ActorSelection _selection; private readonly ActorSelection _selection;
private readonly EphemeralConfig _config; private readonly Configuration.EphemeralConfig _config;
public ActorsHeader(SetFromClipboardButton setFromClipboard, ExportToClipboardButton exportToClipboard, SaveAsDesignButton save, public ActorsHeader(SetFromClipboardButton setFromClipboard, ExportToClipboardButton exportToClipboard, SaveAsDesignButton save,
UndoButton undo, LockedButton locked, IncognitoButton incognito, ActorSelection selection, EphemeralConfig config) UndoButton undo, LockedButton locked, IncognitoButton incognito, ActorSelection selection, Configuration.EphemeralConfig config)
{ {
_selection = selection; _selection = selection;
_config = config; _config = config;

View file

@ -10,7 +10,7 @@ namespace Glamourer.Gui.Tabs.AutomationTab;
public sealed class AutomationButtons : ButtonFooter public sealed class AutomationButtons : ButtonFooter
{ {
public AutomationButtons(Configuration config, AutoDesignManager manager, AutomationSelection selection, ActorObjectManager objects) public AutomationButtons(Configuration.Configuration config, AutoDesignManager manager, AutomationSelection selection, ActorObjectManager objects)
{ {
Buttons.AddButton(new AddButton(objects, manager), 100); Buttons.AddButton(new AddButton(objects, manager), 100);
Buttons.AddButton(new DuplicateButton(selection, manager), 90); Buttons.AddButton(new DuplicateButton(selection, manager), 90);
@ -134,7 +134,7 @@ public sealed class AutomationButtons : ButtonFooter
} }
} }
private sealed class DeleteButton(AutomationSelection selection, Configuration config, AutoDesignManager manager) private sealed class DeleteButton(AutomationSelection selection, Configuration.Configuration config, AutoDesignManager manager)
: BaseIconButton<AwesomeIcon> : BaseIconButton<AwesomeIcon>
{ {
private bool _enabled; private bool _enabled;

View file

@ -3,7 +3,7 @@ using Luna;
namespace Glamourer.Gui.Tabs.AutomationTab; namespace Glamourer.Gui.Tabs.AutomationTab;
public sealed class AutomationHeader(Configuration config, AutomationSelection selection) : IHeader public sealed class AutomationHeader(Configuration.Configuration config, AutomationSelection selection) : IHeader
{ {
public bool Collapsed public bool Collapsed
=> false; => false;

View file

@ -5,10 +5,10 @@ namespace Glamourer.Gui.Tabs.AutomationTab;
public class AutomationTab : TwoPanelLayout, ITab<MainTabType> public class AutomationTab : TwoPanelLayout, ITab<MainTabType>
{ {
private readonly Configuration _config; private readonly Configuration.Configuration _config;
public AutomationTab(AutomationFilter filter, SetSelector selector, SetPanel panel, AutomationButtons buttons, AutomationHeader header, public AutomationTab(AutomationFilter filter, SetSelector selector, SetPanel panel, AutomationButtons buttons, AutomationHeader header,
Configuration config) Configuration.Configuration config)
{ {
_config = config; _config = config;
LeftHeader = new FilterHeader<AutomationCacheItem>(filter, new StringU8("Filter..."u8)); LeftHeader = new FilterHeader<AutomationCacheItem>(filter, new StringU8("Filter..."u8));
@ -30,7 +30,11 @@ public class AutomationTab : TwoPanelLayout, ITab<MainTabType>
=> MainTabType.Automation; => MainTabType.Automation;
public void DrawContent() public void DrawContent()
{ => Draw(_config.Ui.AutomationTabScale);
Draw(TwoPanelWidth.IndeterminateRelative);
} protected override float MinimumWidth
=> LeftFooter.MinimumWidth;
protected override float MaximumWidth
=> Im.Window.Width - 500 * Im.Style.GlobalScale;
} }

View file

@ -14,7 +14,7 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
private int _designIndex = -1; private int _designIndex = -1;
private readonly AutomationChanged _automationChanged; private readonly AutomationChanged _automationChanged;
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly AutoDesignManager _autoDesignManager; private readonly AutoDesignManager _autoDesignManager;
private readonly RandomDesignCombo _randomDesignCombo; private readonly RandomDesignCombo _randomDesignCombo;
private readonly AutomationSelection _selection; private readonly AutomationSelection _selection;
@ -25,7 +25,7 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
private string? _newDefinition; private string? _newDefinition;
private Design? _newDesign; private Design? _newDesign;
public RandomRestrictionDrawer(AutomationChanged automationChanged, Configuration config, AutoDesignManager autoDesignManager, public RandomRestrictionDrawer(AutomationChanged automationChanged, Configuration.Configuration config, AutoDesignManager autoDesignManager,
RandomDesignCombo randomDesignCombo, AutomationSelection selection, DesignFileSystem designFileSystem, DesignStorage designs) RandomDesignCombo randomDesignCombo, AutomationSelection selection, DesignFileSystem designFileSystem, DesignStorage designs)
{ {
_automationChanged = automationChanged; _automationChanged = automationChanged;

View file

@ -19,7 +19,7 @@ public class SetPanel(
CustomizeUnlockManager customizeUnlocks, CustomizeUnlockManager customizeUnlocks,
CustomizeService customizations, CustomizeService customizations,
IdentifierDrawer identifierDrawer, IdentifierDrawer identifierDrawer,
Configuration config, Configuration.Configuration config,
RandomRestrictionDrawer randomDrawer, RandomRestrictionDrawer randomDrawer,
AutomationSelection selection) : IPanel AutomationSelection selection) : IPanel
{ {
@ -33,8 +33,7 @@ public class SetPanel(
public void Draw() public void Draw()
{ {
using var child = Im.Child.Begin("##Panel"u8, Im.ContentRegion.Available, true); if (selection.Index < 0)
if (!child || selection.Index < 0)
return; return;
using (Im.Group()) using (Im.Group())

View file

@ -8,7 +8,7 @@ namespace Glamourer.Gui.Tabs.AutomationTab;
public sealed class SetSelector( public sealed class SetSelector(
AutomationSelection selection, AutomationSelection selection,
Configuration config, Configuration.Configuration config,
AutoDesignManager manager, AutoDesignManager manager,
AutomationFilter filter, AutomationFilter filter,
ActorObjectManager objects, ActorObjectManager objects,

View file

@ -5,7 +5,7 @@ namespace Glamourer.Gui.Tabs.DebugTab;
public sealed class DebugTab(ServiceManager manager) : ITab<MainTabType> public sealed class DebugTab(ServiceManager manager) : ITab<MainTabType>
{ {
private readonly Configuration _config = manager.GetService<Configuration>(); private readonly Configuration.Configuration _config = manager.GetService<Configuration.Configuration>();
public bool IsVisible public bool IsVisible
=> _config.DebugMode; => _config.DebugMode;

View file

@ -4,7 +4,7 @@ using Penumbra.GameData.Gui.Debug;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public sealed class FunPanel(FunModule funModule, Configuration config) : IGameDataDrawer public sealed class FunPanel(FunModule funModule, Configuration.Configuration config) : IGameDataDrawer
{ {
public ReadOnlySpan<byte> Label public ReadOnlySpan<byte> Label
=> "Fun Module"u8; => "Fun Module"u8;

View file

@ -1,4 +1,5 @@
using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ImGuiNotification;
using Glamourer.Configuration;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Services; using Glamourer.Services;
using ImSharp; using ImSharp;
@ -9,7 +10,7 @@ namespace Glamourer.Gui.Tabs.DesignTab;
public class DesignDetailTab public class DesignDetailTab
{ {
private readonly SaveService _saveService; private readonly SaveService _saveService;
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly DesignFileSystemSelector _selector; private readonly DesignFileSystemSelector _selector;
private readonly DesignFileSystem _fileSystem; private readonly DesignFileSystem _fileSystem;
private readonly DesignManager _manager; private readonly DesignManager _manager;
@ -19,7 +20,7 @@ public class DesignDetailTab
private bool _editDescriptionMode; private bool _editDescriptionMode;
public DesignDetailTab(SaveService saveService, DesignFileSystemSelector selector, DesignManager manager, DesignFileSystem fileSystem, public DesignDetailTab(SaveService saveService, DesignFileSystemSelector selector, DesignManager manager, DesignFileSystem fileSystem,
DesignColors colors, Configuration config) DesignColors colors, Configuration.Configuration config)
{ {
_saveService = saveService; _saveService = saveService;
_selector = selector; _selector = selector;

View file

@ -22,7 +22,7 @@ public sealed class DesignFileSystemSelector : FileSystemSelector<Design, Design
{ {
private readonly DesignManager _designManager; private readonly DesignManager _designManager;
private readonly DesignChanged _event; private readonly DesignChanged _event;
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly DesignConverter _converter; private readonly DesignConverter _converter;
private readonly TabSelected _selectionEvent; private readonly TabSelected _selectionEvent;
private readonly DesignColors _designColors; private readonly DesignColors _designColors;
@ -62,7 +62,7 @@ public sealed class DesignFileSystemSelector : FileSystemSelector<Design, Design
} }
public DesignFileSystemSelector(DesignManager designManager, DesignFileSystem fileSystem, IKeyState keyState, DesignChanged @event, public DesignFileSystemSelector(DesignManager designManager, DesignFileSystem fileSystem, IKeyState keyState, DesignChanged @event,
Configuration config, DesignConverter converter, TabSelected selectionEvent, OtterGui.Log.Logger log, DesignColors designColors, Configuration.Configuration config, DesignConverter converter, TabSelected selectionEvent, OtterGui.Log.Logger log, DesignColors designColors,
DesignApplier designApplier) DesignApplier designApplier)
: base(fileSystem, keyState, log, allowMultipleSelection: true) : base(fileSystem, keyState, log, allowMultipleSelection: true)
{ {

View file

@ -1,5 +1,6 @@
using Dalamud.Interface; using Dalamud.Interface;
using Glamourer.Automation; using Glamourer.Automation;
using Glamourer.Configuration;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Designs.Links; using Glamourer.Designs.Links;
using ImSharp; using ImSharp;
@ -12,7 +13,7 @@ public class DesignLinkDrawer(
DesignFileSystemSelector selector, DesignFileSystemSelector selector,
LinkDesignCombo combo, LinkDesignCombo combo,
DesignColors colorManager, DesignColors colorManager,
Configuration config) : IUiService Configuration.Configuration config) : IUiService
{ {
private int _dragDropIndex = -1; private int _dragDropIndex = -1;
private LinkOrder _dragDropOrder = LinkOrder.None; private LinkOrder _dragDropOrder = LinkOrder.None;

View file

@ -13,6 +13,7 @@ using Glamourer.Gui.Materials;
using Glamourer.Interop; using Glamourer.Interop;
using Glamourer.State; using Glamourer.State;
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Glamourer.Configuration;
using ImSharp; using ImSharp;
using Luna; using Luna;
using OtterGui; using OtterGui;
@ -34,7 +35,7 @@ public class DesignPanel : IPanel
private readonly StateManager _state; private readonly StateManager _state;
private readonly EquipmentDrawer _equipmentDrawer; private readonly EquipmentDrawer _equipmentDrawer;
private readonly ModAssociationsTab _modAssociations; private readonly ModAssociationsTab _modAssociations;
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly DesignDetailTab _designDetails; private readonly DesignDetailTab _designDetails;
private readonly ImportService _importService; private readonly ImportService _importService;
private readonly DesignConverter _converter; private readonly DesignConverter _converter;
@ -53,7 +54,7 @@ public class DesignPanel : IPanel
StateManager state, StateManager state,
EquipmentDrawer equipmentDrawer, EquipmentDrawer equipmentDrawer,
ModAssociationsTab modAssociations, ModAssociationsTab modAssociations,
Configuration config, Configuration.Configuration config,
DesignDetailTab designDetails, DesignDetailTab designDetails,
DesignConverter converter, DesignConverter converter,
ImportService importService, ImportService importService,
@ -473,7 +474,8 @@ public class DesignPanel : IPanel
public void Draw() public void Draw()
{ {
using var group = ImUtf8.Group(); using var group = ImUtf8.Group();
if (_selection.DesignPaths.Count > 1) //if (_selection.DesignPaths.Count > 1)
if (false)
{ {
_multiDesignPanel.Draw(); _multiDesignPanel.Draw();
} }
@ -597,7 +599,7 @@ public class DesignPanel : IPanel
private static unsafe string GetUserPath() private static unsafe string GetUserPath()
=> Framework.Instance()->UserPathString; => Framework.Instance()->UserPathString;
}
private sealed class LockButton(DesignPanel panel) : Button private sealed class LockButton(DesignPanel panel) : Button
{ {
@ -757,3 +759,4 @@ private sealed class UndoButton(DesignPanel panel) : Button
protected override void OnClick() protected override void OnClick()
=> panel._history.Undo(panel._selection.Design!); => panel._history.Undo(panel._selection.Design!);
} }
}

View file

@ -1,4 +1,5 @@
using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ImGuiNotification;
using Glamourer.Configuration;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Interop; using Glamourer.Interop;
using ImSharp; using ImSharp;
@ -29,4 +30,13 @@ public sealed class DesignTab(DesignFileSystemSelector selector, DesignPanel pan
panel.Draw(); panel.Draw();
importService.CreateCharaSource(); importService.CreateCharaSource();
} }
//protected override void SetWidth(float width, ScalingMode mode)
// => _uiConfig.ActorsTabScale = new TwoPanelWidth(width, mode);
//
//protected override float MinimumWidth
// => LeftFooter.MinimumWidth;
//
//protected override float MaximumWidth
// => Im.Window.Width - 500 * Im.Style.GlobalScale;
} }

View file

@ -1,4 +1,5 @@
using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ImGuiNotification;
using Glamourer.Configuration;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Interop.Penumbra; using Glamourer.Interop.Penumbra;
using Glamourer.State; using Glamourer.State;
@ -7,9 +8,9 @@ using Luna;
namespace Glamourer.Gui.Tabs.DesignTab; namespace Glamourer.Gui.Tabs.DesignTab;
public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelector selector, DesignManager manager, Configuration config) public class ModAssociationsTab(PenumbraService penumbra, DesignSelection selection, DesignManager manager, Configuration.Configuration config)
{ {
private readonly ModCombo _modCombo = new(penumbra, Glamourer.Log, selector); private readonly ModCombo _modCombo = new(penumbra, selection);
private (Mod, ModSettings)[]? _copy; private (Mod, ModSettings)[]? _copy;
public void Draw() public void Draw()
@ -35,7 +36,7 @@ public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelect
{ {
var size = new Vector2((Im.ContentRegion.Available.X - 2 * Im.Style.ItemSpacing.X) / 3, 0); var size = new Vector2((Im.ContentRegion.Available.X - 2 * Im.Style.ItemSpacing.X) / 3, 0);
if (Im.Button("Copy All to Clipboard"u8, size)) if (Im.Button("Copy All to Clipboard"u8, size))
_copy = selector.Selected!.AssociatedMods.Select(kvp => (kvp.Key, kvp.Value)).ToArray(); _copy = selection.Design!.AssociatedMods.Select(kvp => (kvp.Key, kvp.Value)).ToArray();
Im.Line.Same(); Im.Line.Same();
@ -44,7 +45,7 @@ public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelect
? $"Add {_copy.Length} mod association(s) from clipboard." ? $"Add {_copy.Length} mod association(s) from clipboard."
: "Copy some mod associations to the clipboard, first."u8, _copy is null)) : "Copy some mod associations to the clipboard, first."u8, _copy is null))
foreach (var (mod, setting) in _copy!) foreach (var (mod, setting) in _copy!)
manager.UpdateMod(selector.Selected!, mod, setting); manager.UpdateMod(selection.Design!, mod, setting);
Im.Line.Same(); Im.Line.Same();
@ -53,10 +54,10 @@ public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelect
? $"Set {_copy.Length} mod association(s) from clipboard and discard existing." ? $"Set {_copy.Length} mod association(s) from clipboard and discard existing."
: "Copy some mod associations to the clipboard, first."u8, _copy is null)) : "Copy some mod associations to the clipboard, first."u8, _copy is null))
{ {
while (selector.Selected!.AssociatedMods.Count > 0) while (selection.Design!.AssociatedMods.Count > 0)
manager.RemoveMod(selector.Selected!, selector.Selected!.AssociatedMods.Keys[0]); manager.RemoveMod(selection.Design!, selection.Design!.AssociatedMods.Keys[0]);
foreach (var (mod, setting) in _copy!) foreach (var (mod, setting) in _copy!)
manager.AddMod(selector.Selected!, mod, setting); manager.AddMod(selection.Design!, mod, setting);
} }
} }
@ -75,13 +76,13 @@ public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelect
var (id, name) = penumbra.CurrentCollection; var (id, name) = penumbra.CurrentCollection;
if (ImEx.Button("Apply Mod Associations"u8, Vector2.Zero, if (ImEx.Button("Apply Mod Associations"u8, Vector2.Zero,
$"Try to apply all associated mod settings to Penumbras current collection {name}", $"Try to apply all associated mod settings to Penumbras current collection {name}",
selector.Selected!.AssociatedMods.Count is 0 || id == Guid.Empty)) selection.Design!.AssociatedMods.Count is 0 || id == Guid.Empty))
ApplyAll(); ApplyAll();
} }
public void ApplyAll() public void ApplyAll()
{ {
foreach (var (mod, settings) in selector.Selected!.AssociatedMods) foreach (var (mod, settings) in selection.Design!.AssociatedMods)
penumbra.SetMod(mod, settings, StateSource.Manual, false); penumbra.SetMod(mod, settings, StateSource.Manual, false);
} }
@ -103,7 +104,7 @@ public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelect
Mod? removedMod = null; Mod? removedMod = null;
(Mod mod, ModSettings settings)? updatedMod = null; (Mod mod, ModSettings settings)? updatedMod = null;
foreach (var (idx, (mod, settings)) in selector.Selected!.AssociatedMods.Index()) foreach (var (idx, (mod, settings)) in selection.Design!.AssociatedMods.Index())
{ {
using var id = Im.Id.Push(idx); using var id = Im.Id.Push(idx);
DrawAssociatedModRow(table, mod, settings, out var removedModTmp, out var updatedModTmp); DrawAssociatedModRow(table, mod, settings, out var removedModTmp, out var updatedModTmp);
@ -116,10 +117,10 @@ public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelect
DrawNewModRow(table); DrawNewModRow(table);
if (removedMod.HasValue) if (removedMod.HasValue)
manager.RemoveMod(selector.Selected!, removedMod.Value); manager.RemoveMod(selection.Design!, removedMod.Value);
if (updatedMod.HasValue) if (updatedMod.HasValue)
manager.UpdateMod(selector.Selected!, updatedMod.Value.mod, updatedMod.Value.settings); manager.UpdateMod(selection.Design!, updatedMod.Value.mod, updatedMod.Value.settings);
} }
private void DrawAssociatedModRow(in Im.TableDisposable table, Mod mod, ModSettings settings, out Mod? removedMod, private void DrawAssociatedModRow(in Im.TableDisposable table, Mod mod, ModSettings settings, out Mod? removedMod,
@ -240,18 +241,17 @@ public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelect
private void DrawNewModRow(in Im.TableDisposable table) private void DrawNewModRow(in Im.TableDisposable table)
{ {
var currentName = _modCombo.CurrentSelection.Mod.Name; var currentDir = _modCombo.Selection;
table.NextColumn(); table.NextColumn();
var tt = string.IsNullOrEmpty(currentName) var tt = currentDir.Length is 0
? "Please select a mod first."u8 ? "Please select a mod first."u8
: selector.Selected!.AssociatedMods.ContainsKey(_modCombo.CurrentSelection.Mod) : selection.Design!.AssociatedMods.ContainsKey(new Mod(_modCombo.SelectionName, currentDir))
? "The design already contains an association with the selected mod."u8 ? "The design already contains an association with the selected mod."u8
: StringU8.Empty; : StringU8.Empty;
if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, tt, tt.Length > 0)) if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, tt, tt.Length > 0))
manager.AddMod(selector.Selected!, _modCombo.CurrentSelection.Mod, _modCombo.CurrentSelection.Settings); manager.AddMod(selection.Design!, new Mod(_modCombo.SelectionName, _modCombo.Selection), _modCombo.Settings);
table.NextColumn(); table.NextColumn();
_modCombo.Draw("##new", string.IsNullOrEmpty(currentName) ? "Select new Mod..." : currentName, string.Empty, _modCombo.Draw("##new"u8, Im.ContentRegion.Available.X);
Im.ContentRegion.Available.X, Im.Style.TextHeight);
} }
} }

View file

@ -3,7 +3,7 @@ using ImSharp;
namespace Glamourer.Gui.Tabs.DesignTab; namespace Glamourer.Gui.Tabs.DesignTab;
public sealed class ModCombo(PenumbraService penumbra, DesignSelection selection) : ImSharp.FilterComboBase<ModCombo.CacheItem>(new ModFilter()) public sealed class ModCombo(PenumbraService penumbra, DesignSelection selection) : FilterComboBase<ModCombo.CacheItem>(new ModFilter())
{ {
public readonly struct CacheItem(in Mod mod, in ModSettings settings, int count) public readonly struct CacheItem(in Mod mod, in ModSettings settings, int count)
{ {
@ -23,6 +23,21 @@ public sealed class ModCombo(PenumbraService penumbra, DesignSelection selection
public readonly bool DifferingNames = string.Equals(mod.Name, mod.DirectoryName, StringComparison.CurrentCultureIgnoreCase); public readonly bool DifferingNames = string.Equals(mod.Name, mod.DirectoryName, StringComparison.CurrentCultureIgnoreCase);
} }
public StringPair SelectionName { get; private set; } = new("Select new Mod...", new StringU8("Select new Mod..."u8));
public string Selection { get; private set; } = string.Empty;
public ModSettings Settings { get; private set; } = ModSettings.Empty;
public bool Draw(Utf8StringHandler<LabelStringHandlerBuffer> label, float previewWidth)
{
if (!Draw(label, SelectionName.Utf8, StringU8.Empty, previewWidth, out var newItem))
return false;
SelectionName = newItem.Name;
Selection = newItem.Directory.Utf16;
Settings = newItem.Settings;
return true;
}
protected override float ItemHeight protected override float ItemHeight
=> Im.Style.TextHeightWithSpacing; => Im.Style.TextHeightWithSpacing;
@ -48,7 +63,7 @@ public sealed class ModCombo(PenumbraService penumbra, DesignSelection selection
using var style = ImStyleSingle.PopupBorderThickness.Push(2 * Im.Style.GlobalScale); using var style = ImStyleSingle.PopupBorderThickness.Push(2 * Im.Style.GlobalScale);
using var tt = Im.Tooltip.Begin(); using var tt = Im.Tooltip.Begin();
Im.Dummy(new Vector2(300 * Im.Style.GlobalScale, 0)); Im.Dummy(ImEx.ScaledVectorX(300));
using (Im.Group()) using (Im.Group())
{ {
if (item.DifferingNames) if (item.DifferingNames)
@ -71,7 +86,7 @@ public sealed class ModCombo(PenumbraService penumbra, DesignSelection selection
} }
} }
private static void DrawSettingsLeft(in ModSettings settings) public static void DrawSettingsLeft(in ModSettings settings)
{ {
foreach (var setting in settings.Settings) foreach (var setting in settings.Settings)
{ {
@ -81,7 +96,7 @@ public sealed class ModCombo(PenumbraService penumbra, DesignSelection selection
} }
} }
private static void DrawSettingsRight(in ModSettings settings) public static void DrawSettingsRight(in ModSettings settings)
{ {
foreach (var setting in settings.Settings) foreach (var setting in settings.Settings)
{ {
@ -94,7 +109,7 @@ public sealed class ModCombo(PenumbraService penumbra, DesignSelection selection
} }
protected override bool IsSelected(CacheItem item, int globalIndex) protected override bool IsSelected(CacheItem item, int globalIndex)
=> throw new NotImplementedException(); => Selection.Equals(item.Directory.Utf16, StringComparison.OrdinalIgnoreCase);
private sealed class ModFilter : TextFilterBase<CacheItem> private sealed class ModFilter : TextFilterBase<CacheItem>
{ {

View file

@ -9,7 +9,7 @@ public class MultiDesignPanel(
DesignFileSystemSelector selector, DesignFileSystemSelector selector,
DesignManager editor, DesignManager editor,
DesignColors colors, DesignColors colors,
Configuration config) Configuration.Configuration config)
{ {
private readonly DesignColorCombo _colorCombo = new(colors, true); private readonly DesignColorCombo _colorCombo = new(colors, true);

View file

@ -3,7 +3,7 @@ using Luna;
namespace Glamourer.Gui.Tabs; namespace Glamourer.Gui.Tabs;
public sealed class IncognitoButton(Configuration config) : BaseIconButton<AwesomeIcon>, IUiService public sealed class IncognitoButton(Configuration.Configuration config) : BaseIconButton<AwesomeIcon>, IUiService
{ {
public override AwesomeIcon Icon public override AwesomeIcon Icon
=> config.Ephemeral.IncognitoMode => config.Ephemeral.IncognitoMode

View file

@ -93,7 +93,7 @@ public class LocalNpcAppearanceData : ISavable
public event Action DataChanged = null!; public event Action DataChanged = null!;
public string ToFilename(FilenameService fileNames) public string ToFilePath(FilenameService fileNames)
=> fileNames.NpcAppearanceFile; => fileNames.NpcAppearanceFile;
public void Save(StreamWriter writer) public void Save(StreamWriter writer)

View file

@ -1,4 +1,5 @@
using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.Game.Object;
using Glamourer.Configuration;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Gui.Customization; using Glamourer.Gui.Customization;
using Glamourer.Gui.Equipment; using Glamourer.Gui.Equipment;
@ -12,7 +13,7 @@ using Penumbra.GameData.Interop;
namespace Glamourer.Gui.Tabs.NpcTab; namespace Glamourer.Gui.Tabs.NpcTab;
public sealed class NpcPanel( public sealed class NpcPanel(
Configuration config, Configuration.Configuration config,
NpcSelection selection, NpcSelection selection,
CustomizationDrawer customizeDrawer, CustomizationDrawer customizeDrawer,
EquipmentDrawer equipmentDrawer, EquipmentDrawer equipmentDrawer,

View file

@ -1,12 +1,16 @@
using ImSharp; using Glamourer.Configuration;
using ImSharp;
using Luna; using Luna;
namespace Glamourer.Gui.Tabs.NpcTab; namespace Glamourer.Gui.Tabs.NpcTab;
public sealed class NpcTab : TwoPanelLayout, ITab<MainTabType> public sealed class NpcTab : TwoPanelLayout, ITab<MainTabType>
{ {
public NpcTab(NpcFilter filter, NpcSelector selector, NpcPanel panel, NpcHeader header) private readonly UiConfig _uiConfig;
public NpcTab(NpcFilter filter, NpcSelector selector, NpcPanel panel, NpcHeader header, UiConfig uiConfig)
{ {
_uiConfig = uiConfig;
LeftHeader = new FilterHeader<NpcCacheItem>(filter, new StringU8("Filter..."u8)); LeftHeader = new FilterHeader<NpcCacheItem>(filter, new StringU8("Filter..."u8));
LeftPanel = selector; LeftPanel = selector;
LeftFooter = NopHeaderFooter.Instance; LeftFooter = NopHeaderFooter.Instance;
@ -22,5 +26,14 @@ public sealed class NpcTab : TwoPanelLayout, ITab<MainTabType>
=> MainTabType.Npcs; => MainTabType.Npcs;
public void DrawContent() public void DrawContent()
=> Draw(TwoPanelWidth.IndeterminateRelative); => Draw(_uiConfig.NpcTabScale);
protected override void SetWidth(float width, ScalingMode mode)
=> _uiConfig.NpcTabScale = new TwoPanelWidth(width, mode);
protected override float MinimumWidth
=> LeftHeader.MinimumWidth;
protected override float MaximumWidth
=> Im.Window.Width - 500 * Im.Style.GlobalScale;
} }

View file

@ -10,7 +10,7 @@ using OtterGui.Text.EndObjects;
namespace Glamourer.Gui.Tabs.SettingsTab; namespace Glamourer.Gui.Tabs.SettingsTab;
public class CodeDrawer(Configuration config, CodeService codeService, FunModule funModule) : IUiService public class CodeDrawer(Configuration.Configuration config, CodeService codeService, FunModule funModule) : IUiService
{ {
private static ReadOnlySpan<byte> Tooltip private static ReadOnlySpan<byte> Tooltip
=> "Cheat Codes are not actually for cheating in the game, but for 'cheating' in Glamourer. "u8 => "Cheat Codes are not actually for cheating in the game, but for 'cheating' in Glamourer. "u8

View file

@ -8,7 +8,7 @@ using MouseWheelType = OtterGui.Widgets.MouseWheelType;
namespace Glamourer.Gui.Tabs.SettingsTab; namespace Glamourer.Gui.Tabs.SettingsTab;
public sealed class CollectionCombo(Configuration config, PenumbraService penumbra, Logger log) public sealed class CollectionCombo(Configuration.Configuration config, PenumbraService penumbra, Logger log)
: FilterComboCache<(Guid Id, string IdShort, string Name)>( : FilterComboCache<(Guid Id, string IdShort, string Name)>(
() => penumbra.GetCollections().Select(kvp => (kvp.Key, kvp.Key.ToString()[..8], kvp.Value)).ToArray(), () => penumbra.GetCollections().Select(kvp => (kvp.Key, kvp.Key.ToString()[..8], kvp.Value)).ToArray(),
MouseWheelType.Control, log), IUiService MouseWheelType.Control, log), IUiService

View file

@ -10,7 +10,7 @@ namespace Glamourer.Gui.Tabs.SettingsTab;
public class CollectionOverrideDrawer( public class CollectionOverrideDrawer(
CollectionOverrideService collectionOverrides, CollectionOverrideService collectionOverrides,
Configuration config, Configuration.Configuration config,
ActorObjectManager objects, ActorObjectManager objects,
ActorManager actors, ActorManager actors,
PenumbraService penumbra, PenumbraService penumbra,

View file

@ -2,6 +2,7 @@
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Glamourer.Automation; using Glamourer.Automation;
using Glamourer.Configuration;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Events; using Glamourer.Events;
using Glamourer.Gui.Tabs.DesignTab; using Glamourer.Gui.Tabs.DesignTab;
@ -14,7 +15,7 @@ using Luna;
namespace Glamourer.Gui.Tabs.SettingsTab; namespace Glamourer.Gui.Tabs.SettingsTab;
public sealed class SettingsTab( public sealed class SettingsTab(
Configuration config, Configuration.Configuration config,
DesignFileSystemSelector selector, DesignFileSystemSelector selector,
ContextMenuService contextMenuService, ContextMenuService contextMenuService,
IUiBuilder uiBuilder, IUiBuilder uiBuilder,
@ -255,7 +256,7 @@ public sealed class SettingsTab(
Im.Line.New(); Im.Line.New();
Im.Text("Show the following panels in their respective tabs:"u8); Im.Text("Show the following panels in their respective tabs:"u8);
Im.Dummy(Vector2.Zero); Im.Dummy(Vector2.Zero);
DesignPanelFlagExtensions.DrawTable("##panelTable"u8, config.HideDesignPanel, config.AutoExpandDesignPanel, v => Configuration.DesignPanelFlagExtensions.DrawTable("##panelTable"u8, config.HideDesignPanel, config.AutoExpandDesignPanel, v =>
{ {
config.HideDesignPanel = v; config.HideDesignPanel = v;
config.Save(); config.Save();
@ -444,7 +445,7 @@ public sealed class SettingsTab(
using (var combo = Im.Combo.Begin("##sortMode"u8, sortMode.Name)) using (var combo = Im.Combo.Begin("##sortMode"u8, sortMode.Name))
{ {
if (combo) if (combo)
foreach (var val in Configuration.Constants.ValidSortModes) foreach (var val in Configuration.Configuration.Constants.ValidSortModes)
{ {
if (Im.Selectable(val.Name, val.GetType() == sortMode.GetType()) && val.GetType() != sortMode.GetType()) if (Im.Selectable(val.Name, val.GetType() == sortMode.GetType()) && val.GetType() != sortMode.GetType())
{ {

View file

@ -5,11 +5,11 @@ namespace Glamourer.Gui.Tabs.UnlocksTab;
public sealed class UnlocksTab : Window, ITab<MainTabType> public sealed class UnlocksTab : Window, ITab<MainTabType>
{ {
private readonly EphemeralConfig _config; private readonly Configuration.EphemeralConfig _config;
private readonly UnlockOverview _overview; private readonly UnlockOverview _overview;
private readonly UnlockTable _table; private readonly UnlockTable _table;
public UnlocksTab(EphemeralConfig config, UnlockOverview overview, UnlockTable table) public UnlocksTab(Configuration.EphemeralConfig config, UnlockOverview overview, UnlockTable table)
: base("Unlocked Equipment") : base("Unlocked Equipment")
{ {
_config = config; _config = config;

View file

@ -23,7 +23,7 @@ public class ContextMenuService : IDisposable
private readonly MenuItem _inventoryItem; private readonly MenuItem _inventoryItem;
public ContextMenuService(ItemManager items, StateManager state, ActorObjectManager objects, Configuration config, public ContextMenuService(ItemManager items, StateManager state, ActorObjectManager objects, Configuration.Configuration config,
IContextMenu context) IContextMenu context)
{ {
_contextMenu = context; _contextMenu = context;

View file

@ -24,7 +24,7 @@ public sealed unsafe class MaterialManager : IRequiredService, IDisposable
private readonly ThreadLocal<List<MaterialValueIndex>> _deleteList = new(() => []); private readonly ThreadLocal<List<MaterialValueIndex>> _deleteList = new(() => []);
public MaterialManager(PrepareColorSet prepareColorSet, StateManager stateManager, ActorManager actors, PenumbraService penumbra, public MaterialManager(PrepareColorSet prepareColorSet, StateManager stateManager, ActorManager actors, PenumbraService penumbra,
Configuration config) Configuration.Configuration config)
{ {
_stateManager = stateManager; _stateManager = stateManager;
_actors = actors; _actors = actors;

View file

@ -7,7 +7,7 @@ using Penumbra.GameData.Structs;
namespace Glamourer.Interop.Penumbra; namespace Glamourer.Interop.Penumbra;
public class ModSettingApplier(PenumbraService penumbra, PenumbraAutoRedrawSkip autoRedrawSkip, Configuration config, ActorObjectManager objects, CollectionOverrideService overrides) public class ModSettingApplier(PenumbraService penumbra, PenumbraAutoRedrawSkip autoRedrawSkip, Configuration.Configuration config, ActorObjectManager objects, CollectionOverrideService overrides)
: IService : IService
{ {
private readonly HashSet<Guid> _collectionTracker = []; private readonly HashSet<Guid> _collectionTracker = [];

View file

@ -12,7 +12,7 @@ namespace Glamourer.Interop.Penumbra;
public class PenumbraAutoRedraw : IDisposable, IRequiredService public class PenumbraAutoRedraw : IDisposable, IRequiredService
{ {
private const int WaitFrames = 5; private const int WaitFrames = 5;
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly PenumbraService _penumbra; private readonly PenumbraService _penumbra;
private readonly StateManager _state; private readonly StateManager _state;
private readonly ActorObjectManager _objects; private readonly ActorObjectManager _objects;
@ -21,7 +21,7 @@ public class PenumbraAutoRedraw : IDisposable, IRequiredService
private readonly PenumbraAutoRedrawSkip _skip; private readonly PenumbraAutoRedrawSkip _skip;
public PenumbraAutoRedraw(PenumbraService penumbra, Configuration config, StateManager state, ActorObjectManager objects, public PenumbraAutoRedraw(PenumbraService penumbra, Configuration.Configuration config, StateManager state, ActorObjectManager objects,
IFramework framework, IFramework framework,
StateChanged stateChanged, PenumbraAutoRedrawSkip skip) StateChanged stateChanged, PenumbraAutoRedrawSkip skip)
{ {

View file

@ -45,7 +45,7 @@ public class PenumbraService : IDisposable
private const string NameManual = "Glamourer (Manually)"; private const string NameManual = "Glamourer (Manually)";
private readonly IDalamudPluginInterface _pluginInterface; private readonly IDalamudPluginInterface _pluginInterface;
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly EventSubscriber<ChangedItemType, uint> _tooltipSubscriber; private readonly EventSubscriber<ChangedItemType, uint> _tooltipSubscriber;
private readonly EventSubscriber<MouseButton, ChangedItemType, uint> _clickSubscriber; private readonly EventSubscriber<MouseButton, ChangedItemType, uint> _clickSubscriber;
private readonly EventSubscriber<nint, Guid, nint, nint, nint> _creatingCharacterBase; private readonly EventSubscriber<nint, Guid, nint, nint, nint> _creatingCharacterBase;
@ -96,7 +96,7 @@ public class PenumbraService : IDisposable
public int CurrentMinor { get; private set; } public int CurrentMinor { get; private set; }
public DateTime AttachTime { get; private set; } public DateTime AttachTime { get; private set; }
public PenumbraService(IDalamudPluginInterface pi, PenumbraReloaded penumbraReloaded, Configuration config) public PenumbraService(IDalamudPluginInterface pi, PenumbraReloaded penumbraReloaded, Configuration.Configuration config)
{ {
_pluginInterface = pi; _pluginInterface = pi;
_penumbraReloaded = penumbraReloaded; _penumbraReloaded = penumbraReloaded;

View file

@ -14,8 +14,8 @@ public class BackupService : IAsyncService
{ {
_logger = logger; _logger = logger;
_fileNames = GlamourerFiles(fileNames); _fileNames = GlamourerFiles(fileNames);
_configDirectory = new DirectoryInfo(fileNames.ConfigDirectory); _configDirectory = new DirectoryInfo(fileNames.ConfigurationDirectory);
Awaiter = Task.Run(() => Backup.CreateAutomaticBackup(logger, new DirectoryInfo(fileNames.ConfigDirectory), _fileNames)); Awaiter = Task.Run(() => Backup.CreateAutomaticBackup(logger, new DirectoryInfo(fileNames.ConfigurationDirectory), _fileNames));
} }
/// <summary> Create a permanent backup with a given name for migrations. </summary> /// <summary> Create a permanent backup with a given name for migrations. </summary>
@ -27,7 +27,8 @@ public class BackupService : IAsyncService
{ {
var list = new List<FileInfo>(16) var list = new List<FileInfo>(16)
{ {
new(fileNames.ConfigFile), new(fileNames.ConfigurationFile),
new(fileNames.UiConfiguration),
new(fileNames.DesignFileSystem), new(fileNames.DesignFileSystem),
new(fileNames.MigrationDesignFile), new(fileNames.MigrationDesignFile),
new(fileNames.AutomationFile), new(fileNames.AutomationFile),

View file

@ -6,7 +6,7 @@ namespace Glamourer.Services;
public class CodeService public class CodeService
{ {
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly SHA256 _hasher = SHA256.Create(); private readonly SHA256 _hasher = SHA256.Create();
[Flags] [Flags]
@ -87,7 +87,7 @@ public class CodeService
_ => Race.Unknown, _ => Race.Unknown,
}; };
public CodeService(Configuration config) public CodeService(Configuration.Configuration config)
{ {
_config = config; _config = config;
Load(); Load();

View file

@ -41,7 +41,7 @@ public sealed class CollectionOverrideService : IService, ISavable
public IReadOnlyList<(ActorIdentifier Actor, Guid CollectionId, string DisplayName)> Overrides public IReadOnlyList<(ActorIdentifier Actor, Guid CollectionId, string DisplayName)> Overrides
=> _overrides; => _overrides;
public string ToFilename(FilenameService fileNames) public string ToFilePath(FilenameService fileNames)
=> fileNames.CollectionOverrideFile; => fileNames.CollectionOverrideFile;
public void AddOverride(IEnumerable<ActorIdentifier> identifiers, Guid collectionId, string displayName) public void AddOverride(IEnumerable<ActorIdentifier> identifiers, Guid collectionId, string displayName)

View file

@ -32,7 +32,7 @@ public class CommandService : IDisposable, IApiService
private readonly StateManager _stateManager; private readonly StateManager _stateManager;
private readonly AutoDesignApplier _autoDesignApplier; private readonly AutoDesignApplier _autoDesignApplier;
private readonly AutoDesignManager _autoDesignManager; private readonly AutoDesignManager _autoDesignManager;
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly ModSettingApplier _modApplier; private readonly ModSettingApplier _modApplier;
private readonly ItemManager _items; private readonly ItemManager _items;
private readonly CustomizeService _customizeService; private readonly CustomizeService _customizeService;
@ -43,7 +43,7 @@ public class CommandService : IDisposable, IApiService
public CommandService(ICommandManager commands, MainWindow mainWindow, IChatGui chat, ActorManager actors, ActorObjectManager objects, public CommandService(ICommandManager commands, MainWindow mainWindow, IChatGui chat, ActorManager actors, ActorObjectManager objects,
AutoDesignApplier autoDesignApplier, StateManager stateManager, DesignManager designManager, DesignConverter converter, AutoDesignApplier autoDesignApplier, StateManager stateManager, DesignManager designManager, DesignConverter converter,
DesignFileSystem designFileSystem, AutoDesignManager autoDesignManager, Configuration config, ModSettingApplier modApplier, DesignFileSystem designFileSystem, AutoDesignManager autoDesignManager, Configuration.Configuration config, ModSettingApplier modApplier,
ItemManager items, RandomDesignGenerator randomDesign, CustomizeService customizeService, DesignFileSystemSelector designSelector, ItemManager items, RandomDesignGenerator randomDesign, CustomizeService customizeService, DesignFileSystemSelector designSelector,
QuickDesignCombo quickDesignCombo, DesignResolver resolver, PenumbraService penumbra) QuickDesignCombo quickDesignCombo, DesignResolver resolver, PenumbraService penumbra)
{ {

View file

@ -8,19 +8,19 @@ namespace Glamourer.Services;
public class ConfigMigrationService(SaveService saveService, FixedDesignMigrator fixedDesignMigrator, BackupService backupService) public class ConfigMigrationService(SaveService saveService, FixedDesignMigrator fixedDesignMigrator, BackupService backupService)
{ {
private Configuration _config = null!; private Configuration.Configuration _config = null!;
private JObject _data = null!; private JObject _data = null!;
public void Migrate(Configuration config) public void Migrate(Configuration.Configuration config)
{ {
_config = config; _config = config;
if (config.Version >= Configuration.Constants.CurrentVersion || !File.Exists(saveService.FileNames.ConfigFile)) if (config.Version >= Configuration.Configuration.Constants.CurrentVersion || !File.Exists(saveService.FileNames.ConfigurationFile))
{ {
AddColors(config, false); AddColors(config, false);
return; return;
} }
_data = JObject.Parse(File.ReadAllText(saveService.FileNames.ConfigFile)); _data = JObject.Parse(File.ReadAllText(saveService.FileNames.ConfigurationFile));
MigrateV1To2(); MigrateV1To2();
MigrateV2To4(); MigrateV2To4();
MigrateV4To5(); MigrateV4To5();
@ -103,7 +103,7 @@ public class ConfigMigrationService(SaveService saveService, FixedDesignMigrator
_config.Codes = _config.Codes.DistinctBy(c => c.Code).ToList(); _config.Codes = _config.Codes.DistinctBy(c => c.Code).ToList();
} }
private static void AddColors(Configuration config, bool forceSave) private static void AddColors(Configuration.Configuration config, bool forceSave)
{ {
var save = false; var save = false;
foreach (var color in ColorId.Values) foreach (var color in ColorId.Values)

View file

@ -1,40 +1,28 @@
using Dalamud.Plugin; using Dalamud.Plugin;
using Glamourer.Designs; using Glamourer.Designs;
using Luna;
namespace Glamourer.Services; namespace Glamourer.Services;
public class FilenameService public class FilenameService(IDalamudPluginInterface pi) : BaseFilePathProvider(pi)
{ {
public readonly string ConfigDirectory; public readonly string DesignFileSystem = Path.Combine(pi.ConfigDirectory.FullName, "sort_order.json");
public readonly string ConfigFile; public readonly string MigrationDesignFile = Path.Combine(pi.ConfigDirectory.FullName, "Designs.json");
public readonly string DesignFileSystem; public readonly string DesignDirectory = Path.Combine(pi.ConfigDirectory.FullName, "designs");
public readonly string MigrationDesignFile; public readonly string AutomationFile = Path.Combine(pi.ConfigDirectory.FullName, "automation.json");
public readonly string DesignDirectory; public readonly string UnlockFileCustomize = Path.Combine(pi.ConfigDirectory.FullName, "unlocks_customize.json");
public readonly string AutomationFile; public readonly string UnlockFileItems = Path.Combine(pi.ConfigDirectory.FullName, "unlocks_items.json");
public readonly string UnlockFileCustomize; public readonly string FavoriteFile = Path.Combine(pi.ConfigDirectory.FullName, "favorites.json");
public readonly string UnlockFileItems; public readonly string DesignColorFile = Path.Combine(pi.ConfigDirectory.FullName, "design_colors.json");
public readonly string FavoriteFile; public readonly string EphemeralConfigFile = Path.Combine(pi.ConfigDirectory.FullName, "ephemeral_config.json");
public readonly string DesignColorFile; public readonly string NpcAppearanceFile = Path.Combine(pi.ConfigDirectory.FullName, "npc_appearance_data.json");
public readonly string EphemeralConfigFile; public readonly string CollectionOverrideFile = Path.Combine(pi.ConfigDirectory.FullName, "collection_overrides.json");
public readonly string NpcAppearanceFile; public readonly string UiConfiguration = Path.Combine(pi.ConfigDirectory.FullName, "ui_config.json");
public readonly string CollectionOverrideFile; public readonly string FileSystemFolder = Path.Combine(pi.ConfigDirectory.FullName, "design_filesystem");
public readonly string FileSystemEmptyFolders = Path.Combine(pi.ConfigDirectory.FullName, "design_filesystem", "empty_folders.json");
public FilenameService(IDalamudPluginInterface pi) public readonly string FileSystemExpandedFolders = Path.Combine(pi.ConfigDirectory.FullName, "design_filesystem", "expanded_folders.json");
{ public readonly string FileSystemLockedNodes = Path.Combine(pi.ConfigDirectory.FullName, "design_filesystem", "locked_nodes.json");
ConfigDirectory = pi.ConfigDirectory.FullName; public readonly string FileSystemSelectedNodes = Path.Combine(pi.ConfigDirectory.FullName, "design_filesystem", "selected_nodes.json");
ConfigFile = pi.ConfigFile.FullName;
AutomationFile = Path.Combine(ConfigDirectory, "automation.json");
DesignFileSystem = Path.Combine(ConfigDirectory, "sort_order.json");
MigrationDesignFile = Path.Combine(ConfigDirectory, "Designs.json");
UnlockFileCustomize = Path.Combine(ConfigDirectory, "unlocks_customize.json");
UnlockFileItems = Path.Combine(ConfigDirectory, "unlocks_items.json");
DesignDirectory = Path.Combine(ConfigDirectory, "designs");
FavoriteFile = Path.Combine(ConfigDirectory, "favorites.json");
DesignColorFile = Path.Combine(ConfigDirectory, "design_colors.json");
EphemeralConfigFile = Path.Combine(ConfigDirectory, "ephemeral_config.json");
NpcAppearanceFile = Path.Combine(ConfigDirectory, "npc_appearance_data.json");
CollectionOverrideFile = Path.Combine(ConfigDirectory, "collection_overrides.json");
}
public IEnumerable<FileInfo> Designs() public IEnumerable<FileInfo> Designs()
{ {
@ -50,4 +38,8 @@ public class FilenameService
public string DesignFile(Design design) public string DesignFile(Design design)
=> DesignFile(design.Identifier.ToString()); => DesignFile(design.Identifier.ToString());
// TODO
public override List<FileInfo> GetBackupFiles()
=> [];
} }

View file

@ -15,7 +15,7 @@ public class ItemManager
public const string SmallClothesNpc = "Smallclothes (NPC)"; public const string SmallClothesNpc = "Smallclothes (NPC)";
public const ushort SmallClothesNpcModel = 9903; public const ushort SmallClothesNpcModel = 9903;
private readonly Configuration _config; private readonly Configuration.Configuration _config;
public readonly ObjectIdentification ObjectIdentification; public readonly ObjectIdentification ObjectIdentification;
public readonly ExcelSheet<Item> ItemSheet; public readonly ExcelSheet<Item> ItemSheet;
@ -26,7 +26,7 @@ public class ItemManager
public readonly EquipItem DefaultSword; public readonly EquipItem DefaultSword;
public ItemManager(Configuration config, IDataManager gameData, ObjectIdentification objectIdentification, public ItemManager(Configuration.Configuration config, IDataManager gameData, ObjectIdentification objectIdentification,
ItemData itemData, DictStain stains, RestrictedGear restrictedGear, DictBonusItems dictBonusItems) ItemData itemData, DictStain stains, RestrictedGear restrictedGear, DictBonusItems dictBonusItems)
{ {
_config = config; _config = config;

View file

@ -10,14 +10,14 @@ namespace Glamourer.Services;
public class PcpService : IRequiredService public class PcpService : IRequiredService
{ {
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly PenumbraService _penumbra; private readonly PenumbraService _penumbra;
private readonly ActorObjectManager _objects; private readonly ActorObjectManager _objects;
private readonly StateManager _state; private readonly StateManager _state;
private readonly DesignConverter _designConverter; private readonly DesignConverter _designConverter;
private readonly DesignManager _designManager; private readonly DesignManager _designManager;
public PcpService(Configuration config, PenumbraService penumbra, ActorObjectManager objects, StateManager state, public PcpService(Configuration.Configuration config, PenumbraService penumbra, ActorObjectManager objects, StateManager state,
DesignConverter designConverter, DesignManager designManager) DesignConverter designConverter, DesignManager designManager)
{ {
_config = config; _config = config;

View file

@ -1,17 +1,11 @@
using OtterGui.Classes; using Luna;
using OtterGui.Log;
namespace Glamourer.Services; namespace Glamourer.Services;
/// <summary> /// <summary>
/// Any file type that we want to save via SaveService. /// Any file type that we want to save via SaveService.
/// </summary> /// </summary>
public interface ISavable : ISavable<FilenameService> public interface ISavable : ISavable<FilenameService>;
{ }
public sealed class SaveService : SaveServiceBase<FilenameService> public sealed class SaveService(Logger log, FrameworkManager framework, FilenameService fileNames)
{ : BaseSaveService<FilenameService>(log, framework, fileNames);
public SaveService(Logger log, FrameworkManager framework, FilenameService fileNames)
: base(log, framework, fileNames)
{ }
}

View file

@ -73,8 +73,8 @@ public static class StaticServiceManager
.AddSingleton<SaveService>() .AddSingleton<SaveService>()
.AddSingleton<CodeService>() .AddSingleton<CodeService>()
.AddSingleton<ConfigMigrationService>() .AddSingleton<ConfigMigrationService>()
.AddSingleton<Configuration>() .AddSingleton<Configuration.Configuration>()
.AddSingleton<EphemeralConfig>() .AddSingleton<Configuration.EphemeralConfig>()
.AddSingleton<TextureService>() .AddSingleton<TextureService>()
.AddSingleton<FavoriteManager>(); .AddSingleton<FavoriteManager>();

View file

@ -26,7 +26,7 @@ public unsafe class FunModule : IDisposable
private readonly WorldSets _worldSets = new(); private readonly WorldSets _worldSets = new();
private readonly ItemManager _items; private readonly ItemManager _items;
private readonly CustomizeService _customizations; private readonly CustomizeService _customizations;
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly CodeService _codes; private readonly CodeService _codes;
private readonly Random _rng; private readonly Random _rng;
private readonly GenericPopupWindow _popupWindow; private readonly GenericPopupWindow _popupWindow;
@ -66,7 +66,7 @@ public unsafe class FunModule : IDisposable
internal void ResetFestival() internal void ResetFestival()
=> OnDayChange(DateTime.Now.Day, DateTime.Now.Month, DateTime.Now.Year); => OnDayChange(DateTime.Now.Day, DateTime.Now.Month, DateTime.Now.Year);
public FunModule(CodeService codes, CustomizeService customizations, ItemManager items, Configuration config, public FunModule(CodeService codes, CustomizeService customizations, ItemManager items, Configuration.Configuration config,
GenericPopupWindow popupWindow, StateManager stateManager, ActorObjectManager objects, DesignConverter designConverter, GenericPopupWindow popupWindow, StateManager stateManager, ActorObjectManager objects, DesignConverter designConverter,
DesignManager designManager, NpcCustomizeSet npcs) DesignManager designManager, NpcCustomizeSet npcs)
{ {

View file

@ -20,7 +20,7 @@ public class StateEditor(
StateChanged stateChanged, StateChanged stateChanged,
StateFinalized stateFinalized, StateFinalized stateFinalized,
JobChangeState jobChange, JobChangeState jobChange,
Configuration config, Configuration.Configuration config,
ItemManager items, ItemManager items,
DesignMerger merger, DesignMerger merger,
ModSettingApplier modApplier, ModSettingApplier modApplier,
@ -30,7 +30,7 @@ public class StateEditor(
protected readonly StateApplier Applier = applier; protected readonly StateApplier Applier = applier;
protected readonly StateChanged StateChanged = stateChanged; protected readonly StateChanged StateChanged = stateChanged;
protected readonly StateFinalized StateFinalized = stateFinalized; protected readonly StateFinalized StateFinalized = stateFinalized;
protected readonly Configuration Config = config; protected readonly Configuration.Configuration Config = config;
protected readonly ItemManager Items = items; protected readonly ItemManager Items = items;
/// <summary> Turn an actor to. </summary> /// <summary> Turn an actor to. </summary>

View file

@ -25,7 +25,7 @@ namespace Glamourer.State;
/// </summary> /// </summary>
public class StateListener : IDisposable public class StateListener : IDisposable
{ {
private readonly Configuration _config; private readonly Configuration.Configuration _config;
private readonly ActorManager _actors; private readonly ActorManager _actors;
private readonly ActorObjectManager _objects; private readonly ActorObjectManager _objects;
private readonly StateManager _manager; private readonly StateManager _manager;
@ -58,7 +58,7 @@ public class StateListener : IDisposable
private ActorState? _creatingState; private ActorState? _creatingState;
private ActorState? _customizeState; private ActorState? _customizeState;
public StateListener(StateManager manager, ItemManager items, PenumbraService penumbra, ActorManager actors, Configuration config, public StateListener(StateManager manager, ItemManager items, PenumbraService penumbra, ActorManager actors, Configuration.Configuration config,
EquipSlotUpdating equipSlotUpdating, GearsetDataLoaded gearsetDataLoaded, WeaponLoading weaponLoading, VisorStateChanged visorState, EquipSlotUpdating equipSlotUpdating, GearsetDataLoaded gearsetDataLoaded, WeaponLoading weaponLoading, VisorStateChanged visorState,
WeaponVisibilityChanged weaponVisibility, HeadGearVisibilityChanged headGearVisibility, AutoDesignApplier autoDesignApplier, WeaponVisibilityChanged weaponVisibility, HeadGearVisibilityChanged headGearVisibility, AutoDesignApplier autoDesignApplier,
FunModule funModule, HumanModelList humans, StateApplier applier, MovedEquipment movedEquipment, ActorObjectManager objects, FunModule funModule, HumanModelList humans, StateApplier applier, MovedEquipment movedEquipment, ActorObjectManager objects,

View file

@ -27,7 +27,7 @@ public sealed class StateManager(
InternalStateEditor editor, InternalStateEditor editor,
HumanModelList humans, HumanModelList humans,
IClientState clientState, IClientState clientState,
Configuration config, Configuration.Configuration config,
JobChangeState jobChange, JobChangeState jobChange,
DesignMerger merger, DesignMerger merger,
ModSettingApplier modApplier, ModSettingApplier modApplier,

View file

@ -139,7 +139,7 @@ public class CustomizeUnlockManager : IDisposable, ISavable
_setUnlockLinkValueHook.Original(uiState, data, value); _setUnlockLinkValueHook.Original(uiState, data, value);
try try
{ {
if (value == 0) if (value is 0)
return; return;
var time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); var time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
@ -159,7 +159,7 @@ public class CustomizeUnlockManager : IDisposable, ISavable
} }
} }
public string ToFilename(FilenameService fileNames) public string ToFilePath(FilenameService fileNames)
=> fileNames.UnlockFileCustomize; => fileNames.UnlockFileCustomize;
public void Save() public void Save()
@ -169,7 +169,7 @@ public class CustomizeUnlockManager : IDisposable, ISavable
=> UnlockDictionaryHelpers.Save(writer, Unlocked); => UnlockDictionaryHelpers.Save(writer, Unlocked);
private void Load() private void Load()
=> UnlockDictionaryHelpers.Load(ToFilename(_saveService.FileNames), _unlocked, id => Unlockable.Any(c => c.Value.Data == id), => UnlockDictionaryHelpers.Load(ToFilePath(_saveService.FileNames), _unlocked, id => Unlockable.Any(c => c.Value.Data == id),
"customization"); "customization");
/// <summary> Create a list of all unlockable hairstyles and face paints. </summary> /// <summary> Create a list of all unlockable hairstyles and face paints. </summary>

View file

@ -94,7 +94,7 @@ public sealed class FavoriteManager : ISavable
Save(); Save();
} }
public string ToFilename(FilenameService fileNames) public string ToFilePath(FilenameService fileNames)
=> fileNames.FavoriteFile; => fileNames.FavoriteFile;
private void Save() private void Save()

View file

@ -254,7 +254,7 @@ public class ItemUnlockManager : ISavable, IDisposable, IReadOnlyDictionary<Item
Save(); Save();
} }
public string ToFilename(FilenameService fileNames) public string ToFilePath(FilenameService fileNames)
=> fileNames.UnlockFileItems; => fileNames.UnlockFileItems;
public void Save() public void Save()
@ -265,7 +265,7 @@ public class ItemUnlockManager : ISavable, IDisposable, IReadOnlyDictionary<Item
private void Load() private void Load()
{ {
var version = UnlockDictionaryHelpers.Load(ToFilename(_saveService.FileNames), _unlocked, var version = UnlockDictionaryHelpers.Load(ToFilePath(_saveService.FileNames), _unlocked,
id => _items.ItemData.TryGetValue(id, EquipSlot.MainHand, out _), "item"); id => _items.ItemData.TryGetValue(id, EquipSlot.MainHand, out _), "item");
UpdateModels(version); UpdateModels(version);
} }

2
Luna

@ -1 +1 @@
Subproject commit 0ee15af5c45b6c72df25b972e48b9a57347c25a5 Subproject commit bff400eb44aeded41fb6b1b3d35948881b578737