diff --git a/Assets/Editor Toolbox/CHANGELOG.md b/Assets/Editor Toolbox/CHANGELOG.md index 16d1aa47..a6a47413 100644 --- a/Assets/Editor Toolbox/CHANGELOG.md +++ b/Assets/Editor Toolbox/CHANGELOG.md @@ -1,3 +1,16 @@ +## 0.14.3 [29.12.2025] + +### Added: +- Ability to specify 'ValueStep' in the ProgressBar attribute + +### Changed: +- Toolbar support for Unity 6.3+ +- Material Drawers support for Unity 6.3+ +- Serialized Scene support for Unity 6.3+ +- Fix issues with copy/past operations for the [SerializeReference]-based arrays +- Ability to display parent objects in the SceneView tool +- Ability to display managed reference values while using LabelByChild attribute + ## 0.14.2 [10.08.2025] ### Added: diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceCache.cs b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceCache.cs index f8e4ae71..4c6d9d65 100644 --- a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceCache.cs +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceCache.cs @@ -9,10 +9,11 @@ namespace Toolbox.Editor.ContextMenu.Operations /// internal class CopySerializeReferenceCache { - public CopySerializeReferenceCache(Type referenceType, IReadOnlyList entires) + public CopySerializeReferenceCache(Type referenceType, IReadOnlyList entires, bool isArrayCopy) { ReferenceType = referenceType; Entries = entires; + IsArrayCopy = isArrayCopy; } /// @@ -20,6 +21,6 @@ public CopySerializeReferenceCache(Type referenceType, IReadOnlyList public Type ReferenceType { get; } public IReadOnlyList Entries { get; } - public bool IsArrayCopy => Entries != null && Entries.Count > 1; + public bool IsArrayCopy { get; } } } \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs index 6d2293c8..e7850684 100644 --- a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs @@ -51,6 +51,7 @@ public bool IsEnabled(SerializedProperty property) public void Perform(SerializedProperty property) { + var isArrayCopy = false; var entries = new List(); if (property.propertyType == SerializedPropertyType.ManagedReference) { @@ -59,6 +60,7 @@ public void Perform(SerializedProperty property) } else if (property.isArray) { + isArrayCopy = true; var propertiesCount = property.arraySize; for (var i = 0; i < propertiesCount; i++) { @@ -69,7 +71,7 @@ public void Perform(SerializedProperty property) } PropertyUtility.TryGetSerializeReferenceType(property, out var referenceType); - Cache = new CopySerializeReferenceCache(referenceType, entries); + Cache = new CopySerializeReferenceCache(referenceType, entries, isArrayCopy); } public GUIContent Label => new GUIContent("Copy Serialized References"); diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs index c8376054..65d560c8 100644 --- a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs @@ -36,7 +36,7 @@ private bool IsAssignmentValid(Type targetType, CopySerializeReferenceEntry entr return true; } - return TypeUtility.IsTypeAssignableFrom(targetType, entry.ReferenceType); + return TypeUtility.IsTypeAssignableFrom(targetType, entryType); } private bool IsOperationSupported(SerializedProperty targetProperty, CopySerializeReferenceCache cache) diff --git a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialCompactTextureDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialCompactTextureDrawer.cs index b0c39af5..e2720ca4 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialCompactTextureDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialCompactTextureDrawer.cs @@ -27,7 +27,11 @@ protected override void OnGUISafe(Rect position, MaterialProperty prop, string l protected override bool IsPropertyValid(MaterialProperty prop) { +#if UNITY_6000_3_OR_NEWER + return prop.propertyType == UnityEngine.Rendering.ShaderPropertyType.Texture; +#else return prop.type == MaterialProperty.PropType.Texture; +#endif } } } \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialConditionalDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialConditionalDrawer.cs index f7baa652..9930ad9d 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialConditionalDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialConditionalDrawer.cs @@ -12,6 +12,17 @@ protected MaterialConditionalDrawer(string togglePropertyName) this.togglePropertyName = togglePropertyName; } + private bool IsValidToggleType(MaterialProperty toggleProp) + { +#if UNITY_6000_3_OR_NEWER + return toggleProp.propertyType == UnityEngine.Rendering.ShaderPropertyType.Float || + toggleProp.propertyType == UnityEngine.Rendering.ShaderPropertyType.Range; +#else + return toggleProp.type == MaterialProperty.PropType.Float || + toggleProp.type == MaterialProperty.PropType.Range; +#endif + } + protected override float GetPropertyHeightSafe(MaterialProperty prop, string label, MaterialEditor editor) { if (!HasToggle(prop)) @@ -48,7 +59,7 @@ protected virtual bool HasToggle(MaterialProperty prop) { var targets = prop.targets; var toggle = MaterialEditor.GetMaterialProperty(targets, togglePropertyName); - return toggle != null && toggle.type == MaterialProperty.PropType.Float || toggle.type == MaterialProperty.PropType.Range; + return toggle != null && IsValidToggleType(toggle); } protected virtual bool? GetValue(MaterialProperty prop) diff --git a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialMinMaxSliderDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialMinMaxSliderDrawer.cs index 0e9c2157..a649d601 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialMinMaxSliderDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialMinMaxSliderDrawer.cs @@ -44,7 +44,11 @@ protected override void OnGUISafe(Rect position, MaterialProperty prop, string l protected override bool IsPropertyValid(MaterialProperty prop) { +#if UNITY_6000_3_OR_NEWER + return prop.propertyType == UnityEngine.Rendering.ShaderPropertyType.Vector; +#else return prop.type == MaterialProperty.PropType.Vector; +#endif } } } \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialVector2Drawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialVector2Drawer.cs index 85e2e794..54cb2d65 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialVector2Drawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialVector2Drawer.cs @@ -30,7 +30,11 @@ protected override void OnGUISafe(Rect position, MaterialProperty prop, string l protected override bool IsPropertyValid(MaterialProperty prop) { +#if UNITY_6000_3_OR_NEWER + return prop.propertyType == UnityEngine.Rendering.ShaderPropertyType.Vector; +#else return prop.type == MaterialProperty.PropType.Vector; +#endif } } } \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialVector3Drawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialVector3Drawer.cs index 6768c73e..bd8e8cf5 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialVector3Drawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialVector3Drawer.cs @@ -30,7 +30,11 @@ protected override void OnGUISafe(Rect position, MaterialProperty prop, string l protected override bool IsPropertyValid(MaterialProperty prop) { +#if UNITY_6000_3_OR_NEWER + return prop.propertyType == UnityEngine.Rendering.ShaderPropertyType.Vector; +#else return prop.type == MaterialProperty.PropType.Vector; +#endif } } } \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Drawers/Regular/ProgressBarAttributeDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Regular/ProgressBarAttributeDrawer.cs index dffbddf2..a7f42777 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Regular/ProgressBarAttributeDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Regular/ProgressBarAttributeDrawer.cs @@ -43,12 +43,18 @@ private void SetProgressValue(SerializedProperty property, Rect progressBarRect, { var minValue = Attribute.MinValue; var maxValue = Attribute.MaxValue; + var valueStep = Attribute.ValueStep; var range = progressBarRect.xMax - progressBarRect.xMin; xPosition = Mathf.Clamp(xPosition - progressBarRect.xMin, 0, range); var fill = Mathf.Clamp01(xPosition / range); var newValue = (maxValue - minValue) * fill + minValue; + if (!Mathf.Approximately(valueStep, 0.0f)) + { + newValue = Mathf.Round(newValue / valueStep) * valueStep; + newValue = Mathf.Clamp(newValue, minValue, maxValue); + } switch (property.propertyType) { diff --git a/Assets/Editor Toolbox/Editor/SceneView/ToolboxEditorSceneViewObjectSelector.cs b/Assets/Editor Toolbox/Editor/SceneView/ToolboxEditorSceneViewObjectSelector.cs index 6556c12e..f392b780 100644 --- a/Assets/Editor Toolbox/Editor/SceneView/ToolboxEditorSceneViewObjectSelector.cs +++ b/Assets/Editor Toolbox/Editor/SceneView/ToolboxEditorSceneViewObjectSelector.cs @@ -8,7 +8,6 @@ public class ToolboxEditorSceneViewObjectSelector : EditorWindow { private static readonly Color selectionColor = new Color(0.50f, 0.70f, 1.00f); private static readonly Color highlightWireColor = Color.yellow; - private const float outlineFillOpacity = 1f; private const float sizeXPadding = 2f; private const float sizeYPadding = 2f; @@ -17,10 +16,10 @@ public class ToolboxEditorSceneViewObjectSelector : EditorWindow private const float sizeXOffset = -30f; private const float indentWidth = 12f; - private List displayEntries; + private readonly List highlightedRenderers = new List(); + private List displayEntries; private GameObject highlightedObject; - private readonly List highlightedRenderers = new List(); private Vector2 size; private Vector2 buttonSize; @@ -42,12 +41,16 @@ public static void Show(List gameObjects, Vector2 position) private void OnEnable() { - UnityEditor.SceneView.duringSceneGui += OnSceneViewDuringSceneGui; +#if UNITY_2019_1_OR_NEWER + UnityEditor.SceneView.duringSceneGui += OnSceneViewGui; +#endif } private void OnDisable() { - UnityEditor.SceneView.duringSceneGui -= OnSceneViewDuringSceneGui; +#if UNITY_2019_1_OR_NEWER + UnityEditor.SceneView.duringSceneGui -= OnSceneViewGui; +#endif highlightedRenderers.Clear(); highlightedObject = null; } @@ -325,7 +328,10 @@ private void SelectObject(int id, bool control, bool shift) } else { - Selection.objects = new Object[] { gameObject }; + Selection.objects = new Object[] + { + gameObject + }; } } @@ -377,27 +383,6 @@ private void RemoveSelectedObject(GameObject gameObject) Selection.objects = newSelection; } - private GameObject HighlightedObject - { - set - { - if (highlightedObject == value) - { - return; - } - - highlightedObject = value; - UnityEditor.SceneView.RepaintAll(); - - if (highlightedObject != null) - { - EditorGUIUtility.PingObject(highlightedObject); - } - - UpdateHighlightedRenderers(); - } - } - private void UpdateHighlightedRenderers() { highlightedRenderers.Clear(); @@ -410,7 +395,8 @@ private void UpdateHighlightedRenderers() highlightedRenderers.AddRange(highlightedObject.GetComponentsInChildren(true)); } - private void OnSceneViewDuringSceneGui(UnityEditor.SceneView sceneView) +#if UNITY_2019_1_OR_NEWER + private void OnSceneViewGui(UnityEditor.SceneView sceneView) { if (highlightedRenderers.Count == 0 || Event.current.type != EventType.Repaint) @@ -420,7 +406,7 @@ private void OnSceneViewDuringSceneGui(UnityEditor.SceneView sceneView) // Unity 6.1+ provides Handles.DrawOutline which also highlights children in one call. #if UNITY_6000_1_OR_NEWER - Handles.DrawOutline(highlightedRenderers.ToArray(), highlightWireColor, highlightWireColor, outlineFillOpacity); + Handles.DrawOutline(highlightedRenderers.ToArray(), highlightWireColor, highlightWireColor, 0.5f); #else using (new Handles.DrawingScope(highlightWireColor)) { @@ -437,6 +423,28 @@ private void OnSceneViewDuringSceneGui(UnityEditor.SceneView sceneView) } #endif } +#endif + + private GameObject HighlightedObject + { + set + { + if (highlightedObject == value) + { + return; + } + + highlightedObject = value; + UnityEditor.SceneView.RepaintAll(); + + if (highlightedObject != null) + { + EditorGUIUtility.PingObject(highlightedObject); + } + + UpdateHighlightedRenderers(); + } + } private readonly struct DisplayEntry { diff --git a/Assets/Editor Toolbox/Editor/ToolboxEditorHierarchy.cs b/Assets/Editor Toolbox/Editor/ToolboxEditorHierarchy.cs index 9baff2c9..5f947558 100644 --- a/Assets/Editor Toolbox/Editor/ToolboxEditorHierarchy.cs +++ b/Assets/Editor Toolbox/Editor/ToolboxEditorHierarchy.cs @@ -46,8 +46,12 @@ private static void OnItemCallback(int instanceId, Rect rect) } //use Unity's internal method to determinate the proper GameObject instance +#if UNITY_6000_3_OR_NEWER + var gameObject = EditorUtility.EntityIdToObject(instanceId) as GameObject; +#else var gameObject = EditorUtility.InstanceIDToObject(instanceId) as GameObject; - if (gameObject) +#endif + if (gameObject != null) { var type = GetLabelType(gameObject, out var label); //draw label using one of the possible forms diff --git a/Assets/Editor Toolbox/Editor/ToolboxEditorToolbar.cs b/Assets/Editor Toolbox/Editor/ToolboxEditorToolbar.cs index fff824c2..fa3db88d 100644 --- a/Assets/Editor Toolbox/Editor/ToolboxEditorToolbar.cs +++ b/Assets/Editor Toolbox/Editor/ToolboxEditorToolbar.cs @@ -5,16 +5,20 @@ using System.Reflection; using UnityEditor; -using UnityEngine; using Object = UnityEngine.Object; using Unity.EditorCoroutines.Editor; +using UnityEngine; + #if UNITY_2019_1_OR_NEWER using UnityEngine.UIElements; #else using UnityEngine.Experimental.UIElements; #endif -//NOTE: since everything in this class is reflection-based it is a little bit "hacky" +//NOTE: since everything in this class is reflection-based it is a little bit "hacky"; supporting each version makes it very hard to maintain - +// consider implementing different 'drawers' for each Toolbar iteration + +//NOTE: unfortunately latest (6.3) official API is very limited and can't be used to port this implementation namespace Toolbox.Editor { @@ -30,7 +34,11 @@ static ToolboxEditorToolbar() } private static readonly Type containterType = typeof(IMGUIContainer); +#if UNITY_6000_3_OR_NEWER + private static readonly Type toolbarType = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.MainToolbarWindow"); +#else private static readonly Type toolbarType = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.Toolbar"); +#endif private static readonly Type guiViewType = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.GUIView"); #if UNITY_2020_1_OR_NEWER private static readonly Type backendType = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.IWindowBackend"); @@ -55,24 +63,57 @@ private static IEnumerator Initialize() { while (toolbar == null) { - var toolbars = Resources.FindObjectsOfTypeAll(toolbarType); - if (toolbars == null || toolbars.Length == 0) + if (!TryGetToolbarInstance(out toolbar)) { yield return null; continue; } - else + } + +#if UNITY_6000_3_OR_NEWER + VisualElement root = null; + if (toolbar is EditorWindow editorWindow) + { + root = editorWindow.rootVisualElement; + } + + var builder = root.Query(name: "DockArea"); + var states = builder.Build(); + + var toolbarLeftZone = states.AtIndex(0); + AddIMGUIContainer(toolbarLeftZone, OnGuiLeft, "Editor Toolbox Left Area"); + + var toolbarRightZone = states.AtIndex(1); + AddIMGUIContainer(toolbarRightZone, OnGuiRight, "Editor Toolbox Right Area"); + + static void AddIMGUIContainer(VisualElement parentElement, Action guiCallback, string name) + { + if (parentElement == null) { - toolbar = toolbars[0]; + return; } - } + var element = new VisualElement(); + element.name = name; + element.StretchToParentSize(); + element.style.left = 10; + element.style.right = 10; + element.style.flexGrow = 1; + element.style.flexDirection = FlexDirection.Row; + + var guiContainer = new IMGUIContainer(); + guiContainer.style.flexGrow = 1; + guiContainer.onGUIHandler = guiCallback; + element.Add(guiContainer); + parentElement.Add(element); + } +#else #if UNITY_2021_1_OR_NEWER var rootField = toolbar.GetType().GetField("m_Root", BindingFlags.NonPublic | BindingFlags.Instance); var root = rootField.GetValue(toolbar) as VisualElement; var toolbarLeftZone = root.Q("ToolbarZoneLeftAlign"); - var element = new VisualElement() + var leftElement = new VisualElement() { style = { @@ -81,11 +122,11 @@ private static IEnumerator Initialize() } }; - var container = new IMGUIContainer(); - container.style.flexGrow = 1; - container.onGUIHandler += OnGuiLeft; - element.Add(container); - toolbarLeftZone.Add(element); + var leftContainer = new IMGUIContainer(); + leftContainer.style.flexGrow = 1; + leftContainer.onGUIHandler = OnGuiLeft; + leftElement.Add(leftContainer); + toolbarLeftZone.Add(leftElement); var toolbarRightZone = root.Q("ToolbarZoneRightAlign"); var rightElement = new VisualElement() @@ -99,7 +140,7 @@ private static IEnumerator Initialize() var rightContainer = new IMGUIContainer(); rightContainer.style.flexGrow = 1; - rightContainer.onGUIHandler += OnGuiRight; + rightContainer.onGUIHandler = OnGuiRight; rightElement.Add(rightContainer); toolbarRightZone.Add(rightElement); #else @@ -109,7 +150,6 @@ private static IEnumerator Initialize() #else var elements = visualTree.GetValue(toolbar, null) as VisualElement; #endif - #if UNITY_2019_1_OR_NEWER var container = elements[0]; #else @@ -119,6 +159,27 @@ private static IEnumerator Initialize() handler -= OnGuiLeft; handler += OnGuiLeft; onGuiHandler.SetValue(container, handler); +#endif +#endif + } + + private static bool TryGetToolbarInstance(out Object toolbarInstance) + { +#if UNITY_6000_3_OR_NEWER + toolbarInstance = EditorWindow.GetWindow(toolbarType); + return toolbarInstance != null; +#else + var toolbars = Resources.FindObjectsOfTypeAll(toolbarType); + if (toolbars == null || toolbars.Length == 0) + { + toolbarInstance = null; + return false; + } + else + { + toolbarInstance = toolbars[0]; + return true; + } #endif } @@ -130,9 +191,15 @@ private static void OnGuiLeft() } #if UNITY_2021_1_OR_NEWER - using (new GUILayout.HorizontalScope()) + using (new EditorGUILayout.VerticalScope()) { - OnToolbarGuiLeft(); + GUILayout.FlexibleSpace(); + using (new EditorGUILayout.HorizontalScope()) + { + OnToolbarGuiLeft(); + } + + GUILayout.FlexibleSpace(); } #else var screenWidth = EditorGUIUtility.currentViewWidth; @@ -167,9 +234,15 @@ private static void OnGuiRight() return; } - using (new EditorGUILayout.HorizontalScope()) + using (new EditorGUILayout.VerticalScope()) { - OnToolbarGuiRight(); + GUILayout.FlexibleSpace(); + using (new EditorGUILayout.HorizontalScope()) + { + OnToolbarGuiRight(); + } + + GUILayout.FlexibleSpace(); } } @@ -180,7 +253,12 @@ public static void Repaint() return; } +#if UNITY_6000_3_OR_NEWER + var toolbarWindow = EditorWindow.GetWindow(toolbarType); + toolbarWindow.Repaint(); +#else repaintMethod?.Invoke(toolbar, null); +#endif } public static bool IsToolbarAllowed { get; set; } = true; diff --git a/Assets/Editor Toolbox/Editor/Utilities/PropertyUtility.cs b/Assets/Editor Toolbox/Editor/Utilities/PropertyUtility.cs index 5c038fed..32e57b07 100644 --- a/Assets/Editor Toolbox/Editor/Utilities/PropertyUtility.cs +++ b/Assets/Editor Toolbox/Editor/Utilities/PropertyUtility.cs @@ -428,9 +428,11 @@ public static void OverrideLabelByValue(GUIContent label, SerializedProperty pro case SerializedPropertyType.ObjectReference: label.text = property.objectReferenceValue ? property.objectReferenceValue.ToString() : "null"; break; +#if UNITY_2021_3_OR_NEWER case SerializedPropertyType.ManagedReference: label.text = property.managedReferenceValue?.ToString() ?? "null"; break; +#endif case SerializedPropertyType.LayerMask: switch (property.intValue) { @@ -675,20 +677,21 @@ internal static bool IsSerializeReferenceProperty(SerializedProperty property) internal static bool TryGetSerializeReferenceType(SerializedProperty property, out Type referenceType) { - var fieldInfo = GetFieldInfo(property, out var propertyType); + var fieldInfo = GetFieldInfo(property, propertyType: out _); if (fieldInfo == null) { referenceType = null; return false; } - if (property.isArray) + var fieldType = fieldInfo.FieldType; + if (property.isArray || IsSerializableArrayElement(property)) { - referenceType = GetElementTypeFromArrayType(propertyType); + referenceType = GetElementTypeFromArrayType(fieldType); } else { - referenceType = fieldInfo.FieldType; + referenceType = fieldType; } return true; diff --git a/Assets/Editor Toolbox/README.md b/Assets/Editor Toolbox/README.md index e776a691..bedb6b66 100644 --- a/Assets/Editor Toolbox/README.md +++ b/Assets/Editor Toolbox/README.md @@ -1029,6 +1029,9 @@ Properties that can be edited include: ### Toolbar +> [!IMPORTANT] +> Unity 6.3 provides a new [official API](https://docs.unity3d.com/6000.3/Documentation/ScriptReference/Toolbars.MainToolbarElement.html) for extending the main toolbar. Toolbox implementation still relies on the Reflection and overriding predefined VisualElements setup, therefore consider using the new API. + > Editor Toolbox/Editor/ToolboxEditorToolbar.cs Check **Examples** for more details. @@ -1088,6 +1091,8 @@ public static class MyEditorUtility Select a specific object that is under the cursor (default key: tab). +Requires at least Unity 2019.1.x to work. + ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/sceneview.png) ### Utilities diff --git a/Assets/Editor Toolbox/Runtime/Attributes/Property/Regular/ProgressBarAttribute.cs b/Assets/Editor Toolbox/Runtime/Attributes/Property/Regular/ProgressBarAttribute.cs index 0db77f9c..ec69cfc5 100644 --- a/Assets/Editor Toolbox/Runtime/Attributes/Property/Regular/ProgressBarAttribute.cs +++ b/Assets/Editor Toolbox/Runtime/Attributes/Property/Regular/ProgressBarAttribute.cs @@ -26,6 +26,13 @@ public ProgressBarAttribute(string name = "", float minValue = 0, float maxValue public float MaxValue { get; private set; } + /// + /// Indicates value change step if is interactable. + /// + public float ValueStep { get; set; } = 0.001f; + + public bool IsInteractable { get; set; } + public Color Color { get => ColorUtility.TryParseHtmlString(HexColor, out var color) @@ -34,7 +41,5 @@ public Color Color } public string HexColor { get; set; } - - public bool IsInteractable { get; set; } } } \ No newline at end of file diff --git a/Assets/Editor Toolbox/Runtime/Serialization/SceneSerializationUtility.cs b/Assets/Editor Toolbox/Runtime/Serialization/SceneSerializationUtility.cs index cd4d9d3d..62e09219 100644 --- a/Assets/Editor Toolbox/Runtime/Serialization/SceneSerializationUtility.cs +++ b/Assets/Editor Toolbox/Runtime/Serialization/SceneSerializationUtility.cs @@ -27,6 +27,30 @@ private static void Initialize() isInitialized = true; } + private static bool TryCreateSceneData(SceneAsset sceneAsset, out SceneData sceneData) + { + var path = AssetDatabase.GetAssetPath(sceneAsset); + if (string.IsNullOrEmpty(path)) + { + sceneData = null; + return false; + } + + sceneData = new SceneData() + { + BuildIndex = SceneUtility.GetBuildIndexByScenePath(path), + SceneName = sceneAsset.name, + ScenePath = path, + }; + + return true; + } + + private static bool CanRefreshCache() + { + return !EditorApplication.isUpdating; + } + internal static void ConfirmCache() { //NOTE: refresh data only if the cache is empty, @@ -39,6 +63,11 @@ internal static void ConfirmCache() internal static void RefreshCache() { + if (!CanRefreshCache()) + { + return; + } + cachedScenes.Clear(); foreach (var scene in EditorBuildSettings.scenes) { @@ -59,12 +88,10 @@ internal static void RefreshCache() continue; } - cachedScenes.Add(sceneAsset, new SceneData() + if (TryCreateSceneData(sceneAsset, out var sceneData)) { - BuildIndex = SceneUtility.GetBuildIndexByScenePath(path), - SceneName = sceneAsset.name, - ScenePath = path - }); + cachedScenes.Add(sceneAsset, sceneData); + } } OnCacheRefreshed?.Invoke(); @@ -72,14 +99,30 @@ internal static void RefreshCache() internal static bool TryGetSceneData(SceneAsset sceneAsset, out SceneData data) { - ConfirmCache(); - if (!sceneAsset || !cachedScenes.TryGetValue(sceneAsset, out data)) + if (sceneAsset == null) { data = null; return false; } - return true; + if (CanRefreshCache()) + { + ConfirmCache(); + if (cachedScenes.TryGetValue(sceneAsset, out data)) + { + return true; + } + } + else + { + if (TryCreateSceneData(sceneAsset, out data)) + { + return true; + } + } + + data = null; + return false; } #endif /// diff --git a/Assets/Editor Toolbox/Runtime/Serialization/SerializedScene.cs b/Assets/Editor Toolbox/Runtime/Serialization/SerializedScene.cs index 649afed9..4cd7a9ee 100644 --- a/Assets/Editor Toolbox/Runtime/Serialization/SerializedScene.cs +++ b/Assets/Editor Toolbox/Runtime/Serialization/SerializedScene.cs @@ -1,5 +1,4 @@ using System; - using Toolbox.Serialization; #if UNITY_EDITOR diff --git a/Assets/Editor Toolbox/package.json b/Assets/Editor Toolbox/package.json index fa196562..737b33e0 100644 --- a/Assets/Editor Toolbox/package.json +++ b/Assets/Editor Toolbox/package.json @@ -1,7 +1,7 @@ { "name": "com.browar.editor-toolbox", "displayName": "Editor Toolbox", - "version": "0.14.2", + "version": "0.14.3", "unity": "2018.1", "description": "Tools, custom attributes, drawers, hierarchy overlay, and other extensions for the Unity Editor.", "keywords": [ diff --git a/Assets/Examples/Materials/TestMat.mat b/Assets/Examples/Materials/TestMat.mat index dc71e8b7..e2060a2f 100644 --- a/Assets/Examples/Materials/TestMat.mat +++ b/Assets/Examples/Materials/TestMat.mat @@ -2,14 +2,15 @@ %TAG !u! tag:unity3d.com,2011: --- !u!21 &2100000 Material: - serializedVersion: 6 + serializedVersion: 8 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: TestMat m_Shader: {fileID: 4800000, guid: 026435d85e5fd1f429a0ff9e8492c6b8, type: 3} - m_ShaderKeywords: + m_ValidKeywords: [] + m_InvalidKeywords: [] m_LightmapFlags: 4 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 @@ -59,6 +60,7 @@ Material: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + m_Ints: [] m_Floats: - _BumpScale: 1 - _Cutoff: 0.5 diff --git a/Assets/Examples/Scenes/SampleScene.unity b/Assets/Examples/Scenes/SampleScene.unity index b56b3b9a..cefc5421 100644 --- a/Assets/Examples/Scenes/SampleScene.unity +++ b/Assets/Examples/Scenes/SampleScene.unity @@ -1287,7 +1287,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: targetTag: Untagged - progressBar1: 9.159664 + progressBar1: 30 progressBar2: 25.4 minMaxVector: {x: 10, y: 73.893524} minMaxVectorInt: {x: 2, y: 7} diff --git a/Assets/Examples/Scripts/SampleBehaviour1.cs b/Assets/Examples/Scripts/SampleBehaviour1.cs index 2f657de1..42383b86 100644 --- a/Assets/Examples/Scripts/SampleBehaviour1.cs +++ b/Assets/Examples/Scripts/SampleBehaviour1.cs @@ -11,7 +11,7 @@ public class SampleBehaviour1 : MonoBehaviour [Label("Progress Bar", skinStyle: SkinStyle.Box)] - [ProgressBar(minValue: -10.0f, maxValue: 50.0f, HexColor = "#234DEA", IsInteractable = true)] + [ProgressBar(minValue: -10.0f, maxValue: 50.0f, HexColor = "#234DEA", IsInteractable = true, ValueStep = 2.5f)] public float progressBar1 = 25.4f; [ProgressBar(minValue: -10.0f, maxValue: 50.0f, HexColor = "#32A852", IsInteractable = false)] public float progressBar2 = 25.4f; diff --git a/Assets/Examples/Scripts/SampleBehaviour6.cs b/Assets/Examples/Scripts/SampleBehaviour6.cs index 63b58fbb..fcbb747a 100644 --- a/Assets/Examples/Scripts/SampleBehaviour6.cs +++ b/Assets/Examples/Scripts/SampleBehaviour6.cs @@ -96,6 +96,7 @@ public interface IGenericInterface TValue Value { get; } } + [Serializable] public class IntInterfaceImplementationInt : IGenericInterface { [SerializeField] @@ -104,6 +105,7 @@ public class IntInterfaceImplementationInt : IGenericInterface public int Value => value; } + [Serializable] public class StringInterfaceImplementation : IGenericInterface { [SerializeField] @@ -112,6 +114,7 @@ public class StringInterfaceImplementation : IGenericInterface public string Value => value; } + [Serializable] public class GenericInterfaceImplementation : IGenericInterface { [SerializeField] @@ -122,6 +125,7 @@ public class GenericInterfaceImplementation : IGenericInterface public TValue Value => value; } + [Serializable] public class WrongConstraintGenericInterfaceImplementation : IGenericInterface where TValue : struct { [SerializeField] diff --git a/README.md b/README.md index e776a691..bedb6b66 100644 --- a/README.md +++ b/README.md @@ -1029,6 +1029,9 @@ Properties that can be edited include: ### Toolbar +> [!IMPORTANT] +> Unity 6.3 provides a new [official API](https://docs.unity3d.com/6000.3/Documentation/ScriptReference/Toolbars.MainToolbarElement.html) for extending the main toolbar. Toolbox implementation still relies on the Reflection and overriding predefined VisualElements setup, therefore consider using the new API. + > Editor Toolbox/Editor/ToolboxEditorToolbar.cs Check **Examples** for more details. @@ -1088,6 +1091,8 @@ public static class MyEditorUtility Select a specific object that is under the cursor (default key: tab). +Requires at least Unity 2019.1.x to work. + ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/sceneview.png) ### Utilities