/// <summary>
        /// Validates currently cached layout scopes (vertical and horizontal).
        /// </summary>
        /// <returns>true if scopes were clean.</returns>
        private static bool ValidateScopes()
        {
            if (vLayoutClips > 0 || hLayoutClips > 0)
            {
                if (!isExitedLayout)
                {
                    ToolboxEditorLog.LogWarning("Invalid layout data. Check if created groups (vertical or horizontal) are properly closed.");
                }

                while (vLayoutClips > 0)
                {
                    CloseVertical();
                }

                while (hLayoutClips > 0)
                {
                    CloseHorizontal();
                }

                return(false);
            }
            else
            {
                return(true);
            }
        }
        internal static bool InitializeSettings()
        {
            var guids = AssetDatabase.FindAssets("t:" + settingsType);
            //try to find a settings file in a non-package directory
            foreach (var guid in guids)
            {
                var path = AssetDatabase.GUIDToAssetPath(guid);
                if (path.StartsWith("Assets"))
                {
                    guids[0] = guid;
                    break;
                }
            }

            if (InitializeSettings(guids.Length > 0 ? guids[0] : null))
            {
                IsInitialized = true;
                return true;
            }
            else
            {
                ToolboxEditorLog.KitInitializationMessage();
                return false;
            }
        }
        internal static void InitializeSettings(string assetGuid)
        {
            settingsGuid = assetGuid;
            settingsPath = AssetDatabase.GUIDToAssetPath(assetGuid);
            //try to get proper settings asset from provided guid
            var settings = AssetDatabase.LoadAssetAtPath <ToolboxEditorSettings>(settingsPath);

            if (settings == null)
            {
                ToolboxEditorLog.KitInitializationWarning(settingsType);
                return;
            }

            Settings = settings;
            Settings.AddOnSettingsUpdatedListener(() =>
            {
                //perform separated data models update
                ToolboxDrawerUtility.PerformData();
                ToolboxProjectUtility.PerformData();
                ToolboxHierarchyUtility.PerformData();

                //perform additional repaint to update GUI
                ToolboxEditorProject.RepaintProjectOverlay();
                ToolboxEditorHierarchy.RepaintHierarchyOverlay();
            });

            //initialize core functionalities
            ToolboxDrawerUtility.PerformData(Settings);
            ToolboxProjectUtility.PerformData(Settings);
            ToolboxHierarchyUtility.PerformData(Settings);
        }
        /// <summary>
        /// Creates all possible type-based drawers and add them to the related collection.
        /// </summary>
        /// <param name="settings"></param>
        private static void CreateTargetTypeDrawers(IToolboxInspectorSettings settings)
        {
            var childrenTypesMap = new Dictionary <ToolboxTargetTypeDrawer, List <Type> >();

            targetTypeDrawers.Clear();
            for (var i = 0; i < settings.TargetTypeDrawersCount; i++)
            {
                var drawerType = settings.GetTargetTypeDrawerTypeAt(i);
                if (drawerType == null)
                {
                    if (validationEnabled)
                    {
                        ToolboxEditorLog.LogWarning("One of assigned drawer types in the " + nameof(ToolboxEditorSettings) + " is empty.");
                    }

                    continue;
                }

                var drawerInstance = Activator.CreateInstance(drawerType) as ToolboxTargetTypeDrawer;
                var targetBaseType = drawerInstance.GetTargetType();
                if (targetBaseType != null)
                {
                    if (targetTypeDrawers.ContainsKey(targetBaseType))
                    {
                        if (validationEnabled)
                        {
                            ToolboxEditorLog.LogError("Type:" + targetBaseType + " is associated to more than one ToolboxDrawer.");
                        }

                        continue;
                    }

                    targetTypeDrawers[targetBaseType] = drawerInstance;

                    if (drawerInstance.UseForChildren())
                    {
                        childrenTypesMap[drawerInstance] = targetBaseType.GetAllChildClasses();
                    }
                }
            }

            foreach (var typesMap in childrenTypesMap)
            {
                var typesDrawer = typesMap.Key;
                var targetTypes = typesMap.Value;

                for (var i = 0; i < targetTypes.Count; i++)
                {
                    var targetType = targetTypes[i];
                    if (targetTypeDrawers.ContainsKey(targetType))
                    {
                        continue;
                    }

                    targetTypeDrawers[targetType] = typesDrawer;
                }
            }
        }
