This commit is contained in:
Mikhail 2023-04-22 23:40:09 +08:00
parent e2371103c1
commit 22ff801f15
15 changed files with 244 additions and 108 deletions

17
src/Builtin/Components.cs Normal file
View File

@ -0,0 +1,17 @@
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
{
public struct Parent : IEcsAttachComponent
{
public EcsEntity entity;
public EcsEntity Target
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => entity;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set => entity = value;
}
}
}

View File

@ -1,60 +1,83 @@
using System;
using Mono.CompilerServices.SymbolWriter;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using Unity.Profiling;
using UnityEngine;
using UnityEngine.Jobs;
namespace DCFApixels.DragonECS
{
public abstract class EcsJoinQueryBase : EcsQueryBase
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected void ExecuteWhere()
{
var pools = World.GetAllPools();
EcsReadonlyGroup all = World.Entities;
groupFilter.Clear();
foreach (var e in all)
{
int entityID = e.id;
for (int i = 0, iMax = mask.Inc.Length; i < iMax; i++)
{
if (!pools[mask.Inc[i]].Has(entityID))
goto next;
}
for (int i = 0, iMax = mask.Exc.Length; i < iMax; i++)
{
if (pools[mask.Exc[i]].Has(entityID))
goto next;
}
groupFilter.AggressiveAdd(entityID);
next: continue;
}
groupFilter.Sort();
}
public abstract void ExecuteJoin();
}
public abstract class EcsJoinAttachQuery<TAttachComponent> : EcsJoinQueryBase
where TAttachComponent : struct, IEcsAttachComponent
{
private EcsWorld _targetWorld;
private EcsAttachPool<TAttachComponent> _targetPool;
public EcsAttachPool<TAttachComponent> Attach => _targetPool;
private int[] _mapping = Array.Empty<int>();
//private LinkedList<int>
private bool _isInitTargetWorlds = false;
private ProfilerMarker _execute = new ProfilerMarker("EcsJoinAttachQuery.Execute");
protected sealed override void OnBuild(Builder b)
{
_targetPool = b.Include<TAttachComponent>();
}
public sealed override void Execute()
public sealed override void ExecuteWhere()
{
using (_execute.Auto())
ExecuteWhere(_targetPool.Entites, groupFilter);
}
public sealed override void ExecuteJoin()
{
ExecuteWhere(_targetPool.Entites, groupFilter);
if (_isInitTargetWorlds == false) InitTargetWorlds();
if (source.Capacity != _mapping.Length)
_mapping = new int[World.Capacity];
else
ArrayUtility.Fill(_mapping, 0);
foreach (var e in groupFilter)
{
ExecuteWhere();
int entityID = e.id;
}
}
private void InitTargetWorlds()
{
foreach (var e in groupFilter)
{
ref readonly var rel = ref _targetPool.Read(e);
if (rel.Target.IsNotNull)
_targetWorld = EcsWorld.Worlds[rel.Target.world];
if (_targetWorld != null)
{
_isInitTargetWorlds = true;
break;
}
}
}
public EcsGroup.Enumerator GetEnumerator()
{
return groupFilter.GetEnumerator();
}
public NodesEnumrable GetNodes(int entityID)
{
throw new NotImplementedException();
}
}
public abstract class EcsJoinRelationQuery<TRelationComponent> : EcsJoinQueryBase
where TRelationComponent : struct, IEcsRelationComponent
@ -62,22 +85,77 @@ namespace DCFApixels.DragonECS
private EcsWorld _firstWorld;
private EcsWorld _secondWorld;
private EcsRelationPool<TRelationComponent> _targetPool;
public EcsRelationPool<TRelationComponent> Relation => _targetPool;
private bool _isInitTargetWorlds = false;
private ProfilerMarker _execute = new ProfilerMarker("EcsJoinRelationQuery.Execute");
protected sealed override void OnBuild(Builder b)
{
_targetPool = source.GetPool<TRelationComponent>();
_targetPool = b.Include<TRelationComponent>();
}
public sealed override void Execute()
public sealed override void ExecuteWhere()
{
using (_execute.Auto())
ExecuteWhere(_targetPool.Entites, groupFilter);
}
public sealed override void ExecuteJoin()
{
if (_isInitTargetWorlds == false) InitTargetWorlds();
}
private void InitTargetWorlds()
{
foreach (var e in groupFilter)
{
ExecuteWhere();
ref readonly var rel = ref _targetPool.Read(e);
if (rel.First.IsNotNull)
_firstWorld = EcsWorld.Worlds[rel.First.world];
if (rel.Second.IsNotNull)
_secondWorld = EcsWorld.Worlds[rel.Second.world];
if (_firstWorld != null && _secondWorld != null)
{
_isInitTargetWorlds = true;
break;
}
}
}
public EcsGroup.Enumerator GetEnumerator()
{
return groupFilter.GetEnumerator();
}
public NodesEnumrable GetNodes(int entityID)
{
throw new NotImplementedException();
}
}
public readonly ref struct NodesEnumrable
{
private readonly int[] _nodes;
private readonly int _start;
private readonly int _count;
public NodesEnumrable(int[] nodes, int start, int count)
{
_nodes = nodes;
_start = start;
_count = count;
}
public NodesEnumerator GetEnumerator() => new NodesEnumerator(_nodes, _start, _count);
}
public ref struct NodesEnumerator
{
private readonly int[] _nodes;
private readonly int _end;
private int _index;
public NodesEnumerator(int[] nodes, int start, int count)
{
_nodes = nodes;
int end = start + count;
_end = end < _nodes.Length ? end : _nodes.Length;
_index = start;
}
public ent Current => new ent(_nodes[_index]);
public bool MoveNext() => ++_index <= _end;
}
}

