From f5830cf09a33a295c2080b147d71b1aa9ca5c9e5 Mon Sep 17 00:00:00 2001 From: goat <16760685+goaaats@users.noreply.github.com> Date: Wed, 31 Mar 2021 17:03:11 +0200 Subject: [PATCH] refactor: new code style in UiBuilder.cs --- Dalamud/Interface/DalamudPluginStatWindow.cs | 14 +- Dalamud/Interface/UiBuilder.cs | 231 +++++++++++-------- Dalamud/Plugin/PluginInstallerWindow.cs | 4 +- 3 files changed, 143 insertions(+), 106 deletions(-) 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)) {