Automatic switch between Player <-> Editor Tabs

+ Allow Editor to inject into Settings
This commit is contained in:
Simon Lübeß
2023-08-14 22:10:27 +02:00
parent f71e851ab5
commit a112fcc64a
4 changed files with 203 additions and 92 deletions
+29
View File
@@ -711,6 +711,20 @@ namespace GlitchyEditor
#endregion Project Management
#region Scene Management
/// Focuses the Play window, so that its tab will be shown.
private void SwitchToPlayWindow()
{
let window = ImGui.FindWindowByName(GameViewportWindow.s_WindowTitle);
ImGui.FocusWindow(window);
}
/// Focuses the Editor window, so that its tab will be shown.
private void SwitchToEditorWindow()
{
let window = ImGui.FindWindowByName(EditorViewportWindow.s_WindowTitle);
ImGui.FocusWindow(window);
}
/// Starts the play mode for the current scene
private void OnScenePlay()
@@ -728,6 +742,9 @@ namespace GlitchyEditor
}
_editor.CurrentScene = _activeScene;
if (Application.Instance.Settings.EditorSettings.SwitchToPlayerOnPlay)
SwitchToPlayWindow();
}
/// Starts the physics simulation mode for the current scene
@@ -746,18 +763,27 @@ namespace GlitchyEditor
}
_editor.CurrentScene = _activeScene;
if (Application.Instance.Settings.EditorSettings.SwitchToPlayerOnSimulate)
SwitchToPlayWindow();
}
/// Pauses the scene
private void OnScenePause()
{
_isPaused = true;
if (Application.Instance.Settings.EditorSettings.SwitchToEditorOnPause)
SwitchToEditorWindow();
}
/// Resumes the simulation / game
private void OnSceneResume()
{
_isPaused = false;
if (Application.Instance.Settings.EditorSettings.SwitchToPlayerOnResume)
SwitchToPlayWindow();
}
/// Requests execution of a single simulation / game tick
@@ -792,6 +818,9 @@ namespace GlitchyEditor
*/
GameViewportSizeChanged(null, _editor.GameViewportWindow.ViewportSize);
}
if (Application.Instance.Settings.EditorSettings.SwitchToEditorOnStop)
SwitchToEditorWindow();
}
/// Stops the scene and cleans up the subsystems to allow loading another scene.
+47
View File
@@ -0,0 +1,47 @@
using System;
using GlitchyEngine;
using Bon;
using GlitchyEditor;
using System.Collections;
namespace GlitchyEngine
{
extension Settings
{
[SettingContainer, BonInclude]
public readonly EditorSettings EditorSettings = new .() ~ delete _;
public this()
{
OnApplySettings.Add(new (s, e) => EditorSettings.Apply());
}
}
}
namespace GlitchyEditor;
[Reflect]
class EditorSettings
{
[Setting("Editor", "Switch to Player on play", "If checked the editor will automatically switch to the \"Play\" window after starting the game."), BonInclude]
public bool SwitchToPlayerOnPlay = true;
[Setting("Editor", "Switch to Player on simulate", "If checked the editor will automatically switch to the \"Play\" window after starting the simulation."), BonInclude]
public bool SwitchToPlayerOnSimulate = true;
[Setting("Editor", "Switch to Player on continue", "If checked the editor will automatically switch to the \"Play\" window when the game is continued after pausing."), BonInclude]
public bool SwitchToPlayerOnResume = false;
[Setting("Editor", "Switch to Editor on stop", "If checked the editor will automatically switch to the \"Editor\" window after stopping the game."), BonInclude]
public bool SwitchToEditorOnStop = true;
[Setting("Editor", "Switch to Editor on pause", "If checked the editor will automatically switch to the \"Editor\" window when the game is being paused."), BonInclude]
public bool SwitchToEditorOnPause = false;
//
//public readonly List<String> RecentProjects = new .() ~ delete _;
public void Apply()
{
}
}
+119 -90
View File
@@ -14,12 +14,14 @@ namespace GlitchyEditor
public Object SettingsObject;
public String Name ~ delete _;
public String FieldName ~ delete _;
public StringView Tooltip;
public this(StringView name, StringView fieldName, Object settingsObject)
public this(StringView name, StringView fieldName, Object settingsObject, StringView tooltip)
{
Name = new String(name);
FieldName = new String(fieldName);
SettingsObject = settingsObject;
Tooltip = tooltip;
}
}
@@ -36,9 +38,9 @@ namespace GlitchyEditor
Header = new String(header);
}
public void AddSetting(StringView name, StringView fieldName, Object settingsObject = null)
public void AddSetting(StringView name, StringView fieldName, Object settingsObject = null, StringView tooltip = "")
{
Binding binding = new .(name, fieldName, settingsObject ?? SettingsObject);
Binding binding = new .(name, fieldName, settingsObject ?? SettingsObject, tooltip);
_bindings.Add(binding);
}
}
@@ -89,7 +91,7 @@ namespace GlitchyEditor
if (settingResult case .Ok(let settingInfo))
{
AddSetting(settingInfo.Category, settingInfo.Name, field.Name, container);
AddSetting(settingInfo.Category, settingInfo.Name, field.Name, container, settingInfo.Tooltip);
}
Result<SettingContainerAttribute> containerResult = field.GetCustomAttribute<SettingContainerAttribute>();
@@ -110,11 +112,11 @@ namespace GlitchyEditor
}
}
void AddSetting(String categoryName, String name, StringView fieldName, Object container)
void AddSetting(String categoryName, String name, StringView fieldName, Object container, StringView tooltip)
{
Category category = AddCategory(categoryName);
category.AddSetting(name, fieldName, container);
category.AddSetting(name, fieldName, container, tooltip);
}
protected override void InternalShow()
@@ -131,90 +133,7 @@ namespace GlitchyEditor
{
if (ImGui.BeginTabItem(category.Header))
{
ImGui.Columns(2);
defer ImGui.Columns(1);
ImGui.SetColumnWidth(0, 100);
for (Binding setting in category._bindings)
{
ImGui.TextUnformatted(setting.Name);
ImGui.NextColumn();
Type settingsObjectType = setting.SettingsObject.GetType();
Result<FieldInfo> result = settingsObjectType.GetField(setting.FieldName);
if (result case .Err)
{
ImGui.PushStyleColor(.Text, ImGui.Vec4(1f, 0f, 0f, 1f));
ImGui.Text($"Field {setting.FieldName} not found.");
ImGui.PopStyleColor();
continue;
}
FieldInfo fieldInfo = result.Get();
Type fieldType = fieldInfo.FieldType;
mixin GetSettingValue<T>()
{
var error = fieldInfo.GetValue<T>(setting.SettingsObject, var value);
if (error case .Err(let err))
{
Log.EngineLogger.Error($"Could not get value of setting {setting.FieldName}. Error: {err}");
ImGui.PushStyleColor(.Text, ImGui.Vec4(1f, 0f, 0f, 1f));
ImGui.Text($"Could not get value of setting {setting.FieldName}. Error: {err}");
ImGui.PopStyleColor();
break;
}
value
}
mixin SetSettingValue<T>(T value)
{
var error = fieldInfo.SetValue(setting.SettingsObject, value);
if (error case .Err(let err))
{
Log.EngineLogger.Error($"Could not set value of setting {setting.FieldName}. Error: {err}");
}
}
switch (fieldType)
{
case typeof(int32):
int32 value = GetSettingValue!<int32>();
if (!ImGui.InputInt(scope $"##{setting.Name}", &value))
break;
SetSettingValue!(value);
_settingsChanged = true;
case typeof(String):
String value = GetSettingValue!<String>();
char8[256] buffer = .();
value.CopyTo(buffer);
if (ImGui.InputText(scope $"##{setting.Name}", &buffer, buffer.Count))
{
value..Clear().Append(&buffer);
_settingsChanged = true;
}
}
ImGui.NextColumn();
}
ShowCategory(category);
ImGui.EndTabItem();
}
}
@@ -249,5 +168,115 @@ namespace GlitchyEditor
_open = false;
}
}
private void ShowCategory(Category category)
{
if (ImGui.BeginTable("SettingsTable", 2, .SizingFixedFit | .RowBg))
{
ImGui.TableSetupColumn("Settings");
ImGui.TableSetupColumn("Values", .WidthStretch);
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(1);
ImGui.PushItemWidth(ImGui.GetContentRegionAvail().x);
for (Binding setting in category._bindings)
{
ImGui.TableNextRow();
ImGui.TableNextColumn();
// Name of setting
ImGui.TextUnformatted(setting.Name);
if (!setting.Tooltip.IsWhiteSpace)
ImGui.AttachTooltip(setting.Tooltip);
ImGui.TableNextColumn();
Type settingsObjectType = setting.SettingsObject.GetType();
Result<FieldInfo> result = settingsObjectType.GetField(setting.FieldName);
if (result case .Err)
{
ImGui.PushStyleColor(.Text, ImGui.Vec4(1f, 0f, 0f, 1f));
ImGui.Text($"Field {setting.FieldName} not found.");
ImGui.PopStyleColor();
continue;
}
FieldInfo fieldInfo = result.Get();
Type fieldType = fieldInfo.FieldType;
mixin GetSettingValue<T>()
{
var error = fieldInfo.GetValue<T>(setting.SettingsObject, var value);
if (error case .Err(let err))
{
Log.EngineLogger.Error($"Could not get value of setting {setting.FieldName}. Error: {err}");
ImGui.PushStyleColor(.Text, ImGui.Vec4(1f, 0f, 0f, 1f));
ImGui.Text($"Could not get value of setting {setting.FieldName}. Error: {err}");
ImGui.PopStyleColor();
break;
}
value
}
mixin SetSettingValue<T>(T value)
{
var error = fieldInfo.SetValue(setting.SettingsObject, value);
if (error case .Err(let err))
{
Log.EngineLogger.Error($"Could not set value of setting {setting.FieldName}. Error: {err}");
}
}
switch (fieldType)
{
case typeof(bool):
let value = GetSettingValue!<bool>();
if (!ImGui.Checkbox(scope $"##{setting.Name}", &value))
break;
SetSettingValue!(value);
_settingsChanged = true;
case typeof(int32):
int32 value = GetSettingValue!<int32>();
if (!ImGui.InputInt(scope $"##{setting.Name}", &value))
break;
SetSettingValue!(value);
_settingsChanged = true;
case typeof(String):
String value = GetSettingValue!<String>();
char8[256] buffer = .();
value.CopyTo(buffer);
if (ImGui.InputText(scope $"##{setting.Name}", &buffer, buffer.Count))
{
value..Clear().Append(&buffer);
_settingsChanged = true;
}
}
}
ImGui.EndTable();
}
}
}
}