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:
@@ -0,0 +1 @@
|
||||
project_user.bon
|
||||
@@ -30,10 +30,10 @@
|
||||
}
|
||||
},
|
||||
MeshComponent = {
|
||||
Mesh = "Models/sphere.glb"
|
||||
Mesh = "Assets/Models/sphere.glb"
|
||||
},
|
||||
MeshRendererComponent = {
|
||||
Material = "Textures/TestMaterial.mat"
|
||||
Material = "Assets/Textures/TestMaterial.mat"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -49,12 +49,12 @@
|
||||
},
|
||||
Rotation = {
|
||||
X = 0.614328027,
|
||||
Y = 0.239776045,
|
||||
Y = 0.23977606,
|
||||
Z = 0.0315669999,
|
||||
W = 0.751073837
|
||||
W = 0.751073778
|
||||
},
|
||||
Scale = {
|
||||
X = 0.999998868,
|
||||
X = 0.999998808,
|
||||
Y = 1,
|
||||
Z = 1.00000095
|
||||
},
|
||||
@@ -70,7 +70,7 @@
|
||||
Color = {
|
||||
R = 1,
|
||||
G = 0.991771996,
|
||||
B = 0.74086225
|
||||
B = 0.74086231
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -103,10 +103,10 @@
|
||||
}
|
||||
},
|
||||
MeshComponent = {
|
||||
Mesh = "Models/plane.glb"
|
||||
Mesh = "Assets/Models/plane.glb"
|
||||
},
|
||||
MeshRendererComponent = {
|
||||
Material = "Textures/TestMaterial.mat"
|
||||
Material = "Assets/Textures/TestMaterial.mat"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -146,7 +146,7 @@
|
||||
OrthographicHeight = 10,
|
||||
OrthographicNearPlane = 0,
|
||||
OrthographicFarPlane = 10,
|
||||
AspectRatio = 2.19888878,
|
||||
AspectRatio = 1.87453413,
|
||||
FixedAspectRatio = false
|
||||
}
|
||||
},
|
||||
@@ -164,7 +164,7 @@
|
||||
Rotation = {
|
||||
X = 0.18301262,
|
||||
Y = -0.683013558,
|
||||
Z = 0.683012128,
|
||||
Z = 0.683012187,
|
||||
W = 0.183013007
|
||||
},
|
||||
Scale = {
|
||||
@@ -173,13 +173,13 @@
|
||||
Z = 1
|
||||
},
|
||||
EditorEulerRotation = {
|
||||
X = 1.57079446,
|
||||
Y = -2.61799312,
|
||||
X = 1.57079458,
|
||||
Y = -2.61799288,
|
||||
Z = 0
|
||||
}
|
||||
},
|
||||
MeshComponent = {
|
||||
Mesh = "Models/plane.glb"
|
||||
Mesh = ""
|
||||
},
|
||||
MeshRendererComponent = {
|
||||
Material = ""
|
||||
@@ -192,32 +192,32 @@
|
||||
},
|
||||
TransformComponent = {
|
||||
Position = {
|
||||
X = 2.37353587,
|
||||
X = 2.37353563,
|
||||
Y = 0.629615188,
|
||||
Z = -1.34831977
|
||||
},
|
||||
Rotation = {
|
||||
X = 0.270598024,
|
||||
Y = -0.65328145,
|
||||
Y = -0.65328151,
|
||||
Z = 0.65328151,
|
||||
W = 0.270598054
|
||||
},
|
||||
Scale = {
|
||||
X = 0.999999881,
|
||||
Y = 0.999999821,
|
||||
X = 0.999999821,
|
||||
Y = 0.999999762,
|
||||
Z = 0.999999702
|
||||
},
|
||||
EditorEulerRotation = {
|
||||
X = 1.57079637,
|
||||
Y = -2.3561945,
|
||||
Z = 8.94069743e-08
|
||||
X = 1.57079649,
|
||||
Y = -2.35619426,
|
||||
Z = 8.94069601e-08
|
||||
}
|
||||
},
|
||||
MeshComponent = {
|
||||
Mesh = "Models/plane.glb"
|
||||
Mesh = "Assets/Models/plane.glb"
|
||||
},
|
||||
MeshRendererComponent = {
|
||||
Material = "Textures/RocketMaterial.mat"
|
||||
Material = "Assets/Textures/RocketMaterial.mat"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
project_user.bon
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,17 @@ static class ScriptEngine
|
||||
_userAssemblyWatcher.StartRaisingEvents();
|
||||
}
|
||||
|
||||
/// Gets rid of all entity fields.
|
||||
public static void ClearEntityScriptFields()
|
||||
{
|
||||
for (var value in _entityFields.Values)
|
||||
{
|
||||
DeleteDictionaryAndKeys!(value);
|
||||
}
|
||||
|
||||
_entityFields.Clear();
|
||||
}
|
||||
|
||||
static void LoadScriptAssemblies()
|
||||
{
|
||||
CreateAppDomain("GlitchyEngineScriptRuntime");
|
||||
@@ -201,11 +212,13 @@ static class ScriptEngine
|
||||
s_AppAssembly = null;
|
||||
s_AppAssemblyImage = null;
|
||||
}
|
||||
|
||||
ClearDictionaryAndReleaseValues!(_sharpClasses);
|
||||
|
||||
|
||||
GetCoreAttributes();
|
||||
GetCoreClasses();
|
||||
|
||||
ClearDictionaryAndReleaseValues!(_sharpClasses);
|
||||
ClearDictionaryAndReleaseValues!(_componentClasses);
|
||||
ClearDictionaryAndReleaseValues!(_entityScripts);
|
||||
|
||||
GetComponentsFromAssemblies();
|
||||
|
||||
@@ -366,9 +379,9 @@ static class ScriptEngine
|
||||
/// Retrieves the base classes from which every Component or Entity inherits
|
||||
static void GetCoreClasses()
|
||||
{
|
||||
s_EngineObject?.ReleaseRef();
|
||||
s_EntityRoot?.ReleaseRef();
|
||||
s_ComponentRoot?.ReleaseRef();
|
||||
ReleaseRefAndNullify!(s_EngineObject);
|
||||
ReleaseRefAndNullify!(s_EntityRoot);
|
||||
ReleaseRefAndNullify!(s_ComponentRoot);
|
||||
|
||||
s_EngineObject = new ScriptClass("GlitchyEngine.Core", "EngineObject", s_CoreAssemblyImage, .Class);
|
||||
s_EntityRoot = new ScriptClass("GlitchyEngine", "Entity", s_CoreAssemblyImage, .Entity);
|
||||
@@ -383,8 +396,6 @@ static class ScriptEngine
|
||||
|
||||
private static void GetEntitiesFromAssemblies()
|
||||
{
|
||||
ClearDictionaryAndReleaseValues!(_entityScripts);
|
||||
|
||||
if (s_AppAssemblyImage == null)
|
||||
return;
|
||||
|
||||
@@ -413,8 +424,6 @@ static class ScriptEngine
|
||||
}
|
||||
private static void GetComponentsFromAssemblies()
|
||||
{
|
||||
ClearDictionaryAndReleaseValues!(_componentClasses);
|
||||
|
||||
MonoTableInfo* typeDefinitionsTable = Mono.mono_image_get_table_info(s_CoreAssemblyImage, .MONO_TABLE_TYPEDEF);
|
||||
int32 numTypes = Mono.mono_table_info_get_rows(typeDefinitionsTable);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user