forked from Misaki/GhostEngine
Removed Ghost.ArcEntities project, it's replaced by Ghost.Entities
Added Playback to EntityCommandBuffer Added JobSchedular to world Added ISystem and SystemGroup Updated packages
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
using Ghost.Core;
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ghost.Entities;
|
||||
|
||||
@@ -17,18 +20,24 @@ public unsafe class EntityCommandBuffer : IDisposable
|
||||
private struct Command
|
||||
{
|
||||
public UnsafeArray<byte> data;
|
||||
public CommandType type;
|
||||
public Entity entity;
|
||||
public int componentTypeID;
|
||||
public CommandType type;
|
||||
public Identifier<IComponent> componentTypeID;
|
||||
}
|
||||
|
||||
private readonly EntityManager _entityManager;
|
||||
private UnsafeList<Command> _commands; // TODO: Maybe use UnsafeArray<byte> directly?
|
||||
private UnsafeList<Command> _commands; // TODO: Maybe use UnsafeArray<byte> directly to save additional memory allocation in Unsafe<byte> data inside Command struct.
|
||||
private bool _disposed;
|
||||
|
||||
public EntityCommandBuffer(EntityManager entityManager)
|
||||
{
|
||||
_entityManager = entityManager;
|
||||
_commands = new UnsafeList<Command>(32, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
|
||||
_commands = new UnsafeList<Command>(32, Allocator.Persistent);
|
||||
}
|
||||
|
||||
~EntityCommandBuffer()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public void CreateEntity()
|
||||
@@ -44,48 +53,107 @@ public unsafe class EntityCommandBuffer : IDisposable
|
||||
_commands.Add(command);
|
||||
}
|
||||
|
||||
public void DestroyEntity(Entity entity)
|
||||
public void CreateEntity(params ReadOnlySpan<Identifier<IComponent>> componentTypeIDs)
|
||||
{
|
||||
var data = new UnsafeArray<byte>(componentTypeIDs.Length * sizeof(int), Allocator.Temp);
|
||||
MemoryMarshal.Cast<Identifier<IComponent>, byte>(componentTypeIDs).CopyTo(data.AsSpan());
|
||||
|
||||
var command = new Command
|
||||
{
|
||||
type = CommandType.DestroyEntity,
|
||||
data = default,
|
||||
entity = entity,
|
||||
componentTypeID = -1
|
||||
type = CommandType.CreateEntity,
|
||||
data = data,
|
||||
entity = Entity.Invalid,
|
||||
componentTypeID = Identifier<IComponent>.Invalid
|
||||
};
|
||||
|
||||
_commands.Add(command);
|
||||
}
|
||||
|
||||
public void AddComponent<T>(Entity entity, T component)
|
||||
public void DestroyEntity(Entity entity)
|
||||
{
|
||||
_commands.Add(new Command
|
||||
{
|
||||
type = CommandType.DestroyEntity,
|
||||
data = default,
|
||||
entity = entity,
|
||||
componentTypeID = Identifier<IComponent>.Invalid
|
||||
});
|
||||
}
|
||||
|
||||
public void AddComponent<T>(Entity entity, T component = default)
|
||||
where T : unmanaged, IComponent
|
||||
{
|
||||
var data = new UnsafeArray<byte>(sizeof(T), Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
|
||||
MemoryUtility.MemCpy(&component, data.GetUnsafePtr(), (nuint)sizeof(T));
|
||||
var data = new UnsafeArray<byte>(sizeof(T), Allocator.Temp);
|
||||
MemoryUtility.MemCpy(data.GetUnsafePtr(), &component, (nuint)sizeof(T));
|
||||
|
||||
var command = new Command
|
||||
_commands.Add(new Command
|
||||
{
|
||||
type = CommandType.AddComponent,
|
||||
data = data,
|
||||
entity = entity,
|
||||
componentTypeID = ComponentTypeID<T>.value
|
||||
};
|
||||
|
||||
_commands.Add(command);
|
||||
});
|
||||
}
|
||||
|
||||
public void RemoveComponent<T>(Entity entity)
|
||||
where T : unmanaged, IComponent
|
||||
{
|
||||
var command = new Command
|
||||
_commands.Add(new Command
|
||||
{
|
||||
type = CommandType.RemoveComponent,
|
||||
data = default,
|
||||
entity = entity,
|
||||
componentTypeID = ComponentTypeID<T>.value
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
_commands.Add(command);
|
||||
public void SetComponent<T>(Entity entity, T component)
|
||||
where T : unmanaged, IComponent
|
||||
{
|
||||
var data = new UnsafeArray<byte>(sizeof(T), Allocator.Temp);
|
||||
MemoryUtility.MemCpy(data.GetUnsafePtr(), &component, (nuint)sizeof(T));
|
||||
|
||||
_commands.Add(new Command
|
||||
{
|
||||
type = CommandType.SetComponent,
|
||||
data = data,
|
||||
entity = entity,
|
||||
componentTypeID = ComponentTypeID<T>.value
|
||||
});
|
||||
}
|
||||
|
||||
internal void Playback()
|
||||
{
|
||||
foreach (ref var command in _commands)
|
||||
{
|
||||
switch (command.type)
|
||||
{
|
||||
case CommandType.CreateEntity:
|
||||
if (command.data.Count > 0)
|
||||
{
|
||||
_entityManager.CreateEntity(MemoryMarshal.Cast<byte, Identifier<IComponent>>(command.data.AsSpan()));
|
||||
}
|
||||
else
|
||||
{
|
||||
_entityManager.CreateEntity();
|
||||
}
|
||||
break;
|
||||
case CommandType.DestroyEntity:
|
||||
_entityManager.DestroyEntity(command.entity);
|
||||
break;
|
||||
case CommandType.AddComponent:
|
||||
_entityManager.AddComponent(command.entity, command.componentTypeID, command.data.GetUnsafePtr());
|
||||
break;
|
||||
case CommandType.RemoveComponent:
|
||||
_entityManager.RemoveComponent(command.entity, command.componentTypeID);
|
||||
break;
|
||||
case CommandType.SetComponent:
|
||||
_entityManager.SetComponent(command.entity, command.componentTypeID, command.data.GetUnsafePtr());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
@@ -100,11 +168,19 @@ public unsafe class EntityCommandBuffer : IDisposable
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (ref var command in _commands)
|
||||
{
|
||||
command.data.Dispose();
|
||||
}
|
||||
|
||||
_commands.Dispose();
|
||||
|
||||
_disposed = true;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user