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(' ');
if (split.Length < 1) {
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;
}
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) {
chat.PrintError($"[{SoundFilterPlugin.Name}] {Language.CommandNoSuchFilter}");
return;

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Configuration;
using Dalamud.Plugin;
using DotNet.Globbing;
@ -8,30 +7,37 @@ using DotNet.Globbing;
namespace SoundFilter.Config {
[Serializable]
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 Dictionary<string, Glob> CachedGlobs { get; } = new();
public bool Enabled = true;
public bool ShowLog;
public bool LogEnabled = true;
public bool LogFiltered = false;
public uint LogEntries = 250;
public Dictionary<string, CustomFilter> Filtered { get; set; } = new();
public List<CustomFilter> Filters { get; set; } = new();
internal IReadOnlyDictionary<Glob, bool> Globs {
get {
return this.Filtered.ToDictionary(
entry => {
if (this.CachedGlobs.TryGetValue(entry.Key, out var cached)) {
return cached;
var dictionary = new Dictionary<Glob, bool>();
foreach (var filter in this.Filters) {
foreach (var globString in filter.Globs) {
if (this.CachedGlobs.TryGetValue(globString, out var cached)) {
dictionary[cached] = filter.Enabled;
continue;
}
var glob = Glob.Parse(entry.Key);
this.CachedGlobs[entry.Key] = glob;
return glob;
},
entry => entry.Value.Enabled
);
var glob = Glob.Parse(globString);
this.CachedGlobs[globString] = glob;
dictionary[glob] = filter.Enabled;
}
}
return dictionary;
}
}

View File

@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
namespace SoundFilter.Config {
[Serializable]
internal class CustomFilter {
public string Name = "Unnamed filter";
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();
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
.Where(entry => entry.Value)
.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) {
return this.PlaySpecificSoundHook!.Original((long) this.InfoPtr, 0);
}

View File

@ -1,171 +1,207 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SoundFilter.Resources {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Language {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Language() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SoundFilter.Resources.Language", typeof(Language).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Invalid subcommand..
/// </summary>
internal static string CommandInvalidSubcommand {
get {
return ResourceManager.GetString("CommandInvalidSubcommand", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No such filter..
/// </summary>
internal static string CommandNoSuchFilter {
get {
return ResourceManager.GetString("CommandNoSuchFilter", resourceCulture);
}
}
/// <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.
/// </summary>
internal static string CommandNotEnoughArguments {
get {
return ResourceManager.GetString("CommandNotEnoughArguments", resourceCulture);
}
}
/// <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..
/// </summary>
internal static string LoadWarning {
get {
return ResourceManager.GetString("LoadWarning", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Max sounds.
/// </summary>
internal static string LogMaxRecentSounds {
get {
return ResourceManager.GetString("LogMaxRecentSounds", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Search.
/// </summary>
internal static string LogSearch {
get {
return ResourceManager.GetString("LogSearch", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sound log.
/// </summary>
internal static string LogWindowTitle {
get {
return ResourceManager.GetString("LogWindowTitle", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Filter name.
/// </summary>
internal static string SettingsAddFilterName {
get {
return ResourceManager.GetString("SettingsAddFilterName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sound path to filter.
/// </summary>
internal static string SettingsAddPathToFilter {
get {
return ResourceManager.GetString("SettingsAddPathToFilter", 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);
}
}
}
}
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SoundFilter.Resources {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Language {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Language() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SoundFilter.Resources.Language", typeof(Language).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Invalid subcommand..
/// </summary>
internal static string CommandInvalidSubcommand {
get {
return ResourceManager.GetString("CommandInvalidSubcommand", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No such filter..
/// </summary>
internal static string CommandNoSuchFilter {
get {
return ResourceManager.GetString("CommandNoSuchFilter", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Not enough arguments..
/// </summary>
internal static string CommandNotEnoughArguments {
get {
return ResourceManager.GetString("CommandNotEnoughArguments", resourceCulture);
}
}
/// <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..
/// </summary>
internal static string LoadWarning {
get {
return ResourceManager.GetString("LoadWarning", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Enable logging.
/// </summary>
internal static string LogEnableLogging {
get {
return ResourceManager.GetString("LogEnableLogging", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Log filtered.
/// </summary>
internal static string LogLogFiltered {
get {
return ResourceManager.GetString("LogLogFiltered", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Max sounds.
/// </summary>
internal static string LogMaxRecentSounds {
get {
return ResourceManager.GetString("LogMaxRecentSounds", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Search.
/// </summary>
internal static string LogSearch {
get {
return ResourceManager.GetString("LogSearch", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sound log.
/// </summary>
internal static string LogWindowTitle {
get {
return ResourceManager.GetString("LogWindowTitle", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Add filter.
/// </summary>
internal static string SettingsAddFilter {
get {
return ResourceManager.GetString("SettingsAddFilter", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Filter name.
/// </summary>
internal static string SettingsAddFilterName {
get {
return ResourceManager.GetString("SettingsAddFilterName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sound path to filter.
/// </summary>
internal static string SettingsAddPathToFilter {
get {
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>
</data>
<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 name="CommandInvalidSubcommand" xml:space="preserve">
<value>Invalid subcommand.</value>
@ -54,4 +54,16 @@
<data name="CommandNoSuchFilter" xml:space="preserve">
<value>No such filter.</value>
</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>

View File

@ -19,6 +19,10 @@
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\ImGuiScene.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Newtonsoft.Json.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resources\Language.resx">

View File

@ -20,7 +20,7 @@ namespace SoundFilter {
internal SoundFilterPlugin(DalamudPluginInterface @interface) {
this.Interface = @interface;
this.Config = this.Interface.GetPluginConfig() as Configuration ?? new Configuration();
this.Config = Migrator.LoadConfiguration(this);
this.Config.Initialise(this.Interface);
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.Linq;
using System.Numerics;
using Dalamud.Interface;
using ImGuiNET;
using SoundFilter.Config;
using SoundFilter.Resources;
namespace SoundFilter.Ui {
public class Settings : IDisposable {
private SoundFilterPlugin Plugin { get; }
private AddFilter AddFilter { get; }
private AddFilter? EditFilter { get; set; }
private bool _showWindow;
private string _filterName = string.Empty;
private string _soundPath = string.Empty;
private int _dragging = -1;
internal Settings(SoundFilterPlugin plugin) {
this.Plugin = plugin;
this.AddFilter = new AddFilter(plugin);
this.Plugin.Interface.UiBuilder.OnOpenConfigUi += this.Toggle;
}
@ -33,6 +33,19 @@ namespace SoundFilter.Ui {
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);
var windowTitle = string.Format(Language.SettingsWindowTitle, SoundFilterPlugin.Name);
@ -56,49 +69,80 @@ namespace SoundFilter.Ui {
ImGui.Separator();
ImGui.TextUnformatted(Language.SettingsAddFilterName);
ImGui.InputText("##sound-filter-name", ref this._filterName, 255);
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;
if (ImGui.CollapsingHeader(Language.SettingsAddFilter)) {
this.AddFilter.Draw();
}
ImGui.Separator();
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()) {
var glob = entry.Key;
if (Util.IconButton(FontAwesomeIcon.Trash, $"delete-{glob}")) {
this.Plugin.Config.Filtered.Remove(glob);
if (Util.IconButton(FontAwesomeIcon.Trash, $"delete-filter-{i}")) {
toRemove = i;
shouldSave = true;
}
ImGui.SameLine();
if (Util.IconButton(FontAwesomeIcon.Copy, $"copy-{glob}")) {
ImGui.SetClipboardText(glob);
if (Util.IconButton(FontAwesomeIcon.PencilAlt, $"edit-filter-{i}")) {
this.EditFilter = new AddFilter(this.Plugin, filter);
}
ImGui.SameLine();
shouldSave |= ImGui.Checkbox($"{entry.Value.Name}##{i}-{glob}", ref entry.Value.Enabled);
if (ImGui.IsItemHovered()) {
ImGui.BeginTooltip();
ImGui.TextUnformatted(glob);
ImGui.EndTooltip();
if (Util.IconButton(FontAwesomeIcon.Copy, $"copy-filter-{i}")) {
ImGui.SetClipboardText(string.Join("\n", filter.Globs));
}
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();

View File

@ -28,6 +28,16 @@ namespace SoundFilter.Ui {
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);
var entries = (int) this.Plugin.Config.LogEntries;