<commit_before>// Copyright (c) ppy Pty Ltd <<EMAIL>>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

// ReSharper disable StaticMemberInGenericType

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using osuTK.Graphics.ES30;

namespace osu.Framework.Graphics.OpenGL.Vertices
{
    /// <summary>
    /// Helper method that provides functionality to enable and bind vertex attributes.
    /// </summary>
    internal static class VertexUtils<T>
        where T : IVertex
    {
        /// <summary>
        /// The stride of the vertex of type <see cref="T"/>.
        /// </summary>
        public static readonly int STRIDE = Marshal.SizeOf(default(T));

        private static readonly List<VertexMemberAttribute> attributes = new List<VertexMemberAttribute>();
        private static int amountEnabledAttributes;

        static VertexUtils()
        {
            addAttributesRecursive(typeof(T), 0);
        }

        private static void addAttributesRecursive(Type type, int currentOffset)
        {
            foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
            {
                int fieldOffset = currentOffset + Marshal.OffsetOf(type, field.Name).ToInt32();

                if (typeof(IVertex).IsAssignableFrom(field.FieldType))
                    addAttributesRecursive(field.FieldType, fieldOffset);
                else if (field.IsDefined(typeof(VertexMemberAttribute), true))
                {
                    var attrib = (VertexMemberAttribute)field.GetCustomAttribute(typeof(VertexMemberAttribute));

                    // Because this is an un-seen vertex, the attribute locations are unknown, but they're needed for marshalling
                    attrib.Offset = new IntPtr(fieldOffset);

                    attributes.Add(attrib);
                }
            }
        }

        /// <summary>
        /// Enables and binds the vertex attributes/pointers for the vertex of type <see cref="T"/>.
        /// </summary>
        public static void Bind()
        {
            enableAttributes(attributes.Count);
            for (int i = 0; i < attributes.Count; i++)
                GL.VertexAttribPointer(i, attributes[i].Count, attributes[i].Type, attributes[i].Normalized, STRIDE, attributes[i].Offset);
        }

        private static void enableAttributes(int amount)
        {
            if (amount == amountEnabledAttributes)
                return;

            if (amount > amountEnabledAttributes)
            {
                for (int i = amountEnabledAttributes; i < amount; ++i)
                    GL.EnableVertexAttribArray(i);
            }
            else
            {
                for (int i = amountEnabledAttributes - 1; i >= amount; --i)
                    GL.DisableVertexAttribArray(i);
            }

            amountEnabledAttributes = amount;
        }
    }
}
<commit_msg>Add comment<commit_after>// Copyright (c) ppy Pty Ltd <<EMAIL>>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

// ReSharper disable StaticMemberInGenericType

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using osuTK.Graphics.ES30;

namespace osu.Framework.Graphics.OpenGL.Vertices
{
    /// <summary>
    /// Helper method that provides functionality to enable and bind vertex attributes.
    /// </summary>
    internal static class VertexUtils<T>
        where T : IVertex
    {
        /// <summary>
        /// The stride of the vertex of type <see cref="T"/>.
        /// </summary>
        public static readonly int STRIDE = Marshal.SizeOf(default(T));

        private static readonly List<VertexMemberAttribute> attributes = new List<VertexMemberAttribute>();
        private static int amountEnabledAttributes;

        static VertexUtils()
        {
            addAttributesRecursive(typeof(T), 0);
        }

        private static void addAttributesRecursive(Type type, int currentOffset)
        {
            foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
            {
                int fieldOffset = currentOffset + Marshal.OffsetOf(type, field.Name).ToInt32();

                if (typeof(IVertex).IsAssignableFrom(field.FieldType))
                {
                    // Vertices may contain others, but the attributes of contained vertices belong to the parent when marshalled, so they are recursively added for their parent
                    // Their field offsets must be adjusted to reflect the position of the child attribute in the parent vertex
                    addAttributesRecursive(field.FieldType, fieldOffset);
                }
                else if (field.IsDefined(typeof(VertexMemberAttribute), true))
                {
                    var attrib = (VertexMemberAttribute)field.GetCustomAttribute(typeof(VertexMemberAttribute));

                    // Because this is an un-seen vertex, the attribute locations are unknown, but they're needed for marshalling
                    attrib.Offset = new IntPtr(fieldOffset);

                    attributes.Add(attrib);
                }
            }
        }

        /// <summary>
        /// Enables and binds the vertex attributes/pointers for the vertex of type <see cref="T"/>.
        /// </summary>
        public static void Bind()
        {
            enableAttributes(attributes.Count);
            for (int i = 0; i < attributes.Count; i++)
                GL.VertexAttribPointer(i, attributes[i].Count, attributes[i].Type, attributes[i].Normalized, STRIDE, attributes[i].Offset);
        }

        private static void enableAttributes(int amount)
        {
            if (amount == amountEnabledAttributes)
                return;

            if (amount > amountEnabledAttributes)
            {
                for (int i = amountEnabledAttributes; i < amount; ++i)
                    GL.EnableVertexAttribArray(i);
            }
            else
            {
                for (int i = amountEnabledAttributes - 1; i >= amount; --i)
                    GL.DisableVertexAttribArray(i);
            }

            amountEnabledAttributes = amount;
        }
    }
}

{'fraction_non_alphanumeric': 0.08923556942277691, 'fraction_numerical': 0.00218408736349454, 'mean_word_length': 1.9957943925233645, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6435238', 'n_tokens_mistral': 1601, 'n_tokens_neox': 1526, 'n_words': 455}