Example #1
0
        static unsafe void Initialize(ComponentSystemBase system, EntityQuery entityQuery, Type jobType, Type wrapperJobType,
                                      bool isParallelFor, ref JobForEachCache cache, out ProcessIterationData iterator)
        {
            // Get the job reflection data and cache it if we don't already have it cached.
            if (isParallelFor && cache.JobReflectionDataParallelFor == IntPtr.Zero ||
                !isParallelFor && cache.JobReflectionData == IntPtr.Zero)
            {
                var iType = GetIJobForEachInterface(jobType);
                if (cache.Types == null)
                {
                    cache.Types = GetComponentTypes(jobType, iType, out cache.ProcessTypesCount,
                                                    out cache.FilterChanged);
                }

                var res = GetJobReflection(jobType, wrapperJobType, iType, isParallelFor);

                if (isParallelFor)
                {
                    cache.JobReflectionDataParallelFor = res;
                }
                else
                {
                    cache.JobReflectionData = res;
                }
            }

            // Update cached EntityQuery and ComponentSystem data.
            if (system != null)
            {
                if (cache.ComponentSystem != system)
                {
                    cache.EntityQuery = system.GetEntityQueryInternal(cache.Types);

                    // If the cached filter has changed, update the newly cached EntityQuery with those changes.
                    if (cache.FilterChanged.Length != 0)
                    {
                        cache.EntityQuery.SetFilterChanged(cache.FilterChanged);
                    }

                    // Otherwise, just reset our newly cached EntityQuery's filter.
                    else
                    {
                        cache.EntityQuery.ResetFilter();
                    }

                    cache.ComponentSystem = system;
                }
            }
            else if (entityQuery != null)
            {
                if (cache.EntityQuery != entityQuery)
                {
                    // Cache the new EntityQuery and cache that our system is null.
                    cache.EntityQuery     = entityQuery;
                    cache.ComponentSystem = null;
                }
            }

            var query = cache.EntityQuery;

            iterator.IsReadOnly0 = iterator.IsReadOnly1 = iterator.IsReadOnly2 = iterator.IsReadOnly3 = iterator.IsReadOnly4 = iterator.IsReadOnly5 = 0;
            fixed(int *isReadOnly = &iterator.IsReadOnly0)
            {
                for (var i = 0; i != cache.ProcessTypesCount; i++)
                {
                    isReadOnly[i] = cache.Types[i].AccessModeType == ComponentType.AccessMode.ReadOnly ? 1 : 0;
                }
            }

            iterator.TypeIndex0 = iterator.TypeIndex1 = iterator.TypeIndex2 = iterator.TypeIndex3 = iterator.TypeIndex4 = iterator.TypeIndex5 = -1;
            fixed(int *typeIndices = &iterator.TypeIndex0)
            {
                for (var i = 0; i != cache.ProcessTypesCount; i++)
                {
                    typeIndices[i] = cache.Types[i].TypeIndex;
                }
            }

            iterator.m_IsParallelFor = isParallelFor;
            iterator.m_Length        = query.CalculateNumberOfChunksWithoutFiltering();

            iterator.GlobalSystemVersion = query.GetComponentChunkIterator().m_GlobalSystemVersion;

#if ENABLE_UNITY_COLLECTIONS_CHECKS
            iterator.m_MaxIndex = iterator.m_Length - 1;
            iterator.m_MinIndex = 0;

            iterator.m_Safety0     = iterator.m_Safety1 = iterator.m_Safety2 = iterator.m_Safety3 = iterator.m_Safety4 =
                iterator.m_Safety5 = default(AtomicSafetyHandle);

            iterator.m_SafetyReadOnlyCount = 0;
            fixed(AtomicSafetyHandle *safety = &iterator.m_Safety0)
            {
                for (var i = 0; i != cache.ProcessTypesCount; i++)
                {
                    if (cache.Types[i].AccessModeType == ComponentType.AccessMode.ReadOnly)
                    {
                        safety[iterator.m_SafetyReadOnlyCount] =
                            query.GetSafetyHandle(query.GetIndexInEntityQuery(cache.Types[i].TypeIndex));
                        iterator.m_SafetyReadOnlyCount++;
                    }
                }
            }

            iterator.m_SafetyReadWriteCount = 0;
            fixed(AtomicSafetyHandle *safety = &iterator.m_Safety0)
            {
                for (var i = 0; i != cache.ProcessTypesCount; i++)
                {
                    if (cache.Types[i].AccessModeType == ComponentType.AccessMode.ReadWrite)
                    {
                        safety[iterator.m_SafetyReadOnlyCount + iterator.m_SafetyReadWriteCount] =
                            query.GetSafetyHandle(query.GetIndexInEntityQuery(cache.Types[i].TypeIndex));
                        iterator.m_SafetyReadWriteCount++;
                    }
                }
            }

            Assert.AreEqual(cache.ProcessTypesCount, iterator.m_SafetyReadWriteCount + iterator.m_SafetyReadOnlyCount);
#endif
        }
