public override void OnGUI(Rect rect)
            {
                InitializeStyles();

                List <GeneratorTreeItem> items;

                var selectedCategory = _openCategory;

                if (_openCategory == null)
                {
                    items = _generatorTree;

                    GUILayout.Label(GUIContent.none, _titleStyle, GUILayout.ExpandWidth(true));
                    var titleRect     = GUILayoutUtility.GetLastRect();
                    var titleTextRect = titleRect;
                    titleTextRect.yMin += 4;
                    GUI.Label(titleTextRect, "Generator", _titleTextStyle);
                }
                else
                {
                    items = _openCategory.items;

                    GUILayout.Label(GUIContent.none, _titleStyle, GUILayout.ExpandWidth(true));
                    var titleRect = GUILayoutUtility.GetLastRect();
                    if (GUI.Button(titleRect, GUIContent.none, GUIStyle.none))
                    {
                        selectedCategory = selectedCategory.parent;
                    }
                    var titleTextRect = titleRect;
                    titleTextRect.yMin += 4;
                    GUI.Label(titleTextRect, _openCategory.content, _subtitleTextStyle);

                    GUI.DrawTexture(
                        new Rect(
                            5f,
                            titleRect.yMin + (titleRect.height - _leftArrowTexture.height) / 2f + 1f,
                            _leftArrowTexture.width,
                            _leftArrowTexture.height),
                        _leftArrowTexture,
                        ScaleMode.ScaleAndCrop,
                        true);
                }

                _scrollPosition = GUILayout.BeginScrollView(_scrollPosition, false, false);

                foreach (var item in items)
                {
                    if (item is GeneratorTreeCategory)
                    {
                        var category = (GeneratorTreeCategory)item;
                        GUIExtensions.PushEnable(category.items.Count > 0);
                        if (GUILayout.Button(category.content, _categoryStyle))
                        {
                            selectedCategory = category;
                        }
                        GUIExtensions.PopEnable();

                        var categoryRect = GUILayoutUtility.GetLastRect();

                        GUI.DrawTexture(
                            new Rect(
                                categoryRect.xMax - _rightArrowTexture.width - 1f,
                                categoryRect.yMin + (categoryRect.height - _rightArrowTexture.height) / 2f,
                                _rightArrowTexture.width,
                                _rightArrowTexture.height),
                            _rightArrowTexture,
                            ScaleMode.ScaleAndCrop,
                            true);
                    }
                    else if (item is GeneratorTreeGenerator)
                    {
                        var generator = (GeneratorTreeGenerator)item;
                        GUIExtensions.PushEnable(generator.onSelect != null);
                        if (GUILayout.Button(generator.content, _generatorStyle))
                        {
                            generator.onSelect(_executive, _executive.generators.Count);
                            editorWindow.Close();
                        }
                        GUIExtensions.PopEnable();
                    }
                }

                GUILayout.EndScrollView();

                editorWindow.Repaint();

                _openCategory = selectedCategory;
            }
        public static bool OnInspectorGUI(OutputSlot output, bool foldout, AnimBool foldoutAnimation)
        {
            InitializeStyles();

            float foldoutMinWidth, foldoutMaxWidth;

            EditorStyles.foldout.CalcMinMaxWidth(GUIContent.none, out foldoutMinWidth, out foldoutMaxWidth);

            EditorGUILayout.BeginVertical(_outlineStyle);

            EditorGUILayout.BeginHorizontal();
            var foldoutRect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight, GUILayout.Width(0));

            foldout = EditorGUI.Foldout(foldoutRect, foldout, GUIContent.none, false);
            foldoutAnimation.target = foldout;
            EditorGUILayout.BeginVertical();

            if (foldout)
            {
                EditorGUILayout.BeginHorizontal();
                output.isEnabled = EditorGUILayout.ToggleLeft("Enabled", output.isEnabled, GUILayout.Width(EditorStyles.toggle.CalcSize(new GUIContent("Enabled")).x));
                GUIExtensions.PushEnable(output.isEnabled);
                if (output.mustBeAvailableAfterGeneration)
                {
                    output.availability = (OutputSlot.Availability)EditorGUILayout.IntPopup((int)output.availability, _alwaysAfterAvailabilityContent, _alwaysAfterAvailabilityValues);
                }
                else if (output.canBeAvailableAfterGeneration)
                {
                    output.availability = (OutputSlot.Availability)EditorGUILayout.IntPopup((int)output.availability, _fullAvailabilityContent, _fullAvailabilityValues);
                }
                else
                {
                    output.availability = (OutputSlot.Availability)EditorGUILayout.IntPopup((int)output.availability, _neverAfterAvailabilityContent, _neverAfterAvailabilityValues);
                }
                EditorGUILayout.EndHorizontal();
            }
            else
            {
                EditorGUILayout.BeginHorizontal();
                output.isEnabled = EditorGUILayout.Toggle(output.isEnabled, GUILayout.Width(EditorStyles.toggle.CalcSize(GUIContent.none).x));
                GUIExtensions.PushEnable(output.isEnabled);
                EditorGUILayout.LabelField(new GUIContent(string.Format("{0} ({1})", output.name, output.assetType.GetPrettyName()), output.assetType.GetPrettyName(true)));
                EditorGUILayout.EndHorizontal();
            }

            if (EditorGUILayout.BeginFadeGroup(foldoutAnimation.faded))
            {
                var priorLabelWidth = EditorGUIUtility.labelWidth;

                var labelWidth = 0f;
                labelWidth = Mathf.Max(labelWidth, EditorStyles.label.CalcSize(new GUIContent("Name")).x);
                labelWidth = Mathf.Max(labelWidth, EditorStyles.label.CalcSize(new GUIContent("Type")).x);
                if (output.canBeGrouped)
                {
                    labelWidth = Mathf.Max(labelWidth, EditorStyles.label.CalcSize(new GUIContent("Group")).x);
                }

                EditorGUIUtility.labelWidth = labelWidth;
                output.name = EditorGUILayout.TextField("Name", output.name);

                if (output.canBeGrouped)
                {
                    EditorGUILayout.BeginHorizontal();
                    output.path = EditorGUILayout.TextField("Path", output.path);
                    var assetPaths       = output.generator.executive.GetAllAssetPaths("<none>");
                    var currentPathIndex = System.Array.IndexOf(assetPaths, output.path);
                    if (currentPathIndex == -1)
                    {
                        currentPathIndex = 0;
                    }
                    currentPathIndex = EditorGUILayout.Popup(currentPathIndex, assetPaths, GUILayout.Width(EditorGUIUtility.singleLineHeight));
                    output.path      = currentPathIndex == 0 ? "" : assetPaths[currentPathIndex];
                    EditorGUILayout.EndHorizontal();
                }

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.PrefixLabel("Type");
                EditorGUILayout.SelectableLabel(output.assetType.GetPrettyName(), EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
                EditorGUILayout.EndHorizontal();
                var typeRect = GUILayoutUtility.GetLastRect();
                GUI.Label(typeRect, new GUIContent("", output.assetType.GetPrettyName(true)));

                EditorGUIUtility.labelWidth = priorLabelWidth;
            }
            EditorGUILayout.EndFadeGroup();

            EditorGUILayout.EndVertical();
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();

            GUIExtensions.PopEnable();

            return(foldout);
        }
        public override void OnInspectorGUI()
        {
            InitializeStyles();

            if (AssetDatabase.Contains(_executive))
            {
                var path = System.IO.Path.GetFileName(System.IO.Path.GetDirectoryName(AssetDatabase.GetAssetPath(_executive)));
                GUI.Label(new Rect(44f, 24f, Mathf.Max(0f, Screen.width - 64f), EditorStyles.label.CalcHeight(new GUIContent("M"), 1920f)), path, EditorStyles.boldLabel);
            }

            GUIExtensions.ResetEnable();
            GUIExtensions.PushEnable(!_executive.isGenerating);

            EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);

            bool canGenerate = _executive.canGenerate;

            GUIExtensions.PushEnable(canGenerate);
            if (GUILayout.Button("Generate", _generateButtonStyle))
            {
                _executive.Generate();
            }
            GUIExtensions.PopEnable();

            if (!canGenerate)
            {
                var priorBackgroundColor = GUI.backgroundColor;

                int  count    = 0;
                bool showMore = false;
                foreach (var generator in _executive.generators)
                {
                    var message = generator.canGenerateMessage;
                    if (!string.IsNullOrEmpty(message))
                    {
                        if (count == 0)
                        {
                            GUILayout.Space(_sectionEndSpaceHeight / 2);
                            GUI.backgroundColor = Color.Lerp(GUI.color, Color.red, 0.5f);
                            EditorGUILayout.BeginVertical(_messageBoxStyle);
                        }
                        else if (count == 1)
                        {
                            _messageFoldoutAnimation.target = _messageFoldout;
                            showMore = EditorGUILayout.BeginFadeGroup(_messageFoldoutAnimation.faded);
                        }

                        if (count == 0 || showMore)
                        {
                            EditorGUILayout.LabelField(new GUIContent(string.Format("{0}: {1}", generator.name, message)), _messageStyle);
                        }

                        ++count;
                    }
                }

                if (count > 0)
                {
                    if (count > 1)
                    {
                        EditorGUILayout.EndFadeGroup();

                        EditorGUILayout.BeginHorizontal();
                        {
                            EditorGUILayout.Space();
                            if (GUILayout.Button(new GUIContent(_messageFoldout ? "hide" : "more..."), _messageMoreHideButtonStyle, GUILayout.ExpandWidth(false)))
                            {
                                _messageFoldout = !_messageFoldout;
                            }
                            var rect = GUILayoutUtility.GetLastRect();
                            GUI.Label(rect, new GUIContent("________________"), _messageMoreHideButtonStyle);
                            EditorGUILayout.Space();
                        }
                        EditorGUILayout.EndHorizontal();
                    }
                    EditorGUILayout.EndVertical();
                    GUI.backgroundColor = priorBackgroundColor;
                }
            }

            GUILayout.Space(_sectionEndSpaceHeight / 2);

            EditorGUILayout.BeginHorizontal();
            {
                if (GUILayout.Button(new GUIContent("Detach Assets", "Disassociate all assets from this generator.")))
                {
                    if (EditorUtility.DisplayDialog("Detach Assets", "This will disassociate all assets from this generator, which means that these assets will no longer be automatically destroyed or replaced by future executions of the generator.\n\nIt is recommended that you move these assets to another location before you execute the generator again, so that they do not conflict with newly generated assets.", "OK", "Cancel"))
                    {
                        _executive.DetachAssets();
                    }
                }

                if (GUILayout.Button(new GUIContent("Delete Assets", "Delete all assets generated by this generator.")))
                {
                    if (EditorUtility.DisplayDialog("Delete Assets", "This will delete all assets generated by and still associated with this generator.\n\nAre you sure you want to proceed?", "OK", "Cancel"))
                    {
                        _executive.DeleteAssets();
                    }
                }
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.EndVertical();

            GUILayout.Space(_sectionEndSpaceHeight);

            foreach (var generator in _executive.generators)
            {
                GeneratorEditorState editorState;
                if (!_editorStates.TryGetValue(generator, out editorState))
                {
                    editorState                  = new GeneratorEditorState();
                    editorState.editor           = CreateEditor(generator);
                    editorState.foldout          = true;
                    editorState.foldoutAnimation = new AnimBool(editorState.foldout);
                    editorState.foldoutAnimation.valueChanged.AddListener(Repaint);
                    _editorStates[generator] = editorState;
                }

                GUILayout.BeginHorizontal(_generatorHeaderStyle);
                GUILayout.BeginVertical();
                GUILayout.Space(1f);
                GUILayout.Label(generator.name, _generatorHeaderLabelStyle, GUILayout.ExpandWidth(true));
                GUILayout.EndVertical();
                if (GUILayout.Button(GUIContent.none, _generatorHeaderMenuButtonStyle))
                {
                    ShowGeneratorMenu(generator, _editorStates[generator]._menuButtonRect);
                }
                if (Event.current.type == EventType.Repaint)
                {
                    _editorStates[generator]._menuButtonRect = GUILayoutUtility.GetLastRect();
                }

                GUILayout.EndHorizontal();
                var rect = GUILayoutUtility.GetLastRect();
                rect.xMin          += EditorStyles.foldout.padding.left;
                rect.yMin          += 3;
                rect.yMax           = rect.yMin + EditorStyles.foldout.CalcHeight(new GUIContent("M"), 1920f);
                editorState.foldout = EditorGUI.Foldout(rect, editorState.foldout, GUIContent.none);

                editorState.foldoutAnimation.target = editorState.foldout;
                if (EditorGUILayout.BeginFadeGroup(editorState.foldoutAnimation.faded))
                {
                    EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
                    editorState.editor.OnInspectorGUI();
                    EditorGUILayout.Space();
                    EditorGUILayout.EndVertical();
                }
                EditorGUILayout.EndFadeGroup();
            }

            Separator();
            GUILayout.Space(_sectionEndSpaceHeight);

            OnAddGeneratorButtonGUI();

            GUIExtensions.PopEnable();
        }