private bool AvailablePluginsGUI(AbstractPluginDefinition.PluginCategory category)
        {
            List <AbstractPluginDefinition> plugins;

            try
            {
                plugins = availablePluginsCache[category];
                if (plugins.Count > 0)
                {
                    EditorGUILayout.LabelField("Available for use");
                    for (int i = availablePluginsCache[category].Count - 1; i >= 0; i--)
                    {
                        AbstractPluginDefinition defn = availablePluginsCache[category][i];

                        EditorGUILayout.BeginHorizontal();
                        EditorGUI.indentLevel++;

                        float columnWidth = EditorGUIUtility.currentViewWidth / 3;
                        EditorGUILayout.LabelField(defn.GetReadableName(), GUILayout.Width(columnWidth));

                        bool hasManager = manager.gameObject.GetComponentInChildren(defn.GetManagerType()) != null;
                        if (!hasManager || defn.MultipleAllowed)
                        {
                            if (GUILayout.Button("Enable"))
                            {
                                defn.Enable();
                                timeOfNextPluginRefresh = DateTime.Now;
                                UpdateAllPluginDefinitions();
                            }
                            if (GUILayout.Button("Learn more"))
                            {
                                Application.OpenURL(defn.GetURL());
                            }
                        }

                        EditorGUI.indentLevel--;
                        EditorGUILayout.EndHorizontal();
                    }
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            catch (KeyNotFoundException e)
            {
                return(false);
            }
        }
        /// <summary>
        /// Finds all the plugin implementations of a given type and updates their status in
        /// the internal cache:
        ///
        /// `avaiallbePluginsCache` - Available to be used, but not enabled in the scene.
        /// `enabledPluginsCache` - Available to be used and enabled in the scene.
        /// `supportedPluginsCache` - Known plugins that are not yet available for use (likely has a dependency on a missing asset)
        /// </summary>
        /// <param name="T"></param>
        private void UpdatePluginStatus(Type T)
        {
            // Iterate over all the known plugins of this type
            IEnumerable <Type> plugins = ReflectionHelper.GetEnumerableOfType(T);

            foreach (Type pluginType in plugins)
            {
                // If any dependencies are present then provide enable/disable buttons, otherwise provide more info only
                AbstractPluginDefinition pluginDef = Activator.CreateInstance(pluginType) as AbstractPluginDefinition;
                if (pluginDef.AvailableForUse)
                {
                    bool isAvailable = true;
                    // See if there are any existing instances of this plugin in the scene
                    Component[]             components     = manager.GetComponentsInChildren(pluginDef.GetManagerType());
                    AbstractPluginManager[] pluginManagers = Array.ConvertAll(components, item => (AbstractPluginManager)item);

                    if (pluginManagers != null && pluginManagers.Count() != 0)
                    {
                        for (int i = 0; i < pluginManagers.Count(); i++)
                        {
                            AbstractPluginProfile pluginProfile = pluginManagers[i].m_pluginProfile;
                            if (pluginProfile != null && pluginDef.GetProfileTypeName().EndsWith(pluginProfile.GetType().Name))
                            {
                                AddToCache(enabledPluginsCache, pluginDef);
                                if (!pluginDef.MultipleAllowed)
                                {
                                    isAvailable = false;
                                }
                            }
                        }
                    }

                    if (isAvailable)
                    {
                        // There are no existing managers in the scene or multiple are allowed, show enable options
                        AddToCache(availablePluginsCache, pluginDef);
                    }
                }
                else
                {
                    AddToCache(supportedPluginsCache, pluginDef);
                }
            }
        }
        private bool EnabledPluginsGUI(AbstractPluginDefinition.PluginCategory category)
        {
            try {
                if (enabledPluginsCache[category].Count > 0)
                {
                    GUILayout.Label("Currently Enabled");
                    for (int i = enabledPluginsCache[category].Count - 1; i >= 0; i--)
                    {
                        AbstractPluginDefinition defn = enabledPluginsCache[category][i];

                        Component pluginManager = manager.gameObject.GetComponentsInChildren(defn.GetManagerType())[i];

                        EditorGUILayout.BeginHorizontal();
                        EditorGUI.indentLevel++;

                        float columnWidth = EditorGUIUtility.currentViewWidth / 3;
                        EditorGUILayout.LabelField(pluginManager.name + " (" + defn.GetReadableName() + ")", GUILayout.Width(columnWidth));

                        if (GUILayout.Button("Disable"))
                        {
                            DestroyImmediate(pluginManager.gameObject);
                            timeOfNextPluginRefresh = DateTime.Now;
                            UpdateAllPluginDefinitions();
                        }
                        if (GUILayout.Button("Learn more"))
                        {
                            Application.OpenURL(defn.GetURL());
                        }

                        EditorGUI.indentLevel--;
                        EditorGUILayout.EndHorizontal();
                    }
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            catch (KeyNotFoundException e)
            {
                return(false);
            }
        }
 /// <summary>
 /// Add a plugin definition to a cache.
 /// </summary>
 /// <param name="cache"></param>
 /// <param name="defn"></param>
 private void AddToCache(Dictionary <AbstractPluginDefinition.PluginCategory, List <AbstractPluginDefinition> > cache, AbstractPluginDefinition defn)
 {
     try
     {
         cache[defn.GetCategory()].Add(defn);
     } catch (KeyNotFoundException e)
     {
         List <AbstractPluginDefinition> list = new List <AbstractPluginDefinition>();
         list.Add(defn);
         cache.Add(defn.GetCategory(), list);
     }
 }