misc fixes
parent
001b6714cc
commit
8774314f62
|
@ -9,7 +9,10 @@ internal class Archetype
|
|||
public ArchetypeSignature Signature;
|
||||
public NativeArray<Entity> Entities = new NativeArray<Entity>();
|
||||
|
||||
public SortedDictionary<TypeId, ArchetypeEdge> Edges = new SortedDictionary<TypeId, ArchetypeEdge>();
|
||||
public SortedDictionary<TypeId, Archetype> AddEdges =
|
||||
new SortedDictionary<TypeId, Archetype>();
|
||||
public SortedDictionary<TypeId, Archetype> RemoveEdges =
|
||||
new SortedDictionary<TypeId, Archetype>();
|
||||
|
||||
public int Count => Entities.Count;
|
||||
|
||||
|
@ -25,13 +28,6 @@ internal class Archetype
|
|||
return Entities.Count - 1;
|
||||
}
|
||||
|
||||
public int Transfer(int row, Archetype transferTo)
|
||||
{
|
||||
var newIndex = transferTo.Append(Entities[row]);
|
||||
Entities.Delete(row);
|
||||
return newIndex;
|
||||
}
|
||||
|
||||
public void ClearAll()
|
||||
{
|
||||
for (int i = Entities.Count - 1; i >= 0; i -= 1)
|
||||
|
|
|
@ -41,7 +41,7 @@ internal class ArchetypeSignature : IEquatable<ArchetypeSignature>
|
|||
|
||||
public void CopyTo(ArchetypeSignature other)
|
||||
{
|
||||
foreach (var id in other.Ids.AsSpan())
|
||||
foreach (var id in Ids.AsSpan())
|
||||
{
|
||||
other.Ids.Add(id);
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ public unsafe class NativeArray<T> : IDisposable where T : unmanaged
|
|||
// Fills gap by copying final element to the deleted index
|
||||
public void Delete(int index)
|
||||
{
|
||||
if (Count > 1)
|
||||
if (index != Count - 1)
|
||||
{
|
||||
NativeMemory.Copy(
|
||||
(void*) (Elements + ((Count - 1) * ElementSize)),
|
||||
|
|
|
@ -53,7 +53,7 @@ internal unsafe class NativeArray : IDisposable
|
|||
// Fills gap by copying final element to the deleted index
|
||||
public void Delete(int index)
|
||||
{
|
||||
if (Count > 1)
|
||||
if (index != Count - 1)
|
||||
{
|
||||
NativeMemory.Copy(
|
||||
(void*) (Elements + ((Count - 1) * ElementSize)),
|
||||
|
|
|
@ -30,7 +30,6 @@ namespace MoonTools.ECS
|
|||
|
||||
public ref T Get<T>(in Entity entity) where T : unmanaged
|
||||
{
|
||||
|
||||
return ref Components.Get<T>(EntityIDToStorageIndex[entity]);
|
||||
}
|
||||
|
||||
|
|
|
@ -59,17 +59,14 @@ public class Filter
|
|||
// WARNING: this WILL crash if the index is out of range!
|
||||
public Entity NthEntity(int index)
|
||||
{
|
||||
var count = 0;
|
||||
|
||||
foreach (var archetype in Archetypes)
|
||||
{
|
||||
count += archetype.Count;
|
||||
if (index < count)
|
||||
if (index < archetype.Count)
|
||||
{
|
||||
return archetype.Entities[index];
|
||||
}
|
||||
|
||||
index -= count;
|
||||
index -= archetype.Count;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Filter index out of range!");
|
||||
|
@ -135,12 +132,12 @@ public class Filter
|
|||
|
||||
// breadth-first search
|
||||
// ignore excluded component edges
|
||||
foreach (var (componentId, edge) in current.Edges)
|
||||
foreach (var (componentId, edge) in current.AddEdges)
|
||||
{
|
||||
if (!Explored.Contains(edge.Add) && !filter.Excluded.Contains(componentId))
|
||||
if (!filter.Excluded.Contains(componentId))
|
||||
{
|
||||
Explored.Add(edge.Add);
|
||||
ArchetypeSearchQueue.Enqueue(edge.Add);
|
||||
Explored.Add(edge);
|
||||
ArchetypeSearchQueue.Enqueue(edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,4 +2,10 @@ using System;
|
|||
|
||||
namespace MoonTools.ECS;
|
||||
|
||||
public readonly record struct TypeId(uint Value);
|
||||
public readonly record struct TypeId(uint Value) : IComparable<TypeId>
|
||||
{
|
||||
public int CompareTo(TypeId other)
|
||||
{
|
||||
return Value.CompareTo(other.Value);
|
||||
}
|
||||
}
|
||||
|
|
83
src/World.cs
83
src/World.cs
|
@ -90,6 +90,14 @@ namespace MoonTools.ECS
|
|||
var entity = new Entity(EntityIdAssigner.Assign());
|
||||
EntityIndex.Add(entity, new ArchetypeRecord(EmptyArchetype, EmptyArchetype.Count));
|
||||
EmptyArchetype.Append(entity);
|
||||
|
||||
if (!EntityRelationIndex.ContainsKey(entity))
|
||||
{
|
||||
EntityRelationIndex.Add(entity, new IndexableSet<TypeId>());
|
||||
}
|
||||
|
||||
EntityTags[entity] = tag;
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
@ -177,7 +185,7 @@ namespace MoonTools.ECS
|
|||
|
||||
if (!componentStorage.Set(entity, component))
|
||||
{
|
||||
UpdateArchetype<T>(entity, true);
|
||||
TransferArchetype(entity, FindArchetypeByAdd<T>(entity));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,48 +195,79 @@ namespace MoonTools.ECS
|
|||
|
||||
if (componentStorage.Remove(entity))
|
||||
{
|
||||
UpdateArchetype<T>(entity, false);
|
||||
TransferArchetype(entity, FindArchetypeByRemove<T>(entity));
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateArchetype<T>(in Entity entity, bool insert)
|
||||
private Archetype FindArchetypeByAdd<T>(in Entity entity)
|
||||
{
|
||||
Archetype? nextArchetype;
|
||||
|
||||
var componentTypeId = TypeToId[typeof(T)];
|
||||
var record = EntityIndex[entity];
|
||||
var archetype = record.Archetype;
|
||||
|
||||
if (archetype.Edges.TryGetValue(TypeToId[typeof(T)], out var edge))
|
||||
if (archetype.AddEdges.TryGetValue(componentTypeId, out var nextArchetype))
|
||||
{
|
||||
nextArchetype = insert ? edge.Add : edge.Remove;
|
||||
return nextArchetype;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
var nextSignature = new ArchetypeSignature(archetype.Signature.Count + 1);
|
||||
archetype.Signature.CopyTo(nextSignature);
|
||||
|
||||
if (insert)
|
||||
{
|
||||
nextSignature.Insert(componentTypeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextSignature.Remove(componentTypeId);
|
||||
}
|
||||
|
||||
if (!ArchetypeIndex.TryGetValue(nextSignature, out nextArchetype))
|
||||
{
|
||||
nextArchetype = CreateArchetype(nextSignature);
|
||||
}
|
||||
|
||||
var newEdge = new ArchetypeEdge(nextArchetype, archetype);
|
||||
archetype.Edges.Add(componentTypeId, newEdge);
|
||||
nextArchetype.Edges.Add(componentTypeId, newEdge);
|
||||
archetype.AddEdges.Add(componentTypeId, nextArchetype);
|
||||
nextArchetype.RemoveEdges.Add(componentTypeId, archetype);
|
||||
|
||||
return nextArchetype;
|
||||
}
|
||||
|
||||
var newRow = archetype.Transfer(record.Row, nextArchetype);
|
||||
EntityIndex[entity] = new ArchetypeRecord(nextArchetype, newRow);
|
||||
private Archetype FindArchetypeByRemove<T>(in Entity entity)
|
||||
{
|
||||
var componentTypeId = TypeToId[typeof(T)];
|
||||
var record = EntityIndex[entity];
|
||||
var archetype = record.Archetype;
|
||||
|
||||
if (archetype.RemoveEdges.TryGetValue(componentTypeId, out var nextArchetype))
|
||||
{
|
||||
return nextArchetype;
|
||||
}
|
||||
|
||||
var nextSignature = new ArchetypeSignature(archetype.Signature.Count + 1);
|
||||
archetype.Signature.CopyTo(nextSignature);
|
||||
nextSignature.Remove(componentTypeId);
|
||||
|
||||
if (!ArchetypeIndex.TryGetValue(nextSignature, out nextArchetype))
|
||||
{
|
||||
nextArchetype = CreateArchetype(nextSignature);
|
||||
}
|
||||
|
||||
archetype.RemoveEdges.Add(componentTypeId, nextArchetype);
|
||||
nextArchetype.AddEdges.Add(componentTypeId, archetype);
|
||||
|
||||
return nextArchetype;
|
||||
}
|
||||
|
||||
private void TransferArchetype(in Entity entity, Archetype nextArchetype)
|
||||
{
|
||||
var record = EntityIndex[entity];
|
||||
var archetype = record.Archetype;
|
||||
var row = record.Row;
|
||||
|
||||
// fill the gap
|
||||
if (row != archetype.Count - 1)
|
||||
{
|
||||
var lastEntity = archetype.Entities[archetype.Count - 1];
|
||||
archetype.Entities[row] = lastEntity;
|
||||
EntityIndex[lastEntity] = new ArchetypeRecord(archetype, row);
|
||||
}
|
||||
|
||||
archetype.Entities.RemoveLastElement();
|
||||
nextArchetype.Entities.Append(entity);
|
||||
EntityIndex[entity] = new ArchetypeRecord(nextArchetype, nextArchetype.Count - 1);
|
||||
}
|
||||
|
||||
// RELATIONS
|
||||
|
|
Loading…
Reference in New Issue