View File

@ -15,13 +15,15 @@ namespace DCFApixels.DragonECS
#region Builder
protected virtual void Init(Builder b) { }
protected abstract void OnBuild(Builder b);
public abstract void Execute();
public abstract void ExecuteWhere();
public sealed class Builder : EcsQueryBuilderBase
{
private EcsWorld _world;
private List<int> _inc;
private List<int> _exc;
public EcsWorld World => _world;
private Builder(EcsWorld world)
{
_world = world;
@ -76,36 +78,45 @@ namespace DCFApixels.DragonECS
}
}
#endregion
protected void ExecuteWhere(EcsReadonlyGroup group, EcsGroup result)
{
var pools = World.GetAllPools();
result.Clear();
foreach (var e in group)
{
int entityID = e.id;
for (int i = 0, iMax = mask.Inc.Length; i < iMax; i++)
{
if (!pools[mask.Inc[i]].Has(entityID))
goto next;
}
for (int i = 0, iMax = mask.Exc.Length; i < iMax; i++)
{
if (pools[mask.Exc[i]].Has(entityID))
goto next;
}
result.AggressiveAdd(entityID);
next: continue;
}
result.Sort();
}
protected void ExecuteWhereAndSort(EcsReadonlyGroup group, EcsGroup result)
{
ExecuteWhere(group, result);
result.Sort();
}
}
public abstract class EcsQuery : EcsQueryBase
{
private ProfilerMarker _execute = new ProfilerMarker("EcsQuery.Execute");
private ProfilerMarker _execute = new ProfilerMarker("EcsQuery.ExecuteWhere");
protected sealed override void OnBuild(Builder b) { }
public sealed override void Execute()
public sealed override void ExecuteWhere()
{
using (_execute.Auto())
{
var pools = World.GetAllPools();
EcsReadonlyGroup all = World.Entities;
groupFilter.Clear();
foreach (var e in all)
{
int entityID = e.id;
for (int i = 0, iMax = mask.Inc.Length; i < iMax; i++)
{
if (!pools[mask.Inc[i]].Has(entityID))
goto next;
}
for (int i = 0, iMax = mask.Exc.Length; i < iMax; i++)
{
if (pools[mask.Exc[i]].Has(entityID))
goto next;
}
groupFilter.AggressiveAdd(entityID);
next: continue;
}
groupFilter.Sort();
ExecuteWhereAndSort(World.Entities, groupFilter);
}
}
public EcsGroup.Enumerator GetEnumerator()
@ -125,8 +136,8 @@ namespace DCFApixels.DragonECS
}
public abstract class EcsQueryBuilderBase
{
public abstract TPool Include<TComponent, TPool>() where TComponent : struct where TPool : EcsPoolBase, new();
public abstract TPool Exclude<TComponent, TPool>() where TComponent : struct where TPool : EcsPoolBase, new();
public abstract TPool Optional<TComponent, TPool>() where TComponent : struct where TPool : EcsPoolBase, new();
public abstract TPool Include<TComponent, TPool>() where TComponent : struct where TPool : EcsPoolBase<TComponent>, new();
public abstract TPool Exclude<TComponent, TPool>() where TComponent : struct where TPool : EcsPoolBase<TComponent>, new();
public abstract TPool Optional<TComponent, TPool>() where TComponent : struct where TPool : EcsPoolBase<TComponent>, new();
}
}

