From 8a40bb675971324c81902301e48b1ee4ec5f9cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Sidenvall?= Date: Thu, 5 Oct 2023 08:48:46 +0200 Subject: [PATCH 01/16] wip --- .../InputActionReferencePropertyDrawer.cs | 70 +++++++++++++++++++ ...InputActionReferencePropertyDrawer.cs.meta | 3 + 2 files changed, 73 insertions(+) create mode 100644 Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs create mode 100644 Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs.meta diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs new file mode 100644 index 0000000000..0306843282 --- /dev/null +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs @@ -0,0 +1,70 @@ +using UnityEditor; + +namespace UnityEngine.InputSystem.Editor +{ + [CustomPropertyDrawer(typeof(InputActionReference))] + public class InputActionReferencePropertyDrawer : PropertyDrawer + { + static class Styles + { + public static readonly GUIStyle popup = new GUIStyle("PaneOptions") { imagePosition = ImagePosition.ImageOnly }; + } + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + // Using BeginProperty / EndProperty on the parent property means that + // // prefab override logic works on the entire property. + label = EditorGUI.BeginProperty(position, label, property); + + DrawProperty(position, property, label); + + EditorGUI.EndProperty(); + } + + private void DrawProperty(Rect position, SerializedProperty property, GUIContent label) + { + position = EditorGUI.PrefixLabel(position, label); + EditorGUI.PropertyField(position, property, GUIContent.none); + } + + private void DrawAltProperty(Rect position, SerializedProperty property, GUIContent label) + { + position = EditorGUI.PrefixLabel(position, label); + + /*var assetProperty = property.FindPropertyRelative("m_Asset"); + var actionIdProperty = property.FindPropertyRelative("m_ActionId");*/ + + /*var popupStyle = Styles.popup; + var buttonRect = position; + buttonRect.yMin += popupStyle.margin.top + 1f; + buttonRect.width = popupStyle.fixedWidth + popupStyle.margin.right; + buttonRect.height = EditorGUIUtility.singleLineHeight; + buttonRect.x = position.x - buttonRect.height;*/ + //position.xMin = buttonRect.xMax; + + // Don't make child fields be indented + //var indent = EditorGUI.indentLevel; + //EditorGUI.indentLevel = 0; + + // Using BeginProperty / EndProperty on the popup button allows the user to + // revert prefab overrides to Use Reference by right-clicking the configuration button. + //EditorGUI.BeginProperty(buttonRect, GUIContent.none, property); + + /*EditorGUI.BeginProperty(buttonRect, GUIContent.none, useReference); + using (var check = new EditorGUI.ChangeCheckScope()) + { + var newPopupIndex = EditorGUI.Popup(buttonRect, GetCompactPopupIndex(useReference), Contents.compactPopupOptions, popupStyle); + if (check.changed) + useReference.boolValue = IsUseReference(newPopupIndex); + } + EditorGUI.EndProperty();*/ + + //EditorGUI.EndProperty(); + + EditorGUI.PropertyField(position, property, GUIContent.none); + //label = EditorGUILayout.PropertyField(property, label, true); + + //EditorGUI.indentLevel = indent; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs.meta b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs.meta new file mode 100644 index 0000000000..81dbe3820f --- /dev/null +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 51c21f59436e49b2b33f24614146473c +timeCreated: 1696451307 \ No newline at end of file From c5b7cff94258707a9dcffa86e7eb5ead5e84515d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Sidenvall?= Date: Thu, 5 Oct 2023 14:26:06 +0200 Subject: [PATCH 02/16] wip object picker for Input Action References --- .../AssetImporter/InputActionImporter.cs | 4 +- .../InputActionRefferenceSearchProvider.cs | 145 ++++++++++++++++++ ...nputActionRefferenceSearchProvider.cs.meta | 3 + 3 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs create mode 100644 Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs.meta diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs index 3edceebd36..032b89b3a1 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs @@ -29,8 +29,8 @@ internal class InputActionImporter : ScriptedImporter { private const int kVersion = 13; - private const string kActionIcon = "Packages/com.unity.inputsystem/InputSystem/Editor/Icons/InputAction.png"; - private const string kAssetIcon = "Packages/com.unity.inputsystem/InputSystem/Editor/Icons/InputActionAsset.png"; + internal const string kActionIcon = "Packages/com.unity.inputsystem/InputSystem/Editor/Icons/InputAction.png"; + internal const string kAssetIcon = "Packages/com.unity.inputsystem/InputSystem/Editor/Icons/InputActionAsset.png"; [SerializeField] private bool m_GenerateWrapperCode; [SerializeField] private string m_WrapperCodePath; diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs new file mode 100644 index 0000000000..9d6d7352fe --- /dev/null +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs @@ -0,0 +1,145 @@ +using System.Collections.Generic; +using UnityEditor; +using UnityEditor.Search; + +// TODO Why is project wide input asset (InputManager.asset) not up to date when loaded? +// TODO Fix asset icons to make sense +// TODO Fix filter so that search is possible, what is default method to fallback to it? +// TODO Why is grouping not working as expected? +// TODO Possible to remove/eliminate options in search? +// TODO Why is picker flag not making a difference? +// TODO Does it make sense to fetch assets as currently done + +namespace UnityEngine.InputSystem.Editor +{ + static class InputActionReferenceSearchProviderConstants + { + internal const string type = "InputActionReference"; // This allows picking up also assets + internal const string defaultSearchQuery = "t:InputActionReference"; + //internal const string displayName = "Input Action"; + } + + static class InputActionReferenceSearchProvider + { + [SearchItemProvider] + internal static SearchProvider CreateProjectSettingsAssetProvider() + { + return new SearchProvider(InputActionReferenceSearchProviderConstants.type, "Project Settings") + { + priority = 25, + showDetails = true, + showDetailsOptions = ShowDetailsOptions.Default | ShowDetailsOptions.DefaultGroup, + toObject = (item, type) => GetObject(item, type), + fetchItems = (context, items, provider) => SearchDefaultCustomAssets(context, provider), + }; + } + + [SearchItemProvider] + internal static SearchProvider CreateAssetDatabaseProvider() + { + return new SearchProvider(InputActionReferenceSearchProviderConstants.type, "Assets") + { + priority = 25, + showDetails = true, // true + showDetailsOptions = ShowDetailsOptions.Default | ShowDetailsOptions.DefaultGroup, + toObject = (item, type) => GetObject(item, type), + fetchItems = (context, items, provider) => SearchStandardAssets(context, provider), + }; + } + + static IEnumerable SearchDefaultCustomAssets(SearchContext context, SearchProvider provider) + { + // TODO This could in theory be another icon to differentiate a project-wide action + var icon = AssetDatabase.GetCachedIcon(ProjectWideActionsAsset.kAssetPath) as Texture2D; + + // This yields all accepted assets (InputActionReference) from ProjectWideActionsAsset.kAssetPath. + var assets = AssetDatabase.LoadAllAssetsAtPath(ProjectWideActionsAsset.kAssetPath); // TODO Why does this return an outdated asset?! + foreach (var asset in assets) + { + // We filter the returned result to only contain InputActionReference types since this + // otherwise would also pick up InputActionMaps + //if (AcceptAsset(asset)) + yield return provider.CreateItem(context, asset.GetInstanceID().ToString(), asset.name, + "Input Action Reference (Project Settings)", icon, asset); + } + } + + static IEnumerable SearchStandardAssets(SearchContext context, SearchProvider provider) + { + // TODO This could in theory be another icone, e.g. action icon, but this seems to be what is registered + //var icon = AssetDatabase.GetCachedIcon(ProjectWideActionsAsset.kAssetPath) as Texture2D; + var icon = (Texture2D)EditorGUIUtility.Load(InputActionImporter.kActionIcon); + + // Note that this would just find the first InputActionReference within each InputActionMap + // so it could be questioned whether we should just look for maps here? + // However, this might pickup any other asset that may contain InputActionReference which might + // be better from a future-proofing perspective. + var guids = AssetDatabase.FindAssets($"t:{typeof(InputActionReference)}"); + foreach (var guid in guids) + { + // We use LoadAllAssetsAtPath to load all InputActionReference assets within whatever we found + var assetPath = AssetDatabase.GUIDToAssetPath(guid); + var assets = AssetDatabase.LoadAllAssetsAtPath(assetPath); + foreach (var asset in assets) + yield return provider.CreateItem(context, asset.GetInstanceID().ToString(), asset.name, + $"Input Action Reference ({assetPath})", icon, asset); + } + } + + static Object GetObject(SearchItem item, System.Type type) + { + return item.data as Object; + } + + [MenuItem("Test/Load Input Manager")] + static void LoadInputManager() + { + var assets = AssetDatabase.LoadAllAssetsAtPath(ProjectWideActionsAsset.kAssetPath); + foreach (var asset in assets) + { + Debug.Log($"asset: {asset.name} {asset.GetType()} {AcceptAsset(asset)}"); + } + } + + static bool AcceptAsset(Object asset) + { + // Only include assets of type InputActionReference + if (asset.GetType() == typeof(InputActionReference)) + return true; + return false; + } + } + + // Custom property drawer in order to use the Advance picker: + [CustomPropertyDrawer(typeof(InputActionReference))] + public class MyCustomAssetPropertyDrawer : PropertyDrawer + { + private SearchContext m_Context; + public MyCustomAssetPropertyDrawer() + { + // Create a SearchContext with the normal asset provider which should be used to filter your type. + // Add to it the DefaultCustomAsset provider to yield all defaults assets. + //var assetProvider = UnityEditor.Search.SearchService.GetProvider("asset"); // TODO This is what allows us to find InputActionReferences + var assetProvider = InputActionReferenceSearchProvider.CreateAssetDatabaseProvider(); + var defaultProvider = InputActionReferenceSearchProvider.CreateProjectSettingsAssetProvider(); + + // Note that since we use custom providers we can skip using a type-based query + m_Context = UnityEditor.Search.SearchService.CreateContext( + new[] { assetProvider, defaultProvider }, + "", + SearchFlags.Sorted | SearchFlags.OpenPicker); // t:InputActionReference seems to be required to find InputActionReferences in regular assets? + } + + // Draw the property inside the given rect + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + // Pop the picker. + // IMPORTANT Note: in your case the filterType should be typeof(InputActionReference) + // If the default asset in InputManager were InputActionReference as well (it doesn't seem to be the case for me) you wouldn't need + // to specify the custom query above (t:MyCustomAsset) + // FINDING: .inputactions objects only found if having typeof(Object) + // FINDING: having proper typeof(InputActionReference) does not include InputActionReference results + ObjectField.DoObjectField(position, property, typeof(InputActionReference), label, m_Context); + } + } +} diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs.meta b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs.meta new file mode 100644 index 0000000000..343a83f26a --- /dev/null +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3a321ed133764ac2b2ca53fde879482d +timeCreated: 1696488621 \ No newline at end of file From d7dd88c96bf48cc72302f15f223234ee5d2d0b4b Mon Sep 17 00:00:00 2001 From: Sebastien Phaneuf Date: Thu, 5 Oct 2023 13:04:16 -0400 Subject: [PATCH 03/16] Simplified the advance picker workflow. Add a MonoBehavior to test picking InputReference --- Assets/InputActionReferenceContainer.cs | 30 ++ Assets/InputActionReferenceContainer.cs.meta | 2 + Assets/SceneWithInputContainer.unity | 381 ++++++++++++++++++ Assets/SceneWithInputContainer.unity.meta | 7 + .../InputActionRefferenceSearchProvider.cs | 105 +---- 5 files changed, 441 insertions(+), 84 deletions(-) create mode 100644 Assets/InputActionReferenceContainer.cs create mode 100644 Assets/InputActionReferenceContainer.cs.meta create mode 100644 Assets/SceneWithInputContainer.unity create mode 100644 Assets/SceneWithInputContainer.unity.meta diff --git a/Assets/InputActionReferenceContainer.cs b/Assets/InputActionReferenceContainer.cs new file mode 100644 index 0000000000..278d8f8858 --- /dev/null +++ b/Assets/InputActionReferenceContainer.cs @@ -0,0 +1,30 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.InputSystem; + +public class InputActionContainer: MonoBehaviour +{ + public InputAction myAction; + public InputActionReference myReference; + public InputActionReference mySecondReferenceWithAVeryLongName; + public InputActionProperty myProperty; + public InputActionAsset myAsset; + public InputControl myControl; + + // Start is called before the first frame update + void Start() + { + if (myReference.action != null) + myReference.action.performed += context => { Debug.Log("Performed"); }; + } + + // Update is called once per frame + void Update() + { + } +} \ No newline at end of file diff --git a/Assets/InputActionReferenceContainer.cs.meta b/Assets/InputActionReferenceContainer.cs.meta new file mode 100644 index 0000000000..3cb5f399a4 --- /dev/null +++ b/Assets/InputActionReferenceContainer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: abb3ee11c825d6e41b8740fcfc377222 \ No newline at end of file diff --git a/Assets/SceneWithInputContainer.unity b/Assets/SceneWithInputContainer.unity new file mode 100644 index 0000000000..2d28f9138b --- /dev/null +++ b/Assets/SceneWithInputContainer.unity @@ -0,0 +1,381 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 10 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0.46169513, g: 0.5124164, b: 0.58993304, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 1 + m_PVRFilteringGaussRadiusAO: 1 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &88645882 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 88645885} + - component: {fileID: 88645884} + - component: {fileID: 88645883} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &88645883 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 88645882} + m_Enabled: 1 +--- !u!20 &88645884 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 88645882} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &88645885 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 88645882} + serializedVersion: 2 + 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_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &730029164 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 730029165} + - component: {fileID: 730029166} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &730029165 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 730029164} + serializedVersion: 2 + 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_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &730029166 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 730029164} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: abb3ee11c825d6e41b8740fcfc377222, type: 3} + m_Name: + m_EditorClassIdentifier: + myAction: + m_Name: My + m_Type: 0 + m_ExpectedControlType: + m_Id: ad881367-1275-4d43-9175-61675f8ecc6c + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + myReference: {fileID: 0} + mySecondReferenceWithAVeryLongName: {fileID: 0} + myProperty: + m_UseReference: 0 + m_Action: + m_Name: My Property + m_Type: 0 + m_ExpectedControlType: + m_Id: e04f2259-efc2-41c2-97bd-86854b61922a + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} + myAsset: {fileID: 0} +--- !u!1 &1013191913 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1013191915} + - component: {fileID: 1013191914} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1013191914 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1013191913} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 1 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1013191915 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1013191913} + serializedVersion: 2 + 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_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 88645885} + - {fileID: 1013191915} + - {fileID: 730029165} diff --git a/Assets/SceneWithInputContainer.unity.meta b/Assets/SceneWithInputContainer.unity.meta new file mode 100644 index 0000000000..a596b3ee11 --- /dev/null +++ b/Assets/SceneWithInputContainer.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 908750d0cc8bbc342a41f37bbaac8876 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs index 9d6d7352fe..d72b9f6dea 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs @@ -15,39 +15,23 @@ namespace UnityEngine.InputSystem.Editor static class InputActionReferenceSearchProviderConstants { internal const string type = "InputActionReference"; // This allows picking up also assets - internal const string defaultSearchQuery = "t:InputActionReference"; - //internal const string displayName = "Input Action"; } static class InputActionReferenceSearchProvider { - [SearchItemProvider] + // No need to use the SearchItemProvider -> this attribute is used to register the provider to the SearchWindow. + // [SearchItemProvider] internal static SearchProvider CreateProjectSettingsAssetProvider() { return new SearchProvider(InputActionReferenceSearchProviderConstants.type, "Project Settings") { priority = 25, - showDetails = true, - showDetailsOptions = ShowDetailsOptions.Default | ShowDetailsOptions.DefaultGroup, toObject = (item, type) => GetObject(item, type), - fetchItems = (context, items, provider) => SearchDefaultCustomAssets(context, provider), + fetchItems = (context, items, provider) => SearchProjectSettingsInputReferenceActionAssets(context, provider), }; } - [SearchItemProvider] - internal static SearchProvider CreateAssetDatabaseProvider() - { - return new SearchProvider(InputActionReferenceSearchProviderConstants.type, "Assets") - { - priority = 25, - showDetails = true, // true - showDetailsOptions = ShowDetailsOptions.Default | ShowDetailsOptions.DefaultGroup, - toObject = (item, type) => GetObject(item, type), - fetchItems = (context, items, provider) => SearchStandardAssets(context, provider), - }; - } - - static IEnumerable SearchDefaultCustomAssets(SearchContext context, SearchProvider provider) + static IEnumerable SearchProjectSettingsInputReferenceActionAssets(SearchContext context, SearchProvider provider) { // TODO This could in theory be another icon to differentiate a project-wide action var icon = AssetDatabase.GetCachedIcon(ProjectWideActionsAsset.kAssetPath) as Texture2D; @@ -56,90 +40,43 @@ static IEnumerable SearchDefaultCustomAssets(SearchContext context, var assets = AssetDatabase.LoadAllAssetsAtPath(ProjectWideActionsAsset.kAssetPath); // TODO Why does this return an outdated asset?! foreach (var asset in assets) { - // We filter the returned result to only contain InputActionReference types since this - // otherwise would also pick up InputActionMaps - //if (AcceptAsset(asset)) - yield return provider.CreateItem(context, asset.GetInstanceID().ToString(), asset.name, - "Input Action Reference (Project Settings)", icon, asset); - } - } - - static IEnumerable SearchStandardAssets(SearchContext context, SearchProvider provider) - { - // TODO This could in theory be another icone, e.g. action icon, but this seems to be what is registered - //var icon = AssetDatabase.GetCachedIcon(ProjectWideActionsAsset.kAssetPath) as Texture2D; - var icon = (Texture2D)EditorGUIUtility.Load(InputActionImporter.kActionIcon); - - // Note that this would just find the first InputActionReference within each InputActionMap - // so it could be questioned whether we should just look for maps here? - // However, this might pickup any other asset that may contain InputActionReference which might - // be better from a future-proofing perspective. - var guids = AssetDatabase.FindAssets($"t:{typeof(InputActionReference)}"); - foreach (var guid in guids) - { - // We use LoadAllAssetsAtPath to load all InputActionReference assets within whatever we found - var assetPath = AssetDatabase.GUIDToAssetPath(guid); - var assets = AssetDatabase.LoadAllAssetsAtPath(assetPath); - foreach (var asset in assets) - yield return provider.CreateItem(context, asset.GetInstanceID().ToString(), asset.name, - $"Input Action Reference ({assetPath})", icon, asset); + var label = asset.name; + if (asset is InputActionReference && label.Contains(context.searchText, System.StringComparison.InvariantCultureIgnoreCase)) + yield return provider.CreateItem(context, asset.GetInstanceID().ToString(), label, + "Input Action Reference (Project Settings)", icon, asset); } - } + } static Object GetObject(SearchItem item, System.Type type) { return item.data as Object; } - - [MenuItem("Test/Load Input Manager")] - static void LoadInputManager() - { - var assets = AssetDatabase.LoadAllAssetsAtPath(ProjectWideActionsAsset.kAssetPath); - foreach (var asset in assets) - { - Debug.Log($"asset: {asset.name} {asset.GetType()} {AcceptAsset(asset)}"); - } - } - - static bool AcceptAsset(Object asset) - { - // Only include assets of type InputActionReference - if (asset.GetType() == typeof(InputActionReference)) - return true; - return false; - } } // Custom property drawer in order to use the Advance picker: [CustomPropertyDrawer(typeof(InputActionReference))] - public class MyCustomAssetPropertyDrawer : PropertyDrawer + public class AdvanceInputActionReferencePropertyDrawer : PropertyDrawer { private SearchContext m_Context; - public MyCustomAssetPropertyDrawer() + public AdvanceInputActionReferencePropertyDrawer() { - // Create a SearchContext with the normal asset provider which should be used to filter your type. - // Add to it the DefaultCustomAsset provider to yield all defaults assets. - //var assetProvider = UnityEditor.Search.SearchService.GetProvider("asset"); // TODO This is what allows us to find InputActionReferences - var assetProvider = InputActionReferenceSearchProvider.CreateAssetDatabaseProvider(); + // By default ADB search provider yields ALL assets even if the search query is empty. AssetProvider will NOT yield anything if searchQuery is empty + var adbProvider = UnityEditor.Search.SearchService.GetProvider("adb"); var defaultProvider = InputActionReferenceSearchProvider.CreateProjectSettingsAssetProvider(); - - // Note that since we use custom providers we can skip using a type-based query m_Context = UnityEditor.Search.SearchService.CreateContext( - new[] { assetProvider, defaultProvider }, + new[] { adbProvider, defaultProvider }, "", - SearchFlags.Sorted | SearchFlags.OpenPicker); // t:InputActionReference seems to be required to find InputActionReferences in regular assets? + // SearchFlags : these flags are used to customize how search is performed and how search results are displayed. + SearchFlags.Sorted | SearchFlags.OpenPicker | SearchFlags.Packages); + } - // Draw the property inside the given rect public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { - // Pop the picker. - // IMPORTANT Note: in your case the filterType should be typeof(InputActionReference) - // If the default asset in InputManager were InputActionReference as well (it doesn't seem to be the case for me) you wouldn't need - // to specify the custom query above (t:MyCustomAsset) - // FINDING: .inputactions objects only found if having typeof(Object) - // FINDING: having proper typeof(InputActionReference) does not include InputActionReference results - ObjectField.DoObjectField(position, property, typeof(InputActionReference), label, m_Context); + // Search.SearchViewFlags : these flags are used to customize the appearance of the PickerWindow. + + ObjectField.DoObjectField(position, property, typeof(InputActionReference), label, m_Context, + Search.SearchViewFlags.OpenInBuilderMode | Search.SearchViewFlags.DisableBuilderModeToggle | Search.SearchViewFlags.DisableInspectorPreview | Search.SearchViewFlags.DisableSavedSearchQuery); } } } From feba8d4a4cc5fd3ae91be110cc79fce11209a97c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Sidenvall?= Date: Thu, 5 Oct 2023 21:15:51 +0200 Subject: [PATCH 04/16] Refactoring --- .../InputActionReferencePropertyDrawer.cs | 70 ------------------- ...InputActionReferencePropertyDrawer.cs.meta | 3 - .../InputActionRefferenceSearchProvider.cs | 48 ++++++++----- 3 files changed, 29 insertions(+), 92 deletions(-) delete mode 100644 Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs delete mode 100644 Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs.meta diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs deleted file mode 100644 index 0306843282..0000000000 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs +++ /dev/null @@ -1,70 +0,0 @@ -using UnityEditor; - -namespace UnityEngine.InputSystem.Editor -{ - [CustomPropertyDrawer(typeof(InputActionReference))] - public class InputActionReferencePropertyDrawer : PropertyDrawer - { - static class Styles - { - public static readonly GUIStyle popup = new GUIStyle("PaneOptions") { imagePosition = ImagePosition.ImageOnly }; - } - - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - // Using BeginProperty / EndProperty on the parent property means that - // // prefab override logic works on the entire property. - label = EditorGUI.BeginProperty(position, label, property); - - DrawProperty(position, property, label); - - EditorGUI.EndProperty(); - } - - private void DrawProperty(Rect position, SerializedProperty property, GUIContent label) - { - position = EditorGUI.PrefixLabel(position, label); - EditorGUI.PropertyField(position, property, GUIContent.none); - } - - private void DrawAltProperty(Rect position, SerializedProperty property, GUIContent label) - { - position = EditorGUI.PrefixLabel(position, label); - - /*var assetProperty = property.FindPropertyRelative("m_Asset"); - var actionIdProperty = property.FindPropertyRelative("m_ActionId");*/ - - /*var popupStyle = Styles.popup; - var buttonRect = position; - buttonRect.yMin += popupStyle.margin.top + 1f; - buttonRect.width = popupStyle.fixedWidth + popupStyle.margin.right; - buttonRect.height = EditorGUIUtility.singleLineHeight; - buttonRect.x = position.x - buttonRect.height;*/ - //position.xMin = buttonRect.xMax; - - // Don't make child fields be indented - //var indent = EditorGUI.indentLevel; - //EditorGUI.indentLevel = 0; - - // Using BeginProperty / EndProperty on the popup button allows the user to - // revert prefab overrides to Use Reference by right-clicking the configuration button. - //EditorGUI.BeginProperty(buttonRect, GUIContent.none, property); - - /*EditorGUI.BeginProperty(buttonRect, GUIContent.none, useReference); - using (var check = new EditorGUI.ChangeCheckScope()) - { - var newPopupIndex = EditorGUI.Popup(buttonRect, GetCompactPopupIndex(useReference), Contents.compactPopupOptions, popupStyle); - if (check.changed) - useReference.boolValue = IsUseReference(newPopupIndex); - } - EditorGUI.EndProperty();*/ - - //EditorGUI.EndProperty(); - - EditorGUI.PropertyField(position, property, GUIContent.none); - //label = EditorGUILayout.PropertyField(property, label, true); - - //EditorGUI.indentLevel = indent; - } - } -} \ No newline at end of file diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs.meta b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs.meta deleted file mode 100644 index 81dbe3820f..0000000000 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 51c21f59436e49b2b33f24614146473c -timeCreated: 1696451307 \ No newline at end of file diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs index d72b9f6dea..3df4809e18 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs @@ -1,3 +1,7 @@ +// Note: If not UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS we do not use a custom property drawer and +// picker for InputActionReferences but rather rely on default (classic) object picker. +#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS + using System.Collections.Generic; using UnityEditor; using UnityEditor.Search; @@ -12,18 +16,16 @@ namespace UnityEngine.InputSystem.Editor { - static class InputActionReferenceSearchProviderConstants - { - internal const string type = "InputActionReference"; // This allows picking up also assets - } - static class InputActionReferenceSearchProvider { - // No need to use the SearchItemProvider -> this attribute is used to register the provider to the SearchWindow. + private const string kInputActionReferenceType = "InputActionReference"; + + // No need to use the SearchItemProvider -> this attribute is used to register the provider to + // the SearchWindow and here we are mainly interested in using SearchItemProvider as a picker. // [SearchItemProvider] internal static SearchProvider CreateProjectSettingsAssetProvider() { - return new SearchProvider(InputActionReferenceSearchProviderConstants.type, "Project Settings") + return new SearchProvider(kInputActionReferenceType, "Project Settings") { priority = 25, toObject = (item, type) => GetObject(item, type), @@ -37,7 +39,8 @@ static IEnumerable SearchProjectSettingsInputReferenceActionAssets(S var icon = AssetDatabase.GetCachedIcon(ProjectWideActionsAsset.kAssetPath) as Texture2D; // This yields all accepted assets (InputActionReference) from ProjectWideActionsAsset.kAssetPath. - var assets = AssetDatabase.LoadAllAssetsAtPath(ProjectWideActionsAsset.kAssetPath); // TODO Why does this return an outdated asset?! + // TODO Why does this return an outdated asset?! Must be a problem unrelated to this search. + var assets = AssetDatabase.LoadAllAssetsAtPath(ProjectWideActionsAsset.kAssetPath); foreach (var asset in assets) { var label = asset.name; @@ -45,9 +48,9 @@ static IEnumerable SearchProjectSettingsInputReferenceActionAssets(S yield return provider.CreateItem(context, asset.GetInstanceID().ToString(), label, "Input Action Reference (Project Settings)", icon, asset); } - } + } - static Object GetObject(SearchItem item, System.Type type) + private static Object GetObject(SearchItem item, System.Type type) { return item.data as Object; } @@ -55,20 +58,22 @@ static Object GetObject(SearchItem item, System.Type type) // Custom property drawer in order to use the Advance picker: [CustomPropertyDrawer(typeof(InputActionReference))] - public class AdvanceInputActionReferencePropertyDrawer : PropertyDrawer + public sealed class InputActionReferencePropertyDrawer : PropertyDrawer { - private SearchContext m_Context; - public AdvanceInputActionReferencePropertyDrawer() + private readonly SearchContext m_Context; + + public InputActionReferencePropertyDrawer() { - // By default ADB search provider yields ALL assets even if the search query is empty. AssetProvider will NOT yield anything if searchQuery is empty + // By default ADB search provider yields ALL assets even if the search query is empty. + // AssetProvider ("asset") will NOT yield anything if searchQuery is empty. var adbProvider = UnityEditor.Search.SearchService.GetProvider("adb"); - var defaultProvider = InputActionReferenceSearchProvider.CreateProjectSettingsAssetProvider(); + var projectSettingsProvider = InputActionReferenceSearchProvider.CreateProjectSettingsAssetProvider(); m_Context = UnityEditor.Search.SearchService.CreateContext( - new[] { adbProvider, defaultProvider }, + new[] { adbProvider, projectSettingsProvider }, "", - // SearchFlags : these flags are used to customize how search is performed and how search results are displayed. + // SearchFlags : these flags are used to customize how search is performed and how search + // results are displayed. SearchFlags.Sorted | SearchFlags.OpenPicker | SearchFlags.Packages); - } public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) @@ -76,7 +81,12 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten // Search.SearchViewFlags : these flags are used to customize the appearance of the PickerWindow. ObjectField.DoObjectField(position, property, typeof(InputActionReference), label, m_Context, - Search.SearchViewFlags.OpenInBuilderMode | Search.SearchViewFlags.DisableBuilderModeToggle | Search.SearchViewFlags.DisableInspectorPreview | Search.SearchViewFlags.DisableSavedSearchQuery); + Search.SearchViewFlags.OpenInBuilderMode | + Search.SearchViewFlags.DisableBuilderModeToggle | + Search.SearchViewFlags.DisableInspectorPreview | + Search.SearchViewFlags.DisableSavedSearchQuery); } } } + +#endif From cece1359d2791bd03f4ff09cfe6234b38564f322 Mon Sep 17 00:00:00 2001 From: Sebastien Phaneuf Date: Thu, 5 Oct 2023 15:32:52 -0400 Subject: [PATCH 05/16] Create advance picker in UITK --- .../InputActionRefferenceSearchProvider.cs | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs index 3df4809e18..fede24e009 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using UnityEditor; using UnityEditor.Search; +using UnityEngine.UIElements; // TODO Why is project wide input asset (InputManager.asset) not up to date when loaded? // TODO Fix asset icons to make sense @@ -62,6 +63,12 @@ public sealed class InputActionReferencePropertyDrawer : PropertyDrawer { private readonly SearchContext m_Context; + // Search.SearchViewFlags : these flags are used to customize the appearance of the PickerWindow. + private readonly Search.SearchViewFlags m_ViewFlags = Search.SearchViewFlags.OpenInBuilderMode | + Search.SearchViewFlags.DisableBuilderModeToggle | + Search.SearchViewFlags.DisableInspectorPreview | + Search.SearchViewFlags.DisableSavedSearchQuery; + public InputActionReferencePropertyDrawer() { // By default ADB search provider yields ALL assets even if the search query is empty. @@ -76,16 +83,29 @@ public InputActionReferencePropertyDrawer() SearchFlags.Sorted | SearchFlags.OpenPicker | SearchFlags.Packages); } - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + // Advance Picker in UITk + public override VisualElement CreatePropertyGUI(SerializedProperty prop) { - // Search.SearchViewFlags : these flags are used to customize the appearance of the PickerWindow. - ObjectField.DoObjectField(position, property, typeof(InputActionReference), label, m_Context, - Search.SearchViewFlags.OpenInBuilderMode | - Search.SearchViewFlags.DisableBuilderModeToggle | - Search.SearchViewFlags.DisableInspectorPreview | - Search.SearchViewFlags.DisableSavedSearchQuery); + ObjectField obj = new ObjectField() + { + name = "InputActionReferenceProperty", + label = preferredLabel, + bindingPath = prop.propertyPath, + objectType = fieldInfo.FieldType, + searchViewFlags = m_ViewFlags, + searchContext = m_Context + }; + return obj; + } + + /* + // Advance Picker in IMGUI + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + ObjectField.DoObjectField(position, property, typeof(InputActionReference), label, m_Context,m_ViewFlags); } + */ } } From 48abd7f0d47daf7b9011551ee6c29429c99e4d10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Sidenvall?= Date: Thu, 5 Oct 2023 22:43:33 +0200 Subject: [PATCH 06/16] Modified description to be possible to decipher when min zoom mode (fallback) --- ... => InputActionReferencePropertyDrawer.cs} | 55 +++++++++++-------- ...nputActionReferencePropertyDrawer.cs.meta} | 0 2 files changed, 32 insertions(+), 23 deletions(-) rename Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/{InputActionRefferenceSearchProvider.cs => InputActionReferencePropertyDrawer.cs} (66%) rename Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/{InputActionRefferenceSearchProvider.cs.meta => InputActionReferencePropertyDrawer.cs.meta} (100%) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs similarity index 66% rename from Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs rename to Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs index fede24e009..c60eeb554d 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs @@ -9,24 +9,17 @@ // TODO Why is project wide input asset (InputManager.asset) not up to date when loaded? // TODO Fix asset icons to make sense -// TODO Fix filter so that search is possible, what is default method to fallback to it? -// TODO Why is grouping not working as expected? -// TODO Possible to remove/eliminate options in search? -// TODO Why is picker flag not making a difference? -// TODO Does it make sense to fetch assets as currently done namespace UnityEngine.InputSystem.Editor { - static class InputActionReferenceSearchProvider + static class ProjectWideInputActionReferenceSearchProvider { - private const string kInputActionReferenceType = "InputActionReference"; - // No need to use the SearchItemProvider -> this attribute is used to register the provider to // the SearchWindow and here we are mainly interested in using SearchItemProvider as a picker. // [SearchItemProvider] internal static SearchProvider CreateProjectSettingsAssetProvider() { - return new SearchProvider(kInputActionReferenceType, "Project Settings") + return new SearchProvider("InputActionReferenceSearchProvider", "Project-Wide Actions") { priority = 25, toObject = (item, type) => GetObject(item, type), @@ -34,20 +27,35 @@ internal static SearchProvider CreateProjectSettingsAssetProvider() }; } + static Object[] GetInputActionReferenceAssets() + { + // TODO Why does this return outdated assets?! Must be a problem unrelated to this search + // TODO Why does this return duplicates with different GUIDs + return AssetDatabase.LoadAllAssetsAtPath(ProjectWideActionsAsset.kAssetPath); + } + static IEnumerable SearchProjectSettingsInputReferenceActionAssets(SearchContext context, SearchProvider provider) { // TODO This could in theory be another icon to differentiate a project-wide action var icon = AssetDatabase.GetCachedIcon(ProjectWideActionsAsset.kAssetPath) as Texture2D; // This yields all accepted assets (InputActionReference) from ProjectWideActionsAsset.kAssetPath. - // TODO Why does this return an outdated asset?! Must be a problem unrelated to this search. - var assets = AssetDatabase.LoadAllAssetsAtPath(ProjectWideActionsAsset.kAssetPath); - foreach (var asset in assets) + foreach (var asset in GetInputActionReferenceAssets()) { + var inputActionReference = asset as InputActionReference; + if (inputActionReference == null) + continue; // Ignore item since not an InputActionReference + var label = asset.name; - if (asset is InputActionReference && label.Contains(context.searchText, System.StringComparison.InvariantCultureIgnoreCase)) - yield return provider.CreateItem(context, asset.GetInstanceID().ToString(), label, - "Input Action Reference (Project Settings)", icon, asset); + if (!label.Contains(context.searchText, System.StringComparison.InvariantCultureIgnoreCase)) + continue; // Ignore time since not matching search text filter + + //Debug.Log($"name:{asset.name} instance:{asset.GetInstanceID()} type:{asset.GetType()} subAsset:{AssetDatabase.IsSubAsset(asset)} actionId:{inputActionReference.m_ActionId}, map:{inputActionReference.m_Asset}"); + + var description = $"{AssetDatabase.GetAssetPath(asset)} ({label})"; + + yield return provider.CreateItem(context, asset.GetInstanceID().ToString(), label, + description, icon, asset); } } @@ -65,16 +73,16 @@ public sealed class InputActionReferencePropertyDrawer : PropertyDrawer // Search.SearchViewFlags : these flags are used to customize the appearance of the PickerWindow. private readonly Search.SearchViewFlags m_ViewFlags = Search.SearchViewFlags.OpenInBuilderMode | - Search.SearchViewFlags.DisableBuilderModeToggle | - Search.SearchViewFlags.DisableInspectorPreview | - Search.SearchViewFlags.DisableSavedSearchQuery; + Search.SearchViewFlags.DisableBuilderModeToggle | + Search.SearchViewFlags.DisableInspectorPreview | + Search.SearchViewFlags.DisableSavedSearchQuery; public InputActionReferencePropertyDrawer() { // By default ADB search provider yields ALL assets even if the search query is empty. // AssetProvider ("asset") will NOT yield anything if searchQuery is empty. var adbProvider = UnityEditor.Search.SearchService.GetProvider("adb"); - var projectSettingsProvider = InputActionReferenceSearchProvider.CreateProjectSettingsAssetProvider(); + var projectSettingsProvider = ProjectWideInputActionReferenceSearchProvider.CreateProjectSettingsAssetProvider(); m_Context = UnityEditor.Search.SearchService.CreateContext( new[] { adbProvider, projectSettingsProvider }, "", @@ -83,6 +91,8 @@ public InputActionReferencePropertyDrawer() SearchFlags.Sorted | SearchFlags.OpenPicker | SearchFlags.Packages); } + // TODO: Enable UITk picker as part of modernizing all pickers since sizing policies are different. + /* // Advance Picker in UITk public override VisualElement CreatePropertyGUI(SerializedProperty prop) { @@ -98,14 +108,13 @@ public override VisualElement CreatePropertyGUI(SerializedProperty prop) }; return obj; } + */ - /* // Advance Picker in IMGUI public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - ObjectField.DoObjectField(position, property, typeof(InputActionReference), label, m_Context,m_ViewFlags); + { + ObjectField.DoObjectField(position, property, typeof(InputActionReference), label, m_Context, m_ViewFlags); } - */ } } diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs.meta b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs.meta similarity index 100% rename from Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionRefferenceSearchProvider.cs.meta rename to Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs.meta From 98d9b30e364ea1c61362b9fc3cbdb8ea5ceeb37c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Sidenvall?= Date: Fri, 6 Oct 2023 09:16:21 +0200 Subject: [PATCH 07/16] Fixed duplicates returned when loading project settings asset, modified project-wide actions icon to use sub-asset icon from InputActionImporter --- .../PropertyDrawers/AssetSearchProviders.cs | 89 +++++++++++++++++ .../AssetSearchProviders.cs.meta | 3 + .../InputActionReferencePropertyDrawer.cs | 99 +++---------------- 3 files changed, 107 insertions(+), 84 deletions(-) create mode 100644 Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs create mode 100644 Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs.meta diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs new file mode 100644 index 0000000000..c5f17deed3 --- /dev/null +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs @@ -0,0 +1,89 @@ +#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEditor.Search; +using UnityEditor.VersionControl; + +namespace UnityEngine.InputSystem.Editor +{ + internal static class SearchConstants + { + // SearchFlags : these flags are used to customize how search is performed and how search + // results are displayed. + internal static readonly SearchFlags SearchFlags = SearchFlags.Sorted | + SearchFlags.OpenPicker | + SearchFlags.Packages; + + // Search.SearchViewFlags : these flags are used to customize the appearance of the PickerWindow. + internal static readonly Search.SearchViewFlags ViewFlags = Search.SearchViewFlags.OpenInBuilderMode | + Search.SearchViewFlags.DisableBuilderModeToggle | + Search.SearchViewFlags.DisableInspectorPreview | + Search.SearchViewFlags.DisableSavedSearchQuery; + } + + internal static class AssetSearchProviders + { + // Note that if this method is annotated with [SearchItemProvider] we would register the provider to + // the SearchWindow, we currently skip this since we are mainly interested in using SearchItemProvider as + // a picker. + private static SearchProvider CreateAssetSearchProvider(string id, string displayName, + Func> assetProvider, Texture2D thumbnail = null) + { + return new SearchProvider(id, displayName) + { + priority = 25, + toObject = GetObject, + fetchItems = (context, items, provider) => Search(context, provider, assetProvider, thumbnail), + }; + } + + internal static SearchProvider CreateInputActionReferenceSearchProvider() + { + // Match icon used for sub-assets from importer, if null will use cached icon from asset database instead. + // Note that .inputactions has one icon and sub-assets (actions) have another in the importer. + return CreateAssetSearchProvider( + "InputActionReferenceSearchProvider", + "Project-Wide Input Actions", + GetInputActionReferenceAssets, + (Texture2D)EditorGUIUtility.Load(InputActionImporter.kActionIcon)); + } + + private static IEnumerable GetInputActionReferenceAssets() + { + // Extract actions from actions maps from ProjectWideActionAsset. + // Note that we cannot do something like: + // return AssetDatabase.LoadAllAssetsAtPath(ProjectWideActionsAsset.kAssetPath) + // .Where((asset) => (asset is InputActionReference)); + // Since that would return an outdated asset that is out of sync with ProjectWideActionsAsset. + // TODO Understand why this is a problem and update this comment + var asset = ProjectWideActionsAsset.GetOrCreate(); + return (from actionMap in asset.actionMaps from action in actionMap.actions select InputActionReference.Create(action)).ToList(); + } + + static IEnumerable Search( + SearchContext context, SearchProvider provider, Func> assetProvider, Texture2D thumbnail) + { + foreach (var asset in assetProvider()) + { + var label = asset.name; + if (!label.Contains(context.searchText, System.StringComparison.InvariantCultureIgnoreCase)) + continue; // Ignore: not matching search text filter + + yield return provider.CreateItem(context, + asset.GetInstanceID().ToString(), + label, + $"{AssetDatabase.GetAssetPath(asset)} ({label})", + (thumbnail == null) ? AssetDatabase.GetCachedIcon(ProjectWideActionsAsset.kAssetPath) as Texture2D : thumbnail, + asset); + } + } + + private static Object GetObject(SearchItem item, System.Type type) + { + return item.data as Object; + } + } +} +#endif diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs.meta b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs.meta new file mode 100644 index 0000000000..188b26ae2d --- /dev/null +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2305180900cc45989b0cbfd4a0dd1c35 +timeCreated: 1696573295 \ No newline at end of file diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs index c60eeb554d..754a44eee1 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs @@ -2,98 +2,28 @@ // picker for InputActionReferences but rather rely on default (classic) object picker. #if UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS -using System.Collections.Generic; using UnityEditor; using UnityEditor.Search; -using UnityEngine.UIElements; - -// TODO Why is project wide input asset (InputManager.asset) not up to date when loaded? -// TODO Fix asset icons to make sense namespace UnityEngine.InputSystem.Editor { - static class ProjectWideInputActionReferenceSearchProvider - { - // No need to use the SearchItemProvider -> this attribute is used to register the provider to - // the SearchWindow and here we are mainly interested in using SearchItemProvider as a picker. - // [SearchItemProvider] - internal static SearchProvider CreateProjectSettingsAssetProvider() - { - return new SearchProvider("InputActionReferenceSearchProvider", "Project-Wide Actions") - { - priority = 25, - toObject = (item, type) => GetObject(item, type), - fetchItems = (context, items, provider) => SearchProjectSettingsInputReferenceActionAssets(context, provider), - }; - } - - static Object[] GetInputActionReferenceAssets() - { - // TODO Why does this return outdated assets?! Must be a problem unrelated to this search - // TODO Why does this return duplicates with different GUIDs - return AssetDatabase.LoadAllAssetsAtPath(ProjectWideActionsAsset.kAssetPath); - } - - static IEnumerable SearchProjectSettingsInputReferenceActionAssets(SearchContext context, SearchProvider provider) - { - // TODO This could in theory be another icon to differentiate a project-wide action - var icon = AssetDatabase.GetCachedIcon(ProjectWideActionsAsset.kAssetPath) as Texture2D; - - // This yields all accepted assets (InputActionReference) from ProjectWideActionsAsset.kAssetPath. - foreach (var asset in GetInputActionReferenceAssets()) - { - var inputActionReference = asset as InputActionReference; - if (inputActionReference == null) - continue; // Ignore item since not an InputActionReference - - var label = asset.name; - if (!label.Contains(context.searchText, System.StringComparison.InvariantCultureIgnoreCase)) - continue; // Ignore time since not matching search text filter - - //Debug.Log($"name:{asset.name} instance:{asset.GetInstanceID()} type:{asset.GetType()} subAsset:{AssetDatabase.IsSubAsset(asset)} actionId:{inputActionReference.m_ActionId}, map:{inputActionReference.m_Asset}"); - - var description = $"{AssetDatabase.GetAssetPath(asset)} ({label})"; - - yield return provider.CreateItem(context, asset.GetInstanceID().ToString(), label, - description, icon, asset); - } - } - - private static Object GetObject(SearchItem item, System.Type type) - { - return item.data as Object; - } - } - - // Custom property drawer in order to use the Advance picker: + /// + /// Custom property drawer in order to use the "Advanced Picker" from UnityEditor.Search. + /// [CustomPropertyDrawer(typeof(InputActionReference))] - public sealed class InputActionReferencePropertyDrawer : PropertyDrawer + internal sealed class InputActionReferencePropertyDrawer : PropertyDrawer { - private readonly SearchContext m_Context; - - // Search.SearchViewFlags : these flags are used to customize the appearance of the PickerWindow. - private readonly Search.SearchViewFlags m_ViewFlags = Search.SearchViewFlags.OpenInBuilderMode | - Search.SearchViewFlags.DisableBuilderModeToggle | - Search.SearchViewFlags.DisableInspectorPreview | - Search.SearchViewFlags.DisableSavedSearchQuery; - - public InputActionReferencePropertyDrawer() + // By default ADB search provider yields ALL assets even if the search query is empty. + // AssetProvider ("asset") will NOT yield anything if searchQuery is empty. + private readonly SearchContext m_Context = UnityEditor.Search.SearchService.CreateContext(new[] { - // By default ADB search provider yields ALL assets even if the search query is empty. - // AssetProvider ("asset") will NOT yield anything if searchQuery is empty. - var adbProvider = UnityEditor.Search.SearchService.GetProvider("adb"); - var projectSettingsProvider = ProjectWideInputActionReferenceSearchProvider.CreateProjectSettingsAssetProvider(); - m_Context = UnityEditor.Search.SearchService.CreateContext( - new[] { adbProvider, projectSettingsProvider }, - "", - // SearchFlags : these flags are used to customize how search is performed and how search - // results are displayed. - SearchFlags.Sorted | SearchFlags.OpenPicker | SearchFlags.Packages); - } + UnityEditor.Search.SearchService.GetProvider("adb"), + AssetSearchProviders.CreateInputActionReferenceSearchProvider() + }, string.Empty, SearchConstants.SearchFlags); - // TODO: Enable UITk picker as part of modernizing all pickers since sizing policies are different. + // TODO: Enable UITk picker as part of modernizing all pickers. Since sizing policies are different its not advised to introduce this change at the moment without further work. /* - // Advance Picker in UITk + // Advanced Picker in UITk public override VisualElement CreatePropertyGUI(SerializedProperty prop) { @@ -110,10 +40,11 @@ public override VisualElement CreatePropertyGUI(SerializedProperty prop) } */ - // Advance Picker in IMGUI + // Advanced Picker in IMGUI public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { - ObjectField.DoObjectField(position, property, typeof(InputActionReference), label, m_Context, m_ViewFlags); + ObjectField.DoObjectField(position, property, typeof(InputActionReference), label, + m_Context, SearchConstants.ViewFlags); } } } From 260e8b3cc11161a4747a380e613ca33c03f56cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Sidenvall?= Date: Fri, 6 Oct 2023 11:54:01 +0200 Subject: [PATCH 08/16] Modified property drawer to rely on UITK to avoid bug in IMGUI version resulting in exceptions --- .../InputActionReferencePropertyDrawer.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs index 754a44eee1..4adca199d7 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs @@ -21,31 +21,28 @@ internal sealed class InputActionReferencePropertyDrawer : PropertyDrawer AssetSearchProviders.CreateInputActionReferenceSearchProvider() }, string.Empty, SearchConstants.SearchFlags); - // TODO: Enable UITk picker as part of modernizing all pickers. Since sizing policies are different its not advised to introduce this change at the moment without further work. - /* // Advanced Picker in UITk - public override VisualElement CreatePropertyGUI(SerializedProperty prop) + public override UIElements.VisualElement CreatePropertyGUI(SerializedProperty prop) { - ObjectField obj = new ObjectField() { name = "InputActionReferenceProperty", label = preferredLabel, bindingPath = prop.propertyPath, objectType = fieldInfo.FieldType, - searchViewFlags = m_ViewFlags, + searchViewFlags = SearchConstants.ViewFlags, searchContext = m_Context }; + obj.AddToClassList(ObjectField.alignedFieldUssClassName); // align width return obj; } - */ - // Advanced Picker in IMGUI - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + // Advanced Picker in IMGUI, keeping for reference + /*public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { ObjectField.DoObjectField(position, property, typeof(InputActionReference), label, m_Context, SearchConstants.ViewFlags); - } + }*/ } } From b2ec69c6bde4956f73719e31dc88f54f5e08059d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Sidenvall?= Date: Fri, 6 Oct 2023 11:59:44 +0200 Subject: [PATCH 09/16] Added workaround for Unity older than 2022_2 --- .../InputActionReferencePropertyDrawer.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs index 4adca199d7..621741d968 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs @@ -33,7 +33,14 @@ public override UIElements.VisualElement CreatePropertyGUI(SerializedProperty pr searchViewFlags = SearchConstants.ViewFlags, searchContext = m_Context }; - obj.AddToClassList(ObjectField.alignedFieldUssClassName); // align width + + // Align width in Inspector - note that ObjectField.alignedFieldUssClassName was made public in 2022.2 + #if UNITY_2022_2_OR_NEWER + obj.AddToClassList(ObjectField.alignedFieldUssClassName); + #else + obj.AddToClassList(ObjectField.ussClassName + "__aligned"); + #endif + return obj; } From f26126426cb2ba78e35bc810eb2433152fd4171f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Sidenvall?= Date: Mon, 9 Oct 2023 09:22:56 +0200 Subject: [PATCH 10/16] Minor refactoring and cleanup relating to implemented functionality. Reduced scopes and made internal dependencies restricted in scope. Moved icon handling out of InputActionAssetImporter. --- .../InputActionAssetIconProvider.cs | 35 ++++++++++++++ .../InputActionAssetIconProvider.cs.meta | 3 ++ .../AssetImporter/InputActionImporter.cs | 7 +-- .../ProjectWideActionsAsset.cs | 47 ++++++++++++------- .../PropertyDrawers/AssetSearchProviders.cs | 21 ++++----- .../PropertyDrawers/InputActionAssetDrawer.cs | 12 +---- .../InputActionReferencePropertyDrawer.cs | 25 +++++----- .../InputActionsEditorWindowUtils.cs | 2 +- 8 files changed, 97 insertions(+), 55 deletions(-) create mode 100644 Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionAssetIconProvider.cs create mode 100644 Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionAssetIconProvider.cs.meta diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionAssetIconProvider.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionAssetIconProvider.cs new file mode 100644 index 0000000000..d953dc7817 --- /dev/null +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionAssetIconProvider.cs @@ -0,0 +1,35 @@ +#if UNITY_EDITOR +using UnityEditor; + +namespace UnityEngine.InputSystem.Editor +{ + /// + /// Provides access to icons associated with InputActionAsset. + /// + internal static class InputActionAssetIconProvider + { + private const string kActionIcon = "Packages/com.unity.inputsystem/InputSystem/Editor/Icons/InputAction.png"; + private const string kAssetIcon = "Packages/com.unity.inputsystem/InputSystem/Editor/Icons/InputActionAsset.png"; + + /// + /// Attempts to load the icon associated with an InputActionAsset (.inputactions) asset. + /// + /// Icon resource reference or null if the resource could not be loaded. + public static Texture2D LoadAssetIcon() + { + return (Texture2D)EditorGUIUtility.Load(kAssetIcon); + } + + /// + /// Attempts to load the icon associated with an InputActionReference sub-asset of an + /// InputActionAsset (.inputactions) asset. + /// + /// Icon resource reference or null if the resource could not be loaded. + public static Texture2D LoadActionIcon() + { + return (Texture2D)EditorGUIUtility.Load(kActionIcon); + } + } +} + +#endif // #if UNITY_EDITOR diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionAssetIconProvider.cs.meta b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionAssetIconProvider.cs.meta new file mode 100644 index 0000000000..3f68a790e1 --- /dev/null +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionAssetIconProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 310c27cc89b74e5291ce1fcb0a9d793d +timeCreated: 1696829469 \ No newline at end of file diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs index 032b89b3a1..540cac0890 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs @@ -29,9 +29,6 @@ internal class InputActionImporter : ScriptedImporter { private const int kVersion = 13; - internal const string kActionIcon = "Packages/com.unity.inputsystem/InputSystem/Editor/Icons/InputAction.png"; - internal const string kAssetIcon = "Packages/com.unity.inputsystem/InputSystem/Editor/Icons/InputActionAsset.png"; - [SerializeField] private bool m_GenerateWrapperCode; [SerializeField] private string m_WrapperCodePath; [SerializeField] private string m_WrapperClassName; @@ -88,8 +85,8 @@ public override void OnImportAsset(AssetImportContext ctx) // Load icons. ////REVIEW: the icons won't change if the user changes skin; not sure it makes sense to differentiate here - var assetIcon = (Texture2D)EditorGUIUtility.Load(kAssetIcon); - var actionIcon = (Texture2D)EditorGUIUtility.Load(kActionIcon); + var assetIcon = InputActionAssetIconProvider.LoadAssetIcon(); + var actionIcon = InputActionAssetIconProvider.LoadActionIcon(); // Add asset. ctx.AddObjectToAsset("", asset, assetIcon); diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/ProjectWideActions/ProjectWideActionsAsset.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/ProjectWideActions/ProjectWideActionsAsset.cs index c2b6d1b54f..7284464d5a 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/ProjectWideActions/ProjectWideActionsAsset.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/ProjectWideActions/ProjectWideActionsAsset.cs @@ -10,18 +10,18 @@ namespace UnityEngine.InputSystem.Editor { internal static class ProjectWideActionsAsset { - internal const string kDefaultAssetPath = "Packages/com.unity.inputsystem/InputSystem/Editor/ProjectWideActions/ProjectWideActionsTemplate.inputactions"; - internal const string kAssetPath = "ProjectSettings/InputManager.asset"; - internal const string kAssetName = InputSystem.kProjectWideActionsAssetName; - - static string s_DefaultAssetPath = kDefaultAssetPath; - static string s_AssetPath = kAssetPath; + private const string kDefaultAssetPath = "Packages/com.unity.inputsystem/InputSystem/Editor/ProjectWideActions/ProjectWideActionsTemplate.inputactions"; + private const string kAssetPath = "ProjectSettings/InputManager.asset"; + private const string kAssetName = InputSystem.kProjectWideActionsAssetName; #if UNITY_INCLUDE_TESTS - internal static void SetAssetPaths(string defaultAssetPath, string assetPath) + private static string s_DefaultAssetPath = kDefaultAssetPath; + private static string s_AssetPath = kAssetPath; + + internal static void SetAssetPaths(string defaultAssetPathOverride, string assetPathOverride) { - s_DefaultAssetPath = defaultAssetPath; - s_AssetPath = assetPath; + s_DefaultAssetPath = defaultAssetPathOverride; + s_AssetPath = assetPathOverride; } internal static void Reset() @@ -30,6 +30,11 @@ internal static void Reset() s_AssetPath = kAssetPath; } + internal static string defaultAssetPath => s_DefaultAssetPath; + internal static string assetPath => s_AssetPath; +#else + internal static string defaultAssetPath => kDefaultAssetPath; + internal static string assetPath => kAssetPath; #endif [InitializeOnLoadMethod] @@ -38,17 +43,25 @@ internal static void InstallProjectWideActions() GetOrCreate(); } + internal static bool IsProjectWideActionsAsset(Object obj) + { + return IsProjectWideActionsAsset(obj as InputActionAsset); + } + + internal static bool IsProjectWideActionsAsset(InputActionAsset asset) + { + if (ReferenceEquals(asset, null)) + return false; + return kAssetName.Equals(asset.name); + } + internal static InputActionAsset GetOrCreate() { var objects = AssetDatabase.LoadAllAssetsAtPath(s_AssetPath); - if (objects != null) - { - var inputActionsAsset = objects.FirstOrDefault(o => o != null && o.name == kAssetName) as InputActionAsset; - if (inputActionsAsset != null) - return inputActionsAsset; - } - - return CreateNewActionAsset(); + var inputActionsAsset = (InputActionAsset)objects?.FirstOrDefault(IsProjectWideActionsAsset); + if (ReferenceEquals(inputActionsAsset, null)) + return CreateNewActionAsset(); + return inputActionsAsset; } private static InputActionAsset CreateNewActionAsset() diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs index c5f17deed3..105acd2ad2 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs @@ -4,7 +4,6 @@ using System.Linq; using UnityEditor; using UnityEditor.Search; -using UnityEditor.VersionControl; namespace UnityEngine.InputSystem.Editor { @@ -39,6 +38,11 @@ private static SearchProvider CreateAssetSearchProvider(string id, string displa }; } + internal static SearchProvider CreateDefaultProvider() + { + return UnityEditor.Search.SearchService.GetProvider("adb"); + } + internal static SearchProvider CreateInputActionReferenceSearchProvider() { // Match icon used for sub-assets from importer, if null will use cached icon from asset database instead. @@ -47,18 +51,12 @@ internal static SearchProvider CreateInputActionReferenceSearchProvider() "InputActionReferenceSearchProvider", "Project-Wide Input Actions", GetInputActionReferenceAssets, - (Texture2D)EditorGUIUtility.Load(InputActionImporter.kActionIcon)); + InputActionAssetIconProvider.LoadActionIcon()); } private static IEnumerable GetInputActionReferenceAssets() { - // Extract actions from actions maps from ProjectWideActionAsset. - // Note that we cannot do something like: - // return AssetDatabase.LoadAllAssetsAtPath(ProjectWideActionsAsset.kAssetPath) - // .Where((asset) => (asset is InputActionReference)); - // Since that would return an outdated asset that is out of sync with ProjectWideActionsAsset. - // TODO Understand why this is a problem and update this comment - var asset = ProjectWideActionsAsset.GetOrCreate(); + var asset = ProjectWideActionsAsset.GetOrCreate(); // alt. InputSystem.actions return (from actionMap in asset.actionMaps from action in actionMap.actions select InputActionReference.Create(action)).ToList(); } @@ -71,11 +69,12 @@ static IEnumerable Search( if (!label.Contains(context.searchText, System.StringComparison.InvariantCultureIgnoreCase)) continue; // Ignore: not matching search text filter + var assetPath = AssetDatabase.GetAssetPath(asset); yield return provider.CreateItem(context, asset.GetInstanceID().ToString(), label, - $"{AssetDatabase.GetAssetPath(asset)} ({label})", - (thumbnail == null) ? AssetDatabase.GetCachedIcon(ProjectWideActionsAsset.kAssetPath) as Texture2D : thumbnail, + $"{assetPath} ({label})", + (thumbnail == null) ? AssetDatabase.GetCachedIcon(assetPath) as Texture2D : thumbnail, asset); } } diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionAssetDrawer.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionAssetDrawer.cs index a31d736f9a..ca0f25b7cb 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionAssetDrawer.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionAssetDrawer.cs @@ -87,17 +87,9 @@ static void UpdatePropertyWithSelectedOption(SerializedProperty assetProperty, A static bool IsAssetProjectWideActions(SerializedProperty property) { - var isAssetProjectWideActions = false; - // Check if the property InputActionAsset name is the same as project-wide actions to determine if - // project-wide actions are set - if (property.objectReferenceValue != null) - { - var asset = (InputActionAsset)property.objectReferenceValue; - isAssetProjectWideActions = asset?.name == ProjectWideActionsAsset.kAssetName; - } - - return isAssetProjectWideActions; + // project-wide actions are set. + return ProjectWideActionsAsset.IsProjectWideActionsAsset(property.objectReferenceValue); } } } diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs index 621741d968..1b40c32e52 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs @@ -17,12 +17,22 @@ internal sealed class InputActionReferencePropertyDrawer : PropertyDrawer // AssetProvider ("asset") will NOT yield anything if searchQuery is empty. private readonly SearchContext m_Context = UnityEditor.Search.SearchService.CreateContext(new[] { - UnityEditor.Search.SearchService.GetProvider("adb"), + AssetSearchProviders.CreateDefaultProvider(), AssetSearchProviders.CreateInputActionReferenceSearchProvider() }, string.Empty, SearchConstants.SearchFlags); + // Advanced Picker in IMGUI, keeping for reference + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + ObjectField.DoObjectField(position, property, typeof(InputActionReference), label, + m_Context, SearchConstants.ViewFlags); + } + // Advanced Picker in UITk - public override UIElements.VisualElement CreatePropertyGUI(SerializedProperty prop) + // Kept uncommented as a future reference for modernizing property drawers. + // We can only use this one if we rewrite InputProperty property drawer for UITK as well since it would + // render UI where InputActionReferecePropertyDrawer is a sub interface. + /*public override UIElements.VisualElement CreatePropertyGUI(SerializedProperty prop) { ObjectField obj = new ObjectField() { @@ -34,21 +44,14 @@ public override UIElements.VisualElement CreatePropertyGUI(SerializedProperty pr searchContext = m_Context }; - // Align width in Inspector - note that ObjectField.alignedFieldUssClassName was made public in 2022.2 - #if UNITY_2022_2_OR_NEWER + // Align width in Inspector - note that ObjectField.alignedFieldUssClassName was made public in 2021.2.7f1 + #if UNITY_2021_3_OR_NEWER obj.AddToClassList(ObjectField.alignedFieldUssClassName); #else obj.AddToClassList(ObjectField.ussClassName + "__aligned"); #endif return obj; - } - - // Advanced Picker in IMGUI, keeping for reference - /*public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - ObjectField.DoObjectField(position, property, typeof(InputActionReference), label, - m_Context, SearchConstants.ViewFlags); }*/ } } diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindowUtils.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindowUtils.cs index 1ace6c81bd..e87d0877b8 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindowUtils.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindowUtils.cs @@ -15,7 +15,7 @@ public static void SaveAsset(SerializedObject serializedAsset) { var asset = (InputActionAsset)serializedAsset.targetObject; // for the global actions asset: save differently (as it is a yaml file and not a json) - if (asset.name == ProjectWideActionsAsset.kAssetName) + if (ProjectWideActionsAsset.IsProjectWideActionsAsset(asset)) { AssetDatabase.SaveAssets(); return; From ae426eeea3d5b881656635805fdbd1fa1363c1c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Sidenvall?= Date: Mon, 9 Oct 2023 09:25:16 +0200 Subject: [PATCH 11/16] Fixed problem in InputActionAsset importer --- .../InputSystem/Editor/AssetImporter/InputActionImporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs index 540cac0890..a8944ea27c 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs @@ -217,7 +217,7 @@ public override void OnImportAsset(AssetImportContext ctx) public static void CreateInputAsset() { ProjectWindowUtil.CreateAssetWithContent("New Controls." + InputActionAsset.Extension, - kDefaultAssetLayout, (Texture2D)EditorGUIUtility.Load(kAssetIcon)); + kDefaultAssetLayout, InputActionAssetIconProvider.LoadAssetIcon()); } } } From 1fd79e52090cefa95953db93134ef9ab7d81e7bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Sidenvall?= Date: Mon, 9 Oct 2023 10:47:05 +0200 Subject: [PATCH 12/16] Removed test files that should never have been part of PR --- Assets/InputActionReferenceContainer.cs | 30 -- Assets/InputActionReferenceContainer.cs.meta | 2 - Assets/SceneWithInputContainer.unity | 381 ------------------- Assets/SceneWithInputContainer.unity.meta | 7 - 4 files changed, 420 deletions(-) delete mode 100644 Assets/InputActionReferenceContainer.cs delete mode 100644 Assets/InputActionReferenceContainer.cs.meta delete mode 100644 Assets/SceneWithInputContainer.unity delete mode 100644 Assets/SceneWithInputContainer.unity.meta diff --git a/Assets/InputActionReferenceContainer.cs b/Assets/InputActionReferenceContainer.cs deleted file mode 100644 index 278d8f8858..0000000000 --- a/Assets/InputActionReferenceContainer.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.InputSystem; - -public class InputActionContainer: MonoBehaviour -{ - public InputAction myAction; - public InputActionReference myReference; - public InputActionReference mySecondReferenceWithAVeryLongName; - public InputActionProperty myProperty; - public InputActionAsset myAsset; - public InputControl myControl; - - // Start is called before the first frame update - void Start() - { - if (myReference.action != null) - myReference.action.performed += context => { Debug.Log("Performed"); }; - } - - // Update is called once per frame - void Update() - { - } -} \ No newline at end of file diff --git a/Assets/InputActionReferenceContainer.cs.meta b/Assets/InputActionReferenceContainer.cs.meta deleted file mode 100644 index 3cb5f399a4..0000000000 --- a/Assets/InputActionReferenceContainer.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: abb3ee11c825d6e41b8740fcfc377222 \ No newline at end of file diff --git a/Assets/SceneWithInputContainer.unity b/Assets/SceneWithInputContainer.unity deleted file mode 100644 index 2d28f9138b..0000000000 --- a/Assets/SceneWithInputContainer.unity +++ /dev/null @@ -1,381 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 10 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0.46169513, g: 0.5124164, b: 0.58993304, a: 1} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 12 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 512 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 256 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 1 - m_PVRDenoiserTypeDirect: 1 - m_PVRDenoiserTypeIndirect: 1 - m_PVRDenoiserTypeAO: 1 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 1 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 1 - m_PVRFilteringGaussRadiusAO: 1 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 0} - m_LightingSettings: {fileID: 0} ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 3 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - buildHeightMesh: 0 - maxJobWorkers: 0 - preserveTilesOutsideBounds: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &88645882 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 88645885} - - component: {fileID: 88645884} - - component: {fileID: 88645883} - m_Layer: 0 - m_Name: Main Camera - m_TagString: MainCamera - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!81 &88645883 -AudioListener: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 88645882} - m_Enabled: 1 ---- !u!20 &88645884 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 88645882} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} - m_projectionMatrixMode: 1 - m_GateFitMode: 2 - m_FOVAxisMode: 0 - m_Iso: 200 - m_ShutterSpeed: 0.005 - m_Aperture: 16 - m_FocusDistance: 10 - m_FocalLength: 50 - m_BladeCount: 5 - m_Curvature: {x: 2, y: 11} - m_BarrelClipping: 0.25 - m_Anamorphism: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: -1 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 3 - m_HDR: 1 - m_AllowMSAA: 1 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 ---- !u!4 &88645885 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 88645882} - serializedVersion: 2 - 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_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &730029164 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 730029165} - - component: {fileID: 730029166} - m_Layer: 0 - m_Name: GameObject - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &730029165 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 730029164} - serializedVersion: 2 - 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_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &730029166 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 730029164} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: abb3ee11c825d6e41b8740fcfc377222, type: 3} - m_Name: - m_EditorClassIdentifier: - myAction: - m_Name: My - m_Type: 0 - m_ExpectedControlType: - m_Id: ad881367-1275-4d43-9175-61675f8ecc6c - m_Processors: - m_Interactions: - m_SingletonActionBindings: [] - m_Flags: 0 - myReference: {fileID: 0} - mySecondReferenceWithAVeryLongName: {fileID: 0} - myProperty: - m_UseReference: 0 - m_Action: - m_Name: My Property - m_Type: 0 - m_ExpectedControlType: - m_Id: e04f2259-efc2-41c2-97bd-86854b61922a - m_Processors: - m_Interactions: - m_SingletonActionBindings: [] - m_Flags: 0 - m_Reference: {fileID: 0} - myAsset: {fileID: 0} ---- !u!1 &1013191913 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1013191915} - - component: {fileID: 1013191914} - m_Layer: 0 - m_Name: Directional Light - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!108 &1013191914 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1013191913} - m_Enabled: 1 - serializedVersion: 11 - m_Type: 1 - m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} - m_Intensity: 1 - m_Range: 10 - m_SpotAngle: 30 - m_InnerSpotAngle: 21.80208 - m_CookieSize: 10 - m_Shadows: - m_Type: 2 - m_Resolution: -1 - m_CustomResolution: -1 - m_Strength: 1 - m_Bias: 0.05 - m_NormalBias: 0.4 - m_NearPlane: 0.2 - m_CullingMatrixOverride: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_UseCullingMatrixOverride: 0 - m_Cookie: {fileID: 0} - m_DrawHalo: 0 - m_Flare: {fileID: 0} - m_RenderMode: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingLayerMask: 1 - m_Lightmapping: 4 - m_LightShadowCasterMode: 0 - m_AreaSize: {x: 1, y: 1} - m_BounceIntensity: 1 - m_ColorTemperature: 6570 - m_UseColorTemperature: 0 - m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} - m_UseBoundingSphereOverride: 0 - m_UseViewFrustumForShadowCasterCull: 1 - m_ShadowRadius: 0 - m_ShadowAngle: 0 ---- !u!4 &1013191915 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1013191913} - serializedVersion: 2 - 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_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!1660057539 &9223372036854775807 -SceneRoots: - m_ObjectHideFlags: 0 - m_Roots: - - {fileID: 88645885} - - {fileID: 1013191915} - - {fileID: 730029165} diff --git a/Assets/SceneWithInputContainer.unity.meta b/Assets/SceneWithInputContainer.unity.meta deleted file mode 100644 index a596b3ee11..0000000000 --- a/Assets/SceneWithInputContainer.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 908750d0cc8bbc342a41f37bbaac8876 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: From 1181c6745aea711f6bbeab5f1b3b8b183b081d97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Sidenvall?= Date: Mon, 9 Oct 2023 10:56:09 +0200 Subject: [PATCH 13/16] Simplified code, adressed filter from review. --- .../Editor/PropertyDrawers/AssetSearchProviders.cs | 5 ++--- .../Editor/PropertyDrawers/InputActionAssetDrawer.cs | 11 +++-------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs index 105acd2ad2..44e3cdc31d 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs @@ -11,9 +11,8 @@ internal static class SearchConstants { // SearchFlags : these flags are used to customize how search is performed and how search // results are displayed. - internal static readonly SearchFlags SearchFlags = SearchFlags.Sorted | - SearchFlags.OpenPicker | - SearchFlags.Packages; + // Note that SearchFlags.Packages is not currently used and hides all results from packages. + internal static readonly SearchFlags SearchFlags = SearchFlags.Sorted | SearchFlags.OpenPicker; // Search.SearchViewFlags : these flags are used to customize the appearance of the PickerWindow. internal static readonly Search.SearchViewFlags ViewFlags = Search.SearchViewFlags.OpenInBuilderMode | diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionAssetDrawer.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionAssetDrawer.cs index ca0f25b7cb..a167ae4e46 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionAssetDrawer.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionAssetDrawer.cs @@ -28,7 +28,9 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten { EditorGUI.BeginProperty(position, label, property); - var isAssetProjectWideActions = IsAssetProjectWideActions(property); + // Check if the property InputActionAsset name is the same as project-wide actions to determine if + // project-wide actions are set. + var isAssetProjectWideActions = ProjectWideActionsAsset.IsProjectWideActionsAsset(property.objectReferenceValue); var selectedAssetOptionIndex = isAssetProjectWideActions ? AssetOptions.ProjectWideActions : AssetOptions.ActionsAsset; EditorGUILayout.BeginHorizontal(); @@ -84,13 +86,6 @@ static void UpdatePropertyWithSelectedOption(SerializedProperty assetProperty, A assetProperty.serializedObject.ApplyModifiedProperties(); } - - static bool IsAssetProjectWideActions(SerializedProperty property) - { - // Check if the property InputActionAsset name is the same as project-wide actions to determine if - // project-wide actions are set. - return ProjectWideActionsAsset.IsProjectWideActionsAsset(property.objectReferenceValue); - } } } From efe707fa4a2aad00a77ce2d9975e79030408bf84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Sidenvall?= Date: Mon, 9 Oct 2023 11:01:46 +0200 Subject: [PATCH 14/16] Removed comment that is obsolete due to it commenting on an internal detail moved to ProjectWideInputActionsAsset --- .../Editor/PropertyDrawers/InputActionAssetDrawer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionAssetDrawer.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionAssetDrawer.cs index a167ae4e46..458d3c0dda 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionAssetDrawer.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionAssetDrawer.cs @@ -28,8 +28,6 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten { EditorGUI.BeginProperty(position, label, property); - // Check if the property InputActionAsset name is the same as project-wide actions to determine if - // project-wide actions are set. var isAssetProjectWideActions = ProjectWideActionsAsset.IsProjectWideActionsAsset(property.objectReferenceValue); var selectedAssetOptionIndex = isAssetProjectWideActions ? AssetOptions.ProjectWideActions : AssetOptions.ActionsAsset; From 51b78c6d84041a9e7caca7b13b02f382aa284930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Sidenvall?= Date: Wed, 18 Oct 2023 13:44:54 +0200 Subject: [PATCH 15/16] wip --- Assets/Tests/InputSystem/CoreTests_Actions.cs | 31 ++- .../InputSystem/Actions/InputActionAsset.cs | 31 ++- .../Actions/InputActionReference.cs | 24 +++ .../AssetImporter/InputActionImporter.cs | 8 + .../Internal/InputActionReferenceValidator.cs | 185 ++++++++++++++++++ .../InputActionReferenceValidator.cs.meta | 3 + .../ProjectWideActionsAsset.cs | 16 +- .../PropertyDrawers/AssetSearchProviders.cs | 91 +++++---- .../InputActionReferencePropertyDrawer.cs | 36 +++- .../InputActionsEditorSettingsProvider.cs | 3 +- .../InputActionsEditorWindowUtils.cs | 1 + .../InputSystem/Utilities/ArrayHelpers.cs | 21 ++ 12 files changed, 400 insertions(+), 50 deletions(-) create mode 100644 Packages/com.unity.inputsystem/InputSystem/Editor/Internal/InputActionReferenceValidator.cs create mode 100644 Packages/com.unity.inputsystem/InputSystem/Editor/Internal/InputActionReferenceValidator.cs.meta diff --git a/Assets/Tests/InputSystem/CoreTests_Actions.cs b/Assets/Tests/InputSystem/CoreTests_Actions.cs index aa84d64f0b..b33cae8f10 100644 --- a/Assets/Tests/InputSystem/CoreTests_Actions.cs +++ b/Assets/Tests/InputSystem/CoreTests_Actions.cs @@ -9307,7 +9307,6 @@ public void Actions_CanApplyOverrideToActionWithEmptyBinding() action.Disable(); action.ApplyBindingOverride(0, "/gamepad/leftTrigger"); action.Enable(); - Press(gamepad.leftTrigger); Assert.That(performed); @@ -9550,6 +9549,36 @@ public void Actions_CanResolveActionReference() Assert.That(referencedAction, Is.SameAs(action2)); } + + [Test] + [Category("Actions")] + public void Actions_CanResolveActionReference_WhenUsingToInputActionToConstructANewReference() + { + var map = new InputActionMap("map"); + map.AddAction("action1"); + var action2 = map.AddAction("action2"); + var asset = ScriptableObject.CreateInstance(); + asset.AddActionMap(map); + + var reference = ScriptableObject.CreateInstance(); + reference.Set(asset, "map", "action2"); + + var copy1 = InputActionReference.Create(reference.action); + var copy2 = InputActionReference.Create(reference.ToInputAction()); + + // Expecting action to be the same + Assert.That(reference.action, Is.SameAs(copy1.action)); + Assert.That(reference.action, Is.SameAs(copy2.action)); + } + + [Test] + [Category("Actions")] + public void Actions_CanImplicitlyConvertReferenceToAction_WhenAssigningActionFromReference() + { + var reference = ScriptableObject.CreateInstance(); + InputAction action = reference; // implicit conversion + Assert.That(reference.action, Is.Null); + } [Test] [Category("Actions")] diff --git a/Packages/com.unity.inputsystem/InputSystem/Actions/InputActionAsset.cs b/Packages/com.unity.inputsystem/InputSystem/Actions/InputActionAsset.cs index 5c54b13bcd..ab32a889ed 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Actions/InputActionAsset.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Actions/InputActionAsset.cs @@ -1,7 +1,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Linq; using UnityEngine.InputSystem.Utilities; ////TODO: make the FindAction logic available on any IEnumerable and IInputActionCollection via extension methods @@ -924,11 +923,41 @@ private void OnDestroy() } } + #if UNITY_EDITOR + + private void OnValidate() + { + // Only currently validates references if serialized property has been set to true + if (m_ValidateReferencesInEditMode) + Editor.InputActionReferenceValidator.ValidateReferences(this); + } + + #endif + + internal InputAction FindActionById(string actionId) + { + if (m_ActionMaps == null) + return null; + + foreach (var t in m_ActionMaps) + { + var action = t.FindAction(actionId); + if (action != null) + return action; + } + + return null; + } + ////TODO: ApplyBindingOverrides, RemoveBindingOverrides, RemoveAllBindingOverrides [SerializeField] internal InputActionMap[] m_ActionMaps; [SerializeField] internal InputControlScheme[] m_ControlSchemes; + // Note: not serialized to JSON only as asset objects + [NonSerialized] internal InputActionReference[] m_References; // TODO Tentative + [SerializeField] internal bool m_ValidateReferencesInEditMode;// TODO Tentative + ////TODO: make this persistent across domain reloads /// /// Shared state for all action maps in the asset. diff --git a/Packages/com.unity.inputsystem/InputSystem/Actions/InputActionReference.cs b/Packages/com.unity.inputsystem/InputSystem/Actions/InputActionReference.cs index 0090f46bb8..2bc2fc1b9b 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Actions/InputActionReference.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Actions/InputActionReference.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using UnityEditor; ////REVIEW: Can we somehow make this a simple struct? The one problem we have is that we can't put struct instances as sub-assets into //// the import (i.e. InputActionImporter can't do AddObjectToAsset with them). However, maybe there's a way around that. The thing @@ -160,6 +161,29 @@ public override string ToString() return base.ToString(); } +#if UNITY_EDITOR + + private void OnEnable() + { + // This is invoked after InputActionReference deserialization + if (m_Action == null && m_Asset != null) + { + m_Action = m_Asset.FindActionById(m_ActionId); + Invalidate(); + } + } + + internal void Invalidate() + { + // TODO Check if it makes a difference to do full re-evaluation here (only to see if reference invalidation for asset is broken) + + // Reflect action name as the name of this SerializableObject + if (m_Action != null) + name = GetDisplayName(m_Action); + } + +#endif // #if UNITY_EDITOR + private static string GetDisplayName(InputAction action) { return !string.IsNullOrEmpty(action?.actionMap?.name) ? $"{action.actionMap?.name}/{action.name}" : action?.name; diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs index 9d308c6946..3e2a25b285 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs @@ -1,5 +1,6 @@ #if UNITY_EDITOR using System; +using System.Collections.Generic; using System.IO; using System.Linq; using UnityEditor; @@ -209,6 +210,13 @@ public override void OnImportAsset(AssetImportContext ctx) InputActionEditorWindow.RefreshAllOnAssetReimport(); } + internal static IEnumerable LoadInputActionReferencesFromAsset(InputActionAsset asset) + { + // Assuming InputActionReferences are stored at the same asset path as InputActionAsset + return AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(asset)).Where( + o => o is InputActionReference).Cast(); + } + // Add item to plop an .inputactions asset into the project. [MenuItem("Assets/Create/Input Actions")] public static void CreateInputAsset() diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/Internal/InputActionReferenceValidator.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/Internal/InputActionReferenceValidator.cs new file mode 100644 index 0000000000..2b49d909a6 --- /dev/null +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/Internal/InputActionReferenceValidator.cs @@ -0,0 +1,185 @@ +#if UNITY_EDITOR + +using System.Linq; +using UnityEditor; +using UnityEngine.InputSystem.Utilities; + +namespace UnityEngine.InputSystem.Editor +{ + interface IInputActionAssetReferenceValidator + { + void OnInvalidate(InputActionAsset asset, InputActionReference reference); + void OnInvalidReference(InputActionAsset asset, InputActionReference reference); + void OnDuplicateReference(InputActionAsset asset, InputActionReference reference); + void OnMissingReference(InputActionAsset asset, InputAction action); + } + + internal class DefaultInputActionAssetReferenceValidator : IInputActionAssetReferenceValidator + { + public void OnInvalidate(InputActionAsset asset, InputActionReference reference) + { + reference.Invalidate(); + } + + public void OnInvalidReference(InputActionAsset asset, InputActionReference reference) + { + AssetDatabase.RemoveObjectFromAsset(reference); + Undo.DestroyObjectImmediate(reference); // Enable undo + } + + public void OnDuplicateReference(InputActionAsset asset, InputActionReference reference) + { + OnInvalidReference(asset, reference); // Same action, delete it + } + + public void OnMissingReference(InputActionAsset asset, InputAction action) + { + var reference = InputActionReference.Create(action); + AssetDatabase.AddObjectToAsset(reference, asset); + } + } + + internal class LoggingInputActionAssetReferenceValidator : IInputActionAssetReferenceValidator + { + public void OnInvalidate(InputActionAsset asset, InputActionReference reference) + { + Debug.Log($"OnInvalidate(asset: {asset}, reference:{reference})"); + } + + public void OnInvalidReference(InputActionAsset asset, InputActionReference reference) + { + Debug.Log($"OnInvalidReference(asset: {asset}, reference:{reference})"); + } + + public void OnDuplicateReference(InputActionAsset asset, InputActionReference reference) + { + Debug.Log($"OnDuplicateReference(asset: {asset}, reference:{reference})"); + } + + public void OnMissingReference(InputActionAsset asset, InputAction action) + { + Debug.Log($"OnMissingReference(asset: {asset}, action:{action})"); + } + } + + // TODO Known issues: + // This doesn't work correctly, doing bulk updates like this works well only up to the point the user + // engages with the undo system. Scenario: Reference an action in the Inspector. Delete action in editor, + // notice that inspector changes to "Missing (Input Action Reference)" as object is destroyed. + // Then if user undo the operation there are two issues: + // - Editor is restored to an object not referencing an existing editor object. + // - The deletion in editor and inspector re-resolve is considered two different undo steps, they need + // to be an atomic step. + // + // TODO Instead we likely need to integrate all reference management into each step of the editor. + internal class InputActionReferenceValidator + { + public static void ValidateReferences(InputActionAsset asset) + { + if (asset == null) + return; + + //Debug.Log("ValidateReferences " + asset); + + void RemoveReferenceAtIndex(InputActionReference[] references, ref int count, int index) + { + var reference = references[index]; + ArrayHelpers.EraseAtByMovingTail(references, ref count, index); + AssetDatabase.RemoveObjectFromAsset(reference); + Undo.DestroyObjectImmediate(reference); // Enable undo + } + + // Fetch input action references (Note that this will allocate an array) + var references = InputActionImporter.LoadInputActionReferencesFromAsset(asset).ToArray(); + + // Remove dangling references + var initialCount = references.Length; + var count = initialCount; + for (var i = count - 1; i >= 0; --i) + { + // TODO Below comparison want work,. maybe ReferenceEquals works or find another way + // If invalid (no asset, no action ID or not found within this asset) - remove the reference + /*if (!references[i].m_Asset != asset) + { + Debug.Log("Removing reference with invalid asset reference"); + RemoveReferenceAtIndex(references, ref count, i); + continue; + }*/ + + var referencedAction = asset.FindActionById(references[i].m_ActionId); + if (referencedAction == null) + { + Debug.Log("Removing invalid or dangling InputActionReference: " + references[i]); + RemoveReferenceAtIndex(references, ref count, i); + } + else // Reference is associated with an action of this asset as expected + { + // Look for first duplicate reference referencing the same action and eliminate this reference + // if duplicates exist (Should not happen, basically corrupt asset). Additional duplicates are + // covered since this is evaluated for each element. + for (var j = i - 1; j >= 0; --j) + { + if (ReferenceEquals(references[j].m_Asset, references[i].m_Asset) && + references[j].m_ActionId == references[i].m_ActionId) + { + Debug.Log("Removing duplicate InputActionReference: " + references[i]); + RemoveReferenceAtIndex(references, ref count, i); + break; + } + } + } + } + + // Handle added or removed actions + foreach (var action in asset) + { + var referenceIndex = references.IndexOf(r => r.m_ActionId == action.m_Id, 0, count); + if (referenceIndex >= 0) + { + // Action has exactly one reference as expected, invalidate name if action has changed name + var reference = references[referenceIndex]; + //SerializedObject obj = new SerializedObject(reference); + //var assetProperty = obj.FindProperty(nameof(InputActionReference.m_Asset)); + //var actionIdProperty = obj.FindProperty(nameof(InputActionReference.m_ActionId)); + //var action = obj.FindProperty(nameof(InputActionReference.m_Ac)) + reference.Set(action); // Invalidate() + } + else + { + // Action is missing a reference so we add it + var reference = InputActionReference.Create(action); + ArrayHelpers.Append(ref references, reference); + AssetDatabase.AddObjectToAsset(reference, asset); + Debug.Log("Added missing action reference: " + reference); + } + } + + asset.m_References = references; + } + + // TODO Code below this point is targeted at debugging and should be removed before merge + + [MenuItem("Test/Log AssetPath References")] + public static void Dump() + { + var assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(ProjectWideActionsAsset.GetOrCreate())); + foreach (var asset in assets) + { + var reference = asset as InputActionReference; + if (reference != null) + Debug.Log(reference); + } + } + + [MenuItem("Test/Log InputActionAsset References")] + public static void Dump2() + { + foreach (var reference in ProjectWideActionsAsset.GetOrCreate().m_References) + { + Debug.Log(reference); + } + } + } +} + +#endif // #if UNITY_EDITOR diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/Internal/InputActionReferenceValidator.cs.meta b/Packages/com.unity.inputsystem/InputSystem/Editor/Internal/InputActionReferenceValidator.cs.meta new file mode 100644 index 0000000000..95c97e3b57 --- /dev/null +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/Internal/InputActionReferenceValidator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ddac3ccb045745ed9e89e0772832e82f +timeCreated: 1697620704 \ No newline at end of file diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/ProjectWideActions/ProjectWideActionsAsset.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/ProjectWideActions/ProjectWideActionsAsset.cs index 66707855ce..54ef227e34 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/ProjectWideActions/ProjectWideActionsAsset.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/ProjectWideActions/ProjectWideActionsAsset.cs @@ -66,11 +66,13 @@ internal static InputActionAsset GetOrCreate() private static InputActionAsset CreateNewActionAsset() { + // Read JSON file content representing a serialized version of the InputActionAsset var json = File.ReadAllText(Path.Combine(Environment.CurrentDirectory, s_DefaultAssetPath)); var asset = ScriptableObject.CreateInstance(); asset.LoadFromJson(json); asset.name = kAssetName; + asset.m_ValidateReferencesInEditMode = true; AssetDatabase.AddObjectToAsset(asset, s_AssetPath); @@ -101,16 +103,26 @@ private static InputActionAsset CreateNewActionAsset() // Create sub-asset for each action. This is so that users can select individual input actions from the asset when they're // trying to assign to a field that accepts only one action. + var index = 0; + var inputActionReferences = new InputActionReference[asset.Count()]; foreach (var map in maps) { foreach (var action in map.actions) { - var actionReference = ScriptableObject.CreateInstance(); - actionReference.Set(action); + var actionReference = InputActionReference.Create(action); AssetDatabase.AddObjectToAsset(actionReference, asset); + + // Keep track of associated references to avoid creating new ones when queried by e.g. pickers + // (not a big deal) but also to provide object persistence. If we would not create these we could + // instead let all references serialize at user-side, but that would also require us to anyway + // keep a registry of them in InputActionAsset in order to validate them. + //asset.m_References.Add(actionReference); + inputActionReferences[index++] = actionReference; } } + asset.m_References = inputActionReferences; + AssetDatabase.SaveAssets(); return asset; diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs index 44e3cdc31d..d737fd9e29 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; -using UnityEditor; using UnityEditor.Search; namespace UnityEngine.InputSystem.Editor @@ -12,10 +11,10 @@ internal static class SearchConstants // SearchFlags : these flags are used to customize how search is performed and how search // results are displayed. // Note that SearchFlags.Packages is not currently used and hides all results from packages. - internal static readonly SearchFlags SearchFlags = SearchFlags.Sorted | SearchFlags.OpenPicker; + internal static readonly SearchFlags PickerSearchFlags = SearchFlags.Sorted | SearchFlags.OpenPicker; // Search.SearchViewFlags : these flags are used to customize the appearance of the PickerWindow. - internal static readonly Search.SearchViewFlags ViewFlags = Search.SearchViewFlags.OpenInBuilderMode | + internal static readonly Search.SearchViewFlags PickerViewFlags = Search.SearchViewFlags.OpenInBuilderMode | Search.SearchViewFlags.DisableBuilderModeToggle | Search.SearchViewFlags.DisableInspectorPreview | Search.SearchViewFlags.DisableSavedSearchQuery; @@ -23,64 +22,74 @@ internal static class SearchConstants internal static class AssetSearchProviders { - // Note that if this method is annotated with [SearchItemProvider] we would register the provider to - // the SearchWindow, we currently skip this since we are mainly interested in using SearchItemProvider as - // a picker. - private static SearchProvider CreateAssetSearchProvider(string id, string displayName, - Func> assetProvider, Texture2D thumbnail = null) + internal static SearchProvider CreateDefaultProvider() + { + // Known issues with current ADB implementation: + // - Asset icon reverts to file-icon on minimum zoom level. + // - AssetDatabase.CachedIcon fails to retrieve custom package type icon. + return UnityEditor.Search.SearchService.GetProvider("adb"); + } + + private static SearchProvider CreateInputActionReferenceSearchProvider(string id, string displayName, + Func createItemFetchDescription, Func> fetchAssets) { + // Match icon used for sub-assets from importer for InputActionReferences. + // Note that we assign description+label in FilteredSearch but also provide a fetchDescription+fetchLabel below. + // This is needed to support all zoom-modes for unknown reason. + // ALso not that fetchLabel/fetchDescription and what is provided to CreateItem is playing different + // roles at different zoom levels. + var inputActionReferenceIcon = InputActionAssetIconProvider.LoadActionIcon(); return new SearchProvider(id, displayName) { priority = 25, - toObject = GetObject, - fetchItems = (context, items, provider) => Search(context, provider, assetProvider, thumbnail), + fetchDescription = FetchLabel, + fetchItems = (context, items, provider) => FilteredSearch(context, provider, FetchLabel, createItemFetchDescription, + fetchAssets, "(Project-Wide Input Actions)"), + fetchLabel = FetchLabel, + fetchPreview = (item, context, size, options) => inputActionReferenceIcon, + fetchThumbnail = (item, context) => inputActionReferenceIcon, + toObject = (item, type) => item.data as Object }; } - internal static SearchProvider CreateDefaultProvider() + internal static SearchProvider CreateProjectWideInputActionReferenceSearchProvider() { - return UnityEditor.Search.SearchService.GetProvider("adb"); + return CreateInputActionReferenceSearchProvider("InputActionReferencePickerSearchProvider", + "Project-Wide Input Actions", + (obj) => "(Project-Wide Input Actions)", + () => InputActionImporter.LoadInputActionReferencesFromAsset(ProjectWideActionsAsset.GetOrCreate())); } - internal static SearchProvider CreateInputActionReferenceSearchProvider() + // Custom search function with label matching filtering. + private static IEnumerable FilteredSearch(SearchContext context, SearchProvider provider, + Func fetchObjectLabel, Func createItemFetchDescription, Func> fetchAssets, string description) { - // Match icon used for sub-assets from importer, if null will use cached icon from asset database instead. - // Note that .inputactions has one icon and sub-assets (actions) have another in the importer. - return CreateAssetSearchProvider( - "InputActionReferenceSearchProvider", - "Project-Wide Input Actions", - GetInputActionReferenceAssets, - InputActionAssetIconProvider.LoadActionIcon()); + foreach (var asset in fetchAssets()) + { + var label = fetchObjectLabel(asset); + if (!label.Contains(context.searchText, System.StringComparison.InvariantCultureIgnoreCase)) + continue; // Ignore due to filtering + yield return provider.CreateItem(context, asset.GetInstanceID().ToString(), label, createItemFetchDescription(asset), + null, asset); + } } - private static IEnumerable GetInputActionReferenceAssets() + // Note that this is overloaded to allow utilizing FetchLabel inside fetchItems to keep label formatting + // consistent between CreateItem and additional fetchLabel calls. + + private static string FetchLabel(Object obj) { - var asset = ProjectWideActionsAsset.GetOrCreate(); // alt. InputSystem.actions - return (from actionMap in asset.actionMaps from action in actionMap.actions select InputActionReference.Create(action)).ToList(); + return obj.name; } - static IEnumerable Search( - SearchContext context, SearchProvider provider, Func> assetProvider, Texture2D thumbnail) + private static string FetchLabel(SearchItem item, SearchContext context) { - foreach (var asset in assetProvider()) - { - var label = asset.name; - if (!label.Contains(context.searchText, System.StringComparison.InvariantCultureIgnoreCase)) - continue; // Ignore: not matching search text filter - - var assetPath = AssetDatabase.GetAssetPath(asset); - yield return provider.CreateItem(context, - asset.GetInstanceID().ToString(), - label, - $"{assetPath} ({label})", - (thumbnail == null) ? AssetDatabase.GetCachedIcon(assetPath) as Texture2D : thumbnail, - asset); - } + return FetchLabel((item.data as Object) !); } - private static Object GetObject(SearchItem item, System.Type type) + private static IEnumerable GetInputActionReferences(InputActionAsset asset) { - return item.data as Object; + return (from actionMap in asset.actionMaps from action in actionMap.actions select InputActionReference.Create(action)); } } } diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs index 1b40c32e52..7e5f341010 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs @@ -18,14 +18,42 @@ internal sealed class InputActionReferencePropertyDrawer : PropertyDrawer private readonly SearchContext m_Context = UnityEditor.Search.SearchService.CreateContext(new[] { AssetSearchProviders.CreateDefaultProvider(), - AssetSearchProviders.CreateInputActionReferenceSearchProvider() - }, string.Empty, SearchConstants.SearchFlags); + AssetSearchProviders.CreateProjectWideInputActionReferenceSearchProvider(), + }, string.Empty, SearchConstants.PickerSearchFlags); + + private void OnValidate() + { + Debug.Log("OnValidate editor"); + } - // Advanced Picker in IMGUI, keeping for reference public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { ObjectField.DoObjectField(position, property, typeof(InputActionReference), label, - m_Context, SearchConstants.ViewFlags); + m_Context, SearchConstants.PickerViewFlags); + +#if false // TODO Remove this code before final version/merge + // This is debug code to simplify evaluate desynchronized InputActionReference instances + var buttonRect = position; + var popupStyle = Styles.popup; + buttonRect.yMin += popupStyle.margin.top + 1f; + buttonRect.width = popupStyle.fixedWidth + popupStyle.margin.right + 5f; + buttonRect.height = EditorGUIUtility.singleLineHeight; + buttonRect.x += 75; + + if (GUI.Button(buttonRect, "D")) + { + var reference = property.objectReferenceValue as InputActionReference; + if (reference != null) + Debug.Log(label + ": " + property.objectReferenceValue + ", " + reference.action); + else + Debug.Log(label + ": null"); + } +#endif + } + + static class Styles + { + public static readonly GUIStyle popup = new GUIStyle("PaneOptions") { imagePosition = ImagePosition.ImageOnly }; } // Advanced Picker in UITk diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorSettingsProvider.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorSettingsProvider.cs index 3b186ad404..9e8a97e5db 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorSettingsProvider.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorSettingsProvider.cs @@ -35,7 +35,7 @@ public override void OnActivate(string searchContext, VisualElement rootElement) // Note that focused element will be set if we are navigating back to // an existing instance when switching setting in the left project settings panel since // this doesn't recreate the editor. - if (m_RootVisualElement.focusController.focusedElement != null) + if (m_RootVisualElement?.focusController?.focusedElement != null) OnEditFocus(null); } @@ -76,6 +76,7 @@ private void OnEditFocusLost(FocusOutEvent @event) m_HasEditFocus = false; #if UNITY_INPUT_SYSTEM_INPUT_ACTIONS_EDITOR_AUTO_SAVE_ON_FOCUS_LOST + Debug.Log("SaveAsset"); InputActionsEditorWindowUtils.SaveAsset(m_State.serializedObject); #endif } diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindowUtils.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindowUtils.cs index e87d0877b8..ee9f5b4bde 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindowUtils.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindowUtils.cs @@ -17,6 +17,7 @@ public static void SaveAsset(SerializedObject serializedAsset) // for the global actions asset: save differently (as it is a yaml file and not a json) if (ProjectWideActionsAsset.IsProjectWideActionsAsset(asset)) { + InputActionReferenceValidator.ValidateReferences(asset); AssetDatabase.SaveAssets(); return; } diff --git a/Packages/com.unity.inputsystem/InputSystem/Utilities/ArrayHelpers.cs b/Packages/com.unity.inputsystem/InputSystem/Utilities/ArrayHelpers.cs index 54a4972495..3312a19f95 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Utilities/ArrayHelpers.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Utilities/ArrayHelpers.cs @@ -628,6 +628,27 @@ public static bool Erase(ref TValue[] array, TValue value) return false; } + public static void EraseAll(ref TValue[] array, TValue value, IEqualityComparer comparer) + { + Debug.Assert(array != null); + + // Move tail element into position of element to be deleted (if necessary) and finally + // resize the array to to match capacity of elements contained. + // Note that Array.Resize is a no-op if size is unchanged. + var count = array.Length; + for (var i = count - 1; i >= 0; --i) + { + if (comparer.Equals(array[i], value)) + { + if (i != count - 1) + array[i] = array[count - 1]; + --count; + } + } + + Array.Resize(ref array, count); + } + /// /// Erase an element from the array by moving the tail element into its place. /// From 2c76576c3ffff60e1e37b40072555f2aedc77187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Freire?= Date: Mon, 23 Oct 2023 12:35:27 +0200 Subject: [PATCH 16/16] Change asset search provider to same logic as project-wide actions provider Instead of relying in the default provider, a "custom" provider was created to search input action references on all assets in the asset DB. --- .../AssetImporter/InputActionImporter.cs | 33 ++++++++++- .../PropertyDrawers/AssetSearchProviders.cs | 35 ++++++------ .../InputActionReferencePropertyDrawer.cs | 56 +------------------ 3 files changed, 51 insertions(+), 73 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs index 3e2a25b285..7863b1edf4 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs @@ -212,11 +212,42 @@ public override void OnImportAsset(AssetImportContext ctx) internal static IEnumerable LoadInputActionReferencesFromAsset(InputActionAsset asset) { - // Assuming InputActionReferences are stored at the same asset path as InputActionAsset + //Get all InputActionReferences are stored at the same asset path as InputActionAsset return AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(asset)).Where( o => o is InputActionReference).Cast(); } + internal static IEnumerable LoadInputActionReferencesFromAssetDatabase(string[] folderPath = null) + { + string[] searchInFolderPath = null; + // If folderPath is null, search in "Assets" folder. + if (folderPath == null) + { + searchInFolderPath = new string[] { "Assets" }; + } + + // Get all InputActionReference from assets in "Asset" folder. It does not search inside "Packages" folder. + var inputActionReferenceGUIDs = AssetDatabase.FindAssets($"t:{typeof(InputActionReference).Name}", searchInFolderPath); + + // To find all the InputActionReferences, the GUID of the asset containing at least one action reference is + // used to find the asset path. This is because InputActionReferences are stored in the asset database as sub-assets of InputActionAsset. + // Then the whole asset is loaded and all the InputActionReferences are extracted from it. + // Also, the action references are duplicated to have backwards compatibility with the 1.0.0-preview.7. That + // is why we look for references withouth the `HideFlags.HideInHierarchy` flag. + var inputActionReferencesList = new List(); + foreach (var guid in inputActionReferenceGUIDs) + { + var assetName = AssetDatabase.GUIDToAssetPath(guid); + var assetInputActionReferenceList = AssetDatabase.LoadAllAssetsAtPath(assetName).Where( + o => o is InputActionReference && + !((InputActionReference)o).hideFlags.HasFlag(HideFlags.HideInHierarchy)) + .Cast().ToList(); + + inputActionReferencesList.AddRange(assetInputActionReferenceList); + } + return inputActionReferencesList; + } + // Add item to plop an .inputactions asset into the project. [MenuItem("Assets/Create/Input Actions")] public static void CreateInputAsset() diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs index d737fd9e29..18e3c84594 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/AssetSearchProviders.cs @@ -14,20 +14,23 @@ internal static class SearchConstants internal static readonly SearchFlags PickerSearchFlags = SearchFlags.Sorted | SearchFlags.OpenPicker; // Search.SearchViewFlags : these flags are used to customize the appearance of the PickerWindow. - internal static readonly Search.SearchViewFlags PickerViewFlags = Search.SearchViewFlags.OpenInBuilderMode | - Search.SearchViewFlags.DisableBuilderModeToggle | - Search.SearchViewFlags.DisableInspectorPreview | - Search.SearchViewFlags.DisableSavedSearchQuery; + internal static readonly Search.SearchViewFlags PickerViewFlags = Search.SearchViewFlags.OpenInBuilderMode + | Search.SearchViewFlags.DisableBuilderModeToggle + | Search.SearchViewFlags.DisableInspectorPreview + | Search.SearchViewFlags.DisableSavedSearchQuery; } internal static class AssetSearchProviders { - internal static SearchProvider CreateDefaultProvider() + const string k_AssetFolderSearchProviderId = "AssetsInputActionReferenceSearchProvider"; + const string k_ProjectWideActionsSearchProviderId = "ProjectWideInputActionReferenceSearchProvider"; + + internal static SearchProvider CreateInputActionReferenceSearchProviderForAssets() { - // Known issues with current ADB implementation: - // - Asset icon reverts to file-icon on minimum zoom level. - // - AssetDatabase.CachedIcon fails to retrieve custom package type icon. - return UnityEditor.Search.SearchService.GetProvider("adb"); + return CreateInputActionReferenceSearchProvider(k_AssetFolderSearchProviderId, + "Asset Input Actions", + (obj) => "(Input Actions)", + () => InputActionImporter.LoadInputActionReferencesFromAssetDatabase()); } private static SearchProvider CreateInputActionReferenceSearchProvider(string id, string displayName, @@ -36,9 +39,10 @@ private static SearchProvider CreateInputActionReferenceSearchProvider(string id // Match icon used for sub-assets from importer for InputActionReferences. // Note that we assign description+label in FilteredSearch but also provide a fetchDescription+fetchLabel below. // This is needed to support all zoom-modes for unknown reason. - // ALso not that fetchLabel/fetchDescription and what is provided to CreateItem is playing different + // Also note that fetchLabel/fetchDescription and what is provided to CreateItem is playing different // roles at different zoom levels. var inputActionReferenceIcon = InputActionAssetIconProvider.LoadActionIcon(); + return new SearchProvider(id, displayName) { priority = 25, @@ -48,13 +52,13 @@ private static SearchProvider CreateInputActionReferenceSearchProvider(string id fetchLabel = FetchLabel, fetchPreview = (item, context, size, options) => inputActionReferenceIcon, fetchThumbnail = (item, context) => inputActionReferenceIcon, - toObject = (item, type) => item.data as Object + toObject = (item, type) => item.data as Object, }; } - internal static SearchProvider CreateProjectWideInputActionReferenceSearchProvider() + internal static SearchProvider CreateInputActionReferenceSearchProviderForProjectWideActions() { - return CreateInputActionReferenceSearchProvider("InputActionReferencePickerSearchProvider", + return CreateInputActionReferenceSearchProvider(k_ProjectWideActionsSearchProviderId, "Project-Wide Input Actions", (obj) => "(Project-Wide Input Actions)", () => InputActionImporter.LoadInputActionReferencesFromAsset(ProjectWideActionsAsset.GetOrCreate())); @@ -86,11 +90,6 @@ private static string FetchLabel(SearchItem item, SearchContext context) { return FetchLabel((item.data as Object) !); } - - private static IEnumerable GetInputActionReferences(InputActionAsset asset) - { - return (from actionMap in asset.actionMaps from action in actionMap.actions select InputActionReference.Create(action)); - } } } #endif diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs index 7e5f341010..13508d968c 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs @@ -13,12 +13,10 @@ namespace UnityEngine.InputSystem.Editor [CustomPropertyDrawer(typeof(InputActionReference))] internal sealed class InputActionReferencePropertyDrawer : PropertyDrawer { - // By default ADB search provider yields ALL assets even if the search query is empty. - // AssetProvider ("asset") will NOT yield anything if searchQuery is empty. private readonly SearchContext m_Context = UnityEditor.Search.SearchService.CreateContext(new[] { - AssetSearchProviders.CreateDefaultProvider(), - AssetSearchProviders.CreateProjectWideInputActionReferenceSearchProvider(), + AssetSearchProviders.CreateInputActionReferenceSearchProviderForAssets(), + AssetSearchProviders.CreateInputActionReferenceSearchProviderForProjectWideActions(), }, string.Empty, SearchConstants.PickerSearchFlags); private void OnValidate() @@ -30,57 +28,7 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten { ObjectField.DoObjectField(position, property, typeof(InputActionReference), label, m_Context, SearchConstants.PickerViewFlags); - -#if false // TODO Remove this code before final version/merge - // This is debug code to simplify evaluate desynchronized InputActionReference instances - var buttonRect = position; - var popupStyle = Styles.popup; - buttonRect.yMin += popupStyle.margin.top + 1f; - buttonRect.width = popupStyle.fixedWidth + popupStyle.margin.right + 5f; - buttonRect.height = EditorGUIUtility.singleLineHeight; - buttonRect.x += 75; - - if (GUI.Button(buttonRect, "D")) - { - var reference = property.objectReferenceValue as InputActionReference; - if (reference != null) - Debug.Log(label + ": " + property.objectReferenceValue + ", " + reference.action); - else - Debug.Log(label + ": null"); - } -#endif - } - - static class Styles - { - public static readonly GUIStyle popup = new GUIStyle("PaneOptions") { imagePosition = ImagePosition.ImageOnly }; } - - // Advanced Picker in UITk - // Kept uncommented as a future reference for modernizing property drawers. - // We can only use this one if we rewrite InputProperty property drawer for UITK as well since it would - // render UI where InputActionReferecePropertyDrawer is a sub interface. - /*public override UIElements.VisualElement CreatePropertyGUI(SerializedProperty prop) - { - ObjectField obj = new ObjectField() - { - name = "InputActionReferenceProperty", - label = preferredLabel, - bindingPath = prop.propertyPath, - objectType = fieldInfo.FieldType, - searchViewFlags = SearchConstants.ViewFlags, - searchContext = m_Context - }; - - // Align width in Inspector - note that ObjectField.alignedFieldUssClassName was made public in 2021.2.7f1 - #if UNITY_2021_3_OR_NEWER - obj.AddToClassList(ObjectField.alignedFieldUssClassName); - #else - obj.AddToClassList(ObjectField.ussClassName + "__aligned"); - #endif - - return obj; - }*/ } }