improved ECS and added new render component
This commit is contained in:
@ -0,0 +1,8 @@
|
|||||||
|
using Silk.NET.OpenGL;
|
||||||
|
|
||||||
|
namespace EngineSharp.Core.ECS;
|
||||||
|
|
||||||
|
public abstract class RenderComponent : IComponent
|
||||||
|
{
|
||||||
|
internal abstract void Render(GL gl);
|
||||||
|
}
|
||||||
@ -1,13 +1,15 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Silk.NET.OpenGL;
|
||||||
|
|
||||||
namespace EngineSharp.Core.ECS;
|
namespace EngineSharp.Core.ECS;
|
||||||
|
|
||||||
public class Scene
|
public class Scene
|
||||||
{
|
{
|
||||||
private Dictionary<long, LogicComponent> _logicComponents = new();
|
private readonly Dictionary<long, List<LogicComponent>> _logicComponents = new();
|
||||||
private Dictionary<long, DataComponent> _dataComponents = new();
|
private readonly Dictionary<long, List<DataComponent>> _dataComponents = new();
|
||||||
|
private readonly Dictionary<long, List<RenderComponent>> _renderComponents = new();
|
||||||
|
|
||||||
private long _nextSceneId; // ugly solution but it works
|
private long _nextSceneId; // not the prettiest solution but it works
|
||||||
|
|
||||||
public Entity CreateEntity(string name)
|
public Entity CreateEntity(string name)
|
||||||
{
|
{
|
||||||
@ -16,63 +18,80 @@ public class Scene
|
|||||||
|
|
||||||
internal void StartComponents()
|
internal void StartComponents()
|
||||||
{
|
{
|
||||||
foreach (var component in _logicComponents.Values)
|
foreach (var components in _logicComponents.Values)
|
||||||
{
|
{
|
||||||
component.Start();
|
components.ForEach(c => c.Start());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void UpdateComponents(double deltaTime)
|
internal void UpdateComponents(double deltaTime)
|
||||||
{
|
{
|
||||||
foreach (var component in _logicComponents.Values)
|
foreach (var components in _logicComponents.Values)
|
||||||
{
|
{
|
||||||
component.OnUpdate(deltaTime);
|
components.ForEach(c => c.OnUpdate(deltaTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AddComponent(Entity entity, IComponent component)
|
internal void RenderComponents(GL gl)
|
||||||
|
{
|
||||||
|
foreach (var components in _renderComponents.Values)
|
||||||
|
{
|
||||||
|
components.ForEach(c => c.Render(gl));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void AddComponent<T>(Entity entity, T component)
|
||||||
|
where T : class, IComponent
|
||||||
{
|
{
|
||||||
switch (component)
|
switch (component)
|
||||||
{
|
{
|
||||||
case LogicComponent logic:
|
case LogicComponent logic:
|
||||||
_logicComponents.TryAdd(entity.Id, logic);
|
AddComponent(entity.Id, logic, _logicComponents);
|
||||||
break;
|
break;
|
||||||
case DataComponent data:
|
case DataComponent data:
|
||||||
_dataComponents.TryAdd(entity.Id, data);
|
AddComponent(entity.Id, data, _dataComponents);
|
||||||
|
break;
|
||||||
|
case RenderComponent render:
|
||||||
|
AddComponent(entity.Id, render, _renderComponents);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal IComponent? GetComponent(Entity entity, IComponent component)
|
internal T? GetComponent<T>(Entity entity, T component)
|
||||||
|
where T : class, IComponent
|
||||||
{
|
{
|
||||||
switch (component)
|
return component switch
|
||||||
{
|
{
|
||||||
case LogicComponent logic:
|
LogicComponent => GetComponent<T, LogicComponent>(entity.Id, _logicComponents),
|
||||||
return GetComponent(entity.Id, logic);
|
DataComponent => GetComponent<T, DataComponent>(entity.Id, _dataComponents),
|
||||||
case DataComponent data:
|
RenderComponent => GetComponent<T, RenderComponent>(entity.Id, _renderComponents),
|
||||||
return GetComponent(entity.Id, data);
|
_ => null
|
||||||
default:
|
};
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LogicComponent? GetComponent(long id, LogicComponent component)
|
private static TComponent? GetComponent<TComponent, TArchetype>(long id, Dictionary<long, List<TArchetype>> componentStore)
|
||||||
|
where TComponent : class, IComponent
|
||||||
{
|
{
|
||||||
if (_logicComponents.TryGetValue(id, out var logic))
|
// ReSharper disable once ConvertIfStatementToReturnStatement
|
||||||
|
if (componentStore.TryGetValue(id, out var components))
|
||||||
{
|
{
|
||||||
return logic;
|
return components.OfType<TComponent>().SingleOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataComponent? GetComponent(long id, DataComponent component)
|
private static void AddComponent<TComponent, TArchetype>(long id, TComponent component, Dictionary<long, List<TArchetype>> componentStore)
|
||||||
|
where TArchetype : class, IComponent
|
||||||
|
where TComponent : TArchetype
|
||||||
{
|
{
|
||||||
if (_dataComponents.TryGetValue(id, out var data))
|
if (componentStore.TryGetValue(id, out var components))
|
||||||
{
|
{
|
||||||
return data;
|
components.Add(component);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
componentStore.Add(id, [component]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,8 +80,12 @@ internal class OpenGLEngine : IEngine
|
|||||||
var viewMatrix = _camera.ViewMatrix;
|
var viewMatrix = _camera.ViewMatrix;
|
||||||
|
|
||||||
// TODO: Here render all meshes etc.
|
// TODO: Here render all meshes etc.
|
||||||
// On constructing a MeshRenderer, register it somewhere so it can be rendered here (MeshRenderer would then be a component while Mesh would be a normal C# object in the context of an ECS)
|
|
||||||
// MeshRenderer contains a mesh; Mesh contains a material; Material contains a shader and the values for all uniforms of the shader (apart from the matrices; I am not sure how to best handle the model matrix with this approach)
|
// MeshRenderer contains a mesh; Mesh contains a material; Material contains a shader and the values for all uniforms of the shader (apart from the matrices; I am not sure how to best handle the model matrix with this approach)
|
||||||
|
|
||||||
|
if (_currentScene is not null)
|
||||||
|
{
|
||||||
|
_currentScene.RenderComponents(_gl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnResize(Vector2D<int> newDimensions)
|
private void OnResize(Vector2D<int> newDimensions)
|
||||||
|
|||||||
@ -1,14 +1,15 @@
|
|||||||
using Silk.NET.OpenGL;
|
using EngineSharp.Core.ECS;
|
||||||
|
using Silk.NET.OpenGL;
|
||||||
|
|
||||||
namespace EngineSharp.Core.Rendering;
|
namespace EngineSharp.Core.Rendering;
|
||||||
|
|
||||||
public class MeshRenderer
|
public class MeshRenderer : RenderComponent
|
||||||
{
|
{
|
||||||
public Mesh Mesh { get; set; }
|
public Mesh Mesh { get; set; }
|
||||||
|
|
||||||
private uint vao, vbo, ebo;
|
private uint vao, vbo, ebo;
|
||||||
|
|
||||||
internal void Render(GL gl)
|
internal override void Render(GL gl)
|
||||||
{
|
{
|
||||||
GenerateRenderableMesh(gl);
|
GenerateRenderableMesh(gl);
|
||||||
gl.BindVertexArray(vao);
|
gl.BindVertexArray(vao);
|
||||||
|
|||||||
Reference in New Issue
Block a user