fixed scene management; but now I need to improve component management (see todo in Program.cs
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
namespace EngineSharp.Core.ECS;
|
||||
|
||||
public interface IComponent
|
||||
public abstract class Component
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace EngineSharp.Core.ECS;
|
||||
|
||||
public abstract class DataComponent : IComponent
|
||||
public abstract class DataComponent : Component
|
||||
{
|
||||
|
||||
}
|
||||
@@ -22,12 +22,12 @@ public struct Entity
|
||||
/// <summary>
|
||||
/// If the component already exists on the entity, it will not be added.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<float> projectionMatrix, Matrix4X4<float> viewMatrix, Matrix4X4<float> modelMatrix);
|
||||
}
|
||||
@@ -54,7 +54,7 @@ public class Scene
|
||||
/// If the component already exists on the entity, it will not be added
|
||||
/// </summary>
|
||||
internal void AddComponent<T>(Entity entity, T component)
|
||||
where T : class, IComponent
|
||||
where T : Component
|
||||
{
|
||||
switch (component)
|
||||
{
|
||||
@@ -71,7 +71,7 @@ public class Scene
|
||||
}
|
||||
|
||||
internal T? GetComponent<T>(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<TComponent, TArchetype>(long id, Dictionary<long, List<TArchetype>> 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
|
||||
/// </summary>
|
||||
private static void AddComponent<TComponent, TArchetype>(long id, TComponent component, Dictionary<long, List<TArchetype>> componentStore)
|
||||
where TArchetype : class, IComponent
|
||||
where TArchetype : Component
|
||||
where TComponent : TArchetype
|
||||
{
|
||||
if (componentStore.TryGetValue(id, out var components) && !components.OfType<TComponent>().Any())
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace EngineSharp.Core;
|
||||
internal class OpenGLEngine : Engine
|
||||
{
|
||||
private readonly IWindow _window;
|
||||
private readonly List<Scene> _scenes;
|
||||
private readonly Dictionary<string, Scene> _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<string> 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<float>.Zero, _window.FramebufferSize);
|
||||
|
||||
InitialiseShaders(Directory.GetFiles("./assets/shaders", "*.vert"));
|
||||
// TODO: SetCurrentScene -> with the default scene
|
||||
SetCurrentScene(_defaultSceneName);
|
||||
}
|
||||
|
||||
private void OnUpdate(double deltaTime)
|
||||
|
||||
@@ -13,14 +13,28 @@ internal abstract class Engine : IEngine
|
||||
}
|
||||
|
||||
protected readonly Dictionary<string, Shader> _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);
|
||||
|
||||
35
src/EngineSharp.Core/EngineSharp.Core/SceneManager.cs
Normal file
35
src/EngineSharp.Core/EngineSharp.Core/SceneManager.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using EngineSharp.Core.ECS;
|
||||
using EngineSharp.Core.Rendering;
|
||||
|
||||
namespace EngineSharp.Core;
|
||||
|
||||
public static class SceneManager
|
||||
{
|
||||
private static bool DefaultSceneCreated = false;
|
||||
|
||||
/// <summary>
|
||||
/// Creates the scene that will be loaded once the game is started. <br/>
|
||||
/// Can only be called once.
|
||||
/// </summary>
|
||||
/// <param name="sceneName"></param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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(),
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user