Added basic central popup service and way to highlight settings.

This commit is contained in:
Simon Lübeß
2025-07-08 19:35:40 +02:00
parent 081f7b4a7e
commit ecfe838ad4
7 changed files with 246 additions and 79 deletions
@@ -2,6 +2,10 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using GlitchyEngine; using GlitchyEngine;
using System.Collections; using System.Collections;
using System.IO;
using System.IO;
using GlitchyEditor.EditWindows;
using ImGui;
namespace GlitchyEditor.CodeEditors; namespace GlitchyEditor.CodeEditors;
@@ -29,6 +33,23 @@ class RiderIdeAdapter : IIdeAdapter
String solutionPath = scope .(); String solutionPath = scope .();
Editor.Instance.CurrentProject.PathInProject(solutionPath, scope $"{Editor.Instance.CurrentProject.Name}.sln"); Editor.Instance.CurrentProject.PathInProject(solutionPath, scope $"{Editor.Instance.CurrentProject.Name}.sln");
if (!File.Exists(solutionPath))
{
Log.EngineLogger.Error("Could not find solution file?");
return;
}
if (!File.Exists(Application.Instance.Settings.ScriptSettings.RiderPath))
{
Editor.Instance.ShowSettings();
Editor.Instance.SettingsWindow.HighlightSetting("Tools", "Rider path");
PopupService.Instance.ShowMessageBox("Rider not found.",
"The rider path could not be found. Please select the correct path.");
return;
}
ProcessStartInfo startInfo = scope .(); ProcessStartInfo startInfo = scope .();
startInfo.SetFileName(Application.Instance.Settings.ScriptSettings.RiderPath); startInfo.SetFileName(Application.Instance.Settings.ScriptSettings.RiderPath);
startInfo.SetArguments(solutionPath); startInfo.SetArguments(solutionPath);
@@ -36,3 +57,4 @@ class RiderIdeAdapter : IIdeAdapter
scope SpawnedProcess().Start(startInfo); scope SpawnedProcess().Start(startInfo);
} }
} }
@@ -1199,7 +1199,7 @@ namespace GlitchyEditor.EditWindows
} }
} }
/// Shows the context menu for the given file/folder. /// Shows the context menu for the selected files and directories.
private void ShowItemContextMenu() private void ShowItemContextMenu()
{ {
bool singleEntry = _selectedFiles.Count == 1; bool singleEntry = _selectedFiles.Count == 1;
@@ -0,0 +1,83 @@
using System;
using ImGui;
using System.Collections;
using GlitchyEngine;
namespace GlitchyEditor.EditWindows;
class Popup
{
public String Title ~ delete _;
public ImGui.WindowFlags WindowFlags;
public delegate void(out bool) Render ~ delete _;
public this(StringView title, delegate void(out bool) render, ImGui.WindowFlags flags)
{
Title = new String(title);
Render = render;
WindowFlags = flags;
}
}
class PopupService
{
private static PopupService _service = new PopupService() ~ delete _;
public static PopupService Instance => _service;
private append List<Popup> _popups = .() ~ ClearAndDeleteItems(_);
public void OpenPopup(StringView popupTitle, delegate void(out bool) render, ImGui.WindowFlags flags = .AlwaysAutoResize | .NoSavedSettings | .NoResize)
{
Popup popup = new Popup(popupTitle, render, flags);
_popups.Add(popup);
Log.EngineLogger.Info($"Opened {popupTitle}");
}
public void ShowMessageBox(StringView title, StringView message)
{
String messageCopy = new String(message);
OpenPopup(title, new (close) =>
{
close = false;
ImGui.NewLine();
ImGui.TextUnformatted(messageCopy);
ImGui.NewLine();
if (ImGui.Button("Ok"))
{
delete messageCopy;
close = true;
}
}
);
}
public void ImGuiDraw()
{
for (Popup popup in _popups)
{
ImGui.OpenPopup(popup.Title);
let center = ImGui.GetWindowViewport().GetCenter();
ImGui.SetNextWindowPos(center, .Appearing, .(0.5f, 0.5f));
if (ImGui.BeginPopupModal(popup.Title, null, popup.WindowFlags))
{
popup.Render(let close);
if (close)
{
ImGui.CloseCurrentPopup();
@popup.Remove();
delete popup;
}
ImGui.EndPopup();
}
}
}
}
+11
View File
@@ -27,6 +27,7 @@ namespace GlitchyEditor
private InspectorWindow _inspectorWindow ~ delete _; private InspectorWindow _inspectorWindow ~ delete _;
private AssetViewer _assetViewer ~ delete _; private AssetViewer _assetViewer ~ delete _;
private LogWindow _logWindow ~ delete _; private LogWindow _logWindow ~ delete _;
private SettingsWindow _settingsWindow ~ delete _;
private List<ClosableWindow> _windows = new .() ~ DeleteContainerAndItems!(_); private List<ClosableWindow> _windows = new .() ~ DeleteContainerAndItems!(_);
@@ -67,6 +68,7 @@ namespace GlitchyEditor
public InspectorWindow InspectorWindow => _inspectorWindow; public InspectorWindow InspectorWindow => _inspectorWindow;
public AssetViewer AssetViewer => _assetViewer; public AssetViewer AssetViewer => _assetViewer;
public LogWindow LogWindow => _logWindow; public LogWindow LogWindow => _logWindow;
public SettingsWindow SettingsWindow => _settingsWindow;
public EditorCamera* CurrentCamera { get; set; } public EditorCamera* CurrentCamera { get; set; }
@@ -108,10 +110,13 @@ namespace GlitchyEditor
_inspectorWindow = new InspectorWindow(this); _inspectorWindow = new InspectorWindow(this);
_assetViewer = new AssetViewer((.)Application.Get().ContentManager); _assetViewer = new AssetViewer((.)Application.Get().ContentManager);
_logWindow = new LogWindow(); _logWindow = new LogWindow();
_settingsWindow = new SettingsWindow();
} }
public void Update() public void Update()
{ {
PopupService.Instance.ImGuiDraw();
_sceneViewportWindow.Show(); _sceneViewportWindow.Show();
_gameViewportWindow.Show(); _gameViewportWindow.Show();
_entityHierarchyWindow.Show(); _entityHierarchyWindow.Show();
@@ -120,6 +125,7 @@ namespace GlitchyEditor
_inspectorWindow.Show(); _inspectorWindow.Show();
_assetViewer.Show(); _assetViewer.Show();
_logWindow.Show(); _logWindow.Show();
_settingsWindow.Show();
for (ClosableWindow window in _windows) for (ClosableWindow window in _windows)
window.Show(); window.Show();
@@ -135,5 +141,10 @@ namespace GlitchyEditor
_windows.Remove(closableWindow); _windows.Remove(closableWindow);
delete closableWindow; delete closableWindow;
} }
public void ShowSettings()
{
_settingsWindow.Open = true;
}
} }
} }
+57 -70
View File
@@ -63,8 +63,6 @@ namespace GlitchyEditor
RenderTargetGroup _editorViewportTarget ~ _.ReleaseRef(); RenderTargetGroup _editorViewportTarget ~ _.ReleaseRef();
RenderTargetGroup _gameViewportTarget ~ _.ReleaseRef(); RenderTargetGroup _gameViewportTarget ~ _.ReleaseRef();
SettingsWindow _settingsWindow = new .() ~ delete _;
ProjectUserSettings _projectUserSettings; ProjectUserSettings _projectUserSettings;
EditorCamera _camera ~ _.Dispose(); EditorCamera _camera ~ _.Dispose();
@@ -656,91 +654,83 @@ namespace GlitchyEditor
return .Ok; return .Ok;
} }
/// If set to true, the popup for creating a new project will be shown. public void OpenCreateNewProjectModal()
private bool _openCreateProjectModal;
private void ShowCreateNewProjectModal()
{ {
PopupService.Instance.OpenPopup("Create new Project", new => ShowCreateNewProjectModal);
}
private void ShowCreateNewProjectModal(out bool close)
{
close = false;
static char8[128] projectNameBuffer = .(); static char8[128] projectNameBuffer = .();
static char8[256] projectDirectoryBuffer = .(); static char8[1024] projectDirectoryBuffer = .();
if (_openCreateProjectModal)
{
ImGui.OpenPopup("Create new Project");
_openCreateProjectModal = false;
projectNameBuffer = .();
}
// Always center this window when appearing // Always center this window when appearing
var center = ImGui.GetMainViewport().GetCenter(); var center = ImGui.GetMainViewport().GetCenter();
ImGui.SetNextWindowPos(center, .Appearing, .(0.5f, 0.5f)); ImGui.SetNextWindowPos(center, .Appearing, .(0.5f, 0.5f));
if (ImGui.BeginPopupModal("Create new Project", null, .AlwaysAutoResize)) ImGui.TextUnformatted("Project Name:");
ImGui.InputText("##projectName", &projectNameBuffer, projectNameBuffer.Count - 1);
StringView projectName = StringView(&projectNameBuffer);
if (projectName.IsWhiteSpace)
{ {
ImGui.TextUnformatted("Project Name:"); ImGui.TextColored(.(1, 0, 0, 1), "Project Name required!");
ImGui.InputText("##projectName", &projectNameBuffer, projectNameBuffer.Count - 1); }
StringView projectName = StringView(&projectNameBuffer);
if (projectName.IsWhiteSpace) ImGui.NewLine();
ImGui.TextUnformatted("Directory:");
ImGui.InputText("##directory", &projectDirectoryBuffer, projectDirectoryBuffer.Count - 1);
ImGui.SameLine();
if (ImGui.Button("..."))
{
FolderBrowserDialog folderDialog = scope FolderBrowserDialog();
Result<DialogResult> result = folderDialog.ShowDialog();
if (result case .Ok(let dialogResult) && dialogResult case .OK)
{ {
ImGui.TextColored(.(1, 0, 0, 1), "Project Name required!"); folderDialog.SelectedPath.CopyTo(projectDirectoryBuffer);
} }
}
ImGui.NewLine(); StringView directory = StringView(&projectDirectoryBuffer);
ImGui.TextUnformatted("Directory:"); String target = scope String();
ImGui.InputText("##directory", &projectDirectoryBuffer, projectDirectoryBuffer.Count - 1); Path.Combine(target, directory, projectName);
ImGui.SameLine();
ImGui.NewLine();
if (ImGui.Button("...")) ImGui.Text($"The Project will be in:\n{target}");
{
FolderBrowserDialog folderDialog = scope FolderBrowserDialog();
Result<DialogResult> result = folderDialog.ShowDialog();
if (result case .Ok(let dialogResult) && dialogResult case .OK) if (Directory.Exists(target) && !Directory.IsEmpty(target))
{ {
folderDialog.SelectedPath.CopyTo(projectDirectoryBuffer); ImGui.TextColored(.(1, 1, 0, 1), "The directory is not empty!");
} }
}
StringView directory = StringView(&projectDirectoryBuffer); ImGui.NewLine();
String target = scope String(); ImGui.BeginDisabled(directory.IsWhiteSpace || projectName.IsWhiteSpace);
Path.Combine(target, directory, projectName);
ImGui.NewLine();
ImGui.Text($"The Project will be in:\n{target}"); if (ImGui.Button("Create"))
{
Result<void> result = CreateNewProject(target, projectName);
if (Directory.Exists(target) && !Directory.IsEmpty(target)) if (result case .Ok)
{ close = true;
ImGui.TextColored(.(1, 1, 0, 1), "The directory is not empty!");
}
ImGui.NewLine(); }
ImGui.BeginDisabled(directory.IsWhiteSpace || projectName.IsWhiteSpace); ImGui.EndDisabled();
if (ImGui.Button("Create")) ImGui.SameLine();
{
Result<void> result = CreateNewProject(target, projectName);
if (result case .Ok) if (ImGui.Button("Cancel"))
ImGui.CloseCurrentPopup(); {
} close = true;
ImGui.EndDisabled();
ImGui.SameLine();
if (ImGui.Button("Cancel"))
{
ImGui.CloseCurrentPopup();
}
ImGui.EndPopup();
} }
} }
@@ -1209,9 +1199,6 @@ namespace GlitchyEditor
_editor.Update(); _editor.Update();
_settingsWindow.Show();
ShowCreateNewProjectModal();
return false; return false;
} }
@@ -1479,7 +1466,7 @@ namespace GlitchyEditor
ImGui.Separator(); ImGui.Separator();
if (ImGui.MenuItem("Create new Project...", "Ctrl+ALT+N")) if (ImGui.MenuItem("Create new Project...", "Ctrl+ALT+N"))
_openCreateProjectModal = true; OpenCreateNewProjectModal();
if (ImGui.MenuItem("Open Project...", "Ctrl+ALT+O")) if (ImGui.MenuItem("Open Project...", "Ctrl+ALT+O"))
ShowOpenProjectDialog(); ShowOpenProjectDialog();
@@ -1493,7 +1480,7 @@ namespace GlitchyEditor
ImGui.Separator(); ImGui.Separator();
if (ImGui.MenuItem("Settings")) if (ImGui.MenuItem("Settings"))
_settingsWindow.Open = true; Editor.Instance.SettingsWindow.Open = true;
ImGui.Separator(); ImGui.Separator();
@@ -1611,7 +1598,7 @@ namespace GlitchyEditor
case .N: case .N:
if (alt) if (alt)
// "Create new Project..." // "Create new Project..."
_openCreateProjectModal = true; OpenCreateNewProjectModal();
else else
// "New Scene" // "New Scene"
CreateAndOpenNewScene(); CreateAndOpenNewScene();
+63 -7
View File
@@ -4,6 +4,8 @@ using GlitchyEngine;
using System; using System;
using System.Collections; using System.Collections;
using System.Reflection; using System.Reflection;
using GlitchyEngine.Math;
using System.IO;
namespace GlitchyEditor namespace GlitchyEditor
{ {
@@ -15,13 +17,15 @@ namespace GlitchyEditor
public String Name ~ delete _; public String Name ~ delete _;
public String FieldName ~ delete _; public String FieldName ~ delete _;
public StringView Tooltip; public StringView Tooltip;
public SettingEditor EditorType;
public this(StringView name, StringView fieldName, Object settingsObject, StringView tooltip) public this(StringView name, StringView fieldName, Object settingsObject, StringView tooltip, SettingEditor editorType)
{ {
Name = new String(name); Name = new String(name);
FieldName = new String(fieldName); FieldName = new String(fieldName);
SettingsObject = settingsObject; SettingsObject = settingsObject;
Tooltip = tooltip; Tooltip = tooltip;
EditorType = editorType;
} }
} }
@@ -38,9 +42,9 @@ namespace GlitchyEditor
Header = new String(header); Header = new String(header);
} }
public void AddSetting(StringView name, StringView fieldName, Object settingsObject = null, StringView tooltip = "") public void AddSetting(StringView name, StringView fieldName, Object settingsObject = null, StringView tooltip = "", SettingEditor editorType = .Default)
{ {
Binding binding = new .(name, fieldName, settingsObject ?? SettingsObject, tooltip); Binding binding = new .(name, fieldName, settingsObject ?? SettingsObject, tooltip, editorType);
_bindings.Add(binding); _bindings.Add(binding);
} }
} }
@@ -91,7 +95,7 @@ namespace GlitchyEditor
if (settingResult case .Ok(let settingInfo)) if (settingResult case .Ok(let settingInfo))
{ {
AddSetting(settingInfo.Category, settingInfo.Name, field.Name, container, settingInfo.Tooltip); AddSetting(settingInfo.Category, settingInfo.Name, field.Name, container, settingInfo.Tooltip, settingInfo.EditorMode);
} }
Result<SettingContainerAttribute> containerResult = field.GetCustomAttribute<SettingContainerAttribute>(); Result<SettingContainerAttribute> containerResult = field.GetCustomAttribute<SettingContainerAttribute>();
@@ -112,11 +116,22 @@ namespace GlitchyEditor
} }
} }
void AddSetting(String categoryName, String name, StringView fieldName, Object container, StringView tooltip) void AddSetting(String categoryName, String name, StringView fieldName, Object container, StringView tooltip, SettingEditor settingEditor)
{ {
Category category = AddCategory(categoryName); Category category = AddCategory(categoryName);
category.AddSetting(name, fieldName, container, tooltip); category.AddSetting(name, fieldName, container, tooltip, settingEditor);
}
private String _tabToSelect = new String() ~ delete _;
private String _SettingToHighlight = new String() ~ delete _;
private float _timeToHighlight;
public void HighlightSetting(StringView tabName, StringView settingName = "")
{
_tabToSelect.Set(tabName);
_SettingToHighlight.Set(settingName);
_timeToHighlight = 10;
} }
protected override void InternalShow() protected override void InternalShow()
@@ -131,7 +146,15 @@ namespace GlitchyEditor
for (Category category in _categories.Values) for (Category category in _categories.Values)
{ {
if (ImGui.BeginTabItem(category.Header)) ImGui.TabItemFlags flags = .None;
if (_tabToSelect == category.Header)
{
flags |= .SetSelected;
_tabToSelect.Clear();
}
if (ImGui.BeginTabItem(category.Header, null, flags))
{ {
ShowCategory(category); ShowCategory(category);
ImGui.EndTabItem(); ImGui.EndTabItem();
@@ -260,6 +283,7 @@ namespace GlitchyEditor
_settingsChanged = true; _settingsChanged = true;
case typeof(String): case typeof(String):
String value = GetSettingValue!<String>(); String value = GetSettingValue!<String>();
char8[256] buffer = .(); char8[256] buffer = .();
@@ -275,6 +299,38 @@ namespace GlitchyEditor
_settingsChanged = true; _settingsChanged = true;
} }
/*if (setting.EditorType == .FilePath)
{
ImGui.SameLine();
if (ImGui.Button("..."))
{
OpenFileDialog ofd = scope .();
ofd.InitialDirectory = value;
ofd.SetFilter("All Files (*.*)|*.*");
ofd.Multiselect = false;
if (ofd.ShowDialog() case .Ok(let result) && result == .OK)
{
SetSettingValue!(new String(ofd.FileNames[0]));
}
}
}*/
}
if (setting.Name == _SettingToHighlight)
{
let min = (float2)ImGui.GetItemRectMin() - 2;
let max = (float2)ImGui.GetItemRectMax() + 2;
ImGui.DrawRect((.)min, (.)max, (.)ColorRGBA.Yellow);
_timeToHighlight -= Application.Instance.GameTime.DeltaTime;
if (_timeToHighlight < 0)
{
_SettingToHighlight.Clear();
}
} }
/*if (fieldInfo.FieldType.IsEnum) /*if (fieldInfo.FieldType.IsEnum)
+9 -1
View File
@@ -17,6 +17,12 @@ namespace GlitchyEngine
{ {
} }
enum SettingEditor
{
case Default;
case Path;//(bool MultiSelect, bool OpenFolderDialog, StringView Filter);
}
/// Fields with this Attribute will be exposed as settings. /// Fields with this Attribute will be exposed as settings.
[AttributeUsage(.Field, .ReflectAttribute)] [AttributeUsage(.Field, .ReflectAttribute)]
struct SettingAttribute : Attribute struct SettingAttribute : Attribute
@@ -24,12 +30,14 @@ namespace GlitchyEngine
public String Category; public String Category;
public String Name; public String Name;
public String Tooltip; public String Tooltip;
public SettingEditor EditorMode;
public this(String category, String name, String tooltip = "") public this(String category, String name, String tooltip = "", SettingEditor editorMode = .Default)
{ {
Category = category; Category = category;
Name = name; Name = name;
Tooltip = tooltip; Tooltip = tooltip;
EditorMode = editorMode;
} }
} }