Refactor project structure and enhance functionality

Added `InternalsVisibleTo` attribute for "Ghost.Editor" in `AssemblyInfo.cs`.
Added a binary file `Empty.zip` to the project.
Added a new `ProjectMetadata` class in `ProjectMetadata.cs`.
Added new states and interfaces for managing application states in `EditorState.cs`, `LandingState.cs`, and `IAppState.cs`.
Added a notification service in `INotificationService.cs` and `StackedNotificationService.cs`.
Added new XAML files for UI components, including `InspectorView.xaml` and `InternalControls.xaml`.

Changed the `ProjectInfo` class in `ProjectInfo.cs` to include a `MetadataPath` property instead of `Path` and `EngineVersion`.
Changed the `TemplateInfo` class in `TemplateInfo.cs` to use a struct instead of a class for `TemplateData`.
Changed the `ProjectService` class to use the new `ProjectRepository` for managing project data.

Removed several using directives and the entire `ProjectRepository` class from `ProjectRepository.cs`, replacing it with a new implementation.
Removed old methods and properties in `EntityManager` and `World` classes to improve entity management and component handling.

Updated the `Ghost.Data.csproj` file to include the new `Empty.zip` file as a content item.
Updated the `ProjectRepository` class to manage project data using SQLite.
Updated various XAML files to include new styles and controls, improving the overall UI design.
Updated the `CreateProjectViewModel` to include a notification service and handle project creation logic.
Updated the test project to include references to the new `Ghost.Graphics` project and modified test cases to align with the new structure.
This commit is contained in:
2025-05-31 01:45:34 +09:00
parent 67b6040b5e
commit 61bbb1bc68
66 changed files with 1923 additions and 733 deletions

View File

@@ -1,190 +0,0 @@
using Ghost.Engine.Models;
using Ghost.Entities;
using System.ComponentModel;
namespace Ghost.Engine;
public unsafe class GameObject : INotifyPropertyChanged
{
private readonly Dictionary<Type, ScriptComponent> _components = new();
private readonly List<GameObject> _children = new();
public event PropertyChangedEventHandler? PropertyChanged;
public Entity Entity
{
get;
}
public Scene Scene
{
get;
internal set;
}
public GameObject? Parent
{
get;
internal set;
}
public string Name
{
get;
set;
}
public bool IsActive
{
get;
set;
}
public IEnumerable<ScriptComponent> Components => _components.Values;
public IEnumerable<GameObject> Children => _children;
public GameObject(Scene scene, string name)
{
// TODO: Initialize Entity properly
//Entity =
Scene = scene;
Name = name;
IsActive = true;
}
public void AddComponent<T>(T component)
where T : ScriptComponent
{
_components.Add(typeof(T), component);
component.Owner = Entity;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Components)));
}
public void RemoveComponent<T>()
where T : ScriptComponent
{
var key = typeof(T);
if (_components.Remove(key, out var component))
{
component.OnDestroy();
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Components)));
}
}
public T? GetComponent<T>()
where T : ScriptComponent
{
if (_components.TryGetValue(typeof(T), out var component))
{
return (T)component;
}
return null;
}
public void AddChild(GameObject child)
{
if (child.Scene != Scene)
{
throw new InvalidOperationException("Child GameObject must belong to the same Scene.");
}
_children.Add(child);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Children)));
}
public void RemoveChild(GameObject child)
{
if (_children.Remove(child))
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Children)));
}
}
internal void OnEnable()
{
foreach (var component in Components)
{
if (!component.Enable)
{
continue;
}
component.OnEnable();
}
foreach (var child in _children)
{
child.OnEnable();
}
}
internal void Start()
{
foreach (var component in Components)
{
if (!component.Enable)
{
continue;
}
component.Start();
}
}
internal void Update()
{
foreach (var component in Components)
{
if (!component.Enable)
{
continue;
}
component.Update();
}
}
internal void LateUpdate()
{
foreach (var component in Components)
{
if (!component.Enable)
{
continue;
}
component.LateUpdate();
}
}
internal void FixedUpdate()
{
foreach (var component in Components)
{
if (!component.Enable)
{
continue;
}
component.FixedUpdate();
}
}
public void Destroy()
{
foreach (var component in Components)
{
if (!component.Enable)
{
continue;
}
component.OnDestroy();
}
foreach (var child in _children)
{
child.Destroy();
}
_children.Clear();
_components.Clear();
Parent?._children.Remove(this);
}
}

