mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 09:54:35 +08:00
update
This commit is contained in:
parent
7ef556556b
commit
5d6c095142
@ -30,6 +30,13 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
void Run();
|
||||
}
|
||||
[MetaName(nameof(RunFinally))]
|
||||
[MetaColor(MetaColor.DragonRose)]
|
||||
[MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.PROCESSES_GROUP)]
|
||||
public interface IEcsRunFinally : IEcsProcess
|
||||
{
|
||||
void RunFinally();
|
||||
}
|
||||
[MetaName(nameof(Destroy))]
|
||||
[MetaColor(MetaColor.DragonRose)]
|
||||
[MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.PROCESSES_GROUP)]
|
||||
@ -97,26 +104,45 @@ namespace DCFApixels.DragonECS.Internal
|
||||
[MetaID("2098527C9201F260C840BFD50BC7E0BA")]
|
||||
internal sealed class EcsRunRunner : EcsRunner<IEcsRun>, IEcsRun
|
||||
{
|
||||
private readonly struct Pair
|
||||
{
|
||||
public readonly IEcsRun run;
|
||||
public readonly IEcsRunFinally cleanup;
|
||||
public Pair(IEcsRun run)
|
||||
{
|
||||
this.run = run;
|
||||
cleanup = run as IEcsRunFinally;
|
||||
}
|
||||
}
|
||||
private Pair[] _pairs;
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
private EcsProfilerMarker[] _markers;
|
||||
#endif
|
||||
protected override void OnSetup()
|
||||
{
|
||||
_pairs = new Pair[Process.Length];
|
||||
for (int i = 0; i < Process.Length; i++)
|
||||
{
|
||||
_pairs[i] = new Pair(Process[i]);
|
||||
}
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
_markers = new EcsProfilerMarker[Process.Length];
|
||||
for (int i = 0; i < Process.Length; i++)
|
||||
{
|
||||
_markers[i] = new EcsProfilerMarker($"{Process[i].GetMeta().Name}.{nameof(Run)}");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
public void Run()
|
||||
{
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
for (int i = 0, n = Process.Length < _markers.Length ? Process.Length : _markers.Length; i < n; i++)
|
||||
for (int i = 0, n = _pairs.Length < _markers.Length ? _pairs.Length : _markers.Length; i < n; i++)
|
||||
{
|
||||
var pair = _pairs[i];
|
||||
_markers[i].Begin();
|
||||
try
|
||||
{
|
||||
Process[i].Run();
|
||||
pair.run.Run();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -125,6 +151,10 @@ namespace DCFApixels.DragonECS.Internal
|
||||
#endif
|
||||
EcsDebug.PrintError(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
pair.cleanup?.RunFinally();
|
||||
}
|
||||
_markers[i].End();
|
||||
}
|
||||
#else
|
||||
|
@ -25,7 +25,63 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
public static implicit operator Singleton<T>(SingletonMarker a) { return new Singleton<T>(a.Builder.World.ID); }
|
||||
}
|
||||
public abstract class EcsAspect : ITemplateNode, IComponentMask
|
||||
public interface IEcsAspect
|
||||
{
|
||||
EcsMask Mask { get; set; }
|
||||
}
|
||||
|
||||
#region IEcsAspectExtensions tmp
|
||||
// public static class IEcsAspectExtensions
|
||||
// {
|
||||
// public static void Apply(this IEcsAspect aspect, short worldID, int entityID)
|
||||
// {
|
||||
// EcsWorld world = EcsWorld.GetWorld(worldID);
|
||||
// EcsMask mask = aspect.Mask;
|
||||
// foreach (var incTypeID in mask._incs)
|
||||
// {
|
||||
// var pool = world.FindPoolInstance(incTypeID);
|
||||
// if (pool != null)
|
||||
// {
|
||||
// if (pool.Has(entityID) == false)
|
||||
// {
|
||||
// pool.AddEmpty(entityID);
|
||||
// }
|
||||
// }
|
||||
//#if DEBUG
|
||||
// else
|
||||
// {
|
||||
// EcsDebug.PrintWarning("Component has not been added because the pool has not been initialized yet.");
|
||||
// }
|
||||
//#endif
|
||||
// }
|
||||
// foreach (var excTypeID in mask._excs)
|
||||
// {
|
||||
// var pool = world.FindPoolInstance(excTypeID);
|
||||
// if (pool != null && pool.Has(entityID))
|
||||
// {
|
||||
// pool.Del(entityID);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
#endregion
|
||||
|
||||
public static partial class API
|
||||
{
|
||||
public static IncludeMarker Inc
|
||||
{
|
||||
get { return EcsAspect.CurrentBuilder.Inc; }
|
||||
}
|
||||
public static ExcludeMarker Exc
|
||||
{
|
||||
get { return EcsAspect.CurrentBuilder.Exc; }
|
||||
}
|
||||
public static OptionalMarker Opt
|
||||
{
|
||||
get { return EcsAspect.CurrentBuilder.Opt; }
|
||||
}
|
||||
}
|
||||
public abstract class EcsAspect : IEcsAspect, ITemplateNode, IComponentMask
|
||||
{
|
||||
#region Initialization Halpers
|
||||
[ThreadStatic]
|
||||
@ -43,7 +99,7 @@ namespace DCFApixels.DragonECS
|
||||
return _constructorBuildersStack[_constructorBuildersStackIndex];
|
||||
}
|
||||
}
|
||||
protected static Builder CurrentBuilder
|
||||
public static Builder CurrentBuilder
|
||||
{
|
||||
get { return B; }
|
||||
}
|
||||
@ -77,6 +133,7 @@ namespace DCFApixels.DragonECS
|
||||
public EcsMask Mask
|
||||
{
|
||||
get { return _mask; }
|
||||
set { }
|
||||
}
|
||||
public EcsWorld World
|
||||
{
|
||||
@ -138,7 +195,8 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region Constructors/New
|
||||
private Builder() { }
|
||||
internal static unsafe TAspect New<TAspect>(EcsWorld world) where TAspect : EcsAspect, new()
|
||||
|
||||
internal static unsafe (TAspect aspect, EcsMask mask) New<TAspect>(EcsWorld world) where TAspect : new()
|
||||
{
|
||||
//Get Builder
|
||||
if (_constructorBuildersStack == null)
|
||||
@ -168,26 +226,34 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
//Building
|
||||
TAspect newAspect = new TAspect();
|
||||
newAspect._source = world;
|
||||
newAspect.Init(builder);
|
||||
EcsAspect builtinAspect = newAspect as EcsAspect;
|
||||
if(builtinAspect != null)
|
||||
{
|
||||
builtinAspect._source = world;
|
||||
builtinAspect.Init(builder);
|
||||
}
|
||||
|
||||
//Build Mask
|
||||
if (staticMask == null)
|
||||
{
|
||||
staticMask = builder._maskBuilder.Build();
|
||||
builder._maskBuilder = default;
|
||||
if (newAspect.IsStaticInitialization)
|
||||
if (builtinAspect == null || builtinAspect.IsStaticInitialization)
|
||||
{
|
||||
_staticMaskCache.Add(typeof(TAspect), staticMask);
|
||||
}
|
||||
}
|
||||
newAspect._mask = staticMask.ToMask(world);
|
||||
EcsMask mask = staticMask.ToMask(world);
|
||||
if(builtinAspect != null)
|
||||
{
|
||||
builtinAspect._mask = mask;
|
||||
//var pools = new IEcsPool[builder._poolsBufferCount];
|
||||
//Array.Copy(builder._poolsBuffer, pools, pools.Length);
|
||||
newAspect._isBuilt = true;
|
||||
builtinAspect._isBuilt = true;
|
||||
}
|
||||
|
||||
_constructorBuildersStackIndex--;
|
||||
return newAspect;
|
||||
return (newAspect, mask);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -386,7 +452,9 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
namespace DCFApixels.DragonECS.Core
|
||||
{
|
||||
#region Constraint Markers
|
||||
public readonly ref struct IncludeMarker
|
||||
{
|
||||
|
@ -214,7 +214,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
case IEcsProcess system: return AddSystem_Internal(system, settedAddParams);
|
||||
case IEcsModule module: return AddModule_Internal(module, settedAddParams);
|
||||
default: Throw.ArgumentException("Unsupported type"); return this;
|
||||
default: Throw.ArgumentException($"{raw.GetMeta().TypeName} Unsupported type"); return this;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
@ -68,7 +68,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
get { return _isInit; }
|
||||
}
|
||||
public bool IsDestoryed
|
||||
public bool IsDestroyed
|
||||
{
|
||||
get { return _isDestoryed; }
|
||||
}
|
||||
@ -250,7 +250,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
public static bool IsNullOrDestroyed(this EcsPipeline self)
|
||||
{
|
||||
return self == null || self.IsDestoryed;
|
||||
return self == null || self.IsDestroyed;
|
||||
}
|
||||
public static EcsPipeline.Builder Add(this EcsPipeline.Builder self, IEnumerable<IEcsProcess> range, string layerName = null)
|
||||
{
|
||||
|
333
src/EcsRunner.cs
333
src/EcsRunner.cs
@ -4,6 +4,7 @@ using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using static DCFApixels.DragonECS.EcsDebugUtility;
|
||||
#pragma warning disable CS0162 // Обнаружен недостижимый код
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
@ -16,6 +17,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
namespace RunnersCore
|
||||
{
|
||||
//добавить инъекцию в раннеры
|
||||
public abstract class EcsRunner
|
||||
{
|
||||
internal abstract void Init_Internal(EcsPipeline source);
|
||||
@ -57,6 +59,8 @@ namespace DCFApixels.DragonECS
|
||||
#endif
|
||||
}
|
||||
#endregion
|
||||
|
||||
public delegate void ActionWithData<in TProcess, T>(TProcess process, ref T Data);
|
||||
}
|
||||
|
||||
[MetaColor(MetaColor.DragonRose)]
|
||||
@ -124,7 +128,12 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region RunHelper
|
||||
public struct RunHelper
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
public
|
||||
#else
|
||||
public readonly
|
||||
#endif
|
||||
struct RunHelper
|
||||
{
|
||||
private readonly EcsProcess<TProcess> _process;
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
@ -182,7 +191,6 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region Do
|
||||
#pragma warning disable CS0162 // Обнаружен недостижимый код
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Run(Action<TProcess> translationCallback)
|
||||
{
|
||||
@ -223,7 +231,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Run<T0>(Action<TProcess, T0> translationCallback, T0 t0)
|
||||
public void Run<TData>(ActionWithData<TProcess, TData> translationCallback, ref TData data)
|
||||
{
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
CheckCache(translationCallback);
|
||||
@ -232,7 +240,7 @@ namespace DCFApixels.DragonECS
|
||||
_markers[i].Begin();
|
||||
try
|
||||
{
|
||||
translationCallback(_process[i], t0);
|
||||
translationCallback(_process[i], ref data);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -248,7 +256,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
try
|
||||
{
|
||||
translationCallback(item, t0);
|
||||
translationCallback(item, ref data);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -260,128 +268,205 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Run<T0, T1>(Action<TProcess, T0, T1> translationCallback, T0 t0, T1 t1)
|
||||
{
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
CheckCache(translationCallback);
|
||||
for (int i = 0, n = _process.Length < _markers.Length ? _process.Length : _markers.Length; i < n; i++)
|
||||
{
|
||||
_markers[i].Begin();
|
||||
try
|
||||
{
|
||||
translationCallback(_process[i], t0, t1);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DISABLE_CATH_EXCEPTIONS
|
||||
throw;
|
||||
#endif
|
||||
EcsDebug.PrintError(e);
|
||||
}
|
||||
_markers[i].End();
|
||||
}
|
||||
#else
|
||||
foreach (var item in _process)
|
||||
{
|
||||
try
|
||||
{
|
||||
translationCallback(item, t0, t1);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DISABLE_CATH_EXCEPTIONS
|
||||
throw;
|
||||
#endif
|
||||
EcsDebug.PrintError(e);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Run<T0, T1, T2>(Action<TProcess, T0, T1, T2> translationCallback, T0 t0, T1 t1, T2 t2)
|
||||
{
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
CheckCache(translationCallback);
|
||||
for (int i = 0, n = _process.Length < _markers.Length ? _process.Length : _markers.Length; i < n; i++)
|
||||
{
|
||||
_markers[i].Begin();
|
||||
try
|
||||
{
|
||||
translationCallback(_process[i], t0, t1, t2);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DISABLE_CATH_EXCEPTIONS
|
||||
throw;
|
||||
#endif
|
||||
EcsDebug.PrintError(e);
|
||||
}
|
||||
_markers[i].End();
|
||||
}
|
||||
#else
|
||||
foreach (var item in _process)
|
||||
{
|
||||
try
|
||||
{
|
||||
translationCallback(item, t0, t1, t2);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DISABLE_CATH_EXCEPTIONS
|
||||
throw;
|
||||
#endif
|
||||
EcsDebug.PrintError(e);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Run<T0, T1, T2, T3>(Action<TProcess, T0, T1, T2, T3> translationCallback, T0 t0, T1 t1, T2 t2, T3 t3)
|
||||
{
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
CheckCache(translationCallback);
|
||||
for (int i = 0, n = _process.Length < _markers.Length ? _process.Length : _markers.Length; i < n; i++)
|
||||
{
|
||||
_markers[i].Begin();
|
||||
try
|
||||
{
|
||||
translationCallback(_process[i], t0, t1, t2, t3);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DISABLE_CATH_EXCEPTIONS
|
||||
throw;
|
||||
#endif
|
||||
EcsDebug.PrintError(e);
|
||||
}
|
||||
_markers[i].End();
|
||||
}
|
||||
#else
|
||||
foreach (var item in _process)
|
||||
{
|
||||
try
|
||||
{
|
||||
translationCallback(item, t0, t1, t2, t3);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DISABLE_CATH_EXCEPTIONS
|
||||
throw;
|
||||
#endif
|
||||
EcsDebug.PrintError(e);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#pragma warning restore CS0162 // Обнаружен недостижимый код
|
||||
//------------------------
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RunHelperWithFinally
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
public
|
||||
#else
|
||||
public readonly
|
||||
#endif
|
||||
struct RunHelperWithFinally<TProcessFinally> where TProcessFinally : class, IEcsProcess
|
||||
{
|
||||
private readonly Pair[] _pairs;
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
private Delegate _cacheCheck;
|
||||
private Delegate _cacheCheckF;
|
||||
private bool _cacheCheckInit;
|
||||
private readonly EcsProfilerMarker[] _markers;
|
||||
#endif
|
||||
|
||||
#region Constructors
|
||||
public RunHelperWithFinally(EcsRunner<TProcess> runner) : this(runner,
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
typeof(TProcess).ToMeta().Name)
|
||||
#else
|
||||
string.Empty)
|
||||
#endif
|
||||
{ }
|
||||
|
||||
public RunHelperWithFinally(EcsRunner<TProcess> runner, string methodName)
|
||||
{
|
||||
_pairs = new Pair[runner.Process.Length];
|
||||
for (int i = 0; i < runner.Process.Length; i++)
|
||||
{
|
||||
_pairs[i] = new Pair(runner.Process[i]);
|
||||
}
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
_cacheCheck = null;
|
||||
_cacheCheckF = null;
|
||||
_cacheCheckInit = false;
|
||||
_markers = new EcsProfilerMarker[_pairs.Length];
|
||||
for (int i = 0; i < _pairs.Length; i++)
|
||||
{
|
||||
_markers[i] = new EcsProfilerMarker($"{_pairs[i].run.GetMeta().Name}.{methodName}");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Utils
|
||||
private readonly struct Pair
|
||||
{
|
||||
public readonly TProcess run;
|
||||
public readonly TProcessFinally runFinally;
|
||||
public Pair(TProcess run)
|
||||
{
|
||||
this.run = run;
|
||||
runFinally = run as TProcessFinally;
|
||||
}
|
||||
}
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void CheckCache(Delegate d, Delegate df)
|
||||
{
|
||||
if (_cacheCheckInit == false)
|
||||
{
|
||||
if (_cacheCheck == null)
|
||||
{
|
||||
_cacheCheck = d;
|
||||
_cacheCheckF = df;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ReferenceEquals(_cacheCheck, d) == false || ReferenceEquals(_cacheCheckF, df) == false)
|
||||
{
|
||||
EcsDebug.PrintWarning("The delegate is not cached");
|
||||
}
|
||||
_cacheCheckInit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
#region Do
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Run(
|
||||
Action<TProcess> translationCallback,
|
||||
Action<TProcessFinally> translationFinnalyCallback)
|
||||
{
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
CheckCache(translationCallback, translationFinnalyCallback);
|
||||
for (int i = 0, n = _pairs.Length < _markers.Length ? _pairs.Length : _markers.Length; i < n; i++)
|
||||
{
|
||||
var pair = _pairs[i];
|
||||
_markers[i].Begin();
|
||||
try
|
||||
{
|
||||
translationCallback(pair.run);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DISABLE_CATH_EXCEPTIONS
|
||||
throw;
|
||||
#endif
|
||||
EcsDebug.PrintError(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(pair.runFinally != null)
|
||||
{
|
||||
translationFinnalyCallback(pair.runFinally);
|
||||
}
|
||||
}
|
||||
_markers[i].End();
|
||||
}
|
||||
#else
|
||||
foreach (var item in _pairs)
|
||||
{
|
||||
try
|
||||
{
|
||||
translationCallback(item.run);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DISABLE_CATH_EXCEPTIONS
|
||||
throw;
|
||||
#endif
|
||||
EcsDebug.PrintError(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
translationFinnalyCallback(item.runFinally);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Run<TData>(
|
||||
ActionWithData<TProcess, TData> translationCallback,
|
||||
ActionWithData<TProcessFinally, TData> translationFinnalyCallback,
|
||||
ref TData data)
|
||||
{
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
CheckCache(translationCallback, translationFinnalyCallback);
|
||||
for (int i = 0, n = _pairs.Length < _markers.Length ? _pairs.Length : _markers.Length; i < n; i++)
|
||||
{
|
||||
var pair = _pairs[i];
|
||||
_markers[i].Begin();
|
||||
try
|
||||
{
|
||||
translationCallback(pair.run, ref data);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DISABLE_CATH_EXCEPTIONS
|
||||
throw;
|
||||
#endif
|
||||
EcsDebug.PrintError(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pair.runFinally != null)
|
||||
{
|
||||
translationFinnalyCallback(pair.runFinally, ref data);
|
||||
}
|
||||
}
|
||||
_markers[i].End();
|
||||
}
|
||||
#else
|
||||
foreach (var pair in _pairs)
|
||||
{
|
||||
try
|
||||
{
|
||||
translationCallback(pair.run, t0);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DISABLE_CATH_EXCEPTIONS
|
||||
throw;
|
||||
#endif
|
||||
EcsDebug.PrintError(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pair.runFinally != null)
|
||||
{
|
||||
translationFinnalyCallback(pair.runFinally, t0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
|
||||
//----
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,13 +20,22 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
internal readonly struct AspectCache<T> : IEcsWorldComponent<AspectCache<T>>
|
||||
where T : EcsAspect, new()
|
||||
where T : new()
|
||||
{
|
||||
public readonly T Instance;
|
||||
public AspectCache(T instance) { Instance = instance; }
|
||||
public readonly EcsMask Mask;
|
||||
public AspectCache(T instance, EcsMask mask)
|
||||
{
|
||||
Instance = instance;
|
||||
Mask = mask;
|
||||
}
|
||||
void IEcsWorldComponent<AspectCache<T>>.Init(ref AspectCache<T> component, EcsWorld world)
|
||||
{
|
||||
component = new AspectCache<T>(EcsAspect.Builder.New<T>(world));
|
||||
#if DEBUG
|
||||
AllowedInWorldsAttribute.CheckAllows<T>(world);
|
||||
#endif
|
||||
var result = EcsAspect.Builder.New<T>(world);
|
||||
component = new AspectCache<T>(result.aspect, result.mask);
|
||||
}
|
||||
void IEcsWorldComponent<AspectCache<T>>.OnDestroy(ref AspectCache<T> component, EcsWorld world)
|
||||
{
|
||||
@ -36,7 +45,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
internal readonly struct WhereQueryCache<TExecutor, TAspcet> : IEcsWorldComponent<WhereQueryCache<TExecutor, TAspcet>>
|
||||
where TExecutor : MaskQueryExecutor, new()
|
||||
where TAspcet : EcsAspect, new()
|
||||
where TAspcet : new()
|
||||
{
|
||||
public readonly TExecutor Executor;
|
||||
public readonly TAspcet Aspcet;
|
||||
@ -47,9 +56,9 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
void IEcsWorldComponent<WhereQueryCache<TExecutor, TAspcet>>.Init(ref WhereQueryCache<TExecutor, TAspcet> component, EcsWorld world)
|
||||
{
|
||||
TAspcet aspect = world.GetAspect<TAspcet>();
|
||||
TExecutor instance = world.GetExecutorForMask<TExecutor>(aspect.Mask);
|
||||
instance.Initialize(world, aspect.Mask);
|
||||
TAspcet aspect = world.GetAspect<TAspcet>(out EcsMask mask);
|
||||
TExecutor instance = world.GetExecutorForMask<TExecutor>(mask);
|
||||
instance.Initialize(world, mask);
|
||||
component = new WhereQueryCache<TExecutor, TAspcet>(instance, aspect);
|
||||
}
|
||||
void IEcsWorldComponent<WhereQueryCache<TExecutor, TAspcet>>.OnDestroy(ref WhereQueryCache<TExecutor, TAspcet> component, EcsWorld world)
|
||||
|
@ -250,14 +250,21 @@ namespace DCFApixels.DragonECS
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
#endif
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public TAspect GetAspect<TAspect>() where TAspect : EcsAspect, new()
|
||||
public TAspect GetAspect<TAspect>() where TAspect : new()
|
||||
{
|
||||
return Get<AspectCache<TAspect>>().Instance;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public TAspect GetAspect<TAspect>(out EcsMask mask) where TAspect : new()
|
||||
{
|
||||
var result = Get<AspectCache<TAspect>>();
|
||||
mask = result.Mask;
|
||||
return result.Instance;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void GetQueryCache<TExecutor, TAspect>(out TExecutor executor, out TAspect aspect)
|
||||
where TExecutor : MaskQueryExecutor, new()
|
||||
where TAspect : EcsAspect, new()
|
||||
where TAspect : new()
|
||||
{
|
||||
ref var cmp = ref Get<WhereQueryCache<TExecutor, TAspect>>();
|
||||
executor = cmp.Executor;
|
||||
@ -270,6 +277,11 @@ namespace DCFApixels.DragonECS
|
||||
return ref WorldComponentPool<T>.GetForWorld(ID);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Has<T>() where T : struct
|
||||
{
|
||||
return WorldComponentPool<T>.Has(ID);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref T GetUnchecked<T>() where T : struct
|
||||
{
|
||||
return ref WorldComponentPool<T>.GetForWorldUnchecked(ID);
|
||||
@ -280,6 +292,11 @@ namespace DCFApixels.DragonECS
|
||||
return ref WorldComponentPool<T>.GetForWorld(worldID);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool Has<T>(short worldID) where T : struct
|
||||
{
|
||||
return WorldComponentPool<T>.Has(worldID);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ref T GetUnchecked<T>(short worldID) where T : struct
|
||||
{
|
||||
return ref WorldComponentPool<T>.GetForWorldUnchecked(worldID);
|
||||
@ -874,6 +891,8 @@ namespace DCFApixels.DragonECS
|
||||
#region Debug Components
|
||||
[ThreadStatic]
|
||||
private static int[] _componentIDsBuffer;
|
||||
[ThreadStatic]
|
||||
private static object[] _componentsBuffer;
|
||||
public ReadOnlySpan<int> GetComponentTypeIDsFor(int entityID)
|
||||
{
|
||||
int count = GetComponentTypeIDsFor_Internal(entityID, ref _componentIDsBuffer);
|
||||
@ -920,6 +939,19 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
}
|
||||
public ReadOnlySpan<object> GetComponentsFor(int entityID)
|
||||
{
|
||||
int count = GetComponentTypeIDsFor_Internal(entityID, ref _componentIDsBuffer);
|
||||
if (_componentsBuffer == null || _componentsBuffer.Length < count)
|
||||
{
|
||||
_componentsBuffer = new object[count];
|
||||
}
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
_componentsBuffer[i] = _pools[_componentIDsBuffer[i]].GetRaw(entityID);
|
||||
}
|
||||
return new ReadOnlySpan<object>(_componentsBuffer, 0, count);
|
||||
}
|
||||
public void GetComponentsFor(int entityID, List<object> list)
|
||||
{
|
||||
list.Clear();
|
||||
|
@ -169,6 +169,10 @@ namespace DCFApixels.DragonECS
|
||||
Array.Resize(ref _items, _items.Length << 1);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
AllowedInWorldsAttribute.CheckAllows<T>(_worlds[worldID]);
|
||||
#endif
|
||||
|
||||
_interface.Init(ref _items[itemIndex], _worlds[worldID]);
|
||||
|
||||
var world = GetWorld(worldID);
|
||||
|
@ -13,7 +13,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
#region Where
|
||||
public static EcsSpan Where<TCollection, TAspect>(this TCollection entities, out TAspect aspect)
|
||||
where TAspect : EcsAspect, new()
|
||||
where TAspect : new()
|
||||
where TCollection : IEntityStorage
|
||||
{
|
||||
if (ReferenceEquals(entities, entities.World))
|
||||
@ -24,12 +24,12 @@ namespace DCFApixels.DragonECS
|
||||
return entities.ToSpan().Where(out aspect);
|
||||
}
|
||||
public static EcsSpan Where<TAspect>(this EcsReadonlyGroup group, out TAspect aspect)
|
||||
where TAspect : EcsAspect, new()
|
||||
where TAspect : new()
|
||||
{
|
||||
return group.ToSpan().Where(out aspect);
|
||||
}
|
||||
public static EcsSpan Where<TAspect>(this EcsSpan span, out TAspect aspect)
|
||||
where TAspect : EcsAspect, new()
|
||||
where TAspect : new()
|
||||
{
|
||||
span.World.GetQueryCache(out EcsWhereExecutor executor, out aspect);
|
||||
return executor.ExecuteFor(span);
|
||||
@ -58,7 +58,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region Where with sort
|
||||
public static EcsSpan Where<TCollection, TAspect>(this TCollection entities, out TAspect aspect, Comparison<int> comparison)
|
||||
where TAspect : EcsAspect, new()
|
||||
where TAspect : new()
|
||||
where TCollection : IEntityStorage
|
||||
{
|
||||
if (ReferenceEquals(entities, entities.World))
|
||||
@ -69,12 +69,12 @@ namespace DCFApixels.DragonECS
|
||||
return entities.ToSpan().Where(out aspect, comparison);
|
||||
}
|
||||
public static EcsSpan Where<TAspect>(this EcsReadonlyGroup group, out TAspect aspect, Comparison<int> comparison)
|
||||
where TAspect : EcsAspect, new()
|
||||
where TAspect : new()
|
||||
{
|
||||
return group.ToSpan().Where(out aspect, comparison);
|
||||
}
|
||||
public static EcsSpan Where<TAspect>(this EcsSpan span, out TAspect aspect, Comparison<int> comparison)
|
||||
where TAspect : EcsAspect, new()
|
||||
where TAspect : new()
|
||||
{
|
||||
span.World.GetQueryCache(out EcsWhereExecutor executor, out aspect);
|
||||
return executor.ExecuteFor(span, comparison);
|
||||
@ -103,7 +103,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region WhereToGroup
|
||||
public static EcsReadonlyGroup WhereToGroup<TCollection, TAspect>(this TCollection entities, out TAspect aspect)
|
||||
where TAspect : EcsAspect, new()
|
||||
where TAspect : new()
|
||||
where TCollection : IEntityStorage
|
||||
{
|
||||
if (ReferenceEquals(entities, entities.World))
|
||||
@ -114,12 +114,12 @@ namespace DCFApixels.DragonECS
|
||||
return entities.ToSpan().WhereToGroup(out aspect);
|
||||
}
|
||||
public static EcsReadonlyGroup WhereToGroup<TAspect>(this EcsReadonlyGroup group, out TAspect aspect)
|
||||
where TAspect : EcsAspect, new()
|
||||
where TAspect : new()
|
||||
{
|
||||
return group.ToSpan().WhereToGroup(out aspect);
|
||||
}
|
||||
public static EcsReadonlyGroup WhereToGroup<TAspect>(this EcsSpan span, out TAspect aspect)
|
||||
where TAspect : EcsAspect, new()
|
||||
where TAspect : new()
|
||||
{
|
||||
span.World.GetQueryCache(out EcsWhereToGroupExecutor executor, out aspect);
|
||||
return executor.ExecuteFor(span);
|
||||
|
43
src/Utils/AllowedInWorldsAttribute.cs
Normal file
43
src/Utils/AllowedInWorldsAttribute.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using DCFApixels.DragonECS.Internal;
|
||||
using System;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
|
||||
public sealed class AllowedInWorldsAttribute : Attribute
|
||||
{
|
||||
public object[] AllowedWorlds;
|
||||
public AllowedInWorldsAttribute(params object[] allowedWorlds)
|
||||
{
|
||||
AllowedWorlds = allowedWorlds;
|
||||
}
|
||||
|
||||
|
||||
public static void CheckAllows<T>(EcsWorld world)
|
||||
{
|
||||
Type componentType = typeof(T);
|
||||
Type worldType = world.GetType();
|
||||
if (componentType.TryGetAttribute(out AllowedInWorldsAttribute attribute))
|
||||
{
|
||||
foreach (var worldTag in attribute.AllowedWorlds)
|
||||
{
|
||||
bool result = false;
|
||||
if (worldTag is Type worldTypeTag)
|
||||
{
|
||||
result = worldTypeTag == worldType;
|
||||
}
|
||||
else
|
||||
{
|
||||
string worldStringTag = worldTag.ToString();
|
||||
result = world.Name == worldStringTag;
|
||||
}
|
||||
if (result)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new EcsFrameworkException($"Using component {componentType.ToMeta().TypeName} is not allowed in the {worldType.ToMeta().TypeName} world.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
src/Utils/AllowedInWorldsAttribute.cs.meta
Normal file
11
src/Utils/AllowedInWorldsAttribute.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a39694cb8b5876346968ef45a8272000
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Reference in New Issue
Block a user