예제 #5
0
        internal static ToolboxConditionDrawerBase GetConditionDrawer <T>(T attribute) where T : ToolboxConditionAttribute
        {
            if (!conditionDrawers.TryGetValue(attribute.GetType(), out ToolboxConditionDrawerBase drawer))
            {
                ToolboxEditorLog.AttributeNotSupportedWarning(attribute);
                return(null);
            }

            return(drawer);
        }
예제 #6
0
        internal static void EndHorizontal()
        {
            if (horizontalScopes.Count == 0)
            {
                ToolboxEditorLog.LogWarning("There is no a horizontal group to end. Call will be ignored.");
                return;
            }

            horizontalScopes.Pop().Dispose();
        }
        internal static void CloseHorizontal()
        {
            if (hLayoutClips == 0)
            {
                ToolboxEditorLog.LogWarning("There is no horizontal group to end. Call will be ignored.");
                return;
            }

            hLayoutClips--;
            EditorGUILayout.EndHorizontal();
        }
        internal static void CloseVertical()
        {
            if (vLayoutClips == 0)
            {
                ToolboxEditorLog.LogWarning("There is no vertical group to end. Call will be ignored.");
                return;
            }

            vLayoutClips--;
            EditorGUILayout.EndVertical();
        }
        internal static Rect BeginVertical(GUIStyle style, params GUILayoutOption[] options)
        {
            if (!isEditorLayout)
            {
                ToolboxEditorLog.LogWarning("Begin vertical layout group action can be executed only within the Toolbox Editor.");
                return(Rect.zero);
            }

            vLayoutClips++;
            return(EditorGUILayout.BeginVertical(style, options));
        }
 internal static ToolboxPropertyDrawerBase GetListPropertyDrawer(Type attributeType)
 {
     if (listPropertyDrawers.TryGetValue(attributeType, out var drawer))
     {
         return(drawer);
     }
     else
     {
         ToolboxEditorLog.AttributeNotSupportedWarning(attributeType);
         return(null);
     }
 }
예제 #11
0
        internal static void BeginVertical(GUIStyle style, params GUILayoutOption[] options)
        {
            if (!inEditorLayout)
            {
                ToolboxEditorLog.LogWarning("Begin vertical layout group action can be executed only within the Toolbox Editor.");
                return;
            }

            var scope = style == null
                ? new EditorGUILayout.VerticalScope(options)
                : new EditorGUILayout.VerticalScope(style, options);

            verticalScopes.Push(scope);
        }
예제 #12
0
        internal static bool InitializeSettings()
        {
            var guids = AssetDatabase.FindAssets("t:" + settingsType);

            if (InitializeSettings(guids.Length > 0 ? guids[0] : null))
            {
                IsInitialized = true;
                return(true);
            }
            else
            {
                ToolboxEditorLog.KitInitializationMessage();
                return(false);
            }
        }