View File

@@ -1,30 +0,0 @@
namespace Ghost.Engine.Models;
public class Scene
{
private readonly HashSet<GameObject> _rootObjects = new();
public IEnumerable<GameObject> RootObjects => _rootObjects;
internal Scene()
{
}
internal void Load()
{
foreach (var gameObject in _rootObjects)
{
gameObject.Start();
}
}
internal void Unload()
{
foreach (var gameObject in _rootObjects)
{
gameObject.Destroy();
}
_rootObjects.Clear();
}
}

View File

@@ -4,5 +4,5 @@ internal class EngineData
{
public const string ENGINE_NAME = "Ghost Engine";
public readonly static Version ENGINE_VERSION = new(0, 1, 0);
public readonly static Version s_engineVersion = new(0, 1, 0);
}

View File

@@ -10,43 +10,43 @@ internal static class PlayerLoopService
public static void Start()
{
if (_isRunning)
{
return;
}
//if (_isRunning)
//{
// return;
//}
foreach (var gameObject in SceneManager.QueryRootGameObjects())
{
gameObject.Start();
}
//foreach (var gameObject in SceneManager.QueryRootGameObjects())
//{
// gameObject.Start();
//}
_timer ??= new Timer(FixedUpdate, null, 0, (int)(fixedDeltaTime * 1000));
//_timer ??= new Timer(FixedUpdate, null, 0, (int)(fixedDeltaTime * 1000));
while (_isRunning)
{
Update();
}
//while (_isRunning)
//{
// Update();
//}
}
private static void Update()
{
foreach (var gameObject in SceneManager.QueryRootGameObjects())
{
gameObject.Update();
}
//foreach (var gameObject in SceneManager.QueryRootGameObjects())
//{
// gameObject.Update();
//}
foreach (var gameObject in SceneManager.QueryRootGameObjects())
{
gameObject.LateUpdate();
}
//foreach (var gameObject in SceneManager.QueryRootGameObjects())
//{
// gameObject.LateUpdate();
//}
}
private static void FixedUpdate(object? state)
{
foreach (var gameObject in SceneManager.QueryRootGameObjects())
{
gameObject.FixedUpdate();
}
//foreach (var gameObject in SceneManager.QueryRootGameObjects())
//{
// gameObject.FixedUpdate();
//}
}
public static void Stop()

View File

@@ -1,6 +1,4 @@
using Ghost.Engine.Models;
namespace Ghost.Engine.Services;
namespace Ghost.Engine.Services;
public enum SceneLoadMode
{
@@ -10,41 +8,41 @@ public enum SceneLoadMode
public static class SceneManager
{
private readonly static HashSet<Scene> _activeScenes = new();
//private readonly static HashSet<Scene> _activeScenes = new();
internal static IEnumerable<GameObject> QueryRootGameObjects()
{
foreach (var scene in _activeScenes)
{
foreach (var gameObject in scene.RootObjects)
{
if (!gameObject.IsActive)
{
continue;
}
//internal static IEnumerable<GameObject> QueryRootGameObjects()
//{
// foreach (var scene in _activeScenes)
// {
// foreach (var gameObject in scene.RootObjects)
// {
// if (!gameObject.IsActive)
// {
// continue;
// }
yield return gameObject;
}
}
}
// yield return gameObject;
// }
// }
//}
public static void LoadScene(Scene scene, SceneLoadMode loadMode)
{
if (loadMode == SceneLoadMode.Single)
{
foreach (var activeScene in _activeScenes)
{
activeScene.Unload();
}
_activeScenes.Clear();
}
//public static void LoadScene(Scene scene, SceneLoadMode loadMode)
//{
// if (loadMode == SceneLoadMode.Single)
// {
// foreach (var activeScene in _activeScenes)
// {
// activeScene.Unload();
// }
// _activeScenes.Clear();
// }
_activeScenes.Add(scene);
scene.Load();
}
// _activeScenes.Add(scene);
// scene.Load();
//}
public static Task LoadSceneAsync(Scene scene, SceneLoadMode loadMode)
{
return Task.Run(() => LoadScene(scene, loadMode));
}
//public static Task LoadSceneAsync(Scene scene, SceneLoadMode loadMode)
//{
// return Task.Run(() => LoadScene(scene, loadMode));
//}
}