mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-02-18 22:07:45 +01:00
Update Filter things.
This commit is contained in:
parent
27e059658d
commit
3b4cab2a1a
22 changed files with 809 additions and 402 deletions
|
|
@ -22,6 +22,9 @@ public class Configuration : IPluginConfiguration, ISavable, IService
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public readonly EphemeralConfig Ephemeral;
|
public readonly EphemeralConfig Ephemeral;
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public readonly FilterConfig Filters;
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public readonly UiConfig Ui;
|
public readonly UiConfig Ui;
|
||||||
|
|
||||||
|
|
@ -122,11 +125,12 @@ public class Configuration : IPluginConfiguration, ISavable, IService
|
||||||
/// Includes adding new colors and migrating from old versions.
|
/// Includes adding new colors and migrating from old versions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Configuration(CharacterUtility utility, ConfigMigrationService migrator, SaveService saveService, EphemeralConfig ephemeral,
|
public Configuration(CharacterUtility utility, ConfigMigrationService migrator, SaveService saveService, EphemeralConfig ephemeral,
|
||||||
UiConfig ui)
|
UiConfig ui, FilterConfig filters)
|
||||||
{
|
{
|
||||||
_saveService = saveService;
|
_saveService = saveService;
|
||||||
Ephemeral = ephemeral;
|
Ephemeral = ephemeral;
|
||||||
Ui = ui;
|
Ui = ui;
|
||||||
|
Filters = filters;
|
||||||
Load(utility, migrator);
|
Load(utility, migrator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
60
Penumbra/Config/ConfigurationFile.cs
Normal file
60
Penumbra/Config/ConfigurationFile.cs
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
|
using Luna;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Penumbra.Services;
|
||||||
|
|
||||||
|
namespace Penumbra;
|
||||||
|
|
||||||
|
public abstract class ConfigurationFile(SaveService saveService, TimeSpan? saveDelay = null) : ISavable, IService
|
||||||
|
{
|
||||||
|
public abstract int CurrentVersion { get; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
protected readonly SaveService SaveService = saveService;
|
||||||
|
|
||||||
|
public virtual void Save()
|
||||||
|
=> SaveService.DelaySave(this, SaveDelay);
|
||||||
|
|
||||||
|
protected TimeSpan SaveDelay { get; set; } = saveDelay ?? TimeSpan.FromMinutes(1);
|
||||||
|
|
||||||
|
public virtual void Save(StreamWriter writer)
|
||||||
|
{
|
||||||
|
using var j = new JsonTextWriter(writer);
|
||||||
|
j.Formatting = Formatting.Indented;
|
||||||
|
j.WriteStartObject();
|
||||||
|
j.WritePropertyName("Version");
|
||||||
|
j.WriteValue(CurrentVersion);
|
||||||
|
AddData(j);
|
||||||
|
j.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void AddData(JsonTextWriter j);
|
||||||
|
protected abstract void LoadData(JObject j);
|
||||||
|
|
||||||
|
public abstract string ToFilePath(FilenameService fileNames);
|
||||||
|
|
||||||
|
protected virtual void Load()
|
||||||
|
{
|
||||||
|
var fileName = ToFilePath(SaveService.FileNames);
|
||||||
|
var logName = ((ISavable)this).LogName(fileName);
|
||||||
|
if (!File.Exists(fileName))
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Penumbra.Log.Debug($"Reading {logName}...");
|
||||||
|
var text = File.ReadAllText(fileName);
|
||||||
|
var jObj = JObject.Parse(text);
|
||||||
|
if (jObj["Version"]?.Value<int>() != CurrentVersion)
|
||||||
|
throw new Exception("Unsupported version.");
|
||||||
|
|
||||||
|
LoadData(jObj);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Penumbra.Messager.NotificationMessage(ex, $"Error reading {logName}, reverting to default.",
|
||||||
|
$"Error reading {logName}", NotificationType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,7 +30,6 @@ public class EphemeralConfig : ISavable, IService
|
||||||
public RecordType ResourceWatcherRecordTypes { get; set; } = ResourceWatcher.AllRecords;
|
public RecordType ResourceWatcherRecordTypes { get; set; } = ResourceWatcher.AllRecords;
|
||||||
public CollectionPanelMode CollectionPanel { get; set; } = CollectionPanelMode.SimpleAssignment;
|
public CollectionPanelMode CollectionPanel { get; set; } = CollectionPanelMode.SimpleAssignment;
|
||||||
public TabType SelectedTab { get; set; } = TabType.Settings;
|
public TabType SelectedTab { get; set; } = TabType.Settings;
|
||||||
public ChangedItemIconFlag ChangedItemFilter { get; set; } = ChangedItemFlagExtensions.DefaultFlags;
|
|
||||||
public bool FixMainWindow { get; set; } = false;
|
public bool FixMainWindow { get; set; } = false;
|
||||||
public HashSet<string> AdvancedEditingOpenForModPaths { get; set; } = [];
|
public HashSet<string> AdvancedEditingOpenForModPaths { get; set; } = [];
|
||||||
public bool ForceRedrawOnFileChange { get; set; } = false;
|
public bool ForceRedrawOnFileChange { get; set; } = false;
|
||||||
|
|
|
||||||
467
Penumbra/Config/FilterConfig.cs
Normal file
467
Penumbra/Config/FilterConfig.cs
Normal file
|
|
@ -0,0 +1,467 @@
|
||||||
|
using Luna.Generators;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Penumbra.Enums;
|
||||||
|
using Penumbra.Services;
|
||||||
|
using Penumbra.UI.Classes;
|
||||||
|
using Penumbra.UI.ModsTab.Selector;
|
||||||
|
using Penumbra.UI.ResourceWatcher;
|
||||||
|
|
||||||
|
namespace Penumbra;
|
||||||
|
|
||||||
|
public sealed partial class FilterConfig : ConfigurationFile
|
||||||
|
{
|
||||||
|
public override int CurrentVersion
|
||||||
|
=> 1;
|
||||||
|
|
||||||
|
public FilterConfig(SaveService saveService)
|
||||||
|
: base(saveService)
|
||||||
|
{
|
||||||
|
Load();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void AddData(JsonTextWriter j)
|
||||||
|
{
|
||||||
|
WriteModsTab(j);
|
||||||
|
WriteCollectionsTab(j);
|
||||||
|
WriteChangedItemsTab(j);
|
||||||
|
WriteEffectiveChangesTab(j);
|
||||||
|
WriteOnScreenTab(j);
|
||||||
|
WriteResourceManagerTab(j);
|
||||||
|
WriteResourceWatcherTab(j);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadData(JObject j)
|
||||||
|
{
|
||||||
|
LoadModsTab(j);
|
||||||
|
LoadCollectionsTab(j);
|
||||||
|
LoadChangedItemsTab(j);
|
||||||
|
LoadEffectiveChangesTab(j);
|
||||||
|
LoadOnScreenTab(j);
|
||||||
|
LoadResourceManagerTab(j);
|
||||||
|
LoadResourceWatcherTab(j);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToFilePath(FilenameService fileNames)
|
||||||
|
=> fileNames.FilterFile;
|
||||||
|
|
||||||
|
|
||||||
|
#region Mods Tab
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private ModTypeFilter _modTypeFilter = ModTypeFilterExtensions.UnfilteredStateMods;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _modFilter = string.Empty;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private ChangedItemIconFlag _modChangedItemTypeFilter = ChangedItemFlagExtensions.DefaultFlags;
|
||||||
|
|
||||||
|
private void WriteModsTab(JsonTextWriter j)
|
||||||
|
{
|
||||||
|
if (ModTypeFilter is ModTypeFilterExtensions.UnfilteredStateMods
|
||||||
|
&& ModFilter.Length is 0
|
||||||
|
&& ModChangedItemTypeFilter is ChangedItemFlagExtensions.DefaultFlags)
|
||||||
|
return;
|
||||||
|
|
||||||
|
j.WritePropertyName("Mods");
|
||||||
|
j.WriteStartObject();
|
||||||
|
if (ModTypeFilter is not ModTypeFilterExtensions.UnfilteredStateMods)
|
||||||
|
{
|
||||||
|
j.WritePropertyName("TypeFilter");
|
||||||
|
j.WriteValue((uint)ModTypeFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ModFilter.Length > 0)
|
||||||
|
{
|
||||||
|
j.WritePropertyName("ModFilter");
|
||||||
|
j.WriteValue(ModFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ModChangedItemTypeFilter is not ChangedItemFlagExtensions.DefaultFlags)
|
||||||
|
{
|
||||||
|
j.WritePropertyName("ChangedItemTypeFilter");
|
||||||
|
j.WriteValue((uint)ModChangedItemTypeFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
j.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadModsTab(JObject j)
|
||||||
|
{
|
||||||
|
if (j["Mods"] is not JObject mods)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_modTypeFilter = mods["TypeFilter"]?.Value<uint>() is { } modTypeFilter
|
||||||
|
? (ModTypeFilter)modTypeFilter
|
||||||
|
: ModTypeFilterExtensions.UnfilteredStateMods;
|
||||||
|
_modFilter = mods["ModFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
_modChangedItemTypeFilter = mods["ChangedItemTypeFilter"]?.Value<uint>() is { } changedItemFilter
|
||||||
|
? (ChangedItemIconFlag)changedItemFilter
|
||||||
|
: ChangedItemFlagExtensions.DefaultFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Collections Tab
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _collectionFilter = string.Empty;
|
||||||
|
|
||||||
|
private void WriteCollectionsTab(JsonTextWriter j)
|
||||||
|
{
|
||||||
|
if (CollectionFilter.Length is 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
j.WritePropertyName("Collections");
|
||||||
|
j.WriteStartObject();
|
||||||
|
if (CollectionFilter.Length > 0)
|
||||||
|
{
|
||||||
|
j.WritePropertyName("CollectionFilter");
|
||||||
|
j.WriteValue(CollectionFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
j.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadCollectionsTab(JObject j)
|
||||||
|
{
|
||||||
|
if (j["Collections"] is JObject collections)
|
||||||
|
_collectionFilter = collections["CollectionFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Changed Items Tab
|
||||||
|
|
||||||
|
// Changed Items tab
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _changedItemItemFilter = string.Empty;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _changedItemModFilter = string.Empty;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private ChangedItemIconFlag _changedItemTypeFilter = ChangedItemFlagExtensions.DefaultFlags;
|
||||||
|
|
||||||
|
private void WriteChangedItemsTab(JsonTextWriter j)
|
||||||
|
{
|
||||||
|
if (ChangedItemItemFilter.Length is 0
|
||||||
|
&& ChangedItemModFilter.Length is 0
|
||||||
|
&& ChangedItemTypeFilter is ChangedItemFlagExtensions.DefaultFlags)
|
||||||
|
return;
|
||||||
|
|
||||||
|
j.WritePropertyName("ChangedItems");
|
||||||
|
j.WriteStartObject();
|
||||||
|
if (ChangedItemItemFilter.Length > 0)
|
||||||
|
{
|
||||||
|
j.WritePropertyName("ItemFilter");
|
||||||
|
j.WriteValue(ChangedItemItemFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ChangedItemModFilter.Length > 0)
|
||||||
|
{
|
||||||
|
j.WritePropertyName("ModFilter");
|
||||||
|
j.WriteValue(ChangedItemModFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ChangedItemTypeFilter is not ChangedItemFlagExtensions.DefaultFlags)
|
||||||
|
{
|
||||||
|
j.WritePropertyName("TypeFilter");
|
||||||
|
j.WriteValue((uint)ChangedItemTypeFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
j.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadChangedItemsTab(JObject j)
|
||||||
|
{
|
||||||
|
if (j["ChangedItems"] is not JObject changedItems)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_changedItemItemFilter = changedItems["ItemFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
_changedItemModFilter = changedItems["ModFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
_changedItemTypeFilter = changedItems["TypeFilter"]?.Value<uint>() is { } typeFilter
|
||||||
|
? (ChangedItemIconFlag)typeFilter
|
||||||
|
: ChangedItemFlagExtensions.DefaultFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Effective Changes tab
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _effectiveChangesGamePathFilter = string.Empty;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _effectiveChangesFilePathFilter = string.Empty;
|
||||||
|
|
||||||
|
private void WriteEffectiveChangesTab(JsonTextWriter j)
|
||||||
|
{
|
||||||
|
if (EffectiveChangesGamePathFilter.Length is 0 && EffectiveChangesFilePathFilter.Length is 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
j.WritePropertyName("EffectiveChanges");
|
||||||
|
j.WriteStartObject();
|
||||||
|
if (EffectiveChangesGamePathFilter.Length > 0)
|
||||||
|
{
|
||||||
|
j.WritePropertyName("GamePathFilter");
|
||||||
|
j.WriteValue(EffectiveChangesGamePathFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EffectiveChangesFilePathFilter.Length > 0)
|
||||||
|
{
|
||||||
|
j.WritePropertyName("FilePathFilter");
|
||||||
|
j.WriteValue(EffectiveChangesFilePathFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
j.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadEffectiveChangesTab(JObject j)
|
||||||
|
{
|
||||||
|
if (j["EffectiveChanges"] is not JObject effectiveChanges)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_effectiveChangesGamePathFilter = effectiveChanges["GamePathFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
_effectiveChangesFilePathFilter = effectiveChanges["FilePathFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region On-Screen tab
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _onScreenCharacterFilter = string.Empty;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _onScreenItemFilter = string.Empty;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private ChangedItemIconFlag _onScreenTypeFilter = ChangedItemFlagExtensions.DefaultFlags;
|
||||||
|
|
||||||
|
private void WriteOnScreenTab(JsonTextWriter j)
|
||||||
|
{
|
||||||
|
if (OnScreenCharacterFilter.Length is 0
|
||||||
|
&& OnScreenItemFilter.Length is 0
|
||||||
|
&& OnScreenTypeFilter is ChangedItemFlagExtensions.DefaultFlags)
|
||||||
|
return;
|
||||||
|
|
||||||
|
j.WritePropertyName("OnScreen");
|
||||||
|
j.WriteStartObject();
|
||||||
|
if (OnScreenCharacterFilter.Length > 0)
|
||||||
|
{
|
||||||
|
j.WritePropertyName("CharacterFilter");
|
||||||
|
j.WriteValue(OnScreenCharacterFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OnScreenItemFilter.Length > 0)
|
||||||
|
{
|
||||||
|
j.WritePropertyName("ItemFilter");
|
||||||
|
j.WriteValue(OnScreenItemFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OnScreenTypeFilter is not ChangedItemFlagExtensions.DefaultFlags)
|
||||||
|
{
|
||||||
|
j.WritePropertyName("TypeFilter");
|
||||||
|
j.WriteValue((uint)OnScreenTypeFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
j.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadOnScreenTab(JObject j)
|
||||||
|
{
|
||||||
|
if (j["OnScreen"] is not JObject onScreen)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_onScreenCharacterFilter = onScreen["CharacterFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
_onScreenItemFilter = onScreen["ItemFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
_onScreenTypeFilter = onScreen["TypeFilter"]?.Value<uint>() is { } typeFilter
|
||||||
|
? (ChangedItemIconFlag)typeFilter
|
||||||
|
: ChangedItemFlagExtensions.DefaultFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Resource Manager tab
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _resourceManagerFilter = string.Empty;
|
||||||
|
|
||||||
|
private void WriteResourceManagerTab(JsonTextWriter j)
|
||||||
|
{
|
||||||
|
if (ResourceManagerFilter.Length is 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
j.WritePropertyName("ResourceManager");
|
||||||
|
j.WriteStartObject();
|
||||||
|
if (ResourceManagerFilter.Length > 0)
|
||||||
|
{
|
||||||
|
j.WritePropertyName("PathFilter");
|
||||||
|
j.WriteValue(ResourceManagerFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
j.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadResourceManagerTab(JObject j)
|
||||||
|
{
|
||||||
|
if (j["ResourceManager"] is JObject resourceManager)
|
||||||
|
_resourceManagerFilter = resourceManager["PathFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private bool _resourceLoggerEnabled = false;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private int _resourceLoggerMaxEntries = 500;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private bool _resourceLoggerStoreOnlyMatching = true;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private bool _resourceLoggerWriteToLog = false;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _resourceLoggerLogFilter = string.Empty;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _resourceLoggerPathFilter = string.Empty;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _resourceLoggerCollectionFilter = string.Empty;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _resourceLoggerObjectFilter = string.Empty;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _resourceLoggerOriginalPathFilter = string.Empty;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _resourceLoggerResourceFilter = string.Empty;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _resourceLoggerCrcFilter = string.Empty;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _resourceLoggerRefFilter = string.Empty;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private string _resourceLoggerThreadFilter = string.Empty;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private RecordType _resourceLoggerRecordFilter = RecordTypeExtensions.All;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private BoolEnum _resourceLoggerCustomFilter = BoolEnumExtensions.All;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private BoolEnum _resourceLoggerSyncFilter = BoolEnumExtensions.All;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private ResourceCategoryFlag _resourceLoggerCategoryFilter = ResourceExtensions.AllResourceCategories;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private ResourceTypeFlag _resourceLoggerTypeFilter = ResourceExtensions.AllResourceTypes;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private LoadStateFlag _resourceLoggerLoadStateFilter = LoadStateExtensions.All;
|
||||||
|
|
||||||
|
private void WriteResourceWatcherTab(JsonTextWriter j)
|
||||||
|
{
|
||||||
|
var jObj = new JObject();
|
||||||
|
|
||||||
|
if (ResourceLoggerEnabled)
|
||||||
|
jObj["Enabled"] = true;
|
||||||
|
if (ResourceLoggerWriteToLog)
|
||||||
|
jObj["WriteToLog"] = true;
|
||||||
|
if (ResourceLoggerMaxEntries is not 500)
|
||||||
|
jObj["MaxEntries"] = ResourceLoggerMaxEntries;
|
||||||
|
if (!ResourceLoggerStoreOnlyMatching)
|
||||||
|
jObj["StoreOnlyMatching"] = false;
|
||||||
|
if (ResourceLoggerLogFilter.Length > 0)
|
||||||
|
jObj["LogFilter"] = ResourceLoggerLogFilter;
|
||||||
|
if (ResourceLoggerPathFilter.Length > 0)
|
||||||
|
jObj["PathFilter"] = ResourceLoggerPathFilter;
|
||||||
|
if (ResourceLoggerCollectionFilter.Length > 0)
|
||||||
|
jObj["CollectionFilter"] = ResourceLoggerCollectionFilter;
|
||||||
|
if (ResourceLoggerObjectFilter.Length > 0)
|
||||||
|
jObj["ObjectFilter"] = ResourceLoggerObjectFilter;
|
||||||
|
if (ResourceLoggerOriginalPathFilter.Length > 0)
|
||||||
|
jObj["OriginalPathFilter"] = ResourceLoggerOriginalPathFilter;
|
||||||
|
if (ResourceLoggerResourceFilter.Length > 0)
|
||||||
|
jObj["ResourceFilter"] = ResourceLoggerResourceFilter;
|
||||||
|
if (ResourceLoggerCrcFilter.Length > 0)
|
||||||
|
jObj["CrcFilter"] = ResourceLoggerCrcFilter;
|
||||||
|
if (ResourceLoggerRefFilter.Length > 0)
|
||||||
|
jObj["RefFilter"] = ResourceLoggerRefFilter;
|
||||||
|
if (ResourceLoggerThreadFilter.Length > 0)
|
||||||
|
jObj["ThreadFilter"] = ResourceLoggerThreadFilter;
|
||||||
|
|
||||||
|
if (ResourceLoggerRecordFilter is not RecordTypeExtensions.All)
|
||||||
|
jObj["RecordFilter"] = (uint)ResourceLoggerRecordFilter;
|
||||||
|
if (ResourceLoggerCustomFilter is not BoolEnumExtensions.All)
|
||||||
|
jObj["CustomFilter"] = (uint)ResourceLoggerCustomFilter;
|
||||||
|
if (ResourceLoggerSyncFilter is not BoolEnumExtensions.All)
|
||||||
|
jObj["SyncFilter"] = (uint)ResourceLoggerSyncFilter;
|
||||||
|
if (ResourceLoggerCategoryFilter != ResourceExtensions.AllResourceCategories)
|
||||||
|
jObj["CategoryFilter"] = (uint)ResourceLoggerCategoryFilter;
|
||||||
|
if (ResourceLoggerTypeFilter != ResourceExtensions.AllResourceTypes)
|
||||||
|
jObj["TypeFilter"] = (uint)ResourceLoggerTypeFilter;
|
||||||
|
if (ResourceLoggerLoadStateFilter is not LoadStateExtensions.All)
|
||||||
|
jObj["LoadStateFilter"] = (uint)ResourceLoggerLoadStateFilter;
|
||||||
|
|
||||||
|
if (jObj.Count is not 0)
|
||||||
|
{
|
||||||
|
j.WritePropertyName("ResourceWatcher");
|
||||||
|
jObj.WriteTo(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadResourceWatcherTab(JObject j)
|
||||||
|
{
|
||||||
|
if (j["ResourceWatcher"] is not JObject resourceWatcher)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_resourceLoggerEnabled = resourceWatcher["Enabled"]?.Value<bool>() ?? false;
|
||||||
|
_resourceLoggerMaxEntries = resourceWatcher["MaxEntries"]?.Value<int>() ?? 500;
|
||||||
|
_resourceLoggerStoreOnlyMatching = resourceWatcher["StoreOnlyMatching"]?.Value<bool>() ?? true;
|
||||||
|
_resourceLoggerWriteToLog = resourceWatcher["WriteToLog"]?.Value<bool>() ?? false;
|
||||||
|
|
||||||
|
_resourceLoggerLogFilter = resourceWatcher["LogFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
_resourceLoggerPathFilter = resourceWatcher["PathFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
_resourceLoggerCollectionFilter = resourceWatcher["CollectionFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
_resourceLoggerObjectFilter = resourceWatcher["ObjectFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
_resourceLoggerOriginalPathFilter = resourceWatcher["OriginalPathFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
_resourceLoggerResourceFilter = resourceWatcher["ResourceFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
_resourceLoggerCrcFilter = resourceWatcher["CrcFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
_resourceLoggerRefFilter = resourceWatcher["RefFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
_resourceLoggerThreadFilter = resourceWatcher["ThreadFilter"]?.Value<string>() ?? string.Empty;
|
||||||
|
|
||||||
|
_resourceLoggerRecordFilter = resourceWatcher["RecordFilter"]?.Value<uint>() is { } recordFilter
|
||||||
|
? (RecordType)recordFilter
|
||||||
|
: RecordTypeExtensions.All;
|
||||||
|
_resourceLoggerCustomFilter = resourceWatcher["CustomFilter"]?.Value<uint>() is { } customFilter
|
||||||
|
? (BoolEnum)customFilter
|
||||||
|
: BoolEnumExtensions.All;
|
||||||
|
_resourceLoggerSyncFilter = resourceWatcher["SyncFilter"]?.Value<uint>() is { } syncFilter
|
||||||
|
? (BoolEnum)syncFilter
|
||||||
|
: BoolEnumExtensions.All;
|
||||||
|
_resourceLoggerCategoryFilter = resourceWatcher["CategoryFilter"]?.Value<uint>() is { } categoryFilter
|
||||||
|
? (ResourceCategoryFlag)categoryFilter
|
||||||
|
: ResourceExtensions.AllResourceCategories;
|
||||||
|
_resourceLoggerTypeFilter = resourceWatcher["TypeFilter"]?.Value<uint>() is { } typeFilter
|
||||||
|
? (ResourceTypeFlag)typeFilter
|
||||||
|
: ResourceExtensions.AllResourceTypes;
|
||||||
|
_resourceLoggerLoadStateFilter = resourceWatcher["LoadStateFilter"]?.Value<uint>() is { } loadStateFilter
|
||||||
|
? (LoadStateFlag)loadStateFilter
|
||||||
|
: LoadStateExtensions.All;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
@ -1,73 +1,27 @@
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
|
||||||
using Luna;
|
using Luna;
|
||||||
|
using Luna.Generators;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
|
|
||||||
namespace Penumbra;
|
namespace Penumbra;
|
||||||
|
|
||||||
public class UiConfig : ISavable, IService
|
public sealed partial class UiConfig : ConfigurationFile
|
||||||
{
|
{
|
||||||
public const int CurrentVersion = 1;
|
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
private readonly SaveService _saveService;
|
|
||||||
|
|
||||||
public UiConfig(SaveService saveService)
|
public UiConfig(SaveService saveService)
|
||||||
|
: base(saveService, TimeSpan.FromMinutes(5))
|
||||||
{
|
{
|
||||||
_saveService = saveService;
|
|
||||||
Load();
|
Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
private TwoPanelWidth _collectionsTabScale = new(0.25f, ScalingMode.Percentage);
|
protected override void AddData(JsonTextWriter j)
|
||||||
|
|
||||||
public TwoPanelWidth CollectionTabScale
|
|
||||||
{
|
{
|
||||||
get => _collectionsTabScale;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value == _collectionsTabScale)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_collectionsTabScale = value;
|
|
||||||
Save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private TwoPanelWidth _modTabScale = new(0.3f, ScalingMode.Percentage);
|
|
||||||
|
|
||||||
public TwoPanelWidth ModTabScale
|
|
||||||
{
|
|
||||||
get => _modTabScale;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value == _modTabScale)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_modTabScale = value;
|
|
||||||
Save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ToFilePath(FilenameService fileNames)
|
|
||||||
=> fileNames.UiConfigFile;
|
|
||||||
|
|
||||||
public void Save()
|
|
||||||
=> _saveService.DelaySave(this);
|
|
||||||
|
|
||||||
public void Save(StreamWriter writer)
|
|
||||||
{
|
|
||||||
using var j = new JsonTextWriter(writer);
|
|
||||||
j.Formatting = Formatting.Indented;
|
|
||||||
j.WriteStartObject();
|
|
||||||
j.WritePropertyName("Version");
|
|
||||||
j.WriteValue(CurrentVersion);
|
|
||||||
j.WritePropertyName("CollectionsTab");
|
j.WritePropertyName("CollectionsTab");
|
||||||
j.WriteStartObject();
|
j.WriteStartObject();
|
||||||
j.WritePropertyName("Mode");
|
j.WritePropertyName("Mode");
|
||||||
j.WriteValue(CollectionTabScale.Mode.ToString());
|
j.WriteValue(CollectionsTabScale.Mode.ToString());
|
||||||
j.WritePropertyName("Width");
|
j.WritePropertyName("Width");
|
||||||
j.WriteValue(CollectionTabScale.Width);
|
j.WriteValue(CollectionsTabScale.Width);
|
||||||
j.WriteEndObject();
|
j.WriteEndObject();
|
||||||
j.WritePropertyName("ModsTab");
|
j.WritePropertyName("ModsTab");
|
||||||
j.WriteStartObject();
|
j.WriteStartObject();
|
||||||
|
|
@ -76,33 +30,27 @@ public class UiConfig : ISavable, IService
|
||||||
j.WritePropertyName("Width");
|
j.WritePropertyName("Width");
|
||||||
j.WriteValue(ModTabScale.Width);
|
j.WriteValue(ModTabScale.Width);
|
||||||
j.WriteEndObject();
|
j.WriteEndObject();
|
||||||
j.WriteEndObject();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Load()
|
protected override void LoadData(JObject j)
|
||||||
{
|
{
|
||||||
if (!File.Exists(_saveService.FileNames.UiConfigFile))
|
if (j["CollectionsTab"] is JObject collections)
|
||||||
return;
|
_collectionsTabScale = new TwoPanelWidth(collections["Width"].ValueOr(float.NaN),
|
||||||
|
collections["Mode"].TextEnum(ScalingMode.Percentage));
|
||||||
|
|
||||||
try
|
if (j["ModsTab"] is JObject mods)
|
||||||
{
|
_modTabScale = new TwoPanelWidth(mods["Width"].ValueOr(float.NaN), mods["Mode"].TextEnum(ScalingMode.Percentage));
|
||||||
var text = File.ReadAllText(_saveService.FileNames.UiConfigFile);
|
|
||||||
var jObj = JObject.Parse(text);
|
|
||||||
if (jObj["Version"]?.Value<int>() is not CurrentVersion)
|
|
||||||
throw new Exception("Unsupported version.");
|
|
||||||
|
|
||||||
if (jObj["CollectionsTab"] is JObject collections)
|
|
||||||
_collectionsTabScale = new TwoPanelWidth(collections["Width"].ValueOr(float.NaN),
|
|
||||||
collections["Mode"].TextEnum(ScalingMode.Percentage));
|
|
||||||
|
|
||||||
if (jObj["ModsTab"] is JObject mods)
|
|
||||||
_modTabScale = new TwoPanelWidth(mods["Width"].ValueOr(float.NaN), mods["Mode"].TextEnum(ScalingMode.Percentage));
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Penumbra.Messager.NotificationMessage(ex,
|
|
||||||
"Error reading UI Configuration, reverting to default.",
|
|
||||||
"Error reading UI Configuration", NotificationType.Error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int CurrentVersion
|
||||||
|
=> 1;
|
||||||
|
|
||||||
|
public override string ToFilePath(FilenameService fileNames)
|
||||||
|
=> fileNames.UiConfigFile;
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private TwoPanelWidth _collectionsTabScale = new(0.25f, ScalingMode.Percentage);
|
||||||
|
|
||||||
|
[ConfigProperty]
|
||||||
|
private TwoPanelWidth _modTabScale = new(0.3f, ScalingMode.Percentage);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ using Penumbra.Interop.Services;
|
||||||
using Penumbra.Mods.Editor;
|
using Penumbra.Mods.Editor;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.Mods.Settings;
|
using Penumbra.Mods.Settings;
|
||||||
using Penumbra.UI;
|
|
||||||
using Penumbra.UI.Classes;
|
using Penumbra.UI.Classes;
|
||||||
using Penumbra.UI.ResourceWatcher;
|
using Penumbra.UI.ResourceWatcher;
|
||||||
using Penumbra.UI.Tabs;
|
using Penumbra.UI.Tabs;
|
||||||
|
|
@ -126,8 +125,8 @@ public class ConfigMigrationService(SaveService saveService, BackupService backu
|
||||||
_data["ResourceWatcherRecordTypes"]?.ToObject<RecordType>() ?? _config.Ephemeral.ResourceWatcherRecordTypes;
|
_data["ResourceWatcherRecordTypes"]?.ToObject<RecordType>() ?? _config.Ephemeral.ResourceWatcherRecordTypes;
|
||||||
_config.Ephemeral.CollectionPanel = _data["CollectionPanel"]?.ToObject<CollectionPanelMode>() ?? _config.Ephemeral.CollectionPanel;
|
_config.Ephemeral.CollectionPanel = _data["CollectionPanel"]?.ToObject<CollectionPanelMode>() ?? _config.Ephemeral.CollectionPanel;
|
||||||
_config.Ephemeral.SelectedTab = _data["SelectedTab"]?.ToObject<TabType>() ?? _config.Ephemeral.SelectedTab;
|
_config.Ephemeral.SelectedTab = _data["SelectedTab"]?.ToObject<TabType>() ?? _config.Ephemeral.SelectedTab;
|
||||||
_config.Ephemeral.ChangedItemFilter = _data["ChangedItemFilter"]?.ToObject<ChangedItemIconFlag>()
|
_config.Filters.ChangedItemTypeFilter = _data["ChangedItemFilter"]?.ToObject<ChangedItemIconFlag>()
|
||||||
?? _config.Ephemeral.ChangedItemFilter;
|
?? _config.Filters.ChangedItemTypeFilter;
|
||||||
_config.Ephemeral.FixMainWindow = _data["FixMainWindow"]?.ToObject<bool>() ?? _config.Ephemeral.FixMainWindow;
|
_config.Ephemeral.FixMainWindow = _data["FixMainWindow"]?.ToObject<bool>() ?? _config.Ephemeral.FixMainWindow;
|
||||||
_config.Ephemeral.Save();
|
_config.Ephemeral.Save();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ public sealed class FilenameService(IDalamudPluginInterface pi) : BaseFilePathPr
|
||||||
public readonly string LocalDataDirectory = Path.Combine(pi.ConfigDirectory.FullName, "mod_data");
|
public readonly string LocalDataDirectory = Path.Combine(pi.ConfigDirectory.FullName, "mod_data");
|
||||||
public readonly string EphemeralConfigFile = Path.Combine(pi.ConfigDirectory.FullName, "ephemeral_config.json");
|
public readonly string EphemeralConfigFile = Path.Combine(pi.ConfigDirectory.FullName, "ephemeral_config.json");
|
||||||
public readonly string UiConfigFile = Path.Combine(pi.ConfigDirectory.FullName, "ui_config.json");
|
public readonly string UiConfigFile = Path.Combine(pi.ConfigDirectory.FullName, "ui_config.json");
|
||||||
|
public readonly string FilterFile = Path.Combine(pi.ConfigDirectory.FullName, "filters.json");
|
||||||
public readonly string OldFilesystemFile = Path.Combine(pi.ConfigDirectory.FullName, "sort_order.json");
|
public readonly string OldFilesystemFile = Path.Combine(pi.ConfigDirectory.FullName, "sort_order.json");
|
||||||
public readonly string ActiveCollectionsFile = Path.Combine(pi.ConfigDirectory.FullName, "active_collections.json");
|
public readonly string ActiveCollectionsFile = Path.Combine(pi.ConfigDirectory.FullName, "active_collections.json");
|
||||||
public readonly string PredefinedTagFile = Path.Combine(pi.ConfigDirectory.FullName, "predefined_tags.json");
|
public readonly string PredefinedTagFile = Path.Combine(pi.ConfigDirectory.FullName, "predefined_tags.json");
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,9 @@ public class ResourceTreeViewer(
|
||||||
private readonly Dictionary<nint, NodeVisibility> _filterCache = [];
|
private readonly Dictionary<nint, NodeVisibility> _filterCache = [];
|
||||||
private readonly Dictionary<FullPath, IWritable?> _writableCache = [];
|
private readonly Dictionary<FullPath, IWritable?> _writableCache = [];
|
||||||
|
|
||||||
private TreeCategory _categoryFilter = AllCategories;
|
private TreeCategory _categoryFilter = AllCategories;
|
||||||
private ChangedItemIconFlag _typeFilter = ChangedItemFlagExtensions.AllFlags;
|
|
||||||
private string _nameFilter = string.Empty;
|
private string _note = string.Empty;
|
||||||
private string _nodeFilter = string.Empty;
|
|
||||||
private string _note = string.Empty;
|
|
||||||
|
|
||||||
private Task<ResourceTree[]>? _task;
|
private Task<ResourceTree[]>? _task;
|
||||||
|
|
||||||
|
|
@ -73,7 +71,7 @@ public class ResourceTreeViewer(
|
||||||
foreach (var (index, tree) in _task.Result.Index())
|
foreach (var (index, tree) in _task.Result.Index())
|
||||||
{
|
{
|
||||||
var category = Classify(tree);
|
var category = Classify(tree);
|
||||||
if (!_categoryFilter.HasFlag(category) || !tree.Name.Contains(_nameFilter, StringComparison.OrdinalIgnoreCase))
|
if (!_categoryFilter.HasFlag(category) || !tree.Name.Contains(config.Filters.OnScreenCharacterFilter, StringComparison.OrdinalIgnoreCase))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
using (ImGuiColor.Text.Push(CategoryColor(category).Value()))
|
using (ImGuiColor.Text.Push(CategoryColor(category).Value()))
|
||||||
|
|
@ -198,15 +196,31 @@ public class ResourceTreeViewer(
|
||||||
Im.Cursor.Y -= yOffset;
|
Im.Cursor.Y -= yOffset;
|
||||||
using (Im.Child.Begin("##typeFilter"u8, new Vector2(Im.ContentRegion.Available.X, ChangedItemDrawer.TypeFilterIconSize.Y)))
|
using (Im.Child.Begin("##typeFilter"u8, new Vector2(Im.ContentRegion.Available.X, ChangedItemDrawer.TypeFilterIconSize.Y)))
|
||||||
{
|
{
|
||||||
filterChanged |= changedItemDrawer.DrawTypeFilter(ref _typeFilter);
|
if (changedItemDrawer.DrawTypeFilter(config.Filters.OnScreenTypeFilter, out var newTypeFilter))
|
||||||
|
{
|
||||||
|
filterChanged = true;
|
||||||
|
config.Filters.OnScreenTypeFilter = newTypeFilter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var fieldWidth = (Im.ContentRegion.Available.X - checkSpacing * 2.0f - Im.Style.FrameHeightWithSpacing) / 2.0f;
|
var fieldWidth = (Im.ContentRegion.Available.X - checkSpacing * 2.0f - Im.Style.FrameHeightWithSpacing) / 2.0f;
|
||||||
Im.Item.SetNextWidth(fieldWidth);
|
Im.Item.SetNextWidth(fieldWidth);
|
||||||
filterChanged |= Im.Input.Text("##TreeNameFilter"u8, ref _nameFilter, "Filter by Character/Entity Name..."u8);
|
var filter = config.Filters.OnScreenCharacterFilter;
|
||||||
|
if (Im.Input.Text("##TreeNameFilter"u8, ref filter, "Filter by Character/Entity Name..."u8))
|
||||||
|
{
|
||||||
|
filterChanged = true;
|
||||||
|
config.Filters.OnScreenCharacterFilter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
Im.Line.Same(0, checkSpacing);
|
Im.Line.Same(0, checkSpacing);
|
||||||
Im.Item.SetNextWidth(fieldWidth);
|
Im.Item.SetNextWidth(fieldWidth);
|
||||||
filterChanged |= Im.Input.Text("##NodeFilter"u8, ref _nodeFilter, "Filter by Item/Part Name or Path..."u8);
|
filter = config.Filters.OnScreenItemFilter;
|
||||||
|
if (Im.Input.Text("##NodeFilter"u8, ref filter, "Filter by Item/Part Name or Path..."u8))
|
||||||
|
{
|
||||||
|
filterChanged = true;
|
||||||
|
config.Filters.OnScreenItemFilter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
Im.Line.Same(0, checkSpacing);
|
Im.Line.Same(0, checkSpacing);
|
||||||
incognito.DrawToggle(Im.Style.FrameHeightWithSpacing);
|
incognito.DrawToggle(Im.Style.FrameHeightWithSpacing);
|
||||||
|
|
||||||
|
|
@ -353,7 +367,9 @@ public class ResourceTreeViewer(
|
||||||
if (hasMod && Im.Item.RightClicked() && Im.Io.KeyControl)
|
if (hasMod && Im.Item.RightClicked() && Im.Io.KeyControl)
|
||||||
communicator.SelectTab.Invoke(new SelectTab.Arguments(TabType.Mods, mod));
|
communicator.SelectTab.Invoke(new SelectTab.Arguments(TabType.Mods, mod));
|
||||||
|
|
||||||
Im.Tooltip.OnHover(default, $"{resourceNode.FullPath.ToPath()}\n\nClick to copy to clipboard.{(hasMod ? "\nControl + Right-Click to jump to mod." : string.Empty)}{GetAdditionalDataSuffix(resourceNode.AdditionalData)}", true);
|
Im.Tooltip.OnHover(default,
|
||||||
|
$"{resourceNode.FullPath.ToPath()}\n\nClick to copy to clipboard.{(hasMod ? "\nControl + Right-Click to jump to mod." : string.Empty)}{GetAdditionalDataSuffix(resourceNode.AdditionalData)}",
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -411,16 +427,17 @@ public class ResourceTreeViewer(
|
||||||
|
|
||||||
bool MatchesFilter(ResourceNode node, ChangedItemIconFlag filterIcon)
|
bool MatchesFilter(ResourceNode node, ChangedItemIconFlag filterIcon)
|
||||||
{
|
{
|
||||||
if (!_typeFilter.HasFlag(filterIcon))
|
if (!config.Filters.OnScreenTypeFilter.HasFlag(filterIcon))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (_nodeFilter.Length == 0)
|
if (config.Filters.OnScreenItemFilter.Length == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return node.Name != null && node.Name.Contains(_nodeFilter, StringComparison.OrdinalIgnoreCase)
|
return node.Name != null && node.Name.Contains(config.Filters.OnScreenItemFilter, StringComparison.OrdinalIgnoreCase)
|
||||||
|| node.FullPath.FullName.Contains(_nodeFilter, StringComparison.OrdinalIgnoreCase)
|
|| node.FullPath.FullName.Contains(config.Filters.OnScreenItemFilter, StringComparison.OrdinalIgnoreCase)
|
||||||
|| node.FullPath.InternalName.ToString().Contains(_nodeFilter, StringComparison.OrdinalIgnoreCase)
|
|| node.FullPath.InternalName.ToString().Contains(config.Filters.OnScreenItemFilter, StringComparison.OrdinalIgnoreCase)
|
||||||
|| Array.Exists(node.PossibleGamePaths, path => path.Path.ToString().Contains(_nodeFilter, StringComparison.OrdinalIgnoreCase));
|
|| Array.Exists(node.PossibleGamePaths,
|
||||||
|
path => path.Path.ToString().Contains(config.Filters.OnScreenItemFilter, StringComparison.OrdinalIgnoreCase));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawActions(ResourceNode resourceNode, Vector2 buttonSize)
|
void DrawActions(ResourceNode resourceNode, Vector2 buttonSize)
|
||||||
|
|
@ -489,7 +506,9 @@ public class ResourceTreeViewer(
|
||||||
|
|
||||||
private static void HeaderInteraction(ResourceTree tree)
|
private static void HeaderInteraction(ResourceTree tree)
|
||||||
{
|
{
|
||||||
Im.Tooltip.OnHover(default, $"Object Index: {tree.GameObjectIndex}\nObject Address: 0x{tree.GameObjectAddress:X16}\nDraw Object Address: 0x{tree.DrawObjectAddress:X16}", true, Im.Font.Mono);
|
Im.Tooltip.OnHover(default,
|
||||||
|
$"Object Index: {tree.GameObjectIndex}\nObject Address: 0x{tree.GameObjectAddress:X16}\nDraw Object Address: 0x{tree.DrawObjectAddress:X16}",
|
||||||
|
true, Im.Font.Mono);
|
||||||
if (tree.GameObjectAddress == nint.Zero)
|
if (tree.GameObjectAddress == nint.Zero)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -513,7 +532,8 @@ public class ResourceTreeViewer(
|
||||||
|
|
||||||
private static void ResourceInteraction(ResourceNode node)
|
private static void ResourceInteraction(ResourceNode node)
|
||||||
{
|
{
|
||||||
Im.Tooltip.OnHover(default, $"Resource Type: {node.Type}\nObject Address: 0x{node.ObjectAddress:X16}\nResource Handle: 0x{node.ResourceHandle:X16}\nLength: 0x{node.Length:X16}",
|
Im.Tooltip.OnHover(default,
|
||||||
|
$"Resource Type: {node.Type}\nObject Address: 0x{node.ObjectAddress:X16}\nResource Handle: 0x{node.ResourceHandle:X16}\nLength: 0x{node.Length:X16}",
|
||||||
true, Im.Font.Mono);
|
true, Im.Font.Mono);
|
||||||
|
|
||||||
if (node.ResourceHandle == nint.Zero)
|
if (node.ResourceHandle == nint.Zero)
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ namespace Penumbra.UI.Classes;
|
||||||
|
|
||||||
public class ChangedItemDrawer : IDisposable, IUiService
|
public class ChangedItemDrawer : IDisposable, IUiService
|
||||||
{
|
{
|
||||||
private static readonly string[] LowerNames = ChangedItemFlagExtensions.Order.Select(f => f.ToDescription().ToString().ToLowerInvariant()).ToArray();
|
private static readonly string[] LowerNames =
|
||||||
|
ChangedItemFlagExtensions.Order.Select(f => f.ToDescription().ToString().ToLowerInvariant()).ToArray();
|
||||||
|
|
||||||
public static bool TryParseIndex(ReadOnlySpan<char> input, out ChangedItemIconFlag slot)
|
public static bool TryParseIndex(ReadOnlySpan<char> input, out ChangedItemIconFlag slot)
|
||||||
{
|
{
|
||||||
|
|
@ -83,9 +84,15 @@ public class ChangedItemDrawer : IDisposable, IUiService
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Check if a changed item should be drawn based on its category. </summary>
|
/// <summary> Check if a changed item should be drawn based on its category. </summary>
|
||||||
public bool FilterChangedItem(string name, IIdentifiedObjectData data, string filter)
|
public bool FilterChangedItemGlobal(string name, IIdentifiedObjectData data, string filter)
|
||||||
=> (_config.Ephemeral.ChangedItemFilter == ChangedItemFlagExtensions.AllFlags
|
=> (_config.Filters.ChangedItemTypeFilter == ChangedItemFlagExtensions.AllFlags
|
||||||
|| _config.Ephemeral.ChangedItemFilter.HasFlag(data.GetIcon().ToFlag()))
|
|| _config.Filters.ChangedItemTypeFilter.HasFlag(data.GetIcon().ToFlag()))
|
||||||
|
&& (filter.Length is 0 || !data.IsFilteredOut(name, filter));
|
||||||
|
|
||||||
|
/// <summary> Check if a changed item should be drawn based on its category. </summary>
|
||||||
|
public bool FilterChangedItemMod(string name, IIdentifiedObjectData data, string filter)
|
||||||
|
=> (_config.Filters.ModChangedItemTypeFilter == ChangedItemFlagExtensions.AllFlags
|
||||||
|
|| _config.Filters.ModChangedItemTypeFilter.HasFlag(data.GetIcon().ToFlag()))
|
||||||
&& (filter.Length is 0 || !data.IsFilteredOut(name, filter));
|
&& (filter.Length is 0 || !data.IsFilteredOut(name, filter));
|
||||||
|
|
||||||
/// <summary> Draw the icon corresponding to the category of a changed item. </summary>
|
/// <summary> Draw the icon corresponding to the category of a changed item. </summary>
|
||||||
|
|
@ -160,31 +167,33 @@ public class ChangedItemDrawer : IDisposable, IUiService
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Draw a header line with the different icon types to filter them. </summary>
|
/// <summary> Draw a header line with the different icon types to filter them. </summary>
|
||||||
public void DrawTypeFilter()
|
public void DrawTypeFilter(bool global)
|
||||||
{
|
{
|
||||||
if (_config.HideChangedItemFilters)
|
if (_config.HideChangedItemFilters)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var typeFilter = _config.Ephemeral.ChangedItemFilter;
|
var typeFilter = global ? _config.Filters.ChangedItemTypeFilter : _config.Filters.ModChangedItemTypeFilter;
|
||||||
if (DrawTypeFilter(ref typeFilter))
|
if (DrawTypeFilter(typeFilter, out typeFilter))
|
||||||
{
|
{
|
||||||
_config.Ephemeral.ChangedItemFilter = typeFilter;
|
if (global)
|
||||||
_config.Ephemeral.Save();
|
_config.Filters.ChangedItemTypeFilter = typeFilter;
|
||||||
|
else
|
||||||
|
_config.Filters.ModChangedItemTypeFilter = typeFilter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Draw a header line with the different icon types to filter them. </summary>
|
/// <summary> Draw a header line with the different icon types to filter them. </summary>
|
||||||
public bool DrawTypeFilter(ref ChangedItemIconFlag typeFilter)
|
public bool DrawTypeFilter(ChangedItemIconFlag typeFilter, out ChangedItemIconFlag newTypeFilter)
|
||||||
{
|
{
|
||||||
var ret = false;
|
var ret = false;
|
||||||
using var _ = Im.Id.Push("ChangedItemIconFilter"u8);
|
using var _ = Im.Id.Push("ChangedItemIconFilter"u8);
|
||||||
var size = TypeFilterIconSize;
|
var size = TypeFilterIconSize;
|
||||||
using var style = ImStyleDouble.ItemSpacing.Push(Vector2.Zero);
|
using var style = ImStyleDouble.ItemSpacing.Push(Vector2.Zero);
|
||||||
|
newTypeFilter = typeFilter;
|
||||||
|
|
||||||
foreach (var iconType in ChangedItemFlagExtensions.Order)
|
foreach (var iconType in ChangedItemFlagExtensions.Order)
|
||||||
{
|
{
|
||||||
ret |= DrawIcon(iconType, ref typeFilter);
|
ret |= DrawIcon(iconType, ref newTypeFilter);
|
||||||
Im.Line.Same();
|
Im.Line.Same();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -198,30 +207,30 @@ public class ChangedItemDrawer : IDisposable, IUiService
|
||||||
});
|
});
|
||||||
if (Im.Item.Clicked())
|
if (Im.Item.Clicked())
|
||||||
{
|
{
|
||||||
typeFilter = typeFilter is ChangedItemFlagExtensions.AllFlags ? 0 : ChangedItemFlagExtensions.AllFlags;
|
newTypeFilter = typeFilter is ChangedItemFlagExtensions.AllFlags ? 0 : ChangedItemFlagExtensions.AllFlags;
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
bool DrawIcon(ChangedItemIconFlag type, ref ChangedItemIconFlag typeFilter)
|
bool DrawIcon(ChangedItemIconFlag type, ref ChangedItemIconFlag filter)
|
||||||
{
|
{
|
||||||
var localRet = false;
|
var localRet = false;
|
||||||
var icon = _icons[type];
|
var icon = _icons[type];
|
||||||
var flag = typeFilter.HasFlag(type);
|
var flag = filter.HasFlag(type);
|
||||||
Im.Image.Draw(icon.Id(), size, Vector2.Zero, Vector2.One, flag ? Vector4.One : new Vector4(0.6f, 0.3f, 0.3f, 1f));
|
Im.Image.Draw(icon.Id(), size, Vector2.Zero, Vector2.One, flag ? Vector4.One : new Vector4(0.6f, 0.3f, 0.3f, 1f));
|
||||||
if (Im.Item.Clicked())
|
if (Im.Item.Clicked())
|
||||||
{
|
{
|
||||||
typeFilter = flag ? typeFilter & ~type : typeFilter | type;
|
filter = flag ? filter & ~type : filter | type;
|
||||||
localRet = true;
|
localRet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
using var popup = Im.Popup.BeginContextItem($"{type}");
|
using var popup = Im.Popup.BeginContextItem($"{type}");
|
||||||
if (popup)
|
if (popup)
|
||||||
if (Im.Menu.Item("Enable Only This"u8))
|
if (Im.Menu.Item("Enable Only This"u8))
|
||||||
{
|
{
|
||||||
typeFilter = type;
|
filter = type;
|
||||||
localRet = true;
|
localRet = true;
|
||||||
Im.Popup.CloseCurrent();
|
Im.Popup.CloseCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ public static class ChangedItemFlagExtensions
|
||||||
|
|
||||||
public const ChangedItemIconFlag AllFlags = (ChangedItemIconFlag)0x01FFFF;
|
public const ChangedItemIconFlag AllFlags = (ChangedItemIconFlag)0x01FFFF;
|
||||||
public static readonly int NumCategories = Order.Count;
|
public static readonly int NumCategories = Order.Count;
|
||||||
public const ChangedItemIconFlag DefaultFlags = AllFlags & ~ChangedItemIconFlag.Offhand;
|
public const ChangedItemIconFlag DefaultFlags = AllFlags;
|
||||||
|
|
||||||
public static ReadOnlySpan<byte> ToDescription(this ChangedItemIconFlag iconFlag)
|
public static ReadOnlySpan<byte> ToDescription(this ChangedItemIconFlag iconFlag)
|
||||||
=> iconFlag switch
|
=> iconFlag switch
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,12 @@ namespace Penumbra.UI.CollectionTab;
|
||||||
|
|
||||||
public sealed class CollectionFilter : TextFilterBase<CollectionSelector.Entry>, IUiService
|
public sealed class CollectionFilter : TextFilterBase<CollectionSelector.Entry>, IUiService
|
||||||
{
|
{
|
||||||
|
public CollectionFilter(FilterConfig filterConfig)
|
||||||
|
{
|
||||||
|
Set(filterConfig.CollectionFilter);
|
||||||
|
FilterChanged += () => filterConfig.CollectionFilter = Text;
|
||||||
|
}
|
||||||
|
|
||||||
public override bool WouldBeVisible(in CollectionSelector.Entry item, int globalIndex)
|
public override bool WouldBeVisible(in CollectionSelector.Entry item, int globalIndex)
|
||||||
=> base.WouldBeVisible(in item, globalIndex) || WouldBeVisible(item.AnonymousName.Utf16);
|
=> base.WouldBeVisible(in item, globalIndex) || WouldBeVisible(item.AnonymousName.Utf16);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,24 +11,12 @@ using Penumbra.UI.Classes;
|
||||||
|
|
||||||
namespace Penumbra.UI.MainWindow;
|
namespace Penumbra.UI.MainWindow;
|
||||||
|
|
||||||
public class UiState : ISavable, IService
|
|
||||||
{
|
|
||||||
public string ChangedItemTabNameFilter = string.Empty;
|
|
||||||
public string ChangedItemTabModFilter = string.Empty;
|
|
||||||
public ChangedItemIconFlag ChangedItemTabCategoryFilter = ChangedItemFlagExtensions.DefaultFlags;
|
|
||||||
|
|
||||||
public string ToFilePath(FilenameService fileNames)
|
|
||||||
=> "uiState";
|
|
||||||
|
|
||||||
public void Save(StreamWriter writer)
|
|
||||||
{ }
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class ChangedItemsTab(
|
public sealed class ChangedItemsTab(
|
||||||
CollectionManager collectionManager,
|
CollectionManager collectionManager,
|
||||||
CollectionSelectHeader collectionHeader,
|
CollectionSelectHeader collectionHeader,
|
||||||
ChangedItemDrawer drawer,
|
ChangedItemDrawer drawer,
|
||||||
CommunicatorService communicator)
|
CommunicatorService communicator,
|
||||||
|
FilterConfig filterConfig)
|
||||||
: ITab<TabType>
|
: ITab<TabType>
|
||||||
{
|
{
|
||||||
public ReadOnlySpan<byte> Label
|
public ReadOnlySpan<byte> Label
|
||||||
|
|
@ -39,14 +27,14 @@ public sealed class ChangedItemsTab(
|
||||||
|
|
||||||
private Vector2 _buttonSize;
|
private Vector2 _buttonSize;
|
||||||
|
|
||||||
private readonly ChangedItemFilter _filter = new(drawer, new UiState());
|
private readonly ChangedItemFilter _filter = new(drawer, filterConfig);
|
||||||
|
|
||||||
private sealed class ChangedItemFilter(ChangedItemDrawer drawer, UiState uiState) : IFilter<Item>
|
private sealed class ChangedItemFilter(ChangedItemDrawer drawer, FilterConfig filterConfig) : IFilter<Item>
|
||||||
{
|
{
|
||||||
public bool WouldBeVisible(in Item item, int globalIndex)
|
public bool WouldBeVisible(in Item item, int globalIndex)
|
||||||
=> drawer.FilterChangedItem(item.Name, item.Data, uiState.ChangedItemTabNameFilter)
|
=> drawer.FilterChangedItemGlobal(item.Name, item.Data, filterConfig.ChangedItemItemFilter)
|
||||||
&& (uiState.ChangedItemTabModFilter.Length is 0
|
&& (filterConfig.ChangedItemModFilter.Length is 0
|
||||||
|| item.Mods.Any(m => m.Name.Contains(uiState.ChangedItemTabModFilter, StringComparison.OrdinalIgnoreCase)));
|
|| item.Mods.Any(m => m.Name.Contains(filterConfig.ChangedItemModFilter, StringComparison.OrdinalIgnoreCase)));
|
||||||
|
|
||||||
public event Action? FilterChanged;
|
public event Action? FilterChanged;
|
||||||
|
|
||||||
|
|
@ -56,29 +44,36 @@ public sealed class ChangedItemsTab(
|
||||||
- 450 * Im.Style.GlobalScale
|
- 450 * Im.Style.GlobalScale
|
||||||
- Im.Style.ItemSpacing.X;
|
- Im.Style.ItemSpacing.X;
|
||||||
Im.Item.SetNextWidth(450 * Im.Style.GlobalScale);
|
Im.Item.SetNextWidth(450 * Im.Style.GlobalScale);
|
||||||
var ret = Im.Input.Text("##changedItemsFilter"u8, ref uiState.ChangedItemTabNameFilter, "Filter Item..."u8);
|
var filter = filterConfig.ChangedItemItemFilter;
|
||||||
|
var ret = Im.Input.Text("##changedItemsFilter"u8, ref filter, "Filter Item..."u8);
|
||||||
|
if (ret)
|
||||||
|
filterConfig.ChangedItemItemFilter = filter;
|
||||||
Im.Line.Same();
|
Im.Line.Same();
|
||||||
Im.Item.SetNextWidth(varWidth);
|
Im.Item.SetNextWidth(varWidth);
|
||||||
ret |= Im.Input.Text("##changedItemsModFilter"u8, ref uiState.ChangedItemTabModFilter, "Filter Mods..."u8);
|
filter = filterConfig.ChangedItemModFilter;
|
||||||
if (!ret)
|
if (Im.Input.Text("##changedItemsModFilter"u8, ref filter, "Filter Mods..."u8))
|
||||||
return false;
|
{
|
||||||
|
ret = true;
|
||||||
|
filterConfig.ChangedItemModFilter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
FilterChanged?.Invoke();
|
if (ret)
|
||||||
return true;
|
FilterChanged?.Invoke();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
uiState.ChangedItemTabModFilter = string.Empty;
|
filterConfig.ChangedItemModFilter = string.Empty;
|
||||||
uiState.ChangedItemTabNameFilter = string.Empty;
|
filterConfig.ChangedItemItemFilter = string.Empty;
|
||||||
uiState.ChangedItemTabCategoryFilter = ChangedItemFlagExtensions.DefaultFlags;
|
filterConfig.ChangedItemTypeFilter = ChangedItemFlagExtensions.DefaultFlags;
|
||||||
FilterChanged?.Invoke();
|
FilterChanged?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsEmpty
|
public bool IsEmpty
|
||||||
=> uiState.ChangedItemTabModFilter.Length is 0
|
=> filterConfig.ChangedItemModFilter.Length is 0
|
||||||
&& uiState.ChangedItemTabNameFilter.Length is 0
|
&& filterConfig.ChangedItemItemFilter.Length is 0
|
||||||
&& uiState.ChangedItemTabCategoryFilter is ChangedItemFlagExtensions.DefaultFlags;
|
&& filterConfig.ChangedItemTypeFilter is ChangedItemFlagExtensions.DefaultFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly record struct Item(string Label, IIdentifiedObjectData Data, SingleArray<IMod> Mods)
|
private readonly record struct Item(string Label, IIdentifiedObjectData Data, SingleArray<IMod> Mods)
|
||||||
|
|
@ -124,7 +119,7 @@ public sealed class ChangedItemsTab(
|
||||||
public void DrawContent()
|
public void DrawContent()
|
||||||
{
|
{
|
||||||
collectionHeader.Draw(true);
|
collectionHeader.Draw(true);
|
||||||
drawer.DrawTypeFilter();
|
drawer.DrawTypeFilter(true);
|
||||||
_filter.DrawFilter("##Filter"u8, Im.ContentRegion.Available);
|
_filter.DrawFilter("##Filter"u8, Im.ContentRegion.Available);
|
||||||
using var child = Im.Child.Begin("##changedItemsChild"u8, Im.ContentRegion.Available);
|
using var child = Im.Child.Begin("##changedItemsChild"u8, Im.ContentRegion.Available);
|
||||||
if (!child)
|
if (!child)
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ namespace Penumbra.UI.MainWindow;
|
||||||
public sealed class EffectiveTab(
|
public sealed class EffectiveTab(
|
||||||
CollectionManager collectionManager,
|
CollectionManager collectionManager,
|
||||||
CollectionSelectHeader collectionHeader,
|
CollectionSelectHeader collectionHeader,
|
||||||
CommunicatorService communicatorService)
|
CommunicatorService communicatorService,
|
||||||
|
FilterConfig filterConfig)
|
||||||
: ITab<TabType>
|
: ITab<TabType>
|
||||||
{
|
{
|
||||||
public ReadOnlySpan<byte> Label
|
public ReadOnlySpan<byte> Label
|
||||||
|
|
@ -31,7 +32,7 @@ public sealed class EffectiveTab(
|
||||||
public TabType Identifier
|
public TabType Identifier
|
||||||
=> TabType.EffectiveChanges;
|
=> TabType.EffectiveChanges;
|
||||||
|
|
||||||
private readonly PairFilter<Item> _filter = new(new GamePathFilter(), new FullPathFilter());
|
private readonly PairFilter<Item> _filter = new(new GamePathFilter(filterConfig), new FullPathFilter(filterConfig));
|
||||||
|
|
||||||
private sealed class Cache : BasicFilterCache<Item>, IPanel
|
private sealed class Cache : BasicFilterCache<Item>, IPanel
|
||||||
{
|
{
|
||||||
|
|
@ -111,7 +112,6 @@ public sealed class EffectiveTab(
|
||||||
Filter.Filter1.DrawFilter("Filter game path..."u8, new Vector2(_gamePathSize + Im.Style.CellPadding.X, Im.Style.FrameHeight));
|
Filter.Filter1.DrawFilter("Filter game path..."u8, new Vector2(_gamePathSize + Im.Style.CellPadding.X, Im.Style.FrameHeight));
|
||||||
Im.Line.Same(0, _arrowSize + 2 * Im.Style.CellPadding.X);
|
Im.Line.Same(0, _arrowSize + 2 * Im.Style.CellPadding.X);
|
||||||
Filter.Filter2.DrawFilter("Filter file path..."u8, Im.ContentRegion.Available with { Y = Im.Style.FrameHeight });
|
Filter.Filter2.DrawFilter("Filter file path..."u8, Im.ContentRegion.Available with { Y = Im.Style.FrameHeight });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawTable()
|
private void DrawTable()
|
||||||
|
|
@ -143,12 +143,24 @@ public sealed class EffectiveTab(
|
||||||
|
|
||||||
private sealed class GamePathFilter : RegexFilterBase<Item>
|
private sealed class GamePathFilter : RegexFilterBase<Item>
|
||||||
{
|
{
|
||||||
|
public GamePathFilter(FilterConfig config)
|
||||||
|
{
|
||||||
|
Set(config.EffectiveChangesGamePathFilter);
|
||||||
|
FilterChanged += () => config.EffectiveChangesGamePathFilter = Text;
|
||||||
|
}
|
||||||
|
|
||||||
protected override string ToFilterString(in Item item, int globalIndex)
|
protected override string ToFilterString(in Item item, int globalIndex)
|
||||||
=> item.GamePath.Utf16;
|
=> item.GamePath.Utf16;
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class FullPathFilter : RegexFilterBase<Item>
|
private sealed class FullPathFilter : RegexFilterBase<Item>
|
||||||
{
|
{
|
||||||
|
public FullPathFilter(FilterConfig config)
|
||||||
|
{
|
||||||
|
Set(config.EffectiveChangesFilePathFilter);
|
||||||
|
FilterChanged += () => config.EffectiveChangesFilePathFilter = Text;
|
||||||
|
}
|
||||||
|
|
||||||
protected override string ToFilterString(in Item item, int globalIndex)
|
protected override string ToFilterString(in Item item, int globalIndex)
|
||||||
=> item.FilePath.FullName;
|
=> item.FilePath.FullName;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ public class ModPanelChangedItemsTab(
|
||||||
{
|
{
|
||||||
foreach (var (s, i) in _lastSelected.ChangedItems)
|
foreach (var (s, i) in _lastSelected.ChangedItems)
|
||||||
{
|
{
|
||||||
if (drawer.FilterChangedItem(s, i, string.Empty))
|
if (drawer.FilterChangedItemMod(s, i, string.Empty))
|
||||||
Data.Add(Container.Single(s, i));
|
Data.Add(Container.Single(s, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,7 +124,7 @@ public class ModPanelChangedItemsTab(
|
||||||
if (i is not IdentifiedItem item)
|
if (i is not IdentifiedItem item)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!drawer.FilterChangedItem(s, item, string.Empty))
|
if (!drawer.FilterChangedItemMod(s, item, string.Empty))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tmp.TryGetValue((item.Item.PrimaryId, item.Item.Type), out var p))
|
if (tmp.TryGetValue((item.Item.PrimaryId, item.Item.Type), out var p))
|
||||||
|
|
@ -160,7 +160,7 @@ public class ModPanelChangedItemsTab(
|
||||||
if (i is IdentifiedItem)
|
if (i is IdentifiedItem)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!drawer.FilterChangedItem(s, i, string.Empty))
|
if (!drawer.FilterChangedItemMod(s, i, string.Empty))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
while (sortedTmpIdx < sortedTmp.Length
|
while (sortedTmpIdx < sortedTmp.Length
|
||||||
|
|
@ -221,9 +221,9 @@ public class ModPanelChangedItemsTab(
|
||||||
_id = Im.Id.Current;
|
_id = Im.Id.Current;
|
||||||
_mod = fileSystem.Selection.Selection!.GetValue<Mod>()!;
|
_mod = fileSystem.Selection.Selection!.GetValue<Mod>()!;
|
||||||
var cache = CacheManager.Instance.GetOrCreateCache(_id, () => new ChangedItemsCache());
|
var cache = CacheManager.Instance.GetOrCreateCache(_id, () => new ChangedItemsCache());
|
||||||
drawer.DrawTypeFilter();
|
drawer.DrawTypeFilter(false);
|
||||||
|
|
||||||
cache.Update(_mod, drawer, config.Ephemeral.ChangedItemFilter, config.ChangedItemDisplay);
|
cache.Update(_mod, drawer, config.Filters.ModChangedItemTypeFilter, config.ChangedItemDisplay);
|
||||||
Im.Separator();
|
Im.Separator();
|
||||||
_buttonSize = new Vector2(Im.Style.ItemSpacing.Y + Im.Style.FrameHeight);
|
_buttonSize = new Vector2(Im.Style.ItemSpacing.Y + Im.Style.FrameHeight);
|
||||||
using var style = ImStyleDouble.CellPadding.Push(Vector2.Zero)
|
using var style = ImStyleDouble.CellPadding.Push(Vector2.Zero)
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,25 @@ using static ImSharp.Im;
|
||||||
|
|
||||||
namespace Penumbra.UI.ModsTab.Selector;
|
namespace Penumbra.UI.ModsTab.Selector;
|
||||||
|
|
||||||
public sealed class ModFilter(ModManager modManager, ActiveCollections collections)
|
public sealed class ModFilter : TokenizedFilter<ModFilterTokenType, ModFileSystemCache.ModData, ModFilterToken>,
|
||||||
: TokenizedFilter<ModFilterTokenType, ModFileSystemCache.ModData, ModFilterToken>,
|
IFileSystemFilter<ModFileSystemCache.ModData>
|
||||||
IFileSystemFilter<ModFileSystemCache.ModData>
|
|
||||||
{
|
{
|
||||||
private ModTypeFilter _stateFilter = ModTypeFilterExtensions.UnfilteredStateMods;
|
private ModTypeFilter _stateFilter;
|
||||||
|
private readonly ModManager _modManager;
|
||||||
|
private readonly ActiveCollections _collections;
|
||||||
|
|
||||||
|
public ModFilter(ModManager modManager, ActiveCollections collections, FilterConfig filterConfig)
|
||||||
|
{
|
||||||
|
_modManager = modManager;
|
||||||
|
_collections = collections;
|
||||||
|
_stateFilter = filterConfig.ModTypeFilter;
|
||||||
|
Set(filterConfig.ModFilter);
|
||||||
|
FilterChanged += () =>
|
||||||
|
{
|
||||||
|
filterConfig.ModFilter = Text;
|
||||||
|
filterConfig.ModTypeFilter = StateFilter;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public ModTypeFilter StateFilter
|
public ModTypeFilter StateFilter
|
||||||
=> _stateFilter;
|
=> _stateFilter;
|
||||||
|
|
@ -156,8 +170,8 @@ public sealed class ModFilter(ModManager modManager, ActiveCollections collectio
|
||||||
|
|
||||||
private bool CheckStateFilters(Mod mod)
|
private bool CheckStateFilters(Mod mod)
|
||||||
{
|
{
|
||||||
var (settings, collection) = collections.Current.GetActualSettings(mod.Index);
|
var (settings, collection) = _collections.Current.GetActualSettings(mod.Index);
|
||||||
var isNew = modManager.IsNew(mod);
|
var isNew = _modManager.IsNew(mod);
|
||||||
// Handle mod details.
|
// Handle mod details.
|
||||||
if (CheckFlags(mod.TotalFileCount, ModTypeFilter.HasNoFiles, ModTypeFilter.HasFiles)
|
if (CheckFlags(mod.TotalFileCount, ModTypeFilter.HasNoFiles, ModTypeFilter.HasFiles)
|
||||||
|| CheckFlags(mod.TotalSwapCount, ModTypeFilter.HasNoFileSwaps, ModTypeFilter.HasFileSwaps)
|
|| CheckFlags(mod.TotalSwapCount, ModTypeFilter.HasNoFileSwaps, ModTypeFilter.HasFileSwaps)
|
||||||
|
|
@ -182,7 +196,7 @@ public sealed class ModFilter(ModManager modManager, ActiveCollections collectio
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Inheritance
|
// Handle Inheritance
|
||||||
if (collection == collections.Current)
|
if (collection == _collections.Current)
|
||||||
{
|
{
|
||||||
if (!_stateFilter.HasFlag(ModTypeFilter.Uninherited))
|
if (!_stateFilter.HasFlag(ModTypeFilter.Uninherited))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -213,7 +227,7 @@ public sealed class ModFilter(ModManager modManager, ActiveCollections collectio
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Conflicts can only be relevant if the mod is enabled.
|
// Conflicts can only be relevant if the mod is enabled.
|
||||||
var conflicts = collections.Current.Conflicts(mod);
|
var conflicts = _collections.Current.Conflicts(mod);
|
||||||
if (conflicts.Count > 0)
|
if (conflicts.Count > 0)
|
||||||
{
|
{
|
||||||
if (conflicts.Any(c => !c.Solved))
|
if (conflicts.Any(c => !c.Solved))
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,10 @@ public sealed class ModFileSystemDrawer : FileSystemDrawer<ModFileSystemCache.Mo
|
||||||
public readonly FileDialogService FileService;
|
public readonly FileDialogService FileService;
|
||||||
public readonly TutorialService Tutorial;
|
public readonly TutorialService Tutorial;
|
||||||
public readonly CommunicatorService Communicator;
|
public readonly CommunicatorService Communicator;
|
||||||
public readonly GlobalModImporter GlobalModImporter;
|
|
||||||
|
|
||||||
public ModFileSystemDrawer(ModFileSystem fileSystem, ModManager modManager, CollectionManager collectionManager, Configuration config,
|
public ModFileSystemDrawer(ModFileSystem fileSystem, ModManager modManager, CollectionManager collectionManager, Configuration config,
|
||||||
ModImportManager modImport, FileDialogService fileService, TutorialService tutorial, CommunicatorService communicator,
|
ModImportManager modImport, FileDialogService fileService, TutorialService tutorial, CommunicatorService communicator)
|
||||||
GlobalModImporter globalModImporter)
|
: base(fileSystem, new ModFilter(modManager, collectionManager.Active, config.Filters))
|
||||||
: base(fileSystem, new ModFilter(modManager, collectionManager.Active))
|
|
||||||
{
|
{
|
||||||
ModManager = modManager;
|
ModManager = modManager;
|
||||||
CollectionManager = collectionManager;
|
CollectionManager = collectionManager;
|
||||||
|
|
@ -31,7 +29,6 @@ public sealed class ModFileSystemDrawer : FileSystemDrawer<ModFileSystemCache.Mo
|
||||||
FileService = fileService;
|
FileService = fileService;
|
||||||
Tutorial = tutorial;
|
Tutorial = tutorial;
|
||||||
Communicator = communicator;
|
Communicator = communicator;
|
||||||
GlobalModImporter = globalModImporter;
|
|
||||||
SortMode = Config.SortMode;
|
SortMode = Config.SortMode;
|
||||||
|
|
||||||
MainContext.AddButton(new ClearTemporarySettingsButton(this), 105);
|
MainContext.AddButton(new ClearTemporarySettingsButton(this), 105);
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,15 @@ public enum RecordType : byte
|
||||||
ResourceComplete = 0x10,
|
ResourceComplete = 0x10,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static partial class RecordTypeExtensions
|
||||||
|
{
|
||||||
|
public const RecordType All = RecordType.Request
|
||||||
|
| RecordType.ResourceLoad
|
||||||
|
| RecordType.FileLoad
|
||||||
|
| RecordType.Destruction
|
||||||
|
| RecordType.ResourceComplete;
|
||||||
|
}
|
||||||
|
|
||||||
internal unsafe struct Record()
|
internal unsafe struct Record()
|
||||||
{
|
{
|
||||||
public DateTime Time;
|
public DateTime Time;
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ public sealed class ResourceWatcher : IDisposable, ITab<TabType>
|
||||||
_resources = resources;
|
_resources = resources;
|
||||||
_destructor = destructor;
|
_destructor = destructor;
|
||||||
_loader = loader;
|
_loader = loader;
|
||||||
_table = new ResourceWatcherTable(new ResourceWatcherConfig(), _records);
|
_table = new ResourceWatcherTable(config.Filters, _records);
|
||||||
_resources.ResourceRequested += OnResourceRequested;
|
_resources.ResourceRequested += OnResourceRequested;
|
||||||
_destructor.Subscribe(OnResourceDestroyed, ResourceHandleDestructor.Priority.ResourceWatcher);
|
_destructor.Subscribe(OnResourceDestroyed, ResourceHandleDestructor.Priority.ResourceWatcher);
|
||||||
_loader.ResourceLoaded += OnResourceLoaded;
|
_loader.ResourceLoaded += OnResourceLoaded;
|
||||||
|
|
|
||||||
|
|
@ -9,33 +9,6 @@ using Penumbra.UI.Classes;
|
||||||
|
|
||||||
namespace Penumbra.UI.ResourceWatcher;
|
namespace Penumbra.UI.ResourceWatcher;
|
||||||
|
|
||||||
public class ResourceWatcherConfig
|
|
||||||
{
|
|
||||||
public int Version = 1;
|
|
||||||
public bool Enabled = false;
|
|
||||||
public int MaxEntries = 500;
|
|
||||||
public bool StoreOnlyMatching = true;
|
|
||||||
public bool WriteToLog = false;
|
|
||||||
public string LogFilter = string.Empty;
|
|
||||||
public string PathFilter = string.Empty;
|
|
||||||
public string CollectionFilter = string.Empty;
|
|
||||||
public string ObjectFilter = string.Empty;
|
|
||||||
public string OriginalPathFilter = string.Empty;
|
|
||||||
public string ResourceFilter = string.Empty;
|
|
||||||
public string CrcFilter = string.Empty;
|
|
||||||
public string RefFilter = string.Empty;
|
|
||||||
public string ThreadFilter = string.Empty;
|
|
||||||
public RecordType RecordFilter = Enum.GetValues<RecordType>().Or();
|
|
||||||
public BoolEnum CustomFilter = BoolEnum.True | BoolEnum.False | BoolEnum.Unknown;
|
|
||||||
public BoolEnum SyncFilter = BoolEnum.True | BoolEnum.False | BoolEnum.Unknown;
|
|
||||||
public ResourceCategoryFlag CategoryFilter = ResourceExtensions.AllResourceCategories;
|
|
||||||
public ResourceTypeFlag TypeFilter = ResourceExtensions.AllResourceTypes;
|
|
||||||
public LoadStateFlag LoadStateFilter = Enum.GetValues<LoadStateFlag>().Or();
|
|
||||||
|
|
||||||
public void Save()
|
|
||||||
{ }
|
|
||||||
}
|
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum BoolEnum : byte
|
public enum BoolEnum : byte
|
||||||
{
|
{
|
||||||
|
|
@ -44,6 +17,11 @@ public enum BoolEnum : byte
|
||||||
Unknown = 0x04,
|
Unknown = 0x04,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class BoolEnumExtensions
|
||||||
|
{
|
||||||
|
public const BoolEnum All = BoolEnum.True | BoolEnum.False | BoolEnum.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum LoadStateFlag : byte
|
public enum LoadStateFlag : byte
|
||||||
{
|
{
|
||||||
|
|
@ -55,6 +33,16 @@ public enum LoadStateFlag : byte
|
||||||
None = 0xFF,
|
None = 0xFF,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class LoadStateExtensions
|
||||||
|
{
|
||||||
|
public const LoadStateFlag All = LoadStateFlag.Success
|
||||||
|
| LoadStateFlag.Async
|
||||||
|
| LoadStateFlag.Failed
|
||||||
|
| LoadStateFlag.FailedSub
|
||||||
|
| LoadStateFlag.Unknown
|
||||||
|
| LoadStateFlag.None;
|
||||||
|
}
|
||||||
|
|
||||||
internal sealed unsafe class CachedRecord(Record record)
|
internal sealed unsafe class CachedRecord(Record record)
|
||||||
{
|
{
|
||||||
public readonly Record Record = record;
|
public readonly Record Record = record;
|
||||||
|
|
@ -84,23 +72,23 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
|
||||||
public bool WouldBeVisible(Record record)
|
public bool WouldBeVisible(Record record)
|
||||||
=> Columns.OfType<ICheckRecord>().All(column => column.WouldBeVisible(record));
|
=> Columns.OfType<ICheckRecord>().All(column => column.WouldBeVisible(record));
|
||||||
|
|
||||||
public ResourceWatcherTable(ResourceWatcherConfig config, IReadOnlyList<Record> records)
|
public ResourceWatcherTable(FilterConfig filterConfig, IReadOnlyList<Record> records)
|
||||||
: base(new StringU8("##records"u8),
|
: base(new StringU8("##records"u8),
|
||||||
new PathColumn(config) { Label = new StringU8("Path"u8) },
|
new PathColumn(filterConfig) { Label = new StringU8("Path"u8) },
|
||||||
new RecordTypeColumn(config) { Label = new StringU8("Record"u8) },
|
new RecordTypeColumn(filterConfig) { Label = new StringU8("Record"u8) },
|
||||||
new CollectionColumn(config) { Label = new StringU8("Collection"u8) },
|
new CollectionColumn(filterConfig) { Label = new StringU8("Collection"u8) },
|
||||||
new ObjectColumn(config) { Label = new StringU8("Game Object"u8) },
|
new ObjectColumn(filterConfig) { Label = new StringU8("Game Object"u8) },
|
||||||
new CustomLoadColumn(config) { Label = new StringU8("Custom"u8) },
|
new CustomLoadColumn(filterConfig) { Label = new StringU8("Custom"u8) },
|
||||||
new SynchronousLoadColumn(config) { Label = new StringU8("Sync"u8) },
|
new SynchronousLoadColumn(filterConfig) { Label = new StringU8("Sync"u8) },
|
||||||
new OriginalPathColumn(config) { Label = new StringU8("Original Path"u8) },
|
new OriginalPathColumn(filterConfig) { Label = new StringU8("Original Path"u8) },
|
||||||
new ResourceCategoryColumn(config) { Label = new StringU8("Category"u8) },
|
new ResourceCategoryColumn(filterConfig) { Label = new StringU8("Category"u8) },
|
||||||
new ResourceTypeColumn(config) { Label = new StringU8("Type"u8) },
|
new ResourceTypeColumn(filterConfig) { Label = new StringU8("Type"u8) },
|
||||||
new HandleColumn(config) { Label = new StringU8("Resource"u8) },
|
new HandleColumn(filterConfig) { Label = new StringU8("Resource"u8) },
|
||||||
new LoadStateColumn(config) { Label = new StringU8("State"u8) },
|
new LoadStateColumn(filterConfig) { Label = new StringU8("State"u8) },
|
||||||
new RefCountColumn(config) { Label = new StringU8("#Ref"u8) },
|
new RefCountColumn(filterConfig) { Label = new StringU8("#Ref"u8) },
|
||||||
new DateColumn { Label = new StringU8("Time"u8) },
|
new DateColumn { Label = new StringU8("Time"u8) },
|
||||||
new Crc64Column(config) { Label = new StringU8("Crc64"u8) },
|
new Crc64Column(filterConfig) { Label = new StringU8("Crc64"u8) },
|
||||||
new OsThreadColumn(config) { Label = new StringU8("TID"u8) }
|
new OsThreadColumn(filterConfig) { Label = new StringU8("TID"u8) }
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_records = records;
|
_records = records;
|
||||||
|
|
@ -149,26 +137,15 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
|
||||||
|
|
||||||
private sealed class PathColumn : TextColumn<CachedRecord>, ICheckRecord
|
private sealed class PathColumn : TextColumn<CachedRecord>, ICheckRecord
|
||||||
{
|
{
|
||||||
private readonly ResourceWatcherConfig _config;
|
public PathColumn(FilterConfig config)
|
||||||
|
|
||||||
public PathColumn(ResourceWatcherConfig config)
|
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
UnscaledWidth = 300;
|
UnscaledWidth = 300;
|
||||||
Filter.Set(config.PathFilter);
|
Filter.Set(config.ResourceLoggerPathFilter);
|
||||||
Filter.FilterChanged += OnFilterChanged;
|
Filter.FilterChanged += () => config.ResourceLoggerPathFilter = Filter.Text;
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFilterChanged()
|
|
||||||
{
|
|
||||||
_config.PathFilter = Filter.Text;
|
|
||||||
_config.Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DrawColumn(in CachedRecord item, int globalIndex)
|
public override void DrawColumn(in CachedRecord item, int globalIndex)
|
||||||
{
|
=> DrawByteString(item.Record.Path, 290 * Im.Style.GlobalScale);
|
||||||
DrawByteString(item.Record.Path, 290 * Im.Style.GlobalScale);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override string ComparisonText(in CachedRecord item, int globalIndex)
|
protected override string ComparisonText(in CachedRecord item, int globalIndex)
|
||||||
=> item.PathU16;
|
=> item.PathU16;
|
||||||
|
|
@ -182,20 +159,11 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
|
||||||
|
|
||||||
private sealed class RecordTypeColumn : FlagColumn<RecordType, CachedRecord>, ICheckRecord
|
private sealed class RecordTypeColumn : FlagColumn<RecordType, CachedRecord>, ICheckRecord
|
||||||
{
|
{
|
||||||
private readonly ResourceWatcherConfig _config;
|
public RecordTypeColumn(FilterConfig config)
|
||||||
|
|
||||||
public RecordTypeColumn(ResourceWatcherConfig config)
|
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
UnscaledWidth = 80;
|
UnscaledWidth = 80;
|
||||||
Filter.LoadValue(config.RecordFilter);
|
Filter.LoadValue(config.ResourceLoggerRecordFilter);
|
||||||
Filter.FilterChanged += OnFilterChanged;
|
Filter.FilterChanged += () => config.ResourceLoggerRecordFilter = Filter.FilterValue;
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFilterChanged()
|
|
||||||
{
|
|
||||||
_config.RecordFilter = Filter.FilterValue;
|
|
||||||
_config.Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override StringU8 DisplayString(in CachedRecord item, int globalIndex)
|
protected override StringU8 DisplayString(in CachedRecord item, int globalIndex)
|
||||||
|
|
@ -225,20 +193,11 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
|
||||||
|
|
||||||
private sealed class Crc64Column : TextColumn<CachedRecord>, ICheckRecord
|
private sealed class Crc64Column : TextColumn<CachedRecord>, ICheckRecord
|
||||||
{
|
{
|
||||||
private readonly ResourceWatcherConfig _config;
|
public Crc64Column(FilterConfig config)
|
||||||
|
|
||||||
public Crc64Column(ResourceWatcherConfig config)
|
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
UnscaledWidth = 17 * 8;
|
UnscaledWidth = 17 * 8;
|
||||||
Filter.Set(config.CrcFilter);
|
Filter.Set(config.ResourceLoggerCrcFilter);
|
||||||
Filter.FilterChanged += OnFilterChanged;
|
Filter.FilterChanged += () => config.ResourceLoggerCrcFilter = Filter.Text;
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFilterChanged()
|
|
||||||
{
|
|
||||||
_config.CrcFilter = Filter.Text;
|
|
||||||
_config.Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int Compare(in CachedRecord lhs, int lhsGlobalIndex, in CachedRecord rhs, int rhsGlobalIndex)
|
public override int Compare(in CachedRecord lhs, int lhsGlobalIndex, in CachedRecord rhs, int rhsGlobalIndex)
|
||||||
|
|
@ -266,20 +225,11 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
|
||||||
|
|
||||||
private sealed class CollectionColumn : TextColumn<CachedRecord>, ICheckRecord
|
private sealed class CollectionColumn : TextColumn<CachedRecord>, ICheckRecord
|
||||||
{
|
{
|
||||||
private readonly ResourceWatcherConfig _config;
|
public CollectionColumn(FilterConfig config)
|
||||||
|
|
||||||
public CollectionColumn(ResourceWatcherConfig config)
|
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
UnscaledWidth = 80;
|
UnscaledWidth = 80;
|
||||||
Filter.Set(config.CollectionFilter);
|
Filter.Set(config.ResourceLoggerCollectionFilter);
|
||||||
Filter.FilterChanged += OnFilterChanged;
|
Filter.FilterChanged += () => config.ResourceLoggerCollectionFilter = Filter.Text;
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFilterChanged()
|
|
||||||
{
|
|
||||||
_config.CollectionFilter = Filter.Text;
|
|
||||||
_config.Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string ComparisonText(in CachedRecord item, int globalIndex)
|
protected override string ComparisonText(in CachedRecord item, int globalIndex)
|
||||||
|
|
@ -294,20 +244,11 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
|
||||||
|
|
||||||
private sealed class ObjectColumn : TextColumn<CachedRecord>, ICheckRecord
|
private sealed class ObjectColumn : TextColumn<CachedRecord>, ICheckRecord
|
||||||
{
|
{
|
||||||
private readonly ResourceWatcherConfig _config;
|
public ObjectColumn(FilterConfig config)
|
||||||
|
|
||||||
public ObjectColumn(ResourceWatcherConfig config)
|
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
UnscaledWidth = 150;
|
UnscaledWidth = 150;
|
||||||
Filter.Set(config.ObjectFilter);
|
Filter.Set(config.ResourceLoggerObjectFilter);
|
||||||
Filter.FilterChanged += OnFilterChanged;
|
Filter.FilterChanged += () => config.ResourceLoggerObjectFilter = Filter.Text;
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFilterChanged()
|
|
||||||
{
|
|
||||||
_config.ObjectFilter = Filter.Text;
|
|
||||||
_config.Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string ComparisonText(in CachedRecord item, int globalIndex)
|
protected override string ComparisonText(in CachedRecord item, int globalIndex)
|
||||||
|
|
@ -322,20 +263,11 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
|
||||||
|
|
||||||
private sealed class OriginalPathColumn : TextColumn<CachedRecord>, ICheckRecord
|
private sealed class OriginalPathColumn : TextColumn<CachedRecord>, ICheckRecord
|
||||||
{
|
{
|
||||||
private readonly ResourceWatcherConfig _config;
|
public OriginalPathColumn(FilterConfig config)
|
||||||
|
|
||||||
public OriginalPathColumn(ResourceWatcherConfig config)
|
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
UnscaledWidth = 200;
|
UnscaledWidth = 200;
|
||||||
Filter.Set(config.OriginalPathFilter);
|
Filter.Set(config.ResourceLoggerOriginalPathFilter);
|
||||||
Filter.FilterChanged += OnFilterChanged;
|
Filter.FilterChanged += () => config.ResourceLoggerOriginalPathFilter = Filter.Text;
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFilterChanged()
|
|
||||||
{
|
|
||||||
_config.OriginalPathFilter = Filter.Text;
|
|
||||||
_config.Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DrawColumn(in CachedRecord item, int globalIndex)
|
public override void DrawColumn(in CachedRecord item, int globalIndex)
|
||||||
|
|
@ -355,20 +287,11 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
|
||||||
|
|
||||||
private sealed class ResourceCategoryColumn : FlagColumn<ResourceCategoryFlag, CachedRecord>, ICheckRecord
|
private sealed class ResourceCategoryColumn : FlagColumn<ResourceCategoryFlag, CachedRecord>, ICheckRecord
|
||||||
{
|
{
|
||||||
private readonly ResourceWatcherConfig _config;
|
public ResourceCategoryColumn(FilterConfig config)
|
||||||
|
|
||||||
public ResourceCategoryColumn(ResourceWatcherConfig config)
|
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
UnscaledWidth = 80;
|
UnscaledWidth = 80;
|
||||||
Filter.LoadValue(config.CategoryFilter);
|
Filter.LoadValue(config.ResourceLoggerCategoryFilter);
|
||||||
Filter.FilterChanged += OnFilterChanged;
|
Filter.FilterChanged += () => config.ResourceLoggerCategoryFilter = Filter.FilterValue;
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFilterChanged()
|
|
||||||
{
|
|
||||||
_config.CategoryFilter = Filter.FilterValue;
|
|
||||||
_config.Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override StringU8 DisplayString(in CachedRecord item, int globalIndex)
|
protected override StringU8 DisplayString(in CachedRecord item, int globalIndex)
|
||||||
|
|
@ -386,20 +309,11 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
|
||||||
|
|
||||||
private sealed class ResourceTypeColumn : FlagColumn<ResourceTypeFlag, CachedRecord>, ICheckRecord
|
private sealed class ResourceTypeColumn : FlagColumn<ResourceTypeFlag, CachedRecord>, ICheckRecord
|
||||||
{
|
{
|
||||||
private readonly ResourceWatcherConfig _config;
|
public ResourceTypeColumn(FilterConfig config)
|
||||||
|
|
||||||
public ResourceTypeColumn(ResourceWatcherConfig config)
|
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
UnscaledWidth = 50;
|
UnscaledWidth = 50;
|
||||||
Filter.LoadValue(config.TypeFilter);
|
Filter.LoadValue(config.ResourceLoggerTypeFilter);
|
||||||
Filter.FilterChanged += OnFilterChanged;
|
Filter.FilterChanged += () => config.ResourceLoggerTypeFilter = Filter.FilterValue;
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFilterChanged()
|
|
||||||
{
|
|
||||||
_config.TypeFilter = Filter.FilterValue;
|
|
||||||
_config.Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IReadOnlyList<(ResourceTypeFlag Value, StringU8 Name)> EnumData { get; } =
|
protected override IReadOnlyList<(ResourceTypeFlag Value, StringU8 Name)> EnumData { get; } =
|
||||||
|
|
@ -417,20 +331,11 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
|
||||||
|
|
||||||
private sealed class LoadStateColumn : FlagColumn<LoadStateFlag, CachedRecord>, ICheckRecord
|
private sealed class LoadStateColumn : FlagColumn<LoadStateFlag, CachedRecord>, ICheckRecord
|
||||||
{
|
{
|
||||||
private readonly ResourceWatcherConfig _config;
|
public LoadStateColumn(FilterConfig config)
|
||||||
|
|
||||||
public LoadStateColumn(ResourceWatcherConfig config)
|
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
UnscaledWidth = 50;
|
UnscaledWidth = 50;
|
||||||
Filter.LoadValue(config.LoadStateFilter);
|
Filter.LoadValue(config.ResourceLoggerLoadStateFilter);
|
||||||
Filter.FilterChanged += OnFilterChanged;
|
Filter.FilterChanged += () => config.ResourceLoggerLoadStateFilter = Filter.FilterValue;
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFilterChanged()
|
|
||||||
{
|
|
||||||
_config.LoadStateFilter = Filter.FilterValue;
|
|
||||||
_config.Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DrawColumn(in CachedRecord item, int globalIndex)
|
public override void DrawColumn(in CachedRecord item, int globalIndex)
|
||||||
|
|
@ -474,39 +379,30 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
|
||||||
|
|
||||||
protected override LoadStateFlag GetValue(in CachedRecord item, int globalIndex)
|
protected override LoadStateFlag GetValue(in CachedRecord item, int globalIndex)
|
||||||
=> GetValue(item.Record.LoadState);
|
=> GetValue(item.Record.LoadState);
|
||||||
|
|
||||||
|
|
||||||
public bool WouldBeVisible(in Record record)
|
public bool WouldBeVisible(in Record record)
|
||||||
=> Filter.FilterValue.HasFlag(GetValue(record.LoadState));
|
=> Filter.FilterValue.HasFlag(GetValue(record.LoadState));
|
||||||
|
|
||||||
private static LoadStateFlag GetValue(LoadState value)
|
private static LoadStateFlag GetValue(LoadState value)
|
||||||
=> value switch
|
=> value switch
|
||||||
{
|
{
|
||||||
LoadState.None => LoadStateFlag.None,
|
LoadState.None => LoadStateFlag.None,
|
||||||
LoadState.Success => LoadStateFlag.Success,
|
LoadState.Success => LoadStateFlag.Success,
|
||||||
LoadState.FailedSubResource => LoadStateFlag.FailedSub,
|
LoadState.FailedSubResource => LoadStateFlag.FailedSub,
|
||||||
<= LoadState.Constructed => LoadStateFlag.Unknown,
|
<= LoadState.Constructed => LoadStateFlag.Unknown,
|
||||||
< LoadState.Success => LoadStateFlag.Async,
|
< LoadState.Success => LoadStateFlag.Async,
|
||||||
> LoadState.Success => LoadStateFlag.Failed,
|
> LoadState.Success => LoadStateFlag.Failed,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class HandleColumn : TextColumn<CachedRecord>, ICheckRecord
|
private sealed class HandleColumn : TextColumn<CachedRecord>, ICheckRecord
|
||||||
{
|
{
|
||||||
private readonly ResourceWatcherConfig _config;
|
public HandleColumn(FilterConfig config)
|
||||||
|
|
||||||
public HandleColumn(ResourceWatcherConfig config)
|
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
UnscaledWidth = 120;
|
UnscaledWidth = 120;
|
||||||
Filter.Set(config.ResourceFilter);
|
Filter.Set(config.ResourceLoggerResourceFilter);
|
||||||
Filter.FilterChanged += OnFilterChanged;
|
Filter.FilterChanged += () => config.ResourceLoggerResourceFilter = Filter.Text;
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFilterChanged()
|
|
||||||
{
|
|
||||||
_config.ResourceFilter = Filter.Text;
|
|
||||||
_config.Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override unsafe void DrawColumn(in CachedRecord item, int globalIndex)
|
public override unsafe void DrawColumn(in CachedRecord item, int globalIndex)
|
||||||
|
|
@ -569,20 +465,11 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
|
||||||
|
|
||||||
private sealed class CustomLoadColumn : OptBoolColumn, ICheckRecord
|
private sealed class CustomLoadColumn : OptBoolColumn, ICheckRecord
|
||||||
{
|
{
|
||||||
private readonly ResourceWatcherConfig _config;
|
public CustomLoadColumn(FilterConfig config)
|
||||||
|
|
||||||
public CustomLoadColumn(ResourceWatcherConfig config)
|
|
||||||
: base(60f)
|
: base(60f)
|
||||||
{
|
{
|
||||||
_config = config;
|
Filter.LoadValue(config.ResourceLoggerCustomFilter);
|
||||||
Filter.LoadValue(config.CustomFilter);
|
Filter.FilterChanged += () => config.ResourceLoggerCustomFilter = Filter.FilterValue;
|
||||||
Filter.FilterChanged += OnFilterChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFilterChanged()
|
|
||||||
{
|
|
||||||
_config.CustomFilter = Filter.FilterValue;
|
|
||||||
_config.Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override BoolEnum GetValue(in CachedRecord item, int globalIndex)
|
protected override BoolEnum GetValue(in CachedRecord item, int globalIndex)
|
||||||
|
|
@ -594,20 +481,11 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
|
||||||
|
|
||||||
private sealed class SynchronousLoadColumn : OptBoolColumn, ICheckRecord
|
private sealed class SynchronousLoadColumn : OptBoolColumn, ICheckRecord
|
||||||
{
|
{
|
||||||
private readonly ResourceWatcherConfig _config;
|
public SynchronousLoadColumn(FilterConfig config)
|
||||||
|
|
||||||
public SynchronousLoadColumn(ResourceWatcherConfig config)
|
|
||||||
: base(45)
|
: base(45)
|
||||||
{
|
{
|
||||||
_config = config;
|
Filter.LoadValue(config.ResourceLoggerSyncFilter);
|
||||||
Filter.LoadValue(config.SyncFilter);
|
Filter.FilterChanged += () => config.ResourceLoggerSyncFilter = Filter.FilterValue;
|
||||||
Filter.FilterChanged += OnFilterChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFilterChanged()
|
|
||||||
{
|
|
||||||
_config.SyncFilter = Filter.FilterValue;
|
|
||||||
_config.Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override BoolEnum GetValue(in CachedRecord item, int globalIndex)
|
protected override BoolEnum GetValue(in CachedRecord item, int globalIndex)
|
||||||
|
|
@ -619,20 +497,11 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
|
||||||
|
|
||||||
private sealed class RefCountColumn : NumberColumn<uint, CachedRecord>, ICheckRecord
|
private sealed class RefCountColumn : NumberColumn<uint, CachedRecord>, ICheckRecord
|
||||||
{
|
{
|
||||||
private readonly ResourceWatcherConfig _config;
|
public RefCountColumn(FilterConfig config)
|
||||||
|
|
||||||
public RefCountColumn(ResourceWatcherConfig config)
|
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
UnscaledWidth = 60;
|
UnscaledWidth = 60;
|
||||||
Filter.Set(config.RefFilter);
|
Filter.Set(config.ResourceLoggerRefFilter);
|
||||||
Filter.FilterChanged += OnFilterChanged;
|
Filter.FilterChanged += () => config.ResourceLoggerRefFilter = Filter.Text;
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFilterChanged()
|
|
||||||
{
|
|
||||||
_config.RefFilter = Filter.Text;
|
|
||||||
_config.Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override uint ToValue(in CachedRecord item, int globalIndex)
|
public override uint ToValue(in CachedRecord item, int globalIndex)
|
||||||
|
|
@ -650,20 +519,11 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
|
||||||
|
|
||||||
private sealed class OsThreadColumn : NumberColumn<uint, CachedRecord>, ICheckRecord
|
private sealed class OsThreadColumn : NumberColumn<uint, CachedRecord>, ICheckRecord
|
||||||
{
|
{
|
||||||
private readonly ResourceWatcherConfig _config;
|
public OsThreadColumn(FilterConfig config)
|
||||||
|
|
||||||
public OsThreadColumn(ResourceWatcherConfig config)
|
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
UnscaledWidth = 60;
|
UnscaledWidth = 60;
|
||||||
Filter.Set(config.ThreadFilter);
|
Filter.Set(config.ResourceLoggerThreadFilter);
|
||||||
Filter.FilterChanged += OnFilterChanged;
|
Filter.FilterChanged += () => config.ResourceLoggerThreadFilter = Filter.Text;
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFilterChanged()
|
|
||||||
{
|
|
||||||
_config.ThreadFilter = Filter.Text;
|
|
||||||
_config.Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override uint ToValue(in CachedRecord item, int globalIndex)
|
public override uint ToValue(in CachedRecord item, int globalIndex)
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,10 @@ public sealed class CollectionsTab : TwoPanelLayout, ITab<TabType>
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawContent()
|
public void DrawContent()
|
||||||
=> Draw(_config.CollectionTabScale);
|
=> Draw(_config.CollectionsTabScale);
|
||||||
|
|
||||||
protected override void SetWidth(float width, ScalingMode mode)
|
protected override void SetWidth(float width, ScalingMode mode)
|
||||||
=> _config.CollectionTabScale = new TwoPanelWidth(width, mode);
|
=> _config.CollectionsTabScale = new TwoPanelWidth(width, mode);
|
||||||
|
|
||||||
public void PostTabButton()
|
public void PostTabButton()
|
||||||
=> _tutorial.OpenTutorial(BasicTutorialSteps.Collections);
|
=> _tutorial.OpenTutorial(BasicTutorialSteps.Collections);
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,16 @@ public sealed class ResourceTab(Configuration config, ResourceManagerService res
|
||||||
public bool IsVisible
|
public bool IsVisible
|
||||||
=> config.DebugMode;
|
=> config.DebugMode;
|
||||||
|
|
||||||
public readonly ResourceFilter Filter = new();
|
public readonly ResourceFilter Filter = new(config.Filters);
|
||||||
|
|
||||||
public sealed class ResourceFilter : Utf8FilterBase<ResourceHandle>
|
public sealed class ResourceFilter : Utf8FilterBase<ResourceHandle>
|
||||||
{
|
{
|
||||||
|
public ResourceFilter(FilterConfig filterConfig)
|
||||||
|
{
|
||||||
|
Set(new StringU8(filterConfig.ResourceManagerFilter));
|
||||||
|
FilterChanged += () => filterConfig.ResourceManagerFilter = Text.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
protected override ReadOnlySpan<byte> ToFilterString(in ResourceHandle item, int globalIndex)
|
protected override ReadOnlySpan<byte> ToFilterString(in ResourceHandle item, int globalIndex)
|
||||||
=> item.FileName.AsSpan();
|
=> item.FileName.AsSpan();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -432,7 +432,8 @@ public sealed class SettingsTab : ITab<TabType>
|
||||||
_config.HideChangedItemFilters = v;
|
_config.HideChangedItemFilters = v;
|
||||||
if (v)
|
if (v)
|
||||||
{
|
{
|
||||||
_config.Ephemeral.ChangedItemFilter = ChangedItemFlagExtensions.AllFlags;
|
_config.Filters.ModChangedItemTypeFilter = ChangedItemFlagExtensions.AllFlags;
|
||||||
|
_config.Filters.ChangedItemTypeFilter = ChangedItemFlagExtensions.AllFlags;
|
||||||
_config.Ephemeral.Save();
|
_config.Ephemeral.Save();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue