2025-03-14 16:53:25 +08:00
|
|
|
|
#if DISABLE_DEBUG
|
|
|
|
|
|
#undef DEBUG
|
|
|
|
|
|
#endif
|
|
|
|
|
|
using DCFApixels.DragonECS.Core;
|
2025-05-18 10:52:24 +08:00
|
|
|
|
using DCFApixels.DragonECS.Core.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;
|
2025-05-21 17:41:28 +08:00
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
#if ENABLE_IL2CPP
|
|
|
|
|
|
using Unity.IL2CPP.CompilerServices;
|
|
|
|
|
|
#endif
|
2023-12-24 15:40:19 +08:00
|
|
|
|
|
|
|
|
|
|
namespace DCFApixels.DragonECS
|
2023-05-07 00:50:02 +08:00
|
|
|
|
{
|
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-07 08:22:10 +08:00
|
|
|
|
|
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-11-07 08:22:10 +08:00
|
|
|
|
var executorType = typeof(TExecutor);
|
2024-11-05 15:50:03 +08:00
|
|
|
|
//проверяет ключ по абстрактной маске
|
2024-11-07 08:22:10 +08:00
|
|
|
|
if (_executorCoures.TryGetValue((executorType, 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 ||
|
2024-11-07 08:22:10 +08:00
|
|
|
|
_executorCoures.TryGetValue((executorType, mask), out executor) == false)
|
2024-11-05 15:50:03 +08:00
|
|
|
|
{
|
2024-11-07 08:22:10 +08:00
|
|
|
|
TExecutor executorCore = new TExecutor();
|
|
|
|
|
|
executorCore.Initialize(this, mask);
|
|
|
|
|
|
executor = executorCore;
|
2024-11-05 15:50:03 +08:00
|
|
|
|
}
|
2024-11-07 08:22:10 +08:00
|
|
|
|
_executorCoures.Add((executorType, 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-11-07 10:19:44 +08:00
|
|
|
|
|
|
|
|
|
|
public void GetMaskQueryExecutors(List<MaskQueryExecutor> result, ref int version)
|
|
|
|
|
|
{
|
2024-11-07 16:21:51 +08:00
|
|
|
|
if (_executorCoures == null || version == _executorCoures.Count)
|
2024-11-07 10:19:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result.Clear();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var item in _executorCoures)
|
|
|
|
|
|
{
|
2024-11-07 16:21:51 +08:00
|
|
|
|
if (item.Value is MaskQueryExecutor x)
|
2024-11-07 10:19:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
result.Add(x);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
version = _executorCoures.Count;
|
|
|
|
|
|
}
|
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; }
|
2024-11-07 08:22:10 +08:00
|
|
|
|
int LastCachedCount { get; }
|
2024-11-05 15:50:03 +08:00
|
|
|
|
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-11-07 16:21:51 +08:00
|
|
|
|
public EcsMask Mask
|
2024-08-24 13:10:50 +08:00
|
|
|
|
{
|
|
|
|
|
|
[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-11-07 08:22:10 +08:00
|
|
|
|
public abstract int LastCachedCount { 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();
|
2023-05-26 06:18:09 +08:00
|
|
|
|
protected abstract void OnDestroy();
|
2023-05-07 00:50:02 +08:00
|
|
|
|
}
|
2024-08-23 22:31:43 +08:00
|
|
|
|
|
2025-05-21 17:41:28 +08:00
|
|
|
|
#if ENABLE_IL2CPP
|
|
|
|
|
|
[Il2CppSetOption(Option.NullChecks, false)]
|
|
|
|
|
|
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
|
|
|
|
|
#endif
|
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;
|
2025-05-21 17:41:28 +08:00
|
|
|
|
private readonly MemoryAllocator.Handler _handler;
|
|
|
|
|
|
private readonly int* _componentIDs;
|
|
|
|
|
|
// _versions[0] world version
|
|
|
|
|
|
// _versions[-> EcsMask.Inc.Length] inc versions
|
|
|
|
|
|
// _versions[-> EcsMask.Exc.Length] exc versions
|
|
|
|
|
|
// _versions[-> EcsMask.Any.Length] any versions
|
2024-10-11 18:28:46 +08:00
|
|
|
|
private readonly long* _versions;
|
2025-03-13 16:41:23 +08:00
|
|
|
|
private readonly int _count;
|
2025-05-21 17:41:28 +08:00
|
|
|
|
private readonly bool _isNotOnlyExc;
|
2024-10-11 18:28:46 +08:00
|
|
|
|
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;
|
2025-05-21 17:41:28 +08:00
|
|
|
|
_count = 1 + mask._incs.Length + mask._excs.Length + mask._anys.Length;
|
|
|
|
|
|
|
|
|
|
|
|
_handler = MemoryAllocator.AllocAndInit<int>(_count * 2 + _count);
|
|
|
|
|
|
_versions = _handler.As<long>();
|
|
|
|
|
|
_componentIDs = (int*)(_handler.As<long>() + _count);
|
|
|
|
|
|
|
|
|
|
|
|
var ptr = _componentIDs + 1;
|
|
|
|
|
|
Marshal.Copy(mask._incs, 0, (IntPtr)ptr, mask._incs.Length);
|
|
|
|
|
|
ptr += mask._incs.Length;
|
|
|
|
|
|
Marshal.Copy(mask._excs, 0, (IntPtr)ptr, mask._excs.Length);
|
|
|
|
|
|
ptr += mask._excs.Length;
|
|
|
|
|
|
Marshal.Copy(mask._anys, 0, (IntPtr)ptr, mask._anys.Length);
|
2025-04-19 10:53:52 +08:00
|
|
|
|
|
2025-05-21 17:41:28 +08:00
|
|
|
|
_isNotOnlyExc = mask._incs.Length > 0 || mask._anys.Length > 0;
|
2024-10-11 18:28:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
public bool Check()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (*_versions == _world.Version)
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var slots = _world._poolSlots;
|
2025-05-21 17:41:28 +08:00
|
|
|
|
for (int i = 1; i < _count; i++)
|
2024-10-11 18:28:46 +08:00
|
|
|
|
{
|
2025-05-21 17:41:28 +08:00
|
|
|
|
if(_versions[i] == slots[_componentIDs[i]].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
|
|
|
|
var slots = _world._poolSlots;
|
2025-05-21 17:41:28 +08:00
|
|
|
|
for (int i = 1; i < _count; i++)
|
2024-10-11 18:28:46 +08:00
|
|
|
|
{
|
2025-05-21 17:41:28 +08:00
|
|
|
|
_versions[i] = slots[_componentIDs[i]].version;
|
2024-10-11 18:28:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
|
|
var slots = _world._poolSlots;
|
2025-05-21 17:41:28 +08:00
|
|
|
|
bool result = _isNotOnlyExc;
|
|
|
|
|
|
for (int i = 1; i < _count; i++)
|
2024-08-23 22:31:43 +08:00
|
|
|
|
{
|
2025-05-21 17:41:28 +08:00
|
|
|
|
if (_versions[i] != slots[_componentIDs[i]].version)
|
2025-03-31 11:58:16 +08:00
|
|
|
|
{
|
|
|
|
|
|
result = false;
|
2025-05-21 17:41:28 +08:00
|
|
|
|
_versions[i] = slots[_componentIDs[i]].version;
|
2025-03-31 11:58:16 +08:00
|
|
|
|
}
|
2024-08-23 22:31:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
2024-10-11 18:28:46 +08:00
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
|
{
|
2025-05-21 17:41:28 +08:00
|
|
|
|
MemoryAllocator.Free(_handler);
|
2024-10-11 18:28:46 +08:00
|
|
|
|
}
|
2024-08-23 22:31:43 +08:00
|
|
|
|
}
|
2023-12-24 15:40:19 +08:00
|
|
|
|
}
|