DragonECS/src/Executors/MaskQueryExecutor.cs

183 lines
5.5 KiB
C#
Raw Normal View History

2024-11-01 12:41:10 +08:00
using DCFApixels.DragonECS.Core;
using DCFApixels.DragonECS.Internal;
2024-10-11 18:28:46 +08:00
using System;
2024-08-24 12:29:58 +08:00
using System.Collections.Generic;
using System.Runtime.CompilerServices;
2023-12-24 15:40:19 +08:00
namespace DCFApixels.DragonECS
{
2024-08-24 12:29:58 +08:00
public partial class EcsWorld
{
2024-11-05 17:16:50 +08:00
private readonly Dictionary<(Type, object), IQueryExecutorImplementation> _executorCoures;
2024-11-05 15:50:03 +08:00
public TExecutor GetExecutorForMask<TExecutor>(IComponentMask gmask)
where TExecutor : MaskQueryExecutor, new()
2024-08-24 12:29:58 +08:00
{
2024-10-03 08:20:22 +08:00
var coreType = typeof(TExecutor);
2024-11-05 15:50:03 +08:00
//проверяет ключ по абстрактной маске
if (_executorCoures.TryGetValue((coreType, gmask), out IQueryExecutorImplementation executor) == false)
2024-08-24 12:29:58 +08:00
{
2024-11-05 15:50:03 +08:00
var mask = gmask.ToMask(this);
//проверяет ключ по конкретной маске, или что конкретная и абстрактая одна и таже
if (mask == gmask ||
_executorCoures.TryGetValue((coreType, mask), out executor) == false)
{
TExecutor newCore = new TExecutor();
newCore.Initialize(this, mask);
executor = newCore;
}
_executorCoures.Add((coreType, gmask), executor);
2024-08-24 12:29:58 +08:00
}
2024-11-05 15:50:03 +08:00
return (TExecutor)executor;
2024-10-03 08:20:22 +08:00
}
2024-08-24 12:29:58 +08:00
}
2024-11-05 15:50:03 +08:00
}
namespace DCFApixels.DragonECS.Core
{
public interface IQueryExecutorImplementation
{
EcsWorld World { get; }
long Version { get; }
bool IsCached { get; }
void Destroy();
}
public abstract class MaskQueryExecutor : IQueryExecutorImplementation
2024-08-24 12:29:58 +08:00
{
private EcsWorld _source;
2024-08-24 13:10:50 +08:00
private EcsMask _mask;
2024-08-24 12:29:58 +08:00
public short WorldID
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-10-31 16:27:53 +08:00
get { return _source.ID; }
2024-08-24 12:29:58 +08:00
}
public EcsWorld World
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _source; }
}
2024-08-24 13:10:50 +08:00
protected EcsMask Mask
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _mask; }
}
2024-10-03 08:20:22 +08:00
public abstract long Version { get; }
2024-11-05 15:50:03 +08:00
public abstract bool IsCached { get; }
2024-08-24 13:10:50 +08:00
internal void Initialize(EcsWorld world, EcsMask mask)
2024-08-24 12:29:58 +08:00
{
_source = world;
2024-08-24 13:10:50 +08:00
_mask = mask;
2024-08-24 12:29:58 +08:00
OnInitialize();
}
2024-11-05 15:50:03 +08:00
void IQueryExecutorImplementation.Destroy()
2024-08-24 12:29:58 +08:00
{
OnDestroy();
_source = null;
2023-12-24 15:40:19 +08:00
}
2023-06-08 04:04:39 +08:00
protected abstract void OnInitialize();
protected abstract void OnDestroy();
}
2024-08-23 22:31:43 +08:00
2024-10-11 18:28:46 +08:00
public readonly unsafe struct WorldStateVersionsChecker : IDisposable
2024-08-23 22:31:43 +08:00
{
2024-10-11 18:28:46 +08:00
private readonly EcsWorld _world;
private readonly int[] _maskInc;
private readonly int[] _maskExc;
// [0] world version
// [-> _maskInc.Length] inc versions
// [-> _maskExc.Length] exc versions
private readonly long* _versions;
public long Version
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _versions[0]; }
}
2024-08-23 22:31:43 +08:00
2024-10-11 18:28:46 +08:00
public WorldStateVersionsChecker(EcsMask mask)
2024-08-23 22:31:43 +08:00
{
2024-10-11 18:28:46 +08:00
_world = mask.World;
2024-11-01 12:41:10 +08:00
_maskInc = mask._incs;
_maskExc = mask._excs;
_versions = UnmanagedArrayUtility.New<long>(1 + mask._incs.Length + mask._excs.Length);
2024-10-11 18:28:46 +08:00
}
public bool Check()
{
if (*_versions == _world.Version)
{
return true;
}
2024-10-31 14:46:21 +08:00
long* versionsPtr = _versions;
2024-10-11 18:28:46 +08:00
var slots = _world._poolSlots;
foreach (var slotIndex in _maskInc)
{
2024-10-31 14:46:21 +08:00
versionsPtr++;
if (*versionsPtr != slots[slotIndex].version)
2024-10-11 18:28:46 +08:00
{
return false;
}
}
foreach (var slotIndex in _maskExc)
{
2024-10-31 14:46:21 +08:00
versionsPtr++;
if (*versionsPtr != slots[slotIndex].version)
2024-10-11 18:28:46 +08:00
{
return false;
}
}
return true;
2024-08-23 22:31:43 +08:00
}
2024-10-11 18:28:46 +08:00
public void Next()
{
*_versions = _world.Version;
2024-08-23 22:31:43 +08:00
2024-10-11 18:28:46 +08:00
long* ptr = _versions;
var slots = _world._poolSlots;
foreach (var slotIndex in _maskInc)
{
ptr++;
*ptr = slots[slotIndex].version;
}
foreach (var slotIndex in _maskExc)
{
ptr++;
*ptr = slots[slotIndex].version;
}
}
public bool CheckAndNext()
2024-08-23 22:31:43 +08:00
{
2024-10-11 18:28:46 +08:00
if (*_versions == _world.Version)
{
return true;
}
*_versions = _world.Version;
long* ptr = _versions;
var slots = _world._poolSlots;
2024-08-23 22:31:43 +08:00
bool result = true;
2024-10-11 18:28:46 +08:00
foreach (var slotIndex in _maskInc)
2024-08-23 22:31:43 +08:00
{
2024-10-11 18:28:46 +08:00
ptr++;
if (*ptr != slots[slotIndex].version)
2024-08-23 22:31:43 +08:00
{
result = false;
2024-10-11 18:28:46 +08:00
*ptr = slots[slotIndex].version;
2024-08-23 22:31:43 +08:00
}
}
2024-10-11 18:28:46 +08:00
foreach (var slotIndex in _maskExc)
2024-08-23 22:31:43 +08:00
{
2024-10-11 18:28:46 +08:00
ptr++;
if (*ptr != slots[slotIndex].version)
2024-08-23 22:31:43 +08:00
{
result = false;
2024-10-11 18:28:46 +08:00
*ptr = slots[slotIndex].version;
2024-08-23 22:31:43 +08:00
}
}
return result;
}
2024-10-11 18:28:46 +08:00
public void Dispose()
{
}
2024-08-23 22:31:43 +08:00
}
2023-12-24 15:40:19 +08:00
}