From 804316b6004eb6cbac10d658cfe4443386c6f846 Mon Sep 17 00:00:00 2001 From: ikpil Date: Sat, 18 Mar 2023 13:43:22 +0900 Subject: [PATCH] add file picker for imgui --- .../DotRecast.Recast.Demo.csproj | 18 +- .../Settings/RcSettingsView.cs | 46 ++++- src/DotRecast.Recast.Demo/UI/ImFilePicker.cs | 186 ++++++++++++++++++ 3 files changed, 235 insertions(+), 15 deletions(-) create mode 100644 src/DotRecast.Recast.Demo/UI/ImFilePicker.cs diff --git a/src/DotRecast.Recast.Demo/DotRecast.Recast.Demo.csproj b/src/DotRecast.Recast.Demo/DotRecast.Recast.Demo.csproj index 39e9fd4..65de201 100644 --- a/src/DotRecast.Recast.Demo/DotRecast.Recast.Demo.csproj +++ b/src/DotRecast.Recast.Demo/DotRecast.Recast.Demo.csproj @@ -7,18 +7,18 @@ - - - + + + - - - - - - + + + + + + diff --git a/src/DotRecast.Recast.Demo/Settings/RcSettingsView.cs b/src/DotRecast.Recast.Demo/Settings/RcSettingsView.cs index cb97610..c70c17f 100644 --- a/src/DotRecast.Recast.Demo/Settings/RcSettingsView.cs +++ b/src/DotRecast.Recast.Demo/Settings/RcSettingsView.cs @@ -16,8 +16,8 @@ freely, subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -using System.Linq; -using System.Numerics; +using System; +using System.IO; using DotRecast.Core; using DotRecast.Recast.Demo.Draw; using DotRecast.Recast.Demo.UI; @@ -85,7 +85,25 @@ public class RcSettingsView : IRcView bool mouseInside = false; ImGui.Text("Input Mesh"); ImGui.Separator(); - ImGui.Button("Load Source Geom..."); + + const string strLoadSourceGeom = "Load Source Geom..."; + if (ImGui.Button(strLoadSourceGeom)) + { + ImGui.OpenPopup(strLoadSourceGeom); + } + + bool loadSourceGeomPopup = true; + if (ImGui.BeginPopupModal(strLoadSourceGeom, ref loadSourceGeomPopup, ImGuiWindowFlags.NoTitleBar)) + { + var picker = ImFilePicker.GetFilePicker(strLoadSourceGeom, Path.Combine(Environment.CurrentDirectory)); + if (picker.Draw()) + { + Console.WriteLine(picker.SelectedFile); + ImFilePicker.RemoveFilePicker(strLoadSourceGeom); + } + ImGui.EndPopup(); + } + ImGui.Text($"Verts: {voxels[0]} Tris: {voxels[1]}"); ImGui.NewLine(); @@ -120,7 +138,7 @@ public class RcSettingsView : IRcView ImGui.RadioButton(label, ref _partitioning, partition.Idx); }); ImGui.NewLine(); - + ImGui.Text("Filtering"); ImGui.Separator(); ImGui.Checkbox("Low Hanging Obstacles", ref filterLowHangingObstacles); @@ -159,8 +177,24 @@ public class RcSettingsView : IRcView ImGui.Text($"Build Time: {buildTime} ms"); ImGui.Separator(); buildTriggered = ImGui.Button("Build"); - ImGui.SameLine(); - navMeshInputTrigerred = ImGui.Button("Load Nav Mesh..."); + const string strLoadNavMesh = "Load Nav Mesh..."; + if (ImGui.Button(strLoadNavMesh)) + { + ImGui.OpenPopup(strLoadNavMesh); + } + + bool isLoadNavMesh = true; + if (ImGui.BeginPopupModal(strLoadNavMesh, ref isLoadNavMesh, ImGuiWindowFlags.NoTitleBar)) + { + var picker = ImFilePicker.GetFilePicker(strLoadNavMesh, Path.Combine(Environment.CurrentDirectory)); + if (picker.Draw()) + { + Console.WriteLine(picker.SelectedFile); + ImFilePicker.RemoveFilePicker(strLoadNavMesh); + } + ImGui.EndPopup(); + } + ImGui.NewLine(); ImGui.Text("Draw"); diff --git a/src/DotRecast.Recast.Demo/UI/ImFilePicker.cs b/src/DotRecast.Recast.Demo/UI/ImFilePicker.cs new file mode 100644 index 0000000..522dede --- /dev/null +++ b/src/DotRecast.Recast.Demo/UI/ImFilePicker.cs @@ -0,0 +1,186 @@ +using System; +using System.Numerics; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using ImGuiNET; + +namespace DotRecast.Recast.Demo.UI; + +// original code : https://gist.github.com/prime31/91d1582624eb2635395417393018016e +public class ImFilePicker +{ + private static readonly Dictionary _filePickers = new Dictionary(); + + public string RootFolder; + public string CurrentFolder; + public string SelectedFile; + public List AllowedExtensions; + public bool OnlyAllowFolders; + + public static ImFilePicker GetFolderPicker(string pickerName, string startingPath) + => GetFilePicker(pickerName, startingPath, null, true); + + public static ImFilePicker GetFilePicker(string pickerName, string startingPath, string searchFilter = null, bool onlyAllowFolders = false) + { + if (File.Exists(startingPath)) + { + startingPath = new FileInfo(startingPath).DirectoryName; + } + else if (string.IsNullOrEmpty(startingPath) || !Directory.Exists(startingPath)) + { + startingPath = Environment.CurrentDirectory; + if (string.IsNullOrEmpty(startingPath)) + startingPath = AppContext.BaseDirectory; + } + + if (!_filePickers.TryGetValue(pickerName, out ImFilePicker fp)) + { + fp = new ImFilePicker(); + fp.RootFolder = startingPath; + fp.CurrentFolder = startingPath; + fp.OnlyAllowFolders = onlyAllowFolders; + + if (searchFilter != null) + { + if (fp.AllowedExtensions != null) + fp.AllowedExtensions.Clear(); + else + fp.AllowedExtensions = new List(); + + fp.AllowedExtensions.AddRange(searchFilter.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries)); + } + + _filePickers.Add(pickerName, fp); + } + + return fp; + } + + public static void RemoveFilePicker(string pickerName) => _filePickers.Remove(pickerName); + + public bool Draw() + { + ImGui.Text("Current Folder: " + CurrentFolder); + bool result = false; + + if (ImGui.BeginChildFrame(1, new Vector2(1024, 400))) + { + var di = new DirectoryInfo(CurrentFolder); + if (di.Exists) + { + if (di.Parent != null) + { + ImGui.PushStyleColor(ImGuiCol.Text, (uint)Color.Yellow.ToArgb()); + if (ImGui.Selectable("../", false, ImGuiSelectableFlags.DontClosePopups)) + CurrentFolder = di.Parent.FullName; + + ImGui.PopStyleColor(); + } + + var fileSystemEntries = GetFileSystemEntries(di.FullName); + foreach (var fse in fileSystemEntries) + { + if (Directory.Exists(fse)) + { + var name = Path.GetFileName(fse); + ImGui.PushStyleColor(ImGuiCol.Text, (uint)Color.Yellow.ToArgb()); + if (ImGui.Selectable(name + "/", false, ImGuiSelectableFlags.DontClosePopups)) + CurrentFolder = fse; + ImGui.PopStyleColor(); + } + else + { + var name = Path.GetFileName(fse); + bool isSelected = SelectedFile == fse; + if (ImGui.Selectable(name, isSelected, ImGuiSelectableFlags.DontClosePopups)) + SelectedFile = fse; + + if (ImGui.IsMouseDoubleClicked(0)) + { + result = true; + ImGui.CloseCurrentPopup(); + } + } + } + } + } + + ImGui.EndChildFrame(); + + + if (ImGui.Button("Cancel")) + { + result = false; + ImGui.CloseCurrentPopup(); + } + + if (OnlyAllowFolders) + { + ImGui.SameLine(); + if (ImGui.Button("Open")) + { + result = true; + SelectedFile = CurrentFolder; + ImGui.CloseCurrentPopup(); + } + } + else if (SelectedFile != null) + { + ImGui.SameLine(); + if (ImGui.Button("Open")) + { + result = true; + ImGui.CloseCurrentPopup(); + } + } + + return result; + } + + bool TryGetFileInfo(string fileName, out FileInfo realFile) + { + try + { + realFile = new FileInfo(fileName); + return true; + } + catch + { + realFile = null; + return false; + } + } + + List GetFileSystemEntries(string fullName) + { + var files = new List(); + var dirs = new List(); + + foreach (var fse in Directory.GetFileSystemEntries(fullName, "")) + { + if (Directory.Exists(fse)) + { + dirs.Add(fse); + } + else if (!OnlyAllowFolders) + { + if (AllowedExtensions != null) + { + var ext = Path.GetExtension(fse); + if (AllowedExtensions.Contains(ext)) + files.Add(fse); + } + else + { + files.Add(fse); + } + } + } + + var ret = new List(dirs); + ret.AddRange(files); + + return ret; + } +} \ No newline at end of file