mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2026-02-24 21:51:48 +01:00
Add retained selections and filters and config for them.
This commit is contained in:
parent
baedba11f8
commit
67ee7bd507
26 changed files with 605 additions and 92 deletions
|
|
@ -23,6 +23,9 @@ public sealed partial class Configuration : IPluginConfiguration, ISavable, ISer
|
|||
[JsonIgnore]
|
||||
public readonly UiConfig Ui;
|
||||
|
||||
[JsonIgnore]
|
||||
public readonly FilterConfig Filters;
|
||||
|
||||
public bool AttachToPcp { get; set; } = true;
|
||||
public bool UseRestrictedGearProtection { get; set; } = false;
|
||||
public bool OpenFoldersByDefault { get; set; } = false;
|
||||
|
|
@ -54,6 +57,11 @@ public sealed partial class Configuration : IPluginConfiguration, ISavable, ISer
|
|||
public bool PreventRandomRepeats { get; set; } = false;
|
||||
public string PcpFolder { get; set; } = "PCP";
|
||||
public string PcpColor { get; set; } = "";
|
||||
public bool RememberActorFilter { get; set; } = false;
|
||||
public bool RememberDesignFilter { get; set; } = false;
|
||||
public bool RememberNpcFilter { get; set; } = true;
|
||||
public bool RememberAutomationFilter { get; set; } = false;
|
||||
public bool RememberUnlocksFilters { get; set; } = true;
|
||||
|
||||
public RoughnessSetting RoughnessSetting { get; set; } = RoughnessSetting.AsIs;
|
||||
|
||||
|
|
@ -95,11 +103,12 @@ public sealed partial class Configuration : IPluginConfiguration, ISavable, ISer
|
|||
[JsonIgnore]
|
||||
private readonly SaveService _saveService;
|
||||
|
||||
public Configuration(SaveService saveService, ConfigMigrationService migrator, EphemeralConfig ephemeral, UiConfig ui)
|
||||
public Configuration(SaveService saveService, ConfigMigrationService migrator, EphemeralConfig ephemeral, UiConfig ui, FilterConfig filters)
|
||||
{
|
||||
_saveService = saveService;
|
||||
Ephemeral = ephemeral;
|
||||
Ui = ui;
|
||||
Filters = filters;
|
||||
Load(migrator);
|
||||
}
|
||||
|
||||
|
|
|
|||
201
Glamourer/Config/FilterConfig.cs
Normal file
201
Glamourer/Config/FilterConfig.cs
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
using Glamourer.Gui.Tabs.UnlocksTab;
|
||||
using Glamourer.Services;
|
||||
using ImSharp.Table;
|
||||
using Luna;
|
||||
using Luna.Generators;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Penumbra.GameData.DataContainers;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Config;
|
||||
|
||||
public sealed partial class FilterConfig : ConfigurationFile<FilenameService>
|
||||
{
|
||||
private readonly DictJob _jobs;
|
||||
|
||||
public FilterConfig(SaveService saveService, MessageService messager, DictJob jobs)
|
||||
: base(saveService, messager, TimeSpan.FromMinutes(5))
|
||||
{
|
||||
_jobs = jobs;
|
||||
_unlocksJobFilter = _jobs.AllAvailableJobs;
|
||||
Load();
|
||||
}
|
||||
|
||||
public override int CurrentVersion
|
||||
=> 1;
|
||||
|
||||
protected override void AddData(JsonTextWriter j)
|
||||
{
|
||||
WriteFilter(j, ActorFilter, "Actors");
|
||||
WriteFilter(j, DesignFilter, "Designs");
|
||||
WriteFilter(j, NpcFilter, "Npcs");
|
||||
WriteAutomation(j);
|
||||
WriteUnlocksTab(j);
|
||||
}
|
||||
|
||||
protected override void LoadData(JObject j)
|
||||
{
|
||||
_actorFilter = j["Actors"]?["Filter"]?.Value<string>() ?? string.Empty;
|
||||
_designFilter = j["Designs"]?["Filter"]?.Value<string>() ?? string.Empty;
|
||||
_npcFilter = j["Npcs"]?["Filter"]?.Value<string>() ?? string.Empty;
|
||||
_automationFilter = j["Automation"]?["Filter"]?.Value<string>() ?? string.Empty;
|
||||
_automationStateFilter = j["Automation"]?["State"]?.Value<bool>();
|
||||
LoadUnlocksTab(j);
|
||||
}
|
||||
|
||||
[ConfigProperty]
|
||||
private string _designFilter = string.Empty;
|
||||
|
||||
[ConfigProperty]
|
||||
private string _actorFilter = string.Empty;
|
||||
|
||||
[ConfigProperty]
|
||||
private string _automationFilter = string.Empty;
|
||||
|
||||
[ConfigProperty]
|
||||
private bool? _automationStateFilter;
|
||||
|
||||
[ConfigProperty]
|
||||
private string _npcFilter = string.Empty;
|
||||
|
||||
[ConfigProperty]
|
||||
private YesNoColumn.YesNoFlag _unlocksFavoriteFilter = YesNoColumn.YesOrNo;
|
||||
|
||||
[ConfigProperty]
|
||||
private UnlockCacheItem.Modded _unlocksModdedFilter = UnlockCacheItem.ModdedAll;
|
||||
|
||||
[ConfigProperty]
|
||||
private string _unlocksNameFilter = string.Empty;
|
||||
|
||||
[ConfigProperty]
|
||||
private string _unlocksTypeFilter = string.Empty;
|
||||
|
||||
[ConfigProperty]
|
||||
private EquipFlag _unlocksSlotFilter = UnlockCacheItem.SlotsAll;
|
||||
|
||||
[ConfigProperty]
|
||||
private YesNoColumn.YesNoFlag _unlocksUnlockedFilter = YesNoColumn.YesOrNo;
|
||||
|
||||
[ConfigProperty]
|
||||
private string _unlocksItemIdFilter = string.Empty;
|
||||
|
||||
[ConfigProperty]
|
||||
private string _unlocksModelDataFilter = string.Empty;
|
||||
|
||||
[ConfigProperty]
|
||||
private string _unlocksLevelFilter = string.Empty;
|
||||
|
||||
[ConfigProperty]
|
||||
private JobFlag _unlocksJobFilter;
|
||||
|
||||
[ConfigProperty]
|
||||
private UnlockCacheItem.Dyability _unlocksDyabilityFilter = UnlockCacheItem.DyableAll;
|
||||
|
||||
[ConfigProperty]
|
||||
private YesNoColumn.YesNoFlag _unlocksTradableFilter = YesNoColumn.YesOrNo;
|
||||
|
||||
[ConfigProperty]
|
||||
private YesNoColumn.YesNoFlag _unlocksCrestFilter = YesNoColumn.YesOrNo;
|
||||
|
||||
private void WriteUnlocksTab(JsonTextWriter j)
|
||||
{
|
||||
var obj = new JObject();
|
||||
if (UnlocksFavoriteFilter is not YesNoColumn.YesOrNo)
|
||||
obj["Favorite"] = (uint)UnlocksFavoriteFilter;
|
||||
if (UnlocksCrestFilter is not YesNoColumn.YesOrNo)
|
||||
obj["Crest"] = (uint)UnlocksCrestFilter;
|
||||
if (UnlocksTradableFilter is not YesNoColumn.YesOrNo)
|
||||
obj["Tradable"] = (uint)UnlocksTradableFilter;
|
||||
if (UnlocksUnlockedFilter is not YesNoColumn.YesOrNo)
|
||||
obj["Unlocked"] = (uint)UnlocksUnlockedFilter;
|
||||
|
||||
if (UnlocksModdedFilter is not UnlockCacheItem.ModdedAll)
|
||||
obj["Modded"] = (uint)UnlocksModdedFilter;
|
||||
|
||||
if (UnlocksDyabilityFilter is not UnlockCacheItem.DyableAll)
|
||||
obj["Dyability"] = (uint)UnlocksDyabilityFilter;
|
||||
|
||||
if (UnlocksSlotFilter is not UnlockCacheItem.SlotsAll)
|
||||
obj["Slot"] = (uint)UnlocksSlotFilter;
|
||||
|
||||
if (UnlocksJobFilter != _jobs.AllAvailableJobs)
|
||||
obj["Job"] = (ulong)UnlocksJobFilter;
|
||||
|
||||
if (UnlocksLevelFilter.Length > 0)
|
||||
obj["Level"] = UnlocksLevelFilter;
|
||||
if (UnlocksModelDataFilter.Length > 0)
|
||||
obj["ModelData"] = UnlocksModelDataFilter;
|
||||
if (UnlocksItemIdFilter.Length > 0)
|
||||
obj["ItemId"] = UnlocksItemIdFilter;
|
||||
if (UnlocksNameFilter.Length > 0)
|
||||
obj["Name"] = UnlocksNameFilter;
|
||||
if (UnlocksTypeFilter.Length > 0)
|
||||
obj["Type"] = UnlocksTypeFilter;
|
||||
|
||||
if (obj.Count <= 0)
|
||||
return;
|
||||
|
||||
j.WritePropertyName("Unlocks");
|
||||
obj.WriteTo(j);
|
||||
}
|
||||
|
||||
private void LoadUnlocksTab(JObject j)
|
||||
{
|
||||
if (j["Unlocks"] is not JObject unlocks)
|
||||
return;
|
||||
|
||||
_unlocksFavoriteFilter = unlocks["Favorite"]?.Value<uint>() is { } f ? (YesNoColumn.YesNoFlag)f : YesNoColumn.YesOrNo;
|
||||
_unlocksCrestFilter = unlocks["Crest"]?.Value<uint>() is { } c ? (YesNoColumn.YesNoFlag)c : YesNoColumn.YesOrNo;
|
||||
_unlocksTradableFilter = unlocks["Tradable"]?.Value<uint>() is { } t ? (YesNoColumn.YesNoFlag)t : YesNoColumn.YesOrNo;
|
||||
_unlocksUnlockedFilter = unlocks["Unlocked"]?.Value<uint>() is { } u ? (YesNoColumn.YesNoFlag)u : YesNoColumn.YesOrNo;
|
||||
_unlocksModdedFilter = unlocks["Modded"]?.Value<uint>() is { } m ? (UnlockCacheItem.Modded)m : UnlockCacheItem.ModdedAll;
|
||||
_unlocksDyabilityFilter = unlocks["Dyability"]?.Value<uint>() is { } d ? (UnlockCacheItem.Dyability)d : UnlockCacheItem.DyableAll;
|
||||
_unlocksSlotFilter = unlocks["Slot"]?.Value<uint>() is { } s ? (EquipFlag)s : UnlockCacheItem.SlotsAll;
|
||||
_unlocksJobFilter = unlocks["Job"]?.Value<ulong>() is { } job ? (JobFlag)job : _jobs.AllAvailableJobs;
|
||||
_unlocksLevelFilter = unlocks["Level"]?.Value<string>() ?? string.Empty;
|
||||
_unlocksModelDataFilter = unlocks["ModelData"]?.Value<string>() ?? string.Empty;
|
||||
_unlocksItemIdFilter = unlocks["ItemId"]?.Value<string>() ?? string.Empty;
|
||||
_unlocksNameFilter = unlocks["Name"]?.Value<string>() ?? string.Empty;
|
||||
_unlocksTypeFilter = unlocks["Type"]?.Value<string>() ?? string.Empty;
|
||||
}
|
||||
|
||||
|
||||
public override string ToFilePath(FilenameService fileNames)
|
||||
=> fileNames.FilterFile;
|
||||
|
||||
private void WriteAutomation(JsonTextWriter j)
|
||||
{
|
||||
if (AutomationStateFilter is null && AutomationFilter.Length is 0)
|
||||
return;
|
||||
|
||||
j.WritePropertyName("Automation");
|
||||
j.WriteStartObject();
|
||||
if (AutomationStateFilter is not null)
|
||||
{
|
||||
j.WritePropertyName("State");
|
||||
j.WriteValue(AutomationStateFilter.Value);
|
||||
}
|
||||
|
||||
if (AutomationFilter.Length > 0)
|
||||
{
|
||||
j.WritePropertyName("Filter");
|
||||
j.WriteValue(AutomationFilter);
|
||||
}
|
||||
|
||||
j.WriteEndObject();
|
||||
}
|
||||
|
||||
private static void WriteFilter(JsonTextWriter j, string filter, string tabName)
|
||||
{
|
||||
if (filter.Length is 0)
|
||||
return;
|
||||
|
||||
j.WritePropertyName(tabName);
|
||||
j.WriteStartObject();
|
||||
j.WritePropertyName("Filter");
|
||||
j.WriteValue(filter);
|
||||
j.WriteEndObject();
|
||||
}
|
||||
}
|
||||
|
|
@ -3,14 +3,19 @@ using Luna;
|
|||
using Luna.Generators;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Penumbra.GameData.Actors;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Config;
|
||||
|
||||
public sealed partial class UiConfig : ConfigurationFile<FilenameService>
|
||||
{
|
||||
public UiConfig(SaveService saveService, MessageService messageService)
|
||||
: base(saveService, messageService)
|
||||
private readonly ActorManager _actors;
|
||||
|
||||
public UiConfig(SaveService saveService, MessageService messageService, ActorManager actors)
|
||||
: base(saveService, messageService, TimeSpan.FromMinutes(5))
|
||||
{
|
||||
_actors = actors;
|
||||
Load();
|
||||
}
|
||||
|
||||
|
|
@ -26,6 +31,15 @@ public sealed partial class UiConfig : ConfigurationFile<FilenameService>
|
|||
[ConfigProperty]
|
||||
private TwoPanelWidth _npcTabScale = new(250, ScalingMode.Absolute);
|
||||
|
||||
[ConfigProperty]
|
||||
private NpcId _selectedNpc = 0;
|
||||
|
||||
[ConfigProperty]
|
||||
private int _selectedAutomationIndex = -1;
|
||||
|
||||
[ConfigProperty]
|
||||
private ActorIdentifier _selectedActor = ActorIdentifier.Invalid;
|
||||
|
||||
public override int CurrentVersion
|
||||
=> 1;
|
||||
|
||||
|
|
@ -35,16 +49,36 @@ public sealed partial class UiConfig : ConfigurationFile<FilenameService>
|
|||
DesignsTabScale.WriteJson(j, "DesignsTab");
|
||||
AutomationTabScale.WriteJson(j, "AutomationTab");
|
||||
NpcTabScale.WriteJson(j, "NpcTab");
|
||||
if (_selectedNpc.Id is not 0)
|
||||
{
|
||||
j.WritePropertyName("SelectedNpc");
|
||||
j.WriteValue(_selectedNpc);
|
||||
}
|
||||
|
||||
if (_selectedAutomationIndex >= 0)
|
||||
{
|
||||
j.WritePropertyName("SelectedAutomationIndex");
|
||||
j.WriteValue(_selectedAutomationIndex);
|
||||
}
|
||||
|
||||
if (_selectedActor.IsValid)
|
||||
{
|
||||
j.WritePropertyName("SelectedActor");
|
||||
_selectedActor.ToJson().WriteTo(j);
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
_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));
|
||||
_selectedNpc = j["SelectedNpc"]?.Value<uint>() ?? 0;
|
||||
_selectedAutomationIndex = j["SelectedAutomationIndex"]?.Value<int>() ?? -1;
|
||||
_selectedActor = _actors.FromJson(j["SelectedActor"] as JObject);
|
||||
}
|
||||
|
||||
public override string ToFilePath(FilenameService fileNames)
|
||||
=> fileNames.UiConfiguration;
|
||||
=> fileNames.UiConfigurationFile;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,12 +81,16 @@ public sealed class DesignColors : ISavable, IReadOnlyDictionary<string, Rgba32>
|
|||
|
||||
public void Save(StreamWriter writer)
|
||||
{
|
||||
var dict = new JObject();
|
||||
foreach (var (name, color) in _colors)
|
||||
dict[name] = color.Color;
|
||||
var jObj = new JObject
|
||||
{
|
||||
["Version"] = 1,
|
||||
["MissingColor"] = MissingColor.Color,
|
||||
["Definitions"] = JToken.FromObject(_colors),
|
||||
["Definitions"] = dict,
|
||||
};
|
||||
|
||||
writer.Write(jObj.ToString(Formatting.Indented));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Dalamud.Plugin.Services;
|
||||
using Glamourer.Config;
|
||||
using ImSharp;
|
||||
using Luna;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
|
@ -23,7 +24,7 @@ public sealed class ActorFilter : TextFilterBase<ActorCacheItem>, IUiService
|
|||
|
||||
private FilterMethod _method = FilterMethod.Empty;
|
||||
|
||||
public ActorFilter(IPlayerState playerState)
|
||||
public ActorFilter(IPlayerState playerState, Configuration config)
|
||||
{
|
||||
_playerState = playerState;
|
||||
FilterChanged += () =>
|
||||
|
|
@ -39,7 +40,10 @@ public sealed class ActorFilter : TextFilterBase<ActorCacheItem>, IUiService
|
|||
"<w>" or "<W>" => FilterMethod.Homeworld,
|
||||
_ => FilterMethod.Text,
|
||||
};
|
||||
config.Filters.ActorFilter = Text;
|
||||
};
|
||||
if (config.RememberActorFilter)
|
||||
Set(config.Filters.ActorFilter);
|
||||
}
|
||||
|
||||
public override bool DrawFilter(ReadOnlySpan<byte> label, Vector2 availableRegion)
|
||||
|
|
@ -78,9 +82,21 @@ public sealed class ActorFilter : TextFilterBase<ActorCacheItem>, IUiService
|
|||
Im.Text("<w>"u8, color);
|
||||
Im.Line.NoSpacing();
|
||||
Im.Text(": show only players from your world."u8);
|
||||
|
||||
if (Text.Length > 0)
|
||||
Im.Text("\nMiddle-click to clear filters."u8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected override bool OnMiddleClick()
|
||||
{
|
||||
if (!Im.Item.MiddleClicked())
|
||||
return false;
|
||||
|
||||
Im.Id.ClearActive();
|
||||
return Clear();
|
||||
}
|
||||
|
||||
protected override string ToFilterString(in ActorCacheItem item, int globalIndex)
|
||||
=> item.DisplayText.Utf16;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using Dalamud.Game.ClientState.Conditions;
|
||||
using Dalamud.Plugin.Services;
|
||||
using Glamourer.Config;
|
||||
using Glamourer.State;
|
||||
using ImSharp;
|
||||
using Luna;
|
||||
|
|
@ -9,7 +10,7 @@ using Penumbra.GameData.Interop;
|
|||
|
||||
namespace Glamourer.Gui.Tabs.ActorTab;
|
||||
|
||||
public sealed class ActorSelection(StateManager manager, ActorObjectManager objects, ICondition conditions) : IUiService
|
||||
public sealed class ActorSelection(StateManager manager, ActorObjectManager objects, ICondition conditions, UiConfig config) : IUiService
|
||||
{
|
||||
private static readonly StringU8 NoSelection = new("No Actor Selected"u8);
|
||||
|
||||
|
|
@ -23,7 +24,8 @@ public sealed class ActorSelection(StateManager manager, ActorObjectManager obje
|
|||
|
||||
public void Select(ActorIdentifier identifier, ActorData data)
|
||||
{
|
||||
Identifier = identifier.CreatePermanent();
|
||||
Identifier = identifier.CreatePermanent();
|
||||
config.SelectedActor = Identifier;
|
||||
if (Identifier.IsValid)
|
||||
{
|
||||
ActorName = new StringU8(data.Label);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Glamourer.Interop.Penumbra;
|
||||
using Glamourer.Config;
|
||||
using Glamourer.Interop.Penumbra;
|
||||
using ImSharp;
|
||||
using Luna;
|
||||
using Penumbra.GameData.Actors;
|
||||
|
|
@ -14,25 +15,58 @@ public readonly struct ActorCacheItem(ActorIdentifier identifier, ActorData data
|
|||
public readonly StringU8 IncognitoText = new(identifier.Incognito(data.Label));
|
||||
}
|
||||
|
||||
public sealed class ActorSelector(ActorSelection selection, ActorObjectManager objects, ActorFilter filter, PenumbraService penumbra, Config.EphemeralConfig config) : IPanel
|
||||
public sealed class ActorSelector(
|
||||
ActorSelection selection,
|
||||
ActorObjectManager objects,
|
||||
ActorFilter filter,
|
||||
PenumbraService penumbra,
|
||||
Configuration config) : IPanel
|
||||
{
|
||||
public ReadOnlySpan<byte> Id
|
||||
=> "ActorSelector"u8;
|
||||
|
||||
public void Draw()
|
||||
public unsafe void Draw()
|
||||
{
|
||||
Im.Cursor.Y += Im.Style.FramePadding.Y;
|
||||
var cache = CacheManager.Instance.GetOrCreateCache(Im.Id.Current, () => new ActorSelectorCache(objects, filter, penumbra));
|
||||
using var clip = new Im.ListClipper(cache.Count, Im.Style.TextHeightWithSpacing);
|
||||
var cache = CacheManager.Instance.GetOrCreateCache(Im.Id.Current, () => new ActorSelectorCache(objects, filter, penumbra));
|
||||
HandleRememberedSelection();
|
||||
using var clip = new Im.ListClipper(cache.Count, Im.Style.TextHeightWithSpacing);
|
||||
foreach (var actor in clip.Iterate(cache))
|
||||
{
|
||||
Im.Cursor.X += Im.Style.FramePadding.X;
|
||||
var selected = actor.Identifier.Equals(selection.Identifier);
|
||||
if (Im.Selectable(config.IncognitoMode ? actor.IncognitoText : actor.DisplayText.Utf8, selected) && !selected)
|
||||
if (Im.Selectable(config.Ephemeral.IncognitoMode ? actor.IncognitoText : actor.DisplayText.Utf8, selected) && !selected)
|
||||
selection.Select(actor.Identifier, actor.Data);
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void HandleRememberedSelection()
|
||||
{
|
||||
// We already have a valid selection.
|
||||
if (selection.Identifier.IsValid)
|
||||
return;
|
||||
|
||||
// We do not have a remembered selection.
|
||||
if (!config.Ui.SelectedActor.IsValid)
|
||||
return;
|
||||
|
||||
// We have no actor corresponding to the selection available to create a new state.
|
||||
if (!objects.TryGetValue(config.Ui.SelectedActor, out var data))
|
||||
return;
|
||||
|
||||
// The actor has no model yet.
|
||||
if (data.Objects.First().Model is not { IsCharacterBase: true } model)
|
||||
return;
|
||||
|
||||
// The model still has a staging area, so is not fully loaded.
|
||||
if (model.AsCharacterBase->PerSlotStagingArea is not null || model.AsCharacterBase->TempData is not null)
|
||||
return;
|
||||
|
||||
// The model should be fully loaded, so the selection can probably create the expected state.
|
||||
selection.Select(config.Ui.SelectedActor, data);
|
||||
}
|
||||
|
||||
|
||||
private sealed class ActorSelectorCache : BasicFilterCache<ActorCacheItem>
|
||||
{
|
||||
private readonly ActorObjectManager _objects;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using ImSharp;
|
||||
using Glamourer.Config;
|
||||
using ImSharp;
|
||||
using Luna;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.AutomationTab;
|
||||
|
|
@ -10,6 +11,21 @@ public sealed class AutomationFilter : TextFilterBase<AutomationCacheItem>, IUiS
|
|||
protected override string ToFilterString(in AutomationCacheItem item, int globalIndex)
|
||||
=> item.Name.Utf16;
|
||||
|
||||
public AutomationFilter(Configuration config)
|
||||
{
|
||||
if (config.RememberAutomationFilter)
|
||||
{
|
||||
_setStateFilter = config.Filters.AutomationStateFilter;
|
||||
Set(config.Filters.AutomationFilter);
|
||||
}
|
||||
|
||||
FilterChanged += () =>
|
||||
{
|
||||
config.Filters.AutomationFilter = Text;
|
||||
config.Filters.AutomationStateFilter = _setStateFilter;
|
||||
};
|
||||
}
|
||||
|
||||
public override bool WouldBeVisible(in AutomationCacheItem item, int globalIndex)
|
||||
=> _setStateFilter switch
|
||||
{
|
||||
|
|
@ -54,11 +70,15 @@ public sealed class AutomationFilter : TextFilterBase<AutomationCacheItem>, IUiS
|
|||
return ret;
|
||||
}
|
||||
|
||||
public override void Clear()
|
||||
public override bool Clear()
|
||||
{
|
||||
var changes = _setStateFilter is not null;
|
||||
_setStateFilter = null;
|
||||
if (!Set(string.Empty) && changes)
|
||||
InvokeEvent();
|
||||
if (!SetInternal(string.Empty) && !changes)
|
||||
return false;
|
||||
|
||||
InvokeEvent();
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Glamourer.Automation;
|
||||
using Glamourer.Config;
|
||||
using Glamourer.Events;
|
||||
using ImSharp;
|
||||
using Luna;
|
||||
|
|
@ -10,6 +11,7 @@ public sealed class AutomationSelection : IUiService, IDisposable
|
|||
public static readonly StringU8 NoSelection = new("No Set Selected"u8);
|
||||
|
||||
private readonly AutomationChanged _automationChanged;
|
||||
private readonly UiConfig _config;
|
||||
|
||||
public int DraggedDesignIndex = -1;
|
||||
|
||||
|
|
@ -18,10 +20,12 @@ public sealed class AutomationSelection : IUiService, IDisposable
|
|||
public StringU8 Name { get; private set; } = NoSelection;
|
||||
public StringU8 Incognito { get; private set; } = NoSelection;
|
||||
|
||||
public AutomationSelection(AutomationChanged automationChanged)
|
||||
public AutomationSelection(AutomationChanged automationChanged, UiConfig config, AutoDesignManager autoDesigns)
|
||||
{
|
||||
_automationChanged = automationChanged;
|
||||
_config = config;
|
||||
_automationChanged.Subscribe(OnAutomationChanged, AutomationChanged.Priority.SetSelector);
|
||||
InitialSelect(autoDesigns);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
@ -47,15 +51,34 @@ public sealed class AutomationSelection : IUiService, IDisposable
|
|||
Set = item?.Set;
|
||||
if (Set is null)
|
||||
{
|
||||
Index = -1;
|
||||
Name = NoSelection;
|
||||
Incognito = NoSelection;
|
||||
_config.SelectedAutomationIndex = -1;
|
||||
Index = -1;
|
||||
Name = NoSelection;
|
||||
Incognito = NoSelection;
|
||||
}
|
||||
else
|
||||
{
|
||||
Index = item!.Value.Index;
|
||||
Name = item!.Value.Name.Utf8;
|
||||
Incognito = item!.Value.Incognito;
|
||||
_config.SelectedAutomationIndex = item!.Value.Index;
|
||||
Index = item!.Value.Index;
|
||||
Name = item!.Value.Name.Utf8;
|
||||
Incognito = item!.Value.Incognito;
|
||||
}
|
||||
}
|
||||
|
||||
private void InitialSelect(AutoDesignManager autoDesigns)
|
||||
{
|
||||
if (_config.SelectedAutomationIndex < 0)
|
||||
return;
|
||||
|
||||
if (autoDesigns.Count <= _config.SelectedAutomationIndex)
|
||||
{
|
||||
_config.SelectedAutomationIndex = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
Set = autoDesigns[_config.SelectedAutomationIndex];
|
||||
Index = _config.SelectedAutomationIndex;
|
||||
Name = new StringU8(Set.Name);
|
||||
Incognito = new StringU8($"Auto Design Set #{Index + 1}");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
using Glamourer.Config;
|
||||
using Glamourer.Services;
|
||||
using ImSharp;
|
||||
using InteropGenerator.Runtime;
|
||||
using Luna;
|
||||
using Penumbra.GameData.Files.ShaderStructs;
|
||||
using Vortice.Direct3D11.Debug;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab;
|
||||
|
||||
|
|
@ -33,9 +37,29 @@ public sealed class DebugTab(ServiceManager manager) : ITab<MainTabType>
|
|||
return;
|
||||
|
||||
if (Im.Tree.Header("General"u8))
|
||||
{
|
||||
if (Im.Button("Open Config Directory"u8))
|
||||
OpenFileOrFolder(manager.GetService<FilenameService>().ConfigurationDirectory);
|
||||
StartTimeTracker.Draw("Timers"u8, manager.GetService<StartTimeTracker>());
|
||||
}
|
||||
|
||||
foreach (var header in _headers)
|
||||
header.Draw();
|
||||
}
|
||||
|
||||
private static void OpenFileOrFolder(string text)
|
||||
{
|
||||
try
|
||||
{
|
||||
var process = new ProcessStartInfo(text)
|
||||
{
|
||||
UseShellExecute = true,
|
||||
};
|
||||
Process.Start(process);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ public sealed class PenumbraPanel(PenumbraService penumbra, PenumbraChangedItemT
|
|||
table.NextColumn();
|
||||
Im.Item.SetNextWidthScaled(200);
|
||||
Im.Input.Scalar("##CutsceneIndex"u8, ref _gameObjectIndex);
|
||||
table.DrawColumn(penumbra.Available ? $"{penumbra.CutsceneParent((ushort)_gameObjectIndex)}" : "Penumbra Unavailable"u8);
|
||||
table.DrawColumn(penumbra.Available ? $"{penumbra.ResolveService.CutsceneParent((ushort)_gameObjectIndex)}" : "Penumbra Unavailable"u8);
|
||||
|
||||
table.DrawFrameColumn("Redraw Object"u8);
|
||||
table.NextColumn();
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ public sealed class ModCombo(PenumbraService penumbra, DesignFileSystem fileSyst
|
|||
{
|
||||
foreach (var setting in settings.Settings)
|
||||
{
|
||||
if (setting.Value.Count == 0)
|
||||
if (setting.Value.Count is 0)
|
||||
Im.Text("<None Enabled>"u8);
|
||||
else
|
||||
foreach (var option in setting.Value)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public sealed class DesignFileSystemDrawer : FileSystemDrawer<DesignFileSystemCa
|
|||
|
||||
public DesignFileSystemDrawer(DesignFileSystem fileSystem, DesignManager manager, DesignConverter converter, Configuration config,
|
||||
DesignApplier designApplier, DesignChanged designChanged, DesignColors designColors)
|
||||
: base(fileSystem, new DesignFilter())
|
||||
: base(fileSystem, new DesignFilter(config))
|
||||
{
|
||||
Manager = manager;
|
||||
Config = config;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using ImSharp;
|
||||
using Glamourer.Config;
|
||||
using ImSharp;
|
||||
using Luna;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DesignTab;
|
||||
|
|
@ -6,6 +7,13 @@ namespace Glamourer.Gui.Tabs.DesignTab;
|
|||
public sealed class DesignFilter : TokenizedFilter<DesignFilterTokenType, DesignFileSystemCache.DesignData, DesignFilterToken>,
|
||||
IFileSystemFilter<DesignFileSystemCache.DesignData>, IUiService
|
||||
{
|
||||
public DesignFilter(Configuration config)
|
||||
{
|
||||
if (config.RememberDesignFilter)
|
||||
Set(config.Filters.DesignFilter);
|
||||
FilterChanged += () => config.Filters.DesignFilter = Text;
|
||||
}
|
||||
|
||||
protected override void DrawTooltip()
|
||||
{
|
||||
if (!Im.Item.Hovered())
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using ImSharp;
|
||||
using Glamourer.Config;
|
||||
using ImSharp;
|
||||
using Luna;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.NpcTab;
|
||||
|
|
@ -12,6 +13,13 @@ public sealed class NpcFilter : TokenizedFilter<NpcFilter.TokenType, NpcCacheIte
|
|||
Color,
|
||||
}
|
||||
|
||||
public NpcFilter(Configuration config)
|
||||
{
|
||||
if (config.RememberNpcFilter)
|
||||
Set(config.Filters.NpcFilter);
|
||||
FilterChanged += () => config.Filters.NpcFilter = Text;
|
||||
}
|
||||
|
||||
protected override void DrawTooltip()
|
||||
{
|
||||
if (!Im.Item.Hovered())
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Glamourer.Designs;
|
||||
using Glamourer.Config;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.GameData;
|
||||
using ImSharp;
|
||||
using Luna;
|
||||
|
|
@ -10,15 +11,18 @@ public sealed class NpcSelection : IUiService, IDisposable
|
|||
private readonly LocalNpcAppearanceData _data;
|
||||
private readonly DesignColors _colors;
|
||||
private readonly DesignConverter _converter;
|
||||
private readonly UiConfig _config;
|
||||
|
||||
public NpcSelection(LocalNpcAppearanceData data, DesignColors colors, DesignConverter converter)
|
||||
public NpcSelection(LocalNpcAppearanceData data, DesignColors colors, DesignConverter converter, UiConfig config, NpcCustomizeSet npcs)
|
||||
{
|
||||
_data = data;
|
||||
_colors = colors;
|
||||
_converter = converter;
|
||||
_config = config;
|
||||
|
||||
_data.DataChanged += OnDataChanged;
|
||||
_colors.ColorChanged += OnColorChanged;
|
||||
InitialSelect(npcs);
|
||||
}
|
||||
|
||||
private void OnColorChanged()
|
||||
|
|
@ -81,12 +85,13 @@ public sealed class NpcSelection : IUiService, IDisposable
|
|||
|
||||
public void Update(in NpcCacheItem item)
|
||||
{
|
||||
Data = item.Npc;
|
||||
Name = item.Name.Utf8;
|
||||
Favorite = item.Favorite;
|
||||
ColorText = item.ColorText;
|
||||
ColorTextU8 = ColorText.Length > 0 ? new StringU8(ColorText) : DesignColors.AutomaticNameU8;
|
||||
Color = item.Color;
|
||||
Data = item.Npc;
|
||||
Name = item.Name.Utf8;
|
||||
Favorite = item.Favorite;
|
||||
ColorText = item.ColorText;
|
||||
ColorTextU8 = ColorText.Length > 0 ? new StringU8(ColorText) : DesignColors.AutomaticNameU8;
|
||||
Color = item.Color;
|
||||
_config.SelectedNpc = Data.Id;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
@ -94,4 +99,20 @@ public sealed class NpcSelection : IUiService, IDisposable
|
|||
_data.DataChanged -= OnDataChanged;
|
||||
_colors.ColorChanged -= OnColorChanged;
|
||||
}
|
||||
|
||||
private void InitialSelect(NpcCustomizeSet npcs)
|
||||
{
|
||||
if (_config.SelectedNpc.Id is 0)
|
||||
return;
|
||||
|
||||
if (!npcs.FindFirst(n => n.Id == _config.SelectedNpc.Id, out var npc))
|
||||
return;
|
||||
|
||||
Data = npc;
|
||||
Name = new StringU8(npc.Name);
|
||||
ColorText = _data.GetColor(npc);
|
||||
ColorTextU8 = ColorText.Length is not 0 ? new StringU8(ColorText) : DesignColors.AutomaticNameU8;
|
||||
(var color, Favorite) = _data.GetData(npc);
|
||||
Color = color.ToVector();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -300,6 +300,31 @@ public sealed class SettingsTab(
|
|||
Checkbox("Debug Mode"u8, "Show the debug tab. Only useful for debugging or advanced use. Not recommended in general."u8,
|
||||
config.DebugMode,
|
||||
v => config.DebugMode = v);
|
||||
|
||||
Im.Dummy(Vector2.Zero);
|
||||
Im.Separator();
|
||||
Im.Dummy(Vector2.Zero);
|
||||
|
||||
Checkbox("Remember Design Filter Across Sessions"u8,
|
||||
"Whether the filter in the Designs tab should remember its input and start with its list filtered identically to the last session."u8,
|
||||
config.RememberDesignFilter, v => config.RememberDesignFilter = v);
|
||||
|
||||
Checkbox("Remember Actor Filter Across Sessions"u8,
|
||||
"Whether the filter in the Actors tab should remember its input and start with its list filtered identically to the last session."u8,
|
||||
config.RememberActorFilter, v => config.RememberActorFilter = v);
|
||||
|
||||
Checkbox("Remember Automation Filters Across Sessions"u8,
|
||||
"Whether the filters in the Automation tab should remember their respective inputs and start with their list filtered identically to the last session."u8,
|
||||
config.RememberAutomationFilter, v => config.RememberAutomationFilter = v);
|
||||
|
||||
Checkbox("Remember NPC Filter Across Sessions"u8,
|
||||
"Whether the filter in the NPCs tab should remember its input and start with its list filtered identically to the last session."u8,
|
||||
config.RememberNpcFilter, v => config.RememberNpcFilter = v);
|
||||
|
||||
Checkbox("Remember Unlocks Filters Across Sessions"u8,
|
||||
"Whether the filters in the Unlocks tab should remember their respective inputs and start with its table filtered identically to the last session."u8,
|
||||
config.RememberUnlocksFilters, v => config.RememberUnlocksFilters = v);
|
||||
|
||||
Im.Line.New();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,30 @@ public readonly struct UnlockCacheItem(in EquipItem item, in EquipItem offhand,
|
|||
Two = 4,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum Modded
|
||||
{
|
||||
Relevant = 1,
|
||||
Ignored = 2,
|
||||
None = 4,
|
||||
}
|
||||
|
||||
public const Modded ModdedAll = Modded.Relevant | Modded.Ignored | Modded.None;
|
||||
|
||||
public const Dyability DyableAll = Dyability.No | Dyability.Yes | Dyability.Two;
|
||||
|
||||
public const EquipFlag SlotsAll = EquipFlag.Head
|
||||
| EquipFlag.Body
|
||||
| EquipFlag.Hands
|
||||
| EquipFlag.Legs
|
||||
| EquipFlag.Feet
|
||||
| EquipFlag.Ears
|
||||
| EquipFlag.Neck
|
||||
| EquipFlag.Wrist
|
||||
| EquipFlag.RFinger
|
||||
| EquipFlag.Mainhand
|
||||
| EquipFlag.Offhand;
|
||||
|
||||
public readonly EquipItem Item = item;
|
||||
public readonly StringPair Name = new(item.Name);
|
||||
public readonly EquipFlag Slot = item.Type.ToSlot().ToFlag();
|
||||
|
|
|
|||
|
|
@ -27,10 +27,22 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>,
|
|||
private readonly IgnoredMods _ignoredMods;
|
||||
|
||||
public UnlockTable(JobService jobs, ItemManager items, ItemUnlockManager unlocks, PenumbraChangedItemTooltip tooltip,
|
||||
ObjectUnlocked unlockEvent, FavoriteManager favorites, PenumbraService penumbra, TextureService textures, IgnoredMods ignoredMods)
|
||||
: base(new StringU8("Unlock Table"u8), new FavoriteColumn(favorites), new ModdedColumn(), new NameColumn(textures, tooltip),
|
||||
new SlotColumn(), new TypeColumn(), new UnlockDateColumn(), new ItemIdColumn(), new ModelDataColumn(), new JobColumn(jobs),
|
||||
new RequiredLevelColumn(), new DyableColumn(), new CrestColumn(), new TradableColumn())
|
||||
ObjectUnlocked unlockEvent, FavoriteManager favorites, PenumbraService penumbra, TextureService textures, IgnoredMods ignoredMods,
|
||||
Configuration config)
|
||||
: base(new StringU8("Unlock Table"u8),
|
||||
new FavoriteColumn(config, favorites),
|
||||
new ModdedColumn(config),
|
||||
new NameColumn(config, textures, tooltip),
|
||||
new SlotColumn(config),
|
||||
new TypeColumn(config),
|
||||
new UnlockDateColumn(config),
|
||||
new ItemIdColumn(config),
|
||||
new ModelDataColumn(config),
|
||||
new JobColumn(config, jobs),
|
||||
new RequiredLevelColumn(config),
|
||||
new DyableColumn(config),
|
||||
new CrestColumn(config),
|
||||
new TradableColumn(config))
|
||||
{
|
||||
_jobs = jobs;
|
||||
_items = items;
|
||||
|
|
@ -86,12 +98,15 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>,
|
|||
{
|
||||
private readonly FavoriteManager _favorites;
|
||||
|
||||
public FavoriteColumn(FavoriteManager favorites)
|
||||
public FavoriteColumn(Configuration config, FavoriteManager favorites)
|
||||
{
|
||||
_favorites = favorites;
|
||||
Flags |= TableColumnFlags.NoResize;
|
||||
Label = new StringU8("F"u8);
|
||||
FilterLabel = new StringU8("Favorite"u8);
|
||||
if (config.RememberUnlocksFilters)
|
||||
Filter.LoadValue(config.Filters.UnlocksFavoriteFilter);
|
||||
Filter.FilterChanged += () => config.Filters.UnlocksFavoriteFilter = Filter.FilterValue;
|
||||
}
|
||||
|
||||
public override float ComputeWidth(IEnumerable<UnlockCacheItem> allItems)
|
||||
|
|
@ -104,23 +119,18 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>,
|
|||
=> item.Favorite;
|
||||
}
|
||||
|
||||
private sealed class ModdedColumn : FlagColumn<ModdedColumn.Modded, UnlockCacheItem>
|
||||
private sealed class ModdedColumn : FlagColumn<UnlockCacheItem.Modded, UnlockCacheItem>
|
||||
{
|
||||
[Flags]
|
||||
public enum Modded
|
||||
{
|
||||
Relevant = 1,
|
||||
Ignored = 2,
|
||||
None = 4,
|
||||
}
|
||||
|
||||
private static readonly AwesomeIcon Dot = FontAwesomeIcon.Circle;
|
||||
private static readonly AwesomeIcon Hollow = FontAwesomeIcon.DotCircle;
|
||||
|
||||
public ModdedColumn()
|
||||
public ModdedColumn(Configuration config)
|
||||
{
|
||||
Flags |= TableColumnFlags.NoResize;
|
||||
Label = new StringU8("M");
|
||||
if (config.RememberUnlocksFilters)
|
||||
Filter.LoadValue(config.Filters.UnlocksModdedFilter);
|
||||
Filter.FilterChanged += () => config.Filters.UnlocksModdedFilter = Filter.FilterValue;
|
||||
}
|
||||
|
||||
public override float ComputeWidth(IEnumerable<UnlockCacheItem> allItems)
|
||||
|
|
@ -149,18 +159,19 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>,
|
|||
}
|
||||
}
|
||||
|
||||
protected override Modded GetValue(in UnlockCacheItem item, int globalIndex)
|
||||
=> item.RelevantMods > 0 ? Modded.Relevant : item.Mods.Length > 0 ? Modded.Ignored : Modded.None;
|
||||
protected override UnlockCacheItem.Modded GetValue(in UnlockCacheItem item, int globalIndex)
|
||||
=> item.RelevantMods > 0 ? UnlockCacheItem.Modded.Relevant :
|
||||
item.Mods.Length > 0 ? UnlockCacheItem.Modded.Ignored : UnlockCacheItem.Modded.None;
|
||||
|
||||
protected override StringU8 DisplayString(in UnlockCacheItem item, int globalIndex)
|
||||
=> StringU8.Empty;
|
||||
|
||||
protected override IReadOnlyList<(Modded Value, StringU8 Name)> EnumData
|
||||
protected override IReadOnlyList<(UnlockCacheItem.Modded Value, StringU8 Name)> EnumData
|
||||
=>
|
||||
[
|
||||
(Modded.Relevant, new StringU8("Any Relevant Mods"u8)),
|
||||
(Modded.Ignored, new StringU8("Only Ignored Mods"u8)),
|
||||
(Modded.None, new StringU8("Unmodded"u8)),
|
||||
(UnlockCacheItem.Modded.Relevant, new StringU8("Any Relevant Mods"u8)),
|
||||
(UnlockCacheItem.Modded.Ignored, new StringU8("Only Ignored Mods"u8)),
|
||||
(UnlockCacheItem.Modded.None, new StringU8("Unmodded"u8)),
|
||||
];
|
||||
|
||||
|
||||
|
|
@ -179,13 +190,16 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>,
|
|||
private readonly TextureService _textures;
|
||||
private readonly PenumbraChangedItemTooltip _tooltip;
|
||||
|
||||
public NameColumn(TextureService textures, PenumbraChangedItemTooltip tooltip)
|
||||
public NameColumn(Configuration config, TextureService textures, PenumbraChangedItemTooltip tooltip)
|
||||
{
|
||||
_textures = textures;
|
||||
_tooltip = tooltip;
|
||||
Flags |= TableColumnFlags.NoHide | TableColumnFlags.NoReorder;
|
||||
Label = new StringU8("Item Name..."u8);
|
||||
UnscaledWidth = 400;
|
||||
if (config.RememberUnlocksFilters)
|
||||
Filter.Set(config.Filters.UnlocksNameFilter);
|
||||
Filter.FilterChanged += () => config.Filters.UnlocksNameFilter = Filter.Text;
|
||||
}
|
||||
|
||||
public override void DrawColumn(in UnlockCacheItem item, int _)
|
||||
|
|
@ -215,8 +229,13 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>,
|
|||
|
||||
private sealed class TypeColumn : TextColumn<UnlockCacheItem>
|
||||
{
|
||||
public TypeColumn()
|
||||
=> Label = new StringU8("Item Type..."u8);
|
||||
public TypeColumn(Configuration config)
|
||||
{
|
||||
Label = new StringU8("Item Type..."u8);
|
||||
if (config.RememberUnlocksFilters)
|
||||
Filter.Set(config.Filters.UnlocksTypeFilter);
|
||||
Filter.FilterChanged += () => config.Filters.UnlocksTypeFilter = Filter.Text;
|
||||
}
|
||||
|
||||
public override float ComputeWidth(IEnumerable<UnlockCacheItem> _)
|
||||
=> FullEquipType.CrossPeinHammer.ToNameU8().CalculateSize().X;
|
||||
|
|
@ -233,10 +252,13 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>,
|
|||
|
||||
private sealed class SlotColumn : FlagColumn<EquipFlag, UnlockCacheItem>
|
||||
{
|
||||
public SlotColumn()
|
||||
public SlotColumn(Configuration config)
|
||||
{
|
||||
Flags &= ~TableColumnFlags.NoResize;
|
||||
Label = new StringU8("Equip Slot"u8);
|
||||
if (config.RememberUnlocksFilters)
|
||||
Filter.LoadValue(config.Filters.UnlocksSlotFilter);
|
||||
Filter.FilterChanged += () => config.Filters.UnlocksSlotFilter = Filter.FilterValue;
|
||||
}
|
||||
|
||||
public override float ComputeWidth(IEnumerable<UnlockCacheItem> _)
|
||||
|
|
@ -269,11 +291,14 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>,
|
|||
|
||||
private sealed class UnlockDateColumn : YesNoColumn<UnlockCacheItem>
|
||||
{
|
||||
public UnlockDateColumn()
|
||||
public UnlockDateColumn(Configuration config)
|
||||
{
|
||||
Flags &= ~TableColumnFlags.NoResize;
|
||||
Label = new StringU8("Unlocked"u8);
|
||||
FilterLabel = Label;
|
||||
if (config.RememberUnlocksFilters)
|
||||
Filter.LoadValue(config.Filters.UnlocksUnlockedFilter);
|
||||
Filter.FilterChanged += () => config.Filters.UnlocksUnlockedFilter = Filter.FilterValue;
|
||||
}
|
||||
|
||||
public override float ComputeWidth(IEnumerable<UnlockCacheItem> allItems)
|
||||
|
|
@ -297,10 +322,13 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>,
|
|||
|
||||
private sealed class ItemIdColumn : NumberColumn<uint, UnlockCacheItem>
|
||||
{
|
||||
public ItemIdColumn()
|
||||
public ItemIdColumn(Configuration config)
|
||||
{
|
||||
Label = new StringU8("Item Id..."u8);
|
||||
UnscaledWidth = 70;
|
||||
if (config.RememberUnlocksFilters)
|
||||
Filter.Set(config.Filters.UnlocksItemIdFilter);
|
||||
Filter.FilterChanged += () => config.Filters.UnlocksItemIdFilter = Filter.Text;
|
||||
}
|
||||
|
||||
public override uint ToValue(in UnlockCacheItem item, int globalIndex)
|
||||
|
|
@ -315,10 +343,13 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>,
|
|||
|
||||
private sealed class ModelDataColumn : TextColumn<UnlockCacheItem>
|
||||
{
|
||||
public ModelDataColumn()
|
||||
public ModelDataColumn(Configuration config)
|
||||
{
|
||||
Label = new StringU8("Model Data..."u8);
|
||||
UnscaledWidth = 100;
|
||||
if (config.RememberUnlocksFilters)
|
||||
Filter.Set(config.Filters.UnlocksModelDataFilter);
|
||||
Filter.FilterChanged += () => config.Filters.UnlocksModelDataFilter = Filter.Text;
|
||||
}
|
||||
|
||||
public override void DrawColumn(in UnlockCacheItem item, int globalIndex)
|
||||
|
|
@ -363,10 +394,13 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>,
|
|||
|
||||
private sealed class RequiredLevelColumn : NumberColumn<byte, UnlockCacheItem>
|
||||
{
|
||||
public RequiredLevelColumn()
|
||||
public RequiredLevelColumn(Configuration config)
|
||||
{
|
||||
Label = new StringU8("Level..."u8);
|
||||
UnscaledWidth = 70;
|
||||
if (config.RememberUnlocksFilters)
|
||||
Filter.Set(config.Filters.UnlocksLevelFilter);
|
||||
Filter.FilterChanged += () => config.Filters.UnlocksLevelFilter = Filter.Text;
|
||||
}
|
||||
|
||||
public override byte ToValue(in UnlockCacheItem item, int globalIndex)
|
||||
|
|
@ -383,7 +417,7 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>,
|
|||
{
|
||||
private readonly JobService _jobs;
|
||||
|
||||
public JobColumn(JobService jobs)
|
||||
public JobColumn(Configuration config, JobService jobs)
|
||||
: base(false)
|
||||
{
|
||||
_jobs = jobs;
|
||||
|
|
@ -392,6 +426,9 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>,
|
|||
Label = new StringU8("Jobs"u8);
|
||||
Filter = new JobFilter(this);
|
||||
UnscaledWidth = 200;
|
||||
if (config.RememberUnlocksFilters)
|
||||
Filter.LoadValue(config.Filters.UnlocksJobFilter);
|
||||
Filter.FilterChanged += () => config.Filters.UnlocksJobFilter = Filter.FilterValue;
|
||||
}
|
||||
|
||||
protected override StringU8 DisplayString(in UnlockCacheItem item, int globalIndex)
|
||||
|
|
@ -444,10 +481,13 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>,
|
|||
|
||||
private sealed class DyableColumn : FlagColumn<UnlockCacheItem.Dyability, UnlockCacheItem>
|
||||
{
|
||||
public DyableColumn()
|
||||
public DyableColumn(Configuration config)
|
||||
{
|
||||
Flags &= ~TableColumnFlags.NoResize;
|
||||
Label = new StringU8("Dye"u8);
|
||||
if (config.RememberUnlocksFilters)
|
||||
Filter.LoadValue(config.Filters.UnlocksDyabilityFilter);
|
||||
Filter.FilterChanged += () => config.Filters.UnlocksDyabilityFilter = Filter.FilterValue;
|
||||
}
|
||||
|
||||
public override float ComputeWidth(IEnumerable<UnlockCacheItem> _)
|
||||
|
|
@ -487,8 +527,13 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>,
|
|||
|
||||
private sealed class TradableColumn : LunaStyle.YesNoColumn<UnlockCacheItem>
|
||||
{
|
||||
public TradableColumn()
|
||||
=> Label = new StringU8("Trade"u8);
|
||||
public TradableColumn(Configuration config)
|
||||
{
|
||||
Label = new StringU8("Trade"u8);
|
||||
if (config.RememberUnlocksFilters)
|
||||
Filter.LoadValue(config.Filters.UnlocksTradableFilter);
|
||||
Filter.FilterChanged += () => config.Filters.UnlocksTradableFilter = Filter.FilterValue;
|
||||
}
|
||||
|
||||
protected override bool GetValue(in UnlockCacheItem item, int globalIndex, int triEnumIndex)
|
||||
=> item.Tradable;
|
||||
|
|
@ -496,8 +541,13 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>,
|
|||
|
||||
private sealed class CrestColumn : LunaStyle.YesNoColumn<UnlockCacheItem>
|
||||
{
|
||||
public CrestColumn()
|
||||
=> Label = new StringU8("Crest"u8);
|
||||
public CrestColumn(Configuration config)
|
||||
{
|
||||
Label = new StringU8("Crest"u8);
|
||||
if (config.RememberUnlocksFilters)
|
||||
Filter.LoadValue(config.Filters.UnlocksCrestFilter);
|
||||
Filter.FilterChanged += () => config.Filters.UnlocksCrestFilter = Filter.FilterValue;
|
||||
}
|
||||
|
||||
protected override bool GetValue(in UnlockCacheItem item, int globalIndex, int triEnumIndex)
|
||||
=> item.Crest;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,15 @@ public readonly record struct ModSettings(Dictionary<string, List<string>> Setti
|
|||
=> new();
|
||||
}
|
||||
|
||||
public sealed class CutsceneResolveService : IService
|
||||
{
|
||||
public Func<int, int>? CheckCutsceneParent;
|
||||
|
||||
/// <summary> Obtain the parent of a cutscene actor if it is known. </summary>
|
||||
public short CutsceneParent(ushort idx)
|
||||
=> (short)(CheckCutsceneParent?.Invoke(idx) ?? -1);
|
||||
}
|
||||
|
||||
public sealed class PenumbraService : IDisposable, IService
|
||||
{
|
||||
public const int RequiredPenumbraBreakingVersion = 5;
|
||||
|
|
@ -45,6 +54,8 @@ public sealed class PenumbraService : IDisposable, IService
|
|||
private const int KeyManual = -6160;
|
||||
private const string NameManual = "Glamourer (Manually)";
|
||||
|
||||
public readonly CutsceneResolveService ResolveService;
|
||||
|
||||
private readonly IDalamudPluginInterface _pluginInterface;
|
||||
private readonly Configuration _config;
|
||||
private readonly EventSubscriber<ChangedItemType, uint> _tooltipSubscriber;
|
||||
|
|
@ -84,7 +95,6 @@ public sealed class PenumbraService : IDisposable, IService
|
|||
private global::Penumbra.Api.IpcSubscribers.UnregisterSettingsSection? _unregisterSettingsSection;
|
||||
private IReadOnlyList<(string ModDirectory, IReadOnlyDictionary<string, object?> ChangedItems)>? _changedItems;
|
||||
private Func<string, (string ModDirectory, string ModName)[]>? _checkCurrentChangedItems;
|
||||
private Func<int, int>? _checkCutsceneParent;
|
||||
private Func<nint, nint>? _getGameObject;
|
||||
|
||||
private readonly IDisposable _initializedEvent;
|
||||
|
|
@ -97,10 +107,12 @@ public sealed class PenumbraService : IDisposable, IService
|
|||
public int CurrentMinor { get; private set; }
|
||||
public DateTime AttachTime { get; private set; }
|
||||
|
||||
public PenumbraService(IDalamudPluginInterface pi, PenumbraReloaded penumbraReloaded, Configuration config)
|
||||
public PenumbraService(IDalamudPluginInterface pi, PenumbraReloaded penumbraReloaded, CutsceneResolveService resolveService,
|
||||
Configuration config)
|
||||
{
|
||||
_pluginInterface = pi;
|
||||
_penumbraReloaded = penumbraReloaded;
|
||||
ResolveService = resolveService;
|
||||
_config = config;
|
||||
_initializedEvent = global::Penumbra.Api.IpcSubscribers.Initialized.Subscriber(pi, Reattach);
|
||||
_disposedEvent = global::Penumbra.Api.IpcSubscribers.Disposed.Subscriber(pi, Unattach);
|
||||
|
|
@ -192,7 +204,7 @@ public sealed class PenumbraService : IDisposable, IService
|
|||
|
||||
private ModSettings GetSettings(Guid collection, string modDirectory, string modName, out string source)
|
||||
{
|
||||
if (_getCurrentSettingsWithTemp != null)
|
||||
if (_getCurrentSettingsWithTemp is not null)
|
||||
{
|
||||
source = string.Empty;
|
||||
var (ec, tuple) = _getCurrentSettingsWithTemp!.Invoke(collection, modDirectory, modName, false, false, KeyFixed);
|
||||
|
|
@ -204,7 +216,7 @@ public sealed class PenumbraService : IDisposable, IService
|
|||
: ModSettings.Empty;
|
||||
}
|
||||
|
||||
if (_queryTemporaryModSettings != null)
|
||||
if (_queryTemporaryModSettings is not null)
|
||||
{
|
||||
var tempEc = _queryTemporaryModSettings.Invoke(collection, modDirectory, out var tempTuple, out source, 0, modName);
|
||||
if (tempEc is PenumbraApiEc.Success && tempTuple != null)
|
||||
|
|
@ -485,9 +497,6 @@ public sealed class PenumbraService : IDisposable, IService
|
|||
public Actor GameObjectFromDrawObject(Model drawObject)
|
||||
=> _getGameObject?.Invoke(drawObject.Address) ?? Actor.Null;
|
||||
|
||||
/// <summary> Obtain the parent of a cutscene actor if it is known. </summary>
|
||||
public short CutsceneParent(ushort idx)
|
||||
=> (short)(_checkCutsceneParent?.Invoke(idx) ?? -1);
|
||||
|
||||
/// <summary> Try to redraw the given actor. </summary>
|
||||
public void RedrawObject(Actor actor, RedrawType settings)
|
||||
|
|
@ -554,7 +563,7 @@ public sealed class PenumbraService : IDisposable, IService
|
|||
_collectionByIdentifier = new global::Penumbra.Api.IpcSubscribers.GetCollectionsByIdentifier(_pluginInterface);
|
||||
_collections = new global::Penumbra.Api.IpcSubscribers.GetCollections(_pluginInterface);
|
||||
_redraw = new global::Penumbra.Api.IpcSubscribers.RedrawObject(_pluginInterface);
|
||||
_checkCutsceneParent = new global::Penumbra.Api.IpcSubscribers.GetCutsceneParentIndexFunc(_pluginInterface).Invoke();
|
||||
ResolveService.CheckCutsceneParent = new global::Penumbra.Api.IpcSubscribers.GetCutsceneParentIndexFunc(_pluginInterface).Invoke();
|
||||
_getGameObject = new global::Penumbra.Api.IpcSubscribers.GetGameObjectFromDrawObjectFunc(_pluginInterface).Invoke();
|
||||
_objectCollection = new global::Penumbra.Api.IpcSubscribers.GetCollectionForObject(_pluginInterface);
|
||||
_getMods = new global::Penumbra.Api.IpcSubscribers.GetModList(_pluginInterface);
|
||||
|
|
@ -623,7 +632,7 @@ public sealed class PenumbraService : IDisposable, IService
|
|||
_collections = null;
|
||||
_redraw = null;
|
||||
_getGameObject = null;
|
||||
_checkCutsceneParent = null;
|
||||
ResolveService.CheckCutsceneParent = null;
|
||||
_objectCollection = null;
|
||||
_getMods = null;
|
||||
_currentCollection = null;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ public sealed class BackupService(Logger log, FilenameService provider) : BaseBa
|
|||
var list = new List<FileInfo>(16)
|
||||
{
|
||||
new(fileNames.ConfigurationFile),
|
||||
new(fileNames.UiConfiguration),
|
||||
new(fileNames.UiConfigurationFile),
|
||||
new(fileNames.MigrationDesignFileSystem),
|
||||
new(fileNames.MigrationDesignFile),
|
||||
new(fileNames.AutomationFile),
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ public sealed class FilenameService(IDalamudPluginInterface pi) : BaseFilePathPr
|
|||
public readonly string EphemeralConfigFile = Path.Combine(pi.ConfigDirectory.FullName, "ephemeral_config.json");
|
||||
public readonly string NpcAppearanceFile = Path.Combine(pi.ConfigDirectory.FullName, "npc_appearance_data.json");
|
||||
public readonly string CollectionOverrideFile = Path.Combine(pi.ConfigDirectory.FullName, "collection_overrides.json");
|
||||
public readonly string UiConfiguration = Path.Combine(pi.ConfigDirectory.FullName, "ui_config.json");
|
||||
public readonly string UiConfigurationFile = Path.Combine(pi.ConfigDirectory.FullName, "ui_config.json");
|
||||
public readonly string FilterFile = Path.Combine(pi.ConfigDirectory.FullName, "filters.json");
|
||||
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 readonly string FileSystemExpandedFolders = Path.Combine(pi.ConfigDirectory.FullName, "design_filesystem", "expanded_folders.json");
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public static class StaticServiceManager
|
|||
.AddExistingService(log)
|
||||
.AddSingleton<MessageService>()
|
||||
.AddSingleton<ActorObjectManager>()
|
||||
.AddSingleton(p => new CutsceneResolver(p.GetRequiredService<PenumbraService>().CutsceneParent))
|
||||
.AddSingleton(p => new CutsceneResolver(p.GetRequiredService<CutsceneResolveService>().CutsceneParent))
|
||||
.AddExistingService(glamourer);
|
||||
services.AddIServices(typeof(EquipItem).Assembly);
|
||||
services.AddIServices(typeof(Glamourer).Assembly);
|
||||
|
|
|
|||
2
Luna
2
Luna
|
|
@ -1 +1 @@
|
|||
Subproject commit 4a46e8551dd4438465c013c4a01d2936e5b4d4da
|
||||
Subproject commit bc900c5b5959915a87f60487f5b67aa358b195be
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 9cfcaf39fef363e281f066b55811deef72908f2f
|
||||
Subproject commit c7c1cae55b34c59580492a8e279205844e2116e2
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit f75aa967763347148401ec2cb800dcba2523f8c0
|
||||
Subproject commit 2d83cda9e72c132b90bba20dd862a442a218b6c2
|
||||
Loading…
Add table
Add a link
Reference in a new issue