diff --git a/Dalamud/Game/Gui/GameGui.cs b/Dalamud/Game/Gui/GameGui.cs
index 6b9be88b4..18f59c75a 100644
--- a/Dalamud/Game/Gui/GameGui.cs
+++ b/Dalamud/Game/Gui/GameGui.cs
@@ -363,7 +363,7 @@ public sealed unsafe class GameGui : IDisposable, IServiceType
///
/// The addon address.
/// A pointer to the agent interface.
- public unsafe IntPtr FindAgentInterface(IntPtr addonPtr)
+ public IntPtr FindAgentInterface(IntPtr addonPtr)
{
if (addonPtr == IntPtr.Zero)
return IntPtr.Zero;
@@ -411,11 +411,26 @@ public sealed unsafe class GameGui : IDisposable, IServiceType
this.utf8StringFromSequenceHook.Dispose();
}
+ ///
+ /// Indicates if the game is on the title screen.
+ ///
+ /// A value indicating whether or not the game is on the title screen.
+ internal bool IsOnTitleScreen()
+ {
+ var charaSelect = this.GetAddonByName("CharaSelect", 1);
+ var charaMake = this.GetAddonByName("CharaMake", 1);
+ var titleDcWorldMap = this.GetAddonByName("TitleDCWorldMap", 1);
+ if (charaMake != nint.Zero || charaSelect != nint.Zero || titleDcWorldMap != nint.Zero)
+ return false;
+
+ return !Service.Get().IsLoggedIn;
+ }
+
///
/// Set the current background music.
///
/// The background music key.
- public void SetBgm(ushort bgmKey) => this.setGlobalBgmHook.Original(bgmKey, 0, 0, 0, 0, 0);
+ internal void SetBgm(ushort bgmKey) => this.setGlobalBgmHook.Original(bgmKey, 0, 0, 0, 0, 0);
///
/// Reset the stored "UI hide" state.
diff --git a/Dalamud/Interface/Internal/DalamudCommands.cs b/Dalamud/Interface/Internal/DalamudCommands.cs
index 2d49a8163..7855f9c54 100644
--- a/Dalamud/Interface/Internal/DalamudCommands.cs
+++ b/Dalamud/Interface/Internal/DalamudCommands.cs
@@ -101,11 +101,6 @@ internal class DalamudCommands : IServiceType
HelpMessage = Loc.Localize("DalamudInstallerHelp", "Open the plugin installer"),
});
- commandManager.AddHandler("/xlcredits", new CommandInfo(this.OnOpenCreditsCommand)
- {
- HelpMessage = Loc.Localize("DalamudCreditsHelp", "Opens the credits for dalamud."),
- });
-
commandManager.AddHandler("/xllanguage", new CommandInfo(this.OnSetLanguageCommand)
{
HelpMessage =
@@ -328,11 +323,6 @@ internal class DalamudCommands : IServiceType
Service.Get().TogglePluginInstallerWindow();
}
- private void OnOpenCreditsCommand(string command, string arguments)
- {
- Service.Get().ToggleCreditsWindow();
- }
-
private void OnSetLanguageCommand(string command, string arguments)
{
var chatGui = Service.Get();
diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs
index 68393bfa5..14d8f10de 100644
--- a/Dalamud/Interface/Internal/DalamudInterface.cs
+++ b/Dalamud/Interface/Internal/DalamudInterface.cs
@@ -12,11 +12,13 @@ using Dalamud.Configuration.Internal;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.Gui;
using Dalamud.Game.Internal;
+using Dalamud.Interface.Animation.EasingFunctions;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Internal.ManagedAsserts;
using Dalamud.Interface.Internal.Windows;
using Dalamud.Interface.Internal.Windows.PluginInstaller;
using Dalamud.Interface.Internal.Windows.SelfTest;
+using Dalamud.Interface.Internal.Windows.Settings;
using Dalamud.Interface.Internal.Windows.StyleEditor;
using Dalamud.Interface.Style;
using Dalamud.Interface.Windowing;
@@ -40,12 +42,13 @@ namespace Dalamud.Interface.Internal;
[ServiceManager.EarlyLoadedService]
internal class DalamudInterface : IDisposable, IServiceType
{
+ private const float CreditsDarkeningMaxAlpha = 0.8f;
+
private static readonly ModuleLog Log = new("DUI");
private readonly ChangelogWindow changelogWindow;
private readonly ColorDemoWindow colorDemoWindow;
private readonly ComponentDemoWindow componentDemoWindow;
- private readonly CreditsWindow creditsWindow;
private readonly DataWindow dataWindow;
private readonly GamepadModeNotifierWindow gamepadModeNotifierWindow;
private readonly ImeWindow imeWindow;
@@ -62,6 +65,9 @@ internal class DalamudInterface : IDisposable, IServiceType
private readonly TextureWrap logoTexture;
private readonly TextureWrap tsmLogoTexture;
+ private bool isCreditsDarkening = false;
+ private OutCubic creditsDarkeningAnimation = new(TimeSpan.FromSeconds(10));
+
#if DEBUG
private bool isImGuiDrawDevMenu = true;
#else
@@ -90,7 +96,6 @@ internal class DalamudInterface : IDisposable, IServiceType
this.changelogWindow = new ChangelogWindow() { IsOpen = false };
this.colorDemoWindow = new ColorDemoWindow() { IsOpen = false };
this.componentDemoWindow = new ComponentDemoWindow() { IsOpen = false };
- this.creditsWindow = new CreditsWindow() { IsOpen = false };
this.dataWindow = new DataWindow() { IsOpen = false };
this.gamepadModeNotifierWindow = new GamepadModeNotifierWindow() { IsOpen = false };
this.imeWindow = new ImeWindow() { IsOpen = false };
@@ -107,7 +112,6 @@ internal class DalamudInterface : IDisposable, IServiceType
this.WindowSystem.AddWindow(this.changelogWindow);
this.WindowSystem.AddWindow(this.colorDemoWindow);
this.WindowSystem.AddWindow(this.componentDemoWindow);
- this.WindowSystem.AddWindow(this.creditsWindow);
this.WindowSystem.AddWindow(this.dataWindow);
this.WindowSystem.AddWindow(this.gamepadModeNotifierWindow);
this.WindowSystem.AddWindow(this.imeWindow);
@@ -147,6 +151,9 @@ internal class DalamudInterface : IDisposable, IServiceType
{
tsm.AddEntryCore(Loc.Localize("TSMDalamudDevMenu", "Developer Menu"), this.tsmLogoTexture, () => this.isImGuiDrawDevMenu = true);
}
+
+ this.creditsDarkeningAnimation.Point1 = Vector2.Zero;
+ this.creditsDarkeningAnimation.Point2 = new Vector2(CreditsDarkeningMaxAlpha);
}
///
@@ -176,7 +183,6 @@ internal class DalamudInterface : IDisposable, IServiceType
this.WindowSystem.RemoveAllWindows();
this.changelogWindow.Dispose();
- this.creditsWindow.Dispose();
this.consoleWindow.Dispose();
this.pluginWindow.Dispose();
this.titleScreenMenuWindow.Dispose();
@@ -202,11 +208,6 @@ internal class DalamudInterface : IDisposable, IServiceType
///
public void OpenComponentDemoWindow() => this.componentDemoWindow.IsOpen = true;
- ///
- /// Opens the .
- ///
- public void OpenCreditsWindow() => this.creditsWindow.IsOpen = true;
-
///
/// Opens the .
///
@@ -313,11 +314,6 @@ internal class DalamudInterface : IDisposable, IServiceType
///
public void ToggleComponentDemoWindow() => this.componentDemoWindow.Toggle();
- ///
- /// Toggles the .
- ///
- public void ToggleCreditsWindow() => this.creditsWindow.Toggle();
-
///
/// Toggles the .
///
@@ -388,6 +384,18 @@ internal class DalamudInterface : IDisposable, IServiceType
#endregion
+ ///
+ /// Toggle the screen darkening effect used for the credits.
+ ///
+ /// Whether or not to turn the effect on.
+ public void SetCreditsDarkeningAnimation(bool status)
+ {
+ this.isCreditsDarkening = status;
+
+ if (status)
+ this.creditsDarkeningAnimation.Restart();
+ }
+
private void OnDraw()
{
this.FrameCount++;
@@ -430,6 +438,9 @@ internal class DalamudInterface : IDisposable, IServiceType
if (this.isImGuiTestWindowsInMonospace)
ImGui.PopFont();
+ if (this.isCreditsDarkening)
+ this.DrawCreditsDarkeningAnimation();
+
// Release focus of any ImGui window if we click into the game.
var io = ImGui.GetIO();
if (!io.WantCaptureMouse && (User32.GetKeyState((int)User32.VirtualKey.VK_LBUTTON) & 0x8000) != 0)
@@ -443,6 +454,26 @@ internal class DalamudInterface : IDisposable, IServiceType
}
}
+ private void DrawCreditsDarkeningAnimation()
+ {
+ ImGui.PushStyleVar(ImGuiStyleVar.WindowRounding, 0f);
+ ImGui.SetNextWindowPos(new Vector2(0, 0));
+ ImGui.SetNextWindowSize(ImGuiHelpers.MainViewport.Size);
+ ImGuiHelpers.ForceNextWindowMainViewport();
+
+ this.creditsDarkeningAnimation.Update();
+ ImGui.SetNextWindowBgAlpha(Math.Min(this.creditsDarkeningAnimation.EasedPoint.X, CreditsDarkeningMaxAlpha));
+
+ ImGui.Begin(
+ "###CreditsDarkenWindow",
+ ImGuiWindowFlags.NoInputs | ImGuiWindowFlags.NoDocking | ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoMove |
+ ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoFocusOnAppearing | ImGuiWindowFlags.NoBringToFrontOnFocus |
+ ImGuiWindowFlags.NoNav);
+ ImGui.End();
+
+ ImGui.PopStyleVar();
+ }
+
private void DrawHiddenDevMenuOpener()
{
var condition = Service.Get();
@@ -573,11 +604,6 @@ internal class DalamudInterface : IDisposable, IServiceType
this.OpenDataWindow();
}
- if (ImGui.MenuItem("Open Credits window"))
- {
- this.OpenCreditsWindow();
- }
-
if (ImGui.MenuItem("Open Settings window"))
{
this.OpenSettings();
diff --git a/Dalamud/Interface/Internal/Windows/ConsoleWindow.cs b/Dalamud/Interface/Internal/Windows/ConsoleWindow.cs
index 0d19a340a..d2d51b8d6 100644
--- a/Dalamud/Interface/Internal/Windows/ConsoleWindow.cs
+++ b/Dalamud/Interface/Internal/Windows/ConsoleWindow.cs
@@ -52,7 +52,7 @@ internal class ConsoleWindow : Window, IDisposable
/// Initializes a new instance of the class.
///
public ConsoleWindow()
- : base("Dalamud Console")
+ : base("Dalamud Console", ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse)
{
var configuration = Service.Get();
diff --git a/Dalamud/Interface/Internal/Windows/Settings/SettingsEntry.cs b/Dalamud/Interface/Internal/Windows/Settings/SettingsEntry.cs
new file mode 100644
index 000000000..5e1dc7884
--- /dev/null
+++ b/Dalamud/Interface/Internal/Windows/Settings/SettingsEntry.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Dalamud.Interface.Internal.Windows.Settings;
+
+///
+/// Basic, drawable settings entry.
+///
+public abstract class SettingsEntry
+{
+ ///
+ /// Gets or sets the public, searchable name of this settings entry.
+ ///
+ public string? Name { get; protected set; }
+
+ ///
+ /// Gets or sets a value indicating whether or not this entry is valid.
+ ///
+ public virtual bool IsValid { get; protected set; } = true;
+
+ ///
+ /// Gets or sets a value indicating whether or not this entry is visible.
+ ///
+ public virtual bool IsVisible { get; protected set; } = true;
+
+ ///
+ /// Gets the ID of this settings entry, used for ImGui uniqueness.
+ ///
+ protected Guid Id { get; } = Guid.NewGuid();
+
+ ///
+ /// Load this setting.
+ ///
+ public abstract void Load();
+
+ ///
+ /// Save this setting.
+ ///
+ public abstract void Save();
+
+ ///
+ /// Draw this setting control.
+ ///
+ public abstract void Draw();
+
+ ///
+ /// Function to be called when the tab is closed.
+ ///
+ public virtual void OnClose()
+ {
+ // ignored
+ }
+}
diff --git a/Dalamud/Interface/Internal/Windows/Settings/SettingsTab.cs b/Dalamud/Interface/Internal/Windows/Settings/SettingsTab.cs
new file mode 100644
index 000000000..16b7749cb
--- /dev/null
+++ b/Dalamud/Interface/Internal/Windows/Settings/SettingsTab.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Dalamud.Interface.Internal.Windows.Settings;
+
+[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Internals")]
+public abstract class SettingsTab : IDisposable
+{
+ public abstract SettingsEntry[] Entries { get; }
+
+ public abstract string Title { get; }
+
+ public bool IsOpen { get; set; } = false;
+
+ public virtual bool IsVisible { get; } = true;
+
+ public virtual void OnOpen()
+ {
+ // ignored
+ }
+
+ public virtual void OnClose()
+ {
+ foreach (var settingsEntry in this.Entries)
+ {
+ settingsEntry.OnClose();
+ }
+ }
+
+ public virtual void Draw()
+ {
+ foreach (var settingsEntry in this.Entries)
+ {
+ if (settingsEntry.IsVisible)
+ settingsEntry.Draw();
+
+ ImGuiHelpers.ScaledDummy(5);
+ }
+
+ ImGuiHelpers.ScaledDummy(15);
+ }
+
+ public virtual void Load()
+ {
+ foreach (var settingsEntry in this.Entries)
+ {
+ settingsEntry.Load();
+ }
+ }
+
+ public virtual void Save()
+ {
+ foreach (var settingsEntry in this.Entries)
+ {
+ settingsEntry.Save();
+ }
+ }
+
+ public virtual void Discard()
+ {
+ foreach (var settingsEntry in this.Entries)
+ {
+ settingsEntry.Load();
+ }
+ }
+
+ ///
+ public virtual void Dispose()
+ {
+ // ignored
+ }
+}
diff --git a/Dalamud/Interface/Internal/Windows/Settings/SettingsWindow.cs b/Dalamud/Interface/Internal/Windows/Settings/SettingsWindow.cs
new file mode 100644
index 000000000..24423b48c
--- /dev/null
+++ b/Dalamud/Interface/Internal/Windows/Settings/SettingsWindow.cs
@@ -0,0 +1,232 @@
+using System.Linq;
+using System.Numerics;
+
+using CheapLoc;
+using Dalamud.Configuration.Internal;
+using Dalamud.Interface.Colors;
+using Dalamud.Interface.Internal.Windows.Settings.Tabs;
+using Dalamud.Interface.Windowing;
+using Dalamud.Plugin.Internal;
+using Dalamud.Utility;
+using ImGuiNET;
+
+namespace Dalamud.Interface.Internal.Windows.Settings;
+
+///
+/// The window that allows for general configuration of Dalamud itself.
+///
+internal class SettingsWindow : Window
+{
+ private readonly SettingsTab[] tabs =
+ {
+ new SettingsTabGeneral(),
+ new SettingsTabLook(),
+ new SettingsTabDtr(),
+ new SettingsTabExperimental(),
+ new SettingsTabAbout(),
+ };
+
+ private string searchInput = string.Empty;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SettingsWindow()
+ : base(Loc.Localize("DalamudSettingsHeader", "Dalamud Settings") + "###XlSettings2", ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoScrollbar)
+ {
+ this.Size = new Vector2(740, 550);
+ this.SizeConstraints = new WindowSizeConstraints()
+ {
+ MinimumSize = new Vector2(752, 610),
+ MaximumSize = new Vector2(1780, 940),
+ };
+
+ this.SizeCondition = ImGuiCond.FirstUseEver;
+ }
+
+ ///
+ public override void OnOpen()
+ {
+ foreach (var settingsTab in this.tabs)
+ {
+ settingsTab.Load();
+ }
+
+ this.searchInput = string.Empty;
+
+ base.OnOpen();
+ }
+
+ ///
+ public override void OnClose()
+ {
+ var configuration = Service.Get();
+ var interfaceManager = Service.Get();
+
+ var rebuildFont =
+ ImGui.GetIO().FontGlobalScale != configuration.GlobalUiScale ||
+ interfaceManager.FontGamma != configuration.FontGammaLevel ||
+ interfaceManager.UseAxis != configuration.UseAxisFontsFromGame;
+
+ ImGui.GetIO().FontGlobalScale = configuration.GlobalUiScale;
+ interfaceManager.FontGammaOverride = null;
+ interfaceManager.UseAxisOverride = null;
+
+ if (rebuildFont)
+ interfaceManager.RebuildFonts();
+
+ foreach (var settingsTab in this.tabs)
+ {
+ if (settingsTab.IsOpen)
+ settingsTab.OnClose();
+
+ settingsTab.IsOpen = false;
+ }
+ }
+
+ ///
+ public override void Draw()
+ {
+ var windowSize = ImGui.GetWindowSize();
+
+ if (ImGui.BeginTabBar("###settingsTabs"))
+ {
+ if (string.IsNullOrEmpty(this.searchInput))
+ {
+ foreach (var settingsTab in this.tabs.Where(x => x.IsVisible))
+ {
+ if (ImGui.BeginTabItem(settingsTab.Title))
+ {
+ if (!settingsTab.IsOpen)
+ {
+ settingsTab.IsOpen = true;
+ settingsTab.OnOpen();
+ }
+
+ if (ImGui.BeginChild($"###settings_scrolling_{settingsTab.Title}", new Vector2(-1, -1), false))
+ {
+ settingsTab.Draw();
+ }
+
+ ImGui.EndChild();
+ ImGui.EndTabItem();
+ }
+ else if (settingsTab.IsOpen)
+ {
+ settingsTab.IsOpen = false;
+ settingsTab.OnClose();
+ }
+ }
+ }
+ else
+ {
+ if (ImGui.BeginTabItem("Search Results"))
+ {
+ var any = false;
+
+ foreach (var settingsTab in this.tabs.Where(x => x.IsVisible))
+ {
+ var eligible = settingsTab.Entries.Where(x => !x.Name.IsNullOrEmpty() && x.Name.ToLower().Contains(this.searchInput.ToLower())).ToArray();
+
+ if (!eligible.Any())
+ continue;
+
+ any = true;
+
+ ImGui.TextColored(ImGuiColors.DalamudGrey, settingsTab.Title);
+ ImGui.Dummy(new Vector2(5));
+
+ foreach (var settingsTabEntry in eligible)
+ {
+ settingsTabEntry.Draw();
+ ImGuiHelpers.ScaledDummy(3);
+ }
+
+ ImGui.Separator();
+
+ ImGui.Dummy(new Vector2(10));
+ }
+
+ if (!any)
+ ImGui.TextColored(ImGuiColors.DalamudGrey, "No results found...");
+
+ ImGui.EndTabItem();
+ }
+ }
+ }
+
+ ImGui.SetCursorPos(windowSize - ImGuiHelpers.ScaledVector2(70));
+
+ if (ImGui.BeginChild("###settingsFinishButton"))
+ {
+ ImGui.PushStyleVar(ImGuiStyleVar.FrameRounding, 100f);
+ ImGui.PushFont(InterfaceManager.IconFont);
+
+ var invalid = this.tabs.Any(x => x.Entries.Any(y => !y.IsValid));
+ if (invalid)
+ ImGui.BeginDisabled();
+
+ if (ImGui.Button(FontAwesomeIcon.Save.ToIconString(), new Vector2(40)))
+ {
+ this.Save();
+
+ this.IsOpen = false;
+ }
+
+ ImGui.PopStyleVar();
+ ImGui.PopFont();
+
+ if (ImGui.IsItemHovered())
+ ImGui.SetTooltip(Loc.Localize("DalamudSettingsSaveAndExit", "Save changes and close"));
+
+ if (invalid)
+ ImGui.EndDisabled();
+ }
+
+ ImGui.EndChild();
+
+ ImGui.SetCursorPos(new Vector2(windowSize.X - 250, ImGui.GetTextLineHeightWithSpacing() + (ImGui.GetStyle().FramePadding.Y * 2)));
+ ImGui.SetNextItemWidth(240);
+ ImGui.InputTextWithHint("###searchInput", "Search for settings...", ref this.searchInput, 100);
+ }
+
+ private void Save()
+ {
+ var configuration = Service.Get();
+
+ foreach (var settingsTab in this.tabs)
+ {
+ settingsTab.Save();
+ }
+
+ // Apply docking flag
+ if (!configuration.IsDocking)
+ {
+ ImGui.GetIO().ConfigFlags &= ~ImGuiConfigFlags.DockingEnable;
+ }
+ else
+ {
+ ImGui.GetIO().ConfigFlags |= ImGuiConfigFlags.DockingEnable;
+ }
+
+ // NOTE (Chiv) Toggle gamepad navigation via setting
+ if (!configuration.IsGamepadNavigationEnabled)
+ {
+ ImGui.GetIO().BackendFlags &= ~ImGuiBackendFlags.HasGamepad;
+ ImGui.GetIO().ConfigFlags &= ~ImGuiConfigFlags.NavEnableSetMousePos;
+
+ var di = Service.Get();
+ di.CloseGamepadModeNotifierWindow();
+ }
+ else
+ {
+ ImGui.GetIO().BackendFlags |= ImGuiBackendFlags.HasGamepad;
+ ImGui.GetIO().ConfigFlags |= ImGuiConfigFlags.NavEnableSetMousePos;
+ }
+
+ configuration.QueueSave();
+
+ _ = Service.Get().ReloadPluginMastersAsync();
+ Service.Get().RebuildFonts();
+ }
+}
diff --git a/Dalamud/Interface/Internal/Windows/CreditsWindow.cs b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs
similarity index 70%
rename from Dalamud/Interface/Internal/Windows/CreditsWindow.cs
rename to Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs
index 83857a826..3ad67a841 100644
--- a/Dalamud/Interface/Internal/Windows/CreditsWindow.cs
+++ b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs
@@ -1,23 +1,22 @@
-using System;
+using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Numerics;
+using CheapLoc;
using Dalamud.Game.Gui;
using Dalamud.Interface.GameFonts;
-using Dalamud.Interface.Windowing;
using Dalamud.Plugin.Internal;
using Dalamud.Utility;
using ImGuiNET;
using ImGuiScene;
-namespace Dalamud.Interface.Internal.Windows;
+namespace Dalamud.Interface.Internal.Windows.Settings.Tabs;
-///
-/// A window documenting contributors to the project.
-///
-internal class CreditsWindow : Window, IDisposable
+[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Internals")]
+public class SettingsTabAbout : SettingsTab
{
private const float CreditFps = 60.0f;
private const string ThankYouText = "Thank you!";
@@ -27,7 +26,8 @@ A FFXIV Plugin Framework
Version D{0}
-created by:
+
+Created by:
goat
daemitus
@@ -124,8 +124,15 @@ philpax
We use these awesome libraries:
+FFXIVClientStructs ({2})
+Copyright (c) 2021 aers
+Licensed under the MIT License
+
Lumina by Adam
-FFXIVClientStructs by aers ({2})
+Licensed under the WTFPL v2.0
+
+Reloaded Libraries by Sewer56
+Licensed under the GNU Lesser General Public License v3.0
DotNetCorePlugins
Copyright (c) Nate McMaster
@@ -145,17 +152,20 @@ Licensed under the BSD 2-Clause License
SRELL
Copyright (c) 2012-2022, Nozomu Katoo
+STB Libraries
+Copyright (c) 2017 Sean Barrett
+Licensed under the MIT License
+
Please see licenses.txt for more information.
-Thanks to everyone in the XIVLauncher Discord server
-
+Thanks to everyone in the XIVLauncher Discord server!
Join us at: https://discord.gg/3NMcUV5
-Dalamud is licensed under AGPL v3 or later
-Contribute at: https://github.com/goatsoft/Dalamud
+Dalamud is licensed under AGPL v3 or later.
+Contribute at: https://github.com/goatcorp/Dalamud
";
private readonly TextureWrap logoTexture;
@@ -163,28 +173,22 @@ Contribute at: https://github.com/goatsoft/Dalamud
private string creditsText;
+ private bool resetNow = false;
private GameFontHandle? thankYouFont;
- ///
- /// Initializes a new instance of the class.
- ///
- public CreditsWindow()
- : base("Dalamud Credits", ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoTitleBar, true)
+ public SettingsTabAbout()
{
var dalamud = Service.Get();
var interfaceManager = Service.Get();
- this.logoTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "logo.png"));
+ this.logoTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "logo.png"))!;
this.creditsThrottler = new();
-
- this.Size = new Vector2(500, 400);
- this.SizeCondition = ImGuiCond.Always;
-
- this.PositionCondition = ImGuiCond.Always;
-
- this.BgAlpha = 0.8f;
}
+ public override SettingsEntry[] Entries { get; } = { };
+
+ public override string Title => Loc.Localize("DalamudAbout", "About");
+
///
public override void OnOpen()
{
@@ -195,7 +199,10 @@ Contribute at: https://github.com/goatsoft/Dalamud
this.creditsText = string.Format(CreditsTextTempl, typeof(Dalamud).Assembly.GetName().Version, pluginCredits, Util.GetGitHashClientStructs());
- Service.Get().SetBgm(833);
+ var gg = Service.Get();
+ if (!gg.IsOnTitleScreen())
+ gg.SetBgm(833);
+
this.creditsThrottler.Restart();
if (this.thankYouFont == null)
@@ -203,41 +210,36 @@ Contribute at: https://github.com/goatsoft/Dalamud
var gfm = Service.Get();
this.thankYouFont = gfm.NewFontRef(new GameFontStyle(GameFontFamilyAndSize.TrumpGothic34));
}
+
+ this.resetNow = true;
+
+ Service.Get().SetCreditsDarkeningAnimation(true);
}
///
public override void OnClose()
{
this.creditsThrottler.Reset();
- Service.Get().SetBgm(9999);
+
+ var gg = Service.Get();
+ if (!gg.IsOnTitleScreen())
+ gg.SetBgm(9999);
+
+ Service.Get().SetCreditsDarkeningAnimation(false);
}
- ///
- public override void PreDraw()
- {
- ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(0, 0));
-
- base.PreDraw();
- }
-
- ///
- public override void PostDraw()
- {
- ImGui.PopStyleVar();
-
- base.PostDraw();
- }
-
- ///
public override void Draw()
{
- var screenSize = ImGui.GetMainViewport().Size;
var windowSize = ImGui.GetWindowSize();
- this.Position = (screenSize - windowSize) / 2;
-
ImGui.BeginChild("scrolling", Vector2.Zero, false, ImGuiWindowFlags.NoScrollbar);
+ if (this.resetNow)
+ {
+ ImGui.SetScrollY(0);
+ this.resetNow = false;
+ }
+
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, Vector2.Zero);
ImGuiHelpers.ScaledDummy(0, windowSize.Y + 20f);
@@ -295,30 +297,13 @@ Contribute at: https://github.com/goatsoft/Dalamud
ImGui.EndChild();
- ImGui.SetCursorPos(new Vector2(0));
- ImGui.BeginChild("button", Vector2.Zero, false, ImGuiWindowFlags.NoScrollbar);
-
- var closeButtonSize = new Vector2(30);
- ImGui.PushFont(InterfaceManager.IconFont);
- ImGui.SetCursorPos(new Vector2(windowSize.X - closeButtonSize.X - 5, 5));
- ImGui.PushStyleColor(ImGuiCol.Button, Vector4.Zero);
- ImGui.PushStyleColor(ImGuiCol.ButtonHovered, Vector4.Zero);
- ImGui.PushStyleColor(ImGuiCol.ButtonActive, Vector4.Zero);
-
- if (ImGui.Button(FontAwesomeIcon.Times.ToIconString(), closeButtonSize))
- {
- this.IsOpen = false;
- }
-
- ImGui.PopStyleColor(3);
- ImGui.PopFont();
- ImGui.EndChild();
+ base.Draw();
}
///
/// Disposes of managed and unmanaged resources.
///
- public void Dispose()
+ public override void Dispose()
{
this.logoTexture?.Dispose();
this.thankYouFont?.Dispose();
diff --git a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabDtr.cs b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabDtr.cs
new file mode 100644
index 000000000..85cb8219f
--- /dev/null
+++ b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabDtr.cs
@@ -0,0 +1,162 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+
+using CheapLoc;
+using Dalamud.Configuration.Internal;
+using Dalamud.Game.Gui.Dtr;
+using Dalamud.Interface.Colors;
+using Dalamud.Interface.Components;
+using ImGuiNET;
+
+namespace Dalamud.Interface.Internal.Windows.Settings.Tabs;
+
+[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Internals")]
+public class SettingsTabDtr : SettingsTab
+{
+ private List? dtrOrder;
+ private List? dtrIgnore;
+ private int dtrSpacing;
+ private bool dtrSwapDirection;
+
+ public override SettingsEntry[] Entries { get; } = Array.Empty();
+
+ public override string Title => Loc.Localize("DalamudSettingsServerInfoBar", "Server Info Bar");
+
+ public override void Draw()
+ {
+ ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingServerInfoBarHint", "Plugins can put additional information into your server information bar(where world & time can be seen).\nYou can reorder and disable these here."));
+
+ ImGuiHelpers.ScaledDummy(10);
+
+ var configuration = Service.Get();
+ var dtrBar = Service.Get();
+
+ var order = configuration.DtrOrder!.Where(x => dtrBar.HasEntry(x)).ToList();
+ var ignore = configuration.DtrIgnore!.Where(x => dtrBar.HasEntry(x)).ToList();
+ var orderLeft = configuration.DtrOrder!.Where(x => !order.Contains(x)).ToList();
+ var ignoreLeft = configuration.DtrIgnore!.Where(x => !ignore.Contains(x)).ToList();
+
+ if (order.Count == 0)
+ {
+ ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingServerInfoBarDidNone", "You have no plugins that use this feature."));
+ }
+
+ var isOrderChange = false;
+ for (var i = 0; i < order.Count; i++)
+ {
+ var title = order[i];
+
+ // TODO: Maybe we can also resort the rest of the bar in the future?
+ // var isRequired = search is Configuration.SearchSetting.Internal or Configuration.SearchSetting.MacroLinks;
+
+ ImGui.PushFont(UiBuilder.IconFont);
+
+ var arrowUpText = $"{FontAwesomeIcon.ArrowUp.ToIconString()}##{title}";
+ if (i == 0)
+ {
+ ImGuiComponents.DisabledButton(arrowUpText);
+ }
+ else
+ {
+ if (ImGui.Button(arrowUpText))
+ {
+ (order[i], order[i - 1]) = (order[i - 1], order[i]);
+ isOrderChange = true;
+ }
+ }
+
+ ImGui.SameLine();
+
+ var arrowDownText = $"{FontAwesomeIcon.ArrowDown.ToIconString()}##{title}";
+ if (i == order.Count - 1)
+ {
+ ImGuiComponents.DisabledButton(arrowDownText);
+ }
+ else
+ {
+ if (ImGui.Button(arrowDownText) && i != order.Count - 1)
+ {
+ (order[i], order[i + 1]) = (order[i + 1], order[i]);
+ isOrderChange = true;
+ }
+ }
+
+ ImGui.PopFont();
+
+ ImGui.SameLine();
+
+ // if (isRequired) {
+ // ImGui.TextUnformatted($"Search in {name}");
+ // } else {
+
+ var isShown = ignore.All(x => x != title);
+ var nextIsShow = isShown;
+ if (ImGui.Checkbox($"{title}###dtrEntry{i}", ref nextIsShow) && nextIsShow != isShown)
+ {
+ if (nextIsShow)
+ ignore.Remove(title);
+ else
+ ignore.Add(title);
+
+ dtrBar.MakeDirty(title);
+ }
+
+ // }
+ }
+
+ configuration.DtrOrder = order.Concat(orderLeft).ToList();
+ configuration.DtrIgnore = ignore.Concat(ignoreLeft).ToList();
+
+ if (isOrderChange)
+ dtrBar.ApplySort();
+
+ ImGuiHelpers.ScaledDummy(10);
+
+ ImGui.Text(Loc.Localize("DalamudSettingServerInfoBarSpacing", "Server Info Bar spacing"));
+ ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingServerInfoBarSpacingHint", "Configure the amount of space between entries in the server info bar here."));
+ ImGui.SliderInt("Spacing", ref this.dtrSpacing, 0, 40);
+
+ ImGui.Text(Loc.Localize("DalamudSettingServerInfoBarDirection", "Server Info Bar direction"));
+ ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingServerInfoBarDirectionHint", "If checked, the Server Info Bar elements will expand to the right instead of the left."));
+ ImGui.Checkbox("Swap Direction", ref this.dtrSwapDirection);
+
+ base.Draw();
+ }
+
+ public override void OnClose()
+ {
+ var configuration = Service.Get();
+ configuration.DtrOrder = this.dtrOrder;
+ configuration.DtrIgnore = this.dtrIgnore;
+
+ base.OnClose();
+ }
+
+ public override void Load()
+ {
+ var configuration = Service.Get();
+
+ this.dtrSpacing = configuration.DtrSpacing;
+ this.dtrSwapDirection = configuration.DtrSwapDirection;
+
+ this.dtrOrder = configuration.DtrOrder;
+ this.dtrIgnore = configuration.DtrIgnore;
+
+ base.Load();
+ }
+
+ public override void Save()
+ {
+ var configuration = Service.Get();
+
+ configuration.DtrSpacing = this.dtrSpacing;
+ configuration.DtrSwapDirection = this.dtrSwapDirection;
+
+ this.dtrOrder = configuration.DtrOrder;
+ this.dtrIgnore = configuration.DtrIgnore;
+
+ base.Save();
+ }
+}
diff --git a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabExperimental.cs b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabExperimental.cs
new file mode 100644
index 000000000..a1c2c3336
--- /dev/null
+++ b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabExperimental.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+using CheapLoc;
+using Dalamud.Configuration.Internal;
+using Dalamud.Interface.Colors;
+using Dalamud.Interface.Internal.Windows.PluginInstaller;
+using Dalamud.Interface.Internal.Windows.Settings.Widgets;
+using Dalamud.Plugin.Internal;
+using Dalamud.Utility;
+
+namespace Dalamud.Interface.Internal.Windows.Settings.Tabs;
+
+[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Internals")]
+public class SettingsTabExperimental : SettingsTab
+{
+ public override SettingsEntry[] Entries { get; } =
+ {
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingsPluginTest", "Get plugin testing builds"),
+ string.Format(
+ Loc.Localize("DalamudSettingsPluginTestHint", "Receive testing prereleases for selected plugins.\nTo opt-in to testing builds for a plugin, you have to right click it in the \"{0}\" tab of the plugin installer and select \"{1}\"."),
+ PluginCategoryManager.Locs.Group_Installed,
+ PluginInstallerWindow.Locs.PluginContext_TestingOptIn),
+ c => c.DoPluginTest,
+ (v, c) => c.DoPluginTest = v),
+ new HintSettingsEntry(
+ Loc.Localize("DalamudSettingsPluginTestWarning", "Testing plugins may not have been vetted before being published. Please only enable this if you are aware of the risks."),
+ ImGuiColors.DalamudRed),
+
+ new GapSettingsEntry(5),
+
+ new ButtonSettingsEntry(
+ Loc.Localize("DalamudSettingsClearHidden", "Clear hidden plugins"),
+ Loc.Localize("DalamudSettingsClearHiddenHint", "Restore plugins you have previously hidden from the plugin installer."),
+ () =>
+ {
+ Service.Get().HiddenPluginInternalName.Clear();
+ Service.Get().RefilterPluginMasters();
+ }),
+
+ new GapSettingsEntry(5, true),
+
+ new DevPluginsSettingsEntry(),
+
+ new GapSettingsEntry(5, true),
+
+ new ThirdRepoSettingsEntry(),
+ };
+
+ public override string Title => Loc.Localize("DalamudSettingsExperimental", "Experimental");
+
+ public override void Draw()
+ {
+ base.Draw();
+
+ ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, "Total memory used by Dalamud & Plugins: " + Util.FormatBytes(GC.GetTotalMemory(false)));
+ }
+}
diff --git a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabGeneral.cs b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabGeneral.cs
new file mode 100644
index 000000000..7e5c9dd98
--- /dev/null
+++ b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabGeneral.cs
@@ -0,0 +1,92 @@
+using System.Diagnostics.CodeAnalysis;
+
+using CheapLoc;
+using Dalamud.Game.Text;
+using Dalamud.Interface.Internal.Windows.Settings.Widgets;
+
+namespace Dalamud.Interface.Internal.Windows.Settings.Tabs;
+
+[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Internals")]
+public class SettingsTabGeneral : SettingsTab
+{
+ public override SettingsEntry[] Entries { get; } =
+ {
+ new LanguageChooserSettingsEntry(),
+
+ new GapSettingsEntry(5),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingsChannel", "Dalamud Chat Channel"),
+ Loc.Localize("DalamudSettingsChannelHint", "Select the chat channel that is to be used for general Dalamud messages."),
+ c => c.GeneralChatType,
+ (v, c) => c.GeneralChatType = v,
+ warning: (v) =>
+ {
+ // TODO: Maybe actually implement UI for the validity check...
+ if (v == XivChatType.None)
+ return Loc.Localize("DalamudSettingsChannelNone", "Do not pick \"None\".");
+
+ return null;
+ }),
+
+ new GapSettingsEntry(5),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingsWaitForPluginsOnStartup", "Wait for plugins before game loads"),
+ Loc.Localize("DalamudSettingsWaitForPluginsOnStartupHint", "Do not let the game load, until plugins are loaded."),
+ c => c.IsResumeGameAfterPluginLoad,
+ (v, c) => c.IsResumeGameAfterPluginLoad = v),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingsFlash", "Flash FFXIV window on duty pop"),
+ Loc.Localize("DalamudSettingsFlashHint", "Flash the FFXIV window in your task bar when a duty is ready."),
+ c => c.DutyFinderTaskbarFlash,
+ (v, c) => c.DutyFinderTaskbarFlash = v),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingsDutyFinderMessage", "Chatlog message on duty pop"),
+ Loc.Localize("DalamudSettingsDutyFinderMessageHint", "Send a message in FFXIV chat when a duty is ready."),
+ c => c.DutyFinderChatMessage,
+ (v, c) => c.DutyFinderChatMessage = v),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingsPrintPluginsWelcomeMsg", "Display loaded plugins in the welcome message"),
+ Loc.Localize("DalamudSettingsPrintPluginsWelcomeMsgHint", "Display loaded plugins in FFXIV chat when logging in with a character."),
+ c => c.PrintPluginsWelcomeMsg,
+ (v, c) => c.PrintPluginsWelcomeMsg = v),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingsAutoUpdatePlugins", "Auto-update plugins"),
+ Loc.Localize("DalamudSettingsAutoUpdatePluginsMsgHint", "Automatically update plugins when logging in with a character."),
+ c => c.AutoUpdatePlugins,
+ (v, c) => c.AutoUpdatePlugins = v),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingsSystemMenu", "Dalamud buttons in system menu"),
+ Loc.Localize("DalamudSettingsSystemMenuMsgHint", "Add buttons for Dalamud plugins and settings to the system menu."),
+ c => c.DoButtonsSystemMenu,
+ (v, c) => c.DoButtonsSystemMenu = v),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingsSystemMenu", "Dalamud buttons in system menu"),
+ Loc.Localize("DalamudSettingsSystemMenuMsgHint", "Add buttons for Dalamud plugins and settings to the system menu."),
+ c => c.DoButtonsSystemMenu,
+ (v, c) => c.DoButtonsSystemMenu = v),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingsEnableRmtFiltering", "Enable RMT Filtering"),
+ Loc.Localize("DalamudSettingsEnableRmtFilteringMsgHint", "Enable Dalamud's built-in RMT ad filtering."),
+ c => !c.DisableRmtFiltering,
+ (v, c) => c.DisableRmtFiltering = !v),
+
+ new GapSettingsEntry(5),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingDoMbCollect", "Anonymously upload market board data"),
+ Loc.Localize("DalamudSettingDoMbCollectHint", "Anonymously provide data about in-game economics to Universalis when browsing the market board. This data can't be tied to you in any way and everyone benefits!"),
+ c => c.IsMbCollect,
+ (v, c) => c.IsMbCollect = v),
+ };
+
+ public override string Title => Loc.Localize("DalamudSettingsGeneral", "General");
+}
diff --git a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabLook.cs b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabLook.cs
new file mode 100644
index 000000000..8b9ef9952
--- /dev/null
+++ b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabLook.cs
@@ -0,0 +1,194 @@
+using System.Diagnostics.CodeAnalysis;
+
+using CheapLoc;
+using Dalamud.Configuration.Internal;
+using Dalamud.Interface.Colors;
+using Dalamud.Interface.Internal.Windows.Settings.Widgets;
+using ImGuiNET;
+
+namespace Dalamud.Interface.Internal.Windows.Settings.Tabs;
+
+[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Internals")]
+public class SettingsTabLook : SettingsTab
+{
+ private float globalUiScale;
+ private float fontGamma;
+
+ public override SettingsEntry[] Entries { get; } =
+ {
+ new GapSettingsEntry(5),
+
+ new ButtonSettingsEntry(
+ Loc.Localize("DalamudSettingsOpenStyleEditor", "Open Style Editor"),
+ Loc.Localize("DalamudSettingsStyleEditorHint", "Modify the look & feel of Dalamud windows."),
+ () => Service.Get().OpenStyleEditor()),
+
+ new GapSettingsEntry(5),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingToggleAxisFonts", "Use AXIS fonts as default Dalamud font"),
+ Loc.Localize("DalamudSettingToggleUiAxisFontsHint", "Use AXIS fonts (the game's main UI fonts) as default Dalamud font."),
+ c => c.UseAxisFontsFromGame,
+ (v, c) => c.UseAxisFontsFromGame = v,
+ v =>
+ {
+ var im = Service.Get();
+ im.UseAxisOverride = v;
+ im.RebuildFonts();
+ }),
+
+ new GapSettingsEntry(5, true),
+
+ new HintSettingsEntry(Loc.Localize("DalamudSettingToggleUiHideOptOutNote", "Plugins may independently opt out of the settings below.")),
+ new GapSettingsEntry(3),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingToggleUiHide", "Hide plugin UI when the game UI is toggled off"),
+ Loc.Localize("DalamudSettingToggleUiHideHint", "Hide any open windows by plugins when toggling the game overlay."),
+ c => c.ToggleUiHide,
+ (v, c) => c.ToggleUiHide = v),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingToggleUiHideDuringCutscenes", "Hide plugin UI during cutscenes"),
+ Loc.Localize("DalamudSettingToggleUiHideDuringCutscenesHint", "Hide any open windows by plugins during cutscenes."),
+ c => c.ToggleUiHideDuringCutscenes,
+ (v, c) => c.ToggleUiHideDuringCutscenes = v),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingToggleUiHideDuringGpose", "Hide plugin UI while gpose is active"),
+ Loc.Localize("DalamudSettingToggleUiHideDuringGposeHint", "Hide any open windows by plugins while gpose is active."),
+ c => c.ToggleUiHideDuringGpose,
+ (v, c) => c.ToggleUiHideDuringGpose = v),
+
+ new GapSettingsEntry(5, true),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingToggleFocusManagement", "Use escape to close Dalamud windows"),
+ Loc.Localize("DalamudSettingToggleFocusManagementHint", "This will cause Dalamud windows to behave like in-game windows when pressing escape.\nThey will close one after another until all are closed. May not work for all plugins."),
+ c => c.IsFocusManagementEnabled,
+ (v, c) => c.IsFocusManagementEnabled = v),
+
+ // This is applied every frame in InterfaceManager::CheckViewportState()
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingToggleViewports", "Enable multi-monitor windows"),
+ Loc.Localize("DalamudSettingToggleViewportsHint", "This will allow you move plugin windows onto other monitors.\nWill only work in Borderless Window or Windowed mode."),
+ c => !c.IsDisableViewport,
+ (v, c) => c.IsDisableViewport = !v),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingToggleDocking", "Enable window docking"),
+ Loc.Localize("DalamudSettingToggleDockingHint", "This will allow you to fuse and tab plugin windows."),
+ c => c.IsDocking,
+ (v, c) => c.IsDocking = v),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingToggleGamepadNavigation", "Control plugins via gamepad"),
+ Loc.Localize("DalamudSettingToggleGamepadNavigationHint", "This will allow you to toggle between game and plugin navigation via L1+L3.\nToggle the PluginInstaller window via R3 if ImGui navigation is enabled."),
+ c => c.IsGamepadNavigationEnabled,
+ (v, c) => c.IsGamepadNavigationEnabled = v),
+
+ new SettingsEntry(
+ Loc.Localize("DalamudSettingToggleTsm", "Show title screen menu"),
+ Loc.Localize("DalamudSettingToggleTsmHint", "This will allow you to access certain Dalamud and Plugin functionality from the title screen."),
+ c => c.ShowTsm,
+ (v, c) => c.ShowTsm = v),
+ };
+
+ public override string Title => Loc.Localize("DalamudSettingsVisual", "Look & Feel");
+
+ public override void Draw()
+ {
+ var interfaceManager = Service.Get();
+
+ ImGui.SetCursorPosY(ImGui.GetCursorPosY() + 3);
+ ImGui.Text(Loc.Localize("DalamudSettingsGlobalUiScale", "Global Font Scale"));
+ ImGui.SameLine();
+ ImGui.SetCursorPosY(ImGui.GetCursorPosY() - 3);
+ if (ImGui.Button("9.6pt##DalamudSettingsGlobalUiScaleReset96"))
+ {
+ this.globalUiScale = 9.6f / 12.0f;
+ ImGui.GetIO().FontGlobalScale = this.globalUiScale;
+ interfaceManager.RebuildFonts();
+ }
+
+ ImGui.SameLine();
+ if (ImGui.Button("12pt##DalamudSettingsGlobalUiScaleReset12"))
+ {
+ this.globalUiScale = 1.0f;
+ ImGui.GetIO().FontGlobalScale = this.globalUiScale;
+ interfaceManager.RebuildFonts();
+ }
+
+ ImGui.SameLine();
+ if (ImGui.Button("14pt##DalamudSettingsGlobalUiScaleReset14"))
+ {
+ this.globalUiScale = 14.0f / 12.0f;
+ ImGui.GetIO().FontGlobalScale = this.globalUiScale;
+ interfaceManager.RebuildFonts();
+ }
+
+ ImGui.SameLine();
+ if (ImGui.Button("18pt##DalamudSettingsGlobalUiScaleReset18"))
+ {
+ this.globalUiScale = 18.0f / 12.0f;
+ ImGui.GetIO().FontGlobalScale = this.globalUiScale;
+ interfaceManager.RebuildFonts();
+ }
+
+ ImGui.SameLine();
+ if (ImGui.Button("36pt##DalamudSettingsGlobalUiScaleReset36"))
+ {
+ this.globalUiScale = 36.0f / 12.0f;
+ ImGui.GetIO().FontGlobalScale = this.globalUiScale;
+ interfaceManager.RebuildFonts();
+ }
+
+ var globalUiScaleInPt = 12f * this.globalUiScale;
+ if (ImGui.DragFloat("##DalamudSettingsGlobalUiScaleDrag", ref globalUiScaleInPt, 0.1f, 9.6f, 36f, "%.1fpt", ImGuiSliderFlags.AlwaysClamp))
+ {
+ this.globalUiScale = globalUiScaleInPt / 12f;
+ ImGui.GetIO().FontGlobalScale = this.globalUiScale;
+ interfaceManager.RebuildFonts();
+ }
+
+ ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsGlobalUiScaleHint", "Scale text in all XIVLauncher UI elements - this is useful for 4K displays."));
+
+ ImGuiHelpers.ScaledDummy(5);
+
+ ImGui.SetCursorPosY(ImGui.GetCursorPosY() + 3);
+ ImGui.Text(Loc.Localize("DalamudSettingsFontGamma", "Font Gamma"));
+ ImGui.SameLine();
+ ImGui.SetCursorPosY(ImGui.GetCursorPosY() - 3);
+ if (ImGui.Button(Loc.Localize("DalamudSettingsIndividualConfigResetToDefaultValue", "Reset") + "##DalamudSettingsFontGammaReset"))
+ {
+ this.fontGamma = 1.4f;
+ interfaceManager.FontGammaOverride = this.fontGamma;
+ interfaceManager.RebuildFonts();
+ }
+
+ if (ImGui.DragFloat("##DalamudSettingsFontGammaDrag", ref this.fontGamma, 0.005f, 0.3f, 3f, "%.2f", ImGuiSliderFlags.AlwaysClamp))
+ {
+ interfaceManager.FontGammaOverride = this.fontGamma;
+ interfaceManager.RebuildFonts();
+ }
+
+ ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsFontGammaHint", "Changes the thickness of text."));
+
+ base.Draw();
+ }
+
+ public override void Load()
+ {
+ this.globalUiScale = Service.Get().GlobalUiScale;
+ this.fontGamma = Service.Get().FontGammaLevel;
+
+ base.Load();
+ }
+
+ public override void Save()
+ {
+ Service.Get().GlobalUiScale = this.globalUiScale;
+
+ base.Save();
+ }
+}
diff --git a/Dalamud/Interface/Internal/Windows/Settings/Widgets/ButtonSettingsEntry.cs b/Dalamud/Interface/Internal/Windows/Settings/Widgets/ButtonSettingsEntry.cs
new file mode 100644
index 000000000..9c635fb99
--- /dev/null
+++ b/Dalamud/Interface/Internal/Windows/Settings/Widgets/ButtonSettingsEntry.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+using Dalamud.Interface.Colors;
+using ImGuiNET;
+
+namespace Dalamud.Interface.Internal.Windows.Settings.Widgets;
+
+[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Internals")]
+public class ButtonSettingsEntry : SettingsEntry
+{
+ private readonly string description;
+ private readonly Action runs;
+
+ public ButtonSettingsEntry(string name, string description, Action runs)
+ {
+ this.description = description;
+ this.runs = runs;
+ this.Name = name;
+ }
+
+ public override void Load()
+ {
+ // ignored
+ }
+
+ public override void Save()
+ {
+ // ignored
+ }
+
+ public override void Draw()
+ {
+ if (ImGui.Button(this.Name))
+ {
+ this.runs.Invoke();
+ }
+
+ ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, this.description);
+ }
+}
diff --git a/Dalamud/Interface/Internal/Windows/Settings/Widgets/DevPluginsSettingsEntry.cs b/Dalamud/Interface/Internal/Windows/Settings/Widgets/DevPluginsSettingsEntry.cs
new file mode 100644
index 000000000..b1a231335
--- /dev/null
+++ b/Dalamud/Interface/Internal/Windows/Settings/Widgets/DevPluginsSettingsEntry.cs
@@ -0,0 +1,184 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Numerics;
+using System.Threading.Tasks;
+
+using CheapLoc;
+using Dalamud.Configuration;
+using Dalamud.Configuration.Internal;
+using Dalamud.Interface.Colors;
+using Dalamud.Interface.Components;
+using Dalamud.Plugin.Internal;
+using ImGuiNET;
+
+namespace Dalamud.Interface.Internal.Windows.Settings.Widgets;
+
+[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Internals")]
+public class DevPluginsSettingsEntry : SettingsEntry
+{
+ private List devPluginLocations = new();
+ private bool devPluginLocationsChanged;
+ private string devPluginTempLocation = string.Empty;
+ private string devPluginLocationAddError = string.Empty;
+
+ public DevPluginsSettingsEntry()
+ {
+ this.Name = Loc.Localize("DalamudSettingsDevPluginLocation", "Dev Plugin Locations");
+ }
+
+ public override void OnClose()
+ {
+ this.devPluginLocations =
+ Service.Get().DevPluginLoadLocations.Select(x => x.Clone()).ToList();
+ }
+
+ public override void Load()
+ {
+ this.devPluginLocations =
+ Service.Get().DevPluginLoadLocations.Select(x => x.Clone()).ToList();
+ this.devPluginLocationsChanged = false;
+ }
+
+ public override void Save()
+ {
+ Service.Get().DevPluginLoadLocations = this.devPluginLocations.Select(x => x.Clone()).ToList();
+
+ if (this.devPluginLocationsChanged)
+ {
+ Service.Get().ScanDevPlugins();
+ this.devPluginLocationsChanged = false;
+ }
+ }
+
+ public override void Draw()
+ {
+ ImGui.Text(this.Name);
+ if (this.devPluginLocationsChanged)
+ {
+ ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.HealerGreen);
+ ImGui.SameLine();
+ ImGui.Text(Loc.Localize("DalamudSettingsChanged", "(Changed)"));
+ ImGui.PopStyleColor();
+ }
+
+ ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsDevPluginLocationsHint", "Add additional dev plugin load locations.\nThese can be either the directory or DLL path."));
+
+ ImGuiHelpers.ScaledDummy(5);
+
+ ImGui.Columns(4);
+ ImGui.SetColumnWidth(0, 18 + (5 * ImGuiHelpers.GlobalScale));
+ ImGui.SetColumnWidth(1, ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X - (18 + 16 + 14) - ((5 + 45 + 26) * ImGuiHelpers.GlobalScale));
+ ImGui.SetColumnWidth(2, 16 + (45 * ImGuiHelpers.GlobalScale));
+ ImGui.SetColumnWidth(3, 14 + (26 * ImGuiHelpers.GlobalScale));
+
+ ImGui.Separator();
+
+ ImGui.Text("#");
+ ImGui.NextColumn();
+ ImGui.Text("Path");
+ ImGui.NextColumn();
+ ImGui.Text("Enabled");
+ ImGui.NextColumn();
+ ImGui.Text(string.Empty);
+ ImGui.NextColumn();
+
+ ImGui.Separator();
+
+ DevPluginLocationSettings locationToRemove = null;
+
+ var locNumber = 1;
+ foreach (var devPluginLocationSetting in this.devPluginLocations)
+ {
+ var isEnabled = devPluginLocationSetting.IsEnabled;
+
+ ImGui.PushID($"devPluginLocation_{devPluginLocationSetting.Path}");
+
+ ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (ImGui.GetColumnWidth() / 2) - 8 - (ImGui.CalcTextSize(locNumber.ToString()).X / 2));
+ ImGui.Text(locNumber.ToString());
+ ImGui.NextColumn();
+
+ ImGui.SetNextItemWidth(-1);
+ var path = devPluginLocationSetting.Path;
+ if (ImGui.InputText($"##devPluginLocationInput", ref path, 65535, ImGuiInputTextFlags.EnterReturnsTrue))
+ {
+ var contains = this.devPluginLocations.Select(loc => loc.Path).Contains(path);
+ if (devPluginLocationSetting.Path == path)
+ {
+ // no change.
+ }
+ else if (contains && devPluginLocationSetting.Path != path)
+ {
+ this.devPluginLocationAddError = Loc.Localize("DalamudDevPluginLocationExists", "Location already exists.");
+ Task.Delay(5000).ContinueWith(t => this.devPluginLocationAddError = string.Empty);
+ }
+ else
+ {
+ devPluginLocationSetting.Path = path;
+ this.devPluginLocationsChanged = path != devPluginLocationSetting.Path;
+ }
+ }
+
+ ImGui.NextColumn();
+
+ ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (ImGui.GetColumnWidth() / 2) - 7 - (12 * ImGuiHelpers.GlobalScale));
+ ImGui.Checkbox("##devPluginLocationCheck", ref isEnabled);
+ ImGui.NextColumn();
+
+ if (ImGuiComponents.IconButton(FontAwesomeIcon.Trash))
+ {
+ locationToRemove = devPluginLocationSetting;
+ }
+
+ ImGui.PopID();
+
+ ImGui.NextColumn();
+ ImGui.Separator();
+
+ devPluginLocationSetting.IsEnabled = isEnabled;
+
+ locNumber++;
+ }
+
+ if (locationToRemove != null)
+ {
+ this.devPluginLocations.Remove(locationToRemove);
+ this.devPluginLocationsChanged = true;
+ }
+
+ ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (ImGui.GetColumnWidth() / 2) - 8 - (ImGui.CalcTextSize(locNumber.ToString()).X / 2));
+ ImGui.Text(locNumber.ToString());
+ ImGui.NextColumn();
+ ImGui.SetNextItemWidth(-1);
+ ImGui.InputText("##devPluginLocationInput", ref this.devPluginTempLocation, 300);
+ ImGui.NextColumn();
+ // Enabled button
+ ImGui.NextColumn();
+ if (!string.IsNullOrEmpty(this.devPluginTempLocation) && ImGuiComponents.IconButton(FontAwesomeIcon.Plus))
+ {
+ if (this.devPluginLocations.Any(r => string.Equals(r.Path, this.devPluginTempLocation, StringComparison.InvariantCultureIgnoreCase)))
+ {
+ this.devPluginLocationAddError = Loc.Localize("DalamudDevPluginLocationExists", "Location already exists.");
+ Task.Delay(5000).ContinueWith(t => this.devPluginLocationAddError = string.Empty);
+ }
+ else
+ {
+ this.devPluginLocations.Add(new DevPluginLocationSettings
+ {
+ Path = this.devPluginTempLocation.Replace("\"", string.Empty),
+ IsEnabled = true,
+ });
+ this.devPluginLocationsChanged = true;
+ this.devPluginTempLocation = string.Empty;
+ }
+ }
+
+ ImGui.Columns(1);
+
+ if (!string.IsNullOrEmpty(this.devPluginLocationAddError))
+ {
+ ImGuiHelpers.SafeTextColoredWrapped(new Vector4(1, 0, 0, 1), this.devPluginLocationAddError);
+ }
+ }
+}
diff --git a/Dalamud/Interface/Internal/Windows/Settings/Widgets/GapSettingsEntry.cs b/Dalamud/Interface/Internal/Windows/Settings/Widgets/GapSettingsEntry.cs
new file mode 100644
index 000000000..bc5c2fd0a
--- /dev/null
+++ b/Dalamud/Interface/Internal/Windows/Settings/Widgets/GapSettingsEntry.cs
@@ -0,0 +1,40 @@
+using System.Diagnostics.CodeAnalysis;
+
+using ImGuiNET;
+
+namespace Dalamud.Interface.Internal.Windows.Settings.Widgets;
+
+[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Internals")]
+public sealed class GapSettingsEntry : SettingsEntry
+{
+ private readonly float size;
+ private readonly bool hr;
+
+ public GapSettingsEntry(float size, bool hr = false)
+ {
+ this.size = size;
+ this.hr = hr;
+ this.IsValid = true;
+ }
+
+ public override void Load()
+ {
+ // ignored
+ }
+
+ public override void Save()
+ {
+ // ignored
+ }
+
+ public override void Draw()
+ {
+ ImGuiHelpers.ScaledDummy(this.size);
+
+ if (this.hr)
+ {
+ ImGui.Separator();
+ ImGuiHelpers.ScaledDummy(this.size);
+ }
+ }
+}
diff --git a/Dalamud/Interface/Internal/Windows/Settings/Widgets/HintSettingsEntry.cs b/Dalamud/Interface/Internal/Windows/Settings/Widgets/HintSettingsEntry.cs
new file mode 100644
index 000000000..d1eb43c1f
--- /dev/null
+++ b/Dalamud/Interface/Internal/Windows/Settings/Widgets/HintSettingsEntry.cs
@@ -0,0 +1,34 @@
+using System.Diagnostics.CodeAnalysis;
+using System.Numerics;
+
+using Dalamud.Interface.Colors;
+
+namespace Dalamud.Interface.Internal.Windows.Settings.Widgets;
+
+[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Internals")]
+public class HintSettingsEntry : SettingsEntry
+{
+ private readonly string text;
+ private readonly Vector4 color;
+
+ public HintSettingsEntry(string text, Vector4? color = null)
+ {
+ this.text = text;
+ this.color = color ?? ImGuiColors.DalamudGrey;
+ }
+
+ public override void Load()
+ {
+ // ignore
+ }
+
+ public override void Save()
+ {
+ // ignore
+ }
+
+ public override void Draw()
+ {
+ ImGuiHelpers.SafeTextColoredWrapped(this.color, this.text);
+ }
+}
diff --git a/Dalamud/Interface/Internal/Windows/Settings/Widgets/LanguageChooserSettingsEntry.cs b/Dalamud/Interface/Internal/Windows/Settings/Widgets/LanguageChooserSettingsEntry.cs
new file mode 100644
index 000000000..0bb373576
--- /dev/null
+++ b/Dalamud/Interface/Internal/Windows/Settings/Widgets/LanguageChooserSettingsEntry.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Linq;
+
+using CheapLoc;
+using Dalamud.Configuration.Internal;
+using Dalamud.Interface.Colors;
+using ImGuiNET;
+
+namespace Dalamud.Interface.Internal.Windows.Settings.Widgets;
+
+[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Internals")]
+public sealed class LanguageChooserSettingsEntry : SettingsEntry
+{
+ private readonly string[] languages;
+ private readonly string[] locLanguages;
+
+ private int langIndex = -1;
+
+ public LanguageChooserSettingsEntry()
+ {
+ this.languages = Localization.ApplicableLangCodes.Prepend("en").ToArray();
+
+ this.Name = Loc.Localize("DalamudSettingsLanguage", "Language");
+ this.IsValid = true;
+ this.IsVisible = true;
+
+ try
+ {
+ var locLanguagesList = new List();
+ string locLanguage;
+ foreach (var language in this.languages)
+ {
+ if (language != "ko")
+ {
+ locLanguage = CultureInfo.GetCultureInfo(language).NativeName;
+ locLanguagesList.Add(char.ToUpper(locLanguage[0]) + locLanguage[1..]);
+ }
+ else
+ {
+ locLanguagesList.Add("Korean");
+ }
+ }
+
+ this.locLanguages = locLanguagesList.ToArray();
+ }
+ catch (Exception)
+ {
+ this.locLanguages = this.languages; // Languages not localized, only codes.
+ }
+ }
+
+ public override void Load()
+ {
+ this.langIndex = Array.IndexOf(this.languages, Service.Get().EffectiveLanguage);
+ if (this.langIndex == -1)
+ this.langIndex = 0;
+ }
+
+ public override void Save()
+ {
+ Service.Get().SetupWithLangCode(this.languages[this.langIndex]);
+ Service.Get().LanguageOverride = this.languages[this.langIndex];
+ }
+
+ public override void Draw()
+ {
+ ImGui.Text(this.Name);
+ ImGui.Combo("##XlLangCombo", ref this.langIndex, this.locLanguages, this.locLanguages.Length);
+ ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsLanguageHint", "Select the language Dalamud will be displayed in."));
+ }
+}
diff --git a/Dalamud/Interface/Internal/Windows/Settings/Widgets/SettingsEntry{T}.cs b/Dalamud/Interface/Internal/Windows/Settings/Widgets/SettingsEntry{T}.cs
new file mode 100644
index 000000000..c08eb99f6
--- /dev/null
+++ b/Dalamud/Interface/Internal/Windows/Settings/Widgets/SettingsEntry{T}.cs
@@ -0,0 +1,174 @@
+using System;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Linq;
+
+using Dalamud.Configuration.Internal;
+
+using Dalamud.Interface.Colors;
+using Dalamud.Utility;
+using ImGuiNET;
+
+namespace Dalamud.Interface.Internal.Windows.Settings.Widgets;
+
+[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Internals")]
+internal sealed class SettingsEntry : SettingsEntry
+{
+ private readonly LoadSettingDelegate load;
+ private readonly SaveSettingDelegate save;
+ private readonly Action? change;
+
+ private object? valueBacking;
+
+ public SettingsEntry(string name, string description, LoadSettingDelegate load, SaveSettingDelegate save, Action? change = null, Func? warning = null, Func? validity = null)
+ {
+ this.load = load;
+ this.save = save;
+ this.change = change;
+ this.Name = name;
+ this.Description = description;
+ this.CheckWarning = warning;
+ this.CheckValidity = validity;
+ }
+
+ public delegate T? LoadSettingDelegate(DalamudConfiguration config);
+
+ public delegate void SaveSettingDelegate(T? value, DalamudConfiguration config);
+
+ public T? Value => this.valueBacking == default ? default : (T)this.valueBacking;
+
+ public string Description { get; }
+
+ public Func? CheckValidity { get; init; }
+
+ public Func? CheckWarning { get; init; }
+
+ public Func? CheckVisibility { get; init; }
+
+ public override bool IsVisible => this.CheckVisibility?.Invoke() ?? true;
+
+ public override void Draw()
+ {
+ Debug.Assert(this.Name != null, "this.Name != null");
+
+ var type = typeof(T);
+
+ if (type == typeof(DirectoryInfo))
+ {
+ ImGuiHelpers.SafeTextWrapped(this.Name);
+
+ var value = this.Value as DirectoryInfo;
+ var nativeBuffer = value?.FullName ?? string.Empty;
+
+ if (ImGui.InputText($"###{this.Id.ToString()}", ref nativeBuffer, 1000))
+ {
+ this.valueBacking = !string.IsNullOrEmpty(nativeBuffer) ? new DirectoryInfo(nativeBuffer) : null;
+ }
+ }
+ else if (type == typeof(string))
+ {
+ ImGuiHelpers.SafeTextWrapped(this.Name);
+
+ var nativeBuffer = this.Value as string ?? string.Empty;
+
+ if (ImGui.InputText($"###{this.Id.ToString()}", ref nativeBuffer, 1000))
+ {
+ this.valueBacking = nativeBuffer;
+ }
+ }
+ else if (type == typeof(bool))
+ {
+ var nativeValue = this.Value as bool? ?? false;
+
+ if (ImGui.Checkbox($"{this.Name}###{this.Id.ToString()}", ref nativeValue))
+ {
+ this.valueBacking = nativeValue;
+ this.change?.Invoke(this.Value);
+ }
+ }
+ else if (type.IsEnum)
+ {
+ ImGuiHelpers.SafeTextWrapped(this.Name);
+
+ var idx = (Enum)(this.valueBacking ?? 0);
+ var values = Enum.GetValues(type);
+ var descriptions =
+ values.Cast().ToDictionary(x => x, x => x.GetAttribute() ?? new SettingsAnnotationAttribute(x.ToString(), string.Empty));
+
+ if (ImGui.BeginCombo($"###{this.Id.ToString()}", descriptions[idx].FriendlyName))
+ {
+ foreach (Enum value in values)
+ {
+ if (ImGui.Selectable(descriptions[value].FriendlyName, idx.Equals(value)))
+ {
+ this.valueBacking = value;
+ }
+ }
+
+ ImGui.EndCombo();
+ }
+ }
+
+ ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudGrey);
+ ImGuiHelpers.SafeTextWrapped(this.Description);
+ ImGui.PopStyleColor();
+
+ if (this.CheckValidity != null)
+ {
+ var validityMsg = this.CheckValidity.Invoke(this.Value);
+ this.IsValid = string.IsNullOrEmpty(validityMsg);
+
+ if (!this.IsValid)
+ {
+ ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudRed);
+ ImGui.Text(validityMsg);
+ ImGui.PopStyleColor();
+ }
+ }
+ else
+ {
+ this.IsValid = true;
+ }
+
+ var warningMessage = this.CheckWarning?.Invoke(this.Value);
+
+ if (warningMessage != null)
+ {
+ ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudRed);
+ ImGui.Text(warningMessage);
+ ImGui.PopStyleColor();
+ }
+ }
+
+ public override void Load()
+ {
+ this.valueBacking = this.load(Service.Get());
+
+ if (this.CheckValidity != null)
+ {
+ this.IsValid = this.CheckValidity(this.Value) == null;
+ }
+ else
+ {
+ this.IsValid = true;
+ }
+ }
+
+ public override void Save() => this.save(this.Value, Service.Get());
+}
+
+[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Internals")]
+[AttributeUsage(AttributeTargets.Field)]
+internal class SettingsAnnotationAttribute : Attribute
+{
+ public SettingsAnnotationAttribute(string friendlyName, string description)
+ {
+ this.FriendlyName = friendlyName;
+ this.Description = description;
+ }
+
+ public string FriendlyName { get; set; }
+
+ public string Description { get; set; }
+}
diff --git a/Dalamud/Interface/Internal/Windows/Settings/Widgets/ThirdRepoSettingsEntry.cs b/Dalamud/Interface/Internal/Windows/Settings/Widgets/ThirdRepoSettingsEntry.cs
new file mode 100644
index 000000000..e410b3482
--- /dev/null
+++ b/Dalamud/Interface/Internal/Windows/Settings/Widgets/ThirdRepoSettingsEntry.cs
@@ -0,0 +1,193 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Numerics;
+using System.Threading.Tasks;
+
+using CheapLoc;
+using Dalamud.Configuration;
+using Dalamud.Configuration.Internal;
+using Dalamud.Interface.Colors;
+using Dalamud.Interface.Components;
+using Dalamud.Plugin.Internal;
+using ImGuiNET;
+
+namespace Dalamud.Interface.Internal.Windows.Settings.Widgets;
+
+[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Internals")]
+public class ThirdRepoSettingsEntry : SettingsEntry
+{
+ private List thirdRepoList = new();
+ private bool thirdRepoListChanged;
+ private string thirdRepoTempUrl = string.Empty;
+ private string thirdRepoAddError = string.Empty;
+
+ public override void OnClose()
+ {
+ this.thirdRepoList =
+ Service.Get().ThirdRepoList.Select(x => x.Clone()).ToList();
+ }
+
+ public override void Load()
+ {
+ this.thirdRepoList =
+ Service.Get().ThirdRepoList.Select(x => x.Clone()).ToList();
+ this.thirdRepoListChanged = false;
+ }
+
+ public override void Save()
+ {
+ Service.Get().ThirdRepoList =
+ this.thirdRepoList.Select(x => x.Clone()).ToList();
+
+ if (this.thirdRepoListChanged)
+ {
+ _ = Service.Get().SetPluginReposFromConfigAsync(true);
+ this.thirdRepoListChanged = false;
+ }
+ }
+
+ public override void Draw()
+ {
+ ImGui.Text(Loc.Localize("DalamudSettingsCustomRepo", "Custom Plugin Repositories"));
+ if (this.thirdRepoListChanged)
+ {
+ ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.HealerGreen);
+ ImGui.SameLine();
+ ImGui.Text(Loc.Localize("DalamudSettingsChanged", "(Changed)"));
+ ImGui.PopStyleColor();
+ }
+
+ ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingCustomRepoHint", "Add custom plugin repositories."));
+ ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("DalamudSettingCustomRepoWarning", "We cannot take any responsibility for third-party plugins and repositories."));
+ ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("DalamudSettingCustomRepoWarning2", "Plugins have full control over your PC, like any other program, and may cause harm or crashes."));
+ ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("DalamudSettingCustomRepoWarning4", "They can delete your character, upload your family photos and burn down your house."));
+ ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("DalamudSettingCustomRepoWarning3", "Please make absolutely sure that you only install third-party plugins from developers you trust."));
+
+ ImGuiHelpers.ScaledDummy(5);
+
+ ImGui.Columns(4);
+ ImGui.SetColumnWidth(0, 18 + (5 * ImGuiHelpers.GlobalScale));
+ ImGui.SetColumnWidth(1, ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X - (18 + 16 + 14) - ((5 + 45 + 26) * ImGuiHelpers.GlobalScale));
+ ImGui.SetColumnWidth(2, 16 + (45 * ImGuiHelpers.GlobalScale));
+ ImGui.SetColumnWidth(3, 14 + (26 * ImGuiHelpers.GlobalScale));
+
+ ImGui.Separator();
+
+ ImGui.Text("#");
+ ImGui.NextColumn();
+ ImGui.Text("URL");
+ ImGui.NextColumn();
+ ImGui.Text("Enabled");
+ ImGui.NextColumn();
+ ImGui.Text(string.Empty);
+ ImGui.NextColumn();
+
+ ImGui.Separator();
+
+ ImGui.Text("0");
+ ImGui.NextColumn();
+ ImGui.Text("XIVLauncher");
+ ImGui.NextColumn();
+ ImGui.NextColumn();
+ ImGui.NextColumn();
+ ImGui.Separator();
+
+ ThirdPartyRepoSettings repoToRemove = null;
+
+ var repoNumber = 1;
+ foreach (var thirdRepoSetting in this.thirdRepoList)
+ {
+ var isEnabled = thirdRepoSetting.IsEnabled;
+
+ ImGui.PushID($"thirdRepo_{thirdRepoSetting.Url}");
+
+ ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (ImGui.GetColumnWidth() / 2) - 8 - (ImGui.CalcTextSize(repoNumber.ToString()).X / 2));
+ ImGui.Text(repoNumber.ToString());
+ ImGui.NextColumn();
+
+ ImGui.SetNextItemWidth(-1);
+ var url = thirdRepoSetting.Url;
+ if (ImGui.InputText($"##thirdRepoInput", ref url, 65535, ImGuiInputTextFlags.EnterReturnsTrue))
+ {
+ var contains = this.thirdRepoList.Select(repo => repo.Url).Contains(url);
+ if (thirdRepoSetting.Url == url)
+ {
+ // no change.
+ }
+ else if (contains && thirdRepoSetting.Url != url)
+ {
+ this.thirdRepoAddError = Loc.Localize("DalamudThirdRepoExists", "Repo already exists.");
+ Task.Delay(5000).ContinueWith(t => this.thirdRepoAddError = string.Empty);
+ }
+ else
+ {
+ thirdRepoSetting.Url = url;
+ this.thirdRepoListChanged = url != thirdRepoSetting.Url;
+ }
+ }
+
+ ImGui.NextColumn();
+
+ ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (ImGui.GetColumnWidth() / 2) - 7 - (12 * ImGuiHelpers.GlobalScale));
+ ImGui.Checkbox("##thirdRepoCheck", ref isEnabled);
+ ImGui.NextColumn();
+
+ if (ImGuiComponents.IconButton(FontAwesomeIcon.Trash))
+ {
+ repoToRemove = thirdRepoSetting;
+ }
+
+ ImGui.PopID();
+
+ ImGui.NextColumn();
+ ImGui.Separator();
+
+ thirdRepoSetting.IsEnabled = isEnabled;
+
+ repoNumber++;
+ }
+
+ if (repoToRemove != null)
+ {
+ this.thirdRepoList.Remove(repoToRemove);
+ this.thirdRepoListChanged = true;
+ }
+
+ ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (ImGui.GetColumnWidth() / 2) - 8 - (ImGui.CalcTextSize(repoNumber.ToString()).X / 2));
+ ImGui.Text(repoNumber.ToString());
+ ImGui.NextColumn();
+ ImGui.SetNextItemWidth(-1);
+ ImGui.InputText("##thirdRepoUrlInput", ref this.thirdRepoTempUrl, 300);
+ ImGui.NextColumn();
+ // Enabled button
+ ImGui.NextColumn();
+ if (!string.IsNullOrEmpty(this.thirdRepoTempUrl) && ImGuiComponents.IconButton(FontAwesomeIcon.Plus))
+ {
+ this.thirdRepoTempUrl = this.thirdRepoTempUrl.TrimEnd();
+ if (this.thirdRepoList.Any(r => string.Equals(r.Url, this.thirdRepoTempUrl, StringComparison.InvariantCultureIgnoreCase)))
+ {
+ this.thirdRepoAddError = Loc.Localize("DalamudThirdRepoExists", "Repo already exists.");
+ Task.Delay(5000).ContinueWith(t => this.thirdRepoAddError = string.Empty);
+ }
+ else
+ {
+ this.thirdRepoList.Add(new ThirdPartyRepoSettings
+ {
+ Url = this.thirdRepoTempUrl,
+ IsEnabled = true,
+ });
+ this.thirdRepoListChanged = true;
+ this.thirdRepoTempUrl = string.Empty;
+ }
+ }
+
+ ImGui.Columns(1);
+
+ if (!string.IsNullOrEmpty(this.thirdRepoAddError))
+ {
+ ImGuiHelpers.SafeTextColoredWrapped(new Vector4(1, 0, 0, 1), this.thirdRepoAddError);
+ }
+ }
+}
diff --git a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs
deleted file mode 100644
index 72292faa3..000000000
--- a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs
+++ /dev/null
@@ -1,982 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Numerics;
-using System.Threading.Tasks;
-
-using CheapLoc;
-using Dalamud.Configuration;
-using Dalamud.Configuration.Internal;
-using Dalamud.Game.Gui.Dtr;
-using Dalamud.Game.Text;
-using Dalamud.Interface.Colors;
-using Dalamud.Interface.Components;
-using Dalamud.Interface.Internal.Windows.PluginInstaller;
-using Dalamud.Interface.Windowing;
-using Dalamud.Plugin.Internal;
-using Dalamud.Utility;
-using ImGuiNET;
-
-namespace Dalamud.Interface.Internal.Windows;
-
-///
-/// The window that allows for general configuration of Dalamud itself.
-///
-internal class SettingsWindow : Window
-{
- private readonly string[] languages;
- private readonly string[] locLanguages;
-
- private int langIndex;
-
- private XivChatType dalamudMessagesChatType;
-
- private bool doWaitForPluginsOnStartup;
- private bool doCfTaskBarFlash;
- private bool doCfChatMessage;
- private bool doMbCollect;
-
- private float globalUiScale;
- private bool doUseAxisFontsFromGame;
- private float fontGamma;
- private bool doToggleUiHide;
- private bool doToggleUiHideDuringCutscenes;
- private bool doToggleUiHideDuringGpose;
- private bool doDocking;
- private bool doViewport;
- private bool doGamepad;
- private bool doFocus;
- private bool doTsm;
-
- private List? dtrOrder;
- private List? dtrIgnore;
- private int dtrSpacing;
- private bool dtrSwapDirection;
-
- private int? pluginWaitBeforeFree;
-
- private List thirdRepoList;
- private bool thirdRepoListChanged;
- private string thirdRepoTempUrl = string.Empty;
- private string thirdRepoAddError = string.Empty;
-
- private List devPluginLocations;
- private bool devPluginLocationsChanged;
- private string devPluginTempLocation = string.Empty;
- private string devPluginLocationAddError = string.Empty;
-
- private bool printPluginsWelcomeMsg;
- private bool autoUpdatePlugins;
- private bool doButtonsSystemMenu;
- private bool disableRmtFiltering;
-
- #region Experimental
-
- private bool doPluginTest;
-
- #endregion
-
- ///
- /// Initializes a new instance of the class.
- ///
- public SettingsWindow()
- : base(Loc.Localize("DalamudSettingsHeader", "Dalamud Settings") + "###XlSettings2", ImGuiWindowFlags.NoCollapse)
- {
- var configuration = Service.Get();
-
- this.Size = new Vector2(740, 550);
- this.SizeCondition = ImGuiCond.FirstUseEver;
-
- this.dalamudMessagesChatType = configuration.GeneralChatType;
-
- this.doWaitForPluginsOnStartup = configuration.IsResumeGameAfterPluginLoad;
- this.doCfTaskBarFlash = configuration.DutyFinderTaskbarFlash;
- this.doCfChatMessage = configuration.DutyFinderChatMessage;
- this.doMbCollect = configuration.IsMbCollect;
-
- this.globalUiScale = configuration.GlobalUiScale;
- this.fontGamma = configuration.FontGammaLevel;
- this.doUseAxisFontsFromGame = configuration.UseAxisFontsFromGame;
- this.doToggleUiHide = configuration.ToggleUiHide;
- this.doToggleUiHideDuringCutscenes = configuration.ToggleUiHideDuringCutscenes;
- this.doToggleUiHideDuringGpose = configuration.ToggleUiHideDuringGpose;
-
- this.doDocking = configuration.IsDocking;
- this.doViewport = !configuration.IsDisableViewport;
- this.doGamepad = configuration.IsGamepadNavigationEnabled;
- this.doFocus = configuration.IsFocusManagementEnabled;
- this.doTsm = configuration.ShowTsm;
-
- this.dtrSpacing = configuration.DtrSpacing;
- this.dtrSwapDirection = configuration.DtrSwapDirection;
-
- this.pluginWaitBeforeFree = configuration.PluginWaitBeforeFree;
-
- this.doPluginTest = configuration.DoPluginTest;
- this.thirdRepoList = configuration.ThirdRepoList.Select(x => x.Clone()).ToList();
- this.devPluginLocations = configuration.DevPluginLoadLocations.Select(x => x.Clone()).ToList();
-
- this.printPluginsWelcomeMsg = configuration.PrintPluginsWelcomeMsg;
- this.autoUpdatePlugins = configuration.AutoUpdatePlugins;
- this.doButtonsSystemMenu = configuration.DoButtonsSystemMenu;
- this.disableRmtFiltering = configuration.DisableRmtFiltering;
-
- this.languages = Localization.ApplicableLangCodes.Prepend("en").ToArray();
- this.langIndex = Array.IndexOf(this.languages, configuration.EffectiveLanguage);
- if (this.langIndex == -1)
- this.langIndex = 0;
-
- try
- {
- var locLanguagesList = new List();
- string locLanguage;
- foreach (var language in this.languages)
- {
- if (language != "ko")
- {
- locLanguage = CultureInfo.GetCultureInfo(language).NativeName;
- locLanguagesList.Add(char.ToUpper(locLanguage[0]) + locLanguage[1..]);
- }
- else
- {
- locLanguagesList.Add("Korean");
- }
- }
-
- this.locLanguages = locLanguagesList.ToArray();
- }
- catch (Exception)
- {
- this.locLanguages = this.languages; // Languages not localized, only codes.
- }
- }
-
- ///
- public override void OnOpen()
- {
- this.thirdRepoListChanged = false;
- this.devPluginLocationsChanged = false;
-
- var configuration = Service.Get();
- this.dtrOrder = configuration.DtrOrder;
- this.dtrIgnore = configuration.DtrIgnore;
- }
-
- ///
- public override void OnClose()
- {
- var configuration = Service.Get();
- var interfaceManager = Service.Get();
-
- var rebuildFont = ImGui.GetIO().FontGlobalScale != configuration.GlobalUiScale
- || interfaceManager.FontGamma != configuration.FontGammaLevel
- || interfaceManager.UseAxis != configuration.UseAxisFontsFromGame;
-
- ImGui.GetIO().FontGlobalScale = configuration.GlobalUiScale;
- interfaceManager.FontGammaOverride = null;
- interfaceManager.UseAxisOverride = null;
- this.thirdRepoList = configuration.ThirdRepoList.Select(x => x.Clone()).ToList();
- this.devPluginLocations = configuration.DevPluginLoadLocations.Select(x => x.Clone()).ToList();
-
- configuration.DtrOrder = this.dtrOrder;
- configuration.DtrIgnore = this.dtrIgnore;
-
- if (rebuildFont)
- interfaceManager.RebuildFonts();
- }
-
- ///
- public override void Draw()
- {
- var windowSize = ImGui.GetWindowSize();
- ImGui.BeginChild("scrolling", new Vector2(windowSize.X - 5 - (5 * ImGuiHelpers.GlobalScale), windowSize.Y - 35 - (35 * ImGuiHelpers.GlobalScale)), false);
-
- if (ImGui.BeginTabBar("SetTabBar"))
- {
- if (ImGui.BeginTabItem(Loc.Localize("DalamudSettingsGeneral", "General") + "###settingsTabGeneral"))
- {
- this.DrawGeneralTab();
- ImGui.EndTabItem();
- }
-
- if (ImGui.BeginTabItem(Loc.Localize("DalamudSettingsVisual", "Look & Feel") + "###settingsTabVisual"))
- {
- this.DrawLookAndFeelTab();
- ImGui.EndTabItem();
- }
-
- if (ImGui.BeginTabItem(Loc.Localize("DalamudSettingsServerInfoBar", "Server Info Bar") + "###settingsTabInfoBar"))
- {
- this.DrawServerInfoBarTab();
- ImGui.EndTabItem();
- }
-
- if (ImGui.BeginTabItem(Loc.Localize("DalamudSettingsExperimental", "Experimental") + "###settingsTabExperimental"))
- {
- this.DrawExperimentalTab();
- ImGui.EndTabItem();
- }
-
- ImGui.EndTabBar();
- }
-
- ImGui.EndChild();
-
- this.DrawSaveCloseButtons();
- }
-
- private void DrawGeneralTab()
- {
- ImGui.Text(Loc.Localize("DalamudSettingsLanguage", "Language"));
- ImGui.Combo("##XlLangCombo", ref this.langIndex, this.locLanguages, this.locLanguages.Length);
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsLanguageHint", "Select the language Dalamud will be displayed in."));
-
- ImGuiHelpers.ScaledDummy(5);
-
- ImGui.Text(Loc.Localize("DalamudSettingsChannel", "General Chat Channel"));
- if (ImGui.BeginCombo("##XlChatTypeCombo", this.dalamudMessagesChatType.ToString()))
- {
- foreach (var type in Enum.GetValues(typeof(XivChatType)).Cast())
- {
- if (ImGui.Selectable(type.ToString(), type == this.dalamudMessagesChatType))
- {
- this.dalamudMessagesChatType = type;
- }
- }
-
- ImGui.EndCombo();
- }
-
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsChannelHint", "Select the chat channel that is to be used for general Dalamud messages."));
-
- ImGuiHelpers.ScaledDummy(5);
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingsWaitForPluginsOnStartup", "Wait for plugins before game loads"), ref this.doWaitForPluginsOnStartup);
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsWaitForPluginsOnStartupHint", "Do not let the game load, until plugins are loaded."));
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingsFlash", "Flash FFXIV window on duty pop"), ref this.doCfTaskBarFlash);
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsFlashHint", "Flash the FFXIV window in your task bar when a duty is ready."));
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingsDutyFinderMessage", "Chatlog message on duty pop"), ref this.doCfChatMessage);
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsDutyFinderMessageHint", "Send a message in FFXIV chat when a duty is ready."));
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingsPrintPluginsWelcomeMsg", "Display loaded plugins in the welcome message"), ref this.printPluginsWelcomeMsg);
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsPrintPluginsWelcomeMsgHint", "Display loaded plugins in FFXIV chat when logging in with a character."));
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingsAutoUpdatePlugins", "Auto-update plugins"), ref this.autoUpdatePlugins);
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsAutoUpdatePluginsMsgHint", "Automatically update plugins when logging in with a character."));
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingsSystemMenu", "Dalamud buttons in system menu"), ref this.doButtonsSystemMenu);
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsSystemMenuMsgHint", "Add buttons for Dalamud plugins and settings to the system menu."));
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingsDisableRmtFiltering", "Disable RMT Filtering"), ref this.disableRmtFiltering);
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsDisableRmtFilteringMsgHint", "Disable Dalamud's built-in RMT ad filtering."));
-
- ImGuiHelpers.ScaledDummy(5);
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingDoMbCollect", "Anonymously upload market board data"), ref this.doMbCollect);
-
- ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudGrey);
- ImGui.TextWrapped(Loc.Localize("DalamudSettingDoMbCollectHint", "Anonymously provide data about in-game economics to Universalis when browsing the market board. This data can't be tied to you in any way and everyone benefits!"));
- ImGui.PopStyleColor();
- }
-
- private void DrawLookAndFeelTab()
- {
- var interfaceManager = Service.Get();
-
- ImGui.SetCursorPosY(ImGui.GetCursorPosY() + 3);
- ImGui.Text(Loc.Localize("DalamudSettingsGlobalUiScale", "Global Font Scale"));
- ImGui.SameLine();
- ImGui.SetCursorPosY(ImGui.GetCursorPosY() - 3);
- if (ImGui.Button("9.6pt##DalamudSettingsGlobalUiScaleReset96"))
- {
- this.globalUiScale = 9.6f / 12.0f;
- ImGui.GetIO().FontGlobalScale = this.globalUiScale;
- interfaceManager.RebuildFonts();
- }
-
- ImGui.SameLine();
- if (ImGui.Button("12pt##DalamudSettingsGlobalUiScaleReset12"))
- {
- this.globalUiScale = 1.0f;
- ImGui.GetIO().FontGlobalScale = this.globalUiScale;
- interfaceManager.RebuildFonts();
- }
-
- ImGui.SameLine();
- if (ImGui.Button("14pt##DalamudSettingsGlobalUiScaleReset14"))
- {
- this.globalUiScale = 14.0f / 12.0f;
- ImGui.GetIO().FontGlobalScale = this.globalUiScale;
- interfaceManager.RebuildFonts();
- }
-
- ImGui.SameLine();
- if (ImGui.Button("18pt##DalamudSettingsGlobalUiScaleReset18"))
- {
- this.globalUiScale = 18.0f / 12.0f;
- ImGui.GetIO().FontGlobalScale = this.globalUiScale;
- interfaceManager.RebuildFonts();
- }
-
- ImGui.SameLine();
- if (ImGui.Button("36pt##DalamudSettingsGlobalUiScaleReset36"))
- {
- this.globalUiScale = 36.0f / 12.0f;
- ImGui.GetIO().FontGlobalScale = this.globalUiScale;
- interfaceManager.RebuildFonts();
- }
-
- var globalUiScaleInPt = 12f * this.globalUiScale;
- if (ImGui.DragFloat("##DalamudSettingsGlobalUiScaleDrag", ref globalUiScaleInPt, 0.1f, 9.6f, 36f, "%.1fpt", ImGuiSliderFlags.AlwaysClamp))
- {
- this.globalUiScale = globalUiScaleInPt / 12f;
- ImGui.GetIO().FontGlobalScale = this.globalUiScale;
- interfaceManager.RebuildFonts();
- }
-
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsGlobalUiScaleHint", "Scale text in all XIVLauncher UI elements - this is useful for 4K displays."));
-
- ImGuiHelpers.ScaledDummy(10, 16);
-
- if (ImGui.Button(Loc.Localize("DalamudSettingsOpenStyleEditor", "Open Style Editor")))
- {
- Service.Get().OpenStyleEditor();
- }
-
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsStyleEditorHint", "Modify the look & feel of Dalamud windows."));
-
- ImGuiHelpers.ScaledDummy(10);
-
- if (ImGui.Checkbox(Loc.Localize("DalamudSettingToggleAxisFonts", "Use AXIS fonts as default Dalamud font"), ref this.doUseAxisFontsFromGame))
- {
- interfaceManager.UseAxisOverride = this.doUseAxisFontsFromGame;
- interfaceManager.RebuildFonts();
- }
-
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingToggleUiAxisFontsHint", "Use AXIS fonts (the game's main UI fonts) as default Dalamud font."));
-
- ImGuiHelpers.ScaledDummy(10);
-
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingToggleUiHideOptOutNote", "Plugins may independently opt out of the settings below."));
-
- ImGuiHelpers.ScaledDummy(3);
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingToggleUiHide", "Hide plugin UI when the game UI is toggled off"), ref this.doToggleUiHide);
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingToggleUiHideHint", "Hide any open windows by plugins when toggling the game overlay."));
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingToggleUiHideDuringCutscenes", "Hide plugin UI during cutscenes"), ref this.doToggleUiHideDuringCutscenes);
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingToggleUiHideDuringCutscenesHint", "Hide any open windows by plugins during cutscenes."));
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingToggleUiHideDuringGpose", "Hide plugin UI while gpose is active"), ref this.doToggleUiHideDuringGpose);
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingToggleUiHideDuringGposeHint", "Hide any open windows by plugins while gpose is active."));
-
- ImGuiHelpers.ScaledDummy(10, 16);
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingToggleFocusManagement", "Use escape to close Dalamud windows"), ref this.doFocus);
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingToggleFocusManagementHint", "This will cause Dalamud windows to behave like in-game windows when pressing escape.\nThey will close one after another until all are closed. May not work for all plugins."));
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingToggleViewports", "Enable multi-monitor windows"), ref this.doViewport);
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingToggleViewportsHint", "This will allow you move plugin windows onto other monitors.\nWill only work in Borderless Window or Windowed mode."));
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingToggleDocking", "Enable window docking"), ref this.doDocking);
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingToggleDockingHint", "This will allow you to fuse and tab plugin windows."));
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingToggleGamepadNavigation", "Control plugins via gamepad"), ref this.doGamepad);
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingToggleGamepadNavigationHint", "This will allow you to toggle between game and plugin navigation via L1+L3.\nToggle the PluginInstaller window via R3 if ImGui navigation is enabled."));
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingToggleTsm", "Show title screen menu"), ref this.doTsm);
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingToggleTsmHint", "This will allow you to access certain Dalamud and Plugin functionality from the title screen."));
-
- ImGuiHelpers.ScaledDummy(10, 16);
- ImGui.SetCursorPosY(ImGui.GetCursorPosY() + 3);
- ImGui.Text(Loc.Localize("DalamudSettingsFontGamma", "Font Gamma"));
- ImGui.SameLine();
- ImGui.SetCursorPosY(ImGui.GetCursorPosY() - 3);
- if (ImGui.Button(Loc.Localize("DalamudSettingsIndividualConfigResetToDefaultValue", "Reset") + "##DalamudSettingsFontGammaReset"))
- {
- this.fontGamma = 1.4f;
- interfaceManager.FontGammaOverride = this.fontGamma;
- interfaceManager.RebuildFonts();
- }
-
- if (ImGui.DragFloat("##DalamudSettingsFontGammaDrag", ref this.fontGamma, 0.005f, 0.3f, 3f, "%.2f", ImGuiSliderFlags.AlwaysClamp))
- {
- interfaceManager.FontGammaOverride = this.fontGamma;
- interfaceManager.RebuildFonts();
- }
-
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsFontGammaHint", "Changes the thickness of text."));
-
- ImGuiHelpers.ScaledDummy(10, 16);
- }
-
- private void DrawServerInfoBarTab()
- {
- ImGui.Text(Loc.Localize("DalamudSettingServerInfoBar", "Server Info Bar configuration"));
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingServerInfoBarHint", "Plugins can put additional information into your server information bar(where world & time can be seen).\nYou can reorder and disable these here."));
-
- ImGuiHelpers.ScaledDummy(10);
-
- var configuration = Service.Get();
- var dtrBar = Service.Get();
-
- var order = configuration.DtrOrder!.Where(x => dtrBar.HasEntry(x)).ToList();
- var ignore = configuration.DtrIgnore!.Where(x => dtrBar.HasEntry(x)).ToList();
- var orderLeft = configuration.DtrOrder!.Where(x => !order.Contains(x)).ToList();
- var ignoreLeft = configuration.DtrIgnore!.Where(x => !ignore.Contains(x)).ToList();
-
- if (order.Count == 0)
- {
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingServerInfoBarDidNone", "You have no plugins that use this feature."));
- }
-
- var isOrderChange = false;
- for (var i = 0; i < order.Count; i++)
- {
- var title = order[i];
-
- // TODO: Maybe we can also resort the rest of the bar in the future?
- // var isRequired = search is Configuration.SearchSetting.Internal or Configuration.SearchSetting.MacroLinks;
-
- ImGui.PushFont(UiBuilder.IconFont);
-
- var arrowUpText = $"{FontAwesomeIcon.ArrowUp.ToIconString()}##{title}";
- if (i == 0)
- {
- ImGuiComponents.DisabledButton(arrowUpText);
- }
- else
- {
- if (ImGui.Button(arrowUpText))
- {
- (order[i], order[i - 1]) = (order[i - 1], order[i]);
- isOrderChange = true;
- }
- }
-
- ImGui.SameLine();
-
- var arrowDownText = $"{FontAwesomeIcon.ArrowDown.ToIconString()}##{title}";
- if (i == order.Count - 1)
- {
- ImGuiComponents.DisabledButton(arrowDownText);
- }
- else
- {
- if (ImGui.Button(arrowDownText) && i != order.Count - 1)
- {
- (order[i], order[i + 1]) = (order[i + 1], order[i]);
- isOrderChange = true;
- }
- }
-
- ImGui.PopFont();
-
- ImGui.SameLine();
-
- // if (isRequired) {
- // ImGui.TextUnformatted($"Search in {name}");
- // } else {
-
- var isShown = ignore.All(x => x != title);
- var nextIsShow = isShown;
- if (ImGui.Checkbox($"{title}###dtrEntry{i}", ref nextIsShow) && nextIsShow != isShown)
- {
- if (nextIsShow)
- ignore.Remove(title);
- else
- ignore.Add(title);
-
- dtrBar.MakeDirty(title);
- }
-
- // }
- }
-
- configuration.DtrOrder = order.Concat(orderLeft).ToList();
- configuration.DtrIgnore = ignore.Concat(ignoreLeft).ToList();
-
- if (isOrderChange)
- dtrBar.ApplySort();
-
- ImGuiHelpers.ScaledDummy(10);
-
- ImGui.Text(Loc.Localize("DalamudSettingServerInfoBarSpacing", "Server Info Bar spacing"));
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingServerInfoBarSpacingHint", "Configure the amount of space between entries in the server info bar here."));
- ImGui.SliderInt("Spacing", ref this.dtrSpacing, 0, 40);
-
- ImGui.Text(Loc.Localize("DalamudSettingServerInfoBarDirection", "Server Info Bar direction"));
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingServerInfoBarDirectionHint", "If checked, the Server Info Bar elements will expand to the right instead of the left."));
- ImGui.Checkbox("Swap Direction", ref this.dtrSwapDirection);
- }
-
- private void DrawExperimentalTab()
- {
- var configuration = Service.Get();
- var pluginManager = Service.Get();
-
- var useCustomPluginWaitBeforeFree = this.pluginWaitBeforeFree.HasValue;
- if (ImGui.Checkbox(
- Loc.Localize("DalamudSettingsPluginCustomizeWaitTime", "Customize wait time for plugin unload"),
- ref useCustomPluginWaitBeforeFree))
- {
- if (!useCustomPluginWaitBeforeFree)
- this.pluginWaitBeforeFree = null;
- else
- this.pluginWaitBeforeFree = PluginManager.PluginWaitBeforeFreeDefault;
- }
-
- if (useCustomPluginWaitBeforeFree)
- {
- var waitTime = this.pluginWaitBeforeFree ?? PluginManager.PluginWaitBeforeFreeDefault;
- if (ImGui.SliderInt(
- "Wait time###DalamudSettingsPluginCustomizeWaitTimeSlider",
- ref waitTime,
- 0,
- 5000))
- {
- this.pluginWaitBeforeFree = waitTime;
- }
- }
-
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsPluginCustomizeWaitTimeHint", "Configure the wait time between stopping plugin and completely unloading plugin. If you are experiencing crashes when exiting the game, try increasing this value."));
-
- ImGuiHelpers.ScaledDummy(12);
-
- #region Plugin testing
-
- ImGui.Checkbox(Loc.Localize("DalamudSettingsPluginTest", "Get plugin testing builds"), ref this.doPluginTest);
- ImGuiHelpers.SafeTextColoredWrapped(
- ImGuiColors.DalamudGrey,
- string.Format(
- Loc.Localize("DalamudSettingsPluginTestHint", "Receive testing prereleases for selected plugins.\nTo opt-in to testing builds for a plugin, you have to right click it in the \"{0}\" tab of the plugin installer and select \"{1}\"."),
- PluginCategoryManager.Locs.Group_Installed,
- PluginInstallerWindow.Locs.PluginContext_TestingOptIn));
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("DalamudSettingsPluginTestWarning", "Testing plugins may not have been vetted before being published. Please only enable this if you are aware of the risks."));
-
- #endregion
-
- ImGuiHelpers.ScaledDummy(12);
-
- #region Hidden plugins
-
- if (ImGui.Button(Loc.Localize("DalamudSettingsClearHidden", "Clear hidden plugins")))
- {
- configuration.HiddenPluginInternalName.Clear();
- pluginManager.RefilterPluginMasters();
- }
-
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsClearHiddenHint", "Restore plugins you have previously hidden from the plugin installer."));
-
- #endregion
-
- ImGuiHelpers.ScaledDummy(12);
-
- this.DrawCustomReposSection();
-
- ImGuiHelpers.ScaledDummy(12);
-
- this.DrawDevPluginLocationsSection();
-
- ImGuiHelpers.ScaledDummy(12);
-
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, "Total memory used by Dalamud & Plugins: " + Util.FormatBytes(GC.GetTotalMemory(false)));
- }
-
- private void DrawCustomReposSection()
- {
- ImGui.Text(Loc.Localize("DalamudSettingsCustomRepo", "Custom Plugin Repositories"));
- if (this.thirdRepoListChanged)
- {
- ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.HealerGreen);
- ImGui.SameLine();
- ImGui.Text(Loc.Localize("DalamudSettingsChanged", "(Changed)"));
- ImGui.PopStyleColor();
- }
-
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingCustomRepoHint", "Add custom plugin repositories."));
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("DalamudSettingCustomRepoWarning", "We cannot take any responsibility for third-party plugins and repositories."));
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("DalamudSettingCustomRepoWarning2", "Plugins have full control over your PC, like any other program, and may cause harm or crashes."));
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("DalamudSettingCustomRepoWarning3", "Please make absolutely sure that you only install third-party plugins from developers you trust."));
-
- ImGuiHelpers.ScaledDummy(5);
-
- ImGui.Columns(4);
- ImGui.SetColumnWidth(0, 18 + (5 * ImGuiHelpers.GlobalScale));
- ImGui.SetColumnWidth(1, ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X - (18 + 16 + 14) - ((5 + 45 + 26) * ImGuiHelpers.GlobalScale));
- ImGui.SetColumnWidth(2, 16 + (45 * ImGuiHelpers.GlobalScale));
- ImGui.SetColumnWidth(3, 14 + (26 * ImGuiHelpers.GlobalScale));
-
- ImGui.Separator();
-
- ImGui.Text("#");
- ImGui.NextColumn();
- ImGui.Text("URL");
- ImGui.NextColumn();
- ImGui.Text("Enabled");
- ImGui.NextColumn();
- ImGui.Text(string.Empty);
- ImGui.NextColumn();
-
- ImGui.Separator();
-
- ImGui.Text("0");
- ImGui.NextColumn();
- ImGui.Text("XIVLauncher");
- ImGui.NextColumn();
- ImGui.NextColumn();
- ImGui.NextColumn();
- ImGui.Separator();
-
- ThirdPartyRepoSettings repoToRemove = null;
-
- var repoNumber = 1;
- foreach (var thirdRepoSetting in this.thirdRepoList)
- {
- var isEnabled = thirdRepoSetting.IsEnabled;
-
- ImGui.PushID($"thirdRepo_{thirdRepoSetting.Url}");
-
- ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (ImGui.GetColumnWidth() / 2) - 8 - (ImGui.CalcTextSize(repoNumber.ToString()).X / 2));
- ImGui.Text(repoNumber.ToString());
- ImGui.NextColumn();
-
- ImGui.SetNextItemWidth(-1);
- var url = thirdRepoSetting.Url;
- if (ImGui.InputText($"##thirdRepoInput", ref url, 65535, ImGuiInputTextFlags.EnterReturnsTrue))
- {
- var contains = this.thirdRepoList.Select(repo => repo.Url).Contains(url);
- if (thirdRepoSetting.Url == url)
- {
- // no change.
- }
- else if (contains && thirdRepoSetting.Url != url)
- {
- this.thirdRepoAddError = Loc.Localize("DalamudThirdRepoExists", "Repo already exists.");
- Task.Delay(5000).ContinueWith(t => this.thirdRepoAddError = string.Empty);
- }
- else
- {
- thirdRepoSetting.Url = url;
- this.thirdRepoListChanged = url != thirdRepoSetting.Url;
- }
- }
-
- ImGui.NextColumn();
-
- ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (ImGui.GetColumnWidth() / 2) - 7 - (12 * ImGuiHelpers.GlobalScale));
- ImGui.Checkbox("##thirdRepoCheck", ref isEnabled);
- ImGui.NextColumn();
-
- if (ImGuiComponents.IconButton(FontAwesomeIcon.Trash))
- {
- repoToRemove = thirdRepoSetting;
- }
-
- ImGui.PopID();
-
- ImGui.NextColumn();
- ImGui.Separator();
-
- thirdRepoSetting.IsEnabled = isEnabled;
-
- repoNumber++;
- }
-
- if (repoToRemove != null)
- {
- this.thirdRepoList.Remove(repoToRemove);
- this.thirdRepoListChanged = true;
- }
-
- ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (ImGui.GetColumnWidth() / 2) - 8 - (ImGui.CalcTextSize(repoNumber.ToString()).X / 2));
- ImGui.Text(repoNumber.ToString());
- ImGui.NextColumn();
- ImGui.SetNextItemWidth(-1);
- ImGui.InputText("##thirdRepoUrlInput", ref this.thirdRepoTempUrl, 300);
- ImGui.NextColumn();
- // Enabled button
- ImGui.NextColumn();
- if (!string.IsNullOrEmpty(this.thirdRepoTempUrl) && ImGuiComponents.IconButton(FontAwesomeIcon.Plus))
- {
- this.thirdRepoTempUrl = this.thirdRepoTempUrl.TrimEnd();
- if (this.thirdRepoList.Any(r => string.Equals(r.Url, this.thirdRepoTempUrl, StringComparison.InvariantCultureIgnoreCase)))
- {
- this.thirdRepoAddError = Loc.Localize("DalamudThirdRepoExists", "Repo already exists.");
- Task.Delay(5000).ContinueWith(t => this.thirdRepoAddError = string.Empty);
- }
- else
- {
- this.thirdRepoList.Add(new ThirdPartyRepoSettings
- {
- Url = this.thirdRepoTempUrl,
- IsEnabled = true,
- });
- this.thirdRepoListChanged = true;
- this.thirdRepoTempUrl = string.Empty;
- }
- }
-
- ImGui.Columns(1);
-
- if (!string.IsNullOrEmpty(this.thirdRepoAddError))
- {
- ImGuiHelpers.SafeTextColoredWrapped(new Vector4(1, 0, 0, 1), this.thirdRepoAddError);
- }
- }
-
- private void DrawDevPluginLocationsSection()
- {
- ImGui.Text(Loc.Localize("DalamudSettingsDevPluginLocation", "Dev Plugin Locations"));
- if (this.devPluginLocationsChanged)
- {
- ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.HealerGreen);
- ImGui.SameLine();
- ImGui.Text(Loc.Localize("DalamudSettingsChanged", "(Changed)"));
- ImGui.PopStyleColor();
- }
-
- ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsDevPluginLocationsHint", "Add additional dev plugin load locations.\nThese can be either the directory or DLL path."));
-
- ImGuiHelpers.ScaledDummy(5);
-
- ImGui.Columns(4);
- ImGui.SetColumnWidth(0, 18 + (5 * ImGuiHelpers.GlobalScale));
- ImGui.SetColumnWidth(1, ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X - (18 + 16 + 14) - ((5 + 45 + 26) * ImGuiHelpers.GlobalScale));
- ImGui.SetColumnWidth(2, 16 + (45 * ImGuiHelpers.GlobalScale));
- ImGui.SetColumnWidth(3, 14 + (26 * ImGuiHelpers.GlobalScale));
-
- ImGui.Separator();
-
- ImGui.Text("#");
- ImGui.NextColumn();
- ImGui.Text("Path");
- ImGui.NextColumn();
- ImGui.Text("Enabled");
- ImGui.NextColumn();
- ImGui.Text(string.Empty);
- ImGui.NextColumn();
-
- ImGui.Separator();
-
- DevPluginLocationSettings locationToRemove = null;
-
- var locNumber = 1;
- foreach (var devPluginLocationSetting in this.devPluginLocations)
- {
- var isEnabled = devPluginLocationSetting.IsEnabled;
-
- ImGui.PushID($"devPluginLocation_{devPluginLocationSetting.Path}");
-
- ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (ImGui.GetColumnWidth() / 2) - 8 - (ImGui.CalcTextSize(locNumber.ToString()).X / 2));
- ImGui.Text(locNumber.ToString());
- ImGui.NextColumn();
-
- ImGui.SetNextItemWidth(-1);
- var path = devPluginLocationSetting.Path;
- if (ImGui.InputText($"##devPluginLocationInput", ref path, 65535, ImGuiInputTextFlags.EnterReturnsTrue))
- {
- var contains = this.devPluginLocations.Select(loc => loc.Path).Contains(path);
- if (devPluginLocationSetting.Path == path)
- {
- // no change.
- }
- else if (contains && devPluginLocationSetting.Path != path)
- {
- this.devPluginLocationAddError = Loc.Localize("DalamudDevPluginLocationExists", "Location already exists.");
- Task.Delay(5000).ContinueWith(t => this.devPluginLocationAddError = string.Empty);
- }
- else
- {
- devPluginLocationSetting.Path = path;
- this.devPluginLocationsChanged = path != devPluginLocationSetting.Path;
- }
- }
-
- ImGui.NextColumn();
-
- ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (ImGui.GetColumnWidth() / 2) - 7 - (12 * ImGuiHelpers.GlobalScale));
- ImGui.Checkbox("##devPluginLocationCheck", ref isEnabled);
- ImGui.NextColumn();
-
- if (ImGuiComponents.IconButton(FontAwesomeIcon.Trash))
- {
- locationToRemove = devPluginLocationSetting;
- }
-
- ImGui.PopID();
-
- ImGui.NextColumn();
- ImGui.Separator();
-
- devPluginLocationSetting.IsEnabled = isEnabled;
-
- locNumber++;
- }
-
- if (locationToRemove != null)
- {
- this.devPluginLocations.Remove(locationToRemove);
- this.devPluginLocationsChanged = true;
- }
-
- ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (ImGui.GetColumnWidth() / 2) - 8 - (ImGui.CalcTextSize(locNumber.ToString()).X / 2));
- ImGui.Text(locNumber.ToString());
- ImGui.NextColumn();
- ImGui.SetNextItemWidth(-1);
- ImGui.InputText("##devPluginLocationInput", ref this.devPluginTempLocation, 300);
- ImGui.NextColumn();
- // Enabled button
- ImGui.NextColumn();
- if (!string.IsNullOrEmpty(this.devPluginTempLocation) && ImGuiComponents.IconButton(FontAwesomeIcon.Plus))
- {
- if (this.devPluginLocations.Any(r => string.Equals(r.Path, this.devPluginTempLocation, StringComparison.InvariantCultureIgnoreCase)))
- {
- this.devPluginLocationAddError = Loc.Localize("DalamudDevPluginLocationExists", "Location already exists.");
- Task.Delay(5000).ContinueWith(t => this.devPluginLocationAddError = string.Empty);
- }
- else
- {
- this.devPluginLocations.Add(new DevPluginLocationSettings
- {
- Path = this.devPluginTempLocation.Replace("\"", string.Empty),
- IsEnabled = true,
- });
- this.devPluginLocationsChanged = true;
- this.devPluginTempLocation = string.Empty;
- }
- }
-
- ImGui.Columns(1);
-
- if (!string.IsNullOrEmpty(this.devPluginLocationAddError))
- {
- ImGuiHelpers.SafeTextColoredWrapped(new Vector4(1, 0, 0, 1), this.devPluginLocationAddError);
- }
- }
-
- private void DrawSaveCloseButtons()
- {
- var buttonSave = false;
- var buttonClose = false;
-
- var pluginManager = Service.Get();
-
- if (ImGui.Button(Loc.Localize("Save", "Save")))
- buttonSave = true;
-
- ImGui.SameLine();
-
- if (ImGui.Button(Loc.Localize("Close", "Close")))
- buttonClose = true;
-
- ImGui.SameLine();
-
- if (ImGui.Button(Loc.Localize("SaveAndClose", "Save and Close")))
- buttonSave = buttonClose = true;
-
- if (buttonSave)
- {
- this.Save();
-
- if (this.thirdRepoListChanged)
- {
- _ = pluginManager.SetPluginReposFromConfigAsync(true);
- this.thirdRepoListChanged = false;
- }
-
- if (this.devPluginLocationsChanged)
- {
- pluginManager.ScanDevPlugins();
- this.devPluginLocationsChanged = false;
- }
- }
-
- if (buttonClose)
- {
- this.IsOpen = false;
- }
- }
-
- private void Save()
- {
- var configuration = Service.Get();
- var localization = Service.Get();
-
- localization.SetupWithLangCode(this.languages[this.langIndex]);
- configuration.LanguageOverride = this.languages[this.langIndex];
-
- configuration.GeneralChatType = this.dalamudMessagesChatType;
-
- configuration.IsResumeGameAfterPluginLoad = this.doWaitForPluginsOnStartup;
- configuration.DutyFinderTaskbarFlash = this.doCfTaskBarFlash;
- configuration.DutyFinderChatMessage = this.doCfChatMessage;
- configuration.IsMbCollect = this.doMbCollect;
-
- configuration.GlobalUiScale = this.globalUiScale;
- configuration.ToggleUiHide = this.doToggleUiHide;
- configuration.ToggleUiHideDuringCutscenes = this.doToggleUiHideDuringCutscenes;
- configuration.ToggleUiHideDuringGpose = this.doToggleUiHideDuringGpose;
-
- configuration.IsDocking = this.doDocking;
- configuration.IsGamepadNavigationEnabled = this.doGamepad;
- configuration.IsFocusManagementEnabled = this.doFocus;
- configuration.ShowTsm = this.doTsm;
-
- configuration.UseAxisFontsFromGame = this.doUseAxisFontsFromGame;
- configuration.FontGammaLevel = this.fontGamma;
-
- // This is applied every frame in InterfaceManager::CheckViewportState()
- configuration.IsDisableViewport = !this.doViewport;
-
- // Apply docking flag
- if (!configuration.IsDocking)
- {
- ImGui.GetIO().ConfigFlags &= ~ImGuiConfigFlags.DockingEnable;
- }
- else
- {
- ImGui.GetIO().ConfigFlags |= ImGuiConfigFlags.DockingEnable;
- }
-
- // NOTE (Chiv) Toggle gamepad navigation via setting
- if (!configuration.IsGamepadNavigationEnabled)
- {
- ImGui.GetIO().BackendFlags &= ~ImGuiBackendFlags.HasGamepad;
- ImGui.GetIO().ConfigFlags &= ~ImGuiConfigFlags.NavEnableSetMousePos;
-
- var di = Service.Get();
- di.CloseGamepadModeNotifierWindow();
- }
- else
- {
- ImGui.GetIO().BackendFlags |= ImGuiBackendFlags.HasGamepad;
- ImGui.GetIO().ConfigFlags |= ImGuiConfigFlags.NavEnableSetMousePos;
- }
-
- this.dtrOrder = configuration.DtrOrder;
- this.dtrIgnore = configuration.DtrIgnore;
-
- configuration.DtrSpacing = this.dtrSpacing;
- configuration.DtrSwapDirection = this.dtrSwapDirection;
-
- configuration.PluginWaitBeforeFree = this.pluginWaitBeforeFree;
-
- configuration.DoPluginTest = this.doPluginTest;
- configuration.ThirdRepoList = this.thirdRepoList.Select(x => x.Clone()).ToList();
- configuration.DevPluginLoadLocations = this.devPluginLocations.Select(x => x.Clone()).ToList();
-
- configuration.PrintPluginsWelcomeMsg = this.printPluginsWelcomeMsg;
- configuration.AutoUpdatePlugins = this.autoUpdatePlugins;
- configuration.DoButtonsSystemMenu = this.doButtonsSystemMenu;
- configuration.DisableRmtFiltering = this.disableRmtFiltering;
-
- configuration.QueueSave();
-
- _ = Service.Get().ReloadPluginMastersAsync();
- Service.Get().RebuildFonts();
- }
-}
diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs
index 06cb52845..e03db5e91 100644
--- a/Dalamud/Plugin/Internal/PluginManager.cs
+++ b/Dalamud/Plugin/Internal/PluginManager.cs
@@ -43,7 +43,7 @@ internal partial class PluginManager : IDisposable, IServiceType
///
/// Default time to wait between plugin unload and plugin assembly unload.
///
- public const int PluginWaitBeforeFreeDefault = 500;
+ public const int PluginWaitBeforeFreeDefault = 1000; // upped from 500ms, seems more stable
private const string DevPluginsDisclaimerFilename = "DONT_USE_THIS_FOLDER.txt";
diff --git a/Dalamud/Utility/EnumExtensions.cs b/Dalamud/Utility/EnumExtensions.cs
index 8868e4c1f..b4c58d95c 100644
--- a/Dalamud/Utility/EnumExtensions.cs
+++ b/Dalamud/Utility/EnumExtensions.cs
@@ -14,12 +14,15 @@ public static class EnumExtensions
/// The type of attribute to get.
/// The enum value that has an attached attribute.
/// The attached attribute, if any.
- public static TAttribute GetAttribute(this Enum value)
+ public static TAttribute? GetAttribute(this Enum value)
where TAttribute : Attribute
{
var type = value.GetType();
var name = Enum.GetName(type, value);
- return type.GetField(name) // I prefer to get attributes this way
+ if (name.IsNullOrEmpty())
+ return null;
+
+ return type.GetField(name)?
.GetCustomAttributes(false)
.OfType()
.SingleOrDefault();