From 76f8e538ff2c42505a8ddd1012070f92933fd3da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Sun, 23 Oct 2022 01:13:00 +0200 Subject: [PATCH 01/23] Basic implementation of custom Context Menus for SerializedProperties --- .../Editor/ContextMenuController.cs | 58 +++++++++++++++++++ .../Editor/ContextMenuController.cs.meta | 11 ++++ 2 files changed, 69 insertions(+) create mode 100644 Assets/Editor Toolbox/Editor/ContextMenuController.cs create mode 100644 Assets/Editor Toolbox/Editor/ContextMenuController.cs.meta diff --git a/Assets/Editor Toolbox/Editor/ContextMenuController.cs b/Assets/Editor Toolbox/Editor/ContextMenuController.cs new file mode 100644 index 00000000..17081334 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenuController.cs @@ -0,0 +1,58 @@ +using UnityEditor; +using UnityEngine; + +namespace Toolbox.Editor +{ + [InitializeOnLoad] + internal static class ContextMenuController + { + static ContextMenuController() + { + EditorApplication.contextualPropertyMenu -= OnContextMenuOpening; + EditorApplication.contextualPropertyMenu += OnContextMenuOpening; + } + + private static void OnContextMenuOpening(GenericMenu menu, SerializedProperty property) + { + HandleSerializeReference(menu, property); + } + + //TODO: dedicated class to handle it + private static void HandleSerializeReference(GenericMenu menu, SerializedProperty property) + { + if (property.propertyType != SerializedPropertyType.ManagedReference || + !PropertyUtility.IsSerializableArrayElement(property)) + { + return; + } + + menu.AddItem(new GUIContent("Copy Reference"), false, () => + { + //propertyToCopy = property; + }); + //if (propertyToCopy != null) + //{ + // menu.AddItem(new GUIContent("Paste Reference"), false, () => + // { + // property.serializedObject.Update(); + // //property.managedReferenceValue = null; + // property.serializedObject.ApplyModifiedProperties(); + // propertyToCopy = null; + // }); + //} + //else + { + menu.AddDisabledItem(new GUIContent("Paste Reference")); + } + + menu.AddItem(new GUIContent("Duplicate Reference"), false, () => + { + var parent = property.GetParent(); + parent.arraySize++; + parent.serializedObject.ApplyModifiedProperties(); + var newProperty = parent.GetArrayElementAtIndex(parent.arraySize - 1); + //TODO: fill all serializable fields + }); + } + } +} \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/ContextMenuController.cs.meta b/Assets/Editor Toolbox/Editor/ContextMenuController.cs.meta new file mode 100644 index 00000000..2ae05c32 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenuController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2ce87ad5f7cff7d478ab9f199a1619c4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From a53a8844d4ace4c9c9bc11c8acbfd51ab1efe529 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Fri, 23 Aug 2024 14:05:11 +0200 Subject: [PATCH 02/23] Update README.md --- Assets/Editor Toolbox/README.md | 44 +++++++++++++++++++-------------- README.md | 44 +++++++++++++++++++-------------- 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/Assets/Editor Toolbox/README.md b/Assets/Editor Toolbox/README.md index c92fa027..8b33c2ec 100644 --- a/Assets/Editor Toolbox/README.md +++ b/Assets/Editor Toolbox/README.md @@ -124,6 +124,9 @@ Supported types: UnityEngine.**Object**. ```csharp [AssetPreview] public GameObject var1; +``` + +```csharp [AssetPreview(useLabel: false)] public Component var2; ``` @@ -302,19 +305,17 @@ Each **ToolboxDecoratorAttribute** has two basic properties **Order** (indicates ```csharp [BeginGroup("Group1", Style = GroupStyle.Round)] public int var1; -public int var2; -public int var3; [EndGroup] -public int var4; +public int var2; ``` ```csharp //NOTE: you can use [SpaceArea] to adjust positions between layout elements [BeginHorizontal(LabelWidth = 50.0f)] public int var1; -public int var2; [EndHorizontal] -public int var3; - +public int var2; +``` +```csharp [BeginHorizontalGroup(Label = "Horizontal Group", ControlFieldWidth = true, ElementsInLayout = 2)] public GameObject gameObject; [SpaceArea] @@ -325,13 +326,12 @@ public int[] ints; ```csharp [BeginIndent] public int var1; -public int var2; -public int var3; [EndIndent] -public int var4; - +public int var2; +``` +```csharp [IndentArea(4)] -public int var5; +public int var1; ``` ```csharp [SpaceArea(spaceBefore = 10.0f, spaceAfter = 5.0f, Order = 1)] @@ -370,6 +370,8 @@ private bool ValidationMethod() ```csharp [Help("Help information", UnityMessageType.Warning, Order = -1)] public int var1; +``` +```csharp [DynamicHelp(nameof(Message), UnityMessageType.Error)] public int var2; @@ -403,7 +405,8 @@ You are able to pass values from fields, properties, and methods. public string StringValue => "Sho"; [ShowIf(nameof(StringValue), "show")] public int var1; - +``` +```csharp public GameObject objectValue; [HideIf(nameof(objectValue), false)] public int var2; @@ -413,7 +416,8 @@ public int var2; public KeyCode enumValue = KeyCode.A; [EnableIf(nameof(enumValue), KeyCode.A)] public int var1; - +``` +```csharp [DisableIf(nameof(GetFloatValue), 2.0f, Comparison = UnityComparisonMethod.GreaterEqual)] public int var2; @@ -422,22 +426,24 @@ public float GetFloatValue() return 1.6f; } ``` - ```csharp [DisableInPlayMode] public int var1; ``` - +```csharp +[DisableInEditMode] +public int var1; +``` ```csharp public int var1; - [ShowDisabledIf(nameof(var1), 3, Comparison = UnityComparisonMethod.LessEqual)] public int var2; - +``` +```csharp +public int var1; [HideDisabledIf(nameof(var1), 3, Comparison = UnityComparisonMethod.GreaterEqual)] -public int var3; +public int var2; ``` - ```csharp public bool boolValue = true; [ShowWarningIf(nameof(boolValue), false, "Message", DisableField = true)] diff --git a/README.md b/README.md index c92fa027..8b33c2ec 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,9 @@ Supported types: UnityEngine.**Object**. ```csharp [AssetPreview] public GameObject var1; +``` + +```csharp [AssetPreview(useLabel: false)] public Component var2; ``` @@ -302,19 +305,17 @@ Each **ToolboxDecoratorAttribute** has two basic properties **Order** (indicates ```csharp [BeginGroup("Group1", Style = GroupStyle.Round)] public int var1; -public int var2; -public int var3; [EndGroup] -public int var4; +public int var2; ``` ```csharp //NOTE: you can use [SpaceArea] to adjust positions between layout elements [BeginHorizontal(LabelWidth = 50.0f)] public int var1; -public int var2; [EndHorizontal] -public int var3; - +public int var2; +``` +```csharp [BeginHorizontalGroup(Label = "Horizontal Group", ControlFieldWidth = true, ElementsInLayout = 2)] public GameObject gameObject; [SpaceArea] @@ -325,13 +326,12 @@ public int[] ints; ```csharp [BeginIndent] public int var1; -public int var2; -public int var3; [EndIndent] -public int var4; - +public int var2; +``` +```csharp [IndentArea(4)] -public int var5; +public int var1; ``` ```csharp [SpaceArea(spaceBefore = 10.0f, spaceAfter = 5.0f, Order = 1)] @@ -370,6 +370,8 @@ private bool ValidationMethod() ```csharp [Help("Help information", UnityMessageType.Warning, Order = -1)] public int var1; +``` +```csharp [DynamicHelp(nameof(Message), UnityMessageType.Error)] public int var2; @@ -403,7 +405,8 @@ You are able to pass values from fields, properties, and methods. public string StringValue => "Sho"; [ShowIf(nameof(StringValue), "show")] public int var1; - +``` +```csharp public GameObject objectValue; [HideIf(nameof(objectValue), false)] public int var2; @@ -413,7 +416,8 @@ public int var2; public KeyCode enumValue = KeyCode.A; [EnableIf(nameof(enumValue), KeyCode.A)] public int var1; - +``` +```csharp [DisableIf(nameof(GetFloatValue), 2.0f, Comparison = UnityComparisonMethod.GreaterEqual)] public int var2; @@ -422,22 +426,24 @@ public float GetFloatValue() return 1.6f; } ``` - ```csharp [DisableInPlayMode] public int var1; ``` - +```csharp +[DisableInEditMode] +public int var1; +``` ```csharp public int var1; - [ShowDisabledIf(nameof(var1), 3, Comparison = UnityComparisonMethod.LessEqual)] public int var2; - +``` +```csharp +public int var1; [HideDisabledIf(nameof(var1), 3, Comparison = UnityComparisonMethod.GreaterEqual)] -public int var3; +public int var2; ``` - ```csharp public bool boolValue = true; [ShowWarningIf(nameof(boolValue), false, "Message", DisableField = true)] From 6075ff72d60de79db1b50d7ba280486d779a1fae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Fri, 23 Aug 2024 14:27:14 +0200 Subject: [PATCH 03/23] Fix duplicated Validation operations during Toolbox initialization --- .../Editor/ToolboxEditorSettings.cs | 16 ++++++++++++++-- Assets/Editor Toolbox/Editor/ToolboxManager.cs | 4 +++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Assets/Editor Toolbox/Editor/ToolboxEditorSettings.cs b/Assets/Editor Toolbox/Editor/ToolboxEditorSettings.cs index 401d58cb..8ed7b1ab 100644 --- a/Assets/Editor Toolbox/Editor/ToolboxEditorSettings.cs +++ b/Assets/Editor Toolbox/Editor/ToolboxEditorSettings.cs @@ -117,6 +117,7 @@ internal class ToolboxEditorSettings : ScriptableObject, IToolboxGeneralSettings private bool projectSettingsDirty; private bool inspectorSettingsDirty; private bool sceneViewSettingsDirty; + private int lastValidationFrame; internal event Action OnHierarchySettingsChanged; internal event Action OnProjectSettingsChanged; @@ -179,13 +180,25 @@ internal void ValidateSceneViewSettings() internal void Validate() { + Validate(false); + } + + internal void Validate(bool force) + { + //NOTE: additional check to prevent multiple validations in the same frame, e.g. typical case: + // - after recompilation we are initializing toolbox and we want to validate settings, in the same time Unity validates all SOs + if (lastValidationFrame == Time.frameCount && !force) + { + return; + } + ValidateHierarchySettings(); ValidateProjectSettings(); ValidateInspectorSettings(); ValidateSceneViewSettings(); + lastValidationFrame = Time.frameCount; } - /// /// Called internally by the Editor after any value change or the Undo/Redo operation. /// @@ -334,7 +347,6 @@ public void ResetIconRectProperties() Defaults.smallFolderIconYPaddingDefault); } - public bool UseToolboxHierarchy { get => useToolboxHierarchy; diff --git a/Assets/Editor Toolbox/Editor/ToolboxManager.cs b/Assets/Editor Toolbox/Editor/ToolboxManager.cs index 6447ec09..36ec4407 100644 --- a/Assets/Editor Toolbox/Editor/ToolboxManager.cs +++ b/Assets/Editor Toolbox/Editor/ToolboxManager.cs @@ -152,13 +152,15 @@ internal static bool TryInitializeSettings(string settingsGuid) //try to get proper settings asset from the provided guid if (Settings = AssetDatabase.LoadAssetAtPath(SettingsPath)) { + //TODO: instead of relying on validation events let's prepare appropriate initialize/deinitialize process for all sub-systems + //subscribe to all related events Settings.OnHierarchySettingsChanged += ManageHierarchyCore; Settings.OnProjectSettingsChanged += ManageProjectCore; Settings.OnInspectorSettingsChanged += ManageInspectorCore; Settings.OnSceneViewSettingsChanged += ManageSceneViewCore; //initialize core functionalities - Settings.Validate(); + Settings.Validate(true); return true; } else From 0b53887f637f986149c653610121a4d5d540bb2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Sun, 25 Aug 2024 23:56:50 +0200 Subject: [PATCH 04/23] Add limit to visible components in the Hierarchy --- .../Hierarchy/HierarchyPropertyLabel.cs | 39 ++++++++-- .../Editor/Hierarchy/HierarchyTreeUtility.cs | 1 + Assets/Examples/Scenes/SampleScene.unity | 73 +++++++++++++++++++ 3 files changed, 107 insertions(+), 6 deletions(-) diff --git a/Assets/Editor Toolbox/Editor/Hierarchy/HierarchyPropertyLabel.cs b/Assets/Editor Toolbox/Editor/Hierarchy/HierarchyPropertyLabel.cs index 5853fc2d..629c74cc 100644 --- a/Assets/Editor Toolbox/Editor/Hierarchy/HierarchyPropertyLabel.cs +++ b/Assets/Editor Toolbox/Editor/Hierarchy/HierarchyPropertyLabel.cs @@ -179,6 +179,14 @@ public override float GetWidth() private class HierarchyScriptLabel : HierarchyPropertyLabel { + //TODO: properties to expose when switching to SerializedReference-based implementation: + // - max components + // - how to render standard scripts without custom icons + + private const int maxComponents = 5; + + private static readonly GUIContent moreLabelContent = new GUIContent("..."); + private static Texture componentIcon; private static Texture transformIcon; private static Texture warningIcon; @@ -248,8 +256,15 @@ public override bool Prepare(GameObject target, Rect availableRect) baseWidth = Style.minWidth; components = target.GetComponents(); var componentsCount = components.Length; + //NOTE: ignore transform for >1 components + var componentsToDisplay = componentsCount - 1; + if (componentsToDisplay > maxComponents) + { + componentsToDisplay = maxComponents + 1; + } + summWidth = componentsCount > 1 - ? (componentsCount - 1) * baseWidth + ? componentsToDisplay * baseWidth : baseWidth; isHighlighted = availableRect.Contains(Event.current.mousePosition); @@ -275,20 +290,32 @@ public override void OnGui(Rect rect) return; } - rect.xMin -= baseWidth * (componentsCount - 2); + //NOTE: we are already in appropriate position for the first component, let's move it depending on the count + var componentsToDisplay = componentsCount - 1; + if (componentsToDisplay > maxComponents) + { + //NOTE: one additional place for "more" + componentsToDisplay = maxComponents + 1; + } + + rect.xMin -= baseWidth * (componentsToDisplay - 1); var iconRect = rect; iconRect.xMin = rect.xMin; iconRect.xMax = rect.xMin + baseWidth; - //draw all icons associated to cached components (except transform) - for (var i = 1; i < components.Length; i++) + //NOTE: draw all icons associated to cached components (except transform) + for (var i = 1; i < componentsCount; i++) { + if (i > maxComponents) + { + GUI.Label(iconRect, moreLabelContent); + break; + } + var component = components[i]; var content = GetContent(component); - //draw icon for the current component GUI.Label(iconRect, content); - //adjust rect for the next script icon iconRect.x += baseWidth; } diff --git a/Assets/Editor Toolbox/Editor/Hierarchy/HierarchyTreeUtility.cs b/Assets/Editor Toolbox/Editor/Hierarchy/HierarchyTreeUtility.cs index dd3673d1..cd6a6f06 100644 --- a/Assets/Editor Toolbox/Editor/Hierarchy/HierarchyTreeUtility.cs +++ b/Assets/Editor Toolbox/Editor/Hierarchy/HierarchyTreeUtility.cs @@ -8,6 +8,7 @@ namespace Toolbox.Editor.Hierarchy /// internal static class HierarchyTreeUtility { + //NOTE: consider caching pre-created texturess for dashed lines and use them to optimize each call private const float dashLength = 4.0f; private const float spaceLength = 1.0f; diff --git a/Assets/Examples/Scenes/SampleScene.unity b/Assets/Examples/Scenes/SampleScene.unity index e7bf1d76..43c5a27c 100644 --- a/Assets/Examples/Scenes/SampleScene.unity +++ b/Assets/Examples/Scenes/SampleScene.unity @@ -468,7 +468,12 @@ GameObject: - component: {fileID: 580334320} - component: {fileID: 580334319} - component: {fileID: 580334318} + - component: {fileID: 580334325} - component: {fileID: 580334317} + - component: {fileID: 580334324} + - component: {fileID: 580334323} + - component: {fileID: 580334322} + - component: {fileID: 580334321} m_Layer: 0 m_Name: GameObject (8) m_TagString: Untagged @@ -552,6 +557,74 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 22 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &580334321 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 580334316} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!65 &580334322 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 580334316} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!65 &580334323 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 580334316} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!65 &580334324 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 580334316} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!54 &580334325 +Rigidbody: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 580334316} + serializedVersion: 2 + m_Mass: 1 + m_Drag: 0 + m_AngularDrag: 0.05 + m_UseGravity: 1 + m_IsKinematic: 0 + m_Interpolate: 0 + m_Constraints: 0 + m_CollisionDetection: 0 --- !u!1 &661896457 GameObject: m_ObjectHideFlags: 0 From 298c0cf9d13e3acb72d96cb2858de497e4235b57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Mon, 26 Aug 2024 12:05:17 +0200 Subject: [PATCH 05/23] Display warning if there is a conflict in a type field --- .../Editor/Internal/TypeField.cs | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/Assets/Editor Toolbox/Editor/Internal/TypeField.cs b/Assets/Editor Toolbox/Editor/Internal/TypeField.cs index 8adcad8d..4705ceba 100644 --- a/Assets/Editor Toolbox/Editor/Internal/TypeField.cs +++ b/Assets/Editor Toolbox/Editor/Internal/TypeField.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; - using UnityEditor; using UnityEngine; @@ -14,7 +13,6 @@ public class TypeField private TypeConstraintContext constraintContext; private TypeAppearanceContext appearanceContext; - public TypeField() : this(null, null) { } @@ -27,7 +25,6 @@ public TypeField(TypeConstraintContext constraintContext, TypeAppearanceContext this.appearanceContext = appearanceContext ?? new TypeAppearanceContext(this.constraintContext, TypeGrouping.None, true); } - private Type RetriveSelectedType(IReadOnlyList types, int selectedIndex, bool includeEmptyValue) { if (includeEmptyValue) @@ -38,6 +35,18 @@ private Type RetriveSelectedType(IReadOnlyList types, int selectedIndex, b return selectedIndex >= 0 ? types[selectedIndex] : null; } + private void DrawTypeConflictWarning(Rect position) + { + const float warningSpace = 18.0f; + + var warningPosition = position; + warningPosition.xMax = position.xMin; + warningPosition.xMin -= warningSpace; + var warningIcon = EditorGuiUtility.GetHelpIcon(MessageType.Warning); + var warningLabel = new GUIContent(warningIcon, "Currently active type is not available from the selection. " + + "It may be caused by a conflict between the type filter and cached data."); + GUI.Label(warningPosition, warningLabel); + } public void OnGui(Rect position, bool addSearchField, Action onSelect) { @@ -46,12 +55,19 @@ public void OnGui(Rect position, bool addSearchField, Action onSelect) public void OnGui(Rect position, bool addSearchField, Action onSelect, Type activeType) { + var addEmptyValue = AppearanceContext.AddEmptyValue; + var collection = TypeUtilities.GetCollection(AppearanceContext); var values = collection.Values; var labels = collection.Labels; var index = collection.IndexOf(activeType); - var addEmptyValue = AppearanceContext.AddEmptyValue; + var selectedType = RetriveSelectedType(values, index, addEmptyValue); + if (activeType != selectedType) + { + DrawTypeConflictWarning(position); + } + if (addSearchField) { var buttonLabel = new GUIContent(labels[index]); @@ -82,7 +98,6 @@ public void OnGui(Rect position, bool addSearchField, Action onSelect, Typ OnGui(position, addSearchField, onSelect, activeType); } - public TypeConstraintContext ConstraintContext { get => constraintContext; From 184c24dc9a16536902310b8443c7388254c24699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Mon, 26 Aug 2024 12:51:23 +0200 Subject: [PATCH 06/23] Update project to Unity 2021.x; implement SerializeReference-based context menu operations (Copy, Paster, Duplicate) --- Assets/Editor Toolbox/Editor/ContextMenu.meta | 8 + .../ContextMenu/IContextMenuOperation.cs | 14 ++ .../ContextMenu/IContextMenuOperation.cs.meta | 11 ++ .../Editor/ContextMenu/Management.meta | 8 + .../Management/ToolboxContextMenuManager.cs | 60 +++++++ .../ToolboxContextMenuManager.cs.meta} | 0 .../Editor/ContextMenu/Operations.meta | 8 + .../Operations/SerializeReference.meta | 8 + .../CopySerializeReferenceOperation.cs | 48 +++++ .../CopySerializeReferenceOperation.cs.meta | 11 ++ .../CopySerializedRererenceCache.cs | 16 ++ .../CopySerializedRererenceCache.cs.meta | 11 ++ ...SerializeReferenceArrayElementOperation.cs | 46 +++++ ...lizeReferenceArrayElementOperation.cs.meta | 11 ++ .../PasteSerializeReferenceOperation.cs | 54 ++++++ .../PasteSerializeReferenceOperation.cs.meta | 11 ++ .../Editor/ContextMenuController.cs | 58 ------ Assets/Examples/Scenes/SampleScene.unity | 125 +++++++++---- Assets/Examples/Scripts/SampleBehaviour6.cs | 4 +- Packages/manifest.json | 10 +- Packages/packages-lock.json | 25 +-- ProjectSettings/MemorySettings.asset | 35 ++++ ProjectSettings/ProjectSettings.asset | 117 +++++++++++- ProjectSettings/ProjectVersion.txt | 4 +- ProjectSettings/SceneTemplateSettings.json | 167 ++++++++++++++++++ ProjectSettings/boot.config | 0 26 files changed, 750 insertions(+), 120 deletions(-) create mode 100644 Assets/Editor Toolbox/Editor/ContextMenu.meta create mode 100644 Assets/Editor Toolbox/Editor/ContextMenu/IContextMenuOperation.cs create mode 100644 Assets/Editor Toolbox/Editor/ContextMenu/IContextMenuOperation.cs.meta create mode 100644 Assets/Editor Toolbox/Editor/ContextMenu/Management.meta create mode 100644 Assets/Editor Toolbox/Editor/ContextMenu/Management/ToolboxContextMenuManager.cs rename Assets/Editor Toolbox/Editor/{ContextMenuController.cs.meta => ContextMenu/Management/ToolboxContextMenuManager.cs.meta} (100%) create mode 100644 Assets/Editor Toolbox/Editor/ContextMenu/Operations.meta create mode 100644 Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference.meta create mode 100644 Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs create mode 100644 Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs.meta create mode 100644 Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializedRererenceCache.cs create mode 100644 Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializedRererenceCache.cs.meta create mode 100644 Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/DuplicateSerializeReferenceArrayElementOperation.cs create mode 100644 Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/DuplicateSerializeReferenceArrayElementOperation.cs.meta create mode 100644 Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs create mode 100644 Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs.meta delete mode 100644 Assets/Editor Toolbox/Editor/ContextMenuController.cs create mode 100644 ProjectSettings/MemorySettings.asset create mode 100644 ProjectSettings/SceneTemplateSettings.json create mode 100644 ProjectSettings/boot.config diff --git a/Assets/Editor Toolbox/Editor/ContextMenu.meta b/Assets/Editor Toolbox/Editor/ContextMenu.meta new file mode 100644 index 00000000..2d2628a8 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenu.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a1e662719d3a4f8428bc265f89ff3e3f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/IContextMenuOperation.cs b/Assets/Editor Toolbox/Editor/ContextMenu/IContextMenuOperation.cs new file mode 100644 index 00000000..37720bb4 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenu/IContextMenuOperation.cs @@ -0,0 +1,14 @@ +using UnityEditor; +using UnityEngine; + +namespace Toolbox.Editor.ContextMenu +{ + internal interface IContextMenuOperation + { + bool IsVisible(SerializedProperty property); + bool IsEnabled(SerializedProperty property); + void Perform(SerializedProperty property); + + GUIContent Label { get; } + } +} \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/IContextMenuOperation.cs.meta b/Assets/Editor Toolbox/Editor/ContextMenu/IContextMenuOperation.cs.meta new file mode 100644 index 00000000..d3278ecb --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenu/IContextMenuOperation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3e9621ae61945d547b96764dfcc91297 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Management.meta b/Assets/Editor Toolbox/Editor/ContextMenu/Management.meta new file mode 100644 index 00000000..604e1a60 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Management.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f9550a0c98e053e40a4634f10ca80436 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Management/ToolboxContextMenuManager.cs b/Assets/Editor Toolbox/Editor/ContextMenu/Management/ToolboxContextMenuManager.cs new file mode 100644 index 00000000..69004448 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Management/ToolboxContextMenuManager.cs @@ -0,0 +1,60 @@ +using System.Collections.Generic; + +using UnityEditor; + +namespace Toolbox.Editor.ContextMenu.Management +{ + using Toolbox.Editor.ContextMenu.Operations; + + [InitializeOnLoad] + internal static class ToolboxContextMenuManager + { + private static readonly List registeredOperations; + + static ToolboxContextMenuManager() + { + registeredOperations = new List() + { + new CopySerializeReferenceOperation(), + new PasteSerializeReferenceOperation(), + new DuplicateSerializeReferenceArrayElementOperation() + }; + + EditorApplication.contextualPropertyMenu -= OnContextMenuOpening; + EditorApplication.contextualPropertyMenu += OnContextMenuOpening; + } + + public static void AppendOpertation(IContextMenuOperation operation) + { + registeredOperations.Add(operation); + } + + public static bool RemoveOperation(IContextMenuOperation operation) + { + return registeredOperations.Remove(operation); + } + + private static void OnContextMenuOpening(GenericMenu menu, SerializedProperty property) + { + foreach (var operation in registeredOperations) + { + if (!operation.IsVisible(property)) + { + continue; + } + + var label = operation.Label; + if (!operation.IsEnabled(property)) + { + menu.AddDisabledItem(label); + continue; + } + + menu.AddItem(label, false, () => + { + operation.Perform(property); + }); + } + } + } +} \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/ContextMenuController.cs.meta b/Assets/Editor Toolbox/Editor/ContextMenu/Management/ToolboxContextMenuManager.cs.meta similarity index 100% rename from Assets/Editor Toolbox/Editor/ContextMenuController.cs.meta rename to Assets/Editor Toolbox/Editor/ContextMenu/Management/ToolboxContextMenuManager.cs.meta diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations.meta b/Assets/Editor Toolbox/Editor/ContextMenu/Operations.meta new file mode 100644 index 00000000..d58726a4 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6594e87a290f93e43ac2a6fb741e38b0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference.meta b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference.meta new file mode 100644 index 00000000..3d68e19f --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e9778a5dacff47d488da2a0e59f144d0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs new file mode 100644 index 00000000..892baa88 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs @@ -0,0 +1,48 @@ +using UnityEditor; +using UnityEngine; + +namespace Toolbox.Editor.ContextMenu.Operations +{ + internal class CopySerializeReferenceOperation : IContextMenuOperation + { + internal static CopySerializedRererenceCache Cache { get; private set; } + + public bool IsVisible(SerializedProperty property) + { +#if UNITY_2021_3_OR_NEWER + return property != null && property.propertyType == SerializedPropertyType.ManagedReference; +#else + return false; +#endif + } + + public bool IsEnabled(SerializedProperty property) + { + return true; + } + + public void Perform(SerializedProperty property) + { +#if UNITY_2021_3_OR_NEWER + var value = property.managedReferenceValue; + if (value != null) + { + var referenceType = value.GetType(); + var data = JsonUtility.ToJson(value); + Cache = new CopySerializedRererenceCache(referenceType, data); + return; + } + + Cache = new CopySerializedRererenceCache(null, null); +#endif + } + + public GUIContent Label => new GUIContent("Copy Serialize Reference"); + + [InitializeOnLoadMethod] + private static void Initialize() + { + Cache = null; + } + } +} \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs.meta b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs.meta new file mode 100644 index 00000000..ed72d431 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8afa3e7c770d3b94193bcb0c6fac70ae +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializedRererenceCache.cs b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializedRererenceCache.cs new file mode 100644 index 00000000..4b15ff51 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializedRererenceCache.cs @@ -0,0 +1,16 @@ +using System; + +namespace Toolbox.Editor.ContextMenu.Operations +{ + internal class CopySerializedRererenceCache + { + public CopySerializedRererenceCache(Type referenceType, string data) + { + ReferenceType = referenceType; + Data = data; + } + + public Type ReferenceType { get; } + public string Data { get; } + } +} \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializedRererenceCache.cs.meta b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializedRererenceCache.cs.meta new file mode 100644 index 00000000..4558c922 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializedRererenceCache.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f9324f134d404e2499b9815283f88ff2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/DuplicateSerializeReferenceArrayElementOperation.cs b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/DuplicateSerializeReferenceArrayElementOperation.cs new file mode 100644 index 00000000..7e2130a2 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/DuplicateSerializeReferenceArrayElementOperation.cs @@ -0,0 +1,46 @@ +using UnityEditor; +using UnityEngine; + +namespace Toolbox.Editor.ContextMenu.Operations +{ + internal class DuplicateSerializeReferenceArrayElementOperation : IContextMenuOperation + { + public GUIContent Label => new GUIContent("Duplicate Serialize Reference Array Element"); + + public bool IsVisible(SerializedProperty property) + { +#if UNITY_2021_3_OR_NEWER + return property != null && property.propertyType == SerializedPropertyType.ManagedReference && + PropertyUtility.IsSerializableArrayElement(property); +#else + return false; +#endif + } + + public bool IsEnabled(SerializedProperty property) + { + return true; + } + + public void Perform(SerializedProperty property) + { + var sourceProperty = property.Copy(); + sourceProperty.serializedObject.Update(); + var sourceValue = sourceProperty.managedReferenceValue; + + var arrayProperty = PropertyUtility.GetArray(sourceProperty); + var newElementIndex = arrayProperty.arraySize; + arrayProperty.arraySize = newElementIndex + 1; + //NOTE: there will be null by default anyway + if (sourceValue != null) + { + var targetData = JsonUtility.ToJson(sourceValue); + var targetValue = JsonUtility.FromJson(targetData, sourceValue.GetType()); + var targetProperty = arrayProperty.GetArrayElementAtIndex(newElementIndex); + targetProperty.managedReferenceValue = targetValue; + } + + sourceProperty.serializedObject.ApplyModifiedProperties(); + } + } +} \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/DuplicateSerializeReferenceArrayElementOperation.cs.meta b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/DuplicateSerializeReferenceArrayElementOperation.cs.meta new file mode 100644 index 00000000..390afa85 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/DuplicateSerializeReferenceArrayElementOperation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f84e86374ad959446a33376ed6b751ac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs new file mode 100644 index 00000000..c68486ec --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs @@ -0,0 +1,54 @@ +using System; + +using UnityEditor; +using UnityEngine; + +namespace Toolbox.Editor.ContextMenu.Operations +{ + + internal class PasteSerializeReferenceOperation : IContextMenuOperation + { + private object GetCachedManagedReferenceValue() + { + var cachedData = CopySerializeReferenceOperation.Cache; + if (cachedData.ReferenceType != null) + { + var newValue = JsonUtility.FromJson(cachedData.Data, cachedData.ReferenceType); + return newValue; + } + else + { + return null; + } + } + + public bool IsVisible(SerializedProperty property) + { +#if UNITY_2021_3_OR_NEWER + return property != null && property.propertyType == SerializedPropertyType.ManagedReference; +#else + return false; +#endif + } + + public bool IsEnabled(SerializedProperty property) + { + return CopySerializeReferenceOperation.Cache != null; + } + + public void Perform(SerializedProperty property) + { + var targetProperty = property.Copy(); + try + { + targetProperty.serializedObject.Update(); + targetProperty.managedReferenceValue = GetCachedManagedReferenceValue(); + targetProperty.serializedObject.ApplyModifiedProperties(); + } + catch (Exception) + { } + } + + public GUIContent Label => new GUIContent("Paste Serialize Reference"); + } +} \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs.meta b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs.meta new file mode 100644 index 00000000..fa889033 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c5d139b9e4126bb4da4c01c8480bf209 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/ContextMenuController.cs b/Assets/Editor Toolbox/Editor/ContextMenuController.cs deleted file mode 100644 index 17081334..00000000 --- a/Assets/Editor Toolbox/Editor/ContextMenuController.cs +++ /dev/null @@ -1,58 +0,0 @@ -using UnityEditor; -using UnityEngine; - -namespace Toolbox.Editor -{ - [InitializeOnLoad] - internal static class ContextMenuController - { - static ContextMenuController() - { - EditorApplication.contextualPropertyMenu -= OnContextMenuOpening; - EditorApplication.contextualPropertyMenu += OnContextMenuOpening; - } - - private static void OnContextMenuOpening(GenericMenu menu, SerializedProperty property) - { - HandleSerializeReference(menu, property); - } - - //TODO: dedicated class to handle it - private static void HandleSerializeReference(GenericMenu menu, SerializedProperty property) - { - if (property.propertyType != SerializedPropertyType.ManagedReference || - !PropertyUtility.IsSerializableArrayElement(property)) - { - return; - } - - menu.AddItem(new GUIContent("Copy Reference"), false, () => - { - //propertyToCopy = property; - }); - //if (propertyToCopy != null) - //{ - // menu.AddItem(new GUIContent("Paste Reference"), false, () => - // { - // property.serializedObject.Update(); - // //property.managedReferenceValue = null; - // property.serializedObject.ApplyModifiedProperties(); - // propertyToCopy = null; - // }); - //} - //else - { - menu.AddDisabledItem(new GUIContent("Paste Reference")); - } - - menu.AddItem(new GUIContent("Duplicate Reference"), false, () => - { - var parent = property.GetParent(); - parent.arraySize++; - parent.serializedObject.ApplyModifiedProperties(); - var newProperty = parent.GetArrayElementAtIndex(parent.arraySize - 1); - //TODO: fill all serializable fields - }); - } - } -} \ No newline at end of file diff --git a/Assets/Examples/Scenes/SampleScene.unity b/Assets/Examples/Scenes/SampleScene.unity index 43c5a27c..803df7e2 100644 --- a/Assets/Examples/Scenes/SampleScene.unity +++ b/Assets/Examples/Scenes/SampleScene.unity @@ -155,6 +155,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3} m_Name: m_EditorClassIdentifier: + m_SendPointerHoverToParent: 1 m_HorizontalAxis: Horizontal m_VerticalAxis: Vertical m_SubmitButton: Submit @@ -187,6 +188,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 12 @@ -280,6 +282,7 @@ Transform: m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} m_LocalPosition: {x: 0, y: 3, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 10 @@ -310,6 +313,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1414023087} m_RootOrder: 1 @@ -340,6 +344,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 0 @@ -370,6 +375,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 685318311} m_RootOrder: 0 @@ -453,6 +459,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 1, z: -10} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 9 @@ -505,6 +512,7 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 @@ -553,6 +561,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -7.59, y: -2.12, z: 0.53} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 22 @@ -712,6 +721,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 2 @@ -744,6 +754,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 941031098} m_RootOrder: 1 @@ -817,6 +828,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 758033805} m_Father: {fileID: 0} @@ -848,6 +860,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 456522775} m_Father: {fileID: 1414023087} @@ -881,6 +894,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 968382739} m_RootOrder: 0 @@ -956,6 +970,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 941031098} m_RootOrder: 0 @@ -1033,71 +1048,93 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: var1: - id: 0 + rid: 0 var2: - id: 1 + rid: 7033609465735938071 var3: - id: 2 + rid: 7033609465735938065 + var4: + rid: 7033609465735938072 vars: - - id: 3 - - id: 4 - - id: 5 - - id: 6 + - rid: 3 + - rid: 4 + - rid: 5 + - rid: 6 + - rid: 7033609465735938087 references: - version: 1 - 00000000: + version: 2 + RefIds: + - rid: -2 + type: {class: , ns: , asm: } + - rid: 0 type: {class: SampleBehaviour6/ClassWithInterface1, ns: , asm: Assembly-CSharp} data: go: {fileID: 977748987} var1: - id: 7 - 00000001: + rid: 7 + - rid: 3 type: {class: SampleBehaviour6/ClassWithInterface1, ns: , asm: Assembly-CSharp} data: go: {fileID: 0} var1: - id: 8 - 00000002: + rid: 7033609465735938082 + - rid: 4 type: {class: SampleBehaviour6/ClassWithInterface2, ns: , asm: Assembly-CSharp} data: var1: 0 mat: {fileID: 0} - 00000003: + - rid: 5 + type: {class: SampleBehaviour6/ClassWithInterface4, ns: , asm: Assembly-CSharp} + data: + var1: 0 + mat: {fileID: 0} + var33: 0 + - rid: 6 + type: {class: SampleBehaviour6/Struct, ns: , asm: Assembly-CSharp} + data: + var1: 1 + var2: 0 + - rid: 7 type: {class: SampleBehaviour6/ClassWithInterface1, ns: , asm: Assembly-CSharp} data: go: {fileID: 0} var1: - id: 9 - 00000004: - type: {class: SampleBehaviour6/ClassWithInterface2, ns: , asm: Assembly-CSharp} + rid: -2 + - rid: 7033609465735938065 + type: {class: SampleBehaviour6/ClassWithInterface1, ns: , asm: Assembly-CSharp} + data: + go: {fileID: 1972418676} + var1: + rid: 7033609465735938066 + - rid: 7033609465735938066 + type: {class: SampleBehaviour6/ClassWithInterface1, ns: , asm: Assembly-CSharp} + data: + go: {fileID: 0} + var1: + rid: -2 + - rid: 7033609465735938071 + type: {class: SampleBehaviour6/ClassWithInterface4, ns: , asm: Assembly-CSharp} data: var1: 0 mat: {fileID: 0} - 00000005: + var33: 0 + - rid: 7033609465735938072 type: {class: SampleBehaviour6/ClassWithInterface4, ns: , asm: Assembly-CSharp} data: var1: 0 mat: {fileID: 0} var33: 0 - 00000006: + - rid: 7033609465735938082 type: {class: SampleBehaviour6/Struct, ns: , asm: Assembly-CSharp} data: - var1: 1 + var1: 0 var2: 0 - 00000007: - type: {class: SampleBehaviour6/ClassWithInterface1, ns: , asm: Assembly-CSharp} - data: - go: {fileID: 0} - var1: - id: 9 - 00000008: + - rid: 7033609465735938087 type: {class: SampleBehaviour6/ClassWithInterface4, ns: , asm: Assembly-CSharp} data: var1: 0 mat: {fileID: 0} var33: 0 - 00000009: - type: {class: , ns: , asm: } --- !u!4 &752799893 Transform: m_ObjectHideFlags: 2 @@ -1108,6 +1145,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 6 @@ -1138,6 +1176,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 666544667} m_RootOrder: 0 @@ -1168,6 +1207,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 8 @@ -1200,6 +1240,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 704298045} - {fileID: 663659268} @@ -1311,6 +1352,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 1 @@ -1343,6 +1385,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 699596840} - {fileID: 1246829911} @@ -1421,6 +1464,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0.5, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 18 @@ -1449,6 +1493,7 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 @@ -1515,6 +1560,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1707505306} m_RootOrder: 1 @@ -1590,6 +1636,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2143522254} m_RootOrder: 1 @@ -1727,6 +1774,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 0, y: 0, z: 0} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 2113405572} m_Father: {fileID: 0} @@ -1764,6 +1812,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 5 @@ -1785,7 +1834,7 @@ MonoBehaviour: type2: typeReference: UnityEngine.UI.RawImage, UnityEngine.UI type3: - typeReference: + typeReference: UnityEngine.UI.RawImage, UnityEngine.UI type4: typeReference: UnityEngine.BoxCollider, UnityEngine.PhysicsModule type5: @@ -1837,6 +1886,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1707505306} m_RootOrder: 0 @@ -1910,6 +1960,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 19 @@ -2004,6 +2055,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 0, y: 0, z: 0} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 941031098} - {fileID: 2143522254} @@ -2045,6 +2097,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 968382739} m_RootOrder: 1 @@ -2118,6 +2171,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 685318311} - {fileID: 259978188} @@ -2195,6 +2249,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 4 @@ -2258,6 +2313,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 7 @@ -2290,6 +2346,7 @@ RectTransform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2143522254} m_RootOrder: 0 @@ -2363,6 +2420,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 15 @@ -2394,6 +2452,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 3 @@ -2452,6 +2511,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 1221313407} - {fileID: 1114929483} @@ -2527,6 +2587,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 17 @@ -2557,6 +2618,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 11 @@ -2587,6 +2649,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_RootOrder: 16 @@ -2619,6 +2682,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1165497328} m_RootOrder: 0 @@ -2691,6 +2755,7 @@ RectTransform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 1584091012} - {fileID: 1125523744} diff --git a/Assets/Examples/Scripts/SampleBehaviour6.cs b/Assets/Examples/Scripts/SampleBehaviour6.cs index ddd423af..9a12e321 100644 --- a/Assets/Examples/Scripts/SampleBehaviour6.cs +++ b/Assets/Examples/Scripts/SampleBehaviour6.cs @@ -11,8 +11,10 @@ public class SampleBehaviour6 : MonoBehaviour public Interface1 var1; [SerializeReference, ReferencePicker(ForceUninitializedInstance = true)] public ClassWithInterfaceBase var2; - [SerializeReference, ReferencePicker(ParentType = typeof(ClassWithInterface2), AddTextSearchField = false)] + [SerializeReference, ReferencePicker] public ClassWithInterfaceBase var3; + [SerializeReference, ReferencePicker(ParentType = typeof(ClassWithInterface2), AddTextSearchField = false)] + public ClassWithInterfaceBase var4; [SerializeReference, ReferencePicker, ReorderableList] public Interface1[] vars; #endif diff --git a/Packages/manifest.json b/Packages/manifest.json index a1ac03af..9e4d1c2d 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -3,17 +3,17 @@ "com.unity.2d.sprite": "1.0.0", "com.unity.2d.tilemap": "1.0.0", "com.unity.analytics": "3.6.12", - "com.unity.collab-proxy": "1.15.15", + "com.unity.collab-proxy": "2.0.0", "com.unity.editorcoroutines": "1.0.0", - "com.unity.ide.rider": "2.0.7", - "com.unity.ide.visualstudio": "2.0.14", + "com.unity.ide.rider": "3.0.18", + "com.unity.ide.visualstudio": "2.0.17", "com.unity.ide.vscode": "1.2.5", "com.unity.test-framework": "1.1.31", "com.unity.textmeshpro": "3.0.6", - "com.unity.timeline": "1.4.8", + "com.unity.timeline": "1.6.4", "com.unity.toolchain.win-x86_64-linux-x86_64": "1.0.0", "com.unity.ugui": "1.0.0", - "com.unity.xr.legacyinputhelpers": "2.1.9", + "com.unity.xr.legacyinputhelpers": "2.1.10", "com.unity.modules.ai": "1.0.0", "com.unity.modules.androidjni": "1.0.0", "com.unity.modules.animation": "1.0.0", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index dfda880c..4ae6aadb 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -22,12 +22,10 @@ "url": "https://packages.unity.com" }, "com.unity.collab-proxy": { - "version": "1.15.15", + "version": "2.0.0", "depth": 0, "source": "registry", - "dependencies": { - "com.unity.services.core": "1.0.1" - }, + "dependencies": {}, "url": "https://packages.unity.com" }, "com.unity.editorcoroutines": { @@ -45,16 +43,16 @@ "url": "https://packages.unity.com" }, "com.unity.ide.rider": { - "version": "2.0.7", + "version": "3.0.18", "depth": 0, "source": "registry", "dependencies": { - "com.unity.test-framework": "1.1.1" + "com.unity.ext.nunit": "1.0.6" }, "url": "https://packages.unity.com" }, "com.unity.ide.visualstudio": { - "version": "2.0.14", + "version": "2.0.17", "depth": 0, "source": "registry", "dependencies": { @@ -69,15 +67,6 @@ "dependencies": {}, "url": "https://packages.unity.com" }, - "com.unity.services.core": { - "version": "1.0.1", - "depth": 1, - "source": "registry", - "dependencies": { - "com.unity.modules.unitywebrequest": "1.0.0" - }, - "url": "https://packages.unity.com" - }, "com.unity.sysroot": { "version": "1.0.0", "depth": 1, @@ -115,7 +104,7 @@ "url": "https://packages.unity.com" }, "com.unity.timeline": { - "version": "1.4.8", + "version": "1.6.4", "depth": 0, "source": "registry", "dependencies": { @@ -146,7 +135,7 @@ } }, "com.unity.xr.legacyinputhelpers": { - "version": "2.1.9", + "version": "2.1.10", "depth": 0, "source": "registry", "dependencies": { diff --git a/ProjectSettings/MemorySettings.asset b/ProjectSettings/MemorySettings.asset new file mode 100644 index 00000000..5b5facec --- /dev/null +++ b/ProjectSettings/MemorySettings.asset @@ -0,0 +1,35 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!387306366 &1 +MemorySettings: + m_ObjectHideFlags: 0 + m_EditorMemorySettings: + m_MainAllocatorBlockSize: -1 + m_ThreadAllocatorBlockSize: -1 + m_MainGfxBlockSize: -1 + m_ThreadGfxBlockSize: -1 + m_CacheBlockSize: -1 + m_TypetreeBlockSize: -1 + m_ProfilerBlockSize: -1 + m_ProfilerEditorBlockSize: -1 + m_BucketAllocatorGranularity: -1 + m_BucketAllocatorBucketsCount: -1 + m_BucketAllocatorBlockSize: -1 + m_BucketAllocatorBlockCount: -1 + m_ProfilerBucketAllocatorGranularity: -1 + m_ProfilerBucketAllocatorBucketsCount: -1 + m_ProfilerBucketAllocatorBlockSize: -1 + m_ProfilerBucketAllocatorBlockCount: -1 + m_TempAllocatorSizeMain: -1 + m_JobTempAllocatorBlockSize: -1 + m_BackgroundJobTempAllocatorBlockSize: -1 + m_JobTempAllocatorReducedBlockSize: -1 + m_TempAllocatorSizeGIBakingWorker: -1 + m_TempAllocatorSizeNavMeshWorker: -1 + m_TempAllocatorSizeAudioWorker: -1 + m_TempAllocatorSizeCloudWorker: -1 + m_TempAllocatorSizeGfx: -1 + m_TempAllocatorSizeJobWorker: -1 + m_TempAllocatorSizeBackgroundWorker: -1 + m_TempAllocatorSizePreloadManager: -1 + m_PlatformMemorySettings: {} diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index 3a8ee156..a917543d 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -3,7 +3,7 @@ --- !u!129 &1 PlayerSettings: m_ObjectHideFlags: 0 - serializedVersion: 22 + serializedVersion: 23 productGUID: 8a5218c0d05cb524792aaa1333627b48 AndroidProfiler: 0 AndroidFilterTouchesWhenObscured: 0 @@ -145,11 +145,13 @@ PlayerSettings: enable360StereoCapture: 0 isWsaHolographicRemotingEnabled: 0 enableFrameTimingStats: 0 + enableOpenGLProfilerGPURecorders: 1 useHDRDisplay: 0 D3DHDRBitDepth: 0 m_ColorGamuts: 00000000 targetPixelDensity: 30 resolutionScalingMode: 0 + resetResolutionOnWindowResize: 0 androidSupportedAspectRatio: 1 androidMaxAspectRatio: 2.1 applicationIdentifier: @@ -160,7 +162,7 @@ PlayerSettings: tvOS: 0 overrideDefaultApplicationIdentifier: 0 AndroidBundleVersionCode: 1 - AndroidMinSdkVersion: 19 + AndroidMinSdkVersion: 22 AndroidTargetSdkVersion: 0 AndroidPreferredInstallLocation: 1 aotOptions: @@ -216,6 +218,7 @@ PlayerSettings: iOSLaunchScreeniPadCustomStoryboardPath: iOSDeviceRequirements: [] iOSURLSchemes: [] + macOSURLSchemes: [] iOSBackgroundModes: 0 iOSMetalForceHardShadows: 0 metalEditorSupport: 1 @@ -267,7 +270,99 @@ PlayerSettings: AndroidValidateAppBundleSize: 1 AndroidAppBundleSizeToValidate: 150 m_BuildTargetIcons: [] - m_BuildTargetPlatformIcons: [] + m_BuildTargetPlatformIcons: + - m_BuildTarget: Android + m_Icons: + - m_Textures: [] + m_Width: 432 + m_Height: 432 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 324 + m_Height: 324 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 216 + m_Height: 216 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 162 + m_Height: 162 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 108 + m_Height: 108 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 81 + m_Height: 81 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 192 + m_Height: 192 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 144 + m_Height: 144 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 96 + m_Height: 96 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 72 + m_Height: 72 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 48 + m_Height: 48 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 36 + m_Height: 36 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 192 + m_Height: 192 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 144 + m_Height: 144 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 96 + m_Height: 96 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 72 + m_Height: 72 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 48 + m_Height: 48 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 36 + m_Height: 36 + m_Kind: 0 + m_SubKind: m_BuildTargetBatching: - m_BuildTarget: Standalone m_StaticBatching: 1 @@ -284,6 +379,7 @@ PlayerSettings: - m_BuildTarget: WebGL m_StaticBatching: 0 m_DynamicBatching: 0 + m_BuildTargetShaderSettings: [] m_BuildTargetGraphicsJobs: - m_BuildTarget: MacStandaloneSupport m_GraphicsJobs: 0 @@ -327,7 +423,7 @@ PlayerSettings: m_BuildTargetGraphicsAPIs: - m_BuildTarget: AndroidPlayer m_APIs: 0b00000008000000 - m_Automatic: 1 + m_Automatic: 0 - m_BuildTarget: iOSSupport m_APIs: 10000000 m_Automatic: 1 @@ -343,6 +439,8 @@ PlayerSettings: m_Devices: - Oculus - OpenVR + m_DefaultShaderChunkSizeInMB: 16 + m_DefaultShaderChunkCount: 0 openGLRequireES31: 0 openGLRequireES31AEP: 0 openGLRequireES32: 0 @@ -354,6 +452,7 @@ PlayerSettings: m_BuildTargetGroupLightmapEncodingQuality: [] m_BuildTargetGroupLightmapSettings: [] m_BuildTargetNormalMapEncoding: [] + m_BuildTargetDefaultTextureCompressionFormat: [] playModeTestRunnerEnabled: 0 runPlayModeTestAsEditModeTest: 0 actionOnDotNetUnhandledException: 1 @@ -372,6 +471,7 @@ PlayerSettings: switchScreenResolutionBehavior: 2 switchUseCPUProfiler: 0 switchUseGOLDLinker: 0 + switchLTOSetting: 0 switchApplicationID: 0x01004b9000490000 switchNSODependencies: switchTitleNames_0: @@ -501,6 +601,7 @@ PlayerSettings: switchNetworkInterfaceManagerInitializeEnabled: 1 switchPlayerConnectionEnabled: 1 switchUseNewStyleFilepaths: 0 + switchUseLegacyFmodPriorities: 1 switchUseMicroSleepForYield: 1 switchEnableRamDiskSupport: 0 switchMicroSleepForYieldTime: 25 @@ -600,8 +701,9 @@ PlayerSettings: webGLLinkerTarget: 1 webGLThreadsSupport: 0 webGLDecompressionFallback: 0 + webGLPowerPreference: 2 scriptingDefineSymbols: - 1: + Standalone: additionalCompilerArguments: {} platformArchitecture: {} scriptingBackend: {} @@ -611,8 +713,8 @@ PlayerSettings: suppressCommonWarnings: 1 allowUnsafeCode: 0 useDeterministicCompilation: 1 - useReferenceAssemblies: 1 enableRoslynAnalyzers: 1 + selectedPlatform: 0 additionalIl2CppArgs: scriptingRuntimeVersion: 1 gcIncremental: 1 @@ -692,6 +794,7 @@ PlayerSettings: m_VersionName: apiCompatibilityLevel: 6 activeInputHandler: 0 + windowsGamepadBackendHint: 0 cloudProjectId: 7c3cffca-cc4e-4f8f-93f7-97568a17fdbb framebufferDepthMemorylessMode: 0 qualitySettingsNames: [] @@ -699,4 +802,6 @@ PlayerSettings: organizationId: whitefox-studio cloudEnabled: 0 legacyClampBlendShapeWeights: 0 + playerDataPath: + forceSRGBBlit: 1 virtualTexturingSupportEnabled: 0 diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt index 02057f26..8e3af85c 100644 --- a/ProjectSettings/ProjectVersion.txt +++ b/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 2020.3.33f1 -m_EditorVersionWithRevision: 2020.3.33f1 (915a7af8b0d5) +m_EditorVersion: 2021.3.19f1 +m_EditorVersionWithRevision: 2021.3.19f1 (c9714fde33b6) diff --git a/ProjectSettings/SceneTemplateSettings.json b/ProjectSettings/SceneTemplateSettings.json new file mode 100644 index 00000000..6f3e60fd --- /dev/null +++ b/ProjectSettings/SceneTemplateSettings.json @@ -0,0 +1,167 @@ +{ + "templatePinStates": [], + "dependencyTypeInfos": [ + { + "userAdded": false, + "type": "UnityEngine.AnimationClip", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.Animations.AnimatorController", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.AnimatorOverrideController", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.Audio.AudioMixerController", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.ComputeShader", + "ignore": true, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Cubemap", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.GameObject", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.LightingDataAsset", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": false + }, + { + "userAdded": false, + "type": "UnityEngine.LightingSettings", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Material", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.MonoScript", + "ignore": true, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.PhysicMaterial", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.PhysicsMaterial2D", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.PostProcessing.PostProcessProfile", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.PostProcessing.PostProcessResources", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.VolumeProfile", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.SceneAsset", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": false + }, + { + "userAdded": false, + "type": "UnityEngine.Shader", + "ignore": true, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.ShaderVariantCollection", + "ignore": true, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Texture", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Texture2D", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Timeline.TimelineAsset", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + } + ], + "defaultDependencyTypeInfo": { + "userAdded": false, + "type": "", + "ignore": false, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + "newSceneOverride": 0 +} \ No newline at end of file diff --git a/ProjectSettings/boot.config b/ProjectSettings/boot.config new file mode 100644 index 00000000..e69de29b From 637292e9e32127eae1be52249fafc49ec78fd13a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Mon, 26 Aug 2024 13:16:35 +0200 Subject: [PATCH 07/23] Minor refactor changes --- .../CopySerializeReferenceOperation.cs | 12 ++++++------ ...plicateSerializeReferenceArrayElementOperation.cs | 6 ++++-- .../PasteSerializeReferenceOperation.cs | 2 ++ .../PropertySelf/ReferencePickerAttributeDrawer.cs | 2 +- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs index 892baa88..ef5988c1 100644 --- a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs @@ -7,6 +7,12 @@ internal class CopySerializeReferenceOperation : IContextMenuOperation { internal static CopySerializedRererenceCache Cache { get; private set; } + [InitializeOnLoadMethod] + private static void Initialize() + { + Cache = null; + } + public bool IsVisible(SerializedProperty property) { #if UNITY_2021_3_OR_NEWER @@ -38,11 +44,5 @@ public void Perform(SerializedProperty property) } public GUIContent Label => new GUIContent("Copy Serialize Reference"); - - [InitializeOnLoadMethod] - private static void Initialize() - { - Cache = null; - } } } \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/DuplicateSerializeReferenceArrayElementOperation.cs b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/DuplicateSerializeReferenceArrayElementOperation.cs index 7e2130a2..e8b70b29 100644 --- a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/DuplicateSerializeReferenceArrayElementOperation.cs +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/DuplicateSerializeReferenceArrayElementOperation.cs @@ -5,8 +5,6 @@ namespace Toolbox.Editor.ContextMenu.Operations { internal class DuplicateSerializeReferenceArrayElementOperation : IContextMenuOperation { - public GUIContent Label => new GUIContent("Duplicate Serialize Reference Array Element"); - public bool IsVisible(SerializedProperty property) { #if UNITY_2021_3_OR_NEWER @@ -24,6 +22,7 @@ public bool IsEnabled(SerializedProperty property) public void Perform(SerializedProperty property) { +#if UNITY_2021_3_OR_NEWER var sourceProperty = property.Copy(); sourceProperty.serializedObject.Update(); var sourceValue = sourceProperty.managedReferenceValue; @@ -41,6 +40,9 @@ public void Perform(SerializedProperty property) } sourceProperty.serializedObject.ApplyModifiedProperties(); +#endif } + + public GUIContent Label => new GUIContent("Duplicate Serialize Reference Array Element"); } } \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs index c68486ec..6f065777 100644 --- a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs @@ -38,6 +38,7 @@ public bool IsEnabled(SerializedProperty property) public void Perform(SerializedProperty property) { +#if UNITY_2019_3_OR_NEWER var targetProperty = property.Copy(); try { @@ -47,6 +48,7 @@ public void Perform(SerializedProperty property) } catch (Exception) { } +#endif } public GUIContent Label => new GUIContent("Paste Serialize Reference"); diff --git a/Assets/Editor Toolbox/Editor/Drawers/Toolbox/PropertySelf/ReferencePickerAttributeDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Toolbox/PropertySelf/ReferencePickerAttributeDrawer.cs index fd7a04a6..63a7649a 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Toolbox/PropertySelf/ReferencePickerAttributeDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Toolbox/PropertySelf/ReferencePickerAttributeDrawer.cs @@ -58,7 +58,7 @@ private void CreateTypeProperty(SerializedProperty property, Type parentType, Re { using (var so = new SerializedObject(target)) { - SerializedProperty sp = so.FindProperty(property.propertyPath); + var sp = so.FindProperty(property.propertyPath); UpdateTypeProperty(sp, type, attribute); } } From 690d3fe2d8ac32747fc34edfd2338553600351df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Mon, 26 Aug 2024 14:04:53 +0200 Subject: [PATCH 08/23] Rename TypeConstraintReference to TypeConstraintSerializeReference --- .../PropertySelf/ReferencePickerAttributeDrawer.cs | 2 +- .../Editor/Internal/TypeConstraintContext.cs | 3 --- ...eference.cs => TypeConstraintSerializeReference.cs} | 10 ++++++---- ...s.meta => TypeConstraintSerializeReference.cs.meta} | 2 +- Assets/Editor Toolbox/Editor/Internal/TypeField.cs | 3 ++- .../Editor Toolbox/Tests/Editor/TypesFilteringTest.cs | 6 +++--- 6 files changed, 13 insertions(+), 13 deletions(-) rename Assets/Editor Toolbox/Editor/Internal/{TypeConstraintReference.cs => TypeConstraintSerializeReference.cs} (73%) rename Assets/Editor Toolbox/Editor/Internal/{TypeConstraintReference.cs.meta => TypeConstraintSerializeReference.cs.meta} (83%) diff --git a/Assets/Editor Toolbox/Editor/Drawers/Toolbox/PropertySelf/ReferencePickerAttributeDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Toolbox/PropertySelf/ReferencePickerAttributeDrawer.cs index 63a7649a..ddd9b404 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Toolbox/PropertySelf/ReferencePickerAttributeDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Toolbox/PropertySelf/ReferencePickerAttributeDrawer.cs @@ -12,7 +12,7 @@ public class ReferencePickerAttributeDrawer : ToolboxSelfPropertyDrawer targetType; public Comparison Comparer { get; set; } = (t1, t2) => t1.Name.CompareTo(t2.Name); public bool IsOrdered { get; set; } = true; diff --git a/Assets/Editor Toolbox/Editor/Internal/TypeConstraintReference.cs b/Assets/Editor Toolbox/Editor/Internal/TypeConstraintSerializeReference.cs similarity index 73% rename from Assets/Editor Toolbox/Editor/Internal/TypeConstraintReference.cs rename to Assets/Editor Toolbox/Editor/Internal/TypeConstraintSerializeReference.cs index dace68fe..3668c210 100644 --- a/Assets/Editor Toolbox/Editor/Internal/TypeConstraintReference.cs +++ b/Assets/Editor Toolbox/Editor/Internal/TypeConstraintSerializeReference.cs @@ -5,12 +5,14 @@ namespace Toolbox.Editor.Internal { - public class TypeConstraintReference : TypeConstraintContext + /// + /// Dedicated for SerializeReference-based types. + /// + public class TypeConstraintSerializeReference : TypeConstraintContext { - public TypeConstraintReference(Type targetType) : base(targetType) + public TypeConstraintSerializeReference(Type targetType) : base(targetType) { } - public override bool IsSatisfied(Type type) { return base.IsSatisfied(type) && @@ -25,7 +27,7 @@ public override bool IsSatisfied(Type type) public override bool Equals(object other) { - return other is TypeConstraintReference constraint && + return other is TypeConstraintSerializeReference constraint && base.Equals(other) && EqualityComparer.Default.Equals(targetType, constraint.targetType); } diff --git a/Assets/Editor Toolbox/Editor/Internal/TypeConstraintReference.cs.meta b/Assets/Editor Toolbox/Editor/Internal/TypeConstraintSerializeReference.cs.meta similarity index 83% rename from Assets/Editor Toolbox/Editor/Internal/TypeConstraintReference.cs.meta rename to Assets/Editor Toolbox/Editor/Internal/TypeConstraintSerializeReference.cs.meta index 3df95e93..1ed7eb48 100644 --- a/Assets/Editor Toolbox/Editor/Internal/TypeConstraintReference.cs.meta +++ b/Assets/Editor Toolbox/Editor/Internal/TypeConstraintSerializeReference.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 7a47d5ab7d6588a4b82a5b97925f44b0 +guid: 31b19ac86e78b784385b3afb582a1488 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/Editor Toolbox/Editor/Internal/TypeField.cs b/Assets/Editor Toolbox/Editor/Internal/TypeField.cs index 4705ceba..f6125d7c 100644 --- a/Assets/Editor Toolbox/Editor/Internal/TypeField.cs +++ b/Assets/Editor Toolbox/Editor/Internal/TypeField.cs @@ -37,11 +37,12 @@ private Type RetriveSelectedType(IReadOnlyList types, int selectedIndex, b private void DrawTypeConflictWarning(Rect position) { - const float warningSpace = 18.0f; + const float warningSpace = 20.0f; var warningPosition = position; warningPosition.xMax = position.xMin; warningPosition.xMin -= warningSpace; + warningPosition.y += EditorGUIUtility.standardVerticalSpacing; var warningIcon = EditorGuiUtility.GetHelpIcon(MessageType.Warning); var warningLabel = new GUIContent(warningIcon, "Currently active type is not available from the selection. " + "It may be caused by a conflict between the type filter and cached data."); diff --git a/Assets/Editor Toolbox/Tests/Editor/TypesFilteringTest.cs b/Assets/Editor Toolbox/Tests/Editor/TypesFilteringTest.cs index 5115070c..4bae665a 100644 --- a/Assets/Editor Toolbox/Tests/Editor/TypesFilteringTest.cs +++ b/Assets/Editor Toolbox/Tests/Editor/TypesFilteringTest.cs @@ -139,7 +139,7 @@ public void TestStandardConstraintPass7() [Test] public void TestReferenceConstraintPass1() { - var constraint = new TypeConstraintReference(typeof(Component)); + var constraint = new TypeConstraintSerializeReference(typeof(Component)); var collection = TypeUtilities.GetCollection(constraint); Assert.AreEqual(0, collection.Values.Count); } @@ -147,7 +147,7 @@ public void TestReferenceConstraintPass1() [Test] public void TestReferenceConstraintPass2() { - var constraint = new TypeConstraintReference(typeof(ClassBase)); + var constraint = new TypeConstraintSerializeReference(typeof(ClassBase)); var collection = TypeUtilities.GetCollection(constraint); Assert.IsTrue(collection.Contains(typeof(ClassWithInterface1))); #pragma warning disable CS0612 @@ -161,7 +161,7 @@ public void TestReferenceConstraintPass2() [Test] public void TestReferenceConstraintPass3() { - var constraint = new TypeConstraintReference(typeof(Interface1)); + var constraint = new TypeConstraintSerializeReference(typeof(Interface1)); var collection = TypeUtilities.GetCollection(constraint); Assert.IsTrue(collection.Contains(typeof(ClassWithInterface1))); #pragma warning disable CS0612 From db56817c73ea8a0cc96ad3751403813e307dabed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Mon, 26 Aug 2024 14:21:13 +0200 Subject: [PATCH 09/23] Implemenet for unit tests for the PropertyUtility class --- .../Tests/Editor/PropertyUtilitesTest.cs | 44 ++++++++++++++----- .../Tests/Editor/ReorderableListTest.cs | 1 - .../Tests/Editor/TestObject2.cs | 13 ++++++ 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/Assets/Editor Toolbox/Tests/Editor/PropertyUtilitesTest.cs b/Assets/Editor Toolbox/Tests/Editor/PropertyUtilitesTest.cs index 9594badf..e1d96a82 100644 --- a/Assets/Editor Toolbox/Tests/Editor/PropertyUtilitesTest.cs +++ b/Assets/Editor Toolbox/Tests/Editor/PropertyUtilitesTest.cs @@ -1,5 +1,7 @@ using NUnit.Framework; +using System; + using UnityEditor; using UnityEngine; @@ -7,16 +9,24 @@ namespace Toolbox.Editor.Tests { public class PropertyUtilitesTest { - private SerializedObject scriptableObject; - + private SerializedObject serializedObject; [OneTimeSetUp] public void SetUp() { var target = ScriptableObject.CreateInstance(); - scriptableObject = new SerializedObject(target); - var array = scriptableObject.FindProperty("var2.var3"); - array.InsertArrayElementAtIndex(0); + serializedObject = new SerializedObject(target); + + var var2var3Property = serializedObject.FindProperty("var2.var3"); + var2var3Property.InsertArrayElementAtIndex(0); + +#if UNITY_2019_3_OR_NEWER + var var3Property = serializedObject.FindProperty("var3"); + var3Property.managedReferenceValue = new TestObject2.TestNestedObject3() + { + var1 = 3.0f + }; +#endif } [TestCase("var1", null)] @@ -24,7 +34,7 @@ public void SetUp() [TestCase("var2.var2.var1", "var2")] public void TestGetParentPass(string propertyPath, string parentName) { - var property = scriptableObject.FindProperty(propertyPath); + var property = serializedObject.FindProperty(propertyPath); var parent = property?.GetParent(); Assert.AreEqual(parent?.name, parentName); } @@ -35,7 +45,7 @@ public void TestGetParentPass(string propertyPath, string parentName) [TestCase("var2.var3.Array.data[0]", 1)] public void TestGetValuePass(string propertyPath, object value) { - var property = scriptableObject.FindProperty(propertyPath); + var property = serializedObject.FindProperty(propertyPath); var fieldInfo = property.GetFieldInfo(out _); property.SetProperValue(fieldInfo, value); var newValue = property.GetProperValue(fieldInfo); @@ -47,7 +57,7 @@ public void TestGetValuePass(string propertyPath, object value) [TestCase("var2.var3.Array.data[0]", true)] public void TestIsArrayElementPass(string propertyPath, bool expected) { - var property = scriptableObject.FindProperty(propertyPath); + var property = serializedObject.FindProperty(propertyPath); var actual = PropertyUtility.IsSerializableArrayElement(property); Assert.AreEqual(expected, actual); } @@ -59,7 +69,7 @@ public void TestIsArrayElementPass(string propertyPath, bool expected) [TestCase("var2.var3.Array.data[0]", "var2.var3.[0]")] public void TestGetPathTreePass(string propertyPath, string path) { - var property = scriptableObject.FindProperty(propertyPath); + var property = serializedObject.FindProperty(propertyPath); var pathTree = PropertyUtility.GetPropertyFieldTree(property); var actual = string.Join(".", pathTree); Assert.AreEqual(path, actual); @@ -69,9 +79,23 @@ public void TestGetPathTreePass(string propertyPath, string path) [TestCase("var2.var1", false)] public void TestIsMonoScriptPass(string propertyPath, bool expected) { - var property = scriptableObject.FindProperty(propertyPath); + var property = serializedObject.FindProperty(propertyPath); var actual = PropertyUtility.IsDefaultScriptProperty(property); Assert.AreEqual(expected, actual); } + + [TestCase("var1", typeof(int))] + [TestCase("var2.var1", typeof(string))] +#if UNITY_2019_3_OR_NEWER + [TestCase("var3", typeof(TestObject2.TestNestedObject3))] + [TestCase("var3.var1", typeof(float))] +#endif + public void TestGetFieldInfoPass(string propertyPath, Type expected) + { + var property = serializedObject.FindProperty(propertyPath); + var fieldInfo = PropertyUtility.GetFieldInfo(property, out var propertyType); + Assert.IsNotNull(fieldInfo); + Assert.AreEqual(expected, propertyType); + } } } \ No newline at end of file diff --git a/Assets/Editor Toolbox/Tests/Editor/ReorderableListTest.cs b/Assets/Editor Toolbox/Tests/Editor/ReorderableListTest.cs index 62d54996..a8fba9ba 100644 --- a/Assets/Editor Toolbox/Tests/Editor/ReorderableListTest.cs +++ b/Assets/Editor Toolbox/Tests/Editor/ReorderableListTest.cs @@ -13,7 +13,6 @@ public class ReorderableListTest private ToolboxEditorList list; - [OneTimeSetUp] public void SetUp() { diff --git a/Assets/Editor Toolbox/Tests/Editor/TestObject2.cs b/Assets/Editor Toolbox/Tests/Editor/TestObject2.cs index 1cbb1d00..c090dae1 100644 --- a/Assets/Editor Toolbox/Tests/Editor/TestObject2.cs +++ b/Assets/Editor Toolbox/Tests/Editor/TestObject2.cs @@ -7,6 +7,10 @@ internal class TestObject2 : ScriptableObject { public int var1; public TestNestedObject1 var2; +#if UNITY_2019_3_OR_NEWER + [SerializeReference] + public ITestInterface var3; +#endif public bool BoolValue { @@ -23,6 +27,9 @@ public double GetDoubleValue(int arg) return arg + 2.0005; } + public interface ITestInterface + { } + [Serializable] public class TestNestedObject1 { @@ -50,5 +57,11 @@ public int IntValue public void DoSomething() { } } + + [Serializable] + public class TestNestedObject3 : ITestInterface + { + public float var1; + } } } \ No newline at end of file From b5cfa6f8094281bf8e5bda50aa346b2f68cf1970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Wed, 28 Aug 2024 14:39:24 +0200 Subject: [PATCH 10/23] Implement basic support for generic types while using SerializeReference; more unit tests covering types filtering & constraints; add warning when pasting invalid/mismatched reference; update samples --- .../PasteSerializeReferenceOperation.cs | 31 ++- .../Drawers/Regular/SerializedTypeDrawer.cs | 5 +- .../ReferencePickerAttributeDrawer.cs | 3 +- .../Internal/TypeAppearanceContext.cs.meta | 11 - .../Internal/TypeConstraintContext.cs.meta | 11 - .../TypeConstraintSerializeReference.cs.meta | 11 - .../Internal/TypeConstraintStandard.cs.meta | 11 - .../Editor/Internal/TypeField.cs.meta | 11 - .../Editor Toolbox/Editor/Internal/Types.meta | 8 + .../{ => Types}/TypeAppearanceContext.cs | 2 +- .../Types/TypeAppearanceContext.cs.meta | 2 + .../{ => Types}/TypeConstraintContext.cs | 8 +- .../Types/TypeConstraintContext.cs.meta | 2 + .../TypeConstraintSerializeReference.cs | 9 +- .../TypeConstraintSerializeReference.cs.meta | 2 + .../{ => Types}/TypeConstraintStandard.cs | 2 +- .../Types/TypeConstraintStandard.cs.meta | 2 + .../Editor/Internal/{ => Types}/TypeField.cs | 5 +- .../Editor/Internal/Types/TypeField.cs.meta | 2 + .../{ => Types}/TypesCachedCollection.cs | 5 +- .../Types/TypesCachedCollection.cs.meta | 2 + .../Internal/Types/TypesEditorCollection.cs | 170 ++++++++++++ .../Types/TypesEditorCollection.cs.meta | 2 + .../Internal/TypesCachedCollection.cs.meta | 11 - .../Editor/Internal/TypesEditorCollection.cs | 105 -------- .../Internal/TypesEditorCollection.cs.meta | 11 - .../Editor/ToolboxDrawerModule.cs | 3 +- .../Utilities/AssemblyUtilities.cs.meta | 11 - ...semblyUtilities.cs => AssemblyUttility.cs} | 4 +- .../Editor/Utilities/AssemblyUttility.cs.meta | 2 + .../Editor/Utilities/PropertyUtility.cs | 2 +- .../Editor/Utilities/TypeUtilities.cs | 130 --------- .../Editor/Utilities/TypeUtilities.cs.meta | 11 - .../Editor/Utilities/TypeUtility.cs | 248 ++++++++++++++++++ .../Editor/Utilities/TypeUtility.cs.meta | 2 + .../Wizards/ScriptableObjectCreationWizard.cs | 5 +- .../Runtime/Extensions/TypeExtensions.cs | 35 ++- .../Tests/Editor/TypesFilteringTest.cs | 108 +++++--- Assets/Examples/Scripts/SampleBehaviour1.cs | 33 ++- Assets/Examples/Scripts/SampleBehaviour3.cs | 2 +- Assets/Examples/Scripts/SampleBehaviour4.cs | 2 +- Assets/Examples/Scripts/SampleBehaviour5.cs | 9 +- Assets/Examples/Scripts/SampleBehaviour6.cs | 73 +++++- 43 files changed, 687 insertions(+), 437 deletions(-) delete mode 100644 Assets/Editor Toolbox/Editor/Internal/TypeAppearanceContext.cs.meta delete mode 100644 Assets/Editor Toolbox/Editor/Internal/TypeConstraintContext.cs.meta delete mode 100644 Assets/Editor Toolbox/Editor/Internal/TypeConstraintSerializeReference.cs.meta delete mode 100644 Assets/Editor Toolbox/Editor/Internal/TypeConstraintStandard.cs.meta delete mode 100644 Assets/Editor Toolbox/Editor/Internal/TypeField.cs.meta create mode 100644 Assets/Editor Toolbox/Editor/Internal/Types.meta rename Assets/Editor Toolbox/Editor/Internal/{ => Types}/TypeAppearanceContext.cs (97%) create mode 100644 Assets/Editor Toolbox/Editor/Internal/Types/TypeAppearanceContext.cs.meta rename Assets/Editor Toolbox/Editor/Internal/{ => Types}/TypeConstraintContext.cs (83%) create mode 100644 Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintContext.cs.meta rename Assets/Editor Toolbox/Editor/Internal/{ => Types}/TypeConstraintSerializeReference.cs (82%) create mode 100644 Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintSerializeReference.cs.meta rename Assets/Editor Toolbox/Editor/Internal/{ => Types}/TypeConstraintStandard.cs (98%) create mode 100644 Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintStandard.cs.meta rename Assets/Editor Toolbox/Editor/Internal/{ => Types}/TypeField.cs (97%) create mode 100644 Assets/Editor Toolbox/Editor/Internal/Types/TypeField.cs.meta rename Assets/Editor Toolbox/Editor/Internal/{ => Types}/TypesCachedCollection.cs (96%) create mode 100644 Assets/Editor Toolbox/Editor/Internal/Types/TypesCachedCollection.cs.meta create mode 100644 Assets/Editor Toolbox/Editor/Internal/Types/TypesEditorCollection.cs create mode 100644 Assets/Editor Toolbox/Editor/Internal/Types/TypesEditorCollection.cs.meta delete mode 100644 Assets/Editor Toolbox/Editor/Internal/TypesCachedCollection.cs.meta delete mode 100644 Assets/Editor Toolbox/Editor/Internal/TypesEditorCollection.cs delete mode 100644 Assets/Editor Toolbox/Editor/Internal/TypesEditorCollection.cs.meta delete mode 100644 Assets/Editor Toolbox/Editor/Utilities/AssemblyUtilities.cs.meta rename Assets/Editor Toolbox/Editor/Utilities/{AssemblyUtilities.cs => AssemblyUttility.cs} (96%) create mode 100644 Assets/Editor Toolbox/Editor/Utilities/AssemblyUttility.cs.meta delete mode 100644 Assets/Editor Toolbox/Editor/Utilities/TypeUtilities.cs delete mode 100644 Assets/Editor Toolbox/Editor/Utilities/TypeUtilities.cs.meta create mode 100644 Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs create mode 100644 Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs.meta diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs index 6f065777..5c716ad4 100644 --- a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs @@ -5,9 +5,29 @@ namespace Toolbox.Editor.ContextMenu.Operations { - internal class PasteSerializeReferenceOperation : IContextMenuOperation { + private bool IsAssignmentValid(SerializedProperty property, object newValue) + { + if (newValue == null) + { + return true; + } + + if (!TypeUtility.TryGetTypeFromManagedReferenceFullTypeName(property.managedReferenceFieldTypename, out var referenceType)) + { + return true; + } + + var newValueType = newValue.GetType(); + if (TypeUtility.IsTypeAssignableFrom(referenceType, newValueType)) + { + return true; + } + + return false; + } + private object GetCachedManagedReferenceValue() { var cachedData = CopySerializeReferenceOperation.Cache; @@ -42,8 +62,15 @@ public void Perform(SerializedProperty property) var targetProperty = property.Copy(); try { + var newValue = GetCachedManagedReferenceValue(); + if (!IsAssignmentValid(targetProperty, newValue)) + { + ToolboxEditorLog.LogWarning("Cannot perform paste operation, types are mismatched."); + return; + } + targetProperty.serializedObject.Update(); - targetProperty.managedReferenceValue = GetCachedManagedReferenceValue(); + targetProperty.managedReferenceValue = newValue; targetProperty.serializedObject.ApplyModifiedProperties(); } catch (Exception) diff --git a/Assets/Editor Toolbox/Editor/Drawers/Regular/SerializedTypeDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Regular/SerializedTypeDrawer.cs index 228c8dcf..8e73b5ec 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Regular/SerializedTypeDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Regular/SerializedTypeDrawer.cs @@ -5,7 +5,7 @@ namespace Toolbox.Editor.Drawers { - using Toolbox.Editor.Internal; + using Toolbox.Editor.Internal.Types; [CustomPropertyDrawer(typeof(TypeConstraintAttribute), true)] [CustomPropertyDrawer(typeof(SerializedType))] @@ -15,7 +15,6 @@ public sealed class SerializedTypeDrawer : PropertyDrawerBase private static readonly TypeAppearanceContext sharedAppearance = new TypeAppearanceContext(sharedConstraint, TypeGrouping.None, true); private static readonly TypeField typeField = new TypeField(sharedConstraint, sharedAppearance); - private bool IsDefaultField(TypeConstraintAttribute attribute) { return attribute == null || attribute.AssemblyType == null; @@ -65,7 +64,6 @@ private void UpdateAppearance(TypeConstraintAttribute attribute) sharedAppearance.TypeGrouping = attribute.TypeGrouping; } - protected override float GetPropertyHeightSafe(SerializedProperty property, GUIContent label) { return EditorStyles.popup.CalcHeight(GUIContent.none, 0); @@ -101,7 +99,6 @@ protected override void OnGUISafe(Rect position, SerializedProperty property, GU EditorGUI.EndProperty(); } - /// public override bool IsPropertyValid(SerializedProperty property) { diff --git a/Assets/Editor Toolbox/Editor/Drawers/Toolbox/PropertySelf/ReferencePickerAttributeDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Toolbox/PropertySelf/ReferencePickerAttributeDrawer.cs index ddd9b404..a854feb5 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Toolbox/PropertySelf/ReferencePickerAttributeDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Toolbox/PropertySelf/ReferencePickerAttributeDrawer.cs @@ -7,6 +7,7 @@ namespace Toolbox.Editor.Drawers { using Toolbox.Editor.Internal; + using Toolbox.Editor.Internal.Types; public class ReferencePickerAttributeDrawer : ToolboxSelfPropertyDrawer { @@ -42,7 +43,7 @@ private Type GetParentType(ReferencePickerAttribute attribute, SerializedPropert private void CreateTypeProperty(SerializedProperty property, Type parentType, ReferencePickerAttribute attribute, Rect position) { - TypeUtilities.TryGetTypeFromManagedReferenceFullTypeName(property.managedReferenceFullTypename, out var currentType); + TypeUtility.TryGetTypeFromManagedReferenceFullTypeName(property.managedReferenceFullTypename, out var currentType); typeField.OnGui(position, attribute.AddTextSearchField, (type) => { try diff --git a/Assets/Editor Toolbox/Editor/Internal/TypeAppearanceContext.cs.meta b/Assets/Editor Toolbox/Editor/Internal/TypeAppearanceContext.cs.meta deleted file mode 100644 index d4bac0ed..00000000 --- a/Assets/Editor Toolbox/Editor/Internal/TypeAppearanceContext.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7fda8e70563fab94ca8aa551a1d83dc0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Internal/TypeConstraintContext.cs.meta b/Assets/Editor Toolbox/Editor/Internal/TypeConstraintContext.cs.meta deleted file mode 100644 index 1d35d43d..00000000 --- a/Assets/Editor Toolbox/Editor/Internal/TypeConstraintContext.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 118c19767a8066a47a7f2330c22d7c22 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Internal/TypeConstraintSerializeReference.cs.meta b/Assets/Editor Toolbox/Editor/Internal/TypeConstraintSerializeReference.cs.meta deleted file mode 100644 index 1ed7eb48..00000000 --- a/Assets/Editor Toolbox/Editor/Internal/TypeConstraintSerializeReference.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 31b19ac86e78b784385b3afb582a1488 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Internal/TypeConstraintStandard.cs.meta b/Assets/Editor Toolbox/Editor/Internal/TypeConstraintStandard.cs.meta deleted file mode 100644 index 1cf1fc2f..00000000 --- a/Assets/Editor Toolbox/Editor/Internal/TypeConstraintStandard.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3b7a7e43ed392854f9bbcb7381c02e34 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Internal/TypeField.cs.meta b/Assets/Editor Toolbox/Editor/Internal/TypeField.cs.meta deleted file mode 100644 index a1094e7c..00000000 --- a/Assets/Editor Toolbox/Editor/Internal/TypeField.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5870e4659fe35474db2d34642d21d930 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Internal/Types.meta b/Assets/Editor Toolbox/Editor/Internal/Types.meta new file mode 100644 index 00000000..c4f19c09 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/Internal/Types.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 27ab57e21e3484f41a400c5ea540421f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Internal/TypeAppearanceContext.cs b/Assets/Editor Toolbox/Editor/Internal/Types/TypeAppearanceContext.cs similarity index 97% rename from Assets/Editor Toolbox/Editor/Internal/TypeAppearanceContext.cs rename to Assets/Editor Toolbox/Editor/Internal/Types/TypeAppearanceContext.cs index c8322ddc..22b78f99 100644 --- a/Assets/Editor Toolbox/Editor/Internal/TypeAppearanceContext.cs +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypeAppearanceContext.cs @@ -2,7 +2,7 @@ using UnityEngine; -namespace Toolbox.Editor.Internal +namespace Toolbox.Editor.Internal.Types { public class TypeAppearanceContext { diff --git a/Assets/Editor Toolbox/Editor/Internal/Types/TypeAppearanceContext.cs.meta b/Assets/Editor Toolbox/Editor/Internal/Types/TypeAppearanceContext.cs.meta new file mode 100644 index 00000000..f700b5c7 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypeAppearanceContext.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 80454d63dd02c0d42b6ac59f8eaee024 \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Internal/TypeConstraintContext.cs b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintContext.cs similarity index 83% rename from Assets/Editor Toolbox/Editor/Internal/TypeConstraintContext.cs rename to Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintContext.cs index e8684080..3d27ef3c 100644 --- a/Assets/Editor Toolbox/Editor/Internal/TypeConstraintContext.cs +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintContext.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace Toolbox.Editor.Internal +namespace Toolbox.Editor.Internal.Types { public class TypeConstraintContext { @@ -14,13 +14,7 @@ public TypeConstraintContext(Type targetType) public virtual bool IsSatisfied(Type type) { -#if UNITY_2019_2_OR_NEWER return type.IsVisible; -#else - return type.IsVisible && (targetType.IsGenericType - ? targetType.IsAssignableFromGeneric(type) - : targetType.IsAssignableFrom(type)); -#endif } public virtual void ApplyTarget(Type type) diff --git a/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintContext.cs.meta b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintContext.cs.meta new file mode 100644 index 00000000..2d1ca679 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintContext.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 8c2d536076f643b4689c9d04b8b5b2f0 \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Internal/TypeConstraintSerializeReference.cs b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintSerializeReference.cs similarity index 82% rename from Assets/Editor Toolbox/Editor/Internal/TypeConstraintSerializeReference.cs rename to Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintSerializeReference.cs index 3668c210..b37f5a60 100644 --- a/Assets/Editor Toolbox/Editor/Internal/TypeConstraintSerializeReference.cs +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintSerializeReference.cs @@ -3,7 +3,7 @@ using Object = UnityEngine.Object; -namespace Toolbox.Editor.Internal +namespace Toolbox.Editor.Internal.Types { /// /// Dedicated for SerializeReference-based types. @@ -15,6 +15,13 @@ public TypeConstraintSerializeReference(Type targetType) : base(targetType) public override bool IsSatisfied(Type type) { + //NOTE: generic types are not supported below Unity 2023 while using the Serialize References +#if !UNITY_2023_2_OR_NEWER + if (type.IsGenericType) + { + return false; + } +#endif return base.IsSatisfied(type) && !type.IsInterface && !type.IsAbstract && diff --git a/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintSerializeReference.cs.meta b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintSerializeReference.cs.meta new file mode 100644 index 00000000..08bba96d --- /dev/null +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintSerializeReference.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: f2f4619c41ded3c418dfbcd3d93ea5c7 \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Internal/TypeConstraintStandard.cs b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintStandard.cs similarity index 98% rename from Assets/Editor Toolbox/Editor/Internal/TypeConstraintStandard.cs rename to Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintStandard.cs index d6265f98..43264c5e 100644 --- a/Assets/Editor Toolbox/Editor/Internal/TypeConstraintStandard.cs +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintStandard.cs @@ -2,7 +2,7 @@ using UnityEngine; -namespace Toolbox.Editor.Internal +namespace Toolbox.Editor.Internal.Types { public class TypeConstraintStandard : TypeConstraintContext { diff --git a/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintStandard.cs.meta b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintStandard.cs.meta new file mode 100644 index 00000000..bfec77bd --- /dev/null +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintStandard.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 79789e5b77277274fa20fbed57488a1a \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Internal/TypeField.cs b/Assets/Editor Toolbox/Editor/Internal/Types/TypeField.cs similarity index 97% rename from Assets/Editor Toolbox/Editor/Internal/TypeField.cs rename to Assets/Editor Toolbox/Editor/Internal/Types/TypeField.cs index f6125d7c..5c084b9d 100644 --- a/Assets/Editor Toolbox/Editor/Internal/TypeField.cs +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypeField.cs @@ -1,9 +1,10 @@ using System; using System.Collections.Generic; + using UnityEditor; using UnityEngine; -namespace Toolbox.Editor.Internal +namespace Toolbox.Editor.Internal.Types { /// /// Out-of-the-box field that can be used as a picker. @@ -58,7 +59,7 @@ public void OnGui(Rect position, bool addSearchField, Action onSelect, Typ { var addEmptyValue = AppearanceContext.AddEmptyValue; - var collection = TypeUtilities.GetCollection(AppearanceContext); + var collection = TypeUtility.GetCollection(AppearanceContext); var values = collection.Values; var labels = collection.Labels; var index = collection.IndexOf(activeType); diff --git a/Assets/Editor Toolbox/Editor/Internal/Types/TypeField.cs.meta b/Assets/Editor Toolbox/Editor/Internal/Types/TypeField.cs.meta new file mode 100644 index 00000000..91e47895 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypeField.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 8f3a75051e0f62a45bd84f4d36763f84 \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Internal/TypesCachedCollection.cs b/Assets/Editor Toolbox/Editor/Internal/Types/TypesCachedCollection.cs similarity index 96% rename from Assets/Editor Toolbox/Editor/Internal/TypesCachedCollection.cs rename to Assets/Editor Toolbox/Editor/Internal/Types/TypesCachedCollection.cs index 2a37ffd6..31d2dc85 100644 --- a/Assets/Editor Toolbox/Editor/Internal/TypesCachedCollection.cs +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypesCachedCollection.cs @@ -2,13 +2,12 @@ using System.Collections; using System.Collections.Generic; -namespace Toolbox.Editor.Internal +namespace Toolbox.Editor.Internal.Types { public class TypesCachedCollection : IEnumerable { private readonly List values; - public TypesCachedCollection() : this(new List()) { } @@ -17,7 +16,6 @@ public TypesCachedCollection(List values) this.values = values; } - public virtual int IndexOf(Type type) { return values.IndexOf(type); @@ -38,7 +36,6 @@ IEnumerator IEnumerable.GetEnumerator() return values.GetEnumerator(); } - public IReadOnlyList Values => values; public static implicit operator List(TypesCachedCollection collection) => collection.values; diff --git a/Assets/Editor Toolbox/Editor/Internal/Types/TypesCachedCollection.cs.meta b/Assets/Editor Toolbox/Editor/Internal/Types/TypesCachedCollection.cs.meta new file mode 100644 index 00000000..6292f196 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypesCachedCollection.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: b1c652a61bba0af4c946b01f28117ae8 \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Internal/Types/TypesEditorCollection.cs b/Assets/Editor Toolbox/Editor/Internal/Types/TypesEditorCollection.cs new file mode 100644 index 00000000..ce9e0154 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypesEditorCollection.cs @@ -0,0 +1,170 @@ +using System; +using System.Reflection; +using System.Text; +using UnityEngine; + +namespace Toolbox.Editor.Internal.Types +{ + /// + /// Dedicated collection that additionally holds labels linked to associated s. + /// Useful for Editor-based drawers and tools. + /// + public class TypesEditorCollection : TypesCachedCollection + { + private readonly bool hasEmptyValue; + private string[] labels; + + public TypesEditorCollection(TypesCachedCollection cachedCollection) + : this(cachedCollection, true) + { } + + public TypesEditorCollection(TypesCachedCollection cachedCollection, bool hasEmptyValue) + : this(cachedCollection, hasEmptyValue, TypeGrouping.None) + { } + + public TypesEditorCollection(TypesCachedCollection cachedCollection, bool hasEmptyValue, TypeGrouping grouping) + : base(cachedCollection) + { + this.hasEmptyValue = hasEmptyValue; + CreateLabels(grouping); + } + + private void CreateLabels(TypeGrouping grouping) + { + var count = Values.Count; + var shift = 0; + if (hasEmptyValue) + { + shift += 1; + count += 1; + labels = new string[count]; + labels[0] = ""; + } + else + { + labels = new string[count]; + } + + for (var i = 0; i < count - shift; i++) + { + var type = Values[i]; + var name = FormatGroupedTypeName(type, grouping); + labels[i + shift] = name; + } + } + + /// + /// Creates a bit nicer (in terms of display) or equivalent. + /// + private static string GetTypeName(Type type, bool createFull) + { + var stringBuilder = new StringBuilder(); + if (createFull) + { + var namespaceName = type.Namespace; + if (!string.IsNullOrEmpty(namespaceName)) + { + stringBuilder.Append(type.Namespace); + stringBuilder.Append('.'); + } + } + + if (type.IsNested) + { + var declaringType = type.DeclaringType; + stringBuilder.Append(declaringType.Name); + stringBuilder.Append(':'); + } + + if (type.IsGenericType) + { + var name = type.Name; + name = name.Substring(0, name.IndexOf("`")); + + stringBuilder.Append(name); + stringBuilder.Append('<'); + var arguments = type.GetGenericArguments(); + for (var i = 0; i < arguments.Length; i++) + { + var argumentType = arguments[i]; + var argumentName = string.IsNullOrEmpty(argumentType.FullName) + ? argumentType.Name + : GetTypeName(argumentType, false); + + stringBuilder.Append(argumentName); + if (i < arguments.Length - 1) + { + stringBuilder.Append(", "); + } + } + + stringBuilder.Append('>'); + } + else + { + stringBuilder.Append(type.Name); + } + + return stringBuilder.ToString(); + } + + private static string FormatGroupedTypeName(Type type, TypeGrouping grouping) + { + switch (grouping) + { + default: + case TypeGrouping.None: + { + var name = GetTypeName(type, true); + return name; + } + case TypeGrouping.ByNamespace: + { + var name = GetTypeName(type, true); + return name.Replace('.', '/'); + } + case TypeGrouping.ByNamespaceFlat: + { + var name = GetTypeName(type, true); + var lastPeriodIndex = name.LastIndexOf('.'); + if (lastPeriodIndex != -1) + { + name = name.Substring(0, lastPeriodIndex) + "/" + name.Substring(lastPeriodIndex + 1); + } + + return name; + } + case TypeGrouping.ByAddComponentMenu: + { + var addComponentMenuAttributes = type.GetCustomAttributes(typeof(AddComponentMenu), false); + if (addComponentMenuAttributes.Length == 1) + { + return ((AddComponentMenu)addComponentMenuAttributes[0]).componentMenu; + } + + return "Scripts/" + type.FullName.Replace('.', '/'); + } + case TypeGrouping.ByFlatName: + { + var name = GetTypeName(type, false); + return name; + } + } + } + + public override int IndexOf(Type type) + { + var index = -1; + if (type != null) + { + index = base.IndexOf(type); + } + + return hasEmptyValue + ? index + 1 + : index; + } + + public string[] Labels => labels; + } +} \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Internal/Types/TypesEditorCollection.cs.meta b/Assets/Editor Toolbox/Editor/Internal/Types/TypesEditorCollection.cs.meta new file mode 100644 index 00000000..9b184e3b --- /dev/null +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypesEditorCollection.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 79255218de0423940a945ec3f922e22c \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Internal/TypesCachedCollection.cs.meta b/Assets/Editor Toolbox/Editor/Internal/TypesCachedCollection.cs.meta deleted file mode 100644 index 3a97281c..00000000 --- a/Assets/Editor Toolbox/Editor/Internal/TypesCachedCollection.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2c13ae41dd9ca444fbab3d954167c674 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Internal/TypesEditorCollection.cs b/Assets/Editor Toolbox/Editor/Internal/TypesEditorCollection.cs deleted file mode 100644 index 9adab2c1..00000000 --- a/Assets/Editor Toolbox/Editor/Internal/TypesEditorCollection.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System; - -using UnityEngine; - -namespace Toolbox.Editor.Internal -{ - public class TypesEditorCollection : TypesCachedCollection - { - private readonly bool hasEmptyValue; - private string[] labels; - - - public TypesEditorCollection(TypesCachedCollection cachedCollection) - : this(cachedCollection, true) - { } - - public TypesEditorCollection(TypesCachedCollection cachedCollection, bool hasEmptyValue) - : this(cachedCollection, hasEmptyValue, TypeGrouping.None) - { } - - public TypesEditorCollection(TypesCachedCollection cachedCollection, bool hasEmptyValue, TypeGrouping grouping) - : base(cachedCollection) - { - this.hasEmptyValue = hasEmptyValue; - CreateLabels(grouping); - } - - - private void CreateLabels(TypeGrouping grouping) - { - var count = Values.Count; - var shift = 0; - if (hasEmptyValue) - { - shift += 1; - count += 1; - labels = new string[count]; - labels[0] = ""; - } - else - { - labels = new string[count]; - } - - for (var i = 0; i < count - shift; i++) - { - var type = Values[i]; - var name = FormatGroupedTypeName(type, grouping); - labels[i + shift] = name; - } - } - - private static string FormatGroupedTypeName(Type type, TypeGrouping grouping) - { - var name = type.FullName; - switch (grouping) - { - default: - case TypeGrouping.None: - return name; - - case TypeGrouping.ByNamespace: - return name.Replace('.', '/'); - - case TypeGrouping.ByNamespaceFlat: - var lastPeriodIndex = name.LastIndexOf('.'); - if (lastPeriodIndex != -1) - { - name = name.Substring(0, lastPeriodIndex) + "/" + name.Substring(lastPeriodIndex + 1); - } - - return name; - - case TypeGrouping.ByAddComponentMenu: - var addComponentMenuAttributes = type.GetCustomAttributes(typeof(AddComponentMenu), false); - if (addComponentMenuAttributes.Length == 1) - { - return ((AddComponentMenu)addComponentMenuAttributes[0]).componentMenu; - } - - return "Scripts/" + type.FullName.Replace('.', '/'); - - case TypeGrouping.ByFlatName: - return type.Name; - } - } - - - public override int IndexOf(Type type) - { - var index = -1; - if (type != null) - { - index = base.IndexOf(type); - } - - return hasEmptyValue - ? index + 1 - : index; - } - - - public string[] Labels => labels; - } -} \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Internal/TypesEditorCollection.cs.meta b/Assets/Editor Toolbox/Editor/Internal/TypesEditorCollection.cs.meta deleted file mode 100644 index 9534b36b..00000000 --- a/Assets/Editor Toolbox/Editor/Internal/TypesEditorCollection.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 51cefceaf65b2ea479dd3abb2c3db1c5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/ToolboxDrawerModule.cs b/Assets/Editor Toolbox/Editor/ToolboxDrawerModule.cs index 1aeadca3..bcc63674 100644 --- a/Assets/Editor Toolbox/Editor/ToolboxDrawerModule.cs +++ b/Assets/Editor Toolbox/Editor/ToolboxDrawerModule.cs @@ -440,10 +440,9 @@ internal static ToolboxPropertyHandler GetPropertyHandler(SerializedProperty pro } } - internal static bool ToolboxDrawersAllowed { get; set; } - //TODO: + //TODO: move to utilities //NOTE: unfortunately there is no valid, non-reflection way to check if property has a custom native drawer private static readonly MethodInfo getDrawerTypeForTypeMethod = ReflectionUtility.GetEditorMethod("UnityEditor.ScriptAttributeUtility", "GetDrawerTypeForType", diff --git a/Assets/Editor Toolbox/Editor/Utilities/AssemblyUtilities.cs.meta b/Assets/Editor Toolbox/Editor/Utilities/AssemblyUtilities.cs.meta deleted file mode 100644 index 2f9721f9..00000000 --- a/Assets/Editor Toolbox/Editor/Utilities/AssemblyUtilities.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ed880dff07607b848b2e9ab175a21f9c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Utilities/AssemblyUtilities.cs b/Assets/Editor Toolbox/Editor/Utilities/AssemblyUttility.cs similarity index 96% rename from Assets/Editor Toolbox/Editor/Utilities/AssemblyUtilities.cs rename to Assets/Editor Toolbox/Editor/Utilities/AssemblyUttility.cs index c3d20e61..67df33a9 100644 --- a/Assets/Editor Toolbox/Editor/Utilities/AssemblyUtilities.cs +++ b/Assets/Editor Toolbox/Editor/Utilities/AssemblyUttility.cs @@ -6,7 +6,7 @@ namespace Toolbox.Editor { [InitializeOnLoad] - public static class AssemblyUtilities + public static class AssemblyUttility { private static readonly HashSet projectAssemblyNames = new HashSet(); private static readonly HashSet internalAssemblyNames = new HashSet() @@ -26,7 +26,7 @@ public static class AssemblyUtilities private static bool isCached; - static AssemblyUtilities() + static AssemblyUttility() { isCached = false; } diff --git a/Assets/Editor Toolbox/Editor/Utilities/AssemblyUttility.cs.meta b/Assets/Editor Toolbox/Editor/Utilities/AssemblyUttility.cs.meta new file mode 100644 index 00000000..0f93c545 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/Utilities/AssemblyUttility.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9819eec002d0dfa4bba43c76f04d191c \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Utilities/PropertyUtility.cs b/Assets/Editor Toolbox/Editor/Utilities/PropertyUtility.cs index 0149aaec..63aed9ae 100644 --- a/Assets/Editor Toolbox/Editor/Utilities/PropertyUtility.cs +++ b/Assets/Editor Toolbox/Editor/Utilities/PropertyUtility.cs @@ -340,7 +340,7 @@ public static FieldInfo GetFieldInfoFromProperty(SerializedProperty property, ou var parent = property.GetParent(); if (parent != null && parent.propertyType == SerializedPropertyType.ManagedReference) { - TypeUtilities.TryGetTypeFromManagedReferenceFullTypeName(parent.managedReferenceFullTypename, out var parentType); + TypeUtility.TryGetTypeFromManagedReferenceFullTypeName(parent.managedReferenceFullTypename, out var parentType); foundField = parentType.GetField(member, fieldFlags); } } diff --git a/Assets/Editor Toolbox/Editor/Utilities/TypeUtilities.cs b/Assets/Editor Toolbox/Editor/Utilities/TypeUtilities.cs deleted file mode 100644 index a85266e8..00000000 --- a/Assets/Editor Toolbox/Editor/Utilities/TypeUtilities.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -using UnityEditor; - -namespace Toolbox.Editor -{ - using Toolbox.Editor.Internal; - - public static class TypeUtilities - { - internal static readonly Dictionary cachedCollections = new Dictionary(); - internal static readonly Dictionary editorCollections = new Dictionary(); - internal static readonly Dictionary referenceTypesByNames = new Dictionary(); - - internal static void ClearCache() - { - cachedCollections.Clear(); - editorCollections.Clear(); - referenceTypesByNames.Clear(); - } - - public static TypesCachedCollection GetCollection(Type parentType) - { - return GetCollection(new TypeConstraintContext(parentType)); - } - - public static TypesCachedCollection GetCollection(TypeConstraintContext constraint) - { - var key = constraint.GetHashCode(); - if (cachedCollections.TryGetValue(key, out var collection)) - { - return collection; - } - - var parentType = constraint.TargetType; - if (parentType == null) - { - return new TypesCachedCollection(); - } - - var typesList = FindTypes(constraint); - return cachedCollections[key] = new TypesCachedCollection(typesList); - } - - public static TypesEditorCollection GetCollection(TypeAppearanceContext appearance) - { - var key = appearance.GetHashCode(); - if (editorCollections.TryGetValue(key, out var collection)) - { - return collection; - } - - var types = GetCollection(appearance.Constraint); - return editorCollections[key] = new TypesEditorCollection(types, - appearance.AddEmptyValue, appearance.TypeGrouping); - } - - public static bool TryGetTypeFromManagedReferenceFullTypeName(string managedReferenceFullTypeName, out Type managedReferenceInstanceType) - { - if (referenceTypesByNames.TryGetValue(managedReferenceFullTypeName, out managedReferenceInstanceType)) - { - return true; - } - - var parts = managedReferenceFullTypeName.Split(' '); - managedReferenceInstanceType = parts.Length == 2 - ? Type.GetType($"{parts[1]}, {parts[0]}") : null; - if (managedReferenceInstanceType != null) - { - referenceTypesByNames[managedReferenceFullTypeName] = managedReferenceInstanceType; - return true; - } - - return false; - } - - public static List FindTypes(TypeConstraintContext constraint) - { -#if UNITY_2019_2_OR_NEWER - var parentType = constraint.TargetType; - var typesCache = TypeCache.GetTypesDerivedFrom(parentType); - var typesList = typesCache.ToList(); - typesList.Add(parentType); - for (var i = typesList.Count - 1; i >= 0; i--) - { - var type = typesList[i]; - if (constraint.IsSatisfied(type)) - { - continue; - } - - typesList.RemoveAt(i); - } -#else - var typesList = new List(); - var assemblies = AppDomain.CurrentDomain.GetAssemblies(); - foreach (var assembly in assemblies) - { - typesList.AddRange(FindTypes(constraint, assembly)); - } -#endif - if (constraint.IsOrdered) - { - var comparer = constraint.Comparer; - typesList.Sort(comparer); - } - - return typesList; - } - - public static List FindTypes(TypeConstraintContext constraint, Assembly assembly) - { - var types = new List(); - foreach (var type in assembly.GetTypes()) - { - if (!constraint.IsSatisfied(type)) - { - continue; - } - - types.Add(type); - } - - return types; - } - } -} \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Utilities/TypeUtilities.cs.meta b/Assets/Editor Toolbox/Editor/Utilities/TypeUtilities.cs.meta deleted file mode 100644 index 2c07c185..00000000 --- a/Assets/Editor Toolbox/Editor/Utilities/TypeUtilities.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3688f6c8b9775cf4f80143c85f5b36a1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs b/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs new file mode 100644 index 00000000..e92c814b --- /dev/null +++ b/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs @@ -0,0 +1,248 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +using UnityEditor; + +namespace Toolbox.Editor +{ + using Toolbox.Editor.Internal.Types; + + public static class TypeUtility + { + internal static readonly Dictionary cachedCollections = new Dictionary(); + internal static readonly Dictionary editorCollections = new Dictionary(); + internal static readonly Dictionary referenceTypesByNames = new Dictionary(); + + internal static void ClearCache() + { + cachedCollections.Clear(); + editorCollections.Clear(); + referenceTypesByNames.Clear(); + } + + internal static List GetDerviedTypesUsingAssemblies(Type parentType, Func typeProcessor = null) + { + var typesList = new List(); + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + foreach (var assembly in assemblies) + { + var derivedTypes = GetDerviedTypesUsingAssemblies(parentType, typeProcessor, assembly); + typesList.AddRange(derivedTypes); + } + + return typesList; + } + + internal static List GetDerviedTypesUsingAssemblies(Type parentType, Func typeProcessor, Assembly assembly) + { + var types = new List(); + var assemblyTypes = assembly.GetTypes(); + for (var i = 0; i < assemblyTypes.Length; i++) + { + var type = assemblyTypes[i]; + if (typeProcessor != null) + { + type = typeProcessor(type); + } + + if (type == null) + { + continue; + } + + if (!IsTypeAssignableFrom(parentType, type) || type == parentType) + { + continue; + } + + types.Add(type); + } + + return types; + } + + internal static List GetDerivedTypesUsingTypesCache(Type parentType, Func typeProcessor) + { + var typesList = new List(); +#if UNITY_2019_2_OR_NEWER + var typesCache = TypeCache.GetTypesDerivedFrom(parentType); + for (var i = 0; i < typesCache.Count; i++) + { + var derivedType = typesCache[i]; + if (typeProcessor != null) + { + derivedType = typeProcessor(derivedType); + } + + if (derivedType == null) + { + continue; + } + + typesList.Add(derivedType); + } +#endif + return typesList; + } + + public static TypesCachedCollection GetCollection(Type parentType) + { + return GetCollection(new TypeConstraintContext(parentType)); + } + + public static TypesCachedCollection GetCollection(TypeConstraintContext constraint) + { + var key = constraint.GetHashCode(); + if (cachedCollections.TryGetValue(key, out var collection)) + { + return collection; + } + + var parentType = constraint.TargetType; + if (parentType == null) + { + return new TypesCachedCollection(); + } + + var typesList = FindTypes(constraint); + return cachedCollections[key] = new TypesCachedCollection(typesList); + } + + public static TypesEditorCollection GetCollection(TypeAppearanceContext appearance) + { + var key = appearance.GetHashCode(); + if (editorCollections.TryGetValue(key, out var collection)) + { + return collection; + } + + var types = GetCollection(appearance.Constraint); + return editorCollections[key] = new TypesEditorCollection(types, + appearance.AddEmptyValue, appearance.TypeGrouping); + } + + public static bool TryGetTypeFromManagedReferenceFullTypeName(string managedReferenceFullTypeName, out Type managedReferenceInstanceType) + { + if (referenceTypesByNames.TryGetValue(managedReferenceFullTypeName, out managedReferenceInstanceType)) + { + return true; + } + + const int typeFormatParts = 2; + + var parts = managedReferenceFullTypeName.Split(' ', typeFormatParts, StringSplitOptions.None); + managedReferenceInstanceType = parts.Length == typeFormatParts + ? Type.GetType($"{parts[1]}, {parts[0]}") : null; + if (managedReferenceInstanceType != null) + { + referenceTypesByNames[managedReferenceFullTypeName] = managedReferenceInstanceType; + return true; + } + + return false; + } + + /// + /// Finds all derived s using provided . + /// + public static List FindTypes(TypeConstraintContext constraint) + { + List typesList; + var parentType = constraint.TargetType; + //NOTE: if parent type is generic and has non-generic arguments then we can try to create derived generic types with the same generic constraints + if (CanBeSourceForGenericTypes(parentType)) + { + var parentGenericType = parentType.GetGenericTypeDefinition(); + var parentGenericArgs = parentGenericType.GetGenericArguments(); + typesList = GetDerivedTypes(parentGenericType, (sourceType) => + { + //NOTE: type is a standard type implementation (even if generic), it means we can check the standard way + if (!sourceType.IsGenericTypeDefinition) + { + if (!IsTypeAssignableFrom(parentType, sourceType)) + { + return null; + } + + return constraint.IsSatisfied(sourceType) ? sourceType : null; + } + + var foundGenericArgs = sourceType.GetGenericArguments(); + if (foundGenericArgs.Length != parentGenericArgs.Length) + { + return null; + } + + try + { + var genericType = sourceType.MakeGenericType(parentType.GenericTypeArguments); + return constraint.IsSatisfied(genericType) ? genericType : null; + } + catch (ArgumentException) + { + //NOTE: that's the easiest way to check if all generic constraints are ok + return null; + } + }); + } + else + { + typesList = GetDerivedTypes(parentType, (sourceType) => + { + return constraint.IsSatisfied(sourceType) ? sourceType : null; + }); + } + + if (constraint.IsSatisfied(parentType)) + { + typesList.Add(parentType); + } + + if (constraint.IsOrdered) + { + var comparer = constraint.Comparer; + typesList.Sort(comparer); + } + + return typesList; + + static bool CanBeSourceForGenericTypes(Type type) + { + return type.IsGenericType && !type.IsGenericTypeDefinition; + } + + static List GetDerivedTypes(Type parentType, Func typeProcessor) + { +#if UNITY_2019_2_OR_NEWER + return GetDerivedTypesUsingTypesCache(parentType, typeProcessor); +#else + return GetDerviedTypesUsingAssemblies(parentType, typeProcessor); +#endif + } + } + + public static List FindTypes(TypeConstraintContext constraint, Assembly assembly) + { + var types = new List(); + foreach (var type in assembly.GetTypes()) + { + if (!constraint.IsSatisfied(type)) + { + continue; + } + + types.Add(type); + } + + return types; + } + + public static bool IsTypeAssignableFrom(Type parentType, Type type) + { + return parentType.IsGenericTypeDefinition + ? parentType.IsAssignableFromGenericDefinition(type) + : parentType.IsAssignableFrom(type); + } + } +} \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs.meta b/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs.meta new file mode 100644 index 00000000..6c9c854f --- /dev/null +++ b/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4bf3a64f9f909ca48962e4e94d609d9d \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Wizards/ScriptableObjectCreationWizard.cs b/Assets/Editor Toolbox/Editor/Wizards/ScriptableObjectCreationWizard.cs index 3954dbf3..37868438 100644 --- a/Assets/Editor Toolbox/Editor/Wizards/ScriptableObjectCreationWizard.cs +++ b/Assets/Editor Toolbox/Editor/Wizards/ScriptableObjectCreationWizard.cs @@ -9,8 +9,7 @@ namespace Toolbox.Editor.Wizards { using Toolbox.Attributes; - using Toolbox.Editor.Internal; - + using Toolbox.Editor.Internal.Types; using Editor = UnityEditor.Editor; /// @@ -28,7 +27,7 @@ public TypeConstraintScriptableObject() : base(typeof(ScriptableObject), TypeSet public override bool IsSatisfied(Type type) { - return AssemblyUtilities.IsProjectAssembly(type.Assembly) && + return AssemblyUttility.IsProjectAssembly(type.Assembly) && (Attribute.IsDefined(type, typeof(CreateInWizardAttribute)) || Attribute.IsDefined(type, typeof(CreateAssetMenuAttribute))) && base.IsSatisfied(type); } diff --git a/Assets/Editor Toolbox/Runtime/Extensions/TypeExtensions.cs b/Assets/Editor Toolbox/Runtime/Extensions/TypeExtensions.cs index 35abcf7d..9a743bf3 100644 --- a/Assets/Editor Toolbox/Runtime/Extensions/TypeExtensions.cs +++ b/Assets/Editor Toolbox/Runtime/Extensions/TypeExtensions.cs @@ -6,16 +6,16 @@ namespace Toolbox public static class TypeExtensions { /// - /// Generic equivalent of the . + /// Generic definition equivalent of the . /// - public static bool IsSubclassOfGeneric(this Type toCheck, Type generic) + public static bool IsSubclassOfGenericDefinition(this Type toCheck, Type genericDefinition) { while (toCheck != null && toCheck != typeof(object)) { var current = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck; - if (generic == current) + if (genericDefinition == current) { return true; } @@ -27,20 +27,35 @@ public static bool IsSubclassOfGeneric(this Type toCheck, Type generic) } /// - /// Generic equivalent of the . + /// Generic definition equivalent of the . /// - public static bool IsAssignableFromGeneric(this Type generic, Type toCheck) + public static bool IsAssignableFromGenericDefinition(this Type genericDefinition, Type toCheck) { while (toCheck != null && toCheck != typeof(object)) { var current = toCheck.IsGenericType - ? toCheck.GetGenericTypeDefinition() - : toCheck; - if (generic == current) + ? toCheck.GetGenericTypeDefinition() + : toCheck; + + if (genericDefinition == current) { return true; } + var interfaces = toCheck.GetInterfaces(); + foreach (var interfaceType in interfaces) + { + if (!interfaceType.IsGenericType) + { + continue; + } + + if (genericDefinition == interfaceType.GetGenericTypeDefinition()) + { + return true; + } + } + toCheck = toCheck.BaseType; } @@ -57,7 +72,7 @@ public static List GetAllChildClasses(this Type baseType, bool allowAbstra var assemblies = AppDomain.CurrentDomain.GetAssemblies(); var isSubclass = baseType.IsGenericType ? (Func) - ((type) => type.IsSubclassOfGeneric(baseType)) + ((type) => type.IsSubclassOfGenericDefinition(baseType)) : ((type) => type.IsSubclassOf(baseType)); foreach (var assembly in assemblies) @@ -83,7 +98,7 @@ public static List GetAllChildClasses(this Type baseType, bool allowAbstra public static Type GetEnumeratedType(this Type type) { var elementType = type.GetElementType(); - if (null != elementType) + if (elementType != null) { return elementType; } diff --git a/Assets/Editor Toolbox/Tests/Editor/TypesFilteringTest.cs b/Assets/Editor Toolbox/Tests/Editor/TypesFilteringTest.cs index 4bae665a..dc9cd5ba 100644 --- a/Assets/Editor Toolbox/Tests/Editor/TypesFilteringTest.cs +++ b/Assets/Editor Toolbox/Tests/Editor/TypesFilteringTest.cs @@ -1,52 +1,59 @@ -using System; +#pragma warning disable CS0612 using NUnit.Framework; - +using System; using UnityEngine; namespace Toolbox.Editor.Tests { - using Toolbox.Editor.Internal; + using Toolbox.Editor.Internal.Types; + using static Toolbox.Editor.Tests.TypesFilteringTest; public class TypesFilteringTest { public interface Interface1 { } + [Obsolete] public interface Interface2 : Interface1 { } public interface Interface3 : Interface1 { } public interface Interface4 : Interface2 { } public interface Interface4 : Interface3 { } + public interface Interface5 : Interface4 { } + public interface Interface6 : Interface4 { } + public interface Interface7 : Interface4 { } public abstract class ClassBase : Interface1 { } + public class ClassWithInterface1 : ClassBase { } [Obsolete] public class ClassWithInterface2 : ClassBase { } public class ClassWithInterface3 : ClassBase { } - + public class ClassWithInterface4 : ClassBase, Interface4 { } + public class ClassWithInterface5 : ClassWithInterface4 { } + public class ClassWithInterface6: ClassWithInterface4 { } + public class ClassWithInterface7 : ClassWithInterface4 { } [TestCase(typeof(ClassBase), 3)] [TestCase(typeof(Interface1), 6)] [TestCase(typeof(MonoBehaviour), 2)] public void TestTypesCachingPass(Type parentType, int count) { - TypeUtilities.ClearCache(); + TypeUtility.ClearCache(); for (var i = 0; i < count; i++) { - TypeUtilities.GetCollection(parentType); + TypeUtility.GetCollection(parentType); } - Assert.AreEqual(1, TypeUtilities.cachedCollections.Count); + Assert.AreEqual(1, TypeUtility.cachedCollections.Count); } [Test] public void TestStandardConstraintPass1() { var constraint = new TypeConstraintStandard(typeof(Interface1), TypeSettings.Class, false, false); - var collection = TypeUtilities.GetCollection(constraint); + var collection = TypeUtility.GetCollection(constraint); Assert.IsFalse(collection.Contains(typeof(ClassBase))); Assert.IsTrue(collection.Contains(typeof(ClassWithInterface1))); -#pragma warning disable CS0612 Assert.IsFalse(collection.Contains(typeof(ClassWithInterface2))); -#pragma warning restore CS0612 Assert.IsTrue(collection.Contains(typeof(ClassWithInterface3))); Assert.IsFalse(collection.Contains(typeof(Interface2))); Assert.IsFalse(collection.Contains(typeof(Interface3))); @@ -56,12 +63,10 @@ public void TestStandardConstraintPass1() public void TestStandardConstraintPass2() { var constraint = new TypeConstraintStandard(typeof(Interface1), TypeSettings.Class, true, false); - var collection = TypeUtilities.GetCollection(constraint); + var collection = TypeUtility.GetCollection(constraint); Assert.IsTrue(collection.Contains(typeof(ClassBase))); Assert.IsTrue(collection.Contains(typeof(ClassWithInterface1))); -#pragma warning disable CS0612 Assert.IsFalse(collection.Contains(typeof(ClassWithInterface2))); -#pragma warning restore CS0612 Assert.IsTrue(collection.Contains(typeof(ClassWithInterface3))); Assert.IsFalse(collection.Contains(typeof(Interface2))); Assert.IsFalse(collection.Contains(typeof(Interface3))); @@ -71,12 +76,10 @@ public void TestStandardConstraintPass2() public void TestStandardConstraintPass3() { var constraint = new TypeConstraintStandard(typeof(Interface1), TypeSettings.Class, true, true); - var collection = TypeUtilities.GetCollection(constraint); + var collection = TypeUtility.GetCollection(constraint); Assert.IsTrue(collection.Contains(typeof(ClassBase))); Assert.IsTrue(collection.Contains(typeof(ClassWithInterface1))); -#pragma warning disable CS0612 Assert.IsTrue(collection.Contains(typeof(ClassWithInterface2))); -#pragma warning restore CS0612 Assert.IsTrue(collection.Contains(typeof(ClassWithInterface3))); Assert.IsFalse(collection.Contains(typeof(Interface2))); Assert.IsFalse(collection.Contains(typeof(Interface3))); @@ -86,12 +89,10 @@ public void TestStandardConstraintPass3() public void TestStandardConstraintPass4() { var constraint = new TypeConstraintStandard(typeof(Interface1), TypeSettings.Interface, true, true); - var collection = TypeUtilities.GetCollection(constraint); + var collection = TypeUtility.GetCollection(constraint); Assert.IsFalse(collection.Contains(typeof(ClassBase))); Assert.IsFalse(collection.Contains(typeof(ClassWithInterface1))); -#pragma warning disable CS0612 Assert.IsFalse(collection.Contains(typeof(ClassWithInterface2))); -#pragma warning restore CS0612 Assert.IsFalse(collection.Contains(typeof(ClassWithInterface3))); Assert.IsTrue(collection.Contains(typeof(Interface2))); Assert.IsTrue(collection.Contains(typeof(Interface3))); @@ -101,14 +102,12 @@ public void TestStandardConstraintPass4() public void TestStandardConstraintPass5() { var constraint = new TypeConstraintStandard(typeof(Interface1), TypeSettings.Class | TypeSettings.Interface, true, false); - var collection = TypeUtilities.GetCollection(constraint); + var collection = TypeUtility.GetCollection(constraint); Assert.IsTrue(collection.Contains(typeof(ClassBase))); Assert.IsTrue(collection.Contains(typeof(ClassWithInterface1))); -#pragma warning disable CS0612 Assert.IsFalse(collection.Contains(typeof(ClassWithInterface2))); -#pragma warning restore CS0612 Assert.IsTrue(collection.Contains(typeof(ClassWithInterface3))); - Assert.IsTrue(collection.Contains(typeof(Interface2))); + Assert.IsFalse(collection.Contains(typeof(Interface2))); Assert.IsTrue(collection.Contains(typeof(Interface3))); } @@ -116,12 +115,10 @@ public void TestStandardConstraintPass5() public void TestStandardConstraintPass6() { var constraint = new TypeConstraintStandard(typeof(ClassBase), TypeSettings.Class | TypeSettings.Interface, false, false); - var collection = TypeUtilities.GetCollection(constraint); + var collection = TypeUtility.GetCollection(constraint); Assert.IsFalse(collection.Contains(typeof(ClassBase))); Assert.IsTrue(collection.Contains(typeof(ClassWithInterface1))); -#pragma warning disable CS0612 Assert.IsFalse(collection.Contains(typeof(ClassWithInterface2))); -#pragma warning restore CS0612 Assert.IsTrue(collection.Contains(typeof(ClassWithInterface3))); Assert.IsFalse(collection.Contains(typeof(Interface2))); Assert.IsFalse(collection.Contains(typeof(Interface3))); @@ -131,45 +128,80 @@ public void TestStandardConstraintPass6() public void TestStandardConstraintPass7() { var constraint = new TypeConstraintStandard(typeof(Component), TypeSettings.Class | TypeSettings.Interface, true, false); - var collection = TypeUtilities.GetCollection(constraint); + var collection = TypeUtility.GetCollection(constraint); Assert.IsFalse(collection.Contains(typeof(ClassBase))); Assert.IsTrue(collection.Contains(typeof(Collider))); } [Test] - public void TestReferenceConstraintPass1() + public void TestStandardConstraintWithGenericPass() + { + var constraint = new TypeConstraintStandard(typeof(Interface4), TypeSettings.Interface, true, false); + var collection = TypeUtility.GetCollection(constraint); + Assert.IsFalse(collection.Contains(typeof(ClassWithInterface1))); + Assert.IsFalse(collection.Contains(typeof(ClassWithInterface2))); + Assert.IsFalse(collection.Contains(typeof(ClassWithInterface3))); + Assert.IsFalse(collection.Contains(typeof(Interface2))); + Assert.IsFalse(collection.Contains(typeof(Interface3))); + Assert.IsTrue(collection.Contains(typeof(Interface4))); + Assert.IsTrue(collection.Contains(typeof(Interface5))); + Assert.IsFalse(collection.Contains(typeof(Interface6))); + Assert.IsTrue(collection.Contains(typeof(Interface7))); + } + + [Test] + public void TestSerializeReferenceConstraintPass1() { var constraint = new TypeConstraintSerializeReference(typeof(Component)); - var collection = TypeUtilities.GetCollection(constraint); + var collection = TypeUtility.GetCollection(constraint); Assert.AreEqual(0, collection.Values.Count); } [Test] - public void TestReferenceConstraintPass2() + public void TestSerializeReferenceConstraintPass2() { var constraint = new TypeConstraintSerializeReference(typeof(ClassBase)); - var collection = TypeUtilities.GetCollection(constraint); + var collection = TypeUtility.GetCollection(constraint); Assert.IsTrue(collection.Contains(typeof(ClassWithInterface1))); -#pragma warning disable CS0612 Assert.IsFalse(collection.Contains(typeof(ClassWithInterface2))); -#pragma warning restore CS0612 Assert.IsTrue(collection.Contains(typeof(ClassWithInterface3))); Assert.IsFalse(collection.Contains(typeof(Interface2))); Assert.IsFalse(collection.Contains(typeof(Interface3))); } [Test] - public void TestReferenceConstraintPass3() + public void TestSerializeReferenceConstraintPass3() { var constraint = new TypeConstraintSerializeReference(typeof(Interface1)); - var collection = TypeUtilities.GetCollection(constraint); + var collection = TypeUtility.GetCollection(constraint); Assert.IsTrue(collection.Contains(typeof(ClassWithInterface1))); -#pragma warning disable CS0612 Assert.IsFalse(collection.Contains(typeof(ClassWithInterface2))); -#pragma warning restore CS0612 Assert.IsTrue(collection.Contains(typeof(ClassWithInterface3))); Assert.IsFalse(collection.Contains(typeof(Interface2))); Assert.IsFalse(collection.Contains(typeof(Interface3))); } + + [Test] + public void TestSerializeReferenceConstraintWithGenericPass() + { + var constraint = new TypeConstraintSerializeReference(typeof(Interface4)); + var collection = TypeUtility.GetCollection(constraint); + Assert.IsFalse(collection.Contains(typeof(ClassWithInterface1))); + Assert.IsFalse(collection.Contains(typeof(ClassWithInterface2))); + Assert.IsFalse(collection.Contains(typeof(ClassWithInterface3))); + Assert.IsFalse(collection.Contains(typeof(Interface2))); + Assert.IsFalse(collection.Contains(typeof(Interface3))); + Assert.IsFalse(collection.Contains(typeof(Interface5))); + Assert.IsFalse(collection.Contains(typeof(Interface6))); + Assert.IsFalse(collection.Contains(typeof(Interface7))); + Assert.IsTrue(collection.Contains(typeof(ClassWithInterface4))); + Assert.IsFalse(collection.Contains(typeof(ClassWithInterface4))); + Assert.IsTrue(collection.Contains(typeof(ClassWithInterface5))); + Assert.IsFalse(collection.Contains(typeof(ClassWithInterface6))); + Assert.IsTrue(collection.Contains(typeof(ClassWithInterface7))); + Assert.IsFalse(collection.Contains(typeof(ClassWithInterface7))); + } } -} \ No newline at end of file +} + +#pragma warning restore CS0612 \ No newline at end of file diff --git a/Assets/Examples/Scripts/SampleBehaviour1.cs b/Assets/Examples/Scripts/SampleBehaviour1.cs index 31ff2e32..57eca4e6 100644 --- a/Assets/Examples/Scripts/SampleBehaviour1.cs +++ b/Assets/Examples/Scripts/SampleBehaviour1.cs @@ -89,30 +89,37 @@ public enum FlagExample [Password] public string password; - [Label("Validation", skinStyle: SkinStyle.Box)] + [Label("Formatted Number", skinStyle: SkinStyle.Box)] + + [FormattedNumber] + public int bigNumber; + [FormattedNumber("c")] + public float currency; + + [BeginGroup(Order = -2)] [Help("NotNullAttribute, ClampAttribute, SceneObjectOnlyAttribute, ChildObjectOnlyAttribute, PrefabObjectOnlyAttribute " + "are part of group that will be re-implemented in future as ToolboxValidationAttributes. " + - "Unfortunately, for now, you can't use them together with any other PropertyDrawer.", UnityMessageType.Warning)] - [NotNull] - public Transform var13; + "Unfortunately, for now, you can't use them together with any other PropertyDrawer.", UnityMessageType.Warning, Order = -1)] + + [Label("Validation", skinStyle: SkinStyle.Box)] [Clamp(0.0f, 11.2f)] public double clampedValue; - [SceneObjectOnly] - public GameObject sceneReference; + [NotNull] + public GameObject notNullReference; + [ChildObjectOnly] public GameObject childReference; + + [SceneObjectOnly] + public GameObject sceneReference; + [PrefabObjectOnly] public GameObject prefabReference; + + [EndGroup] [NotPrefabObjectOnly(AllowInstancedPrefabs = false)] public GameObject notPrefabReference; - - [Label("Formatted Number", skinStyle: SkinStyle.Box)] - - [FormattedNumber] - public int bigNumber; - [FormattedNumber("c")] - public float currency; } \ No newline at end of file diff --git a/Assets/Examples/Scripts/SampleBehaviour3.cs b/Assets/Examples/Scripts/SampleBehaviour3.cs index c785f834..df1b8f65 100644 --- a/Assets/Examples/Scripts/SampleBehaviour3.cs +++ b/Assets/Examples/Scripts/SampleBehaviour3.cs @@ -1,7 +1,7 @@ using UnityEngine; [ExecuteAlways] -[AddComponentMenu("Editor Toolbox/Cheat Sheet 3 (Condition)")] +[AddComponentMenu("Editor Toolbox/Cheat Sheet 3 (Toolbox Conditions)")] public class SampleBehaviour3 : MonoBehaviour { [Label("Show If", skinStyle: SkinStyle.Box)] diff --git a/Assets/Examples/Scripts/SampleBehaviour4.cs b/Assets/Examples/Scripts/SampleBehaviour4.cs index a9bc0be0..ce7ecb65 100644 --- a/Assets/Examples/Scripts/SampleBehaviour4.cs +++ b/Assets/Examples/Scripts/SampleBehaviour4.cs @@ -3,7 +3,7 @@ using UnityEngine; [ExecuteAlways] -[AddComponentMenu("Editor Toolbox/Cheat Sheet 4 (Decorator)")] +[AddComponentMenu("Editor Toolbox/Cheat Sheet 4 (Toolbox Decorators)")] public class SampleBehaviour4 : MonoBehaviour { [Label("Help", skinStyle: SkinStyle.Box)] diff --git a/Assets/Examples/Scripts/SampleBehaviour5.cs b/Assets/Examples/Scripts/SampleBehaviour5.cs index d3a248d1..e971dea6 100644 --- a/Assets/Examples/Scripts/SampleBehaviour5.cs +++ b/Assets/Examples/Scripts/SampleBehaviour5.cs @@ -15,8 +15,15 @@ public class SampleBehaviour5 : MonoBehaviour public SerializedType type3; [TypeConstraint(typeof(Collider), AllowAbstract = false, AllowObsolete = false, TypeSettings = TypeSettings.Class, TypeGrouping = TypeGrouping.None)] public SerializedType type4; - [TypeConstraint(typeof(Collider), AllowAbstract = false, AllowObsolete = false, TypeSettings = TypeSettings.Class, TypeGrouping = TypeGrouping.ByFlatName)] + [TypeConstraint(typeof(Collider), AllowAbstract = true, AllowObsolete = false, TypeSettings = TypeSettings.Class, TypeGrouping = TypeGrouping.ByFlatName)] public SerializedType type5; + [TypeConstraint(typeof(ISampleGenericInterface<>), AllowAbstract = false, AllowObsolete = false, TypeSettings = TypeSettings.Class, TypeGrouping = TypeGrouping.ByFlatName)] + public SerializedType type6; + + public interface ISampleGenericInterface { } + public class ClassWithInterface1 : ISampleGenericInterface { } + public class ClassWithInterface2 : ISampleGenericInterface { } + public class ClassWithInterface3 : ISampleGenericInterface { } [Label("Serialized Scene", skinStyle: SkinStyle.Box)] diff --git a/Assets/Examples/Scripts/SampleBehaviour6.cs b/Assets/Examples/Scripts/SampleBehaviour6.cs index 9a12e321..550b28e1 100644 --- a/Assets/Examples/Scripts/SampleBehaviour6.cs +++ b/Assets/Examples/Scripts/SampleBehaviour6.cs @@ -1,14 +1,16 @@ using System; using UnityEngine; +using UnityEngine.Scripting.APIUpdating; [ExecuteAlways] [AddComponentMenu("Editor Toolbox/Cheat Sheet 6 (Serialize Reference)")] public class SampleBehaviour6 : MonoBehaviour { #if UNITY_2019_3_OR_NEWER + [Label("Standard Types", skinStyle: SkinStyle.Box)] [SerializeReference, ReferencePicker(TypeGrouping = TypeGrouping.ByFlatName)] - public Interface1 var1; + public ISampleInterface var1; [SerializeReference, ReferencePicker(ForceUninitializedInstance = true)] public ClassWithInterfaceBase var2; [SerializeReference, ReferencePicker] @@ -16,26 +18,34 @@ public class SampleBehaviour6 : MonoBehaviour [SerializeReference, ReferencePicker(ParentType = typeof(ClassWithInterface2), AddTextSearchField = false)] public ClassWithInterfaceBase var4; [SerializeReference, ReferencePicker, ReorderableList] - public Interface1[] vars; + public ISampleInterface[] vars; #endif - public interface Interface1 +#if UNITY_2023_2_OR_NEWER + [Label("Generic Types", skinStyle: SkinStyle.Box)] + [SerializeReference, ReferencePicker(TypeGrouping = TypeGrouping.None)] + public IGenericInterface generic; +#endif + + #region Standard Types + + public interface ISampleInterface { } - [Serializable] - public struct Struct : Interface1 + [Serializable, MovedFrom(false, null, null, "SampleBehaviour6/Struct")] + public struct SampleStruct : ISampleInterface { public bool var1; public bool var2; - public Struct(bool var1, bool var2) + public SampleStruct(bool var1, bool var2) { this.var1 = var1; this.var2 = var2; } } - public abstract class ClassWithInterfaceBase : Interface1 + public abstract class ClassWithInterfaceBase : ISampleInterface { } [Serializable] @@ -46,7 +56,7 @@ public class ClassWithInterface1 : ClassWithInterfaceBase #if UNITY_2019_2_OR_NEWER [SerializeReference, ReferencePicker] #endif - public Interface1 var1; + public ISampleInterface var1; } [Serializable] @@ -74,4 +84,51 @@ public class ClassWithInterface4 : ClassWithInterface2 { public int var33; } + + #endregion + + #region Generic Types + + public interface IGenericInterface + { + TValue Value { get; } + } + + public class IntInterfaceImplementationInt : IGenericInterface + { + [SerializeField] + private int value; + + public int Value => value; + } + + public class StringInterfaceImplementation : IGenericInterface + { + [SerializeField] + private string value; + + public string Value => value; + } + + public class GenericInterfaceImplementation : IGenericInterface + { + [SerializeField] + private TValue value; + [SerializeField] + private bool var1; + + public TValue Value => value; + } + + public class WrongConstraintGenericInterfaceImplementation : IGenericInterface where TValue : struct + { + [SerializeField] + private TValue value; + [SerializeField] + private float var1; + + public TValue Value => value; + } + + #endregion } \ No newline at end of file From 438ff7f4339428fe3677e623dd9bbe9aa4f0edff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Wed, 28 Aug 2024 15:55:40 +0200 Subject: [PATCH 11/23] Minor fixes and refactor changes --- .../PasteSerializeReferenceOperation.cs | 3 +- .../Types/TypeAppearanceContext.cs.meta | 11 +- .../Types/TypeConstraintContext.cs.meta | 11 +- .../TypeConstraintSerializeReference.cs.meta | 11 +- .../Types/TypeConstraintStandard.cs.meta | 11 +- .../Editor/Internal/Types/TypeField.cs.meta | 11 +- .../Types/TypesCachedCollection.cs.meta | 11 +- .../Types/TypesEditorCollection.cs.meta | 11 +- .../Editor/Utilities/AssemblyUttility.cs.meta | 11 +- .../Editor/Utilities/TypeUtility.cs | 63 +++++------ .../Editor/Utilities/TypeUtility.cs.meta | 11 +- .../Tests/Editor/TypesFilteringTest.cs | 14 ++- Assets/Examples/Scenes/SampleScene.unity | 105 ++++++------------ .../Scenes/SampleSceneSettings.lighting | 5 +- Assets/Examples/Scripts/SampleBehaviour5.cs | 2 +- Assets/Examples/Scripts/SampleBehaviour6.cs | 7 +- 16 files changed, 176 insertions(+), 122 deletions(-) diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs index 5c716ad4..09f0d342 100644 --- a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/PasteSerializeReferenceOperation.cs @@ -9,6 +9,7 @@ internal class PasteSerializeReferenceOperation : IContextMenuOperation { private bool IsAssignmentValid(SerializedProperty property, object newValue) { +#if UNITY_2021_3_OR_NEWER if (newValue == null) { return true; @@ -24,7 +25,7 @@ private bool IsAssignmentValid(SerializedProperty property, object newValue) { return true; } - +#endif return false; } diff --git a/Assets/Editor Toolbox/Editor/Internal/Types/TypeAppearanceContext.cs.meta b/Assets/Editor Toolbox/Editor/Internal/Types/TypeAppearanceContext.cs.meta index f700b5c7..901a8aa0 100644 --- a/Assets/Editor Toolbox/Editor/Internal/Types/TypeAppearanceContext.cs.meta +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypeAppearanceContext.cs.meta @@ -1,2 +1,11 @@ fileFormatVersion: 2 -guid: 80454d63dd02c0d42b6ac59f8eaee024 \ No newline at end of file +guid: 80454d63dd02c0d42b6ac59f8eaee024 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintContext.cs.meta b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintContext.cs.meta index 2d1ca679..75399aaf 100644 --- a/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintContext.cs.meta +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintContext.cs.meta @@ -1,2 +1,11 @@ fileFormatVersion: 2 -guid: 8c2d536076f643b4689c9d04b8b5b2f0 \ No newline at end of file +guid: 8c2d536076f643b4689c9d04b8b5b2f0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintSerializeReference.cs.meta b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintSerializeReference.cs.meta index 08bba96d..992b49e0 100644 --- a/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintSerializeReference.cs.meta +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintSerializeReference.cs.meta @@ -1,2 +1,11 @@ fileFormatVersion: 2 -guid: f2f4619c41ded3c418dfbcd3d93ea5c7 \ No newline at end of file +guid: f2f4619c41ded3c418dfbcd3d93ea5c7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintStandard.cs.meta b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintStandard.cs.meta index bfec77bd..618f1761 100644 --- a/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintStandard.cs.meta +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintStandard.cs.meta @@ -1,2 +1,11 @@ fileFormatVersion: 2 -guid: 79789e5b77277274fa20fbed57488a1a \ No newline at end of file +guid: 79789e5b77277274fa20fbed57488a1a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Internal/Types/TypeField.cs.meta b/Assets/Editor Toolbox/Editor/Internal/Types/TypeField.cs.meta index 91e47895..c9b4aabc 100644 --- a/Assets/Editor Toolbox/Editor/Internal/Types/TypeField.cs.meta +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypeField.cs.meta @@ -1,2 +1,11 @@ fileFormatVersion: 2 -guid: 8f3a75051e0f62a45bd84f4d36763f84 \ No newline at end of file +guid: 8f3a75051e0f62a45bd84f4d36763f84 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Internal/Types/TypesCachedCollection.cs.meta b/Assets/Editor Toolbox/Editor/Internal/Types/TypesCachedCollection.cs.meta index 6292f196..3cf50555 100644 --- a/Assets/Editor Toolbox/Editor/Internal/Types/TypesCachedCollection.cs.meta +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypesCachedCollection.cs.meta @@ -1,2 +1,11 @@ fileFormatVersion: 2 -guid: b1c652a61bba0af4c946b01f28117ae8 \ No newline at end of file +guid: b1c652a61bba0af4c946b01f28117ae8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Internal/Types/TypesEditorCollection.cs.meta b/Assets/Editor Toolbox/Editor/Internal/Types/TypesEditorCollection.cs.meta index 9b184e3b..fa40d6d5 100644 --- a/Assets/Editor Toolbox/Editor/Internal/Types/TypesEditorCollection.cs.meta +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypesEditorCollection.cs.meta @@ -1,2 +1,11 @@ fileFormatVersion: 2 -guid: 79255218de0423940a945ec3f922e22c \ No newline at end of file +guid: 79255218de0423940a945ec3f922e22c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Utilities/AssemblyUttility.cs.meta b/Assets/Editor Toolbox/Editor/Utilities/AssemblyUttility.cs.meta index 0f93c545..08dd6d9e 100644 --- a/Assets/Editor Toolbox/Editor/Utilities/AssemblyUttility.cs.meta +++ b/Assets/Editor Toolbox/Editor/Utilities/AssemblyUttility.cs.meta @@ -1,2 +1,11 @@ fileFormatVersion: 2 -guid: 9819eec002d0dfa4bba43c76f04d191c \ No newline at end of file +guid: 9819eec002d0dfa4bba43c76f04d191c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs b/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs index e92c814b..343b1147 100644 --- a/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs +++ b/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs @@ -86,6 +86,20 @@ internal static List GetDerivedTypesUsingTypesCache(Type parentType, Func< return typesList; } + internal static List GetDerivedTypes(Type parentType, Func typeProcessor) + { +#if UNITY_2019_2_OR_NEWER + return GetDerivedTypesUsingTypesCache(parentType, typeProcessor); +#else + return GetDerviedTypesUsingAssemblies(parentType, typeProcessor); +#endif + } + + internal static bool CanBeSourceForGenericTypes(Type type) + { + return type.IsGenericType && !type.IsGenericTypeDefinition; + } + public static TypesCachedCollection GetCollection(Type parentType) { return GetCollection(new TypeConstraintContext(parentType)); @@ -131,7 +145,7 @@ public static bool TryGetTypeFromManagedReferenceFullTypeName(string managedRefe const int typeFormatParts = 2; - var parts = managedReferenceFullTypeName.Split(' ', typeFormatParts, StringSplitOptions.None); + var parts = managedReferenceFullTypeName.Split(new char[] { ' ' }, typeFormatParts, StringSplitOptions.None); managedReferenceInstanceType = parts.Length == typeFormatParts ? Type.GetType($"{parts[1]}, {parts[0]}") : null; if (managedReferenceInstanceType != null) @@ -157,33 +171,34 @@ public static List FindTypes(TypeConstraintContext constraint) var parentGenericArgs = parentGenericType.GetGenericArguments(); typesList = GetDerivedTypes(parentGenericType, (sourceType) => { - //NOTE: type is a standard type implementation (even if generic), it means we can check the standard way - if (!sourceType.IsGenericTypeDefinition) + var targetType = sourceType; + //NOTE: type is a generic definition, it means we can check if constraints are matched + if (sourceType.IsGenericTypeDefinition) { - if (!IsTypeAssignableFrom(parentType, sourceType)) + var foundGenericArgs = sourceType.GetGenericArguments(); + if (foundGenericArgs.Length != parentGenericArgs.Length) { return null; } - return constraint.IsSatisfied(sourceType) ? sourceType : null; + try + { + targetType = sourceType.MakeGenericType(parentType.GenericTypeArguments); + } + catch (ArgumentException) + { + //NOTE: that's the easiest way to check if all generic constraints are ok + return null; + } } - var foundGenericArgs = sourceType.GetGenericArguments(); - if (foundGenericArgs.Length != parentGenericArgs.Length) + //NOTE: we need to check inheritance since all processed types are derived from the generic type definition + if (!IsTypeAssignableFrom(parentType, targetType)) { return null; } - try - { - var genericType = sourceType.MakeGenericType(parentType.GenericTypeArguments); - return constraint.IsSatisfied(genericType) ? genericType : null; - } - catch (ArgumentException) - { - //NOTE: that's the easiest way to check if all generic constraints are ok - return null; - } + return constraint.IsSatisfied(targetType) ? targetType : null; }); } else @@ -206,20 +221,6 @@ public static List FindTypes(TypeConstraintContext constraint) } return typesList; - - static bool CanBeSourceForGenericTypes(Type type) - { - return type.IsGenericType && !type.IsGenericTypeDefinition; - } - - static List GetDerivedTypes(Type parentType, Func typeProcessor) - { -#if UNITY_2019_2_OR_NEWER - return GetDerivedTypesUsingTypesCache(parentType, typeProcessor); -#else - return GetDerviedTypesUsingAssemblies(parentType, typeProcessor); -#endif - } } public static List FindTypes(TypeConstraintContext constraint, Assembly assembly) diff --git a/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs.meta b/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs.meta index 6c9c854f..8befc008 100644 --- a/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs.meta +++ b/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs.meta @@ -1,2 +1,11 @@ fileFormatVersion: 2 -guid: 4bf3a64f9f909ca48962e4e94d609d9d \ No newline at end of file +guid: 4bf3a64f9f909ca48962e4e94d609d9d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Tests/Editor/TypesFilteringTest.cs b/Assets/Editor Toolbox/Tests/Editor/TypesFilteringTest.cs index dc9cd5ba..73e373f8 100644 --- a/Assets/Editor Toolbox/Tests/Editor/TypesFilteringTest.cs +++ b/Assets/Editor Toolbox/Tests/Editor/TypesFilteringTest.cs @@ -1,13 +1,14 @@ #pragma warning disable CS0612 using NUnit.Framework; + using System; + using UnityEngine; namespace Toolbox.Editor.Tests { using Toolbox.Editor.Internal.Types; - using static Toolbox.Editor.Tests.TypesFilteringTest; public class TypesFilteringTest { @@ -29,7 +30,7 @@ public class ClassWithInterface2 : ClassBase { } public class ClassWithInterface3 : ClassBase { } public class ClassWithInterface4 : ClassBase, Interface4 { } public class ClassWithInterface5 : ClassWithInterface4 { } - public class ClassWithInterface6: ClassWithInterface4 { } + public class ClassWithInterface6 : ClassWithInterface4 { } public class ClassWithInterface7 : ClassWithInterface4 { } [TestCase(typeof(ClassBase), 3)] @@ -194,12 +195,17 @@ public void TestSerializeReferenceConstraintWithGenericPass() Assert.IsFalse(collection.Contains(typeof(Interface5))); Assert.IsFalse(collection.Contains(typeof(Interface6))); Assert.IsFalse(collection.Contains(typeof(Interface7))); - Assert.IsTrue(collection.Contains(typeof(ClassWithInterface4))); Assert.IsFalse(collection.Contains(typeof(ClassWithInterface4))); Assert.IsTrue(collection.Contains(typeof(ClassWithInterface5))); Assert.IsFalse(collection.Contains(typeof(ClassWithInterface6))); - Assert.IsTrue(collection.Contains(typeof(ClassWithInterface7))); Assert.IsFalse(collection.Contains(typeof(ClassWithInterface7))); +#if UNITY_2023_2_OR_NEWER + Assert.IsTrue(collection.Contains(typeof(ClassWithInterface7))); + Assert.IsTrue(collection.Contains(typeof(ClassWithInterface4))); +#else + Assert.IsFalse(collection.Contains(typeof(ClassWithInterface7))); + Assert.IsFalse(collection.Contains(typeof(ClassWithInterface4))); +#endif } } } diff --git a/Assets/Examples/Scenes/SampleScene.unity b/Assets/Examples/Scenes/SampleScene.unity index 803df7e2..3c618426 100644 --- a/Assets/Examples/Scenes/SampleScene.unity +++ b/Assets/Examples/Scenes/SampleScene.unity @@ -1048,93 +1048,56 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: var1: - rid: 0 + rid: 7033609514626056197 var2: - rid: 7033609465735938071 + rid: 7033609514626056196 var3: - rid: 7033609465735938065 + rid: 7033609514626056198 var4: - rid: 7033609465735938072 + rid: 7033609514626056199 vars: - - rid: 3 - - rid: 4 - - rid: 5 - - rid: 6 - - rid: 7033609465735938087 + - rid: 7033609514626056193 + - rid: 7033609514626056204 references: version: 2 RefIds: - - rid: -2 - type: {class: , ns: , asm: } - - rid: 0 - type: {class: SampleBehaviour6/ClassWithInterface1, ns: , asm: Assembly-CSharp} - data: - go: {fileID: 977748987} - var1: - rid: 7 - - rid: 3 + - rid: 7033609514626056193 type: {class: SampleBehaviour6/ClassWithInterface1, ns: , asm: Assembly-CSharp} data: go: {fileID: 0} var1: - rid: 7033609465735938082 - - rid: 4 - type: {class: SampleBehaviour6/ClassWithInterface2, ns: , asm: Assembly-CSharp} + rid: 7033609514626056194 + - rid: 7033609514626056194 + type: {class: SampleBehaviour6/SampleStruct, ns: , asm: Assembly-CSharp} data: var1: 0 - mat: {fileID: 0} - - rid: 5 + var2: 0 + - rid: 7033609514626056196 type: {class: SampleBehaviour6/ClassWithInterface4, ns: , asm: Assembly-CSharp} data: - var1: 0 + var1: 1 mat: {fileID: 0} - var33: 0 - - rid: 6 - type: {class: SampleBehaviour6/Struct, ns: , asm: Assembly-CSharp} + var33: 11 + - rid: 7033609514626056197 + type: {class: SampleBehaviour6/SampleStruct, ns: , asm: Assembly-CSharp} data: var1: 1 - var2: 0 - - rid: 7 - type: {class: SampleBehaviour6/ClassWithInterface1, ns: , asm: Assembly-CSharp} - data: - go: {fileID: 0} - var1: - rid: -2 - - rid: 7033609465735938065 - type: {class: SampleBehaviour6/ClassWithInterface1, ns: , asm: Assembly-CSharp} - data: - go: {fileID: 1972418676} - var1: - rid: 7033609465735938066 - - rid: 7033609465735938066 - type: {class: SampleBehaviour6/ClassWithInterface1, ns: , asm: Assembly-CSharp} - data: - go: {fileID: 0} - var1: - rid: -2 - - rid: 7033609465735938071 - type: {class: SampleBehaviour6/ClassWithInterface4, ns: , asm: Assembly-CSharp} - data: - var1: 0 - mat: {fileID: 0} - var33: 0 - - rid: 7033609465735938072 - type: {class: SampleBehaviour6/ClassWithInterface4, ns: , asm: Assembly-CSharp} + var2: 1 + - rid: 7033609514626056198 + type: {class: SampleBehaviour6/ClassWithInterface2, ns: , asm: Assembly-CSharp} data: var1: 0 mat: {fileID: 0} - var33: 0 - - rid: 7033609465735938082 - type: {class: SampleBehaviour6/Struct, ns: , asm: Assembly-CSharp} + - rid: 7033609514626056199 + type: {class: SampleBehaviour6/ClassWithInterface2, ns: , asm: Assembly-CSharp} data: var1: 0 - var2: 0 - - rid: 7033609465735938087 - type: {class: SampleBehaviour6/ClassWithInterface4, ns: , asm: Assembly-CSharp} + mat: {fileID: 2100000, guid: 26a618e7877b8c94f967effc172108f2, type: 2} + - rid: 7033609514626056204 + type: {class: SampleBehaviour6/ClassWithInterface2, ns: , asm: Assembly-CSharp} data: - var1: 0 - mat: {fileID: 0} - var33: 0 + var1: 1 + mat: {fileID: 2100000, guid: 7404c70251f9d0045a4aabaa49d83963, type: 2} --- !u!4 &752799893 Transform: m_ObjectHideFlags: 2 @@ -1334,14 +1297,14 @@ MonoBehaviour: presetTarget: 4 enumSearch: 8 password: password - var13: {fileID: 0} + bigNumber: 12345678 + currency: 20.41 clampedValue: 4.699999809265137 - sceneReference: {fileID: 0} + notNullReference: {fileID: 0} childReference: {fileID: 0} + sceneReference: {fileID: 0} prefabReference: {fileID: 0} notPrefabReference: {fileID: 0} - bigNumber: 12345678 - currency: 20.41 --- !u!4 &959025299 Transform: m_ObjectHideFlags: 2 @@ -1839,6 +1802,8 @@ MonoBehaviour: typeReference: UnityEngine.BoxCollider, UnityEngine.PhysicsModule type5: typeReference: UnityEngine.TerrainCollider, UnityEngine.TerrainPhysicsModule + type6: + typeReference: SampleBehaviour5+ClassWithInterface2`1, Assembly-CSharp scene1: sceneReference: {fileID: 102900000, guid: f11034f4657f51a47aac14f26410c500, type: 3} sceneName: SampleScene @@ -1850,11 +1815,7 @@ MonoBehaviour: scenePath: Assets/Examples/Scenes/SampleScene.unity buildIndex: 0 dictionary: - pairs: - - key: 0 - value: {fileID: 2037155952} - - key: 1 - value: {fileID: 1972418676} + pairs: [] error: 0 date: ticks: 637820719200000000 diff --git a/Assets/Examples/Scenes/SampleSceneSettings.lighting b/Assets/Examples/Scenes/SampleSceneSettings.lighting index 83d93342..0f7d437c 100644 --- a/Assets/Examples/Scenes/SampleSceneSettings.lighting +++ b/Assets/Examples/Scenes/SampleSceneSettings.lighting @@ -7,7 +7,7 @@ LightingSettings: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: SampleSceneSettings - serializedVersion: 3 + serializedVersion: 4 m_GIWorkflowMode: 1 m_EnableBakedLightmaps: 1 m_EnableRealtimeLightmaps: 0 @@ -20,7 +20,7 @@ LightingSettings: m_LightmapMaxSize: 512 m_BakeResolution: 10 m_Padding: 2 - m_TextureCompression: 1 + m_LightmapCompression: 3 m_AO: 0 m_AOMaxDistance: 1 m_CompAOExponent: 1 @@ -61,3 +61,4 @@ LightingSettings: m_PVRFilteringAtrousPositionSigmaDirect: 0.5 m_PVRFilteringAtrousPositionSigmaIndirect: 2 m_PVRFilteringAtrousPositionSigmaAO: 1 + m_PVRTiledBaking: 0 diff --git a/Assets/Examples/Scripts/SampleBehaviour5.cs b/Assets/Examples/Scripts/SampleBehaviour5.cs index e971dea6..a8490bfa 100644 --- a/Assets/Examples/Scripts/SampleBehaviour5.cs +++ b/Assets/Examples/Scripts/SampleBehaviour5.cs @@ -17,7 +17,7 @@ public class SampleBehaviour5 : MonoBehaviour public SerializedType type4; [TypeConstraint(typeof(Collider), AllowAbstract = true, AllowObsolete = false, TypeSettings = TypeSettings.Class, TypeGrouping = TypeGrouping.ByFlatName)] public SerializedType type5; - [TypeConstraint(typeof(ISampleGenericInterface<>), AllowAbstract = false, AllowObsolete = false, TypeSettings = TypeSettings.Class, TypeGrouping = TypeGrouping.ByFlatName)] + [TypeConstraint(typeof(ISampleGenericInterface), AllowAbstract = false, AllowObsolete = false, TypeSettings = TypeSettings.Class, TypeGrouping = TypeGrouping.ByFlatName)] public SerializedType type6; public interface ISampleGenericInterface { } diff --git a/Assets/Examples/Scripts/SampleBehaviour6.cs b/Assets/Examples/Scripts/SampleBehaviour6.cs index 550b28e1..02cb0077 100644 --- a/Assets/Examples/Scripts/SampleBehaviour6.cs +++ b/Assets/Examples/Scripts/SampleBehaviour6.cs @@ -32,7 +32,10 @@ public class SampleBehaviour6 : MonoBehaviour public interface ISampleInterface { } - [Serializable, MovedFrom(false, null, null, "SampleBehaviour6/Struct")] + [Serializable] +#if UNITY_2019_3_OR_NEWER + [MovedFrom(false, null, null, "SampleBehaviour6/Struct")] +#endif public struct SampleStruct : ISampleInterface { public bool var1; @@ -85,7 +88,7 @@ public class ClassWithInterface4 : ClassWithInterface2 public int var33; } - #endregion +#endregion #region Generic Types From 9f2520d7e56edc423a741c29c286515c6c339cf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Wed, 28 Aug 2024 16:05:47 +0200 Subject: [PATCH 12/23] Minor refactor changes --- Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs b/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs index 343b1147..e8f0c101 100644 --- a/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs +++ b/Assets/Editor Toolbox/Editor/Utilities/TypeUtility.cs @@ -164,14 +164,14 @@ public static List FindTypes(TypeConstraintContext constraint) { List typesList; var parentType = constraint.TargetType; - //NOTE: if parent type is generic and has non-generic arguments then we can try to create derived generic types with the same generic constraints + //NOTE: if parent type is generic and has non-generic arguments then we can try to create derived generic types with the same constraints if (CanBeSourceForGenericTypes(parentType)) { var parentGenericType = parentType.GetGenericTypeDefinition(); var parentGenericArgs = parentGenericType.GetGenericArguments(); typesList = GetDerivedTypes(parentGenericType, (sourceType) => { - var targetType = sourceType; + Type targetType; //NOTE: type is a generic definition, it means we can check if constraints are matched if (sourceType.IsGenericTypeDefinition) { @@ -187,10 +187,14 @@ public static List FindTypes(TypeConstraintContext constraint) } catch (ArgumentException) { - //NOTE: that's the easiest way to check if all generic constraints are ok + //NOTE: unfortunately, this is the easiest way to check if all generic constraints are ok return null; } } + else + { + targetType = sourceType; + } //NOTE: we need to check inheritance since all processed types are derived from the generic type definition if (!IsTypeAssignableFrom(parentType, targetType)) From accfc4cfe06d32d57b444b260276bffbb60ad8fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Wed, 28 Aug 2024 16:12:13 +0200 Subject: [PATCH 13/23] Update upm-dev workflow --- .github/workflows/upm-dev.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/upm-dev.yml b/.github/workflows/upm-dev.yml index 8e3b9997..9864c383 100644 --- a/.github/workflows/upm-dev.yml +++ b/.github/workflows/upm-dev.yml @@ -13,6 +13,7 @@ jobs: fetch-depth: 0 - name: split upm branch run: | + git pull git subtree split -P "$PKG_ROOT" -b upm-dev git push -u origin upm-dev env: From b24ee968b05b9d4fb3ad735dd199ff4bd40e7ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Wed, 28 Aug 2024 16:29:59 +0200 Subject: [PATCH 14/23] no message --- .github/workflows/upm-dev.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/upm-dev.yml b/.github/workflows/upm-dev.yml index 9864c383..8e3b9997 100644 --- a/.github/workflows/upm-dev.yml +++ b/.github/workflows/upm-dev.yml @@ -13,7 +13,6 @@ jobs: fetch-depth: 0 - name: split upm branch run: | - git pull git subtree split -P "$PKG_ROOT" -b upm-dev git push -u origin upm-dev env: From eab215dfc8c63d21d6a0e4f7e863e74717cec5f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Wed, 28 Aug 2024 17:39:22 +0200 Subject: [PATCH 15/23] Update README.md --- Docs/serializereferencegenerics.png | Bin 0 -> 17668 bytes Docs/serializereferenceoperations.png | Bin 0 -> 14243 bytes README.md | 35 ++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 Docs/serializereferencegenerics.png create mode 100644 Docs/serializereferenceoperations.png diff --git a/Docs/serializereferencegenerics.png b/Docs/serializereferencegenerics.png new file mode 100644 index 0000000000000000000000000000000000000000..c6d19fe8ef35a66b1aa93ff5c8ebaa22d94d53c5 GIT binary patch literal 17668 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 S;G0X%XsPL|zEZgx{{I2bF0lRp literal 0 HcmV?d00001 diff --git a/Docs/serializereferenceoperations.png b/Docs/serializereferenceoperations.png new file mode 100644 index 0000000000000000000000000000000000000000..b23663f85037aca27bc637e2014cb44ce8a6b95c GIT binary patch literal 14243 zcmb7rby!x>x+mS;h{T7aG)Q-sbV_$O0!nwPbO=g!cb9}nDBT^>-OVh{Id`6OX6}8S znLh+Ker(rXYrVgE*N#wDltxE+fdT~ug)S>2p$Y{BeGdMQl~2SkYfIt{@rH;iK(gEz|_d2+|&C*K}%*2i$gS6*8t7f* zYUHNpY!XV|N5~SJ=sN}J~R9#4m$E8)gzo_t2kdsS&V?9=FKFF-sNbzcD zWurfSXJ=>3wC58s$Dx|6f`ZTAL@j26R=QVug*9};`-?3e6NM_4f4;>&B2=05MxLzq zDSc)Cd(g0)B+4grw_o#>!}1FW_hA4c*-WEz4$^tm90d!DV|OTe*JmYKYHIVd&EH*K zhYP$P1_uUe^EEUykjMKM-9}fXqsbD<2y6G3Doy(^^a$~fg`)VC^MoIEl(w70$UF;M zTlGTYlA;3|9T%JNvtJ2Hl^V3&e&$|^Axp#*x?Tw(G>9QP@=v&5Cx7yTE;2rpxuoeXm!W-S&d7#+8HxeeXX!JwDXsXL)W*@hs>Q z224&)j;#kKEs~(1qMj5PQ`Or}DEkJ$e_xSVs_rqj`@5TJ`pL^LmNQ_nd9^6DDst8{GTBAf0BDimu@{N7Mg!qlsNDM?=>Jw3b(&~D& zFhRf}j^D$@bhh^bgtDhDePlK}n-Uu}-RE)^%mXyMjR`G^G{M`00>$rQNUxuUIEKTu z{ZAoZvL*RF4!;TeJw86%8G4`e?(f^F=$5+a)Y*h2fNOZwt^gryR0=90e)s+5r$>(k z6-89+>Eggw(qB5cq%SY_rb$ALx@PL_)4~HsammRm+WevVE~X7DIMJJ1y{;VYdtb;< zIUO(uSj}k}`qWvCW*21mzIX@{DcCP34`>%ZJv(C?UuoVJmmua+NbnEMgtMn;A&5FJ z(`^X-y;P!A0qXGAFPRrd&_O5lXb1=iFjw3TqSKSN8d~}xEpTG5T8S{7mfw#nIGI}C zfO#~{{gIDF?5q~)g^lp%M-bxVOBA9!OyPT{<#wNn)>An&$PhIYGn$Nc zPaAmIgPA;RzjL4!{VM3iC9(UH#IXkvg)}+Kowdt2#=!MAXP0dXQQhs9@Kc2K3fR@! zj;r0ArIr#Ba0HZ;^6%aeqYW|ZH)ndLZmf#;!Lhn*{PMZGeAwjf2;kc@{c-wtP;zA~ zPaa|b%D0=3oskiZaA0WY8@Ho@l@(nv^p9ug*!-QAl_m3Zmhq&w*`QtCeruC5BSZ7x z(2N&=OY;^96O)|N2G1h-YT0j@6Yh#uh(-@)Cu_5jax?L${SIU4V7_6!ee!iQaWeqA z>nLO?yu%57B)o7;)ZY@{0l4{dBEo#HZt;b?#b{cKWRNhKfeTf@rOwP?d*}?7la(EX z`5r0h%K9~;A1B0!OtQ*GXHD8}x%~jsFJ#J^gZl&B92*ZlQ5>66Ym{#gNxg z8|?xSEKvy&Y~wJiUe-~^buWw4p77OzYq%uEp($et+r~MnD-tn5kdsl&^9rS~N_k_zWk*=8wI0t@qhxzq#_PIyf12D8tljDJ^l-K8xmV_~ z;EYJ4*wcj)dTea&bJTW4`PtXH&T^RS7j8bZ)l^QjP$WZALPB^UK+#uNFM{8IAw-Au zG!nD3v#+hKZT|W0b-E!tG#+}<^9@}di;HtXTO-pG0)aT88o?P6_}!oMsqol%^;0LW zY{oh>clwKPD#N^pvN0+On_3n6QK#&i#%0fCH{72`Rt+(oK9FK1|^#iPj`M6oc}uleE&SZdHaUd$iqndl_hZvXL1wIB+(v6A|dad zO5^T4X?O!Txo8rBh!&{gDuD0>_PD=LLh~x6E78ITF%~SfdAo3aeCX8AW-@YCGx?2# z?Aqo?A+D{^z1#Qwbx>f0JWCs%AnX~g#e}Y78~nI#u<1*aMnE(e>*(wd82g;G|F= zFXI&)Dn_@b$sED3Kvfr(EjIf0`bd_zisfnu_O3B56hW;OOMcihfT_Bj{pMbFo7UH^ z3ok0sZEy$|>orm;KX~?|72lOjI|2mK^`y#QEcQwr#4E$zvK}qfaHYDLosSsLRlNJ$q1it#Kj$w z@hHEWgyvbncfg!rI&91{QqV5b+|k+rEUd0R0Z{A~Y&6rA)po*FR`JK{K4Hc0eE3(9 zTyxIJ4fgYzjo&-5JOLnA35~D}1;NS0RXSy1E5`tQErhgI+8d83q`pBOB(+b}r`4{v zCHh0Tq( z>_mm34U1gZ_a$V6!oHv}KOZ6A-^q5xLY!J9_1OJj4qvmtDJTFIv5T2Nml~#OI%^r( zS!;5(#@mLeyRs&Q?nXQd?x$ z;ah2AEE}dJrHvqM@#yCS0tMFQ6!9MSTLq9CubTQGi;IKvdAl` z#F8no3`%2sPvbN22ncpPZs1eseLkM(4Ich;uJFCAt&6rT-=pTw@9x@o^qO3R{u%D? z7gZ{5ipYS$wVbQHI~o37wjW&8Xlk_bB_b+{gw@Euh2G?Rdz9Sg92+5JCLTI5F_8!X zkR)e$*}<=t^{g;5oC?boq4`>C+zpXnL`*Ev89hvaV<^7k+r5guxAYc0v9F{}QmCn@ z7To9U%P*7p`8*EM*aFi{%0mu&`uYZu+;pL&i1}VJc<7<(qc`EH05KavA8GuQfKt8( zwiDUz$F1)kNy*8!+@T0&@Tdtuj(r9jYON=N!}8CkFJGjt7n)qv)YL|iM?At4WJ)bp zyFyqCN9k%Y_I~yBNEA+HJf72@v_h|aX|x+hzUO(Jw3AUp-4S| z-(+6`F>VsCcM{{C$S(eeI*XA8Ndeh1MOKd2y@s?co%$16@bB)IV|5p2zg;ND658QLIUzIap*zkG zLm#!QnBFpAF?~oNHOgCSF4*Vac4BPE3&XFT2zu1r-_!t&-Ev=*38d?DXy$))5XGfd%hs${&-t;Ov?xm3+LSw}m3@3T! z&yEFGOa{v2F`XY09AgodvXF~^E#S4%+^gV}Umw%6=JqqMiuQxC zTmy2C(IzeOL&4|b{i}X*s7D|K_gdE^uPuH1wnAKNPy_C;JM)7>T~?nc{BDYdS6l;j zee0x;JUN{r$g=T%0$!^)huNav(o9O^-z z3EV?p`)`XE_bk5rc8sR6Ai(|yo(QWDK~BU}1wB2h*bQm76MQZbe6CoV_-%%e{%ug4 z{KwGZI|V51k?ghGM2xYM>+^Kpr!_5h&ix=R0eN z{|i6B%)#QM@Gz~QO^OB~JS;ywkPk8Ven?K6RUMit>?r;%mR9ihat-92izLKW)_E06j}RhFeDgK;kYm{nmGCQy zS5g7of_C9TUTs1w-T4tXnJaVR7|InUvV&b6f0WU=^m-TZ-Z&@wipdw1cML8!Yu;d9-+XXf>Y!f(zE1{AfkacUWdV0VyWLlwGR<7$x4fho3~Gc zOrC#~J~A>A9v%(=Tc$&F2Ldb1by~X|D{MNuRAoRDQ zIc+f36LcWjyQwE9+`@*x20A(~h>7V1!Ogrkdm?ZxhttcP1>h!0fh1!c)9(oP-5!BF zuoS8-AVYF_1GE7LPubLY-b6ibshU~4>%BL`JQ4gJT1b%Guf%-s3zG*hV#d-8+1R8P zrpt5-NF69<+I{YdHA-^Bu*AZ>1fI;604+>c7(Oj|9a&p)eNbd!m0ke0^zO*-N!L?- z34mu|A>9rH44=Zr#wK4W!$423)phGnky?T06Gk)d+G9<|!+uu?Dn34bm)HIbTch+R zjYWk>K#z-vE5FpRW)3GMp|*aw}vvQ>owL z-gbXF2xRrdeObfO3xN+#R#sLP78c+UVpr;>4d(01zMQopL#PV3#|wsEMGL?nCb%9g zwE-J~zv^a^+PLg}_8YKM><3TOL?9Hm?*NbIzy0d+n{#>rJUmc9MX8#+Y(|?yU%40G zksA;A=hoH^c`>@evOA8%!X5F4pmfCVq;^u(hfQUVEew1 zlCYbFBlW4D_24RX`ug4O6x0XFr z`3^#GE2yd4XL0xgk-QU!P?*Hfz@Yv8&KMA>_;U}(-I!5kiVLp8g2Td3_bF_qOFmbN zU0q_tV53U>{c4$BR9^n)*RL4gBUZHq$HvuAC7~O$@q7gnC4`qk-i=xn20@6Jq2DnU z2?IRapC0d8TLpRmqv&}Z)V04PQ$m6S^bs0*SA95H1NFUB4zu@8Y9i$88W|bc<9Nnn zt#}wlo7WWqWMr?hva+_e7Q`sq!Jh6lxPo4n0$>9GelwbOoUgZEXmn-|#1accupgXD zgouak&o>-_#N(r`Iapn!^B991dSBnn;^N}6$nzGb-HD>q)E7f2fD|C2;xaNaSBHyW zJ@|35Cn{h;&8S=bA_=s=O;_`fmJ zm1;%;Q5J6dVbk6j$iYq!zx8~bXMg@jWl%*_Q2*ovF=yJ~7^vViMI;C`Qtx*xF&L~! zKoW2i-otHQd7amKfTV1@VP}H``^Ut@0O9GjKcjMcz!SmI+r}GEy)GUZ83{s`c+p_2 zwb-+*VR9ZPD5kB+8gO9tlR;yyfrII*^tS?{X?@pq0_4e^`r^CYuG(pqi2(HHZfL$o&|ZnUly~ zVKLYMpq%hn_93i^`s9@LCtCniT}H?KUlw5JlOJzuT>cJ#?ei?vTsMdMfe1D1N5cOA z0<#|^4vo-SO@RNO?zeGw9fU!b{%2}-(z5(;_#e5Mx9b0#n`uX-q+kaQ2%imc zP!eQ%d*}au#%5R4@<}{Q5_%;lz{v$R5zp2sP0_>QhUR;+3azcL*Ii++G=lZ0%NI>% zYguQR5}^#R^+1*wZ@=9wk&Ge`d^jK9CWqrQ_jmy6CN3ibllQ0FXjnMAT`Cc_9w- zDyy~iWkBOaRs@l-QwKn}^cs*b6TYZ=zoVKpEn}#o6B!BW?Md~FoNAr2NvY~$y^0{rl zJM1nn)gBHHM`DzaNCNdpl%n7KUi9Kke>Yw@vJpVcXMXefzdOZxsJ>2*C|fOxnZg6ktteWEc_oD9G5Y6rvEEJV^}f(Nhcgi zPgsaW_8&xym;UvXBlInM(wRpw4CRetRG|t+&+`A4cw9+RQc_MXl3-h%5dpiEGU*NB ze1qd%H@OAhgLvkr%Ty_B4>Z`L*pCZARVWM=0G`ST3N4K$o{{Di3J0779HjBW(D%k% z1}zkhSr8y!cNnJWvFSES(4aoS5Zo`Ah+y;2onXpDa*wq*%Aq%q13+$oYkt)HRr4u1qxdzn+rrQRPG?5#izaYhk9@aVliD!d`k2ogKS0Lo@+XMQ+xsQ}} z4GWclsOzf4@L?BdBFPtTVJQh`YAi7~kjJ6kpmMz^FD!HW8BHE7@`l_Rh#4}>h?6Wc zGqaxFUSsxW)dR{IeGhpMgz{6BMXNuHVJ62j@FNltH7%lrA9+xu?OB>Oa4@f6H}%zF zsWYnzrGR16@tD-mTGgTJP)Oq<;j$Cq4Z|Saoh(TnT1V(E267S)UG(NTL_CfVf2l7X zgNB19+M^GR3!$Mwa6x9FBFT;*k!3P~=9|xv#=P&fhpMpkh%kdm2#v=1+a3N>FlcJ0 zrsWQ)7DJR&!o=GtR6!gWs)q5kKmUFGyhAtsBEEd;_tkD`G!ia7PxTea%<~TlIjzNP zp66CO?3ji4W`vuK{V9XkZwbpdxls++5B(8e{!1>;8-Ze}8{A4C!M%857Lg%BDE@5`6lIM^OrC%~asT)_ZPWR24QM z1tVBTLqiX}d27wO6+#$FYoU-EKtdYmZv0Jrko9b}!g$U1;np}dS08Va_ZIFsfqOUs zgBJf=)djdOKI^sB%0FYc-t!2oQpw3z|P=FikB;Ht(daLCCqb4YAeS3`KRrD+tug`d0FWI_JEoyf z99A-4Fa=w)^gIM%3ehn#28$x1zM!f9L=${1sO_${AgYmgdd)O>DzN5&g5^=j zJJrEDQ3w(B#lz^xBd%3*>&E08ZT zts-8C#P9cKoFDIR0BOhiUM!M~$4UbGo`Jn0{1V}zcY%WO>gR~b^mj_J@aPejt55>F zrZkw|yiS9IenH|3^;(|_g}**W#q|8u{3WtXFBcyI!!c-2 zhhB(TeJ%c57IkIlD+g$|5i;wogn9*KHKs*U?z80)Ys3i*&dp^=oPVDw#mSq9W0bd$ zTaU=S!r52wq1(=dgl`q9yBlUUrpZV;$mQ2%zNR&}Wg0CiN}U(TR^y0^LY=<-Y;vpX zg9Pzkb0EXFMU9HbMVr)X(1@q8|2Ub;6t`OJTtZdd=V^WVI$~^0IW%>+q@-{n9}l_C zMMSkdkB0++t?8m7I!-QoBUp*yw?WLqSnU?FwfeQlB<;)eGm&~##*ceyIeCWSqdZZS z+p#qHtW|Ik>Z?(|Rln&NN$T{Z!WrMZnmfd!pzw-`)6ojmsa9ahA=6TUF<1G8rG2#l9D56xP{q{WG`c#V$T6>E{lh2&a83QvClZx>xpRYZPz)G?>5myv-I-bz@uW z^T|_L#R2!r^*N)iyMv^pLp_u8r>Mhz#1xIxxGBto*HA8YeQL%RrI<8Cy<~{g@2V)n zu}s)mwR5twDGtYu5F%S5=#&V~;@{s*;5RinNn_UP>}O+s9h$!Ud!PhyOS?#+U<{E@ z!qY*ko#0q9lvF_O*EHSB^t~veWBNjxo2yn%9f$eLn;zp0%3E8`qv$Hc02{81KUiFzq3)XwzxTN<;$P5OqVN`jphP0lZsx|_p^2S~# zvSb48kL=sZ1<;w+X{$yhVA4sjEdZGU=r+%`cpQPS8AKe+4}FU*jQ!<~4qH?~yFp+#5P{+X9&LZ2iG#@l47zp!UPGhrg!^BRnZ$oS z=VeCrisJjj?M2i-5^)h9^EWg!`K_(qAV+?-xJ)R&n)%JI5S};%*ytBQmsiW+qdD*v zW--|Dv`V25%-SvPWoUKUeD3=^U~)khP(~OyQ(WlBZev0ggAG^>F&%=1q?1sB`}$As z-t2O#UmY#8=m%qEU?1_RE$nUF-<&@+zs` z_Q7Ly8)_fEv|3uB`m@gt&Y6h((|P~9xmI;_#zaSNb6O2N#{v!iC7C`p%0Us=>IgYf|(Omw`imRp_cd+>BS=@clQlP58(7R1Ez0l+APs@&-ntwL0OXMF+b* z>qaev^9Wg#+1EM^>mkn+Q)<{}w!(#q@O#oqINgU#fm=G*g)ZVsOI=QI+S^}hZkz{zb z4MI^<+d~H?O&r;&Tgag(`3?*G`{n8h1W_0Maq@6G;bc~IJo(d|d7Se)S>=fBQiQ4v zu1Soe1W-#WS#pO~A_QXLukbuvM;X`mMX6JJiw-qui+9bmMM}nZvX7ZJ+#@ zBO__sGM=N^py3jo{O%l`Hn-?qo96|tyF~c8z==fA)$$b}xL$a;f$iJQs|BB~uxZCA zoo)WP!mCuc!-N>A+`QH;40w-*;iV40C+GE_vPwSwU&sYL)jjt?YWUYu`0nd@W0;`{ zdweGD71;84QT@w)ls&OY*VHuHd)NHnaM-Fn0k{}ro!}leMZxXWWd<2_=-QHA&z5=} zBPOi7)18RTrg>QddNDsl zBnEj^Cu&VEbqF4BscFQ**?do_X+~7P;7LA-%#Lb3A4I!C24XUQU3hIN+c+5;bZo?& zxv@Xihjgw(-plMfK-|)mnXMlkDf!+=FfG-h;EJUJl5VomKyu5 z^jii5b|~kvU^#6Uk%HF`%Y+7ODX|+#m*Ftu>o1;m2A<99&V|8PFraipA6d~Z2=Q&X zdCz$yet5bGj4q2yWgVDiPmagFanssgu6<*MlV|PF`%1-IuBncCYS7BPJTA3K27yv0 zs)A{ZRldA5CKV0x1)Vnd8lkrhnN?uWa0L(l;6rvt*r(L`lA7?K0|Psf1j}WGBDcP+ z!oQi`f1&sHnUiRpTKZK}Gv!0) zc1RSFPVhnXWs`~7cqes4hS9CCX^y*R9jeOUpBL=xER4Mm3n<0;wwTp+ERYLu&b zw9VsJT@4d z+P&#xYeFa?L}n9McSN3Xs0j(Td_)BB$pZ4Sji-$C%$5v0sMs^&0$MX82lfO$6v#FM z0|Vg14x%XqJ3Efwb6Xb&hjKl9`dI$0(5k`0s$zAa3&TP^W1GVc{%`#RC;r~K(E`b?f%cE0YSEXp4F^SqY405NkD>~` zMq%>Eu-ZX@Fa67jjKNP6{D!}FK_Nh&poeZbz{Mv)4hb2K?(m0f$m!LJg{u6Xe0L~=uit{U!%6b8GADdwi_&rW ztDg6Chu~>m{r9=^zu)CQD~g-+BIZ@V`s`S{Y64Bv#U`3{9>F1Vbl?P?lJ$a$F7iqd z8D&K(NW zCraE|{6fE%ijJx;d+}gRI+8UF-64%?Y+9T(Q{lkqmv3Jb6*%{RlR=nl$x64lm-&9Sumaw;wsQx@5k%YQA}QNhTI;+FjO$$@p$50!~in+t;<) zesJ{eSHXs?yf{&7-Ayk-L}1N#rtxhXOQm(aYHUf{Q&ZeNBzO;*Xp{I;rrxh?moGjP z7dYEFl$X|)W9sd0C{QCKYl4|Gu`46U>!l-T6O&D1k{vGrRU@DN!b;^mKOg5SUcb)? z^mLXkp}tD5gbIqOs#v88%;@S_RSsjctIe}|>qY6R-A|xm)TreCG!(cXIZ7DVO{Af4$IdyT%()oeba6u~z(_f)>nr=KdXk-fPTXMweU^sp}kF#*H zcx{Fc7h>426M>Z>`7{!_V3!skQzB8YIk{VWI;6U0RJ!Ni&ydk07HysaT{p&DSYnp< zLQW&E;mdh@k7wo&Vq|1*u%y|CB}g?o%CTvv9_Jz@z2!e+4!rFR+Z&zAUVmx+?fDif zsf$`3h3U_nL4qxzDs^4;Lk@xNm3#0dm1aL}pq_Jr`;nZKZP^;V{}#BfO(AZ9I6Dgm z4o<1^f`a5MkygC|6@3z0q|whUtAGKnDw^zn8JlAI63VYPH=1FjNFmn&c_yf03T21p z481xVKZEZqBel`OCFt`sxszH>m$Kn&;v!EaI$Po-M(lN}IpS^NLL`IVtLIr zSyO+z_3VDF1D&b?1xfb`ohsC^<(M^Ohy{2syyoZ^K9fI&?U#yLv|b9muaq|9UOg1D zQ73ixif8@sOCt#uaj{;dgc*`cY{ltw`+f&axiWKau8!d)ILS@fBOxXxmMgy+W8Xc! zI{mp(VBrV);C+!67v0MpV$09!pO1S7mvEp3?Ul-A%y};^xV%b*R27&a(0EU$(saec zBFCuzL^u~E*1wuJ`1p4|-5El%RaUAV-=Z#3k`_m1-PJH3H9FQ<659T`g}Yt#M5=4&dWvYvg(>#|WZEVKvGI?(1mX#g(l z3+(3)@W8SxM0oxEndq4Q;&m{~*o%U(vtJBH3^sQM^T1&kByd5CPRU4I3RGvgSlupI zcV{WKXfZ8$@-BE#G}-?pjCI$CmEk=^69$}94;~L57DadEX~E~jhFsy!pLlxK+E=6B&rwTX>*vqC`TPF z+AEnVkdiml|3Hh5wMHc$P^jOZdCFI^sX)4`rG)Oqf={(Y+q9RHU7LGvrrrSEoA!^C zi+46@5vjUlkyeBEguO6!^&b1Z@&ZZ3^|!dvnS0KBT_5y<>{=f87`%b)i3yr9yyzZU zDqXw34*1d~4rj_$^&@d9>FHMVdh#k%Oqf7)Vhhr!6t^r{jV%=C&~Yp3r?t$e-!cv? zg^6f4g~!wRUdI8x)~5YswYA}%ncMr7UXhTUj-Qzc-S~KF>c>f>r&;QpiT{?(HoZU8rb@6Z*eXNrjqyRm+Q}GX!@& zffP*b^)lUz7{8^%*A>J9p(4FFRKI<-@9!RHr5aqzZgyvN0>+d`S2)^nsJn#- z${GlzvXw{8JbBSmFY^9R4KSU4t}P23HPwMp%idkV)WMA8Xc2M$Ts69ywoB;vW?UQM zx4J0>-5#IpeG|#tLPhd~LtKOSp+0fzJbiD6hKoU8 zgUx=cuZ~vGK>feGz(bBJzZ-TrgRWNXPnx}K@p)H|2^|l6?5l_|f;)WM`M>&Svd5y% zj&JZdt1u?scj68}T@Vmuo;J}3L(_c~GJjY}Z zEV!bcf<0s>VCrYAm$#4r=36o?42^9&`}%#I+kp7HMY|PvbSwFwG$k0~NUv7`y)OA0 zHu~q8+AWeH)XldYa#eZrtA*;^hi)k0J(pYAa?IGduRJp+*DUsO>88m_H`E7? zW3;2U8022&Ew;o}nN&qS(ES5ToDO6$i4()1-Jh*_*t(Q{uEQ4NyKE+?)*plQ+twlk zI4?oOC0TP>jhJYqna~WImWxnPMHR&wqHSv(iKESr-iY(P*}$hnRdQB7K+;O(0cehv z*g}EVk})s7=j^Wxo@4MgpTNqSSGowgvCR9J2qI{`m-^^9N|{zD)OA*Frcz6Jls*eqLP25d=K^KBf8Lz;FYfV{wtyRm5RaVPLZT=(;(<16cCF81SlxoTWbw z0fBojzE-F6$(kg#38m1>0fU76w@|;Y3AnA_9}`!|t|-d3(K9gUwtIgB$LMb__QIa? z?JMIa?iqZ=3fPg4XIiUQhSl zvabKPs)?b%xf+oYAy7bq_#*s`0H<7HGOuys-(!pEAl>7{AHlUZ@;l$2?|??DA2@&{ z4I25bn{Q3M?Gv%qUV-ijI1F(BPGU4TEQ0rsq@5k1L}?EJCG&$9kIc=fA2qeKrY9zT zA&G@AkAR~R;3%ov(UKq~Wj2VS@vacC-mm$B4$k)7zq&cAUGTu?`^so*6QQ}!94X&u mmg$6mH(`+0s0jw2VBLlNwmj1GO~H$GP_mMW66In>f&UAd7M+Ix literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 8b33c2ec..4d874003 100644 --- a/README.md +++ b/README.md @@ -694,6 +694,41 @@ public class ClassWithInterface3 : ClassWithInterfaceBase ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/referencepicker.png) +##### SerializeReference generics support + +```csharp +[SerializeReference, ReferencePicker(TypeGrouping = TypeGrouping.None)] +public IGenericInterface genericString; +[SerializeReference, ReferencePicker(TypeGrouping = TypeGrouping.None)] +public IGenericInterface genericInt; +[SerializeReference, ReferencePicker(TypeGrouping = TypeGrouping.None)] +public IGenericInterface genericBool; + +public interface IGenericInterface +{ + TValue Value { get; } +} + +public class GenericInterfaceImplementation : IGenericInterface +{ + [SerializeField] + private TValue value; + + public TValue Value => value; +} +``` + +![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/serializereferencegenerics.png) + +##### SerializeReference context menu operations + +You can use few custom context menu operations for the SerializeReference-based fields: +- Copy Serialize Reference: creates deep copy of linked reference +- Paste Serialize Reference: allows to paste preserved copy to a fields +- Duplicate Serialize Reference: allows to duplicate linked reference (works only on collection elements) + +![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/serializereferenceoperations.png) + #### Custom Editors If you want to create a custom **UnityEditor.Editor** for your components and still use Toolbox-related features be sure to inherit from the **Toolbox.Editor.ToolboxEditor** class. From e2c6d98206645a25b05c1043dd0bba4cd93b5f60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Wed, 28 Aug 2024 18:36:48 +0200 Subject: [PATCH 16/23] Update: README.md, CHANGELOG.md & samples --- Assets/Editor Toolbox/CHANGELOG.md | 45 +++++++---- Assets/Editor Toolbox/README.md | 83 ++++++++++++++++---- Assets/Editor Toolbox/package.json | 2 +- Assets/Examples/Scenes/SampleScene.unity | 3 + Assets/Examples/Scripts/SampleBehaviour5.cs | 6 +- Docs/serializeddate.png | Bin 0 -> 1744 bytes Docs/serializedirectory.png | Bin 0 -> 5728 bytes README.md | 54 ++++++++----- 8 files changed, 140 insertions(+), 53 deletions(-) create mode 100644 Docs/serializeddate.png create mode 100644 Docs/serializedirectory.png diff --git a/Assets/Editor Toolbox/CHANGELOG.md b/Assets/Editor Toolbox/CHANGELOG.md index 5a5f001c..329401cc 100644 --- a/Assets/Editor Toolbox/CHANGELOG.md +++ b/Assets/Editor Toolbox/CHANGELOG.md @@ -1,5 +1,21 @@ +## 0.13.0 [28.08.2024] + +### Added: +- Warning information if currently serialized type in TypeField-based drawers (SerializedType, [ReferencerPicker]) is not available in the filtered types collection +- Context menu operations for [SerializeReference] properties (Copy, Paste, Duplicate), all operations are based on a deep copy of the source reference +- Basic support for generic references while using [SerializeReference] & [ReferencePicker], can be utilized in Unity 2023+ +- More unit tests (PropertyUtility, filtering generic types) + +### Changed: +- Fix duplicated initialization process forced by the OnValidate call +- Hierarchy: For now 'Script' label displays maximum 5 scripts +- Improved types label generation for TypeField-based drawers (SerializedType, [ReferencerPicker]) + ## 0.12.13 [22.08.2024] +### Added: +- DisableInEditModeAttribute + ### Changed: - Hierarchy: Added Tree List renderer, which improves visual identification of parent and child gameobjects - Hierarchy: For now 'Script' label will display all available components linked to a GameObject/Prefabs @@ -7,20 +23,17 @@ - Fix SceneView settings change events firing when they shouldn't - Fix issue when trying to find private fields/properties from parent classes (e.g. while using conditional attributes) -### Added: -- DisableInEditModeAttribute - ## 0.12.12 [17.06.2024] +### Added: +- NotPrefabObjectOnlyAttribute + ### Changed: - LabelWidthAttribute is now part of the Toolbox decorator attributes (can be mixed with other attributes) - Hierarchy: Script, Tag, and Layer columns are now excluded from the default settings - Possibility to change style for groups ([BeginGroup] and [BeginHorizontalGroup] attributes) - ScriptableObject Creation Wizard now accepts only ScriptableObjects marked with the [CreateInWizard] or [CreateAssetMenu] attributes -### Added: -- NotPrefabObjectOnlyAttribute - ## 0.12.11 [05.04.2024] ### Changed: @@ -53,13 +66,13 @@ ## 0.12.7 [10.12.2023] +### Added: +- 'Revert Prefab Name' option for prefabs in the GameObject/Prefabs context menu + ### Changed: - Possibility to interact with ProgressBarDrawer (added IsInteractable property to the ProgressBarAttribute) - MinMaxAttribute now supports Vector2Int -### Added: -- 'Revert Prefab Name' option for prefabs in the GameObject/Prefabs context menu - ## 0.12.6 [19.10.2023] ### Changed: @@ -68,12 +81,12 @@ ## 0.12.5 [11.09.2023] -### Changed: -- Make ToolboxEditorHandler public - ### Added: - Add public OnCacheRefreshed event to the SceneSerializationUtility +### Changed: +- Make ToolboxEditorHandler public + ## 0.12.4 [31.07.2023] ### Changed: @@ -85,16 +98,16 @@ ## 0.12.3 [17.06.2023] +### Added: +- SceneView extension: better way to select raycasted objects in the Scene view +- LabelWidthAttribute + ### Changed: - Fix updating SerializedScene index after deleting Scene - Fix SerializedScene index calculation - Fix NRE when deleted Scene was still included in Build Settings - Fix compilation errors in Unity 2018.x -### Added: -- SceneView extension: better way to select raycasted objects in the Scene view -- LabelWidthAttribute - ## 0.12.1 [12.04.2023] ### Changed: diff --git a/Assets/Editor Toolbox/README.md b/Assets/Editor Toolbox/README.md index 8b33c2ec..ace6eb49 100644 --- a/Assets/Editor Toolbox/README.md +++ b/Assets/Editor Toolbox/README.md @@ -56,8 +56,8 @@ Unity 2018.x or newer - [Hierarchy](#hierarchy) - [Project](#project) - [Toolbar](#toolbar) - - [Utilities](#utilities) - [SceneView](#sceneview) + - [Utilities](#utilities) ## Settings @@ -655,22 +655,22 @@ To prevent issues after renaming types use `UnityEngine.Scripting.APIUpdating.Mo ```csharp [SerializeReference, ReferencePicker(TypeGrouping = TypeGrouping.ByFlatName)] -public Interface1 var1; +public ISampleInterface var1; [SerializeReference, ReferencePicker(ForceUninitializedInstance = true)] -public Interface1 var1; +public ISampleInterface var1; [SerializeReference, ReferencePicker(ParentType = typeof(ClassWithInterface2)] public ClassWithInterfaceBase var2; -public interface Interface1 { } +public interface ISampleInterface { } [Serializable] -public struct Struct : Interface1 +public struct Struct : ISampleInterface { public bool var1; public bool var2; } -public abstract class ClassWithInterfaceBase : Interface1 { } +public abstract class ClassWithInterfaceBase : ISampleInterface { } [Serializable] public class ClassWithInterface1 : ClassWithInterfaceBase @@ -694,6 +694,47 @@ public class ClassWithInterface3 : ClassWithInterfaceBase ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/referencepicker.png) +##### SerializeReference generics support + +Unity 2023.x introduced support for serializing generic references. +In this case you can serialize generic types or use generics as a base class for your references. +**ReferencePicker** will automatically create all available generic types if the generic definition satisfies the constraints. + +```csharp +#if UNITY_2023_2_OR_NEWER +[SerializeReference, ReferencePicker(TypeGrouping = TypeGrouping.None)] +public IGenericInterface genericString; +[SerializeReference, ReferencePicker(TypeGrouping = TypeGrouping.None)] +public IGenericInterface genericInt; +[SerializeReference, ReferencePicker(TypeGrouping = TypeGrouping.None)] +public IGenericInterface genericBool; + +public interface IGenericInterface +{ + TValue Value { get; } +} + +public class GenericInterfaceImplementation : IGenericInterface +{ + [SerializeField] + private TValue value; + + public TValue Value => value; +} +#endif +``` + +![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/serializereferencegenerics.png) + +##### SerializeReference context menu operations + +You can use few custom context menu operations for the SerializeReference-based fields: +- **Copy Serialize Reference**: creates a deep copy of the linked reference +- **Paste Serialize Reference**: allows to paste preserved copy to a field +- **Duplicate Serialize Reference**: allows to duplicate the linked reference (works only on collection elements) + +![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/serializereferenceoperations.png) + #### Custom Editors If you want to create a custom **UnityEditor.Editor** for your components and still use Toolbox-related features be sure to inherit from the **Toolbox.Editor.ToolboxEditor** class. @@ -727,9 +768,9 @@ public class SampleEditor : ToolboxEditor } ``` -##### Custom Editor Implementation -- **Toolbox.Editor.ToolboxEditor** - default class, override it if you want to implement a custom Editor for your components and ScriptableObjects -- **Toolbox.Editor.ToolboxScriptedImporterEditor** - override it if you want to implement a custom Editor for your custom importers +##### Custom Editor Implementations +- **Toolbox.Editor.ToolboxEditor**: default class, override it if you want to implement a custom Editor for your components and ScriptableObjects +- **Toolbox.Editor.ToolboxScriptedImporterEditor**: override it if you want to implement a custom Editor for your custom importers ### Material Drawers @@ -832,10 +873,14 @@ public void Usage() Allows to serialize DateTime. +![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/serializeddate.png) + #### SerializedDirectory Allows to serialize folders in form of assets and retrieve direct paths in runtime. +![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/serializeddirectory.png) + ## Editor Extensions ### Hierarchy @@ -916,12 +961,24 @@ public static class MyEditorUtility ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/toolbar.png) +### SceneView + +Select a specific object that is under the cursor (default key: tab). + +![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/sceneview.png) + ### Utilities +In this section you will find various extensions that don't fit into a specific category. + +#### Context Menu operations + Copy and paste all components from/to particular GameObject. ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/utils.png) +#### ScriptableObject Creation Wizard + Create multiple ScriptableObjects at once. Wizard will allow only ScritpableObjects marked with **[Toolbox.Attributes.CreateInWizard]** or **[UnityEngine.CreateAssetMenu]** attributes. @@ -929,10 +986,4 @@ Wizard will allow only ScritpableObjects marked with **[Toolbox.Attributes.Creat Assets/Create/Editor Toolbox/ScriptableObject Creation Wizard ``` -![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/createso.png) - -### SceneView - -Select a specific object that is under the cursor (default key: tab). - -![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/sceneview.png) \ No newline at end of file +![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/createso.png) \ No newline at end of file diff --git a/Assets/Editor Toolbox/package.json b/Assets/Editor Toolbox/package.json index b9f68449..3eb4de61 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.12.13", + "version": "0.13.0", "unity": "2018.1", "description": "Tools, custom attributes, drawers, hierarchy overlay, and other extensions for the Unity Editor.", "keywords": [ diff --git a/Assets/Examples/Scenes/SampleScene.unity b/Assets/Examples/Scenes/SampleScene.unity index 3c618426..04c636db 100644 --- a/Assets/Examples/Scenes/SampleScene.unity +++ b/Assets/Examples/Scenes/SampleScene.unity @@ -1819,6 +1819,9 @@ MonoBehaviour: error: 0 date: ticks: 637820719200000000 + directory: + directoryAsset: {fileID: 102900000, guid: 6c5a542f2ff6e87499c1a85957eafd9e, type: 3} + path: Assets/Editor Toolbox --- !u!1 &1221313406 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Examples/Scripts/SampleBehaviour5.cs b/Assets/Examples/Scripts/SampleBehaviour5.cs index a8490bfa..7d1bda23 100644 --- a/Assets/Examples/Scripts/SampleBehaviour5.cs +++ b/Assets/Examples/Scripts/SampleBehaviour5.cs @@ -17,7 +17,7 @@ public class SampleBehaviour5 : MonoBehaviour public SerializedType type4; [TypeConstraint(typeof(Collider), AllowAbstract = true, AllowObsolete = false, TypeSettings = TypeSettings.Class, TypeGrouping = TypeGrouping.ByFlatName)] public SerializedType type5; - [TypeConstraint(typeof(ISampleGenericInterface), AllowAbstract = false, AllowObsolete = false, TypeSettings = TypeSettings.Class, TypeGrouping = TypeGrouping.ByFlatName)] + [TypeConstraint(typeof(ISampleGenericInterface<>), AllowAbstract = false, AllowObsolete = false, TypeSettings = TypeSettings.Class, TypeGrouping = TypeGrouping.ByFlatName)] public SerializedType type6; public interface ISampleGenericInterface { } @@ -41,4 +41,8 @@ public class ClassWithInterface3 : ISampleGenericInterface { } [Label("Serialized DateTime", skinStyle: SkinStyle.Box)] public SerializedDateTime date; + + [Label("Serialized Directory", skinStyle: SkinStyle.Box)] + + public SerializedDirectory directory; } \ No newline at end of file diff --git a/Docs/serializeddate.png b/Docs/serializeddate.png new file mode 100644 index 0000000000000000000000000000000000000000..5c9be23db307bdffa47dcc9f25205c909d594240 GIT binary patch literal 1744 zcmV;>1~2)EP)000*V0ssI2auX^=00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D24zV^K~#8N?VQ_7 zRa+Fs&ucvtbVN-wljxWk`Jhs$X=+I+k=w2k1WJkzWkQe=(nS+BOz83uMs?gm`e4~b zD)F>S@kSv;ig(%9yXJB~?B(ICJ$_GP4#yaCEt=z7W9=RLw?2kp z7{+$6xHAmH*bo+XW;J;J{JGQV{F7lA3qW(B#YD3$!Q#$Xj!R>1ZtfSuFcyI3qAn9H zr@`XRSk9X_Z@z#3E{-9?FcyFoL!*h7(_nFDEa&y>*Wv&&3}YE+G|_SzEbffuu(&hK zD&QS)-?wjHe0+RDLc+m=2TMvyIyySU9~88=x33t(*cH9FsNh!eVUH3u`%%n4OP~UA3v^Kxw325uDyHrHZ(K{uZ}NYzU1ZQ#l*xo91dIwIaSpR zgAJXM#l^*{s;Z2P46#-hmn=^)-$GSz#f=zW!#m>c=jV6p)-5#TjT<*oQ&Xd&qRh4X z(4j+DuU-`k#>dc$dvS3w#OT9^4-X$c3=R&4u95%j*|QfeT)-(Jpj_l9R9QJWImeG5 z@9*!&^bi&n_V(>t@=Nyb-;dnE!9gT$*|KG3W(H1GHN#*-CowWIg8Am?(WC3vuNN+L zal$agWDB4wXuc8SgLqBcU%q@P7JYrt_jBjYk&QMhDk?g0;>4v(mwI}7;Hj*v+_r67 zQc@BI4J^C5x=Kq+Po6w^@#4kK&Q2|fu`^QK=jP^uf`W#JhiRFgpI=c?L3U0F*-MxEPiW>aY)zxGZ3kwT)v&3{y%ec5WOt`9QhQWqTvO#xu_tU3OaRE}PO)iz5 zSj$sXTTr~Jpvgvz&ti$VqsOA7qha7ghK7db=H_Cq$ICSaD>(7KynFZVQ>RYV)zx7M zKPHaa+FCpS;^X80$!Bbh6!(uGKknSQlWgF0I`NDrJ0>OulY4e{Hl_s3u;e66vLv5B zf8M@*yUC{$6B83SnUj-~o>Y^;Vy$851bU@b6`!A6a>@-Wzvwys!BA1pC+5_+Zf@CFUV-Ea$4K@T@#dz=+UE1 zn>N+e)pc}qJbwImxwzNV)a==_=Pw;NrWC{26)EnMlam1f0rCsO%a<<~6&1n2(Av|} zLr##NpI=s1CKl?fg@uLg?rw5|Cr_T}hgnHUNy&i&2jn-js%nH=Fk$GF=#|>MxMaDw ztF}-T^l&4_r|`14x3{rk3+#b`fzZ%Um&*m)>2yv_ zO{uaV?m{ zbaG^5ByusMQ2=9O^x{4=G!z>f3o*jKepOYK@M`}#1g9k;A|fy_u(q}qp85HC*w3Cl zgRRPHZEeM2Lsm#gh{NHSo}PwNCXSDfuU)%#!-fsWBJSP0hXBKBhQX=|dfb%Su(kak*Um{r#-(3}X>!F0>f`!+0Gumz%N!7I%hW7#qUk m&M*vPLs;AyhGA?+U*F&Tx`@m1frk|U0000j>e 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 genericString; [SerializeReference, ReferencePicker(TypeGrouping = TypeGrouping.None)] @@ -716,6 +721,7 @@ public class GenericInterfaceImplementation : IGenericInterface public TValue Value => value; } +#endif ``` ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/serializereferencegenerics.png) @@ -723,9 +729,9 @@ public class GenericInterfaceImplementation : IGenericInterface ##### SerializeReference context menu operations You can use few custom context menu operations for the SerializeReference-based fields: -- Copy Serialize Reference: creates deep copy of linked reference -- Paste Serialize Reference: allows to paste preserved copy to a fields -- Duplicate Serialize Reference: allows to duplicate linked reference (works only on collection elements) +- **Copy Serialize Reference**: creates a deep copy of the linked reference +- **Paste Serialize Reference**: allows to paste preserved copy to a field +- **Duplicate Serialize Reference**: allows to duplicate the linked reference (works only on collection elements) ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/serializereferenceoperations.png) @@ -762,9 +768,9 @@ public class SampleEditor : ToolboxEditor } ``` -##### Custom Editor Implementation -- **Toolbox.Editor.ToolboxEditor** - default class, override it if you want to implement a custom Editor for your components and ScriptableObjects -- **Toolbox.Editor.ToolboxScriptedImporterEditor** - override it if you want to implement a custom Editor for your custom importers +##### Custom Editor Implementations +- **Toolbox.Editor.ToolboxEditor**: default class, override it if you want to implement a custom Editor for your components and ScriptableObjects +- **Toolbox.Editor.ToolboxScriptedImporterEditor**: override it if you want to implement a custom Editor for your custom importers ### Material Drawers @@ -867,10 +873,14 @@ public void Usage() Allows to serialize DateTime. +![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/serializeddate.png) + #### SerializedDirectory Allows to serialize folders in form of assets and retrieve direct paths in runtime. +![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/serializeddirectory.png) + ## Editor Extensions ### Hierarchy @@ -951,12 +961,24 @@ public static class MyEditorUtility ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/toolbar.png) +### SceneView + +Select a specific object that is under the cursor (default key: tab). + +![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/sceneview.png) + ### Utilities +In this section you will find various extensions that don't fit into a specific category. + +#### Context Menu operations + Copy and paste all components from/to particular GameObject. ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/utils.png) +#### ScriptableObject Creation Wizard + Create multiple ScriptableObjects at once. Wizard will allow only ScritpableObjects marked with **[Toolbox.Attributes.CreateInWizard]** or **[UnityEngine.CreateAssetMenu]** attributes. @@ -964,10 +986,4 @@ Wizard will allow only ScritpableObjects marked with **[Toolbox.Attributes.Creat Assets/Create/Editor Toolbox/ScriptableObject Creation Wizard ``` -![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/createso.png) - -### SceneView - -Select a specific object that is under the cursor (default key: tab). - -![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/sceneview.png) \ No newline at end of file +![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/createso.png) \ No newline at end of file From 4630c9aaacb589f049174bf8f75752bbbddb202c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Wed, 28 Aug 2024 18:53:33 +0200 Subject: [PATCH 17/23] Update: README.md, samples --- Assets/Editor Toolbox/README.md | 38 +++++++++--------- Assets/Examples/Scenes/SampleScene.unity | 3 +- Assets/Examples/Scripts/SampleBehaviour1.cs | 5 +++ Docs/layer.png | Bin 0 -> 6074 bytes ...edirectory.png => serializeddirectory.png} | Bin README.md | 38 +++++++++--------- 6 files changed, 47 insertions(+), 37 deletions(-) create mode 100644 Docs/layer.png rename Docs/{serializedirectory.png => serializeddirectory.png} (100%) diff --git a/Assets/Editor Toolbox/README.md b/Assets/Editor Toolbox/README.md index ace6eb49..01644f4b 100644 --- a/Assets/Editor Toolbox/README.md +++ b/Assets/Editor Toolbox/README.md @@ -242,22 +242,6 @@ public string password; ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/password.png) -#### ChildObjectOnlyAttribute - -Supported types: **GameObject, Component**. - -#### SceneObjectOnlyAttribute - -Supported types: **GameObject, Component**. - -#### PrefabObjectOnlyAttribute - -Supported types: **GameObject, Component**. - -#### NotPrefabObjectOnlyAttribute - -Supported types: **GameObject, Component**. - #### LeftToggleAttribute Supported types: **bool**. @@ -281,9 +265,27 @@ Supported types: **int**. ```csharp [Layer] -public int var1; +public int layer; ``` +![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/layer.png) + +#### ChildObjectOnlyAttribute + +Supported types: **GameObject, Component**. + +#### SceneObjectOnlyAttribute + +Supported types: **GameObject, Component**. + +#### PrefabObjectOnlyAttribute + +Supported types: **GameObject, Component**. + +#### NotPrefabObjectOnlyAttribute + +Supported types: **GameObject, Component**. + --- ### Toolbox Drawers @@ -728,7 +730,7 @@ public class GenericInterfaceImplementation : IGenericInterface ##### SerializeReference context menu operations -You can use few custom context menu operations for the SerializeReference-based fields: +You can use few custom context menu operations for the **[SerializeReference]** fields: - **Copy Serialize Reference**: creates a deep copy of the linked reference - **Paste Serialize Reference**: allows to paste preserved copy to a field - **Duplicate Serialize Reference**: allows to duplicate the linked reference (works only on collection elements) diff --git a/Assets/Examples/Scenes/SampleScene.unity b/Assets/Examples/Scenes/SampleScene.unity index 04c636db..2e16fc9c 100644 --- a/Assets/Examples/Scenes/SampleScene.unity +++ b/Assets/Examples/Scenes/SampleScene.unity @@ -1299,7 +1299,8 @@ MonoBehaviour: password: password bigNumber: 12345678 currency: 20.41 - clampedValue: 4.699999809265137 + layer: 5 + clampedValue: 6 notNullReference: {fileID: 0} childReference: {fileID: 0} sceneReference: {fileID: 0} diff --git a/Assets/Examples/Scripts/SampleBehaviour1.cs b/Assets/Examples/Scripts/SampleBehaviour1.cs index 57eca4e6..830418f4 100644 --- a/Assets/Examples/Scripts/SampleBehaviour1.cs +++ b/Assets/Examples/Scripts/SampleBehaviour1.cs @@ -96,6 +96,11 @@ public enum FlagExample [FormattedNumber("c")] public float currency; + [Label("Layer", skinStyle: SkinStyle.Box)] + + [Layer] + public int layer; + [BeginGroup(Order = -2)] [Help("NotNullAttribute, ClampAttribute, SceneObjectOnlyAttribute, ChildObjectOnlyAttribute, PrefabObjectOnlyAttribute " + diff --git a/Docs/layer.png b/Docs/layer.png new file mode 100644 index 0000000000000000000000000000000000000000..adf09561d1f63c1eb5d53d255dde6b39d85cfb4f GIT binary patch literal 6074 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 bk*LIe+&>gpS{6TVmvOXrIZ(0x)aAbe_xy4Q literal 0 HcmV?d00001 diff --git a/Docs/serializedirectory.png b/Docs/serializeddirectory.png similarity index 100% rename from Docs/serializedirectory.png rename to Docs/serializeddirectory.png diff --git a/README.md b/README.md index ace6eb49..01644f4b 100644 --- a/README.md +++ b/README.md @@ -242,22 +242,6 @@ public string password; ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/password.png) -#### ChildObjectOnlyAttribute - -Supported types: **GameObject, Component**. - -#### SceneObjectOnlyAttribute - -Supported types: **GameObject, Component**. - -#### PrefabObjectOnlyAttribute - -Supported types: **GameObject, Component**. - -#### NotPrefabObjectOnlyAttribute - -Supported types: **GameObject, Component**. - #### LeftToggleAttribute Supported types: **bool**. @@ -281,9 +265,27 @@ Supported types: **int**. ```csharp [Layer] -public int var1; +public int layer; ``` +![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/layer.png) + +#### ChildObjectOnlyAttribute + +Supported types: **GameObject, Component**. + +#### SceneObjectOnlyAttribute + +Supported types: **GameObject, Component**. + +#### PrefabObjectOnlyAttribute + +Supported types: **GameObject, Component**. + +#### NotPrefabObjectOnlyAttribute + +Supported types: **GameObject, Component**. + --- ### Toolbox Drawers @@ -728,7 +730,7 @@ public class GenericInterfaceImplementation : IGenericInterface ##### SerializeReference context menu operations -You can use few custom context menu operations for the SerializeReference-based fields: +You can use few custom context menu operations for the **[SerializeReference]** fields: - **Copy Serialize Reference**: creates a deep copy of the linked reference - **Paste Serialize Reference**: allows to paste preserved copy to a field - **Duplicate Serialize Reference**: allows to duplicate the linked reference (works only on collection elements) From 42deedbde4aa6304ed07ca88cb38fea2508aeb5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Wed, 28 Aug 2024 19:56:54 +0200 Subject: [PATCH 18/23] Add information about the default settings in the settings window; minor refactor changes --- .../Editor Toolbox/Editor/ToolboxManager.cs | 20 +++++++++++++++---- Assets/Editor Toolbox/Editor/ToolboxPrefs.cs | 1 - 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Assets/Editor Toolbox/Editor/ToolboxManager.cs b/Assets/Editor Toolbox/Editor/ToolboxManager.cs index 36ec4407..1136af29 100644 --- a/Assets/Editor Toolbox/Editor/ToolboxManager.cs +++ b/Assets/Editor Toolbox/Editor/ToolboxManager.cs @@ -1,5 +1,6 @@ using System.Collections; using System.IO; + using Unity.EditorCoroutines.Editor; using UnityEditor; using UnityEngine; @@ -91,7 +92,7 @@ private static void ManageSceneViewCore(IToolboxSceneViewSettings settings) private static string GetSettingsFileGuid() { - var guids = AssetDatabase.FindAssets("t:" + settingsType); + var guids = AssetDatabase.FindAssets($"t:{settingsType}"); string targetGuid = null; //try to find a settings file in a non-package directory for (var i = guids.Length - 1; i >= 0; i--) @@ -99,7 +100,7 @@ private static string GetSettingsFileGuid() var guid = guids[i]; var path = AssetDatabase.GUIDToAssetPath(guid); targetGuid = guid; - if (path.StartsWith("Assets")) + if (!IsDefaultSettingsPath(path)) { break; } @@ -108,6 +109,11 @@ private static string GetSettingsFileGuid() return targetGuid; } + private static bool IsDefaultSettingsPath(string path) + { + return path.StartsWith("Packages"); + } + [InitializeOnLoadMethod] internal static void InitializeToolbox() { @@ -223,7 +229,7 @@ void ReintializeProvider() AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); - ToolboxEditorLog.LogInfo("Created a settings file at - " + relativePath); + ToolboxEditorLog.LogInfo($"Created a settings file at - {relativePath}"); ReintializeProvider(); } @@ -232,7 +238,13 @@ void ReintializeProvider() } EditorGUILayout.Space(); - EditorGUILayout.LabelField("Settings file location - " + SettingsPath); + EditorGUILayout.LabelField($"Settings file location - {SettingsPath}"); + if (IsDefaultSettingsPath(SettingsPath)) + { + EditorGUILayout.HelpBox("The currently displayed settings file is the default one, located in the packages directory. " + + "This means all changes can be easily lost. Create a new file for better maintainability.", MessageType.Info); + } + EditorGUILayout.Space(); globalSettingsEditor.OnInspectorGUI(); diff --git a/Assets/Editor Toolbox/Editor/ToolboxPrefs.cs b/Assets/Editor Toolbox/Editor/ToolboxPrefs.cs index d9ad3c3e..c74d88d0 100644 --- a/Assets/Editor Toolbox/Editor/ToolboxPrefs.cs +++ b/Assets/Editor Toolbox/Editor/ToolboxPrefs.cs @@ -20,7 +20,6 @@ private static string GetKey(string causer, string propertyName) return string.Format("{0}{3}{1}{3}{2}", "Toolbox", causer, propertyName, "."); } - public static void DeleteAll() { EditorPrefs.DeleteAll(); From 450f34068c8008161bfa6bdb4e50bdf75bf8d548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Thu, 29 Aug 2024 00:12:17 +0200 Subject: [PATCH 19/23] Implement basic path validation for the SerializedDirectory class; minor refactor changes --- .../Drawers/Internal/FolderDataDrawer.cs | 9 ----- .../Material/BaseMaterialPropertyDrawer.cs | 5 +-- .../Material/MaterialCompactTextureDrawer.cs | 2 - .../Material/MaterialConditionalDrawer.cs | 2 - .../Drawers/Material/MaterialHelpDecorator.cs | 3 -- .../Material/MaterialHideIfToggleDrawer.cs | 1 - .../Drawers/Material/MaterialIndentDrawer.cs | 2 - .../Material/MaterialMinMaxSliderDrawer.cs | 2 - .../Material/MaterialShowIfToggleDrawer.cs | 1 - .../Material/MaterialTitleDecorator.cs | 2 - .../Regular/SerializedDateTimeDrawer.cs | 5 ++- .../Regular/SerializedDirectoryDrawer.cs | 38 +++++++++++++++++++ .../Regular/SerializedDirectoryDrawer.cs.meta | 11 ++++++ .../Regular/TypeConstraintAttribute.cs | 1 - .../Serialization/SerializedDirectory.cs | 37 +++++++++++++++++- Assets/Examples/Scenes/SampleScene.unity | 6 ++- 16 files changed, 94 insertions(+), 33 deletions(-) create mode 100644 Assets/Editor Toolbox/Editor/Drawers/Regular/SerializedDirectoryDrawer.cs create mode 100644 Assets/Editor Toolbox/Editor/Drawers/Regular/SerializedDirectoryDrawer.cs.meta diff --git a/Assets/Editor Toolbox/Editor/Drawers/Internal/FolderDataDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Internal/FolderDataDrawer.cs index 56eb9daa..1634c939 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Internal/FolderDataDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Internal/FolderDataDrawer.cs @@ -11,7 +11,6 @@ internal class FolderDataDrawer : PropertyDrawer private const int largeIconPickedId = 1001; private const int smallIconPickedId = 1002; - private void DrawFolderByNameIcon(Rect rect) { var diff = rect.height - Style.dataByNameLabelStyle.fixedHeight; @@ -67,7 +66,6 @@ private int GetSelectorHash(SerializedProperty property) return property.propertyPath.GetHashCode() + property.serializedObject.GetHashCode(); } - public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { //if expanded - draw foldout + 3 properties + buttons strip + additional icon @@ -154,14 +152,11 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten EditorGUI.indentLevel++; var rawPropertyHeight = propertyPosition.height + Style.spacing; - var summaryFieldHeight = rawPropertyHeight; propertyPosition.y += rawPropertyHeight; - summaryFieldHeight += rawPropertyHeight; //draw the folder data type property EditorGUI.PropertyField(propertyPosition, dataTypeProperty, new GUIContent("Type"), false); propertyPosition.y += rawPropertyHeight; - summaryFieldHeight += rawPropertyHeight; //decide what property should be drawn depending on the folder data type if (isPathBased) @@ -169,20 +164,17 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten propertyPosition.height = EditorGUI.GetPropertyHeight(pathProperty); EditorGUI.PropertyField(propertyPosition, pathProperty, false); propertyPosition.y += propertyPosition.height + Style.spacing; - summaryFieldHeight += propertyPosition.height + Style.spacing; propertyPosition.height = Style.height; } else { EditorGUI.PropertyField(propertyPosition, nameProperty, false); propertyPosition.y += rawPropertyHeight; - summaryFieldHeight += rawPropertyHeight; } propertyPosition.height = EditorGUI.GetPropertyHeight(tooltipProperty); EditorGUI.PropertyField(propertyPosition, tooltipProperty, false); propertyPosition.y += propertyPosition.height + Style.spacing; - summaryFieldHeight += propertyPosition.height + Style.spacing; propertyPosition.height = Style.height; //adjust rect for folder icons + button strip @@ -244,7 +236,6 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten EditorGUI.EndProperty(); } - private static class Style { internal static readonly float height = EditorGUIUtility.singleLineHeight; diff --git a/Assets/Editor Toolbox/Editor/Drawers/Material/BaseMaterialPropertyDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Material/BaseMaterialPropertyDrawer.cs index adbb8ff5..ab61738b 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Material/BaseMaterialPropertyDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Material/BaseMaterialPropertyDrawer.cs @@ -29,15 +29,14 @@ protected virtual void DrawInvalidDrawerLabel(Rect position, string label) EditorGUI.LabelField(position, content); } - - public override sealed float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + public sealed override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) { return IsPropertyValid(prop) ? GetPropertyHeightSafe(prop, label, editor) : base.GetPropertyHeight(prop, label, editor); } - public override sealed void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor) + public sealed override void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor) { if (IsPropertyValid(prop)) { diff --git a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialCompactTextureDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialCompactTextureDrawer.cs index bb3b88c7..b0c39af5 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialCompactTextureDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialCompactTextureDrawer.cs @@ -7,7 +7,6 @@ public class MaterialCompactTextureDrawer : BaseMaterialPropertyDrawer { private readonly string tooltip; - public MaterialCompactTextureDrawer() : this(string.Empty) { } @@ -16,7 +15,6 @@ public MaterialCompactTextureDrawer(string tooltip) this.tooltip = tooltip; } - protected override float GetPropertyHeightSafe(MaterialProperty prop, string label, MaterialEditor editor) { return EditorGUIUtility.singleLineHeight; diff --git a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialConditionalDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialConditionalDrawer.cs index adfe8e8e..f7baa652 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialConditionalDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialConditionalDrawer.cs @@ -7,13 +7,11 @@ public abstract class MaterialConditionalDrawer : BaseMaterialPropertyDrawer { protected readonly string togglePropertyName; - protected MaterialConditionalDrawer(string togglePropertyName) { this.togglePropertyName = togglePropertyName; } - protected override float GetPropertyHeightSafe(MaterialProperty prop, string label, MaterialEditor editor) { if (!HasToggle(prop)) diff --git a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialHelpDecorator.cs b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialHelpDecorator.cs index e4727a50..b46a26d3 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialHelpDecorator.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialHelpDecorator.cs @@ -8,7 +8,6 @@ public class MaterialHelpDecorator : BaseMaterialPropertyDrawer private readonly string message; private readonly MessageType type; - public MaterialHelpDecorator(string message) : this(message, 1) { this.message = message; @@ -20,7 +19,6 @@ public MaterialHelpDecorator(string message, float type) this.type = (MessageType)type; } - protected override float GetPropertyHeightSafe(MaterialProperty prop, string label, MaterialEditor editor) { var minHeight = 24.0f; @@ -33,7 +31,6 @@ protected override void OnGUISafe(Rect position, MaterialProperty prop, string l EditorGUI.HelpBox(position, message, type); } - private static class Style { internal static readonly GUIStyle textStyle = new GUIStyle(EditorStyles.label) diff --git a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialHideIfToggleDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialHideIfToggleDrawer.cs index 930d7418..5e21ad44 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialHideIfToggleDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialHideIfToggleDrawer.cs @@ -5,7 +5,6 @@ public class MaterialHideIfToggleDrawer : MaterialConditionalDrawer public MaterialHideIfToggleDrawer(string togglePropertyName) : base(togglePropertyName) { } - protected override bool IsVisible(bool? value) { return value.HasValue && !value.Value; diff --git a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialIndentDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialIndentDrawer.cs index 6f21dcce..199188a3 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialIndentDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialIndentDrawer.cs @@ -7,7 +7,6 @@ public class MaterialIndentDrawer : BaseMaterialPropertyDrawer { private readonly int indent; - public MaterialIndentDrawer() : this(1) { } @@ -16,7 +15,6 @@ public MaterialIndentDrawer(float indent) this.indent = (int)indent; } - protected override float GetPropertyHeightSafe(MaterialProperty prop, string label, MaterialEditor editor) { return base.GetPropertyHeightSafe(prop, label, editor); diff --git a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialMinMaxSliderDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialMinMaxSliderDrawer.cs index b28242cd..0e9c2157 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialMinMaxSliderDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialMinMaxSliderDrawer.cs @@ -10,14 +10,12 @@ public class MaterialMinMaxSliderDrawer : BaseMaterialPropertyDrawer private readonly float minValue; private readonly float maxValue; - public MaterialMinMaxSliderDrawer(float minValue, float maxValue) { this.minValue = minValue; this.maxValue = maxValue; } - protected override float GetPropertyHeightSafe(MaterialProperty prop, string label, MaterialEditor editor) { return EditorGUIUtility.singleLineHeight; diff --git a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialShowIfToggleDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialShowIfToggleDrawer.cs index ca7a586c..77e61e31 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialShowIfToggleDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialShowIfToggleDrawer.cs @@ -5,7 +5,6 @@ public class MaterialShowIfToggleDrawer : MaterialConditionalDrawer public MaterialShowIfToggleDrawer(string togglePropertyName) : base(togglePropertyName) { } - protected override bool IsVisible(bool? value) { return value ?? false; diff --git a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialTitleDecorator.cs b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialTitleDecorator.cs index 5d7cd22c..6cc68f3a 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialTitleDecorator.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Material/MaterialTitleDecorator.cs @@ -8,7 +8,6 @@ public class MaterialTitleDecorator : BaseMaterialPropertyDrawer private readonly GUIContent header; private readonly float spacing; - public MaterialTitleDecorator(string header) : this(header, 4.0f) { } @@ -18,7 +17,6 @@ public MaterialTitleDecorator(string header, float spacing) this.spacing = spacing; } - protected override float GetPropertyHeightSafe(MaterialProperty prop, string label, MaterialEditor editor) { return EditorGUIUtility.singleLineHeight + spacing; diff --git a/Assets/Editor Toolbox/Editor/Drawers/Regular/SerializedDateTimeDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Regular/SerializedDateTimeDrawer.cs index c988cc80..0d5ece0b 100644 --- a/Assets/Editor Toolbox/Editor/Drawers/Regular/SerializedDateTimeDrawer.cs +++ b/Assets/Editor Toolbox/Editor/Drawers/Regular/SerializedDateTimeDrawer.cs @@ -1,4 +1,5 @@ -using System; +using System; + using UnityEditor; using UnityEngine; @@ -12,7 +13,7 @@ protected override void OnGUISafe(Rect position, SerializedProperty property, GU label = EditorGUI.BeginProperty(position, label, property); var fieldPosition = EditorGUI.PrefixLabel(position, label); var ticksProperty = property.FindPropertyRelative("ticks"); - DateTime dateTime = new DateTime(ticksProperty.longValue); + var dateTime = new DateTime(ticksProperty.longValue); EditorGUI.BeginChangeCheck(); var dateTimeString = EditorGUI.DelayedTextField(fieldPosition, dateTime.ToString()); if (EditorGUI.EndChangeCheck()) diff --git a/Assets/Editor Toolbox/Editor/Drawers/Regular/SerializedDirectoryDrawer.cs b/Assets/Editor Toolbox/Editor/Drawers/Regular/SerializedDirectoryDrawer.cs new file mode 100644 index 00000000..386b1ba6 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/Drawers/Regular/SerializedDirectoryDrawer.cs @@ -0,0 +1,38 @@ +using UnityEditor; +using UnityEngine; + +namespace Toolbox.Editor.Drawers +{ + [CustomPropertyDrawer(typeof(SerializedDirectory))] + public class SerializedDirectoryDrawer : PropertyDrawerBase + { + protected override void OnGUISafe(Rect position, SerializedProperty property, GUIContent label) + { + var assetProperty = property.FindPropertyRelative("directoryAsset"); + var pathProperty = property.FindPropertyRelative("path"); + + label = EditorGUI.BeginProperty(position, label, property); + + position.yMax = position.yMin + EditorGUIUtility.singleLineHeight; + property.isExpanded = EditorGUI.Foldout(position, property.isExpanded, label); + + if (property.isExpanded) + { + EditorGUI.indentLevel++; + + position.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(position, assetProperty); + + position.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + using (new EditorGUI.DisabledScope(true)) + { + EditorGUI.PropertyField(position, pathProperty); + } + + EditorGUI.indentLevel--; + } + + EditorGUI.EndProperty(); + } + } +} \ No newline at end of file diff --git a/Assets/Editor Toolbox/Editor/Drawers/Regular/SerializedDirectoryDrawer.cs.meta b/Assets/Editor Toolbox/Editor/Drawers/Regular/SerializedDirectoryDrawer.cs.meta new file mode 100644 index 00000000..6599c5e9 --- /dev/null +++ b/Assets/Editor Toolbox/Editor/Drawers/Regular/SerializedDirectoryDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5ee7a63d55129bf48acd4381ec8c9b5c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor Toolbox/Runtime/Attributes/Property/Regular/TypeConstraintAttribute.cs b/Assets/Editor Toolbox/Runtime/Attributes/Property/Regular/TypeConstraintAttribute.cs index ee13940f..6e9670d2 100644 --- a/Assets/Editor Toolbox/Runtime/Attributes/Property/Regular/TypeConstraintAttribute.cs +++ b/Assets/Editor Toolbox/Runtime/Attributes/Property/Regular/TypeConstraintAttribute.cs @@ -17,7 +17,6 @@ public TypeConstraintAttribute(Type assemblyType) AssemblyType = assemblyType; } - /// /// Associated type which will define what type we are looking for. /// diff --git a/Assets/Editor Toolbox/Runtime/Serialization/SerializedDirectory.cs b/Assets/Editor Toolbox/Runtime/Serialization/SerializedDirectory.cs index aa273592..a8a6ce89 100644 --- a/Assets/Editor Toolbox/Runtime/Serialization/SerializedDirectory.cs +++ b/Assets/Editor Toolbox/Runtime/Serialization/SerializedDirectory.cs @@ -1,4 +1,5 @@ -using System; +using System; + #if UNITY_EDITOR using UnityEditor; #endif @@ -15,13 +16,38 @@ public class SerializedDirectory : ISerializationCallbackReceiver [SerializeField, Disable] private string path; + internal static bool IsAssetValid(DefaultAsset asset, out string path) + { + path = asset != null ? AssetDatabase.GetAssetPath(asset) : null; + if (path == null) + { + return true; + } + + //NOTE: assume that directory can't have any extension + var extension = System.IO.Path.GetExtension(path); + if (string.IsNullOrEmpty(extension)) + { + return true; + } + + return false; + } + void ISerializationCallbackReceiver.OnAfterDeserialize() { } void ISerializationCallbackReceiver.OnBeforeSerialize() { #if UNITY_EDITOR - path = directoryAsset ? AssetDatabase.GetAssetPath(directoryAsset) : null; + if (IsAssetValid(directoryAsset, out var assetPath)) + { + DirectoryPath = assetPath; + return; + } + + DirectoryAsset = null; + DirectoryPath = null; #endif } @@ -32,6 +58,13 @@ public DefaultAsset DirectoryAsset set => directoryAsset = value; } #endif + public string DirectoryPath + { + get => path; + set => path = value; + } + + [Obsolete("Use " + nameof(DirectoryPath) + " instead.")] public string Path { get => path; diff --git a/Assets/Examples/Scenes/SampleScene.unity b/Assets/Examples/Scenes/SampleScene.unity index 2e16fc9c..8b88216c 100644 --- a/Assets/Examples/Scenes/SampleScene.unity +++ b/Assets/Examples/Scenes/SampleScene.unity @@ -1816,7 +1816,11 @@ MonoBehaviour: scenePath: Assets/Examples/Scenes/SampleScene.unity buildIndex: 0 dictionary: - pairs: [] + pairs: + - key: 0 + value: {fileID: 2037155952} + - key: 1 + value: {fileID: 1972418676} error: 0 date: ticks: 637820719200000000 From 4f744fd54c97762990817fda04182c225891d7db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Thu, 29 Aug 2024 00:18:49 +0200 Subject: [PATCH 20/23] Update: README.md, CHANGELOG.md --- Assets/Editor Toolbox/CHANGELOG.md | 1 + Assets/Editor Toolbox/README.md | 9 ++++++++- README.md | 9 ++++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Assets/Editor Toolbox/CHANGELOG.md b/Assets/Editor Toolbox/CHANGELOG.md index 329401cc..4d204e43 100644 --- a/Assets/Editor Toolbox/CHANGELOG.md +++ b/Assets/Editor Toolbox/CHANGELOG.md @@ -5,6 +5,7 @@ - Context menu operations for [SerializeReference] properties (Copy, Paste, Duplicate), all operations are based on a deep copy of the source reference - Basic support for generic references while using [SerializeReference] & [ReferencePicker], can be utilized in Unity 2023+ - More unit tests (PropertyUtility, filtering generic types) +- Validation of assigned assets in the SerializedDirectory class ### Changed: - Fix duplicated initialization process forced by the OnValidate call diff --git a/Assets/Editor Toolbox/README.md b/Assets/Editor Toolbox/README.md index 01644f4b..b6f35c3b 100644 --- a/Assets/Editor Toolbox/README.md +++ b/Assets/Editor Toolbox/README.md @@ -979,7 +979,14 @@ Copy and paste all components from/to particular GameObject. ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/utils.png) -#### ScriptableObject Creation Wizard +#### Wizards + +If you want to create custom wizards and still utilize Toolbox-related features then feel free to use the **ToolboxWizard** class. +Works in similar way to Unity's ScriptableWizard. + +> Editor Toolbox/Editor/Wizards/ToolboxWizard.cs + +##### ScriptableObject Creation Wizard Create multiple ScriptableObjects at once. Wizard will allow only ScritpableObjects marked with **[Toolbox.Attributes.CreateInWizard]** or **[UnityEngine.CreateAssetMenu]** attributes. diff --git a/README.md b/README.md index 01644f4b..b6f35c3b 100644 --- a/README.md +++ b/README.md @@ -979,7 +979,14 @@ Copy and paste all components from/to particular GameObject. ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/utils.png) -#### ScriptableObject Creation Wizard +#### Wizards + +If you want to create custom wizards and still utilize Toolbox-related features then feel free to use the **ToolboxWizard** class. +Works in similar way to Unity's ScriptableWizard. + +> Editor Toolbox/Editor/Wizards/ToolboxWizard.cs + +##### ScriptableObject Creation Wizard Create multiple ScriptableObjects at once. Wizard will allow only ScritpableObjects marked with **[Toolbox.Attributes.CreateInWizard]** or **[UnityEngine.CreateAssetMenu]** attributes. From 37e7ea15416e6a25d27a6da39a57f81c517838eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Thu, 29 Aug 2024 00:38:44 +0200 Subject: [PATCH 21/23] Update: README.md & docs --- Assets/Editor Toolbox/README.md | 28 ++++++++++++++---- .../Runtime/Serialization/SerializedScene.cs | 1 - Docs/serializedtype.png | Bin 11284 -> 9717 bytes README.md | 28 ++++++++++++++---- 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/Assets/Editor Toolbox/README.md b/Assets/Editor Toolbox/README.md index b6f35c3b..3483f689 100644 --- a/Assets/Editor Toolbox/README.md +++ b/Assets/Editor Toolbox/README.md @@ -810,11 +810,11 @@ Allows to serialize Types and pick them through a dedicated picker. ```csharp [TypeConstraint(typeof(Collider), AllowAbstract = false, AllowObsolete = false, TypeSettings = TypeSettings.Class, TypeGrouping = TypeGrouping.None)] -public SerializedType var1; +public SerializedType serializedType; public void Usage() { - var type = var1.Type; + System.Type type = serializedType.Type; } ``` @@ -825,11 +825,11 @@ public void Usage() Allows to serialize SceneAssets and use them in Runtime. ```csharp -public SerializedScene scene; +public SerializedScene serializedScene; public void Usage() { - UnityEngine.SceneManagement.SceneManager.LoadScene(scene.BuildIndex); + UnityEngine.SceneManagement.SceneManager.LoadScene(serializedScene.BuildIndex); } ``` @@ -837,7 +837,7 @@ public void Usage() ```csharp [SceneDetails] -public SerializedScene scene; +public SerializedScene serializedScene; ``` ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/scenedetails.png) @@ -875,12 +875,30 @@ public void Usage() Allows to serialize DateTime. +```csharp +public SerializedDateTime serializedDateTime; + +public void Usage() +{ + System.DateTime dateTime = serializedDateTime; +} +``` + ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/serializeddate.png) #### SerializedDirectory Allows to serialize folders in form of assets and retrieve direct paths in runtime. +```csharp +public SerializedDirectory serializeDirectory; + +public void Usage() +{ + string path = serializeDirectory.DirectoryPath; +} +``` + ![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/serializeddirectory.png) ## Editor Extensions diff --git a/Assets/Editor Toolbox/Runtime/Serialization/SerializedScene.cs b/Assets/Editor Toolbox/Runtime/Serialization/SerializedScene.cs index d483bc7f..0bda74f8 100644 --- a/Assets/Editor Toolbox/Runtime/Serialization/SerializedScene.cs +++ b/Assets/Editor Toolbox/Runtime/Serialization/SerializedScene.cs @@ -25,7 +25,6 @@ public class SerializedScene : ISerializationCallbackReceiver [SerializeField] private int buildIndex; - void ISerializationCallbackReceiver.OnBeforeSerialize() { UpdateProperties(); diff --git a/Docs/serializedtype.png b/Docs/serializedtype.png index 17beda1767b08365faa410c8e231e0816b6909a6..bd87ddcfd12bb9896c275f85e032896abb285803 100644 GIT binary patch literal 9717 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 JmWdm``F}^f!q@-+ literal 11284 zcma)?cU%+QzV#6V1QY}W1Sv|FUPW3EiS!~}5}Nc50-+ZH6%gsYOYglzLK9Kxy?3OA z77#+H0`K7CbI!TvoX>mjA0!zvduC_P{(bjaYbNx$s@yF?8bT~AtXm55U=1v+YX`vR zfg5AP7FJax(XW@dz&3%Cyq*gd7V+1sziaWF z#P_hUIExg((pnyds5v4hPVIC2pS!r%cb>f`bny+)WjmlGD5Pe)Ux)*_b#ALwsNR83 zL$AqjKC<+|G(^qkTxRbY_xI=sldt&MRoOb+Lmcz!x3hKLer(8#Ak5A_E`0ym=_GTZ zYsyTd&*4#Ie&69)@{~e#WR2y~{2CnT-fsa%P1PVD+$JSeH<}q}A_LwTOo`G9L(g_w z8E|lLJZ6{agK>x-f9_>r+$_VV_rP+W_hi%2)qS-XfS=MJY?nnYytf!cB9KHr^e%Sy z{s~XaZm#Uz!O#?s^{n8#y`ff`QM-&Msy1(~rH6#DV@(sT8(p4G@JmTKg2sOR43_#D zuWM)xs*@|1XgSE^{bBFuoti9Ddy)nl*E`-ay0iglbMf*n_c{92oUAyQo8zkapN_m5 zkUUx+xIFHV`k8t8ORm*X_V8>!v2~Vz&SN>;!g_0SYxtH%M};rSb}e>fX5qq3-|u8~ zO>^twWWaxE)@49Aljdwg&Hw#G>jlPR9-R>^I3Pj3aB&FlBXc~gM(w7iGl^#G`W-c{ zkq>>h=KLtN7pevZWr}3llsBx=q%Sxo`beuPD=&^i9ls3^$0RG&p3FM6-}4V1X+$d zS@ON{=i{*_w!{~3ouNU!s=6i91Oce#6D?nxw4ZR+AuL{iXMYt~p zG5or}({kp}tSno6u`VYyyvq``;Dhcv#b{=p#u3Xe9Df%%5a?k^)L%Ll7d@Ob-5V_c z)rrx$O}@-HBR`t==C!c2j8@Eh&VHw|vhpKu3JPYe^X_`XfZt(_e8I@4rT3iU`h%0_ z!1ey3=C@CdE_zz+E=LE8JJI@~y#`!jOS(7~C>y3O)~-{0;Y3y6b?DjgNalsv+SA0? zK8w9#-DX0dUF_a)Vv807ywuVczY8RVP99i)a=91juRk#sc1}xBw9E$DBk<+ff?hgw zn5NI9Iv@xfJ$s-(&lWBX2iP|A>(2&R(#_QbeRsVV+66ODlxbZDrB9`*Y8jaeGhK%j zPD!8_SZ{o)^kHM#Vr4v3cr$Rv3G_4eJ6{Oc(u_f*7~T`?%gGK<{^df?v+`M+eZ)j_ zIYK!Q?lByj@rEhl@zYktkD!A=nY{oKpC`QJt-n@zVXvcLO&%yU`4Wt!)ERZg*(`GN z^~L;Ai*BNQg;I^cJTSCN_)^E$GSF$r^)UB_V>k5lL>@2O}`KE5F zD20Q0_vxMoEs6he``$046a&NQVDQf}M_(o0STDt>gxysC%d-W`3J-$UkvK%44Gbn9T?_w$?x0L46KeS-&%#)`&VdUSex8x_G z@m)^pRNeR5-UmwwoM2k#kPJ1~_FEInP3ZYSrx^1xEAfv#3{$WP16?|Mwl;$`0)ow9 zfkY5H!C-~QH_qo=lo){rx=qew+*>_VchzrqB_4avqv_M!rmYcmoCXRp3Gmpk=?>6g z)hXsHxf+<6tgW5?kdMyit*a>uS*Q&k8QE)QE4|olxlbrH$WrS$$`P}W%N4um@v{wo z%YL&V{sFZxK@!Ua-Q*bRD7=6;rZ)Bd zpiu?+pUpqN5b+BL1Rgc-`g)~G{rW+I$n#r?mfM8Q#woJ+f^sQ%7o>K9@q;s6Y~BZDGyA!s>4~tkHVB6b8Eump6*T$UV8EwQnk<(^@iX!$?&z zoNXuD@{{E?fxqES^yfzic&Vo5AT+T0;q5Mm`zn&%GJegi37fcX}$^(9r)BCc3e zH!~GM>)G7y0Roe2&dt5e>+^%?6b(>z!wN-IA;17&bF22Gi!HMhUgIt!Plw{xCx{^X zW!`d=?_eJoB}IR=DgQVb9wD<9hT+X}sl;K_gA@RWYz|Z!wRO$=@fB_S9kjL}>DENg zG8^%aL=9i!6HbSm%|5^5r*4I69w?q^}w<)~*_0wD6N(!)J&WX7w3K!Nl_N5rTM%@yCN;gxmW zy{FKiv@Ctv*eqY->ElD|=+S=9=?n$m@^pT{WDZ*6j~tq#tX8vj>MXN=8rZBap%Cx){@=NN)9~ba?~ZZ^ah4wZ@#w~vo%E1NHRh+dJ__xx6Q@ga_W_PIX~cT z8&08_duqeR-7(;Qfku2|4^YA$Br-aFS~JREy{c4?+O8QG59-RT^F0`nTUL+sin}QD zrrxv1RS-WpOI+mW&>SdHZV=YtNifS0qHHs-u?U;+~!l?`Rk>bZm%4pP3m=L&;B5ZU-B6@K2h_1B*)dbGo*oS zYa&Jpdt2Mh66Kg+%mWBQ?2mj^^{bL8-5-VGpE=U3aCQ=_y`CTe-wOu1nn}TWkYj*c z4!cW|?3pn5SmTG#_gUv{PQ9B-HuK7L<4p>EmYn82LUz3ERp}I8W$qe%Fg0A`=YCTA z066q%G=&y&*~_?Jxwp51Jhh7{jox<9u{_X?Io!!l+p!gq3qccjbGC-KHfS8$fI>~Y zrms6pIS}V4Su{%UY0t60qfVyEtZ004pRlEmk1qn~5D7*82*-+Sbh2yciZ(~*TD!d3 z#IuQb^SCJR?6f`v-No2F_S%6{oKn{|p^~fTz>Q;4PMJtDTBfRA{h1wEGJBK~AFkS{ z5-_H|?2nkZSM-c~GY;JzT&pj^S&8XXQkqRE-nh0Qmw5W&T1~Z`tbyun`&&Ty@BN4a z&hDttT6bM_qwx?yr&1=u`4Ds6*@F0K(2Wu`v`&;!mkEcZZB--x%-HZYCBd4`eaFE} zHSpF|w|5m5V6pdUXgW$)+Db+rAr@wH`(dr0GAUu^;<-%mD6?S||AtS-_t~c9X8>_o z*=mOWDloS`s5z4gR<~K7<0jK|HMrrzN7Y}=!LNhV6x!b6uS{2;| zW6HXmGOF*EgTED*iF7~HLCgbEv8>zy@- zS!S{M02EB%a^ai@twWoEJ={aP=hqkb(yPRAgWAH6J~nJr{9s9-% z_O9Z`so=bh?JeNC}=6zT6z>-Y(EQ8L9g!EwR}mf9R(N=Zul> z(8GF9uq{7Od@+Qht-h~V416}Gj{EWwM{xs3e!jm~(blDdIK>{rmOQf4zdX0?b6yGiRs+u^EtL|efTh@vY#}n_HshjN<3QOG=<2CH?Cf}LGC?TicrfAzAoo8+q9L3H@pM zP_Aj;-X{58qyTN(DdDd*IA=VD7PvqRLAGV%mGkrC)1Xa>G`H_6$0Kz6(guTtuRTvf z3vd$0al4>?ZyS4Oge7_o+P0cJ=ywT1B(|*38HN0KuGuZ*UveS^9l6Es(gvr~-D(oM z)s9@qhQ9T0*t~Q?qAv=@ZRYqamocY|UzEqj;bA!!_|eOd8lEr1JZ>%CrSNyn+xqbf z(ekPe1>2vhQD$iB58K)!JGnY>a76Q>MOpxS$rqvKEzV=qa(CCRLD-!pLaII2gIB;8 z8S|9B344NM8ZW`RUaK;N7H5JcCeDq8ulqDp`U}(Qj%<8%>)lTW$D4j77}v@%l_O~= zJVd*`b!0TFT6uU&fPKeR__A-)mxc3HgYVA;1-%gwhx*u!r;Cs2YUjESdbXO5B@MH` zA0KNmGSm+*YdSVti93Mu+P(X>y4F!&E1YQXVd@Oa%bKBu{_=!V{CCU6T@zm;*IzMi z-T|un;aY(z%Uho;6lHn6sJ|FyzakCQB>W)+5%JI+IG{#%dI*gv@DdU-PWL}xa5fm~ zQ+brNI|Em1J?xe}>LHCL2mTilVm0^Q+3|-em~?Dbym!$C{0w!nXqp#YCX)kR#2SZK zcy=S;HZB`ED9p+Ncj_gSF1W@ldxhz;qG(R3_rGJcoY z&x+?gXBSW^d0|kdEXXg|NEadI8bEAE8mC!zTGo$El&cNS;hDN?*l0>-ojJ~S^0iCzn>UpU>$Xa{jLVb2vrO!itfiL~m)gR0sa@{YX`Fi+7pq?nCr%c7M48Gz)3djhZzuf%~grUs6X;CrMT; zO=PBax_MFEa==S$AaS%H&Z)uJs&mW7JH3NZQKrV`;=?I}^f|DEUG*wM$Y`kQ6X7fi zmk1GYwV{Kd?|B&ZniBPkXOGVYQAQU$XL@?F4NmY)lC?sh7N%#poZ@mbj|o0`zRBoGpEj`#gF zsVH4l*R&@MC)2i7mK-UMF60Le;&RHBMN9JlCnUFBeuG?{sMBkzsn+w}USW-{WS`rZ zIbxtO-p{@QjY3OkEL@SoXHqdzEnfWxdXIQlxPq-{SDv~^MetY=a-w+`vgA8EDh2|@ zhdh!}z=+|s!-99ntORJ%L&N|cg5NhBK{T4jJ9i@<@2;u>;)>TTN1xHTJx)BD1p07Q z6+EBhe5HwDS3Cb#_41cA{%^YG>YGvb?MRY3p_GZ&63pMO$l->v)HmN;e`#PpmPL(J z>m$AijZDCJ8a|?cn@-(0L{CH_oo!z}VVhQby8J@FE`x8po67Z0a-Mc+xlVpW#@Dq% z8LD-nH#fSAAm=)k0dH@4KefUSa5RW`8{ko5{DdtVln<#f-RD9h!fwKb_*z6WMy3Pr z(-GNU2Uf7p{M^;sU}1Z4eftc(GGR}Z`@xLEq;>sZodQp~qJzNcdBM4@I)-QPM`b5^ zP|l%wlLMpgpFh8WH1>C6uf13Jnu;qSXJE71Q?pQZPOL@JqEQeU`ePGxuYxUYV=wgS zxu@{fBZ&ya`LQUaoamuHFC0Bt2(pbFXx1kIMTB~VU6tr4m4~RI!qi$UdwxM5RXNMM zPFkqinf{weI}~76e5P^y)Q=< zG01?2-j#46-+ly#KVg!+6OV~tzMUvl!$T+p5i&ejnj)3cA2;Jg*2|Q1&p@Cj*WAG0 z(A>6S*=eWa>_r;V74|Sl;|qe1EWF<|=TvLF34}EXV(eNEAkdB0 zS-8CYq&a_sMEjp0QTaKfe^^ufL8G?b*GeKUp<$0*CNK{6Ao@9~*EuMNJwdYi#?yF5 z$>rt?eR;~KM!E8w<2>(&NTF8twHemx1u3`ieqIff2VEFX$9Nz~I8!`Vwi_^GMc^p7 zb;GS%XXR1Be}zir6;vc?enSQF7gSPeeY_upHnoKCX`Wj(4c?H=5uGF>x=`qTd`OHQ;Cpqb>_PFrGsBx4bXU)^xJst#V{eAtpy(C0(Ir@_T0$BH?pz;4c5v7 zSv5L3R=0nc(2TG??!pc9?w)%amsJl*wcyn{4a00d&nvmFKCxR8=v1#~tp6~_D(@4_ z7CKZPp`5ny}k8((b2bv8Z!n>odj6CB##HSlaY#?Hm?bE&JSM|Pnl z3!m@u4R5=CWwk{*m42v%_RPQ}DPB{dZ_I4!78#y}F~#2V~YHNgIH49p7ztzHH%-F7P|U93r5yt^*z7O%qKSxn)e|xwPlI z;B)KU`R2}5=g9^aHaFCCo)O$}VIJK&<^`A#_3&IMUCOEzbP6{<#c9?}M&uo<772AS77!~J5$I0jOZY}g=<|7nS?eV!Q)@u^&> zcl%a`zdqrhMDNn-iL4!hf4Ln^4)~-0l}Mv9{*B9z(BL)Tm-m!&>ZSIA+um^)#pa*{*~doiFLMI-ANyBkJi3h|rk*G-)~v2LN8c+m;1Q7An4#PwF0QVEPokSz zp;Mx7NZy$h;tJLn*GmVvnUxa(21%&;${@Y3TeGyE!t%EG>`#q@LvDlm{*G1iMnQpn zkM>|X#{)rXk<9RStD>672$#jjc$yXQxV;pyA>O!-9e%%D)h7o+mnL_sldXj$-gO_6 zlMjDe^vhtM1ST_L1-Wp{T;6=(Pbb}c)Ha)q4FjNti;QI#3rr7rX(3zzsbGx<!d&G87Pby<8?~8Qop7Bc1z!BWy`eu>65DQy@T&Ab;nO*Ejz*q+6` zvl#OMO*xd9JYn06i5>6}CzkwGHTJRPRhxd{6G`iqann~6pOjuWP(C+no^2w4;Pxg8 zRK9mQ%$mV@*W;&?p#FZmo+P{gSXAlFCwZC4MDO(M;FG3m1-KN)sIx1VynfMqmw&dK z=+=W2rN@FeDaDBxyW>-r7hH{&JO_Su+{Zxl(#0rIyt4w^kr+_8lhe<6ciQClV11?| z=|Hpbjz}BewU!z2k-TKLnTH%u`Q8np^UdtwOMbXPxuEDqm^VZksbf{a96dorYOzlf zPDP_`zc0#lr#i`5|HGs(yBdjnY{JhZ;uw{Yw9tze7E&E5tDpV*RzTXm1M!O*%q>SSHgC6(8P0@h&9I zV}^#5l(g*Lf7$;Zjk8-u*7vd;BJY$jktpodWCX<-oKfp0i+O$4g~EOsdqbuH?NMwm z2pZ6qOOx^y=hOEdEfe={wgc#-%Nz0b^lx`%fEu>!a|+N#stU+}4DQKThHilzdxW@`Ng z4Wp90XUIEE2uv&Nj@qW0I;{hzI%5Oi$ZTlw z_^(p#d&UDdk9l)mib+z+RVRH<^1as=2d$jQa-fqtPeIja%zyprWN(;*(V^tiRc73w zXrh}r*=VWE33 zM$i(zOc?=l$^FsmesUjg0|H5!S;M-hyIQZeC=CCf0;xzi02*ORkmEvXAY$pHwW)W^{oHA4pj$w3X!6e&ow+}FNU*42w#At@1L#l?xNOI|*(oquYTRHp|7g`c^VT>~xUo=* zOgqN`m@aw56>Cwl6b zxPiZo5@^$WPprakOEmx}s?lH*L8Z?7;UT#?V{yNIk}cPj*0CyEXL`8!m)3do5Xzye zVvCnlM%u32LN;l3&i`RtqrIg_z;(er&tG2+!_;XK#ICzVAuX2HVN$oG{-(z?-W;(o zrFK~r>1#v3_06Jq<8rf_-x$2xRBZrD-a$L$8O{7PkQ5A=iYx6pUOqN2O|bqLqnrvr z&UigySAy(a8Kd)=QC}Y)4pMu+7;Lwj@3x4qsBoJ4hYBY}8Vc8-Ij!PLzcxm|JfXi# zM7miRMU)%JPb%XzcEBs)K;pv42od>j>gE4nmV7%7j|Yo^OeHEf_gHU0y1V@RLy0n- zt?bpF-4IU8w@J?!muJfrWL1`jOiI?%@KX%$>1ae z0dUGLf6k5O_uTQC!;K{DUT*fZ;Ie;pHS=wxc^Gg~WnbWs_kW`V(fkgkO zb|AXa4)TogS)0DtTm$3N_otmD^3Q& zG!2op@uvA70ikepYPP-!cdl}5cY>Zi?BLSGRFSr#e^$8he^z+LUll$jcYvO~@-*I^ zWoKM^1inLzQ$!;4$a{FT-w{^>r2m|t~ zBqXk3hh)M9db`*a%Dj2{eeCU19Z;&5Hcm^5RJ`pl(g6umosqO4yaNy!bSG7vTRxX` zXyeB?4s2N^=v5Ke3bn#XA}JZZ&^+T98L+M4LICex%Y-N4jRsdqyVuSt== zoy$00v8T05n(5AYJ`G%(tDjhHKae3w zl6(YSG3kh)n{4)m`?WeQfX=5m&rlOHTMpD4l7Fr6G5ry7(MzAX2wyjQA2BBOyhQe= zPuAHc`pvcYdJkOcY*oEg1q;XE{iDLM|6cb`8Z;De1|aZa*q0M@L8w02$v1~MC9ngq z?8y_n^ih|UbKkO*E!!^*Epp4oeE&bx^xroM|1%BoEf`vsNtMtTW&EEjeH5_LTPf2s zFPAC>p`R!5snMf7BYdp263|Eo{CBpIaF``;$KgDh7KVPzE)VpqK4$PSWr@`8w4!kc zV~y6?!->B_5lfRjX6G^d51gDm>{%fVZ>OcpxDs#EL6An#6W1OGI(Hwsz-vA~ZKMJj zNXXT~fXr9@lJM382&BCJjV|Td?S8Y@&M@Lpt`8BVmS$Sq=qjNvCkP@sinxvwoWoI> ze-Odu)cw=+O*mwAKjn#PoyEvs=}8#fhOL6OcYgR46?97ejS3S4;l_7d3WYj3+q|vJ zZvU8V(sRdMHMtvf=&@6n80jlq(*9Sx(i{lSxhZ8pdFYb+c(cjQg67ti?v$U2$>gKR zz(4UO5V{sE{1v(;di^tWRmo4=*!to_+!crE)FeNqla~2}lEaOY&l}_DvCtmu+c*jL zi02Ph=N!w#&)>fGg6JimzR)daiY9Fj27+(5)qwkuXhL)+%W^$ibCECLGFpyS3y9w% zYv$9DCcm>1%2MFYOrjx%Gh0ZgWDTw04h7Vg`u(CSXYu{YS*W~5Gj3@^>;J`8yy@}F z6Ni~4zIp@RM>V{eu;+qvg4BqcP$G~}gw`

P7|-X?CH zZDD10hn=@}(toGEf)y53>o0_VHrX`4|0=>t3DBaO;_*T*UZvx$21%+p>+;-iIs7j` z7~(D##q}puUHR8k^%Ygxc@Kg?G8{}(_~^U&j6TiA>4l4k!l(GKZU{x4KHsY*EU2tG=gh>f0%7SN#m`0U!% zLxul(Hy2R(yC(}alJ$e3g|fqK5p7O$S&i2vJ;wT;YBWqyN9?1AseYgK*yOrw@MB-@h^%7nL`oN%q?Xz~F?w z<8}d{8toCt3~#5SIrra>oK*nN2|5n=KZ^)?^iF?;!SDFT Date: Thu, 29 Aug 2024 11:51:13 +0200 Subject: [PATCH 22/23] Update: README.md, CHANGELOG.md; minor fixes and refactor changes --- Assets/Editor Toolbox/CHANGELOG.md | 3 ++- ...ache.cs => CopySerializeReferenceCache.cs} | 4 ++-- ...ta => CopySerializeReferenceCache.cs.meta} | 0 .../CopySerializeReferenceOperation.cs | 6 ++--- .../Internal/Types/TypeConstraintStandard.cs | 2 -- Assets/Editor Toolbox/README.md | 8 +++++++ .../Tests/Editor/TypesFilteringTest.cs | 22 ++++++++++++++----- README.md | 8 +++++++ 8 files changed, 40 insertions(+), 13 deletions(-) rename Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/{CopySerializedRererenceCache.cs => CopySerializeReferenceCache.cs} (66%) rename Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/{CopySerializedRererenceCache.cs.meta => CopySerializeReferenceCache.cs.meta} (100%) diff --git a/Assets/Editor Toolbox/CHANGELOG.md b/Assets/Editor Toolbox/CHANGELOG.md index 4d204e43..59b3773d 100644 --- a/Assets/Editor Toolbox/CHANGELOG.md +++ b/Assets/Editor Toolbox/CHANGELOG.md @@ -3,12 +3,13 @@ ### Added: - Warning information if currently serialized type in TypeField-based drawers (SerializedType, [ReferencerPicker]) is not available in the filtered types collection - Context menu operations for [SerializeReference] properties (Copy, Paste, Duplicate), all operations are based on a deep copy of the source reference -- Basic support for generic references while using [SerializeReference] & [ReferencePicker], can be utilized in Unity 2023+ +- Basic support for generic references while using [SerializeReference] & [ReferencePicker], can be utilized in Unity 2023.2.x+ - More unit tests (PropertyUtility, filtering generic types) - Validation of assigned assets in the SerializedDirectory class ### Changed: - Fix duplicated initialization process forced by the OnValidate call +- Better support for generic types for the SerializedType & associated drawer - Hierarchy: For now 'Script' label displays maximum 5 scripts - Improved types label generation for TypeField-based drawers (SerializedType, [ReferencerPicker]) diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializedRererenceCache.cs b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceCache.cs similarity index 66% rename from Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializedRererenceCache.cs rename to Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceCache.cs index 4b15ff51..b88da35e 100644 --- a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializedRererenceCache.cs +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceCache.cs @@ -2,9 +2,9 @@ namespace Toolbox.Editor.ContextMenu.Operations { - internal class CopySerializedRererenceCache + internal class CopySerializeReferenceCache { - public CopySerializedRererenceCache(Type referenceType, string data) + public CopySerializeReferenceCache(Type referenceType, string data) { ReferenceType = referenceType; Data = data; diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializedRererenceCache.cs.meta b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceCache.cs.meta similarity index 100% rename from Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializedRererenceCache.cs.meta rename to Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceCache.cs.meta diff --git a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs index ef5988c1..c25eb218 100644 --- a/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs +++ b/Assets/Editor Toolbox/Editor/ContextMenu/Operations/SerializeReference/CopySerializeReferenceOperation.cs @@ -5,7 +5,7 @@ namespace Toolbox.Editor.ContextMenu.Operations { internal class CopySerializeReferenceOperation : IContextMenuOperation { - internal static CopySerializedRererenceCache Cache { get; private set; } + internal static CopySerializeReferenceCache Cache { get; private set; } [InitializeOnLoadMethod] private static void Initialize() @@ -35,11 +35,11 @@ public void Perform(SerializedProperty property) { var referenceType = value.GetType(); var data = JsonUtility.ToJson(value); - Cache = new CopySerializedRererenceCache(referenceType, data); + Cache = new CopySerializeReferenceCache(referenceType, data); return; } - Cache = new CopySerializedRererenceCache(null, null); + Cache = new CopySerializeReferenceCache(null, null); #endif } diff --git a/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintStandard.cs b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintStandard.cs index 43264c5e..87bc2d2f 100644 --- a/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintStandard.cs +++ b/Assets/Editor Toolbox/Editor/Internal/Types/TypeConstraintStandard.cs @@ -16,7 +16,6 @@ public TypeConstraintStandard(Type targetType, TypeSettings settings, bool allow AllowObsolete = allowObsolete; } - public override bool IsSatisfied(Type type) { return base.IsSatisfied(type) && @@ -46,7 +45,6 @@ public override int GetHashCode() return hashCode; } - public TypeSettings Settings { get; set; } public bool AllowAbstract { get; set; } public bool AllowObsolete { get; set; } diff --git a/Assets/Editor Toolbox/README.md b/Assets/Editor Toolbox/README.md index 3483f689..5bdd6f33 100644 --- a/Assets/Editor Toolbox/README.md +++ b/Assets/Editor Toolbox/README.md @@ -38,6 +38,10 @@ Unity 2018.x or newer - Enable/disable Toolbox drawers or/and assign custom drawers - Enable/disable Toolbox Scene View and assign hotkeys +--- +> [!IMPORTANT] +> This package is fully IMGUI-based, which means it may conflict with pure UI Toolkit features in your project. Additionally, Toolbox overwrites the 'base' custom Editor for all `UnityEngine.Objects`, it's a common solution but means that you can't combine other Inspector extensions/plugins. + ## Table Of Contents - [Attributes & Drawers](#drawers) @@ -76,6 +80,10 @@ If you want to keep your custom settings between UET versions, create your own s Create/Editor Toolbox/Settings ``` +--- +> [!IMPORTANT] +> If you are getting warnings related to the current settings state, it most likely means that some features are not present in your Unity version. I suggest creating your own settings file and adjusting potential issues. Generally, it's always better to use a custom settings file rather than the default one. I'm planning to replace the ScriptableObject-based solution in the future, so it won't be a problem anymore. + ## Attributes & Drawers ### Regular Drawers diff --git a/Assets/Editor Toolbox/Tests/Editor/TypesFilteringTest.cs b/Assets/Editor Toolbox/Tests/Editor/TypesFilteringTest.cs index 73e373f8..e5d4688b 100644 --- a/Assets/Editor Toolbox/Tests/Editor/TypesFilteringTest.cs +++ b/Assets/Editor Toolbox/Tests/Editor/TypesFilteringTest.cs @@ -1,9 +1,7 @@ #pragma warning disable CS0612 -using NUnit.Framework; - using System; - +using NUnit.Framework; using UnityEngine; namespace Toolbox.Editor.Tests @@ -21,6 +19,8 @@ public interface Interface4 : Interface3 { } public interface Interface5 : Interface4 { } public interface Interface6 : Interface4 { } public interface Interface7 : Interface4 { } + public interface Interface8 : Interface4 { } + public interface Interface9 : Interface8 { } public abstract class ClassBase : Interface1 { } @@ -32,6 +32,8 @@ public class ClassWithInterface4 : ClassBase, Interface4 { } public class ClassWithInterface5 : ClassWithInterface4 { } public class ClassWithInterface6 : ClassWithInterface4 { } public class ClassWithInterface7 : ClassWithInterface4 { } + public class ClassWithInterface8 : ClassWithInterface4 { } + public class ClassWithInterface9 : ClassWithInterface8 { } [TestCase(typeof(ClassBase), 3)] [TestCase(typeof(Interface1), 6)] @@ -148,6 +150,12 @@ public void TestStandardConstraintWithGenericPass() Assert.IsTrue(collection.Contains(typeof(Interface5))); Assert.IsFalse(collection.Contains(typeof(Interface6))); Assert.IsTrue(collection.Contains(typeof(Interface7))); + Assert.IsFalse(collection.Contains(typeof(Interface8))); + Assert.IsTrue(collection.Contains(typeof(Interface9))); + + //NOTE: not supported since the 2nd argument should be "picked", we don't want to generate all available options + Assert.IsFalse(collection.Contains(typeof(Interface8))); + Assert.IsFalse(collection.Contains(typeof(Interface8))); } [Test] @@ -199,13 +207,17 @@ public void TestSerializeReferenceConstraintWithGenericPass() Assert.IsTrue(collection.Contains(typeof(ClassWithInterface5))); Assert.IsFalse(collection.Contains(typeof(ClassWithInterface6))); Assert.IsFalse(collection.Contains(typeof(ClassWithInterface7))); + Assert.IsTrue(collection.Contains(typeof(ClassWithInterface9))); #if UNITY_2023_2_OR_NEWER - Assert.IsTrue(collection.Contains(typeof(ClassWithInterface7))); Assert.IsTrue(collection.Contains(typeof(ClassWithInterface4))); + Assert.IsTrue(collection.Contains(typeof(ClassWithInterface7))); #else - Assert.IsFalse(collection.Contains(typeof(ClassWithInterface7))); Assert.IsFalse(collection.Contains(typeof(ClassWithInterface4))); + Assert.IsFalse(collection.Contains(typeof(ClassWithInterface7))); #endif + + //NOTE: not supported since the 2nd argument should be "picked", we don't want to generate all available options + Assert.IsFalse(collection.Contains(typeof(ClassWithInterface8))); } } } diff --git a/README.md b/README.md index 3483f689..5bdd6f33 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,10 @@ Unity 2018.x or newer - Enable/disable Toolbox drawers or/and assign custom drawers - Enable/disable Toolbox Scene View and assign hotkeys +--- +> [!IMPORTANT] +> This package is fully IMGUI-based, which means it may conflict with pure UI Toolkit features in your project. Additionally, Toolbox overwrites the 'base' custom Editor for all `UnityEngine.Objects`, it's a common solution but means that you can't combine other Inspector extensions/plugins. + ## Table Of Contents - [Attributes & Drawers](#drawers) @@ -76,6 +80,10 @@ If you want to keep your custom settings between UET versions, create your own s Create/Editor Toolbox/Settings ``` +--- +> [!IMPORTANT] +> If you are getting warnings related to the current settings state, it most likely means that some features are not present in your Unity version. I suggest creating your own settings file and adjusting potential issues. Generally, it's always better to use a custom settings file rather than the default one. I'm planning to replace the ScriptableObject-based solution in the future, so it won't be a problem anymore. + ## Attributes & Drawers ### Regular Drawers From d7afe76b867b703989eb1652ea3f0edce1a4d25b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Matkowski?= Date: Thu, 29 Aug 2024 12:50:35 +0200 Subject: [PATCH 23/23] Update: README.md & samples --- Assets/Examples/Scenes/SampleScene.unity | 33 ++++++------ Assets/Examples/Scripts/SampleBehaviour2.cs | 53 ++++++++++---------- Docs/ignoreparent.png | Bin 0 -> 4330 bytes README.md | 5 ++ 4 files changed, 49 insertions(+), 42 deletions(-) create mode 100644 Docs/ignoreparent.png diff --git a/Assets/Examples/Scenes/SampleScene.unity b/Assets/Examples/Scenes/SampleScene.unity index 8b88216c..58f6e488 100644 --- a/Assets/Examples/Scenes/SampleScene.unity +++ b/Assets/Examples/Scenes/SampleScene.unity @@ -675,17 +675,11 @@ MonoBehaviour: - b - c ints: 01000000080000000c00000010000000 - var21: {fileID: 977748988} - var22: {fileID: 2100000, guid: 7404c70251f9d0045a4aabaa49d83963, type: 2} - var23: {fileID: 2800000, guid: 45980f2b5045fab4a95e80d4cd1d91a8, type: 3} - var24: {fileID: 8300000, guid: e83fc6426e5f2e0448cc3e51102509aa, type: 3} - var25: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} - var27: - i: 2 - strings: - - MainCamera - - Untagged - - Respawn + component: {fileID: 2037155953} + material: {fileID: 2100000, guid: 7404c70251f9d0045a4aabaa49d83963, type: 2} + texture: {fileID: 2800000, guid: d7cf546aa64aceb488a523b6662319b6, type: 3} + audioClip: {fileID: 8300000, guid: e83fc6426e5f2e0448cc3e51102509aa, type: 3} + mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} largeArray: - {fileID: 0} - {fileID: 0} @@ -706,11 +700,18 @@ MonoBehaviour: - {fileID: 0} - {fileID: 0} - {fileID: 0} - q: {x: 0, y: 0, z: 0, w: 0} - a1: -1 - b1: 5.5 - var40: 1.33 - var41: {x: 0, y: 1.9792935} + quaternion: {x: 0, y: 0, z: 0, w: 0} + q2: {x: 0, y: 0, z: 0, w: 0} + min: -1 + max: 5.5 + dynamicRange: 1.5 + dynamicMinMax: {x: 0, y: 3} + nestedObject: + i: 1 + strings: + - EditorOnly + - Player + - Untagged --- !u!4 &661896459 Transform: m_ObjectHideFlags: 2 diff --git a/Assets/Examples/Scripts/SampleBehaviour2.cs b/Assets/Examples/Scripts/SampleBehaviour2.cs index 49a2e28e..d7cc1ac2 100644 --- a/Assets/Examples/Scripts/SampleBehaviour2.cs +++ b/Assets/Examples/Scripts/SampleBehaviour2.cs @@ -27,24 +27,44 @@ public int GetValue() [Label("InLine Editor", skinStyle: SkinStyle.Box)] [InLineEditor(DisableEditor = false)] - public Transform var21; + public Component component; [InLineEditor(drawSettings: true)] - public Material var22; + public Material material; [InLineEditor(true, true)] - public Texture var23; + public Texture texture; [InLineEditor(drawSettings: true)] - public AudioClip var24; + public AudioClip audioClip; [InLineEditor(HideScript = true)] - public Mesh var25; + public Mesh mesh; - [Label("Nested Properties", skinStyle: SkinStyle.Box)] + [Label("Scrollable Items", skinStyle: SkinStyle.Box)] + + [ScrollableItems(defaultMinIndex: 0, defaultMaxIndex: 5)] + public GameObject[] largeArray = new GameObject[19]; + + [Label("Ignore Parent", skinStyle: SkinStyle.Box)] + + public Quaternion quaternion; + [IgnoreParent] + public Quaternion q2; + + [Label("Dynamic Range & MinMax Slider", skinStyle: SkinStyle.Box)] + + public float min = -1; + public float max = 5.5f; + [DynamicRange(nameof(min), nameof(max))] + public float dynamicRange; + [DynamicMinMaxSlider(nameof(min), nameof(max))] + public Vector2 dynamicMinMax; + + [Label("Nested Objects", skinStyle: SkinStyle.Box)] [Help("You can use Toolbox Properties inside serializable types without limitations.")] - public SampleNestedClass var27; + public SampleNestedClass nestedObject; [System.Serializable] public class SampleNestedClass @@ -55,23 +75,4 @@ public class SampleNestedClass [Help("Nested Information.", ApplyCondition = true)] public string[] strings; } - - [Label("Scrollable Items", skinStyle: SkinStyle.Box)] - - [ScrollableItems(defaultMinIndex: 0, defaultMaxIndex: 5)] - public GameObject[] largeArray = new GameObject[19]; - - [Label("Ignore Parent", skinStyle: SkinStyle.Box)] - - [IgnoreParent] - public Quaternion q; - - [Label("Dynamic Range & MinMax Slider", skinStyle: SkinStyle.Box)] - - public float a1 = -1; - public float b1 = 5.5f; - [DynamicRange(nameof(a1), nameof(b1))] - public float var40; - [DynamicMinMaxSlider(nameof(a1), nameof(b1))] - public Vector2 var41; } \ No newline at end of file diff --git a/Docs/ignoreparent.png b/Docs/ignoreparent.png new file mode 100644 index 0000000000000000000000000000000000000000..3fa6aab772109708a8cee4b3896368b175df8630 GIT binary patch literal 4330 zcmcgwc{r5o-+xBg*N#xhmZc-5O^LB&ONgjy!6 zEzCEp&AZSUf&{`1bhRvl?7t3eA~F^?+vX5gOMBkpY0Yoc9HpF5z0o&UUDK4>3@utB zYnvnP9&bFgk8?kp6-qbK#9-g~yWUa?mN93exx_!iOBOx+JUpfgd>Qkrf*Rd8N+)HU z>kVHXg;0i@4qI!k&nutKy{VZ?xk(8ibSGVMf@lasSUp#oqK=8hO0 zpHo&+5Pn zx+Ru>e0Lo;NTccXfr$)-OL!e_U2nl)`RlWtEheNKUA;ymoDMu+j}n zr^=Tf9Vu_zsJ(xG__gw+u-BUQlPxcMuxS$yO&pH#7Bb9qrcjX$i2$mAJ;e5W;-|ME84_ARC!oiSo9`| z!R>=+tc%e1O8cZUKA)rN9D{>v*UzOq^1H_ZX&groI$zn&TaE``EludRdcU&%y<0Xb zz=u*&-ms4=`U@|1@516@QMTWBm-^aFg00`kJ3-oztou-)chrtztz*UN8A@88Hk?``uLc7h4 zs=B)MccrM*_8mKR=;-JqYig7K&7g1hd1PK^9YMVt z9F!l)QTFy4#OpmA%InkAI|GQRDZ4QMnh-oh;9UKp{(zz zGnp4N8N?`GZCxz3TGfAj#YcY3R8KFOM~3Rsl83_`$!-WvXvS1}mH<4+4(o6n->k`PHje zI5>7{u)S{e`x7bm5{+5%Z9~t6lY95Y`XBn)Eu=ZZrhVhMy(6xDWB&vnx5Vktjg@bQ$OS}*kGuhB1G_;`3G_BD+1U{!EWi;4ybJ|iCG^`}pqc<2T@{KhGEZD7F0 z&d$!lBJB`%_9NQV^!}@FN8AY3*49Q(Hy3&l%rzAwOTso8*ifiR`*0v3J}D{5@z@@| zSeM(mxoQjDflt3l3DSY@Q>tHn{ZNfuUHagytfW+UJc89nimG?%60IS0?Zk-_&XZH} zD|a}T?}cxy0^Let9-_h)TF=QZrLYc)Jio;;DEmJ}EF zsa@}kA`Vo#A<$?XkJqOL+}*o}8rS;OB3Nx_Fy4Rsao))2%Nh|aO{Hmg?PnWkO>7zFq_rOj zCu5tqYz^`E31dgqv_9U#_uLjVfR3l;D=7@J{zEVermUV1Vh`16Gqf_qiz9>vhb54Z*ZV)0Ze^>SMh($doN!wch|Trlr!#bIW@e$C*0-;trPwzjso z`}$u|aCJ)!sX7=7f`r3f_j3{T#DuT`Ul9ain;51Fw1A7i)H8ZWZ> z9Z_jlOp48=DHfyw{GF-?XySaavY!$Y5)z7w4~6oCjqxzIVg*bA@9*z-adSf;5Yzj@ zTu987A1R9t2@h|a=?o4D3E-7DNi*R`HVI=%=)h?e6%_z_ZA@b}rU2|V9!|4Ip@{Ci zavHZIowjaPj0$mZ_yn9+h9*AoSjpQ04b0T(gu>h%g8;u=okrQz8y24UtRhZbqr7v;w;~zBV;e-tvmQfdz?(f z9hL^!L{lX9+*Pg}4Z*{@Jr*ySWmRlGs=x8x;#9x66%tv*-sJsjkO&@*YPi1IUt*2S&d3nr*xAQE$4tl@Of}P^ z)|zj!y9`Y^xqfL+k#2T075OHy#TN;OVb9H_l>x+W?E?Du89COZ2+{(0cVIkx!+~wK(e^x zi`eW0)kc6G5g<&euc^7VxxuKtlU?I8a?Z<(-qaLP78yRmEEbP};o#gfjnk(yGc(`y z^*!zY^;2Z`?!w~&yxR)~Iq;8KprrJeA2K_(1v{Lk$i>aQ{PjatN{Up883NX`&4&j~ zLrtyDf70AGyO!;t>z3T#k<@o{8Q>4f$pr=kOv+2DZc*%Xkjl=+mYSMcOC%~NC{W5B zG}YBh|1n9yThQ;GxO4YzDyE?Sl<>=~0Ev#?4r);e32PTn%_IeeRk6C=d+ET*PoGu# zu{+Utu+bn56F}-Di^jqN0p3B{cK}K1`1FYfT;;cwA9^Z{>i!0TRsOYMpw_Q;9e9bI z8EVWyrs1af%)I(f-f)wmii(PMc69jfGP`)uvz89q?AS~9RW;y8N(Ks(&{m+Ls)Z~) zJ%mD`EG#Va_4SdQ>)S>qX%n~y3(8T|UO; zaal-6=);Svy%uNvx7BDz0L@rOp2t{627|!}=DL-%l_NIXzw%h}$~M#|sYZr|eEZMb z=l<_Y+Ju%+IV#v2Oo18A+t}@;H{JA!A!>t_pNoQ1+Y(zKBEe^mn%2;K)^+x$xAS%R zkwMXQyIdYg9ZZFsWQ^Rc@Z5iEfnwnRxB+l`klvY}p7>9-3J zj{&AFv}dD4(0rRAk@?9mGt5?S9F8JdpwZ~Sz$MVumPP)4XDel2V`gV(vr4VJz01oY zC$=wEVX}sTO-xLTjT6fv3%B#Q3R7NMI`rIKP@;VpwmlG(w&`h9)s_A#4~jqU;izpO zIk1DJoq6a$dM%r9`!DS^Vrbgn^-#yeBuRr!w|N^n0s7g5|6hkQCVCznMC4hHkjdoN zIm*?~pBMUidS2+5oAW`keD{qZ=9;_(c>^H+H-StAZ44;ZEJJ? z+d!tKZDBURxlAIFOn+BWRo%z26Z}YBq7R`Q95g{sYRHfr7T?yc2|-y|d3cxu= z^Yrp8!44CVS_rQ=9GS`@#Pd5M-cdqFbizc;mkS Dpx{01 literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 5bdd6f33..d6e747e5 100644 --- a/README.md +++ b/README.md @@ -550,11 +550,16 @@ public GameObject[] largeArray = new GameObject[19]; ##### Other ToolboxProperty attributes +**IgnoreParent** allows you to hide the parent's label, foldout arrow and remove the standard indentation for nested fields. + ```csharp +public Quaternion quaternion; [IgnoreParent] public Quaternion q; ``` +![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/ignoreparent.png) + ```csharp [DynamicMinMaxSlider(nameof(minValue), nameof(MaxValue))] public Vector2 vec2;