mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Project user settings, load recent scenes, properly cleanup ScriptEngine when switching scenes
This commit is contained in:
@@ -62,6 +62,8 @@ namespace GlitchyEditor
|
||||
|
||||
SettingsWindow _settingsWindow = new .() ~ delete _;
|
||||
|
||||
ProjectUserSettings _projectUserSettings;
|
||||
|
||||
EditorCamera _camera ~ _.Dispose();
|
||||
|
||||
EditorIcons _editorIcons ~ _.ReleaseRef();
|
||||
@@ -135,6 +137,11 @@ namespace GlitchyEditor
|
||||
CreateAndOpenNewScene();
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
CloseCurrentProject();
|
||||
}
|
||||
|
||||
private void RegisterAssetCreators()
|
||||
{
|
||||
Editor.Instance.ContentBrowserWindow.RegisterAssetCreator(new AssetCreator("Scene", "New Scene.scene", new (path) =>
|
||||
@@ -393,6 +400,12 @@ namespace GlitchyEditor
|
||||
Renderer2D.DrawCircle(transform.WorldTransform * Matrix.Translation(collider.Offset.X, collider.Offset.Y, 0) * Matrix.Scaling(collider.Radius * 2), (Texture2D)null, ColorRGBA(0f, 1f, 0f), 0.01f);
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates the title of the window.
|
||||
private void UpdateWindowTitle()
|
||||
{
|
||||
Application.Instance.Window.Title = scope $"Glitchy Engine - {_currentProject.Name}";
|
||||
}
|
||||
|
||||
#region Project Management
|
||||
|
||||
@@ -605,11 +618,11 @@ namespace GlitchyEditor
|
||||
|
||||
private void CloseCurrentProject()
|
||||
{
|
||||
OnSceneStop();
|
||||
CloseCurrentScene();
|
||||
|
||||
SetReference!(_editorScene, null);
|
||||
SetReference!(_activeScene, null);
|
||||
_editor.CurrentScene = null;
|
||||
SetEditorScene(null);
|
||||
|
||||
_currentProject?.SaveUserSettings();
|
||||
|
||||
// TODO: Do actual work here!
|
||||
delete _currentProject;
|
||||
@@ -629,6 +642,7 @@ namespace GlitchyEditor
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
/// Opens the given project and makes it the current project.
|
||||
private Result<void> OpenProject(Project project)
|
||||
{
|
||||
if (project == null)
|
||||
@@ -645,8 +659,19 @@ namespace GlitchyEditor
|
||||
|
||||
ScriptEngine.SetAppAssemblyPath(appAssemblyPath);
|
||||
|
||||
// TODO: Load last opened scene
|
||||
CreateAndOpenNewScene();
|
||||
if (!_currentProject.UserSettings.LastOpenedScene.IsWhiteSpace)
|
||||
{
|
||||
String lastSceneFile = _currentProject.GetScopedPath!(_currentProject.UserSettings.LastOpenedScene);
|
||||
|
||||
if (File.Exists(lastSceneFile))
|
||||
LoadSceneFile(lastSceneFile);
|
||||
else
|
||||
CreateAndOpenNewScene();
|
||||
}
|
||||
else
|
||||
CreateAndOpenNewScene();
|
||||
|
||||
UpdateWindowTitle();
|
||||
|
||||
return .Ok;
|
||||
}
|
||||
@@ -737,11 +762,18 @@ namespace GlitchyEditor
|
||||
}
|
||||
}
|
||||
|
||||
/// Stops the scene and cleans up the subsystems to allow loading another scene.
|
||||
private void CloseCurrentScene()
|
||||
{
|
||||
OnSceneStop();
|
||||
|
||||
ScriptEngine.ClearEntityScriptFields();
|
||||
}
|
||||
|
||||
/// Creates a new scene and openes it.
|
||||
private void CreateAndOpenNewScene()
|
||||
{
|
||||
OnSceneStop();
|
||||
CloseCurrentScene();
|
||||
|
||||
SceneFilePath = null;
|
||||
|
||||
@@ -749,13 +781,19 @@ namespace GlitchyEditor
|
||||
{
|
||||
_camera.Position = .(-1.5f, 1.5f, -2.5f);
|
||||
_camera.RotationEuler = .(MathHelper.ToRadians(25), MathHelper.ToRadians(35), 0);
|
||||
|
||||
SetReference!(_editorScene, newScene);
|
||||
_editor.CurrentScene = _editorScene;
|
||||
SetReference!(_activeScene, _editorScene);
|
||||
|
||||
SetEditorScene(newScene);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the current editor scene
|
||||
private void SetEditorScene(Scene scene)
|
||||
{
|
||||
SetReference!(_editorScene, scene);
|
||||
_editor.CurrentScene = _editorScene;
|
||||
SetReference!(_activeScene, _editorScene);
|
||||
}
|
||||
|
||||
/// Creates a new default scene.
|
||||
private static Scene CreateNewScene()
|
||||
{
|
||||
@@ -801,6 +839,11 @@ namespace GlitchyEditor
|
||||
{
|
||||
SaveScene(_editorScene, SceneFilePath);
|
||||
}
|
||||
|
||||
// Note: We only update the last opened scene if the CURRENT scene is saved, NOT when ANY scene is saved.
|
||||
String relativePath = scope .();
|
||||
Path.GetRelativePath(SceneFilePath, _currentProject.WorkspacePath, relativePath);
|
||||
_currentProject.UserSettings.LastOpenedScene = relativePath;
|
||||
}
|
||||
|
||||
/// Saves the given scene with the specified file name.
|
||||
@@ -838,7 +881,9 @@ namespace GlitchyEditor
|
||||
/// Loads the given scene file and opens it as the current scene.
|
||||
private void LoadSceneFile(StringView filename)
|
||||
{
|
||||
OnSceneStop();
|
||||
CloseCurrentScene();
|
||||
|
||||
ScriptEngine.ClearEntityScriptFields();
|
||||
|
||||
SceneFilePath = scope String(filename);
|
||||
|
||||
@@ -850,9 +895,11 @@ namespace GlitchyEditor
|
||||
// Make sure we actually loaded something!
|
||||
if (result case .Ok)
|
||||
{
|
||||
SetReference!(_editorScene, newScene);
|
||||
_editor.CurrentScene = _editorScene;
|
||||
SetReference!(_activeScene, _editorScene);
|
||||
SetEditorScene(newScene);
|
||||
|
||||
String relativePath = scope .();
|
||||
Path.GetRelativePath(filename, _currentProject.WorkspacePath, relativePath);
|
||||
_currentProject.UserSettings.LastOpenedScene = relativePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1042,22 +1089,26 @@ namespace GlitchyEditor
|
||||
|
||||
private void ShowOpenRecentSceneMenu()
|
||||
{
|
||||
if (_currentProject == null)
|
||||
return;
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (let (name, path) in _recentScenePaths)
|
||||
for (let scenePath in _currentProject.UserSettings.RecentScenes)
|
||||
{
|
||||
i++;
|
||||
if (i >= 10)
|
||||
break;
|
||||
|
||||
if (!File.Exists(path))
|
||||
String fullScenePath = _currentProject.GetScopedPath!(scenePath);
|
||||
|
||||
if (!File.Exists(fullScenePath))
|
||||
{
|
||||
// TODO!
|
||||
delete scenePath;
|
||||
@scenePath.Remove();
|
||||
}
|
||||
|
||||
if (ImGui.MenuItem(scope $"{i}: {name} ({path})"))
|
||||
if (ImGui.MenuItem(scope $"{i}: {scenePath}"))
|
||||
{
|
||||
LoadSceneFile(path);
|
||||
LoadSceneFile(fullScenePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,12 +19,17 @@ class Project
|
||||
|
||||
[BonIgnore]
|
||||
private String _scriptFolder ~ delete _;
|
||||
|
||||
[BonIgnore]
|
||||
private ProjectUserSettings _userSettings ~ delete _;
|
||||
|
||||
public StringView Name => _projectName;
|
||||
public StringView WorkspacePath => _workspacePath;
|
||||
|
||||
public StringView AssetsFolder => _assetsFolder;
|
||||
|
||||
public ProjectUserSettings UserSettings => _userSettings;
|
||||
|
||||
[AllowAppend]
|
||||
private this(StringView workspacePath)
|
||||
{
|
||||
@@ -32,13 +37,62 @@ class Project
|
||||
|
||||
_assetsFolder = new String();
|
||||
PathInProject(_assetsFolder, "Assets");
|
||||
}
|
||||
|
||||
InitUserSettings();
|
||||
}
|
||||
|
||||
/// Writes the the absolute path of the give project-file into target.
|
||||
/// @param target The string that will contain the full path.
|
||||
/// @param relativePath The path of the file relative to the workspace folder.
|
||||
public void PathInProject(String target, StringView relativePath)
|
||||
{
|
||||
Path.Combine(target, WorkspacePath, relativePath);
|
||||
}
|
||||
|
||||
/// Creates a new scoped string that contains the absolute path of the give project-file
|
||||
/// @param relativePath The path of the file relative to the workspace folder.
|
||||
public mixin GetScopedPath(StringView relativePath)
|
||||
{
|
||||
String target = scope:mixin String();
|
||||
|
||||
PathInProject(target, relativePath);
|
||||
|
||||
target
|
||||
}
|
||||
|
||||
/// Loads or creates the user specific settings for this project.
|
||||
private void InitUserSettings()
|
||||
{
|
||||
_userSettings = new ProjectUserSettings();
|
||||
|
||||
String userSettingsFile = scope .();
|
||||
PathInProject(userSettingsFile, ProjectUserSettings.FileName);
|
||||
|
||||
// It's not a problem if we couldn't find or deserialize the settings. We will simply restore the defaults.
|
||||
if (Bon.DeserializeFromFile(ref _userSettings, userSettingsFile) case .Err)
|
||||
{
|
||||
// Log anyway, just in case...
|
||||
Log.EngineLogger.Info($"Failed to deserialize project user settings file \"{userSettingsFile}\".");
|
||||
_userSettings.RestoreDefaults();
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveUserSettings()
|
||||
{
|
||||
if (_userSettings == null || !_userSettings.SettignsDirty)
|
||||
return;
|
||||
|
||||
String userSettingsFile = scope .();
|
||||
PathInProject(userSettingsFile, ProjectUserSettings.FileName);
|
||||
|
||||
// It's not a big problem, if we fail to serialize this file.
|
||||
if (Bon.SerializeIntoFile(_userSettings, userSettingsFile) case .Err)
|
||||
{
|
||||
// Log anyway, just in case...
|
||||
Log.EngineLogger.Error($"Failed to deserialize project user settings file \"{userSettingsFile}\".");
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new project with the given directory and name.
|
||||
public static Project CreateNew(StringView projectDirectory, StringView projectName)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
using Bon;
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace GlitchyEditor;
|
||||
|
||||
/// The user settings of this project
|
||||
[BonTarget]
|
||||
class ProjectUserSettings
|
||||
{
|
||||
public static StringView FileName = "project_user.bon";
|
||||
|
||||
/*[BonInclude]
|
||||
private String _lastOpenedScene ~ delete _;*/
|
||||
|
||||
[BonInclude]
|
||||
private List<String> _recentScenes ~ DeleteContainerAndItems!(_);
|
||||
|
||||
[BonIgnore]
|
||||
private bool _settingsDirty;
|
||||
|
||||
/// Gets or sets the path of the Scene that was last open. (Relative to the workspace)
|
||||
public StringView LastOpenedScene
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_recentScenes == null || _recentScenes.Count == 0)
|
||||
return "";
|
||||
|
||||
return _recentScenes[0];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_recentScenes == null)
|
||||
_recentScenes = new List<String>();
|
||||
|
||||
// Remove duplicates
|
||||
for (var entry in _recentScenes)
|
||||
{
|
||||
if (entry == value)
|
||||
{
|
||||
delete entry;
|
||||
@entry.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
_recentScenes.Insert(0, new String(value));
|
||||
|
||||
if (_recentScenes.Count > 10)
|
||||
{
|
||||
// We only store 10 entries, delete the rest
|
||||
for (int i = 10; i < _recentScenes.Count; i++)
|
||||
{
|
||||
delete _recentScenes[i];
|
||||
}
|
||||
|
||||
_recentScenes.Count = 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The scenes that were recently used.
|
||||
public List<String> RecentScenes => _recentScenes;
|
||||
|
||||
public bool SettignsDirty
|
||||
{
|
||||
get => _settingsDirty;
|
||||
set => _settingsDirty = value;
|
||||
}
|
||||
|
||||
public void RestoreDefaults()
|
||||
{
|
||||
//_lastOpenedScene?.Clear();
|
||||
if (_recentScenes != null)
|
||||
ClearAndDeleteItems!(_recentScenes);
|
||||
|
||||
_settingsDirty = true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user