/// <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; } } }
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); }
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); } }
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); }
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); } }
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)); }
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)); }
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); }
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); }
/// <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); } }
/// <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); } }
private void ValidateDrawers() { ToolboxEditorLog.LogInfo("Function not implemented."); }
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--; }
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; }