Example #2
0
        //NOTE: It would be much better if C# could resolve the branch with generic resolving,
        //      but apparently the interface constraint is not enough..

        public static void PrepareEntityQuery <T>(this T jobData, ComponentSystemBase system)
            where T : struct, IBaseJobForEach
        {
            PrepareEntityQuery(system, typeof(T));
        }
 public DummyDelegateWrapper(ComponentSystemBase sys)
 {
     m_System = sys;
 }
Example #4
0
 public unsafe static JobHandle ScheduleSingle <TJob>(this TJob job, ComponentSystemBase system, JobHandle dependsOn = default(JobHandle))
     where TJob : struct, IBaseJobForEach
 {
     throw new CodegenShouldReplaceException();
 }
Example #5
0
        public ComponentGroupArrayStaticCache(Type type, EntityManager entityManager, ComponentSystemBase system = null)
        {
            var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            var componentFieldOffsetsBuilder = new List <int>();
            var componentTypesBuilder        = new List <ComponentType>();

            var componentDataFieldOffsetsBuilder = new List <int>();
            var componentDataTypesBuilder        = new List <ComponentType>();

            var subtractiveComponentTypesBuilder = new List <ComponentType>();

            foreach (var field in fields)
            {
                var fieldType = field.FieldType;
                var offset    = UnsafeUtility.GetFieldOffset(field);

                if (fieldType.IsPointer)
                {
                    var isReadOnly = field.GetCustomAttributes(typeof(ReadOnlyAttribute), true).Length != 0;
                    var accessMode = isReadOnly ? ComponentType.AccessMode.ReadOnly : ComponentType.AccessMode.ReadWrite;

                    var elementType = fieldType.GetElementType();

#if ENABLE_UNITY_COLLECTIONS_CHECKS
                    if (!typeof(IComponentData).IsAssignableFrom(elementType) && elementType != typeof(Entity))
                    {
                        throw new ArgumentException($"{type}.{field.Name} is a pointer type but not a IComponentData. Only IComponentData or Entity may be a pointer type for enumeration.");
                    }
#endif
                    componentDataFieldOffsetsBuilder.Add(offset);
                    componentDataTypesBuilder.Add(new ComponentType(elementType, accessMode));
                }
                else if (fieldType.IsSubclassOf(TypeManager.UnityEngineComponentType))
                {
                    componentFieldOffsetsBuilder.Add(offset);
                    componentTypesBuilder.Add(fieldType);
                }
                else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(SubtractiveComponent <>))
                {
                    subtractiveComponentTypesBuilder.Add(ComponentType.Subtractive(fieldType.GetGenericArguments()[0]));
                }
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                else if (typeof(IComponentData).IsAssignableFrom(fieldType))
                {
                    throw new ArgumentException($"{type}.{field.Name} must be an unsafe pointer to the {fieldType}. Like this: {fieldType}* {field.Name};");
                }
                else
                {
                    throw new ArgumentException($"{type}.{field.Name} can not be used in a component enumerator");
                }
#endif
            }
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            if (componentTypesBuilder.Count + componentDataTypesBuilder.Count > ComponentGroupArrayData.kMaxStream)
            {
                throw new ArgumentException($"{type} has too many component references. A ComponentGroup Array can have up to {ComponentGroupArrayData.kMaxStream}.");
            }
