/// <summary> /// Function to normalize the offsets in the element list. /// </summary> public void NormalizeOffsets() { int lastOffset = 0; for (int i = 0; i < _elements.Length - 1; i++) { _elements[i] = new GorgonInputElement(_elements[i], lastOffset); lastOffset += _elements[i].Size; } }
/// <summary> /// Function to determine if an element already exists with the same context, index and slot. /// </summary> /// <param name="element"></param> private void FindDuplicateElements(GorgonInputElement element) { if (_elements.Any( elementItem => !string.IsNullOrWhiteSpace(elementItem.Context) && ((element.Offset == elementItem.Offset) || (string.Equals(element.Context, elementItem.Context, StringComparison.OrdinalIgnoreCase))) && element.Index == elementItem.Index && element.Slot == elementItem.Slot)) { throw new ArgumentException( string.Format(Resources.GORGFX_LAYOUT_ELEMENT_IN_USE, element.Offset, element.Context), "element"); } }
/// <summary> /// Function to retrieve the input layout from a specific type. /// </summary> /// <param name="type">Type of retrieve layout info from.</param> /// <remarks>Use this to create an input element layout from a type. Properties and fields in this type must be marked with the <see cref="GorgonLibrary.Graphics.InputElementAttribute">GorgonInputElementAttribute</see> in order for the element list to consider it and those fields or properties must be public. /// <para>Fields/properties marked with the attribute must be either a (u)byte, (u)short, (u)int, (u)long, float or one of the Vector2/3/4D types.</para> /// </remarks> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="type"/> parameter is NULL (Nothing in VB.Net).</exception> /// <exception cref="GorgonLibrary.GorgonException">Thrown if a field/property type cannot be mapped to a <see cref="GorgonLibrary.Graphics.BufferFormat">GorgonBufferFormat</see>.</exception> internal void InitializeFromType(Type type) { IList <MemberInfo> members = type.GetMembers(); int byteOffset = 0; if (type == null) { throw new ArgumentNullException("type"); } // Get only properties and fields, and sort by explicit ordering (then by offset). var propertiesAndFields = (from member in members let memberAttribute = member.GetCustomAttributes(typeof(InputElementAttribute), true) as IList <InputElementAttribute> where ((member.MemberType == MemberTypes.Property) || (member.MemberType == MemberTypes.Field)) && ((memberAttribute != null) && (memberAttribute.Count > 0)) orderby memberAttribute[0].ExplicitOrder, memberAttribute[0].Offset select new { member.Name, ReturnType = (member is FieldInfo ? ((FieldInfo)member).FieldType : ((PropertyInfo)member).PropertyType), Attribute = memberAttribute[0] }).ToArray(); _elements = new GorgonInputElement[propertiesAndFields.Length]; for (int i = 0; i < _elements.Length; i++) { var item = propertiesAndFields[i]; BufferFormat format = item.Attribute.Format; string contextName = item.Attribute.Context; // Try to determine the format from the type. if (format == BufferFormat.Unknown) { if (!_typeMapping.ContainsKey(item.ReturnType)) { throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_LAYOUT_INVALID_ELEMENT_TYPE, item.ReturnType.FullName)); } format = _typeMapping[item.ReturnType]; } // Determine the context name from the field name. if (string.IsNullOrEmpty(contextName)) { contextName = item.Name; } var element = new GorgonInputElement(contextName, format, (item.Attribute.AutoOffset ? byteOffset : item.Attribute.Offset), item.Attribute.Index, item.Attribute.Slot, item.Attribute.Instanced, item.Attribute.InstanceCount); FindDuplicateElements(element); _elements[i] = element; byteOffset += element.Size; } UpdateVertexSize(); }