View File

@ -121,7 +121,7 @@ namespace DCFApixels.DragonECS
#endregion
#region GetPool
public TPool GetPool<TComponent, TPool>() where TComponent : struct where TPool : EcsPoolBase, new()
public TPool GetPool<TComponent, TPool>() where TComponent : struct where TPool : EcsPoolBase<TComponent>, new()
{
int uniqueID = WorldMetaStorage.GetComponentId<TComponent>(_worldArchetypeID);
@ -149,7 +149,7 @@ namespace DCFApixels.DragonECS
public TQuery Where<TQuery>(out TQuery query) where TQuery : EcsQuery
{
query = Select<TQuery>();
query.Execute();
query.ExecuteWhere();
return query;
}
public TQuery Select<TQuery>() where TQuery : EcsQueryBase

View File

@ -83,6 +83,15 @@ namespace DCFApixels.DragonECS
return this == NULL;
}
}
public bool IsNotNull
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
//using (_IsNullMarker.Auto())
return this != NULL;
}
}
}
public static partial class entExtensions

View File

@ -0,0 +1,15 @@
using System;
namespace DCFApixels.DragonECS
{
[Serializable]
public class EcsRelationException : Exception
{
public EcsRelationException() { }
public EcsRelationException(string message) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message) { }
public EcsRelationException(string message, Exception inner) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message, inner) { }
protected EcsRelationException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
}

View File

@ -1,15 +0,0 @@
using System;
namespace DCFApixels.DragonECS
{
[Serializable]
public class EcsRelationsException : Exception
{
public EcsRelationsException() { }
public EcsRelationsException(string message) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message) { }
public EcsRelationsException(string message, Exception inner) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message, inner) { }
protected EcsRelationsException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
}

View File

@ -15,7 +15,7 @@ namespace DCFApixels.DragonECS
#region Methods
public int GetComponentID<T>();
public TPool GetPool<TComponent, TPool>() where TComponent : struct where TPool : EcsPoolBase, new();
public TPool GetPool<TComponent, TPool>() where TComponent : struct where TPool : EcsPoolBase<TComponent>, new();
public ReadOnlySpan<EcsPoolBase> GetAllPools();
public TQuery Select<TQuery>() where TQuery : EcsQueryBase;
public TQuery Where<TQuery>(out TQuery query) where TQuery : EcsQuery;

View File

@ -1,7 +0,0 @@
namespace DCFApixels.DragonECS
{
public interface INullDummy
{
public bool IsDummy { get; }
}
}

View File