#endif

            ComponentDataCount = componentDataTypesBuilder.Count;
            ComponentCount     = componentTypesBuilder.Count;

            componentDataTypesBuilder.AddRange(componentTypesBuilder);
            componentDataTypesBuilder.AddRange(subtractiveComponentTypesBuilder);
            ComponentTypes = componentDataTypesBuilder.ToArray();

            componentDataFieldOffsetsBuilder.AddRange(componentFieldOffsetsBuilder);
            ComponentFieldOffsets = componentDataFieldOffsetsBuilder.ToArray();

            if (system != null)
            {
                ComponentGroup = system.GetComponentGroup(ComponentTypes);
                SafetyManager  = entityManager.ComponentJobSafetyManager;
            }
            else
            {
                ComponentGroup = entityManager.CreateComponentGroup(ComponentTypes);
                SafetyManager  = entityManager.ComponentJobSafetyManager;
            }

            CachedType = type;
        }
        private static string CollectInjectedGroup(ComponentSystemBase system, FieldInfo groupField, Type injectedGroupType, out FieldInfo entityArrayField, out FieldInfo indexFromEntityField, InjectionContext injectionContext, out FieldInfo lengthField, out FieldInfo componentGroupIndexField, ISet <ComponentType> componentRequirements, ICollection <InjectionData> componentDataInjections, ICollection <InjectionData> bufferDataInjections, ICollection <InjectionData> sharedComponentInjections)
        {
            string str;

            FieldInfo[] fields = injectedGroupType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
            entityArrayField         = null;
            indexFromEntityField     = null;
            lengthField              = null;
            componentGroupIndexField = null;
            FieldInfo[] infoArray2 = fields;
            int         index      = 0;

            while (true)
            {
                if (index >= infoArray2.Length)
                {
                    if (injectionContext.HasComponentRequirements)
                    {
                        foreach (ComponentType type in injectionContext.ComponentRequirements)
                        {
                            componentRequirements.Add(type);
                        }
                    }
                    str = null;
                    break;
                }
                FieldInfo field      = infoArray2[index];
                bool      isReadOnly = field.GetCustomAttributes(typeof(ReadOnlyAttribute), true).Length != 0;
                if (field.FieldType.IsGenericType && (field.FieldType.GetGenericTypeDefinition() == typeof(ComponentDataArray <>)))
                {
                    InjectionData item = new InjectionData(field, field.FieldType.GetGenericArguments()[0], isReadOnly);
                    componentDataInjections.Add(item);
                    componentRequirements.Add(item.ComponentType);
                }
                else if (field.FieldType.IsGenericType && (field.FieldType.GetGenericTypeDefinition() == typeof(SubtractiveComponent <>)))
                {
                    componentRequirements.Add(ComponentType.Subtractive(field.FieldType.GetGenericArguments()[0]));
                }
                else if (field.FieldType.IsGenericType && (field.FieldType.GetGenericTypeDefinition() == typeof(BufferArray <>)))
                {
                    InjectionData item = new InjectionData(field, field.FieldType.GetGenericArguments()[0], isReadOnly);
                    bufferDataInjections.Add(item);
                    componentRequirements.Add(item.ComponentType);
                }
                else if (field.FieldType.IsGenericType && (field.FieldType.GetGenericTypeDefinition() == typeof(SharedComponentDataArray <>)))
                {
                    if (!isReadOnly)
                    {
                        str = $"{system.GetType().Name}:{groupField.Name} SharedComponentDataArray<> must always be injected as [ReadOnly]";
                        break;
                    }
                    InjectionData item = new InjectionData(field, field.FieldType.GetGenericArguments()[0], true);
                    sharedComponentInjections.Add(item);
                    componentRequirements.Add(item.ComponentType);
                }
                else if (field.FieldType == typeof(EntityArray))
                {
                    if (entityArrayField != null)
                    {
                        str = $"{system.GetType().Name}:{groupField.Name} An [Inject] struct, may only contain a single EntityArray";
                        break;
                    }
                    entityArrayField = field;
                }
                else if (!(field.FieldType == typeof(int)))
                {
                    InjectionHook hook = InjectionHookSupport.HookFor(field);
                    if (hook == null)
                    {
                        str = $"{system.GetType().Name}:{groupField.Name} [Inject] may only be used on ComponentDataArray<>, ComponentArray<>, TransformAccessArray, EntityArray, {string.Join(",", (IEnumerable<string>) (from h in InjectionHookSupport.Hooks select h.FieldTypeOfInterest.Name))} and int Length.";
                        break;
                    }
                    string str2 = hook.ValidateField(field, isReadOnly, injectionContext);
                    if (str2 != null)
                    {
                        str = str2;
                        break;
                    }
                    injectionContext.AddEntry(hook.CreateInjectionInfoFor(field, isReadOnly));
                }
                else
                {
                    if ((field.Name != "Length") && (field.Name != "GroupIndex"))
                    {
                        str = $"{system.GetType().Name}:{groupField.Name} Int in an [Inject] struct should be named " Length " (group length) or " GroupIndex " (index in ComponentGroup[])";
                        break;
                    }
                    if (!field.IsInitOnly)
                    {
                        str = $"{system.GetType().Name}:{groupField.Name} {field.Name} must use the " readonly " keyword";
Example #7
0
 public static void PrepareComponentGroup <T>(this T jobData, ComponentSystemBase system)
     where T : struct, JobForEachExtensions.IBaseJobForEach
 {
     jobData.PrepareEntityQuery(system);
 }
 public static int CalculateEntityCount <T>(this T jobData, ComponentSystemBase system)
     where T : struct, IBaseJobProcessComponentData
 {
     return(CalculateEntityCount(system, typeof(T)));
 }
 public static void PrepareComponentGroup <T>(this T jobData, ComponentSystemBase system)
     where T : struct, JobForEachExtensions.IBaseJobForEach
 {
     throw new NotImplementedException();
 }
 public static ComponentGroup GetComponentGroupForIJobForEach(this ComponentSystemBase system,
                                                              Type jobType)
 {
     throw new NotImplementedException();
 }
Example #11
0
 public unsafe static JobHandle Schedule <TJob>(this TJob job, ComponentSystemBase system, JobHandle dependsOn = default(JobHandle))
     where TJob : struct, IBaseJobForEach
 {
     throw new NotImplementedException("Schedule<TJob>(ComponentSystemBase system) should have been replaced by code-gen.");
 }
Example #12
0
 void AddSystem_Add_Internal(ComponentSystemBase system)
 {
     m_Systems.Add(system);
     AddTypeLookupInternal(system.GetType(), system);
 }
Example #13
0
        public ComponentGroupArrayStaticCache(Type type, EntityManager entityManager, ComponentSystemBase system)
        {
            List <int>           collection = new List <int>();
            List <ComponentType> list2      = new List <ComponentType>();
            List <int>           list3      = new List <int>();
            List <ComponentType> list4      = new List <ComponentType>();
            List <ComponentType> list5      = new List <ComponentType>();

            foreach (FieldInfo info in type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
            {
                Type fieldType   = info.FieldType;
                int  fieldOffset = UnsafeUtility.GetFieldOffset(info);
                if (fieldType.IsPointer)
                {
                    ComponentType.AccessMode accessModeType = (info.GetCustomAttributes(typeof(ReadOnlyAttribute), true).Length != 0) ? ComponentType.AccessMode.ReadOnly : ComponentType.AccessMode.ReadWrite;
                    Type elementType = fieldType.GetElementType();
                    if (!typeof(IComponentData).IsAssignableFrom(elementType) && (elementType != typeof(Entity)))
                    {
                        throw new ArgumentException($"{type}.{info.Name} is a pointer type but not a IComponentData. Only IComponentData or Entity may be a pointer type for enumeration.");
                    }
                    list3.Add(fieldOffset);
                    list4.Add(new ComponentType(elementType, accessModeType));
                }
                else
                {
                    bool flag1;
                    if (TypeManager.UnityEngineComponentType != null)
                    {
                        flag1 = TypeManager.UnityEngineComponentType.IsAssignableFrom(fieldType);
                    }
                    else
                    {
                        object unityEngineComponentType = TypeManager.UnityEngineComponentType;
                        flag1 = false;
                    }
                    if (flag1)
                    {
                        collection.Add(fieldOffset);
                        list2.Add(fieldType);
                    }
                    else
                    {
                        if (!(fieldType.IsGenericType && (fieldType.GetGenericTypeDefinition() == typeof(SubtractiveComponent <>))))
                        {
                            if (!typeof(IComponentData).IsAssignableFrom(fieldType))
                            {
                                throw new ArgumentException($"{type}.{info.Name} can not be used in a component enumerator");
                            }
                            throw new ArgumentException($"{type}.{info.Name} must be an unsafe pointer to the {fieldType}. Like this: {fieldType}* {info.Name};");
                        }
                        list5.Add(ComponentType.Subtractive(fieldType.GetGenericArguments()[0]));
                    }
                }
            }
            if ((list2.Count + list4.Count) > 6)
            {
                throw new ArgumentException($"{type} has too many component references. A ComponentGroup Array can have up to {6}.");
            }
            this.ComponentDataCount = list4.Count;
            this.ComponentCount     = list2.Count;
            list4.AddRange(list2);
            list4.AddRange(list5);
            this.ComponentTypes = list4.ToArray();
            list3.AddRange(collection);
            this.ComponentFieldOffsets = list3.ToArray();
            this.ComponentGroup        = system.GetComponentGroupInternal(this.ComponentTypes);
            this.SafetyManager         = entityManager.ComponentJobSafetyManager;
            this.CachedType            = type;
        }
        static unsafe void Initialize(ComponentSystemBase system, ComponentGroup componentGroup, Type jobType, Type wrapperJobType,
                                      bool isParallelFor, ref JobProcessComponentDataCache cache, out ProcessIterationData iterator)
        {
            // Get the job reflection data and cache it if we don't already have it cached.
            if (isParallelFor && cache.JobReflectionDataParallelFor == IntPtr.Zero ||
                !isParallelFor && cache.JobReflectionData == IntPtr.Zero)
            {
                var iType = GetIJobProcessComponentDataInterface(jobType);
                if (cache.Types == null)
                {
                    cache.Types = GetComponentTypes(jobType, iType, out cache.ProcessTypesCount,
                                                    out cache.FilterChanged);
                }

                var res = GetJobReflection(jobType, wrapperJobType, iType, isParallelFor);

                if (isParallelFor)
                {
                    cache.JobReflectionDataParallelFor = res;
                }
                else
                {
                    cache.JobReflectionData = res;
                }
            }

            // Update cached ComponentGroup and ComponentSystem data.
            if (system != null)
            {
                if (cache.ComponentSystem != system)
                {
                    cache.ComponentGroup = system.GetComponentGroupInternal(cache.Types);

                    // If the cached filter has changed, update the newly cached ComponentGroup with those changes.
                    if (cache.FilterChanged.Length != 0)
                    {
                        cache.ComponentGroup.SetFilterChanged(cache.FilterChanged);
                    }

                    // Otherwise, just reset our newly cached ComponentGroup's filter.
                    else
                    {
                        cache.ComponentGroup.ResetFilter();
                    }

                    cache.ComponentSystem = system;
                }
            }
            else if (componentGroup != null)
            {
                if (cache.ComponentGroup != componentGroup)
                {
                    // Cache the new ComponentGroup and cache that our system is null.
                    cache.ComponentGroup  = componentGroup;
                    cache.ComponentSystem = null;
                }
            }

            var group = cache.ComponentGroup;

            iterator.IsReadOnly0 = iterator.IsReadOnly1 = iterator.IsReadOnly2 = iterator.IsReadOnly3 = iterator.IsReadOnly4 = iterator.IsReadOnly5 = 0;
            fixed(int *isReadOnly = &iterator.IsReadOnly0)
            {
                for (var i = 0; i != cache.ProcessTypesCount; i++)
                {
                    isReadOnly[i] = cache.Types[i].AccessModeType == ComponentType.AccessMode.ReadOnly ? 1 : 0;
                }
            }

            // Set process iteration data's ComponentChunkIterator
            iterator.Iterator = group.GetComponentChunkIterator();

            // Get each type's index in the component group and store them on the process iteration data for output.
            iterator.IndexInGroup0 = iterator.IndexInGroup1 = iterator.IndexInGroup2 = iterator.IndexInGroup3 = iterator.IndexInGroup4 = iterator.IndexInGroup5 = -1;
            fixed(int *groupIndices = &iterator.IndexInGroup0)
            {
                for (var i = 0; i != cache.ProcessTypesCount; i++)
                {
                    groupIndices[i] = group.GetIndexInComponentGroup(cache.Types[i].TypeIndex);
                }
            }

            iterator.m_IsParallelFor = isParallelFor;
            iterator.m_Length        = group.CalculateNumberOfChunksWithoutFiltering();

#if ENABLE_UNITY_COLLECTIONS_CHECKS
            iterator.m_MaxIndex = iterator.m_Length - 1;
            iterator.m_MinIndex = 0;

            iterator.m_Safety0 = iterator.m_Safety1 = iterator.m_Safety2 = iterator.m_Safety3 = iterator.m_Safety4 = iterator.m_Safety5 = default(AtomicSafetyHandle);

            iterator.m_SafetyReadOnlyCount = 0;
            fixed(AtomicSafetyHandle *safety = &iterator.m_Safety0)
            {
                for (var i = 0; i != cache.ProcessTypesCount; i++)
                {
                    if (cache.Types[i].AccessModeType == ComponentType.AccessMode.ReadOnly)
                    {
                        safety[iterator.m_SafetyReadOnlyCount] = group.GetSafetyHandle(group.GetIndexInComponentGroup(cache.Types[i].TypeIndex));
                        iterator.m_SafetyReadOnlyCount++;
                    }
                }
            }

            iterator.m_SafetyReadWriteCount = 0;
            fixed(AtomicSafetyHandle *safety = &iterator.m_Safety0)
            {
                for (var i = 0; i != cache.ProcessTypesCount; i++)
                {
                    if (cache.Types[i].AccessModeType == ComponentType.AccessMode.ReadWrite)
                    {
                        safety[iterator.m_SafetyReadOnlyCount + iterator.m_SafetyReadWriteCount] = group.GetSafetyHandle(group.GetIndexInComponentGroup(cache.Types[i].TypeIndex));
                        iterator.m_SafetyReadWriteCount++;
                    }
                }
            }

            Assert.AreEqual(cache.ProcessTypesCount, iterator.m_SafetyReadWriteCount + iterator.m_SafetyReadOnlyCount);
#endif
        }
Example #15
0
 public static ComponentGroup GetComponentGroupForIJobProcessComponentData(this ComponentSystemBase system, Type jobType)
 {
     return(system.GetEntityQueryForIJobForEach(jobType));
 }
        //NOTE: It would be much better if C# could resolve the branch with generic resolving,
        //      but apparently the interface constraint is not enough..

        public static void PrepareComponentGroup <T>(this T jobData, ComponentSystemBase system)
            where T : struct, IBaseJobProcessComponentData
        {
            PrepareComponentGroup(system, typeof(T));
        }
Example #17
0
        public static InjectComponentGroupData CreateInjection(Type injectedGroupType, FieldInfo groupField, ComponentSystemBase system)
        {
            FieldInfo entityArrayField;
            FieldInfo indexFromEntityField;
            FieldInfo lengthField;

            var injectionContext          = new InjectionContext();
            var componentDataInjections   = new List <InjectionData>();
            var fixedArrayInjections      = new List <InjectionData>();
            var sharedComponentInjections = new List <InjectionData>();

            var componentRequirements = new HashSet <ComponentType>();
            var error = CollectInjectedGroup(system, groupField, injectedGroupType, out entityArrayField, out indexFromEntityField, injectionContext, out lengthField, componentRequirements, componentDataInjections, fixedArrayInjections, sharedComponentInjections);

            if (error != null)
            {
                throw new ArgumentException(error);
            }

            return(new InjectComponentGroupData(system, groupField, componentDataInjections.ToArray(), fixedArrayInjections.ToArray(), sharedComponentInjections.ToArray(), entityArrayField, indexFromEntityField, injectionContext, lengthField, componentRequirements.ToArray()));
        }
Example #18
0
 public void RemoveSystemFromUpdateList(ComponentSystemBase sys)
 {
     m_systemSortDirty = true;
     m_systemsToRemove.Add(sys);
 }
Example #19
0
        static string CollectInjectedGroup(ComponentSystemBase system, FieldInfo groupField, Type injectedGroupType, out FieldInfo entityArrayField, out FieldInfo indexFromEntityField, InjectionContext injectionContext, out FieldInfo lengthField, ISet <ComponentType> componentRequirements,
                                           ICollection <InjectionData> componentDataInjections, ICollection <InjectionData> fixedArrayInjections, ICollection <InjectionData> sharedComponentInjections)
        {
            //@TODO: Improve error messages...
            var fields = injectedGroupType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            entityArrayField     = null;
            indexFromEntityField = null;
            lengthField          = null;

            foreach (var field in fields)
            {
                var isReadOnly = field.GetCustomAttributes(typeof(ReadOnlyAttribute), true).Length != 0;
                //@TODO: Prevent using GameObjectEntity, it will never show up. Point to GameObjectArray instead...

                if (field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(ComponentDataArray <>))
                {
                    var injection = new InjectionData(field, field.FieldType.GetGenericArguments()[0], isReadOnly);
                    componentDataInjections.Add(injection);
                    componentRequirements.Add(injection.ComponentType);
                }
                else if (field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(SubtractiveComponent <>))
                {
                    componentRequirements.Add(ComponentType.Subtractive(field.FieldType.GetGenericArguments()[0]));
                }
                else if (field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(FixedArrayArray <>))
                {
                    var injection = new InjectionData(field, field.FieldType.GetGenericArguments()[0], isReadOnly);

                    fixedArrayInjections.Add(injection);
                    componentRequirements.Add(injection.ComponentType);
                }
                else if (field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(SharedComponentDataArray <>))
                {
                    if (!isReadOnly)
                    {
                        return($"{system.GetType().Name}:{groupField.Name} SharedComponentDataArray<> must always be injected as [ReadOnly]");
                    }
                    var injection = new InjectionData(field, field.FieldType.GetGenericArguments()[0], true);

                    sharedComponentInjections.Add(injection);
                    componentRequirements.Add(injection.ComponentType);
                }
                else if (field.FieldType == typeof(EntityArray))
                {
                    // Error on multiple EntityArray
                    if (entityArrayField != null)
                    {
                        return($"{system.GetType().Name}:{groupField.Name} An [Inject] struct, may only contain a single EntityArray");
                    }

                    entityArrayField = field;
                }
                else if (field.FieldType == typeof(IndexFromEntity))
                {
                    // Error on multiple IndexFromEntity
                    if (indexFromEntityField != null)
                    {
                        return($"{system.GetType().Name}:{groupField.Name} An [Inject] struct, may only contain a single IndexFromEntity");
                    }

                    indexFromEntityField = field;
                }
                else if (field.FieldType == typeof(int))
                {
                    // Error on multiple EntityArray
                    if (field.Name != "Length")
                    {
                        return($"{system.GetType().Name}:{groupField.Name} An [Inject] struct, supports only a specialized int storing the length of the group. (\"int Length;\")");
                    }
                    lengthField = field;
                }
                else
                {
                    var hook = InjectionHookSupport.HookFor(field);
                    if (hook == null)
                    {
                        return
                            ($"{system.GetType().Name}:{groupField.Name} [Inject] may only be used on ComponentDataArray<>, ComponentArray<>, TransformAccessArray, EntityArray, {string.Join(",", InjectionHookSupport.Hooks.Select(h => h.FieldTypeOfInterest.Name))} and int Length.");
                    }

                    var error = hook.ValidateField(field, isReadOnly, injectionContext);
                    if (error != null)
                    {
                        return(error);
                    }

                    injectionContext.AddEntry(hook.CreateInjectionInfoFor(field, isReadOnly));
                }
            }

            if (injectionContext.HasComponentRequirements)
            {
                foreach (var requirement in injectionContext.ComponentRequirements)
                {
                    componentRequirements.Add(requirement);
                }
            }

            return(null);
        }
Example #20
0
        internal static unsafe void Initialize(ComponentSystemBase system, Type jobType, Type wrapperJobType,
                                               bool isParallelFor, ref JobProcessComponentDataCache cache, out ProcessIterationData iterator)
        {
            if (isParallelFor && cache.JobReflectionDataParallelFor == IntPtr.Zero ||
                !isParallelFor && cache.JobReflectionData == IntPtr.Zero)
            {
                var iType = GetIJobProcessComponentDataInterface(jobType);
                if (cache.Types == null)
                {
                    cache.Types = GetComponentTypes(jobType, iType, out cache.ProcessTypesCount,
                                                    out cache.FilterChanged);
                }

                var res = GetJobReflection(jobType, wrapperJobType, iType, isParallelFor);

                if (isParallelFor)
                {
                    cache.JobReflectionDataParallelFor = res;
                }
                else
                {
                    cache.JobReflectionData = res;
                }
            }

            if (cache.ComponentSystem != system)
            {
                cache.ComponentGroup = system.GetComponentGroupInternal(cache.Types);
                if (cache.FilterChanged.Length != 0)
                {
                    cache.ComponentGroup.SetFilterChanged(cache.FilterChanged);
                }
                else
                {
                    cache.ComponentGroup.ResetFilter();
                }

                cache.ComponentSystem = system;
            }

            var group = cache.ComponentGroup;

            // Readonly
            iterator.IsReadOnly0 = iterator.IsReadOnly1 = iterator.IsReadOnly2 = 0;
            fixed(int *isReadOnly = &iterator.IsReadOnly0)
            {
                for (var i = 0; i != cache.ProcessTypesCount; i++)
                {
                    isReadOnly[i] = cache.Types[i].AccessModeType == ComponentType.AccessMode.ReadOnly ? 1 : 0;
                }
            }

            // Iterator & length
            iterator.Iterator0 = default(ComponentChunkIterator);
            iterator.Iterator1 = default(ComponentChunkIterator);
            iterator.Iterator2 = default(ComponentChunkIterator);
            var length = -1;

            fixed(ComponentChunkIterator *iterators = &iterator.Iterator0)
            {
                for (var i = 0; i != cache.ProcessTypesCount; i++)
                {
                    group.GetComponentChunkIterator(out length, out iterators[i]);
                    iterators[i].IndexInComponentGroup = group.GetIndexInComponentGroup(cache.Types[i].TypeIndex);
                }
            }

            iterator.IsChangedFilter0 = 0;
            iterator.IsChangedFilter1 = 0;
            iterator.IsChangedFilter2 = 0;

            fixed(ComponentChunkIterator *iterators = &iterator.Iterator0)
            fixed(int *isChangedFilters = &iterator.IsChangedFilter0)
            {
                foreach (var type in cache.FilterChanged)
                {
                    var componentIndexInGroup = group.GetIndexInComponentGroup(type.TypeIndex);

                    for (var iteratorIndex = 0; iteratorIndex < 3; ++iteratorIndex)
                    {
                        if (componentIndexInGroup == iterators[iteratorIndex].IndexInComponentGroup)
                        {
                            isChangedFilters[iteratorIndex] = 1;
                        }
                    }
                }
            }

            iterator.m_IsParallelFor = isParallelFor;
            iterator.m_Length        = cache.FilterChanged.Length > 0
                ? group.CalculateNumberOfChunksWithoutFiltering()
                : length;

#if ENABLE_UNITY_COLLECTIONS_CHECKS
            iterator.m_MaxIndex = length - 1;
            iterator.m_MinIndex = 0;

            // Safety
            iterator.m_Safety0 = iterator.m_Safety1 = iterator.m_Safety2 = default(AtomicSafetyHandle);

            iterator.m_SafetyReadOnlyCount = 0;
            fixed(AtomicSafetyHandle *safety = &iterator.m_Safety0)
            {
                for (var i = 0; i != cache.ProcessTypesCount; i++)
                {
                    if (cache.Types[i].AccessModeType == ComponentType.AccessMode.ReadOnly)
                    {
                        safety[iterator.m_SafetyReadOnlyCount] =
                            group.GetSafetyHandle(group.GetIndexInComponentGroup(cache.Types[i].TypeIndex));
                        iterator.m_SafetyReadOnlyCount++;
                    }
                }
            }

            iterator.m_SafetyReadWriteCount = 0;
            fixed(AtomicSafetyHandle *safety = &iterator.m_Safety0)
            {
                for (var i = 0; i != cache.ProcessTypesCount; i++)
                {
                    if (cache.Types[i].AccessModeType == ComponentType.AccessMode.ReadWrite)
                    {
                        safety[iterator.m_SafetyReadOnlyCount + iterator.m_SafetyReadWriteCount] =
                            group.GetSafetyHandle(group.GetIndexInComponentGroup(cache.Types[i].TypeIndex));
                        iterator.m_SafetyReadWriteCount++;
                    }
                }
            }

            Assert.AreEqual(cache.ProcessTypesCount, iterator.m_SafetyReadWriteCount + iterator.m_SafetyReadOnlyCount);
#endif
        }
Example #21
0
 public void DestroyManager(ComponentSystemBase manager)
 {
     throw new NotImplementedException();
 }