diff --git a/Dalamud/Interface/DalamudPluginStatWindow.cs b/Dalamud/Interface/DalamudPluginStatWindow.cs
index d99192a14..78b6c4f0b 100644
--- a/Dalamud/Interface/DalamudPluginStatWindow.cs
+++ b/Dalamud/Interface/DalamudPluginStatWindow.cs
@@ -35,9 +35,9 @@ namespace Dalamud.Interface {
ImGui.SameLine();
if (ImGui.Button("Reset")) {
foreach (var a in this.pluginManager.Plugins) {
- a.PluginInterface.UiBuilder.lastDrawTime = -1;
- a.PluginInterface.UiBuilder.maxDrawTime = -1;
- a.PluginInterface.UiBuilder.drawTimeHistory.Clear();
+ a.PluginInterface.UiBuilder.LastDrawTime = -1;
+ a.PluginInterface.UiBuilder.MaxDrawTime = -1;
+ a.PluginInterface.UiBuilder.DrawTimeHistory.Clear();
}
}
@@ -59,12 +59,12 @@ namespace Dalamud.Interface {
foreach (var a in this.pluginManager.Plugins) {
ImGui.Text(a.Definition.Name);
ImGui.NextColumn();
- ImGui.Text($"{a.PluginInterface.UiBuilder.lastDrawTime/10000f:F4}ms");
+ ImGui.Text($"{a.PluginInterface.UiBuilder.LastDrawTime/10000f:F4}ms");
ImGui.NextColumn();
- ImGui.Text($"{a.PluginInterface.UiBuilder.maxDrawTime/10000f:F4}ms");
+ ImGui.Text($"{a.PluginInterface.UiBuilder.MaxDrawTime/10000f:F4}ms");
ImGui.NextColumn();
- if (a.PluginInterface.UiBuilder.drawTimeHistory.Count > 0) {
- ImGui.Text($"{a.PluginInterface.UiBuilder.drawTimeHistory.Average()/10000f:F4}ms");
+ if (a.PluginInterface.UiBuilder.DrawTimeHistory.Count > 0) {
+ ImGui.Text($"{a.PluginInterface.UiBuilder.DrawTimeHistory.Average()/10000f:F4}ms");
} else {
ImGui.Text("-");
}
diff --git a/Dalamud/Interface/UiBuilder.cs b/Dalamud/Interface/UiBuilder.cs
index 12cb86047..44f2e7259 100644
--- a/Dalamud/Interface/UiBuilder.cs
+++ b/Dalamud/Interface/UiBuilder.cs
@@ -1,10 +1,7 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+
using Dalamud.Game.ClientState;
-using Dalamud.Game.Internal.Gui;
using ImGuiNET;
using ImGuiScene;
using Serilog;
@@ -16,27 +13,28 @@ namespace Dalamud.Interface
/// This class represents the Dalamud UI that is drawn on top of the game.
/// It can be used to draw custom windows and overlays.
///
- public class UiBuilder : IDisposable {
+ public class UiBuilder : IDisposable
+ {
private readonly string namespaceName;
+ private readonly Dalamud dalamud;
+ private readonly System.Diagnostics.Stopwatch stopwatch;
+
+ private bool hasErrorWindow;
///
- /// The game's active Direct3D device.
+ /// Initializes a new instance of the class and registers it.
+ /// You do not have to call this manually.
///
- public Device Device => this.dalamud.InterfaceManager.Device;
-
- ///
- /// The game's main window handle.
- ///
- public IntPtr WindowHandlePtr => this.dalamud.InterfaceManager.WindowHandlePtr;
+ /// The dalamud to register on.
+ /// The plugin namespace.
+ internal UiBuilder(Dalamud dalamud, string namespaceName)
+ {
+ this.namespaceName = namespaceName;
- ///
- /// The default Dalamud font based on Noto Sans CJK Medium in 17pt - supporting all game languages and icons.
- ///
- public static ImFontPtr DefaultFont => InterfaceManager.DefaultFont;
- ///
- /// The default Dalamud icon font based on FontAwesome 5 Free solid in 17pt.
- ///
- public static ImFontPtr IconFont => InterfaceManager.IconFont;
+ this.dalamud = dalamud;
+ this.dalamud.InterfaceManager.OnDraw += this.OnDraw;
+ this.stopwatch = new System.Diagnostics.Stopwatch();
+ }
///
/// The delegate that gets called when Dalamud is ready to draw your windows or overlays.
@@ -45,69 +43,104 @@ namespace Dalamud.Interface
public event RawDX11Scene.BuildUIDelegate OnBuildUi;
///
- /// Choose if this plugin should hide its UI automatically when the game's UI is hidden.
+ /// Event that is fired when the plugin should open its configuration interface.
+ ///
+ public event EventHandler OnOpenConfigUi;
+
+ ///
+ /// Gets the default Dalamud font based on Noto Sans CJK Medium in 17pt - supporting all game languages and icons.
+ ///
+ public static ImFontPtr DefaultFont => InterfaceManager.DefaultFont;
+
+ ///
+ /// Gets the default Dalamud icon font based on FontAwesome 5 Free solid in 17pt.
+ ///
+ public static ImFontPtr IconFont => InterfaceManager.IconFont;
+
+ ///
+ /// Gets the game's active Direct3D device.
+ ///
+ public Device Device => this.dalamud.InterfaceManager.Device;
+
+ ///
+ /// Gets the game's main window handle.
+ ///
+ public IntPtr WindowHandlePtr => this.dalamud.InterfaceManager.WindowHandlePtr;
+
+ ///
+ /// Gets or sets a value indicating whether this plugin should hide its UI automatically when the game's UI is hidden.
///
public bool DisableAutomaticUiHide { get; set; } = false;
///
- /// Choose if this plugin should hide its UI automatically when the user toggles the UI.
+ /// Gets or sets a value indicating whether this plugin should hide its UI automatically when the user toggles the UI.
///
public bool DisableUserUiHide { get; set; } = false;
///
- /// Choose if this plugin should hide its UI automatically during cutscenes.
+ /// Gets or sets a value indicating whether this plugin should hide its UI automatically during cutscenes.
///
public bool DisableCutsceneUiHide { get; set; } = false;
///
- /// Choose if this plugin should hide its UI automatically while gpose is active.
+ /// Gets or sets a value indicating whether this plugin should hide its UI automatically while gpose is active.
///
public bool DisableGposeUiHide { get; set; } = false;
+ ///
+ /// Gets or sets an action that is called any time ImGui fonts need to be rebuilt.
+ /// Any ImFontPtr objects that you store can be invalidated when fonts are rebuilt
+ /// (at any time), so you should both reload your custom fonts and restore those
+ /// pointers inside this handler.
+ /// PLEASE remove this handler inside Dispose, or when you no longer need your fonts!
+ ///
+ public Action OnBuildFonts
+ {
+ get => this.dalamud.InterfaceManager.OnBuildFonts;
+ set => this.dalamud.InterfaceManager.OnBuildFonts = value;
+ }
+
+ ///
+ /// Gets or sets a value indicating whether statistics about UI draw time should be collected.
+ ///
+#if DEBUG
+ internal static bool DoStats { get; set; } = true;
+#else
+ internal static bool DoStats { get; set; } = false;
+#endif
+
+ ///
+ /// Gets a value indicating whether this UiBuilder has a configuration UI registered.
+ ///
+ internal bool HasConfigUi => this.OnOpenConfigUi != null;
+
+ ///
+ /// Gets or sets the time this plugin took to draw on the last frame.
+ ///
+ internal long LastDrawTime { get; set; } = -1;
+
+ ///
+ /// Gets or sets the longest amount of time this plugin ever took to draw.
+ ///
+ internal long MaxDrawTime { get; set; } = -1;
+
+ ///
+ /// Gets or sets a history of the last draw times, used to calculate an average.
+ ///
+ internal List DrawTimeHistory { get; set; } = new List();
+
private bool CutsceneActive => this.dalamud.ClientState != null &&
(this.dalamud.ClientState.Condition[ConditionFlag.OccupiedInCutSceneEvent] ||
- this.dalamud.ClientState.Condition[ConditionFlag.WatchingCutscene78]);
+ this.dalamud.ClientState.Condition[ConditionFlag.WatchingCutscene78]);
private bool GposeActive => this.dalamud.ClientState != null &&
this.dalamud.ClientState.Condition[ConditionFlag.WatchingCutscene];
- private Dalamud dalamud;
-
-#if DEBUG
- internal static bool DoStats { get; set; } = true;
- #else
- internal static bool DoStats { get; set; } = false;
- #endif
- private System.Diagnostics.Stopwatch stopwatch;
- internal long lastDrawTime = -1;
- internal long maxDrawTime = -1;
- internal List drawTimeHistory = new List();
-
- ///
- /// Create a new UiBuilder and register it. You do not have to call this manually.
- ///
- /// The interface manager to register on.
- /// The plugin namespace.
- internal UiBuilder(Dalamud dalamud, string namespaceName) {
- this.namespaceName = namespaceName;
-
- this.dalamud = dalamud;
- this.dalamud.InterfaceManager.OnDraw += OnDraw;
- this.stopwatch = new System.Diagnostics.Stopwatch();
- }
-
- ///
- /// Unregister the UiBuilder. Do not call this in plugin code.
- ///
- public void Dispose() {
- this.dalamud.InterfaceManager.OnDraw -= OnDraw;
- }
-
///
/// Loads an image from the specified file.
///
/// The full filepath to the image.
- /// A object wrapping the created image. Use inside ImGui.Image()
+ /// A object wrapping the created image. Use inside ImGui.Image().
public TextureWrap LoadImage(string filePath) =>
this.dalamud.InterfaceManager.LoadImage(filePath);
@@ -115,7 +148,7 @@ namespace Dalamud.Interface
/// Loads an image from a byte stream, such as a png downloaded into memory.
///
/// A byte array containing the raw image data.
- /// A object wrapping the created image. Use inside ImGui.Image()
+ /// A object wrapping the created image. Use inside ImGui.Image().
public TextureWrap LoadImage(byte[] imageData) =>
this.dalamud.InterfaceManager.LoadImage(imageData);
@@ -126,23 +159,10 @@ namespace Dalamud.Interface
/// The width of the image contained in .
/// The height of the image contained in .
/// The number of channels (bytes per pixel) of the image contained in . This should usually be 4.
- /// A object wrapping the created image. Use inside ImGui.Image()
+ /// A object wrapping the created image. Use inside ImGui.Image().
public TextureWrap LoadImageRaw(byte[] imageData, int width, int height, int numChannels) =>
this.dalamud.InterfaceManager.LoadImageRaw(imageData, width, height, numChannels);
- ///
- /// An event that is called any time ImGui fonts need to be rebuilt.
- /// Any ImFontPtr objects that you store can be invalidated when fonts are rebuilt
- /// (at any time), so you should both reload your custom fonts and restore those
- /// pointers inside this handler.
- /// PLEASE remove this handler inside Dispose, or when you no longer need your fonts!
- ///
- public Action OnBuildFonts
- {
- get { return this.dalamud.InterfaceManager.OnBuildFonts; }
- set { this.dalamud.InterfaceManager.OnBuildFonts = value; }
- }
-
///
/// Call this to queue a rebuild of the font atlas.
/// This will invoke any handlers and ensure that any loaded fonts are
@@ -155,53 +175,70 @@ namespace Dalamud.Interface
}
///
- /// Event that is fired when the plugin should open its configuration interface.
+ /// Unregister the UiBuilder. Do not call this in plugin code.
///
- public EventHandler OnOpenConfigUi;
+ public void Dispose()
+ {
+ this.dalamud.InterfaceManager.OnDraw -= this.OnDraw;
+ }
- private bool hasErrorWindow;
+ ///
+ /// Open the registered configuration UI, if it exists.
+ ///
+ internal void OpenConfigUi()
+ {
+ this.OnOpenConfigUi?.Invoke(this, null);
+ }
- private void OnDraw() {
-
- if (this.dalamud.Framework.Gui.GameUiHidden && this.dalamud.Configuration.ToggleUiHide && !(DisableUserUiHide || DisableAutomaticUiHide) ||
- CutsceneActive && this.dalamud.Configuration.ToggleUiHideDuringCutscenes && !(DisableCutsceneUiHide || DisableAutomaticUiHide) ||
- GposeActive && this.dalamud.Configuration.ToggleUiHideDuringGpose && !(DisableGposeUiHide || DisableAutomaticUiHide))
+ private void OnDraw()
+ {
+ if ((this.dalamud.Framework.Gui.GameUiHidden && this.dalamud.Configuration.ToggleUiHide && !(this.DisableUserUiHide || this.DisableAutomaticUiHide)) ||
+ (this.CutsceneActive && this.dalamud.Configuration.ToggleUiHideDuringCutscenes && !(this.DisableCutsceneUiHide || this.DisableAutomaticUiHide)) ||
+ (this.GposeActive && this.dalamud.Configuration.ToggleUiHideDuringGpose && !(this.DisableGposeUiHide || this.DisableAutomaticUiHide)))
return;
ImGui.PushID(this.namespaceName);
- if (DoStats) {
+ if (DoStats)
+ {
this.stopwatch.Restart();
}
- if (this.hasErrorWindow && ImGui.Begin(string.Format("{0} Error", this.namespaceName), ref this.hasErrorWindow,
- ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoResize)) {
- ImGui.Text(string.Format("The plugin {0} ran into an error.\nContact the plugin developer for support.\n\nPlease try restarting your game.", this.namespaceName));
+ if (this.hasErrorWindow && ImGui.Begin($"{this.namespaceName} Error", ref this.hasErrorWindow, ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoResize))
+ {
+ ImGui.Text(
+ $"The plugin {this.namespaceName} ran into an error.\nContact the plugin developer for support.\n\nPlease try restarting your game.");
ImGui.Spacing();
- if (ImGui.Button("OK")) {
+ if (ImGui.Button("OK"))
+ {
this.hasErrorWindow = false;
}
ImGui.End();
}
- try {
- OnBuildUi?.Invoke();
- } catch (Exception ex) {
+ try
+ {
+ this.OnBuildUi?.Invoke();
+ }
+ catch (Exception ex)
+ {
Log.Error(ex, "[{0}] UiBuilder OnBuildUi caught exception", this.namespaceName);
- OnBuildUi = null;
- OnOpenConfigUi = null;
+ this.OnBuildUi = null;
+ this.OnOpenConfigUi = null;
this.hasErrorWindow = true;
}
-
- if (DoStats) {
+
+ if (DoStats)
+ {
this.stopwatch.Stop();
- this.lastDrawTime = this.stopwatch.ElapsedTicks;
- this.maxDrawTime = Math.Max(this.lastDrawTime, this.maxDrawTime);
- this.drawTimeHistory.Add(lastDrawTime);
- while (drawTimeHistory.Count > 100) drawTimeHistory.RemoveAt(0);
+ this.LastDrawTime = this.stopwatch.ElapsedTicks;
+ this.MaxDrawTime = Math.Max(this.LastDrawTime, this.MaxDrawTime);
+ this.DrawTimeHistory.Add(this.LastDrawTime);
+ while (this.DrawTimeHistory.Count > 100) this.DrawTimeHistory.RemoveAt(0);
}
+
ImGui.PopID();
}
}
diff --git a/Dalamud/Plugin/PluginInstallerWindow.cs b/Dalamud/Plugin/PluginInstallerWindow.cs
index 1ccd1002f..f487eac8d 100644
--- a/Dalamud/Plugin/PluginInstallerWindow.cs
+++ b/Dalamud/Plugin/PluginInstallerWindow.cs
@@ -439,11 +439,11 @@ namespace Dalamud.Plugin
}
}
- if (installedPlugin.PluginInterface.UiBuilder.OnOpenConfigUi != null) {
+ if (installedPlugin.PluginInterface.UiBuilder.HasConfigUi) {
ImGui.SameLine();
if (ImGui.Button(Loc.Localize("InstallerOpenConfig", "Open Configuration")))
- installedPlugin.PluginInterface.UiBuilder.OnOpenConfigUi?.Invoke(null, null);
+ installedPlugin.PluginInterface.UiBuilder.OpenConfigUi();
}
if (!string.IsNullOrEmpty(installedPlugin.Definition.RepoUrl)) {