diff --git a/src/EngineSharp.Core/EngineSharp.Core/ECS/IComponent.cs b/src/EngineSharp.Core/EngineSharp.Core/ECS/Component.cs
similarity index 54%
rename from src/EngineSharp.Core/EngineSharp.Core/ECS/IComponent.cs
rename to src/EngineSharp.Core/EngineSharp.Core/ECS/Component.cs
index ba64139..34088d2 100644
--- a/src/EngineSharp.Core/EngineSharp.Core/ECS/IComponent.cs
+++ b/src/EngineSharp.Core/EngineSharp.Core/ECS/Component.cs
@@ -1,6 +1,6 @@
namespace EngineSharp.Core.ECS;
-public interface IComponent
+public abstract class Component
{
-
+
}
\ No newline at end of file
diff --git a/src/EngineSharp.Core/EngineSharp.Core/ECS/DataComponent.cs b/src/EngineSharp.Core/EngineSharp.Core/ECS/DataComponent.cs
index ed9af42..c4ae577 100644
--- a/src/EngineSharp.Core/EngineSharp.Core/ECS/DataComponent.cs
+++ b/src/EngineSharp.Core/EngineSharp.Core/ECS/DataComponent.cs
@@ -1,6 +1,6 @@
namespace EngineSharp.Core.ECS;
-public abstract class DataComponent : IComponent
+public abstract class DataComponent : Component
{
}
\ No newline at end of file
diff --git a/src/EngineSharp.Core/EngineSharp.Core/ECS/Entity.cs b/src/EngineSharp.Core/EngineSharp.Core/ECS/Entity.cs
index 8850f70..f201d87 100644
--- a/src/EngineSharp.Core/EngineSharp.Core/ECS/Entity.cs
+++ b/src/EngineSharp.Core/EngineSharp.Core/ECS/Entity.cs
@@ -22,12 +22,12 @@ public struct Entity
///
/// If the component already exists on the entity, it will not be added.
///
- public void AddComponent(IComponent component)
+ public void AddComponent(Component component)
{
_scene.AddComponent(this, component);
}
- public IComponent? GetComponent(IComponent component)
+ public Component? GetComponent(Component component)
{
return _scene.GetComponent(this, component);
}
diff --git a/src/EngineSharp.Core/EngineSharp.Core/ECS/LogicComponent.cs b/src/EngineSharp.Core/EngineSharp.Core/ECS/LogicComponent.cs
index 637aa23..2eeacab 100644
--- a/src/EngineSharp.Core/EngineSharp.Core/ECS/LogicComponent.cs
+++ b/src/EngineSharp.Core/EngineSharp.Core/ECS/LogicComponent.cs
@@ -1,6 +1,6 @@
namespace EngineSharp.Core.ECS;
-public abstract class LogicComponent : IComponent // Kinda like Unity's MonoBehaviour
+public abstract class LogicComponent : Component // Kinda like Unity's MonoBehaviour
{
public abstract void Initialise();
public abstract void OnUpdate(double deltaTime);
diff --git a/src/EngineSharp.Core/EngineSharp.Core/ECS/RenderComponent.cs b/src/EngineSharp.Core/EngineSharp.Core/ECS/RenderComponent.cs
index e9729c9..b92cf3a 100644
--- a/src/EngineSharp.Core/EngineSharp.Core/ECS/RenderComponent.cs
+++ b/src/EngineSharp.Core/EngineSharp.Core/ECS/RenderComponent.cs
@@ -3,7 +3,7 @@ using Silk.NET.OpenGL;
namespace EngineSharp.Core.ECS;
-public abstract class RenderComponent : IComponent
+public abstract class RenderComponent : Component
{
internal abstract void Render(GL gl, Matrix4X4 projectionMatrix, Matrix4X4 viewMatrix, Matrix4X4 modelMatrix);
}
\ No newline at end of file
diff --git a/src/EngineSharp.Core/EngineSharp.Core/ECS/Scene.cs b/src/EngineSharp.Core/EngineSharp.Core/ECS/Scene.cs
index 2ef75e3..d888bdd 100644
--- a/src/EngineSharp.Core/EngineSharp.Core/ECS/Scene.cs
+++ b/src/EngineSharp.Core/EngineSharp.Core/ECS/Scene.cs
@@ -54,7 +54,7 @@ public class Scene
/// If the component already exists on the entity, it will not be added
///
internal void AddComponent(Entity entity, T component)
- where T : class, IComponent
+ where T : Component
{
switch (component)
{
@@ -71,7 +71,7 @@ public class Scene
}
internal T? GetComponent(Entity entity, T component)
- where T : class, IComponent
+ where T : Component
{
return component switch
{
@@ -83,7 +83,7 @@ public class Scene
}
private static TComponent? GetComponent(long id, Dictionary> componentStore)
- where TComponent : class, IComponent
+ where TComponent : Component
{
// ReSharper disable once ConvertIfStatementToReturnStatement
if (componentStore.TryGetValue(id, out var components))
@@ -98,7 +98,7 @@ public class Scene
/// If the component already exists on the entity, it will not be added
///
private static void AddComponent(long id, TComponent component, Dictionary> componentStore)
- where TArchetype : class, IComponent
+ where TArchetype : Component
where TComponent : TArchetype
{
if (componentStore.TryGetValue(id, out var components) && !components.OfType().Any())
diff --git a/src/EngineSharp.Core/EngineSharp.Core/IEngine.cs b/src/EngineSharp.Core/EngineSharp.Core/IEngine.cs
index 23fb0fe..411bb55 100644
--- a/src/EngineSharp.Core/EngineSharp.Core/IEngine.cs
+++ b/src/EngineSharp.Core/EngineSharp.Core/IEngine.cs
@@ -1,6 +1,4 @@
-using System;
-using EngineSharp.Core.ECS;
-using EngineSharp.Core.Rendering;
+using EngineSharp.Core.Rendering;
using Silk.NET.Windowing;
namespace EngineSharp.Core;
@@ -9,10 +7,7 @@ public interface IEngine
{
void Start();
void Stop();
-
- Scene CreateScene();
- void SetCurrentScene(Scene scene);
-
+
Shader GetShader(string vertexShaderPath);
}
diff --git a/src/EngineSharp.Core/EngineSharp.Core/OpenGLEngine.cs b/src/EngineSharp.Core/EngineSharp.Core/OpenGLEngine.cs
index f7af9da..3d18d20 100644
--- a/src/EngineSharp.Core/EngineSharp.Core/OpenGLEngine.cs
+++ b/src/EngineSharp.Core/EngineSharp.Core/OpenGLEngine.cs
@@ -12,7 +12,7 @@ namespace EngineSharp.Core;
internal class OpenGLEngine : Engine
{
private readonly IWindow _window;
- private readonly List _scenes;
+ private readonly Dictionary _scenes;
private GL _gl = null!; // because between constructing the engine and OnLoad being called nothing should call these fields. Therefore, we do "!" to get rid of warnings
private Input _input = null!;
private PerspectiveCamera _camera = null!;
@@ -47,16 +47,6 @@ internal class OpenGLEngine : Engine
_window.Close();
}
- // TODO: pass in name as parameter
- // Name must be unique and is used to switch scenes while the application is running.
- // We need exactly one default scene which is the initial scene (call SetCurrentScene during the Load() method
- public override Scene CreateScene()
- {
- var scene = new Scene();
- _scenes.Add(scene);
- return scene;
- }
-
private void InitialiseShaders(IEnumerable vertexShaderFiles)
{
foreach (var vertexShaderFile in vertexShaderFiles)
@@ -69,14 +59,37 @@ internal class OpenGLEngine : Engine
}
}
- public override void SetCurrentScene(Scene scene)
+ internal override Scene CreateScene(string name)
{
- _currentScene = scene;
- _currentScene.InitialiseComponents();
+ var scene = new Scene();
+ if (!_scenes.TryAdd(name, scene))
+ {
+ throw new ArgumentException($"Scene '{name}' already exists.");
+ }
+
+ return scene;
+ }
+
+ internal override void SetCurrentScene(string sceneName)
+ {
+ if (_scenes.TryGetValue(sceneName, out var scene))
+ {
+ _currentScene = scene;
+ _currentScene.InitialiseComponents();
+ }
+ else
+ {
+ throw new ArgumentException($"Scene '{sceneName}' does not exist.");
+ }
}
private void OnLoad()
{
+ if (string.IsNullOrEmpty(_defaultSceneName))
+ {
+ throw new InvalidOperationException("No default scene defined.");
+ }
+
_gl = _window.CreateOpenGL();
_input = new Input(_window.CreateInput());
@@ -86,7 +99,7 @@ internal class OpenGLEngine : Engine
_camera = new PerspectiveCamera(Vector3D.Zero, _window.FramebufferSize);
InitialiseShaders(Directory.GetFiles("./assets/shaders", "*.vert"));
- // TODO: SetCurrentScene -> with the default scene
+ SetCurrentScene(_defaultSceneName);
}
private void OnUpdate(double deltaTime)
diff --git a/src/EngineSharp.Core/EngineSharp.Core/Rendering/Engine.cs b/src/EngineSharp.Core/EngineSharp.Core/Rendering/Engine.cs
index 87b6061..93ebb9f 100644
--- a/src/EngineSharp.Core/EngineSharp.Core/Rendering/Engine.cs
+++ b/src/EngineSharp.Core/EngineSharp.Core/Rendering/Engine.cs
@@ -13,14 +13,28 @@ internal abstract class Engine : IEngine
}
protected readonly Dictionary _shaders = [];
+ protected string? _defaultSceneName;
public static Engine Instance => SingletonInstance ?? throw new InvalidOperationException("No engine has been created yet. Cannot return an instance.");
public abstract void Start();
public abstract void Stop();
- public abstract Scene CreateScene();
- public abstract void SetCurrentScene(Scene scene);
+ internal abstract Scene CreateScene(string name);
+ internal abstract void SetCurrentScene(string sceneName);
+ internal Scene CreateScene(string sceneName, bool isDefaultScene)
+ {
+
+ if (isDefaultScene && !string.IsNullOrEmpty(_defaultSceneName))
+ {
+ throw new InvalidOperationException(
+ $"A default scene already exists, cannot create a new one. Name of the current default scene: '{_defaultSceneName}'.");
+ }
+
+ _defaultSceneName = sceneName;
+ return CreateScene(sceneName);
+ }
+
public Shader GetShader(string vertexShaderPath)
{
Instance._shaders.TryGetValue(vertexShaderPath, out var shader);
diff --git a/src/EngineSharp.Core/EngineSharp.Core/SceneManager.cs b/src/EngineSharp.Core/EngineSharp.Core/SceneManager.cs
new file mode 100644
index 0000000..c452083
--- /dev/null
+++ b/src/EngineSharp.Core/EngineSharp.Core/SceneManager.cs
@@ -0,0 +1,35 @@
+using EngineSharp.Core.ECS;
+using EngineSharp.Core.Rendering;
+
+namespace EngineSharp.Core;
+
+public static class SceneManager
+{
+ private static bool DefaultSceneCreated = false;
+
+ ///
+ /// Creates the scene that will be loaded once the game is started.
+ /// Can only be called once.
+ ///
+ ///
+ public static Scene CreateDefaultScene(string sceneName)
+ {
+ if (DefaultSceneCreated)
+ {
+ throw new InvalidOperationException("Default scene has already been created.");
+ }
+
+ var scene = Engine.Instance.CreateScene(sceneName, true);
+ return scene;
+ }
+
+ public static Scene CreateScene(string sceneName)
+ {
+ return Engine.Instance.CreateScene(sceneName);
+ }
+
+ public static void SetCurrentScene(string sceneName)
+ {
+ Engine.Instance.SetCurrentScene(sceneName);
+ }
+}
\ No newline at end of file
diff --git a/src/EngineSharp/Planet.cs b/src/EngineSharp/Planet.cs
index 8978726..a261251 100644
--- a/src/EngineSharp/Planet.cs
+++ b/src/EngineSharp/Planet.cs
@@ -1,4 +1,5 @@
using Engine_silk.NET;
+using EngineSharp.Core;
using EngineSharp.Core.Rendering;
namespace EngineSharp;
@@ -19,6 +20,7 @@ public class Planet : Core.ECS.LogicComponent
Resolution = 10,
Material = material,
};
+
PlanetMesh = new MeshRenderer
{
Mesh = sphereGenerator.CreateSphere(),
diff --git a/src/EngineSharp/Program.cs b/src/EngineSharp/Program.cs
index 01e7358..5a0a927 100644
--- a/src/EngineSharp/Program.cs
+++ b/src/EngineSharp/Program.cs
@@ -17,12 +17,12 @@ internal static class Program
};
var engine = EngineFactory.Create(GraphicsAPI.OpenGL, options);
- var mainScene = engine.CreateScene();
+ var mainScene = SceneManager.CreateDefaultScene("default");
var planet = mainScene.CreateEntity("planet");
+ // TODO: Find a way to call "AddComponent" from a component. Otherwise the MeshRenderer I created inside the Planet-Component doesn't get registered and can't therefore be rendered
planet.AddComponent(new Planet());
- engine.SetCurrentScene(mainScene);
engine.Start();
}
}
\ No newline at end of file