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())); }
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); }
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";