@ -4,7 +4,7 @@ using Unity.Profiling;
namespace DCFApixels.DragonECS
{
public sealed class EcsAttachPool<T> : EcsPoolBase
public sealed class EcsAttachPool<T> : EcsPoolBase<T>
where T : struct, IEcsAttachComponent
{
private EcsWorld _source;
@ -12,18 +12,19 @@ namespace DCFApixels.DragonECS
private bool[] _entityFlags;// index = entityID / value = entityFlag;/ value = 0 = no entityID
private T[] _items; //sparse
private int _count;
private PoolRunners _poolRunners;
private EcsGroup _entities;
public EcsReadonlyGroup Entites => _entities.Readonly;
#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
private int _sanitizeTargetWorld = -1;
private short _sanitizeTargetWorld = -1;
#endif
#region Properites
public int Count => _count;
public int Capacity => _items.Length;
public sealed override EcsWorld World => _source;
public sealed override Type ComponentType => typeof(T);
#endregion
#region Init
@ -49,8 +50,9 @@ namespace DCFApixels.DragonECS
#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
if (_sanitizeTargetWorld >= 0 && target.world != _sanitizeTargetWorld)
{
throw new EcsRelationsException();
throw new EcsRelationException();
}
_sanitizeTargetWorld = target.world;
#endif
// using (_addMark.Auto())
// {
@ -59,6 +61,7 @@ namespace DCFApixels.DragonECS
{
entityFlag = true;
_count++;
_entities.Add(entityID);
_poolRunners.add.OnComponentAdd<T>(entityID);
}
_poolRunners.write.OnComponentWrite<T>(entityID);
@ -71,8 +74,9 @@ namespace DCFApixels.DragonECS
#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
if (_sanitizeTargetWorld >= 0 && target.world != _sanitizeTargetWorld)
{
throw new EcsRelationsException();
throw new EcsRelationException();
}
_sanitizeTargetWorld = target.world;
#endif
// using (_writeMark.Auto())
_poolRunners.write.OnComponentWrite<T>(entityID);
@ -94,6 +98,7 @@ namespace DCFApixels.DragonECS
{
// using (_delMark.Auto())
// {
_entities.Remove(entityID);
_entityFlags[entityID] = false;
_count--;
_poolRunners.del.OnComponentDel<T>(entityID);

View File

@ -4,7 +4,7 @@ using Unity.Profiling;
namespace DCFApixels.DragonECS
{
public sealed class EcsNotNullPool<T> : EcsPoolBase
public sealed class EcsNotNullPool<T> : EcsPoolBase<T>
where T : struct, INotNullComponent
{
private EcsWorld _source;
@ -19,7 +19,6 @@ namespace DCFApixels.DragonECS
public int Count => _count;
public int Capacity => _items.Length;
public sealed override EcsWorld World => _source;
public sealed override Type ComponentType => typeof(T);
#endregion
#region Init

View File

@ -1,4 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Unity.Profiling;
@ -25,6 +28,15 @@ namespace DCFApixels.DragonECS
internal void InvokeOnDestroy() => OnDestroy();
#endregion
}
public abstract class EcsPoolBase<T> : EcsPoolBase, IEnumerable<T>
{
public sealed override Type ComponentType => typeof(T);
//Ðåëàçèàöèÿ èíòåðôåéñà IEnumerator íå ðàáîòàåò, íóæíî òîëüêî ÷òîáû IntelliSense ïðåäëàãàëà íàçâàíèÿ íà îñíîâå T. Íå íàøåë äðóãîãî ñïîñîáà
#region IEnumerable
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
#endregion
}
public struct NullComponent { }
public sealed class EcsNullPool : EcsPoolBase
@ -48,10 +60,11 @@ namespace DCFApixels.DragonECS
protected override void OnDestroy() { }
#endregion
}
public sealed class EcsPool<T> : EcsPoolBase
public sealed class EcsPool<T> : EcsPoolBase<T>
where T : struct, IEcsComponent
{
public static string name = typeof(T).Name;
private EcsWorld _source;
private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
@ -67,7 +80,6 @@ namespace DCFApixels.DragonECS
public int Count => _itemsCount;
public int Capacity => _items.Length;
public sealed override EcsWorld World => _source;
public sealed override Type ComponentType => typeof(T);
#endregion
#region Init
@ -160,6 +172,7 @@ namespace DCFApixels.DragonECS
Array.Resize(ref _mapping, newSize);
}
protected override void OnDestroy() { }
#endregion
}

View File

@ -1,10 +1,11 @@
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Unity.Profiling;
namespace DCFApixels.DragonECS
{
public sealed class EcsRelationPool<T> : EcsPoolBase
public sealed class EcsRelationPool<T> : EcsPoolBase<T>
where T : struct, IEcsRelationComponent
{
private EcsWorld _source;
@ -12,19 +13,20 @@ namespace DCFApixels.DragonECS
private bool[] _entityFlags;// index = entityID / value = entityFlag;/ value = 0 = no entityID
private T[] _items; //sparse
private int _count;
private PoolRunners _poolRunners;
private EcsGroup _entities;
public EcsReadonlyGroup Entites => _entities.Readonly;
#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
private int _sanitizeFirstWorld = -1;
private int _sanitizeSecondWorld = -1;
private short _sanitizeFirstWorld = -1;
private short _sanitizeSecondWorld = -1;
#endif
#region Properites
public int Count => _count;
public int Capacity => _items.Length;
public sealed override EcsWorld World => _source;
public sealed override Type ComponentType => typeof(T);
#endregion
#region Init
@ -51,7 +53,7 @@ namespace DCFApixels.DragonECS
if((_sanitizeFirstWorld >= 0 && first.world != _sanitizeFirstWorld) &&
(_sanitizeSecondWorld >= 0 && second.world != _sanitizeSecondWorld))
{
throw new EcsRelationsException();
throw new EcsRelationException();
}
#endif
// using (_addMark.Auto())
@ -61,6 +63,7 @@ namespace DCFApixels.DragonECS
{
entityFlag = true;
_count++;
_entities.Add(entityID);
_poolRunners.add.OnComponentAdd<T>(entityID);
}
_poolRunners.write.OnComponentWrite<T>(entityID);
@ -74,8 +77,10 @@ namespace DCFApixels.DragonECS
if ((_sanitizeFirstWorld >= 0 && first.world != _sanitizeFirstWorld) &&
(_sanitizeSecondWorld >= 0 && second.world != _sanitizeSecondWorld))
{
throw new EcsRelationsException();
throw new EcsRelationException();
}
_sanitizeFirstWorld = first.world;
_sanitizeSecondWorld = second.world;
#endif
// using (_writeMark.Auto())
//{
@ -99,6 +104,7 @@ namespace DCFApixels.DragonECS
{
// using (_delMark.Auto())
// {
_entities.Remove(entityID);
_entityFlags[entityID] = false;
_count--;
_poolRunners.del.OnComponentDel<T>(entityID);
@ -120,7 +126,14 @@ namespace DCFApixels.DragonECS
{
public EcsEntity First { get; set; }
public EcsEntity Second { get; set; }
public void Set(EcsEntity first, EcsEntity second);
}
public static class IEcsRelationComponentExt
{
public static void Set<T>(this ref T self, EcsEntity first, EcsEntity second) where T : struct, IEcsRelationComponent
{
self.First = first;
self.Second = second;
}
}
public static class EcsRelationPoolExt
{

View File

@ -4,7 +4,7 @@ using Unity.Profiling;
namespace DCFApixels.DragonECS
{
public sealed class EcsSinglePool<T> : EcsPoolBase
public sealed class EcsSinglePool<T> : EcsPoolBase<T>
where T : struct, IEcsSingleComponent
{
private EcsWorld _source;
@ -23,7 +23,6 @@ namespace DCFApixels.DragonECS
#region Properites
public int Count => _count;
public sealed override EcsWorld World => _source;
public sealed override Type ComponentType => typeof(T);
#endregion
#region Init

View File

@ -4,7 +4,7 @@ using Unity.Profiling;
namespace DCFApixels.DragonECS
{
public sealed class EcsTagPool<T> : EcsPoolBase
public sealed class EcsTagPool<T> : EcsPoolBase<T>
where T : struct, IEcsTagComponent
{
private EcsWorld _source;
@ -17,7 +17,6 @@ namespace DCFApixels.DragonECS
#region Properites
public int Count => _count;
public sealed override EcsWorld World => _source;
public sealed override Type ComponentType => typeof(T);
#endregion
#region Init