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 diff --git a/ImGuiWidgets/Directory.Build.props b/ImGuiWidgets/Directory.Build.props index 1935ae3..3a796b7 100644 --- a/ImGuiWidgets/Directory.Build.props +++ b/ImGuiWidgets/Directory.Build.props @@ -4,7 +4,7 @@ net7.0 false 1.0.0 - alpha.6 + alpha.8 A library for custom widgets using ImGui.NET. diff --git a/ImGuiWidgets/PopupInput.cs b/ImGuiWidgets/PopupInput.cs new file mode 100644 index 0000000..1705c4b --- /dev/null +++ b/ImGuiWidgets/PopupInput.cs @@ -0,0 +1,136 @@ +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() +{ + private TInput? cachedValue; + + 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; } + + /// + /// 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. + /// + /// 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) + { + Title = title; + Label = label; + OnConfirm = onConfirm; + cachedValue = defaultValue; + ImGui.OpenPopup(PopupName); + } + + /// + /// Show the popup if it is open. + /// + /// True if the popup is open. + public bool ShowIfOpen() + { + bool result = ImGui.IsPopupOpen(PopupName); + if (cachedValue is not null && ImGui.BeginPopupModal(PopupName, ref result, ImGuiWindowFlags.AlwaysAutoResize)) + { + ImGui.TextUnformatted(Label); + ImGui.NewLine(); + + if (!WasOpen && !ImGui.IsItemFocused()) + { + ImGui.SetKeyboardFocusHere(); + } + + if (ShowEdit(ref cachedValue)) + { + OnConfirm(cachedValue); + ImGui.CloseCurrentPopup(); + } + + ImGui.SameLine(); + if (ImGui.Button($"OK###{PopupName}_OK")) + { + OnConfirm(cachedValue); + ImGui.CloseCurrentPopup(); + } + + if (ImGui.IsKeyPressed(ImGuiKey.Escape)) + { + ImGui.CloseCurrentPopup(); + } + + ImGui.EndPopup(); + } + + WasOpen = result; + return result; + } + + /// + /// 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 +{ + /// + /// Show the input field for strings. + /// + /// The input value. + /// True if Enter is pressed. + protected override bool ShowEdit(ref string value) => ImGui.InputText($"###{PopupName}_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/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 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