private static void CreateLayoutRecurse(Type type, int baseOffset, List <Layout> layouts, ref int begin, ref int end, ref int typeHash) { var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); var fieldsWithOffset = new FieldData[fields.Length]; for (int i = 0; i != fields.Length; i++) { fieldsWithOffset[i].Offset = UnsafeUtility.GetFieldOffset(fields[i]); fieldsWithOffset[i].Field = fields[i]; } Array.Sort(fieldsWithOffset, (a, b) => a.Offset - b.Offset); foreach (var fieldWithOffset in fieldsWithOffset) { var field = fieldWithOffset.Field; var fixedBuffer = GetFixedBufferAttribute(field); var offset = baseOffset + fieldWithOffset.Offset; if (fixedBuffer != null) { var stride = UnsafeUtility.SizeOf(fixedBuffer.ElementType); for (int i = 0; i < fixedBuffer.Length; ++i) { CreateLayoutRecurse(fixedBuffer.ElementType, offset + i * stride, layouts, ref begin, ref end, ref typeHash); } } else if (field.FieldType.IsPrimitive || field.FieldType.IsPointer || field.FieldType.IsClass || field.FieldType.IsEnum) { CombineHash(ref typeHash, offset, (int)Type.GetTypeCode(field.FieldType)); var sizeOf = -1; if (field.FieldType.IsPointer || field.FieldType.IsClass) { sizeOf = UnsafeUtility.SizeOf <PointerSize>(); } else if (field.FieldType.IsEnum) { //@TODO: Workaround IL2CPP bug // sizeOf = UnsafeUtility.SizeOf(field.FieldType); sizeOf = UnsafeUtility.SizeOf(field.FieldType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)[0].FieldType); } else { sizeOf = UnsafeUtility.SizeOf(field.FieldType); } if (end != offset) { layouts.Add(new Layout { offset = begin, count = end - begin, Aligned4 = false }); begin = offset; end = offset + sizeOf; } else { end += sizeOf; } } else { CreateLayoutRecurse(field.FieldType, offset, layouts, ref begin, ref end, ref typeHash); } } }
private static void CreateLayoutRecurse(Type type, int baseOffset, List <Layout> layouts, ref int begin, ref int end, ref int typeHash) { FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); FieldData[] array = new FieldData[fields.Length]; int index = 0; while (true) { if (index == fields.Length) { Array.Sort <FieldData>(array, (a, b) => a.Offset - b.Offset); foreach (FieldData data in array) { FieldInfo field = data.Field; FixedBufferAttribute fixedBufferAttribute = GetFixedBufferAttribute(field); int num3 = baseOffset + data.Offset; if (fixedBufferAttribute != null) { int num4 = UnsafeUtility.SizeOf(fixedBufferAttribute.ElementType); int num5 = 0; while (true) { if (num5 >= fixedBufferAttribute.Length) { break; } CreateLayoutRecurse(fixedBufferAttribute.ElementType, num3 + (num5 * num4), layouts, ref begin, ref end, ref typeHash); num5++; } } else { int isEnum; if ((field.FieldType.IsPrimitive || field.FieldType.IsPointer) || field.FieldType.IsClass) { isEnum = 1; } else { isEnum = (int)field.FieldType.IsEnum; } if (isEnum == 0) { CreateLayoutRecurse(field.FieldType, num3, layouts, ref begin, ref end, ref typeHash); } else { int[] values = new int[] { num3, (int)Type.GetTypeCode(field.FieldType) }; CombineHash(ref typeHash, values); int num6 = -1; if (field.FieldType.IsPointer || field.FieldType.IsClass) { num6 = UnsafeUtility.SizeOf <PointerSize>(); } else if (field.FieldType.IsEnum) { num6 = UnsafeUtility.SizeOf(field.FieldType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)[0].FieldType); } else { num6 = UnsafeUtility.SizeOf(field.FieldType); } if (end == num3) { end += num6; } else { Layout item = new Layout { offset = begin, count = end - begin, Aligned4 = false }; layouts.Add(item); begin = num3; end = num3 + num6; } } } } return; } array[index].Offset = UnsafeUtility.GetFieldOffset(fields[index]); array[index].Field = fields[index]; index++; } }