using System; using System.Runtime.CompilerServices; using Svelto.Common; using Svelto.DataStructures; using Svelto.DataStructures.Native; using Svelto.ECS.Internal; 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, _IInternalEntityComponent { public static readonly NativeEGIDMapper empty = new NativeEGIDMapper (default, new SharedSveltoDictionaryNative(0, Allocator.Persistent)); public NativeEGIDMapper(ExclusiveGroupStruct groupStructId, in SharedSveltoDictionaryNative toDisposableNative) : this() { groupID = groupStructId; _map = toDisposableNative; } public int count => _map.dictionary.count; public Type entityType => TypeCache.type; public ExclusiveGroupStruct groupID { get; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref T Entity(uint entityID) { var sveltoDictionary = _map.dictionary; #if DEBUG && !PROFILE_SVELTO if (sveltoDictionary.TryFindIndex(entityID, out var findIndex) == false) throw new Exception($"Entity {entityID} not found in this group {groupID} - {typeof(T).Name}"); #else sveltoDictionary.TryFindIndex(entityID, out var findIndex); #endif return ref sveltoDictionary.GetDirectValueByRef(findIndex); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryGetEntity(uint entityID, out T value) { var sveltoDictionary = _map.dictionary; if (sveltoDictionary.count > 0 && sveltoDictionary.TryFindIndex(entityID, out var index)) { var values = sveltoDictionary.unsafeValues.ToRealBuffer(); value = values[index]; return true; } value = default; return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public NB GetArrayAndEntityIndex(uint entityID, out uint index) { var sveltoDictionary = _map.dictionary; if (sveltoDictionary.TryFindIndex(entityID, out index)) return sveltoDictionary.unsafeValues.ToRealBuffer(); #if DEBUG && !PROFILE_SVELTO 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; var sveltoDictionary = _map.dictionary; if (sveltoDictionary.count > 0 && sveltoDictionary.TryFindIndex(entityID, out index)) { array = sveltoDictionary.unsafeValues.ToRealBuffer(); return true; } array = default; return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Exists(uint idEntityId) { var sveltoDictionary = _map.dictionary; return sveltoDictionary.count > 0 && sveltoDictionary.TryFindIndex(idEntityId, out _); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public uint GetIndex(uint entityID) { return _map.dictionary.GetIndex(entityID); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool FindIndex(uint valueKey, out uint index) { return _map.dictionary.TryFindIndex(valueKey, out index); } readonly SharedSveltoDictionaryNative _map; } }