feat: add reordering, editing, and multiple globs per filter
This commit is contained in:
parent
cd3b8bd066
commit
af20de19fd
|
@ -32,11 +32,19 @@ namespace SoundFilter {
|
||||||
var split = args.Split(' ');
|
var split = args.Split(' ');
|
||||||
if (split.Length < 1) {
|
if (split.Length < 1) {
|
||||||
chat.PrintError($"[{SoundFilterPlugin.Name}] {Language.CommandNotEnoughArguments}");
|
chat.PrintError($"[{SoundFilterPlugin.Name}] {Language.CommandNotEnoughArguments}");
|
||||||
|
chat.PrintError($"[{SoundFilterPlugin.Name}] /soundfilter log");
|
||||||
|
chat.PrintError($"[{SoundFilterPlugin.Name}] /soundfilter <enable|disable|toggle> [filter name]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (split[0] == "log") {
|
||||||
|
this.Plugin.Config.ShowLog ^= true;
|
||||||
|
this.Plugin.Config.Save();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var filterName = split.Length > 1 ? string.Join(" ", split.Skip(1)) : null;
|
var filterName = split.Length > 1 ? string.Join(" ", split.Skip(1)) : null;
|
||||||
var filter = filterName == null ? null : this.Plugin.Config.Filtered.Values.FirstOrDefault(filter => filter.Name == filterName);
|
var filter = filterName == null ? null : this.Plugin.Config.Filters.FirstOrDefault(filter => filter.Name == filterName);
|
||||||
if (filterName != null && filter == null) {
|
if (filterName != null && filter == null) {
|
||||||
chat.PrintError($"[{SoundFilterPlugin.Name}] {Language.CommandNoSuchFilter}");
|
chat.PrintError($"[{SoundFilterPlugin.Name}] {Language.CommandNoSuchFilter}");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using Dalamud.Configuration;
|
using Dalamud.Configuration;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using DotNet.Globbing;
|
using DotNet.Globbing;
|
||||||
|
@ -8,30 +7,37 @@ using DotNet.Globbing;
|
||||||
namespace SoundFilter.Config {
|
namespace SoundFilter.Config {
|
||||||
[Serializable]
|
[Serializable]
|
||||||
internal class Configuration : IPluginConfiguration {
|
internal class Configuration : IPluginConfiguration {
|
||||||
public int Version { get; set; } = 1;
|
internal const int LatestVersion = 2;
|
||||||
|
|
||||||
|
public int Version { get; set; } = LatestVersion;
|
||||||
|
|
||||||
private DalamudPluginInterface? Interface { get; set; }
|
private DalamudPluginInterface? Interface { get; set; }
|
||||||
private Dictionary<string, Glob> CachedGlobs { get; } = new();
|
private Dictionary<string, Glob> CachedGlobs { get; } = new();
|
||||||
|
|
||||||
public bool Enabled = true;
|
public bool Enabled = true;
|
||||||
public bool ShowLog;
|
public bool ShowLog;
|
||||||
|
public bool LogEnabled = true;
|
||||||
|
public bool LogFiltered = false;
|
||||||
public uint LogEntries = 250;
|
public uint LogEntries = 250;
|
||||||
public Dictionary<string, CustomFilter> Filtered { get; set; } = new();
|
public List<CustomFilter> Filters { get; set; } = new();
|
||||||
|
|
||||||
internal IReadOnlyDictionary<Glob, bool> Globs {
|
internal IReadOnlyDictionary<Glob, bool> Globs {
|
||||||
get {
|
get {
|
||||||
return this.Filtered.ToDictionary(
|
var dictionary = new Dictionary<Glob, bool>();
|
||||||
entry => {
|
foreach (var filter in this.Filters) {
|
||||||
if (this.CachedGlobs.TryGetValue(entry.Key, out var cached)) {
|
foreach (var globString in filter.Globs) {
|
||||||
return cached;
|
if (this.CachedGlobs.TryGetValue(globString, out var cached)) {
|
||||||
|
dictionary[cached] = filter.Enabled;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var glob = Glob.Parse(entry.Key);
|
var glob = Glob.Parse(globString);
|
||||||
this.CachedGlobs[entry.Key] = glob;
|
this.CachedGlobs[globString] = glob;
|
||||||
return glob;
|
dictionary[glob] = filter.Enabled;
|
||||||
},
|
}
|
||||||
entry => entry.Value.Enabled
|
}
|
||||||
);
|
|
||||||
|
return dictionary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace SoundFilter.Config {
|
namespace SoundFilter.Config {
|
||||||
[Serializable]
|
[Serializable]
|
||||||
internal class CustomFilter {
|
internal class CustomFilter {
|
||||||
public string Name = "Unnamed filter";
|
public string Name = "Unnamed filter";
|
||||||
public bool Enabled = true;
|
public bool Enabled = true;
|
||||||
|
public List<string> Globs { get; set; } = new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Dalamud.Plugin;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace SoundFilter.Config {
|
||||||
|
internal static class Migrator {
|
||||||
|
private static void WithEachObject(JToken old, Action<string, JObject> action) {
|
||||||
|
foreach (var property in old.Children<JProperty>()) {
|
||||||
|
if (property.Name == "$type") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var layout = (JObject) property.Value;
|
||||||
|
|
||||||
|
action(property.Name, layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void MigrateV1(JObject old) {
|
||||||
|
var filters = new List<CustomFilter>();
|
||||||
|
|
||||||
|
WithEachObject(old["Filtered"], (glob, filter) => {
|
||||||
|
var name = filter["Name"].Value<string>();
|
||||||
|
var enabled = filter["Enabled"].Value<bool>();
|
||||||
|
filters.Add(new CustomFilter {
|
||||||
|
Name = name,
|
||||||
|
Enabled = enabled,
|
||||||
|
Globs = { glob },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
old.Remove("Filtered");
|
||||||
|
old["Filters"] = JArray.FromObject(filters);
|
||||||
|
|
||||||
|
old["Version"] = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Configuration LoadConfiguration(SoundFilterPlugin plugin) {
|
||||||
|
var fileInfo = plugin.Interface.ConfigFile;
|
||||||
|
var text = fileInfo.Exists
|
||||||
|
? File.ReadAllText(fileInfo.FullName)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (text == null) {
|
||||||
|
goto DefaultConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = JsonConvert.DeserializeObject<JObject>(text);
|
||||||
|
|
||||||
|
int GetVersion() {
|
||||||
|
if (config.TryGetValue("Version", out var token)) {
|
||||||
|
return token.Value<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var version = GetVersion();
|
||||||
|
if (version < 1) {
|
||||||
|
goto DefaultConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
// run migrations until done
|
||||||
|
while (version < Configuration.LatestVersion) {
|
||||||
|
switch (version) {
|
||||||
|
case 1:
|
||||||
|
MigrateV1(config);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PluginLog.Warning($"Tried to migrate from an unknown version: {version}");
|
||||||
|
goto DefaultConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
version = GetVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version == Configuration.LatestVersion) {
|
||||||
|
return config.ToObject<Configuration>();
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultConfiguration:
|
||||||
|
return plugin.Interface.GetPluginConfig() as Configuration ?? new Configuration();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -159,14 +159,17 @@ namespace SoundFilter {
|
||||||
path = path.ToLowerInvariant();
|
path = path.ToLowerInvariant();
|
||||||
var specificPath = $"{path}/{idx}";
|
var specificPath = $"{path}/{idx}";
|
||||||
|
|
||||||
this.Recent.Enqueue(specificPath);
|
|
||||||
while (this.Recent.Count > this.Plugin.Config.LogEntries) {
|
|
||||||
this.Recent.TryDequeue(out _);
|
|
||||||
}
|
|
||||||
|
|
||||||
var shouldFilter = this.Plugin.Config.Globs
|
var shouldFilter = this.Plugin.Config.Globs
|
||||||
.Where(entry => entry.Value)
|
.Where(entry => entry.Value)
|
||||||
.Any(entry => entry.Key.IsMatch(specificPath));
|
.Any(entry => entry.Key.IsMatch(specificPath));
|
||||||
|
|
||||||
|
if (this.Plugin.Config.LogEnabled && (!shouldFilter || this.Plugin.Config.LogFiltered)) {
|
||||||
|
this.Recent.Enqueue(specificPath);
|
||||||
|
while (this.Recent.Count > this.Plugin.Config.LogEntries) {
|
||||||
|
this.Recent.TryDequeue(out _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (shouldFilter) {
|
if (shouldFilter) {
|
||||||
return this.PlaySpecificSoundHook!.Original((long) this.InfoPtr, 0);
|
return this.PlaySpecificSoundHook!.Original((long) this.InfoPtr, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,171 +1,207 @@
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.42000
|
// Runtime Version:4.0.30319.42000
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
// </auto-generated>
|
// </auto-generated>
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
namespace SoundFilter.Resources {
|
namespace SoundFilter.Resources {
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
// class via a tool like ResGen or Visual Studio.
|
// class via a tool like ResGen or Visual Studio.
|
||||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
// with the /str option, or rebuild your VS project.
|
// with the /str option, or rebuild your VS project.
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
internal class Language {
|
internal class Language {
|
||||||
|
|
||||||
private static global::System.Resources.ResourceManager resourceMan;
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
internal Language() {
|
internal Language() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the cached ResourceManager instance used by this class.
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
get {
|
get {
|
||||||
if (object.ReferenceEquals(resourceMan, null)) {
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SoundFilter.Resources.Language", typeof(Language).Assembly);
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SoundFilter.Resources.Language", typeof(Language).Assembly);
|
||||||
resourceMan = temp;
|
resourceMan = temp;
|
||||||
}
|
}
|
||||||
return resourceMan;
|
return resourceMan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overrides the current thread's CurrentUICulture property for all
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
/// resource lookups using this strongly typed resource class.
|
/// resource lookups using this strongly typed resource class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
internal static global::System.Globalization.CultureInfo Culture {
|
internal static global::System.Globalization.CultureInfo Culture {
|
||||||
get {
|
get {
|
||||||
return resourceCulture;
|
return resourceCulture;
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
resourceCulture = value;
|
resourceCulture = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Invalid subcommand..
|
/// Looks up a localized string similar to Invalid subcommand..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string CommandInvalidSubcommand {
|
internal static string CommandInvalidSubcommand {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("CommandInvalidSubcommand", resourceCulture);
|
return ResourceManager.GetString("CommandInvalidSubcommand", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to No such filter..
|
/// Looks up a localized string similar to No such filter..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string CommandNoSuchFilter {
|
internal static string CommandNoSuchFilter {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("CommandNoSuchFilter", resourceCulture);
|
return ResourceManager.GetString("CommandNoSuchFilter", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Not enough arguments. Please specify 'enable' or 'disable' and an optional filter name.
|
/// Looks up a localized string similar to Not enough arguments..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string CommandNotEnoughArguments {
|
internal static string CommandNotEnoughArguments {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("CommandNotEnoughArguments", resourceCulture);
|
return ResourceManager.GetString("CommandNotEnoughArguments", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Due to the way FFXIV's resource loading works, {0} has to hear a sound once before it can filter it after a fresh install or update. Restart your game after installing or updating if this is a problem for you..
|
/// Looks up a localized string similar to Due to the way FFXIV's resource loading works, {0} has to hear a sound once before it can filter it after a fresh install or update. Restart your game after installing or updating if this is a problem for you..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string LoadWarning {
|
internal static string LoadWarning {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("LoadWarning", resourceCulture);
|
return ResourceManager.GetString("LoadWarning", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Max sounds.
|
/// Looks up a localized string similar to Enable logging.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string LogMaxRecentSounds {
|
internal static string LogEnableLogging {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("LogMaxRecentSounds", resourceCulture);
|
return ResourceManager.GetString("LogEnableLogging", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Search.
|
/// Looks up a localized string similar to Log filtered.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string LogSearch {
|
internal static string LogLogFiltered {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("LogSearch", resourceCulture);
|
return ResourceManager.GetString("LogLogFiltered", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Sound log.
|
/// Looks up a localized string similar to Max sounds.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string LogWindowTitle {
|
internal static string LogMaxRecentSounds {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("LogWindowTitle", resourceCulture);
|
return ResourceManager.GetString("LogMaxRecentSounds", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Filter name.
|
/// Looks up a localized string similar to Search.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string SettingsAddFilterName {
|
internal static string LogSearch {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("SettingsAddFilterName", resourceCulture);
|
return ResourceManager.GetString("LogSearch", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Sound path to filter.
|
/// Looks up a localized string similar to Sound log.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string SettingsAddPathToFilter {
|
internal static string LogWindowTitle {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("SettingsAddPathToFilter", resourceCulture);
|
return ResourceManager.GetString("LogWindowTitle", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Enable sound filter.
|
/// Looks up a localized string similar to Add filter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string SettingsEnableSoundFilter {
|
internal static string SettingsAddFilter {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("SettingsEnableSoundFilter", resourceCulture);
|
return ResourceManager.GetString("SettingsAddFilter", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Show sound log window.
|
/// Looks up a localized string similar to Filter name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string SettingsShowSoundLogWindow {
|
internal static string SettingsAddFilterName {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("SettingsShowSoundLogWindow", resourceCulture);
|
return ResourceManager.GetString("SettingsAddFilterName", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to {0} settings.
|
/// Looks up a localized string similar to Sound path to filter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string SettingsWindowTitle {
|
internal static string SettingsAddPathToFilter {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("SettingsWindowTitle", resourceCulture);
|
return ResourceManager.GetString("SettingsAddPathToFilter", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Edit filter.
|
||||||
|
/// </summary>
|
||||||
|
internal static string SettingsEditFilter {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("SettingsEditFilter", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Enable sound filter.
|
||||||
|
/// </summary>
|
||||||
|
internal static string SettingsEnableSoundFilter {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("SettingsEnableSoundFilter", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Show sound log window.
|
||||||
|
/// </summary>
|
||||||
|
internal static string SettingsShowSoundLogWindow {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("SettingsShowSoundLogWindow", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to {0} settings.
|
||||||
|
/// </summary>
|
||||||
|
internal static string SettingsWindowTitle {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("SettingsWindowTitle", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
<value>Sound path to filter</value>
|
<value>Sound path to filter</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CommandNotEnoughArguments" xml:space="preserve">
|
<data name="CommandNotEnoughArguments" xml:space="preserve">
|
||||||
<value>Not enough arguments. Please specify 'enable' or 'disable' and an optional filter name</value>
|
<value>Not enough arguments.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CommandInvalidSubcommand" xml:space="preserve">
|
<data name="CommandInvalidSubcommand" xml:space="preserve">
|
||||||
<value>Invalid subcommand.</value>
|
<value>Invalid subcommand.</value>
|
||||||
|
@ -54,4 +54,16 @@
|
||||||
<data name="CommandNoSuchFilter" xml:space="preserve">
|
<data name="CommandNoSuchFilter" xml:space="preserve">
|
||||||
<value>No such filter.</value>
|
<value>No such filter.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SettingsAddFilter" xml:space="preserve">
|
||||||
|
<value>Add filter</value>
|
||||||
|
</data>
|
||||||
|
<data name="LogEnableLogging" xml:space="preserve">
|
||||||
|
<value>Enable logging</value>
|
||||||
|
</data>
|
||||||
|
<data name="LogLogFiltered" xml:space="preserve">
|
||||||
|
<value>Log filtered</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingsEditFilter" xml:space="preserve">
|
||||||
|
<value>Edit filter</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\ImGuiScene.dll</HintPath>
|
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\ImGuiScene.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Newtonsoft.Json">
|
||||||
|
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Newtonsoft.Json.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Update="Resources\Language.resx">
|
<EmbeddedResource Update="Resources\Language.resx">
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace SoundFilter {
|
||||||
internal SoundFilterPlugin(DalamudPluginInterface @interface) {
|
internal SoundFilterPlugin(DalamudPluginInterface @interface) {
|
||||||
this.Interface = @interface;
|
this.Interface = @interface;
|
||||||
|
|
||||||
this.Config = this.Interface.GetPluginConfig() as Configuration ?? new Configuration();
|
this.Config = Migrator.LoadConfiguration(this);
|
||||||
this.Config.Initialise(this.Interface);
|
this.Config.Initialise(this.Interface);
|
||||||
|
|
||||||
this.Filter = new Filter(this);
|
this.Filter = new Filter(this);
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Dalamud.Interface;
|
||||||
|
using ImGuiNET;
|
||||||
|
using SoundFilter.Config;
|
||||||
|
using SoundFilter.Resources;
|
||||||
|
|
||||||
|
namespace SoundFilter.Ui {
|
||||||
|
internal class AddFilter {
|
||||||
|
private Guid Id { get; } = Guid.NewGuid();
|
||||||
|
private SoundFilterPlugin Plugin { get; }
|
||||||
|
private CustomFilter? Filter { get; }
|
||||||
|
|
||||||
|
private string _filterName = string.Empty;
|
||||||
|
private string _newSoundPath = string.Empty;
|
||||||
|
private readonly List<string> _soundPaths = new();
|
||||||
|
|
||||||
|
internal AddFilter(SoundFilterPlugin plugin) {
|
||||||
|
this.Plugin = plugin;
|
||||||
|
this.Filter = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal AddFilter(SoundFilterPlugin plugin, CustomFilter filter) {
|
||||||
|
this.Plugin = plugin;
|
||||||
|
this.Filter = filter;
|
||||||
|
|
||||||
|
this._filterName = filter.Name;
|
||||||
|
this._soundPaths.AddRange(filter.Globs);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool Draw() {
|
||||||
|
ImGui.TextUnformatted(Language.SettingsAddFilterName);
|
||||||
|
|
||||||
|
ImGui.SetNextItemWidth(-1f);
|
||||||
|
ImGui.InputText($"##sound-filter-name-{this.Id}", ref this._filterName, 255);
|
||||||
|
|
||||||
|
ImGui.TextUnformatted(Language.SettingsAddPathToFilter);
|
||||||
|
int? toRemove = null;
|
||||||
|
for (var i = 0; i < this._soundPaths.Count; i++) {
|
||||||
|
var path = this._soundPaths[i];
|
||||||
|
SetNextItemWidth();
|
||||||
|
if (ImGui.InputText($"##sound-path-edit-{i}-{this.Id}", ref path, 255)) {
|
||||||
|
this._soundPaths[i] = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
|
||||||
|
if (Util.IconButton(FontAwesomeIcon.Trash, $"sound-path-delete-{i}-{this.Id}")) {
|
||||||
|
toRemove = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toRemove != null) {
|
||||||
|
this._soundPaths.RemoveAt(toRemove.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetNextItemWidth();
|
||||||
|
ImGui.InputText($"##sound-path-{this.Id}", ref this._newSoundPath, 255);
|
||||||
|
ImGui.SameLine();
|
||||||
|
if (Util.IconButton(FontAwesomeIcon.Plus, "add") && !string.IsNullOrWhiteSpace(this._newSoundPath)) {
|
||||||
|
this._soundPaths.Add(this._newSoundPath);
|
||||||
|
this._newSoundPath = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Util.IconButton(FontAwesomeIcon.Save, $"save-filter-{this.Id}") && this._soundPaths.Count > 0 && !string.IsNullOrWhiteSpace(this._filterName)) {
|
||||||
|
if (!string.IsNullOrWhiteSpace(this._newSoundPath)) {
|
||||||
|
this._soundPaths.Add(this._newSoundPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Save();
|
||||||
|
|
||||||
|
this._filterName = string.Empty;
|
||||||
|
this._newSoundPath = string.Empty;
|
||||||
|
this._soundPaths.Clear();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (this.Filter != null) {
|
||||||
|
ImGui.SameLine();
|
||||||
|
if (Util.IconButton(FontAwesomeIcon.Ban, $"cancel-filter-{this.Id}")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetNextItemWidth() {
|
||||||
|
ImGui.PushFont(UiBuilder.IconFont);
|
||||||
|
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X - ImGui.CalcTextSize(FontAwesomeIcon.Ban.ToIconString()).X - ImGui.GetStyle().ItemSpacing.X * 2);
|
||||||
|
ImGui.PopFont();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Save() {
|
||||||
|
if (this.Filter != null) {
|
||||||
|
this.Filter.Name = this._filterName;
|
||||||
|
this.Filter.Globs.Clear();
|
||||||
|
this.Filter.Globs.AddRange(this._soundPaths);
|
||||||
|
} else {
|
||||||
|
this.Plugin.Config.Filters.Add(new CustomFilter {
|
||||||
|
Name = this._filterName,
|
||||||
|
Enabled = true,
|
||||||
|
Globs = this._soundPaths.ToList(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Plugin.Config.Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,21 +1,21 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using SoundFilter.Config;
|
|
||||||
using SoundFilter.Resources;
|
using SoundFilter.Resources;
|
||||||
|
|
||||||
namespace SoundFilter.Ui {
|
namespace SoundFilter.Ui {
|
||||||
public class Settings : IDisposable {
|
public class Settings : IDisposable {
|
||||||
private SoundFilterPlugin Plugin { get; }
|
private SoundFilterPlugin Plugin { get; }
|
||||||
|
private AddFilter AddFilter { get; }
|
||||||
|
private AddFilter? EditFilter { get; set; }
|
||||||
|
|
||||||
private bool _showWindow;
|
private bool _showWindow;
|
||||||
private string _filterName = string.Empty;
|
private int _dragging = -1;
|
||||||
private string _soundPath = string.Empty;
|
|
||||||
|
|
||||||
internal Settings(SoundFilterPlugin plugin) {
|
internal Settings(SoundFilterPlugin plugin) {
|
||||||
this.Plugin = plugin;
|
this.Plugin = plugin;
|
||||||
|
this.AddFilter = new AddFilter(plugin);
|
||||||
|
|
||||||
this.Plugin.Interface.UiBuilder.OnOpenConfigUi += this.Toggle;
|
this.Plugin.Interface.UiBuilder.OnOpenConfigUi += this.Toggle;
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,19 @@ namespace SoundFilter.Ui {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.EditFilter != null) {
|
||||||
|
ImGui.SetNextWindowSize(new Vector2(ImGui.GetWindowSize().X, -1));
|
||||||
|
if (ImGui.BeginPopupModal($"{Language.SettingsEditFilter}###edit-filter-modal")) {
|
||||||
|
if (this.EditFilter.Draw()) {
|
||||||
|
this.EditFilter = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.OpenPopup("###edit-filter-modal");
|
||||||
|
}
|
||||||
|
|
||||||
ImGui.SetNextWindowSize(new Vector2(500, 450), ImGuiCond.FirstUseEver);
|
ImGui.SetNextWindowSize(new Vector2(500, 450), ImGuiCond.FirstUseEver);
|
||||||
|
|
||||||
var windowTitle = string.Format(Language.SettingsWindowTitle, SoundFilterPlugin.Name);
|
var windowTitle = string.Format(Language.SettingsWindowTitle, SoundFilterPlugin.Name);
|
||||||
|
@ -56,49 +69,80 @@ namespace SoundFilter.Ui {
|
||||||
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
ImGui.TextUnformatted(Language.SettingsAddFilterName);
|
if (ImGui.CollapsingHeader(Language.SettingsAddFilter)) {
|
||||||
ImGui.InputText("##sound-filter-name", ref this._filterName, 255);
|
this.AddFilter.Draw();
|
||||||
|
|
||||||
ImGui.TextUnformatted(Language.SettingsAddPathToFilter);
|
|
||||||
ImGui.InputText("##sound-path", ref this._soundPath, 255);
|
|
||||||
ImGui.SameLine();
|
|
||||||
if (Util.IconButton(FontAwesomeIcon.Plus, "add") && !string.IsNullOrWhiteSpace(this._soundPath) && !string.IsNullOrWhiteSpace(this._filterName)) {
|
|
||||||
this.Plugin.Config.Filtered[this._soundPath] = new CustomFilter {
|
|
||||||
Name = this._filterName,
|
|
||||||
Enabled = true,
|
|
||||||
};
|
|
||||||
shouldSave = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
if (ImGui.BeginChild("filtered-sounds")) {
|
if (ImGui.BeginChild("filtered-sounds")) {
|
||||||
var i = 0;
|
int? toRemove = null;
|
||||||
|
(int src, int dst)? drag = null;
|
||||||
|
for (var i = 0; i < this.Plugin.Config.Filters.Count; i++) {
|
||||||
|
var filter = this.Plugin.Config.Filters[i];
|
||||||
|
|
||||||
foreach (var entry in this.Plugin.Config.Filtered.ToList()) {
|
if (Util.IconButton(FontAwesomeIcon.Trash, $"delete-filter-{i}")) {
|
||||||
var glob = entry.Key;
|
toRemove = i;
|
||||||
|
|
||||||
if (Util.IconButton(FontAwesomeIcon.Trash, $"delete-{glob}")) {
|
|
||||||
this.Plugin.Config.Filtered.Remove(glob);
|
|
||||||
shouldSave = true;
|
shouldSave = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
if (Util.IconButton(FontAwesomeIcon.PencilAlt, $"edit-filter-{i}")) {
|
||||||
if (Util.IconButton(FontAwesomeIcon.Copy, $"copy-{glob}")) {
|
this.EditFilter = new AddFilter(this.Plugin, filter);
|
||||||
ImGui.SetClipboardText(glob);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
|
||||||
shouldSave |= ImGui.Checkbox($"{entry.Value.Name}##{i}-{glob}", ref entry.Value.Enabled);
|
if (Util.IconButton(FontAwesomeIcon.Copy, $"copy-filter-{i}")) {
|
||||||
if (ImGui.IsItemHovered()) {
|
ImGui.SetClipboardText(string.Join("\n", filter.Globs));
|
||||||
ImGui.BeginTooltip();
|
|
||||||
ImGui.TextUnformatted(glob);
|
|
||||||
ImGui.EndTooltip();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i += 1;
|
ImGui.SameLine();
|
||||||
|
|
||||||
|
shouldSave |= ImGui.Checkbox($"{filter.Name}##{i}", ref filter.Enabled);
|
||||||
|
|
||||||
|
if (ImGui.IsItemActive() || this._dragging == i) {
|
||||||
|
this._dragging = i;
|
||||||
|
var step = 0;
|
||||||
|
if (ImGui.GetIO().MouseDelta.Y < 0 && ImGui.GetMousePos().Y < ImGui.GetItemRectMin().Y) {
|
||||||
|
step = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.GetIO().MouseDelta.Y > 0 && ImGui.GetMousePos().Y > ImGui.GetItemRectMax().Y) {
|
||||||
|
step = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (step != 0) {
|
||||||
|
drag = (i, i + step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ImGui.IsItemHovered()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.BeginTooltip();
|
||||||
|
foreach (var glob in filter.Globs) {
|
||||||
|
ImGui.TextUnformatted(glob);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ImGui.IsMouseDown(ImGuiMouseButton.Left) && this._dragging != -1) {
|
||||||
|
this._dragging = -1;
|
||||||
|
this.Plugin.Config.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drag != null && drag.Value.dst < this.Plugin.Config.Filters.Count && drag.Value.dst >= 0) {
|
||||||
|
this._dragging = drag.Value.dst;
|
||||||
|
var temp = this.Plugin.Config.Filters[drag.Value.src];
|
||||||
|
this.Plugin.Config.Filters[drag.Value.src] = this.Plugin.Config.Filters[drag.Value.dst];
|
||||||
|
this.Plugin.Config.Filters[drag.Value.dst] = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toRemove != null) {
|
||||||
|
this.Plugin.Config.Filters.RemoveAt(toRemove.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.EndChild();
|
ImGui.EndChild();
|
||||||
|
|
|
@ -28,6 +28,16 @@ namespace SoundFilter.Ui {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui.Checkbox(Language.LogEnableLogging, ref this.Plugin.Config.LogEnabled)) {
|
||||||
|
this.Plugin.Config.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
|
||||||
|
if (ImGui.Checkbox(Language.LogLogFiltered, ref this.Plugin.Config.LogFiltered)) {
|
||||||
|
this.Plugin.Config.Save();
|
||||||
|
}
|
||||||
|
|
||||||
ImGui.InputText(Language.LogSearch, ref this._search, 255);
|
ImGui.InputText(Language.LogSearch, ref this._search, 255);
|
||||||
|
|
||||||
var entries = (int) this.Plugin.Config.LogEntries;
|
var entries = (int) this.Plugin.Config.LogEntries;
|
||||||
|
|
Loading…
Reference in New Issue