From 327cfaad0d59ebcd01f49e238c733ea03da38555 Mon Sep 17 00:00:00 2001 From: matt-edmondson Date: Fri, 16 Feb 2024 12:29:16 +1100 Subject: [PATCH 1/5] WIP PopupInput --- ImGuiWidgets/PopupInput.cs | 44 ++++++++++++++++++++++++++ ImGuiWidgetsDemo/Directory.Build.props | 4 +-- 2 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 ImGuiWidgets/PopupInput.cs diff --git a/ImGuiWidgets/PopupInput.cs b/ImGuiWidgets/PopupInput.cs new file mode 100644 index 0000000..0768a25 --- /dev/null +++ b/ImGuiWidgets/PopupInput.cs @@ -0,0 +1,44 @@ +namespace ktsu.io.ImGuiWidgets; + +using ImGuiNET; + +/// +/// Base class for a popup input window. +/// +/// The type of the input value. +/// The type of the derived class for CRTP. +public abstract class PopupInput where TDerived : PopupInput, new() +{ + public static bool Show(string title, string label, ref TInput input) + { + bool result = false; + if (ImGui.IsPopupOpen(title)) + { + ImGui.OpenPopup(title); + } + + if (ImGui.BeginPopupModal(title, ref result, ImGuiWindowFlags.AlwaysAutoResize)) + { + ImGui.Text(label); + ImGui.NewLine(); + if (new TDerived().ShowEdit(ref input)) + { + ImGui.CloseCurrentPopup(); + } + ImGui.SameLine(); + if (ImGui.Button("OK")) + { + ImGui.CloseCurrentPopup(); + } + ImGui.EndPopup(); + } + return result; + } + + protected abstract bool ShowEdit(ref TInput input); +} + +public class PopupInputString : PopupInput +{ + protected override bool ShowEdit(ref string input) => ImGui.InputText("##Input", ref input, 100); +} diff --git a/ImGuiWidgetsDemo/Directory.Build.props b/ImGuiWidgetsDemo/Directory.Build.props index 3d6f8bb..d65a9de 100644 --- a/ImGuiWidgetsDemo/Directory.Build.props +++ b/ImGuiWidgetsDemo/Directory.Build.props @@ -1,9 +1,7 @@ - net7.0-windows - true - true + net7.0 Exe false From 685ce46044bbb27aaa2acdf75424d0878a1ebac3 Mon Sep 17 00:00:00 2001 From: matt-edmondson Date: Sun, 18 Feb 2024 12:13:33 +1100 Subject: [PATCH 2/5] Add modal input popups for strings, ints, and floats --- ImGuiWidgets/Directory.Build.props | 2 +- ImGuiWidgets/PopupInput.cs | 95 +++++++++++++++++++++--- ImGuiWidgetsDemo/ImGuiWidgetsDemo.cs | 12 +++ ImGuiWidgetsDemo/ImGuiWidgetsDemo.csproj | 2 +- README.md | 13 +++- 5 files changed, 110 insertions(+), 14 deletions(-) diff --git a/ImGuiWidgets/Directory.Build.props b/ImGuiWidgets/Directory.Build.props index 1935ae3..497a9e2 100644 --- a/ImGuiWidgets/Directory.Build.props +++ b/ImGuiWidgets/Directory.Build.props @@ -4,7 +4,7 @@ net7.0 false 1.0.0 - alpha.6 + alpha.7 A library for custom widgets using ImGui.NET. diff --git a/ImGuiWidgets/PopupInput.cs b/ImGuiWidgets/PopupInput.cs index 0768a25..addd8d1 100644 --- a/ImGuiWidgets/PopupInput.cs +++ b/ImGuiWidgets/PopupInput.cs @@ -9,25 +9,51 @@ namespace ktsu.io.ImGuiWidgets; /// The type of the derived class for CRTP. public abstract class PopupInput where TDerived : PopupInput, new() { - public static bool Show(string title, string label, ref TInput input) + private TInput? cachedValue; + + private string Title { get; set; } = string.Empty; + private string Label { get; set; } = string.Empty; + private Action OnConfirm { get; set; } = null!; + + private string GetPopupName() => $"{Title}##{nameof(PopupInput)}{Title}"; + + /// + /// Open the popup and set the title, label, and default value. + /// + /// The title of the popup window. + /// The label of the input field. + /// The default value of the input field. + /// A callback to handle the new input value. + public void Open(string title, string label, TInput defaultValue, Action onConfirm) { - bool result = false; - if (ImGui.IsPopupOpen(title)) - { - ImGui.OpenPopup(title); - } + Title = title; + Label = label; + OnConfirm = onConfirm; + cachedValue = defaultValue; + ImGui.OpenPopup(GetPopupName()); + } - if (ImGui.BeginPopupModal(title, ref result, ImGuiWindowFlags.AlwaysAutoResize)) + /// + /// Show the popup if it is open. + /// + /// True if the popup is open. + public bool ShowIfOpen() + { + bool result = true; + if (cachedValue is not null && ImGui.BeginPopupModal(GetPopupName(), ref result, ImGuiWindowFlags.AlwaysAutoResize)) { - ImGui.Text(label); + ImGui.Text(Label); ImGui.NewLine(); - if (new TDerived().ShowEdit(ref input)) + ImGui.SetKeyboardFocusHere(); + if (ShowEdit(ref cachedValue)) { + OnConfirm(cachedValue); ImGui.CloseCurrentPopup(); } ImGui.SameLine(); if (ImGui.Button("OK")) { + OnConfirm(cachedValue); ImGui.CloseCurrentPopup(); } ImGui.EndPopup(); @@ -35,10 +61,57 @@ public static bool Show(string title, string label, ref TInput input) return result; } - protected abstract bool ShowEdit(ref TInput input); + /// + /// Show the input field for the derived class. + /// + /// The input value. + /// True if the input field is changed. + protected abstract bool ShowEdit(ref TInput value); } +/// +/// A popup input window for strings. +/// public class PopupInputString : PopupInput { - protected override bool ShowEdit(ref string input) => ImGui.InputText("##Input", ref input, 100); + /// + /// Show the input field for strings. + /// + /// The input value. + /// True if Enter is pressed. + protected override bool ShowEdit(ref string value) => ImGui.InputText("##Input", ref value, 100, ImGuiInputTextFlags.EnterReturnsTrue); +} + +/// +/// A popup input window for integers. +/// +public class PopupInputInt : PopupInput +{ + /// + /// Show the input field for integers. + /// + /// The input value. + /// False + protected override bool ShowEdit(ref int value) + { + ImGui.InputInt("##Input", ref value); + return false; + } +} + +/// +/// A popup input window for floats. +/// +public class PopupInputFloat : PopupInput +{ + /// + /// Show the input field for floats. + /// + /// The input value. + /// False + protected override bool ShowEdit(ref float value) + { + ImGui.InputFloat("##Input", ref value); + return false; + } } diff --git a/ImGuiWidgetsDemo/ImGuiWidgetsDemo.cs b/ImGuiWidgetsDemo/ImGuiWidgetsDemo.cs index 9aae3a5..891464f 100644 --- a/ImGuiWidgetsDemo/ImGuiWidgetsDemo.cs +++ b/ImGuiWidgetsDemo/ImGuiWidgetsDemo.cs @@ -15,12 +15,24 @@ private static void Main(string[] args) } private static float value = 0.5f; + + private readonly PopupInputString popupInputString = new(); + private string inputString = "String Input Popup"; private void Tick(float dt) { float ms = dt * 1000; Knob.Draw("DT", ref ms, 0, 10, 150f); ImGui.SameLine(); Knob.Draw("Value", ref value, 0f, 1f, 150f); + if (ImGui.Button(inputString)) + { + popupInputString.Open("Enter a string", "Enter", "Yeet", (string result) => + { + inputString = result; + }); + } + + popupInputString.ShowIfOpen(); } private void ShowMenu() diff --git a/ImGuiWidgetsDemo/ImGuiWidgetsDemo.csproj b/ImGuiWidgetsDemo/ImGuiWidgetsDemo.csproj index fc10b11..f8093f8 100644 --- a/ImGuiWidgetsDemo/ImGuiWidgetsDemo.csproj +++ b/ImGuiWidgetsDemo/ImGuiWidgetsDemo.csproj @@ -1,7 +1,7 @@ - + diff --git a/README.md b/README.md index e7e1f31..96d68fa 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,14 @@ # ImGuiWidgets -Knob Widget \ No newline at end of file +A library for custom widgets using ImGui.NET. + +Includes: + +Rotary Knob + +Resizable Layout Dividers + +Input Popups +- String +- Integer +- Float From 7752c014faa45366e72a5ee92d7b15c6f50a4fa1 Mon Sep 17 00:00:00 2001 From: matt-edmondson Date: Sun, 18 Feb 2024 13:22:39 +1100 Subject: [PATCH 3/5] Fix ID stack issues in popups and add escape key to cancel popup --- ImGuiWidgets/PopupInput.cs | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/ImGuiWidgets/PopupInput.cs b/ImGuiWidgets/PopupInput.cs index addd8d1..1705c4b 100644 --- a/ImGuiWidgets/PopupInput.cs +++ b/ImGuiWidgets/PopupInput.cs @@ -14,8 +14,13 @@ namespace ktsu.io.ImGuiWidgets; private string Title { get; set; } = string.Empty; private string Label { get; set; } = string.Empty; private Action OnConfirm { get; set; } = null!; + private bool WasOpen { get; set; } - private string GetPopupName() => $"{Title}##{nameof(PopupInput)}{Title}"; + /// + /// Gets the id of the popup window. + /// + /// The id of the popup window. + protected string PopupName => $"{Title}###PopupInput{Title}"; /// /// Open the popup and set the title, label, and default value. @@ -30,7 +35,7 @@ public void Open(string title, string label, TInput defaultValue, Action Label = label; OnConfirm = onConfirm; cachedValue = defaultValue; - ImGui.OpenPopup(GetPopupName()); + ImGui.OpenPopup(PopupName); } /// @@ -39,25 +44,39 @@ public void Open(string title, string label, TInput defaultValue, Action /// True if the popup is open. public bool ShowIfOpen() { - bool result = true; - if (cachedValue is not null && ImGui.BeginPopupModal(GetPopupName(), ref result, ImGuiWindowFlags.AlwaysAutoResize)) + bool result = ImGui.IsPopupOpen(PopupName); + if (cachedValue is not null && ImGui.BeginPopupModal(PopupName, ref result, ImGuiWindowFlags.AlwaysAutoResize)) { - ImGui.Text(Label); + ImGui.TextUnformatted(Label); ImGui.NewLine(); - ImGui.SetKeyboardFocusHere(); + + if (!WasOpen && !ImGui.IsItemFocused()) + { + ImGui.SetKeyboardFocusHere(); + } + if (ShowEdit(ref cachedValue)) { OnConfirm(cachedValue); ImGui.CloseCurrentPopup(); } + ImGui.SameLine(); - if (ImGui.Button("OK")) + if (ImGui.Button($"OK###{PopupName}_OK")) { OnConfirm(cachedValue); ImGui.CloseCurrentPopup(); } + + if (ImGui.IsKeyPressed(ImGuiKey.Escape)) + { + ImGui.CloseCurrentPopup(); + } + ImGui.EndPopup(); } + + WasOpen = result; return result; } @@ -79,7 +98,7 @@ public class PopupInputString : PopupInput /// /// The input value. /// True if Enter is pressed. - protected override bool ShowEdit(ref string value) => ImGui.InputText("##Input", ref value, 100, ImGuiInputTextFlags.EnterReturnsTrue); + protected override bool ShowEdit(ref string value) => ImGui.InputText($"###{PopupName}_INPUT", ref value, 100, ImGuiInputTextFlags.EnterReturnsTrue); } /// From 06f2a414f985967c11d808e10cd655e7b3975c37 Mon Sep 17 00:00:00 2001 From: matt-edmondson Date: Sun, 18 Feb 2024 13:23:18 +1100 Subject: [PATCH 4/5] v1.0.0-alpha.8 --- ImGuiWidgets/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ImGuiWidgets/Directory.Build.props b/ImGuiWidgets/Directory.Build.props index 497a9e2..3a796b7 100644 --- a/ImGuiWidgets/Directory.Build.props +++ b/ImGuiWidgets/Directory.Build.props @@ -4,7 +4,7 @@ net7.0 false 1.0.0 - alpha.7 + alpha.8 A library for custom widgets using ImGui.NET. From ae4fa388b6e6e97e540e582e521d1e9437f2b89a Mon Sep 17 00:00:00 2001 From: matt-edmondson Date: Wed, 28 Feb 2024 09:30:20 +1100 Subject: [PATCH 5/5] Update url in gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d0b9e0f..8089939 100644 --- a/.gitignore +++ b/.gitignore @@ -397,5 +397,6 @@ FodyWeavers.xsd # JetBrains Rider *.sln.iml -# Custom medmondson +# Custom entries by https://github.com/ktsu-io .project.props.default +.project.props.default-winforms