Skip to content

Commit

Permalink
component as entitty
Browse files Browse the repository at this point in the history
  • Loading branch information
andreakarasho committed Mar 7, 2024
1 parent f4d6cfd commit 2b63265
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 48 deletions.
6 changes: 4 additions & 2 deletions samples/MyBattleground/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@
e.Enable();
enabled = e.IsEnabled();

ecs.Filter<(Position, Velocity)>()
ecs.Filter<(Position, Velocity, Not<Disabled>)>()
.Query((EntityView entity) => {
Console.WriteLine(entity.Name());
});


ecs.Query((EntityView entity, ref ComponentInfo cmp) => {
Console.WriteLine("cmp {0} size {1}", cmp.ID, cmp.Size);
});

// var e2 = ecs.Entity("Main");
// ref var pp = ref e2.Get<Position>();
Expand Down
12 changes: 6 additions & 6 deletions src/Archetype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public sealed class Archetype

internal Archetype(
World world,
ReadOnlySpan<EcsComponent> components,
ReadOnlySpan<ComponentInfo> components,
ComponentComparer comparer
)
{
Expand Down Expand Up @@ -97,7 +97,7 @@ ComponentComparer comparer

public World World => _world;
public int Count => _count;
public readonly ImmutableArray<EcsComponent> Components;
public readonly ImmutableArray<ComponentInfo> Components;
internal Span<ArchetypeChunk> Chunks => _chunks.AsSpan(0, (_count + CHUNK_THRESHOLD - 1) / CHUNK_THRESHOLD);
internal int EmptyChunks => _chunks.Length - Chunks.Length;

Expand Down Expand Up @@ -127,7 +127,7 @@ public ChunkEnumerator GetEnumerator()
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal int GetComponentIndex(ref readonly EcsComponent cmp)
internal int GetComponentIndex(ref readonly ComponentInfo cmp)
{
return GetComponentIndex(cmp.ID);
}
Expand Down Expand Up @@ -180,8 +180,8 @@ internal EcsID Remove(ref EcsRecord record)

internal Archetype InsertVertex(
Archetype left,
ReadOnlySpan<EcsComponent> components,
ref readonly EcsComponent component
ReadOnlySpan<ComponentInfo> components,
ref readonly ComponentInfo component
)
{
var vertex = new Archetype(left._world, components, _comparer);
Expand Down Expand Up @@ -303,7 +303,7 @@ private void InsertVertex(Archetype newNode)
MakeEdges(newNode, this, Components[i].ID);
}

private bool IsSuperset(ReadOnlySpan<EcsComponent> other)
private bool IsSuperset(ReadOnlySpan<ComponentInfo> other)
{
int i = 0, j = 0;
while (i < Components.Length && j < other.Length)
Expand Down
6 changes: 3 additions & 3 deletions src/Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public ref T Set<T>(EcsID id, T component) where T : struct
return ref Unsafe.As<object, T>(ref objRef);
}

private ref object Set(EcsID id, ref readonly EcsComponent cmp)
private ref object Set(EcsID id, ref readonly ComponentInfo cmp)
{
EcsAssert.Assert(_main.Exists(id));

Expand Down Expand Up @@ -130,7 +130,7 @@ public void Merge()
{
EcsAssert.Assert(_main.Exists(set.Entity));

var cmp = new EcsComponent(set.Component, set.DataLength);
var cmp = new ComponentInfo(set.Component, set.DataLength);

ref var record = ref _main.GetRecord(set.Entity);
var array = _main.Set(_main.Entity(set.Entity), ref record, in cmp);
Expand All @@ -144,7 +144,7 @@ public void Merge()
{
EcsAssert.Assert(_main.Exists(unset.Entity));

var cmp = new EcsComponent(unset.Component, unset.ComponentSize);
var cmp = new ComponentInfo(unset.Component, unset.ComponentSize);
_main.DetachComponent(unset.Entity, ref cmp);
}

Expand Down
4 changes: 2 additions & 2 deletions src/ComponentComparer.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace TinyEcs;

sealed class ComponentComparer : IComparer<ulong>, IComparer<Term>, IComparer<EcsComponent>
sealed class ComponentComparer : IComparer<ulong>, IComparer<Term>, IComparer<ComponentInfo>
{
private readonly World _world;

Expand All @@ -10,7 +10,7 @@ public ComponentComparer(World world)
}


public int Compare(EcsComponent x, EcsComponent y)
public int Compare(ComponentInfo x, ComponentInfo y)
{
return CompareTerms(_world, x.ID, y.ID);
}
Expand Down
6 changes: 2 additions & 4 deletions src/Default.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
namespace TinyEcs;

[DebuggerDisplay("ID: {ID}, Size: {Size}")]
public readonly struct EcsComponent
public readonly struct ComponentInfo
{
public readonly ulong ID;
public readonly int Size;

internal EcsComponent(ulong id, int size)
internal ComponentInfo(ulong id, int size)
{
ID = id;
Size = size;
}
}

public readonly struct EcsDisabled { }
2 changes: 1 addition & 1 deletion src/EntityView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public readonly EntityView Unset<T>() where T : struct
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly ReadOnlySpan<EcsComponent> Type() => World.GetType(ID);
public readonly ReadOnlySpan<ComponentInfo> Type() => World.GetType(ID);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly ref T Get<T>() where T : struct => ref World.Get<T>(ID);
Expand Down
57 changes: 33 additions & 24 deletions src/World.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,33 @@ namespace TinyEcs;

public sealed partial class World : IDisposable
{
const ulong ECS_MAX_COMPONENT_FAST_ID = 256;
const ulong ECS_START_USER_ENTITY_DEFINE = ECS_MAX_COMPONENT_FAST_ID;

private readonly Archetype _archRoot;
private readonly EntitySparseSet<EcsRecord> _entities = new();
private readonly DictionarySlim<ulong, Archetype> _typeIndex = new();
private Archetype[] _archetypes = new Archetype[16];
private int _archetypeCount;
private readonly ComponentComparer _comparer;
private readonly Commands _commands;
private int _frame;
private EcsID _lastCompID = 1;
private readonly EcsID _maxCmpId;

public World()
public World(ulong maxComponentId = 256)
{
_comparer = new ComponentComparer(this);
_archRoot = new Archetype(
this,
ReadOnlySpan<EcsComponent>.Empty,
ReadOnlySpan<ComponentInfo>.Empty,
_comparer
);
_commands = new(this);

//InitializeDefaults();
//_entities.MaxID = ECS_START_USER_ENTITY_DEFINE;
_maxCmpId = maxComponentId;
_entities.MaxID = maxComponentId;

OnPluginInitialization?.Invoke(this);
}

public event Action<EntityView>? OnEntityCreated, OnEntityDeleted;
public event Action<EntityView, EcsComponent>? OnComponentSet, OnComponentUnset;
public event Action<EntityView, ComponentInfo>? OnComponentSet, OnComponentUnset;
public static event Action<World>? OnPluginInitialization;


Expand Down Expand Up @@ -73,10 +69,18 @@ static void InternalOptimize(Archetype root)
}
}

public unsafe ref readonly EcsComponent Component<T>() where T : struct
public ref readonly ComponentInfo Component<T>() where T : struct
{
ref readonly var lookup = ref Lookup.Component<T>.Value;

EcsAssert.Panic(lookup.ID < _maxCmpId);

if (!Exists(lookup.ID))
{
var e = Entity(lookup.ID)
.Set(lookup);
}

// if (lookup.ID == 0 || !Exists(lookup.ID))
// {
// EcsID id = lookup.ID;
Expand Down Expand Up @@ -129,6 +133,11 @@ public unsafe ref readonly EcsComponent Component<T>() where T : struct
// return entity;
// }

public EntityView Entity<T>() where T : struct
{
return Entity(Component<T>().ID);
}

public EntityView Entity(EcsID id = default)
{
return id == 0 || !Exists(id) ? NewEmpty(id) : new(this, id);
Expand Down Expand Up @@ -181,7 +190,7 @@ public bool Exists(EcsID entity)
return _entities.Contains(entity);
}

internal void DetachComponent(EcsID entity, ref readonly EcsComponent cmp)
internal void DetachComponent(EcsID entity, ref readonly ComponentInfo cmp)
{
OnComponentUnset?.Invoke(Entity(entity), cmp);
ref var record = ref GetRecord(entity);
Expand All @@ -190,7 +199,7 @@ internal void DetachComponent(EcsID entity, ref readonly EcsComponent cmp)

private bool InternalAttachDetach(
ref EcsRecord record,
ref readonly EcsComponent cmp,
ref readonly ComponentInfo cmp,
bool add
)
{
Expand All @@ -207,7 +216,7 @@ bool add
}

[SkipLocalsInit]
private Archetype? AttachToArchetype(Archetype root, ref readonly EcsComponent cmp, bool add)
private Archetype? AttachToArchetype(Archetype root, ref readonly ComponentInfo cmp, bool add)
{
if (!add && root.GetComponentIndex(in cmp) < 0)
return null;
Expand All @@ -216,8 +225,8 @@ bool add
var cmpCount = Math.Max(0, initType.Length + (add ? 1 : -1));

const int STACKALLOC_SIZE = 16;
EcsComponent[]? buffer = null;
scoped var span = cmpCount <= STACKALLOC_SIZE ? stackalloc EcsComponent[STACKALLOC_SIZE] : (buffer = ArrayPool<EcsComponent>.Shared.Rent(cmpCount));
ComponentInfo[]? buffer = null;
scoped var span = cmpCount <= STACKALLOC_SIZE ? stackalloc ComponentInfo[STACKALLOC_SIZE] : (buffer = ArrayPool<ComponentInfo>.Shared.Rent(cmpCount));

span = span[..cmpCount];

Expand Down Expand Up @@ -249,12 +258,12 @@ bool add
}

if (buffer != null)
ArrayPool<EcsComponent>.Shared.Return(buffer);
ArrayPool<ComponentInfo>.Shared.Return(buffer);

return arch;
}

private ref Archetype? GetArchetype(Span<EcsComponent> components, bool create)
private ref Archetype? GetArchetype(Span<ComponentInfo> components, bool create)
{
var hash = Hashing.Calculate(components);
ref var arch = ref Unsafe.NullRef<Archetype>();
Expand All @@ -280,7 +289,7 @@ bool add
return ref arch;
}

internal Array? Set(EntityView entity, ref EcsRecord record, ref readonly EcsComponent cmp)
internal Array? Set(EntityView entity, ref EcsRecord record, ref readonly ComponentInfo cmp)
{
var emit = false;
var column = record.Archetype.GetComponentIndex(in cmp);
Expand All @@ -303,13 +312,13 @@ bool add
return array;
}

internal bool Has(EcsID entity, ref readonly EcsComponent cmp)
internal bool Has(EcsID entity, ref readonly ComponentInfo cmp)
{
ref var record = ref GetRecord(entity);
return record.Archetype.GetComponentIndex(in cmp) >= 0;
}

public ReadOnlySpan<EcsComponent> GetType(EcsID id)
public ReadOnlySpan<ComponentInfo> GetType(EcsID id)
{
ref var record = ref GetRecord(id);
return record.Archetype.Components.AsSpan();
Expand Down Expand Up @@ -509,7 +518,7 @@ public QueryInternal Build()

internal static class Hashing
{
public static ulong Calculate(ReadOnlySpan<EcsComponent> components)
public static ulong Calculate(ReadOnlySpan<ComponentInfo> components)
{
var hc = (ulong)components.Length;
foreach (ref readonly var val in components)
Expand Down Expand Up @@ -552,9 +561,9 @@ internal static class Component<T> where T : struct
{
public static readonly int Size = GetSize();
public static readonly string Name = typeof(T).ToString();
public static readonly ulong HashCode = (ulong)System.Threading.Interlocked.Increment(ref Unsafe.As<ulong, int>(ref _index)) - 1;
public static readonly ulong HashCode = (ulong)System.Threading.Interlocked.Increment(ref Unsafe.As<ulong, int>(ref _index)) - 0;

public static readonly EcsComponent Value = new EcsComponent(HashCode, Size);
public static readonly ComponentInfo Value = new ComponentInfo(HashCode, Size);

static Component()
{
Expand Down
2 changes: 1 addition & 1 deletion tests/Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void Merge_Create_Entity()
cmd.Merge();

Assert.True(ctx.World.Exists(e.ID));
Assert.False(ctx.World.Has<EcsDisabled>(e.ID));
Assert.False(ctx.World.Has<Disabled>(e.ID));
}

[Fact]
Expand Down
2 changes: 1 addition & 1 deletion tests/SparseSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public void SparseSet_Add(int amount)
[Fact]
public void SparseSet_Recycle()
{
var set = new EntitySparseSet<EcsComponent>();
var set = new EntitySparseSet<ComponentInfo>();
int count = 1000;
var genCount = 100;
var ids = new List<ulong>();
Expand Down
5 changes: 1 addition & 4 deletions tests/TinyEcs.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,9 @@
</PackageReference>
</ItemGroup>

<ItemGroup>
<Compile Include="../src/TinyEcs.Core/**/*.cs" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\src\TinyEcs.csproj" />
<ProjectReference Include="..\plugins\TinyEcs.Plugins\TinyEcs.Plugins.csproj" />
</ItemGroup>

</Project>

0 comments on commit 2b63265

Please sign in to comment.