#if UNITY_NATIVE
using System;
using System.Runtime.CompilerServices;
using Svelto.Common;
using Svelto.DataStructures;
using Svelto.DataStructures.Native;
namespace Svelto.ECS.Native
{
///
/// Note: this class should really be ref struct by design. It holds the reference of a dictionary that can become
/// invalid. Unfortunately it can be a ref struct, because Jobs needs to hold if by paramater. So the deal is
/// that a job can use it as long as nothing else is modifying the entities database and the NativeEGIDMapper
/// is disposed right after the use.
///
public readonly struct NativeEGIDMapper : IEGIDMapper where T : unmanaged, IEntityComponent
{
public NativeEGIDMapper
(ExclusiveGroupStruct groupStructId
, SveltoDictionary>, NativeStrategy, NativeStrategy>
toNative) : this()
{
groupID = groupStructId;
_map = new SveltoDictionaryNative();
_map.UnsafeCast(toNative);
}
public int count => _map.count;
public Type entityType => TypeCache.type;
public ExclusiveGroupStruct groupID { get; }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref T Entity(uint entityID)
{
#if DEBUG
if (_map.TryFindIndex(entityID, out var findIndex) == false)
throw new Exception("Entity not found in this group ".FastConcat(typeof(T).ToString()));
#else
_map.TryFindIndex(entityID, out var findIndex);
#endif
return ref _map.GetDirectValueByRef(findIndex);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryGetEntity(uint entityID, out T value)
{
if (_map.count > 0 && _map.TryFindIndex(entityID, out var index))
unsafe
{
value = Unsafe.AsRef(Unsafe.Add((void*) _map.GetValues(out _).ToNativeArray(out _)
, (int) index));
return true;
}
value = default;
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public NB GetArrayAndEntityIndex(uint entityID, out uint index)
{
if (_map.TryFindIndex(entityID, out index))
return new NB(_map.GetValues(out var count).ToNativeArray(out _), count);
#if DEBUG
throw new ECSException("Entity not found");
#else
return default;
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryGetArrayAndEntityIndex(uint entityID, out uint index, out NB array)
{
index = 0;
if (_map.count > 0 && _map.TryFindIndex(entityID, out index))
{
array = new NB(_map.GetValues(out var count).ToNativeArray(out _), count);
return true;
}
array = default;
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Exists(uint idEntityId)
{
return _map.count > 0 && _map.TryFindIndex(idEntityId, out _);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetIndex(uint entityID)
{
return _map.GetIndex(entityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool FindIndex(uint valueKey, out uint index)
{
return _map.TryFindIndex(valueKey, out index);
}
readonly SveltoDictionaryNative _map;
}
}
#endif