public static InjectComponentGroupData CreateInjection(Type injectedGroupType, FieldInfo groupField,
                                                               ComponentSystemBase system)
        {
            FieldInfo entityArrayField;
            FieldInfo indexFromEntityField;
            FieldInfo lengthField;
            FieldInfo componentGroupIndexField;

            var injectionContext          = new InjectionContext();
            var componentDataInjections   = new List <InjectionData>();
            var bufferDataInjections      = 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, out componentGroupIndexField,
                                             componentRequirements, componentDataInjections, bufferDataInjections, sharedComponentInjections);

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

            return(new InjectComponentGroupData(system, groupField, componentDataInjections.ToArray(),
                                                bufferDataInjections.ToArray(), sharedComponentInjections.ToArray(), entityArrayField,
                                                indexFromEntityField, injectionContext, lengthField, componentGroupIndexField,
                                                componentRequirements.ToArray()));
        }
Exemplo n.º 2
0
        private unsafe InjectComponentGroupData(ComponentSystemBase system, FieldInfo groupField,
                                                InjectionData[] componentDataInjections, InjectionData[] bufferArrayInjections,
                                                InjectionData[] sharedComponentInjections,
                                                FieldInfo entityArrayInjection, FieldInfo indexFromEntityInjection, InjectionContext injectionContext,
                                                FieldInfo lengthInjection, FieldInfo componentGroupIndexField, ComponentType[] componentRequirements)
        {
            m_EntityGroup = system.GetComponentGroupInternal(componentRequirements);

            m_ComponentGroupIndex = Array.IndexOf(system.ComponentGroups, m_EntityGroup);

            m_ComponentDataInjections   = componentDataInjections;
            m_BufferArrayInjections     = bufferArrayInjections;
            m_SharedComponentInjections = sharedComponentInjections;
            m_InjectionContext          = injectionContext;

            PatchGetIndexInComponentGroup(m_ComponentDataInjections);
            PatchGetIndexInComponentGroup(m_BufferArrayInjections);
            PatchGetIndexInComponentGroup(m_SharedComponentInjections);

            injectionContext.PrepareEntries(m_EntityGroup);

            if (entityArrayInjection != null)
            {
                m_EntityArrayOffset = UnsafeUtility.GetFieldOffset(entityArrayInjection);
            }
            else
            {
                m_EntityArrayOffset = -1;
            }

            if (lengthInjection != null)
            {
                m_LengthOffset = UnsafeUtility.GetFieldOffset(lengthInjection);
            }
            else
            {
                m_LengthOffset = -1;
            }

            m_GroupFieldOffset = UnsafeUtility.GetFieldOffset(groupField);

            if (componentGroupIndexField != null)
            {
                ulong gchandle;
                var   pinnedSystemPtr = (byte *)UnsafeUtility.PinGCObjectAndGetAddress(system, out gchandle);
                var   groupIndexPtr   = pinnedSystemPtr + m_GroupFieldOffset + UnsafeUtility.GetFieldOffset(componentGroupIndexField);

                int groupIndex = m_ComponentGroupIndex;
                UnsafeUtility.CopyStructureToPtr(ref groupIndex, groupIndexPtr);

                UnsafeUtility.ReleaseGCObject(gchandle);
            }
        }
        public override string ValidateField(FieldInfo field, bool isReadOnly, InjectionContext injectionInfo)
        {
            if (field.FieldType != typeof(ComponentArray <>))
            {
                return(null);
            }

            if (isReadOnly)
            {
                return("[ReadOnly] may not be used on ComponentArray<>, it can only be used on ComponentDataArray<>");
            }

            return(null);
        }
        InjectComponentGroupData(ComponentSystemBase system, FieldInfo groupField,
                                 InjectionData[] componentDataInjections, InjectionData[] fixedArrayInjections, InjectionData[] sharedComponentInjections,
                                 FieldInfo entityArrayInjection, FieldInfo indexFromEntityInjection, InjectionContext injectionContext,
                                 FieldInfo lengthInjection, ComponentType[] componentRequirements)
        {
            var requiredComponentTypes = componentRequirements;

            m_EntityGroup = system.GetComponentGroup(requiredComponentTypes);

            m_ComponentDataInjections   = componentDataInjections;
            m_FixedArrayInjections      = fixedArrayInjections;
            m_SharedComponentInjections = sharedComponentInjections;
            m_InjectionContext          = injectionContext;

            PatchGetIndexInComponentGroup(m_ComponentDataInjections);
            PatchGetIndexInComponentGroup(m_FixedArrayInjections);
            PatchGetIndexInComponentGroup(m_SharedComponentInjections);

            injectionContext.PrepareEntries(m_EntityGroup);

            if (entityArrayInjection != null)
            {
                m_EntityArrayOffset = UnsafeUtility.GetFieldOffset(entityArrayInjection);
            }
            else
            {
                m_EntityArrayOffset = -1;
            }

            if (indexFromEntityInjection != null)
            {
                m_IndexFromEntityOffset = UnsafeUtility.GetFieldOffset(indexFromEntityInjection);
            }
            else
            {
                m_IndexFromEntityOffset = -1;
            }

            if (lengthInjection != null)
            {
                m_LengthOffset = UnsafeUtility.GetFieldOffset(lengthInjection);
            }
            else
            {
                m_LengthOffset = -1;
            }

            m_GroupFieldOffset = UnsafeUtility.GetFieldOffset(groupField);
        }
        public override string ValidateField(FieldInfo field, bool isReadOnly, InjectionContext injectionInfo)
        {
            if (isReadOnly)
            {
                return("[ReadOnly] may not be used on a TransformAccessArray only on ComponentDataArray<>");
            }

            // Error on multiple TransformAccessArray
            if (injectionInfo.Entries.Any(i => i.FieldInfo.FieldType == typeof(TransformAccessArray)))
            {
                return("A [Inject] struct, may only contain a single TransformAccessArray");
            }

            return(null);
        }
 private unsafe InjectComponentGroupData(ComponentSystemBase system, FieldInfo groupField, InjectionData[] componentDataInjections, InjectionData[] bufferArrayInjections, InjectionData[] sharedComponentInjections, FieldInfo entityArrayInjection, FieldInfo indexFromEntityInjection, InjectionContext injectionContext, FieldInfo lengthInjection, FieldInfo componentGroupIndexField, ComponentType[] componentRequirements)
 {
     this.m_EntityGroup               = system.GetComponentGroupInternal(componentRequirements);
     this.m_ComponentGroupIndex       = Array.IndexOf <ComponentGroup>(system.ComponentGroups, this.m_EntityGroup);
     this.m_ComponentDataInjections   = componentDataInjections;
     this.m_BufferArrayInjections     = bufferArrayInjections;
     this.m_SharedComponentInjections = sharedComponentInjections;
     this.m_InjectionContext          = injectionContext;
     this.PatchGetIndexInComponentGroup(this.m_ComponentDataInjections);
     this.PatchGetIndexInComponentGroup(this.m_BufferArrayInjections);
     this.PatchGetIndexInComponentGroup(this.m_SharedComponentInjections);
     injectionContext.PrepareEntries(this.m_EntityGroup);
     if (entityArrayInjection != null)
     {
         this.m_EntityArrayOffset = UnsafeUtility.GetFieldOffset(entityArrayInjection);
     }
     else
     {
         this.m_EntityArrayOffset = -1;
     }
     if (lengthInjection != null)
     {
         this.m_LengthOffset = UnsafeUtility.GetFieldOffset(lengthInjection);
     }
     else
     {
         this.m_LengthOffset = -1;
     }
     this.m_GroupFieldOffset = UnsafeUtility.GetFieldOffset(groupField);
     if (componentGroupIndexField != null)
     {
         ulong num;
         UnsafeUtility.CopyStructureToPtr <int>(ref this.m_ComponentGroupIndex, (UnsafeUtility.PinGCObjectAndGetAddress(system, out num) + this.m_GroupFieldOffset) + UnsafeUtility.GetFieldOffset(componentGroupIndexField));
         UnsafeUtility.ReleaseGCObject(num);
     }
 }
        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)
        {
            //@TODO: Improve error messages...
            var fields =
                injectedGroupType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            entityArrayField         = null;
            indexFromEntityField     = null;
            lengthField              = null;
            componentGroupIndexField = 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(BufferArray <>))
                {
                    var injection = new InjectionData(field, field.FieldType.GetGenericArguments()[0], isReadOnly);

                    bufferDataInjections.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(int))
                {
                    if (field.Name != "Length" && field.Name != "GroupIndex")
                    {
                        return
                            ($"{system.GetType().Name}:{groupField.Name} Int in an [Inject] struct should be named \"Length\" (group length) or \"GroupIndex\" (index in ComponentGroup[])");
                    }

                    if (!field.IsInitOnly)
                    {
                        return
                            ($"{system.GetType().Name}:{groupField.Name} {field.Name} must use the \"readonly\" keyword");
                    }

                    if (field.Name == "Length")
                    {
                        lengthField = field;
                    }

                    if (field.Name == "GroupIndex")
                    {
                        componentGroupIndexField = 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);
        }
        static string CollectInjectedGroup(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("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("A [Inject] struct, may only contain a single EntityArray");
                    }

                    entityArrayField = field;
                }
                else if (field.FieldType == typeof(IndexFromEntity))
                {
                    // Error on multiple IndexFromEntity
                    if (indexFromEntityField != null)
                    {
                        return("A [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("A [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
                            ($"[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);
        }
Exemplo n.º 9
0
 public abstract string ValidateField(FieldInfo field, bool isReadOnly, InjectionContext injectionInfo);
        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";