예제 #13
0
        internal static ToolboxTargetTypeDrawer GetTargetTypeDrawer(Type propertyType)
        {
            var targetType = propertyType.IsGenericType
                ? propertyType.GetGenericTypeDefinition()
                : propertyType;

            if (targetTypeDrawers.TryGetValue(targetType, out var drawer))
            {
                return(drawer);
            }
            else
            {
                ToolboxEditorLog.LogWarning("There is no type-based drawer associated to the " + propertyType + " type.");
                return(null);
            }
        }
        internal static Rect BeginHorizontal(GUIStyle style, params GUILayoutOption[] options)
        {
            if (!isEditorLayout)
            {
                ToolboxEditorLog.LogWarning("Begin horizontal layout group action can be executed only within the Toolbox Editor.");
                return(Rect.zero);
            }

            if (hLayoutClips > 0)
            {
                ToolboxEditorLog.LogWarning("Nested horizontal layout groups are not supported.");
                return(Rect.zero);
            }

            hLayoutClips++;
            return(EditorGUILayout.BeginHorizontal(style, options));
        }
예제 #15
0
        internal static object GetTreePathReference(string treeField, object treeParent)
        {
            if (IsSerializableArrayElement(treeField, out var index))
            {
                if (treeParent is IList list)
                {
                    return(list[index]);
                }

                ToolboxEditorLog.LogError("Cannot parse array element properly.");
            }

            var fieldType = treeParent.GetType();
            var fieldInfo = fieldType.GetField(treeField,
                                               BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            return(fieldInfo.GetValue(treeParent));
        }
예제 #16
0
        internal static void InitializeSettings(string assetGuid)
        {
            settingsGuid = assetGuid;
            settingsPath = AssetDatabase.GUIDToAssetPath(assetGuid);
            //try to get proper settings asset from provided guid
            var settings = AssetDatabase.LoadAssetAtPath <ToolboxEditorSettings>(settingsPath);

            if (settings == null)
            {
                ToolboxEditorLog.KitInitializationWarning(settingsType);
                return;
            }

            Settings = settings;

            //initialize core functionalities
            ToolboxDrawerUtility.InitializeDrawers(Settings);
            ToolboxFolderUtility.InitializeProject(Settings);
        }
예제 #17
0
        internal static void BeginHorizontal(GUIStyle style, params GUILayoutOption[] options)
        {
            if (!inEditorLayout)
            {
                ToolboxEditorLog.LogWarning("Begin horizontal layout group action can be executed only within the Toolbox Editor.");
                return;
            }

            if (horizontalScopes.Count > 0)
            {
                ToolboxEditorLog.LogWarning("Nested horizontal layout groups are not supported.");
                return;
            }

            var scope = style == null
                ? new EditorGUILayout.HorizontalScope(options)
                : new EditorGUILayout.HorizontalScope(style, options);

            horizontalScopes.Push(scope);
        }
예제 #18
0
 /// <summary>
 /// Returns and/or creates (if needed) <see cref="ToolboxPropertyHandler"/> for given property.
 /// </summary>
 internal static ToolboxPropertyHandler GetPropertyHandler(SerializedProperty property)
 {
     if (InspectorUtility.InToolboxEditor)
     {
         //NOTE: maybe type-based key?
         var propertyKey = property.GetPropertyHashKey();
         if (propertyHandlers.TryGetValue(propertyKey, out var propertyHandler))
         {
             return(propertyHandler);
         }
         else
         {
             return(propertyHandlers[propertyKey] = new ToolboxPropertyHandler(property));
         }
     }
     else
     {
         ToolboxEditorLog.LogWarning("Do not use Toolbox-related drawers outside ToolboxEditor.");
         return(null);
     }
 }
예제 #19
0
        /// <summary>
        /// Validates currently cached layout scopes (vertical and horizontal).
        /// </summary>
        /// <returns>true if scopes were clean.</returns>
        private static bool ValidateScope()
        {
            if (verticalScopes.Count == 0 && horizontalScopes.Count == 0)
            {
                return(true);
            }
            else
            {
                ToolboxEditorLog.LogWarning("Invalid layout data. Check if created groups (vertical or horizontal) are properly closed.");

                while (verticalScopes.Count > 0)
                {
                    verticalScopes.Pop().Dispose();
                }

                while (horizontalScopes.Count > 0)
                {
                    horizontalScopes.Pop().Dispose();
                }
            }

            return(false);
        }
        /// <summary>
        /// Creates all possible attribute-based drawers and add them to proper collections.
        /// </summary>
        /// <param name="settings"></param>
        private static void CreateAttributeDrawers(IToolboxInspectorSettings settings)
        {
            void AddAttributeDrawer <T>(Type drawerType, Type attributeType, Dictionary <Type, T> drawersCollection) where T : ToolboxAttributeDrawer
            {
                if (drawerType == null)
                {
                    return;
                }

                var drawerInstance = Activator.CreateInstance(drawerType) as T;

                if (drawersCollection.ContainsKey(attributeType))
                {
                    if (validationEnabled)
                    {
                        ToolboxEditorLog.LogError("Attribute:" + attributeType + " is associated to more than one ToolboxDrawer.");
                    }

                    return;
                }

                drawersCollection.Add(attributeType, drawerInstance);
            }

            Type GetDrawersGenericType(Type drawerType, Type drawerBaseType)
            {
                if (drawerType == null)
                {
                    if (validationEnabled)
                    {
                        ToolboxEditorLog.LogWarning("One of assigned drawer types in the " + nameof(ToolboxEditorSettings) + " is empty.");
                    }

                    return(null);
                }

                while (!drawerType.IsGenericType || drawerType.GetGenericTypeDefinition() != drawerBaseType)
                {
                    if (drawerType.BaseType == null)
                    {
                        return(null);
                    }

                    drawerType = drawerType.BaseType;
                }

                return(drawerType.IsGenericType ? drawerType.GetGenericArguments().FirstOrDefault() : null);
            }

            decoratorDrawers.Clear();
            for (var i = 0; i < settings.DecoratorDrawersCount; i++)
            {
                var drawerType = settings.GetDecoratorDrawerTypeAt(i);
                var targetType = GetDrawersGenericType(settings.GetDecoratorDrawerTypeAt(i), decoratorDrawerBase);
                AddAttributeDrawer(drawerType, targetType, decoratorDrawers);
            }

            conditionDrawers.Clear();
            for (var i = 0; i < settings.ConditionDrawersCount; i++)
            {
                var drawerType = settings.GetConditionDrawerTypeAt(i);
                var targetType = GetDrawersGenericType(settings.GetConditionDrawerTypeAt(i), conditionDrawerBase);
                AddAttributeDrawer(drawerType, targetType, conditionDrawers);
            }

            selfPropertyDrawers.Clear();
            for (var i = 0; i < settings.SelfPropertyDrawersCount; i++)
            {
                var drawerType = settings.GetSelfPropertyDrawerTypeAt(i);
                var targetType = GetDrawersGenericType(settings.GetSelfPropertyDrawerTypeAt(i), selfPropertyDrawerBase);
                AddAttributeDrawer(drawerType, targetType, selfPropertyDrawers);
            }

            listPropertyDrawers.Clear();
            for (var i = 0; i < settings.ListPropertyDrawersCount; i++)
            {
                var drawerType = settings.GetListPropertyDrawerTypeAt(i);
                var targetType = GetDrawersGenericType(settings.GetListPropertyDrawerTypeAt(i), listPropertyDrawerBase);
                AddAttributeDrawer(drawerType, targetType, listPropertyDrawers);
            }
        }
예제 #21
0
 private void ValidateDrawers()
 {
     ToolboxEditorLog.LogInfo("Function not implemented.");
 }
예제 #22
0
        private void DrawInspectorSettings()
        {
            EditorGUI.indentLevel++;
            EditorGUI.BeginChangeCheck();
            EditorGUILayout.Space();
            EditorGUILayout.PropertyField(useToolboxDrawersProperty);
            EditorGUILayout.Space();

            var validateInspector = false;

#if UNITY_2019_3_OR_NEWER
            EditorGUILayout.BeginVertical(Style.groupStyle);
#endif
#if UNITY_2019_3_OR_NEWER
            enabledToShowDrawerType = GUILayout.Toolbar(enabledToShowDrawerType, drawerHandlersShortNames, EditorStyles.toolbarButton);
#else
            enabledToShowDrawerType = GUILayout.Toolbar(enabledToShowDrawerType, drawerHandlersShortNames);
#endif
            EditorGUI.BeginDisabledGroup(!useToolboxDrawersProperty.boolValue);

            var longName = drawerHandlersLongNames[enabledToShowDrawerType];
            var tooltip  = drawerHandlersInfoLabels[enabledToShowDrawerType];
            var content  = new GUIContent(longName + " Drawers", tooltip);
            EditorGUILayout.LabelField(content, Style.drawersHeaderStyle);

#if UNITY_2019_3_OR_NEWER
            EditorGUILayout.EndVertical();
#endif
#if UNITY_2019_3_OR_NEWER
            EditorGUILayout.BeginVertical(Style.groupStyle);
#endif
            drawerHandlersLists[enabledToShowDrawerType].DoLayoutList();
#if UNITY_2019_3_OR_NEWER
            EditorGUILayout.EndVertical();
#endif
#if UNITY_2019_3_OR_NEWER
            EditorGUILayout.BeginVertical(Style.groupStyle);
#endif
            EditorGUILayout.BeginHorizontal();
            if (GUILayout.Button(Style.clearListContent, EditorStyles.miniButtonLeft))
            {
                Undo.RecordObject(target, "Clear Drawers");
                switch (enabledToShowDrawerType)
                {
                case 0:
                    currentTarget.ClearDecoratorDrawerHandlers();
                    break;

                case 1:
                    currentTarget.ClearConditionDrawerHandlers();
                    break;

                case 2:
                    currentTarget.ClearSelfPropertyDrawerHandlers();
                    break;

                case 3:
                    currentTarget.ClearListPropertyDrawerHandlers();
                    break;

                case 4:
                    currentTarget.ClearTargetTypeDrawerHandlers();
                    break;
                }
                validateInspector = true;
            }

            if (GUILayout.Button(Style.assignAllContent, EditorStyles.miniButtonMid))
            {
                Undo.RecordObject(target, "Assign Drawers");
                switch (enabledToShowDrawerType)
                {
                case 0:
                    currentTarget.SetAllPossibleDecoratorDrawers();
                    break;

                case 1:
                    currentTarget.SetAllPossibleConditionDrawers();
                    break;

                case 2:
                    currentTarget.SetAllPossibleSelfPropertyDrawers();
                    break;

                case 3:
                    currentTarget.SetAllPossibleListPropertyDrawers();
                    break;

                case 4:
                    currentTarget.SetAllPossibleTargetTypeDrawers();
                    break;
                }
                validateInspector = true;
            }

            if (GUILayout.Button(Style.validListContent, EditorStyles.miniButtonRight))
            {
                ToolboxEditorLog.LogMessage("Function not implemented, force recompilation to validate drawers assignment.");
            }
            EditorGUILayout.EndHorizontal();
#if UNITY_2019_3_OR_NEWER
            EditorGUILayout.EndVertical();
#endif
            EditorGUILayout.Space();

            if (validateInspector)
            {
                currentTarget.ValidateInspectorSettings();
            }

            EditorGUI.EndDisabledGroup();

            if (EditorGUI.EndChangeCheck())
            {
                currentTarget.SetInspectorSettingsDirty();
            }
            EditorGUI.indentLevel--;
        }
예제 #23
0
        internal static SettingsProvider SettingsProvider()
        {
            var provider = new SettingsProvider("Project/Editor Toolbox", SettingsScope.Project);

            provider.guiHandler = (searchContext) =>
            {
                if (globalSettingsEditor == null || globalSettingsEditor.serializedObject.targetObject == null)
                {
                    EditorGUILayout.Space();
                    EditorGUILayout.LabelField("Cannot find " + settingsType + " file located in this Project");
                    EditorGUILayout.Space();

                    void InitializeProvider()
                    {
                        provider.OnDeactivate();
                        provider.OnActivate("", null);
                    }

                    if (GUILayout.Button("Try to find the settings file"))
                    {
                        InitializeSettings();
                        InitializeProvider();
                    }

                    if (GUILayout.Button("Create the new settings file"))
                    {
                        var settingsInstance = ScriptableObject.CreateInstance(settingsType);

                        var directoryPath = EditorUtility.OpenFolderPanel("New Settings file location", "Assets", "");
                        var settingsPath  = directoryPath.Substring(directoryPath.IndexOf("Assets/")) + "/" + settingsType + ".asset";

                        AssetDatabase.CreateAsset(settingsInstance, settingsPath);
                        AssetDatabase.SaveAssets();
                        AssetDatabase.Refresh();

                        ToolboxEditorLog.LogMessage("Created the settings file at - " + settingsPath);

                        InitializeSettings();
                        InitializeProvider();
                    }

                    return;
                }

                EditorGUILayout.Space();
                EditorGUILayout.LabelField("Settings file location - " + SettingsPath);
                EditorGUILayout.Space();

                globalSettingsEditor.serializedObject.Update();
                globalSettingsEditor.OnInspectorGUI();
                globalSettingsEditor.serializedObject.ApplyModifiedProperties();
            };
            provider.activateHandler = (searchContext, elements) =>
            {
                globalSettingsEditor = Editor.CreateEditor(Settings);
            };
            provider.deactivateHandler = () =>
            {
                Object.DestroyImmediate(globalSettingsEditor);
            };

            return(provider);
        }
        internal static SettingsProvider SettingsProvider()
        {
            var provider = new SettingsProvider("Project/Editor Toolbox", SettingsScope.Project);

            void ReintializeProvider()
            {
                InitializeSettings();

                //rebuild the settings provider right after initialization
                provider.OnDeactivate();
                provider.OnActivate("", null);
            }

            provider.guiHandler = (searchContext) =>
            {
                if (globalSettingsEditor == null || globalSettingsEditor.serializedObject.targetObject == null)
                {
                    EditorGUILayout.Space();
                    EditorGUILayout.LabelField("Cannot find " + settingsType + " file located in this Project");
                    EditorGUILayout.Space();

                    if (GUILayout.Button("Create a new settings file"))
                    {
                        var settingsInstance = ScriptableObject.CreateInstance(settingsType);

                        var locationPath = EditorUtility.OpenFolderPanel("New Settings file location", "Assets", "");
                        //validate returned path and create relative one if possible
                        if (string.IsNullOrEmpty(locationPath))
                        {
                            return;
                        }

                        var relativePath = locationPath
                                               .Substring(locationPath
                                                   .IndexOf("Assets/")) + "/" + settingsType + ".asset";

                        AssetDatabase.CreateAsset(settingsInstance, relativePath);
                        AssetDatabase.SaveAssets();
                        AssetDatabase.Refresh();

                        ToolboxEditorLog.Log("Created a settings file at - " + relativePath);

                        ReintializeProvider();
                    }

                    return;
                }

                EditorGUILayout.Space();
                EditorGUILayout.LabelField("Settings file location - " + SettingsPath);
                EditorGUILayout.Space();

                globalSettingsEditor.OnInspectorGUI();
            };
            provider.activateHandler = (searchContext, elements) =>
            {
                globalSettingsEditor = Editor.CreateEditor(Settings);
            };
            provider.deactivateHandler = () =>
            {
                Object.DestroyImmediate(globalSettingsEditor);
            };
            provider.titleBarGuiHandler = () =>
            {
                if (GUILayout.Button(new GUIContent("Refresh", "Try to find a settings file in the main (Assets) directory")))
                {
                    ReintializeProvider();
                }
            };

            return provider;
        }