static void UpdateSkyTypes()
        {
            if (m_SkyTypesDict == null)
            {
                m_SkyTypesDict = new Dictionary <int, Type>();

                var skyTypes = CoreUtils.GetAllTypesDerivedFrom <SkySettings>().Where(t => !t.IsAbstract);
                foreach (Type skyType in skyTypes)
                {
                    var uniqueIDs = skyType.GetCustomAttributes(typeof(SkyUniqueID), false);
                    if (uniqueIDs.Length == 0)
                    {
                        Debug.LogWarningFormat("Missing attribute SkyUniqueID on class {0}. Class won't be registered as an available sky.", skyType);
                    }
                    else
                    {
                        int uniqueID = ((SkyUniqueID)uniqueIDs[0]).uniqueID;
                        if (uniqueID == 0)
                        {
                            Debug.LogWarningFormat("0 is a reserved SkyUniqueID and is used in class {0}. Class won't be registered as an available sky.", skyType);
                            continue;
                        }

                        Type value;
                        if (m_SkyTypesDict.TryGetValue(uniqueID, out value))
                        {
                            Debug.LogWarningFormat("SkyUniqueID {0} used in class {1} is already used in class {2}. Class won't be registered as an available sky.", uniqueID, skyType, value);
                            continue;
                        }

                        m_SkyTypesDict.Add(uniqueID, skyType);
                    }
                }
            }
        }
        static void ReloadDocumentation()
        {
            if (m_EditorDocumentationURLs == null)
            {
                m_EditorDocumentationURLs = new Dictionary <Type, string>();
            }
            m_EditorDocumentationURLs.Clear();

            string GetVolumeComponentDocumentation(Type component)
            {
                var attrs = component.GetCustomAttributes(false);

                foreach (var attr in attrs)
                {
                    if (attr is HelpURLAttribute attrDocumentation)
                    {
                        return(attrDocumentation.URL);
                    }
                }

                // There is no documentation for this volume component.
                return(null);
            }

            var componentTypes = CoreUtils.GetAllTypesDerivedFrom <VolumeComponent>();

            foreach (var componentType in componentTypes)
            {
                if (!m_EditorDocumentationURLs.ContainsKey(componentType))
                {
                    m_EditorDocumentationURLs.Add(componentType, GetVolumeComponentDocumentation(componentType));
                }
            }
        }
        static string[] s_DisplayTypes; // Pretty names

        static DebugUIHandlerCanvasEditor()
        {
            s_Types = CoreUtils.GetAllTypesDerivedFrom <DebugUI.Widget>()
                      .Where(t => !t.IsAbstract)
                      .Select(t => t.AssemblyQualifiedName)
                      .ToArray();

            s_DisplayTypes = new string[s_Types.Length];
            for (int i = 0; i < s_Types.Length; i++)
            {
                s_DisplayTypes[i] = Type.GetType(s_Types[i]).Name;
            }
        }
        static void ReloadDecoratorTypes()
        {
            s_ParameterDrawers.Clear();

            // Look for all the valid parameter drawers
            var types = CoreUtils.GetAllTypesDerivedFrom <VolumeParameterDrawer>()
                        .Where(
                t => t.IsDefined(typeof(VolumeParameterDrawerAttribute), false) &&
                !t.IsAbstract
                );

            // Store them
            foreach (var type in types)
            {
                var attr      = (VolumeParameterDrawerAttribute)type.GetCustomAttributes(typeof(VolumeParameterDrawerAttribute), false)[0];
                var decorator = (VolumeParameterDrawer)Activator.CreateInstance(type);
                s_ParameterDrawers.Add(attr.parameterType, decorator);
            }
        }
        public void Init(VolumeProfile asset, SerializedObject serializedObject)
        {
            Assert.IsNotNull(asset);
            Assert.IsNotNull(serializedObject);

            this.asset           = asset;
            m_SerializedObject   = serializedObject;
            m_ComponentsProperty = serializedObject.Find((VolumeProfile x) => x.components);
            Assert.IsNotNull(m_ComponentsProperty);

            m_EditorTypes = new Dictionary <Type, Type>();
            m_Editors     = new List <VolumeComponentEditor>();

            // Gets the list of all available component editors
            var editorTypes = CoreUtils.GetAllTypesDerivedFrom <VolumeComponentEditor>()
                              .Where(
                t => t.IsDefined(typeof(VolumeComponentEditorAttribute), false) &&
                !t.IsAbstract
                );

            // Map them to their corresponding component type
            foreach (var editorType in editorTypes)
            {
                var attribute = (VolumeComponentEditorAttribute)editorType.GetCustomAttributes(typeof(VolumeComponentEditorAttribute), false)[0];
                m_EditorTypes.Add(attribute.componentType, editorType);
            }

            // Create editors for existing components
            var components = asset.components;

            for (int i = 0; i < components.Count; i++)
            {
                CreateEditor(components[i], m_ComponentsProperty.GetArrayElementAtIndex(i));
            }

            // Keep track of undo/redo to redraw the inspector when that happens
            Undo.undoRedoPerformed += OnUndoRedoPerformed;
        }