From 266865a14c5aed696d50d6cd0b85d4677c1af288 Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Mon, 5 Apr 2021 17:48:03 +0200
Subject: [PATCH] feat: add new ImGui windowing system
---
Dalamud/Interface/Windowing/Window.cs | 144 ++++++++++++++++++++
Dalamud/Interface/Windowing/WindowSystem.cs | 73 ++++++++++
2 files changed, 217 insertions(+)
create mode 100644 Dalamud/Interface/Windowing/Window.cs
create mode 100644 Dalamud/Interface/Windowing/WindowSystem.cs
diff --git a/Dalamud/Interface/Windowing/Window.cs b/Dalamud/Interface/Windowing/Window.cs
new file mode 100644
index 000000000..98e73f6f9
--- /dev/null
+++ b/Dalamud/Interface/Windowing/Window.cs
@@ -0,0 +1,144 @@
+using System.Numerics;
+
+using ImGuiNET;
+
+namespace Dalamud.Interface.Windowing
+{
+ ///
+ /// Base class you can use to implement an ImGui window for use with the built-in .
+ ///
+ public abstract class Window
+ {
+ private bool internalIsOpen;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The name/ID of this window.
+ /// If you have multiple windows with the same name, you will need to
+ /// append an unique ID to it by specifying it after "###" behind the window title.
+ ///
+ /// The of this window.
+ /// Whether or not this window should be limited to the main game window.
+ protected Window(string name, ImGuiWindowFlags flags, bool forceMainWindow = false)
+ {
+ this.WindowName = name;
+ this.Flags = flags;
+ this.ForceMainWindow = forceMainWindow;
+ }
+
+ ///
+ /// Gets or sets the name of the window.
+ /// If you have multiple windows with the same name, you will need to
+ /// append an unique ID to it by specifying it after "###" behind the window title.
+ ///
+ public string WindowName { get; set; }
+
+ ///
+ /// Gets or sets the position of this window.
+ ///
+ public Vector2? Position { get; set; }
+
+ ///
+ /// Gets or sets the condition that defines when the position of this window is set.
+ ///
+ public ImGuiCond PositionCondition { get; set; }
+
+ ///
+ /// Gets or sets the size of the window.
+ ///
+ public Vector2? Size { get; set; }
+
+ ///
+ /// Gets or sets the condition that defines when the size of this window is set.
+ ///
+ public ImGuiCond SizeCondition { get; set; }
+
+ ///
+ /// Gets or sets the minimum size of this window.
+ ///
+ public Vector2? SizeConstraintsMin { get; set; }
+
+ ///
+ /// Gets or sets the maximum size of this window.
+ ///
+ public Vector2? SizeConstraintsMax { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether or not this window is collapsed.
+ ///
+ public bool? Collapsed { get; set; }
+
+ ///
+ /// Gets or sets the condition that defines when the collapsed state of this window is set.
+ ///
+ public ImGuiCond CollapsedCondition { get; set; }
+
+ ///
+ /// Gets or sets the window flags.
+ ///
+ public ImGuiWindowFlags Flags { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether or not this ImGui window will be forced to stay inside the main game window.
+ ///
+ public bool ForceMainWindow { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether or not this window will stay open.
+ ///
+ public bool IsOpen
+ {
+ get => this.internalIsOpen;
+ set => this.internalIsOpen = value;
+ }
+
+ ///
+ /// In this method, implement your drawing code.
+ /// You do NOT need to ImGui.Begin your window.
+ ///
+ public abstract void Draw();
+
+ ///
+ /// Draw the window via ImGui.
+ ///
+ internal void DrawInternal()
+ {
+ this.ApplyConditionals();
+
+ if (this.ForceMainWindow)
+ ImGuiHelpers.ForceMainWindow();
+
+ if (ImGui.Begin(this.WindowName, ref this.internalIsOpen, this.Flags))
+ {
+ // Draw the actual window contents
+ this.Draw();
+
+ ImGui.End();
+ }
+ }
+
+ private void ApplyConditionals()
+ {
+ if (this.Position.HasValue)
+ {
+ ImGui.SetNextWindowPos(this.Position.Value, this.PositionCondition);
+ }
+
+ if (this.Size.HasValue)
+ {
+ ImGui.SetNextWindowPos(this.Size.Value, this.SizeCondition);
+ }
+
+ if (this.Collapsed.HasValue)
+ {
+ ImGui.SetNextWindowCollapsed(this.Collapsed.Value, this.CollapsedCondition);
+ }
+
+ if (this.SizeConstraintsMin.HasValue && this.SizeConstraintsMax.HasValue)
+ {
+ ImGui.SetNextWindowSizeConstraints(this.SizeConstraintsMin.Value, this.SizeConstraintsMax.Value);
+ }
+ }
+ }
+}
diff --git a/Dalamud/Interface/Windowing/WindowSystem.cs b/Dalamud/Interface/Windowing/WindowSystem.cs
new file mode 100644
index 000000000..b683bb8c3
--- /dev/null
+++ b/Dalamud/Interface/Windowing/WindowSystem.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using ImGuiNET;
+
+namespace Dalamud.Interface.Windowing
+{
+ ///
+ /// Class running a WindowSystem using implementations to simplify ImGui windowing.
+ ///
+ public class WindowSystem
+ {
+ private readonly List windows = new List();
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The name/ID-space of this .
+ public WindowSystem(string imNamespace = null)
+ {
+ this.Namespace = imNamespace;
+ }
+
+ ///
+ /// Gets or sets the name/ID-space of this .
+ ///
+ public string Namespace { get; set; }
+
+ ///
+ /// Add a window to this .
+ ///
+ /// The window to add.
+ public void AddWindow(Window window)
+ {
+ if (this.windows.Any(x => x.WindowName == window.WindowName))
+ throw new ArgumentException("A window with this name/ID already exists.");
+
+ this.windows.Add(window);
+ }
+
+ ///
+ /// Remove a window from this .
+ ///
+ /// The window to remove.
+ public void RemoveWindow(Window window)
+ {
+ if (!this.windows.Contains(window))
+ throw new ArgumentException("This window is not registered on this WindowSystem.");
+
+ this.windows.Remove(window);
+ }
+
+ ///
+ /// Draw all registered windows using ImGui.
+ ///
+ public void Draw()
+ {
+ var hasNamespace = !string.IsNullOrEmpty(this.Namespace);
+
+ if (hasNamespace)
+ ImGui.PushID(this.Namespace);
+
+ foreach (var window in this.windows)
+ {
+ window.DrawInternal();
+ }
+
+ if (hasNamespace)
+ ImGui.PopID();
+ }
+ }
+}