public void Start()
        {
            UMAAssetIndexer index = UMAAssetIndexer.Instance;

            races = index.GetAllAssets <RaceData>();
#if UMA_ADDRESSABLES
            // Preload all the races.
            List <string> labels = new List <string>();
            labels.Add("UMA_Recipes");

            // Because of a bug in the current addressables implementation (crashes if you pass a
            // label that doesn't exist), we'll need to check first to see if they are there.
            // If so, they'll need to be loaded first, so they can be sorted into the availablerecipes.
            // Your app will know this in advance, and know whether to just call
            // LoadLabelList.
            // But since we don't know that for this sample, we'll check for resource locators, which
            // doesn't crash.

            var op = Addressables.LoadResourceLocationsAsync("UMA_Recipes");

            if (op.Result != null && op.Result.Count > 1)
            {
                var recipeOp = UMAAssetIndexer.Instance.LoadLabelList(labels, true); // Load the recipes!
                recipeOp.Completed += Recipes_Loaded;
            }

            if (RaceDropdown != null)
            {
                RaceDropdown.options.Clear();
                foreach (RaceData race in races)
                {
                    RaceDropdown.options.Add(new Dropdown.OptionData(race.raceName));
                }
            }
            else
            {
                if (PreloadAndUnload)
                {
                    var asyncop = UMAAssetIndexer.Instance.Preload(races, true); // Base races will always be loaded.
                    asyncop.Completed += Asyncop_Completed;
                }
            }
#else
            Avatar.gameObject.SetActive(true);
            if (RaceDropdown != null)
            {
                RaceDropdown.options.Clear();
                foreach (RaceData race in races)
                {
                    RaceDropdown.options.Add(new Dropdown.OptionData(race.raceName));
                }
            }
#endif
        }
        private void SetupMenus()
        {
            _FileMenu         = new GenericMenu();
            _AddressablesMenu = new GenericMenu();
            _ItemsMenu        = new GenericMenu();

            AddPlugins(GetAddressablePlugins());

            // ***********************************************************************************
            // File Menu items
            // ***********************************************************************************
            AddMenuItemWithCallback(FileMenu, "Rebuild From Project", () =>
            {
                UAI.Clear();
                UAI.AddEverything(false);
                Resources.UnloadUnusedAssets();
                m_Initialized = false;
                Repaint();
            });

            AddMenuItemWithCallback(FileMenu, "Rebuild From Project (include text assets)", () =>
            {
                UAI.Clear();
                UAI.AddEverything(true);
                Resources.UnloadUnusedAssets();
                m_Initialized = false;
                Repaint();
            });
            AddMenuItemWithCallback(FileMenu, "Cleanup References", () =>
            {
                UAI.UpdateReferences();
                Resources.UnloadUnusedAssets();
                m_Initialized = false;
                Repaint();
                EditorUtility.DisplayDialog("Repair", "References cleaned", "OK");
            });

            AddMenuItemWithCallback(FileMenu, "Repair and remove invalid items", () =>
            {
                UAI.RepairAndCleanup();
                Resources.UnloadUnusedAssets();
                m_Initialized = false;
                Repaint();
                EditorUtility.DisplayDialog("Repair", "AssetIndex successfully repaired", "OK");
            });

            /* AddMenuItemWithCallback(FileMenu, "Add Build refs to all non-addressables", () =>
             * {
             *      UAI.AddReferences();
             *      RecountTypes();
             *      Resources.UnloadUnusedAssets();
             *      Repaint();
             * });
             * AddMenuItemWithCallback(FileMenu, "Clear build refs from all items", () =>
             * {
             *      UAI.ClearReferences();
             *      Resources.UnloadUnusedAssets();
             *      RecountTypes();
             *      Repaint();
             * }); */
            FileMenu.AddSeparator("");
            AddMenuItemWithCallback(FileMenu, "Toggle Utilities Panel", () =>
            {
                ShowUtilities = !ShowUtilities;
                Repaint();
            });
            FileMenu.AddSeparator("");

            AddMenuItemWithCallback(FileMenu, "Empty Index", () =>
            {
                UAI.Clear();
                m_Initialized = false;
                Repaint();
            });

#if UMA_ADDRESSABLES
            foreach (IUMAAddressablePlugin plugin in addressablePlugins)
            {
                AddMenuItemWithCallbackParm(_AddressablesMenu, "Generators/" + plugin.Menu, (object o) =>
                {
                    IUMAAddressablePlugin addrplug = o as IUMAAddressablePlugin;
                    UMAAddressablesSupport.Instance.GenerateAddressables(addrplug);
                    Resources.UnloadUnusedAssets();
                    m_Initialized = false;
                    Repaint();
                }, plugin);
            }

            _AddressablesMenu.AddSeparator("Generators/");

            // ***********************************************************************************
            // Addressables Menu items
            // ***********************************************************************************
            AddMenuItemWithCallback(_AddressablesMenu, "Generators/Generate Groups (optimized)", () =>
            {
                UMAAddressablesSupport.Instance.CleanupAddressables();
                UMAAddressablesSupport.Instance.GenerateAddressables();
                Resources.UnloadUnusedAssets();
                m_Initialized = false;
                Repaint();
            });

            /* AddMenuItemWithCallback(AddressablesMenu, "Generators/Generate Shared Group (fast)", () =>
             * {
             *      UAI.CleanupAddressables();
             *      UAI.GenerateSingleGroup();
             *      Resources.UnloadUnusedAssets();
             *      m_Initialized = false;
             *      Repaint();
             * });
             *
             * AddMenuItemWithCallback(AddressablesMenu, "Generators/Generate Shared Group (incl recipes)", () =>
             * {
             *      UAI.CleanupAddressables();
             *      UAI.GenerateSingleGroup(true);
             *      Resources.UnloadUnusedAssets();
             *      m_Initialized = false;
             *      Repaint();
             * }); */

            AddMenuItemWithCallback(_AddressablesMenu, "Remove Addressables", () =>
            {
                UMAAddressablesSupport.Instance.CleanupAddressables(false, true);
                m_Initialized = false;
                Repaint();
            });
            AddMenuItemWithCallback(_AddressablesMenu, "Delete Empty Groups", () =>
            {
                UMAAddressablesSupport.Instance.CleanupAddressables(true);
            });

            /*
             * AddMenuItemWithCallback(AddressablesMenu, "Force Add Refs (Bad!!)", () =>
             * {
             *      UAI.AddReferences(true);
             *      RecountTypes();
             *      Resources.UnloadUnusedAssets();
             *      Repaint();
             * }); */

            AddMenuItemWithCallback(_AddressablesMenu, "Remove Orphaned Slots", () =>
            {
                if (EditorUtility.DisplayDialog("Warning!", "You *must* build the addressable groups, and mark any slots you want to keep as 'keep' before running this!", "OK", "Cancel"))
                {
                    UMAAddressablesSupport.Instance.CleanupOrphans(typeof(SlotDataAsset));
                    m_Initialized = false;
                    Repaint();
                }
            });
            AddMenuItemWithCallback(_AddressablesMenu, "Remove Orphaned Overlays", () =>
            {
                if (EditorUtility.DisplayDialog("Warning!", "You *must* build the addressable groups, and mark any slots you want to keep as 'keep' before running this.", "OK", "Cancel"))
                {
                    UMAAddressablesSupport.Instance.CleanupOrphans(typeof(OverlayDataAsset));
                    m_Initialized = false;
                    Repaint();
                }
            });
#else
            AddMenuItemWithCallback(_AddressablesMenu, "Enable Addressables (Package must be installed first)", () =>
            {
                if (EditorUtility.DisplayDialog("Warning!", "The Addressables Package must be installed first before enabling Addressables support in UMA. Enabling addressables will trigger a recompile during which the library will be unavailable.", "OK", "Cancel"))
                {
                    var defineSymbols = new HashSet <string>(PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup).Split(';'));
                    defineSymbols.Add("UMA_ADDRESSABLES");
                    PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, string.Join(";", defineSymbols));
                    m_Initialized = false;
                    Repaint();
                }
            });
