feat: add reordering, editing, and multiple globs per filter

This commit is contained in:
Anna 2021-05-11 21:58:38 -04:00
parent cd3b8bd066
commit af20de19fd
12 changed files with 549 additions and 223 deletions

View File

@ -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;

View File

@ -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;
} }
} }

View File

@ -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();
} }
} }

88
SoundFilter/Config/Migrator.cs Executable file
View File

@ -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();
}
}
}

View File

@ -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);
} }

View File

@ -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 &apos;enable&apos; or &apos;disable&apos; 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&apos;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&apos;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);
}
}
}
}

View File

@ -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>

View File

@ -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">

View File

@ -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);

113
SoundFilter/Ui/AddFilter.cs Executable file
View File

@ -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();
}
}
}

View File

@ -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();

View File

@ -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;