-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathListPoolAccessor.cs
137 lines (132 loc) · 5.77 KB
/
ListPoolAccessor.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
using VodeoECS.Internal;
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
namespace VodeoECS
{
/// <summary>
/// Component Pool Reader for use with Burst Compiled Jobs.
/// Can be passed to a job and can read and write the Elements of List Components, destroy or append them, but not destroy or create new List Components.
/// </summary>
/// <typeparam name="T">The type of the List Component Elements accessed by this Accessor.</typeparam>
public unsafe struct ListPoolAccessor<T> : IDisposable, IEnumerable<ListAccessor<T>> where T : unmanaged, IElementComponent
{
private NativeArray<UnsafeList<UnsafeList<T>>> lists;
private NativeSlice<ComponentIndex> indexMap;
private readonly NativeSlice<Taxon> taxa;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
private NativeArray<AtomicSafetyHandle> handles;
#endif
/// <summary>
/// For internal use by the Component Pool class. Constructs a List Pool Accessor.
/// </summary>
/// <param name="components">List of List Component NativeNested containers for each Taxon in the Pool.</param>
/// <param name="indices">Slice into the index map for the Pool.</param>
/// <param name="taxa">Slice into the list of all created taxa for the pool.</param>
/// <param name="allocator">Memory Allocator to use.</param>
public ListPoolAccessor ( List<NativeNested<T>> components, NativeSlice<ComponentIndex> indices, NativeSlice<Taxon> taxa, Allocator allocator )
{
this.lists = new NativeArray<UnsafeList<UnsafeList<T>>>( components.Count, allocator );
this.indexMap = indices;
this.taxa = taxa;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
this.handles = new NativeArray<AtomicSafetyHandle>( components.Count, allocator );
#endif
for ( int i = 0; i < taxa.Length; i++ )
{
int taxonID = taxa[i].ID;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
handles[taxonID] = components[taxonID].Safety;
AtomicSafetyHandle.CheckReadAndThrow( handles[taxonID] );
AtomicSafetyHandle.SetAllowSecondaryVersionWriting( handles[taxonID], false );
#endif
lists[taxonID] = new UnsafeList<UnsafeList<T>>( ( UnsafeList<T>* )components[taxonID].GetNestedSlice( ).GetUnsafeReadOnlyPtr( ), components[taxonID].Length );
}
}
public ListAccessor<T> this[ComponentIndex index]
{
get
{
return this[index.taxonID, index.entry];
}
}
public ListAccessor<T> this[Entity entity]
{
get
{
ComponentIndex index = this.indexMap[entity.ID];
return this[index];
}
}
/// <summary>
/// Get the Component Index for a given Entity. Components within an Archetype share the same ComponentIndex if their Entities implement the Archetype!
/// Component Indices should not be stored permanently as they are invalidated by Component removal, and Archetype or Filter changes. Accessing a Component through a Component Index is more efficient than through an Entity.
/// </summary>
/// <param name="entity">The ComponentIndex for this Entity will be returned.</param>
/// <returns>The ComponentIndex requested.</returns>
public ComponentIndex GetIndex ( Entity entity )
{
return this.indexMap[entity.ID];
}
/// <summary>
/// Does the given Entity have a Component in this pool?
/// </summary>
/// <param name="entity">The Entity to test.</param>
/// <returns>Returns true if the Entity has a Component in this Pool, false if not.</returns>
public bool HasComponent ( Entity entity )
{
if ( entity.ID >= indexMap.Length ) return false;
return indexMap[entity.ID] != ComponentIndex.Null;
}
/// <summary>
/// Enumerates through access to all components in this pool.
/// The order of Entities associated with each Component in a Taxon Slice is preserved across all Component Pools sharing the Taxon.
/// </summary>
/// <returns>An accessor to each component in this pool.</returns>
public IEnumerator<ListAccessor<T>> GetEnumerator ( )
{
foreach ( Taxon taxon in taxa )
{
for ( int i = 0; i < this.lists[taxon.ID].Length; i++ )
{
yield return this[i, taxon.ID];
}
}
}
IEnumerator IEnumerable.GetEnumerator ( )
{
return GetEnumerator( );
}
/// <summary>
/// Dispose the native memory reserved by this Pool Accessor.
/// </summary>
public void Dispose ( )
{
for ( int i = 0; i < taxa.Length; i++ )
{
int id = taxa[i].ID;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
AtomicSafetyHandle.SetAllowSecondaryVersionWriting( handles[id], true );
#endif
this.lists[id].Dispose( );
}
#if ENABLE_UNITY_COLLECTIONS_CHECKS
this.handles.Dispose( );
#endif
this.lists.Dispose( );
}
private ListAccessor<T> this[int t, int i]
{
get
{
NativeSlice<UnsafeList<T>> slice = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice<UnsafeList<T>>( lists[t].Ptr, sizeof( UnsafeList<T> ), lists[t].Length );
#if ENABLE_UNITY_COLLECTIONS_CHECKS
NativeSliceUnsafeUtility.SetAtomicSafetyHandle( ref slice, handles[t] );
#endif
return new ListAccessor<T>( slice, i );
}
}
}
}