#endif
            // ***********************************************************************************
            // Items Menu items
            // ***********************************************************************************
            AddMenuItemWithCallback(ItemsMenu, "Select All", () =>
            {
                var treeElements = new List <AssetTreeElement>();
                TreeElementUtility.TreeToList <AssetTreeElement>(treeView.treeModel.root, treeElements);
                foreach (AssetTreeElement ate in treeElements)
                {
                    ate.Checked = true;
                }
                treeView.RecalcTypeChecks();
                Repaint();
                return;
            });

            AddMenuItemWithCallback(ItemsMenu, "Clear Selection", () =>
            {
                var treeElements = new List <AssetTreeElement>();
                TreeElementUtility.TreeToList <AssetTreeElement>(treeView.treeModel.root, treeElements);
                foreach (AssetTreeElement ate in treeElements)
                {
                    ate.Checked = false;
                }
                treeView.RecalcTypeChecks();
                Repaint();
                return;
            });

            foreach (RaceData rc in UAI.GetAllAssets <RaceData>())
            {
                if (rc != null)
                {
                    AddMenuItemWithCallbackParm(ItemsMenu, "Select Slots + Overlays By Race/" + rc.raceName, SelectByRace, rc);
                    AddMenuItemWithCallbackParm(ItemsMenu, "Select Slots By Race/" + rc.raceName, SelectSlotsByRace, rc);
                    AddMenuItemWithCallbackParm(ItemsMenu, "Select Overlays By Race/" + rc.raceName, SelectOverlaysByRace, rc);
                }
            }

            ItemsMenu.AddSeparator("");

            AddMenuItemWithCallback(ItemsMenu, "Add Keep Flag to Selected Items", () =>
            {
                MarkKeep(true);
                Repaint();
                return;
            });

            AddMenuItemWithCallback(ItemsMenu, "Clear Keep Flag from Selected Items", () =>
            {
                MarkKeep(false);
                Repaint();
                return;
            });

            ItemsMenu.AddSeparator("");

            AddMenuItemWithCallback(ItemsMenu, "Remove Selected", () =>
            {
                RemoveSelected();
                m_Initialized = false;
                Repaint();
                return;
            });
            AddMenuItemWithCallback(ItemsMenu, "Force Selected Items to Save", () =>
            {
                ForceSave();
                m_Initialized = false;
                Repaint();
                return;
            });
        }