From e87f0b8af3a1da0701e8e47e068dfc446b129e15 Mon Sep 17 00:00:00 2001 From: Jono Forbes Date: Tue, 14 Nov 2017 18:08:10 -0800 Subject: [PATCH 01/89] Flick left or right on a hidden radial menu to undo/redo. --- Menus/RadialMenu/RadialMenu.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Menus/RadialMenu/RadialMenu.cs b/Menus/RadialMenu/RadialMenu.cs index 5d52e66ae..9510e2f51 100644 --- a/Menus/RadialMenu/RadialMenu.cs +++ b/Menus/RadialMenu/RadialMenu.cs @@ -13,6 +13,7 @@ sealed class RadialMenu : MonoBehaviour, IInstantiateUI, IAlternateMenu, IUsesMe IControlHaptics, IUsesNode, IConnectInterfaces, IRequestFeedback { const float k_ActivationThreshold = 0.5f; // Do not consume thumbstick or activate menu if the control vector's magnitude is below this threshold + const float k_UndoRedoThreshold = 0.5f; [SerializeField] ActionMap m_ActionMap; @@ -33,6 +34,7 @@ sealed class RadialMenu : MonoBehaviour, IInstantiateUI, IAlternateMenu, IUsesMe List m_MenuActions; Transform m_AlternateMenuOrigin; MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; + float m_PrevNavigateX; readonly BindingDictionary m_Controls = new BindingDictionary(); @@ -113,6 +115,21 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon var radialMenuInput = (RadialMenuInput)input; if (radialMenuInput == null || m_MenuHideFlags != 0) { + if (radialMenuInput != null) + { + var navigateX = radialMenuInput.navigateX.value; + if (navigateX < -k_UndoRedoThreshold && m_PrevNavigateX > -k_UndoRedoThreshold) + { + Undo.PerformUndo(); + consumeControl(radialMenuInput.navigateX); + } + else if (navigateX > k_UndoRedoThreshold && m_PrevNavigateX < k_UndoRedoThreshold) + { + Undo.PerformRedo(); + consumeControl(radialMenuInput.navigateX); + } + m_PrevNavigateX = navigateX; + } this.ClearFeedbackRequests(); return; } From 1dd81ec60362f9c60584aabedb5907f94ddefd31 Mon Sep 17 00:00:00 2001 From: Jono Forbes Date: Thu, 16 Nov 2017 14:44:10 -0800 Subject: [PATCH 02/89] Add UndoMenu as a new menu (no longer in the RadialMenu). --- Menus/RadialMenu/RadialMenu.cs | 16 -- Menus/UndoMenu.meta | 10 + Menus/UndoMenu/HapticPulses.meta | 10 + .../HapticPulses/UndoMenuEngaged.asset | 17 ++ .../HapticPulses/UndoMenuEngaged.asset.meta | 10 + Menus/UndoMenu/Materials.meta | 10 + Menus/UndoMenu/Materials/UndoIcon.mat | 77 ++++++ Menus/UndoMenu/Materials/UndoIcon.mat.meta | 10 + Menus/UndoMenu/Prefabs.meta | 10 + Menus/UndoMenu/Prefabs/UndoMenu.prefab | 227 ++++++++++++++++++ Menus/UndoMenu/Prefabs/UndoMenu.prefab.meta | 10 + Menus/UndoMenu/Scripts.meta | 10 + Menus/UndoMenu/Scripts/UndoMenuUI.cs | 68 ++++++ Menus/UndoMenu/Scripts/UndoMenuUI.cs.meta | 17 ++ Menus/UndoMenu/UndoMenu.cs | 150 ++++++++++++ Menus/UndoMenu/UndoMenu.cs.meta | 17 ++ Menus/UndoMenu/UndoMenuInput.asset | 57 +++++ Menus/UndoMenu/UndoMenuInput.asset.meta | 10 + Menus/UndoMenu/UndoMenuInput.cs | 12 + Menus/UndoMenu/UndoMenuInput.cs.meta | 13 + Scripts/Core/EditorVR.Menus.cs | 19 ++ Scripts/Core/EditorVR.Tools.cs | 4 + Scripts/Core/EditorVR.cs | 1 + 23 files changed, 769 insertions(+), 16 deletions(-) create mode 100644 Menus/UndoMenu.meta create mode 100644 Menus/UndoMenu/HapticPulses.meta create mode 100644 Menus/UndoMenu/HapticPulses/UndoMenuEngaged.asset create mode 100644 Menus/UndoMenu/HapticPulses/UndoMenuEngaged.asset.meta create mode 100644 Menus/UndoMenu/Materials.meta create mode 100644 Menus/UndoMenu/Materials/UndoIcon.mat create mode 100644 Menus/UndoMenu/Materials/UndoIcon.mat.meta create mode 100644 Menus/UndoMenu/Prefabs.meta create mode 100644 Menus/UndoMenu/Prefabs/UndoMenu.prefab create mode 100644 Menus/UndoMenu/Prefabs/UndoMenu.prefab.meta create mode 100644 Menus/UndoMenu/Scripts.meta create mode 100644 Menus/UndoMenu/Scripts/UndoMenuUI.cs create mode 100644 Menus/UndoMenu/Scripts/UndoMenuUI.cs.meta create mode 100644 Menus/UndoMenu/UndoMenu.cs create mode 100644 Menus/UndoMenu/UndoMenu.cs.meta create mode 100644 Menus/UndoMenu/UndoMenuInput.asset create mode 100644 Menus/UndoMenu/UndoMenuInput.asset.meta create mode 100644 Menus/UndoMenu/UndoMenuInput.cs create mode 100644 Menus/UndoMenu/UndoMenuInput.cs.meta diff --git a/Menus/RadialMenu/RadialMenu.cs b/Menus/RadialMenu/RadialMenu.cs index 9510e2f51..6039851fc 100644 --- a/Menus/RadialMenu/RadialMenu.cs +++ b/Menus/RadialMenu/RadialMenu.cs @@ -13,7 +13,6 @@ sealed class RadialMenu : MonoBehaviour, IInstantiateUI, IAlternateMenu, IUsesMe IControlHaptics, IUsesNode, IConnectInterfaces, IRequestFeedback { const float k_ActivationThreshold = 0.5f; // Do not consume thumbstick or activate menu if the control vector's magnitude is below this threshold - const float k_UndoRedoThreshold = 0.5f; [SerializeField] ActionMap m_ActionMap; @@ -115,21 +114,6 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon var radialMenuInput = (RadialMenuInput)input; if (radialMenuInput == null || m_MenuHideFlags != 0) { - if (radialMenuInput != null) - { - var navigateX = radialMenuInput.navigateX.value; - if (navigateX < -k_UndoRedoThreshold && m_PrevNavigateX > -k_UndoRedoThreshold) - { - Undo.PerformUndo(); - consumeControl(radialMenuInput.navigateX); - } - else if (navigateX > k_UndoRedoThreshold && m_PrevNavigateX < k_UndoRedoThreshold) - { - Undo.PerformRedo(); - consumeControl(radialMenuInput.navigateX); - } - m_PrevNavigateX = navigateX; - } this.ClearFeedbackRequests(); return; } diff --git a/Menus/UndoMenu.meta b/Menus/UndoMenu.meta new file mode 100644 index 000000000..49cadf4f1 --- /dev/null +++ b/Menus/UndoMenu.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 14f060919ebf4764f9c75cc7f2d1bad4 +folderAsset: yes +timeCreated: 1510791326 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Menus/UndoMenu/HapticPulses.meta b/Menus/UndoMenu/HapticPulses.meta new file mode 100644 index 000000000..8d883ce22 --- /dev/null +++ b/Menus/UndoMenu/HapticPulses.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 580e3ab5f3b5bb743b9efa689995694d +folderAsset: yes +timeCreated: 1510794417 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Menus/UndoMenu/HapticPulses/UndoMenuEngaged.asset b/Menus/UndoMenu/HapticPulses/UndoMenuEngaged.asset new file mode 100644 index 000000000..980b23eb7 --- /dev/null +++ b/Menus/UndoMenu/HapticPulses/UndoMenuEngaged.asset @@ -0,0 +1,17 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1efd705dfe960584581b3390e04777f1, type: 3} + m_Name: UndoMenuEngaged + m_EditorClassIdentifier: + m_Duration: 0.5 + m_Intensity: 0.4 + m_FadeIn: 1 + m_FadeOut: 1 diff --git a/Menus/UndoMenu/HapticPulses/UndoMenuEngaged.asset.meta b/Menus/UndoMenu/HapticPulses/UndoMenuEngaged.asset.meta new file mode 100644 index 000000000..df5b4a6af --- /dev/null +++ b/Menus/UndoMenu/HapticPulses/UndoMenuEngaged.asset.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: bd782c338d41a7946959279464013d86 +timeCreated: 1510794425 +licenseType: Pro +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Menus/UndoMenu/Materials.meta b/Menus/UndoMenu/Materials.meta new file mode 100644 index 000000000..35d37eca9 --- /dev/null +++ b/Menus/UndoMenu/Materials.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 0eed2144b00fdff4faae0b523e7e5e9f +folderAsset: yes +timeCreated: 1510870555 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Menus/UndoMenu/Materials/UndoIcon.mat b/Menus/UndoMenu/Materials/UndoIcon.mat new file mode 100644 index 000000000..60517a69b --- /dev/null +++ b/Menus/UndoMenu/Materials/UndoIcon.mat @@ -0,0 +1,77 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: UndoIcon + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _ALPHABLEND_ON + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: 9503 + stringTagMap: + RenderType: Transparent + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: f7acf93d805e2dd42b4f32bed5d45ce8, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 10 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 2 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 5 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Menus/UndoMenu/Materials/UndoIcon.mat.meta b/Menus/UndoMenu/Materials/UndoIcon.mat.meta new file mode 100644 index 000000000..2d56bd2b1 --- /dev/null +++ b/Menus/UndoMenu/Materials/UndoIcon.mat.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: e7962268b2f9fa74cb6083e33bb15b9f +timeCreated: 1510869715 +licenseType: Pro +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Menus/UndoMenu/Prefabs.meta b/Menus/UndoMenu/Prefabs.meta new file mode 100644 index 000000000..fdab5c1ed --- /dev/null +++ b/Menus/UndoMenu/Prefabs.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 0ce9ff0bef307ae4b81238959cccbfd7 +folderAsset: yes +timeCreated: 1510792833 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Menus/UndoMenu/Prefabs/UndoMenu.prefab b/Menus/UndoMenu/Prefabs/UndoMenu.prefab new file mode 100644 index 000000000..851037ede --- /dev/null +++ b/Menus/UndoMenu/Prefabs/UndoMenu.prefab @@ -0,0 +1,227 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 1828616274790540} + m_IsPrefabParent: 1 +--- !u!1 &1695890495350928 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4386191342587820} + - component: {fileID: 33315744622441324} + - component: {fileID: 64453517736190084} + - component: {fileID: 23859873210418424} + m_Layer: 0 + m_Name: Undo + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1828616274790540 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4579274395351022} + - component: {fileID: 114635161630974218} + m_Layer: 0 + m_Name: UndoMenu + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1919443148181408 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4809501880196944} + - component: {fileID: 33491512569136768} + - component: {fileID: 64290476127420130} + - component: {fileID: 23850276268091638} + m_Layer: 0 + m_Name: Redo + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4386191342587820 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1695890495350928} + m_LocalRotation: {x: 0, y: 0.7071068, z: -0.7071068, w: 0} + m_LocalPosition: {x: 0.01, y: 0, z: 0} + m_LocalScale: {x: 0.02, y: 0.02, z: 0.02} + m_Children: [] + m_Father: {fileID: 4579274395351022} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 90, y: 180, z: 0} +--- !u!4 &4579274395351022 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1828616274790540} + 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_Children: + - {fileID: 4386191342587820} + - {fileID: 4809501880196944} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4809501880196944 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1919443148181408} + m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068} + m_LocalPosition: {x: -0.01, y: 0, z: 0} + m_LocalScale: {x: 0.02, y: 0.02, z: 0.02} + m_Children: [] + m_Father: {fileID: 4579274395351022} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} +--- !u!23 &23850276268091638 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1919443148181408} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 2100000, guid: e7962268b2f9fa74cb6083e33bb15b9f, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &23859873210418424 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1695890495350928} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 2100000, guid: e7962268b2f9fa74cb6083e33bb15b9f, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &33315744622441324 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1695890495350928} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!33 &33491512569136768 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1919443148181408} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!64 &64290476127420130 +MeshCollider: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1919443148181408} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Convex: 0 + m_CookingOptions: 14 + m_SkinWidth: 0.01 + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!64 &64453517736190084 +MeshCollider: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1695890495350928} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Convex: 0 + m_CookingOptions: 14 + m_SkinWidth: 0.01 + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!114 &114635161630974218 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1828616274790540} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b8ebdbcab31646f4da31c5a9a3f2ce5b, type: 3} + m_Name: + m_EditorClassIdentifier: diff --git a/Menus/UndoMenu/Prefabs/UndoMenu.prefab.meta b/Menus/UndoMenu/Prefabs/UndoMenu.prefab.meta new file mode 100644 index 000000000..20e3ac455 --- /dev/null +++ b/Menus/UndoMenu/Prefabs/UndoMenu.prefab.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: ef4e3be7ea1e33b48b3359b2073bb0f3 +timeCreated: 1510792911 +licenseType: Pro +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 100100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Menus/UndoMenu/Scripts.meta b/Menus/UndoMenu/Scripts.meta new file mode 100644 index 000000000..a66b09e4a --- /dev/null +++ b/Menus/UndoMenu/Scripts.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: da8416cc900b6a241991c670bc7c3883 +folderAsset: yes +timeCreated: 1510792819 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Menus/UndoMenu/Scripts/UndoMenuUI.cs b/Menus/UndoMenu/Scripts/UndoMenuUI.cs new file mode 100644 index 000000000..a03362a37 --- /dev/null +++ b/Menus/UndoMenu/Scripts/UndoMenuUI.cs @@ -0,0 +1,68 @@ +#if UNITY_EDITOR +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace UnityEditor.Experimental.EditorVR.Menus +{ + sealed class UndoMenuUI : MonoBehaviour, IConnectInterfaces + { + public Transform alternateMenuOrigin + { + get { return m_AlternateMenuOrigin; } + set + { + if (m_AlternateMenuOrigin == value) + return; + + m_AlternateMenuOrigin = value; + transform.SetParent(m_AlternateMenuOrigin); + transform.localPosition = Vector3.zero; + transform.localRotation = Quaternion.identity; + } + } + + Transform m_AlternateMenuOrigin; + + public bool visible + { + get { return m_Visible; } + set + { + if (m_Visible == value) + return; + + m_Visible = value; + + gameObject.SetActive(value); + } + } + + bool m_Visible; + + public List actions + { + get { return m_Actions; } + set + { + if (value != null) + { + m_Actions = value + .Where(a => a.sectionName != null && a.sectionName == ActionMenuItemAttribute.DefaultActionSectionName) + .OrderBy(a => a.priority) + .ToList(); + } + else if (visible) + visible = false; + } + } + + List m_Actions; + + public void Setup() + { + gameObject.SetActive(false); + } + } +} +#endif diff --git a/Menus/UndoMenu/Scripts/UndoMenuUI.cs.meta b/Menus/UndoMenu/Scripts/UndoMenuUI.cs.meta new file mode 100644 index 000000000..f2e323f09 --- /dev/null +++ b/Menus/UndoMenu/Scripts/UndoMenuUI.cs.meta @@ -0,0 +1,17 @@ +fileFormatVersion: 2 +guid: b8ebdbcab31646f4da31c5a9a3f2ce5b +timeCreated: 1476917998 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: + - m_MissingActionIcon: {fileID: 21300000, guid: 15545907e08dab74692cb3d226382ced, + type: 3} + - m_SlotsMask: {instanceID: 0} + - m_RadialMenuSlotTemplate: {instanceID: 0} + - m_SlotContainer: {instanceID: 0} + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Menus/UndoMenu/UndoMenu.cs b/Menus/UndoMenu/UndoMenu.cs new file mode 100644 index 000000000..9ab692c82 --- /dev/null +++ b/Menus/UndoMenu/UndoMenu.cs @@ -0,0 +1,150 @@ +#if UNITY_EDITOR +using System; +using System.Collections.Generic; +using UnityEditor.Experimental.EditorVR.Core; +using UnityEditor.Experimental.EditorVR.Proxies; +using UnityEditor.Experimental.EditorVR.Utilities; +using UnityEngine; +using UnityEngine.InputNew; + +namespace UnityEditor.Experimental.EditorVR.Menus +{ + sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IAlternateMenu, IUsesMenuOrigins, ICustomActionMap, + IControlHaptics, IUsesNode, IConnectInterfaces, IRequestFeedback + { + const float k_UndoRedoThreshold = 0.5f; + + [SerializeField] + ActionMap m_ActionMap; + + [SerializeField] + UndoMenuUI m_UndoMenuPrefab; + + [SerializeField] + HapticPulse m_UndoPulse; + + UndoMenuUI m_UndoMenuUI; + List m_MenuActions; + Transform m_AlternateMenuOrigin; + MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; + float m_PrevNavigateX; + + readonly BindingDictionary m_Controls = new BindingDictionary(); + + public Transform rayOrigin { private get; set; } + + public Transform menuOrigin { get; set; } + + public GameObject menuContent { get { return m_UndoMenuUI.gameObject; } } + + public Node node { get; set; } + + public event Action itemWasSelected; + + public Bounds localBounds { get { return default(Bounds); } } + + public ActionMap actionMap { get { return m_ActionMap; } } + public bool ignoreLocking { get { return false; } } + + public List menuActions + { + get { return m_MenuActions; } + set + { + m_MenuActions = value; + + if (m_UndoMenuUI) + m_UndoMenuUI.actions = value; + } + } + + public Transform alternateMenuOrigin + { + get { return m_AlternateMenuOrigin; } + set + { + m_AlternateMenuOrigin = value; + + if (m_UndoMenuUI != null) + m_UndoMenuUI.alternateMenuOrigin = value; + } + } + + public MenuHideFlags menuHideFlags + { + get { return m_MenuHideFlags; } + set + { + if (m_MenuHideFlags != value) + { + m_MenuHideFlags = value; + var visible = value == 0; + if (m_UndoMenuUI) + m_UndoMenuUI.visible = visible; + + if (visible) + ShowFeedback(); + else + this.ClearFeedbackRequests(); + } + } + } + + void Start() + { + m_UndoMenuUI = this.InstantiateUI(m_UndoMenuPrefab.gameObject).GetComponent(); + m_UndoMenuUI.alternateMenuOrigin = alternateMenuOrigin; + m_UndoMenuUI.actions = menuActions; + this.ConnectInterfaces(m_UndoMenuUI); // Connect interfaces before performing setup on the UI + m_UndoMenuUI.Setup(); + InputUtils.GetBindingDictionaryFromActionMap(m_ActionMap, m_Controls); + } + + public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl) + { + var undoMenuInput = (UndoMenuInput)input; + if (undoMenuInput == null) + { + this.ClearFeedbackRequests(); + return; + } + + var navigateX = undoMenuInput.navigateX.value; + var undoRedoEngaged = false; + if (navigateX < -k_UndoRedoThreshold && m_PrevNavigateX > -k_UndoRedoThreshold) + { + Undo.PerformUndo(); + undoRedoEngaged = true; + } + else if (navigateX > k_UndoRedoThreshold && m_PrevNavigateX < k_UndoRedoThreshold) + { + Undo.PerformRedo(); + undoRedoEngaged = true; + } + m_PrevNavigateX = navigateX; + if (undoRedoEngaged) + { + consumeControl(undoMenuInput.navigateX); + this.Pulse(node, m_UndoPulse); + } + } + + void ShowFeedback() + { + List controls; + if (m_Controls.TryGetValue("SelectItem", out controls)) + { + foreach (var id in controls) + { + this.AddFeedbackRequest(new ProxyFeedbackRequest + { + control = id, + node = node, + tooltipText = "Select Action (Press to Execute)" + }); + } + } + } + } +} +#endif diff --git a/Menus/UndoMenu/UndoMenu.cs.meta b/Menus/UndoMenu/UndoMenu.cs.meta new file mode 100644 index 000000000..b4e756efd --- /dev/null +++ b/Menus/UndoMenu/UndoMenu.cs.meta @@ -0,0 +1,17 @@ +fileFormatVersion: 2 +guid: c99359ddbc777c54b8bbcb77f816dec5 +timeCreated: 1510794469 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: + - m_ActionMap: {fileID: 11400000, guid: cda0a686e569b574b97504a76b497815, type: 2} + - m_UndoMenuPrefab: {fileID: 114635161630974218, guid: ef4e3be7ea1e33b48b3359b2073bb0f3, + type: 2} + - m_UndoPulse: {fileID: 11400000, guid: bd782c338d41a7946959279464013d86, type: 2} + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Menus/UndoMenu/UndoMenuInput.asset b/Menus/UndoMenu/UndoMenuInput.asset new file mode 100644 index 000000000..5c9b20dc5 --- /dev/null +++ b/Menus/UndoMenu/UndoMenuInput.asset @@ -0,0 +1,57 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 24e5bc088c9caeb44bc4283dc321b033, type: 3} + m_Name: UndoMenuInput + m_EditorClassIdentifier: + m_Actions: + - {fileID: 114324171257110392} + m_ControlSchemes: + - m_Name: UndoMenu + m_DeviceSlots: + - m_Key: 1 + m_Type: + m_TypeName: UnityEngine.InputNew.VRInputDevice, Assembly-CSharp, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + m_TagIndex: -1 + m_ActionMap: {fileID: 11400000} + m_Bindings: + - sources: + - controlIndex: 0 + deviceKey: 1 + deadZone: 0.3 + buttonAxisSources: [] + gravity: 1000 + sensitivity: 1000 + snap: 1 + primaryIsButtonAxis: 0 + m_MapTypeName: UndoMenuInput, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null + m_CustomNamespace: +--- !u!114 &114324171257110392 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5eba7b4b2e3ea134991ccbff5f47c2c8, type: 3} + m_Name: NavigateX + m_EditorClassIdentifier: + m_ActionMap: {fileID: 11400000} + m_ActionIndex: 0 + m_ControlData: + componentControlIndices: + controlType: + m_TypeName: UnityEngine.InputNew.AxisInputControl, Assembly-CSharp, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + name: NavigateX + defaultValue: 0 diff --git a/Menus/UndoMenu/UndoMenuInput.asset.meta b/Menus/UndoMenu/UndoMenuInput.asset.meta new file mode 100644 index 000000000..decfc3487 --- /dev/null +++ b/Menus/UndoMenu/UndoMenuInput.asset.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: cda0a686e569b574b97504a76b497815 +timeCreated: 1510792084 +licenseType: Pro +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Menus/UndoMenu/UndoMenuInput.cs b/Menus/UndoMenu/UndoMenuInput.cs new file mode 100644 index 000000000..2a50b6537 --- /dev/null +++ b/Menus/UndoMenu/UndoMenuInput.cs @@ -0,0 +1,12 @@ +using UnityEngine; +using UnityEngine.InputNew; + +// GENERATED FILE - DO NOT EDIT MANUALLY +namespace UnityEngine.InputNew +{ + public class UndoMenuInput : ActionMapInput { + public UndoMenuInput (ActionMap actionMap) : base (actionMap) { } + + public AxisInputControl @navigateX { get { return (AxisInputControl)this[0]; } } + } +} diff --git a/Menus/UndoMenu/UndoMenuInput.cs.meta b/Menus/UndoMenu/UndoMenuInput.cs.meta new file mode 100644 index 000000000..f74916f28 --- /dev/null +++ b/Menus/UndoMenu/UndoMenuInput.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 8d787422bd98e624aa130c05c11e85b6 +timeCreated: 1510792094 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Core/EditorVR.Menus.cs b/Scripts/Core/EditorVR.Menus.cs index 898dde55d..1933fca9a 100644 --- a/Scripts/Core/EditorVR.Menus.cs +++ b/Scripts/Core/EditorVR.Menus.cs @@ -183,10 +183,12 @@ internal void UpdateMenuVisibilities() { var alternateMenu = deviceData.alternateMenu; var mainMenu = deviceData.mainMenu; + var undoMenu = deviceData.undoMenu; var customMenu = deviceData.customMenu; var menuHideData = deviceData.menuHideData; MenuHideData customMenuHideData = null; MenuHideData alternateMenuData = null; + MenuHideData undoMenuHideData = null; var mainMenuVisible = mainMenu != null && menuHideData[mainMenu].hideFlags == 0; var alternateMenuVisible = false; @@ -203,6 +205,13 @@ internal void UpdateMenuVisibilities() customMenuVisible = customMenuHideData.hideFlags == 0; } + var undoMenuVisible = false; + if (undoMenu != null) + { + undoMenuHideData = menuHideData[undoMenu]; + undoMenuVisible = undoMenuHideData.hideFlags == 0; + } + // Kick the alternate menu to the other hand if a main menu or custom menu is visible if (alternateMenuVisible && (mainMenuVisible || customMenuVisible)) { @@ -224,6 +233,12 @@ internal void UpdateMenuVisibilities() if (alternateMenuVisible && (customMenuVisible || mainMenuVisible)) alternateMenuData.hideFlags |= MenuHideFlags.OtherMenu; + // Temporarily hide undoMenu if other menus are visible + if (undoMenuVisible && (customMenuVisible || mainMenuVisible || alternateMenuVisible)) + undoMenuHideData.hideFlags |= MenuHideFlags.OtherMenu; + else if (!undoMenuVisible && undoMenuHideData != null) + undoMenuHideData.hideFlags = 0; + // Check if menu bounds overlap with any workspace colliders foreach (var kvp in menuHideData) { @@ -281,6 +296,10 @@ internal void UpdateMenuVisibilities() if (customMenu != null) customMenu.menuHideFlags = deviceData.menuHideData[customMenu].hideFlags; + var undoMenu = deviceData.undoMenu; + if (undoMenu != null) + undoMenu.menuHideFlags = deviceData.menuHideData[undoMenu].hideFlags; + UpdateAlternateMenuForDevice(deviceData); Rays.UpdateRayForDevice(deviceData, deviceData.rayOrigin); } diff --git a/Scripts/Core/EditorVR.Tools.cs b/Scripts/Core/EditorVR.Tools.cs index 7f5f24dd0..4c62bbb17 100644 --- a/Scripts/Core/EditorVR.Tools.cs +++ b/Scripts/Core/EditorVR.Tools.cs @@ -136,6 +136,10 @@ internal void SpawnDefaultTools(IProxy proxy) menuHideData[alternateMenu] = new Menus.MenuHideData(); alternateMenu.itemWasSelected += Menus.UpdateAlternateMenuOnSelectionChanged; + var undoMenu = menus.SpawnAlternateMenu(typeof(UndoMenu), rayOrigin); + deviceData.undoMenu = undoMenu; + menuHideData[undoMenu] = new Menus.MenuHideData(); + // Setup ToolsMenu var toolsMenu = menus.SpawnToolsMenu(typeof(Experimental.EditorVR.Menus.ToolsMenu), rayOrigin); deviceData.toolsMenu = toolsMenu; diff --git a/Scripts/Core/EditorVR.cs b/Scripts/Core/EditorVR.cs index b4d283b19..31ab2b4fc 100644 --- a/Scripts/Core/EditorVR.cs +++ b/Scripts/Core/EditorVR.cs @@ -72,6 +72,7 @@ class DeviceData public readonly Stack toolData = new Stack(); public IMainMenu mainMenu; public IAlternateMenu alternateMenu; + public IAlternateMenu undoMenu; public ITool currentTool; public IMenu customMenu; public IToolsMenu toolsMenu; From d4470cdafabdae3b4da0e0c7eb06dd3cb475ae22 Mon Sep 17 00:00:00 2001 From: Jono Forbes Date: Thu, 16 Nov 2017 15:18:09 -0800 Subject: [PATCH 03/89] Click joystick in to engage undo, with a delay after releasing, because it's hard to keep it pressed in while flicking. --- Menus/UndoMenu/UndoMenu.cs | 22 ++++++++++++++++++++++ Menus/UndoMenu/UndoMenuInput.cs | 1 + 2 files changed, 23 insertions(+) diff --git a/Menus/UndoMenu/UndoMenu.cs b/Menus/UndoMenu/UndoMenu.cs index 9ab692c82..16f30b700 100644 --- a/Menus/UndoMenu/UndoMenu.cs +++ b/Menus/UndoMenu/UndoMenu.cs @@ -1,7 +1,9 @@ #if UNITY_EDITOR using System; +using System.Collections; using System.Collections.Generic; using UnityEditor.Experimental.EditorVR.Core; +using UnityEditor.Experimental.EditorVR.Extensions; using UnityEditor.Experimental.EditorVR.Proxies; using UnityEditor.Experimental.EditorVR.Utilities; using UnityEngine; @@ -13,6 +15,7 @@ sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IAlternateMenu, IUsesMenu IControlHaptics, IUsesNode, IConnectInterfaces, IRequestFeedback { const float k_UndoRedoThreshold = 0.5f; + const float k_EngageUndoAfterStickReleasedDuration = 0.1f; // Duration after releasing the joystick to still accept a left/right flick to undo/redo. [SerializeField] ActionMap m_ActionMap; @@ -28,6 +31,8 @@ sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IAlternateMenu, IUsesMenu Transform m_AlternateMenuOrigin; MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; float m_PrevNavigateX; + bool m_StillEngagedAfterStickRelease; + Coroutine m_StillEngagedAfterStickReleasedCoroutine; readonly BindingDictionary m_Controls = new BindingDictionary(); @@ -108,6 +113,11 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon this.ClearFeedbackRequests(); return; } + if (undoMenuInput.engage.wasJustReleased) + this.RestartCoroutine(ref m_StillEngagedAfterStickReleasedCoroutine, AcceptInputAfterStickReleased()); + if (!(undoMenuInput.engage.isHeld || m_StillEngagedAfterStickRelease)) + return; + consumeControl(undoMenuInput.engage); var navigateX = undoMenuInput.navigateX.value; var undoRedoEngaged = false; @@ -129,6 +139,18 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon } } + IEnumerator AcceptInputAfterStickReleased() + { + m_StillEngagedAfterStickRelease = true; + var currentDuration = 0f; + while (currentDuration < k_EngageUndoAfterStickReleasedDuration) + { + currentDuration += Time.deltaTime; + yield return null; + } + m_StillEngagedAfterStickRelease = false; + } + void ShowFeedback() { List controls; diff --git a/Menus/UndoMenu/UndoMenuInput.cs b/Menus/UndoMenu/UndoMenuInput.cs index 2a50b6537..0fef76d03 100644 --- a/Menus/UndoMenu/UndoMenuInput.cs +++ b/Menus/UndoMenu/UndoMenuInput.cs @@ -8,5 +8,6 @@ public class UndoMenuInput : ActionMapInput { public UndoMenuInput (ActionMap actionMap) : base (actionMap) { } public AxisInputControl @navigateX { get { return (AxisInputControl)this[0]; } } + public ButtonInputControl @engage { get { return (ButtonInputControl)this[1]; } } } } From bd8f04bc6aaf0484a8b8c759a658cc80d6de5772 Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Thu, 16 Nov 2017 15:53:52 -0800 Subject: [PATCH 04/89] add MainMenuSelectable base class for buttons and toggles --- Menus/MainMenu/Scripts/MainMenuButton.cs | 42 ++--------- Menus/MainMenu/Scripts/MainMenuSelectable.cs | 75 +++++++++++++++++++ .../Scripts/MainMenuSelectable.cs.meta | 13 ++++ Menus/MainMenu/Scripts/MainMenuToggle.cs | 54 +++++++++++++ Menus/MainMenu/Scripts/MainMenuToggle.cs.meta | 13 ++++ 5 files changed, 161 insertions(+), 36 deletions(-) create mode 100644 Menus/MainMenu/Scripts/MainMenuSelectable.cs create mode 100644 Menus/MainMenu/Scripts/MainMenuSelectable.cs.meta create mode 100644 Menus/MainMenu/Scripts/MainMenuToggle.cs create mode 100644 Menus/MainMenu/Scripts/MainMenuToggle.cs.meta diff --git a/Menus/MainMenu/Scripts/MainMenuButton.cs b/Menus/MainMenu/Scripts/MainMenuButton.cs index c7ea262a5..aec1e07c0 100644 --- a/Menus/MainMenu/Scripts/MainMenuButton.cs +++ b/Menus/MainMenu/Scripts/MainMenuButton.cs @@ -14,61 +14,31 @@ namespace UnityEditor.Experimental.EditorVR.Menus { - sealed class MainMenuButton : MonoBehaviour, ITooltip, IRayEnterHandler, IRayExitHandler, IPointerClickHandler + sealed class MainMenuButton : MainMenuSelectable, ITooltip { [SerializeField] Button m_Button; -#if INCLUDE_TEXT_MESH_PRO - [SerializeField] - TextMeshProUGUI m_ButtonDescription; -#endif - -#if INCLUDE_TEXT_MESH_PRO - [SerializeField] - TextMeshProUGUI m_ButtonTitle; -#endif - - Color m_OriginalColor; - public Button button { get { return m_Button; } } public string tooltipText { get { return tooltip != null ? tooltip.tooltipText : null; } } public ITooltip tooltip { private get; set; } - public Type toolType { get; set; } - - public bool selected - { - set - { - if (value) - { - m_Button.transition = Selectable.Transition.None; - m_Button.targetGraphic.color = m_Button.colors.highlightedColor; - } - else - { - m_Button.transition = Selectable.Transition.ColorTint; - m_Button.targetGraphic.color = m_OriginalColor; - } - } - } - public event Action hovered; public event Action clicked; - void Awake() + new void Awake() { + m_Selectable = m_Button; m_OriginalColor = m_Button.targetGraphic.color; } public void SetData(string name, string description) { #if INCLUDE_TEXT_MESH_PRO - m_ButtonTitle.text = name; - m_ButtonDescription.text = description; + m_Title.text = name; + m_Description.text = description; #endif } @@ -76,7 +46,7 @@ public void OnRayEnter(RayEventData eventData) { #if INCLUDE_TEXT_MESH_PRO if (hovered != null) - hovered(eventData.rayOrigin, toolType, m_ButtonDescription.text); + hovered(eventData.rayOrigin, toolType, m_Description.text); #endif } diff --git a/Menus/MainMenu/Scripts/MainMenuSelectable.cs b/Menus/MainMenu/Scripts/MainMenuSelectable.cs new file mode 100644 index 000000000..3842ec706 --- /dev/null +++ b/Menus/MainMenu/Scripts/MainMenuSelectable.cs @@ -0,0 +1,75 @@ +#if UNITY_EDITOR +using System; +using UnityEditor.Experimental.EditorVR; +using UnityEditor.Experimental.EditorVR.Modules; +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.UI; +using UnityEditor.Experimental.EditorVR.Core; + +#if INCLUDE_TEXT_MESH_PRO +using TMPro; +#endif + +[assembly: OptionalDependency("TMPro.TextMeshProUGUI", "INCLUDE_TEXT_MESH_PRO")] + +namespace UnityEditor.Experimental.EditorVR.Menus +{ + abstract class MainMenuSelectable : MonoBehaviour + { + [SerializeField] + protected Selectable m_Selectable; + + [SerializeField] + HapticPulse m_ClickPulse; + + [SerializeField] + HapticPulse m_HoverPulse; + +#if INCLUDE_TEXT_MESH_PRO + [SerializeField] + protected TextMeshProUGUI m_Description; +#endif + +#if INCLUDE_TEXT_MESH_PRO + [SerializeField] + protected TextMeshProUGUI m_Title; +#endif + + protected Color m_OriginalColor; + + public Type toolType { get; set; } + + public bool selected + { + set + { + if (value) + { + m_Selectable.transition = Selectable.Transition.None; + m_Selectable.targetGraphic.color = m_Selectable.colors.highlightedColor; + } + else + { + m_Selectable.transition = Selectable.Transition.ColorTint; + m_Selectable.targetGraphic.color = m_OriginalColor; + } + } + } + + protected void Awake() + { + m_OriginalColor = m_Selectable.targetGraphic.color; + } + + public void SetData(string name, string description) + { +#if INCLUDE_TEXT_MESH_PRO + m_Title.text = name; + m_Description.text = description; +#endif + } + } +} +#endif + diff --git a/Menus/MainMenu/Scripts/MainMenuSelectable.cs.meta b/Menus/MainMenu/Scripts/MainMenuSelectable.cs.meta new file mode 100644 index 000000000..3d7f4680b --- /dev/null +++ b/Menus/MainMenu/Scripts/MainMenuSelectable.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: cb860360904848e419f421dbd53b9304 +timeCreated: 1510875372 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Menus/MainMenu/Scripts/MainMenuToggle.cs b/Menus/MainMenu/Scripts/MainMenuToggle.cs new file mode 100644 index 000000000..89466b5f9 --- /dev/null +++ b/Menus/MainMenu/Scripts/MainMenuToggle.cs @@ -0,0 +1,54 @@ +#if UNITY_EDITOR +using System; +using UnityEditor.Experimental.EditorVR; +using UnityEditor.Experimental.EditorVR.Modules; +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.UI; + +#if INCLUDE_TEXT_MESH_PRO +using TMPro; +#endif + +[assembly: OptionalDependency("TMPro.TextMeshProUGUI", "INCLUDE_TEXT_MESH_PRO")] + +namespace UnityEditor.Experimental.EditorVR.Menus +{ + sealed class MainMenuToggle : MainMenuSelectable + { + [SerializeField] + Toggle m_Toggle; + + public Toggle toggle { get { return m_Toggle; } } + + public event Action hovered; + public event Action clicked; + + new void Awake() + { + m_Selectable = m_Toggle; + m_OriginalColor = m_Toggle.targetGraphic.color; + } + + public void OnRayEnter(RayEventData eventData) + { +#if INCLUDE_TEXT_MESH_PRO + if (hovered != null) + hovered(eventData.rayOrigin, toolType, m_Description.text); +#endif + } + + public void OnRayExit(RayEventData eventData) + { + if (hovered != null) + hovered(eventData.rayOrigin, null, null); + } + + public void OnPointerClick(PointerEventData eventData) + { + if (clicked != null) + clicked(null); // Pass null to perform the selection haptic pulse on both nodes + } + } +} +#endif diff --git a/Menus/MainMenu/Scripts/MainMenuToggle.cs.meta b/Menus/MainMenu/Scripts/MainMenuToggle.cs.meta new file mode 100644 index 000000000..270dbcaf4 --- /dev/null +++ b/Menus/MainMenu/Scripts/MainMenuToggle.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 766c9196b7801da49b40f523eaa556e6 +timeCreated: 1510876355 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From ad56a328750ef1b95bcdc4c5b471e7da0bd955ac Mon Sep 17 00:00:00 2001 From: Jono Forbes Date: Thu, 16 Nov 2017 17:26:34 -0800 Subject: [PATCH 05/89] No longer consume stick input in MainMenu, which allows it and UndoMenu to work together as expected. --- Menus/MainMenu/MainMenu.cs | 8 +------- Menus/MainMenu/MainMenuInput.asset | 30 ------------------------------ Menus/MainMenu/MainMenuInput.cs | 3 +-- Menus/UndoMenu/UndoMenu.cs | 11 ++++------- Menus/UndoMenu/UndoMenuInput.asset | 30 ++++++++++++++++++++++++++++++ Scripts/Core/EditorVR.Menus.cs | 6 +----- 6 files changed, 37 insertions(+), 51 deletions(-) diff --git a/Menus/MainMenu/MainMenu.cs b/Menus/MainMenu/MainMenu.cs index bcf59f65e..f5cdeda34 100644 --- a/Menus/MainMenu/MainMenu.cs +++ b/Menus/MainMenu/MainMenu.cs @@ -141,10 +141,7 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon var mainMenuInput = (MainMenuInput)input; var rotationInput = -mainMenuInput.rotate.rawValue; - - consumeControl(mainMenuInput.rotate); - consumeControl(mainMenuInput.blockY); - + const float kFlickDeltaThreshold = 0.5f; if ((this.GetDeviceType() != DeviceType.Vive && Mathf.Abs(rotationInput) >= kFlickDeltaThreshold && Mathf.Abs(m_LastRotationInput) < kFlickDeltaThreshold) || mainMenuInput.flickFace.wasJustReleased) @@ -153,9 +150,6 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon this.Pulse(node, m_FaceRotationPulse); } - if (m_MenuHideFlags == 0) - consumeControl(mainMenuInput.flickFace); - m_LastRotationInput = rotationInput; } diff --git a/Menus/MainMenu/MainMenuInput.asset b/Menus/MainMenu/MainMenuInput.asset index e9f0131ac..9b463d4c1 100644 --- a/Menus/MainMenu/MainMenuInput.asset +++ b/Menus/MainMenu/MainMenuInput.asset @@ -14,7 +14,6 @@ MonoBehaviour: m_Actions: - {fileID: 114000011099735542} - {fileID: 114000011460179744} - - {fileID: 114000010466542208} m_ControlSchemes: - m_Name: MainMenu m_DeviceSlots: @@ -43,38 +42,9 @@ MonoBehaviour: sensitivity: 1000 snap: 1 primaryIsButtonAxis: 0 - - sources: - - controlIndex: 1 - deviceKey: 1 - deadZone: 0.3 - buttonAxisSources: [] - gravity: 1000 - sensitivity: 1000 - snap: 1 - primaryIsButtonAxis: 0 m_MapTypeName: MainMenuInput, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null m_CustomNamespace: ---- !u!114 &114000010466542208 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5eba7b4b2e3ea134991ccbff5f47c2c8, type: 3} - m_Name: BlockY - m_EditorClassIdentifier: - m_ActionMap: {fileID: 11400000} - m_ActionIndex: 2 - m_ControlData: - componentControlIndices: - controlType: - m_TypeName: UnityEngine.InputNew.AxisInputControl, Assembly-CSharp, Version=0.0.0.0, - Culture=neutral, PublicKeyToken=null - name: BlockY - defaultValue: 0 --- !u!114 &114000011099735542 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Menus/MainMenu/MainMenuInput.cs b/Menus/MainMenu/MainMenuInput.cs index 5a9131cf7..caa6ca0d1 100644 --- a/Menus/MainMenu/MainMenuInput.cs +++ b/Menus/MainMenu/MainMenuInput.cs @@ -9,6 +9,5 @@ public MainMenuInput (ActionMap actionMap) : base (actionMap) { } public AxisInputControl @rotate { get { return (AxisInputControl)this[0]; } } public ButtonInputControl @flickFace { get { return (ButtonInputControl)this[1]; } } - public AxisInputControl @blockY { get { return (AxisInputControl)this[2]; } } } -} +} diff --git a/Menus/UndoMenu/UndoMenu.cs b/Menus/UndoMenu/UndoMenu.cs index 16f30b700..e7c543eda 100644 --- a/Menus/UndoMenu/UndoMenu.cs +++ b/Menus/UndoMenu/UndoMenu.cs @@ -115,9 +115,10 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon } if (undoMenuInput.engage.wasJustReleased) this.RestartCoroutine(ref m_StillEngagedAfterStickReleasedCoroutine, AcceptInputAfterStickReleased()); - if (!(undoMenuInput.engage.isHeld || m_StillEngagedAfterStickRelease)) + if (!(undoMenuInput.engage.wasJustPressed || undoMenuInput.engage.isHeld || m_StillEngagedAfterStickRelease)) return; consumeControl(undoMenuInput.engage); + m_UndoMenuUI.engaged = true; var navigateX = undoMenuInput.navigateX.value; var undoRedoEngaged = false; @@ -142,13 +143,9 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon IEnumerator AcceptInputAfterStickReleased() { m_StillEngagedAfterStickRelease = true; - var currentDuration = 0f; - while (currentDuration < k_EngageUndoAfterStickReleasedDuration) - { - currentDuration += Time.deltaTime; - yield return null; - } + yield return new WaitForSeconds(k_EngageUndoAfterStickReleasedDuration); m_StillEngagedAfterStickRelease = false; + m_UndoMenuUI.engaged = false; } void ShowFeedback() diff --git a/Menus/UndoMenu/UndoMenuInput.asset b/Menus/UndoMenu/UndoMenuInput.asset index 5c9b20dc5..aa56ff8f3 100644 --- a/Menus/UndoMenu/UndoMenuInput.asset +++ b/Menus/UndoMenu/UndoMenuInput.asset @@ -13,6 +13,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_Actions: - {fileID: 114324171257110392} + - {fileID: 114746503017599090} m_ControlSchemes: - m_Name: UndoMenu m_DeviceSlots: @@ -32,6 +33,15 @@ MonoBehaviour: sensitivity: 1000 snap: 1 primaryIsButtonAxis: 0 + - sources: + - controlIndex: 22 + deviceKey: 1 + deadZone: 0.3 + buttonAxisSources: [] + gravity: 1000 + sensitivity: 1000 + snap: 1 + primaryIsButtonAxis: 0 m_MapTypeName: UndoMenuInput, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null m_CustomNamespace: @@ -55,3 +65,23 @@ MonoBehaviour: Culture=neutral, PublicKeyToken=null name: NavigateX defaultValue: 0 +--- !u!114 &114746503017599090 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5eba7b4b2e3ea134991ccbff5f47c2c8, type: 3} + m_Name: Engage + m_EditorClassIdentifier: + m_ActionMap: {fileID: 11400000} + m_ActionIndex: 1 + m_ControlData: + componentControlIndices: + controlType: + m_TypeName: UnityEngine.InputNew.ButtonInputControl, Assembly-CSharp, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + name: Engage + defaultValue: 0 diff --git a/Scripts/Core/EditorVR.Menus.cs b/Scripts/Core/EditorVR.Menus.cs index 1933fca9a..714edc6f7 100644 --- a/Scripts/Core/EditorVR.Menus.cs +++ b/Scripts/Core/EditorVR.Menus.cs @@ -233,12 +233,8 @@ internal void UpdateMenuVisibilities() if (alternateMenuVisible && (customMenuVisible || mainMenuVisible)) alternateMenuData.hideFlags |= MenuHideFlags.OtherMenu; - // Temporarily hide undoMenu if other menus are visible - if (undoMenuVisible && (customMenuVisible || mainMenuVisible || alternateMenuVisible)) - undoMenuHideData.hideFlags |= MenuHideFlags.OtherMenu; - else if (!undoMenuVisible && undoMenuHideData != null) + if (!undoMenuVisible && undoMenuHideData != null) undoMenuHideData.hideFlags = 0; - // Check if menu bounds overlap with any workspace colliders foreach (var kvp in menuHideData) { From 8316e948691c46998996871cfa4a95d351d8a733 Mon Sep 17 00:00:00 2001 From: Jono Forbes Date: Thu, 16 Nov 2017 18:07:50 -0800 Subject: [PATCH 06/89] Animate undo button alpha on dis/engage. --- Menus/UndoMenu/Materials/UndoIcon.mat | 2 +- Menus/UndoMenu/Prefabs/UndoMenu.prefab | 2 + Menus/UndoMenu/Scripts/UndoMenuUI.cs | 64 ++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/Menus/UndoMenu/Materials/UndoIcon.mat b/Menus/UndoMenu/Materials/UndoIcon.mat index 60517a69b..cc199eaa3 100644 --- a/Menus/UndoMenu/Materials/UndoIcon.mat +++ b/Menus/UndoMenu/Materials/UndoIcon.mat @@ -12,7 +12,7 @@ Material: m_LightmapFlags: 4 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 - m_CustomRenderQueue: 9503 + m_CustomRenderQueue: 3000 stringTagMap: RenderType: Transparent disabledShaderPasses: [] diff --git a/Menus/UndoMenu/Prefabs/UndoMenu.prefab b/Menus/UndoMenu/Prefabs/UndoMenu.prefab index 851037ede..6eef503ac 100644 --- a/Menus/UndoMenu/Prefabs/UndoMenu.prefab +++ b/Menus/UndoMenu/Prefabs/UndoMenu.prefab @@ -225,3 +225,5 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: b8ebdbcab31646f4da31c5a9a3f2ce5b, type: 3} m_Name: m_EditorClassIdentifier: + m_UndoButtonMeshRenderer: {fileID: 23859873210418424} + m_RedoButtonMeshRenderer: {fileID: 23850276268091638} diff --git a/Menus/UndoMenu/Scripts/UndoMenuUI.cs b/Menus/UndoMenu/Scripts/UndoMenuUI.cs index a03362a37..db3e0b052 100644 --- a/Menus/UndoMenu/Scripts/UndoMenuUI.cs +++ b/Menus/UndoMenu/Scripts/UndoMenuUI.cs @@ -1,12 +1,26 @@ #if UNITY_EDITOR +using System.Collections; using System.Collections.Generic; using System.Linq; +using UnityEditor.Experimental.EditorVR.Extensions; +using UnityEditor.Experimental.EditorVR.Utilities; using UnityEngine; namespace UnityEditor.Experimental.EditorVR.Menus { sealed class UndoMenuUI : MonoBehaviour, IConnectInterfaces { + const float k_EngageAnimationDuration = 0.1f; + const float k_EngagedAlpha = 0.85f; + const float k_DisengagedAlpha = 0.5f; + const string k_MaterialColorProperty = "_Color"; + + [SerializeField] + MeshRenderer m_UndoButtonMeshRenderer; + + [SerializeField] + MeshRenderer m_RedoButtonMeshRenderer; + public Transform alternateMenuOrigin { get { return m_AlternateMenuOrigin; } @@ -24,6 +38,20 @@ public Transform alternateMenuOrigin Transform m_AlternateMenuOrigin; + public bool engaged + { + get { return m_Engaged; } + set + { + if (m_Engaged == value) + return; + m_Engaged = value; + this.RestartCoroutine(ref m_EngageCoroutine, AnimateEngage(m_Engaged)); + } + } + + bool m_Engaged; + public bool visible { get { return m_Visible; } @@ -59,10 +87,46 @@ public List actions List m_Actions; + Material m_UndoButtonMaterial; + Material m_RedoButtonMaterial; + Coroutine m_EngageCoroutine; + + void Awake() + { + m_UndoButtonMaterial = MaterialUtils.GetMaterialClone(m_UndoButtonMeshRenderer); + m_RedoButtonMaterial = MaterialUtils.GetMaterialClone(m_RedoButtonMeshRenderer); + } + + void OnDestroy() + { + ObjectUtils.Destroy(m_UndoButtonMaterial); + ObjectUtils.Destroy(m_RedoButtonMaterial); + } + public void Setup() { gameObject.SetActive(false); } + + IEnumerator AnimateEngage(bool engaging) + { + var startingColor = m_UndoButtonMaterial.GetColor(k_MaterialColorProperty); + var targetColor = startingColor; + targetColor.a = engaging ? k_EngagedAlpha : k_DisengagedAlpha; + var transitionAmount = 0f; + var currentDuration = 0f; + while (transitionAmount < 1f) + { + var currentColor = Color.Lerp(startingColor, targetColor, transitionAmount); + m_UndoButtonMaterial.SetColor(k_MaterialColorProperty, currentColor); + m_RedoButtonMaterial.SetColor(k_MaterialColorProperty, currentColor); + currentDuration += Time.deltaTime; + transitionAmount = currentDuration / k_EngageAnimationDuration; + yield return null; + } + m_UndoButtonMaterial.SetColor(k_MaterialColorProperty, targetColor); + m_RedoButtonMaterial.SetColor(k_MaterialColorProperty, targetColor); + } } } #endif From 27c35c0daf58d480d6b67b1cbc5df55e11c36555 Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 17 Nov 2017 09:17:42 -0800 Subject: [PATCH 07/89] don't serialize base Selectable in MainMenuSelectable --- Menus/MainMenu/Scripts/MainMenuSelectable.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Menus/MainMenu/Scripts/MainMenuSelectable.cs b/Menus/MainMenu/Scripts/MainMenuSelectable.cs index 3842ec706..2caa4822f 100644 --- a/Menus/MainMenu/Scripts/MainMenuSelectable.cs +++ b/Menus/MainMenu/Scripts/MainMenuSelectable.cs @@ -17,7 +17,6 @@ namespace UnityEditor.Experimental.EditorVR.Menus { abstract class MainMenuSelectable : MonoBehaviour { - [SerializeField] protected Selectable m_Selectable; [SerializeField] From deee5d61c56d8fbdede20b2a8e672c56dfbab703 Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 17 Nov 2017 09:24:55 -0800 Subject: [PATCH 08/89] remove unused code from mainmenutoggle and mainmenuselectable --- Menus/MainMenu/Scripts/MainMenuButton.cs | 8 -------- Menus/MainMenu/Scripts/MainMenuSelectable.cs | 2 -- 2 files changed, 10 deletions(-) diff --git a/Menus/MainMenu/Scripts/MainMenuButton.cs b/Menus/MainMenu/Scripts/MainMenuButton.cs index aec1e07c0..7c8aeaa66 100644 --- a/Menus/MainMenu/Scripts/MainMenuButton.cs +++ b/Menus/MainMenu/Scripts/MainMenuButton.cs @@ -34,14 +34,6 @@ sealed class MainMenuButton : MainMenuSelectable, ITooltip m_OriginalColor = m_Button.targetGraphic.color; } - public void SetData(string name, string description) - { -#if INCLUDE_TEXT_MESH_PRO - m_Title.text = name; - m_Description.text = description; -#endif - } - public void OnRayEnter(RayEventData eventData) { #if INCLUDE_TEXT_MESH_PRO diff --git a/Menus/MainMenu/Scripts/MainMenuSelectable.cs b/Menus/MainMenu/Scripts/MainMenuSelectable.cs index 2caa4822f..8157b36d1 100644 --- a/Menus/MainMenu/Scripts/MainMenuSelectable.cs +++ b/Menus/MainMenu/Scripts/MainMenuSelectable.cs @@ -1,9 +1,7 @@ #if UNITY_EDITOR using System; using UnityEditor.Experimental.EditorVR; -using UnityEditor.Experimental.EditorVR.Modules; using UnityEngine; -using UnityEngine.EventSystems; using UnityEngine.UI; using UnityEditor.Experimental.EditorVR.Core; From 8ffff5045374254a761c36b0aba9c24f192f0842 Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 17 Nov 2017 10:05:32 -0800 Subject: [PATCH 09/89] update menu button prefabs to use new MainMenuSelectable base --- Menus/MainMenu/Prefabs/MenuActionButton.prefab | 18 ++++++++++-------- Menus/MainMenu/Prefabs/MenuButton.prefab | 6 ++++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Menus/MainMenu/Prefabs/MenuActionButton.prefab b/Menus/MainMenu/Prefabs/MenuActionButton.prefab index b541b1b57..20c7df7cb 100644 --- a/Menus/MainMenu/Prefabs/MenuActionButton.prefab +++ b/Menus/MainMenu/Prefabs/MenuActionButton.prefab @@ -319,9 +319,11 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d6fdf9e0896ac3f4e94809a2cb14ceb8, type: 3} m_Name: m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 114846824440974548} + m_Title: {fileID: 114097649684237516} m_Button: {fileID: 114000011038114608} - m_ButtonDescription: {fileID: 114846824440974548} - m_ButtonTitle: {fileID: 114097649684237516} --- !u!114 &114000012975115684 MonoBehaviour: m_ObjectHideFlags: 1 @@ -719,7 +721,7 @@ RectTransform: m_PrefabInternal: {fileID: 100100000} m_GameObject: {fileID: 1000010480751764} m_LocalRotation: {x: 0, y: 0, z: -0.7071068, w: 0.7071068} - m_LocalPosition: {x: -1.449823, y: 0.0000038146973, z: 0} + m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1.0000001} m_Children: [] m_Father: {fileID: 224000013269318208} @@ -727,7 +729,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: -90} m_AnchorMin: {x: 0.20215935, y: -1.0582141} m_AnchorMax: {x: 0.4918094, y: 2.0516362} - m_AnchoredPosition: {x: 0, y: 0.0000038146973} + m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!224 &224000011878397100 @@ -755,7 +757,7 @@ RectTransform: m_PrefabInternal: {fileID: 100100000} m_GameObject: {fileID: 1000013009823340} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 2.6, y: -0.0024712086, z: 0} + m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 224000013269318208} @@ -763,7 +765,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 2.6, y: -0.0024712086} + m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 5.3, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!224 &224000013226195212 @@ -791,7 +793,7 @@ RectTransform: m_PrefabInternal: {fileID: 100100000} m_GameObject: {fileID: 1000014267655440} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 4.737492, y: 0, z: 0} + m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: - {fileID: 224000013206266848} @@ -801,7 +803,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.00008987377, y: 0.006534843} m_AnchorMax: {x: 0.9659295, y: 1} - m_AnchoredPosition: {x: 4.737492, y: 0} + m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 9.475, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!224 &224000013707443896 diff --git a/Menus/MainMenu/Prefabs/MenuButton.prefab b/Menus/MainMenu/Prefabs/MenuButton.prefab index 307efdadf..ff2a23dad 100644 --- a/Menus/MainMenu/Prefabs/MenuButton.prefab +++ b/Menus/MainMenu/Prefabs/MenuButton.prefab @@ -127,9 +127,11 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d6fdf9e0896ac3f4e94809a2cb14ceb8, type: 3} m_Name: m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 114538117545747488} + m_Title: {fileID: 114736413251300290} m_Button: {fileID: 114000011038114608} - m_ButtonDescription: {fileID: 114538117545747488} - m_ButtonTitle: {fileID: 114736413251300290} --- !u!114 &114000013676702038 MonoBehaviour: m_ObjectHideFlags: 1 From 323d9dc5fba2d145248b7e1484af7538ed53a96c Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 17 Nov 2017 10:06:31 -0800 Subject: [PATCH 10/89] add null check for selectable description --- Menus/MainMenu/Scripts/MainMenuSelectable.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Menus/MainMenu/Scripts/MainMenuSelectable.cs b/Menus/MainMenu/Scripts/MainMenuSelectable.cs index 8157b36d1..375cd8c4c 100644 --- a/Menus/MainMenu/Scripts/MainMenuSelectable.cs +++ b/Menus/MainMenu/Scripts/MainMenuSelectable.cs @@ -63,7 +63,8 @@ public void SetData(string name, string description) { #if INCLUDE_TEXT_MESH_PRO m_Title.text = name; - m_Description.text = description; + if (m_Description != null) + m_Description.text = description; #endif } } From 9c44eda472cb3bb55a6461074ef744bd571cf8bd Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 17 Nov 2017 10:07:35 -0800 Subject: [PATCH 11/89] hook up all new Main Menu Toggle components for snapping menu --- .../Prefabs/MenuFaceSnapping.prefab | 155 +++++++++++++++++- 1 file changed, 154 insertions(+), 1 deletion(-) diff --git a/Scripts/Modules/SnappingModule/Prefabs/MenuFaceSnapping.prefab b/Scripts/Modules/SnappingModule/Prefabs/MenuFaceSnapping.prefab index 6aae839f9..fc783e797 100644 --- a/Scripts/Modules/SnappingModule/Prefabs/MenuFaceSnapping.prefab +++ b/Scripts/Modules/SnappingModule/Prefabs/MenuFaceSnapping.prefab @@ -107,6 +107,7 @@ GameObject: - component: {fileID: 224000011296668950} - component: {fileID: 114000010948304686} - component: {fileID: 222000010942830010} + - component: {fileID: 114037206478316860} m_Layer: 5 m_Name: Manipulator m_TagString: Untagged @@ -210,6 +211,7 @@ GameObject: m_Component: - component: {fileID: 224000011333867530} - component: {fileID: 114000013071561082} + - component: {fileID: 114397974832724302} m_Layer: 5 m_Name: Pivot m_TagString: Untagged @@ -334,6 +336,7 @@ GameObject: - component: {fileID: 224000011344157490} - component: {fileID: 114000010532990664} - component: {fileID: 222000012330798060} + - component: {fileID: 114598190590722842} m_Layer: 5 m_Name: RotateObject m_TagString: Untagged @@ -402,6 +405,7 @@ GameObject: - component: {fileID: 224000012376581548} - component: {fileID: 114000012781285154} - component: {fileID: 222000013846753968} + - component: {fileID: 114433705572082042} m_Layer: 5 m_Name: LimitRadius m_TagString: Untagged @@ -538,6 +542,7 @@ GameObject: - component: {fileID: 224000011269624134} - component: {fileID: 114000011740143044} - component: {fileID: 222000010014886574} + - component: {fileID: 114585731372708882} m_Layer: 5 m_Name: GroundSnapping m_TagString: Untagged @@ -571,6 +576,7 @@ GameObject: - component: {fileID: 224000011535763916} - component: {fileID: 114000012943056720} - component: {fileID: 222000012933658470} + - component: {fileID: 114818556804415882} m_Layer: 5 m_Name: SurfaceSnapping m_TagString: Untagged @@ -589,6 +595,7 @@ GameObject: - component: {fileID: 114000013726484858} - component: {fileID: 222000012289411126} - component: {fileID: 114000012299972308} + - component: {fileID: 114304160726869102} m_Layer: 5 m_Name: EnableSnapping m_TagString: Untagged @@ -639,6 +646,7 @@ GameObject: m_Component: - component: {fileID: 224000013887046414} - component: {fileID: 114000011689962350} + - component: {fileID: 114218909019517356} m_Layer: 5 m_Name: Bounds m_TagString: Untagged @@ -741,6 +749,7 @@ GameObject: - component: {fileID: 224000013602175086} - component: {fileID: 114000013490178622} - component: {fileID: 222000012650615686} + - component: {fileID: 114595155424188078} m_Layer: 5 m_Name: Direct m_TagString: Untagged @@ -2183,6 +2192,38 @@ MonoBehaviour: m_FillAmount: 1 m_FillClockwise: 1 m_FillOrigin: 0 +--- !u!114 &114037206478316860 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000010462312398} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 0} + m_Title: {fileID: 114547171262664456} + m_Toggle: {fileID: 114000010948304686} +--- !u!114 &114218909019517356 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000013493931504} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 0} + m_Title: {fileID: 114487886979728018} + m_Toggle: {fileID: 114000011689962350} --- !u!114 &114243426776915280 MonoBehaviour: m_ObjectHideFlags: 1 @@ -2295,6 +2336,38 @@ MonoBehaviour: - {fileID: 0} m_baseMaterial: {fileID: 0} m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!114 &114304160726869102 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000013416106312} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 0} + m_Title: {fileID: 114422380110548290} + m_Toggle: {fileID: 114000013726484858} +--- !u!114 &114397974832724302 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000011017939822} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 0} + m_Title: {fileID: 114768966837101286} + m_Toggle: {fileID: 114000013071561082} --- !u!114 &114422380110548290 MonoBehaviour: m_ObjectHideFlags: 1 @@ -2407,6 +2480,22 @@ MonoBehaviour: - {fileID: 0} m_baseMaterial: {fileID: 0} m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!114 &114433705572082042 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000012316381912} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 0} + m_Title: {fileID: 114837802559842038} + m_Toggle: {fileID: 114000012781285154} --- !u!114 &114487886979728018 MonoBehaviour: m_ObjectHideFlags: 1 @@ -2631,6 +2720,54 @@ MonoBehaviour: - {fileID: 0} m_baseMaterial: {fileID: 0} m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!114 &114585731372708882 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000013321801100} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 0} + m_Title: {fileID: 114833023654325632} + m_Toggle: {fileID: 114000011740143044} +--- !u!114 &114595155424188078 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000013718046988} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 0} + m_Title: {fileID: 114758890587099868} + m_Toggle: {fileID: 114000013490178622} +--- !u!114 &114598190590722842 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000012102579994} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 0} + m_Title: {fileID: 114936804563099460} + m_Toggle: {fileID: 114000010532990664} --- !u!114 &114758890587099868 MonoBehaviour: m_ObjectHideFlags: 1 @@ -2855,6 +2992,22 @@ MonoBehaviour: - {fileID: 0} m_baseMaterial: {fileID: 0} m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!114 &114818556804415882 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000013390902142} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 0} + m_Title: {fileID: 114243426776915280} + m_Toggle: {fileID: 114000012943056720} --- !u!114 &114833023654325632 MonoBehaviour: m_ObjectHideFlags: 1 @@ -4334,7 +4487,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 1} m_AnchorMax: {x: 0.5, y: 1} - m_AnchoredPosition: {x: -0.0000076293945, y: 0.000015258789} + m_AnchoredPosition: {x: -0.0000076293945, y: 0.000030517578} m_SizeDelta: {x: 279.79852, y: 0} m_Pivot: {x: 0.5, y: 1} --- !u!224 &224000013713290898 From f6d251e29dde858ad6d7b4ce2c444084ccc653ac Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 17 Nov 2017 10:08:14 -0800 Subject: [PATCH 12/89] add ray event interfaces back to mainmenu button and toggle --- Menus/MainMenu/Scripts/MainMenuButton.cs | 2 +- Menus/MainMenu/Scripts/MainMenuToggle.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Menus/MainMenu/Scripts/MainMenuButton.cs b/Menus/MainMenu/Scripts/MainMenuButton.cs index 7c8aeaa66..081075e7a 100644 --- a/Menus/MainMenu/Scripts/MainMenuButton.cs +++ b/Menus/MainMenu/Scripts/MainMenuButton.cs @@ -14,7 +14,7 @@ namespace UnityEditor.Experimental.EditorVR.Menus { - sealed class MainMenuButton : MainMenuSelectable, ITooltip + sealed class MainMenuButton : MainMenuSelectable, ITooltip, IRayEnterHandler, IRayExitHandler, IPointerClickHandler { [SerializeField] Button m_Button; diff --git a/Menus/MainMenu/Scripts/MainMenuToggle.cs b/Menus/MainMenu/Scripts/MainMenuToggle.cs index 89466b5f9..db8d1688e 100644 --- a/Menus/MainMenu/Scripts/MainMenuToggle.cs +++ b/Menus/MainMenu/Scripts/MainMenuToggle.cs @@ -14,7 +14,7 @@ namespace UnityEditor.Experimental.EditorVR.Menus { - sealed class MainMenuToggle : MainMenuSelectable + sealed class MainMenuToggle : MainMenuSelectable, IRayEnterHandler, IRayExitHandler, IPointerClickHandler { [SerializeField] Toggle m_Toggle; @@ -34,7 +34,7 @@ public void OnRayEnter(RayEventData eventData) { #if INCLUDE_TEXT_MESH_PRO if (hovered != null) - hovered(eventData.rayOrigin, toolType, m_Description.text); + hovered(eventData.rayOrigin, toolType, null); #endif } From 538075f3cf3e6e4d402413e468c28849ccd472b7 Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 17 Nov 2017 10:16:50 -0800 Subject: [PATCH 13/89] simplify main menu toggle hover events --- Menus/MainMenu/Scripts/MainMenuToggle.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Menus/MainMenu/Scripts/MainMenuToggle.cs b/Menus/MainMenu/Scripts/MainMenuToggle.cs index db8d1688e..a70c062c7 100644 --- a/Menus/MainMenu/Scripts/MainMenuToggle.cs +++ b/Menus/MainMenu/Scripts/MainMenuToggle.cs @@ -21,7 +21,7 @@ sealed class MainMenuToggle : MainMenuSelectable, IRayEnterHandler, IRayExitHand public Toggle toggle { get { return m_Toggle; } } - public event Action hovered; + public event Action hovered; public event Action clicked; new void Awake() @@ -34,14 +34,14 @@ public void OnRayEnter(RayEventData eventData) { #if INCLUDE_TEXT_MESH_PRO if (hovered != null) - hovered(eventData.rayOrigin, toolType, null); + hovered(eventData.rayOrigin); #endif } public void OnRayExit(RayEventData eventData) { if (hovered != null) - hovered(eventData.rayOrigin, null, null); + hovered(eventData.rayOrigin); } public void OnPointerClick(PointerEventData eventData) From 18b7b2ffafe07c945c115175eeffe66abe674e58 Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 17 Nov 2017 10:17:51 -0800 Subject: [PATCH 14/89] hookup submenu toggle haptics in main menu --- Menus/MainMenu/MainMenu.cs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Menus/MainMenu/MainMenu.cs b/Menus/MainMenu/MainMenu.cs index bcf59f65e..32d03a487 100644 --- a/Menus/MainMenu/MainMenu.cs +++ b/Menus/MainMenu/MainMenu.cs @@ -299,6 +299,11 @@ void OnButtonHovered(Transform rayOrigin, Type buttonType, string buttonDescript this.PreviewInToolMenuButton(rayOrigin, buttonType, buttonDescription); } + void OnToggleHovered(Transform rayOrigin) + { + this.Pulse(this.RequestNodeFromRayOrigin(rayOrigin), m_ButtonHoverPulse); + } + void SendVisibilityPulse() { this.Pulse(node, m_MenuHideFlags == 0 ? m_HidePulse : m_ShowPulse); @@ -333,12 +338,29 @@ void AddSettingsMenu(ISettingsMenuProvider provider, MainMenuUI.ButtonData butto { buttonData.sectionName = k_SettingsMenuSectionName; - CreateFaceButton(buttonData, tooltip, () => + var button = CreateFaceButton(buttonData, tooltip, () => { var instance = m_MainMenuUI.AddSubmenu(k_SettingsMenuSectionName, provider.settingsMenuPrefab); m_SettingsMenus[provider] = instance; provider.settingsMenuInstance = instance; + AddToggleHaptics(instance); }); + + button.hovered += OnButtonHovered; + button.clicked += OnButtonClicked; + } + + void AddToggleHaptics(GameObject menuInstance) + { + var toggles = menuInstance.GetComponentsInChildren(); + if (toggles != null && toggles.Length > 0) + { + foreach (var toggle in toggles) + { + toggle.hovered += OnToggleHovered; + toggle.clicked += OnButtonClicked; + } + } } public void RemoveSettingsMenu(ISettingsMenuProvider provider) From 389cd67d8bd6cfea935ff9dbf2ff7313a592d8f2 Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 17 Nov 2017 10:26:47 -0800 Subject: [PATCH 15/89] add submenu button click haptic pulse --- .../Modules/SnappingModule/HapticPulses.meta | 10 ++++++++++ .../HapticPulses/SubMenuButtonClick.asset | 17 +++++++++++++++++ .../HapticPulses/SubMenuButtonClick.asset.meta | 10 ++++++++++ 3 files changed, 37 insertions(+) create mode 100644 Scripts/Modules/SnappingModule/HapticPulses.meta create mode 100644 Scripts/Modules/SnappingModule/HapticPulses/SubMenuButtonClick.asset create mode 100644 Scripts/Modules/SnappingModule/HapticPulses/SubMenuButtonClick.asset.meta diff --git a/Scripts/Modules/SnappingModule/HapticPulses.meta b/Scripts/Modules/SnappingModule/HapticPulses.meta new file mode 100644 index 000000000..78e653d52 --- /dev/null +++ b/Scripts/Modules/SnappingModule/HapticPulses.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 76dab90d1b2fe7e4cb9b649aff286821 +folderAsset: yes +timeCreated: 1510942918 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Modules/SnappingModule/HapticPulses/SubMenuButtonClick.asset b/Scripts/Modules/SnappingModule/HapticPulses/SubMenuButtonClick.asset new file mode 100644 index 000000000..76fe444e4 --- /dev/null +++ b/Scripts/Modules/SnappingModule/HapticPulses/SubMenuButtonClick.asset @@ -0,0 +1,17 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1efd705dfe960584581b3390e04777f1, type: 3} + m_Name: SubMenuButtonClick + m_EditorClassIdentifier: + m_Duration: 0.25 + m_Intensity: 1 + m_FadeIn: 0 + m_FadeOut: 0 diff --git a/Scripts/Modules/SnappingModule/HapticPulses/SubMenuButtonClick.asset.meta b/Scripts/Modules/SnappingModule/HapticPulses/SubMenuButtonClick.asset.meta new file mode 100644 index 000000000..741251808 --- /dev/null +++ b/Scripts/Modules/SnappingModule/HapticPulses/SubMenuButtonClick.asset.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: ad8089d07bd48a047b9d6b45f7a4fd57 +timeCreated: 1510943030 +licenseType: Pro +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: From dd0e4678c404267a971e50cea1a2776a8e5e22b7 Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 17 Nov 2017 10:27:10 -0800 Subject: [PATCH 16/89] configure snapping menu to use new submenu haptic click --- .../Prefabs/MenuFaceSnapping.prefab | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Scripts/Modules/SnappingModule/Prefabs/MenuFaceSnapping.prefab b/Scripts/Modules/SnappingModule/Prefabs/MenuFaceSnapping.prefab index fc783e797..52eb04eba 100644 --- a/Scripts/Modules/SnappingModule/Prefabs/MenuFaceSnapping.prefab +++ b/Scripts/Modules/SnappingModule/Prefabs/MenuFaceSnapping.prefab @@ -2203,7 +2203,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} m_Name: m_EditorClassIdentifier: - m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} m_Description: {fileID: 0} m_Title: {fileID: 114547171262664456} @@ -2219,7 +2219,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} m_Name: m_EditorClassIdentifier: - m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} m_Description: {fileID: 0} m_Title: {fileID: 114487886979728018} @@ -2347,7 +2347,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} m_Name: m_EditorClassIdentifier: - m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} m_Description: {fileID: 0} m_Title: {fileID: 114422380110548290} @@ -2363,7 +2363,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} m_Name: m_EditorClassIdentifier: - m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} m_Description: {fileID: 0} m_Title: {fileID: 114768966837101286} @@ -2491,7 +2491,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} m_Name: m_EditorClassIdentifier: - m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} m_Description: {fileID: 0} m_Title: {fileID: 114837802559842038} @@ -2731,7 +2731,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} m_Name: m_EditorClassIdentifier: - m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} m_Description: {fileID: 0} m_Title: {fileID: 114833023654325632} @@ -2747,7 +2747,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} m_Name: m_EditorClassIdentifier: - m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} m_Description: {fileID: 0} m_Title: {fileID: 114758890587099868} @@ -2763,7 +2763,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} m_Name: m_EditorClassIdentifier: - m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} m_Description: {fileID: 0} m_Title: {fileID: 114936804563099460} @@ -3003,7 +3003,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} m_Name: m_EditorClassIdentifier: - m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2} + m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} m_Description: {fileID: 0} m_Title: {fileID: 114243426776915280} From 8984fdc0abbc7c4a0d532fb06b9d819f5c902b65 Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 17 Nov 2017 12:05:43 -0800 Subject: [PATCH 17/89] make submenu click haptic more subtle --- .../SnappingModule/HapticPulses/SubMenuButtonClick.asset | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Scripts/Modules/SnappingModule/HapticPulses/SubMenuButtonClick.asset b/Scripts/Modules/SnappingModule/HapticPulses/SubMenuButtonClick.asset index 76fe444e4..d1e0d5940 100644 --- a/Scripts/Modules/SnappingModule/HapticPulses/SubMenuButtonClick.asset +++ b/Scripts/Modules/SnappingModule/HapticPulses/SubMenuButtonClick.asset @@ -11,7 +11,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 1efd705dfe960584581b3390e04777f1, type: 3} m_Name: SubMenuButtonClick m_EditorClassIdentifier: - m_Duration: 0.25 - m_Intensity: 1 + m_Duration: 0.05 + m_Intensity: 0.35 m_FadeIn: 0 m_FadeOut: 0 From a5a9c8399a5cf69eef2d89bd951ebf7534596c70 Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 17 Nov 2017 12:06:15 -0800 Subject: [PATCH 18/89] change locomotion settings UI to use TMP instead of Text --- .../LocomotionTool/Prefabs/SettingsUI.prefab | 332 ++++++++++++++---- 1 file changed, 262 insertions(+), 70 deletions(-) diff --git a/Tools/LocomotionTool/Prefabs/SettingsUI.prefab b/Tools/LocomotionTool/Prefabs/SettingsUI.prefab index b163c5800..720c696cc 100644 --- a/Tools/LocomotionTool/Prefabs/SettingsUI.prefab +++ b/Tools/LocomotionTool/Prefabs/SettingsUI.prefab @@ -20,7 +20,7 @@ GameObject: m_Component: - component: {fileID: 224000012653929454} - component: {fileID: 222000012891014098} - - component: {fileID: 114000012025195674} + - component: {fileID: 114237599994434612} m_Layer: 5 m_Name: Label m_TagString: Untagged @@ -54,7 +54,7 @@ GameObject: m_Component: - component: {fileID: 224000011405639814} - component: {fileID: 222000011416400564} - - component: {fileID: 114000011583981380} + - component: {fileID: 114735976065890330} m_Layer: 5 m_Name: Label m_TagString: Untagged @@ -71,6 +71,7 @@ GameObject: m_Component: - component: {fileID: 224000010858218954} - component: {fileID: 114000011920048442} + - component: {fileID: 114129496827691156} m_Layer: 5 m_Name: Blink m_TagString: Untagged @@ -121,6 +122,7 @@ GameObject: m_Component: - component: {fileID: 224000011444372664} - component: {fileID: 114000013714903302} + - component: {fileID: 114034804745796320} m_Layer: 5 m_Name: Fly m_TagString: Untagged @@ -252,39 +254,6 @@ MonoBehaviour: m_FillAmount: 1 m_FillClockwise: 1 m_FillOrigin: 0 ---- !u!114 &114000011583981380 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000011512978662} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 2100000, guid: dec2d25be9058334c91a0402762efa61, type: 2} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 0 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, - Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_FontData: - m_Font: {fileID: 12800000, guid: 013679fd6ee2085428a7f896aa7b50cc, type: 3} - m_FontSize: 20 - m_FontStyle: 0 - m_BestFit: 0 - m_MinSize: 10 - m_MaxSize: 40 - m_Alignment: 4 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: Blink --- !u!114 &114000011835530144 MonoBehaviour: m_ObjectHideFlags: 1 @@ -357,39 +326,6 @@ MonoBehaviour: m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_IsOn: 0 ---- !u!114 &114000012025195674 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000010398065086} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 2100000, guid: dec2d25be9058334c91a0402762efa61, type: 2} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 0 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, - Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_FontData: - m_Font: {fileID: 12800000, guid: 013679fd6ee2085428a7f896aa7b50cc, type: 3} - m_FontSize: 20 - m_FontStyle: 0 - m_BestFit: 0 - m_MinSize: 10 - m_MaxSize: 40 - m_Alignment: 4 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: Fly --- !u!114 &114000012940195592 MonoBehaviour: m_ObjectHideFlags: 1 @@ -496,6 +432,38 @@ MonoBehaviour: m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_IsOn: 1 +--- !u!114 &114034804745796320 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000013494423478} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 0} + m_Title: {fileID: 114237599994434612} + m_Toggle: {fileID: 114000013714903302} +--- !u!114 &114129496827691156 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000011772923556} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 0} + m_Title: {fileID: 114735976065890330} + m_Toggle: {fileID: 114000011920048442} --- !u!114 &114210595956423184 MonoBehaviour: m_ObjectHideFlags: 1 @@ -529,6 +497,118 @@ MonoBehaviour: m_VerticalOverflow: 0 m_LineSpacing: 1 m_Text: ' Locomotion Mode:' +--- !u!114 &114237599994434612 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000010398065086} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Fly + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 76ff077e92eb4fe41aa26173a3d98fb6, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 54d3f6429fd638b4d9ca906c1354d050, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 20 + m_fontSizeBase: 20 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 514 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 3 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 0} + characterCount: 0 + spriteCount: 0 + spaceCount: 0 + wordCount: 0 + linkCount: 0 + lineCount: 0 + pageCount: 0 + materialCount: 0 + m_havePropertiesChanged: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 1 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} --- !u!114 &114261882201029984 MonoBehaviour: m_ObjectHideFlags: 1 @@ -563,6 +643,118 @@ MonoBehaviour: m_ChildForceExpandHeight: 1 m_ChildControlWidth: 1 m_ChildControlHeight: 0 +--- !u!114 &114735976065890330 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000011512978662} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Blink + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 76ff077e92eb4fe41aa26173a3d98fb6, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 54d3f6429fd638b4d9ca906c1354d050, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 20 + m_fontSizeBase: 20 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 514 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 3 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 0} + characterCount: 0 + spriteCount: 0 + spaceCount: 0 + wordCount: 0 + linkCount: 0 + lineCount: 0 + pageCount: 0 + materialCount: 0 + m_havePropertiesChanged: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 1 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} --- !u!222 &222000010570603678 CanvasRenderer: m_ObjectHideFlags: 1 @@ -671,7 +863,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} + m_AnchoredPosition: {x: -0.000000007450581, y: 0} m_SizeDelta: {x: -0.5, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!224 &224000011444372664 @@ -768,7 +960,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} + m_AnchoredPosition: {x: -0.000000007450581, y: 0} m_SizeDelta: {x: -0.5, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!224 &224000013716393632 From 0bec46cbf067e7d17ea337e5d26bffcbe5216a53 Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 17 Nov 2017 12:07:19 -0800 Subject: [PATCH 19/89] add haptics to settings menu items too --- Menus/MainMenu/MainMenu.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Menus/MainMenu/MainMenu.cs b/Menus/MainMenu/MainMenu.cs index 32d03a487..ee7fd8c1f 100644 --- a/Menus/MainMenu/MainMenu.cs +++ b/Menus/MainMenu/MainMenu.cs @@ -381,6 +381,7 @@ public void AddSettingsMenuItem(ISettingsMenuItemProvider provider) var instance = m_MainMenuUI.CreateCustomButton(provider.settingsMenuItemPrefab, k_SettingsMenuSectionName); m_SettingsMenuItems[provider] = instance; provider.settingsMenuItemInstance = instance; + AddToggleHaptics(instance); } public void RemoveSettingsMenuItem(ISettingsMenuItemProvider provider) From 5b4071769ff9f428bc8177dc085e5c5dd1309abc Mon Sep 17 00:00:00 2001 From: Jono Forbes Date: Fri, 17 Nov 2017 14:47:23 -0800 Subject: [PATCH 20/89] Add animation when undo/redo is performed. --- Menus/UndoMenu/Prefabs/UndoMenu.prefab | 14 +++---- Menus/UndoMenu/Scripts/UndoMenuUI.cs | 54 ++++++++++++++++++++++---- Menus/UndoMenu/UndoMenu.cs | 10 +++-- 3 files changed, 60 insertions(+), 18 deletions(-) diff --git a/Menus/UndoMenu/Prefabs/UndoMenu.prefab b/Menus/UndoMenu/Prefabs/UndoMenu.prefab index 6eef503ac..2511f5bec 100644 --- a/Menus/UndoMenu/Prefabs/UndoMenu.prefab +++ b/Menus/UndoMenu/Prefabs/UndoMenu.prefab @@ -23,7 +23,7 @@ GameObject: - component: {fileID: 64453517736190084} - component: {fileID: 23859873210418424} m_Layer: 0 - m_Name: Undo + m_Name: Redo m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -57,7 +57,7 @@ GameObject: - component: {fileID: 64290476127420130} - component: {fileID: 23850276268091638} m_Layer: 0 - m_Name: Redo + m_Name: Undo m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -74,7 +74,7 @@ Transform: m_LocalScale: {x: 0.02, y: 0.02, z: 0.02} m_Children: [] m_Father: {fileID: 4579274395351022} - m_RootOrder: 0 + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 90, y: 180, z: 0} --- !u!4 &4579274395351022 Transform: @@ -86,8 +86,8 @@ Transform: m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: - - {fileID: 4386191342587820} - {fileID: 4809501880196944} + - {fileID: 4386191342587820} m_Father: {fileID: 0} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} @@ -102,7 +102,7 @@ Transform: m_LocalScale: {x: 0.02, y: 0.02, z: 0.02} m_Children: [] m_Father: {fileID: 4579274395351022} - m_RootOrder: 1 + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} --- !u!23 &23850276268091638 MeshRenderer: @@ -225,5 +225,5 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: b8ebdbcab31646f4da31c5a9a3f2ce5b, type: 3} m_Name: m_EditorClassIdentifier: - m_UndoButtonMeshRenderer: {fileID: 23859873210418424} - m_RedoButtonMeshRenderer: {fileID: 23850276268091638} + m_UndoButtonMeshRenderer: {fileID: 23850276268091638} + m_RedoButtonMeshRenderer: {fileID: 23859873210418424} diff --git a/Menus/UndoMenu/Scripts/UndoMenuUI.cs b/Menus/UndoMenu/Scripts/UndoMenuUI.cs index db3e0b052..2c414582c 100644 --- a/Menus/UndoMenu/Scripts/UndoMenuUI.cs +++ b/Menus/UndoMenu/Scripts/UndoMenuUI.cs @@ -11,8 +11,9 @@ namespace UnityEditor.Experimental.EditorVR.Menus sealed class UndoMenuUI : MonoBehaviour, IConnectInterfaces { const float k_EngageAnimationDuration = 0.1f; - const float k_EngagedAlpha = 0.85f; - const float k_DisengagedAlpha = 0.5f; + const float k_EngagedAlpha = 0.5f; + const float k_DisengagedAlpha = 0.3f; + const float k_UndoPerformedAlpha = 1f; const string k_MaterialColorProperty = "_Color"; [SerializeField] @@ -90,6 +91,7 @@ public List actions Material m_UndoButtonMaterial; Material m_RedoButtonMaterial; Coroutine m_EngageCoroutine; + Coroutine m_UndoPerformedCoroutine; void Awake() { @@ -110,16 +112,16 @@ public void Setup() IEnumerator AnimateEngage(bool engaging) { - var startingColor = m_UndoButtonMaterial.GetColor(k_MaterialColorProperty); - var targetColor = startingColor; + var undoStartingColor = m_UndoButtonMaterial.GetColor(k_MaterialColorProperty); + var redoStartingColor = m_RedoButtonMaterial.GetColor(k_MaterialColorProperty); + var targetColor = Color.white; targetColor.a = engaging ? k_EngagedAlpha : k_DisengagedAlpha; var transitionAmount = 0f; var currentDuration = 0f; while (transitionAmount < 1f) { - var currentColor = Color.Lerp(startingColor, targetColor, transitionAmount); - m_UndoButtonMaterial.SetColor(k_MaterialColorProperty, currentColor); - m_RedoButtonMaterial.SetColor(k_MaterialColorProperty, currentColor); + m_UndoButtonMaterial.SetColor(k_MaterialColorProperty, Color.Lerp(undoStartingColor, targetColor, transitionAmount)); + m_RedoButtonMaterial.SetColor(k_MaterialColorProperty, Color.Lerp(redoStartingColor, targetColor, transitionAmount)); currentDuration += Time.deltaTime; transitionAmount = currentDuration / k_EngageAnimationDuration; yield return null; @@ -127,6 +129,44 @@ IEnumerator AnimateEngage(bool engaging) m_UndoButtonMaterial.SetColor(k_MaterialColorProperty, targetColor); m_RedoButtonMaterial.SetColor(k_MaterialColorProperty, targetColor); } + + public void StartPerformedAnimation(bool undo) + { + StopCoroutine(m_EngageCoroutine); + this.RestartCoroutine(ref m_UndoPerformedCoroutine, AnimateUndoPerformed(undo)); + } + + IEnumerator AnimateUndoPerformed(bool undo) + { + var targetMaterial = undo + ? m_UndoButtonMaterial + : m_RedoButtonMaterial; + var startingColor = m_UndoButtonMaterial.GetColor(k_MaterialColorProperty); + var targetColor = startingColor; + targetColor.a = k_UndoPerformedAlpha; + var transitionAmount = 0f; + var currentDuration = 0f; + while (transitionAmount < 1f) + { + var currentColor = Color.Lerp(startingColor, targetColor, transitionAmount); + targetMaterial.SetColor(k_MaterialColorProperty, currentColor); + currentDuration += Time.deltaTime; + transitionAmount = currentDuration / k_EngageAnimationDuration; + yield return null; + } + transitionAmount = currentDuration = 0f; + startingColor = targetColor; + targetColor.a = k_DisengagedAlpha; + while (transitionAmount < 1f) + { + var currentColor = Color.Lerp(startingColor, targetColor, transitionAmount); + targetMaterial.SetColor(k_MaterialColorProperty, currentColor); + currentDuration += Time.deltaTime; + transitionAmount = currentDuration / k_EngageAnimationDuration; + yield return null; + } + targetMaterial.SetColor(k_MaterialColorProperty, targetColor); + } } } #endif diff --git a/Menus/UndoMenu/UndoMenu.cs b/Menus/UndoMenu/UndoMenu.cs index e7c543eda..709c58c69 100644 --- a/Menus/UndoMenu/UndoMenu.cs +++ b/Menus/UndoMenu/UndoMenu.cs @@ -121,19 +121,21 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon m_UndoMenuUI.engaged = true; var navigateX = undoMenuInput.navigateX.value; - var undoRedoEngaged = false; + var undoRedoPerformed = false; if (navigateX < -k_UndoRedoThreshold && m_PrevNavigateX > -k_UndoRedoThreshold) { Undo.PerformUndo(); - undoRedoEngaged = true; + m_UndoMenuUI.StartPerformedAnimation(true); + undoRedoPerformed = true; } else if (navigateX > k_UndoRedoThreshold && m_PrevNavigateX < k_UndoRedoThreshold) { Undo.PerformRedo(); - undoRedoEngaged = true; + m_UndoMenuUI.StartPerformedAnimation(false); + undoRedoPerformed = true; } m_PrevNavigateX = navigateX; - if (undoRedoEngaged) + if (undoRedoPerformed) { consumeControl(undoMenuInput.navigateX); this.Pulse(node, m_UndoPulse); From 14eec1d48406b5774fd4e15bd0204fdfb40661f7 Mon Sep 17 00:00:00 2001 From: Jono Forbes Date: Fri, 17 Nov 2017 15:18:15 -0800 Subject: [PATCH 21/89] Show feedback for hint & undo/redo performed. --- Menus/UndoMenu/UndoMenu.cs | 23 +++++++++++++++++++++-- Prefabs/UI/Tooltip.prefab | 4 ++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Menus/UndoMenu/UndoMenu.cs b/Menus/UndoMenu/UndoMenu.cs index 709c58c69..c1b682707 100644 --- a/Menus/UndoMenu/UndoMenu.cs +++ b/Menus/UndoMenu/UndoMenu.cs @@ -126,12 +126,14 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon { Undo.PerformUndo(); m_UndoMenuUI.StartPerformedAnimation(true); + ShowUndoPerformedFeedback(true); undoRedoPerformed = true; } else if (navigateX > k_UndoRedoThreshold && m_PrevNavigateX < k_UndoRedoThreshold) { Undo.PerformRedo(); m_UndoMenuUI.StartPerformedAnimation(false); + ShowUndoPerformedFeedback(false); undoRedoPerformed = true; } m_PrevNavigateX = navigateX; @@ -153,7 +155,7 @@ IEnumerator AcceptInputAfterStickReleased() void ShowFeedback() { List controls; - if (m_Controls.TryGetValue("SelectItem", out controls)) + if (m_Controls.TryGetValue("Engage", out controls)) { foreach (var id in controls) { @@ -161,7 +163,24 @@ void ShowFeedback() { control = id, node = node, - tooltipText = "Select Action (Press to Execute)" + tooltipText = "Click + flick left/right to undo/redo" + }); + } + } + } + + void ShowUndoPerformedFeedback(bool undo) + { + List controls; + if (m_Controls.TryGetValue("Engage", out controls)) + { + foreach (var id in controls) + { + this.AddFeedbackRequest(new ProxyFeedbackRequest + { + control = id, + node = node, + tooltipText = string.Format("{0} performed", undo ? "Undo" : "Redo") }); } } diff --git a/Prefabs/UI/Tooltip.prefab b/Prefabs/UI/Tooltip.prefab index cce407930..1ee365acd 100644 --- a/Prefabs/UI/Tooltip.prefab +++ b/Prefabs/UI/Tooltip.prefab @@ -443,7 +443,7 @@ MonoBehaviour: m_Alignment: 4 m_AlignByGeometry: 0 m_RichText: 1 - m_HorizontalOverflow: 0 + m_HorizontalOverflow: 1 m_VerticalOverflow: 0 m_LineSpacing: 1 m_Text: A tooltip @@ -579,7 +579,7 @@ RectTransform: m_PrefabInternal: {fileID: 100100000} m_GameObject: {fileID: 1000013865747660} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 15, z: 0} + m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: - {fileID: 224000011487986384} From a394d0fb0e0fd042442671db9856ac308630f69d Mon Sep 17 00:00:00 2001 From: Jono Forbes Date: Fri, 17 Nov 2017 17:35:21 -0800 Subject: [PATCH 22/89] Add initial Vive undo/redo control mapping. --- Menus/UndoMenu/UndoMenu.cs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Menus/UndoMenu/UndoMenu.cs b/Menus/UndoMenu/UndoMenu.cs index c1b682707..58701ce24 100644 --- a/Menus/UndoMenu/UndoMenu.cs +++ b/Menus/UndoMenu/UndoMenu.cs @@ -12,10 +12,12 @@ namespace UnityEditor.Experimental.EditorVR.Menus { sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IAlternateMenu, IUsesMenuOrigins, ICustomActionMap, - IControlHaptics, IUsesNode, IConnectInterfaces, IRequestFeedback + IControlHaptics, IUsesNode, IConnectInterfaces, IRequestFeedback, IUsesDeviceType { const float k_UndoRedoThreshold = 0.5f; const float k_EngageUndoAfterStickReleasedDuration = 0.1f; // Duration after releasing the joystick to still accept a left/right flick to undo/redo. + const string k_FeedbackHintForJoystickController = "Click + flick left/right to undo/redo"; + const string k_FeedbackHintForTrackpadController = "Click left/right side to undo/redo"; [SerializeField] ActionMap m_ActionMap; @@ -33,6 +35,8 @@ sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IAlternateMenu, IUsesMenu float m_PrevNavigateX; bool m_StillEngagedAfterStickRelease; Coroutine m_StillEngagedAfterStickReleasedCoroutine; + bool m_TrackpadController; + string m_FeedbackHintForCurrentController; readonly BindingDictionary m_Controls = new BindingDictionary(); @@ -103,6 +107,10 @@ void Start() this.ConnectInterfaces(m_UndoMenuUI); // Connect interfaces before performing setup on the UI m_UndoMenuUI.Setup(); InputUtils.GetBindingDictionaryFromActionMap(m_ActionMap, m_Controls); + m_TrackpadController = this.GetDeviceType() == DeviceType.Vive; + m_FeedbackHintForCurrentController = m_TrackpadController + ? k_FeedbackHintForTrackpadController + : k_FeedbackHintForJoystickController; } public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl) @@ -113,23 +121,23 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon this.ClearFeedbackRequests(); return; } - if (undoMenuInput.engage.wasJustReleased) + if (undoMenuInput.engage.wasJustReleased && !m_TrackpadController) this.RestartCoroutine(ref m_StillEngagedAfterStickReleasedCoroutine, AcceptInputAfterStickReleased()); - if (!(undoMenuInput.engage.wasJustPressed || undoMenuInput.engage.isHeld || m_StillEngagedAfterStickRelease)) + if (!(undoMenuInput.engage.wasJustPressed || !m_TrackpadController && (undoMenuInput.engage.isHeld || m_StillEngagedAfterStickRelease))) return; consumeControl(undoMenuInput.engage); m_UndoMenuUI.engaged = true; var navigateX = undoMenuInput.navigateX.value; var undoRedoPerformed = false; - if (navigateX < -k_UndoRedoThreshold && m_PrevNavigateX > -k_UndoRedoThreshold) + if (navigateX < -k_UndoRedoThreshold && (m_TrackpadController || m_PrevNavigateX > -k_UndoRedoThreshold)) { Undo.PerformUndo(); m_UndoMenuUI.StartPerformedAnimation(true); ShowUndoPerformedFeedback(true); undoRedoPerformed = true; } - else if (navigateX > k_UndoRedoThreshold && m_PrevNavigateX < k_UndoRedoThreshold) + else if (navigateX > k_UndoRedoThreshold && (m_TrackpadController || m_PrevNavigateX < k_UndoRedoThreshold)) { Undo.PerformRedo(); m_UndoMenuUI.StartPerformedAnimation(false); @@ -163,7 +171,7 @@ void ShowFeedback() { control = id, node = node, - tooltipText = "Click + flick left/right to undo/redo" + tooltipText = m_FeedbackHintForCurrentController }); } } From ada270485e6695c6cdb4bafd238cccbbef60bbf0 Mon Sep 17 00:00:00 2001 From: Jono Forbes Date: Fri, 17 Nov 2017 18:08:11 -0800 Subject: [PATCH 23/89] Fix undo icon material render queue. --- Menus/UndoMenu/Materials/UndoIcon.mat | 2 +- Menus/UndoMenu/Scripts/UndoMenuUI.cs | 13 ++++++++----- Menus/UndoMenu/UndoMenu.cs | 6 ++++++ Scripts/Core/EditorVR.Menus.cs | 1 + 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Menus/UndoMenu/Materials/UndoIcon.mat b/Menus/UndoMenu/Materials/UndoIcon.mat index cc199eaa3..7cf3668a0 100644 --- a/Menus/UndoMenu/Materials/UndoIcon.mat +++ b/Menus/UndoMenu/Materials/UndoIcon.mat @@ -12,7 +12,7 @@ Material: m_LightmapFlags: 4 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 - m_CustomRenderQueue: 3000 + m_CustomRenderQueue: 9105 stringTagMap: RenderType: Transparent disabledShaderPasses: [] diff --git a/Menus/UndoMenu/Scripts/UndoMenuUI.cs b/Menus/UndoMenu/Scripts/UndoMenuUI.cs index 2c414582c..9610c3ed0 100644 --- a/Menus/UndoMenu/Scripts/UndoMenuUI.cs +++ b/Menus/UndoMenu/Scripts/UndoMenuUI.cs @@ -21,6 +21,11 @@ sealed class UndoMenuUI : MonoBehaviour, IConnectInterfaces [SerializeField] MeshRenderer m_RedoButtonMeshRenderer; + + Material m_UndoButtonMaterial; + Material m_RedoButtonMaterial; + Coroutine m_EngageCoroutine; + Coroutine m_UndoPerformedCoroutine; public Transform alternateMenuOrigin { @@ -88,11 +93,6 @@ public List actions List m_Actions; - Material m_UndoButtonMaterial; - Material m_RedoButtonMaterial; - Coroutine m_EngageCoroutine; - Coroutine m_UndoPerformedCoroutine; - void Awake() { m_UndoButtonMaterial = MaterialUtils.GetMaterialClone(m_UndoButtonMeshRenderer); @@ -126,6 +126,7 @@ IEnumerator AnimateEngage(bool engaging) transitionAmount = currentDuration / k_EngageAnimationDuration; yield return null; } + m_UndoButtonMaterial.SetColor(k_MaterialColorProperty, targetColor); m_RedoButtonMaterial.SetColor(k_MaterialColorProperty, targetColor); } @@ -154,6 +155,7 @@ IEnumerator AnimateUndoPerformed(bool undo) transitionAmount = currentDuration / k_EngageAnimationDuration; yield return null; } + transitionAmount = currentDuration = 0f; startingColor = targetColor; targetColor.a = k_DisengagedAlpha; @@ -165,6 +167,7 @@ IEnumerator AnimateUndoPerformed(bool undo) transitionAmount = currentDuration / k_EngageAnimationDuration; yield return null; } + targetMaterial.SetColor(k_MaterialColorProperty, targetColor); } } diff --git a/Menus/UndoMenu/UndoMenu.cs b/Menus/UndoMenu/UndoMenu.cs index 58701ce24..d0873cee2 100644 --- a/Menus/UndoMenu/UndoMenu.cs +++ b/Menus/UndoMenu/UndoMenu.cs @@ -87,6 +87,7 @@ public MenuHideFlags menuHideFlags if (m_MenuHideFlags != value) { m_MenuHideFlags = value; + var visible = value == 0; if (m_UndoMenuUI) m_UndoMenuUI.visible = visible; @@ -121,10 +122,13 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon this.ClearFeedbackRequests(); return; } + if (undoMenuInput.engage.wasJustReleased && !m_TrackpadController) this.RestartCoroutine(ref m_StillEngagedAfterStickReleasedCoroutine, AcceptInputAfterStickReleased()); + if (!(undoMenuInput.engage.wasJustPressed || !m_TrackpadController && (undoMenuInput.engage.isHeld || m_StillEngagedAfterStickRelease))) return; + consumeControl(undoMenuInput.engage); m_UndoMenuUI.engaged = true; @@ -144,7 +148,9 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon ShowUndoPerformedFeedback(false); undoRedoPerformed = true; } + m_PrevNavigateX = navigateX; + if (undoRedoPerformed) { consumeControl(undoMenuInput.navigateX); diff --git a/Scripts/Core/EditorVR.Menus.cs b/Scripts/Core/EditorVR.Menus.cs index 714edc6f7..24189ed4a 100644 --- a/Scripts/Core/EditorVR.Menus.cs +++ b/Scripts/Core/EditorVR.Menus.cs @@ -235,6 +235,7 @@ internal void UpdateMenuVisibilities() if (!undoMenuVisible && undoMenuHideData != null) undoMenuHideData.hideFlags = 0; + // Check if menu bounds overlap with any workspace colliders foreach (var kvp in menuHideData) { From 4d4724e0e2478ad94f6fcab52100db7e4210738c Mon Sep 17 00:00:00 2001 From: Jono Date: Mon, 20 Nov 2017 16:04:55 -0500 Subject: [PATCH 24/89] Hide the undo menu if radial menu is open, and always show it otherwise. --- Scripts/Core/EditorVR.Menus.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Scripts/Core/EditorVR.Menus.cs b/Scripts/Core/EditorVR.Menus.cs index 24189ed4a..010a7a1f9 100644 --- a/Scripts/Core/EditorVR.Menus.cs +++ b/Scripts/Core/EditorVR.Menus.cs @@ -233,7 +233,10 @@ internal void UpdateMenuVisibilities() if (alternateMenuVisible && (customMenuVisible || mainMenuVisible)) alternateMenuData.hideFlags |= MenuHideFlags.OtherMenu; - if (!undoMenuVisible && undoMenuHideData != null) + // Always show undo menu, unless the radial menu is open. + if (undoMenuVisible && alternateMenuVisible) + undoMenuHideData.hideFlags |= MenuHideFlags.OtherMenu; + else if (!undoMenuVisible && undoMenuHideData != null) undoMenuHideData.hideFlags = 0; // Check if menu bounds overlap with any workspace colliders From a2240eb9efda284398ead043b6179daf7ee32744 Mon Sep 17 00:00:00 2001 From: Jono Date: Mon, 20 Nov 2017 16:25:55 -0500 Subject: [PATCH 25/89] Vertically flip redo arrow. --- Menus/UndoMenu/Prefabs/UndoMenu.prefab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Menus/UndoMenu/Prefabs/UndoMenu.prefab b/Menus/UndoMenu/Prefabs/UndoMenu.prefab index 2511f5bec..a7f498d7f 100644 --- a/Menus/UndoMenu/Prefabs/UndoMenu.prefab +++ b/Menus/UndoMenu/Prefabs/UndoMenu.prefab @@ -71,7 +71,7 @@ Transform: m_GameObject: {fileID: 1695890495350928} m_LocalRotation: {x: 0, y: 0.7071068, z: -0.7071068, w: 0} m_LocalPosition: {x: 0.01, y: 0, z: 0} - m_LocalScale: {x: 0.02, y: 0.02, z: 0.02} + m_LocalScale: {x: 0.02, y: -0.02, z: 0.02} m_Children: [] m_Father: {fileID: 4579274395351022} m_RootOrder: 1 From ad164638f4456e34fd47688a59ec3d81c6c97cf0 Mon Sep 17 00:00:00 2001 From: Jono Date: Mon, 20 Nov 2017 19:37:09 -0500 Subject: [PATCH 26/89] Change Vive MainMenu interaction to swipe, rather than click, to rotate face. --- Menus/MainMenu/MainMenu.cs | 51 +++++++++++++++++++++++--- Menus/MainMenu/Scripts/MainMenuUI.cs | 2 + Menus/UndoMenu/Prefabs/UndoMenu.prefab | 4 +- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/Menus/MainMenu/MainMenu.cs b/Menus/MainMenu/MainMenu.cs index f5cdeda34..4612cbb29 100644 --- a/Menus/MainMenu/MainMenu.cs +++ b/Menus/MainMenu/MainMenu.cs @@ -1,5 +1,6 @@ #if UNITY_EDITOR using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEditor.Experimental.EditorVR.Core; @@ -16,6 +17,7 @@ sealed class MainMenu : MonoBehaviour, IMainMenu, IConnectInterfaces, IInstantia IRequestFeedback { const string k_SettingsMenuSectionName = "Settings"; + const float k_MaxFlickDuration = 0.3f; [SerializeField] ActionMap m_ActionMap; @@ -43,6 +45,8 @@ sealed class MainMenu : MonoBehaviour, IMainMenu, IConnectInterfaces, IInstantia MainMenuUI m_MainMenuUI; float m_LastRotationInput; MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; + float m_RotationInputStartValue; + DateTime m_RotationInputStartTime; readonly Dictionary m_ToolButtons = new Dictionary(); readonly Dictionary m_SettingsMenus = new Dictionary(); readonly Dictionary m_SettingsMenuItems = new Dictionary(); @@ -141,18 +145,53 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon var mainMenuInput = (MainMenuInput)input; var rotationInput = -mainMenuInput.rotate.rawValue; - + const float kFlickDeltaThreshold = 0.5f; - if ((this.GetDeviceType() != DeviceType.Vive && Mathf.Abs(rotationInput) >= kFlickDeltaThreshold - && Mathf.Abs(m_LastRotationInput) < kFlickDeltaThreshold) || mainMenuInput.flickFace.wasJustReleased) + + if (this.GetDeviceType() == DeviceType.Vive) + { + if (rotationInput != 0f) + { + if (m_LastRotationInput == 0f) + { + // Touch began + m_RotationInputStartValue = rotationInput; + m_RotationInputStartTime = DateTime.Now; + } + else + { + // Touch held + var distance = rotationInput - m_RotationInputStartValue; + var lastDistance = m_LastRotationInput - m_RotationInputStartValue; + if (Mathf.Abs(distance) >= kFlickDeltaThreshold + && Mathf.Abs(lastDistance) < kFlickDeltaThreshold + && (float)(DateTime.Now - m_RotationInputStartTime).TotalSeconds < k_MaxFlickDuration) + { + m_RotationInputStartValue = rotationInput; + m_RotationInputStartTime = DateTime.Now; + if (!m_MainMenuUI.rotating) + { + FlickMenu(distance); + } + } + } + } + } + else if (Mathf.Abs(rotationInput) >= kFlickDeltaThreshold + && Mathf.Abs(m_LastRotationInput) < kFlickDeltaThreshold) { - m_MainMenuUI.targetFaceIndex += (int)Mathf.Sign(rotationInput); - this.Pulse(node, m_FaceRotationPulse); + FlickMenu(rotationInput); } m_LastRotationInput = rotationInput; } + void FlickMenu(float rotationInput) + { + m_MainMenuUI.targetFaceIndex += (int)Mathf.Sign(rotationInput); + this.Pulse(node, m_FaceRotationPulse); + } + void OnDestroy() { if (m_MainMenuUI) @@ -370,7 +409,7 @@ public void RemoveSettingsMenuItem(ISettingsMenuItemProvider provider) void ShowFeedback() { - var tooltipText = this.GetDeviceType() == DeviceType.Vive ? "Press to Rotate Menu" : "Rotate Menu"; + var tooltipText = this.GetDeviceType() == DeviceType.Vive ? "Swipe to Rotate Menu" : "Rotate Menu"; List controls; if (m_Controls.TryGetValue("FlickFace", out controls)) { diff --git a/Menus/MainMenu/Scripts/MainMenuUI.cs b/Menus/MainMenu/Scripts/MainMenuUI.cs index e22e75311..eeb289a19 100644 --- a/Menus/MainMenu/Scripts/MainMenuUI.cs +++ b/Menus/MainMenu/Scripts/MainMenuUI.cs @@ -95,6 +95,8 @@ public int targetFaceIndex } } + public bool rotating { get { return m_RotationState != RotationState.AtRest; } } + public Transform menuOrigin { get { return m_MenuOrigin; } diff --git a/Menus/UndoMenu/Prefabs/UndoMenu.prefab b/Menus/UndoMenu/Prefabs/UndoMenu.prefab index a7f498d7f..b5f3988e8 100644 --- a/Menus/UndoMenu/Prefabs/UndoMenu.prefab +++ b/Menus/UndoMenu/Prefabs/UndoMenu.prefab @@ -70,7 +70,7 @@ Transform: m_PrefabInternal: {fileID: 100100000} m_GameObject: {fileID: 1695890495350928} m_LocalRotation: {x: 0, y: 0.7071068, z: -0.7071068, w: 0} - m_LocalPosition: {x: 0.01, y: 0, z: 0} + m_LocalPosition: {x: 0.01, y: 0, z: 0.0032} m_LocalScale: {x: 0.02, y: -0.02, z: 0.02} m_Children: [] m_Father: {fileID: 4579274395351022} @@ -98,7 +98,7 @@ Transform: m_PrefabInternal: {fileID: 100100000} m_GameObject: {fileID: 1919443148181408} m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068} - m_LocalPosition: {x: -0.01, y: 0, z: 0} + m_LocalPosition: {x: -0.01, y: 0, z: 0.0032} m_LocalScale: {x: 0.02, y: 0.02, z: 0.02} m_Children: [] m_Father: {fileID: 4579274395351022} From 70b0c71f39cf0257a3bfe9d98604e06110406be2 Mon Sep 17 00:00:00 2001 From: Jono Date: Tue, 21 Nov 2017 14:47:32 -0500 Subject: [PATCH 27/89] Address PR cleanup feedback. --- Menus/MainMenu/MainMenu.cs | 5 ++--- Menus/RadialMenu/RadialMenu.cs | 1 - Menus/UndoMenu/Scripts/UndoMenuUI.cs | 16 +++++++--------- Menus/UndoMenu/UndoMenu.cs | 13 +++++++------ 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/Menus/MainMenu/MainMenu.cs b/Menus/MainMenu/MainMenu.cs index 4612cbb29..104528e6f 100644 --- a/Menus/MainMenu/MainMenu.cs +++ b/Menus/MainMenu/MainMenu.cs @@ -1,6 +1,5 @@ #if UNITY_EDITOR using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEditor.Experimental.EditorVR.Core; @@ -150,9 +149,9 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon if (this.GetDeviceType() == DeviceType.Vive) { - if (rotationInput != 0f) + if (!Mathf.Approximately(rotationInput, 0f)) { - if (m_LastRotationInput == 0f) + if (Mathf.Approximately(m_LastRotationInput, 0f)) { // Touch began m_RotationInputStartValue = rotationInput; diff --git a/Menus/RadialMenu/RadialMenu.cs b/Menus/RadialMenu/RadialMenu.cs index 6039851fc..5d52e66ae 100644 --- a/Menus/RadialMenu/RadialMenu.cs +++ b/Menus/RadialMenu/RadialMenu.cs @@ -33,7 +33,6 @@ sealed class RadialMenu : MonoBehaviour, IInstantiateUI, IAlternateMenu, IUsesMe List m_MenuActions; Transform m_AlternateMenuOrigin; MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; - float m_PrevNavigateX; readonly BindingDictionary m_Controls = new BindingDictionary(); diff --git a/Menus/UndoMenu/Scripts/UndoMenuUI.cs b/Menus/UndoMenu/Scripts/UndoMenuUI.cs index 9610c3ed0..1da832d6e 100644 --- a/Menus/UndoMenu/Scripts/UndoMenuUI.cs +++ b/Menus/UndoMenu/Scripts/UndoMenuUI.cs @@ -51,6 +51,7 @@ public bool engaged { if (m_Engaged == value) return; + m_Engaged = value; this.RestartCoroutine(ref m_EngageCoroutine, AnimateEngage(m_Engaged)); } @@ -68,6 +69,7 @@ public bool visible m_Visible = value; + StopAllCoroutines(); gameObject.SetActive(value); } } @@ -105,11 +107,6 @@ void OnDestroy() ObjectUtils.Destroy(m_RedoButtonMaterial); } - public void Setup() - { - gameObject.SetActive(false); - } - IEnumerator AnimateEngage(bool engaging) { var undoStartingColor = m_UndoButtonMaterial.GetColor(k_MaterialColorProperty); @@ -120,8 +117,9 @@ IEnumerator AnimateEngage(bool engaging) var currentDuration = 0f; while (transitionAmount < 1f) { - m_UndoButtonMaterial.SetColor(k_MaterialColorProperty, Color.Lerp(undoStartingColor, targetColor, transitionAmount)); - m_RedoButtonMaterial.SetColor(k_MaterialColorProperty, Color.Lerp(redoStartingColor, targetColor, transitionAmount)); + var smoothAmont = MathUtilsExt.SmoothInOutLerpFloat(transitionAmount); + m_UndoButtonMaterial.SetColor(k_MaterialColorProperty, Color.Lerp(undoStartingColor, targetColor, smoothAmont)); + m_RedoButtonMaterial.SetColor(k_MaterialColorProperty, Color.Lerp(redoStartingColor, targetColor, smoothAmont)); currentDuration += Time.deltaTime; transitionAmount = currentDuration / k_EngageAnimationDuration; yield return null; @@ -149,7 +147,7 @@ IEnumerator AnimateUndoPerformed(bool undo) var currentDuration = 0f; while (transitionAmount < 1f) { - var currentColor = Color.Lerp(startingColor, targetColor, transitionAmount); + var currentColor = Color.Lerp(startingColor, targetColor, MathUtilsExt.SmoothInOutLerpFloat(transitionAmount)); targetMaterial.SetColor(k_MaterialColorProperty, currentColor); currentDuration += Time.deltaTime; transitionAmount = currentDuration / k_EngageAnimationDuration; @@ -161,7 +159,7 @@ IEnumerator AnimateUndoPerformed(bool undo) targetColor.a = k_DisengagedAlpha; while (transitionAmount < 1f) { - var currentColor = Color.Lerp(startingColor, targetColor, transitionAmount); + var currentColor = Color.Lerp(startingColor, targetColor, MathUtilsExt.SmoothInOutLerpFloat(transitionAmount)); targetMaterial.SetColor(k_MaterialColorProperty, currentColor); currentDuration += Time.deltaTime; transitionAmount = currentDuration / k_EngageAnimationDuration; diff --git a/Menus/UndoMenu/UndoMenu.cs b/Menus/UndoMenu/UndoMenu.cs index d0873cee2..26acab6a0 100644 --- a/Menus/UndoMenu/UndoMenu.cs +++ b/Menus/UndoMenu/UndoMenu.cs @@ -15,6 +15,7 @@ sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IAlternateMenu, IUsesMenu IControlHaptics, IUsesNode, IConnectInterfaces, IRequestFeedback, IUsesDeviceType { const float k_UndoRedoThreshold = 0.5f; + const string k_EngageControlName = "Engage"; const float k_EngageUndoAfterStickReleasedDuration = 0.1f; // Duration after releasing the joystick to still accept a left/right flick to undo/redo. const string k_FeedbackHintForJoystickController = "Click + flick left/right to undo/redo"; const string k_FeedbackHintForTrackpadController = "Click left/right side to undo/redo"; @@ -39,7 +40,7 @@ sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IAlternateMenu, IUsesMenu string m_FeedbackHintForCurrentController; readonly BindingDictionary m_Controls = new BindingDictionary(); - + public Transform rayOrigin { private get; set; } public Transform menuOrigin { get; set; } @@ -94,8 +95,6 @@ public MenuHideFlags menuHideFlags if (visible) ShowFeedback(); - else - this.ClearFeedbackRequests(); } } } @@ -106,7 +105,7 @@ void Start() m_UndoMenuUI.alternateMenuOrigin = alternateMenuOrigin; m_UndoMenuUI.actions = menuActions; this.ConnectInterfaces(m_UndoMenuUI); // Connect interfaces before performing setup on the UI - m_UndoMenuUI.Setup(); + m_UndoMenuUI.gameObject.SetActive(false); InputUtils.GetBindingDictionaryFromActionMap(m_ActionMap, m_Controls); m_TrackpadController = this.GetDeviceType() == DeviceType.Vive; m_FeedbackHintForCurrentController = m_TrackpadController @@ -154,6 +153,8 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon if (undoRedoPerformed) { consumeControl(undoMenuInput.navigateX); + if (m_StillEngagedAfterStickReleasedCoroutine != null) + StopCoroutine(m_StillEngagedAfterStickReleasedCoroutine); this.Pulse(node, m_UndoPulse); } } @@ -169,7 +170,7 @@ IEnumerator AcceptInputAfterStickReleased() void ShowFeedback() { List controls; - if (m_Controls.TryGetValue("Engage", out controls)) + if (m_Controls.TryGetValue(k_EngageControlName, out controls)) { foreach (var id in controls) { @@ -186,7 +187,7 @@ void ShowFeedback() void ShowUndoPerformedFeedback(bool undo) { List controls; - if (m_Controls.TryGetValue("Engage", out controls)) + if (m_Controls.TryGetValue(k_EngageControlName, out controls)) { foreach (var id in controls) { From 1ed807397af31393d23cc0fe2f7a8034e6a7b220 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Tue, 21 Nov 2017 19:37:51 -0500 Subject: [PATCH 28/89] Replace DateTime.Now with Time.time --- Menus/MainMenu/MainMenu.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Menus/MainMenu/MainMenu.cs b/Menus/MainMenu/MainMenu.cs index 104528e6f..c125c6b67 100644 --- a/Menus/MainMenu/MainMenu.cs +++ b/Menus/MainMenu/MainMenu.cs @@ -45,7 +45,7 @@ sealed class MainMenu : MonoBehaviour, IMainMenu, IConnectInterfaces, IInstantia float m_LastRotationInput; MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; float m_RotationInputStartValue; - DateTime m_RotationInputStartTime; + float m_RotationInputStartTime; readonly Dictionary m_ToolButtons = new Dictionary(); readonly Dictionary m_SettingsMenus = new Dictionary(); readonly Dictionary m_SettingsMenuItems = new Dictionary(); @@ -151,11 +151,12 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon { if (!Mathf.Approximately(rotationInput, 0f)) { + var time = Time.time; if (Mathf.Approximately(m_LastRotationInput, 0f)) { // Touch began m_RotationInputStartValue = rotationInput; - m_RotationInputStartTime = DateTime.Now; + m_RotationInputStartTime = time; } else { @@ -164,10 +165,10 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon var lastDistance = m_LastRotationInput - m_RotationInputStartValue; if (Mathf.Abs(distance) >= kFlickDeltaThreshold && Mathf.Abs(lastDistance) < kFlickDeltaThreshold - && (float)(DateTime.Now - m_RotationInputStartTime).TotalSeconds < k_MaxFlickDuration) + && time - m_RotationInputStartTime < k_MaxFlickDuration) { m_RotationInputStartValue = rotationInput; - m_RotationInputStartTime = DateTime.Now; + m_RotationInputStartTime = time; if (!m_MainMenuUI.rotating) { FlickMenu(distance); From 58f0959a72044722a8a6d5ce9aae9d9e3d1ad3a8 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Tue, 21 Nov 2017 20:24:46 -0500 Subject: [PATCH 29/89] Refactor UndoMenu to be an IMenu, not an IAlternateMenu --- Menus/UndoMenu/UndoMenu.cs | 6 +----- Scripts/Core/EditorVR.Menus.cs | 31 +++---------------------------- Scripts/Core/EditorVR.Tools.cs | 9 +++++---- Scripts/Core/EditorVR.cs | 2 +- 4 files changed, 10 insertions(+), 38 deletions(-) diff --git a/Menus/UndoMenu/UndoMenu.cs b/Menus/UndoMenu/UndoMenu.cs index 26acab6a0..2d52d619b 100644 --- a/Menus/UndoMenu/UndoMenu.cs +++ b/Menus/UndoMenu/UndoMenu.cs @@ -11,7 +11,7 @@ namespace UnityEditor.Experimental.EditorVR.Menus { - sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IAlternateMenu, IUsesMenuOrigins, ICustomActionMap, + sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IMenu, IUsesMenuOrigins, ICustomActionMap, IControlHaptics, IUsesNode, IConnectInterfaces, IRequestFeedback, IUsesDeviceType { const float k_UndoRedoThreshold = 0.5f; @@ -41,16 +41,12 @@ sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IAlternateMenu, IUsesMenu readonly BindingDictionary m_Controls = new BindingDictionary(); - public Transform rayOrigin { private get; set; } - public Transform menuOrigin { get; set; } public GameObject menuContent { get { return m_UndoMenuUI.gameObject; } } public Node node { get; set; } - public event Action itemWasSelected; - public Bounds localBounds { get { return default(Bounds); } } public ActionMap actionMap { get { return m_ActionMap; } } diff --git a/Scripts/Core/EditorVR.Menus.cs b/Scripts/Core/EditorVR.Menus.cs index 3fecfbde2..2473f1449 100644 --- a/Scripts/Core/EditorVR.Menus.cs +++ b/Scripts/Core/EditorVR.Menus.cs @@ -360,7 +360,7 @@ void CheckDirectSelection(DeviceData deviceData, Dictionary } } - void CheckMenuColliderOverlaps(IMenu menu, MenuHideData menuHideData) + static void CheckMenuColliderOverlaps(IMenu menu, MenuHideData menuHideData) { var menuBounds = menu.localBounds; if (menuBounds.extents == Vector3.zero) @@ -547,39 +547,14 @@ static GameObject InstantiateMenuUI(Transform rayOrigin, IMenu prefab) return go; } - internal IMainMenu SpawnMainMenu(Type type, Transform rayOrigin) + internal T SpawnMenu(Transform rayOrigin) where T : Component, IMenu { - if (!typeof(IMainMenu).IsAssignableFrom(type)) - return null; - - var mainMenu = (IMainMenu)ObjectUtils.AddComponent(type, evr.gameObject); + var mainMenu = ObjectUtils.AddComponent(evr.gameObject); this.ConnectInterfaces(mainMenu, rayOrigin); return mainMenu; } - internal IAlternateMenu SpawnAlternateMenu(Type type, Transform rayOrigin) - { - if (!typeof(IAlternateMenu).IsAssignableFrom(type)) - return null; - - var alternateMenu = (IAlternateMenu)ObjectUtils.AddComponent(type, evr.gameObject); - this.ConnectInterfaces(alternateMenu, rayOrigin); - - return alternateMenu; - } - - internal IToolsMenu SpawnToolsMenu(Type type, Transform rayOrigin) - { - if (!typeof(IToolsMenu).IsAssignableFrom(type)) - return null; - - var menu = (IToolsMenu)ObjectUtils.AddComponent(type, evr.gameObject); - this.ConnectInterfaces(menu, rayOrigin); - - return menu; - } - internal static void UpdateAlternateMenuActions() { var actionsModule = evr.GetModule(); diff --git a/Scripts/Core/EditorVR.Tools.cs b/Scripts/Core/EditorVR.Tools.cs index 4c62bbb17..4156db950 100644 --- a/Scripts/Core/EditorVR.Tools.cs +++ b/Scripts/Core/EditorVR.Tools.cs @@ -127,21 +127,22 @@ internal void SpawnDefaultTools(IProxy proxy) var menus = evr.GetNestedModule(); var menuHideData = deviceData.menuHideData; - var mainMenu = menus.SpawnMainMenu(typeof(MainMenu), rayOrigin); + var mainMenu = menus.SpawnMenu(rayOrigin); deviceData.mainMenu = mainMenu; menuHideData[mainMenu] = new Menus.MenuHideData(); - var alternateMenu = menus.SpawnAlternateMenu(typeof(RadialMenu), rayOrigin); + var alternateMenu = menus.SpawnMenu(rayOrigin); deviceData.alternateMenu = alternateMenu; menuHideData[alternateMenu] = new Menus.MenuHideData(); alternateMenu.itemWasSelected += Menus.UpdateAlternateMenuOnSelectionChanged; - var undoMenu = menus.SpawnAlternateMenu(typeof(UndoMenu), rayOrigin); + var undoMenu = menus.SpawnMenu(rayOrigin); deviceData.undoMenu = undoMenu; menuHideData[undoMenu] = new Menus.MenuHideData(); // Setup ToolsMenu - var toolsMenu = menus.SpawnToolsMenu(typeof(Experimental.EditorVR.Menus.ToolsMenu), rayOrigin); + var toolsMenu = ObjectUtils.AddComponent(evr.gameObject); + this.ConnectInterfaces(toolsMenu, rayOrigin); deviceData.toolsMenu = toolsMenu; toolsMenu.rayOrigin = rayOrigin; toolsMenu.setButtonForType(typeof(IMainMenu), null); diff --git a/Scripts/Core/EditorVR.cs b/Scripts/Core/EditorVR.cs index db10d30c3..56a35f6cf 100644 --- a/Scripts/Core/EditorVR.cs +++ b/Scripts/Core/EditorVR.cs @@ -72,7 +72,7 @@ class DeviceData public readonly Stack toolData = new Stack(); public IMainMenu mainMenu; public IAlternateMenu alternateMenu; - public IAlternateMenu undoMenu; + public IMenu undoMenu; public ITool currentTool; public IMenu customMenu; public IToolsMenu toolsMenu; From 71ea2f43f7e38728fe04e2ffdaa2376a0109e5bc Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Tue, 21 Nov 2017 20:39:57 -0500 Subject: [PATCH 30/89] Fix bug in TooltipModule where existing tooltips with new text would not get updated --- .../Modules/TooltipModule/TooltipModule.cs | 37 +++++++++++-------- Scripts/Modules/TooltipModule/TooltipUI.cs | 5 ++- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/Scripts/Modules/TooltipModule/TooltipModule.cs b/Scripts/Modules/TooltipModule/TooltipModule.cs index 2b1046cb6..4f59a8377 100644 --- a/Scripts/Modules/TooltipModule/TooltipModule.cs +++ b/Scripts/Modules/TooltipModule/TooltipModule.cs @@ -268,23 +268,30 @@ public void ShowTooltip(ITooltip tooltip, bool persistent = false, float duratio data.persistent |= persistent; data.placement = placement ?? tooltip as ITooltipPlacement; - var newTarget = data.GetTooltipTarget(tooltip); - if (currentTarget != newTarget) + // Set the text to new text + var tooltipUI = data.tooltipUI; + if (tooltipUI) { - // Get the different between the 'old' tooltip position and 'new' tooltip position, even taking alignment into account - var transitionLerp = 1.0f - Mathf.Clamp01((Time.time - data.transitionTime) / k_ChangeTransitionDuration); - var currentPosition = currentTarget.TransformPoint(GetTooltipOffset(data.tooltipUI, currentPlacement, data.transitionOffset * transitionLerp)); - var newPosition = newTarget.TransformPoint(GetTooltipOffset(data.tooltipUI, data.placement, Vector3.zero)); - - // Store it as an additional offset that we'll quickly lerp from - data.transitionOffset = newTarget.InverseTransformVector(currentPosition - newPosition); - data.transitionTime = Time.time; - } + tooltipUI.Show(tooltip.tooltipText, data.placement.tooltipAlignment); - if (duration > 0) - { - data.duration = duration; - data.lastModifiedTime = Time.time; + var newTarget = data.GetTooltipTarget(tooltip); + if (currentTarget != newTarget) + { + // Get the different between the 'old' tooltip position and 'new' tooltip position, even taking alignment into account + var transitionLerp = 1.0f - Mathf.Clamp01((Time.time - data.transitionTime) / k_ChangeTransitionDuration); + var currentPosition = currentTarget.TransformPoint(GetTooltipOffset(tooltipUI, currentPlacement, data.transitionOffset * transitionLerp)); + var newPosition = newTarget.TransformPoint(GetTooltipOffset(tooltipUI, data.placement, Vector3.zero)); + + // Store it as an additional offset that we'll quickly lerp from + data.transitionOffset = newTarget.InverseTransformVector(currentPosition - newPosition); + data.transitionTime = Time.time; + } + + if (duration > 0) + { + data.duration = duration; + data.lastModifiedTime = Time.time; + } } return; diff --git a/Scripts/Modules/TooltipModule/TooltipUI.cs b/Scripts/Modules/TooltipModule/TooltipUI.cs index 2f72495b3..8020b0d7b 100644 --- a/Scripts/Modules/TooltipModule/TooltipUI.cs +++ b/Scripts/Modules/TooltipModule/TooltipUI.cs @@ -1,4 +1,4 @@ -#if UNITY_EDITOR +#if UNITY_EDITOR using System; using UnityEditor.Experimental.EditorVR; using UnityEngine; @@ -28,6 +28,7 @@ sealed class TooltipUI : MonoBehaviour, IWillRender [SerializeField] Image m_Icon; + #if INCLUDE_TEXT_MESH_PRO [SerializeField] TMP_Text m_TextLeft; @@ -76,10 +77,10 @@ public void Show(string text, TextAlignment alignment, Sprite iconSprite = null) { // if Icon null, fade out opacity of current icon // if icon is not null, fade out current, fade in new icon - var validText = !string.IsNullOrEmpty(text); var iconVisible = iconSprite != null; m_Icon.sprite = iconSprite; m_Icon.enabled = iconVisible; + var validText = !string.IsNullOrEmpty(text); switch (alignment) { case TextAlignment.Center: From 08236e209a08bae35320730b8c4bcb3a941aaf89 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Tue, 21 Nov 2017 20:43:51 -0500 Subject: [PATCH 31/89] Remove unused Actions code from UndoMenu and UndoMenuUI --- Menus/UndoMenu/Scripts/UndoMenuUI.cs | 19 ------------------- Menus/UndoMenu/UndoMenu.cs | 13 ------------- 2 files changed, 32 deletions(-) diff --git a/Menus/UndoMenu/Scripts/UndoMenuUI.cs b/Menus/UndoMenu/Scripts/UndoMenuUI.cs index 1da832d6e..2369bb8a6 100644 --- a/Menus/UndoMenu/Scripts/UndoMenuUI.cs +++ b/Menus/UndoMenu/Scripts/UndoMenuUI.cs @@ -76,25 +76,6 @@ public bool visible bool m_Visible; - public List actions - { - get { return m_Actions; } - set - { - if (value != null) - { - m_Actions = value - .Where(a => a.sectionName != null && a.sectionName == ActionMenuItemAttribute.DefaultActionSectionName) - .OrderBy(a => a.priority) - .ToList(); - } - else if (visible) - visible = false; - } - } - - List m_Actions; - void Awake() { m_UndoButtonMaterial = MaterialUtils.GetMaterialClone(m_UndoButtonMeshRenderer); diff --git a/Menus/UndoMenu/UndoMenu.cs b/Menus/UndoMenu/UndoMenu.cs index 2d52d619b..8a5838d2a 100644 --- a/Menus/UndoMenu/UndoMenu.cs +++ b/Menus/UndoMenu/UndoMenu.cs @@ -52,18 +52,6 @@ sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IMenu, IUsesMenuOrigins, public ActionMap actionMap { get { return m_ActionMap; } } public bool ignoreLocking { get { return false; } } - public List menuActions - { - get { return m_MenuActions; } - set - { - m_MenuActions = value; - - if (m_UndoMenuUI) - m_UndoMenuUI.actions = value; - } - } - public Transform alternateMenuOrigin { get { return m_AlternateMenuOrigin; } @@ -99,7 +87,6 @@ void Start() { m_UndoMenuUI = this.InstantiateUI(m_UndoMenuPrefab.gameObject).GetComponent(); m_UndoMenuUI.alternateMenuOrigin = alternateMenuOrigin; - m_UndoMenuUI.actions = menuActions; this.ConnectInterfaces(m_UndoMenuUI); // Connect interfaces before performing setup on the UI m_UndoMenuUI.gameObject.SetActive(false); InputUtils.GetBindingDictionaryFromActionMap(m_ActionMap, m_Controls); From 1c332147893429e265b20e30e32a6c8cc8a0a326 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Tue, 21 Nov 2017 20:47:47 -0500 Subject: [PATCH 32/89] Use this.StopCoroutine instead of regular StopCoroutine in UndoMenu --- Menus/UndoMenu/UndoMenu.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Menus/UndoMenu/UndoMenu.cs b/Menus/UndoMenu/UndoMenu.cs index 8a5838d2a..e2ecc7023 100644 --- a/Menus/UndoMenu/UndoMenu.cs +++ b/Menus/UndoMenu/UndoMenu.cs @@ -136,8 +136,7 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon if (undoRedoPerformed) { consumeControl(undoMenuInput.navigateX); - if (m_StillEngagedAfterStickReleasedCoroutine != null) - StopCoroutine(m_StillEngagedAfterStickReleasedCoroutine); + this.StopCoroutine(ref m_StillEngagedAfterStickReleasedCoroutine); this.Pulse(node, m_UndoPulse); } } From 0cf9279056fc13ea325902bbae20685d1b44a71f Mon Sep 17 00:00:00 2001 From: Dylan Urquidi Date: Sun, 26 Nov 2017 17:45:41 -0800 Subject: [PATCH 33/89] Implement scene MainCamera settings copying for EXR VRView camera (if a scene MainCamera exists). --- .../Core/Contexts/EditingContextManager.cs | 71 +++++++++++-------- Scripts/Core/Contexts/EditorVR.asset | 2 + Scripts/Core/Contexts/EditorVRContext.cs | 25 +++++-- Scripts/Core/VRView.cs | 40 +++++++++-- Scripts/Interfaces/Entity/IEditingContext.cs | 7 ++ Scripts/Utilities/ObjectUtils.cs | 28 ++++++++ .../Unit/Core/EditingContextManagerTests.cs | 4 +- 7 files changed, 136 insertions(+), 41 deletions(-) diff --git a/Scripts/Core/Contexts/EditingContextManager.cs b/Scripts/Core/Contexts/EditingContextManager.cs index eb48bbd82..0a2fd1e50 100644 --- a/Scripts/Core/Contexts/EditingContextManager.cs +++ b/Scripts/Core/Contexts/EditingContextManager.cs @@ -24,26 +24,26 @@ sealed class EditingContextManager : MonoBehaviour internal static EditingContextManager s_Instance; static InputManager s_InputManager; + static List s_AvailableContexts; + static EditingContextManagerSettings s_Settings; + static UnityObject s_DefaultContext; + static IEditingContext s_CurrentContext; - EditingContextManagerSettings m_Settings; - - List m_AvailableContexts; string[] m_ContextNames; int m_SelectedContextIndex; - IEditingContext m_CurrentContext; readonly List m_PreviousContexts = new List(); - internal IEditingContext defaultContext + internal static IEditingContext defaultContext { get { - var context = m_AvailableContexts.Find(c => c.Equals(m_DefaultContext)) ?? m_AvailableContexts.First(); + var context = s_AvailableContexts.Find(c => c.Equals(s_DefaultContext)) ?? s_AvailableContexts.First(); - var defaultContextName = m_Settings.defaultContextName; + var defaultContextName = s_Settings.defaultContextName; if (!string.IsNullOrEmpty(defaultContextName)) { - var foundContext = m_AvailableContexts.Find(c => c.name == defaultContextName); + var foundContext = s_AvailableContexts.Find(c => c.name == defaultContextName); if (foundContext != null) context = foundContext; } @@ -52,19 +52,20 @@ internal IEditingContext defaultContext } set { - m_Settings.defaultContextName = value.name; + s_Settings.defaultContextName = value.name; } } internal IEditingContext currentContext { - get { return m_CurrentContext; } + get { return s_CurrentContext; } } static EditingContextManager() { VRView.viewEnabled += OnVRViewEnabled; VRView.viewDisabled += OnVRViewDisabled; + VRView.cameraSetupStarted += OnCameraSetupStarted; EditorApplication.update += ReopenOnExitPlaymode; } @@ -81,6 +82,15 @@ static void OnVRViewDisabled() ObjectUtils.Destroy(s_InputManager.gameObject); } + public static ContextSettings OnCameraSetupStarted() + { + ContextSettings settings = new ContextSettings(); + if (s_CurrentContext != null) + settings = s_CurrentContext != null ? s_CurrentContext.contextSettings : defaultContext.contextSettings; + + return settings; + } + [MenuItem("Window/EditorXR %e", false)] internal static void ShowEditorVR() { @@ -129,9 +139,14 @@ static void OnPlayModeStateChanged(PlayModeStateChange stateChange) } } + void Awake() + { + s_DefaultContext = m_DefaultContext; + } + void OnEnable() { - m_Settings = LoadUserSettings(); + s_Settings = LoadUserSettings(); ISetEditingContextMethods.getAvailableEditingContexts = GetAvailableEditingContexts; ISetEditingContextMethods.getPreviousEditingContexts = GetPreviousEditingContexts; @@ -141,12 +156,12 @@ void OnEnable() var availableContexts = GetAvailableEditingContexts(); m_ContextNames = availableContexts.Select(c => c.name).ToArray(); - if (m_AvailableContexts.Count == 0) + if (s_AvailableContexts.Count == 0) throw new Exception("You can't start EditorXR without at least one context. Try re-importing the package or use version control to restore the default context asset"); SetEditingContext(defaultContext); - if (m_AvailableContexts.Count > 1) + if (s_AvailableContexts.Count > 1) VRView.afterOnGUI += OnVRViewGUI; // Force the window to repaint every tick, since we need live updating @@ -164,20 +179,20 @@ void OnDisable() VRView.afterOnGUI -= OnVRViewGUI; - if (m_CurrentContext != null) + if (s_CurrentContext != null) { - defaultContext = m_CurrentContext; - m_CurrentContext.Dispose(); + defaultContext = s_CurrentContext; + s_CurrentContext.Dispose(); } - m_AvailableContexts = null; + s_AvailableContexts = null; ISetEditingContextMethods.getAvailableEditingContexts = null; ISetEditingContextMethods.getPreviousEditingContexts = null; ISetEditingContextMethods.setEditingContext = null; ISetEditingContextMethods.restorePreviousEditingContext = null; - SaveUserSettings(m_Settings); + SaveUserSettings(s_Settings); } #endif @@ -189,7 +204,7 @@ void OnVRViewGUI(EditorWindow window) GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal(); { - DoGUI(m_ContextNames, ref m_SelectedContextIndex, () => SetEditingContext(m_AvailableContexts[m_SelectedContextIndex])); + DoGUI(m_ContextNames, ref m_SelectedContextIndex, () => SetEditingContext(s_AvailableContexts[m_SelectedContextIndex])); GUILayout.FlexibleSpace(); } GUILayout.EndHorizontal(); @@ -213,16 +228,16 @@ internal void SetEditingContext(IEditingContext context) if (context == null) return; - if (m_CurrentContext != null) + if (s_CurrentContext != null) { - m_PreviousContexts.Insert(0, m_CurrentContext); - m_CurrentContext.Dispose(); + m_PreviousContexts.Insert(0, s_CurrentContext); + s_CurrentContext.Dispose(); } context.Setup(); - m_CurrentContext = context; + s_CurrentContext = context; - m_SelectedContextIndex = m_AvailableContexts.IndexOf(context); + m_SelectedContextIndex = s_AvailableContexts.IndexOf(context); } internal void RestorePreviousContext() @@ -254,12 +269,12 @@ internal static string[] GetEditingContextNames() return availableContexts.Select(c => c.name).ToArray(); } - List GetAvailableEditingContexts() + static List GetAvailableEditingContexts() { - if (m_AvailableContexts == null) - m_AvailableContexts = GetEditingContextAssets(); + if (s_AvailableContexts == null) + s_AvailableContexts = GetEditingContextAssets(); - return m_AvailableContexts; + return s_AvailableContexts; } List GetPreviousEditingContexts() diff --git a/Scripts/Core/Contexts/EditorVR.asset b/Scripts/Core/Contexts/EditorVR.asset index 92e9d3f27..05fd7141c 100644 --- a/Scripts/Core/Contexts/EditorVR.asset +++ b/Scripts/Core/Contexts/EditorVR.asset @@ -11,6 +11,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 0bcb87ab5055bd3498c8b75ba8ccde1c, type: 3} m_Name: EditorVR m_EditorClassIdentifier: + m_RenderScale: 1 + m_CopySceneCameraSettings: 1 m_DefaultToolStack: - {fileID: 11500000, guid: 882053426a5f76d46b5505d9a20be912, type: 3} - {fileID: 11500000, guid: aab8fcc587f237c4cb48fb7bc8a59909, type: 3} diff --git a/Scripts/Core/Contexts/EditorVRContext.cs b/Scripts/Core/Contexts/EditorVRContext.cs index ca62916e0..50c9f96f1 100644 --- a/Scripts/Core/Contexts/EditorVRContext.cs +++ b/Scripts/Core/Contexts/EditorVRContext.cs @@ -7,30 +7,47 @@ namespace UnityEditor.Experimental.EditorVR.Core { + public struct ContextSettings + { + public bool copySceneCameraSettings; + + public ContextSettings(bool copySceneCameraSettings) + { + this.copySceneCameraSettings = copySceneCameraSettings; + } + } + [CreateAssetMenu(menuName = "EditorVR/EditorVR Context")] class EditorVRContext : ScriptableObject, IEditingContext { [SerializeField] float m_RenderScale = 1f; + [SerializeField] + bool m_CopySceneCameraSettings = true; + [SerializeField] internal List m_DefaultToolStack; EditorVR m_Instance; + public ContextSettings contextSettings { get { return new ContextSettings(m_CopySceneCameraSettings); } } + public void Setup() { EditorVR.defaultTools = m_DefaultToolStack.Select(ms => ms.GetClass()).ToArray(); m_Instance = ObjectUtils.CreateGameObjectWithComponent(); - XRSettings.eyeTextureResolutionScale = m_RenderScale; } public void Dispose() { - m_Instance.Shutdown(); // Give a chance for dependent systems (e.g. serialization) to shut-down before destroying - ObjectUtils.Destroy(m_Instance.gameObject); - m_Instance = null; + if (m_Instance) + { + m_Instance.Shutdown(); // Give a chance for dependent systems (e.g. serialization) to shut-down before destroying + ObjectUtils.Destroy(m_Instance.gameObject); + m_Instance = null; + } } } } diff --git a/Scripts/Core/VRView.cs b/Scripts/Core/VRView.cs index 3c8c2bc1f..ad539ea65 100644 --- a/Scripts/Core/VRView.cs +++ b/Scripts/Core/VRView.cs @@ -1,10 +1,11 @@ #if UNITY_EDITOR using System; -using UnityEngine; -using UnityEngine.Assertions; using System.Collections; -using UnityEditor.Experimental.EditorVR.Helpers; using System.Reflection; +using UnityEditor.Experimental.EditorVR.Helpers; +using UnityEditor.Experimental.EditorVR.Utilities; +using UnityEngine; +using UnityEngine.Assertions; using UnityEngine.XR; #if ENABLE_STEAMVR_INPUT @@ -18,6 +19,10 @@ sealed class VRView : EditorWindow public const float HeadHeight = 1.7f; const string k_ShowDeviceView = "VRView.ShowDeviceView"; const string k_UseCustomPreviewCamera = "VRView.UseCustomPreviewCamera"; + const string k_CameraName = "VRCamera"; + + static Camera s_ExistingSceneMainCamera; + static bool s_ExistingSceneMainCameraEnabledState; DrawCameraMode m_RenderMode = DrawCameraMode.Textured; @@ -114,6 +119,7 @@ public static Vector3 headCenteredOrigin public static event Action beforeOnGUI; public static event Action afterOnGUI; public static event Action hmdStatusChange; + public static event Func cameraSetupStarted; public Rect guiRect { get; private set; } @@ -135,12 +141,29 @@ public void OnEnable() autoRepaintOnSceneChange = true; s_ActiveView = this; - GameObject cameraGO = EditorUtility.CreateGameObjectWithHideFlags("VRCamera", HideFlags.HideAndDontSave, typeof(Camera)); - m_Camera = cameraGO.GetComponent(); - m_Camera.useOcclusionCulling = false; + ContextSettings contextSettings = new ContextSettings(); + if (cameraSetupStarted != null) + contextSettings = cameraSetupStarted(); + + s_ExistingSceneMainCamera = Camera.main; + if (contextSettings.copySceneCameraSettings && s_ExistingSceneMainCamera && s_ExistingSceneMainCamera.enabled) + { + s_ExistingSceneMainCameraEnabledState = true; + GameObject cameraGO = EditorUtility.CreateGameObjectWithHideFlags(k_CameraName, HideFlags.HideAndDontSave); + m_Camera = ObjectUtils.CopyComponent(s_ExistingSceneMainCamera, cameraGO); + } + else + { + GameObject cameraGO = EditorUtility.CreateGameObjectWithHideFlags(k_CameraName, HideFlags.HideAndDontSave, typeof(Camera)); + m_Camera = cameraGO.GetComponent(); + } + + if (s_ExistingSceneMainCamera) + s_ExistingSceneMainCamera.enabled = false; // Disable existing MainCamera in the scene + m_Camera.enabled = false; m_Camera.cameraType = CameraType.VR; - + m_Camera.useOcclusionCulling = false; GameObject rigGO = EditorUtility.CreateGameObjectWithHideFlags("VRCameraRig", HideFlags.HideAndDontSave, typeof(EditorMonoBehaviour)); m_CameraRig = rigGO.transform; m_Camera.transform.parent = m_CameraRig; @@ -186,6 +209,9 @@ public void OnDisable() Assert.IsNotNull(s_ActiveView, "EditorXR should have an active view"); s_ActiveView = null; + + if (s_ExistingSceneMainCamera) + s_ExistingSceneMainCamera.enabled = s_ExistingSceneMainCameraEnabledState; } void UpdateCameraTransform() diff --git a/Scripts/Interfaces/Entity/IEditingContext.cs b/Scripts/Interfaces/Entity/IEditingContext.cs index c95aeb6f4..7d6f2db3a 100644 --- a/Scripts/Interfaces/Entity/IEditingContext.cs +++ b/Scripts/Interfaces/Entity/IEditingContext.cs @@ -1,4 +1,6 @@ #if UNITY_EDITOR +using UnityEditor.Experimental.EditorVR.Core; + namespace UnityEditor.Experimental.EditorVR { /// @@ -12,6 +14,11 @@ public interface IEditingContext /// string name { get; } + /// + /// Settings denoting that the scene camera's (component_ values should be cloned on the XR runtime camera + /// + ContextSettings contextSettings { get; } + /// /// Perform one-time setup for the context when pushed to the stack. /// diff --git a/Scripts/Utilities/ObjectUtils.cs b/Scripts/Utilities/ObjectUtils.cs index fcc568e32..9132e6da5 100644 --- a/Scripts/Utilities/ObjectUtils.cs +++ b/Scripts/Utilities/ObjectUtils.cs @@ -196,6 +196,34 @@ public static Component AddComponent(Type type, GameObject go) return component; } + public static T CopyComponent(T sourceComponent, GameObject targetGameObject) where T : Component + { + Type sourceType = sourceComponent.GetType(); + var targetComponent = targetGameObject.GetComponent(sourceType) as T; + if (!targetComponent) + targetComponent = targetGameObject.AddComponent(sourceType) as T; + + var fields = sourceType.GetFields(); + foreach (var field in fields) + { + if (field.IsStatic) + continue; + + field.SetValue(targetComponent, field.GetValue(sourceComponent)); + } + + var properties = sourceType.GetProperties(); + foreach (var property in properties) + { + if (!property.CanWrite || property.Name == "name") + continue; + + property.SetValue(targetComponent, property.GetValue(sourceComponent, null), null); + } + + return (T)targetComponent; + } + static IEnumerable GetAssignableTypes(Type type, Func predicate = null) { var list = new List(); diff --git a/Tests/Editor/Unit/Core/EditingContextManagerTests.cs b/Tests/Editor/Unit/Core/EditingContextManagerTests.cs index 777e55065..77708070a 100644 --- a/Tests/Editor/Unit/Core/EditingContextManagerTests.cs +++ b/Tests/Editor/Unit/Core/EditingContextManagerTests.cs @@ -46,7 +46,7 @@ public void Setup() [Test] public void Initializes_WithDefaultContext() { - Assert.AreEqual(manager.defaultContext, manager.currentContext); + Assert.AreEqual(EditingContextManager.defaultContext, manager.currentContext); } [Test] @@ -159,7 +159,7 @@ public void SaveUserSettings_UpdatesUserSettingsFile() public void Cleanup() { ObjectUtils.Destroy(go); - manager.SetEditingContext(manager.defaultContext); + manager.SetEditingContext(EditingContextManager.defaultContext); ObjectUtils.Destroy(context); ObjectUtils.Destroy(context2); } From c5e1cf9fcca7057ecee0e78a10061d7f8e6327ad Mon Sep 17 00:00:00 2001 From: Dylan Urquidi Date: Mon, 27 Nov 2017 11:16:52 -0800 Subject: [PATCH 34/89] Cache the enabled state of the existing scene main camera in VRView; used for latter re-setting in OnDisable --- Scripts/Core/VRView.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Scripts/Core/VRView.cs b/Scripts/Core/VRView.cs index ad539ea65..989951b4c 100644 --- a/Scripts/Core/VRView.cs +++ b/Scripts/Core/VRView.cs @@ -159,7 +159,10 @@ public void OnEnable() } if (s_ExistingSceneMainCamera) + { + s_ExistingSceneMainCameraEnabledState = s_ExistingSceneMainCamera.enabled; s_ExistingSceneMainCamera.enabled = false; // Disable existing MainCamera in the scene + } m_Camera.enabled = false; m_Camera.cameraType = CameraType.VR; From 9d56e4fd74bb5b510bb917eb0b3c4e375d42b907 Mon Sep 17 00:00:00 2001 From: Dylan Urquidi Date: Mon, 27 Nov 2017 11:17:51 -0800 Subject: [PATCH 35/89] Return the current context, if one exists, in EditingContextManager's OnCameraSetupStarted() --- Scripts/Core/Contexts/EditingContextManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/Core/Contexts/EditingContextManager.cs b/Scripts/Core/Contexts/EditingContextManager.cs index 0a2fd1e50..fb50819d8 100644 --- a/Scripts/Core/Contexts/EditingContextManager.cs +++ b/Scripts/Core/Contexts/EditingContextManager.cs @@ -86,7 +86,7 @@ public static ContextSettings OnCameraSetupStarted() { ContextSettings settings = new ContextSettings(); if (s_CurrentContext != null) - settings = s_CurrentContext != null ? s_CurrentContext.contextSettings : defaultContext.contextSettings; + settings = s_CurrentContext.contextSettings; return settings; } From 87e37817389c9708ba3f858f93ddea5a687d7837 Mon Sep 17 00:00:00 2001 From: Dylan Urquidi Date: Mon, 27 Nov 2017 11:22:59 -0800 Subject: [PATCH 36/89] Fix unnecessary setting of existing camera enabled state in VRView --- Scripts/Core/VRView.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Scripts/Core/VRView.cs b/Scripts/Core/VRView.cs index 989951b4c..9cf5aec3b 100644 --- a/Scripts/Core/VRView.cs +++ b/Scripts/Core/VRView.cs @@ -148,7 +148,6 @@ public void OnEnable() s_ExistingSceneMainCamera = Camera.main; if (contextSettings.copySceneCameraSettings && s_ExistingSceneMainCamera && s_ExistingSceneMainCamera.enabled) { - s_ExistingSceneMainCameraEnabledState = true; GameObject cameraGO = EditorUtility.CreateGameObjectWithHideFlags(k_CameraName, HideFlags.HideAndDontSave); m_Camera = ObjectUtils.CopyComponent(s_ExistingSceneMainCamera, cameraGO); } From 86804d977e8b68df50be8784acdaeda116edbdf0 Mon Sep 17 00:00:00 2001 From: Dylan Urquidi Date: Tue, 28 Nov 2017 17:37:53 -0800 Subject: [PATCH 37/89] Remove ContextSettings struct from IEditingContext & EditorVRContext; include copySceneCameraSettings property in IEditingContext; this is used in VRView OnEnable() when setting up the VRView camera --- Scripts/Core/Contexts/EditingContextManager.cs | 8 ++------ Scripts/Core/Contexts/EditorVRContext.cs | 12 +----------- Scripts/Core/VRView.cs | 9 +++------ Scripts/Interfaces/Entity/IEditingContext.cs | 4 ++-- 4 files changed, 8 insertions(+), 25 deletions(-) diff --git a/Scripts/Core/Contexts/EditingContextManager.cs b/Scripts/Core/Contexts/EditingContextManager.cs index fb50819d8..7c18c8acf 100644 --- a/Scripts/Core/Contexts/EditingContextManager.cs +++ b/Scripts/Core/Contexts/EditingContextManager.cs @@ -82,13 +82,9 @@ static void OnVRViewDisabled() ObjectUtils.Destroy(s_InputManager.gameObject); } - public static ContextSettings OnCameraSetupStarted() + public static IEditingContext OnCameraSetupStarted() { - ContextSettings settings = new ContextSettings(); - if (s_CurrentContext != null) - settings = s_CurrentContext.contextSettings; - - return settings; + return s_CurrentContext; } [MenuItem("Window/EditorXR %e", false)] diff --git a/Scripts/Core/Contexts/EditorVRContext.cs b/Scripts/Core/Contexts/EditorVRContext.cs index 50c9f96f1..a055ef758 100644 --- a/Scripts/Core/Contexts/EditorVRContext.cs +++ b/Scripts/Core/Contexts/EditorVRContext.cs @@ -7,16 +7,6 @@ namespace UnityEditor.Experimental.EditorVR.Core { - public struct ContextSettings - { - public bool copySceneCameraSettings; - - public ContextSettings(bool copySceneCameraSettings) - { - this.copySceneCameraSettings = copySceneCameraSettings; - } - } - [CreateAssetMenu(menuName = "EditorVR/EditorVR Context")] class EditorVRContext : ScriptableObject, IEditingContext { @@ -31,7 +21,7 @@ class EditorVRContext : ScriptableObject, IEditingContext EditorVR m_Instance; - public ContextSettings contextSettings { get { return new ContextSettings(m_CopySceneCameraSettings); } } + public bool copySceneCameraSettings { get { return m_CopySceneCameraSettings; } } public void Setup() { diff --git a/Scripts/Core/VRView.cs b/Scripts/Core/VRView.cs index 9cf5aec3b..6bcdcb41e 100644 --- a/Scripts/Core/VRView.cs +++ b/Scripts/Core/VRView.cs @@ -119,7 +119,7 @@ public static Vector3 headCenteredOrigin public static event Action beforeOnGUI; public static event Action afterOnGUI; public static event Action hmdStatusChange; - public static event Func cameraSetupStarted; + public static event Func cameraSetupStarted; public Rect guiRect { get; private set; } @@ -141,12 +141,9 @@ public void OnEnable() autoRepaintOnSceneChange = true; s_ActiveView = this; - ContextSettings contextSettings = new ContextSettings(); - if (cameraSetupStarted != null) - contextSettings = cameraSetupStarted(); - + var currentEditingContext = cameraSetupStarted != null ? cameraSetupStarted() : null; s_ExistingSceneMainCamera = Camera.main; - if (contextSettings.copySceneCameraSettings && s_ExistingSceneMainCamera && s_ExistingSceneMainCamera.enabled) + if (currentEditingContext != null && currentEditingContext.copySceneCameraSettings && s_ExistingSceneMainCamera && s_ExistingSceneMainCamera.enabled) { GameObject cameraGO = EditorUtility.CreateGameObjectWithHideFlags(k_CameraName, HideFlags.HideAndDontSave); m_Camera = ObjectUtils.CopyComponent(s_ExistingSceneMainCamera, cameraGO); diff --git a/Scripts/Interfaces/Entity/IEditingContext.cs b/Scripts/Interfaces/Entity/IEditingContext.cs index 7d6f2db3a..fc2ca8f03 100644 --- a/Scripts/Interfaces/Entity/IEditingContext.cs +++ b/Scripts/Interfaces/Entity/IEditingContext.cs @@ -15,9 +15,9 @@ public interface IEditingContext string name { get; } /// - /// Settings denoting that the scene camera's (component_ values should be cloned on the XR runtime camera + /// Bool denotes that the scene camera's (component) values should be cloned on the XR runtime camera /// - ContextSettings contextSettings { get; } + bool copySceneCameraSettings { get; } /// /// Perform one-time setup for the context when pushed to the stack. From d8de3e74f5969ce489f5e93c508abf490f0b35e7 Mon Sep 17 00:00:00 2001 From: Dylan Urquidi Date: Thu, 30 Nov 2017 15:03:25 -0800 Subject: [PATCH 38/89] Prevent camera from performing a very fast (shortest path) rotational correction when being enabled --- Scripts/Helpers/VRSmoothCamera.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Scripts/Helpers/VRSmoothCamera.cs b/Scripts/Helpers/VRSmoothCamera.cs index b3d05d7b0..5125eefb7 100644 --- a/Scripts/Helpers/VRSmoothCamera.cs +++ b/Scripts/Helpers/VRSmoothCamera.cs @@ -79,6 +79,13 @@ void Start() m_Rotation = transform.localRotation; } + void OnEnable() + { + // Prevent camera from performing a very fast (shortest path) rotational correction when being enabled + if (m_VRCamera) + m_Rotation = m_VRCamera.transform.localRotation; + } + void LateUpdate() { m_SmoothCamera.CopyFrom(m_VRCamera); // This copies the transform as well From dcd822ab8262d3e3aad1ad4525b09dadc19509a5 Mon Sep 17 00:00:00 2001 From: Dylan Urquidi Date: Thu, 30 Nov 2017 16:02:01 -0800 Subject: [PATCH 39/89] Revive new default/static context fetching functionality in EditingContextManager post-dev-merge --- .../Core/Contexts/EditingContextManager.cs | 69 +++++++++++-------- .../Unit/Core/EditingContextManagerTests.cs | 6 +- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/Scripts/Core/Contexts/EditingContextManager.cs b/Scripts/Core/Contexts/EditingContextManager.cs index 371bdecd9..7c18c8acf 100644 --- a/Scripts/Core/Contexts/EditingContextManager.cs +++ b/Scripts/Core/Contexts/EditingContextManager.cs @@ -24,26 +24,26 @@ sealed class EditingContextManager : MonoBehaviour internal static EditingContextManager s_Instance; static InputManager s_InputManager; + static List s_AvailableContexts; + static EditingContextManagerSettings s_Settings; + static UnityObject s_DefaultContext; + static IEditingContext s_CurrentContext; - EditingContextManagerSettings m_Settings = null; - - List m_AvailableContexts; - string[] m_ContextNames = null; + string[] m_ContextNames; int m_SelectedContextIndex; - IEditingContext m_CurrentContext; readonly List m_PreviousContexts = new List(); - internal IEditingContext defaultContext + internal static IEditingContext defaultContext { get { - var context = m_AvailableContexts.Find(c => c.Equals(m_DefaultContext)) ?? m_AvailableContexts.First(); + var context = s_AvailableContexts.Find(c => c.Equals(s_DefaultContext)) ?? s_AvailableContexts.First(); - var defaultContextName = m_Settings.defaultContextName; + var defaultContextName = s_Settings.defaultContextName; if (!string.IsNullOrEmpty(defaultContextName)) { - var foundContext = m_AvailableContexts.Find(c => c.name == defaultContextName); + var foundContext = s_AvailableContexts.Find(c => c.name == defaultContextName); if (foundContext != null) context = foundContext; } @@ -52,19 +52,20 @@ internal IEditingContext defaultContext } set { - m_Settings.defaultContextName = value.name; + s_Settings.defaultContextName = value.name; } } internal IEditingContext currentContext { - get { return m_CurrentContext; } + get { return s_CurrentContext; } } static EditingContextManager() { VRView.viewEnabled += OnVRViewEnabled; VRView.viewDisabled += OnVRViewDisabled; + VRView.cameraSetupStarted += OnCameraSetupStarted; EditorApplication.update += ReopenOnExitPlaymode; } @@ -81,6 +82,11 @@ static void OnVRViewDisabled() ObjectUtils.Destroy(s_InputManager.gameObject); } + public static IEditingContext OnCameraSetupStarted() + { + return s_CurrentContext; + } + [MenuItem("Window/EditorXR %e", false)] internal static void ShowEditorVR() { @@ -129,9 +135,14 @@ static void OnPlayModeStateChanged(PlayModeStateChange stateChange) } } + void Awake() + { + s_DefaultContext = m_DefaultContext; + } + void OnEnable() { - m_Settings = LoadUserSettings(); + s_Settings = LoadUserSettings(); ISetEditingContextMethods.getAvailableEditingContexts = GetAvailableEditingContexts; ISetEditingContextMethods.getPreviousEditingContexts = GetPreviousEditingContexts; @@ -141,12 +152,12 @@ void OnEnable() var availableContexts = GetAvailableEditingContexts(); m_ContextNames = availableContexts.Select(c => c.name).ToArray(); - if (m_AvailableContexts.Count == 0) + if (s_AvailableContexts.Count == 0) throw new Exception("You can't start EditorXR without at least one context. Try re-importing the package or use version control to restore the default context asset"); SetEditingContext(defaultContext); - if (m_AvailableContexts.Count > 1) + if (s_AvailableContexts.Count > 1) VRView.afterOnGUI += OnVRViewGUI; // Force the window to repaint every tick, since we need live updating @@ -164,20 +175,20 @@ void OnDisable() VRView.afterOnGUI -= OnVRViewGUI; - if (m_CurrentContext != null) + if (s_CurrentContext != null) { - defaultContext = m_CurrentContext; - m_CurrentContext.Dispose(); + defaultContext = s_CurrentContext; + s_CurrentContext.Dispose(); } - m_AvailableContexts = null; + s_AvailableContexts = null; ISetEditingContextMethods.getAvailableEditingContexts = null; ISetEditingContextMethods.getPreviousEditingContexts = null; ISetEditingContextMethods.setEditingContext = null; ISetEditingContextMethods.restorePreviousEditingContext = null; - SaveUserSettings(m_Settings); + SaveUserSettings(s_Settings); } #endif @@ -189,7 +200,7 @@ void OnVRViewGUI(EditorWindow window) GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal(); { - DoGUI(m_ContextNames, ref m_SelectedContextIndex, () => SetEditingContext(m_AvailableContexts[m_SelectedContextIndex])); + DoGUI(m_ContextNames, ref m_SelectedContextIndex, () => SetEditingContext(s_AvailableContexts[m_SelectedContextIndex])); GUILayout.FlexibleSpace(); } GUILayout.EndHorizontal(); @@ -213,16 +224,16 @@ internal void SetEditingContext(IEditingContext context) if (context == null) return; - if (m_CurrentContext != null) + if (s_CurrentContext != null) { - m_PreviousContexts.Insert(0, m_CurrentContext); - m_CurrentContext.Dispose(); + m_PreviousContexts.Insert(0, s_CurrentContext); + s_CurrentContext.Dispose(); } context.Setup(); - m_CurrentContext = context; + s_CurrentContext = context; - m_SelectedContextIndex = m_AvailableContexts.IndexOf(context); + m_SelectedContextIndex = s_AvailableContexts.IndexOf(context); } internal void RestorePreviousContext() @@ -254,12 +265,12 @@ internal static string[] GetEditingContextNames() return availableContexts.Select(c => c.name).ToArray(); } - List GetAvailableEditingContexts() + static List GetAvailableEditingContexts() { - if (m_AvailableContexts == null) - m_AvailableContexts = GetEditingContextAssets(); + if (s_AvailableContexts == null) + s_AvailableContexts = GetEditingContextAssets(); - return m_AvailableContexts; + return s_AvailableContexts; } List GetPreviousEditingContexts() diff --git a/Tests/Editor/Unit/Core/EditingContextManagerTests.cs b/Tests/Editor/Unit/Core/EditingContextManagerTests.cs index 45fab1d1f..43e6a6067 100644 --- a/Tests/Editor/Unit/Core/EditingContextManagerTests.cs +++ b/Tests/Editor/Unit/Core/EditingContextManagerTests.cs @@ -1,8 +1,6 @@ #if UNITY_EDITOR && UNITY_2017_2_OR_NEWER -using System; using System.IO; using UnityEngine; -using UnityEditor; using System.Collections.Generic; using NUnit.Framework; using UnityEditor.Experimental.EditorVR.Core; @@ -47,7 +45,7 @@ public void Setup() [Test] public void Initializes_WithDefaultContext() { - Assert.AreEqual(manager.defaultContext, manager.currentContext); + Assert.AreEqual(EditingContextManager.defaultContext, manager.currentContext); } [Test] @@ -160,7 +158,7 @@ public void SaveUserSettings_UpdatesUserSettingsFile() public void Cleanup() { ObjectUtils.Destroy(go); - manager.SetEditingContext(manager.defaultContext); + manager.SetEditingContext(EditingContextManager.defaultContext); ObjectUtils.Destroy(context); ObjectUtils.Destroy(context2); } From 21e7c2f355cc9d55f46d513484f170c275c99029 Mon Sep 17 00:00:00 2001 From: Dylan Urquidi Date: Thu, 30 Nov 2017 17:04:09 -0800 Subject: [PATCH 40/89] Add nearClipPlane correction in VRView camera setup, in OnEnable() --- Scripts/Core/VRView.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Scripts/Core/VRView.cs b/Scripts/Core/VRView.cs index 6bcdcb41e..ce0c3e7a4 100644 --- a/Scripts/Core/VRView.cs +++ b/Scripts/Core/VRView.cs @@ -140,6 +140,8 @@ public void OnEnable() autoRepaintOnSceneChange = true; s_ActiveView = this; + const float nearClipPlane = 0.01f; + const float farClipPlane = 1000f; var currentEditingContext = cameraSetupStarted != null ? cameraSetupStarted() : null; s_ExistingSceneMainCamera = Camera.main; @@ -147,11 +149,22 @@ public void OnEnable() { GameObject cameraGO = EditorUtility.CreateGameObjectWithHideFlags(k_CameraName, HideFlags.HideAndDontSave); m_Camera = ObjectUtils.CopyComponent(s_ExistingSceneMainCamera, cameraGO); + + if (m_Camera.nearClipPlane > nearClipPlane) + { + Debug.LogWarning("Copying settings from scene camera that is tagged 'MainCamera'." + Environment.NewLine + + " Clipping issues may occur with NearClipPlane values is greater than " + nearClipPlane); + + m_Camera.nearClipPlane = nearClipPlane; + } } else { GameObject cameraGO = EditorUtility.CreateGameObjectWithHideFlags(k_CameraName, HideFlags.HideAndDontSave, typeof(Camera)); m_Camera = cameraGO.GetComponent(); + + m_Camera.nearClipPlane = nearClipPlane; + m_Camera.farClipPlane = farClipPlane; } if (s_ExistingSceneMainCamera) @@ -166,8 +179,6 @@ public void OnEnable() GameObject rigGO = EditorUtility.CreateGameObjectWithHideFlags("VRCameraRig", HideFlags.HideAndDontSave, typeof(EditorMonoBehaviour)); m_CameraRig = rigGO.transform; m_Camera.transform.parent = m_CameraRig; - m_Camera.nearClipPlane = 0.01f; - m_Camera.farClipPlane = 1000f; m_CameraRig.position = headCenteredOrigin; m_CameraRig.rotation = Quaternion.identity; From 8d6c18a17c5a48a6b5fdca62b0dc120249a01336 Mon Sep 17 00:00:00 2001 From: Jono Forbes Date: Fri, 1 Dec 2017 16:24:09 -0800 Subject: [PATCH 41/89] Add updated Material undo/redo icon. --- Actions/Icons/RedoIcon.png | 4 ++-- Actions/Icons/UndoIcon.png | 4 ++-- Menus/UndoMenu/Prefabs/UndoMenu.prefab | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Actions/Icons/RedoIcon.png b/Actions/Icons/RedoIcon.png index f868a3d61..696441634 100644 --- a/Actions/Icons/RedoIcon.png +++ b/Actions/Icons/RedoIcon.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:72aecdcd01888c198ddceb3ac2bad7b0f47138e2e76e043de5c3797365789a76 -size 5426 +oid sha256:efda6f73c3b1b47ea50ce98a8636e8c0a002bb6230fd772023e0c75a8a17b20e +size 21741 diff --git a/Actions/Icons/UndoIcon.png b/Actions/Icons/UndoIcon.png index 2ce15dfb8..fe0eb6de6 100644 --- a/Actions/Icons/UndoIcon.png +++ b/Actions/Icons/UndoIcon.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c23ae97e3d31c63fea4f228de859f652f1bc8d1a56c685a6d78935467bdbe12 -size 5724 +oid sha256:c32c3e9f91275bf6f10ce0b4f1be291689f8ca62802a3bdcdf58877d7037f545 +size 7082 diff --git a/Menus/UndoMenu/Prefabs/UndoMenu.prefab b/Menus/UndoMenu/Prefabs/UndoMenu.prefab index b5f3988e8..62053559e 100644 --- a/Menus/UndoMenu/Prefabs/UndoMenu.prefab +++ b/Menus/UndoMenu/Prefabs/UndoMenu.prefab @@ -70,8 +70,8 @@ Transform: m_PrefabInternal: {fileID: 100100000} m_GameObject: {fileID: 1695890495350928} m_LocalRotation: {x: 0, y: 0.7071068, z: -0.7071068, w: 0} - m_LocalPosition: {x: 0.01, y: 0, z: 0.0032} - m_LocalScale: {x: 0.02, y: -0.02, z: 0.02} + m_LocalPosition: {x: 0.01, y: 0, z: 0.00276} + m_LocalScale: {x: 0.017317165, y: -0.01731716, z: 0.01731716} m_Children: [] m_Father: {fileID: 4579274395351022} m_RootOrder: 1 @@ -98,8 +98,8 @@ Transform: m_PrefabInternal: {fileID: 100100000} m_GameObject: {fileID: 1919443148181408} m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068} - m_LocalPosition: {x: -0.01, y: 0, z: 0.0032} - m_LocalScale: {x: 0.02, y: 0.02, z: 0.02} + m_LocalPosition: {x: -0.01, y: 0, z: 0.00276} + m_LocalScale: {x: 0.017317165, y: 0.01731716, z: 0.01731716} m_Children: [] m_Father: {fileID: 4579274395351022} m_RootOrder: 0 From 74df52073cf7113e02bfabd9b7c9dd80a3b8bfbd Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Fri, 1 Dec 2017 22:29:18 -0800 Subject: [PATCH 42/89] Early-out of CreateWorkspace for types that do not implement IWorkspace (i.e. Poly workspace if PolyToolkit is not available) --- Scripts/Modules/WorkspaceModule.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Scripts/Modules/WorkspaceModule.cs b/Scripts/Modules/WorkspaceModule.cs index b27d46c78..41f55ed53 100644 --- a/Scripts/Modules/WorkspaceModule.cs +++ b/Scripts/Modules/WorkspaceModule.cs @@ -167,6 +167,9 @@ public void OnDeserializePreferences(object obj) internal void CreateWorkspace(Type t, Action createdCallback = null) { + if (!typeof(IWorkspace).IsAssignableFrom(t)) + return; + // HACK: MiniWorldWorkspace is not working in single pass yet if (t == typeof(MiniWorldWorkspace) && PlayerSettings.stereoRenderingPath != StereoRenderingPath.MultiPass) { From f21a1c65c65e1c089cde92ef40058a3a7d9e90d3 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Sun, 3 Dec 2017 22:40:52 -0800 Subject: [PATCH 43/89] Register undo on object creation/destruction in CreatePrimitiveTool, AssetGridItem, and Delete Action --- Actions/Delete.cs | 3 ++- Scripts/Modules/SceneObjectModule.cs | 11 +++++++---- Scripts/Utilities/ObjectUtils.cs | 18 ++++++++++++++---- Tools/AnnotationTool/AnnotationTool.cs | 5 +++-- .../CreatePrimitiveTool/CreatePrimitiveTool.cs | 2 ++ .../ProjectWorkspace/Scripts/AssetGridItem.cs | 7 +++++-- 6 files changed, 33 insertions(+), 13 deletions(-) diff --git a/Actions/Delete.cs b/Actions/Delete.cs index 64b24043a..96327a56b 100644 --- a/Actions/Delete.cs +++ b/Actions/Delete.cs @@ -1,6 +1,5 @@ #if UNITY_EDITOR using System; -using UnityEditor.Experimental.EditorVR.Utilities; using UnityEngine; namespace UnityEditor.Experimental.EditorVR.Actions @@ -19,6 +18,8 @@ public override void ExecuteAction() this.DeleteSceneObject(go); } + UnityEditor.Undo.IncrementCurrentGroup(); + Selection.activeGameObject = null; } } diff --git a/Scripts/Modules/SceneObjectModule.cs b/Scripts/Modules/SceneObjectModule.cs index 6050d2f06..21f15b9bf 100644 --- a/Scripts/Modules/SceneObjectModule.cs +++ b/Scripts/Modules/SceneObjectModule.cs @@ -26,13 +26,14 @@ public void PlaceSceneObject(Transform obj, Vector3 targetScale) public void DeleteSceneObject(GameObject sceneObject) { this.RemoveFromSpatialHash(sceneObject); - ObjectUtils.Destroy(sceneObject); + ObjectUtils.Destroy(sceneObject, withUndo: true); } IEnumerator PlaceSceneObjectCoroutine(Transform obj, Vector3 targetScale) { + var go = obj.gameObject; // Don't let us direct select while placing - this.RemoveFromSpatialHash(obj.gameObject); + this.RemoveFromSpatialHash(go); var start = Time.realtimeSinceStartup; var currTime = 0f; @@ -83,9 +84,10 @@ IEnumerator PlaceSceneObjectCoroutine(Transform obj, Vector3 targetScale) yield return null; } obj.localScale = targetScale; - Selection.activeGameObject = obj.gameObject; + Selection.activeGameObject = go; - this.AddToSpatialHash(obj.gameObject); + this.AddToSpatialHash(go); + Undo.IncrementCurrentGroup(); } public void PlaceSceneObjects(Transform[] transforms, Vector3[] targetPositionOffsets, Quaternion[] targetRotations, Vector3[] targetScales) @@ -178,6 +180,7 @@ IEnumerator PlaceSceneObjectsCoroutine(Transform[] transforms, Vector3[] targetP } Selection.objects = objects; + Undo.IncrementCurrentGroup(); } } } diff --git a/Scripts/Utilities/ObjectUtils.cs b/Scripts/Utilities/ObjectUtils.cs index fcc568e32..9f2859daf 100644 --- a/Scripts/Utilities/ObjectUtils.cs +++ b/Scripts/Utilities/ObjectUtils.cs @@ -250,7 +250,7 @@ public static IEnumerable GetExtensionsOfClass(Type type) return Enumerable.Empty(); } - public static void Destroy(UnityObject o, float t = 0f) + public static void Destroy(UnityObject o, float t = 0f, bool withUndo = false) { if (Application.isPlaying) { @@ -260,20 +260,30 @@ public static void Destroy(UnityObject o, float t = 0f) else { if (Mathf.Approximately(t, 0f)) - UnityObject.DestroyImmediate(o); + { + if (withUndo) + Undo.DestroyObjectImmediate(o); + else + UnityObject.DestroyImmediate(o); + } else + { VRView.StartCoroutine(DestroyInSeconds(o, t)); + } } #endif } - static IEnumerator DestroyInSeconds(UnityObject o, float t) + static IEnumerator DestroyInSeconds(UnityObject o, float t, bool withUndo = false) { var startTime = Time.realtimeSinceStartup; while (Time.realtimeSinceStartup <= startTime + t) yield return null; - UnityObject.DestroyImmediate(o); + if (withUndo) + Undo.DestroyObjectImmediate(o); + else + UnityObject.DestroyImmediate(o); } /// diff --git a/Tools/AnnotationTool/AnnotationTool.cs b/Tools/AnnotationTool/AnnotationTool.cs index 6ef5701a6..e88082a0c 100644 --- a/Tools/AnnotationTool/AnnotationTool.cs +++ b/Tools/AnnotationTool/AnnotationTool.cs @@ -392,7 +392,8 @@ void SetupAnnotation() m_Widths.Clear(); m_Length = 0; - var go = new GameObject(string.Format(k_AnnotationFormatStrig,+ m_AnnotationHolder.childCount)); + var go = new GameObject(string.Format(k_AnnotationFormatStrig, m_AnnotationHolder.childCount)); + Undo.RegisterCreatedObjectUndo(go, "Annotation"); var goTrans = go.transform; goTrans.SetParent(m_AnnotationHolder); @@ -420,6 +421,7 @@ void SetupHolder() if (!newSession) { newSession = new GameObject(string.Format(k_GroupFormatString, m_AnnotationRoot.childCount)); + Undo.RegisterCreatedObjectUndo(newSession, "Annotation"); newSession.transform.position = GetPointerPosition(); m_Groups.Add(newSession); } @@ -602,7 +604,6 @@ void FinalizeMesh() this.AddToSpatialHash(go); Undo.IncrementCurrentGroup(); - Undo.RegisterCreatedObjectUndo(go, "Create Annotation"); if (AnnotationFinished != null) { diff --git a/Tools/CreatePrimitiveTool/CreatePrimitiveTool.cs b/Tools/CreatePrimitiveTool/CreatePrimitiveTool.cs index ecfc51572..d9d860e67 100644 --- a/Tools/CreatePrimitiveTool/CreatePrimitiveTool.cs +++ b/Tools/CreatePrimitiveTool/CreatePrimitiveTool.cs @@ -119,6 +119,7 @@ void HandleStartPoint(Standard standardInput, ConsumeControlDelegate consumeCont if (standardInput.action.wasJustPressed) { m_CurrentGameObject = GameObject.CreatePrimitive(m_SelectedPrimitiveType); + Undo.RegisterCreatedObjectUndo(m_CurrentGameObject, "Create Primitive"); // Set starting minimum scale (don't allow zero scale object to be created) const float kMinScale = 0.0025f; @@ -166,6 +167,7 @@ void CheckForTriggerRelease(Standard standardInput, ConsumeControlDelegate consu if (standardInput.action.wasJustReleased) { m_State = PrimitiveCreationStates.StartPoint; + Undo.IncrementCurrentGroup(); consumeControl(standardInput.action); } diff --git a/Workspaces/ProjectWorkspace/Scripts/AssetGridItem.cs b/Workspaces/ProjectWorkspace/Scripts/AssetGridItem.cs index 8d6f48842..ef5d2b3d9 100644 --- a/Workspaces/ProjectWorkspace/Scripts/AssetGridItem.cs +++ b/Workspaces/ProjectWorkspace/Scripts/AssetGridItem.cs @@ -351,9 +351,11 @@ protected override void OnDragEnded(BaseHandle handle, HandleEventData eventData if (!this.IsOverShoulder(eventData.rayOrigin)) { - if (gridItem.m_PreviewObjectTransform) + var previewObjectTransform = gridItem.m_PreviewObjectTransform; + if (previewObjectTransform) { - this.PlaceSceneObject(gridItem.m_PreviewObjectTransform, m_PreviewPrefabScale); + Undo.RegisterCreatedObjectUndo(previewObjectTransform.gameObject, "Place Scene Object"); + this.PlaceSceneObject(previewObjectTransform, m_PreviewPrefabScale); } else { @@ -371,6 +373,7 @@ protected override void OnDragEnded(BaseHandle handle, HandleEventData eventData #endif this.AddToSpatialHash(go); + Undo.RegisterCreatedObjectUndo(go, "Project Workspace"); break; } } From ed68e8e56d43776fea6d598d03d115f967f28693 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Mon, 4 Dec 2017 16:39:21 -0800 Subject: [PATCH 44/89] PR feedback --- .../FunctionalityInjection/IRequestFeedback.cs | 1 + Scripts/Utilities/ObjectUtils.cs | 2 ++ Workspaces/Common/Scripts/FilterUI.cs | 1 - Workspaces/PolyWorkspace/PolyWorkspace.cs | 13 +++++++------ .../PolyWorkspace/Scripts/PolyGridAsset.cs | 2 +- .../PolyWorkspace/Scripts/PolyGridItem.cs | 18 +++++++++--------- .../ProjectWorkspace/ProjectWorkspace.cs | 7 +++++-- .../Shaders/StandardDecal.shader | 11 +++-------- 8 files changed, 28 insertions(+), 27 deletions(-) diff --git a/Scripts/Interfaces/FunctionalityInjection/IRequestFeedback.cs b/Scripts/Interfaces/FunctionalityInjection/IRequestFeedback.cs index 73163487f..779ebbb5c 100644 --- a/Scripts/Interfaces/FunctionalityInjection/IRequestFeedback.cs +++ b/Scripts/Interfaces/FunctionalityInjection/IRequestFeedback.cs @@ -48,6 +48,7 @@ public static void ClearFeedbackRequests(this IRequestFeedback obj) /// /// Get a pooled FeedbackRequest object from the system /// + /// The type of request object desired public static FeedbackRequest GetFeedbackRequestObject(this IRequestFeedback obj, Type type) { return getFeedbackRequestObject(type); diff --git a/Scripts/Utilities/ObjectUtils.cs b/Scripts/Utilities/ObjectUtils.cs index e22160361..9b901fd5a 100644 --- a/Scripts/Utilities/ObjectUtils.cs +++ b/Scripts/Utilities/ObjectUtils.cs @@ -149,7 +149,9 @@ public static Bounds GetBounds(Transform transform) b.center = k_Transforms[0].position; foreach (var t in k_Transforms) + { b.Encapsulate(t.position); + } } return b; diff --git a/Workspaces/Common/Scripts/FilterUI.cs b/Workspaces/Common/Scripts/FilterUI.cs index 4094de725..25b4b1546 100644 --- a/Workspaces/Common/Scripts/FilterUI.cs +++ b/Workspaces/Common/Scripts/FilterUI.cs @@ -189,7 +189,6 @@ void OnFilterClick(FilterButtonUI clickedButton) switch (clickedButton.text.text) { case k_AllText: - m_SummaryText.text = clickedButton.text.text; m_DescriptionText.text = "All objects are visible"; break; diff --git a/Workspaces/PolyWorkspace/PolyWorkspace.cs b/Workspaces/PolyWorkspace/PolyWorkspace.cs index 2474708c5..8ac2c317d 100644 --- a/Workspaces/PolyWorkspace/PolyWorkspace.cs +++ b/Workspaces/PolyWorkspace/PolyWorkspace.cs @@ -25,9 +25,6 @@ namespace UnityEditor.Experimental.EditorVR.Workspaces [MainMenuItem("Poly", "Workspaces", "Import models from Google Poly")] sealed class PolyWorkspace : Workspace, ISerializeWorkspace { - const float k_XBounds = 1.094f; - const float k_YBounds = 0.2f; - const float k_MinScale = 0.05f; const float k_MaxScale = 0.2f; @@ -44,6 +41,10 @@ sealed class PolyWorkspace : Workspace, ISerializeWorkspace const string k_Medium = "Medium"; const string k_Simple = "Simple"; + static readonly Vector3 k_MinBounds = new Vector3(1.094f, 0.2f, 0.5f); + static readonly Vector3 k_ScrollHandleScale = new Vector3(1.03f, 0.02f, 1.02f); // Extra space for scrolling + static readonly Vector3 k_ScrollHandlePosition = new Vector3(0f, -0.015f, 0f); // Offset from content for collision purposes + [Serializable] class Preferences { @@ -89,7 +90,7 @@ public List assetData public override void Setup() { // Initial bounds must be set before the base.Setup() is called - minBounds = new Vector3(k_XBounds, k_YBounds, 0.5f); + minBounds = k_MinBounds; m_CustomStartingBounds = minBounds; base.Setup(); @@ -124,8 +125,8 @@ public override void Setup() var scrollHandle = m_PolyUI.scrollHandle; var scrollHandleTransform = scrollHandle.transform; scrollHandleTransform.SetParent(m_WorkspaceUI.topFaceContainer); - scrollHandleTransform.localScale = new Vector3(1.03f, 0.02f, 1.02f); // Extra space for scrolling - scrollHandleTransform.localPosition = new Vector3(0f, -0.015f, 0f); // Offset from content for collision purposes + scrollHandleTransform.localScale = k_ScrollHandleScale; + scrollHandleTransform.localPosition = k_ScrollHandlePosition; scrollHandle.dragStarted += OnScrollDragStarted; scrollHandle.dragging += OnScrollDragging; diff --git a/Workspaces/PolyWorkspace/Scripts/PolyGridAsset.cs b/Workspaces/PolyWorkspace/Scripts/PolyGridAsset.cs index 544071c02..009fbb67a 100644 --- a/Workspaces/PolyWorkspace/Scripts/PolyGridAsset.cs +++ b/Workspaces/PolyWorkspace/Scripts/PolyGridAsset.cs @@ -36,7 +36,7 @@ public class PolyGridAsset : ListViewItemData, IWeb public Texture2D thumbnail { get { return m_Thumbnail; } } public bool initialized { get { return m_Initialized; } } public long complexity { get { return m_Complexity; } } - public override string index { get { return m_Asset.name; } } + public override string index { get { return m_Asset.name; } } // PolyAsset.name is the GUID public event Action modelImportCompleted; public event Action thumbnailImportCompleted; diff --git a/Workspaces/PolyWorkspace/Scripts/PolyGridItem.cs b/Workspaces/PolyWorkspace/Scripts/PolyGridItem.cs index 9f93d2628..813a33bf9 100644 --- a/Workspaces/PolyWorkspace/Scripts/PolyGridItem.cs +++ b/Workspaces/PolyWorkspace/Scripts/PolyGridItem.cs @@ -94,7 +94,6 @@ class PolyGridItem : DraggableListItem, IPlaceSceneObject Action m_CompleteHoverTransition; Action m_SetThumbnailScale; Action m_SetImportingScale; - Action m_SetImportingColor; void Awake() @@ -102,7 +101,6 @@ void Awake() m_CompleteHoverTransition = CompleteHoverTransition; m_SetThumbnailScale = SetThumbnailScale; m_SetImportingScale = SetImportingScale; - m_SetImportingColor = SetImportingColor; } @@ -422,7 +420,8 @@ IEnumerator AnimateVisibility(bool visible, Action callback) while (currentTime < k_TransitionDuration) { currentTime += Time.deltaTime; - transform.localScale = Vector3.Lerp(currentScale, targetScale, currentTime / k_TransitionDuration); + transform.localScale = Vector3.Lerp(currentScale, targetScale, + MathUtilsExt.SmoothInOutLerpFloat(currentTime / k_TransitionDuration)); yield return null; } @@ -446,8 +445,7 @@ IEnumerator ShowGrabbedObject() currentPreviewOffset = m_PreviewObjectClone.localPosition; var currentTime = 0f; - var currentVelocity = 0f; - const float kDuration = 1f; + const float duration = 1f; var targetScale = Vector3.one * k_IconPreviewScale; var pivotOffset = Vector3.zero; @@ -484,13 +482,14 @@ IEnumerator ShowGrabbedObject() } } - while (currentTime < kDuration - 0.05f) + while (currentTime < duration) { if (m_DragObject == null) yield break; // Exit coroutine if m_GrabbedObject is destroyed before the loop is finished - currentTime = MathUtilsExt.SmoothDamp(currentTime, kDuration, ref currentVelocity, 0.5f, Mathf.Infinity, Time.deltaTime); - m_DragObject.localScale = Vector3.Lerp(currentLocalScale, targetScale, currentTime); + currentTime += Time.deltaTime; + m_DragObject.localScale = Vector3.Lerp(currentLocalScale, targetScale, + MathUtilsExt.SmoothInOutLerpFloat(currentTime / duration)); if (m_PreviewObjectClone) { @@ -501,7 +500,8 @@ IEnumerator ShowGrabbedObject() yield return null; } - m_DragObject.localScale = targetScale; + m_DragObject.localScale = targetScale; + //No need to hard-set the preview object position/rotation because they will set in OnDragging in parent class } static IEnumerator HideGrabbedObject(GameObject itemToHide) diff --git a/Workspaces/ProjectWorkspace/ProjectWorkspace.cs b/Workspaces/ProjectWorkspace/ProjectWorkspace.cs index 9a6ca57b6..67b736162 100644 --- a/Workspaces/ProjectWorkspace/ProjectWorkspace.cs +++ b/Workspaces/ProjectWorkspace/ProjectWorkspace.cs @@ -19,6 +19,9 @@ sealed class ProjectWorkspace : Workspace, IUsesProjectFolderData, IFilterUI, IS const float k_MinScale = 0.04f; const float k_MaxScale = 0.09f; + static readonly Vector3 k_MinBounds = new Vector3(MinBounds.x, k_YBounds, 0.5f); + static readonly Vector3 k_CustomStartingBounds = new Vector3(0.8f, k_YBounds, 0.5f); + bool m_AssetGridDragging; bool m_FolderPanelDragging; @@ -95,8 +98,8 @@ public List expandedFolders public override void Setup() { // Initial bounds must be set before the base.Setup() is called - minBounds = new Vector3(MinBounds.x, k_YBounds, 0.5f); - m_CustomStartingBounds = new Vector3(0.8f, k_YBounds, 0.5f); + minBounds = k_MinBounds; + m_CustomStartingBounds = k_CustomStartingBounds; base.Setup(); diff --git a/Workspaces/ProjectWorkspace/Shaders/StandardDecal.shader b/Workspaces/ProjectWorkspace/Shaders/StandardDecal.shader index 205517310..6197cbb44 100644 --- a/Workspaces/ProjectWorkspace/Shaders/StandardDecal.shader +++ b/Workspaces/ProjectWorkspace/Shaders/StandardDecal.shader @@ -32,14 +32,9 @@ Shader "EditorVR/Standard Decal" void surf (Input IN, inout SurfaceOutputStandard o) { - if (IN.uv_MainTex.x > 1 || IN.uv_MainTex.x < 0 - || IN.uv_MainTex.y > 1 || IN.uv_MainTex.y < 0) - o.Emission = 0; - else { - fixed4 c = tex2D(_MainTex, IN.uv_MainTex); - c *= _Color * c.a; - o.Emission = c.rgb; - } + fixed4 c = tex2D(_MainTex, IN.uv_MainTex); + c *= _Color * c.a; + o.Emission = c.rgb; } ENDCG } From b998b4e09100846e104c99dcfb61750e7a7c64af Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Tue, 5 Dec 2017 01:24:17 -0800 Subject: [PATCH 45/89] Include a patched UnityEngine.CoreModule.dll for 2017.2.0p1, along with CCU-wrapped call to that fix to fix "Driving RectTransform" undo issue --- Scripts/Core/EditorVR.cs | 8 ++++++++ UndoPatch.meta | 10 ++++++++++ UndoPatch/UnityEngine.CoreModule_2017.2.0p1.zip | 3 +++ UndoPatch/UnityEngine.CoreModule_2017.2.0p1.zip.meta | 9 +++++++++ 4 files changed, 30 insertions(+) create mode 100644 UndoPatch.meta create mode 100644 UndoPatch/UnityEngine.CoreModule_2017.2.0p1.zip create mode 100644 UndoPatch/UnityEngine.CoreModule_2017.2.0p1.zip.meta diff --git a/Scripts/Core/EditorVR.cs b/Scripts/Core/EditorVR.cs index 2714e7d7e..8c2667c8d 100644 --- a/Scripts/Core/EditorVR.cs +++ b/Scripts/Core/EditorVR.cs @@ -12,6 +12,7 @@ using UnityEngine.InputNew; [assembly: OptionalDependency("PolyToolkit.PolyApi", "INCLUDE_POLY_TOOLKIT")] +[assembly: OptionalDependency("UnityEngine.DrivenRectTransformTracker+BlockUndoCCU", "UNDO_PATCH")] namespace UnityEditor.Experimental.EditorVR.Core { @@ -126,6 +127,9 @@ static void HandleInitialization() void Awake() { +#if UNDO_PATCH + DrivenRectTransformTracker.BlockUndo = true; +#endif s_Instance = this; // Used only by PreferencesGUI Nested.evr = this; // Set this once for the convenience of all nested classes m_DefaultTools = defaultTools; @@ -346,6 +350,10 @@ void OnDestroy() { nested.OnDestroy(); } + +#if UNDO_PATCH + DrivenRectTransformTracker.BlockUndo = false; +#endif } void Update() diff --git a/UndoPatch.meta b/UndoPatch.meta new file mode 100644 index 000000000..8a73ddc27 --- /dev/null +++ b/UndoPatch.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 09bef22b7a38b1748826705905670959 +folderAsset: yes +timeCreated: 1512465425 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UndoPatch/UnityEngine.CoreModule_2017.2.0p1.zip b/UndoPatch/UnityEngine.CoreModule_2017.2.0p1.zip new file mode 100644 index 000000000..c9a2dbe90 --- /dev/null +++ b/UndoPatch/UnityEngine.CoreModule_2017.2.0p1.zip @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:263509d40ec2fe536344bfaf6e74c421d384466634e67e6b46039f96931a5834 +size 248879 diff --git a/UndoPatch/UnityEngine.CoreModule_2017.2.0p1.zip.meta b/UndoPatch/UnityEngine.CoreModule_2017.2.0p1.zip.meta new file mode 100644 index 000000000..d53a7177e --- /dev/null +++ b/UndoPatch/UnityEngine.CoreModule_2017.2.0p1.zip.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 91ff1c9c19344e04b814821f72db55a8 +timeCreated: 1512465425 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: From d08ce53c028054ba93a2117c258553388abc114e Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Tue, 5 Dec 2017 12:08:11 -0800 Subject: [PATCH 46/89] Fix bug where objects would interpolate when they entered the mini world while snapping --- Tools/TransformTool/TransformTool.cs | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/Tools/TransformTool/TransformTool.cs b/Tools/TransformTool/TransformTool.cs index f88fce69f..a7032f3c1 100644 --- a/Tools/TransformTool/TransformTool.cs +++ b/Tools/TransformTool/TransformTool.cs @@ -58,7 +58,7 @@ public void Reset() } } - public void UpdatePositions(IUsesSnapping usesSnapping) + public void UpdatePositions(IUsesSnapping usesSnapping, bool interpolate = true) { if (suspended) return; @@ -71,13 +71,21 @@ public void UpdatePositions(IUsesSnapping usesSnapping) var position = grabbedObject.position; var rotation = grabbedObject.rotation; var targetPosition = rayOrigin.position + rayOrigin.rotation * m_PositionOffsets[i]; - var targetRotation = rayOrigin.rotation * m_RotationOffsets[i]; + var targetRotation = rayOrigin.rotation * m_RotationOffsets[i]; if (usesSnapping.DirectSnap(rayOrigin, grabbedObject, ref position, ref rotation, targetPosition, targetRotation)) { - var deltaTime = Time.deltaTime; - grabbedObject.position = Vector3.Lerp(grabbedObject.position, position, k_DirectLazyFollowTranslate * deltaTime); - grabbedObject.rotation = Quaternion.Lerp(grabbedObject.rotation, rotation, k_DirectLazyFollowRotate * deltaTime); + if (interpolate) + { + var deltaTime = Time.deltaTime; + grabbedObject.position = Vector3.Lerp(grabbedObject.position, position, k_DirectLazyFollowTranslate * deltaTime); + grabbedObject.rotation = Quaternion.Lerp(grabbedObject.rotation, rotation, k_DirectLazyFollowRotate * deltaTime); + } + else + { + grabbedObject.position = position; + grabbedObject.rotation = rotation; + } } else { @@ -595,7 +603,10 @@ public void Resume(Node node) { var grabData = GrabDataForNode(node); if (grabData != null) - grabData.suspended = false; + { + grabData.suspended = false; + grabData.UpdatePositions(this, false); + } } public Transform[] GetHeldObjects(Node node) @@ -616,7 +627,7 @@ public Transform[] GetHeldObjects(Node node) grabData.TransferTo(destRayOrigin, deltaOffset); this.ClearSnappingState(rayOrigin); - grabData.UpdatePositions(this); + grabData.UpdatePositions(this, false); // Prevent lock from getting stuck this.RemoveRayVisibilitySettings(rayOrigin, this); From cfa29367eef6ca6435232c2b788bfd84682e6891 Mon Sep 17 00:00:00 2001 From: Dylan Urquidi Date: Tue, 5 Dec 2017 15:31:37 -0800 Subject: [PATCH 47/89] Validate that an instance has been created, via the instanceExists bool prop in IEditingContext, before attempting to dispose in EditingContextManager's SetEditingContext() function --- Scripts/Core/Contexts/EditingContextManager.cs | 4 +++- Scripts/Core/Contexts/EditorVRContext.cs | 11 +++++------ Scripts/Interfaces/Entity/IEditingContext.cs | 5 +++++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Scripts/Core/Contexts/EditingContextManager.cs b/Scripts/Core/Contexts/EditingContextManager.cs index 7c18c8acf..fe8163735 100644 --- a/Scripts/Core/Contexts/EditingContextManager.cs +++ b/Scripts/Core/Contexts/EditingContextManager.cs @@ -227,7 +227,9 @@ internal void SetEditingContext(IEditingContext context) if (s_CurrentContext != null) { m_PreviousContexts.Insert(0, s_CurrentContext); - s_CurrentContext.Dispose(); + + if (s_CurrentContext.instanceExists) + s_CurrentContext.Dispose(); } context.Setup(); diff --git a/Scripts/Core/Contexts/EditorVRContext.cs b/Scripts/Core/Contexts/EditorVRContext.cs index a055ef758..8f997c3ee 100644 --- a/Scripts/Core/Contexts/EditorVRContext.cs +++ b/Scripts/Core/Contexts/EditorVRContext.cs @@ -23,6 +23,8 @@ class EditorVRContext : ScriptableObject, IEditingContext public bool copySceneCameraSettings { get { return m_CopySceneCameraSettings; } } + public bool instanceExists { get { return m_Instance != null; } } + public void Setup() { EditorVR.defaultTools = m_DefaultToolStack.Select(ms => ms.GetClass()).ToArray(); @@ -32,12 +34,9 @@ public void Setup() public void Dispose() { - if (m_Instance) - { - m_Instance.Shutdown(); // Give a chance for dependent systems (e.g. serialization) to shut-down before destroying - ObjectUtils.Destroy(m_Instance.gameObject); - m_Instance = null; - } + m_Instance.Shutdown(); // Give a chance for dependent systems (e.g. serialization) to shut-down before destroying + ObjectUtils.Destroy(m_Instance.gameObject); + m_Instance = null; } } } diff --git a/Scripts/Interfaces/Entity/IEditingContext.cs b/Scripts/Interfaces/Entity/IEditingContext.cs index fc2ca8f03..8ceb62e10 100644 --- a/Scripts/Interfaces/Entity/IEditingContext.cs +++ b/Scripts/Interfaces/Entity/IEditingContext.cs @@ -19,6 +19,11 @@ public interface IEditingContext /// bool copySceneCameraSettings { get; } + /// + /// Bool denotes that the EditorVR instance exists, having already been created in Setup() + /// + bool instanceExists { get; } + /// /// Perform one-time setup for the context when pushed to the stack. /// From 24c4406263939eeda86538399fd2efdddf35b924 Mon Sep 17 00:00:00 2001 From: Dylan Urquidi Date: Tue, 5 Dec 2017 15:46:27 -0800 Subject: [PATCH 48/89] Refactor CopyComponent function to utilize addComponent & EditorUtility.CopySerialized instead of custom logic --- Scripts/Utilities/ObjectUtils.cs | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/Scripts/Utilities/ObjectUtils.cs b/Scripts/Utilities/ObjectUtils.cs index 1d1a42a1a..6ed3ffc44 100644 --- a/Scripts/Utilities/ObjectUtils.cs +++ b/Scripts/Utilities/ObjectUtils.cs @@ -202,30 +202,11 @@ public static Component AddComponent(Type type, GameObject go) public static T CopyComponent(T sourceComponent, GameObject targetGameObject) where T : Component { - Type sourceType = sourceComponent.GetType(); - var targetComponent = targetGameObject.GetComponent(sourceType) as T; - if (!targetComponent) - targetComponent = targetGameObject.AddComponent(sourceType) as T; + var sourceType = sourceComponent.GetType(); + var clonedTargetComponent = AddComponent(sourceType, targetGameObject); + EditorUtility.CopySerialized(sourceComponent, clonedTargetComponent); - var fields = sourceType.GetFields(); - foreach (var field in fields) - { - if (field.IsStatic) - continue; - - field.SetValue(targetComponent, field.GetValue(sourceComponent)); - } - - var properties = sourceType.GetProperties(); - foreach (var property in properties) - { - if (!property.CanWrite || property.Name == "name") - continue; - - property.SetValue(targetComponent, property.GetValue(sourceComponent, null), null); - } - - return (T)targetComponent; + return (T)clonedTargetComponent; } static IEnumerable GetAssignableTypes(Type type, Func predicate = null) From 1f7a7145c5480d0d4fc424d60fe4f6b14559e5fb Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Tue, 5 Dec 2017 17:31:00 -0800 Subject: [PATCH 49/89] Add an editor window for editing/viewing serialized feedback info (i.e. presentation counts); Refactor SerializedPreferenceModule to support access while EXR is not running; Fix issue where Feedback preferences can get overwritten with blank data --- Editor/ProxyFeedbackEditor.cs | 143 ++++++++++++++++++ Editor/ProxyFeedbackEditor.cs.meta | 12 ++ Scripts/Core/EditorVR.cs | 4 +- .../Modules/SerializedPreferencesModule.cs | 33 ++-- .../Proxies/Data/SerializedProxyFeedback.cs | 124 +++++++++++++++ .../Data/SerializedProxyFeedback.cs.meta | 13 ++ Scripts/Proxies/ProxyNode.cs | 132 +++------------- Scripts/Proxies/TwoHandedProxyBase.cs | 21 ++- 8 files changed, 346 insertions(+), 136 deletions(-) create mode 100644 Editor/ProxyFeedbackEditor.cs create mode 100644 Editor/ProxyFeedbackEditor.cs.meta create mode 100644 Scripts/Proxies/Data/SerializedProxyFeedback.cs create mode 100644 Scripts/Proxies/Data/SerializedProxyFeedback.cs.meta diff --git a/Editor/ProxyFeedbackEditor.cs b/Editor/ProxyFeedbackEditor.cs new file mode 100644 index 000000000..f474debcf --- /dev/null +++ b/Editor/ProxyFeedbackEditor.cs @@ -0,0 +1,143 @@ +using System; +using System.Collections.Generic; +using UnityEditor.Experimental.EditorVR.Modules; +using UnityEditor.Experimental.EditorVR.Proxies; +using UnityEngine; + +namespace UnityEditor.Experimental.EditorVR.UI +{ + sealed class ProxyFeedbackEditor : EditorWindow + { + Dictionary m_SerializedFeedback = new Dictionary(); + Vector2 m_Scroll; + + [MenuItem("Edit/Project Settings/EditorXR/Proxy Feedback")] + static void Init() + { + GetWindow("Proxy Feedback Editor").Show(); + } + + void OnEnable() + { + Refresh(); + } + + void OnGUI() + { + if (Event.current.Equals(Event.KeyboardEvent("^w"))) + { + Close(); + GUIUtility.ExitGUI(); + } + + if (GUILayout.Button("Reload Data")) + Refresh(); + + if (GUILayout.Button("Clear Data")) + { + ClearData(); + Refresh(); + } + + if (GUILayout.Button("Save Data")) + { + SaveData(); + Refresh(); + } + + m_Scroll = GUILayout.BeginScrollView(m_Scroll); + var hasFeedback = false; + foreach (var kvp in m_SerializedFeedback) + { + GUILayout.Label(kvp.Key.Name, EditorStyles.boldLabel); + DrawPreferences(kvp.Value); + hasFeedback = true; + } + + if (!hasFeedback) + GUILayout.Label("No serialized feedback"); + + GUILayout.EndScrollView(); + } + + static void DrawPreferences(SerializedProxyFeedback feedback) + { + GUILayout.Label("Left Hand"); + DrawNode(feedback.leftNode); + GUILayout.Label("Right Hand"); + DrawNode(feedback.rightNode); + } + + static void DrawNode(SerializedProxyNodeFeedback node) + { + var keys = node.keys; + var values = node.values; + for (var i = 0; i < keys.Length; i++) + { + var data = values[i]; + data.presentations = EditorGUILayout.IntField(keys[i].ToString(), data.presentations); + } + } + + void Refresh() + { + m_SerializedFeedback.Clear(); + var preferences = SerializedPreferencesModule.DeserializePreferences(Core.EditorVR.serializedPreferences); + if (preferences == null) + return; + + foreach (var kvp in preferences.items) + { + var type = kvp.Key; + if (typeof(TwoHandedProxyBase).IsAssignableFrom(type)) + { + var item = kvp.Value; + Type payloadType = null; + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + payloadType = assembly.GetType(item.payloadType); + if (payloadType != null) + break; + } + + if (payloadType == null) + continue; + + var payload = (SerializedProxyFeedback)JsonUtility.FromJson(item.payload, payloadType); + m_SerializedFeedback[kvp.Key] = payload; + } + } + } + + static void ClearData() + { + var preferences = SerializedPreferencesModule.DeserializePreferences(Core.EditorVR.serializedPreferences); + if (preferences == null) + return; + + foreach (var kvp in new Dictionary(preferences.items)) + { + var type = kvp.Key; + if (typeof(TwoHandedProxyBase).IsAssignableFrom(type)) + preferences.Remove(type); + } + + Core.EditorVR.serializedPreferences = JsonUtility.ToJson(preferences); + } + + void SaveData() + { + var preferences = SerializedPreferencesModule.DeserializePreferences(Core.EditorVR.serializedPreferences); + if (preferences == null) + return; + + var items = preferences.items; + foreach (var kvp in m_SerializedFeedback) + { + items[kvp.Key].payload = JsonUtility.ToJson(kvp.Value); + } + + Core.EditorVR.serializedPreferences = JsonUtility.ToJson(preferences); + } + } +} diff --git a/Editor/ProxyFeedbackEditor.cs.meta b/Editor/ProxyFeedbackEditor.cs.meta new file mode 100644 index 000000000..de6675524 --- /dev/null +++ b/Editor/ProxyFeedbackEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d3a9ecd7de8ff2c4fa4a85c66a8feda8 +timeCreated: 1486770624 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Core/EditorVR.cs b/Scripts/Core/EditorVR.cs index 2714e7d7e..13813b586 100644 --- a/Scripts/Core/EditorVR.cs +++ b/Scripts/Core/EditorVR.cs @@ -58,7 +58,7 @@ static bool preserveLayout set { EditorPrefs.SetBool(k_PreserveLayout, value); } } - static string serializedPreferences + internal static string serializedPreferences { get { return EditorPrefs.GetString(k_SerializedPreferences, string.Empty); } set { EditorPrefs.SetString(k_SerializedPreferences, value); } @@ -277,7 +277,7 @@ IEnumerator Start() while (!viewer.hmdReady) yield return null; - GetModule().DeserializePreferences(serializedPreferences); + GetModule().SetupWithPreferences(serializedPreferences); m_HasDeserialized = true; } diff --git a/Scripts/Modules/SerializedPreferencesModule.cs b/Scripts/Modules/SerializedPreferencesModule.cs index 08d341585..02b21d070 100644 --- a/Scripts/Modules/SerializedPreferencesModule.cs +++ b/Scripts/Modules/SerializedPreferencesModule.cs @@ -13,7 +13,7 @@ sealed class SerializedPreferencesModule : MonoBehaviour SerializedPreferences m_Preferences; [Serializable] - class SerializedPreferences : ISerializationCallbackReceiver + internal class SerializedPreferences : ISerializationCallbackReceiver { [SerializeField] SerializedPreferenceItem[] m_Items; @@ -41,10 +41,16 @@ public void OnAfterDeserialize() } } } + + public void Remove(Type type) + { + m_ItemDictionary.Remove(type); + m_Items = m_ItemDictionary.Values.ToArray(); + } } [Serializable] - class SerializedPreferenceItem + internal class SerializedPreferenceItem { [SerializeField] string m_Name; @@ -75,7 +81,7 @@ public string payload public void AddSerializer(ISerializePreferences serializer) { if (m_Preferences != null) - Deserialize(serializer); + Deserialize(m_Preferences, serializer); m_Serializers.Add(serializer); } @@ -87,18 +93,23 @@ public void RemoveSerializer(ISerializePreferences serializer) m_Serializers.Remove(serializer); } - internal void DeserializePreferences(string serializedPreferences) + internal void SetupWithPreferences(string serializedPreferences) + { + m_Preferences = DeserializePreferences(serializedPreferences); + } + + internal static SerializedPreferences DeserializePreferences(string serializedPreferences, List serializers = null) { var preferences = JsonUtility.FromJson(serializedPreferences); - if (preferences != null) + if (preferences != null && serializers != null) { - m_Preferences = preferences; - - foreach (var serializer in m_Serializers) + foreach (var serializer in serializers) { - Deserialize(serializer); + Deserialize(preferences, serializer); } } + + return preferences; } internal string SerializePreferences() @@ -131,10 +142,10 @@ internal string SerializePreferences() return JsonUtility.ToJson(m_Preferences); } - void Deserialize(ISerializePreferences serializer) + static void Deserialize(SerializedPreferences preferences, ISerializePreferences serializer) { SerializedPreferenceItem item; - if (m_Preferences.items.TryGetValue(serializer.GetType(), out item)) + if (preferences.items.TryGetValue(serializer.GetType(), out item)) { var payload = JsonUtility.FromJson(item.payload, Type.GetType(item.payloadType)); serializer.OnDeserializePreferences(payload); diff --git a/Scripts/Proxies/Data/SerializedProxyFeedback.cs b/Scripts/Proxies/Data/SerializedProxyFeedback.cs new file mode 100644 index 000000000..29d8a353f --- /dev/null +++ b/Scripts/Proxies/Data/SerializedProxyFeedback.cs @@ -0,0 +1,124 @@ +#if UNITY_EDITOR +using System; +using UnityEngine; +using UnityEngine.InputNew; + +namespace UnityEditor.Experimental.EditorVR.Proxies +{ + [Serializable] + class SerializedProxyFeedback + { + public SerializedProxyNodeFeedback leftNode; + public SerializedProxyNodeFeedback rightNode; + } + + /// + /// Used as globally unique identifiers for feedback requests + /// They are used to relate feedback requests to the persistent count of visible presentations used to suppress feedback + /// + [Serializable] + class RequestKey + { + /// + /// The control index used to identify the related affordance + /// + [SerializeField] + VRInputDevice.VRControl m_Control; + + /// + /// The tooltip text that was presented + /// + [SerializeField] + string m_TooltipText; + + public void UpdateValues(ProxyFeedbackRequest request) + { + m_Control = request.control; + m_TooltipText = request.tooltipText; + } + + public bool HasTooltip() + { + return !string.IsNullOrEmpty(m_TooltipText); + } + + public override int GetHashCode() + { + var hashCode = (int)m_Control; + + if (m_TooltipText != null) + hashCode ^= m_TooltipText.GetHashCode(); + + return hashCode; + } + + public override bool Equals(object obj) + { + if (obj == null) + return false; + + if (!(obj is RequestKey)) + return false; + + var key = (RequestKey)obj; + return m_Control == key.m_Control && string.Equals(m_TooltipText, key.m_TooltipText); + } + + public override string ToString() + { + return string.Format("{0}: {1}", m_Control, m_TooltipText); + } + } + + /// + /// Contains per-request persistent data + /// + [Serializable] + class RequestData + { + readonly Action m_OnBecameVisible; + + [SerializeField] + int m_Presentations; + + /// + /// How many times the user viewed the presentation of this type of request + /// + public int presentations + { + get { return m_Presentations; } + set { m_Presentations = value; } + } + + public bool visibleThisPresentation { get; set; } + + public Action onBecameVisible + { + get { return m_OnBecameVisible; } + } + + public RequestData() + { + m_OnBecameVisible = OnBecameVisible; + } + + void OnBecameVisible() + { + if (!visibleThisPresentation) + presentations++; + + visibleThisPresentation = true; + } + } + + /// + /// Used to store persistent data about feedback requests + /// + [Serializable] + class SerializedProxyNodeFeedback + { + public RequestKey[] keys; + public RequestData[] values; + } +} +#endif diff --git a/Scripts/Proxies/Data/SerializedProxyFeedback.cs.meta b/Scripts/Proxies/Data/SerializedProxyFeedback.cs.meta new file mode 100644 index 000000000..77bb88bc5 --- /dev/null +++ b/Scripts/Proxies/Data/SerializedProxyFeedback.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: fc2269803667794408d38030eaccab4c +timeCreated: 1512512089 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Proxies/ProxyNode.cs b/Scripts/Proxies/ProxyNode.cs index 8a41add78..ae154ee99 100644 --- a/Scripts/Proxies/ProxyNode.cs +++ b/Scripts/Proxies/ProxyNode.cs @@ -317,102 +317,6 @@ public void OnDestroy() } } - /// - /// Used as globally unique identifiers for feedback requests - /// They are used to relate feedback requests to the persistent count of visible presentations used to suppress feedback - /// - [Serializable] - internal class RequestKey - { - /// - /// The control index used to identify the related affordance - /// - [SerializeField] - VRControl m_Control; - - /// - /// The tooltip text that was presented - /// - [SerializeField] - string m_TooltipText; - - public void UpdateValues(ProxyFeedbackRequest request) - { - m_Control = request.control; - m_TooltipText = request.tooltipText; - } - - public override int GetHashCode() - { - var hashCode = (int)m_Control; - - if (m_TooltipText != null) - hashCode ^= m_TooltipText.GetHashCode(); - - return hashCode; - } - - public override bool Equals(object obj) - { - if (obj == null) - return false; - - if (!(obj is RequestKey)) - return false; - - var key = (RequestKey)obj; - return m_Control == key.m_Control && string.Equals(m_TooltipText, key.m_TooltipText); - } - } - - /// - /// Contains per-request persistent data - /// - [Serializable] - internal class RequestData - { - readonly Action m_OnBecameVisible; - - [SerializeField] - int m_Presentations; - - /// - /// How many times the user viewed the presentation of this type of request - /// - public int presentations - { - get { return m_Presentations; } - set { m_Presentations = value; } - } - - public bool visibleThisPresentation { get; set; } - - public Action onBecameVisible { get { return m_OnBecameVisible; } } - - public RequestData() - { - m_OnBecameVisible = OnBecameVisible; - } - - void OnBecameVisible() - { - if (!visibleThisPresentation) - presentations++; - - visibleThisPresentation = true; - } - } - - /// - /// Used to store persistent data about feedback requests - /// - [Serializable] - internal class SerializedFeedback - { - public RequestKey[] keys; - public RequestData[] values; - } - const string k_ZWritePropertyName = "_ZWrite"; const float k_LastFacingAngleWeight = 0.1f; // How much extra emphasis to give the last facing angle to prevent 'jitter' when looking at a controller on a boundary @@ -461,7 +365,7 @@ internal class SerializedFeedback FacingDirection m_FacingDirection = FacingDirection.Back; - SerializedFeedback m_SerializedFeedback; + SerializedProxyNodeFeedback m_SerializedFeedback; readonly List m_FeedbackRequests = new List(); readonly Dictionary m_RequestData = new Dictionary(); @@ -848,25 +752,29 @@ public void ClearFeedbackRequests(IRequestFeedback caller) } } - public SerializedFeedback OnSerializePreferences() + public SerializedProxyNodeFeedback OnSerializePreferences() { - if (m_SerializedFeedback != null) + if (m_RequestData.Count == 0) + return m_SerializedFeedback; + + if (m_SerializedFeedback == null) + m_SerializedFeedback = new SerializedProxyNodeFeedback(); + + var keys = new List(); + var values = new List(); + foreach (var kvp in m_RequestData) { - var count = m_RequestData.Count; - var keys = new RequestKey[count]; - var values = new RequestData[count]; - count = 0; - foreach (var kvp in m_RequestData) - { - keys[count] = kvp.Key; - values[count] = kvp.Value; - count++; - } + var requestKey = kvp.Key; + if (!requestKey.HasTooltip()) + continue; - m_SerializedFeedback.keys = keys; - m_SerializedFeedback.values = values; + keys.Add(requestKey); + values.Add(kvp.Value); } + m_SerializedFeedback.keys = keys.ToArray(); + m_SerializedFeedback.values = values.ToArray(); + return m_SerializedFeedback; } @@ -875,7 +783,7 @@ public void OnDeserializePreferences(object obj) if (obj == null) return; - m_SerializedFeedback = (SerializedFeedback)obj; + m_SerializedFeedback = (SerializedProxyNodeFeedback)obj; if (m_SerializedFeedback.keys == null) return; diff --git a/Scripts/Proxies/TwoHandedProxyBase.cs b/Scripts/Proxies/TwoHandedProxyBase.cs index ec0bdbca6..4b3f7b35f 100644 --- a/Scripts/Proxies/TwoHandedProxyBase.cs +++ b/Scripts/Proxies/TwoHandedProxyBase.cs @@ -27,13 +27,6 @@ public enum FacingDirection abstract class TwoHandedProxyBase : MonoBehaviour, IProxy, IFeedbackReceiver, ISetTooltipVisibility, ISetHighlight, ISerializePreferences { - [Serializable] - class SerializedFeedback - { - public ProxyNode.SerializedFeedback leftNode; - public ProxyNode.SerializedFeedback rightNode; - } - [SerializeField] protected GameObject m_LeftHandProxyPrefab; @@ -214,16 +207,22 @@ public object OnSerializePreferences() if (!active) return null; - return new SerializedFeedback + var leftNode = m_LeftProxyNode.OnSerializePreferences(); + var rightNode = m_RightProxyNode.OnSerializePreferences(); + + if (leftNode == null && rightNode == null) + return null; + + return new SerializedProxyFeedback { - leftNode = m_LeftProxyNode.OnSerializePreferences(), - rightNode = m_RightProxyNode.OnSerializePreferences() + leftNode = leftNode, + rightNode = rightNode }; } public void OnDeserializePreferences(object obj) { - var serializedFeedback = (SerializedFeedback)obj; + var serializedFeedback = (SerializedProxyFeedback)obj; m_LeftProxyNode.OnDeserializePreferences(serializedFeedback.leftNode); m_RightProxyNode.OnDeserializePreferences(serializedFeedback.rightNode); From cd85c9dad313dea55bd581e5b64d4445822ba437 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Tue, 5 Dec 2017 17:46:28 -0800 Subject: [PATCH 50/89] Fix exception if loading preferences for a type that doesn't exist --- Scripts/Modules/SerializedPreferencesModule.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Scripts/Modules/SerializedPreferencesModule.cs b/Scripts/Modules/SerializedPreferencesModule.cs index 02b21d070..9395821b1 100644 --- a/Scripts/Modules/SerializedPreferencesModule.cs +++ b/Scripts/Modules/SerializedPreferencesModule.cs @@ -147,7 +147,11 @@ static void Deserialize(SerializedPreferences preferences, ISerializePreferences SerializedPreferenceItem item; if (preferences.items.TryGetValue(serializer.GetType(), out item)) { - var payload = JsonUtility.FromJson(item.payload, Type.GetType(item.payloadType)); + var type = Type.GetType(item.payloadType); + if (type == null) + return; + + var payload = JsonUtility.FromJson(item.payload, type); serializer.OnDeserializePreferences(payload); } } From 8cbc79890f3793af624f1cfaa9fa30b47b5d7539 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Tue, 5 Dec 2017 17:54:20 -0800 Subject: [PATCH 51/89] Also set m_Position in OnEnable --- Scripts/Helpers/VRSmoothCamera.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Scripts/Helpers/VRSmoothCamera.cs b/Scripts/Helpers/VRSmoothCamera.cs index 5125eefb7..e3abbb491 100644 --- a/Scripts/Helpers/VRSmoothCamera.cs +++ b/Scripts/Helpers/VRSmoothCamera.cs @@ -81,9 +81,12 @@ void Start() void OnEnable() { - // Prevent camera from performing a very fast (shortest path) rotational correction when being enabled + // Snap camera to starting position if (m_VRCamera) + { m_Rotation = m_VRCamera.transform.localRotation; + m_Position = m_VRCamera.transform.localPosition; + } } void LateUpdate() From 6ca743775519ab6e428495c7c56a455117cc1c50 Mon Sep 17 00:00:00 2001 From: Jono Forbes Date: Thu, 7 Dec 2017 13:13:48 -0800 Subject: [PATCH 52/89] Add ICustomAlternateMenu to manage display of additional menus appearing on the thumb: Undo & AnnotationTool. --- Menus/UndoMenu/UndoMenu.cs | 6 +- Scripts/Core/EditorVR.Menus.cs | 94 ++++++++++++++++--- Scripts/Core/EditorVR.Tools.cs | 1 - Scripts/Core/EditorVR.cs | 3 +- .../ICustomAlternateMenu.cs | 10 ++ .../ICustomAlternateMenu.cs.meta | 13 +++ Tools/AnnotationTool/AnnotationTool.cs | 24 ++++- 7 files changed, 131 insertions(+), 20 deletions(-) create mode 100644 Scripts/Interfaces/FunctionalityInjection/ICustomAlternateMenu.cs create mode 100644 Scripts/Interfaces/FunctionalityInjection/ICustomAlternateMenu.cs.meta diff --git a/Menus/UndoMenu/UndoMenu.cs b/Menus/UndoMenu/UndoMenu.cs index e2ecc7023..2950e4b17 100644 --- a/Menus/UndoMenu/UndoMenu.cs +++ b/Menus/UndoMenu/UndoMenu.cs @@ -11,8 +11,8 @@ namespace UnityEditor.Experimental.EditorVR.Menus { - sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IMenu, IUsesMenuOrigins, ICustomActionMap, - IControlHaptics, IUsesNode, IConnectInterfaces, IRequestFeedback, IUsesDeviceType + sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IUsesMenuOrigins, ICustomActionMap, + IControlHaptics, IUsesNode, IConnectInterfaces, IRequestFeedback, IUsesDeviceType, ICustomAlternateMenu { const float k_UndoRedoThreshold = 0.5f; const string k_EngageControlName = "Engage"; @@ -52,6 +52,8 @@ sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IMenu, IUsesMenuOrigins, public ActionMap actionMap { get { return m_ActionMap; } } public bool ignoreLocking { get { return false; } } + public int menuPriority { get { return 1; } } + public Transform alternateMenuOrigin { get { return m_AlternateMenuOrigin; } diff --git a/Scripts/Core/EditorVR.Menus.cs b/Scripts/Core/EditorVR.Menus.cs index 2473f1449..1492e90bb 100644 --- a/Scripts/Core/EditorVR.Menus.cs +++ b/Scripts/Core/EditorVR.Menus.cs @@ -96,6 +96,10 @@ public void ConnectInterface(object target, object userData = null) menuOrigins.alternateMenuOrigin = alternateMenuOrigin; } } + + var customAlternateMenu = target as ICustomAlternateMenu; + if (customAlternateMenu != null) + AddRemoveCustomAlternateMenu(customAlternateMenu, rayOrigin, true); } public void DisconnectInterface(object target, object userData = null) @@ -128,6 +132,50 @@ public void DisconnectInterface(object target, object userData = null) var mainMenu = target as IMainMenu; if (mainMenu != null && rayOrigin != null) m_MainMenus.Remove(rayOrigin); + + var customAlternateMenu = target as ICustomAlternateMenu; + if (customAlternateMenu != null) + AddRemoveCustomAlternateMenu(customAlternateMenu, rayOrigin, false); + } + + static void AddRemoveCustomAlternateMenu( + ICustomAlternateMenu customAlternateMenu, Transform rayOrigin, bool addMenu) + { + DeviceData deviceData = null; + foreach (var currentDevice in evr.m_DeviceData) + { + if (currentDevice.rayOrigin == rayOrigin) + { + deviceData = currentDevice; + break; + } + } + + if (deviceData != null) + { + if (addMenu) + { + deviceData.alternateMenus.Add(customAlternateMenu); + deviceData.menuHideData[customAlternateMenu] = new MenuHideData(); + } + else + { + deviceData.alternateMenus.Remove(customAlternateMenu); + deviceData.menuHideData.Remove(customAlternateMenu); + } + + ICustomAlternateMenu highestPriorityCustomAlternateMenu = null; + foreach (var alternateMenu in deviceData.alternateMenus) + { + if (highestPriorityCustomAlternateMenu == null + || alternateMenu.menuPriority >= highestPriorityCustomAlternateMenu.menuPriority) + { + highestPriorityCustomAlternateMenu = alternateMenu; + } + } + + deviceData.highestPriorityCustomAlternateMenu = highestPriorityCustomAlternateMenu; + } } public void LateBindInterfaceMethods(Tools provider) @@ -183,12 +231,10 @@ internal void UpdateMenuVisibilities() { var alternateMenu = deviceData.alternateMenu; var mainMenu = deviceData.mainMenu; - var undoMenu = deviceData.undoMenu; var customMenu = deviceData.customMenu; var menuHideData = deviceData.menuHideData; MenuHideData customMenuHideData = null; MenuHideData alternateMenuData = null; - MenuHideData undoMenuHideData = null; var mainMenuVisible = mainMenu != null && menuHideData[mainMenu].hideFlags == 0; var mainMenuSupressed = mainMenu != null && ((menuHideData[mainMenu].hideFlags & MenuHideFlags.Occluded) != 0); @@ -207,11 +253,10 @@ internal void UpdateMenuVisibilities() customMenuVisible = customMenuHideData.hideFlags == 0; } - var undoMenuVisible = false; - if (undoMenu != null) + var customAlternateMenuVisible = false; + foreach (var customAlternateMenu in deviceData.alternateMenus) { - undoMenuHideData = menuHideData[undoMenu]; - undoMenuVisible = undoMenuHideData.hideFlags == 0; + customAlternateMenuVisible = customAlternateMenuVisible || menuHideData[customAlternateMenu].hideFlags == 0; } // Kick the alternate menu to the other hand if a main menu or custom menu is visible @@ -235,11 +280,25 @@ internal void UpdateMenuVisibilities() if (alternateMenuVisible && (customMenuVisible || mainMenuVisible)) alternateMenuData.hideFlags |= MenuHideFlags.OtherMenu; - // Always show undo menu, unless the radial menu is open. - if (undoMenuVisible && alternateMenuVisible) - undoMenuHideData.hideFlags |= MenuHideFlags.OtherMenu; - else if (!undoMenuVisible && undoMenuHideData != null) - undoMenuHideData.hideFlags = 0; + // Temporarily hide custom alternate menu if radial menu is open. + if (customAlternateMenuVisible && alternateMenuVisible) + { + foreach (var customAlternateMenu in deviceData.alternateMenus) + { + customAlternateMenu.menuHideFlags |= MenuHideFlags.OtherMenu; + } + } + else + { + foreach (var customAlternateMenu in deviceData.alternateMenus) + { + // Always display the highest-priority custom alternate menu, and hide all others. + if (customAlternateMenu == deviceData.highestPriorityCustomAlternateMenu) + menuHideData[customAlternateMenu].hideFlags = 0; + else + menuHideData[customAlternateMenu].hideFlags |= MenuHideFlags.OtherMenu; + } + } // Check if menu bounds overlap with any workspace colliders foreach (var kvp in menuHideData) @@ -297,10 +356,15 @@ internal void UpdateMenuVisibilities() var customMenu = deviceData.customMenu; if (customMenu != null) customMenu.menuHideFlags = deviceData.menuHideData[customMenu].hideFlags; - - var undoMenu = deviceData.undoMenu; - if (undoMenu != null) - undoMenu.menuHideFlags = deviceData.menuHideData[undoMenu].hideFlags; + + var customAlternateMenus = deviceData.alternateMenus; + if (customAlternateMenus != null && customAlternateMenus.Count > 0) + { + foreach (var customAlternateMenu in customAlternateMenus) + { + customAlternateMenu.menuHideFlags = deviceData.menuHideData[customAlternateMenu].hideFlags; + } + } UpdateAlternateMenuForDevice(deviceData); Rays.UpdateRayForDevice(deviceData, deviceData.rayOrigin); diff --git a/Scripts/Core/EditorVR.Tools.cs b/Scripts/Core/EditorVR.Tools.cs index 4156db950..6930812e8 100644 --- a/Scripts/Core/EditorVR.Tools.cs +++ b/Scripts/Core/EditorVR.Tools.cs @@ -137,7 +137,6 @@ internal void SpawnDefaultTools(IProxy proxy) alternateMenu.itemWasSelected += Menus.UpdateAlternateMenuOnSelectionChanged; var undoMenu = menus.SpawnMenu(rayOrigin); - deviceData.undoMenu = undoMenu; menuHideData[undoMenu] = new Menus.MenuHideData(); // Setup ToolsMenu diff --git a/Scripts/Core/EditorVR.cs b/Scripts/Core/EditorVR.cs index 56a35f6cf..e40090096 100644 --- a/Scripts/Core/EditorVR.cs +++ b/Scripts/Core/EditorVR.cs @@ -72,10 +72,11 @@ class DeviceData public readonly Stack toolData = new Stack(); public IMainMenu mainMenu; public IAlternateMenu alternateMenu; - public IMenu undoMenu; public ITool currentTool; public IMenu customMenu; public IToolsMenu toolsMenu; + public List alternateMenus = new List(); + public ICustomAlternateMenu highestPriorityCustomAlternateMenu; public readonly Dictionary menuHideData = new Dictionary(); } diff --git a/Scripts/Interfaces/FunctionalityInjection/ICustomAlternateMenu.cs b/Scripts/Interfaces/FunctionalityInjection/ICustomAlternateMenu.cs new file mode 100644 index 000000000..c73562a73 --- /dev/null +++ b/Scripts/Interfaces/FunctionalityInjection/ICustomAlternateMenu.cs @@ -0,0 +1,10 @@ +#if UNITY_EDITOR + +namespace UnityEditor.Experimental.EditorVR +{ + public interface ICustomAlternateMenu : IMenu + { + int menuPriority { get; } + } +} +#endif diff --git a/Scripts/Interfaces/FunctionalityInjection/ICustomAlternateMenu.cs.meta b/Scripts/Interfaces/FunctionalityInjection/ICustomAlternateMenu.cs.meta new file mode 100644 index 000000000..1f2b1479c --- /dev/null +++ b/Scripts/Interfaces/FunctionalityInjection/ICustomAlternateMenu.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: d51c00377380a6e4e8861d1bdee23cd9 +timeCreated: 1512422665 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/AnnotationTool/AnnotationTool.cs b/Tools/AnnotationTool/AnnotationTool.cs index e88082a0c..d2714c9e5 100644 --- a/Tools/AnnotationTool/AnnotationTool.cs +++ b/Tools/AnnotationTool/AnnotationTool.cs @@ -5,6 +5,7 @@ using System.Linq; using UnityEditor.Experimental.EditorVR.Core; using UnityEditor.Experimental.EditorVR.Extensions; +using UnityEditor.Experimental.EditorVR.Menus; using UnityEditor.Experimental.EditorVR.Proxies; using UnityEditor.Experimental.EditorVR.UI; using UnityEditor.Experimental.EditorVR.Utilities; @@ -18,7 +19,7 @@ namespace UnityEditor.Experimental.EditorVR.Tools public class AnnotationTool : MonoBehaviour, ITool, ICustomActionMap, IUsesRayOrigin, IRayVisibilitySettings, IUsesRayOrigins, IInstantiateUI, IUsesMenuOrigins, IUsesCustomMenuOrigins, IUsesViewerScale, IUsesSpatialHash, IIsHoveringOverUI, IMultiDeviceTool, IUsesDeviceType, ISettingsMenuItemProvider, ISerializePreferences, ILinkedObject, - IUsesNode, IRequestFeedback + IUsesNode, IRequestFeedback, ICustomAlternateMenu { [Serializable] class Preferences @@ -114,6 +115,7 @@ public float brushSize Toggle m_TransformToggle; Toggle m_MeshToggle; bool m_BlockValueChangedListener; + MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; public bool primary { private get; set; } public Transform rayOrigin { get; set; } @@ -130,6 +132,24 @@ public float brushSize public GameObject settingsMenuItemPrefab { get { return m_SettingsMenuItemPrefab; } } + public int menuPriority { get { return 2; } } + + public MenuHideFlags menuHideFlags + { + get { return m_MenuHideFlags; } + set + { + if (m_MenuHideFlags != value) + { + m_MenuHideFlags = value; + gameObject.SetActive(value == 0); + } + } + } + + public GameObject menuContent { get { return gameObject; } } + public Bounds localBounds { get; private set; } + public GameObject settingsMenuItemInstance { set @@ -221,6 +241,8 @@ void CleanUpNames() void Start() { + localBounds = ObjectUtils.GetBounds(transform); + // Clear selection so we can't manipulate things Selection.activeGameObject = null; From a84850814bb45d222ddb1fd303e05f33329d6dd3 Mon Sep 17 00:00:00 2001 From: Jono Forbes Date: Thu, 7 Dec 2017 13:15:52 -0800 Subject: [PATCH 53/89] Rename DeviceData.alternateMenus to customAlternateMenus. --- Scripts/Core/EditorVR.Menus.cs | 14 +++++++------- Scripts/Core/EditorVR.cs | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Scripts/Core/EditorVR.Menus.cs b/Scripts/Core/EditorVR.Menus.cs index 1492e90bb..f20c3ba34 100644 --- a/Scripts/Core/EditorVR.Menus.cs +++ b/Scripts/Core/EditorVR.Menus.cs @@ -155,17 +155,17 @@ static void AddRemoveCustomAlternateMenu( { if (addMenu) { - deviceData.alternateMenus.Add(customAlternateMenu); + deviceData.customAlternateMenus.Add(customAlternateMenu); deviceData.menuHideData[customAlternateMenu] = new MenuHideData(); } else { - deviceData.alternateMenus.Remove(customAlternateMenu); + deviceData.customAlternateMenus.Remove(customAlternateMenu); deviceData.menuHideData.Remove(customAlternateMenu); } ICustomAlternateMenu highestPriorityCustomAlternateMenu = null; - foreach (var alternateMenu in deviceData.alternateMenus) + foreach (var alternateMenu in deviceData.customAlternateMenus) { if (highestPriorityCustomAlternateMenu == null || alternateMenu.menuPriority >= highestPriorityCustomAlternateMenu.menuPriority) @@ -254,7 +254,7 @@ internal void UpdateMenuVisibilities() } var customAlternateMenuVisible = false; - foreach (var customAlternateMenu in deviceData.alternateMenus) + foreach (var customAlternateMenu in deviceData.customAlternateMenus) { customAlternateMenuVisible = customAlternateMenuVisible || menuHideData[customAlternateMenu].hideFlags == 0; } @@ -283,14 +283,14 @@ internal void UpdateMenuVisibilities() // Temporarily hide custom alternate menu if radial menu is open. if (customAlternateMenuVisible && alternateMenuVisible) { - foreach (var customAlternateMenu in deviceData.alternateMenus) + foreach (var customAlternateMenu in deviceData.customAlternateMenus) { customAlternateMenu.menuHideFlags |= MenuHideFlags.OtherMenu; } } else { - foreach (var customAlternateMenu in deviceData.alternateMenus) + foreach (var customAlternateMenu in deviceData.customAlternateMenus) { // Always display the highest-priority custom alternate menu, and hide all others. if (customAlternateMenu == deviceData.highestPriorityCustomAlternateMenu) @@ -357,7 +357,7 @@ internal void UpdateMenuVisibilities() if (customMenu != null) customMenu.menuHideFlags = deviceData.menuHideData[customMenu].hideFlags; - var customAlternateMenus = deviceData.alternateMenus; + var customAlternateMenus = deviceData.customAlternateMenus; if (customAlternateMenus != null && customAlternateMenus.Count > 0) { foreach (var customAlternateMenu in customAlternateMenus) diff --git a/Scripts/Core/EditorVR.cs b/Scripts/Core/EditorVR.cs index e40090096..801b4dc59 100644 --- a/Scripts/Core/EditorVR.cs +++ b/Scripts/Core/EditorVR.cs @@ -75,7 +75,7 @@ class DeviceData public ITool currentTool; public IMenu customMenu; public IToolsMenu toolsMenu; - public List alternateMenus = new List(); + public List customAlternateMenus = new List(); public ICustomAlternateMenu highestPriorityCustomAlternateMenu; public readonly Dictionary menuHideData = new Dictionary(); } From 984e59925a913c34fe0d2493618c66f7a3610f10 Mon Sep 17 00:00:00 2001 From: Jono Forbes Date: Thu, 7 Dec 2017 13:35:35 -0800 Subject: [PATCH 54/89] Don't process Undo input if menu is hidden. --- Menus/UndoMenu/Scripts/UndoMenuUI.cs | 2 -- Menus/UndoMenu/UndoMenu.cs | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Menus/UndoMenu/Scripts/UndoMenuUI.cs b/Menus/UndoMenu/Scripts/UndoMenuUI.cs index 2369bb8a6..fa2037865 100644 --- a/Menus/UndoMenu/Scripts/UndoMenuUI.cs +++ b/Menus/UndoMenu/Scripts/UndoMenuUI.cs @@ -1,7 +1,5 @@ #if UNITY_EDITOR using System.Collections; -using System.Collections.Generic; -using System.Linq; using UnityEditor.Experimental.EditorVR.Extensions; using UnityEditor.Experimental.EditorVR.Utilities; using UnityEngine; diff --git a/Menus/UndoMenu/UndoMenu.cs b/Menus/UndoMenu/UndoMenu.cs index 2950e4b17..4ce1c2ccc 100644 --- a/Menus/UndoMenu/UndoMenu.cs +++ b/Menus/UndoMenu/UndoMenu.cs @@ -100,6 +100,9 @@ void Start() public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl) { + if (!m_UndoMenuUI.visible) + return; + var undoMenuInput = (UndoMenuInput)input; if (undoMenuInput == null) { From db6f51ee316f97d2da1763228616268083203afb Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Thu, 7 Dec 2017 14:50:45 -0800 Subject: [PATCH 55/89] change how we add to the menuhide dict in devicedata --- Scripts/Core/EditorVR.Menus.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Scripts/Core/EditorVR.Menus.cs b/Scripts/Core/EditorVR.Menus.cs index f20c3ba34..1b2b34245 100644 --- a/Scripts/Core/EditorVR.Menus.cs +++ b/Scripts/Core/EditorVR.Menus.cs @@ -156,7 +156,12 @@ static void AddRemoveCustomAlternateMenu( if (addMenu) { deviceData.customAlternateMenus.Add(customAlternateMenu); - deviceData.menuHideData[customAlternateMenu] = new MenuHideData(); + + MenuHideData tempData; + if (!deviceData.menuHideData.TryGetValue(customAlternateMenu, out tempData)) + { + deviceData.menuHideData.Add(customAlternateMenu, new MenuHideData()); + } } else { From 38d38e23eba2c1fda14ce2561f4d30cae1528279 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Thu, 7 Dec 2017 15:38:48 -0800 Subject: [PATCH 56/89] PR feedback --- Editor/ProxyFeedbackEditor.cs | 2 +- Scripts/Modules/SerializedPreferencesModule.cs | 4 ++-- Scripts/Proxies/Data/SerializedProxyFeedback.cs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Editor/ProxyFeedbackEditor.cs b/Editor/ProxyFeedbackEditor.cs index f474debcf..8dd5b1898 100644 --- a/Editor/ProxyFeedbackEditor.cs +++ b/Editor/ProxyFeedbackEditor.cs @@ -8,7 +8,7 @@ namespace UnityEditor.Experimental.EditorVR.UI { sealed class ProxyFeedbackEditor : EditorWindow { - Dictionary m_SerializedFeedback = new Dictionary(); + readonly Dictionary m_SerializedFeedback = new Dictionary(); Vector2 m_Scroll; [MenuItem("Edit/Project Settings/EditorXR/Proxy Feedback")] diff --git a/Scripts/Modules/SerializedPreferencesModule.cs b/Scripts/Modules/SerializedPreferencesModule.cs index 9395821b1..365dafaec 100644 --- a/Scripts/Modules/SerializedPreferencesModule.cs +++ b/Scripts/Modules/SerializedPreferencesModule.cs @@ -148,8 +148,8 @@ static void Deserialize(SerializedPreferences preferences, ISerializePreferences if (preferences.items.TryGetValue(serializer.GetType(), out item)) { var type = Type.GetType(item.payloadType); - if (type == null) - return; + if (type == null) + return; var payload = JsonUtility.FromJson(item.payload, type); serializer.OnDeserializePreferences(payload); diff --git a/Scripts/Proxies/Data/SerializedProxyFeedback.cs b/Scripts/Proxies/Data/SerializedProxyFeedback.cs index 29d8a353f..a00dc1ad7 100644 --- a/Scripts/Proxies/Data/SerializedProxyFeedback.cs +++ b/Scripts/Proxies/Data/SerializedProxyFeedback.cs @@ -76,11 +76,11 @@ public override string ToString() [Serializable] class RequestData { - readonly Action m_OnBecameVisible; - [SerializeField] int m_Presentations; + readonly Action m_OnBecameVisible; + /// /// How many times the user viewed the presentation of this type of request /// From 8ee55323ab348f3ce1f99422098f9cd08296b76a Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Thu, 7 Dec 2017 16:24:20 -0800 Subject: [PATCH 57/89] Fix a bug where dropping items into the root of the scene in the Hierarchy Workspace caused a NullReferenceException --- Workspaces/HierarchyWorkspace/Scripts/HierarchyListItem.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Workspaces/HierarchyWorkspace/Scripts/HierarchyListItem.cs b/Workspaces/HierarchyWorkspace/Scripts/HierarchyListItem.cs index 4b02ad769..22dbbf42d 100644 --- a/Workspaces/HierarchyWorkspace/Scripts/HierarchyListItem.cs +++ b/Workspaces/HierarchyWorkspace/Scripts/HierarchyListItem.cs @@ -509,8 +509,11 @@ void ReceiveDrop(BaseHandle handle, object dropObject) { var index = data.index; var gameObject = data.gameObject; + Transform transform = null; + if (gameObject != null) // In case we are dropping into the scene root + transform = gameObject.transform; + var dropGameObject = dropData.gameObject; - var transform = gameObject.transform; var dropTransform = dropGameObject.transform; // OnHierarchyChanged doesn't happen until next frame--delay removal of the extra space From c4a3d97252122761cdaa0905b1cef93460dba7cc Mon Sep 17 00:00:00 2001 From: Jono Forbes Date: Thu, 7 Dec 2017 16:32:05 -0800 Subject: [PATCH 58/89] Fix EXR lockup on hiding AnnotationTool, by hiding AnnotationTool UI objects, not gameObject (EXR root). --- Tools/AnnotationTool/AnnotationTool.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Tools/AnnotationTool/AnnotationTool.cs b/Tools/AnnotationTool/AnnotationTool.cs index d2714c9e5..22973271f 100644 --- a/Tools/AnnotationTool/AnnotationTool.cs +++ b/Tools/AnnotationTool/AnnotationTool.cs @@ -142,7 +142,19 @@ public MenuHideFlags menuHideFlags if (m_MenuHideFlags != value) { m_MenuHideFlags = value; - gameObject.SetActive(value == 0); + var visible = m_MenuHideFlags == 0; + + if (m_ColorPicker) + m_ColorPicker.gameObject.SetActive(visible); + + if (m_BrushSizeUI) + m_BrushSizeUI.gameObject.SetActive(visible); + + if (m_ColorPickerActivator) + m_ColorPickerActivator.SetActive(visible); + + if (m_AnnotationPointer) + m_AnnotationPointer.gameObject.SetActive(visible); } } } From e3d1c04001df812ec40a9ccf080cd8b8268c25a6 Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Thu, 7 Dec 2017 17:04:44 -0800 Subject: [PATCH 59/89] update mainmenu after conflict --- Menus/MainMenu/MainMenu.cs | 422 ------------------------------------- 1 file changed, 422 deletions(-) diff --git a/Menus/MainMenu/MainMenu.cs b/Menus/MainMenu/MainMenu.cs index dfc2e17a6..166ea3420 100644 --- a/Menus/MainMenu/MainMenu.cs +++ b/Menus/MainMenu/MainMenu.cs @@ -1,424 +1,3 @@ -<<<<<<< HEAD -#if UNITY_EDITOR -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.Experimental.EditorVR.Core; -using UnityEditor.Experimental.EditorVR.Proxies; -using UnityEditor.Experimental.EditorVR.Utilities; -using UnityEditor.Experimental.EditorVR.Workspaces; -using UnityEngine; -using UnityEngine.InputNew; - -namespace UnityEditor.Experimental.EditorVR.Menus -{ - sealed class MainMenu : MonoBehaviour, IMainMenu, IConnectInterfaces, IInstantiateUI, ICreateWorkspace, - ICustomActionMap, IUsesMenuOrigins, IUsesDeviceType, IControlHaptics, IUsesNode, IRayToNode, IUsesRayOrigin, - IRequestFeedback - { - const string k_SettingsMenuSectionName = "Settings"; - - [SerializeField] - ActionMap m_ActionMap; - - [SerializeField] - HapticPulse m_FaceRotationPulse; - - [SerializeField] - HapticPulse m_ShowPulse; - - [SerializeField] - HapticPulse m_HidePulse; - - [SerializeField] - MainMenuUI m_MainMenuPrefab; - - [SerializeField] - HapticPulse m_ButtonClickPulse; - - [SerializeField] - HapticPulse m_ButtonHoverPulse; - - Transform m_AlternateMenuOrigin; - Transform m_MenuOrigin; - MainMenuUI m_MainMenuUI; - float m_LastRotationInput; - MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; - readonly Dictionary m_ToolButtons = new Dictionary(); - readonly Dictionary m_SettingsMenus = new Dictionary(); - readonly Dictionary m_SettingsMenuItems = new Dictionary(); - - readonly BindingDictionary m_Controls = new BindingDictionary(); - - public List menuTools { private get; set; } - public List menuWorkspaces { private get; set; } - public Dictionary, ISettingsMenuProvider> settingsMenuProviders { get; set; } - public Dictionary, ISettingsMenuItemProvider> settingsMenuItemProviders { get; set; } - public List menuActions { get; set; } - public Transform targetRayOrigin { private get; set; } - public Node node { get; set; } - - public GameObject menuContent { get { return m_MainMenuUI.gameObject; } } - - public Transform rayOrigin { private get; set; } - - public Bounds localBounds { get { return m_MainMenuUI.localBounds; } } - - public bool focus { get { return m_MainMenuUI.hovering; } } - - public ActionMap actionMap { get { return m_ActionMap; } } - public bool ignoreLocking { get { return false; } } - - public Transform menuOrigin - { - get { return m_MenuOrigin; } - set - { - m_MenuOrigin = value; - if (m_MainMenuUI) - m_MainMenuUI.menuOrigin = value; - } - } - - public Transform alternateMenuOrigin - { - get { return m_AlternateMenuOrigin; } - set - { - m_AlternateMenuOrigin = value; - if (m_MainMenuUI) - m_MainMenuUI.alternateMenuOrigin = value; - } - } - - public MenuHideFlags menuHideFlags - { - get { return m_MenuHideFlags; } - set - { - var wasVisible = m_MenuHideFlags == 0; - var wasPermanent = (m_MenuHideFlags & MenuHideFlags.Hidden) != 0; - if (m_MenuHideFlags != value) - { - m_MenuHideFlags = value; - var visible = value == 0; - if (m_MainMenuUI) - { - var isPermanent = (value & MenuHideFlags.Hidden) != 0; - m_MainMenuUI.visible = visible; - if (wasPermanent && visible || wasVisible && isPermanent) - SendVisibilityPulse(); - } - - if (visible) - ShowFeedback(); - else - this.ClearFeedbackRequests(); - } - } - } - - void Awake() - { - m_MainMenuUI = this.InstantiateUI(m_MainMenuPrefab.gameObject).GetComponent(); - this.ConnectInterfaces(m_MainMenuUI); - m_MainMenuUI.alternateMenuOrigin = alternateMenuOrigin; - m_MainMenuUI.menuOrigin = menuOrigin; - m_MainMenuUI.Setup(); - - InputUtils.GetBindingDictionaryFromActionMap(m_ActionMap, m_Controls); - } - - void Start() - { - CreateFaceButtons(); - UpdateToolButtons(); - } - - public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl) - { - if (!m_MainMenuUI.visible) - return; - - var mainMenuInput = (MainMenuInput)input; - var rotationInput = -mainMenuInput.rotate.rawValue; - - consumeControl(mainMenuInput.rotate); - consumeControl(mainMenuInput.blockY); - - const float kFlickDeltaThreshold = 0.5f; - if ((this.GetDeviceType() != DeviceType.Vive && Mathf.Abs(rotationInput) >= kFlickDeltaThreshold - && Mathf.Abs(m_LastRotationInput) < kFlickDeltaThreshold) || mainMenuInput.flickFace.wasJustReleased) - { - m_MainMenuUI.targetFaceIndex += (int)Mathf.Sign(rotationInput); - this.Pulse(node, m_FaceRotationPulse); - } - - if (m_MenuHideFlags == 0) - consumeControl(mainMenuInput.flickFace); - - m_LastRotationInput = rotationInput; - } - - void OnDestroy() - { - if (m_MainMenuUI) - ObjectUtils.Destroy(m_MainMenuUI.gameObject); - } - - void CreateFaceButtons() - { - var types = new HashSet(); - types.UnionWith(menuTools); - types.UnionWith(menuWorkspaces); - types.UnionWith(settingsMenuProviders.Keys.Select(provider => provider.Key)); - types.UnionWith(settingsMenuItemProviders.Keys.Select(provider => provider.Key)); - - foreach (var type in types) - { - var customMenuAttribute = (MainMenuItemAttribute)type.GetCustomAttributes(typeof(MainMenuItemAttribute), false).FirstOrDefault(); - if (customMenuAttribute != null && !customMenuAttribute.shown) - continue; - - var isTool = typeof(ITool).IsAssignableFrom(type) && menuTools.Contains(type); - var isWorkspace = typeof(Workspace).IsAssignableFrom(type); - var isSettingsProvider = typeof(ISettingsMenuProvider).IsAssignableFrom(type); - var isSettingsItemProvider = typeof(ISettingsMenuItemProvider).IsAssignableFrom(type); - - ITooltip tooltip = null; - MainMenuUI.ButtonData buttonData = null; - - var selectedType = type; // Local variable for closure - if (customMenuAttribute != null && customMenuAttribute.shown) - { - tooltip = customMenuAttribute.tooltip; - - buttonData = new MainMenuUI.ButtonData(customMenuAttribute.name) - { - sectionName = customMenuAttribute.sectionName, - description = customMenuAttribute.description - }; - } - - if (isTool) - { - if (buttonData == null) - buttonData = new MainMenuUI.ButtonData(type.Name); - - var mainMenuButton = CreateFaceButton(buttonData, tooltip, () => - { - if (targetRayOrigin) - { - this.SelectTool(targetRayOrigin, selectedType, - hideMenu: typeof(IInstantiateMenuUI).IsAssignableFrom(selectedType)); - UpdateToolButtons(); - } - }); - - m_ToolButtons[type] = mainMenuButton; - - // Assign Tools Menu button preview properties - if (mainMenuButton != null) - mainMenuButton.toolType = selectedType; - } - - if (isWorkspace) - { - // For workspaces that haven't specified a custom attribute, do some menu categorization automatically - if (buttonData == null) - buttonData = new MainMenuUI.ButtonData(type.Name) { sectionName = "Workspaces" }; - - CreateFaceButton(buttonData, tooltip, () => { this.CreateWorkspace(selectedType); }); - } - - if (isSettingsProvider) - { - foreach (var providerPair in settingsMenuProviders) - { - var kvp = providerPair.Key; - if (kvp.Key == type && (kvp.Value == null || kvp.Value == rayOrigin)) - AddSettingsMenu(providerPair.Value, buttonData, tooltip); - } - } - - if (isSettingsItemProvider) - { - foreach (var providerPair in settingsMenuItemProviders) - { - var kvp = providerPair.Key; - if (kvp.Key == type && (kvp.Value == null || kvp.Value == rayOrigin)) - AddSettingsMenuItem(providerPair.Value); - } - } - } - } - - MainMenuButton CreateFaceButton(MainMenuUI.ButtonData buttonData, ITooltip tooltip, Action buttonClickCallback) - { - var mainMenuButton = m_MainMenuUI.CreateFaceButton(buttonData); - if (mainMenuButton == null) - return null; - - var button = mainMenuButton.button; - button.onClick.RemoveAllListeners(); - button.onClick.AddListener(() => - { - if (m_MenuHideFlags == 0) - buttonClickCallback(); - }); - - mainMenuButton.hovered += OnButtonHovered; - mainMenuButton.clicked += OnButtonClicked; - mainMenuButton.tooltip = tooltip; - - return mainMenuButton; - } - - void UpdateToolButtons() - { - foreach (var kvp in m_ToolButtons) - { - kvp.Value.selected = this.IsToolActive(targetRayOrigin, kvp.Key); - } - } - - void OnButtonClicked(Transform rayOrigin) - { - this.Pulse(this.RequestNodeFromRayOrigin(rayOrigin), m_ButtonClickPulse); - } - - void OnButtonHovered(Transform rayOrigin, Type buttonType, string buttonDescription) - { - this.Pulse(this.RequestNodeFromRayOrigin(rayOrigin), m_ButtonHoverPulse); - - // Pass the pointer which is over us, so this information can supply context (e.g. selecting a tool for a different hand) - // Enable preview-mode on a Tools Menu button; Display on the opposite proxy device by evaluating the entering RayOrigin - // Disable any existing previews being displayed in ToolsMenus - this.ClearToolMenuButtonPreview(); - - if (buttonType != null && rayOrigin != null) - this.PreviewInToolMenuButton(rayOrigin, buttonType, buttonDescription); - } - - void OnToggleHovered(Transform rayOrigin) - { - this.Pulse(this.RequestNodeFromRayOrigin(rayOrigin), m_ButtonHoverPulse); - } - - void SendVisibilityPulse() - { - this.Pulse(node, m_MenuHideFlags == 0 ? m_HidePulse : m_ShowPulse); - } - - public void AddSettingsMenu(ISettingsMenuProvider provider) - { - var type = provider.GetType(); - var customMenuAttribute = (MainMenuItemAttribute)type.GetCustomAttributes(typeof(MainMenuItemAttribute), false).FirstOrDefault(); - - ITooltip tooltip = null; - MainMenuUI.ButtonData buttonData; - if (customMenuAttribute != null && customMenuAttribute.shown) - { - tooltip = customMenuAttribute.tooltip; - - buttonData = new MainMenuUI.ButtonData(customMenuAttribute.name) - { - sectionName = customMenuAttribute.sectionName, - description = customMenuAttribute.description - }; - } - else - { - buttonData = new MainMenuUI.ButtonData(type.Name); - } - - AddSettingsMenu(provider, buttonData, tooltip); - } - - void AddSettingsMenu(ISettingsMenuProvider provider, MainMenuUI.ButtonData buttonData, ITooltip tooltip) - { - buttonData.sectionName = k_SettingsMenuSectionName; - - var button = CreateFaceButton(buttonData, tooltip, () => - { - var instance = m_MainMenuUI.AddSubmenu(k_SettingsMenuSectionName, provider.settingsMenuPrefab); - m_SettingsMenus[provider] = instance; - provider.settingsMenuInstance = instance; - AddToggleHaptics(instance); - }); - - button.hovered += OnButtonHovered; - button.clicked += OnButtonClicked; - } - - void AddToggleHaptics(GameObject menuInstance) - { - var toggles = menuInstance.GetComponentsInChildren(); - if (toggles != null && toggles.Length > 0) - { - foreach (var toggle in toggles) - { - toggle.hovered += OnToggleHovered; - toggle.clicked += OnButtonClicked; - } - } - } - - public void RemoveSettingsMenu(ISettingsMenuProvider provider) - { - GameObject instance; - if (m_SettingsMenus.TryGetValue(provider, out instance)) - { - if (instance) - ObjectUtils.Destroy(instance); - - m_SettingsMenus.Remove(provider); - } - provider.settingsMenuInstance = null; - } - - public void AddSettingsMenuItem(ISettingsMenuItemProvider provider) - { - var instance = m_MainMenuUI.CreateCustomButton(provider.settingsMenuItemPrefab, k_SettingsMenuSectionName); - m_SettingsMenuItems[provider] = instance; - provider.settingsMenuItemInstance = instance; - AddToggleHaptics(instance); - } - - public void RemoveSettingsMenuItem(ISettingsMenuItemProvider provider) - { - GameObject instance; - if (m_SettingsMenuItems.TryGetValue(provider, out instance)) - { - if (instance) - ObjectUtils.Destroy(instance); - - m_SettingsMenuItems.Remove(provider); - } - provider.settingsMenuItemInstance = null; - } - - void ShowFeedback() - { - var tooltipText = this.GetDeviceType() == DeviceType.Vive ? "Press to Rotate Menu" : "Rotate Menu"; - List controls; - if (m_Controls.TryGetValue("FlickFace", out controls)) - { - foreach (var id in controls) - { - this.AddFeedbackRequest(new ProxyFeedbackRequest - { - control = id, - node = node, - tooltipText = tooltipText - }); - } - } - } - } -} -#endif -======= #if UNITY_EDITOR using System; using System.Collections.Generic; @@ -814,4 +393,3 @@ void ShowFeedback() } } #endif ->>>>>>> development From 5332812fc4ef634dc8b964987ee39f07133ca5ae Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Thu, 7 Dec 2017 17:29:01 -0800 Subject: [PATCH 60/89] Convert settings items to TextMeshPro; Fix Snapping Settings Menu not graying out text when disabled --- .../Modules/FeedbackModule/FeedbackModule.cs | 16 +- .../Modules/FeedbackModule/SettingsUI.prefab | 151 +++++-- .../Modules/SnappingModule/SnappingModule.cs | 4 +- .../AnnotationTool/Prefabs/SettingsUI.prefab | 417 ++++++++++++++---- .../LocomotionTool/Prefabs/SettingsUI.prefab | 415 +++++++++++++---- Tools/SelectionTool/Prefabs/SettingsUI.prefab | 417 ++++++++++++++---- 6 files changed, 1111 insertions(+), 309 deletions(-) diff --git a/Scripts/Modules/FeedbackModule/FeedbackModule.cs b/Scripts/Modules/FeedbackModule/FeedbackModule.cs index e98ef4c69..6770df03e 100644 --- a/Scripts/Modules/FeedbackModule/FeedbackModule.cs +++ b/Scripts/Modules/FeedbackModule/FeedbackModule.cs @@ -1,11 +1,18 @@ #if UNITY_EDITOR using System; using System.Collections.Generic; +using UnityEditor.Experimental.EditorVR; using UnityEditor.Experimental.EditorVR.Core; using UnityEditor.Experimental.EditorVR.Handles; using UnityEngine; using UnityEngine.UI; +#if INCLUDE_TEXT_MESH_PRO +using TMPro; +#endif + +[assembly: OptionalDependency("TMPro.TextMeshProUGUI", "INCLUDE_TEXT_MESH_PRO")] + namespace UnityEditor.Experimental.EditorVR { public abstract class FeedbackRequest @@ -49,8 +56,10 @@ public GameObject settingsMenuItemInstance if (m_Preferences != null) toggle.isOn = m_Preferences.enabled; - m_Toggles.Add(toggle); - var label = value.GetComponentInChildren(); + m_Toggles.Add(toggle); + +#if INCLUDE_TEXT_MESH_PRO + var label = value.GetComponentInChildren(); const string feedbackEnabled = "Feedback enabled"; const string feedbackDisabled = "Feedback disabled"; @@ -65,7 +74,8 @@ public GameObject settingsMenuItemInstance var handle = value.GetComponent(); handle.hoverStarted += (baseHandle, data) => { label.text = m_Preferences.enabled ? disableFeedback : enableFeedback; }; - handle.hoverEnded += (baseHandle, data) => { label.text = m_Preferences.enabled ? feedbackEnabled : feedbackDisabled; }; + handle.hoverEnded += (baseHandle, data) => { label.text = m_Preferences.enabled ? feedbackEnabled : feedbackDisabled; }; +#endif } } diff --git a/Scripts/Modules/FeedbackModule/SettingsUI.prefab b/Scripts/Modules/FeedbackModule/SettingsUI.prefab index c6f8dd9d2..428a15cf7 100644 --- a/Scripts/Modules/FeedbackModule/SettingsUI.prefab +++ b/Scripts/Modules/FeedbackModule/SettingsUI.prefab @@ -20,7 +20,7 @@ GameObject: m_Component: - component: {fileID: 224171904768544026} - component: {fileID: 222812621535630740} - - component: {fileID: 114103337935952270} + - component: {fileID: 114454282082524566} m_Layer: 5 m_Name: Label m_TagString: Untagged @@ -80,39 +80,6 @@ GameObject: m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!114 &114103337935952270 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1082264891174920} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 2100000, guid: dec2d25be9058334c91a0402762efa61, type: 2} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 0 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, - Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_FontData: - m_Font: {fileID: 12800000, guid: 013679fd6ee2085428a7f896aa7b50cc, type: 3} - m_FontSize: 20 - m_FontStyle: 0 - m_BestFit: 0 - m_MinSize: 10 - m_MaxSize: 40 - m_Alignment: 3 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: Feedback enabled --- !u!114 &114126329478329400 MonoBehaviour: m_ObjectHideFlags: 1 @@ -152,6 +119,118 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_SelectionFlags: 3 +--- !u!114 &114454282082524566 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1082264891174920} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Feedback enabled + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: ea721564999c75441b5b3aa01ae88f76, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 5be343b145ab9dd42821b06c75f9a60c, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 20 + m_fontSizeBase: 20 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 513 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 114454282082524566} + characterCount: 16 + spriteCount: 0 + spaceCount: 1 + wordCount: 2 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_havePropertiesChanged: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 1 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} --- !u!114 &114548669865996182 MonoBehaviour: m_ObjectHideFlags: 1 @@ -320,6 +399,6 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 0, y: 411.55017} - m_SizeDelta: {x: 263.2, y: 45} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 263.2, y: 60} m_Pivot: {x: 0.5, y: 0.5} diff --git a/Scripts/Modules/SnappingModule/SnappingModule.cs b/Scripts/Modules/SnappingModule/SnappingModule.cs index 6c00c074b..ef05bd6d1 100644 --- a/Scripts/Modules/SnappingModule/SnappingModule.cs +++ b/Scripts/Modules/SnappingModule/SnappingModule.cs @@ -952,10 +952,12 @@ void SetDependentTogglesGhosted() toggle.graphic.gameObject.SetActive(!m_Preferences.disableAll); } - foreach (var text in m_SnappingModuleSettingsUI.GetComponentsInChildren(true)) +#if INCLUDE_TEXT_MESH_PRO + foreach (var text in m_SnappingModuleSettingsUI.GetComponentsInChildren(true)) { text.color = m_Preferences.disableAll ? Color.gray : Color.white; } +#endif } void SetSessionGradientMaterial(GradientPair gradientPair) diff --git a/Tools/AnnotationTool/Prefabs/SettingsUI.prefab b/Tools/AnnotationTool/Prefabs/SettingsUI.prefab index 0d10682ad..2e4c565b4 100644 --- a/Tools/AnnotationTool/Prefabs/SettingsUI.prefab +++ b/Tools/AnnotationTool/Prefabs/SettingsUI.prefab @@ -20,7 +20,7 @@ GameObject: m_Component: - component: {fileID: 224000012653929454} - component: {fileID: 222000012891014098} - - component: {fileID: 114000012025195674} + - component: {fileID: 114693843284214446} m_Layer: 5 m_Name: Label m_TagString: Untagged @@ -54,7 +54,7 @@ GameObject: m_Component: - component: {fileID: 224000011405639814} - component: {fileID: 222000011416400564} - - component: {fileID: 114000011583981380} + - component: {fileID: 114537424663619190} m_Layer: 5 m_Name: Label m_TagString: Untagged @@ -190,7 +190,7 @@ GameObject: m_Component: - component: {fileID: 224874559224435002} - component: {fileID: 222817483957468890} - - component: {fileID: 114210595956423184} + - component: {fileID: 114187873217472778} m_Layer: 5 m_Name: Text m_TagString: Untagged @@ -252,39 +252,6 @@ MonoBehaviour: m_FillAmount: 1 m_FillClockwise: 1 m_FillOrigin: 0 ---- !u!114 &114000011583981380 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000011512978662} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 2100000, guid: dec2d25be9058334c91a0402762efa61, type: 2} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 0 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, - Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_FontData: - m_Font: {fileID: 12800000, guid: 013679fd6ee2085428a7f896aa7b50cc, type: 3} - m_FontSize: 20 - m_FontStyle: 0 - m_BestFit: 0 - m_MinSize: 10 - m_MaxSize: 40 - m_Alignment: 4 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: Mesh --- !u!114 &114000011835530144 MonoBehaviour: m_ObjectHideFlags: 1 @@ -357,39 +324,6 @@ MonoBehaviour: m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_IsOn: 0 ---- !u!114 &114000012025195674 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000010398065086} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 2100000, guid: dec2d25be9058334c91a0402762efa61, type: 2} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 0 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, - Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_FontData: - m_Font: {fileID: 12800000, guid: 013679fd6ee2085428a7f896aa7b50cc, type: 3} - m_FontSize: 20 - m_FontStyle: 0 - m_BestFit: 0 - m_MinSize: 10 - m_MaxSize: 40 - m_Alignment: 4 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: Transform --- !u!114 &114000012940195592 MonoBehaviour: m_ObjectHideFlags: 1 @@ -496,7 +430,7 @@ MonoBehaviour: m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_IsOn: 1 ---- !u!114 &114210595956423184 +--- !u!114 &114187873217472778 MonoBehaviour: m_ObjectHideFlags: 1 m_PrefabParentObject: {fileID: 0} @@ -504,10 +438,10 @@ MonoBehaviour: m_GameObject: {fileID: 1123566551031880} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} m_Name: m_EditorClassIdentifier: - m_Material: {fileID: 2100000, guid: dec2d25be9058334c91a0402762efa61, type: 2} + m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 m_OnCullStateChanged: @@ -515,20 +449,99 @@ MonoBehaviour: m_Calls: [] m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_FontData: - m_Font: {fileID: 12800000, guid: 013679fd6ee2085428a7f896aa7b50cc, type: 3} - m_FontSize: 14 - m_FontStyle: 0 - m_BestFit: 0 - m_MinSize: 10 - m_MaxSize: 280 - m_Alignment: 0 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: ' Annotation Grouping Mode:' + m_text: ' Annotation Grouping Mode:' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: ea721564999c75441b5b3aa01ae88f76, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 5be343b145ab9dd42821b06c75f9a60c, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 14 + m_fontSizeBase: 14 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 257 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 114187873217472778} + characterCount: 27 + spriteCount: 0 + spaceCount: 4 + wordCount: 4 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_havePropertiesChanged: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 1 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} --- !u!114 &114261882201029984 MonoBehaviour: m_ObjectHideFlags: 1 @@ -541,6 +554,118 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_DefaultToggle: {fileID: 114000013714903302} +--- !u!114 &114537424663619190 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000011512978662} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Mesh + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: ea721564999c75441b5b3aa01ae88f76, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 5be343b145ab9dd42821b06c75f9a60c, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 20 + m_fontSizeBase: 20 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 514 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 114537424663619190} + characterCount: 4 + spriteCount: 0 + spaceCount: 0 + wordCount: 1 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_havePropertiesChanged: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 1 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} --- !u!114 &114691388261995722 MonoBehaviour: m_ObjectHideFlags: 1 @@ -563,6 +688,118 @@ MonoBehaviour: m_ChildForceExpandHeight: 1 m_ChildControlWidth: 1 m_ChildControlHeight: 0 +--- !u!114 &114693843284214446 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000010398065086} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Transform + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: ea721564999c75441b5b3aa01ae88f76, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 5be343b145ab9dd42821b06c75f9a60c, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 20 + m_fontSizeBase: 20 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 514 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 114693843284214446} + characterCount: 9 + spriteCount: 0 + spaceCount: 0 + wordCount: 1 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_havePropertiesChanged: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 1 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} --- !u!222 &222000010570603678 CanvasRenderer: m_ObjectHideFlags: 1 @@ -671,8 +908,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: -0.25, y: 0} - m_SizeDelta: {x: -0.5, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!224 &224000011444372664 RectTransform: @@ -768,8 +1005,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0.25, y: 0} - m_SizeDelta: {x: -0.5, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!224 &224000013716393632 RectTransform: diff --git a/Tools/LocomotionTool/Prefabs/SettingsUI.prefab b/Tools/LocomotionTool/Prefabs/SettingsUI.prefab index b163c5800..65e885bb9 100644 --- a/Tools/LocomotionTool/Prefabs/SettingsUI.prefab +++ b/Tools/LocomotionTool/Prefabs/SettingsUI.prefab @@ -20,7 +20,7 @@ GameObject: m_Component: - component: {fileID: 224000012653929454} - component: {fileID: 222000012891014098} - - component: {fileID: 114000012025195674} + - component: {fileID: 114926923194449542} m_Layer: 5 m_Name: Label m_TagString: Untagged @@ -54,7 +54,7 @@ GameObject: m_Component: - component: {fileID: 224000011405639814} - component: {fileID: 222000011416400564} - - component: {fileID: 114000011583981380} + - component: {fileID: 114251560024549528} m_Layer: 5 m_Name: Label m_TagString: Untagged @@ -190,7 +190,7 @@ GameObject: m_Component: - component: {fileID: 224874559224435002} - component: {fileID: 222817483957468890} - - component: {fileID: 114210595956423184} + - component: {fileID: 114630463904937644} m_Layer: 5 m_Name: Text m_TagString: Untagged @@ -252,39 +252,6 @@ MonoBehaviour: m_FillAmount: 1 m_FillClockwise: 1 m_FillOrigin: 0 ---- !u!114 &114000011583981380 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000011512978662} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 2100000, guid: dec2d25be9058334c91a0402762efa61, type: 2} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 0 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, - Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_FontData: - m_Font: {fileID: 12800000, guid: 013679fd6ee2085428a7f896aa7b50cc, type: 3} - m_FontSize: 20 - m_FontStyle: 0 - m_BestFit: 0 - m_MinSize: 10 - m_MaxSize: 40 - m_Alignment: 4 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: Blink --- !u!114 &114000011835530144 MonoBehaviour: m_ObjectHideFlags: 1 @@ -357,39 +324,6 @@ MonoBehaviour: m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_IsOn: 0 ---- !u!114 &114000012025195674 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000010398065086} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 2100000, guid: dec2d25be9058334c91a0402762efa61, type: 2} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 0 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, - Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_FontData: - m_Font: {fileID: 12800000, guid: 013679fd6ee2085428a7f896aa7b50cc, type: 3} - m_FontSize: 20 - m_FontStyle: 0 - m_BestFit: 0 - m_MinSize: 10 - m_MaxSize: 40 - m_Alignment: 4 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: Fly --- !u!114 &114000012940195592 MonoBehaviour: m_ObjectHideFlags: 1 @@ -496,18 +430,18 @@ MonoBehaviour: m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_IsOn: 1 ---- !u!114 &114210595956423184 +--- !u!114 &114251560024549528 MonoBehaviour: m_ObjectHideFlags: 1 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1123566551031880} + m_GameObject: {fileID: 1000011512978662} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} m_Name: m_EditorClassIdentifier: - m_Material: {fileID: 2100000, guid: dec2d25be9058334c91a0402762efa61, type: 2} + m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 m_OnCullStateChanged: @@ -515,20 +449,99 @@ MonoBehaviour: m_Calls: [] m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_FontData: - m_Font: {fileID: 12800000, guid: 013679fd6ee2085428a7f896aa7b50cc, type: 3} - m_FontSize: 14 - m_FontStyle: 0 - m_BestFit: 0 - m_MinSize: 10 - m_MaxSize: 280 - m_Alignment: 0 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: ' Locomotion Mode:' + m_text: Blink + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: ea721564999c75441b5b3aa01ae88f76, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 5be343b145ab9dd42821b06c75f9a60c, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 20 + m_fontSizeBase: 20 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 514 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 114251560024549528} + characterCount: 5 + spriteCount: 0 + spaceCount: 0 + wordCount: 1 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_havePropertiesChanged: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 1 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} --- !u!114 &114261882201029984 MonoBehaviour: m_ObjectHideFlags: 1 @@ -541,6 +554,118 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_DefaultToggle: {fileID: 114000013714903302} +--- !u!114 &114630463904937644 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1123566551031880} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: ' Locomotion Mode:' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: ea721564999c75441b5b3aa01ae88f76, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 5be343b145ab9dd42821b06c75f9a60c, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 14 + m_fontSizeBase: 14 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 257 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 114630463904937644} + characterCount: 18 + spriteCount: 0 + spaceCount: 3 + wordCount: 3 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_havePropertiesChanged: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 1 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} --- !u!114 &114691388261995722 MonoBehaviour: m_ObjectHideFlags: 1 @@ -563,6 +688,118 @@ MonoBehaviour: m_ChildForceExpandHeight: 1 m_ChildControlWidth: 1 m_ChildControlHeight: 0 +--- !u!114 &114926923194449542 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000010398065086} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Fly + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: ea721564999c75441b5b3aa01ae88f76, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 5be343b145ab9dd42821b06c75f9a60c, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 20 + m_fontSizeBase: 20 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 514 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 114926923194449542} + characterCount: 3 + spriteCount: 0 + spaceCount: 0 + wordCount: 1 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_havePropertiesChanged: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 1 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} --- !u!222 &222000010570603678 CanvasRenderer: m_ObjectHideFlags: 1 @@ -672,7 +909,7 @@ RectTransform: m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: -0.5, y: 0} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!224 &224000011444372664 RectTransform: @@ -769,7 +1006,7 @@ RectTransform: m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: -0.5, y: 0} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!224 &224000013716393632 RectTransform: diff --git a/Tools/SelectionTool/Prefabs/SettingsUI.prefab b/Tools/SelectionTool/Prefabs/SettingsUI.prefab index e89bd2e1c..a9016f63a 100644 --- a/Tools/SelectionTool/Prefabs/SettingsUI.prefab +++ b/Tools/SelectionTool/Prefabs/SettingsUI.prefab @@ -20,7 +20,7 @@ GameObject: m_Component: - component: {fileID: 224000012653929454} - component: {fileID: 222000012891014098} - - component: {fileID: 114000012025195674} + - component: {fileID: 114455058579300802} m_Layer: 5 m_Name: Label m_TagString: Untagged @@ -54,7 +54,7 @@ GameObject: m_Component: - component: {fileID: 224000011405639814} - component: {fileID: 222000011416400564} - - component: {fileID: 114000011583981380} + - component: {fileID: 114453297554796428} m_Layer: 5 m_Name: Label m_TagString: Untagged @@ -190,7 +190,7 @@ GameObject: m_Component: - component: {fileID: 224874559224435002} - component: {fileID: 222817483957468890} - - component: {fileID: 114210595956423184} + - component: {fileID: 114070060636110884} m_Layer: 5 m_Name: Text m_TagString: Untagged @@ -252,39 +252,6 @@ MonoBehaviour: m_FillAmount: 1 m_FillClockwise: 1 m_FillOrigin: 0 ---- !u!114 &114000011583981380 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000011512978662} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 2100000, guid: dec2d25be9058334c91a0402762efa61, type: 2} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 0 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, - Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_FontData: - m_Font: {fileID: 12800000, guid: 013679fd6ee2085428a7f896aa7b50cc, type: 3} - m_FontSize: 20 - m_FontStyle: 0 - m_BestFit: 0 - m_MinSize: 10 - m_MaxSize: 40 - m_Alignment: 4 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: Sphere --- !u!114 &114000011835530144 MonoBehaviour: m_ObjectHideFlags: 1 @@ -357,39 +324,6 @@ MonoBehaviour: m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_IsOn: 0 ---- !u!114 &114000012025195674 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000010398065086} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 2100000, guid: dec2d25be9058334c91a0402762efa61, type: 2} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 0 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, - Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_FontData: - m_Font: {fileID: 12800000, guid: 013679fd6ee2085428a7f896aa7b50cc, type: 3} - m_FontSize: 20 - m_FontStyle: 0 - m_BestFit: 0 - m_MinSize: 10 - m_MaxSize: 40 - m_Alignment: 4 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: Cuboid --- !u!114 &114000012940195592 MonoBehaviour: m_ObjectHideFlags: 1 @@ -496,7 +430,7 @@ MonoBehaviour: m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_IsOn: 1 ---- !u!114 &114210595956423184 +--- !u!114 &114070060636110884 MonoBehaviour: m_ObjectHideFlags: 1 m_PrefabParentObject: {fileID: 0} @@ -504,10 +438,10 @@ MonoBehaviour: m_GameObject: {fileID: 1123566551031880} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} m_Name: m_EditorClassIdentifier: - m_Material: {fileID: 2100000, guid: dec2d25be9058334c91a0402762efa61, type: 2} + m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 m_OnCullStateChanged: @@ -515,20 +449,99 @@ MonoBehaviour: m_Calls: [] m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_FontData: - m_Font: {fileID: 12800000, guid: 013679fd6ee2085428a7f896aa7b50cc, type: 3} - m_FontSize: 14 - m_FontStyle: 0 - m_BestFit: 0 - m_MinSize: 10 - m_MaxSize: 280 - m_Alignment: 0 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: ' Block Selection Mode:' + m_text: ' Block Selection Mode:' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: ea721564999c75441b5b3aa01ae88f76, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 5be343b145ab9dd42821b06c75f9a60c, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 14 + m_fontSizeBase: 14 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 257 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 114070060636110884} + characterCount: 23 + spriteCount: 0 + spaceCount: 4 + wordCount: 4 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_havePropertiesChanged: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 1 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} --- !u!114 &114261882201029984 MonoBehaviour: m_ObjectHideFlags: 1 @@ -541,6 +554,230 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_DefaultToggle: {fileID: 114000013714903302} +--- !u!114 &114453297554796428 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000011512978662} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Sphere + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: ea721564999c75441b5b3aa01ae88f76, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 5be343b145ab9dd42821b06c75f9a60c, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 20 + m_fontSizeBase: 20 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 514 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 114453297554796428} + characterCount: 6 + spriteCount: 0 + spaceCount: 0 + wordCount: 1 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_havePropertiesChanged: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 1 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!114 &114455058579300802 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000010398065086} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Cuboid + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: ea721564999c75441b5b3aa01ae88f76, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 5be343b145ab9dd42821b06c75f9a60c, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 20 + m_fontSizeBase: 20 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 514 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 114455058579300802} + characterCount: 6 + spriteCount: 0 + spaceCount: 0 + wordCount: 1 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_havePropertiesChanged: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 1 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} --- !u!114 &114691388261995722 MonoBehaviour: m_ObjectHideFlags: 1 @@ -671,8 +908,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: -0.25, y: 0} - m_SizeDelta: {x: -0.5, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!224 &224000011444372664 RectTransform: @@ -768,8 +1005,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0.25, y: 0} - m_SizeDelta: {x: -0.5, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!224 &224000013716393632 RectTransform: From 895dd8c88cdb4b73787234a26758cb12f368f82b Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Thu, 7 Dec 2017 17:29:28 -0800 Subject: [PATCH 61/89] remove unecessary textmesh pro defines --- Menus/MainMenu/Scripts/MainMenuButton.cs | 4 ---- Menus/MainMenu/Scripts/MainMenuToggle.cs | 6 ------ 2 files changed, 10 deletions(-) diff --git a/Menus/MainMenu/Scripts/MainMenuButton.cs b/Menus/MainMenu/Scripts/MainMenuButton.cs index 081075e7a..df54080c1 100644 --- a/Menus/MainMenu/Scripts/MainMenuButton.cs +++ b/Menus/MainMenu/Scripts/MainMenuButton.cs @@ -6,10 +6,6 @@ using UnityEngine.EventSystems; using UnityEngine.UI; -#if INCLUDE_TEXT_MESH_PRO -using TMPro; -#endif - [assembly: OptionalDependency("TMPro.TextMeshProUGUI", "INCLUDE_TEXT_MESH_PRO")] namespace UnityEditor.Experimental.EditorVR.Menus diff --git a/Menus/MainMenu/Scripts/MainMenuToggle.cs b/Menus/MainMenu/Scripts/MainMenuToggle.cs index a70c062c7..425dddadc 100644 --- a/Menus/MainMenu/Scripts/MainMenuToggle.cs +++ b/Menus/MainMenu/Scripts/MainMenuToggle.cs @@ -6,10 +6,6 @@ using UnityEngine.EventSystems; using UnityEngine.UI; -#if INCLUDE_TEXT_MESH_PRO -using TMPro; -#endif - [assembly: OptionalDependency("TMPro.TextMeshProUGUI", "INCLUDE_TEXT_MESH_PRO")] namespace UnityEditor.Experimental.EditorVR.Menus @@ -32,10 +28,8 @@ sealed class MainMenuToggle : MainMenuSelectable, IRayEnterHandler, IRayExitHand public void OnRayEnter(RayEventData eventData) { -#if INCLUDE_TEXT_MESH_PRO if (hovered != null) hovered(eventData.rayOrigin); -#endif } public void OnRayExit(RayEventData eventData) From c98e605bc598183b7246acf2301cc818ba7b65fa Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Thu, 7 Dec 2017 17:53:31 -0800 Subject: [PATCH 62/89] Fix line endings --- Scripts/UI/InputField.cs | 2 +- Tests/Editor/Unit/Core/EditingContextManagerTests.cs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Scripts/UI/InputField.cs b/Scripts/UI/InputField.cs index 0b93a6bbb..65f413fc0 100644 --- a/Scripts/UI/InputField.cs +++ b/Scripts/UI/InputField.cs @@ -56,7 +56,7 @@ public class OnChangeEvent : UnityEvent public Func spawnKeyboard { private get; set; } - public OnChangeEvent onValueChanged { get { return m_OnValueChanged; } } + public OnChangeEvent onValueChanged { get { return m_OnValueChanged; } } public virtual string text { diff --git a/Tests/Editor/Unit/Core/EditingContextManagerTests.cs b/Tests/Editor/Unit/Core/EditingContextManagerTests.cs index 43e6a6067..c79876178 100644 --- a/Tests/Editor/Unit/Core/EditingContextManagerTests.cs +++ b/Tests/Editor/Unit/Core/EditingContextManagerTests.cs @@ -166,5 +166,4 @@ public void Cleanup() class SetEditingContextImplementor : ISetEditingContext { } } - -#endif \ No newline at end of file +#endif From aec0f73f367ec93ff90536f55f405ab1c79c9ee3 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Thu, 7 Dec 2017 17:55:12 -0800 Subject: [PATCH 63/89] Fix line endings --- Scripts/Modules/FeedbackModule/FeedbackModule.cs | 6 +++--- Workspaces/PolyWorkspace/Scripts/PolyGridItem.cs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Scripts/Modules/FeedbackModule/FeedbackModule.cs b/Scripts/Modules/FeedbackModule/FeedbackModule.cs index 6770df03e..2d96d7b83 100644 --- a/Scripts/Modules/FeedbackModule/FeedbackModule.cs +++ b/Scripts/Modules/FeedbackModule/FeedbackModule.cs @@ -56,8 +56,8 @@ public GameObject settingsMenuItemInstance if (m_Preferences != null) toggle.isOn = m_Preferences.enabled; - m_Toggles.Add(toggle); - + m_Toggles.Add(toggle); + #if INCLUDE_TEXT_MESH_PRO var label = value.GetComponentInChildren(); @@ -74,7 +74,7 @@ public GameObject settingsMenuItemInstance var handle = value.GetComponent(); handle.hoverStarted += (baseHandle, data) => { label.text = m_Preferences.enabled ? disableFeedback : enableFeedback; }; - handle.hoverEnded += (baseHandle, data) => { label.text = m_Preferences.enabled ? feedbackEnabled : feedbackDisabled; }; + handle.hoverEnded += (baseHandle, data) => { label.text = m_Preferences.enabled ? feedbackEnabled : feedbackDisabled; }; #endif } } diff --git a/Workspaces/PolyWorkspace/Scripts/PolyGridItem.cs b/Workspaces/PolyWorkspace/Scripts/PolyGridItem.cs index 813a33bf9..553ee3a78 100644 --- a/Workspaces/PolyWorkspace/Scripts/PolyGridItem.cs +++ b/Workspaces/PolyWorkspace/Scripts/PolyGridItem.cs @@ -488,7 +488,7 @@ IEnumerator ShowGrabbedObject() yield break; // Exit coroutine if m_GrabbedObject is destroyed before the loop is finished currentTime += Time.deltaTime; - m_DragObject.localScale = Vector3.Lerp(currentLocalScale, targetScale, + m_DragObject.localScale = Vector3.Lerp(currentLocalScale, targetScale, MathUtilsExt.SmoothInOutLerpFloat(currentTime / duration)); if (m_PreviewObjectClone) @@ -500,7 +500,7 @@ IEnumerator ShowGrabbedObject() yield return null; } - m_DragObject.localScale = targetScale; + m_DragObject.localScale = targetScale; //No need to hard-set the preview object position/rotation because they will set in OnDragging in parent class } From 668367d67ba2608270cd615a4bdb076a1777fe80 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Thu, 7 Dec 2017 19:27:53 -0800 Subject: [PATCH 64/89] Fix issue if scene camera clear flags are set to Nothing; Fix issue where camera settings copy doesn't happen the first time you launch EXR after a domain reload --- Editor/EditingContextManagerEditor.cs | 8 +- Models/Vive/Materials/ViveController.mat | 2 +- .../Core/Contexts/EditingContextManager.cs | 100 +++++++++--------- Scripts/Core/Contexts/EditorVRContext.cs | 4 +- Scripts/Core/VRView.cs | 15 +-- Scripts/Interfaces/Entity/IEditingContext.cs | 2 +- 6 files changed, 67 insertions(+), 64 deletions(-) diff --git a/Editor/EditingContextManagerEditor.cs b/Editor/EditingContextManagerEditor.cs index 42660c7c9..371469302 100644 --- a/Editor/EditingContextManagerEditor.cs +++ b/Editor/EditingContextManagerEditor.cs @@ -21,7 +21,13 @@ void Awake() public override void OnInspectorGUI() { GUILayout.Label("Available Contexts"); - EditingContextManager.DoGUI(m_ContextNames, ref m_SelectedContextIndex, () => { m_Settings.defaultContextName = m_ContextNames[m_SelectedContextIndex]; }); + + m_SelectedContextIndex = EditorGUILayout.Popup(string.Empty, m_SelectedContextIndex, m_ContextNames); + if (GUI.changed) + { + m_Settings.defaultContextName = m_ContextNames[m_SelectedContextIndex]; + GUIUtility.ExitGUI(); + } EditorGUILayout.Space(); diff --git a/Models/Vive/Materials/ViveController.mat b/Models/Vive/Materials/ViveController.mat index d1e045a5a..3b37e57d2 100644 --- a/Models/Vive/Materials/ViveController.mat +++ b/Models/Vive/Materials/ViveController.mat @@ -75,7 +75,7 @@ Material: - _SpecularHighlights: 1 - _SrcBlend: 5 - _UVSec: 0 - - _ZWrite: 0 + - _ZWrite: 1 m_Colors: - _Color: {r: 1, g: 1, b: 1, a: 1} - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Scripts/Core/Contexts/EditingContextManager.cs b/Scripts/Core/Contexts/EditingContextManager.cs index fe8163735..ab2f8f903 100644 --- a/Scripts/Core/Contexts/EditingContextManager.cs +++ b/Scripts/Core/Contexts/EditingContextManager.cs @@ -22,28 +22,32 @@ sealed class EditingContextManager : MonoBehaviour const string k_LaunchOnExitPlaymode = "EditingContextManager.LaunchOnExitPlaymode"; + IEditingContext m_CurrentContext; + internal static EditingContextManager s_Instance; static InputManager s_InputManager; static List s_AvailableContexts; static EditingContextManagerSettings s_Settings; static UnityObject s_DefaultContext; - static IEditingContext s_CurrentContext; string[] m_ContextNames; int m_SelectedContextIndex; + Rect m_EditingContextPopupRect = new Rect(0, 0, 150, 20); // Y and X position will be set based on window size + readonly List m_PreviousContexts = new List(); internal static IEditingContext defaultContext { get { - var context = s_AvailableContexts.Find(c => c.Equals(s_DefaultContext)) ?? s_AvailableContexts.First(); + var availableContexts = GetAvailableEditingContexts(); + var context = availableContexts.Find(c => c.Equals(s_DefaultContext)) ?? availableContexts.First(); - var defaultContextName = s_Settings.defaultContextName; + var defaultContextName = settings.defaultContextName; if (!string.IsNullOrEmpty(defaultContextName)) { - var foundContext = s_AvailableContexts.Find(c => c.name == defaultContextName); + var foundContext = availableContexts.Find(c => c.name == defaultContextName); if (foundContext != null) context = foundContext; } @@ -52,20 +56,30 @@ internal static IEditingContext defaultContext } set { - s_Settings.defaultContextName = value.name; + settings.defaultContextName = value.name; } } internal IEditingContext currentContext { - get { return s_CurrentContext; } + get { return m_CurrentContext; } + } + + static EditingContextManagerSettings settings + { + get + { + if (!s_Settings) + s_Settings = LoadUserSettings(); + + return s_Settings; + } } static EditingContextManager() { VRView.viewEnabled += OnVRViewEnabled; VRView.viewDisabled += OnVRViewDisabled; - VRView.cameraSetupStarted += OnCameraSetupStarted; EditorApplication.update += ReopenOnExitPlaymode; } @@ -82,11 +96,6 @@ static void OnVRViewDisabled() ObjectUtils.Destroy(s_InputManager.gameObject); } - public static IEditingContext OnCameraSetupStarted() - { - return s_CurrentContext; - } - [MenuItem("Window/EditorXR %e", false)] internal static void ShowEditorVR() { @@ -138,16 +147,6 @@ static void OnPlayModeStateChanged(PlayModeStateChange stateChange) void Awake() { s_DefaultContext = m_DefaultContext; - } - - void OnEnable() - { - s_Settings = LoadUserSettings(); - - ISetEditingContextMethods.getAvailableEditingContexts = GetAvailableEditingContexts; - ISetEditingContextMethods.getPreviousEditingContexts = GetPreviousEditingContexts; - ISetEditingContextMethods.setEditingContext = SetEditingContext; - ISetEditingContextMethods.restorePreviousEditingContext = RestorePreviousContext; var availableContexts = GetAvailableEditingContexts(); m_ContextNames = availableContexts.Select(c => c.name).ToArray(); @@ -155,16 +154,24 @@ void OnEnable() if (s_AvailableContexts.Count == 0) throw new Exception("You can't start EditorXR without at least one context. Try re-importing the package or use version control to restore the default context asset"); - SetEditingContext(defaultContext); - if (s_AvailableContexts.Count > 1) VRView.afterOnGUI += OnVRViewGUI; + } + + void OnEnable() + { + ISetEditingContextMethods.getAvailableEditingContexts = GetAvailableEditingContexts; + ISetEditingContextMethods.getPreviousEditingContexts = GetPreviousEditingContexts; + ISetEditingContextMethods.setEditingContext = SetEditingContext; + ISetEditingContextMethods.restorePreviousEditingContext = RestorePreviousContext; // Force the window to repaint every tick, since we need live updating // This also allows scripts with [ExecuteInEditMode] to run EditorApplication.update += EditorApplication.QueuePlayerLoopUpdate; EditorApplication.playModeStateChanged += OnPlayModeStateChanged; + + SetEditingContext(defaultContext); } void OnDisable() @@ -175,46 +182,35 @@ void OnDisable() VRView.afterOnGUI -= OnVRViewGUI; - if (s_CurrentContext != null) + if (m_CurrentContext != null) { - defaultContext = s_CurrentContext; - s_CurrentContext.Dispose(); + defaultContext = m_CurrentContext; + m_CurrentContext.Dispose(); } s_AvailableContexts = null; + SetEditingContext(null); + ISetEditingContextMethods.getAvailableEditingContexts = null; ISetEditingContextMethods.getPreviousEditingContexts = null; ISetEditingContextMethods.setEditingContext = null; ISetEditingContextMethods.restorePreviousEditingContext = null; - SaveUserSettings(s_Settings); + SaveUserSettings(settings); } #endif - void OnVRViewGUI(EditorWindow window) + void OnVRViewGUI(VRView view) { - var view = (VRView)window; - GUILayout.BeginArea(view.guiRect); - { - GUILayout.FlexibleSpace(); - GUILayout.BeginHorizontal(); - { - DoGUI(m_ContextNames, ref m_SelectedContextIndex, () => SetEditingContext(s_AvailableContexts[m_SelectedContextIndex])); - GUILayout.FlexibleSpace(); - } - GUILayout.EndHorizontal(); - } - GUILayout.EndArea(); - } + var position = view.position; + m_EditingContextPopupRect.y = position.height - m_EditingContextPopupRect.height; + m_EditingContextPopupRect.x = position.width - m_EditingContextPopupRect.width; - internal static void DoGUI(string[] contextNames, ref int selectedContextIndex, Action callback = null) - { - selectedContextIndex = EditorGUILayout.Popup(string.Empty, selectedContextIndex, contextNames); + m_SelectedContextIndex = EditorGUI.Popup(m_EditingContextPopupRect, string.Empty, m_SelectedContextIndex, m_ContextNames); if (GUI.changed) { - if (callback != null) - callback(); + SetEditingContext(s_AvailableContexts[m_SelectedContextIndex]); GUIUtility.ExitGUI(); } } @@ -224,16 +220,16 @@ internal void SetEditingContext(IEditingContext context) if (context == null) return; - if (s_CurrentContext != null) + if (m_CurrentContext != null) { - m_PreviousContexts.Insert(0, s_CurrentContext); + m_PreviousContexts.Insert(0, m_CurrentContext); - if (s_CurrentContext.instanceExists) - s_CurrentContext.Dispose(); + if (m_CurrentContext.instanceExists) + m_CurrentContext.Dispose(); } context.Setup(); - s_CurrentContext = context; + m_CurrentContext = context; m_SelectedContextIndex = s_AvailableContexts.IndexOf(context); } diff --git a/Scripts/Core/Contexts/EditorVRContext.cs b/Scripts/Core/Contexts/EditorVRContext.cs index 8f997c3ee..813e6027c 100644 --- a/Scripts/Core/Contexts/EditorVRContext.cs +++ b/Scripts/Core/Contexts/EditorVRContext.cs @@ -14,14 +14,14 @@ class EditorVRContext : ScriptableObject, IEditingContext float m_RenderScale = 1f; [SerializeField] - bool m_CopySceneCameraSettings = true; + bool m_CopyExistingCameraSettings = true; [SerializeField] internal List m_DefaultToolStack; EditorVR m_Instance; - public bool copySceneCameraSettings { get { return m_CopySceneCameraSettings; } } + public bool copyExistingCameraSettings { get { return m_CopyExistingCameraSettings; } } public bool instanceExists { get { return m_Instance != null; } } diff --git a/Scripts/Core/VRView.cs b/Scripts/Core/VRView.cs index ce0c3e7a4..551f5eba9 100644 --- a/Scripts/Core/VRView.cs +++ b/Scripts/Core/VRView.cs @@ -59,7 +59,7 @@ public static Camera customPreviewCamera bool m_UseCustomPreviewCamera; Rect m_ToggleDeviceViewRect = new Rect(0, 0, 0, 20); // Width will be set based on window size - Rect m_PresentationCameraRect = new Rect(0, 0, 0, 20); // Y position and width will be set based on window size + Rect m_PresentationCameraRect = new Rect(0, 0, 160, 20); // Y position and width will be set based on window size public static Transform cameraRig { @@ -116,10 +116,9 @@ public static Vector3 headCenteredOrigin public static event Action viewEnabled; public static event Action viewDisabled; - public static event Action beforeOnGUI; - public static event Action afterOnGUI; + public static event Action beforeOnGUI; + public static event Action afterOnGUI; public static event Action hmdStatusChange; - public static event Func cameraSetupStarted; public Rect guiRect { get; private set; } @@ -143,9 +142,9 @@ public void OnEnable() const float nearClipPlane = 0.01f; const float farClipPlane = 1000f; - var currentEditingContext = cameraSetupStarted != null ? cameraSetupStarted() : null; s_ExistingSceneMainCamera = Camera.main; - if (currentEditingContext != null && currentEditingContext.copySceneCameraSettings && s_ExistingSceneMainCamera && s_ExistingSceneMainCamera.enabled) + // TODO: Copy camera settings when changing contexts + if (EditingContextManager.defaultContext.copyExistingCameraSettings && s_ExistingSceneMainCamera && s_ExistingSceneMainCamera.enabled) { GameObject cameraGO = EditorUtility.CreateGameObjectWithHideFlags(k_CameraName, HideFlags.HideAndDontSave); m_Camera = ObjectUtils.CopyComponent(s_ExistingSceneMainCamera, cameraGO); @@ -157,6 +156,9 @@ public void OnEnable() m_Camera.nearClipPlane = nearClipPlane; } + + if (m_Camera.clearFlags == CameraClearFlags.Nothing) + m_Camera.clearFlags = CameraClearFlags.SolidColor; } else { @@ -315,7 +317,6 @@ void OnGUI() m_ToggleDeviceViewRect.width = width; m_PresentationCameraRect.y = height - m_PresentationCameraRect.height; - m_PresentationCameraRect.width = width; if (GUI.Button(m_ToggleDeviceViewRect, "Toggle Device View", EditorStyles.toolbarButton)) m_ShowDeviceView = !m_ShowDeviceView; diff --git a/Scripts/Interfaces/Entity/IEditingContext.cs b/Scripts/Interfaces/Entity/IEditingContext.cs index 8ceb62e10..13273843f 100644 --- a/Scripts/Interfaces/Entity/IEditingContext.cs +++ b/Scripts/Interfaces/Entity/IEditingContext.cs @@ -17,7 +17,7 @@ public interface IEditingContext /// /// Bool denotes that the scene camera's (component) values should be cloned on the XR runtime camera /// - bool copySceneCameraSettings { get; } + bool copyExistingCameraSettings { get; } /// /// Bool denotes that the EditorVR instance exists, having already been created in Setup() From 693c142d4e462ecec599771603faea1c851470e9 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Thu, 7 Dec 2017 19:34:33 -0800 Subject: [PATCH 65/89] Force copied camera stereoTargetEye to Both --- Scripts/Core/VRView.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Scripts/Core/VRView.cs b/Scripts/Core/VRView.cs index 551f5eba9..a488b0483 100644 --- a/Scripts/Core/VRView.cs +++ b/Scripts/Core/VRView.cs @@ -157,8 +157,11 @@ public void OnEnable() m_Camera.nearClipPlane = nearClipPlane; } + // TODO: Support multiple cameras if (m_Camera.clearFlags == CameraClearFlags.Nothing) m_Camera.clearFlags = CameraClearFlags.SolidColor; + + m_Camera.stereoTargetEye = StereoTargetEyeMask.Both; } else { From 29e2de5e87c433115438a34e78464c95a5e74b80 Mon Sep 17 00:00:00 2001 From: Jono Date: Thu, 7 Dec 2017 22:11:32 -0800 Subject: [PATCH 66/89] Fix AnnotationTool menuHideFlag logic. --- Tools/AnnotationTool/AnnotationTool.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Tools/AnnotationTool/AnnotationTool.cs b/Tools/AnnotationTool/AnnotationTool.cs index 22973271f..e2749283d 100644 --- a/Tools/AnnotationTool/AnnotationTool.cs +++ b/Tools/AnnotationTool/AnnotationTool.cs @@ -143,18 +143,9 @@ public MenuHideFlags menuHideFlags { m_MenuHideFlags = value; var visible = m_MenuHideFlags == 0; - - if (m_ColorPicker) - m_ColorPicker.gameObject.SetActive(visible); if (m_BrushSizeUI) m_BrushSizeUI.gameObject.SetActive(visible); - - if (m_ColorPickerActivator) - m_ColorPickerActivator.SetActive(visible); - - if (m_AnnotationPointer) - m_AnnotationPointer.gameObject.SetActive(visible); } } } @@ -253,8 +244,6 @@ void CleanUpNames() void Start() { - localBounds = ObjectUtils.GetBounds(transform); - // Clear selection so we can't manipulate things Selection.activeGameObject = null; @@ -348,6 +337,7 @@ void SetupBrushUI() m_BrushSizeUI = brushSizeUi.GetComponent(); var transform = brushSizeUi.transform; + localBounds = ObjectUtils.GetBounds(transform); var scale = transform.localScale; transform.SetParent(alternateMenuOrigin, false); transform.localPosition = Vector3.zero; From 334db2707f49cc2626230ef03be68c19219404b2 Mon Sep 17 00:00:00 2001 From: Jono Date: Thu, 7 Dec 2017 22:19:48 -0800 Subject: [PATCH 67/89] Add namespaces to AnnotationTool scripts. --- .../UserInterface/BrushSizeUI.cs | 122 +++--- .../UserInterface/ColorPickerActivator.cs | 136 +++---- .../UserInterface/ColorPickerSquareUI.cs | 59 +-- .../UserInterface/ColorPickerUI.cs | 369 +++++++++--------- 4 files changed, 348 insertions(+), 338 deletions(-) diff --git a/Tools/AnnotationTool/UserInterface/BrushSizeUI.cs b/Tools/AnnotationTool/UserInterface/BrushSizeUI.cs index e59eda476..357966f34 100644 --- a/Tools/AnnotationTool/UserInterface/BrushSizeUI.cs +++ b/Tools/AnnotationTool/UserInterface/BrushSizeUI.cs @@ -1,60 +1,62 @@ -#if UNITY_EDITOR -using System; -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; -using UnityEngine.UI; - -public class BrushSizeUI : MonoBehaviour -{ - const float k_MinSize = 0.625f; - const float k_MaxSize = 12.5f; - - [SerializeField] - RectTransform m_SliderHandle; - - [SerializeField] - Slider m_Slider; - - Image m_SliderHandleImage; - - public Action onValueChanged { private get; set; } - - void Awake() - { - // We record property modifications on creation and modification of these UI elements, which will look odd when undone - Undo.postprocessModifications += PostProcessModifications; - m_SliderHandleImage = m_SliderHandle.GetComponent(); - } - - UndoPropertyModification[] PostProcessModifications(UndoPropertyModification[] modifications) - { - var modificationList = new List(modifications); - foreach (var modification in modifications) - { - if (modification.currentValue.target == m_SliderHandle) - modificationList.Remove(modification); - } - - return modificationList.ToArray(); - } - - public void OnSliderValueChanged(float value) - { - m_SliderHandle.localScale = Vector3.one * Mathf.Lerp(k_MinSize, k_MaxSize, value); - - if (onValueChanged != null) - onValueChanged(value); - } - - public void ChangeSliderValue(float newValue) - { - m_Slider.value = newValue; - } - - public void OnBrushColorChanged(Color newColor) - { - m_SliderHandleImage.color = newColor; - } -} -#endif +#if UNITY_EDITOR +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +namespace UnityEditor.Experimental.EditorVR.Tools +{ + public class BrushSizeUI : MonoBehaviour + { + const float k_MinSize = 0.625f; + const float k_MaxSize = 12.5f; + + [SerializeField] + RectTransform m_SliderHandle; + + [SerializeField] + Slider m_Slider; + + Image m_SliderHandleImage; + + public Action onValueChanged { private get; set; } + + void Awake() + { + // We record property modifications on creation and modification of these UI elements, which will look odd when undone + Undo.postprocessModifications += PostProcessModifications; + m_SliderHandleImage = m_SliderHandle.GetComponent(); + } + + UndoPropertyModification[] PostProcessModifications(UndoPropertyModification[] modifications) + { + var modificationList = new List(modifications); + foreach (var modification in modifications) + { + if (modification.currentValue.target == m_SliderHandle) + modificationList.Remove(modification); + } + + return modificationList.ToArray(); + } + + public void OnSliderValueChanged(float value) + { + m_SliderHandle.localScale = Vector3.one * Mathf.Lerp(k_MinSize, k_MaxSize, value); + + if (onValueChanged != null) + onValueChanged(value); + } + + public void ChangeSliderValue(float newValue) + { + m_Slider.value = newValue; + } + + public void OnBrushColorChanged(Color newColor) + { + m_SliderHandleImage.color = newColor; + } + } +} +#endif diff --git a/Tools/AnnotationTool/UserInterface/ColorPickerActivator.cs b/Tools/AnnotationTool/UserInterface/ColorPickerActivator.cs index 7ad8f8e52..d66f51b61 100644 --- a/Tools/AnnotationTool/UserInterface/ColorPickerActivator.cs +++ b/Tools/AnnotationTool/UserInterface/ColorPickerActivator.cs @@ -1,67 +1,69 @@ -#if UNITY_EDITOR -using System; -using System.Collections; -using UnityEditor.Experimental.EditorVR; -using UnityEditor.Experimental.EditorVR.Extensions; -using UnityEngine; -using UnityEngine.EventSystems; - -public class ColorPickerActivator : MonoBehaviour, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler -{ - [SerializeField] - Transform m_TargetScale; - - [SerializeField] - Transform m_Icon; - - [SerializeField] - float m_PickerOffset = 0.045f; - - Coroutine m_HighlightCoroutine; - - public Transform rayOrigin { private get; set; } - public Action showColorPicker { private get; set; } - public Action hideColorPicker { private get; set; } - public Node node { private get; set; } - - public void OnPointerClick(PointerEventData eventData) - { - eventData.Use(); - } - - public void OnPointerEnter(PointerEventData eventData) - { - showColorPicker(rayOrigin); - this.RestartCoroutine(ref m_HighlightCoroutine, Highlight(true)); - - eventData.Use(); - } - - public void OnPointerExit(PointerEventData eventData) - { - hideColorPicker(); - this.RestartCoroutine(ref m_HighlightCoroutine, Highlight(false)); - } - - IEnumerator Highlight(bool transitionIn) - { - var amount = 0f; - var currentScale = m_Icon.localScale; - var targetScale = transitionIn ? m_TargetScale.localScale : Vector3.one; - var currentPosition = m_Icon.localPosition; - var targetPosition = transitionIn ? (node == Node.LeftHand ? Vector3.left : Vector3.right) * m_PickerOffset : Vector3.zero; - var speed = (currentScale.x + 0.5f / targetScale.x) * 4; - - while (amount < 1f) - { - amount += Time.unscaledDeltaTime * speed; - var t = Mathf.SmoothStep(0f, 1f, amount); - m_Icon.localScale = Vector3.Lerp(currentScale, targetScale, t); - m_Icon.localPosition = Vector3.Lerp(currentPosition, targetPosition, t); - yield return null; - } - - m_Icon.localScale = targetScale; - } -} -#endif +#if UNITY_EDITOR +using System; +using System.Collections; +using UnityEditor.Experimental.EditorVR.Extensions; +using UnityEngine; +using UnityEngine.EventSystems; + +namespace UnityEditor.Experimental.EditorVR.Tools +{ + public class ColorPickerActivator : MonoBehaviour, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler + { + [SerializeField] + Transform m_TargetScale; + + [SerializeField] + Transform m_Icon; + + [SerializeField] + float m_PickerOffset = 0.045f; + + Coroutine m_HighlightCoroutine; + + public Transform rayOrigin { private get; set; } + public Action showColorPicker { private get; set; } + public Action hideColorPicker { private get; set; } + public Node node { private get; set; } + + public void OnPointerClick(PointerEventData eventData) + { + eventData.Use(); + } + + public void OnPointerEnter(PointerEventData eventData) + { + showColorPicker(rayOrigin); + this.RestartCoroutine(ref m_HighlightCoroutine, Highlight(true)); + + eventData.Use(); + } + + public void OnPointerExit(PointerEventData eventData) + { + hideColorPicker(); + this.RestartCoroutine(ref m_HighlightCoroutine, Highlight(false)); + } + + IEnumerator Highlight(bool transitionIn) + { + var amount = 0f; + var currentScale = m_Icon.localScale; + var targetScale = transitionIn ? m_TargetScale.localScale : Vector3.one; + var currentPosition = m_Icon.localPosition; + var targetPosition = transitionIn ? (node == Node.LeftHand ? Vector3.left : Vector3.right) * m_PickerOffset : Vector3.zero; + var speed = (currentScale.x + 0.5f / targetScale.x) * 4; + + while (amount < 1f) + { + amount += Time.unscaledDeltaTime * speed; + var t = Mathf.SmoothStep(0f, 1f, amount); + m_Icon.localScale = Vector3.Lerp(currentScale, targetScale, t); + m_Icon.localPosition = Vector3.Lerp(currentPosition, targetPosition, t); + yield return null; + } + + m_Icon.localScale = targetScale; + } + } +} +#endif diff --git a/Tools/AnnotationTool/UserInterface/ColorPickerSquareUI.cs b/Tools/AnnotationTool/UserInterface/ColorPickerSquareUI.cs index 6c618ac1f..dfb29f6c5 100644 --- a/Tools/AnnotationTool/UserInterface/ColorPickerSquareUI.cs +++ b/Tools/AnnotationTool/UserInterface/ColorPickerSquareUI.cs @@ -1,28 +1,31 @@ -#if UNITY_EDITOR -using System; -using UnityEngine.EventSystems; -using UnityEngine.UI; - -public class ColorPickerSquareUI : Selectable, IDragHandler, IBeginDragHandler, IEndDragHandler -{ - bool m_AllowDragEvents; - - public Action onDrag { private get; set; } - - public void OnBeginDrag(PointerEventData eventData) - { - m_AllowDragEvents = true; - } - - public void OnDrag(PointerEventData eventData) - { - if (onDrag != null && m_AllowDragEvents) - onDrag(); - } - - public void OnEndDrag(PointerEventData eventData) - { - m_AllowDragEvents = false; - } -} -#endif +#if UNITY_EDITOR +using System; +using UnityEngine.EventSystems; +using UnityEngine.UI; + +namespace UnityEditor.Experimental.EditorVR.Tools +{ + public class ColorPickerSquareUI : Selectable, IDragHandler, IBeginDragHandler, IEndDragHandler + { + bool m_AllowDragEvents; + + public Action onDrag { private get; set; } + + public void OnBeginDrag(PointerEventData eventData) + { + m_AllowDragEvents = true; + } + + public void OnDrag(PointerEventData eventData) + { + if (onDrag != null && m_AllowDragEvents) + onDrag(); + } + + public void OnEndDrag(PointerEventData eventData) + { + m_AllowDragEvents = false; + } + } +} +#endif diff --git a/Tools/AnnotationTool/UserInterface/ColorPickerUI.cs b/Tools/AnnotationTool/UserInterface/ColorPickerUI.cs index da1fb9599..b152aee9c 100644 --- a/Tools/AnnotationTool/UserInterface/ColorPickerUI.cs +++ b/Tools/AnnotationTool/UserInterface/ColorPickerUI.cs @@ -1,183 +1,186 @@ -#if UNITY_EDITOR -using UnityEngine; -using System.Collections; -using UnityEngine.UI; -using System; -using UnityEditor.Experimental.EditorVR.Extensions; -using UnityEngine.EventSystems; - -public class ColorPickerUI : MonoBehaviour, IPointerExitHandler -{ - [SerializeField] - float m_FadeTime; - - [SerializeField] - RawImage m_ColorPicker; - - [SerializeField] - RawImage m_SliderBackground; - - [SerializeField] - RectTransform m_Picker; - - [SerializeField] - RectTransform m_PickerBounds; - - [SerializeField] - ColorPickerSquareUI m_ColorPickerSquare; - - Vector3 m_PickerTargetPosition; - - Texture2D m_BrightnessBarTexture; - Texture2D m_ColorPickerTexture; - - Coroutine m_FadeCoroutine; - - public Transform toolRayOrigin { private get; set; } - - public Action onColorPicked { private get; set; } - - public Action onHideCalled { private get; set; } - - void Start() - { - m_ColorPickerSquare.onDrag = OnDrag; - - m_ColorPickerTexture = m_ColorPickerSquare.GetComponent().texture as Texture2D; - GenerateBrightnessBar(); - } - - void OnDestroy() - { - DestroyImmediate(m_BrightnessBarTexture); - } - - void Update() - { - m_Picker.localPosition = m_PickerTargetPosition; - } - - public void Show() - { - this.RestartCoroutine(ref m_FadeCoroutine, FadeCanvas(false)); - } - - public void Hide() - { - this.RestartCoroutine(ref m_FadeCoroutine, FadeCanvas(true)); - } - - public void OnSliderChanged(float val) - { - m_ColorPicker.color = Color.Lerp(Color.black, Color.white, val); - PositionToColor(); - } - - IEnumerator FadeCanvas(bool fadeOut) - { - enabled = !fadeOut; - m_Picker.localPosition = m_PickerTargetPosition; - - var canvasGroup = GetComponentInChildren(); - var current = canvasGroup.alpha; - var start = fadeOut ? 1 : 0; - var target = 1 - start; - - if (current == target) - yield break; - - var ratio = fadeOut ? 1 - current : current; - while (ratio < 1) - { - canvasGroup.alpha = Mathf.Lerp(start, target, ratio); - ratio += Time.unscaledDeltaTime / m_FadeTime; - yield return null; - } - - GetComponentInChildren().enabled = !fadeOut; - m_Picker.gameObject.SetActive(!fadeOut); - canvasGroup.alpha = target; - canvasGroup.interactable = !fadeOut; - canvasGroup.blocksRaycasts = !fadeOut; - } - - void OnDrag() - { - if (toolRayOrigin && enabled) - { - var worldToLocal = m_ColorPicker.rectTransform.worldToLocalMatrix; - var rect = m_ColorPicker.rectTransform.rect; - - var localRayPos = worldToLocal.MultiplyPoint3x4(toolRayOrigin.position); - var localRayForward = worldToLocal.MultiplyVector(toolRayOrigin.forward).normalized; - - var height = localRayPos.z; - var angle = Vector3.Angle(new Vector3(0, 0, height), localRayForward); - var sine = Mathf.Sin((90 - angle) * Mathf.Deg2Rad); - - var distance = Mathf.Abs(height / sine); - var point = localRayPos + localRayForward * distance; - point = point.normalized * Mathf.Min(point.magnitude, rect.width / 2f); - - m_PickerTargetPosition = point; - GenerateBrightnessBar(); - PositionToColor(); - } - } - - void GenerateBrightnessBar() - { - var rect = m_SliderBackground.rectTransform.rect; - if (!m_BrightnessBarTexture) - m_BrightnessBarTexture = new Texture2D((int)rect.width, 1); - - var col = GetColorForCurrentPosition(); - - for (var y = 0; y < m_BrightnessBarTexture.height; y++) - { - for (var x = 0; x < m_BrightnessBarTexture.width; x++) - { - var brightness = x / rect.width; - var tempCol = col * brightness; - tempCol.a = 1; - m_BrightnessBarTexture.SetPixel(x, y, tempCol); - } - } - m_BrightnessBarTexture.Apply(); - - m_SliderBackground.texture = m_BrightnessBarTexture; - } - - void PositionToColor() - { - if (onColorPicked != null) - { - var col = GetColorForCurrentPosition(); - col *= m_ColorPicker.color; // Apply brightness slider - onColorPicked(col); - } - } - - Color GetColorForCurrentPosition() - { - var rect = m_PickerBounds.rect; - - var position = m_PickerTargetPosition; - - position.x = (position.x + rect.width * 0.5f) / rect.width; - position.y = (position.y + rect.height * 0.5f) / rect.height; - - var textureX = (int)(position.x * m_ColorPickerTexture.width); - var textureY = (int)(position.y * m_ColorPickerTexture.height); - var col = m_ColorPickerTexture.GetPixel(textureX, textureY); - - return col; - } - - public void OnPointerExit(PointerEventData eventData) - { - if (onHideCalled != null) - onHideCalled(); - } -} -#endif +#if UNITY_EDITOR +using UnityEngine; +using System.Collections; +using UnityEngine.UI; +using System; +using UnityEditor.Experimental.EditorVR.Extensions; +using UnityEngine.EventSystems; + +namespace UnityEditor.Experimental.EditorVR.Tools +{ + public class ColorPickerUI : MonoBehaviour, IPointerExitHandler + { + [SerializeField] + float m_FadeTime; + + [SerializeField] + RawImage m_ColorPicker; + + [SerializeField] + RawImage m_SliderBackground; + + [SerializeField] + RectTransform m_Picker; + + [SerializeField] + RectTransform m_PickerBounds; + + [SerializeField] + ColorPickerSquareUI m_ColorPickerSquare; + + Vector3 m_PickerTargetPosition; + + Texture2D m_BrightnessBarTexture; + Texture2D m_ColorPickerTexture; + + Coroutine m_FadeCoroutine; + + public Transform toolRayOrigin { private get; set; } + + public Action onColorPicked { private get; set; } + + public Action onHideCalled { private get; set; } + + void Start() + { + m_ColorPickerSquare.onDrag = OnDrag; + + m_ColorPickerTexture = m_ColorPickerSquare.GetComponent().texture as Texture2D; + GenerateBrightnessBar(); + } + + void OnDestroy() + { + DestroyImmediate(m_BrightnessBarTexture); + } + + void Update() + { + m_Picker.localPosition = m_PickerTargetPosition; + } + + public void Show() + { + this.RestartCoroutine(ref m_FadeCoroutine, FadeCanvas(false)); + } + + public void Hide() + { + this.RestartCoroutine(ref m_FadeCoroutine, FadeCanvas(true)); + } + + public void OnSliderChanged(float val) + { + m_ColorPicker.color = Color.Lerp(Color.black, Color.white, val); + PositionToColor(); + } + + IEnumerator FadeCanvas(bool fadeOut) + { + enabled = !fadeOut; + m_Picker.localPosition = m_PickerTargetPosition; + + var canvasGroup = GetComponentInChildren(); + var current = canvasGroup.alpha; + var start = fadeOut ? 1 : 0; + var target = 1 - start; + + if (current == target) + yield break; + + var ratio = fadeOut ? 1 - current : current; + while (ratio < 1) + { + canvasGroup.alpha = Mathf.Lerp(start, target, ratio); + ratio += Time.unscaledDeltaTime / m_FadeTime; + yield return null; + } + + GetComponentInChildren().enabled = !fadeOut; + m_Picker.gameObject.SetActive(!fadeOut); + canvasGroup.alpha = target; + canvasGroup.interactable = !fadeOut; + canvasGroup.blocksRaycasts = !fadeOut; + } + + void OnDrag() + { + if (toolRayOrigin && enabled) + { + var worldToLocal = m_ColorPicker.rectTransform.worldToLocalMatrix; + var rect = m_ColorPicker.rectTransform.rect; + + var localRayPos = worldToLocal.MultiplyPoint3x4(toolRayOrigin.position); + var localRayForward = worldToLocal.MultiplyVector(toolRayOrigin.forward).normalized; + + var height = localRayPos.z; + var angle = Vector3.Angle(new Vector3(0, 0, height), localRayForward); + var sine = Mathf.Sin((90 - angle) * Mathf.Deg2Rad); + + var distance = Mathf.Abs(height / sine); + var point = localRayPos + localRayForward * distance; + point = point.normalized * Mathf.Min(point.magnitude, rect.width / 2f); + + m_PickerTargetPosition = point; + GenerateBrightnessBar(); + PositionToColor(); + } + } + + void GenerateBrightnessBar() + { + var rect = m_SliderBackground.rectTransform.rect; + if (!m_BrightnessBarTexture) + m_BrightnessBarTexture = new Texture2D((int)rect.width, 1); + + var col = GetColorForCurrentPosition(); + + for (var y = 0; y < m_BrightnessBarTexture.height; y++) + { + for (var x = 0; x < m_BrightnessBarTexture.width; x++) + { + var brightness = x / rect.width; + var tempCol = col * brightness; + tempCol.a = 1; + m_BrightnessBarTexture.SetPixel(x, y, tempCol); + } + } + m_BrightnessBarTexture.Apply(); + + m_SliderBackground.texture = m_BrightnessBarTexture; + } + + void PositionToColor() + { + if (onColorPicked != null) + { + var col = GetColorForCurrentPosition(); + col *= m_ColorPicker.color; // Apply brightness slider + onColorPicked(col); + } + } + + Color GetColorForCurrentPosition() + { + var rect = m_PickerBounds.rect; + + var position = m_PickerTargetPosition; + + position.x = (position.x + rect.width * 0.5f) / rect.width; + position.y = (position.y + rect.height * 0.5f) / rect.height; + + var textureX = (int)(position.x * m_ColorPickerTexture.width); + var textureY = (int)(position.y * m_ColorPickerTexture.height); + var col = m_ColorPickerTexture.GetPixel(textureX, textureY); + + return col; + } + + public void OnPointerExit(PointerEventData eventData) + { + if (onHideCalled != null) + onHideCalled(); + } + } +} +#endif From f055f528ee90d5a9e9301050a97c49ff2c347c10 Mon Sep 17 00:00:00 2001 From: Jono Date: Fri, 8 Dec 2017 01:30:54 -0800 Subject: [PATCH 68/89] WIP ICustomAlternateMenu -> IAlternateMenu refactor, and split actions from IAlternateMenu to IActionsMenu. --- Menus/MainMenu/MainMenu.cs | 860 ++++---- Menus/RadialMenu/RadialMenu.cs | 361 ++-- Menus/UndoMenu/UndoMenu.cs | 381 ++-- Scripts/Actions/ActionMenuItemAttribute.cs | 66 +- Scripts/Core/EditorVR.Menus.cs | 1263 ++++++------ Scripts/Core/EditorVR.Tools.cs | 855 ++++---- Scripts/Core/EditorVR.cs | 1103 +++++----- .../ActionsModuleConnector.cs | 127 +- Scripts/Interfaces/Entity/IAlternateMenu.cs | 32 +- Scripts/Interfaces/Entity/IMainMenu.cs | 136 +- Scripts/Interfaces/Entity/IMenu.cs | 68 +- .../{IUsesMenuActions.cs => IActionsMenu.cs} | 41 +- ...nuActions.cs.meta => IActionsMenu.cs.meta} | 0 .../ICustomAlternateMenu.cs | 10 - .../ICustomAlternateMenu.cs.meta | 13 - .../IInstantiateMenuUI.cs | 3 +- Scripts/Modules/ActionsModule.cs | 139 +- Tools/AnnotationTool/AnnotationTool.cs | 1791 +++++++++-------- .../UserInterface/BrushSizeUI.cs | 23 +- .../CreatePrimitiveMenu.cs | 117 +- Tools/SelectionTool/SelectionTool.cs | 1232 ++++++------ 21 files changed, 4303 insertions(+), 4318 deletions(-) rename Scripts/Interfaces/FunctionalityInjection/{IUsesMenuActions.cs => IActionsMenu.cs} (57%) rename Scripts/Interfaces/FunctionalityInjection/{IUsesMenuActions.cs.meta => IActionsMenu.cs.meta} (100%) delete mode 100644 Scripts/Interfaces/FunctionalityInjection/ICustomAlternateMenu.cs delete mode 100644 Scripts/Interfaces/FunctionalityInjection/ICustomAlternateMenu.cs.meta diff --git a/Menus/MainMenu/MainMenu.cs b/Menus/MainMenu/MainMenu.cs index c125c6b67..0030cfcf4 100644 --- a/Menus/MainMenu/MainMenu.cs +++ b/Menus/MainMenu/MainMenu.cs @@ -1,429 +1,431 @@ -#if UNITY_EDITOR -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.Experimental.EditorVR.Core; -using UnityEditor.Experimental.EditorVR.Proxies; -using UnityEditor.Experimental.EditorVR.Utilities; -using UnityEditor.Experimental.EditorVR.Workspaces; -using UnityEngine; -using UnityEngine.InputNew; - -namespace UnityEditor.Experimental.EditorVR.Menus -{ - sealed class MainMenu : MonoBehaviour, IMainMenu, IConnectInterfaces, IInstantiateUI, ICreateWorkspace, - ICustomActionMap, IUsesMenuOrigins, IUsesDeviceType, IControlHaptics, IUsesNode, IRayToNode, IUsesRayOrigin, - IRequestFeedback - { - const string k_SettingsMenuSectionName = "Settings"; - const float k_MaxFlickDuration = 0.3f; - - [SerializeField] - ActionMap m_ActionMap; - - [SerializeField] - HapticPulse m_FaceRotationPulse; - - [SerializeField] - HapticPulse m_ShowPulse; - - [SerializeField] - HapticPulse m_HidePulse; - - [SerializeField] - MainMenuUI m_MainMenuPrefab; - - [SerializeField] - HapticPulse m_ButtonClickPulse; - - [SerializeField] - HapticPulse m_ButtonHoverPulse; - - Transform m_AlternateMenuOrigin; - Transform m_MenuOrigin; - MainMenuUI m_MainMenuUI; - float m_LastRotationInput; - MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; - float m_RotationInputStartValue; - float m_RotationInputStartTime; - readonly Dictionary m_ToolButtons = new Dictionary(); - readonly Dictionary m_SettingsMenus = new Dictionary(); - readonly Dictionary m_SettingsMenuItems = new Dictionary(); - - readonly BindingDictionary m_Controls = new BindingDictionary(); - - public List menuTools { private get; set; } - public List menuWorkspaces { private get; set; } - public Dictionary, ISettingsMenuProvider> settingsMenuProviders { get; set; } - public Dictionary, ISettingsMenuItemProvider> settingsMenuItemProviders { get; set; } - public List menuActions { get; set; } - public Transform targetRayOrigin { private get; set; } - public Node node { get; set; } - - public GameObject menuContent { get { return m_MainMenuUI.gameObject; } } - - public Transform rayOrigin { private get; set; } - - public Bounds localBounds { get { return m_MainMenuUI.localBounds; } } - - public bool focus { get { return m_MainMenuUI.hovering; } } - - public ActionMap actionMap { get { return m_ActionMap; } } - public bool ignoreLocking { get { return false; } } - - public Transform menuOrigin - { - get { return m_MenuOrigin; } - set - { - m_MenuOrigin = value; - if (m_MainMenuUI) - m_MainMenuUI.menuOrigin = value; - } - } - - public Transform alternateMenuOrigin - { - get { return m_AlternateMenuOrigin; } - set - { - m_AlternateMenuOrigin = value; - if (m_MainMenuUI) - m_MainMenuUI.alternateMenuOrigin = value; - } - } - - public MenuHideFlags menuHideFlags - { - get { return m_MenuHideFlags; } - set - { - var wasVisible = m_MenuHideFlags == 0; - var wasPermanent = (m_MenuHideFlags & MenuHideFlags.Hidden) != 0; - if (m_MenuHideFlags != value) - { - m_MenuHideFlags = value; - var visible = value == 0; - if (m_MainMenuUI) - { - var isPermanent = (value & MenuHideFlags.Hidden) != 0; - m_MainMenuUI.visible = visible; - if (wasPermanent && visible || wasVisible && isPermanent) - SendVisibilityPulse(); - } - - if (visible) - ShowFeedback(); - else - this.ClearFeedbackRequests(); - } - } - } - - void Awake() - { - m_MainMenuUI = this.InstantiateUI(m_MainMenuPrefab.gameObject).GetComponent(); - this.ConnectInterfaces(m_MainMenuUI); - m_MainMenuUI.alternateMenuOrigin = alternateMenuOrigin; - m_MainMenuUI.menuOrigin = menuOrigin; - m_MainMenuUI.Setup(); - - InputUtils.GetBindingDictionaryFromActionMap(m_ActionMap, m_Controls); - } - - void Start() - { - CreateFaceButtons(); - UpdateToolButtons(); - } - - public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl) - { - if (!m_MainMenuUI.visible) - return; - - var mainMenuInput = (MainMenuInput)input; - var rotationInput = -mainMenuInput.rotate.rawValue; - - const float kFlickDeltaThreshold = 0.5f; - - if (this.GetDeviceType() == DeviceType.Vive) - { - if (!Mathf.Approximately(rotationInput, 0f)) - { - var time = Time.time; - if (Mathf.Approximately(m_LastRotationInput, 0f)) - { - // Touch began - m_RotationInputStartValue = rotationInput; - m_RotationInputStartTime = time; - } - else - { - // Touch held - var distance = rotationInput - m_RotationInputStartValue; - var lastDistance = m_LastRotationInput - m_RotationInputStartValue; - if (Mathf.Abs(distance) >= kFlickDeltaThreshold - && Mathf.Abs(lastDistance) < kFlickDeltaThreshold - && time - m_RotationInputStartTime < k_MaxFlickDuration) - { - m_RotationInputStartValue = rotationInput; - m_RotationInputStartTime = time; - if (!m_MainMenuUI.rotating) - { - FlickMenu(distance); - } - } - } - } - } - else if (Mathf.Abs(rotationInput) >= kFlickDeltaThreshold - && Mathf.Abs(m_LastRotationInput) < kFlickDeltaThreshold) - { - FlickMenu(rotationInput); - } - - m_LastRotationInput = rotationInput; - } - - void FlickMenu(float rotationInput) - { - m_MainMenuUI.targetFaceIndex += (int)Mathf.Sign(rotationInput); - this.Pulse(node, m_FaceRotationPulse); - } - - void OnDestroy() - { - if (m_MainMenuUI) - ObjectUtils.Destroy(m_MainMenuUI.gameObject); - } - - void CreateFaceButtons() - { - var types = new HashSet(); - types.UnionWith(menuTools); - types.UnionWith(menuWorkspaces); - types.UnionWith(settingsMenuProviders.Keys.Select(provider => provider.Key)); - types.UnionWith(settingsMenuItemProviders.Keys.Select(provider => provider.Key)); - - foreach (var type in types) - { - var customMenuAttribute = (MainMenuItemAttribute)type.GetCustomAttributes(typeof(MainMenuItemAttribute), false).FirstOrDefault(); - if (customMenuAttribute != null && !customMenuAttribute.shown) - continue; - - var isTool = typeof(ITool).IsAssignableFrom(type) && menuTools.Contains(type); - var isWorkspace = typeof(Workspace).IsAssignableFrom(type); - var isSettingsProvider = typeof(ISettingsMenuProvider).IsAssignableFrom(type); - var isSettingsItemProvider = typeof(ISettingsMenuItemProvider).IsAssignableFrom(type); - - ITooltip tooltip = null; - MainMenuUI.ButtonData buttonData = null; - - var selectedType = type; // Local variable for closure - if (customMenuAttribute != null && customMenuAttribute.shown) - { - tooltip = customMenuAttribute.tooltip; - - buttonData = new MainMenuUI.ButtonData(customMenuAttribute.name) - { - sectionName = customMenuAttribute.sectionName, - description = customMenuAttribute.description - }; - } - - if (isTool) - { - if (buttonData == null) - buttonData = new MainMenuUI.ButtonData(type.Name); - - var mainMenuButton = CreateFaceButton(buttonData, tooltip, () => - { - if (targetRayOrigin) - { - this.SelectTool(targetRayOrigin, selectedType, - hideMenu: typeof(IInstantiateMenuUI).IsAssignableFrom(selectedType)); - UpdateToolButtons(); - } - }); - - m_ToolButtons[type] = mainMenuButton; - - // Assign Tools Menu button preview properties - if (mainMenuButton != null) - mainMenuButton.toolType = selectedType; - } - - if (isWorkspace) - { - // For workspaces that haven't specified a custom attribute, do some menu categorization automatically - if (buttonData == null) - buttonData = new MainMenuUI.ButtonData(type.Name) { sectionName = "Workspaces" }; - - CreateFaceButton(buttonData, tooltip, () => { this.CreateWorkspace(selectedType); }); - } - - if (isSettingsProvider) - { - foreach (var providerPair in settingsMenuProviders) - { - var kvp = providerPair.Key; - if (kvp.Key == type && (kvp.Value == null || kvp.Value == rayOrigin)) - AddSettingsMenu(providerPair.Value, buttonData, tooltip); - } - } - - if (isSettingsItemProvider) - { - foreach (var providerPair in settingsMenuItemProviders) - { - var kvp = providerPair.Key; - if (kvp.Key == type && (kvp.Value == null || kvp.Value == rayOrigin)) - AddSettingsMenuItem(providerPair.Value); - } - } - } - } - - MainMenuButton CreateFaceButton(MainMenuUI.ButtonData buttonData, ITooltip tooltip, Action buttonClickCallback) - { - var mainMenuButton = m_MainMenuUI.CreateFaceButton(buttonData); - if (mainMenuButton == null) - return null; - - var button = mainMenuButton.button; - button.onClick.RemoveAllListeners(); - button.onClick.AddListener(() => - { - if (m_MenuHideFlags == 0) - buttonClickCallback(); - }); - - mainMenuButton.hovered += OnButtonHovered; - mainMenuButton.clicked += OnButtonClicked; - mainMenuButton.tooltip = tooltip; - - return mainMenuButton; - } - - void UpdateToolButtons() - { - foreach (var kvp in m_ToolButtons) - { - kvp.Value.selected = this.IsToolActive(targetRayOrigin, kvp.Key); - } - } - - void OnButtonClicked(Transform rayOrigin) - { - this.Pulse(this.RequestNodeFromRayOrigin(rayOrigin), m_ButtonClickPulse); - } - - void OnButtonHovered(Transform rayOrigin, Type buttonType, string buttonDescription) - { - this.Pulse(this.RequestNodeFromRayOrigin(rayOrigin), m_ButtonHoverPulse); - - // Pass the pointer which is over us, so this information can supply context (e.g. selecting a tool for a different hand) - // Enable preview-mode on a Tools Menu button; Display on the opposite proxy device by evaluating the entering RayOrigin - // Disable any existing previews being displayed in ToolsMenus - this.ClearToolMenuButtonPreview(); - - if (buttonType != null && rayOrigin != null) - this.PreviewInToolMenuButton(rayOrigin, buttonType, buttonDescription); - } - - void SendVisibilityPulse() - { - this.Pulse(node, m_MenuHideFlags == 0 ? m_HidePulse : m_ShowPulse); - } - - public void AddSettingsMenu(ISettingsMenuProvider provider) - { - var type = provider.GetType(); - var customMenuAttribute = (MainMenuItemAttribute)type.GetCustomAttributes(typeof(MainMenuItemAttribute), false).FirstOrDefault(); - - ITooltip tooltip = null; - MainMenuUI.ButtonData buttonData; - if (customMenuAttribute != null && customMenuAttribute.shown) - { - tooltip = customMenuAttribute.tooltip; - - buttonData = new MainMenuUI.ButtonData(customMenuAttribute.name) - { - sectionName = customMenuAttribute.sectionName, - description = customMenuAttribute.description - }; - } - else - { - buttonData = new MainMenuUI.ButtonData(type.Name); - } - - AddSettingsMenu(provider, buttonData, tooltip); - } - - void AddSettingsMenu(ISettingsMenuProvider provider, MainMenuUI.ButtonData buttonData, ITooltip tooltip) - { - buttonData.sectionName = k_SettingsMenuSectionName; - - CreateFaceButton(buttonData, tooltip, () => - { - var instance = m_MainMenuUI.AddSubmenu(k_SettingsMenuSectionName, provider.settingsMenuPrefab); - m_SettingsMenus[provider] = instance; - provider.settingsMenuInstance = instance; - }); - } - - public void RemoveSettingsMenu(ISettingsMenuProvider provider) - { - GameObject instance; - if (m_SettingsMenus.TryGetValue(provider, out instance)) - { - if (instance) - ObjectUtils.Destroy(instance); - - m_SettingsMenus.Remove(provider); - } - provider.settingsMenuInstance = null; - } - - public void AddSettingsMenuItem(ISettingsMenuItemProvider provider) - { - var instance = m_MainMenuUI.CreateCustomButton(provider.settingsMenuItemPrefab, k_SettingsMenuSectionName); - m_SettingsMenuItems[provider] = instance; - provider.settingsMenuItemInstance = instance; - } - - public void RemoveSettingsMenuItem(ISettingsMenuItemProvider provider) - { - GameObject instance; - if (m_SettingsMenuItems.TryGetValue(provider, out instance)) - { - if (instance) - ObjectUtils.Destroy(instance); - - m_SettingsMenuItems.Remove(provider); - } - provider.settingsMenuItemInstance = null; - } - - void ShowFeedback() - { - var tooltipText = this.GetDeviceType() == DeviceType.Vive ? "Swipe to Rotate Menu" : "Rotate Menu"; - List controls; - if (m_Controls.TryGetValue("FlickFace", out controls)) - { - foreach (var id in controls) - { - this.AddFeedbackRequest(new ProxyFeedbackRequest - { - control = id, - node = node, - tooltipText = tooltipText - }); - } - } - } - } -} -#endif +#if UNITY_EDITOR +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor.Experimental.EditorVR.Core; +using UnityEditor.Experimental.EditorVR.Proxies; +using UnityEditor.Experimental.EditorVR.Utilities; +using UnityEditor.Experimental.EditorVR.Workspaces; +using UnityEngine; +using UnityEngine.InputNew; + +namespace UnityEditor.Experimental.EditorVR.Menus +{ + sealed class MainMenu : MonoBehaviour, IMainMenu, IConnectInterfaces, IInstantiateUI, ICreateWorkspace, + ICustomActionMap, IUsesMenuOrigins, IUsesDeviceType, IControlHaptics, IUsesNode, IRayToNode, IUsesRayOrigin, + IRequestFeedback + { + const string k_SettingsMenuSectionName = "Settings"; + const float k_MaxFlickDuration = 0.3f; + + [SerializeField] + ActionMap m_ActionMap; + + [SerializeField] + HapticPulse m_FaceRotationPulse; + + [SerializeField] + HapticPulse m_ShowPulse; + + [SerializeField] + HapticPulse m_HidePulse; + + [SerializeField] + MainMenuUI m_MainMenuPrefab; + + [SerializeField] + HapticPulse m_ButtonClickPulse; + + [SerializeField] + HapticPulse m_ButtonHoverPulse; + + Transform m_AlternateMenuOrigin; + Transform m_MenuOrigin; + MainMenuUI m_MainMenuUI; + float m_LastRotationInput; + MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; + float m_RotationInputStartValue; + float m_RotationInputStartTime; + readonly Dictionary m_ToolButtons = new Dictionary(); + readonly Dictionary m_SettingsMenus = new Dictionary(); + readonly Dictionary m_SettingsMenuItems = new Dictionary(); + + readonly BindingDictionary m_Controls = new BindingDictionary(); + + public List menuTools { private get; set; } + public List menuWorkspaces { private get; set; } + public Dictionary, ISettingsMenuProvider> settingsMenuProviders { get; set; } + public Dictionary, ISettingsMenuItemProvider> settingsMenuItemProviders { get; set; } + public List menuActions { get; set; } + public event Action itemWasSelected; + public Transform targetRayOrigin { private get; set; } + public Node node { get; set; } + + public GameObject menuContent { get { return m_MainMenuUI.gameObject; } } + + public Transform rayOrigin { private get; set; } + + public Bounds localBounds { get { return m_MainMenuUI.localBounds; } } + public int priority { get { return 0; } } + + public bool focus { get { return m_MainMenuUI.hovering; } } + + public ActionMap actionMap { get { return m_ActionMap; } } + public bool ignoreLocking { get { return false; } } + + public Transform menuOrigin + { + get { return m_MenuOrigin; } + set + { + m_MenuOrigin = value; + if (m_MainMenuUI) + m_MainMenuUI.menuOrigin = value; + } + } + + public Transform alternateMenuOrigin + { + get { return m_AlternateMenuOrigin; } + set + { + m_AlternateMenuOrigin = value; + if (m_MainMenuUI) + m_MainMenuUI.alternateMenuOrigin = value; + } + } + + public MenuHideFlags menuHideFlags + { + get { return m_MenuHideFlags; } + set + { + var wasVisible = m_MenuHideFlags == 0; + var wasPermanent = (m_MenuHideFlags & MenuHideFlags.Hidden) != 0; + if (m_MenuHideFlags != value) + { + m_MenuHideFlags = value; + var visible = value == 0; + if (m_MainMenuUI) + { + var isPermanent = (value & MenuHideFlags.Hidden) != 0; + m_MainMenuUI.visible = visible; + if (wasPermanent && visible || wasVisible && isPermanent) + SendVisibilityPulse(); + } + + if (visible) + ShowFeedback(); + else + this.ClearFeedbackRequests(); + } + } + } + + void Awake() + { + m_MainMenuUI = this.InstantiateUI(m_MainMenuPrefab.gameObject).GetComponent(); + this.ConnectInterfaces(m_MainMenuUI); + m_MainMenuUI.alternateMenuOrigin = alternateMenuOrigin; + m_MainMenuUI.menuOrigin = menuOrigin; + m_MainMenuUI.Setup(); + + InputUtils.GetBindingDictionaryFromActionMap(m_ActionMap, m_Controls); + } + + void Start() + { + CreateFaceButtons(); + UpdateToolButtons(); + } + + public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl) + { + if (!m_MainMenuUI.visible) + return; + + var mainMenuInput = (MainMenuInput)input; + var rotationInput = -mainMenuInput.rotate.rawValue; + + const float kFlickDeltaThreshold = 0.5f; + + if (this.GetDeviceType() == DeviceType.Vive) + { + if (!Mathf.Approximately(rotationInput, 0f)) + { + var time = Time.time; + if (Mathf.Approximately(m_LastRotationInput, 0f)) + { + // Touch began + m_RotationInputStartValue = rotationInput; + m_RotationInputStartTime = time; + } + else + { + // Touch held + var distance = rotationInput - m_RotationInputStartValue; + var lastDistance = m_LastRotationInput - m_RotationInputStartValue; + if (Mathf.Abs(distance) >= kFlickDeltaThreshold + && Mathf.Abs(lastDistance) < kFlickDeltaThreshold + && time - m_RotationInputStartTime < k_MaxFlickDuration) + { + m_RotationInputStartValue = rotationInput; + m_RotationInputStartTime = time; + if (!m_MainMenuUI.rotating) + { + FlickMenu(distance); + } + } + } + } + } + else if (Mathf.Abs(rotationInput) >= kFlickDeltaThreshold + && Mathf.Abs(m_LastRotationInput) < kFlickDeltaThreshold) + { + FlickMenu(rotationInput); + } + + m_LastRotationInput = rotationInput; + } + + void FlickMenu(float rotationInput) + { + m_MainMenuUI.targetFaceIndex += (int)Mathf.Sign(rotationInput); + this.Pulse(node, m_FaceRotationPulse); + } + + void OnDestroy() + { + if (m_MainMenuUI) + ObjectUtils.Destroy(m_MainMenuUI.gameObject); + } + + void CreateFaceButtons() + { + var types = new HashSet(); + types.UnionWith(menuTools); + types.UnionWith(menuWorkspaces); + types.UnionWith(settingsMenuProviders.Keys.Select(provider => provider.Key)); + types.UnionWith(settingsMenuItemProviders.Keys.Select(provider => provider.Key)); + + foreach (var type in types) + { + var customMenuAttribute = (MainMenuItemAttribute)type.GetCustomAttributes(typeof(MainMenuItemAttribute), false).FirstOrDefault(); + if (customMenuAttribute != null && !customMenuAttribute.shown) + continue; + + var isTool = typeof(ITool).IsAssignableFrom(type) && menuTools.Contains(type); + var isWorkspace = typeof(Workspace).IsAssignableFrom(type); + var isSettingsProvider = typeof(ISettingsMenuProvider).IsAssignableFrom(type); + var isSettingsItemProvider = typeof(ISettingsMenuItemProvider).IsAssignableFrom(type); + + ITooltip tooltip = null; + MainMenuUI.ButtonData buttonData = null; + + var selectedType = type; // Local variable for closure + if (customMenuAttribute != null && customMenuAttribute.shown) + { + tooltip = customMenuAttribute.tooltip; + + buttonData = new MainMenuUI.ButtonData(customMenuAttribute.name) + { + sectionName = customMenuAttribute.sectionName, + description = customMenuAttribute.description + }; + } + + if (isTool) + { + if (buttonData == null) + buttonData = new MainMenuUI.ButtonData(type.Name); + + var mainMenuButton = CreateFaceButton(buttonData, tooltip, () => + { + if (targetRayOrigin) + { + this.SelectTool(targetRayOrigin, selectedType, + hideMenu: typeof(IInstantiateMenuUI).IsAssignableFrom(selectedType)); + UpdateToolButtons(); + } + }); + + m_ToolButtons[type] = mainMenuButton; + + // Assign Tools Menu button preview properties + if (mainMenuButton != null) + mainMenuButton.toolType = selectedType; + } + + if (isWorkspace) + { + // For workspaces that haven't specified a custom attribute, do some menu categorization automatically + if (buttonData == null) + buttonData = new MainMenuUI.ButtonData(type.Name) { sectionName = "Workspaces" }; + + CreateFaceButton(buttonData, tooltip, () => { this.CreateWorkspace(selectedType); }); + } + + if (isSettingsProvider) + { + foreach (var providerPair in settingsMenuProviders) + { + var kvp = providerPair.Key; + if (kvp.Key == type && (kvp.Value == null || kvp.Value == rayOrigin)) + AddSettingsMenu(providerPair.Value, buttonData, tooltip); + } + } + + if (isSettingsItemProvider) + { + foreach (var providerPair in settingsMenuItemProviders) + { + var kvp = providerPair.Key; + if (kvp.Key == type && (kvp.Value == null || kvp.Value == rayOrigin)) + AddSettingsMenuItem(providerPair.Value); + } + } + } + } + + MainMenuButton CreateFaceButton(MainMenuUI.ButtonData buttonData, ITooltip tooltip, Action buttonClickCallback) + { + var mainMenuButton = m_MainMenuUI.CreateFaceButton(buttonData); + if (mainMenuButton == null) + return null; + + var button = mainMenuButton.button; + button.onClick.RemoveAllListeners(); + button.onClick.AddListener(() => + { + if (m_MenuHideFlags == 0) + buttonClickCallback(); + }); + + mainMenuButton.hovered += OnButtonHovered; + mainMenuButton.clicked += OnButtonClicked; + mainMenuButton.tooltip = tooltip; + + return mainMenuButton; + } + + void UpdateToolButtons() + { + foreach (var kvp in m_ToolButtons) + { + kvp.Value.selected = this.IsToolActive(targetRayOrigin, kvp.Key); + } + } + + void OnButtonClicked(Transform rayOrigin) + { + this.Pulse(this.RequestNodeFromRayOrigin(rayOrigin), m_ButtonClickPulse); + } + + void OnButtonHovered(Transform rayOrigin, Type buttonType, string buttonDescription) + { + this.Pulse(this.RequestNodeFromRayOrigin(rayOrigin), m_ButtonHoverPulse); + + // Pass the pointer which is over us, so this information can supply context (e.g. selecting a tool for a different hand) + // Enable preview-mode on a Tools Menu button; Display on the opposite proxy device by evaluating the entering RayOrigin + // Disable any existing previews being displayed in ToolsMenus + this.ClearToolMenuButtonPreview(); + + if (buttonType != null && rayOrigin != null) + this.PreviewInToolMenuButton(rayOrigin, buttonType, buttonDescription); + } + + void SendVisibilityPulse() + { + this.Pulse(node, m_MenuHideFlags == 0 ? m_HidePulse : m_ShowPulse); + } + + public void AddSettingsMenu(ISettingsMenuProvider provider) + { + var type = provider.GetType(); + var customMenuAttribute = (MainMenuItemAttribute)type.GetCustomAttributes(typeof(MainMenuItemAttribute), false).FirstOrDefault(); + + ITooltip tooltip = null; + MainMenuUI.ButtonData buttonData; + if (customMenuAttribute != null && customMenuAttribute.shown) + { + tooltip = customMenuAttribute.tooltip; + + buttonData = new MainMenuUI.ButtonData(customMenuAttribute.name) + { + sectionName = customMenuAttribute.sectionName, + description = customMenuAttribute.description + }; + } + else + { + buttonData = new MainMenuUI.ButtonData(type.Name); + } + + AddSettingsMenu(provider, buttonData, tooltip); + } + + void AddSettingsMenu(ISettingsMenuProvider provider, MainMenuUI.ButtonData buttonData, ITooltip tooltip) + { + buttonData.sectionName = k_SettingsMenuSectionName; + + CreateFaceButton(buttonData, tooltip, () => + { + var instance = m_MainMenuUI.AddSubmenu(k_SettingsMenuSectionName, provider.settingsMenuPrefab); + m_SettingsMenus[provider] = instance; + provider.settingsMenuInstance = instance; + }); + } + + public void RemoveSettingsMenu(ISettingsMenuProvider provider) + { + GameObject instance; + if (m_SettingsMenus.TryGetValue(provider, out instance)) + { + if (instance) + ObjectUtils.Destroy(instance); + + m_SettingsMenus.Remove(provider); + } + provider.settingsMenuInstance = null; + } + + public void AddSettingsMenuItem(ISettingsMenuItemProvider provider) + { + var instance = m_MainMenuUI.CreateCustomButton(provider.settingsMenuItemPrefab, k_SettingsMenuSectionName); + m_SettingsMenuItems[provider] = instance; + provider.settingsMenuItemInstance = instance; + } + + public void RemoveSettingsMenuItem(ISettingsMenuItemProvider provider) + { + GameObject instance; + if (m_SettingsMenuItems.TryGetValue(provider, out instance)) + { + if (instance) + ObjectUtils.Destroy(instance); + + m_SettingsMenuItems.Remove(provider); + } + provider.settingsMenuItemInstance = null; + } + + void ShowFeedback() + { + var tooltipText = this.GetDeviceType() == DeviceType.Vive ? "Swipe to Rotate Menu" : "Rotate Menu"; + List controls; + if (m_Controls.TryGetValue("FlickFace", out controls)) + { + foreach (var id in controls) + { + this.AddFeedbackRequest(new ProxyFeedbackRequest + { + control = id, + node = node, + tooltipText = tooltipText + }); + } + } + } + } +} +#endif diff --git a/Menus/RadialMenu/RadialMenu.cs b/Menus/RadialMenu/RadialMenu.cs index 5d52e66ae..f478708e1 100644 --- a/Menus/RadialMenu/RadialMenu.cs +++ b/Menus/RadialMenu/RadialMenu.cs @@ -1,180 +1,181 @@ -#if UNITY_EDITOR -using System; -using System.Collections.Generic; -using UnityEditor.Experimental.EditorVR.Core; -using UnityEditor.Experimental.EditorVR.Proxies; -using UnityEditor.Experimental.EditorVR.Utilities; -using UnityEngine; -using UnityEngine.InputNew; - -namespace UnityEditor.Experimental.EditorVR.Menus -{ - sealed class RadialMenu : MonoBehaviour, IInstantiateUI, IAlternateMenu, IUsesMenuOrigins, ICustomActionMap, - IControlHaptics, IUsesNode, IConnectInterfaces, IRequestFeedback - { - const float k_ActivationThreshold = 0.5f; // Do not consume thumbstick or activate menu if the control vector's magnitude is below this threshold - - [SerializeField] - ActionMap m_ActionMap; - - [SerializeField] - RadialMenuUI m_RadialMenuPrefab; - - [SerializeField] - HapticPulse m_ReleasePulse; - - [SerializeField] - HapticPulse m_ButtonHoverPulse; - - [SerializeField] - HapticPulse m_ButtonClickedPulse; - - RadialMenuUI m_RadialMenuUI; - List m_MenuActions; - Transform m_AlternateMenuOrigin; - MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; - - readonly BindingDictionary m_Controls = new BindingDictionary(); - - public event Action itemWasSelected; - - public Transform rayOrigin { private get; set; } - - public Transform menuOrigin { get; set; } - - public GameObject menuContent { get { return m_RadialMenuUI.gameObject; } } - - public Node node { get; set; } - - public Bounds localBounds { get { return default(Bounds); } } - - public ActionMap actionMap { get { return m_ActionMap; } } - public bool ignoreLocking { get { return false; } } - - public List menuActions - { - get { return m_MenuActions; } - set - { - m_MenuActions = value; - - if (m_RadialMenuUI) - m_RadialMenuUI.actions = value; - } - } - - public Transform alternateMenuOrigin - { - get { return m_AlternateMenuOrigin; } - set - { - m_AlternateMenuOrigin = value; - - if (m_RadialMenuUI != null) - m_RadialMenuUI.alternateMenuOrigin = value; - } - } - - public MenuHideFlags menuHideFlags - { - get { return m_MenuHideFlags; } - set - { - if (m_MenuHideFlags != value) - { - m_MenuHideFlags = value; - var visible = value == 0; - if (m_RadialMenuUI) - m_RadialMenuUI.visible = visible; - - if (visible) - ShowFeedback(); - else - this.ClearFeedbackRequests(); - } - } - } - - void Start() - { - m_RadialMenuUI = this.InstantiateUI(m_RadialMenuPrefab.gameObject).GetComponent(); - m_RadialMenuUI.alternateMenuOrigin = alternateMenuOrigin; - m_RadialMenuUI.actions = menuActions; - this.ConnectInterfaces(m_RadialMenuUI); // Connect interfaces before performing setup on the UI - m_RadialMenuUI.Setup(); - m_RadialMenuUI.buttonHovered += OnButtonHovered; - m_RadialMenuUI.buttonClicked += OnButtonClicked; - - InputUtils.GetBindingDictionaryFromActionMap(m_ActionMap, m_Controls); - } - - public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl) - { - var radialMenuInput = (RadialMenuInput)input; - if (radialMenuInput == null || m_MenuHideFlags != 0) - { - this.ClearFeedbackRequests(); - return; - } - - var inputDirection = radialMenuInput.navigate.vector2; - - if (inputDirection.magnitude > k_ActivationThreshold) - { - // Composite controls need to be consumed separately - consumeControl(radialMenuInput.navigateX); - consumeControl(radialMenuInput.navigateY); - m_RadialMenuUI.buttonInputDirection = inputDirection; - } - else - { - m_RadialMenuUI.buttonInputDirection = Vector2.zero; - } - - var selectControl = radialMenuInput.selectItem; - m_RadialMenuUI.pressedDown = selectControl.wasJustPressed; - if (m_RadialMenuUI.pressedDown) - consumeControl(selectControl); - - if (selectControl.wasJustReleased) - { - this.Pulse(node, m_ReleasePulse); - - m_RadialMenuUI.SelectionOccurred(); - - if (itemWasSelected != null) - itemWasSelected(rayOrigin); - - consumeControl(selectControl); - } - } - - void OnButtonClicked() - { - this.Pulse(node, m_ButtonClickedPulse); - } - - void OnButtonHovered() - { - this.Pulse(node, m_ButtonHoverPulse); - } - - void ShowFeedback() - { - List controls; - if (m_Controls.TryGetValue("SelectItem", out controls)) - { - foreach (var id in controls) - { - this.AddFeedbackRequest(new ProxyFeedbackRequest - { - control = id, - node = node, - tooltipText = "Select Action (Press to Execute)" - }); - } - } - } - } -} -#endif +#if UNITY_EDITOR +using System; +using System.Collections.Generic; +using UnityEditor.Experimental.EditorVR.Core; +using UnityEditor.Experimental.EditorVR.Proxies; +using UnityEditor.Experimental.EditorVR.Utilities; +using UnityEngine; +using UnityEngine.InputNew; + +namespace UnityEditor.Experimental.EditorVR.Menus +{ + sealed class RadialMenu : MonoBehaviour, IInstantiateUI, IAlternateMenu, IUsesMenuOrigins, ICustomActionMap, + IControlHaptics, IUsesNode, IConnectInterfaces, IRequestFeedback, IActionsMenu + { + const float k_ActivationThreshold = 0.5f; // Do not consume thumbstick or activate menu if the control vector's magnitude is below this threshold + + [SerializeField] + ActionMap m_ActionMap; + + [SerializeField] + RadialMenuUI m_RadialMenuPrefab; + + [SerializeField] + HapticPulse m_ReleasePulse; + + [SerializeField] + HapticPulse m_ButtonHoverPulse; + + [SerializeField] + HapticPulse m_ButtonClickedPulse; + + RadialMenuUI m_RadialMenuUI; + List m_MenuActions; + Transform m_AlternateMenuOrigin; + MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; + + readonly BindingDictionary m_Controls = new BindingDictionary(); + + public event Action itemWasSelected; + + public Transform rayOrigin { private get; set; } + + public Transform menuOrigin { get; set; } + + public GameObject menuContent { get { return m_RadialMenuUI.gameObject; } } + + public Node node { get; set; } + + public Bounds localBounds { get { return default(Bounds); } } + public int priority { get { return 1; } } + + public ActionMap actionMap { get { return m_ActionMap; } } + public bool ignoreLocking { get { return false; } } + + public List menuActions + { + get { return m_MenuActions; } + set + { + m_MenuActions = value; + + if (m_RadialMenuUI) + m_RadialMenuUI.actions = value; + } + } + + public Transform alternateMenuOrigin + { + get { return m_AlternateMenuOrigin; } + set + { + m_AlternateMenuOrigin = value; + + if (m_RadialMenuUI != null) + m_RadialMenuUI.alternateMenuOrigin = value; + } + } + + public MenuHideFlags menuHideFlags + { + get { return m_MenuHideFlags; } + set + { + if (m_MenuHideFlags != value) + { + m_MenuHideFlags = value; + var visible = value == 0; + if (m_RadialMenuUI) + m_RadialMenuUI.visible = visible; + + if (visible) + ShowFeedback(); + else + this.ClearFeedbackRequests(); + } + } + } + + void Start() + { + m_RadialMenuUI = this.InstantiateUI(m_RadialMenuPrefab.gameObject).GetComponent(); + m_RadialMenuUI.alternateMenuOrigin = alternateMenuOrigin; + m_RadialMenuUI.actions = menuActions; + this.ConnectInterfaces(m_RadialMenuUI); // Connect interfaces before performing setup on the UI + m_RadialMenuUI.Setup(); + m_RadialMenuUI.buttonHovered += OnButtonHovered; + m_RadialMenuUI.buttonClicked += OnButtonClicked; + + InputUtils.GetBindingDictionaryFromActionMap(m_ActionMap, m_Controls); + } + + public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl) + { + var radialMenuInput = (RadialMenuInput)input; + if (radialMenuInput == null || m_MenuHideFlags != 0) + { + this.ClearFeedbackRequests(); + return; + } + + var inputDirection = radialMenuInput.navigate.vector2; + + if (inputDirection.magnitude > k_ActivationThreshold) + { + // Composite controls need to be consumed separately + consumeControl(radialMenuInput.navigateX); + consumeControl(radialMenuInput.navigateY); + m_RadialMenuUI.buttonInputDirection = inputDirection; + } + else + { + m_RadialMenuUI.buttonInputDirection = Vector2.zero; + } + + var selectControl = radialMenuInput.selectItem; + m_RadialMenuUI.pressedDown = selectControl.wasJustPressed; + if (m_RadialMenuUI.pressedDown) + consumeControl(selectControl); + + if (selectControl.wasJustReleased) + { + this.Pulse(node, m_ReleasePulse); + + m_RadialMenuUI.SelectionOccurred(); + + if (itemWasSelected != null) + itemWasSelected(rayOrigin); + + consumeControl(selectControl); + } + } + + void OnButtonClicked() + { + this.Pulse(node, m_ButtonClickedPulse); + } + + void OnButtonHovered() + { + this.Pulse(node, m_ButtonHoverPulse); + } + + void ShowFeedback() + { + List controls; + if (m_Controls.TryGetValue("SelectItem", out controls)) + { + foreach (var id in controls) + { + this.AddFeedbackRequest(new ProxyFeedbackRequest + { + control = id, + node = node, + tooltipText = "Select Action (Press to Execute)" + }); + } + } + } + } +} +#endif diff --git a/Menus/UndoMenu/UndoMenu.cs b/Menus/UndoMenu/UndoMenu.cs index 4ce1c2ccc..30c26a4bc 100644 --- a/Menus/UndoMenu/UndoMenu.cs +++ b/Menus/UndoMenu/UndoMenu.cs @@ -1,192 +1,189 @@ -#if UNITY_EDITOR -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEditor.Experimental.EditorVR.Core; -using UnityEditor.Experimental.EditorVR.Extensions; -using UnityEditor.Experimental.EditorVR.Proxies; -using UnityEditor.Experimental.EditorVR.Utilities; -using UnityEngine; -using UnityEngine.InputNew; - -namespace UnityEditor.Experimental.EditorVR.Menus -{ - sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IUsesMenuOrigins, ICustomActionMap, - IControlHaptics, IUsesNode, IConnectInterfaces, IRequestFeedback, IUsesDeviceType, ICustomAlternateMenu - { - const float k_UndoRedoThreshold = 0.5f; - const string k_EngageControlName = "Engage"; - const float k_EngageUndoAfterStickReleasedDuration = 0.1f; // Duration after releasing the joystick to still accept a left/right flick to undo/redo. - const string k_FeedbackHintForJoystickController = "Click + flick left/right to undo/redo"; - const string k_FeedbackHintForTrackpadController = "Click left/right side to undo/redo"; - - [SerializeField] - ActionMap m_ActionMap; - - [SerializeField] - UndoMenuUI m_UndoMenuPrefab; - - [SerializeField] - HapticPulse m_UndoPulse; - - UndoMenuUI m_UndoMenuUI; - List m_MenuActions; - Transform m_AlternateMenuOrigin; - MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; - float m_PrevNavigateX; - bool m_StillEngagedAfterStickRelease; - Coroutine m_StillEngagedAfterStickReleasedCoroutine; - bool m_TrackpadController; - string m_FeedbackHintForCurrentController; - - readonly BindingDictionary m_Controls = new BindingDictionary(); - - public Transform menuOrigin { get; set; } - - public GameObject menuContent { get { return m_UndoMenuUI.gameObject; } } - - public Node node { get; set; } - - public Bounds localBounds { get { return default(Bounds); } } - - public ActionMap actionMap { get { return m_ActionMap; } } - public bool ignoreLocking { get { return false; } } - - public int menuPriority { get { return 1; } } - - public Transform alternateMenuOrigin - { - get { return m_AlternateMenuOrigin; } - set - { - m_AlternateMenuOrigin = value; - - if (m_UndoMenuUI != null) - m_UndoMenuUI.alternateMenuOrigin = value; - } - } - - public MenuHideFlags menuHideFlags - { - get { return m_MenuHideFlags; } - set - { - if (m_MenuHideFlags != value) - { - m_MenuHideFlags = value; - - var visible = value == 0; - if (m_UndoMenuUI) - m_UndoMenuUI.visible = visible; - - if (visible) - ShowFeedback(); - } - } - } - - void Start() - { - m_UndoMenuUI = this.InstantiateUI(m_UndoMenuPrefab.gameObject).GetComponent(); - m_UndoMenuUI.alternateMenuOrigin = alternateMenuOrigin; - this.ConnectInterfaces(m_UndoMenuUI); // Connect interfaces before performing setup on the UI - m_UndoMenuUI.gameObject.SetActive(false); - InputUtils.GetBindingDictionaryFromActionMap(m_ActionMap, m_Controls); - m_TrackpadController = this.GetDeviceType() == DeviceType.Vive; - m_FeedbackHintForCurrentController = m_TrackpadController - ? k_FeedbackHintForTrackpadController - : k_FeedbackHintForJoystickController; - } - - public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl) - { - if (!m_UndoMenuUI.visible) - return; - - var undoMenuInput = (UndoMenuInput)input; - if (undoMenuInput == null) - { - this.ClearFeedbackRequests(); - return; - } - - if (undoMenuInput.engage.wasJustReleased && !m_TrackpadController) - this.RestartCoroutine(ref m_StillEngagedAfterStickReleasedCoroutine, AcceptInputAfterStickReleased()); - - if (!(undoMenuInput.engage.wasJustPressed || !m_TrackpadController && (undoMenuInput.engage.isHeld || m_StillEngagedAfterStickRelease))) - return; - - consumeControl(undoMenuInput.engage); - m_UndoMenuUI.engaged = true; - - var navigateX = undoMenuInput.navigateX.value; - var undoRedoPerformed = false; - if (navigateX < -k_UndoRedoThreshold && (m_TrackpadController || m_PrevNavigateX > -k_UndoRedoThreshold)) - { - Undo.PerformUndo(); - m_UndoMenuUI.StartPerformedAnimation(true); - ShowUndoPerformedFeedback(true); - undoRedoPerformed = true; - } - else if (navigateX > k_UndoRedoThreshold && (m_TrackpadController || m_PrevNavigateX < k_UndoRedoThreshold)) - { - Undo.PerformRedo(); - m_UndoMenuUI.StartPerformedAnimation(false); - ShowUndoPerformedFeedback(false); - undoRedoPerformed = true; - } - - m_PrevNavigateX = navigateX; - - if (undoRedoPerformed) - { - consumeControl(undoMenuInput.navigateX); - this.StopCoroutine(ref m_StillEngagedAfterStickReleasedCoroutine); - this.Pulse(node, m_UndoPulse); - } - } - - IEnumerator AcceptInputAfterStickReleased() - { - m_StillEngagedAfterStickRelease = true; - yield return new WaitForSeconds(k_EngageUndoAfterStickReleasedDuration); - m_StillEngagedAfterStickRelease = false; - m_UndoMenuUI.engaged = false; - } - - void ShowFeedback() - { - List controls; - if (m_Controls.TryGetValue(k_EngageControlName, out controls)) - { - foreach (var id in controls) - { - this.AddFeedbackRequest(new ProxyFeedbackRequest - { - control = id, - node = node, - tooltipText = m_FeedbackHintForCurrentController - }); - } - } - } - - void ShowUndoPerformedFeedback(bool undo) - { - List controls; - if (m_Controls.TryGetValue(k_EngageControlName, out controls)) - { - foreach (var id in controls) - { - this.AddFeedbackRequest(new ProxyFeedbackRequest - { - control = id, - node = node, - tooltipText = string.Format("{0} performed", undo ? "Undo" : "Redo") - }); - } - } - } - } -} -#endif +#if UNITY_EDITOR +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEditor.Experimental.EditorVR.Core; +using UnityEditor.Experimental.EditorVR.Extensions; +using UnityEditor.Experimental.EditorVR.Proxies; +using UnityEditor.Experimental.EditorVR.Utilities; +using UnityEngine; +using UnityEngine.InputNew; + +namespace UnityEditor.Experimental.EditorVR.Menus +{ + sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IUsesMenuOrigins, ICustomActionMap, + IControlHaptics, IUsesNode, IConnectInterfaces, IRequestFeedback, IUsesDeviceType, IAlternateMenu + { + const float k_UndoRedoThreshold = 0.5f; + const string k_EngageControlName = "Engage"; + const float k_EngageUndoAfterStickReleasedDuration = 0.1f; // Duration after releasing the joystick to still accept a left/right flick to undo/redo. + const string k_FeedbackHintForJoystickController = "Click + flick left/right to undo/redo"; + const string k_FeedbackHintForTrackpadController = "Click left/right side to undo/redo"; + + [SerializeField] + ActionMap m_ActionMap; + + [SerializeField] + UndoMenuUI m_UndoMenuPrefab; + + [SerializeField] + HapticPulse m_UndoPulse; + + UndoMenuUI m_UndoMenuUI; + List m_MenuActions; + Transform m_AlternateMenuOrigin; + MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; + float m_PrevNavigateX; + bool m_StillEngagedAfterStickRelease; + Coroutine m_StillEngagedAfterStickReleasedCoroutine; + bool m_TrackpadController; + string m_FeedbackHintForCurrentController; + + readonly BindingDictionary m_Controls = new BindingDictionary(); + + public Transform menuOrigin { get; set; } + public Transform rayOrigin { get; set; } + public Node node { get; set; } + + public GameObject menuContent { get { return m_UndoMenuUI.gameObject; } } + public Bounds localBounds { get { return default(Bounds); } } + public int priority { get { return 0; } } + public ActionMap actionMap { get { return m_ActionMap; } } + public bool ignoreLocking { get { return false; } } + + public Transform alternateMenuOrigin + { + get { return m_AlternateMenuOrigin; } + set + { + m_AlternateMenuOrigin = value; + + if (m_UndoMenuUI != null) + m_UndoMenuUI.alternateMenuOrigin = value; + } + } + + public MenuHideFlags menuHideFlags + { + get { return m_MenuHideFlags; } + set + { + if (m_MenuHideFlags != value) + { + m_MenuHideFlags = value; + + var visible = value == 0; + if (m_UndoMenuUI) + m_UndoMenuUI.visible = visible; + + if (visible) + ShowFeedback(); + } + } + } + + void Start() + { + m_UndoMenuUI = this.InstantiateUI(m_UndoMenuPrefab.gameObject).GetComponent(); + m_UndoMenuUI.alternateMenuOrigin = alternateMenuOrigin; + this.ConnectInterfaces(m_UndoMenuUI); // Connect interfaces before performing setup on the UI + m_UndoMenuUI.gameObject.SetActive(false); + InputUtils.GetBindingDictionaryFromActionMap(m_ActionMap, m_Controls); + m_TrackpadController = this.GetDeviceType() == DeviceType.Vive; + m_FeedbackHintForCurrentController = m_TrackpadController + ? k_FeedbackHintForTrackpadController + : k_FeedbackHintForJoystickController; + } + + public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl) + { + if (!m_UndoMenuUI.visible) + return; + + var undoMenuInput = (UndoMenuInput)input; + if (undoMenuInput == null) + { + this.ClearFeedbackRequests(); + return; + } + + if (undoMenuInput.engage.wasJustReleased && !m_TrackpadController) + this.RestartCoroutine(ref m_StillEngagedAfterStickReleasedCoroutine, AcceptInputAfterStickReleased()); + + if (!(undoMenuInput.engage.wasJustPressed || !m_TrackpadController && (undoMenuInput.engage.isHeld || m_StillEngagedAfterStickRelease))) + return; + + consumeControl(undoMenuInput.engage); + m_UndoMenuUI.engaged = true; + + var navigateX = undoMenuInput.navigateX.value; + var undoRedoPerformed = false; + if (navigateX < -k_UndoRedoThreshold && (m_TrackpadController || m_PrevNavigateX > -k_UndoRedoThreshold)) + { + Undo.PerformUndo(); + m_UndoMenuUI.StartPerformedAnimation(true); + ShowUndoPerformedFeedback(true); + undoRedoPerformed = true; + } + else if (navigateX > k_UndoRedoThreshold && (m_TrackpadController || m_PrevNavigateX < k_UndoRedoThreshold)) + { + Undo.PerformRedo(); + m_UndoMenuUI.StartPerformedAnimation(false); + ShowUndoPerformedFeedback(false); + undoRedoPerformed = true; + } + + m_PrevNavigateX = navigateX; + + if (undoRedoPerformed) + { + consumeControl(undoMenuInput.navigateX); + this.StopCoroutine(ref m_StillEngagedAfterStickReleasedCoroutine); + this.Pulse(node, m_UndoPulse); + } + } + + IEnumerator AcceptInputAfterStickReleased() + { + m_StillEngagedAfterStickRelease = true; + yield return new WaitForSeconds(k_EngageUndoAfterStickReleasedDuration); + m_StillEngagedAfterStickRelease = false; + m_UndoMenuUI.engaged = false; + } + + void ShowFeedback() + { + List controls; + if (m_Controls.TryGetValue(k_EngageControlName, out controls)) + { + foreach (var id in controls) + { + this.AddFeedbackRequest(new ProxyFeedbackRequest + { + control = id, + node = node, + tooltipText = m_FeedbackHintForCurrentController + }); + } + } + } + + void ShowUndoPerformedFeedback(bool undo) + { + List controls; + if (m_Controls.TryGetValue(k_EngageControlName, out controls)) + { + foreach (var id in controls) + { + this.AddFeedbackRequest(new ProxyFeedbackRequest + { + control = id, + node = node, + tooltipText = string.Format("{0} performed", undo ? "Undo" : "Redo") + }); + } + } + } + } +} +#endif diff --git a/Scripts/Actions/ActionMenuItemAttribute.cs b/Scripts/Actions/ActionMenuItemAttribute.cs index 2641a294f..e1f0f401b 100644 --- a/Scripts/Actions/ActionMenuItemAttribute.cs +++ b/Scripts/Actions/ActionMenuItemAttribute.cs @@ -1,33 +1,33 @@ -#if UNITY_EDITOR -namespace UnityEditor.Experimental.EditorVR -{ - /// - /// Attribute used to tag Action classes in order to be added to VR menus - /// - public class ActionMenuItemAttribute : System.Attribute, ITooltip - { - internal const string DefaultActionSectionName = "DefaultActions"; - internal string name; - internal string sectionName; - internal int priority; - - /// - /// The tooltip string - /// - public string tooltipText { get { return name; } } - - /// - /// Constructor - /// - /// The name of this action - /// The name of the section in which this action should reside - /// The ordinal of this action within the section it resides - public ActionMenuItemAttribute(string name, string sectionName = null, int priority = int.MaxValue) - { - this.name = name; - this.sectionName = sectionName; - this.priority = priority; - } - } -} -#endif +#if UNITY_EDITOR +namespace UnityEditor.Experimental.EditorVR +{ + /// + /// Attribute used to tag Action classes in order to be added to VR menus + /// + public class ActionMenuItemAttribute : System.Attribute, ITooltip + { + internal const string DefaultActionSectionName = "DefaultActions"; + internal string name; + internal string sectionName; + internal int priority; + + /// + /// The tooltip string + /// + public string tooltipText { get { return name; } } + + /// + /// Constructor + /// + /// The name of this action + /// The name of the section in which this action should reside + /// The ordinal of this action within the section it resides + public ActionMenuItemAttribute(string name, string sectionName = null, int priority = int.MaxValue) + { + this.name = name; + this.sectionName = sectionName; + this.priority = priority; + } + } +} +#endif diff --git a/Scripts/Core/EditorVR.Menus.cs b/Scripts/Core/EditorVR.Menus.cs index 1b2b34245..274480c8d 100644 --- a/Scripts/Core/EditorVR.Menus.cs +++ b/Scripts/Core/EditorVR.Menus.cs @@ -1,651 +1,612 @@ -#if UNITY_EDITOR && UNITY_2017_2_OR_NEWER -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.Experimental.EditorVR.Menus; -using UnityEditor.Experimental.EditorVR.Modules; -using UnityEditor.Experimental.EditorVR.UI; -using UnityEditor.Experimental.EditorVR.Utilities; -using UnityEngine; - -namespace UnityEditor.Experimental.EditorVR.Core -{ - partial class EditorVR - { - const float k_MainMenuAutoHideDelay = 0.125f; - const float k_MainMenuAutoShowDelay = 0.25f; - - class Menus : Nested, IInterfaceConnector, ILateBindInterfaceMethods, IConnectInterfaces - { - internal class MenuHideData - { - public MenuHideFlags hideFlags = MenuHideFlags.Hidden; - public MenuHideFlags lastHideFlags = MenuHideFlags.Hidden; - public float autoHideTime; - public float autoShowTime; - } - - const float k_MenuHideMargin = 0.075f; - const float k_TwoHandHideDistance = 0.25f; - const int k_PossibleOverlaps = 16; - - readonly Dictionary m_MainMenus = new Dictionary(); - readonly Dictionary, ISettingsMenuProvider> m_SettingsMenuProviders = new Dictionary, ISettingsMenuProvider>(); - readonly Dictionary, ISettingsMenuItemProvider> m_SettingsMenuItemProviders = new Dictionary, ISettingsMenuItemProvider>(); - List m_MainMenuTools; - - // Local method use only -- created here to reduce garbage collection - static readonly List k_ActiveDeviceData = new List(); - static readonly List k_WorkspaceComponents = new List(); - static readonly List k_ButtonComponents = new List(); - static readonly Collider[] k_ColliderOverlaps = new Collider[k_PossibleOverlaps]; - - public Menus() - { - IInstantiateMenuUIMethods.instantiateMenuUI = InstantiateMenuUI; - IIsMainMenuVisibleMethods.isMainMenuVisible = IsMainMenuVisible; - IUsesCustomMenuOriginsMethods.getCustomMenuOrigin = GetCustomMenuOrigin; - IUsesCustomMenuOriginsMethods.getCustomAlternateMenuOrigin = GetCustomAlternateMenuOrigin; - } - - public void ConnectInterface(object target, object userData = null) - { - var rayOrigin = userData as Transform; - var settingsMenuProvider = target as ISettingsMenuProvider; - if (settingsMenuProvider != null) - { - m_SettingsMenuProviders[new KeyValuePair(target.GetType(), rayOrigin)] = settingsMenuProvider; - foreach (var kvp in m_MainMenus) - { - if (rayOrigin == null || kvp.Key == rayOrigin) - kvp.Value.AddSettingsMenu(settingsMenuProvider); - } - } - - var settingsMenuItemProvider = target as ISettingsMenuItemProvider; - if (settingsMenuItemProvider != null) - { - m_SettingsMenuItemProviders[new KeyValuePair(target.GetType(), rayOrigin)] = settingsMenuItemProvider; - foreach (var kvp in m_MainMenus) - { - if (rayOrigin == null || kvp.Key == rayOrigin) - kvp.Value.AddSettingsMenuItem(settingsMenuItemProvider); - } - } - - var mainMenu = target as IMainMenu; - if (mainMenu != null && rayOrigin != null) - { - mainMenu.menuTools = m_MainMenuTools; - mainMenu.menuWorkspaces = WorkspaceModule.workspaceTypes; - mainMenu.settingsMenuProviders = m_SettingsMenuProviders; - mainMenu.settingsMenuItemProviders = m_SettingsMenuItemProviders; - m_MainMenus[rayOrigin] = mainMenu; - } - - var menuOrigins = target as IUsesMenuOrigins; - if (menuOrigins != null) - { - Transform mainMenuOrigin; - var proxy = Rays.GetProxyForRayOrigin(rayOrigin); - if (proxy != null && proxy.menuOrigins.TryGetValue(rayOrigin, out mainMenuOrigin)) - { - menuOrigins.menuOrigin = mainMenuOrigin; - Transform alternateMenuOrigin; - if (proxy.alternateMenuOrigins.TryGetValue(rayOrigin, out alternateMenuOrigin)) - menuOrigins.alternateMenuOrigin = alternateMenuOrigin; - } - } - - var customAlternateMenu = target as ICustomAlternateMenu; - if (customAlternateMenu != null) - AddRemoveCustomAlternateMenu(customAlternateMenu, rayOrigin, true); - } - - public void DisconnectInterface(object target, object userData = null) - { - var rayOrigin = userData as Transform; - var settingsMenuProvider = target as ISettingsMenuProvider; - if (settingsMenuProvider != null) - { - foreach (var kvp in m_MainMenus) - { - if (rayOrigin == null || kvp.Key == rayOrigin) - kvp.Value.RemoveSettingsMenu(settingsMenuProvider); - } - - m_SettingsMenuProviders.Remove(new KeyValuePair(target.GetType(), rayOrigin)); - } - - var settingsMenuItemProvider = target as ISettingsMenuItemProvider; - if (settingsMenuItemProvider != null) - { - foreach (var kvp in m_MainMenus) - { - if (rayOrigin == null || kvp.Key == rayOrigin) - kvp.Value.RemoveSettingsMenuItem(settingsMenuItemProvider); - } - - m_SettingsMenuItemProviders.Remove(new KeyValuePair(target.GetType(), rayOrigin)); - } - - var mainMenu = target as IMainMenu; - if (mainMenu != null && rayOrigin != null) - m_MainMenus.Remove(rayOrigin); - - var customAlternateMenu = target as ICustomAlternateMenu; - if (customAlternateMenu != null) - AddRemoveCustomAlternateMenu(customAlternateMenu, rayOrigin, false); - } - - static void AddRemoveCustomAlternateMenu( - ICustomAlternateMenu customAlternateMenu, Transform rayOrigin, bool addMenu) - { - DeviceData deviceData = null; - foreach (var currentDevice in evr.m_DeviceData) - { - if (currentDevice.rayOrigin == rayOrigin) - { - deviceData = currentDevice; - break; - } - } - - if (deviceData != null) - { - if (addMenu) - { - deviceData.customAlternateMenus.Add(customAlternateMenu); - - MenuHideData tempData; - if (!deviceData.menuHideData.TryGetValue(customAlternateMenu, out tempData)) - { - deviceData.menuHideData.Add(customAlternateMenu, new MenuHideData()); - } - } - else - { - deviceData.customAlternateMenus.Remove(customAlternateMenu); - deviceData.menuHideData.Remove(customAlternateMenu); - } - - ICustomAlternateMenu highestPriorityCustomAlternateMenu = null; - foreach (var alternateMenu in deviceData.customAlternateMenus) - { - if (highestPriorityCustomAlternateMenu == null - || alternateMenu.menuPriority >= highestPriorityCustomAlternateMenu.menuPriority) - { - highestPriorityCustomAlternateMenu = alternateMenu; - } - } - - deviceData.highestPriorityCustomAlternateMenu = highestPriorityCustomAlternateMenu; - } - } - - public void LateBindInterfaceMethods(Tools provider) - { - m_MainMenuTools = provider.allTools.Where(t => !Tools.IsDefaultTool(t)).ToList(); // Don't show tools that can't be selected/toggled - } - - static void UpdateAlternateMenuForDevice(DeviceData deviceData) - { - var alternateMenu = deviceData.alternateMenu; - alternateMenu.menuHideFlags = deviceData.currentTool is IExclusiveMode ? 0 : deviceData.menuHideData[alternateMenu].hideFlags; - - // Move the Tools Menu buttons to an alternate position if the alternate menu will be shown - deviceData.toolsMenu.alternateMenuVisible = alternateMenu.menuHideFlags == 0; - } - - static Transform GetCustomMenuOrigin(Transform rayOrigin) - { - Transform mainMenuOrigin = null; - - var proxy = Rays.GetProxyForRayOrigin(rayOrigin); - if (proxy != null) - { - var menuOrigins = proxy.menuOrigins; - if (menuOrigins.ContainsKey(rayOrigin)) - mainMenuOrigin = menuOrigins[rayOrigin]; - } - - return mainMenuOrigin; - } - - static Transform GetCustomAlternateMenuOrigin(Transform rayOrigin) - { - Transform alternateMenuOrigin = null; - - var proxy = Rays.GetProxyForRayOrigin(rayOrigin); - if (proxy != null) - { - var alternateMenuOrigins = proxy.alternateMenuOrigins; - if (alternateMenuOrigins.ContainsKey(rayOrigin)) - alternateMenuOrigin = alternateMenuOrigins[rayOrigin]; - } - - return alternateMenuOrigin; - } - - internal void UpdateMenuVisibilities() - { - k_ActiveDeviceData.Clear(); - Rays.ForEachProxyDevice(deviceData => { k_ActiveDeviceData.Add(deviceData); }); - - foreach (var deviceData in k_ActiveDeviceData) - { - var alternateMenu = deviceData.alternateMenu; - var mainMenu = deviceData.mainMenu; - var customMenu = deviceData.customMenu; - var menuHideData = deviceData.menuHideData; - MenuHideData customMenuHideData = null; - MenuHideData alternateMenuData = null; - - var mainMenuVisible = mainMenu != null && menuHideData[mainMenu].hideFlags == 0; - var mainMenuSupressed = mainMenu != null && ((menuHideData[mainMenu].hideFlags & MenuHideFlags.Occluded) != 0); - - var alternateMenuVisible = false; - if (alternateMenu != null) - { - alternateMenuData = menuHideData[alternateMenu]; - alternateMenuVisible = alternateMenuData.hideFlags == 0; - } - - var customMenuVisible = false; - if (customMenu != null) - { - customMenuHideData = menuHideData[customMenu]; - customMenuVisible = customMenuHideData.hideFlags == 0; - } - - var customAlternateMenuVisible = false; - foreach (var customAlternateMenu in deviceData.customAlternateMenus) - { - customAlternateMenuVisible = customAlternateMenuVisible || menuHideData[customAlternateMenu].hideFlags == 0; - } - - // Kick the alternate menu to the other hand if a main menu or custom menu is visible - if (alternateMenuVisible && (mainMenuVisible || customMenuVisible)) - { - foreach (var otherDeviceData in k_ActiveDeviceData) - { - if (otherDeviceData == deviceData) - continue; - - SetAlternateMenuVisibility(otherDeviceData.rayOrigin, true); - break; - } - } - - // Temporarily hide customMenu if other menus are visible or should be - if (customMenuVisible && (mainMenuVisible || mainMenuSupressed)) - customMenuHideData.hideFlags |= MenuHideFlags.OtherMenu; - - // Temporarily hide alternateMenu if other menus are visible - if (alternateMenuVisible && (customMenuVisible || mainMenuVisible)) - alternateMenuData.hideFlags |= MenuHideFlags.OtherMenu; - - // Temporarily hide custom alternate menu if radial menu is open. - if (customAlternateMenuVisible && alternateMenuVisible) - { - foreach (var customAlternateMenu in deviceData.customAlternateMenus) - { - customAlternateMenu.menuHideFlags |= MenuHideFlags.OtherMenu; - } - } - else - { - foreach (var customAlternateMenu in deviceData.customAlternateMenus) - { - // Always display the highest-priority custom alternate menu, and hide all others. - if (customAlternateMenu == deviceData.highestPriorityCustomAlternateMenu) - menuHideData[customAlternateMenu].hideFlags = 0; - else - menuHideData[customAlternateMenu].hideFlags |= MenuHideFlags.OtherMenu; - } - } - - // Check if menu bounds overlap with any workspace colliders - foreach (var kvp in menuHideData) - { - CheckMenuColliderOverlaps(kvp.Key, kvp.Value); - } - - // Check if there are currently any held objects, or if the other hand is in proximity for scaling - CheckDirectSelection(deviceData, menuHideData, alternateMenuVisible); - } - - // Set show/hide timings - foreach (var deviceData in k_ActiveDeviceData) - { - foreach (var kvp in deviceData.menuHideData) - { - var hideFlags = kvp.Value.hideFlags; - if ((hideFlags & ~MenuHideFlags.Hidden & ~MenuHideFlags.OtherMenu) == 0) - kvp.Value.autoHideTime = Time.time; - - if (hideFlags != 0) - { - var menuHideData = kvp.Value; - menuHideData.lastHideFlags = menuHideData.hideFlags; - kvp.Value.autoShowTime = Time.time; - } - } - } - - // Apply MenuHideFlags to UI visibility - foreach (var deviceData in k_ActiveDeviceData) - { - var mainMenu = deviceData.mainMenu; - var mainMenuHideData = deviceData.menuHideData[mainMenu]; - var mainMenuHideFlags = mainMenuHideData.hideFlags; - var lastMainMenuHideFlags = mainMenuHideData.lastHideFlags; - - var permanentlyHidden = (mainMenuHideFlags & MenuHideFlags.Hidden) != 0; - var wasPermanentlyHidden = (lastMainMenuHideFlags & MenuHideFlags.Hidden) != 0; - - //Temporary states take effect after a delay - var temporarilyHidden = (mainMenuHideFlags & MenuHideFlags.Temporary) != 0 - && Time.time > mainMenuHideData.autoHideTime + k_MainMenuAutoHideDelay; - var wasTemporarilyHidden = (lastMainMenuHideFlags & MenuHideFlags.Temporary) != 0 - && Time.time > mainMenuHideData.autoShowTime + k_MainMenuAutoShowDelay; - - // If the menu is focused, only hide if Hidden is set (e.g. not temporary) in order to hide the selected tool - if (permanentlyHidden || wasPermanentlyHidden || !mainMenu.focus && (temporarilyHidden || wasTemporarilyHidden)) - mainMenu.menuHideFlags = mainMenuHideFlags; - - // Disable the main menu activator if any temporary states are set - deviceData.toolsMenu.mainMenuActivatorInteractable = (mainMenuHideFlags & MenuHideFlags.Temporary) == 0; - - // Show/hide custom menu, if it exists - var customMenu = deviceData.customMenu; - if (customMenu != null) - customMenu.menuHideFlags = deviceData.menuHideData[customMenu].hideFlags; - - var customAlternateMenus = deviceData.customAlternateMenus; - if (customAlternateMenus != null && customAlternateMenus.Count > 0) - { - foreach (var customAlternateMenu in customAlternateMenus) - { - customAlternateMenu.menuHideFlags = deviceData.menuHideData[customAlternateMenu].hideFlags; - } - } - - UpdateAlternateMenuForDevice(deviceData); - Rays.UpdateRayForDevice(deviceData, deviceData.rayOrigin); - } - - // Reset Temporary states and set lastHideFlags - foreach (var deviceData in k_ActiveDeviceData) - { - foreach (var kvp in deviceData.menuHideData) - { - kvp.Value.hideFlags &= ~MenuHideFlags.Temporary; - } - } - - evr.GetModule().UpdatePlayerHandleMaps(); - } - - void CheckDirectSelection(DeviceData deviceData, Dictionary menuHideData, bool alternateMenuVisible) - { - var viewerScale = Viewer.GetViewerScale(); - var directSelection = evr.GetNestedModule(); - var rayOrigin = deviceData.rayOrigin; - var rayOriginPosition = rayOrigin.position; - var heldObjects = directSelection.GetHeldObjects(rayOrigin); - - // If this hand is holding any objects, hide its menus - var hasDirectSelection = heldObjects != null && heldObjects.Count > 0; - if (hasDirectSelection) - { - foreach (var kvp in menuHideData) - { - // Only set if hidden--value is reset every frame - kvp.Value.hideFlags |= MenuHideFlags.HasDirectSelection; - } - - foreach (var otherDeviceData in k_ActiveDeviceData) - { - if (otherDeviceData == deviceData) - continue; - - var otherRayOrigin = otherDeviceData.rayOrigin; - if (alternateMenuVisible && otherDeviceData.alternateMenu != null) - SetAlternateMenuVisibility(otherRayOrigin, true); - - // If other hand is within range to do a two-handed scale, hide its menu as well - if (directSelection.IsHovering(otherRayOrigin) || directSelection.IsScaling(otherRayOrigin) - || Vector3.Distance(otherRayOrigin.position, rayOriginPosition) < k_TwoHandHideDistance * viewerScale) - { - foreach (var kvp in otherDeviceData.menuHideData) - { - // Only set if hidden--value is reset every frame - kvp.Value.hideFlags |= MenuHideFlags.HasDirectSelection; - } - break; - } - } - } - } - - static void CheckMenuColliderOverlaps(IMenu menu, MenuHideData menuHideData) - { - var menuBounds = menu.localBounds; - if (menuBounds.extents == Vector3.zero) - return; - - Array.Clear(k_ColliderOverlaps, 0, k_ColliderOverlaps.Length); - var hoveringCollider = false; - var menuTransform = menu.menuContent.transform; - var menuRotation = menuTransform.rotation; - var viewerScale = Viewer.GetViewerScale(); - var center = menuTransform.position + menuRotation * menuBounds.center * viewerScale; - if (Physics.OverlapBoxNonAlloc(center, menuBounds.extents * viewerScale, k_ColliderOverlaps, menuRotation) > 0) - { - foreach (var overlap in k_ColliderOverlaps) - { - if (overlap) - { - k_WorkspaceComponents.Clear(); - overlap.GetComponents(k_WorkspaceComponents); - if (k_WorkspaceComponents.Count > 0) - hoveringCollider = true; - - k_ButtonComponents.Clear(); - overlap.GetComponents(k_ButtonComponents); - if (k_ButtonComponents.Count > 0) - hoveringCollider = true; - } - } - } - - // Only set if hidden--value is reset every frame - if (hoveringCollider) - menuHideData.hideFlags |= MenuHideFlags.OverWorkspace; - } - - internal static bool IsValidHover(MultipleRayInputModule.RaycastSource source) - { - var go = source.draggedObject; - if (!go) - go = source.hoveredObject; - - if (!go) - return true; - - if (go == evr.gameObject) - return true; - - var eventData = source.eventData; - var rayOrigin = eventData.rayOrigin; - - DeviceData deviceData = null; - foreach (var currentDevice in evr.m_DeviceData) - { - if (currentDevice.rayOrigin == rayOrigin) - { - deviceData = currentDevice; - break; - } - } - - if (deviceData != null) - { - if (go.transform.IsChildOf(deviceData.rayOrigin)) // Don't let UI on this hand block the menu - return false; - - var scaledPointerDistance = eventData.pointerCurrentRaycast.distance / Viewer.GetViewerScale(); - var menuHideFlags = deviceData.menuHideData; - var mainMenu = deviceData.mainMenu; - IMenu openMenu = mainMenu; - if (deviceData.customMenu != null && menuHideFlags[mainMenu].hideFlags != 0) - openMenu = deviceData.customMenu; - - if (scaledPointerDistance < openMenu.localBounds.size.y + k_MenuHideMargin) - { - // Only set if hidden--value is reset every frame - menuHideFlags[openMenu].hideFlags |= MenuHideFlags.OverUI; - return true; - } - - return (menuHideFlags[openMenu].hideFlags & MenuHideFlags.Hidden) != 0; - } - - return true; - } - - internal static void UpdateAlternateMenuOnSelectionChanged(Transform rayOrigin) - { - if (rayOrigin == null) - return; - - SetAlternateMenuVisibility(rayOrigin, Selection.gameObjects.Length > 0); - } - - internal static void SetAlternateMenuVisibility(Transform rayOrigin, bool visible) - { - Rays.ForEachProxyDevice(deviceData => - { - var menuHideFlags = deviceData.menuHideData; - var alternateMenu = deviceData.alternateMenu; - if (alternateMenu != null) - { - // Set alternate menu visible on this rayOrigin and hide it on all others - var alternateMenuData = menuHideFlags[alternateMenu]; - if (deviceData.rayOrigin == rayOrigin && visible) - alternateMenuData.hideFlags &= ~MenuHideFlags.Hidden; - else - alternateMenuData.hideFlags |= MenuHideFlags.Hidden; - } - }); - } - - internal static void OnMainMenuActivatorSelected(Transform rayOrigin, Transform targetRayOrigin) - { - foreach (var deviceData in evr.m_DeviceData) - { - var mainMenu = deviceData.mainMenu; - if (mainMenu != null) - { - var customMenu = deviceData.customMenu; - var alternateMenu = deviceData.alternateMenu; - var menuHideData = deviceData.menuHideData; - var mainMenuHideData = menuHideData[mainMenu]; - var alternateMenuVisible = alternateMenu != null - && (menuHideData[alternateMenu].hideFlags & MenuHideFlags.Hidden) == 0; - - // Do not delay when showing via activator - mainMenuHideData.autoShowTime = 0; - - if (deviceData.rayOrigin == rayOrigin) - { - // Toggle main menu hidden flag - mainMenuHideData.hideFlags ^= MenuHideFlags.Hidden; - mainMenu.targetRayOrigin = targetRayOrigin; - } - else - { - mainMenuHideData.hideFlags |= MenuHideFlags.Hidden; - - var customMenuOverridden = customMenu != null && - (menuHideData[customMenu].hideFlags & MenuHideFlags.OtherMenu) != 0; - - // Move alternate menu if overriding custom menu - if (customMenuOverridden && alternateMenuVisible) - { - foreach (var otherDeviceData in evr.m_DeviceData) - { - if (deviceData == otherDeviceData) - continue; - - if (otherDeviceData.alternateMenu != null) - SetAlternateMenuVisibility(rayOrigin, true); - } - } - } - } - } - } - - static GameObject InstantiateMenuUI(Transform rayOrigin, IMenu prefab) - { - var ui = evr.GetNestedModule(); - GameObject go = null; - Rays.ForEachProxyDevice(deviceData => - { - var proxy = deviceData.proxy; - var otherRayOrigin = deviceData.rayOrigin; - if (proxy.rayOrigins.ContainsValue(rayOrigin) && otherRayOrigin != rayOrigin) - { - Transform menuOrigin; - if (proxy.menuOrigins.TryGetValue(otherRayOrigin, out menuOrigin)) - { - if (deviceData.customMenu == null) - { - go = ui.InstantiateUI(prefab.gameObject, menuOrigin, false); - - var customMenu = go.GetComponent(); - deviceData.customMenu = customMenu; - deviceData.menuHideData[customMenu] = new MenuHideData { hideFlags = 0 }; - } - } - } - }); - - return go; - } - - internal T SpawnMenu(Transform rayOrigin) where T : Component, IMenu - { - var mainMenu = ObjectUtils.AddComponent(evr.gameObject); - this.ConnectInterfaces(mainMenu, rayOrigin); - - return mainMenu; - } - - internal static void UpdateAlternateMenuActions() - { - var actionsModule = evr.GetModule(); - foreach (var deviceData in evr.m_DeviceData) - { - var altMenu = deviceData.alternateMenu; - if (altMenu != null) - altMenu.menuActions = actionsModule.menuActions; - } - } - - static bool IsMainMenuVisible(Transform rayOrigin) - { - foreach (var deviceData in evr.m_DeviceData) - { - if (deviceData.rayOrigin == rayOrigin) - return (deviceData.menuHideData[deviceData.mainMenu].hideFlags & MenuHideFlags.Hidden) == 0; - } - - return false; - } - } - } -} -#endif +#if UNITY_EDITOR && UNITY_2017_2_OR_NEWER +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor.Experimental.EditorVR.Menus; +using UnityEditor.Experimental.EditorVR.Modules; +using UnityEditor.Experimental.EditorVR.UI; +using UnityEditor.Experimental.EditorVR.Utilities; +using UnityEngine; + +namespace UnityEditor.Experimental.EditorVR.Core +{ + partial class EditorVR + { + const float k_MainMenuAutoHideDelay = 0.125f; + const float k_MainMenuAutoShowDelay = 0.25f; + + class Menus : Nested, IInterfaceConnector, ILateBindInterfaceMethods, IConnectInterfaces + { + internal class MenuHideData + { + public MenuHideFlags hideFlags = MenuHideFlags.Hidden; + public MenuHideFlags lastHideFlags = MenuHideFlags.Hidden; + public float autoHideTime; + public float autoShowTime; + } + + const float k_MenuHideMargin = 0.075f; + const float k_TwoHandHideDistance = 0.25f; + const int k_PossibleOverlaps = 16; + + readonly Dictionary m_MainMenus = new Dictionary(); + readonly Dictionary, ISettingsMenuProvider> m_SettingsMenuProviders = new Dictionary, ISettingsMenuProvider>(); + readonly Dictionary, ISettingsMenuItemProvider> m_SettingsMenuItemProviders = new Dictionary, ISettingsMenuItemProvider>(); + List m_MainMenuTools; + + // Local method use only -- created here to reduce garbage collection + static readonly List k_ActiveDeviceData = new List(); + static readonly List k_WorkspaceComponents = new List(); + static readonly List k_ButtonComponents = new List(); + static readonly Collider[] k_ColliderOverlaps = new Collider[k_PossibleOverlaps]; + + public Menus() + { + IInstantiateMenuUIMethods.instantiateMenuUI = InstantiateMenuUI; + IIsMainMenuVisibleMethods.isMainMenuVisible = IsMainMenuVisible; + IUsesCustomMenuOriginsMethods.getCustomMenuOrigin = GetCustomMenuOrigin; + IUsesCustomMenuOriginsMethods.getCustomAlternateMenuOrigin = GetCustomAlternateMenuOrigin; + } + + public void ConnectInterface(object target, object userData = null) + { + var rayOrigin = userData as Transform; + var settingsMenuProvider = target as ISettingsMenuProvider; + if (settingsMenuProvider != null) + { + m_SettingsMenuProviders[new KeyValuePair(target.GetType(), rayOrigin)] = settingsMenuProvider; + foreach (var kvp in m_MainMenus) + { + if (rayOrigin == null || kvp.Key == rayOrigin) + kvp.Value.AddSettingsMenu(settingsMenuProvider); + } + } + + var settingsMenuItemProvider = target as ISettingsMenuItemProvider; + if (settingsMenuItemProvider != null) + { + m_SettingsMenuItemProviders[new KeyValuePair(target.GetType(), rayOrigin)] = settingsMenuItemProvider; + foreach (var kvp in m_MainMenus) + { + if (rayOrigin == null || kvp.Key == rayOrigin) + kvp.Value.AddSettingsMenuItem(settingsMenuItemProvider); + } + } + + var mainMenu = target as IMainMenu; + if (mainMenu != null && rayOrigin != null) + { + mainMenu.menuTools = m_MainMenuTools; + mainMenu.menuWorkspaces = WorkspaceModule.workspaceTypes; + mainMenu.settingsMenuProviders = m_SettingsMenuProviders; + mainMenu.settingsMenuItemProviders = m_SettingsMenuItemProviders; + m_MainMenus[rayOrigin] = mainMenu; + } + + var menuOrigins = target as IUsesMenuOrigins; + if (menuOrigins != null) + { + Transform mainMenuOrigin; + var proxy = Rays.GetProxyForRayOrigin(rayOrigin); + if (proxy != null && proxy.menuOrigins.TryGetValue(rayOrigin, out mainMenuOrigin)) + { + menuOrigins.menuOrigin = mainMenuOrigin; + Transform alternateMenuOrigin; + if (proxy.alternateMenuOrigins.TryGetValue(rayOrigin, out alternateMenuOrigin)) + menuOrigins.alternateMenuOrigin = alternateMenuOrigin; + } + } + + var customAlternateMenu = target as IAlternateMenu; + if (customAlternateMenu != null) + AddCustomAlternateMenu(customAlternateMenu, rayOrigin); + } + + public void DisconnectInterface(object target, object userData = null) + { + var rayOrigin = userData as Transform; + var settingsMenuProvider = target as ISettingsMenuProvider; + if (settingsMenuProvider != null) + { + foreach (var kvp in m_MainMenus) + { + if (rayOrigin == null || kvp.Key == rayOrigin) + kvp.Value.RemoveSettingsMenu(settingsMenuProvider); + } + + m_SettingsMenuProviders.Remove(new KeyValuePair(target.GetType(), rayOrigin)); + } + + var settingsMenuItemProvider = target as ISettingsMenuItemProvider; + if (settingsMenuItemProvider != null) + { + foreach (var kvp in m_MainMenus) + { + if (rayOrigin == null || kvp.Key == rayOrigin) + kvp.Value.RemoveSettingsMenuItem(settingsMenuItemProvider); + } + + m_SettingsMenuItemProviders.Remove(new KeyValuePair(target.GetType(), rayOrigin)); + } + + var mainMenu = target as IMainMenu; + if (mainMenu != null && rayOrigin != null) + m_MainMenus.Remove(rayOrigin); + + var customAlternateMenu = target as IAlternateMenu; + if (customAlternateMenu != null) + RemoveCustomAlternateMenu(customAlternateMenu, rayOrigin); + } + + static void AddCustomAlternateMenu(IAlternateMenu alternateMenu, Transform rayOrigin) + { + foreach (var device in evr.m_DeviceData) + { + if (device.rayOrigin != rayOrigin) + continue; + + device.alternateMenus.Add(alternateMenu); + var menuHideData = new MenuHideData(); + device.menuHideData[alternateMenu] = menuHideData; + menuHideData.hideFlags = 0; + + break; + } + } + + static void RemoveCustomAlternateMenu(IAlternateMenu customAlternateMenu, Transform rayOrigin) + { + foreach (var device in evr.m_DeviceData) + { + device.alternateMenus.Remove(customAlternateMenu); + device.menuHideData.Remove(customAlternateMenu); + } + } + + public void LateBindInterfaceMethods(Tools provider) + { + m_MainMenuTools = provider.allTools.Where(t => !Tools.IsDefaultTool(t)).ToList(); // Don't show tools that can't be selected/toggled + } + + static void UpdateAlternateMenuForDevice(DeviceData deviceData) + { + var alternateMenu = deviceData.alternateMenu; + if (alternateMenu == null || !deviceData.menuHideData.ContainsKey(alternateMenu)) + return; + + alternateMenu.menuHideFlags = deviceData.currentTool is IExclusiveMode ? 0 : deviceData.menuHideData[alternateMenu].hideFlags; + + // Move the Tools Menu buttons to an alternate position if the radial menu will be shown + if (alternateMenu is RadialMenu) + deviceData.toolsMenu.alternateMenuVisible = alternateMenu.menuHideFlags == 0; + } + + static Transform GetCustomMenuOrigin(Transform rayOrigin) + { + Transform mainMenuOrigin = null; + + var proxy = Rays.GetProxyForRayOrigin(rayOrigin); + if (proxy != null) + { + var menuOrigins = proxy.menuOrigins; + if (menuOrigins.ContainsKey(rayOrigin)) + mainMenuOrigin = menuOrigins[rayOrigin]; + } + + return mainMenuOrigin; + } + + static Transform GetCustomAlternateMenuOrigin(Transform rayOrigin) + { + Transform alternateMenuOrigin = null; + + var proxy = Rays.GetProxyForRayOrigin(rayOrigin); + if (proxy != null) + { + var alternateMenuOrigins = proxy.alternateMenuOrigins; + if (alternateMenuOrigins.ContainsKey(rayOrigin)) + alternateMenuOrigin = alternateMenuOrigins[rayOrigin]; + } + + return alternateMenuOrigin; + } + + internal void UpdateMenuVisibilities() + { + k_ActiveDeviceData.Clear(); + Rays.ForEachProxyDevice(deviceData => { k_ActiveDeviceData.Add(deviceData); }); + + foreach (var deviceData in k_ActiveDeviceData) + { + IAlternateMenu alternateMenu = null; + var menuHideData = deviceData.menuHideData; + // Always display the highest-priority alternate menu, and hide all others. + foreach (var menu in deviceData.alternateMenus) + { + if ((menuHideData[menu].hideFlags & MenuHideFlags.Hidden) == 0 + && (alternateMenu == null || menu.priority >= alternateMenu.priority)) + { + alternateMenu = menu; + menuHideData[alternateMenu].hideFlags = 0; + deviceData.alternateMenu = alternateMenu; + } + else + { + menuHideData[menu].hideFlags |= MenuHideFlags.OtherMenu; + } + } + + var mainMenu = deviceData.mainMenu; + var customMenu = deviceData.customMenu; + MenuHideData customMenuHideData = null; + MenuHideData alternateMenuData = null; + + var mainMenuVisible = mainMenu != null && menuHideData[mainMenu].hideFlags == 0; + var mainMenuSupressed = mainMenu != null && ((menuHideData[mainMenu].hideFlags & MenuHideFlags.Occluded) != 0); + + var alternateMenuVisible = false; + if (alternateMenu != null) + { + alternateMenuData = menuHideData[alternateMenu]; + alternateMenuVisible = alternateMenuData.hideFlags == 0; + } + + var customMenuVisible = false; + if (customMenu != null) + { + customMenuHideData = menuHideData[customMenu]; + customMenuVisible = customMenuHideData.hideFlags == 0; + } + + // Temporarily hide customMenu if other menus are visible or should be + if (customMenuVisible && (mainMenuVisible || mainMenuSupressed)) + customMenuHideData.hideFlags |= MenuHideFlags.OtherMenu; + + // Temporarily hide alternateMenu if other menus are visible + if (alternateMenuVisible && (customMenuVisible || mainMenuVisible)) + alternateMenuData.hideFlags |= MenuHideFlags.OtherMenu; + + // Kick the alternate menu to the other hand if a main menu or custom menu is visible + if (alternateMenuVisible && (mainMenuVisible || customMenuVisible) && alternateMenu is RadialMenu) + { + foreach (var otherDeviceData in k_ActiveDeviceData) + { + if (otherDeviceData == deviceData) + continue; + + SetAlternateMenuVisibility(otherDeviceData.rayOrigin, true); + break; + } + } + + // Check if menu bounds overlap with any workspace colliders + foreach (var kvp in menuHideData) + { + CheckMenuColliderOverlaps(kvp.Key, kvp.Value); + } + + // Check if there are currently any held objects, or if the other hand is in proximity for scaling + CheckDirectSelection(deviceData, menuHideData, alternateMenuVisible); + } + + // Set show/hide timings + foreach (var deviceData in k_ActiveDeviceData) + { + foreach (var kvp in deviceData.menuHideData) + { + var hideFlags = kvp.Value.hideFlags; + if ((hideFlags & ~MenuHideFlags.Hidden & ~MenuHideFlags.OtherMenu) == 0) + kvp.Value.autoHideTime = Time.time; + + if (hideFlags != 0) + { + var menuHideData = kvp.Value; + menuHideData.lastHideFlags = menuHideData.hideFlags; + kvp.Value.autoShowTime = Time.time; + } + } + } + + // Apply MenuHideFlags to UI visibility + foreach (var deviceData in k_ActiveDeviceData) + { + var mainMenu = deviceData.mainMenu; + var mainMenuHideData = deviceData.menuHideData[mainMenu]; + var mainMenuHideFlags = mainMenuHideData.hideFlags; + var lastMainMenuHideFlags = mainMenuHideData.lastHideFlags; + + var permanentlyHidden = (mainMenuHideFlags & MenuHideFlags.Hidden) != 0; + var wasPermanentlyHidden = (lastMainMenuHideFlags & MenuHideFlags.Hidden) != 0; + + //Temporary states take effect after a delay + var temporarilyHidden = (mainMenuHideFlags & MenuHideFlags.Temporary) != 0 + && Time.time > mainMenuHideData.autoHideTime + k_MainMenuAutoHideDelay; + var wasTemporarilyHidden = (lastMainMenuHideFlags & MenuHideFlags.Temporary) != 0 + && Time.time > mainMenuHideData.autoShowTime + k_MainMenuAutoShowDelay; + + // If the menu is focused, only hide if Hidden is set (e.g. not temporary) in order to hide the selected tool + if (permanentlyHidden || wasPermanentlyHidden || !mainMenu.focus && (temporarilyHidden || wasTemporarilyHidden)) + mainMenu.menuHideFlags = mainMenuHideFlags; + + // Disable the main menu activator if any temporary states are set + deviceData.toolsMenu.mainMenuActivatorInteractable = (mainMenuHideFlags & MenuHideFlags.Temporary) == 0; + + // Show/hide custom menu, if it exists + var customMenu = deviceData.customMenu; + if (customMenu != null) + customMenu.menuHideFlags = deviceData.menuHideData[customMenu].hideFlags; + + var alternateMenus = deviceData.alternateMenus; + foreach (var menu in alternateMenus) + { + menu.menuHideFlags = deviceData.menuHideData[menu].hideFlags; + } + + UpdateAlternateMenuForDevice(deviceData); + Rays.UpdateRayForDevice(deviceData, deviceData.rayOrigin); + } + + // Reset Temporary states and set lastHideFlags + foreach (var deviceData in k_ActiveDeviceData) + { + foreach (var kvp in deviceData.menuHideData) + { + kvp.Value.hideFlags &= ~MenuHideFlags.Temporary; + } + } + + evr.GetModule().UpdatePlayerHandleMaps(); + } + + void CheckDirectSelection(DeviceData deviceData, Dictionary menuHideData, bool alternateMenuVisible) + { + var viewerScale = Viewer.GetViewerScale(); + var directSelection = evr.GetNestedModule(); + var rayOrigin = deviceData.rayOrigin; + var rayOriginPosition = rayOrigin.position; + var heldObjects = directSelection.GetHeldObjects(rayOrigin); + + // If this hand is holding any objects, hide its menus + var hasDirectSelection = heldObjects != null && heldObjects.Count > 0; + if (hasDirectSelection) + { + foreach (var kvp in menuHideData) + { + // Only set if hidden--value is reset every frame + kvp.Value.hideFlags |= MenuHideFlags.HasDirectSelection; + } + + foreach (var otherDeviceData in k_ActiveDeviceData) + { + if (otherDeviceData == deviceData) + continue; + + var otherRayOrigin = otherDeviceData.rayOrigin; + if (alternateMenuVisible) + SetAlternateMenuVisibility(otherRayOrigin, true); + + // If other hand is within range to do a two-handed scale, hide its menu as well + if (directSelection.IsHovering(otherRayOrigin) || directSelection.IsScaling(otherRayOrigin) + || Vector3.Distance(otherRayOrigin.position, rayOriginPosition) < k_TwoHandHideDistance * viewerScale) + { + foreach (var kvp in otherDeviceData.menuHideData) + { + // Only set if hidden--value is reset every frame + kvp.Value.hideFlags |= MenuHideFlags.HasDirectSelection; + } + break; + } + } + } + } + + static void CheckMenuColliderOverlaps(IMenu menu, MenuHideData menuHideData) + { + var menuBounds = menu.localBounds; + if (menuBounds.extents == Vector3.zero) + return; + + Array.Clear(k_ColliderOverlaps, 0, k_ColliderOverlaps.Length); + var hoveringCollider = false; + var menuTransform = menu.menuContent.transform; + var menuRotation = menuTransform.rotation; + var viewerScale = Viewer.GetViewerScale(); + var center = menuTransform.position + menuRotation * menuBounds.center * viewerScale; + if (Physics.OverlapBoxNonAlloc(center, menuBounds.extents * viewerScale, k_ColliderOverlaps, menuRotation) > 0) + { + foreach (var overlap in k_ColliderOverlaps) + { + if (overlap) + { + k_WorkspaceComponents.Clear(); + overlap.GetComponents(k_WorkspaceComponents); + if (k_WorkspaceComponents.Count > 0) + hoveringCollider = true; + + k_ButtonComponents.Clear(); + overlap.GetComponents(k_ButtonComponents); + if (k_ButtonComponents.Count > 0) + hoveringCollider = true; + } + } + } + + // Only set if hidden--value is reset every frame + if (hoveringCollider) + menuHideData.hideFlags |= MenuHideFlags.OverWorkspace; + } + + internal static bool IsValidHover(MultipleRayInputModule.RaycastSource source) + { + var go = source.draggedObject; + if (!go) + go = source.hoveredObject; + + if (!go) + return true; + + if (go == evr.gameObject) + return true; + + var eventData = source.eventData; + var rayOrigin = eventData.rayOrigin; + + DeviceData deviceData = null; + foreach (var currentDevice in evr.m_DeviceData) + { + if (currentDevice.rayOrigin == rayOrigin) + { + deviceData = currentDevice; + break; + } + } + + if (deviceData != null) + { + if (go.transform.IsChildOf(deviceData.rayOrigin)) // Don't let UI on this hand block the menu + return false; + + var scaledPointerDistance = eventData.pointerCurrentRaycast.distance / Viewer.GetViewerScale(); + var menuHideFlags = deviceData.menuHideData; + var mainMenu = deviceData.mainMenu; + IMenu openMenu = mainMenu; + if (deviceData.customMenu != null && menuHideFlags[mainMenu].hideFlags != 0) + openMenu = deviceData.customMenu; + + if (scaledPointerDistance < openMenu.localBounds.size.y + k_MenuHideMargin) + { + // Only set if hidden--value is reset every frame + menuHideFlags[openMenu].hideFlags |= MenuHideFlags.OverUI; + return true; + } + + return (menuHideFlags[openMenu].hideFlags & MenuHideFlags.Hidden) != 0; + } + + return true; + } + + internal static void UpdateAlternateMenuOnSelectionChanged(Transform rayOrigin) + { + if (rayOrigin == null) + return; + + SetAlternateMenuVisibility(rayOrigin, Selection.gameObjects.Length > 0); + } + + internal static void SetAlternateMenuVisibility(Transform rayOrigin, bool visible) + { + Rays.ForEachProxyDevice(deviceData => + { + foreach (var menu in deviceData.alternateMenus) + { + if (!(menu is IActionsMenu)) + continue; + + var menuHideFlags = deviceData.menuHideData; + // Set alternate menu visible on this rayOrigin and hide it on all others + var alternateMenuData = menuHideFlags[menu]; + if (deviceData.rayOrigin == rayOrigin && visible) + alternateMenuData.hideFlags &= ~MenuHideFlags.Hidden; + else + alternateMenuData.hideFlags |= MenuHideFlags.Hidden; + } + }); + } + + internal static void OnMainMenuActivatorSelected(Transform rayOrigin, Transform targetRayOrigin) + { + foreach (var deviceData in evr.m_DeviceData) + { + var mainMenu = deviceData.mainMenu; + if (mainMenu != null) + { + var customMenu = deviceData.customMenu; + var alternateMenu = deviceData.alternateMenu; + var menuHideData = deviceData.menuHideData; + var mainMenuHideData = menuHideData[mainMenu]; + var alternateMenuVisible = alternateMenu != null + && (menuHideData[alternateMenu].hideFlags & MenuHideFlags.Hidden) == 0; + + // Do not delay when showing via activator + mainMenuHideData.autoShowTime = 0; + + if (deviceData.rayOrigin == rayOrigin) + { + // Toggle main menu hidden flag + mainMenuHideData.hideFlags ^= MenuHideFlags.Hidden; + mainMenu.targetRayOrigin = targetRayOrigin; + } + else + { + mainMenuHideData.hideFlags |= MenuHideFlags.Hidden; + + var customMenuOverridden = customMenu != null && + (menuHideData[customMenu].hideFlags & MenuHideFlags.OtherMenu) != 0; + + // Move alternate menu if overriding custom menu + if (customMenuOverridden && alternateMenuVisible) + { + foreach (var otherDeviceData in evr.m_DeviceData) + { + if (deviceData == otherDeviceData) + continue; + + SetAlternateMenuVisibility(rayOrigin, true); + } + } + } + } + } + } + + static GameObject InstantiateMenuUI(Transform rayOrigin, IMenu prefab) + { + var ui = evr.GetNestedModule(); + GameObject go = null; + Rays.ForEachProxyDevice(deviceData => + { + var proxy = deviceData.proxy; + var otherRayOrigin = deviceData.rayOrigin; + if (proxy.rayOrigins.ContainsValue(rayOrigin) && otherRayOrigin != rayOrigin) + { + Transform menuOrigin; + if (proxy.menuOrigins.TryGetValue(otherRayOrigin, out menuOrigin)) + { + if (deviceData.customMenu == null) + { + go = ui.InstantiateUI(prefab.gameObject, menuOrigin, false); + + var customMenu = go.GetComponent(); + deviceData.customMenu = customMenu; + deviceData.menuHideData[customMenu] = new MenuHideData { hideFlags = 0 }; + } + } + } + }); + + return go; + } + + internal T SpawnMenu(Transform rayOrigin) where T : Component, IMenu + { + var mainMenu = ObjectUtils.AddComponent(evr.gameObject); + this.ConnectInterfaces(mainMenu, rayOrigin); + + return mainMenu; + } + + static bool IsMainMenuVisible(Transform rayOrigin) + { + foreach (var deviceData in evr.m_DeviceData) + { + if (deviceData.rayOrigin == rayOrigin) + return (deviceData.menuHideData[deviceData.mainMenu].hideFlags & MenuHideFlags.Hidden) == 0; + } + + return false; + } + } + } +} +#endif diff --git a/Scripts/Core/EditorVR.Tools.cs b/Scripts/Core/EditorVR.Tools.cs index 6930812e8..dc9dec36d 100644 --- a/Scripts/Core/EditorVR.Tools.cs +++ b/Scripts/Core/EditorVR.Tools.cs @@ -1,427 +1,428 @@ -#if UNITY_EDITOR && UNITY_2017_2_OR_NEWER -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.Experimental.EditorVR.Menus; -using UnityEditor.Experimental.EditorVR.Modules; -using UnityEditor.Experimental.EditorVR.Tools; -using UnityEditor.Experimental.EditorVR.Utilities; -using UnityEngine; -using UnityEngine.InputNew; - -namespace UnityEditor.Experimental.EditorVR.Core -{ - partial class EditorVR - { - class Tools : Nested, IInterfaceConnector, IConnectInterfaces - { - internal class ToolData - { - public ITool tool; - public ActionMapInput input; - public Sprite icon; - } - - internal List allTools { get; private set; } - - readonly Dictionary> m_LinkedObjects = new Dictionary>(); - - public Tools() - { - allTools = ObjectUtils.GetImplementationsOfInterface(typeof(ITool)).ToList(); - - ILinkedObjectMethods.isSharedUpdater = IsSharedUpdater; - ISelectToolMethods.selectTool = SelectTool; - ISelectToolMethods.isToolActive = IsToolActive; - } - - public void ConnectInterface(object target, object userData = null) - { - var linkedObject = target as ILinkedObject; - if (linkedObject != null) - { - var type = target.GetType(); - List linkedObjectList; - if (!m_LinkedObjects.TryGetValue(type, out linkedObjectList)) - { - linkedObjectList = new List(); - m_LinkedObjects[type] = linkedObjectList; - } - - linkedObjectList.Add(linkedObject); - linkedObject.linkedObjects = linkedObjectList; - } - } - - public void DisconnectInterface(object target, object userData = null) - { - var linkedObject = target as ILinkedObject; - if (linkedObject != null) - { - // Delay removal of linked objects in case shutdown logic relies on them - // Specifically, SerialzePreferences in AnnotationTool calls IsSharedUpdater - EditorApplication.delayCall += () => - { - var type = target.GetType(); - List linkedObjectList; - if (!m_LinkedObjects.TryGetValue(type, out linkedObjectList)) - return; - - linkedObjectList.Remove(linkedObject); - linkedObject.linkedObjects = null; - - if (linkedObjectList.Count == 0) - m_LinkedObjects.Remove(type); - }; - } - } - - bool IsSharedUpdater(ILinkedObject linkedObject) - { - var type = linkedObject.GetType(); - return m_LinkedObjects[type].IndexOf(linkedObject) == 0; - } - - internal static bool IsDefaultTool(Type type) - { - return evr.m_DefaultTools.Contains(type); - } - - internal void SpawnDefaultTools(IProxy proxy) - { - var vacuumables = evr.GetNestedModule(); - var lockModule = evr.GetModule(); - var defaultTools = evr.m_DefaultTools; - - foreach (var deviceData in evr.m_DeviceData) - { - var inputDevice = deviceData.inputDevice; - ToolData selectionToolData = null; - - if (deviceData.proxy != proxy) - continue; - - var rayOrigin = deviceData.rayOrigin; - foreach (var toolType in defaultTools) - { - HashSet devices; - var toolData = SpawnTool(toolType, out devices, inputDevice, rayOrigin); - AddToolToDeviceData(toolData, devices); - - var tool = toolData.tool; - var selectionTool = tool as SelectionTool; - if (selectionTool) - { - selectionToolData = toolData; - selectionTool.hovered += lockModule.OnHovered; - } - - var vacuumTool = tool as VacuumTool; - if (vacuumTool) - { - vacuumTool.defaultOffset = WorkspaceModule.DefaultWorkspaceOffset; - vacuumTool.defaultTilt = WorkspaceModule.DefaultWorkspaceTilt; - vacuumTool.vacuumables = vacuumables.vacuumables; - } - } - - var menus = evr.GetNestedModule(); - var menuHideData = deviceData.menuHideData; - var mainMenu = menus.SpawnMenu(rayOrigin); - deviceData.mainMenu = mainMenu; - menuHideData[mainMenu] = new Menus.MenuHideData(); - - var alternateMenu = menus.SpawnMenu(rayOrigin); - deviceData.alternateMenu = alternateMenu; - menuHideData[alternateMenu] = new Menus.MenuHideData(); - alternateMenu.itemWasSelected += Menus.UpdateAlternateMenuOnSelectionChanged; - - var undoMenu = menus.SpawnMenu(rayOrigin); - menuHideData[undoMenu] = new Menus.MenuHideData(); - - // Setup ToolsMenu - var toolsMenu = ObjectUtils.AddComponent(evr.gameObject); - this.ConnectInterfaces(toolsMenu, rayOrigin); - deviceData.toolsMenu = toolsMenu; - toolsMenu.rayOrigin = rayOrigin; - toolsMenu.setButtonForType(typeof(IMainMenu), null); - toolsMenu.setButtonForType(typeof(SelectionTool), selectionToolData != null ? selectionToolData.icon : null); - } - - evr.GetModule().UpdatePlayerHandleMaps(); - } - - /// - /// Spawn a tool on a tool stack for a specific device (e.g. right hand). - /// - /// The tool to spawn - /// A list of the used devices coming from the action map - /// The input device whose tool stack the tool should be spawned on (optional). If not - /// specified, then it uses the action map to determine which devices the tool should be spawned on. - /// Returns tool that was spawned or null if the spawn failed. - ToolData SpawnTool(Type toolType, out HashSet usedDevices, InputDevice device, Transform rayOrigin) - { - usedDevices = new HashSet(); - if (!typeof(ITool).IsAssignableFrom(toolType)) - return null; - - var deviceSlots = new HashSet(); - var tool = ObjectUtils.AddComponent(toolType, evr.gameObject) as ITool; - - var actionMapInput = evr.GetModule().CreateActionMapInputForObject(tool, device); - if (actionMapInput != null) - { - usedDevices.UnionWith(actionMapInput.GetCurrentlyUsedDevices()); - InputUtils.CollectDeviceSlotsFromActionMapInput(actionMapInput, ref deviceSlots); - - actionMapInput.Reset(false); - } - - if (usedDevices.Count == 0) - usedDevices.Add(device); - - this.ConnectInterfaces(tool, rayOrigin); - - var icon = tool as IMenuIcon; - return new ToolData { tool = tool, input = actionMapInput, icon = icon != null ? icon.icon : null }; - } - - static void AddToolToDeviceData(ToolData toolData, HashSet devices) - { - foreach (var dd in evr.m_DeviceData) - { - if (devices.Contains(dd.inputDevice)) - AddToolToStack(dd, toolData); - } - } - - static bool IsToolActive(Transform targetRayOrigin, Type toolType) - { - var result = false; - - var deviceData = evr.m_DeviceData.FirstOrDefault(dd => dd.rayOrigin == targetRayOrigin); - if (deviceData != null) - result = deviceData.currentTool.GetType() == toolType; - - return result; - } - - internal bool SelectTool(Transform rayOrigin, Type toolType, bool despawnOnReselect = true, bool hideMenu = false) - { - var result = false; - var deviceInputModule = evr.GetModule(); - Rays.ForEachProxyDevice(deviceData => - { - if (deviceData.rayOrigin == rayOrigin) - { - var spawnTool = true; - var currentTool = deviceData.currentTool; - var currentToolType = currentTool.GetType(); - var currentToolIsSelect = currentToolType == typeof(SelectionTool); - var setSelectAsCurrentTool = toolType == typeof(SelectionTool) && !currentToolIsSelect; - var toolsMenu = deviceData.toolsMenu; - - // If this tool was on the current device already, remove it, if it is selected while already being the current tool - var despawn = (!currentToolIsSelect && currentToolType == toolType && despawnOnReselect) || setSelectAsCurrentTool; // || setSelectAsCurrentTool || toolType == typeof(IMainMenu); - if (currentTool != null && despawn) - { - DespawnTool(deviceData, currentTool); - - if (!setSelectAsCurrentTool) - { - // Delete a button of the first type parameter - // Then select a button the second type param (the new current tool) - // Don't spawn a new tool, since we are only removing the old tool - toolsMenu.deleteToolsMenuButton(toolType, currentToolType); - } - else if (setSelectAsCurrentTool) - { - // Set the selection tool as the active tool, if select is to be the new current tool - toolsMenu.setButtonForType(typeof(SelectionTool), null); - } - - spawnTool = false; - } - - if (spawnTool && !IsDefaultTool(toolType)) - { - var evrDeviceData = evr.m_DeviceData; - - // Spawn tool and collect all devices that this tool will need - HashSet usedDevices; - var device = deviceData.inputDevice; - var newTool = SpawnTool(toolType, out usedDevices, device, rayOrigin); - var multiTool = newTool.tool as IMultiDeviceTool; - if (multiTool != null) - { - multiTool.primary = true; - Rays.ForEachProxyDevice(otherDeviceData => - { - if (otherDeviceData != deviceData) - { - HashSet otherUsedDevices; - var otherToolData = SpawnTool(toolType, out otherUsedDevices, otherDeviceData.inputDevice, otherDeviceData.rayOrigin); - foreach (var dd in evrDeviceData) - { - if (!otherUsedDevices.Contains(dd.inputDevice)) - continue; - - var otherCurrentTool = otherDeviceData.currentTool; - if (otherCurrentTool != null) // Remove the current tool on all devices this tool will be spawned on - DespawnTool(otherDeviceData, otherCurrentTool); - - AddToolToStack(dd, otherToolData); - } - } - }); - } - - // Exclusive mode tools always take over all tool stacks - if (newTool.tool is IExclusiveMode) - { - foreach (var dev in evrDeviceData) - { - usedDevices.Add(dev.inputDevice); - } - } - - foreach (var data in evrDeviceData) - { - if (!usedDevices.Contains(data.inputDevice)) - continue; - - if (currentTool != null) // Remove the current tool on all devices this tool will be spawned on - DespawnTool(deviceData, currentTool); - - AddToolToStack(data, newTool); - - toolsMenu.setButtonForType(toolType, newTool.icon); - } - } - - deviceInputModule.UpdatePlayerHandleMaps(); - result = spawnTool; - } - else if (hideMenu) - { - deviceData.menuHideData[deviceData.mainMenu].hideFlags |= MenuHideFlags.Hidden; - } - }); - - return result; - } - - void DespawnTool(DeviceData deviceData, ITool tool) - { - var toolType = tool.GetType(); - if (!IsDefaultTool(toolType)) - { - // Remove the tool if it is the current tool on this device tool stack - if (deviceData.currentTool == tool) - { - var topTool = deviceData.toolData.Peek(); - if (topTool == null || topTool.tool != deviceData.currentTool) - { - Debug.LogError("Tool at top of stack is not current tool."); - return; - } - - var oldTool = deviceData.toolData.Pop(); - oldTool.input.active = false; - topTool = deviceData.toolData.Peek(); - deviceData.currentTool = topTool.tool; - - // Pop this tool off any other stack that references it (for single instance tools) - foreach (var otherDeviceData in evr.m_DeviceData) - { - if (otherDeviceData != deviceData) - { - // Pop this tool off any other stack that references it (for single instance, multi-device tools) - var otherTool = otherDeviceData.currentTool; - if (otherTool == tool) - { - oldTool = otherDeviceData.toolData.Pop(); - oldTool.input.active = false; - var otherToolData = otherDeviceData.toolData.Peek(); - if (otherToolData != null) - otherDeviceData.currentTool = otherToolData.tool; - - if (tool is IExclusiveMode) - SetToolsEnabled(otherDeviceData, true); - } - - // Pop this tool of any other stack that references it (for IMultiDeviceTools) - if (tool is IMultiDeviceTool) - { - if (otherTool.GetType() == toolType) - { - oldTool = otherDeviceData.toolData.Pop(); - oldTool.input.active = false; - var otherToolData = otherDeviceData.toolData.Peek(); - if (otherToolData != null) - { - otherDeviceData.currentTool = otherToolData.tool; - this.DisconnectInterfaces(otherTool, otherDeviceData.rayOrigin); - ObjectUtils.Destroy(otherTool as MonoBehaviour); - } - } - } - - // If the tool had a custom menu, the custom menu would spawn on the opposite device - var customMenu = otherDeviceData.customMenu; - if (customMenu != null) - { - otherDeviceData.menuHideData.Remove(customMenu); - otherDeviceData.customMenu = null; - } - } - } - } - this.DisconnectInterfaces(tool, deviceData.rayOrigin); - - // Exclusive tools disable other tools underneath, so restore those - if (tool is IExclusiveMode) - SetToolsEnabled(deviceData, true); - - ObjectUtils.Destroy(tool as MonoBehaviour); - } - } - - static void SetToolsEnabled(DeviceData deviceData, bool value) - { - foreach (var td in deviceData.toolData) - { - var mb = td.tool as MonoBehaviour; - if (mb) - mb.enabled = value; - } - } - - static void AddToolToStack(DeviceData deviceData, ToolData toolData) - { - if (toolData != null) - { - // Exclusive tools render other tools disabled while they are on the stack - if (toolData.tool is IExclusiveMode) - SetToolsEnabled(deviceData, false); - - deviceData.toolData.Push(toolData); - deviceData.currentTool = toolData.tool; - } - } - - internal static void UpdatePlayerHandleMaps(List maps) - { - foreach (var deviceData in evr.m_DeviceData) - { - foreach (var td in deviceData.toolData) - { - if (td.input != null && !maps.Contains(td.input)) - maps.Add(td.input); - } - } - } - } - } -} -#endif +#if UNITY_EDITOR && UNITY_2017_2_OR_NEWER +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor.Experimental.EditorVR.Menus; +using UnityEditor.Experimental.EditorVR.Modules; +using UnityEditor.Experimental.EditorVR.Tools; +using UnityEditor.Experimental.EditorVR.Utilities; +using UnityEngine; +using UnityEngine.InputNew; + +namespace UnityEditor.Experimental.EditorVR.Core +{ + partial class EditorVR + { + class Tools : Nested, IInterfaceConnector, IConnectInterfaces + { + internal class ToolData + { + public ITool tool; + public ActionMapInput input; + public Sprite icon; + } + + internal List allTools { get; private set; } + + readonly Dictionary> m_LinkedObjects = new Dictionary>(); + + public Tools() + { + allTools = ObjectUtils.GetImplementationsOfInterface(typeof(ITool)).ToList(); + + ILinkedObjectMethods.isSharedUpdater = IsSharedUpdater; + ISelectToolMethods.selectTool = SelectTool; + ISelectToolMethods.isToolActive = IsToolActive; + } + + public void ConnectInterface(object target, object userData = null) + { + var linkedObject = target as ILinkedObject; + if (linkedObject != null) + { + var type = target.GetType(); + List linkedObjectList; + if (!m_LinkedObjects.TryGetValue(type, out linkedObjectList)) + { + linkedObjectList = new List(); + m_LinkedObjects[type] = linkedObjectList; + } + + linkedObjectList.Add(linkedObject); + linkedObject.linkedObjects = linkedObjectList; + } + } + + public void DisconnectInterface(object target, object userData = null) + { + var linkedObject = target as ILinkedObject; + if (linkedObject != null) + { + // Delay removal of linked objects in case shutdown logic relies on them + // Specifically, SerialzePreferences in AnnotationTool calls IsSharedUpdater + EditorApplication.delayCall += () => + { + var type = target.GetType(); + List linkedObjectList; + if (!m_LinkedObjects.TryGetValue(type, out linkedObjectList)) + return; + + linkedObjectList.Remove(linkedObject); + linkedObject.linkedObjects = null; + + if (linkedObjectList.Count == 0) + m_LinkedObjects.Remove(type); + }; + } + } + + bool IsSharedUpdater(ILinkedObject linkedObject) + { + var type = linkedObject.GetType(); + return m_LinkedObjects[type].IndexOf(linkedObject) == 0; + } + + internal static bool IsDefaultTool(Type type) + { + return evr.m_DefaultTools.Contains(type); + } + + internal void SpawnDefaultTools(IProxy proxy) + { + var vacuumables = evr.GetNestedModule(); + var lockModule = evr.GetModule(); + var defaultTools = evr.m_DefaultTools; + + foreach (var deviceData in evr.m_DeviceData) + { + var inputDevice = deviceData.inputDevice; + ToolData selectionToolData = null; + + if (deviceData.proxy != proxy) + continue; + + var rayOrigin = deviceData.rayOrigin; + foreach (var toolType in defaultTools) + { + HashSet devices; + var toolData = SpawnTool(toolType, out devices, inputDevice, rayOrigin); + AddToolToDeviceData(toolData, devices); + + var tool = toolData.tool; + var selectionTool = tool as SelectionTool; + if (selectionTool) + { + selectionToolData = toolData; + selectionTool.hovered += lockModule.OnHovered; + } + + var vacuumTool = tool as VacuumTool; + if (vacuumTool) + { + vacuumTool.defaultOffset = WorkspaceModule.DefaultWorkspaceOffset; + vacuumTool.defaultTilt = WorkspaceModule.DefaultWorkspaceTilt; + vacuumTool.vacuumables = vacuumables.vacuumables; + } + } + + var menus = evr.GetNestedModule(); + var menuHideData = deviceData.menuHideData; + var mainMenu = menus.SpawnMenu(rayOrigin); + deviceData.mainMenu = mainMenu; + menuHideData[mainMenu] = new Menus.MenuHideData(); + + var radialMenu = menus.SpawnMenu(rayOrigin); + menuHideData[radialMenu] = new Menus.MenuHideData(); + radialMenu.itemWasSelected += Menus.UpdateAlternateMenuOnSelectionChanged; + + var undoMenu = menus.SpawnMenu(rayOrigin); + var hideData = new Menus.MenuHideData(); + menuHideData[undoMenu] = hideData; + hideData.hideFlags = 0; + + // Setup ToolsMenu + var toolsMenu = ObjectUtils.AddComponent(evr.gameObject); + this.ConnectInterfaces(toolsMenu, rayOrigin); + deviceData.toolsMenu = toolsMenu; + toolsMenu.rayOrigin = rayOrigin; + toolsMenu.setButtonForType(typeof(IMainMenu), null); + toolsMenu.setButtonForType(typeof(SelectionTool), selectionToolData != null ? selectionToolData.icon : null); + } + + evr.GetModule().UpdatePlayerHandleMaps(); + } + + /// + /// Spawn a tool on a tool stack for a specific device (e.g. right hand). + /// + /// The tool to spawn + /// A list of the used devices coming from the action map + /// The input device whose tool stack the tool should be spawned on (optional). If not + /// specified, then it uses the action map to determine which devices the tool should be spawned on. + /// Returns tool that was spawned or null if the spawn failed. + ToolData SpawnTool(Type toolType, out HashSet usedDevices, InputDevice device, Transform rayOrigin) + { + usedDevices = new HashSet(); + if (!typeof(ITool).IsAssignableFrom(toolType)) + return null; + + var deviceSlots = new HashSet(); + var tool = ObjectUtils.AddComponent(toolType, evr.gameObject) as ITool; + + var actionMapInput = evr.GetModule().CreateActionMapInputForObject(tool, device); + if (actionMapInput != null) + { + usedDevices.UnionWith(actionMapInput.GetCurrentlyUsedDevices()); + InputUtils.CollectDeviceSlotsFromActionMapInput(actionMapInput, ref deviceSlots); + + actionMapInput.Reset(false); + } + + if (usedDevices.Count == 0) + usedDevices.Add(device); + + this.ConnectInterfaces(tool, rayOrigin); + + var icon = tool as IMenuIcon; + return new ToolData { tool = tool, input = actionMapInput, icon = icon != null ? icon.icon : null }; + } + + static void AddToolToDeviceData(ToolData toolData, HashSet devices) + { + foreach (var dd in evr.m_DeviceData) + { + if (devices.Contains(dd.inputDevice)) + AddToolToStack(dd, toolData); + } + } + + static bool IsToolActive(Transform targetRayOrigin, Type toolType) + { + var result = false; + + var deviceData = evr.m_DeviceData.FirstOrDefault(dd => dd.rayOrigin == targetRayOrigin); + if (deviceData != null) + result = deviceData.currentTool.GetType() == toolType; + + return result; + } + + internal bool SelectTool(Transform rayOrigin, Type toolType, bool despawnOnReselect = true, bool hideMenu = false) + { + var result = false; + var deviceInputModule = evr.GetModule(); + Rays.ForEachProxyDevice(deviceData => + { + if (deviceData.rayOrigin == rayOrigin) + { + var spawnTool = true; + var currentTool = deviceData.currentTool; + var currentToolType = currentTool.GetType(); + var currentToolIsSelect = currentToolType == typeof(SelectionTool); + var setSelectAsCurrentTool = toolType == typeof(SelectionTool) && !currentToolIsSelect; + var toolsMenu = deviceData.toolsMenu; + + // If this tool was on the current device already, remove it, if it is selected while already being the current tool + var despawn = (!currentToolIsSelect && currentToolType == toolType && despawnOnReselect) || setSelectAsCurrentTool; // || setSelectAsCurrentTool || toolType == typeof(IMainMenu); + if (currentTool != null && despawn) + { + DespawnTool(deviceData, currentTool); + + if (!setSelectAsCurrentTool) + { + // Delete a button of the first type parameter + // Then select a button the second type param (the new current tool) + // Don't spawn a new tool, since we are only removing the old tool + toolsMenu.deleteToolsMenuButton(toolType, currentToolType); + } + else if (setSelectAsCurrentTool) + { + // Set the selection tool as the active tool, if select is to be the new current tool + toolsMenu.setButtonForType(typeof(SelectionTool), null); + } + + spawnTool = false; + } + + if (spawnTool && !IsDefaultTool(toolType)) + { + var evrDeviceData = evr.m_DeviceData; + + // Spawn tool and collect all devices that this tool will need + HashSet usedDevices; + var device = deviceData.inputDevice; + var newTool = SpawnTool(toolType, out usedDevices, device, rayOrigin); + var multiTool = newTool.tool as IMultiDeviceTool; + if (multiTool != null) + { + multiTool.primary = true; + Rays.ForEachProxyDevice(otherDeviceData => + { + if (otherDeviceData != deviceData) + { + HashSet otherUsedDevices; + var otherToolData = SpawnTool(toolType, out otherUsedDevices, otherDeviceData.inputDevice, otherDeviceData.rayOrigin); + foreach (var dd in evrDeviceData) + { + if (!otherUsedDevices.Contains(dd.inputDevice)) + continue; + + var otherCurrentTool = otherDeviceData.currentTool; + if (otherCurrentTool != null) // Remove the current tool on all devices this tool will be spawned on + DespawnTool(otherDeviceData, otherCurrentTool); + + AddToolToStack(dd, otherToolData); + } + } + }); + } + + // Exclusive mode tools always take over all tool stacks + if (newTool.tool is IExclusiveMode) + { + foreach (var dev in evrDeviceData) + { + usedDevices.Add(dev.inputDevice); + } + } + + foreach (var data in evrDeviceData) + { + if (!usedDevices.Contains(data.inputDevice)) + continue; + + if (currentTool != null) // Remove the current tool on all devices this tool will be spawned on + DespawnTool(deviceData, currentTool); + + AddToolToStack(data, newTool); + + toolsMenu.setButtonForType(toolType, newTool.icon); + } + } + + deviceInputModule.UpdatePlayerHandleMaps(); + result = spawnTool; + } + else if (hideMenu) + { + deviceData.menuHideData[deviceData.mainMenu].hideFlags |= MenuHideFlags.Hidden; + } + }); + + return result; + } + + void DespawnTool(DeviceData deviceData, ITool tool) + { + var toolType = tool.GetType(); + if (!IsDefaultTool(toolType)) + { + // Remove the tool if it is the current tool on this device tool stack + if (deviceData.currentTool == tool) + { + var topTool = deviceData.toolData.Peek(); + if (topTool == null || topTool.tool != deviceData.currentTool) + { + Debug.LogError("Tool at top of stack is not current tool."); + return; + } + + var oldTool = deviceData.toolData.Pop(); + oldTool.input.active = false; + topTool = deviceData.toolData.Peek(); + deviceData.currentTool = topTool.tool; + + // Pop this tool off any other stack that references it (for single instance tools) + foreach (var otherDeviceData in evr.m_DeviceData) + { + if (otherDeviceData != deviceData) + { + // Pop this tool off any other stack that references it (for single instance, multi-device tools) + var otherTool = otherDeviceData.currentTool; + if (otherTool == tool) + { + oldTool = otherDeviceData.toolData.Pop(); + oldTool.input.active = false; + var otherToolData = otherDeviceData.toolData.Peek(); + if (otherToolData != null) + otherDeviceData.currentTool = otherToolData.tool; + + if (tool is IExclusiveMode) + SetToolsEnabled(otherDeviceData, true); + } + + // Pop this tool of any other stack that references it (for IMultiDeviceTools) + if (tool is IMultiDeviceTool) + { + if (otherTool.GetType() == toolType) + { + oldTool = otherDeviceData.toolData.Pop(); + oldTool.input.active = false; + var otherToolData = otherDeviceData.toolData.Peek(); + if (otherToolData != null) + { + otherDeviceData.currentTool = otherToolData.tool; + this.DisconnectInterfaces(otherTool, otherDeviceData.rayOrigin); + ObjectUtils.Destroy(otherTool as MonoBehaviour); + } + } + } + + // If the tool had a custom menu, the custom menu would spawn on the opposite device + var customMenu = otherDeviceData.customMenu; + if (customMenu != null) + { + otherDeviceData.menuHideData.Remove(customMenu); + otherDeviceData.customMenu = null; + } + } + } + } + this.DisconnectInterfaces(tool, deviceData.rayOrigin); + + // Exclusive tools disable other tools underneath, so restore those + if (tool is IExclusiveMode) + SetToolsEnabled(deviceData, true); + + ObjectUtils.Destroy(tool as MonoBehaviour); + } + } + + static void SetToolsEnabled(DeviceData deviceData, bool value) + { + foreach (var td in deviceData.toolData) + { + var mb = td.tool as MonoBehaviour; + if (mb) + mb.enabled = value; + } + } + + static void AddToolToStack(DeviceData deviceData, ToolData toolData) + { + if (toolData != null) + { + // Exclusive tools render other tools disabled while they are on the stack + if (toolData.tool is IExclusiveMode) + SetToolsEnabled(deviceData, false); + + deviceData.toolData.Push(toolData); + deviceData.currentTool = toolData.tool; + } + } + + internal static void UpdatePlayerHandleMaps(List maps) + { + foreach (var deviceData in evr.m_DeviceData) + { + foreach (var td in deviceData.toolData) + { + if (td.input != null && !maps.Contains(td.input)) + maps.Add(td.input); + } + } + } + } + } +} +#endif diff --git a/Scripts/Core/EditorVR.cs b/Scripts/Core/EditorVR.cs index 801b4dc59..10403fac2 100644 --- a/Scripts/Core/EditorVR.cs +++ b/Scripts/Core/EditorVR.cs @@ -1,552 +1,551 @@ -#if UNITY_EDITOR -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using UnityEditor.Experimental.EditorVR.Extensions; -using UnityEditor.Experimental.EditorVR.Modules; -using UnityEditor.Experimental.EditorVR.Utilities; -using UnityEngine; -using UnityEngine.InputNew; - -namespace UnityEditor.Experimental.EditorVR.Core -{ -#if UNITY_2017_2_OR_NEWER - [InitializeOnLoad] - [RequiresTag(k_VRPlayerTag)] - sealed partial class EditorVR : MonoBehaviour, IConnectInterfaces - { - const string k_ShowGameObjects = "EditorVR.ShowGameObjects"; - const string k_PreserveLayout = "EditorVR.PreserveLayout"; - const string k_SerializedPreferences = "EditorVR.SerializedPreferences"; - const string k_VRPlayerTag = "VRPlayer"; - - Dictionary m_NestedModules = new Dictionary(); - Dictionary m_Modules = new Dictionary(); - - Interfaces m_Interfaces; - Type[] m_DefaultTools; - - event Action selectionChanged; - - readonly List m_DeviceData = new List(); - - bool m_HasDeserialized; - - static bool s_IsInitialized; - - static EditorVR s_Instance; - - static HideFlags defaultHideFlags - { - get { return showGameObjects ? HideFlags.DontSave : HideFlags.HideAndDontSave; } - } - - static bool showGameObjects - { - get { return EditorPrefs.GetBool(k_ShowGameObjects, false); } - set { EditorPrefs.SetBool(k_ShowGameObjects, value); } - } - - static bool preserveLayout - { - get { return EditorPrefs.GetBool(k_PreserveLayout, true); } - set { EditorPrefs.SetBool(k_PreserveLayout, value); } - } - - static string serializedPreferences - { - get { return EditorPrefs.GetString(k_SerializedPreferences, string.Empty); } - set { EditorPrefs.SetString(k_SerializedPreferences, value); } - } - - internal static Type[] defaultTools { get; set; } - - class DeviceData - { - public IProxy proxy; - public InputDevice inputDevice; - public Node node; - public Transform rayOrigin; - public readonly Stack toolData = new Stack(); - public IMainMenu mainMenu; - public IAlternateMenu alternateMenu; - public ITool currentTool; - public IMenu customMenu; - public IToolsMenu toolsMenu; - public List customAlternateMenus = new List(); - public ICustomAlternateMenu highestPriorityCustomAlternateMenu; - public readonly Dictionary menuHideData = new Dictionary(); - } - - class Nested - { - public static EditorVR evr { protected get; set; } - - internal virtual void OnDestroy() { } - } - - static void ResetPreferences() - { - EditorPrefs.DeleteKey(k_ShowGameObjects); - EditorPrefs.DeleteKey(k_PreserveLayout); - EditorPrefs.DeleteKey(k_SerializedPreferences); - } - - // Code from the previous static constructor moved here to allow for testability - static void HandleInitialization() - { - if (!s_IsInitialized) - { - s_IsInitialized = true; - - if (!PlayerSettings.virtualRealitySupported) - Debug.Log("EditorVR requires VR support. Please check Virtual Reality Supported in Edit->Project Settings->Player->Other Settings"); - -#if !ENABLE_OVR_INPUT && !ENABLE_STEAMVR_INPUT && !ENABLE_SIXENSE_INPUT - Debug.Log("EditorVR requires at least one partner (e.g. Oculus, Vive) SDK to be installed for input. You can download these from the Asset Store or from the partner's website"); -#endif - - // Add EVR tags and layers if they don't exist - var tags = TagManager.GetRequiredTags(); - var layers = TagManager.GetRequiredLayers(); - - foreach (var tag in tags) - { - TagManager.AddTag(tag); - } - - foreach (var layer in layers) - { - TagManager.AddLayer(layer); - } - } - } - - void Awake() - { - s_Instance = this; // Used only by PreferencesGUI - Nested.evr = this; // Set this once for the convenience of all nested classes - m_DefaultTools = defaultTools; - SetHideFlags(defaultHideFlags); - ClearDeveloperConsoleIfNecessary(); - HandleInitialization(); - - m_Interfaces = (Interfaces)AddNestedModule(typeof(Interfaces)); - AddModule(); // Added here in case any nested modules have preference serialization - AddNestedModule(typeof(SerializedPreferencesModuleConnector)); - - var nestedClassTypes = ObjectUtils.GetExtensionsOfClass(typeof(Nested)); - foreach (var type in nestedClassTypes) - { - AddNestedModule(type); - } - LateBindNestedModules(nestedClassTypes); - - AddModule(); - AddModule(); - - var viewer = GetNestedModule(); - viewer.preserveCameraRig = preserveLayout; - viewer.InitializeCamera(); - - var deviceInputModule = AddModule(); - deviceInputModule.InitializePlayerHandle(); - deviceInputModule.CreateDefaultActionMapInputs(); - deviceInputModule.processInput = ProcessInput; - deviceInputModule.updatePlayerHandleMaps = Tools.UpdatePlayerHandleMaps; - deviceInputModule.inputDeviceForRayOrigin = rayOrigin => - (from deviceData in m_DeviceData - where deviceData.rayOrigin == rayOrigin - select deviceData.inputDevice).FirstOrDefault(); - - GetNestedModule().Initialize(); - - AddModule(); - - var multipleRayInputModule = GetModule(); - - var dragAndDropModule = AddModule(); - multipleRayInputModule.rayEntered += dragAndDropModule.OnRayEntered; - multipleRayInputModule.rayExited += dragAndDropModule.OnRayExited; - multipleRayInputModule.dragStarted += dragAndDropModule.OnDragStarted; - multipleRayInputModule.dragEnded += dragAndDropModule.OnDragEnded; - - var tooltipModule = AddModule(); - this.ConnectInterfaces(tooltipModule); - multipleRayInputModule.rayEntered += tooltipModule.OnRayEntered; - multipleRayInputModule.rayHovering += tooltipModule.OnRayHovering; - multipleRayInputModule.rayExited += tooltipModule.OnRayExited; - - AddModule(); - AddModule(); - - var lockModule = AddModule(); - lockModule.updateAlternateMenu = (rayOrigin, o) => Menus.SetAlternateMenuVisibility(rayOrigin, o != null); - - AddModule(); - - var spatialHashModule = AddModule(); - spatialHashModule.shouldExcludeObject = go => go.GetComponentInParent(); - spatialHashModule.Setup(); - - var intersectionModule = AddModule(); - this.ConnectInterfaces(intersectionModule); - intersectionModule.Setup(spatialHashModule.spatialHash); - - AddModule(); - - var vacuumables = GetNestedModule(); - - var miniWorlds = GetNestedModule(); - var workspaceModule = AddModule(); - workspaceModule.preserveWorkspaces = preserveLayout; - workspaceModule.workspaceCreated += vacuumables.OnWorkspaceCreated; - workspaceModule.workspaceCreated += miniWorlds.OnWorkspaceCreated; - workspaceModule.workspaceCreated += workspace => { deviceInputModule.UpdatePlayerHandleMaps(); }; - workspaceModule.workspaceDestroyed += vacuumables.OnWorkspaceDestroyed; - workspaceModule.workspaceDestroyed += miniWorlds.OnWorkspaceDestroyed; - - UnityBrandColorScheme.sessionGradient = UnityBrandColorScheme.GetRandomCuratedLightGradient(); - UnityBrandColorScheme.saturatedSessionGradient = UnityBrandColorScheme.GetRandomCuratedGradient(); - - var sceneObjectModule = AddModule(); - sceneObjectModule.tryPlaceObject = (obj, targetScale) => - { - foreach (var miniWorld in miniWorlds.worlds) - { - if (!miniWorld.Contains(obj.position)) - continue; - - var referenceTransform = miniWorld.referenceTransform; - obj.transform.parent = null; - obj.position = referenceTransform.position + Vector3.Scale(miniWorld.miniWorldTransform.InverseTransformPoint(obj.position), miniWorld.referenceTransform.localScale); - obj.rotation = referenceTransform.rotation * Quaternion.Inverse(miniWorld.miniWorldTransform.rotation) * obj.rotation; - obj.localScale = Vector3.Scale(Vector3.Scale(obj.localScale, referenceTransform.localScale), miniWorld.miniWorldTransform.lossyScale.Inverse()); - - spatialHashModule.AddObject(obj.gameObject); - return true; - } - - return false; - }; - - AddModule(); - AddModule(); - AddModule(); - - AddModule(); - - viewer.AddPlayerModel(); - - GetNestedModule().CreateAllProxies(); - - // In case we have anything selected at start, set up manipulators, inspector, etc. - EditorApplication.delayCall += OnSelectionChanged; - } - - IEnumerator Start() - { - var leftHandFound = false; - var rightHandFound = false; - - // Some components depend on both hands existing (e.g. MiniWorldWorkspace), so make sure they exist before restoring - while (!(leftHandFound && rightHandFound)) - { - Rays.ForEachProxyDevice(deviceData => - { - if (deviceData.node == Node.LeftHand) - leftHandFound = true; - - if (deviceData.node == Node.RightHand) - rightHandFound = true; - }); - - yield return null; - } - - var viewer = GetNestedModule(); - while (!viewer.hmdReady) - yield return null; - - GetModule().DeserializePreferences(serializedPreferences); - m_HasDeserialized = true; - } - - static void ClearDeveloperConsoleIfNecessary() - { - var asm = Assembly.GetAssembly(typeof(Editor)); - var consoleWindowType = asm.GetType("UnityEditor.ConsoleWindow"); - - EditorWindow window = null; - foreach (var w in Resources.FindObjectsOfTypeAll()) - { - if (w.GetType() == consoleWindowType) - { - window = w; - break; - } - } - - if (window) - { - var consoleFlagsType = consoleWindowType.GetNestedType("ConsoleFlags", BindingFlags.NonPublic); - var names = Enum.GetNames(consoleFlagsType); - var values = Enum.GetValues(consoleFlagsType); - var clearOnPlayFlag = values.GetValue(Array.IndexOf(names, "ClearOnPlay")); - - var hasFlagMethod = consoleWindowType.GetMethod("HasFlag", BindingFlags.NonPublic | BindingFlags.Static); - var result = (bool)hasFlagMethod.Invoke(window, new[] { clearOnPlayFlag }); - - if (result) - { - var logEntries = asm.GetType("UnityEditor.LogEntries"); - var clearMethod = logEntries.GetMethod("Clear", BindingFlags.Static | BindingFlags.Public); - clearMethod.Invoke(null, null); - } - } - } - - void OnSelectionChanged() - { - if (selectionChanged != null) - selectionChanged(); - - Menus.UpdateAlternateMenuOnSelectionChanged(GetNestedModule().lastSelectionRayOrigin); - } - - void OnEnable() - { - Selection.selectionChanged += OnSelectionChanged; - } - - void OnDisable() - { - Selection.selectionChanged -= OnSelectionChanged; - } - - internal void Shutdown() - { - if (m_HasDeserialized) - serializedPreferences = GetModule().SerializePreferences(); - } - - void OnDestroy() - { - s_Instance = null; - foreach (var nested in m_NestedModules.Values) - { - nested.OnDestroy(); - } - } - - void Update() - { - GetNestedModule().UpdateCamera(); - - Rays.UpdateRaycasts(); - - GetNestedModule().UpdateDefaultProxyRays(); - - GetNestedModule().UpdateDirectSelection(); - - GetModule().UpdateKeyboardMallets(); - - GetModule().ProcessInput(); - - GetNestedModule().UpdateMenuVisibilities(); - - GetNestedModule().UpdateManipulatorVisibilites(); - } - - void ProcessInput(HashSet processedInputs, ConsumeControlDelegate consumeControl) - { - GetNestedModule().UpdateMiniWorlds(); - - foreach (var deviceData in m_DeviceData) - { - if (!deviceData.proxy.active) - continue; - - foreach (var toolData in deviceData.toolData) - { - var process = toolData.tool as IProcessInput; - if (process != null && ((MonoBehaviour)toolData.tool).enabled - && processedInputs.Add(process)) // Only process inputs for an instance of a tool once (e.g. two-handed tools) - process.ProcessInput(toolData.input, consumeControl); - } - } - } - - T GetModule() where T : MonoBehaviour - { - MonoBehaviour module; - m_Modules.TryGetValue(typeof(T), out module); - return (T)module; - } - - T AddModule() where T : MonoBehaviour - { - MonoBehaviour module; - var type = typeof(T); - if (!m_Modules.TryGetValue(type, out module)) - { - module = ObjectUtils.AddComponent(gameObject); - m_Modules.Add(type, module); - - foreach (var nested in m_NestedModules.Values) - { - var lateBinding = nested as ILateBindInterfaceMethods; - if (lateBinding != null) - lateBinding.LateBindInterfaceMethods((T)module); - } - - this.ConnectInterfaces(module); - m_Interfaces.AttachInterfaceConnectors(module); - } - - return (T)module; - } - - T GetNestedModule() where T : Nested - { - return (T)m_NestedModules[typeof(T)]; - } - - Nested AddNestedModule(Type type) - { - Nested nested; - if (!m_NestedModules.TryGetValue(type, out nested)) - { - nested = (Nested)Activator.CreateInstance(type); - m_NestedModules.Add(type, nested); - - if (m_Interfaces != null) - { - this.ConnectInterfaces(nested); - m_Interfaces.AttachInterfaceConnectors(nested); - } - } - - return nested; - } - - void LateBindNestedModules(IEnumerable types) - { - foreach (var type in types) - { - var lateBindings = type.GetInterfaces().Where(i => - i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ILateBindInterfaceMethods<>)); - - Nested nestedModule; - if (m_NestedModules.TryGetValue(type, out nestedModule)) - { - foreach (var lateBinding in lateBindings) - { - var dependencyType = lateBinding.GetGenericArguments().First(); - - Nested dependency; - if (m_NestedModules.TryGetValue(dependencyType, out dependency)) - { - var map = type.GetInterfaceMap(lateBinding); - if (map.InterfaceMethods.Length == 1) - { - var tm = map.TargetMethods[0]; - tm.Invoke(nestedModule, new[] { dependency }); - } - } - } - } - } - } - - void SetHideFlags(HideFlags hideFlags) - { - ObjectUtils.hideFlags = hideFlags; - - foreach (var manager in Resources.FindObjectsOfTypeAll()) - { - manager.gameObject.hideFlags = hideFlags; - } - - foreach (var manager in Resources.FindObjectsOfTypeAll()) - { - manager.gameObject.hideFlags = hideFlags; - } - - foreach (var child in GetComponentsInChildren(true)) - { - child.gameObject.hideFlags = hideFlags; - } - - EditorApplication.DirtyHierarchyWindowSorting(); // Otherwise objects aren't shown/hidden in hierarchy window - } - - [PreferenceItem("EditorVR")] - static void PreferencesGUI() - { - EditorGUILayout.BeginVertical(); - EditorGUILayout.Space(); - - // Show EditorVR GameObjects - { - string title = "Show EditorVR GameObjects"; - string tooltip = "Normally, EditorVR GameObjects are hidden in the Hierarchy. Would you like to show them?"; - - EditorGUI.BeginChangeCheck(); - showGameObjects = EditorGUILayout.Toggle(new GUIContent(title, tooltip), showGameObjects); - if (EditorGUI.EndChangeCheck() && s_Instance) - s_Instance.SetHideFlags(defaultHideFlags); - } - - // Preserve Layout - { - string title = "Preserve Layout"; - string tooltip = "Check this to preserve your layout and location in EditorVR"; - preserveLayout = EditorGUILayout.Toggle(new GUIContent(title, tooltip), preserveLayout); - } - - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Reset to Defaults", GUILayout.Width(140))) - ResetPreferences(); - - EditorGUILayout.EndVertical(); - } - -#if !INCLUDE_TEXT_MESH_PRO - static EditorVR() - { - Debug.LogWarning("EditorVR requires TextMesh Pro. Please go to the Asset Store and download/import Text Mesh Pro."); - } -#endif - } -#else - internal class NoEditorVR - { - const string k_ShowCustomEditorWarning = "EditorVR.ShowCustomEditorWarning"; - - static NoEditorVR() - { - if (EditorPrefs.GetBool(k_ShowCustomEditorWarning, true)) - { - var message = "EditorVR requires Unity 2017.2 or above."; - var result = EditorUtility.DisplayDialogComplex("Update Unity", message, "Download", "Ignore", "Remind Me Again"); - switch (result) - { - case 0: - Application.OpenURL("https://unity3d.com/get-unity/download"); - break; - case 1: - EditorPrefs.SetBool(k_ShowCustomEditorWarning, false); - break; - case 2: - Debug.Log("" + message + ""); - break; - } - } - } - } -#endif -} -#endif +#if UNITY_EDITOR +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEditor.Experimental.EditorVR.Extensions; +using UnityEditor.Experimental.EditorVR.Modules; +using UnityEditor.Experimental.EditorVR.Utilities; +using UnityEngine; +using UnityEngine.InputNew; + +namespace UnityEditor.Experimental.EditorVR.Core +{ +#if UNITY_2017_2_OR_NEWER + [InitializeOnLoad] + [RequiresTag(k_VRPlayerTag)] + sealed partial class EditorVR : MonoBehaviour, IConnectInterfaces + { + const string k_ShowGameObjects = "EditorVR.ShowGameObjects"; + const string k_PreserveLayout = "EditorVR.PreserveLayout"; + const string k_SerializedPreferences = "EditorVR.SerializedPreferences"; + const string k_VRPlayerTag = "VRPlayer"; + + Dictionary m_NestedModules = new Dictionary(); + Dictionary m_Modules = new Dictionary(); + + Interfaces m_Interfaces; + Type[] m_DefaultTools; + + event Action selectionChanged; + + readonly List m_DeviceData = new List(); + + bool m_HasDeserialized; + + static bool s_IsInitialized; + + static EditorVR s_Instance; + + static HideFlags defaultHideFlags + { + get { return showGameObjects ? HideFlags.DontSave : HideFlags.HideAndDontSave; } + } + + static bool showGameObjects + { + get { return EditorPrefs.GetBool(k_ShowGameObjects, false); } + set { EditorPrefs.SetBool(k_ShowGameObjects, value); } + } + + static bool preserveLayout + { + get { return EditorPrefs.GetBool(k_PreserveLayout, true); } + set { EditorPrefs.SetBool(k_PreserveLayout, value); } + } + + static string serializedPreferences + { + get { return EditorPrefs.GetString(k_SerializedPreferences, string.Empty); } + set { EditorPrefs.SetString(k_SerializedPreferences, value); } + } + + internal static Type[] defaultTools { get; set; } + + class DeviceData + { + public IProxy proxy; + public InputDevice inputDevice; + public Node node; + public Transform rayOrigin; + public readonly Stack toolData = new Stack(); + public IMainMenu mainMenu; + public ITool currentTool; + public IMenu customMenu; + public IToolsMenu toolsMenu; + public readonly List alternateMenus = new List(); + public IAlternateMenu alternateMenu; + public readonly Dictionary menuHideData = new Dictionary(); + } + + class Nested + { + public static EditorVR evr { protected get; set; } + + internal virtual void OnDestroy() { } + } + + static void ResetPreferences() + { + EditorPrefs.DeleteKey(k_ShowGameObjects); + EditorPrefs.DeleteKey(k_PreserveLayout); + EditorPrefs.DeleteKey(k_SerializedPreferences); + } + + // Code from the previous static constructor moved here to allow for testability + static void HandleInitialization() + { + if (!s_IsInitialized) + { + s_IsInitialized = true; + + if (!PlayerSettings.virtualRealitySupported) + Debug.Log("EditorVR requires VR support. Please check Virtual Reality Supported in Edit->Project Settings->Player->Other Settings"); + +#if !ENABLE_OVR_INPUT && !ENABLE_STEAMVR_INPUT && !ENABLE_SIXENSE_INPUT + Debug.Log("EditorVR requires at least one partner (e.g. Oculus, Vive) SDK to be installed for input. You can download these from the Asset Store or from the partner's website"); +#endif + + // Add EVR tags and layers if they don't exist + var tags = TagManager.GetRequiredTags(); + var layers = TagManager.GetRequiredLayers(); + + foreach (var tag in tags) + { + TagManager.AddTag(tag); + } + + foreach (var layer in layers) + { + TagManager.AddLayer(layer); + } + } + } + + void Awake() + { + s_Instance = this; // Used only by PreferencesGUI + Nested.evr = this; // Set this once for the convenience of all nested classes + m_DefaultTools = defaultTools; + SetHideFlags(defaultHideFlags); + ClearDeveloperConsoleIfNecessary(); + HandleInitialization(); + + m_Interfaces = (Interfaces)AddNestedModule(typeof(Interfaces)); + AddModule(); // Added here in case any nested modules have preference serialization + AddNestedModule(typeof(SerializedPreferencesModuleConnector)); + + var nestedClassTypes = ObjectUtils.GetExtensionsOfClass(typeof(Nested)); + foreach (var type in nestedClassTypes) + { + AddNestedModule(type); + } + LateBindNestedModules(nestedClassTypes); + + AddModule(); + AddModule(); + + var viewer = GetNestedModule(); + viewer.preserveCameraRig = preserveLayout; + viewer.InitializeCamera(); + + var deviceInputModule = AddModule(); + deviceInputModule.InitializePlayerHandle(); + deviceInputModule.CreateDefaultActionMapInputs(); + deviceInputModule.processInput = ProcessInput; + deviceInputModule.updatePlayerHandleMaps = Tools.UpdatePlayerHandleMaps; + deviceInputModule.inputDeviceForRayOrigin = rayOrigin => + (from deviceData in m_DeviceData + where deviceData.rayOrigin == rayOrigin + select deviceData.inputDevice).FirstOrDefault(); + + GetNestedModule().Initialize(); + + AddModule(); + + var multipleRayInputModule = GetModule(); + + var dragAndDropModule = AddModule(); + multipleRayInputModule.rayEntered += dragAndDropModule.OnRayEntered; + multipleRayInputModule.rayExited += dragAndDropModule.OnRayExited; + multipleRayInputModule.dragStarted += dragAndDropModule.OnDragStarted; + multipleRayInputModule.dragEnded += dragAndDropModule.OnDragEnded; + + var tooltipModule = AddModule(); + this.ConnectInterfaces(tooltipModule); + multipleRayInputModule.rayEntered += tooltipModule.OnRayEntered; + multipleRayInputModule.rayHovering += tooltipModule.OnRayHovering; + multipleRayInputModule.rayExited += tooltipModule.OnRayExited; + + AddModule(); + AddModule(); + + var lockModule = AddModule(); + lockModule.updateAlternateMenu = (rayOrigin, o) => Menus.SetAlternateMenuVisibility(rayOrigin, o != null); + + AddModule(); + + var spatialHashModule = AddModule(); + spatialHashModule.shouldExcludeObject = go => go.GetComponentInParent(); + spatialHashModule.Setup(); + + var intersectionModule = AddModule(); + this.ConnectInterfaces(intersectionModule); + intersectionModule.Setup(spatialHashModule.spatialHash); + + AddModule(); + + var vacuumables = GetNestedModule(); + + var miniWorlds = GetNestedModule(); + var workspaceModule = AddModule(); + workspaceModule.preserveWorkspaces = preserveLayout; + workspaceModule.workspaceCreated += vacuumables.OnWorkspaceCreated; + workspaceModule.workspaceCreated += miniWorlds.OnWorkspaceCreated; + workspaceModule.workspaceCreated += workspace => { deviceInputModule.UpdatePlayerHandleMaps(); }; + workspaceModule.workspaceDestroyed += vacuumables.OnWorkspaceDestroyed; + workspaceModule.workspaceDestroyed += miniWorlds.OnWorkspaceDestroyed; + + UnityBrandColorScheme.sessionGradient = UnityBrandColorScheme.GetRandomCuratedLightGradient(); + UnityBrandColorScheme.saturatedSessionGradient = UnityBrandColorScheme.GetRandomCuratedGradient(); + + var sceneObjectModule = AddModule(); + sceneObjectModule.tryPlaceObject = (obj, targetScale) => + { + foreach (var miniWorld in miniWorlds.worlds) + { + if (!miniWorld.Contains(obj.position)) + continue; + + var referenceTransform = miniWorld.referenceTransform; + obj.transform.parent = null; + obj.position = referenceTransform.position + Vector3.Scale(miniWorld.miniWorldTransform.InverseTransformPoint(obj.position), miniWorld.referenceTransform.localScale); + obj.rotation = referenceTransform.rotation * Quaternion.Inverse(miniWorld.miniWorldTransform.rotation) * obj.rotation; + obj.localScale = Vector3.Scale(Vector3.Scale(obj.localScale, referenceTransform.localScale), miniWorld.miniWorldTransform.lossyScale.Inverse()); + + spatialHashModule.AddObject(obj.gameObject); + return true; + } + + return false; + }; + + AddModule(); + AddModule(); + AddModule(); + + AddModule(); + + viewer.AddPlayerModel(); + + GetNestedModule().CreateAllProxies(); + + // In case we have anything selected at start, set up manipulators, inspector, etc. + EditorApplication.delayCall += OnSelectionChanged; + } + + IEnumerator Start() + { + var leftHandFound = false; + var rightHandFound = false; + + // Some components depend on both hands existing (e.g. MiniWorldWorkspace), so make sure they exist before restoring + while (!(leftHandFound && rightHandFound)) + { + Rays.ForEachProxyDevice(deviceData => + { + if (deviceData.node == Node.LeftHand) + leftHandFound = true; + + if (deviceData.node == Node.RightHand) + rightHandFound = true; + }); + + yield return null; + } + + var viewer = GetNestedModule(); + while (!viewer.hmdReady) + yield return null; + + GetModule().DeserializePreferences(serializedPreferences); + m_HasDeserialized = true; + } + + static void ClearDeveloperConsoleIfNecessary() + { + var asm = Assembly.GetAssembly(typeof(Editor)); + var consoleWindowType = asm.GetType("UnityEditor.ConsoleWindow"); + + EditorWindow window = null; + foreach (var w in Resources.FindObjectsOfTypeAll()) + { + if (w.GetType() == consoleWindowType) + { + window = w; + break; + } + } + + if (window) + { + var consoleFlagsType = consoleWindowType.GetNestedType("ConsoleFlags", BindingFlags.NonPublic); + var names = Enum.GetNames(consoleFlagsType); + var values = Enum.GetValues(consoleFlagsType); + var clearOnPlayFlag = values.GetValue(Array.IndexOf(names, "ClearOnPlay")); + + var hasFlagMethod = consoleWindowType.GetMethod("HasFlag", BindingFlags.NonPublic | BindingFlags.Static); + var result = (bool)hasFlagMethod.Invoke(window, new[] { clearOnPlayFlag }); + + if (result) + { + var logEntries = asm.GetType("UnityEditor.LogEntries"); + var clearMethod = logEntries.GetMethod("Clear", BindingFlags.Static | BindingFlags.Public); + clearMethod.Invoke(null, null); + } + } + } + + void OnSelectionChanged() + { + if (selectionChanged != null) + selectionChanged(); + + Menus.UpdateAlternateMenuOnSelectionChanged(GetNestedModule().lastSelectionRayOrigin); + } + + void OnEnable() + { + Selection.selectionChanged += OnSelectionChanged; + } + + void OnDisable() + { + Selection.selectionChanged -= OnSelectionChanged; + } + + internal void Shutdown() + { + if (m_HasDeserialized) + serializedPreferences = GetModule().SerializePreferences(); + } + + void OnDestroy() + { + s_Instance = null; + foreach (var nested in m_NestedModules.Values) + { + nested.OnDestroy(); + } + } + + void Update() + { + GetNestedModule().UpdateCamera(); + + Rays.UpdateRaycasts(); + + GetNestedModule().UpdateDefaultProxyRays(); + + GetNestedModule().UpdateDirectSelection(); + + GetModule().UpdateKeyboardMallets(); + + GetModule().ProcessInput(); + + GetNestedModule().UpdateMenuVisibilities(); + + GetNestedModule().UpdateManipulatorVisibilites(); + } + + void ProcessInput(HashSet processedInputs, ConsumeControlDelegate consumeControl) + { + GetNestedModule().UpdateMiniWorlds(); + + foreach (var deviceData in m_DeviceData) + { + if (!deviceData.proxy.active) + continue; + + foreach (var toolData in deviceData.toolData) + { + var process = toolData.tool as IProcessInput; + if (process != null && ((MonoBehaviour)toolData.tool).enabled + && processedInputs.Add(process)) // Only process inputs for an instance of a tool once (e.g. two-handed tools) + process.ProcessInput(toolData.input, consumeControl); + } + } + } + + T GetModule() where T : MonoBehaviour + { + MonoBehaviour module; + m_Modules.TryGetValue(typeof(T), out module); + return (T)module; + } + + T AddModule() where T : MonoBehaviour + { + MonoBehaviour module; + var type = typeof(T); + if (!m_Modules.TryGetValue(type, out module)) + { + module = ObjectUtils.AddComponent(gameObject); + m_Modules.Add(type, module); + + foreach (var nested in m_NestedModules.Values) + { + var lateBinding = nested as ILateBindInterfaceMethods; + if (lateBinding != null) + lateBinding.LateBindInterfaceMethods((T)module); + } + + this.ConnectInterfaces(module); + m_Interfaces.AttachInterfaceConnectors(module); + } + + return (T)module; + } + + T GetNestedModule() where T : Nested + { + return (T)m_NestedModules[typeof(T)]; + } + + Nested AddNestedModule(Type type) + { + Nested nested; + if (!m_NestedModules.TryGetValue(type, out nested)) + { + nested = (Nested)Activator.CreateInstance(type); + m_NestedModules.Add(type, nested); + + if (m_Interfaces != null) + { + this.ConnectInterfaces(nested); + m_Interfaces.AttachInterfaceConnectors(nested); + } + } + + return nested; + } + + void LateBindNestedModules(IEnumerable types) + { + foreach (var type in types) + { + var lateBindings = type.GetInterfaces().Where(i => + i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ILateBindInterfaceMethods<>)); + + Nested nestedModule; + if (m_NestedModules.TryGetValue(type, out nestedModule)) + { + foreach (var lateBinding in lateBindings) + { + var dependencyType = lateBinding.GetGenericArguments().First(); + + Nested dependency; + if (m_NestedModules.TryGetValue(dependencyType, out dependency)) + { + var map = type.GetInterfaceMap(lateBinding); + if (map.InterfaceMethods.Length == 1) + { + var tm = map.TargetMethods[0]; + tm.Invoke(nestedModule, new[] { dependency }); + } + } + } + } + } + } + + void SetHideFlags(HideFlags hideFlags) + { + ObjectUtils.hideFlags = hideFlags; + + foreach (var manager in Resources.FindObjectsOfTypeAll()) + { + manager.gameObject.hideFlags = hideFlags; + } + + foreach (var manager in Resources.FindObjectsOfTypeAll()) + { + manager.gameObject.hideFlags = hideFlags; + } + + foreach (var child in GetComponentsInChildren(true)) + { + child.gameObject.hideFlags = hideFlags; + } + + EditorApplication.DirtyHierarchyWindowSorting(); // Otherwise objects aren't shown/hidden in hierarchy window + } + + [PreferenceItem("EditorVR")] + static void PreferencesGUI() + { + EditorGUILayout.BeginVertical(); + EditorGUILayout.Space(); + + // Show EditorVR GameObjects + { + string title = "Show EditorVR GameObjects"; + string tooltip = "Normally, EditorVR GameObjects are hidden in the Hierarchy. Would you like to show them?"; + + EditorGUI.BeginChangeCheck(); + showGameObjects = EditorGUILayout.Toggle(new GUIContent(title, tooltip), showGameObjects); + if (EditorGUI.EndChangeCheck() && s_Instance) + s_Instance.SetHideFlags(defaultHideFlags); + } + + // Preserve Layout + { + string title = "Preserve Layout"; + string tooltip = "Check this to preserve your layout and location in EditorVR"; + preserveLayout = EditorGUILayout.Toggle(new GUIContent(title, tooltip), preserveLayout); + } + + GUILayout.FlexibleSpace(); + if (GUILayout.Button("Reset to Defaults", GUILayout.Width(140))) + ResetPreferences(); + + EditorGUILayout.EndVertical(); + } + +#if !INCLUDE_TEXT_MESH_PRO + static EditorVR() + { + Debug.LogWarning("EditorVR requires TextMesh Pro. Please go to the Asset Store and download/import Text Mesh Pro."); + } +#endif + } +#else + internal class NoEditorVR + { + const string k_ShowCustomEditorWarning = "EditorVR.ShowCustomEditorWarning"; + + static NoEditorVR() + { + if (EditorPrefs.GetBool(k_ShowCustomEditorWarning, true)) + { + var message = "EditorVR requires Unity 2017.2 or above."; + var result = EditorUtility.DisplayDialogComplex("Update Unity", message, "Download", "Ignore", "Remind Me Again"); + switch (result) + { + case 0: + Application.OpenURL("https://unity3d.com/get-unity/download"); + break; + case 1: + EditorPrefs.SetBool(k_ShowCustomEditorWarning, false); + break; + case 2: + Debug.Log("" + message + ""); + break; + } + } + } + } +#endif +} +#endif diff --git a/Scripts/Core/InterfaceConnectors/ActionsModuleConnector.cs b/Scripts/Core/InterfaceConnectors/ActionsModuleConnector.cs index 47cd17466..40981142a 100644 --- a/Scripts/Core/InterfaceConnectors/ActionsModuleConnector.cs +++ b/Scripts/Core/InterfaceConnectors/ActionsModuleConnector.cs @@ -1,62 +1,65 @@ -#if UNITY_EDITOR && UNITY_2017_2_OR_NEWER -using UnityEditor.Experimental.EditorVR.Modules; - -namespace UnityEditor.Experimental.EditorVR.Core -{ - partial class EditorVR - { - class ActionsModuleConnector : Nested, IInterfaceConnector - { - public void ConnectInterface(object target, object userData = null) - { - var actionsModule = evr.GetModule(); - if (actionsModule) - { - var menuActions = actionsModule.menuActions; - - var toolActions = target as IActions; - if (toolActions != null) - { - // Delay connecting actions to allow tool / module to initialize first - EditorApplication.delayCall += () => - { - var actions = toolActions.actions; - if (actions != null) - { - foreach (var action in actions) - { - var actionMenuData = new ActionMenuData() - { - name = action.GetType().Name, - sectionName = ActionMenuItemAttribute.DefaultActionSectionName, - priority = int.MaxValue, - action = action, - }; - menuActions.Add(actionMenuData); - } - Menus.UpdateAlternateMenuActions(); - } - }; - } - - var alternateMenu = target as IAlternateMenu; - if (alternateMenu != null) - alternateMenu.menuActions = menuActions; - } - } - - public void DisconnectInterface(object target, object userData = null) - { - var toolActions = target as IActions; - if (toolActions != null) - { - var evrActionsModule = evr.GetModule(); - - evrActionsModule.RemoveActions(toolActions.actions); - Menus.UpdateAlternateMenuActions(); - } - } - } - } -} -#endif +#if UNITY_EDITOR && UNITY_2017_2_OR_NEWER +using UnityEditor.Experimental.EditorVR.Modules; + +namespace UnityEditor.Experimental.EditorVR.Core +{ + partial class EditorVR + { + class ActionsModuleConnector : Nested, IInterfaceConnector + { + public void ConnectInterface(object target, object userData = null) + { + var actionsModule = evr.GetModule(); + if (actionsModule) + { + var menuActions = actionsModule.menuActions; + + var toolActions = target as IActions; + if (toolActions != null) + { + // Delay connecting actions to allow tool / module to initialize first + EditorApplication.delayCall += () => + { + var actions = toolActions.actions; + if (actions != null) + { + foreach (var action in actions) + { + var actionMenuData = new ActionMenuData() + { + name = action.GetType().Name, + sectionName = ActionMenuItemAttribute.DefaultActionSectionName, + priority = int.MaxValue, + action = action, + }; + menuActions.Add(actionMenuData); + } + actionsModule.UpdateAlternateMenuActions(); + } + }; + } + + var actionsMenu = target as IActionsMenu; + if (actionsMenu != null) + { + actionsMenu.menuActions = menuActions; + actionsModule.AddActionsMenu(actionsMenu); + } + } + } + + public void DisconnectInterface(object target, object userData = null) + { + var toolActions = target as IActions; + if (toolActions != null) + { + var evrActionsModule = evr.GetModule(); + + evrActionsModule.RemoveActions(toolActions.actions); + evrActionsModule.UpdateAlternateMenuActions(); + } + } + } + } +} +#endif diff --git a/Scripts/Interfaces/Entity/IAlternateMenu.cs b/Scripts/Interfaces/Entity/IAlternateMenu.cs index 329f94d1d..1580f25d9 100644 --- a/Scripts/Interfaces/Entity/IAlternateMenu.cs +++ b/Scripts/Interfaces/Entity/IAlternateMenu.cs @@ -1,18 +1,14 @@ -#if UNITY_EDITOR -using System; -using UnityEngine; - -namespace UnityEditor.Experimental.EditorVR -{ - /// - /// An alternate menu that shows on device proxies - /// - public interface IAlternateMenu : IMenu, IUsesMenuActions, IUsesRayOrigin - { - /// - /// Delegate called when any item was selected in the alternate menu - /// - event Action itemWasSelected; - } -} -#endif +#if UNITY_EDITOR +using System; +using UnityEngine; + +namespace UnityEditor.Experimental.EditorVR +{ + /// + /// An alternate menu that shows on device proxies + /// + public interface IAlternateMenu : IMenu, IUsesRayOrigin + { + } +} +#endif diff --git a/Scripts/Interfaces/Entity/IMainMenu.cs b/Scripts/Interfaces/Entity/IMainMenu.cs index f0f540d3b..7e93d6996 100644 --- a/Scripts/Interfaces/Entity/IMainMenu.cs +++ b/Scripts/Interfaces/Entity/IMainMenu.cs @@ -1,68 +1,68 @@ -#if UNITY_EDITOR -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor.Experimental.EditorVR -{ - /// - /// The main menu that can be shown on device proxies - /// - public interface IMainMenu : IMenu, IUsesMenuActions, ISelectTool, IPreviewInToolsMenuButton - { - /// - /// The menu tools that will populate the menu - /// - List menuTools { set; } - - /// - /// The workspaces that are selectable from the menu - /// - List menuWorkspaces { set; } - - /// - /// The types which provide a settings menu - /// - Dictionary, ISettingsMenuProvider> settingsMenuProviders { set; } - - /// - /// The types which provide a settings menu item - /// - Dictionary, ISettingsMenuItemProvider> settingsMenuItemProviders { set; } - - /// - /// The ray origin that spawned the menu and will be used for node-specific operations (e.g. selecting a tool) - /// - Transform targetRayOrigin { set; } - - /// - /// Does this menu have focus? - /// - bool focus { get; } - - /// - /// Add a settings menu to this menu - /// - /// The object providing the settings menu - void AddSettingsMenu(ISettingsMenuProvider provider); - - /// - /// Remove a settings menu from this menu - /// - /// The object which provided the settings menu - void RemoveSettingsMenu(ISettingsMenuProvider provider); - - /// - /// Add a settings menu item to this menu - /// - /// The object providing the settings menu item - void AddSettingsMenuItem(ISettingsMenuItemProvider provider); - - /// - /// Remove a settings menu item from this menu - /// - /// The object which provided the settings menu item - void RemoveSettingsMenuItem(ISettingsMenuItemProvider provider); - } -} -#endif +#if UNITY_EDITOR +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityEditor.Experimental.EditorVR +{ + /// + /// The main menu that can be shown on device proxies + /// + public interface IMainMenu : IMenu, IActionsMenu, ISelectTool, IPreviewInToolsMenuButton + { + /// + /// The menu tools that will populate the menu + /// + List menuTools { set; } + + /// + /// The workspaces that are selectable from the menu + /// + List menuWorkspaces { set; } + + /// + /// The types which provide a settings menu + /// + Dictionary, ISettingsMenuProvider> settingsMenuProviders { set; } + + /// + /// The types which provide a settings menu item + /// + Dictionary, ISettingsMenuItemProvider> settingsMenuItemProviders { set; } + + /// + /// The ray origin that spawned the menu and will be used for node-specific operations (e.g. selecting a tool) + /// + Transform targetRayOrigin { set; } + + /// + /// Does this menu have focus? + /// + bool focus { get; } + + /// + /// Add a settings menu to this menu + /// + /// The object providing the settings menu + void AddSettingsMenu(ISettingsMenuProvider provider); + + /// + /// Remove a settings menu from this menu + /// + /// The object which provided the settings menu + void RemoveSettingsMenu(ISettingsMenuProvider provider); + + /// + /// Add a settings menu item to this menu + /// + /// The object providing the settings menu item + void AddSettingsMenuItem(ISettingsMenuItemProvider provider); + + /// + /// Remove a settings menu item from this menu + /// + /// The object which provided the settings menu item + void RemoveSettingsMenuItem(ISettingsMenuItemProvider provider); + } +} +#endif diff --git a/Scripts/Interfaces/Entity/IMenu.cs b/Scripts/Interfaces/Entity/IMenu.cs index a466e13c6..a43eaa7a0 100644 --- a/Scripts/Interfaces/Entity/IMenu.cs +++ b/Scripts/Interfaces/Entity/IMenu.cs @@ -1,33 +1,35 @@ -#if UNITY_EDITOR -using UnityEditor.Experimental.EditorVR.Menus; -using UnityEngine; - -namespace UnityEditor.Experimental.EditorVR -{ - /// - /// Declares a class as a system-level menu - /// - public interface IMenu - { - /// - /// Visibility state of this menu - /// - MenuHideFlags menuHideFlags { get; set; } - - /// - /// GameObject that this component is attached to - /// - GameObject gameObject { get; } - - /// - /// Root GameObject for visible menu content - /// - GameObject menuContent { get; } - - /// - /// The local bounds of this menu - /// - Bounds localBounds { get; } - } -} -#endif +#if UNITY_EDITOR +using UnityEditor.Experimental.EditorVR.Menus; +using UnityEngine; + +namespace UnityEditor.Experimental.EditorVR +{ + /// + /// Declares a class as a system-level menu + /// + public interface IMenu + { + /// + /// Visibility state of this menu + /// + MenuHideFlags menuHideFlags { get; set; } + + /// + /// GameObject that this component is attached to + /// + GameObject gameObject { get; } + + /// + /// Root GameObject for visible menu content + /// + GameObject menuContent { get; } + + /// + /// The local bounds of this menu + /// + Bounds localBounds { get; } + + int priority { get; } + } +} +#endif diff --git a/Scripts/Interfaces/FunctionalityInjection/IUsesMenuActions.cs b/Scripts/Interfaces/FunctionalityInjection/IActionsMenu.cs similarity index 57% rename from Scripts/Interfaces/FunctionalityInjection/IUsesMenuActions.cs rename to Scripts/Interfaces/FunctionalityInjection/IActionsMenu.cs index 4a73733b0..74ccb196a 100644 --- a/Scripts/Interfaces/FunctionalityInjection/IUsesMenuActions.cs +++ b/Scripts/Interfaces/FunctionalityInjection/IActionsMenu.cs @@ -1,17 +1,24 @@ -#if UNITY_EDITOR -using System.Collections.Generic; - -namespace UnityEditor.Experimental.EditorVR -{ - /// - /// Decorates a class that wants to receive menu actions - /// - public interface IUsesMenuActions - { - /// - /// Collection of actions that can be performed - /// - List menuActions { set; } - } -} -#endif +#if UNITY_EDITOR +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityEditor.Experimental.EditorVR +{ + /// + /// Decorates a class that wants to receive menu actions + /// + public interface IActionsMenu : IMenu + { + /// + /// Collection of actions that can be performed + /// + List menuActions { set; } + + /// + /// Delegate called when any item was selected in the alternate menu + /// + event Action itemWasSelected; + } +} +#endif diff --git a/Scripts/Interfaces/FunctionalityInjection/IUsesMenuActions.cs.meta b/Scripts/Interfaces/FunctionalityInjection/IActionsMenu.cs.meta similarity index 100% rename from Scripts/Interfaces/FunctionalityInjection/IUsesMenuActions.cs.meta rename to Scripts/Interfaces/FunctionalityInjection/IActionsMenu.cs.meta diff --git a/Scripts/Interfaces/FunctionalityInjection/ICustomAlternateMenu.cs b/Scripts/Interfaces/FunctionalityInjection/ICustomAlternateMenu.cs deleted file mode 100644 index c73562a73..000000000 --- a/Scripts/Interfaces/FunctionalityInjection/ICustomAlternateMenu.cs +++ /dev/null @@ -1,10 +0,0 @@ -#if UNITY_EDITOR - -namespace UnityEditor.Experimental.EditorVR -{ - public interface ICustomAlternateMenu : IMenu - { - int menuPriority { get; } - } -} -#endif diff --git a/Scripts/Interfaces/FunctionalityInjection/ICustomAlternateMenu.cs.meta b/Scripts/Interfaces/FunctionalityInjection/ICustomAlternateMenu.cs.meta deleted file mode 100644 index 1f2b1479c..000000000 --- a/Scripts/Interfaces/FunctionalityInjection/ICustomAlternateMenu.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: d51c00377380a6e4e8861d1bdee23cd9 -timeCreated: 1512422665 -licenseType: Pro -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Scripts/Interfaces/FunctionalityInjection/IInstantiateMenuUI.cs b/Scripts/Interfaces/FunctionalityInjection/IInstantiateMenuUI.cs index da1edb7f0..204d450de 100644 --- a/Scripts/Interfaces/FunctionalityInjection/IInstantiateMenuUI.cs +++ b/Scripts/Interfaces/FunctionalityInjection/IInstantiateMenuUI.cs @@ -6,7 +6,8 @@ namespace UnityEditor.Experimental.EditorVR { /// /// Provides custom menu instantiation - /// public interface IInstantiateMenuUI + /// + public interface IInstantiateMenuUI { } diff --git a/Scripts/Modules/ActionsModule.cs b/Scripts/Modules/ActionsModule.cs index 6eff8c245..c0c39fa69 100644 --- a/Scripts/Modules/ActionsModule.cs +++ b/Scripts/Modules/ActionsModule.cs @@ -1,63 +1,76 @@ -#if UNITY_EDITOR -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.Experimental.EditorVR.Utilities; -using UnityEngine; - -namespace UnityEditor.Experimental.EditorVR.Modules -{ - sealed class ActionsModule : MonoBehaviour, IConnectInterfaces - { - public List menuActions { get { return m_MenuActions; } } - - List m_MenuActions = new List(); - List m_Actions; - - public void RemoveActions(List actions) - { - m_MenuActions.Clear(); - m_MenuActions.AddRange(m_MenuActions.Where(a => !actions.Contains(a.action))); - } - - void Start() - { - SpawnActions(); - } - - void SpawnActions() - { - IEnumerable actionTypes = ObjectUtils.GetImplementationsOfInterface(typeof(IAction)); - m_Actions = new List(); - foreach (Type actionType in actionTypes) - { - // Don't treat vanilla actions or tool actions as first class actions - if (actionType.IsNested || !typeof(MonoBehaviour).IsAssignableFrom(actionType)) - continue; - - var action = ObjectUtils.AddComponent(actionType, gameObject) as IAction; - var attribute = (ActionMenuItemAttribute)actionType.GetCustomAttributes(typeof(ActionMenuItemAttribute), false).FirstOrDefault(); - - this.ConnectInterfaces(action); - - if (attribute != null) - { - var actionMenuData = new ActionMenuData() - { - name = attribute.name, - sectionName = attribute.sectionName, - priority = attribute.priority, - action = action, - }; - - m_MenuActions.Add(actionMenuData); - } - - m_Actions.Add(action); - } - - m_MenuActions.Sort((x, y) => y.priority.CompareTo(x.priority)); - } - } -} -#endif +#if UNITY_EDITOR +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor.Experimental.EditorVR.Utilities; +using UnityEngine; + +namespace UnityEditor.Experimental.EditorVR.Modules +{ + sealed class ActionsModule : MonoBehaviour, IConnectInterfaces + { + public List menuActions { get { return m_MenuActions; } } + + List m_MenuActions = new List(); + readonly List m_Actions = new List(); + readonly List m_ActionsMenus = new List(); + + public void RemoveActions(List actions) + { + m_MenuActions.Clear(); + m_MenuActions.AddRange(m_MenuActions.Where(a => !actions.Contains(a.action))); + } + + void Start() + { + SpawnActions(); + } + + void SpawnActions() + { + IEnumerable actionTypes = ObjectUtils.GetImplementationsOfInterface(typeof(IAction)); + foreach (Type actionType in actionTypes) + { + // Don't treat vanilla actions or tool actions as first class actions + if (actionType.IsNested || !typeof(MonoBehaviour).IsAssignableFrom(actionType)) + continue; + + var action = ObjectUtils.AddComponent(actionType, gameObject) as IAction; + var attribute = (ActionMenuItemAttribute)actionType.GetCustomAttributes(typeof(ActionMenuItemAttribute), false).FirstOrDefault(); + + this.ConnectInterfaces(action); + + if (attribute != null) + { + var actionMenuData = new ActionMenuData() + { + name = attribute.name, + sectionName = attribute.sectionName, + priority = attribute.priority, + action = action, + }; + + m_MenuActions.Add(actionMenuData); + } + + m_Actions.Add(action); + } + + m_MenuActions.Sort((x, y) => y.priority.CompareTo(x.priority)); + } + + public void AddActionsMenu(IActionsMenu actionsMenu) + { + m_ActionsMenus.Add(actionsMenu); + } + + internal void UpdateAlternateMenuActions() + { + foreach (var actionsMenu in m_ActionsMenus) + { + actionsMenu.menuActions = m_MenuActions; + } + } + } +} +#endif diff --git a/Tools/AnnotationTool/AnnotationTool.cs b/Tools/AnnotationTool/AnnotationTool.cs index e2749283d..98721ceb8 100644 --- a/Tools/AnnotationTool/AnnotationTool.cs +++ b/Tools/AnnotationTool/AnnotationTool.cs @@ -1,894 +1,897 @@ -#if UNITY_EDITOR -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.Experimental.EditorVR.Core; -using UnityEditor.Experimental.EditorVR.Extensions; -using UnityEditor.Experimental.EditorVR.Menus; -using UnityEditor.Experimental.EditorVR.Proxies; -using UnityEditor.Experimental.EditorVR.UI; -using UnityEditor.Experimental.EditorVR.Utilities; -using UnityEngine; -using UnityEngine.InputNew; -using UnityEngine.UI; - -namespace UnityEditor.Experimental.EditorVR.Tools -{ - [MainMenuItem("Annotation", "Create", "Draw in 3D")] - public class AnnotationTool : MonoBehaviour, ITool, ICustomActionMap, IUsesRayOrigin, IRayVisibilitySettings, - IUsesRayOrigins, IInstantiateUI, IUsesMenuOrigins, IUsesCustomMenuOrigins, IUsesViewerScale, IUsesSpatialHash, - IIsHoveringOverUI, IMultiDeviceTool, IUsesDeviceType, ISettingsMenuItemProvider, ISerializePreferences, ILinkedObject, - IUsesNode, IRequestFeedback, ICustomAlternateMenu - { - [Serializable] - class Preferences - { - [SerializeField] - bool m_MeshGroupingMode; - - [SerializeField] - Color m_AnnotationColor = Color.white; - - [SerializeField] - float m_BrushSize = MinBrushSize; - - public bool meshGroupingMode - { - get { return m_MeshGroupingMode; } - set { m_MeshGroupingMode = value; } - } - - public Color annotationColor - { - get { return m_AnnotationColor; } - set { m_AnnotationColor = value; } - } - - public float brushSize - { - get { return m_BrushSize; } - set { m_BrushSize = value; } - } - } - - const float k_MinDistance = 0.003f; - const int k_InitialListSize = 1024; // Pre-allocate lists to avoid GC - - const string k_GroupFormatString = "Group {0}"; - const string k_AnnotationFormatStrig = "Annotation {0}"; - const string k_MainHolderName = "Annotations"; - const string k_MeshName = "Annotation"; - - public const float TipDistance = 0.05f; - public const float MinBrushSize = 0.0025f; - public const float MaxBrushSize = 0.05f; - - public delegate void AnnotationUpdatedCallback(MeshFilter meshFilter); - public static AnnotationUpdatedCallback AnnotationUpdated; - public delegate void AnnotationFinishedCallback(MeshFilter meshFilter); - public static AnnotationFinishedCallback AnnotationFinished; - - [SerializeField] - ActionMap m_ActionMap; - - [SerializeField] - Material m_AnnotationMaterial; - - [SerializeField] - GameObject m_BrushSizePrefab; - - [SerializeField] - GameObject m_ColorPickerActivatorPrefab; - - [SerializeField] - GameObject m_SettingsMenuItemPrefab; - - Action m_BrushSizeChanged; - - Preferences m_Preferences; - - readonly List m_Points = new List(k_InitialListSize); - readonly List m_UpVectors = new List(k_InitialListSize); - readonly List m_Widths = new List(k_InitialListSize); - readonly List m_Groups = new List(); - float m_Length; - - MeshFilter m_CurrentMeshFilter; - Mesh m_CurrentMesh; - Matrix4x4 m_WorldToLocalMesh; - - ColorPickerUI m_ColorPicker; - BrushSizeUI m_BrushSizeUI; - - Transform m_AnnotationRoot; - Transform m_AnnotationHolder; - - AnnotationPointer m_AnnotationPointer; - Vector3 m_OriginalAnnotationPointerLocalScale; - Coroutine m_AnnotationPointerVisibilityCoroutine; - bool m_WasOverUI; - bool m_WasDoingUndoRedo; - - GameObject m_ColorPickerActivator; - - Toggle m_TransformToggle; - Toggle m_MeshToggle; - bool m_BlockValueChangedListener; - MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; - - public bool primary { private get; set; } - public Transform rayOrigin { get; set; } - public List otherRayOrigins { private get; set; } - - public Transform menuOrigin { private get; set; } - public Transform alternateMenuOrigin { private get; set; } - - public ActionMap actionMap { get { return m_ActionMap; } } - public bool ignoreLocking { get { return false; } } - - public List linkedObjects { private get; set; } - public Node node { private get; set; } - - public GameObject settingsMenuItemPrefab { get { return m_SettingsMenuItemPrefab; } } - - public int menuPriority { get { return 2; } } - - public MenuHideFlags menuHideFlags - { - get { return m_MenuHideFlags; } - set - { - if (m_MenuHideFlags != value) - { - m_MenuHideFlags = value; - var visible = m_MenuHideFlags == 0; - - if (m_BrushSizeUI) - m_BrushSizeUI.gameObject.SetActive(visible); - } - } - } - - public GameObject menuContent { get { return gameObject; } } - public Bounds localBounds { get; private set; } - - public GameObject settingsMenuItemInstance - { - set - { - if (value == null) - { - m_TransformToggle = null; - m_MeshToggle = null; - return; - } - - var defaultToggleGroup = value.GetComponentInChildren(); - foreach (var toggle in value.GetComponentsInChildren()) - { - if (toggle == defaultToggleGroup.defaultToggle) - { - m_TransformToggle = toggle; - toggle.onValueChanged.AddListener(isOn => - { - if (m_BlockValueChangedListener) - return; - - // m_Preferences on all instances refer to a single preferences object - m_Preferences.meshGroupingMode = !isOn; - foreach (var linkedObject in linkedObjects) - { - var annotationTool = (AnnotationTool)linkedObject; - if (annotationTool != this) - { - annotationTool.m_BlockValueChangedListener = true; - - //linkedObject.m_ToggleGroup.NotifyToggleOn(isOn ? m_FlyToggle : m_BlinkToggle); - // HACK: Toggle Group claims these toggles are not a part of the group - annotationTool.m_TransformToggle.isOn = isOn; - annotationTool.m_MeshToggle.isOn = !isOn; - annotationTool.m_BlockValueChangedListener = false; - } - } - }); - } - else - { - m_MeshToggle = toggle; - } - } - } - } - - void OnDestroy() - { - if (m_Preferences != null && m_Preferences.meshGroupingMode) - CombineGroups(); - - CleanUpNames(); - - if (rayOrigin) - this.RemoveRayVisibilitySettings(rayOrigin, this); - - if (m_ColorPicker) - ObjectUtils.Destroy(m_ColorPicker.gameObject); - - if (m_BrushSizeUI) - ObjectUtils.Destroy(m_BrushSizeUI.gameObject); - - if (m_ColorPickerActivator) - ObjectUtils.Destroy(m_ColorPickerActivator); - - if (m_AnnotationPointer) - ObjectUtils.Destroy(m_AnnotationPointer.gameObject); - - this.ClearFeedbackRequests(); - } - - void CleanUpNames() - { - if (m_AnnotationRoot == null) - return; - - var groupCount = 0; - var annotationCount = 0; - foreach (Transform child in m_AnnotationRoot) - { - if (child.childCount > 0) - child.name = string.Format(k_GroupFormatString, groupCount++); - else - child.name = string.Format(k_AnnotationFormatStrig, annotationCount++); - } - } - - void Start() - { - // Clear selection so we can't manipulate things - Selection.activeGameObject = null; - - SetupPreferences(); - - if (primary) - { - this.AddRayVisibilitySettings(rayOrigin, this, false, false); - SetupBrushUI(); - HandleBrushSize(m_Preferences.brushSize); - - m_ColorPickerActivator = this.InstantiateUI(m_ColorPickerActivatorPrefab); - var otherRayOrigin = otherRayOrigins.First(); - var otherAltMenu = this.GetCustomAlternateMenuOrigin(otherRayOrigin); - - const float UIOffset = 0.1f; - var colorPickerActivatorTransform = m_ColorPickerActivator.transform; - colorPickerActivatorTransform.SetParent(otherAltMenu); - colorPickerActivatorTransform.localRotation = Quaternion.identity; - colorPickerActivatorTransform.localPosition = (node == Node.LeftHand ? Vector3.left : Vector3.right) * UIOffset; - colorPickerActivatorTransform.localScale = Vector3.one; - - var activator = m_ColorPickerActivator.GetComponentInChildren(); - - m_ColorPicker = activator.GetComponentInChildren(true); - m_ColorPicker.onHideCalled = HideColorPicker; - m_ColorPicker.toolRayOrigin = rayOrigin; - m_ColorPicker.onColorPicked = OnColorPickerValueChanged; - OnColorPickerValueChanged(m_Preferences.annotationColor); - - activator.node = node; - activator.rayOrigin = otherRayOrigin; - activator.showColorPicker = ShowColorPicker; - activator.hideColorPicker = HideColorPicker; - - var controls = new BindingDictionary(); - InputUtils.GetBindingDictionaryFromActionMap(m_ActionMap, controls); - - foreach (var control in controls) - { - var tooltipText = control.Key; - var suppressExisting = control.Key == "Vertical" || control.Key == "StickButton"; - if (suppressExisting) - tooltipText = null; - - foreach (var id in control.Value) - { - this.AddFeedbackRequest(new ProxyFeedbackRequest - { - node = node, - control = id, - priority = 1, - tooltipText = tooltipText, - suppressExisting = suppressExisting - }); - } - } - } - } - - void SetupPreferences() - { - if (this.IsSharedUpdater(this)) - { - // Share one preferences object across all instances - foreach (var linkedObject in linkedObjects) - { - ((AnnotationTool)linkedObject).m_Preferences = m_Preferences; - } - - if (m_Preferences != null) - { - //Setting toggles on this tool's menu will set them on other tool menus - m_MeshToggle.isOn = m_Preferences.meshGroupingMode; - m_TransformToggle.isOn = !m_Preferences.meshGroupingMode; - } - } - - if (m_Preferences == null) - m_Preferences = new Preferences(); - } - - void SetupBrushUI() - { - m_AnnotationPointer = ObjectUtils.CreateGameObjectWithComponent(rayOrigin, false); - m_OriginalAnnotationPointerLocalScale = m_AnnotationPointer.transform.localScale; - var brushSize = m_Preferences.brushSize; - m_AnnotationPointer.Resize(brushSize); - - var brushSizeUi = this.InstantiateUI(m_BrushSizePrefab); - m_BrushSizeUI = brushSizeUi.GetComponent(); - - var transform = brushSizeUi.transform; - localBounds = ObjectUtils.GetBounds(transform); - var scale = transform.localScale; - transform.SetParent(alternateMenuOrigin, false); - transform.localPosition = Vector3.zero; - transform.localRotation = Quaternion.Euler(-90, 0, 0); - transform.localScale = scale; - - m_BrushSizeUI.onValueChanged = value => - { - var sliderValue = Mathf.Lerp(MinBrushSize, MaxBrushSize, value); - m_Preferences.brushSize = sliderValue; - m_AnnotationPointer.Resize(sliderValue); - }; - m_BrushSizeChanged = m_BrushSizeUI.ChangeSliderValue; - } - - void ShowColorPicker(Transform otherRayOrigin) - { - if (!m_ColorPicker.enabled) - m_ColorPicker.Show(); - - m_AnnotationPointer.gameObject.SetActive(false); - } - - void HideColorPicker() - { - if (m_ColorPicker && m_ColorPicker.enabled) - { - m_ColorPicker.Hide(); - m_AnnotationPointer.gameObject.SetActive(true); - } - } - - void OnColorPickerValueChanged(Color color) - { - m_Preferences.annotationColor = color; - - const float annotationPointerAlpha = 0.75f; - color.a = annotationPointerAlpha; - m_AnnotationPointer.SetColor(color); - - m_BrushSizeUI.OnBrushColorChanged(color); - } - - void HandleBrushSize(float value) - { - if (m_AnnotationPointer != null) - { - var brushSize = m_Preferences.brushSize; - if (this.GetDeviceType() == DeviceType.Vive) // For vive controllers, use 1:1 touchpad setting. - { - brushSize = Mathf.Lerp(MinBrushSize, MaxBrushSize, (value + 1) / 2f); - } - else // For touch and hydra, let the thumbstick gradually modify the width. - { - brushSize += value * Time.unscaledDeltaTime * .1f; - brushSize = Mathf.Clamp(brushSize, MinBrushSize, MaxBrushSize); - } - - if (m_BrushSizeUI && m_BrushSizeChanged != null) - { - var ratio = Mathf.InverseLerp(MinBrushSize, MaxBrushSize, brushSize); - m_BrushSizeChanged(ratio); - } - - m_AnnotationPointer.Resize(brushSize); - m_Preferences.brushSize = brushSize; - } - } - - void SetupAnnotation() - { - SetupHolder(); - - m_Points.Clear(); - m_UpVectors.Clear(); - m_Widths.Clear(); - m_Length = 0; - - var go = new GameObject(string.Format(k_AnnotationFormatStrig, m_AnnotationHolder.childCount)); - Undo.RegisterCreatedObjectUndo(go, "Annotation"); - - var goTrans = go.transform; - goTrans.SetParent(m_AnnotationHolder); - goTrans.position = rayOrigin.position; - - m_CurrentMeshFilter = go.AddComponent(); - var mRenderer = go.AddComponent(); - - var matToUse = Instantiate(m_AnnotationMaterial); - matToUse.SetColor("_EmissionColor", m_Preferences.annotationColor); - mRenderer.sharedMaterial = matToUse; - - m_WorldToLocalMesh = goTrans.worldToLocalMatrix; - - m_CurrentMesh = new Mesh(); - m_CurrentMesh.name = k_MeshName; - } - - void SetupHolder() - { - var mainHolder = GameObject.Find(k_MainHolderName) ?? new GameObject(k_MainHolderName); - m_AnnotationRoot = mainHolder.transform; - - var newSession = GetNewSessionHolder(); - if (!newSession) - { - newSession = new GameObject(string.Format(k_GroupFormatString, m_AnnotationRoot.childCount)); - Undo.RegisterCreatedObjectUndo(newSession, "Annotation"); - newSession.transform.position = GetPointerPosition(); - m_Groups.Add(newSession); - } - - m_AnnotationHolder = newSession.transform; - m_AnnotationHolder.SetParent(m_AnnotationRoot); - } - - GameObject GetNewSessionHolder() - { - const float groupingDistance = 0.3f; - var position = rayOrigin.position; - for (var i = 0; i < m_Groups.Count; i++) - { - var child = m_Groups[i]; - child.name = "Group " + i; - - var renderers = child.GetComponentsInChildren(); - if (renderers.Length > 0) - { - var bound = renderers[0].bounds; - for (var r = 1; r < renderers.Length; r++) - { - bound.Encapsulate(renderers[r].bounds); - } - - if (bound.Contains(position) || bound.SqrDistance(position) < groupingDistance) - return child.gameObject; - } - } - - return null; - } - - void UpdateAnnotation() - { - var upVector = rayOrigin.up; - var viewerScale = this.GetViewerScale(); - var worldPoint = GetPointerPosition(); - var localPoint = m_WorldToLocalMesh.MultiplyPoint3x4(worldPoint); - - if (m_Points.Count > 0) - { - var lastPoint = m_Points.Last(); - localPoint = Vector3.Lerp(lastPoint, localPoint, 0.5f); - var distance = (localPoint - lastPoint).magnitude; - if (distance < k_MinDistance * viewerScale) - return; - - m_Length += distance; - } - - var brushSize = m_Preferences.brushSize * viewerScale; - InterpolatePointsIfNeeded(localPoint, upVector, brushSize); - - m_Points.Add(localPoint); - m_UpVectors.Add(upVector); - m_Widths.Add(brushSize); - - PointsToMesh(); - - if (AnnotationUpdated != null) - { - AnnotationUpdated(m_CurrentMeshFilter); - } - } - - void InterpolatePointsIfNeeded(Vector3 localPoint, Vector3 upVector, float brushSize) - { - if (m_Points.Count > 1) - { - var lastPoint = m_Points.Last(); - var distance = Vector3.Distance(lastPoint, localPoint); - - if (distance > brushSize * .5f) - { - var halfPoint = (lastPoint + localPoint) / 2f; - m_Points.Add(halfPoint); - - var halfUp = (m_UpVectors.Last() + upVector) / 2f; - m_UpVectors.Add(halfUp); - - var halfRadius = (m_Widths.Last() + brushSize) / 2f; - m_Widths.Add(halfRadius); - } - } - } - - void PointsToMesh() - { - if (m_Points.Count < 4) - return; - - if (m_CurrentMesh == null) - m_CurrentMesh = new Mesh(); - - var newVertices = new List(); - var newTriangles = new List(); - var newUvs = new List(); - - LineToPlane(newVertices); - - TriangulatePlane(newTriangles, newVertices.Count); - CalculateUvs(newUvs, newVertices); - - m_CurrentMesh.Clear(); - - m_CurrentMesh.vertices = newVertices.ToArray(); - m_CurrentMesh.triangles = newTriangles.ToArray(); - m_CurrentMesh.uv = newUvs.ToArray(); - - m_CurrentMesh.UploadMeshData(false); - - m_CurrentMeshFilter.sharedMesh = m_CurrentMesh; - } - - void LineToPlane(List newVertices) - { - var distance = 0f; - var lastPoint = m_Points[0]; - for (var i = 1; i < m_Points.Count; i++) - { - var point = m_Points[i]; - var segment = point - lastPoint; - - var width = m_Widths[i]; - - width *= Math.Min(Mathf.Sqrt(distance / width), 1); - var endDistance = m_Length - distance; - width *= Math.Min(Mathf.Sqrt(endDistance / width), 1); - - var upVector = m_UpVectors[i]; - var top = point - upVector * width; - var bottom = point + upVector * width; - - newVertices.Add(top); - newVertices.Add(bottom); - - distance += segment.magnitude; - lastPoint = point; - } - } - - static void TriangulatePlane(List newTriangles, int vertexCount) - { - for (var i = 3; i < vertexCount; i += 2) - { - var upperLeft = i - 1; - var upperRight = i; - var lowerLeft = i - 3; - var lowerRight = i - 2; - - var triangles = VerticesToPolygon(upperLeft, upperRight, lowerLeft, lowerRight); - newTriangles.AddRange(triangles); - } - } - - static void CalculateUvs(List newUvs, List newVertices) - { - for (var i = 0; i < newVertices.Count; i += 2) - { - newUvs.Add(new Vector2(0, i * 0.5f)); - newUvs.Add(new Vector2(1, i * 0.5f)); - } - } - - void FinalizeMesh() - { - CenterMesh(); - - m_CurrentMesh.RecalculateBounds(); - m_CurrentMesh.RecalculateNormals(); - - m_CurrentMesh.UploadMeshData(false); - - CenterHolder(); - - var go = m_CurrentMeshFilter.gameObject; - - this.AddToSpatialHash(go); - - Undo.IncrementCurrentGroup(); - - if (AnnotationFinished != null) - { - AnnotationFinished(m_CurrentMeshFilter); - } - } - - void CenterMesh() - { - if (m_CurrentMesh == null || m_CurrentMesh.vertexCount == 0) - return; - - var center = Vector3.zero; - - var vertices = m_CurrentMesh.vertices; - - for (var i = 0; i < m_CurrentMesh.vertexCount; i++) - { - center += vertices[i]; - } - - center /= m_CurrentMesh.vertexCount; - - for (var i = 0; i < m_CurrentMesh.vertexCount; i++) - { - vertices[i] -= center; - } - - m_CurrentMesh.vertices = vertices; - m_CurrentMeshFilter.transform.localPosition += center; - } - - void CenterHolder() - { - if (m_AnnotationHolder == null || m_AnnotationHolder.childCount == 0) - return; - - var childWorldPositions = new List(); - var center = Vector3.zero; - - for (var i = 0; i < m_AnnotationHolder.childCount; i++) - { - var worldPos = m_AnnotationHolder.GetChild(i).position; - childWorldPositions.Add(worldPos); - center += worldPos; - } - - center /= m_AnnotationHolder.childCount; - - m_AnnotationHolder.localPosition += center; - for (var i = 0; i < m_AnnotationHolder.childCount; i++) - { - m_AnnotationHolder.GetChild(i).position = childWorldPositions[i]; - } - } - - public static int[] VerticesToPolygon(int upperLeft, int upperRight, int lowerLeft, int lowerRight, bool doubleSided = true) - { - var triangleCount = doubleSided ? 12 : 6; - var triangles = new int[triangleCount]; - var index = 0; - - triangles[index++] = upperLeft; - triangles[index++] = lowerRight; - triangles[index++] = lowerLeft; - - triangles[index++] = lowerRight; - triangles[index++] = upperLeft; - triangles[index++] = upperRight; - - if (doubleSided) - { - triangles[index++] = lowerLeft; - triangles[index++] = lowerRight; - triangles[index++] = upperLeft; - - triangles[index++] = upperRight; - triangles[index++] = upperLeft; - triangles[index] = lowerRight; - } - - return triangles; - } - - public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl) - { - var annotationInput = (AnnotationInput)input; - - var draw = annotationInput.draw; - var isHeld = draw.isHeld; - if (primary) - { - if (!Mathf.Approximately(annotationInput.changeBrushSize.value, 0)) - { - HandleBrushSize(annotationInput.changeBrushSize.value); - consumeControl(annotationInput.changeBrushSize); - consumeControl(annotationInput.vertical); - } - - if (draw.wasJustPressed) - { - SetupAnnotation(); - consumeControl(draw); - } - - if (isHeld) - { - UpdateAnnotation(); - consumeControl(draw); - } - - if (draw.wasJustReleased) - { - FinalizeMesh(); - consumeControl(draw); - } - } - else - { - // Secondary hand uses brush size input to do undo/redo - var value = annotationInput.changeBrushSize.value; - if (this.GetDeviceType() == DeviceType.Vive) - { - if (annotationInput.stickButton.wasJustPressed) - { - if (value > 0) - Undo.PerformRedo(); - else - Undo.PerformUndo(); - } - } - else - { - var doUndoRedo = Math.Abs(value) > 0.5f; - if (doUndoRedo != m_WasDoingUndoRedo) - { - m_WasDoingUndoRedo = doUndoRedo; - if (doUndoRedo) - { - if (value > 0) - Undo.PerformRedo(); - else - Undo.PerformUndo(); - } - } - } - } - - if (isHeld) - return; - - var isOverUI = this.IsHoveringOverUI(rayOrigin); - if (isOverUI != m_WasOverUI) - { - m_WasOverUI = isOverUI; - this.RestartCoroutine(ref m_AnnotationPointerVisibilityCoroutine, SetAnnotationPointerVisibility(!isOverUI)); - if (isOverUI) - this.RemoveRayVisibilitySettings(rayOrigin, this); - else - this.AddRayVisibilitySettings(rayOrigin, this, false, false); - } - } - - IEnumerator SetAnnotationPointerVisibility(bool visible) - { - if (!m_AnnotationPointer) - yield break; - - const float transitionTime = 0.1875f; - var annotationPointerTransform = m_AnnotationPointer.transform; - var startTime = Time.time; - var timeDiff = 0f; - var currentScale = annotationPointerTransform.localScale; - var targetScale = visible ? m_OriginalAnnotationPointerLocalScale : Vector3.zero; - while (timeDiff < transitionTime) - { - annotationPointerTransform.localScale = Vector3.Lerp(currentScale, targetScale, timeDiff / transitionTime); - timeDiff = Time.time - startTime; - yield return null; - } - - annotationPointerTransform.localScale = targetScale; - } - - void CombineGroups() - { - foreach (var group in m_Groups) - { - var meshFilters = group.GetComponentsInChildren(); - var renderers = group.GetComponentsInChildren(); - - if (meshFilters.Length == 0) - { - ObjectUtils.Destroy(group); - continue; - } - - var length = meshFilters.Length; - var combines = new List(length); - var materials = new List(length); - for (var i = 0; i < length; i++) - { - var meshFilter = meshFilters[i]; - var sharedMesh = meshFilter.sharedMesh; - if (sharedMesh && sharedMesh.vertexCount > 0) - { - var combine = new CombineInstance - { - mesh = sharedMesh, - transform = group.transform.worldToLocalMatrix * meshFilter.transform.localToWorldMatrix - }; - - sharedMesh.UploadMeshData(false); - combines.Add(combine); - materials.Add(renderers[i].sharedMaterial); - } - } - - var mesh = new Mesh(); - mesh.CombineMeshes(combines.ToArray(), false, true); - group.AddComponent().sharedMesh = mesh; - - group.AddComponent().sharedMaterials = materials.ToArray(); - - this.AddToSpatialHash(group); - - foreach (var meshFilter in meshFilters) - { - var go = meshFilter.gameObject; - this.RemoveFromSpatialHash(go); - ObjectUtils.Destroy(go); - } - } - } - - Vector3 GetPointerPosition() - { - return rayOrigin.position + rayOrigin.forward * TipDistance * this.GetViewerScale(); - } - - public object OnSerializePreferences() - { - if (this.IsSharedUpdater(this)) - { - // Share one preferences object across all instances - foreach (var linkedObject in linkedObjects) - { - ((AnnotationTool)linkedObject).m_Preferences = m_Preferences; - } - - return m_Preferences; - } - - return null; - } - - public void OnDeserializePreferences(object obj) - { - if (m_Preferences == null) - m_Preferences = (Preferences)obj; - } - } -} -#endif +#if UNITY_EDITOR +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using UnityEditor.Experimental.EditorVR.Core; +using UnityEditor.Experimental.EditorVR.Extensions; +using UnityEditor.Experimental.EditorVR.Menus; +using UnityEditor.Experimental.EditorVR.Proxies; +using UnityEditor.Experimental.EditorVR.UI; +using UnityEditor.Experimental.EditorVR.Utilities; +using UnityEngine; +using UnityEngine.InputNew; +using UnityEngine.UI; + +namespace UnityEditor.Experimental.EditorVR.Tools +{ + [MainMenuItem("Annotation", "Create", "Draw in 3D")] + public class AnnotationTool : MonoBehaviour, ITool, ICustomActionMap, IUsesRayOrigin, IRayVisibilitySettings, + IUsesRayOrigins, IInstantiateUI, IUsesMenuOrigins, IUsesCustomMenuOrigins, IUsesViewerScale, IUsesSpatialHash, + IIsHoveringOverUI, IMultiDeviceTool, IUsesDeviceType, ISettingsMenuItemProvider, ISerializePreferences, ILinkedObject, + IUsesNode, IRequestFeedback, IConnectInterfaces + { + [Serializable] + class Preferences + { + [SerializeField] + bool m_MeshGroupingMode; + + [SerializeField] + Color m_AnnotationColor = Color.white; + + [SerializeField] + float m_BrushSize = MinBrushSize; + + public bool meshGroupingMode + { + get { return m_MeshGroupingMode; } + set { m_MeshGroupingMode = value; } + } + + public Color annotationColor + { + get { return m_AnnotationColor; } + set { m_AnnotationColor = value; } + } + + public float brushSize + { + get { return m_BrushSize; } + set { m_BrushSize = value; } + } + } + + const float k_MinDistance = 0.003f; + const int k_InitialListSize = 1024; // Pre-allocate lists to avoid GC + + const string k_GroupFormatString = "Group {0}"; + const string k_AnnotationFormatStrig = "Annotation {0}"; + const string k_MainHolderName = "Annotations"; + const string k_MeshName = "Annotation"; + + public const float TipDistance = 0.05f; + public const float MinBrushSize = 0.0025f; + public const float MaxBrushSize = 0.05f; + + public delegate void AnnotationUpdatedCallback(MeshFilter meshFilter); + public static AnnotationUpdatedCallback AnnotationUpdated; + public delegate void AnnotationFinishedCallback(MeshFilter meshFilter); + public static AnnotationFinishedCallback AnnotationFinished; + + [SerializeField] + ActionMap m_ActionMap; + + [SerializeField] + Material m_AnnotationMaterial; + + [SerializeField] + GameObject m_BrushSizePrefab; + + [SerializeField] + GameObject m_ColorPickerActivatorPrefab; + + [SerializeField] + GameObject m_SettingsMenuItemPrefab; + + Action m_BrushSizeChanged; + + Preferences m_Preferences; + + readonly List m_Points = new List(k_InitialListSize); + readonly List m_UpVectors = new List(k_InitialListSize); + readonly List m_Widths = new List(k_InitialListSize); + readonly List m_Groups = new List(); + float m_Length; + + MeshFilter m_CurrentMeshFilter; + Mesh m_CurrentMesh; + Matrix4x4 m_WorldToLocalMesh; + + ColorPickerUI m_ColorPicker; + BrushSizeUI m_BrushSizeUI; + + Transform m_AnnotationRoot; + Transform m_AnnotationHolder; + + AnnotationPointer m_AnnotationPointer; + Vector3 m_OriginalAnnotationPointerLocalScale; + Coroutine m_AnnotationPointerVisibilityCoroutine; + bool m_WasOverUI; + bool m_WasDoingUndoRedo; + + GameObject m_ColorPickerActivator; + + Toggle m_TransformToggle; + Toggle m_MeshToggle; + bool m_BlockValueChangedListener; + MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; + + public bool primary { private get; set; } + public Transform rayOrigin { get; set; } + public List otherRayOrigins { private get; set; } + + public Transform menuOrigin { private get; set; } + public Transform alternateMenuOrigin { private get; set; } + + public ActionMap actionMap { get { return m_ActionMap; } } + public bool ignoreLocking { get { return false; } } + + public List linkedObjects { private get; set; } + public Node node { private get; set; } + + public GameObject settingsMenuItemPrefab { get { return m_SettingsMenuItemPrefab; } } + + public int menuPriority { get { return 2; } } + + public MenuHideFlags menuHideFlags + { + get { return m_MenuHideFlags; } + set + { + if (m_MenuHideFlags != value) + { + m_MenuHideFlags = value; + var visible = m_MenuHideFlags == 0; + + if (m_BrushSizeUI) + m_BrushSizeUI.gameObject.SetActive(visible); + } + } + } + + public GameObject menuContent { get { return gameObject; } } + public Bounds localBounds { get; private set; } + + public GameObject settingsMenuItemInstance + { + set + { + if (value == null) + { + m_TransformToggle = null; + m_MeshToggle = null; + return; + } + + var defaultToggleGroup = value.GetComponentInChildren(); + foreach (var toggle in value.GetComponentsInChildren()) + { + if (toggle == defaultToggleGroup.defaultToggle) + { + m_TransformToggle = toggle; + toggle.onValueChanged.AddListener(isOn => + { + if (m_BlockValueChangedListener) + return; + + // m_Preferences on all instances refer to a single preferences object + m_Preferences.meshGroupingMode = !isOn; + foreach (var linkedObject in linkedObjects) + { + var annotationTool = (AnnotationTool)linkedObject; + if (annotationTool != this) + { + annotationTool.m_BlockValueChangedListener = true; + + //linkedObject.m_ToggleGroup.NotifyToggleOn(isOn ? m_FlyToggle : m_BlinkToggle); + // HACK: Toggle Group claims these toggles are not a part of the group + annotationTool.m_TransformToggle.isOn = isOn; + annotationTool.m_MeshToggle.isOn = !isOn; + annotationTool.m_BlockValueChangedListener = false; + } + } + }); + } + else + { + m_MeshToggle = toggle; + } + } + } + } + + void OnDestroy() + { + if (m_Preferences != null && m_Preferences.meshGroupingMode) + CombineGroups(); + + CleanUpNames(); + + if (rayOrigin) + this.RemoveRayVisibilitySettings(rayOrigin, this); + + if (m_ColorPicker) + ObjectUtils.Destroy(m_ColorPicker.gameObject); + + if (m_BrushSizeUI) + { + this.DisconnectInterfaces(m_BrushSizeUI, rayOrigin); + ObjectUtils.Destroy(m_BrushSizeUI.gameObject); + } + + if (m_ColorPickerActivator) + ObjectUtils.Destroy(m_ColorPickerActivator); + + if (m_AnnotationPointer) + ObjectUtils.Destroy(m_AnnotationPointer.gameObject); + + this.ClearFeedbackRequests(); + } + + void CleanUpNames() + { + if (m_AnnotationRoot == null) + return; + + var groupCount = 0; + var annotationCount = 0; + foreach (Transform child in m_AnnotationRoot) + { + if (child.childCount > 0) + child.name = string.Format(k_GroupFormatString, groupCount++); + else + child.name = string.Format(k_AnnotationFormatStrig, annotationCount++); + } + } + + void Start() + { + // Clear selection so we can't manipulate things + Selection.activeGameObject = null; + + SetupPreferences(); + + if (primary) + { + this.AddRayVisibilitySettings(rayOrigin, this, false, false); + SetupBrushUI(); + HandleBrushSize(m_Preferences.brushSize); + + m_ColorPickerActivator = this.InstantiateUI(m_ColorPickerActivatorPrefab); + var otherRayOrigin = otherRayOrigins.First(); + var otherAltMenu = this.GetCustomAlternateMenuOrigin(otherRayOrigin); + + const float UIOffset = 0.1f; + var colorPickerActivatorTransform = m_ColorPickerActivator.transform; + colorPickerActivatorTransform.SetParent(otherAltMenu); + colorPickerActivatorTransform.localRotation = Quaternion.identity; + colorPickerActivatorTransform.localPosition = (node == Node.LeftHand ? Vector3.left : Vector3.right) * UIOffset; + colorPickerActivatorTransform.localScale = Vector3.one; + + var activator = m_ColorPickerActivator.GetComponentInChildren(); + + m_ColorPicker = activator.GetComponentInChildren(true); + m_ColorPicker.onHideCalled = HideColorPicker; + m_ColorPicker.toolRayOrigin = rayOrigin; + m_ColorPicker.onColorPicked = OnColorPickerValueChanged; + OnColorPickerValueChanged(m_Preferences.annotationColor); + + activator.node = node; + activator.rayOrigin = otherRayOrigin; + activator.showColorPicker = ShowColorPicker; + activator.hideColorPicker = HideColorPicker; + + var controls = new BindingDictionary(); + InputUtils.GetBindingDictionaryFromActionMap(m_ActionMap, controls); + + foreach (var control in controls) + { + var tooltipText = control.Key; + var suppressExisting = control.Key == "Vertical" || control.Key == "StickButton"; + if (suppressExisting) + tooltipText = null; + + foreach (var id in control.Value) + { + this.AddFeedbackRequest(new ProxyFeedbackRequest + { + node = node, + control = id, + priority = 1, + tooltipText = tooltipText, + suppressExisting = suppressExisting + }); + } + } + } + } + + void SetupPreferences() + { + if (this.IsSharedUpdater(this)) + { + // Share one preferences object across all instances + foreach (var linkedObject in linkedObjects) + { + ((AnnotationTool)linkedObject).m_Preferences = m_Preferences; + } + + if (m_Preferences != null) + { + //Setting toggles on this tool's menu will set them on other tool menus + m_MeshToggle.isOn = m_Preferences.meshGroupingMode; + m_TransformToggle.isOn = !m_Preferences.meshGroupingMode; + } + } + + if (m_Preferences == null) + m_Preferences = new Preferences(); + } + + void SetupBrushUI() + { + m_AnnotationPointer = ObjectUtils.CreateGameObjectWithComponent(rayOrigin, false); + m_OriginalAnnotationPointerLocalScale = m_AnnotationPointer.transform.localScale; + var brushSize = m_Preferences.brushSize; + m_AnnotationPointer.Resize(brushSize); + + var brushSizeUi = this.InstantiateUI(m_BrushSizePrefab, rayOrigin: rayOrigin); + m_BrushSizeUI = brushSizeUi.GetComponent(); + + var transform = brushSizeUi.transform; + localBounds = ObjectUtils.GetBounds(transform); + var scale = transform.localScale; + transform.SetParent(alternateMenuOrigin, false); + transform.localPosition = Vector3.zero; + transform.localRotation = Quaternion.Euler(-90, 0, 0); + transform.localScale = scale; + + m_BrushSizeUI.onValueChanged = value => + { + var sliderValue = Mathf.Lerp(MinBrushSize, MaxBrushSize, value); + m_Preferences.brushSize = sliderValue; + m_AnnotationPointer.Resize(sliderValue); + }; + m_BrushSizeChanged = m_BrushSizeUI.ChangeSliderValue; + } + + void ShowColorPicker(Transform otherRayOrigin) + { + if (!m_ColorPicker.enabled) + m_ColorPicker.Show(); + + m_AnnotationPointer.gameObject.SetActive(false); + } + + void HideColorPicker() + { + if (m_ColorPicker && m_ColorPicker.enabled) + { + m_ColorPicker.Hide(); + m_AnnotationPointer.gameObject.SetActive(true); + } + } + + void OnColorPickerValueChanged(Color color) + { + m_Preferences.annotationColor = color; + + const float annotationPointerAlpha = 0.75f; + color.a = annotationPointerAlpha; + m_AnnotationPointer.SetColor(color); + + m_BrushSizeUI.OnBrushColorChanged(color); + } + + void HandleBrushSize(float value) + { + if (m_AnnotationPointer != null) + { + var brushSize = m_Preferences.brushSize; + if (this.GetDeviceType() == DeviceType.Vive) // For vive controllers, use 1:1 touchpad setting. + { + brushSize = Mathf.Lerp(MinBrushSize, MaxBrushSize, (value + 1) / 2f); + } + else // For touch and hydra, let the thumbstick gradually modify the width. + { + brushSize += value * Time.unscaledDeltaTime * .1f; + brushSize = Mathf.Clamp(brushSize, MinBrushSize, MaxBrushSize); + } + + if (m_BrushSizeUI && m_BrushSizeChanged != null) + { + var ratio = Mathf.InverseLerp(MinBrushSize, MaxBrushSize, brushSize); + m_BrushSizeChanged(ratio); + } + + m_AnnotationPointer.Resize(brushSize); + m_Preferences.brushSize = brushSize; + } + } + + void SetupAnnotation() + { + SetupHolder(); + + m_Points.Clear(); + m_UpVectors.Clear(); + m_Widths.Clear(); + m_Length = 0; + + var go = new GameObject(string.Format(k_AnnotationFormatStrig, m_AnnotationHolder.childCount)); + Undo.RegisterCreatedObjectUndo(go, "Annotation"); + + var goTrans = go.transform; + goTrans.SetParent(m_AnnotationHolder); + goTrans.position = rayOrigin.position; + + m_CurrentMeshFilter = go.AddComponent(); + var mRenderer = go.AddComponent(); + + var matToUse = Instantiate(m_AnnotationMaterial); + matToUse.SetColor("_EmissionColor", m_Preferences.annotationColor); + mRenderer.sharedMaterial = matToUse; + + m_WorldToLocalMesh = goTrans.worldToLocalMatrix; + + m_CurrentMesh = new Mesh(); + m_CurrentMesh.name = k_MeshName; + } + + void SetupHolder() + { + var mainHolder = GameObject.Find(k_MainHolderName) ?? new GameObject(k_MainHolderName); + m_AnnotationRoot = mainHolder.transform; + + var newSession = GetNewSessionHolder(); + if (!newSession) + { + newSession = new GameObject(string.Format(k_GroupFormatString, m_AnnotationRoot.childCount)); + Undo.RegisterCreatedObjectUndo(newSession, "Annotation"); + newSession.transform.position = GetPointerPosition(); + m_Groups.Add(newSession); + } + + m_AnnotationHolder = newSession.transform; + m_AnnotationHolder.SetParent(m_AnnotationRoot); + } + + GameObject GetNewSessionHolder() + { + const float groupingDistance = 0.3f; + var position = rayOrigin.position; + for (var i = 0; i < m_Groups.Count; i++) + { + var child = m_Groups[i]; + child.name = "Group " + i; + + var renderers = child.GetComponentsInChildren(); + if (renderers.Length > 0) + { + var bound = renderers[0].bounds; + for (var r = 1; r < renderers.Length; r++) + { + bound.Encapsulate(renderers[r].bounds); + } + + if (bound.Contains(position) || bound.SqrDistance(position) < groupingDistance) + return child.gameObject; + } + } + + return null; + } + + void UpdateAnnotation() + { + var upVector = rayOrigin.up; + var viewerScale = this.GetViewerScale(); + var worldPoint = GetPointerPosition(); + var localPoint = m_WorldToLocalMesh.MultiplyPoint3x4(worldPoint); + + if (m_Points.Count > 0) + { + var lastPoint = m_Points.Last(); + localPoint = Vector3.Lerp(lastPoint, localPoint, 0.5f); + var distance = (localPoint - lastPoint).magnitude; + if (distance < k_MinDistance * viewerScale) + return; + + m_Length += distance; + } + + var brushSize = m_Preferences.brushSize * viewerScale; + InterpolatePointsIfNeeded(localPoint, upVector, brushSize); + + m_Points.Add(localPoint); + m_UpVectors.Add(upVector); + m_Widths.Add(brushSize); + + PointsToMesh(); + + if (AnnotationUpdated != null) + { + AnnotationUpdated(m_CurrentMeshFilter); + } + } + + void InterpolatePointsIfNeeded(Vector3 localPoint, Vector3 upVector, float brushSize) + { + if (m_Points.Count > 1) + { + var lastPoint = m_Points.Last(); + var distance = Vector3.Distance(lastPoint, localPoint); + + if (distance > brushSize * .5f) + { + var halfPoint = (lastPoint + localPoint) / 2f; + m_Points.Add(halfPoint); + + var halfUp = (m_UpVectors.Last() + upVector) / 2f; + m_UpVectors.Add(halfUp); + + var halfRadius = (m_Widths.Last() + brushSize) / 2f; + m_Widths.Add(halfRadius); + } + } + } + + void PointsToMesh() + { + if (m_Points.Count < 4) + return; + + if (m_CurrentMesh == null) + m_CurrentMesh = new Mesh(); + + var newVertices = new List(); + var newTriangles = new List(); + var newUvs = new List(); + + LineToPlane(newVertices); + + TriangulatePlane(newTriangles, newVertices.Count); + CalculateUvs(newUvs, newVertices); + + m_CurrentMesh.Clear(); + + m_CurrentMesh.vertices = newVertices.ToArray(); + m_CurrentMesh.triangles = newTriangles.ToArray(); + m_CurrentMesh.uv = newUvs.ToArray(); + + m_CurrentMesh.UploadMeshData(false); + + m_CurrentMeshFilter.sharedMesh = m_CurrentMesh; + } + + void LineToPlane(List newVertices) + { + var distance = 0f; + var lastPoint = m_Points[0]; + for (var i = 1; i < m_Points.Count; i++) + { + var point = m_Points[i]; + var segment = point - lastPoint; + + var width = m_Widths[i]; + + width *= Math.Min(Mathf.Sqrt(distance / width), 1); + var endDistance = m_Length - distance; + width *= Math.Min(Mathf.Sqrt(endDistance / width), 1); + + var upVector = m_UpVectors[i]; + var top = point - upVector * width; + var bottom = point + upVector * width; + + newVertices.Add(top); + newVertices.Add(bottom); + + distance += segment.magnitude; + lastPoint = point; + } + } + + static void TriangulatePlane(List newTriangles, int vertexCount) + { + for (var i = 3; i < vertexCount; i += 2) + { + var upperLeft = i - 1; + var upperRight = i; + var lowerLeft = i - 3; + var lowerRight = i - 2; + + var triangles = VerticesToPolygon(upperLeft, upperRight, lowerLeft, lowerRight); + newTriangles.AddRange(triangles); + } + } + + static void CalculateUvs(List newUvs, List newVertices) + { + for (var i = 0; i < newVertices.Count; i += 2) + { + newUvs.Add(new Vector2(0, i * 0.5f)); + newUvs.Add(new Vector2(1, i * 0.5f)); + } + } + + void FinalizeMesh() + { + CenterMesh(); + + m_CurrentMesh.RecalculateBounds(); + m_CurrentMesh.RecalculateNormals(); + + m_CurrentMesh.UploadMeshData(false); + + CenterHolder(); + + var go = m_CurrentMeshFilter.gameObject; + + this.AddToSpatialHash(go); + + Undo.IncrementCurrentGroup(); + + if (AnnotationFinished != null) + { + AnnotationFinished(m_CurrentMeshFilter); + } + } + + void CenterMesh() + { + if (m_CurrentMesh == null || m_CurrentMesh.vertexCount == 0) + return; + + var center = Vector3.zero; + + var vertices = m_CurrentMesh.vertices; + + for (var i = 0; i < m_CurrentMesh.vertexCount; i++) + { + center += vertices[i]; + } + + center /= m_CurrentMesh.vertexCount; + + for (var i = 0; i < m_CurrentMesh.vertexCount; i++) + { + vertices[i] -= center; + } + + m_CurrentMesh.vertices = vertices; + m_CurrentMeshFilter.transform.localPosition += center; + } + + void CenterHolder() + { + if (m_AnnotationHolder == null || m_AnnotationHolder.childCount == 0) + return; + + var childWorldPositions = new List(); + var center = Vector3.zero; + + for (var i = 0; i < m_AnnotationHolder.childCount; i++) + { + var worldPos = m_AnnotationHolder.GetChild(i).position; + childWorldPositions.Add(worldPos); + center += worldPos; + } + + center /= m_AnnotationHolder.childCount; + + m_AnnotationHolder.localPosition += center; + for (var i = 0; i < m_AnnotationHolder.childCount; i++) + { + m_AnnotationHolder.GetChild(i).position = childWorldPositions[i]; + } + } + + public static int[] VerticesToPolygon(int upperLeft, int upperRight, int lowerLeft, int lowerRight, bool doubleSided = true) + { + var triangleCount = doubleSided ? 12 : 6; + var triangles = new int[triangleCount]; + var index = 0; + + triangles[index++] = upperLeft; + triangles[index++] = lowerRight; + triangles[index++] = lowerLeft; + + triangles[index++] = lowerRight; + triangles[index++] = upperLeft; + triangles[index++] = upperRight; + + if (doubleSided) + { + triangles[index++] = lowerLeft; + triangles[index++] = lowerRight; + triangles[index++] = upperLeft; + + triangles[index++] = upperRight; + triangles[index++] = upperLeft; + triangles[index] = lowerRight; + } + + return triangles; + } + + public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl) + { + var annotationInput = (AnnotationInput)input; + + var draw = annotationInput.draw; + var isHeld = draw.isHeld; + if (primary) + { + if (!Mathf.Approximately(annotationInput.changeBrushSize.value, 0)) + { + HandleBrushSize(annotationInput.changeBrushSize.value); + consumeControl(annotationInput.changeBrushSize); + consumeControl(annotationInput.vertical); + } + + if (draw.wasJustPressed) + { + SetupAnnotation(); + consumeControl(draw); + } + + if (isHeld) + { + UpdateAnnotation(); + consumeControl(draw); + } + + if (draw.wasJustReleased) + { + FinalizeMesh(); + consumeControl(draw); + } + } + else + { + // Secondary hand uses brush size input to do undo/redo + var value = annotationInput.changeBrushSize.value; + if (this.GetDeviceType() == DeviceType.Vive) + { + if (annotationInput.stickButton.wasJustPressed) + { + if (value > 0) + Undo.PerformRedo(); + else + Undo.PerformUndo(); + } + } + else + { + var doUndoRedo = Math.Abs(value) > 0.5f; + if (doUndoRedo != m_WasDoingUndoRedo) + { + m_WasDoingUndoRedo = doUndoRedo; + if (doUndoRedo) + { + if (value > 0) + Undo.PerformRedo(); + else + Undo.PerformUndo(); + } + } + } + } + + if (isHeld) + return; + + var isOverUI = this.IsHoveringOverUI(rayOrigin); + if (isOverUI != m_WasOverUI) + { + m_WasOverUI = isOverUI; + this.RestartCoroutine(ref m_AnnotationPointerVisibilityCoroutine, SetAnnotationPointerVisibility(!isOverUI)); + if (isOverUI) + this.RemoveRayVisibilitySettings(rayOrigin, this); + else + this.AddRayVisibilitySettings(rayOrigin, this, false, false); + } + } + + IEnumerator SetAnnotationPointerVisibility(bool visible) + { + if (!m_AnnotationPointer) + yield break; + + const float transitionTime = 0.1875f; + var annotationPointerTransform = m_AnnotationPointer.transform; + var startTime = Time.time; + var timeDiff = 0f; + var currentScale = annotationPointerTransform.localScale; + var targetScale = visible ? m_OriginalAnnotationPointerLocalScale : Vector3.zero; + while (timeDiff < transitionTime) + { + annotationPointerTransform.localScale = Vector3.Lerp(currentScale, targetScale, timeDiff / transitionTime); + timeDiff = Time.time - startTime; + yield return null; + } + + annotationPointerTransform.localScale = targetScale; + } + + void CombineGroups() + { + foreach (var group in m_Groups) + { + var meshFilters = group.GetComponentsInChildren(); + var renderers = group.GetComponentsInChildren(); + + if (meshFilters.Length == 0) + { + ObjectUtils.Destroy(group); + continue; + } + + var length = meshFilters.Length; + var combines = new List(length); + var materials = new List(length); + for (var i = 0; i < length; i++) + { + var meshFilter = meshFilters[i]; + var sharedMesh = meshFilter.sharedMesh; + if (sharedMesh && sharedMesh.vertexCount > 0) + { + var combine = new CombineInstance + { + mesh = sharedMesh, + transform = group.transform.worldToLocalMatrix * meshFilter.transform.localToWorldMatrix + }; + + sharedMesh.UploadMeshData(false); + combines.Add(combine); + materials.Add(renderers[i].sharedMaterial); + } + } + + var mesh = new Mesh(); + mesh.CombineMeshes(combines.ToArray(), false, true); + group.AddComponent().sharedMesh = mesh; + + group.AddComponent().sharedMaterials = materials.ToArray(); + + this.AddToSpatialHash(group); + + foreach (var meshFilter in meshFilters) + { + var go = meshFilter.gameObject; + this.RemoveFromSpatialHash(go); + ObjectUtils.Destroy(go); + } + } + } + + Vector3 GetPointerPosition() + { + return rayOrigin.position + rayOrigin.forward * TipDistance * this.GetViewerScale(); + } + + public object OnSerializePreferences() + { + if (this.IsSharedUpdater(this)) + { + // Share one preferences object across all instances + foreach (var linkedObject in linkedObjects) + { + ((AnnotationTool)linkedObject).m_Preferences = m_Preferences; + } + + return m_Preferences; + } + + return null; + } + + public void OnDeserializePreferences(object obj) + { + if (m_Preferences == null) + m_Preferences = (Preferences)obj; + } + } +} +#endif diff --git a/Tools/AnnotationTool/UserInterface/BrushSizeUI.cs b/Tools/AnnotationTool/UserInterface/BrushSizeUI.cs index 357966f34..9e159d863 100644 --- a/Tools/AnnotationTool/UserInterface/BrushSizeUI.cs +++ b/Tools/AnnotationTool/UserInterface/BrushSizeUI.cs @@ -1,12 +1,14 @@ #if UNITY_EDITOR using System; using System.Collections.Generic; +using UnityEditor.Experimental.EditorVR.Menus; +using UnityEditor.Experimental.EditorVR.Utilities; using UnityEngine; using UnityEngine.UI; namespace UnityEditor.Experimental.EditorVR.Tools { - public class BrushSizeUI : MonoBehaviour + public class BrushSizeUI : MonoBehaviour, IAlternateMenu { const float k_MinSize = 0.625f; const float k_MaxSize = 12.5f; @@ -18,11 +20,30 @@ public class BrushSizeUI : MonoBehaviour Slider m_Slider; Image m_SliderHandleImage; + MenuHideFlags m_MenuHideFlags; public Action onValueChanged { private get; set; } + public Bounds localBounds { get; private set; } + public Transform rayOrigin { get; set; } + + public MenuHideFlags menuHideFlags { + get { return m_MenuHideFlags; } + set + { + if (m_MenuHideFlags == value) + return; + + m_MenuHideFlags = value; + gameObject.SetActive(m_MenuHideFlags == 0); + } + } + + public GameObject menuContent { get { return gameObject; } } + public int priority { get { return 2; } } void Awake() { + localBounds = ObjectUtils.GetBounds(transform); // We record property modifications on creation and modification of these UI elements, which will look odd when undone Undo.postprocessModifications += PostProcessModifications; m_SliderHandleImage = m_SliderHandle.GetComponent(); diff --git a/Tools/CreatePrimitiveTool/CreatePrimitiveMenu.cs b/Tools/CreatePrimitiveTool/CreatePrimitiveMenu.cs index 829afbe9f..783110e7b 100644 --- a/Tools/CreatePrimitiveTool/CreatePrimitiveMenu.cs +++ b/Tools/CreatePrimitiveTool/CreatePrimitiveMenu.cs @@ -1,58 +1,59 @@ -#if UNITY_EDITOR -using System; -using UnityEditor.Experimental.EditorVR.Menus; -using UnityEditor.Experimental.EditorVR.Utilities; -using UnityEngine; - -namespace UnityEditor.Experimental.EditorVR.Tools -{ - sealed class CreatePrimitiveMenu : MonoBehaviour, IMenu - { - [SerializeField] - GameObject[] m_HighlightObjects; - - public Action selectPrimitive; - public Action close; - - public Bounds localBounds { get; private set; } - - public MenuHideFlags menuHideFlags - { - get { return gameObject.activeSelf ? 0 : MenuHideFlags.Hidden; } - set { gameObject.SetActive(value == 0); } - } - - public GameObject menuContent { get { return gameObject; } } - - void Awake() - { - localBounds = ObjectUtils.GetBounds(transform); - } - - public void SelectPrimitive(int type) - { - selectPrimitive((PrimitiveType)type, false); - - // the order of the objects in m_HighlightObjects is matched to the values of the PrimitiveType enum elements - for (var i = 0; i < m_HighlightObjects.Length; i++) - { - var go = m_HighlightObjects[i]; - go.SetActive(i == type); - } - } - - public void SelectFreeformCuboid() - { - selectPrimitive(PrimitiveType.Cube, true); - - foreach (var go in m_HighlightObjects) - go.SetActive(false); - } - - public void Close() - { - close(); - } - } -} -#endif +#if UNITY_EDITOR +using System; +using UnityEditor.Experimental.EditorVR.Menus; +using UnityEditor.Experimental.EditorVR.Utilities; +using UnityEngine; + +namespace UnityEditor.Experimental.EditorVR.Tools +{ + sealed class CreatePrimitiveMenu : MonoBehaviour, IMenu + { + [SerializeField] + GameObject[] m_HighlightObjects; + + public Action selectPrimitive; + public Action close; + + public Bounds localBounds { get; private set; } + public int priority { get { return 1; } } + + public MenuHideFlags menuHideFlags + { + get { return gameObject.activeSelf ? 0 : MenuHideFlags.Hidden; } + set { gameObject.SetActive(value == 0); } + } + + public GameObject menuContent { get { return gameObject; } } + + void Awake() + { + localBounds = ObjectUtils.GetBounds(transform); + } + + public void SelectPrimitive(int type) + { + selectPrimitive((PrimitiveType)type, false); + + // the order of the objects in m_HighlightObjects is matched to the values of the PrimitiveType enum elements + for (var i = 0; i < m_HighlightObjects.Length; i++) + { + var go = m_HighlightObjects[i]; + go.SetActive(i == type); + } + } + + public void SelectFreeformCuboid() + { + selectPrimitive(PrimitiveType.Cube, true); + + foreach (var go in m_HighlightObjects) + go.SetActive(false); + } + + public void Close() + { + close(); + } + } +} +#endif diff --git a/Tools/SelectionTool/SelectionTool.cs b/Tools/SelectionTool/SelectionTool.cs index 1e56c235f..32f23110b 100644 --- a/Tools/SelectionTool/SelectionTool.cs +++ b/Tools/SelectionTool/SelectionTool.cs @@ -1,616 +1,616 @@ -#if UNITY_EDITOR -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.Experimental.EditorVR.Core; -using UnityEditor.Experimental.EditorVR.Proxies; -using UnityEditor.Experimental.EditorVR.UI; -using UnityEditor.Experimental.EditorVR.Utilities; -using UnityEngine; -using UnityEngine.InputNew; -using UnityEngine.UI; - -namespace UnityEditor.Experimental.EditorVR.Tools -{ - sealed class SelectionTool : MonoBehaviour, ITool, IUsesRayOrigin, IUsesRaycastResults, ICustomActionMap, - ISetHighlight, ISelectObject, ISetManipulatorsVisible, IIsHoveringOverUI, IUsesDirectSelection, ILinkedObject, - ICanGrabObject, IGetManipulatorDragState, IUsesNode, IGetRayVisibility, IIsMainMenuVisible, IIsInMiniWorld, - IRayToNode, IGetDefaultRayColor, ISetDefaultRayColor, ITooltip, ITooltipPlacement, ISetTooltipVisibility, - IUsesDeviceType, IMenuIcon, IUsesPointer, IRayVisibilitySettings, IUsesViewerScale, ICheckBounds, - ISettingsMenuItemProvider, ISerializePreferences, IStandardIgnoreList, IBlockUIInteraction, IRequestFeedback, - IGetVRPlayerObjects - { - [Serializable] - class Preferences - { - [SerializeField] - bool m_SphereMode; - - public bool sphereMode - { - get { return m_SphereMode; } - set { m_SphereMode = value; } - } - } - - const float k_MultiselectHueShift = 0.5f; - static readonly Vector3 k_TooltipPosition = new Vector3(0, -0.15f, -0.13f); - const float k_BLockSelectDragThreshold = 0.01f; - static readonly Quaternion k_TooltipRotation = Quaternion.AngleAxis(90, Vector3.right); - - [SerializeField] - Sprite m_Icon; - - [SerializeField] - ActionMap m_ActionMap; - - [SerializeField] - GameObject m_BlockSelectCube; - - [SerializeField] - GameObject m_BlockSelectSphere; - - [SerializeField] - GameObject m_SettingsMenuItemPrefab; - - Preferences m_Preferences; - - GameObject m_PressedObject; - - SelectionInput m_SelectionInput; - - float m_LastMultiSelectClickTime; - Color m_NormalRayColor; - Color m_MultiselectRayColor; - bool m_MultiSelect; - bool m_HasDirectHover; - bool m_BlockSelect; - Vector3 m_SelectStartPosition; - Renderer m_BlockSelectCubeRenderer; - - readonly BindingDictionary m_Controls = new BindingDictionary(); - readonly List m_SelectFeedback = new List(); - readonly List m_DirectSelectFeedback = new List(); - - Toggle m_CubeToggle; - Toggle m_SphereToggle; - bool m_BlockValueChangedListener; - - readonly Dictionary m_HoverGameObjects = new Dictionary(); - - readonly Dictionary m_SelectionHoverGameObjects = new Dictionary(); - readonly List m_BlockSelectHoverGameObjects = new List(); - - public ActionMap actionMap { get { return m_ActionMap; } } - public bool ignoreLocking { get { return false; } } - - public Transform rayOrigin { get; set; } - public Node node { private get; set; } - - public Sprite icon { get { return m_Icon; } } - - public event Action hovered; - - public List ignoreList { private get; set; } - public List linkedObjects { get; set; } - - public string tooltipText { get { return m_MultiSelect ? "Multi-Select Enabled" : ""; } } - public Transform tooltipTarget { get; private set; } - public Transform tooltipSource { get { return rayOrigin; } } - public TextAlignment tooltipAlignment { get { return TextAlignment.Center; } } - - public GameObject settingsMenuItemPrefab { get { return m_SettingsMenuItemPrefab; } } - - public GameObject settingsMenuItemInstance - { - set - { - var defaultToggleGroup = value.GetComponentInChildren(); - foreach (var toggle in value.GetComponentsInChildren()) - { - if (toggle == defaultToggleGroup.defaultToggle) - { - m_CubeToggle = toggle; - toggle.onValueChanged.AddListener(isOn => - { - if (m_BlockValueChangedListener) - return; - - // m_Preferences on all instances refer - m_Preferences.sphereMode = !isOn; - foreach (var linkedObject in linkedObjects) - { - var selectionTool = (SelectionTool)linkedObject; - if (selectionTool != this) - { - selectionTool.m_BlockValueChangedListener = true; - - //selectionTool.m_ToggleGroup.NotifyToggleOn(isOn ? m_CubeToggle : m_SphereToggle); - // HACK: Toggle Group claims these toggles are not a part of the group - selectionTool.m_CubeToggle.isOn = isOn; - selectionTool.m_SphereToggle.isOn = !isOn; - selectionTool.m_BlockValueChangedListener = false; - } - } - }); - } - else - { - m_SphereToggle = toggle; - } - } - } - } - - // Local method use only -- created here to reduce garbage collection - static readonly Dictionary k_TempHovers = new Dictionary(); - - void Start() - { - if (this.IsSharedUpdater(this) && m_Preferences == null) - { - m_Preferences = new Preferences(); - - // Share one preferences object across all instances - foreach (var linkedObject in linkedObjects) - { - ((SelectionTool)linkedObject).m_Preferences = m_Preferences; - } - } - - m_NormalRayColor = this.GetDefaultRayColor(rayOrigin); - m_MultiselectRayColor = m_NormalRayColor; - m_MultiselectRayColor = MaterialUtils.HueShift(m_MultiselectRayColor, k_MultiselectHueShift); - - tooltipTarget = ObjectUtils.CreateEmptyGameObject("SelectionTool Tooltip Target", rayOrigin).transform; - tooltipTarget.localPosition = k_TooltipPosition; - tooltipTarget.localRotation = k_TooltipRotation; - - m_BlockSelectCube = ObjectUtils.Instantiate(m_BlockSelectCube, transform); - m_BlockSelectCube.SetActive(false); - m_BlockSelectCubeRenderer = m_BlockSelectCube.GetComponent(); - - m_BlockSelectSphere = ObjectUtils.Instantiate(m_BlockSelectSphere, transform); - m_BlockSelectSphere.SetActive(false); - - InputUtils.GetBindingDictionaryFromActionMap(m_ActionMap, m_Controls); - } - - void OnDestroy() - { - ObjectUtils.Destroy(m_BlockSelectCube); - this.ClearFeedbackRequests(); - } - - public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl) - { - if (this.GetManipulatorDragState()) - return; - - m_SelectionInput = (SelectionInput)input; - - var multiSelectControl = m_SelectionInput.multiSelect; - if (this.GetDeviceType() == DeviceType.Vive) - multiSelectControl = m_SelectionInput.multiSelectAlt; - - if (multiSelectControl.wasJustPressed) - { - var realTime = Time.realtimeSinceStartup; - if (UIUtils.IsDoubleClick(realTime - m_LastMultiSelectClickTime)) - { - foreach (var linkedObject in linkedObjects) - { - var selectionTool = (SelectionTool)linkedObject; - selectionTool.m_MultiSelect = !selectionTool.m_MultiSelect; - this.HideTooltip(selectionTool); - } - - if (m_MultiSelect) - this.ShowTooltip(this); - } - - m_LastMultiSelectClickTime = realTime; - } - - this.SetDefaultRayColor(rayOrigin, m_MultiSelect ? m_MultiselectRayColor : m_NormalRayColor); - - if (this.IsSharedUpdater(this)) - { - this.SetManipulatorsVisible(this, !m_MultiSelect); - - m_SelectionHoverGameObjects.Clear(); - foreach (var linkedObject in linkedObjects) - { - var selectionTool = (SelectionTool)linkedObject; - selectionTool.m_HasDirectHover = false; // Clear old hover state - - if (selectionTool.m_BlockSelect) - continue; - - if (!selectionTool.IsRayActive()) - continue; - - var selectionRayOrigin = selectionTool.rayOrigin; - - var hover = this.GetFirstGameObject(selectionRayOrigin); - - if (!selectionTool.GetSelectionCandidate(ref hover)) - continue; - - if (hover) - { - GameObject lastHover; - if (m_HoverGameObjects.TryGetValue(selectionRayOrigin, out lastHover) && lastHover != hover) - this.SetHighlight(lastHover, false, selectionRayOrigin); - - m_SelectionHoverGameObjects[selectionRayOrigin] = hover; - m_HoverGameObjects[selectionRayOrigin] = hover; - } - } - - var directSelection = this.GetDirectSelection(); - - // Unset highlight old hovers - k_TempHovers.Clear(); - foreach (var kvp in m_HoverGameObjects) - { - k_TempHovers[kvp.Key] = kvp.Value; - } - - foreach (var kvp in k_TempHovers) - { - var directRayOrigin = kvp.Key; - var hover = kvp.Value; - - if (!directSelection.ContainsKey(directRayOrigin) - && !m_SelectionHoverGameObjects.ContainsKey(directRayOrigin)) - { - this.SetHighlight(hover, false, directRayOrigin); - m_HoverGameObjects.Remove(directRayOrigin); - } - } - - // Find new hovers - foreach (var kvp in directSelection) - { - var directRayOrigin = kvp.Key; - var directHoveredObject = kvp.Value; - - var directSelectionCandidate = this.GetSelectionCandidate(directHoveredObject, true); - - // Can't select this object (it might be locked or static) - if (directHoveredObject && !directSelectionCandidate) - { - if (directHoveredObject != null) - this.SetHighlight(directHoveredObject, false); - - continue; - } - - if (directSelectionCandidate) - directHoveredObject = directSelectionCandidate; - - if (!this.CanGrabObject(directHoveredObject, directRayOrigin)) - continue; - - var grabbingNode = this.RequestNodeFromRayOrigin(directRayOrigin); - var selectionTool = linkedObjects.Cast().FirstOrDefault(linkedObject => linkedObject.node == grabbingNode); - if (selectionTool == null) - continue; - - if (selectionTool.m_BlockSelect) - continue; - - GameObject lastHover; - if (m_HoverGameObjects.TryGetValue(directRayOrigin, out lastHover) && lastHover != directHoveredObject) - this.SetHighlight(lastHover, false, directRayOrigin); - - if (!selectionTool.IsDirectActive()) - { - m_HoverGameObjects.Remove(directRayOrigin); - this.SetHighlight(directHoveredObject, false, directRayOrigin); - continue; - } - - // Only overwrite an existing selection if it does not contain the hovered object - // In the case of multi-select, only add, do not remove - if (selectionTool.m_SelectionInput.select.wasJustPressed && !Selection.objects.Contains(directHoveredObject)) - this.SelectObject(directHoveredObject, directRayOrigin, m_MultiSelect); - - m_HoverGameObjects[directRayOrigin] = directHoveredObject; - selectionTool.m_HasDirectHover = true; - } - - // Set highlight on new hovers - foreach (var hover in m_HoverGameObjects) - { - this.SetHighlight(hover.Value, true, hover.Key); - } - } - - if (!m_HasDirectHover) - HideDirectSelectFeedback(); - else if (m_DirectSelectFeedback.Count == 0) - ShowDirectSelectFeedback(); - - GameObject hoveredObject = null; - var rayActive = IsRayActive(); - if (rayActive) - { - // Need to call GetFirstGameObject a second time because we do not guarantee shared updater executes first - hoveredObject = this.GetFirstGameObject(rayOrigin); - - if (hovered != null) - hovered(hoveredObject, rayOrigin); - - GetSelectionCandidate(ref hoveredObject); - - if (hoveredObject && this.GetVRPlayerObjects().Contains(hoveredObject)) - hoveredObject = null; - } - - if (!hoveredObject) - HideSelectFeedback(); - else if (m_SelectFeedback.Count == 0) - ShowSelectFeedback(); - - var pointerPosition = this.GetPointerPosition(rayOrigin); - - // Capture object on press - var select = m_SelectionInput.select; - if (select.wasJustPressed) - { - m_SelectStartPosition = pointerPosition; - - // Ray selection only if ray is visible - m_PressedObject = hoveredObject; - } - - if (select.isHeld) - { - var startToEnd = pointerPosition - m_SelectStartPosition; - var visuals = m_Preferences.sphereMode ? m_BlockSelectSphere : m_BlockSelectCube; - var distance = startToEnd.magnitude; - if (!m_BlockSelect && distance > k_BLockSelectDragThreshold * this.GetViewerScale()) - { - m_BlockSelect = true; - visuals.SetActive(true); - - m_PressedObject = null; - this.AddRayVisibilitySettings(rayOrigin, this, false, true); - this.SetUIBlockedForRayOrigin(rayOrigin, true); - } - - if (m_BlockSelect) - this.SetManipulatorsVisible(this, false); - - //TODO: use hashsets to only unset highlights for removed objects - foreach (var hover in m_BlockSelectHoverGameObjects) - { - this.SetHighlight(hover, false, rayOrigin); - } - m_BlockSelectHoverGameObjects.Clear(); - - var visualsTransform = visuals.transform; - if (m_Preferences.sphereMode) - { - visualsTransform.localScale = Vector3.one * distance * 2; - visualsTransform.position = m_SelectStartPosition; - this.CheckSphere(m_SelectStartPosition, distance, m_BlockSelectHoverGameObjects, ignoreList); - } - else - { - visualsTransform.localScale = startToEnd; - visualsTransform.position = m_SelectStartPosition + startToEnd * 0.5f; - this.CheckBounds(m_BlockSelectCubeRenderer.bounds, m_BlockSelectHoverGameObjects, ignoreList); - } - - foreach (var hover in m_BlockSelectHoverGameObjects) - { - this.SetHighlight(hover, true, rayOrigin); - } - - if (m_BlockSelect) - consumeControl(select); - } - - // Make selection on release - if (select.wasJustReleased) - { - if (m_BlockSelect) - { - if (!m_MultiSelect) - { - this.SetManipulatorsVisible(this, true); - Selection.activeGameObject = null; - } - - this.SelectObjects(m_BlockSelectHoverGameObjects, rayOrigin, m_MultiSelect); - - foreach (var hover in m_BlockSelectHoverGameObjects) - { - if (hover != null) - this.SetHighlight(hover, false, rayOrigin); - } - - this.ResetDirectSelectionState(); - } - else if (rayActive) - { - if (m_PressedObject == hoveredObject) - { - this.SelectObject(m_PressedObject, rayOrigin, m_MultiSelect, true); - this.ResetDirectSelectionState(); - - if (m_PressedObject != null) - this.SetHighlight(m_PressedObject, false, rayOrigin); - } - - if (m_PressedObject) - consumeControl(select); - } - - this.SetUIBlockedForRayOrigin(rayOrigin, false); - this.RemoveRayVisibilitySettings(rayOrigin, this); - (m_Preferences.sphereMode ? m_BlockSelectSphere : m_BlockSelectCube).SetActive(false); - m_PressedObject = null; - m_BlockSelect = false; - } - } - - bool GetSelectionCandidate(ref GameObject hoveredObject) - { - var selectionCandidate = this.GetSelectionCandidate(hoveredObject, true); - - // Can't select this object (it might be locked or static) - if (hoveredObject && !selectionCandidate) - { - if (hoveredObject != null) - this.SetHighlight(hoveredObject, false); - - return false; - } - - if (selectionCandidate) - hoveredObject = selectionCandidate; - - return true; - } - - bool IsDirectActive() - { - if (rayOrigin == null) - return false; - - if (!this.IsConeVisible(rayOrigin)) - return false; - - if (this.IsInMiniWorld(rayOrigin)) - return true; - - if (this.IsMainMenuVisible(rayOrigin)) - return false; - - return true; - } - - bool IsRayActive() - { - if (rayOrigin == null) - return false; - - if (this.IsHoveringOverUI(rayOrigin)) - return false; - - if (this.IsMainMenuVisible(rayOrigin)) - return false; - - if (this.IsInMiniWorld(rayOrigin)) - return false; - - if (!this.IsRayVisible(rayOrigin)) - return false; - - return true; - } - - void OnDisable() - { - foreach (var kvp in m_HoverGameObjects) - { - this.SetHighlight(kvp.Value, false, kvp.Key); - } - m_HoverGameObjects.Clear(); - } - - public void OnResetDirectSelectionState() { } - - public object OnSerializePreferences() - { - if (this.IsSharedUpdater(this)) - { - // Share one preferences object across all instances - foreach (var linkedObject in linkedObjects) - { - ((SelectionTool)linkedObject).m_Preferences = m_Preferences; - } - - return m_Preferences; - } - - return null; - } - - public void OnDeserializePreferences(object obj) - { - if (this.IsSharedUpdater(this)) - { - var preferences = obj as Preferences; - if (preferences != null) - m_Preferences = preferences; - - // Share one preferences object across all instances - foreach (var linkedObject in linkedObjects) - { - ((SelectionTool)linkedObject).m_Preferences = m_Preferences; - } - - m_SphereToggle.isOn = m_Preferences.sphereMode; - m_CubeToggle.isOn = !m_Preferences.sphereMode; - } - } - - void ShowFeedback(List requests, string controlName, string tooltipText = null) - { - if (tooltipText == null) - tooltipText = controlName; - - List ids; - if (m_Controls.TryGetValue(controlName, out ids)) - { - foreach (var id in ids) - { - var request = new ProxyFeedbackRequest - { - node = node, - control = id, - tooltipText = tooltipText - }; - - this.AddFeedbackRequest(request); - requests.Add(request); - } - } - } - - void ShowSelectFeedback() - { - ShowFeedback(m_SelectFeedback, "Select"); - } - - void ShowDirectSelectFeedback() - { - ShowFeedback(m_DirectSelectFeedback, "Select", "Direct Select"); - } - - void HideFeedback(List requests) - { - foreach (var request in requests) - { - this.RemoveFeedbackRequest(request); - } - requests.Clear(); - } - - void HideSelectFeedback() - { - HideFeedback(m_SelectFeedback); - } - - void HideDirectSelectFeedback() - { - HideFeedback(m_DirectSelectFeedback); - } - } -} -#endif +#if UNITY_EDITOR +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor.Experimental.EditorVR.Core; +using UnityEditor.Experimental.EditorVR.Proxies; +using UnityEditor.Experimental.EditorVR.UI; +using UnityEditor.Experimental.EditorVR.Utilities; +using UnityEngine; +using UnityEngine.InputNew; +using UnityEngine.UI; + +namespace UnityEditor.Experimental.EditorVR.Tools +{ + sealed class SelectionTool : MonoBehaviour, ITool, IUsesRayOrigin, IUsesRaycastResults, ICustomActionMap, + ISetHighlight, ISelectObject, ISetManipulatorsVisible, IIsHoveringOverUI, IUsesDirectSelection, ILinkedObject, + ICanGrabObject, IGetManipulatorDragState, IUsesNode, IGetRayVisibility, IIsMainMenuVisible, IIsInMiniWorld, + IRayToNode, IGetDefaultRayColor, ISetDefaultRayColor, ITooltip, ITooltipPlacement, ISetTooltipVisibility, + IUsesDeviceType, IMenuIcon, IUsesPointer, IRayVisibilitySettings, IUsesViewerScale, ICheckBounds, + ISettingsMenuItemProvider, ISerializePreferences, IStandardIgnoreList, IBlockUIInteraction, IRequestFeedback, + IGetVRPlayerObjects + { + [Serializable] + class Preferences + { + [SerializeField] + bool m_SphereMode; + + public bool sphereMode + { + get { return m_SphereMode; } + set { m_SphereMode = value; } + } + } + + const float k_MultiselectHueShift = 0.5f; + static readonly Vector3 k_TooltipPosition = new Vector3(0, -0.15f, -0.13f); + const float k_BLockSelectDragThreshold = 0.01f; + static readonly Quaternion k_TooltipRotation = Quaternion.AngleAxis(90, Vector3.right); + + [SerializeField] + Sprite m_Icon; + + [SerializeField] + ActionMap m_ActionMap; + + [SerializeField] + GameObject m_BlockSelectCube; + + [SerializeField] + GameObject m_BlockSelectSphere; + + [SerializeField] + GameObject m_SettingsMenuItemPrefab; + + Preferences m_Preferences; + + GameObject m_PressedObject; + + SelectionInput m_SelectionInput; + + float m_LastMultiSelectClickTime; + Color m_NormalRayColor; + Color m_MultiselectRayColor; + bool m_MultiSelect; + bool m_HasDirectHover; + bool m_BlockSelect; + Vector3 m_SelectStartPosition; + Renderer m_BlockSelectCubeRenderer; + + readonly BindingDictionary m_Controls = new BindingDictionary(); + readonly List m_SelectFeedback = new List(); + readonly List m_DirectSelectFeedback = new List(); + + Toggle m_CubeToggle; + Toggle m_SphereToggle; + bool m_BlockValueChangedListener; + + readonly Dictionary m_HoverGameObjects = new Dictionary(); + + readonly Dictionary m_SelectionHoverGameObjects = new Dictionary(); + readonly List m_BlockSelectHoverGameObjects = new List(); + + public ActionMap actionMap { get { return m_ActionMap; } } + public bool ignoreLocking { get { return false; } } + + public Transform rayOrigin { get; set; } + public Node node { private get; set; } + + public Sprite icon { get { return m_Icon; } } + + public event Action hovered; + + public List ignoreList { private get; set; } + public List linkedObjects { get; set; } + + public string tooltipText { get { return m_MultiSelect ? "Multi-Select Enabled" : ""; } } + public Transform tooltipTarget { get; private set; } + public Transform tooltipSource { get { return rayOrigin; } } + public TextAlignment tooltipAlignment { get { return TextAlignment.Center; } } + + public GameObject settingsMenuItemPrefab { get { return m_SettingsMenuItemPrefab; } } + + public GameObject settingsMenuItemInstance + { + set + { + var defaultToggleGroup = value.GetComponentInChildren(); + foreach (var toggle in value.GetComponentsInChildren()) + { + if (toggle == defaultToggleGroup.defaultToggle) + { + m_CubeToggle = toggle; + toggle.onValueChanged.AddListener(isOn => + { + if (m_BlockValueChangedListener) + return; + + // m_Preferences on all instances refer + m_Preferences.sphereMode = !isOn; + foreach (var linkedObject in linkedObjects) + { + var selectionTool = (SelectionTool)linkedObject; + if (selectionTool != this) + { + selectionTool.m_BlockValueChangedListener = true; + + //selectionTool.m_ToggleGroup.NotifyToggleOn(isOn ? m_CubeToggle : m_SphereToggle); + // HACK: Toggle Group claims these toggles are not a part of the group + selectionTool.m_CubeToggle.isOn = isOn; + selectionTool.m_SphereToggle.isOn = !isOn; + selectionTool.m_BlockValueChangedListener = false; + } + } + }); + } + else + { + m_SphereToggle = toggle; + } + } + } + } + + // Local method use only -- created here to reduce garbage collection + static readonly Dictionary k_TempHovers = new Dictionary(); + + void Start() + { + if (this.IsSharedUpdater(this) && m_Preferences == null) + { + m_Preferences = new Preferences(); + + // Share one preferences object across all instances + foreach (var linkedObject in linkedObjects) + { + ((SelectionTool)linkedObject).m_Preferences = m_Preferences; + } + } + + m_NormalRayColor = this.GetDefaultRayColor(rayOrigin); + m_MultiselectRayColor = m_NormalRayColor; + m_MultiselectRayColor = MaterialUtils.HueShift(m_MultiselectRayColor, k_MultiselectHueShift); + + tooltipTarget = ObjectUtils.CreateEmptyGameObject("SelectionTool Tooltip Target", rayOrigin).transform; + tooltipTarget.localPosition = k_TooltipPosition; + tooltipTarget.localRotation = k_TooltipRotation; + + m_BlockSelectCube = ObjectUtils.Instantiate(m_BlockSelectCube, transform); + m_BlockSelectCube.SetActive(false); + m_BlockSelectCubeRenderer = m_BlockSelectCube.GetComponent(); + + m_BlockSelectSphere = ObjectUtils.Instantiate(m_BlockSelectSphere, transform); + m_BlockSelectSphere.SetActive(false); + + InputUtils.GetBindingDictionaryFromActionMap(m_ActionMap, m_Controls); + } + + void OnDestroy() + { + ObjectUtils.Destroy(m_BlockSelectCube); + this.ClearFeedbackRequests(); + } + + public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl) + { + if (this.GetManipulatorDragState()) + return; + + m_SelectionInput = (SelectionInput)input; + + var multiSelectControl = m_SelectionInput.multiSelect; + if (this.GetDeviceType() == DeviceType.Vive) + multiSelectControl = m_SelectionInput.multiSelectAlt; + + if (multiSelectControl.wasJustPressed) + { + var realTime = Time.realtimeSinceStartup; + if (UIUtils.IsDoubleClick(realTime - m_LastMultiSelectClickTime)) + { + foreach (var linkedObject in linkedObjects) + { + var selectionTool = (SelectionTool)linkedObject; + selectionTool.m_MultiSelect = !selectionTool.m_MultiSelect; + this.HideTooltip(selectionTool); + } + + if (m_MultiSelect) + this.ShowTooltip(this); + } + + m_LastMultiSelectClickTime = realTime; + } + + this.SetDefaultRayColor(rayOrigin, m_MultiSelect ? m_MultiselectRayColor : m_NormalRayColor); + + if (this.IsSharedUpdater(this)) + { + this.SetManipulatorsVisible(this, !m_MultiSelect); + + m_SelectionHoverGameObjects.Clear(); + foreach (var linkedObject in linkedObjects) + { + var selectionTool = (SelectionTool)linkedObject; + selectionTool.m_HasDirectHover = false; // Clear old hover state + + if (selectionTool.m_BlockSelect) + continue; + + if (!selectionTool.IsRayActive()) + continue; + + var selectionRayOrigin = selectionTool.rayOrigin; + + var hover = this.GetFirstGameObject(selectionRayOrigin); + + if (!selectionTool.GetSelectionCandidate(ref hover)) + continue; + + if (hover) + { + GameObject lastHover; + if (m_HoverGameObjects.TryGetValue(selectionRayOrigin, out lastHover) && lastHover != hover) + this.SetHighlight(lastHover, false, selectionRayOrigin); + + m_SelectionHoverGameObjects[selectionRayOrigin] = hover; + m_HoverGameObjects[selectionRayOrigin] = hover; + } + } + + var directSelection = this.GetDirectSelection(); + + // Unset highlight old hovers + k_TempHovers.Clear(); + foreach (var kvp in m_HoverGameObjects) + { + k_TempHovers[kvp.Key] = kvp.Value; + } + + foreach (var kvp in k_TempHovers) + { + var directRayOrigin = kvp.Key; + var hover = kvp.Value; + + if (!directSelection.ContainsKey(directRayOrigin) + && !m_SelectionHoverGameObjects.ContainsKey(directRayOrigin)) + { + this.SetHighlight(hover, false, directRayOrigin); + m_HoverGameObjects.Remove(directRayOrigin); + } + } + + // Find new hovers + foreach (var kvp in directSelection) + { + var directRayOrigin = kvp.Key; + var directHoveredObject = kvp.Value; + + var directSelectionCandidate = this.GetSelectionCandidate(directHoveredObject, true); + + // Can't select this object (it might be locked or static) + if (directHoveredObject && !directSelectionCandidate) + { + if (directHoveredObject != null) + this.SetHighlight(directHoveredObject, false); + + continue; + } + + if (directSelectionCandidate) + directHoveredObject = directSelectionCandidate; + + if (!this.CanGrabObject(directHoveredObject, directRayOrigin)) + continue; + + var grabbingNode = this.RequestNodeFromRayOrigin(directRayOrigin); + var selectionTool = linkedObjects.Cast().FirstOrDefault(linkedObject => linkedObject.node == grabbingNode); + if (selectionTool == null) + continue; + + if (selectionTool.m_BlockSelect) + continue; + + GameObject lastHover; + if (m_HoverGameObjects.TryGetValue(directRayOrigin, out lastHover) && lastHover != directHoveredObject) + this.SetHighlight(lastHover, false, directRayOrigin); + + if (!selectionTool.IsDirectActive()) + { + m_HoverGameObjects.Remove(directRayOrigin); + this.SetHighlight(directHoveredObject, false, directRayOrigin); + continue; + } + + // Only overwrite an existing selection if it does not contain the hovered object + // In the case of multi-select, only add, do not remove + if (selectionTool.m_SelectionInput.select.wasJustPressed && !Selection.objects.Contains(directHoveredObject)) + this.SelectObject(directHoveredObject, directRayOrigin, m_MultiSelect); + + m_HoverGameObjects[directRayOrigin] = directHoveredObject; + selectionTool.m_HasDirectHover = true; + } + + // Set highlight on new hovers + foreach (var hover in m_HoverGameObjects) + { + this.SetHighlight(hover.Value, true, hover.Key); + } + } + + if (!m_HasDirectHover) + HideDirectSelectFeedback(); + else if (m_DirectSelectFeedback.Count == 0) + ShowDirectSelectFeedback(); + + GameObject hoveredObject = null; + var rayActive = IsRayActive(); + if (rayActive) + { + // Need to call GetFirstGameObject a second time because we do not guarantee shared updater executes first + hoveredObject = this.GetFirstGameObject(rayOrigin); + + if (hovered != null) + hovered(hoveredObject, rayOrigin); + + GetSelectionCandidate(ref hoveredObject); + + if (hoveredObject && this.GetVRPlayerObjects().Contains(hoveredObject)) + hoveredObject = null; + } + + if (!hoveredObject) + HideSelectFeedback(); + else if (m_SelectFeedback.Count == 0) + ShowSelectFeedback(); + + var pointerPosition = this.GetPointerPosition(rayOrigin); + + // Capture object on press + var select = m_SelectionInput.select; + if (select.wasJustPressed) + { + m_SelectStartPosition = pointerPosition; + + // Ray selection only if ray is visible + m_PressedObject = hoveredObject; + } + + if (select.isHeld) + { + var startToEnd = pointerPosition - m_SelectStartPosition; + var visuals = m_Preferences.sphereMode ? m_BlockSelectSphere : m_BlockSelectCube; + var distance = startToEnd.magnitude; + if (!m_BlockSelect && distance > k_BLockSelectDragThreshold * this.GetViewerScale()) + { + m_BlockSelect = true; + visuals.SetActive(true); + + m_PressedObject = null; + this.AddRayVisibilitySettings(rayOrigin, this, false, true); + this.SetUIBlockedForRayOrigin(rayOrigin, true); + } + + if (m_BlockSelect) + this.SetManipulatorsVisible(this, false); + + //TODO: use hashsets to only unset highlights for removed objects + foreach (var hover in m_BlockSelectHoverGameObjects) + { + this.SetHighlight(hover, false, rayOrigin); + } + m_BlockSelectHoverGameObjects.Clear(); + + var visualsTransform = visuals.transform; + if (m_Preferences.sphereMode) + { + visualsTransform.localScale = Vector3.one * distance * 2; + visualsTransform.position = m_SelectStartPosition; + this.CheckSphere(m_SelectStartPosition, distance, m_BlockSelectHoverGameObjects, ignoreList); + } + else + { + visualsTransform.localScale = startToEnd; + visualsTransform.position = m_SelectStartPosition + startToEnd * 0.5f; + this.CheckBounds(m_BlockSelectCubeRenderer.bounds, m_BlockSelectHoverGameObjects, ignoreList); + } + + foreach (var hover in m_BlockSelectHoverGameObjects) + { + this.SetHighlight(hover, true, rayOrigin); + } + + if (m_BlockSelect) + consumeControl(select); + } + + // Make selection on release + if (select.wasJustReleased) + { + if (m_BlockSelect) + { + if (!m_MultiSelect) + { + this.SetManipulatorsVisible(this, true); + Selection.activeGameObject = null; + } + + this.SelectObjects(m_BlockSelectHoverGameObjects, rayOrigin, m_MultiSelect); + + foreach (var hover in m_BlockSelectHoverGameObjects) + { + if (hover != null) + this.SetHighlight(hover, false, rayOrigin); + } + + this.ResetDirectSelectionState(); + } + else if (rayActive) + { + if (m_PressedObject == hoveredObject) + { + this.SelectObject(m_PressedObject, rayOrigin, m_MultiSelect, true); + this.ResetDirectSelectionState(); + + if (m_PressedObject != null) + this.SetHighlight(m_PressedObject, false, rayOrigin); + } + + if (m_PressedObject) + consumeControl(select); + } + + this.SetUIBlockedForRayOrigin(rayOrigin, false); + this.RemoveRayVisibilitySettings(rayOrigin, this); + (m_Preferences.sphereMode ? m_BlockSelectSphere : m_BlockSelectCube).SetActive(false); + m_PressedObject = null; + m_BlockSelect = false; + } + } + + bool GetSelectionCandidate(ref GameObject hoveredObject) + { + var selectionCandidate = this.GetSelectionCandidate(hoveredObject, true); + + // Can't select this object (it might be locked or static) + if (hoveredObject && !selectionCandidate) + { + if (hoveredObject != null) + this.SetHighlight(hoveredObject, false); + + return false; + } + + if (selectionCandidate) + hoveredObject = selectionCandidate; + + return true; + } + + bool IsDirectActive() + { + if (rayOrigin == null) + return false; + + if (!this.IsConeVisible(rayOrigin)) + return false; + + if (this.IsInMiniWorld(rayOrigin)) + return true; + + if (this.IsMainMenuVisible(rayOrigin)) + return false; + + return true; + } + + bool IsRayActive() + { + if (rayOrigin == null) + return false; + + if (this.IsHoveringOverUI(rayOrigin)) + return false; + + if (this.IsMainMenuVisible(rayOrigin)) + return false; + + if (this.IsInMiniWorld(rayOrigin)) + return false; + + if (!this.IsRayVisible(rayOrigin)) + return false; + + return true; + } + + void OnDisable() + { + foreach (var kvp in m_HoverGameObjects) + { + this.SetHighlight(kvp.Value, false, kvp.Key); + } + m_HoverGameObjects.Clear(); + } + + public void OnResetDirectSelectionState() { } + + public object OnSerializePreferences() + { + if (this.IsSharedUpdater(this)) + { + // Share one preferences object across all instances + foreach (var linkedObject in linkedObjects) + { + ((SelectionTool)linkedObject).m_Preferences = m_Preferences; + } + + return m_Preferences; + } + + return null; + } + + public void OnDeserializePreferences(object obj) + { + if (this.IsSharedUpdater(this)) + { + var preferences = obj as Preferences; + if (preferences != null) + m_Preferences = preferences; + + // Share one preferences object across all instances + foreach (var linkedObject in linkedObjects) + { + ((SelectionTool)linkedObject).m_Preferences = m_Preferences; + } + + m_SphereToggle.isOn = m_Preferences.sphereMode; + m_CubeToggle.isOn = !m_Preferences.sphereMode; + } + } + + void ShowFeedback(List requests, string controlName, string tooltipText = null) + { + if (tooltipText == null) + tooltipText = controlName; + + List ids; + if (m_Controls.TryGetValue(controlName, out ids)) + { + foreach (var id in ids) + { + var request = new ProxyFeedbackRequest + { + node = node, + control = id, + tooltipText = tooltipText + }; + + this.AddFeedbackRequest(request); + requests.Add(request); + } + } + } + + void ShowSelectFeedback() + { + ShowFeedback(m_SelectFeedback, "Select"); + } + + void ShowDirectSelectFeedback() + { + ShowFeedback(m_DirectSelectFeedback, "Select", "Direct Select"); + } + + void HideFeedback(List requests) + { + foreach (var request in requests) + { + this.RemoveFeedbackRequest(request); + } + requests.Clear(); + } + + void HideSelectFeedback() + { + HideFeedback(m_SelectFeedback); + } + + void HideDirectSelectFeedback() + { + HideFeedback(m_DirectSelectFeedback); + } + } +} +#endif From d8d18a80b48a79224ac759070992f565c560cd99 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Fri, 8 Dec 2017 02:16:49 -0800 Subject: [PATCH 69/89] Fix issue where undo menu isn't hidden by BrushSizeUI; Fix issue where alternate menus can overlap the Tools Menu; Remove left/right to undo/redo in AnnotationTool; Consume stick press input in LocomotionTool while two-handed-scaling --- Scripts/Core/EditorVR.Menus.cs | 36 ++++++++++++++------------ Tools/AnnotationTool/AnnotationTool.cs | 33 ++--------------------- Tools/LocomotionTool/LocomotionTool.cs | 7 +++-- 3 files changed, 24 insertions(+), 52 deletions(-) diff --git a/Scripts/Core/EditorVR.Menus.cs b/Scripts/Core/EditorVR.Menus.cs index 274480c8d..5218335ee 100644 --- a/Scripts/Core/EditorVR.Menus.cs +++ b/Scripts/Core/EditorVR.Menus.cs @@ -143,8 +143,8 @@ static void AddCustomAlternateMenu(IAlternateMenu alternateMenu, Transform rayOr foreach (var device in evr.m_DeviceData) { if (device.rayOrigin != rayOrigin) - continue; - + continue; + device.alternateMenus.Add(alternateMenu); var menuHideData = new MenuHideData(); device.menuHideData[alternateMenu] = menuHideData; @@ -221,21 +221,20 @@ internal void UpdateMenuVisibilities() IAlternateMenu alternateMenu = null; var menuHideData = deviceData.menuHideData; // Always display the highest-priority alternate menu, and hide all others. - foreach (var menu in deviceData.alternateMenus) + var alternateMenus = deviceData.alternateMenus; + foreach (var menu in alternateMenus) { - if ((menuHideData[menu].hideFlags & MenuHideFlags.Hidden) == 0 + var hideData = menuHideData[menu]; + if ((hideData.hideFlags & MenuHideFlags.Hidden) == 0 && (alternateMenu == null || menu.priority >= alternateMenu.priority)) - { alternateMenu = menu; - menuHideData[alternateMenu].hideFlags = 0; - deviceData.alternateMenu = alternateMenu; - } - else - { - menuHideData[menu].hideFlags |= MenuHideFlags.OtherMenu; - } + + hideData.hideFlags |= MenuHideFlags.OtherMenu; } - + + deviceData.alternateMenu = alternateMenu; + menuHideData[alternateMenu].hideFlags = 0; + var mainMenu = deviceData.mainMenu; var customMenu = deviceData.customMenu; MenuHideData customMenuHideData = null; @@ -423,10 +422,13 @@ static void CheckMenuColliderOverlaps(IMenu menu, MenuHideData menuHideData) if (k_WorkspaceComponents.Count > 0) hoveringCollider = true; - k_ButtonComponents.Clear(); - overlap.GetComponents(k_ButtonComponents); - if (k_ButtonComponents.Count > 0) - hoveringCollider = true; + if (menu is MainMenu) + { + k_ButtonComponents.Clear(); + overlap.GetComponents(k_ButtonComponents); + if (k_ButtonComponents.Count > 0) + hoveringCollider = true; + } } } } diff --git a/Tools/AnnotationTool/AnnotationTool.cs b/Tools/AnnotationTool/AnnotationTool.cs index 98721ceb8..7b2598fb9 100644 --- a/Tools/AnnotationTool/AnnotationTool.cs +++ b/Tools/AnnotationTool/AnnotationTool.cs @@ -340,13 +340,14 @@ void SetupBrushUI() m_BrushSizeUI = brushSizeUi.GetComponent(); var transform = brushSizeUi.transform; - localBounds = ObjectUtils.GetBounds(transform); var scale = transform.localScale; transform.SetParent(alternateMenuOrigin, false); transform.localPosition = Vector3.zero; transform.localRotation = Quaternion.Euler(-90, 0, 0); transform.localScale = scale; + localBounds = ObjectUtils.GetBounds(transform); + m_BrushSizeUI.onValueChanged = value => { var sliderValue = Mathf.Lerp(MinBrushSize, MaxBrushSize, value); @@ -748,36 +749,6 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon consumeControl(draw); } } - else - { - // Secondary hand uses brush size input to do undo/redo - var value = annotationInput.changeBrushSize.value; - if (this.GetDeviceType() == DeviceType.Vive) - { - if (annotationInput.stickButton.wasJustPressed) - { - if (value > 0) - Undo.PerformRedo(); - else - Undo.PerformUndo(); - } - } - else - { - var doUndoRedo = Math.Abs(value) > 0.5f; - if (doUndoRedo != m_WasDoingUndoRedo) - { - m_WasDoingUndoRedo = doUndoRedo; - if (doUndoRedo) - { - if (value > 0) - Undo.PerformRedo(); - else - Undo.PerformUndo(); - } - } - } - } if (isHeld) return; diff --git a/Tools/LocomotionTool/LocomotionTool.cs b/Tools/LocomotionTool/LocomotionTool.cs index 82f68b857..69714862a 100644 --- a/Tools/LocomotionTool/LocomotionTool.cs +++ b/Tools/LocomotionTool/LocomotionTool.cs @@ -607,6 +607,9 @@ bool DoTwoHandedScaling(ConsumeControlDelegate consumeControl) consumeControl(otherLocomotionInput.horizontal); consumeControl(otherLocomotionInput.vertical); + consumeControl(m_LocomotionInput.scaleReset); + consumeControl(otherLocomotionInput.scaleReset); + var thisPosition = cameraRig.InverseTransformPoint(rayOrigin.position); var otherRayOrigin = otherLocomotionTool.rayOrigin; var otherPosition = cameraRig.InverseTransformPoint(otherRayOrigin.position); @@ -657,13 +660,9 @@ bool DoTwoHandedScaling(ConsumeControlDelegate consumeControl) var scaleReset = m_LocomotionInput.scaleReset; var scaleResetHeld = scaleReset.isHeld; - if (scaleResetHeld) - consumeControl(scaleReset); var otherScaleReset = otherLocomotionInput.scaleReset; var otherScaleResetHeld = otherScaleReset.isHeld; - if (otherScaleResetHeld) - consumeControl(otherScaleReset); // Press both thumb buttons to reset scale if (scaleResetHeld && otherScaleResetHeld) From b5538daac82138ee7a07ddb76d6b444e71f1379b Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Fri, 8 Dec 2017 02:24:38 -0800 Subject: [PATCH 70/89] Fix line endings; Remove IActionsMenu from IMainMenu --- Menus/MainMenu/MainMenu.cs | 2 -- Scripts/Interfaces/Entity/IMainMenu.cs | 2 +- Scripts/Modules/FeedbackModule/FeedbackModule.cs | 6 +++--- Workspaces/PolyWorkspace/Scripts/PolyGridItem.cs | 4 ++-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Menus/MainMenu/MainMenu.cs b/Menus/MainMenu/MainMenu.cs index 99e78779f..13cdbee2e 100644 --- a/Menus/MainMenu/MainMenu.cs +++ b/Menus/MainMenu/MainMenu.cs @@ -56,8 +56,6 @@ sealed class MainMenu : MonoBehaviour, IMainMenu, IConnectInterfaces, IInstantia public List menuWorkspaces { private get; set; } public Dictionary, ISettingsMenuProvider> settingsMenuProviders { get; set; } public Dictionary, ISettingsMenuItemProvider> settingsMenuItemProviders { get; set; } - public List menuActions { get; set; } - public event Action itemWasSelected; public Transform targetRayOrigin { private get; set; } public Node node { get; set; } diff --git a/Scripts/Interfaces/Entity/IMainMenu.cs b/Scripts/Interfaces/Entity/IMainMenu.cs index 7e93d6996..da4c94b13 100644 --- a/Scripts/Interfaces/Entity/IMainMenu.cs +++ b/Scripts/Interfaces/Entity/IMainMenu.cs @@ -8,7 +8,7 @@ namespace UnityEditor.Experimental.EditorVR /// /// The main menu that can be shown on device proxies /// - public interface IMainMenu : IMenu, IActionsMenu, ISelectTool, IPreviewInToolsMenuButton + public interface IMainMenu : IMenu, ISelectTool, IPreviewInToolsMenuButton { /// /// The menu tools that will populate the menu diff --git a/Scripts/Modules/FeedbackModule/FeedbackModule.cs b/Scripts/Modules/FeedbackModule/FeedbackModule.cs index 6770df03e..2d96d7b83 100644 --- a/Scripts/Modules/FeedbackModule/FeedbackModule.cs +++ b/Scripts/Modules/FeedbackModule/FeedbackModule.cs @@ -56,8 +56,8 @@ public GameObject settingsMenuItemInstance if (m_Preferences != null) toggle.isOn = m_Preferences.enabled; - m_Toggles.Add(toggle); - + m_Toggles.Add(toggle); + #if INCLUDE_TEXT_MESH_PRO var label = value.GetComponentInChildren(); @@ -74,7 +74,7 @@ public GameObject settingsMenuItemInstance var handle = value.GetComponent(); handle.hoverStarted += (baseHandle, data) => { label.text = m_Preferences.enabled ? disableFeedback : enableFeedback; }; - handle.hoverEnded += (baseHandle, data) => { label.text = m_Preferences.enabled ? feedbackEnabled : feedbackDisabled; }; + handle.hoverEnded += (baseHandle, data) => { label.text = m_Preferences.enabled ? feedbackEnabled : feedbackDisabled; }; #endif } } diff --git a/Workspaces/PolyWorkspace/Scripts/PolyGridItem.cs b/Workspaces/PolyWorkspace/Scripts/PolyGridItem.cs index 813a33bf9..553ee3a78 100644 --- a/Workspaces/PolyWorkspace/Scripts/PolyGridItem.cs +++ b/Workspaces/PolyWorkspace/Scripts/PolyGridItem.cs @@ -488,7 +488,7 @@ IEnumerator ShowGrabbedObject() yield break; // Exit coroutine if m_GrabbedObject is destroyed before the loop is finished currentTime += Time.deltaTime; - m_DragObject.localScale = Vector3.Lerp(currentLocalScale, targetScale, + m_DragObject.localScale = Vector3.Lerp(currentLocalScale, targetScale, MathUtilsExt.SmoothInOutLerpFloat(currentTime / duration)); if (m_PreviewObjectClone) @@ -500,7 +500,7 @@ IEnumerator ShowGrabbedObject() yield return null; } - m_DragObject.localScale = targetScale; + m_DragObject.localScale = targetScale; //No need to hard-set the preview object position/rotation because they will set in OnDragging in parent class } From 9e0fa057b1470f001791796d668f0f93e50318d4 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Fri, 8 Dec 2017 02:29:37 -0800 Subject: [PATCH 71/89] Fix issue where tools menu didn't return to its initial state when hiding the radial menu --- Scripts/Core/EditorVR.Menus.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Scripts/Core/EditorVR.Menus.cs b/Scripts/Core/EditorVR.Menus.cs index a9fc1e8ce..06b8afd40 100644 --- a/Scripts/Core/EditorVR.Menus.cs +++ b/Scripts/Core/EditorVR.Menus.cs @@ -177,8 +177,7 @@ static void UpdateAlternateMenuForDevice(DeviceData deviceData) alternateMenu.menuHideFlags = deviceData.currentTool is IExclusiveMode ? 0 : deviceData.menuHideData[alternateMenu].hideFlags; // Move the Tools Menu buttons to an alternate position if the radial menu will be shown - if (alternateMenu is RadialMenu) - deviceData.toolsMenu.alternateMenuVisible = alternateMenu.menuHideFlags == 0; + deviceData.toolsMenu.alternateMenuVisible = alternateMenu.menuHideFlags == 0 && alternateMenu is RadialMenu; } static Transform GetCustomMenuOrigin(Transform rayOrigin) From 99378d590d803de4b236438fe0130ca5a2577a0c Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Fri, 8 Dec 2017 02:41:40 -0800 Subject: [PATCH 72/89] Fix null reference exception when undoing annotations and trying to draw the next one; Remove undo/redo buttons from AnnotationUI --- Tools/AnnotationTool/AnnotationTool.cs | 4 - .../Prefabs/AnnotationUI.prefab | 1500 +---------------- .../UserInterface/ColorPickerActivator.cs | 42 - 3 files changed, 92 insertions(+), 1454 deletions(-) diff --git a/Tools/AnnotationTool/AnnotationTool.cs b/Tools/AnnotationTool/AnnotationTool.cs index 889991ba4..c04e5f086 100644 --- a/Tools/AnnotationTool/AnnotationTool.cs +++ b/Tools/AnnotationTool/AnnotationTool.cs @@ -282,9 +282,6 @@ void Start() activator.showColorPicker = ShowColorPicker; activator.hideColorPicker = HideColorPicker; - activator.undoButtonClick += Undo.PerformUndo; - activator.redoButtonClick += Undo.PerformRedo; - var controls = new BindingDictionary(); InputUtils.GetBindingDictionaryFromActionMap(m_ActionMap, controls); @@ -451,7 +448,6 @@ void SetupHolder() if (!newSession) { newSession = new GameObject(string.Format(k_GroupFormatString, m_AnnotationRoot.childCount)); - Undo.RegisterCreatedObjectUndo(newSession, "Annotation"); newSession.transform.position = GetPointerPosition(); m_Groups.Add(newSession); } diff --git a/Tools/AnnotationTool/Prefabs/AnnotationUI.prefab b/Tools/AnnotationTool/Prefabs/AnnotationUI.prefab index 0ea924413..d09b90573 100644 --- a/Tools/AnnotationTool/Prefabs/AnnotationUI.prefab +++ b/Tools/AnnotationTool/Prefabs/AnnotationUI.prefab @@ -241,40 +241,6 @@ GameObject: m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!1 &1036881825388254 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 224393326463988594} - - component: {fileID: 222928571895566388} - - component: {fileID: 114395512104104094} - m_Layer: 5 - m_Name: Text - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 0 ---- !u!1 &1099690223586730 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 4940108482629240} - - component: {fileID: 33257561653289390} - - component: {fileID: 23652728190552066} - m_Layer: 0 - m_Name: ButtonMesh - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 --- !u!1 &1136647751248060 GameObject: m_ObjectHideFlags: 1 @@ -292,88 +258,6 @@ GameObject: m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!1 &1141551173516660 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 224963898299502848} - - component: {fileID: 222582790420601646} - - component: {fileID: 114007618893444894} - m_Layer: 5 - m_Name: Text - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 0 ---- !u!1 &1167948277449984 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 224333717671022096} - - component: {fileID: 33699724321051718} - - component: {fileID: 23309274037775718} - - component: {fileID: 114168715074745758} - - component: {fileID: 65270067782407046} - m_Layer: 5 - m_Name: Base - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &1187994386522324 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 4066649049098668} - m_Layer: 5 - m_Name: TooltipSource - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &1279537530764624 -GameObject: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 4230552379396688} - - component: {fileID: 114543901646842364} - m_Layer: 5 - m_Name: Undo - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &1329748470766914 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 4670339961100958} - m_Layer: 5 - m_Name: RotationPivot - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 --- !u!1 &1346101208067254 GameObject: m_ObjectHideFlags: 0 @@ -391,216 +275,6 @@ GameObject: m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!1 &1347799845701476 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 4702350181192430} - m_Layer: 5 - m_Name: TooltipSource - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &1361017080451862 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 4572708185800628} - - component: {fileID: 33824803535794784} - - component: {fileID: 23437852442812966} - m_Layer: 0 - m_Name: ButtonMesh - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &1365241548943880 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 224107373598291132} - - component: {fileID: 33095966663817246} - - component: {fileID: 23375274514904506} - - component: {fileID: 114257755424135964} - - component: {fileID: 65378884854788314} - m_Layer: 5 - m_Name: Base - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &1382527450794256 -GameObject: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 4843657865520138} - - component: {fileID: 114824239518982862} - m_Layer: 5 - m_Name: Redo - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &1411372913666494 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 224860733548256162} - - component: {fileID: 225914373114193260} - - component: {fileID: 223499351256631318} - m_Layer: 5 - m_Name: ButtonContentContainer - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &1430967031119936 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 224638576672757326} - - component: {fileID: 222975643046639372} - - component: {fileID: 114967506099497140} - m_Layer: 5 - m_Name: Icon - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &1482568457756204 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 224939432255965946} - m_Layer: 5 - m_Name: IconContainer - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &1490901763651664 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 4796074920551568} - m_Layer: 5 - m_Name: RotationPivot - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &1603094234734992 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 224124519857189990} - - component: {fileID: 225328779711015670} - - component: {fileID: 223502477285382174} - m_Layer: 5 - m_Name: ButtonContentContainer - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &1619517534170012 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 224388597326433990} - - component: {fileID: 222227951865979474} - - component: {fileID: 114481225842932662} - m_Layer: 5 - m_Name: Icon - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &1863793980498380 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 4166573009768210} - m_Layer: 5 - m_Name: TooltipTarget - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &1887300028592862 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 224878234700512394} - m_Layer: 5 - m_Name: IconContainer - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &1913076707455610 -GameObject: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - serializedVersion: 5 - m_Component: - - component: {fileID: 4602986436310456} - m_Layer: 5 - m_Name: TooltipTarget - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 --- !u!4 &4000010343588658 Transform: m_ObjectHideFlags: 1 @@ -643,359 +317,77 @@ Transform: - {fileID: 4000010343588658} m_Father: {fileID: 4626871607531114} m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &4000012841704540 -Transform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000010255295176} - 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_Children: - - {fileID: 4626871607531114} - - {fileID: 4230552379396688} - - {fileID: 4843657865520138} - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &4000013117727556 -Transform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000012208465784} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0} - m_LocalScale: {x: 4, y: 1, z: 4} - m_Children: [] - m_Father: {fileID: 4626871607531114} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &4066649049098668 -Transform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1187994386522324} - m_LocalRotation: {x: 0.7071068, y: -0, z: -0, w: 0.7071068} - m_LocalPosition: {x: 0.01267001, y: 0.00078000035, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 4230552379396688} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} ---- !u!4 &4166573009768210 -Transform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1863793980498380} - m_LocalRotation: {x: 0.7071068, y: -0, z: -0, w: 0.7071068} - m_LocalPosition: {x: 0.025, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 4843657865520138} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} ---- !u!4 &4230552379396688 -Transform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1279537530764624} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0.006864082, y: 0.0018081665, z: 0.00087684765} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 4602986436310456} - - {fileID: 4066649049098668} - - {fileID: 4670339961100958} - m_Father: {fileID: 4000012841704540} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &4572708185800628 -Transform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1361017080451862} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: -0, z: 0.00009} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 224939432255965946} - m_Father: {fileID: 224860733548256162} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &4602986436310456 -Transform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1913076707455610} - m_LocalRotation: {x: 0.7071068, y: -0, z: -0, w: 0.7071068} - m_LocalPosition: {x: 0.025, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 4230552379396688} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} ---- !u!4 &4626871607531114 -Transform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1346101208067254} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0.006864082, y: 0.0018081665, z: -0.032373153} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 4000013117727556} - - {fileID: 4000012336507532} - m_Father: {fileID: 4000012841704540} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &4663617041298854 -Transform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1136647751248060} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0.0004, z: 0} - m_LocalScale: {x: 0.5, y: 0.25, z: 0.5} - m_Children: [] - m_Father: {fileID: 4000012336507532} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &4670339961100958 -Transform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1329748470766914} - m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071068} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 224107373598291132} - - {fileID: 224124519857189990} - m_Father: {fileID: 4230552379396688} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: -90, y: 0, z: 0} ---- !u!4 &4702350181192430 -Transform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1347799845701476} - m_LocalRotation: {x: 0.7071068, y: -0, z: -0, w: 0.7071068} - m_LocalPosition: {x: 0.01267001, y: 0.00078000035, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 4843657865520138} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} ---- !u!4 &4796074920551568 -Transform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1490901763651664} - m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071068} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 224333717671022096} - - {fileID: 224860733548256162} - m_Father: {fileID: 4843657865520138} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: -90, y: 0, z: 0} ---- !u!4 &4843657865520138 -Transform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1382527450794256} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0.006864082, y: 0.0018081665, z: 0.029026847} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 4166573009768210} - - {fileID: 4702350181192430} - - {fileID: 4796074920551568} - m_Father: {fileID: 4000012841704540} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &4940108482629240 -Transform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1099690223586730} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: -0, z: 0.00009} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 224878234700512394} - m_Father: {fileID: 224124519857189990} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!23 &23000011095290868 -MeshRenderer: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000011463743810} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_Materials: - - {fileID: 2100000, guid: ed6062fbd167bed46b70b3ae75c81624, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_PreserveUVs: 1 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 0 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!23 &23309274037775718 -MeshRenderer: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1167948277449984} - m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_MotionVectors: 0 - m_LightProbeUsage: 0 - m_ReflectionProbeUsage: 0 - m_Materials: - - {fileID: 2100000, guid: 6adae681ad457e140ac31a9ac83c3a11, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 0 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!23 &23375274514904506 -MeshRenderer: + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4000012841704540 +Transform: m_ObjectHideFlags: 1 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1365241548943880} - m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_MotionVectors: 0 - m_LightProbeUsage: 0 - m_ReflectionProbeUsage: 0 - m_Materials: - - {fileID: 2100000, guid: 6adae681ad457e140ac31a9ac83c3a11, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 0 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!23 &23437852442812966 -MeshRenderer: + m_GameObject: {fileID: 1000010255295176} + 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_Children: + - {fileID: 4626871607531114} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4000013117727556 +Transform: m_ObjectHideFlags: 1 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1361017080451862} - m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_MotionVectors: 0 - m_LightProbeUsage: 0 - m_ReflectionProbeUsage: 0 - m_Materials: - - {fileID: 2100000, guid: 38860ca708e7b5641ace5d1ed4e7c0fc, type: 2} - - {fileID: 2100000, guid: 7c873c9977af7044aa1412eb381756f8, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 0 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!23 &23652728190552066 + m_GameObject: {fileID: 1000012208465784} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -0} + m_LocalScale: {x: 4, y: 1, z: 4} + m_Children: [] + m_Father: {fileID: 4626871607531114} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4626871607531114 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1346101208067254} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.006864082, y: 0.0018081665, z: -0.032373153} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4000013117727556} + - {fileID: 4000012336507532} + m_Father: {fileID: 4000012841704540} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4663617041298854 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1136647751248060} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.0004, z: 0} + m_LocalScale: {x: 0.5, y: 0.25, z: 0.5} + m_Children: [] + m_Father: {fileID: 4000012336507532} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &23000011095290868 MeshRenderer: m_ObjectHideFlags: 1 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1099690223586730} + m_GameObject: {fileID: 1000011463743810} m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 + m_CastShadows: 1 + m_ReceiveShadows: 1 m_DynamicOccludee: 1 - m_MotionVectors: 0 - m_LightProbeUsage: 0 - m_ReflectionProbeUsage: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 m_Materials: - - {fileID: 2100000, guid: 38860ca708e7b5641ace5d1ed4e7c0fc, type: 2} - - {fileID: 2100000, guid: 7c873c9977af7044aa1412eb381756f8, type: 2} + - {fileID: 2100000, guid: ed6062fbd167bed46b70b3ae75c81624, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -1003,7 +395,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 - m_PreserveUVs: 0 + m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -1056,34 +448,6 @@ MeshFilter: m_PrefabInternal: {fileID: 100100000} m_GameObject: {fileID: 1000011463743810} m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!33 &33095966663817246 -MeshFilter: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1365241548943880} - m_Mesh: {fileID: 4300050, guid: 4f7e1c38dff4db9449be30d253d1bd8f, type: 3} ---- !u!33 &33257561653289390 -MeshFilter: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1099690223586730} - m_Mesh: {fileID: 4300000, guid: 7f7c3987753e1bf41bee70661b3eff03, type: 3} ---- !u!33 &33699724321051718 -MeshFilter: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1167948277449984} - m_Mesh: {fileID: 4300050, guid: 4f7e1c38dff4db9449be30d253d1bd8f, type: 3} ---- !u!33 &33824803535794784 -MeshFilter: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1361017080451862} - m_Mesh: {fileID: 4300000, guid: 7f7c3987753e1bf41bee70661b3eff03, type: 3} --- !u!33 &33923684612379296 MeshFilter: m_ObjectHideFlags: 1 @@ -1103,30 +467,6 @@ BoxCollider: serializedVersion: 2 m_Size: {x: 945.4, y: 1268, z: 10} m_Center: {x: 0, y: 0, z: 0} ---- !u!65 &65270067782407046 -BoxCollider: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1167948277449984} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 0.1, y: 0.0028786354, z: 0.07} - m_Center: {x: 0, y: -0.00000005960467, z: 0.000000008381907} ---- !u!65 &65378884854788314 -BoxCollider: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1365241548943880} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 0.1, y: 0.0028786354, z: 0.07} - m_Center: {x: 0, y: -0.00000005960467, z: 0.000000008381907} --- !u!114 &114000010240686482 MonoBehaviour: m_ObjectHideFlags: 1 @@ -1362,428 +702,71 @@ MonoBehaviour: m_IntArgument: 0 m_FloatArgument: 0 m_StringArgument: - m_BoolArgument: 0 - m_CallState: 1 - m_TypeName: UnityEngine.UI.Slider+SliderEvent, UnityEngine.UI, Version=1.0.0.0, - Culture=neutral, PublicKeyToken=null ---- !u!114 &114000013248295880 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000011582997490} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: -98529514, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, - Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_Texture: {fileID: 0} - m_UVRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 ---- !u!114 &114000013959281966 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000010117119988} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 1980459831, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} - m_Name: - m_EditorClassIdentifier: - m_UiScaleMode: 0 - m_ReferencePixelsPerUnit: 100 - m_ScaleFactor: 1 - m_ReferenceResolution: {x: 800, y: 600} - m_ScreenMatchMode: 0 - m_MatchWidthOrHeight: 0 - m_PhysicalUnit: 3 - m_FallbackScreenDPI: 96 - m_DefaultSpriteDPI: 96 - m_DynamicPixelsPerUnit: 1 ---- !u!114 &114007618893444894 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1141551173516660} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 0 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, - Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_text: A - m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: 21452896fabdc4e4ea06c09c6ac05c9e, type: 2} - m_sharedMaterial: {fileID: 2100000, guid: 2800c3c40f001db459e655626fba97bf, type: 2} - m_fontSharedMaterials: [] - m_fontMaterial: {fileID: 0} - m_fontMaterials: [] - m_fontColor32: - serializedVersion: 2 - rgba: 4294967295 - m_fontColor: {r: 1, g: 1, b: 1, a: 1} - m_enableVertexGradient: 0 - m_fontColorGradient: - topLeft: {r: 1, g: 1, b: 1, a: 1} - topRight: {r: 1, g: 1, b: 1, a: 1} - bottomLeft: {r: 1, g: 1, b: 1, a: 1} - bottomRight: {r: 1, g: 1, b: 1, a: 1} - m_fontColorGradientPreset: {fileID: 0} - m_spriteAsset: {fileID: 0} - m_tintAllSprites: 0 - m_overrideHtmlColors: 0 - m_faceColor: - serializedVersion: 2 - rgba: 4294967295 - m_outlineColor: - serializedVersion: 2 - rgba: 4278190080 - m_fontSize: 203.4 - m_fontSizeBase: 36 - m_fontWeight: 400 - m_enableAutoSizing: 1 - m_fontSizeMin: 0 - m_fontSizeMax: 250 - m_fontStyle: 0 - m_textAlignment: 514 - m_isAlignmentEnumConverted: 1 - m_characterSpacing: 0 - m_wordSpacing: 0 - m_lineSpacing: 1 - m_lineSpacingMax: 0 - m_paragraphSpacing: 0 - m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 - m_wordWrappingRatios: 0.4 - m_overflowMode: 3 - m_firstOverflowCharacterIndex: -1 - m_linkedTextComponent: {fileID: 0} - m_isLinkedTextComponent: 0 - m_enableKerning: 1 - m_enableExtraPadding: 0 - checkPaddingRequired: 0 - m_isRichText: 1 - m_parseCtrlCharacters: 1 - m_isOrthographic: 1 - m_isCullingEnabled: 0 - m_ignoreRectMaskCulling: 0 - m_ignoreCulling: 1 - m_horizontalMapping: 0 - m_verticalMapping: 0 - m_uvLineOffset: 0 - m_geometrySortingOrder: 0 - m_firstVisibleCharacter: 0 - m_useMaxVisibleDescender: 1 - m_pageToDisplay: 1 - m_margin: {x: 0, y: 0, z: 0, w: 0} - m_textInfo: - textComponent: {fileID: 0} - characterCount: 1 - spriteCount: 0 - spaceCount: 0 - wordCount: 1 - linkCount: 0 - lineCount: 1 - pageCount: 1 - materialCount: 1 - m_havePropertiesChanged: 1 - m_isUsingLegacyAnimationComponent: 0 - m_isVolumetricText: 0 - m_spriteAnimator: {fileID: 0} - m_isInputParsingRequired: 1 - m_inputSource: 0 - m_hasFontAssetChanged: 0 - m_subTextObjects: - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - m_baseMaterial: {fileID: 0} - m_maskOffset: {x: 0, y: 0, z: 0, w: 0} ---- !u!114 &114168715074745758 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1167948277449984} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c14051f25ea615549aeb702ebe3005d8, type: 3} - m_Name: - m_EditorClassIdentifier: - m_NormalGradientPair: - a: {r: 0.9607843, g: 0.972549, b: 0.9764706, a: 1} - b: {r: 0.9607843, g: 0.972549, b: 0.9764706, a: 1} - m_HighlightGradientPair: - a: {r: 0.19607843, g: 0.2, b: 0.2, a: 1} - b: {r: 0.19607843, g: 0.2, b: 0.2, a: 1} - m_ButtonMeshRenderer: {fileID: 23437852442812966} - m_IconContainer: {fileID: 224939432255965946} - m_ContentContainer: {fileID: 224860733548256162} - m_CanvasGroup: {fileID: 225914373114193260} - m_Text: {fileID: 114395512104104094} - m_Icon: {fileID: 114967506099497140} - m_AlternateIconSprite: {fileID: 0} - m_NormalContentColor: {r: 0.101960786, g: 0.101960786, b: 0.101960786, a: 1} - m_DisabledColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_HighlightItemColor: {r: 0.101960786, g: 0.101960786, b: 0.101960786, a: 1} - m_HighlightItems: - - {fileID: 114967506099497140} - - {fileID: 0} - m_Interactable: 0 - m_IconHighlightedLocalZOffset: -0.0015 - m_BeginHighlightDuration: 0.25 - m_EndHighlightDuration: 0.167 - m_DelayBeforeReveal: 0 - m_HighlightZScaleMultiplier: 2 - m_ContainerContentsAnimationSpeedMultiplier: 1 ---- !u!114 &114257755424135964 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1365241548943880} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c14051f25ea615549aeb702ebe3005d8, type: 3} - m_Name: - m_EditorClassIdentifier: - m_NormalGradientPair: - a: {r: 0.9607843, g: 0.972549, b: 0.9764706, a: 1} - b: {r: 0.9607843, g: 0.972549, b: 0.9764706, a: 1} - m_HighlightGradientPair: - a: {r: 0.19607843, g: 0.2, b: 0.2, a: 1} - b: {r: 0.19607843, g: 0.2, b: 0.2, a: 1} - m_ButtonMeshRenderer: {fileID: 23652728190552066} - m_IconContainer: {fileID: 224878234700512394} - m_ContentContainer: {fileID: 224124519857189990} - m_CanvasGroup: {fileID: 225328779711015670} - m_Text: {fileID: 114007618893444894} - m_Icon: {fileID: 114481225842932662} - m_AlternateIconSprite: {fileID: 0} - m_NormalContentColor: {r: 0.101960786, g: 0.101960786, b: 0.101960786, a: 1} - m_DisabledColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_HighlightItemColor: {r: 0.101960786, g: 0.101960786, b: 0.101960786, a: 1} - m_HighlightItems: - - {fileID: 114481225842932662} - - {fileID: 0} - m_Interactable: 0 - m_IconHighlightedLocalZOffset: -0.0015 - m_BeginHighlightDuration: 0.25 - m_EndHighlightDuration: 0.167 - m_DelayBeforeReveal: 0 - m_HighlightZScaleMultiplier: 2 - m_ContainerContentsAnimationSpeedMultiplier: 1 ---- !u!114 &114360875105238964 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1346101208067254} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 39742408926c5694d89876057a60578a, type: 3} - m_Name: - m_EditorClassIdentifier: - m_TargetScale: {fileID: 4000013117727556} - m_Icon: {fileID: 4000012336507532} - m_Undo: {fileID: 1279537530764624} - m_Redo: {fileID: 1382527450794256} - m_PickerOffset: 0.045 ---- !u!114 &114395512104104094 + m_BoolArgument: 0 + m_CallState: 1 + m_TypeName: UnityEngine.UI.Slider+SliderEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &114000013248295880 MonoBehaviour: m_ObjectHideFlags: 1 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1036881825388254} + m_GameObject: {fileID: 1000011582997490} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} + m_Script: {fileID: -98529514, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 0 + m_RaycastTarget: 1 m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_text: A - m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: 21452896fabdc4e4ea06c09c6ac05c9e, type: 2} - m_sharedMaterial: {fileID: 2100000, guid: 2800c3c40f001db459e655626fba97bf, type: 2} - m_fontSharedMaterials: [] - m_fontMaterial: {fileID: 0} - m_fontMaterials: [] - m_fontColor32: - serializedVersion: 2 - rgba: 4294967295 - m_fontColor: {r: 1, g: 1, b: 1, a: 1} - m_enableVertexGradient: 0 - m_fontColorGradient: - topLeft: {r: 1, g: 1, b: 1, a: 1} - topRight: {r: 1, g: 1, b: 1, a: 1} - bottomLeft: {r: 1, g: 1, b: 1, a: 1} - bottomRight: {r: 1, g: 1, b: 1, a: 1} - m_fontColorGradientPreset: {fileID: 0} - m_spriteAsset: {fileID: 0} - m_tintAllSprites: 0 - m_overrideHtmlColors: 0 - m_faceColor: - serializedVersion: 2 - rgba: 4294967295 - m_outlineColor: + m_Texture: {fileID: 0} + m_UVRect: serializedVersion: 2 - rgba: 4278190080 - m_fontSize: 203.4 - m_fontSizeBase: 36 - m_fontWeight: 400 - m_enableAutoSizing: 1 - m_fontSizeMin: 0 - m_fontSizeMax: 250 - m_fontStyle: 0 - m_textAlignment: 514 - m_isAlignmentEnumConverted: 1 - m_characterSpacing: 0 - m_wordSpacing: 0 - m_lineSpacing: 0 - m_lineSpacingMax: 0 - m_paragraphSpacing: 0 - m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 - m_wordWrappingRatios: 0.4 - m_overflowMode: 3 - m_firstOverflowCharacterIndex: -1 - m_linkedTextComponent: {fileID: 0} - m_isLinkedTextComponent: 0 - m_enableKerning: 1 - m_enableExtraPadding: 0 - checkPaddingRequired: 0 - m_isRichText: 1 - m_parseCtrlCharacters: 1 - m_isOrthographic: 1 - m_isCullingEnabled: 0 - m_ignoreRectMaskCulling: 0 - m_ignoreCulling: 1 - m_horizontalMapping: 0 - m_verticalMapping: 0 - m_uvLineOffset: 0 - m_geometrySortingOrder: 0 - m_firstVisibleCharacter: 0 - m_useMaxVisibleDescender: 1 - m_pageToDisplay: 1 - m_margin: {x: 0, y: 0, z: 0, w: 0} - m_textInfo: - textComponent: {fileID: 0} - characterCount: 1 - spriteCount: 0 - spaceCount: 0 - wordCount: 1 - linkCount: 0 - lineCount: 1 - pageCount: 1 - materialCount: 1 - m_havePropertiesChanged: 1 - m_isUsingLegacyAnimationComponent: 0 - m_isVolumetricText: 0 - m_spriteAnimator: {fileID: 0} - m_isInputParsingRequired: 1 - m_inputSource: 0 - m_hasFontAssetChanged: 0 - m_subTextObjects: - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - m_baseMaterial: {fileID: 0} - m_maskOffset: {x: 0, y: 0, z: 0, w: 0} ---- !u!114 &114481225842932662 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1619517534170012} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 2100000, guid: f51c2d173513e574f91a3666d94906b2, type: 2} - m_Color: {r: 0.101960786, g: 0.101960786, b: 0.101960786, a: 1} - m_RaycastTarget: 0 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, - Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_Sprite: {fileID: 21300000, guid: f7acf93d805e2dd42b4f32bed5d45ce8, type: 3} - m_Type: 0 - m_PreserveAspect: 1 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 2 ---- !u!114 &114543901646842364 + x: 0 + y: 0 + width: 1 + height: 1 +--- !u!114 &114000013959281966 MonoBehaviour: m_ObjectHideFlags: 1 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1279537530764624} + m_GameObject: {fileID: 1000010117119988} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 121a9b94e41e9e444af3e8069a887154, type: 3} + m_Script: {fileID: 1980459831, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} m_Name: m_EditorClassIdentifier: - m_TooltipText: Undo - m_TooltipTarget: {fileID: 4602986436310456} - m_TooltipSource: {fileID: 4066649049098668} - m_TooltipAlignment: 0 ---- !u!114 &114824239518982862 + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!114 &114360875105238964 MonoBehaviour: m_ObjectHideFlags: 1 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1382527450794256} + m_GameObject: {fileID: 1346101208067254} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 121a9b94e41e9e444af3e8069a887154, type: 3} + m_Script: {fileID: 11500000, guid: 39742408926c5694d89876057a60578a, type: 3} m_Name: m_EditorClassIdentifier: - m_TooltipText: Redo - m_TooltipTarget: {fileID: 4166573009768210} - m_TooltipSource: {fileID: 4702350181192430} - m_TooltipAlignment: 0 + m_TargetScale: {fileID: 4000013117727556} + m_Icon: {fileID: 4000012336507532} + m_PickerOffset: 0.045 --- !u!114 &114955240123553084 MonoBehaviour: m_ObjectHideFlags: 1 @@ -1796,33 +779,6 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_SelectionFlags: 3 ---- !u!114 &114967506099497140 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1430967031119936} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 2100000, guid: f51c2d173513e574f91a3666d94906b2, type: 2} - m_Color: {r: 0.101960786, g: 0.101960786, b: 0.101960786, a: 1} - m_RaycastTarget: 0 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, - Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_Sprite: {fileID: 21300000, guid: 6c24010c054434e468a95292a7af0f67, type: 3} - m_Type: 0 - m_PreserveAspect: 1 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 2 --- !u!222 &222000010186370168 CanvasRenderer: m_ObjectHideFlags: 1 @@ -1853,30 +809,6 @@ CanvasRenderer: m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 100100000} m_GameObject: {fileID: 1000014088439944} ---- !u!222 &222227951865979474 -CanvasRenderer: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1619517534170012} ---- !u!222 &222582790420601646 -CanvasRenderer: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1141551173516660} ---- !u!222 &222928571895566388 -CanvasRenderer: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1036881825388254} ---- !u!222 &222975643046639372 -CanvasRenderer: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1430967031119936} --- !u!223 &223000010278076522 Canvas: m_ObjectHideFlags: 1 @@ -1897,46 +829,6 @@ Canvas: m_SortingLayerID: 0 m_SortingOrder: 0 m_TargetDisplay: 0 ---- !u!223 &223499351256631318 -Canvas: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1411372913666494} - m_Enabled: 1 - serializedVersion: 3 - m_RenderMode: 2 - m_Camera: {fileID: 0} - m_PlaneDistance: 100 - m_PixelPerfect: 0 - m_ReceivesEvents: 1 - m_OverrideSorting: 0 - m_OverridePixelPerfect: 0 - m_SortingBucketNormalizedSize: 0 - m_AdditionalShaderChannelsFlag: 25 - m_SortingLayerID: 0 - m_SortingOrder: 0 - m_TargetDisplay: 0 ---- !u!223 &223502477285382174 -Canvas: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1603094234734992} - m_Enabled: 1 - serializedVersion: 3 - m_RenderMode: 2 - m_Camera: {fileID: 0} - m_PlaneDistance: 100 - m_PixelPerfect: 0 - m_ReceivesEvents: 1 - m_OverrideSorting: 0 - m_OverridePixelPerfect: 0 - m_SortingBucketNormalizedSize: 0 - m_AdditionalShaderChannelsFlag: 25 - m_SortingLayerID: 0 - m_SortingOrder: 0 - m_TargetDisplay: 0 --- !u!224 &224000011129790424 RectTransform: m_ObjectHideFlags: 1 @@ -2107,192 +999,6 @@ RectTransform: m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} ---- !u!224 &224107373598291132 -RectTransform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1365241548943880} - m_LocalRotation: {x: 0.7071068, y: -0, z: -0, w: 0.7071068} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 0.425, y: 0.5000001, z: 0.42500013} - m_Children: [] - m_Father: {fileID: 4670339961100958} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 100, y: 100} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!224 &224124519857189990 -RectTransform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1603094234734992} - m_LocalRotation: {x: 1, y: -0, z: -0, w: 0} - m_LocalPosition: {x: 0, y: 0, z: 0.00093460095} - m_LocalScale: {x: 0.85, y: 0.85000026, z: 0.13000003} - m_Children: - - {fileID: 4940108482629240} - m_Father: {fileID: 4670339961100958} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 180, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: -0.0000012314413} - m_SizeDelta: {x: 100, y: 100} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!224 &224333717671022096 -RectTransform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1167948277449984} - m_LocalRotation: {x: 0.7071068, y: -0, z: -0, w: 0.7071068} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 0.425, y: 0.5000001, z: 0.42500013} - m_Children: [] - m_Father: {fileID: 4796074920551568} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 100, y: 100} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!224 &224388597326433990 -RectTransform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1619517534170012} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.00000013453973} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 224878234700512394} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: -24.5, y: -24.5} - m_AnchorMax: {x: 25.5, y: 25.5} - m_AnchoredPosition: {x: -0.00000032782555, y: 0.00000014901161} - m_SizeDelta: {x: -1.13105, y: -1.13086} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!224 &224393326463988594 -RectTransform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1036881825388254} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.00000013408862} - m_LocalScale: {x: 0.00008, y: 0.00008, z: 1} - m_Children: [] - m_Father: {fileID: 224939432255965946} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0.00008, y: 0.0005000001} - m_SizeDelta: {x: 268.38452, y: 268.38452} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!224 &224638576672757326 -RectTransform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1430967031119936} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.00000013453973} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 224939432255965946} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: -24.5, y: -24.5} - m_AnchorMax: {x: 25.5, y: 25.5} - m_AnchoredPosition: {x: -0.00000032782555, y: 0.00000014901161} - m_SizeDelta: {x: -1.13105, y: -1.13086} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!224 &224860733548256162 -RectTransform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1411372913666494} - m_LocalRotation: {x: 1, y: -0, z: -0, w: 0} - m_LocalPosition: {x: 0, y: 0, z: 0.00093460095} - m_LocalScale: {x: 0.85, y: 0.85000026, z: 0.13000003} - m_Children: - - {fileID: 4572708185800628} - m_Father: {fileID: 4796074920551568} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 180, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: -0.0000012314413} - m_SizeDelta: {x: 100, y: 100} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!224 &224878234700512394 -RectTransform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1887300028592862} - 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_Children: - - {fileID: 224388597326433990} - - {fileID: 224963898299502848} - m_Father: {fileID: 4940108482629240} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: -8.731149e-10, y: -2.3283064e-10} - m_SizeDelta: {x: 0.02307, y: 0.02307} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!224 &224939432255965946 -RectTransform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1482568457756204} - 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_Children: - - {fileID: 224638576672757326} - - {fileID: 224393326463988594} - m_Father: {fileID: 4572708185800628} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: -8.731149e-10, y: -2.3283064e-10} - m_SizeDelta: {x: 0.02307, y: 0.02307} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!224 &224963898299502848 -RectTransform: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1141551173516660} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.00000013408862} - m_LocalScale: {x: 0.00008, y: 0.00008, z: 1} - m_Children: [] - m_Father: {fileID: 224878234700512394} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0.00008, y: 0.0005000001} - m_SizeDelta: {x: 268.38452, y: 268.38452} - m_Pivot: {x: 0.5, y: 0.5} --- !u!225 &225000012229749264 CanvasGroup: m_ObjectHideFlags: 1 @@ -2304,25 +1010,3 @@ CanvasGroup: m_Interactable: 0 m_BlocksRaycasts: 0 m_IgnoreParentGroups: 0 ---- !u!225 &225328779711015670 -CanvasGroup: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1603094234734992} - m_Enabled: 1 - m_Alpha: 1 - m_Interactable: 1 - m_BlocksRaycasts: 0 - m_IgnoreParentGroups: 0 ---- !u!225 &225914373114193260 -CanvasGroup: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1411372913666494} - m_Enabled: 1 - m_Alpha: 1 - m_Interactable: 1 - m_BlocksRaycasts: 0 - m_IgnoreParentGroups: 0 diff --git a/Tools/AnnotationTool/UserInterface/ColorPickerActivator.cs b/Tools/AnnotationTool/UserInterface/ColorPickerActivator.cs index 90f4309ce..0961b1a04 100644 --- a/Tools/AnnotationTool/UserInterface/ColorPickerActivator.cs +++ b/Tools/AnnotationTool/UserInterface/ColorPickerActivator.cs @@ -18,51 +18,15 @@ public class ColorPickerActivator : MonoBehaviour, IPointerClickHandler, IPointe Transform m_Icon; [SerializeField] - GameObject m_Undo; - - [SerializeField] - GameObject m_Redo; - - [SerializeField] float m_PickerOffset = 0.045f; Coroutine m_HighlightCoroutine; - GradientButton m_UndoButton; - GradientButton m_RedoButton; public Transform rayOrigin { private get; set; } public Action showColorPicker { private get; set; } public Action hideColorPicker { private get; set; } public Node node { private get; set; } - public event Action undoButtonClick - { - add { m_UndoButton.click += value; } - remove { m_UndoButton.click -= value; } - } - - public event Action redoButtonClick - { - add { m_RedoButton.click += value; } - remove { m_RedoButton.click -= value; } - } - - void Awake() - { - m_UndoButton = m_Undo.GetComponentInChildren(); - m_UndoButton.normalGradientPair = UnityBrandColorScheme.grayscaleSessionGradient; - m_UndoButton.highlightGradientPair = UnityBrandColorScheme.sessionGradient; - m_RedoButton = m_Redo.GetComponentInChildren(); - m_RedoButton.normalGradientPair = UnityBrandColorScheme.grayscaleSessionGradient; - m_RedoButton.highlightGradientPair = UnityBrandColorScheme.sessionGradient; - } - - void Start() - { - m_UndoButton.UpdateMaterialColors(); - m_RedoButton.UpdateMaterialColors(); - } - public void OnPointerClick(PointerEventData eventData) { eventData.Use(); @@ -73,9 +37,6 @@ public void OnPointerEnter(PointerEventData eventData) showColorPicker(rayOrigin); this.RestartCoroutine(ref m_HighlightCoroutine, Highlight(true)); - m_Undo.SetActive(false); - m_Redo.SetActive(false); - eventData.Use(); } @@ -83,9 +44,6 @@ public void OnPointerExit(PointerEventData eventData) { hideColorPicker(); this.RestartCoroutine(ref m_HighlightCoroutine, Highlight(false)); - - m_Undo.SetActive(true); - m_Redo.SetActive(true); } IEnumerator Highlight(bool transitionIn) From 60edbee1f5986e2620e7bfff7c3c4af24ef37c1f Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Fri, 8 Dec 2017 03:02:00 -0800 Subject: [PATCH 73/89] Fix issue where two handed scaling broke alternate menu hiding --- Tools/TransformTool/TransformTool.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Tools/TransformTool/TransformTool.cs b/Tools/TransformTool/TransformTool.cs index f88fce69f..87a34a322 100644 --- a/Tools/TransformTool/TransformTool.cs +++ b/Tools/TransformTool/TransformTool.cs @@ -601,7 +601,9 @@ public void Resume(Node node) public Transform[] GetHeldObjects(Node node) { var grabData = GrabDataForNode(node); - return grabData == null ? null : grabData.grabbedObjects; + var heldObjects = grabData == null ? null : grabData.grabbedObjects; + Debug.Log(node + ", " +heldObjects.Length); + return heldObjects; } public void TransferHeldObjects(Transform rayOrigin, Transform destRayOrigin, Vector3 deltaOffset = default(Vector3)) @@ -635,7 +637,7 @@ public void DropHeldObjects(Node node) var grabbedObjects = grabData.grabbedObjects; var rayOrigin = grabData.rayOrigin; - if (objectsDropped != null && !m_Scaling) + if (objectsDropped != null) objectsDropped(rayOrigin, grabbedObjects); if (node == Node.LeftHand) From f42e7bf410aab23df11c90baa966780df8b329ef Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 8 Dec 2017 11:05:19 -0800 Subject: [PATCH 74/89] include TMPro fields in same ifdef for mainmenu selectable --- Menus/MainMenu/Scripts/MainMenuSelectable.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Menus/MainMenu/Scripts/MainMenuSelectable.cs b/Menus/MainMenu/Scripts/MainMenuSelectable.cs index 375cd8c4c..9267a1df1 100644 --- a/Menus/MainMenu/Scripts/MainMenuSelectable.cs +++ b/Menus/MainMenu/Scripts/MainMenuSelectable.cs @@ -26,9 +26,7 @@ abstract class MainMenuSelectable : MonoBehaviour #if INCLUDE_TEXT_MESH_PRO [SerializeField] protected TextMeshProUGUI m_Description; -#endif -#if INCLUDE_TEXT_MESH_PRO [SerializeField] protected TextMeshProUGUI m_Title; #endif From 89084cd437e1535a0a0e58d9f0bcbc3a9547afc5 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Fri, 8 Dec 2017 11:07:40 -0800 Subject: [PATCH 75/89] Fix line endings --- Menus/MainMenu/MainMenuInput.cs | 24 ++++++++++++------------ Menus/UndoMenu/UndoMenuInput.cs | 24 ++++++++++++------------ Tools/TransformTool/TransformTool.cs | 2 +- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Menus/MainMenu/MainMenuInput.cs b/Menus/MainMenu/MainMenuInput.cs index caa6ca0d1..7475a7755 100644 --- a/Menus/MainMenu/MainMenuInput.cs +++ b/Menus/MainMenu/MainMenuInput.cs @@ -1,13 +1,13 @@ -using UnityEngine; -using UnityEngine.InputNew; - -// GENERATED FILE - DO NOT EDIT MANUALLY -namespace UnityEngine.InputNew -{ - public class MainMenuInput : ActionMapInput { - public MainMenuInput (ActionMap actionMap) : base (actionMap) { } - - public AxisInputControl @rotate { get { return (AxisInputControl)this[0]; } } - public ButtonInputControl @flickFace { get { return (ButtonInputControl)this[1]; } } - } +using UnityEngine; +using UnityEngine.InputNew; + +// GENERATED FILE - DO NOT EDIT MANUALLY +namespace UnityEngine.InputNew +{ + public class MainMenuInput : ActionMapInput { + public MainMenuInput (ActionMap actionMap) : base (actionMap) { } + + public AxisInputControl @rotate { get { return (AxisInputControl)this[0]; } } + public ButtonInputControl @flickFace { get { return (ButtonInputControl)this[1]; } } + } } diff --git a/Menus/UndoMenu/UndoMenuInput.cs b/Menus/UndoMenu/UndoMenuInput.cs index 0fef76d03..801474f0f 100644 --- a/Menus/UndoMenu/UndoMenuInput.cs +++ b/Menus/UndoMenu/UndoMenuInput.cs @@ -1,13 +1,13 @@ -using UnityEngine; -using UnityEngine.InputNew; - -// GENERATED FILE - DO NOT EDIT MANUALLY -namespace UnityEngine.InputNew -{ - public class UndoMenuInput : ActionMapInput { - public UndoMenuInput (ActionMap actionMap) : base (actionMap) { } - - public AxisInputControl @navigateX { get { return (AxisInputControl)this[0]; } } - public ButtonInputControl @engage { get { return (ButtonInputControl)this[1]; } } - } +using UnityEngine; +using UnityEngine.InputNew; + +// GENERATED FILE - DO NOT EDIT MANUALLY +namespace UnityEngine.InputNew +{ + public class UndoMenuInput : ActionMapInput { + public UndoMenuInput (ActionMap actionMap) : base (actionMap) { } + + public AxisInputControl @navigateX { get { return (AxisInputControl)this[0]; } } + public ButtonInputControl @engage { get { return (ButtonInputControl)this[1]; } } + } } diff --git a/Tools/TransformTool/TransformTool.cs b/Tools/TransformTool/TransformTool.cs index 87a34a322..cd2ebf556 100644 --- a/Tools/TransformTool/TransformTool.cs +++ b/Tools/TransformTool/TransformTool.cs @@ -601,7 +601,7 @@ public void Resume(Node node) public Transform[] GetHeldObjects(Node node) { var grabData = GrabDataForNode(node); - var heldObjects = grabData == null ? null : grabData.grabbedObjects; + var heldObjects = grabData == null ? null : grabData.grabbedObjects; Debug.Log(node + ", " +heldObjects.Length); return heldObjects; } From 8f298c019009f868fb8c5d45205033e8526fd39b Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 8 Dec 2017 11:27:35 -0800 Subject: [PATCH 76/89] restore code that adds toggle haptics --- Menus/MainMenu/MainMenu.cs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Menus/MainMenu/MainMenu.cs b/Menus/MainMenu/MainMenu.cs index 166ea3420..4ad4cf241 100644 --- a/Menus/MainMenu/MainMenu.cs +++ b/Menus/MainMenu/MainMenu.cs @@ -299,6 +299,11 @@ void OnButtonHovered(Transform rayOrigin, Type buttonType, string buttonDescript this.PreviewInToolMenuButton(rayOrigin, buttonType, buttonDescription); } + void OnToggleHovered(Transform rayOrigin) + { + this.Pulse(this.RequestNodeFromRayOrigin(rayOrigin), m_ButtonHoverPulse); + } + void SendVisibilityPulse() { this.Pulse(node, m_MenuHideFlags == 0 ? m_HidePulse : m_ShowPulse); @@ -333,12 +338,29 @@ void AddSettingsMenu(ISettingsMenuProvider provider, MainMenuUI.ButtonData butto { buttonData.sectionName = k_SettingsMenuSectionName; - CreateFaceButton(buttonData, tooltip, () => + var button = CreateFaceButton(buttonData, tooltip, () => { var instance = m_MainMenuUI.AddSubmenu(k_SettingsMenuSectionName, provider.settingsMenuPrefab); m_SettingsMenus[provider] = instance; provider.settingsMenuInstance = instance; + AddToggleHaptics(instance); }); + + button.hovered += OnButtonHovered; + button.clicked += OnButtonClicked; + } + + void AddToggleHaptics(GameObject menuInstance) + { + var toggles = menuInstance.GetComponentsInChildren(); + if (toggles != null && toggles.Length > 0) + { + foreach (var toggle in toggles) + { + toggle.hovered += OnToggleHovered; + toggle.clicked += OnButtonClicked; + } + } } public void RemoveSettingsMenu(ISettingsMenuProvider provider) From f9e2eb84f7699c7b81d5400f49ccfc5808d8a15e Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 8 Dec 2017 11:31:19 -0800 Subject: [PATCH 77/89] update settings UI from dev --- .../LocomotionTool/Prefabs/SettingsUI.prefab | 239 +++++++++++------- 1 file changed, 142 insertions(+), 97 deletions(-) diff --git a/Tools/LocomotionTool/Prefabs/SettingsUI.prefab b/Tools/LocomotionTool/Prefabs/SettingsUI.prefab index 720c696cc..65e885bb9 100644 --- a/Tools/LocomotionTool/Prefabs/SettingsUI.prefab +++ b/Tools/LocomotionTool/Prefabs/SettingsUI.prefab @@ -20,7 +20,7 @@ GameObject: m_Component: - component: {fileID: 224000012653929454} - component: {fileID: 222000012891014098} - - component: {fileID: 114237599994434612} + - component: {fileID: 114926923194449542} m_Layer: 5 m_Name: Label m_TagString: Untagged @@ -54,7 +54,7 @@ GameObject: m_Component: - component: {fileID: 224000011405639814} - component: {fileID: 222000011416400564} - - component: {fileID: 114735976065890330} + - component: {fileID: 114251560024549528} m_Layer: 5 m_Name: Label m_TagString: Untagged @@ -71,7 +71,6 @@ GameObject: m_Component: - component: {fileID: 224000010858218954} - component: {fileID: 114000011920048442} - - component: {fileID: 114129496827691156} m_Layer: 5 m_Name: Blink m_TagString: Untagged @@ -122,7 +121,6 @@ GameObject: m_Component: - component: {fileID: 224000011444372664} - component: {fileID: 114000013714903302} - - component: {fileID: 114034804745796320} m_Layer: 5 m_Name: Fly m_TagString: Untagged @@ -192,7 +190,7 @@ GameObject: m_Component: - component: {fileID: 224874559224435002} - component: {fileID: 222817483957468890} - - component: {fileID: 114210595956423184} + - component: {fileID: 114630463904937644} m_Layer: 5 m_Name: Text m_TagString: Untagged @@ -432,39 +430,131 @@ MonoBehaviour: m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_IsOn: 1 ---- !u!114 &114034804745796320 +--- !u!114 &114251560024549528 MonoBehaviour: m_ObjectHideFlags: 1 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000013494423478} + m_GameObject: {fileID: 1000011512978662} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} m_Name: m_EditorClassIdentifier: - m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} - m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} - m_Description: {fileID: 0} - m_Title: {fileID: 114237599994434612} - m_Toggle: {fileID: 114000013714903302} ---- !u!114 &114129496827691156 + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Blink + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: ea721564999c75441b5b3aa01ae88f76, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 5be343b145ab9dd42821b06c75f9a60c, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 20 + m_fontSizeBase: 20 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 514 + m_isAlignmentEnumConverted: 1 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 114251560024549528} + characterCount: 5 + spriteCount: 0 + spaceCount: 0 + wordCount: 1 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_havePropertiesChanged: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_isInputParsingRequired: 1 + m_inputSource: 0 + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!114 &114261882201029984 MonoBehaviour: m_ObjectHideFlags: 1 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000011772923556} + m_GameObject: {fileID: 1000013796857246} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Script: {fileID: 11500000, guid: e93c342d881ae654d8d190dda4e84c44, type: 3} m_Name: m_EditorClassIdentifier: - m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} - m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} - m_Description: {fileID: 0} - m_Title: {fileID: 114735976065890330} - m_Toggle: {fileID: 114000011920048442} ---- !u!114 &114210595956423184 + m_DefaultToggle: {fileID: 114000013714903302} +--- !u!114 &114630463904937644 MonoBehaviour: m_ObjectHideFlags: 1 m_PrefabParentObject: {fileID: 0} @@ -472,39 +562,6 @@ MonoBehaviour: m_GameObject: {fileID: 1123566551031880} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 2100000, guid: dec2d25be9058334c91a0402762efa61, type: 2} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, - Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_FontData: - m_Font: {fileID: 12800000, guid: 013679fd6ee2085428a7f896aa7b50cc, type: 3} - m_FontSize: 14 - m_FontStyle: 0 - m_BestFit: 0 - m_MinSize: 10 - m_MaxSize: 280 - m_Alignment: 0 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: ' Locomotion Mode:' ---- !u!114 &114237599994434612 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000010398065086} - m_Enabled: 1 - m_EditorHideFlags: 0 m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} m_Name: m_EditorClassIdentifier: @@ -516,10 +573,10 @@ MonoBehaviour: m_Calls: [] m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_text: Fly + m_text: ' Locomotion Mode:' m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: 76ff077e92eb4fe41aa26173a3d98fb6, type: 2} - m_sharedMaterial: {fileID: 2100000, guid: 54d3f6429fd638b4d9ca906c1354d050, type: 2} + m_fontAsset: {fileID: 11400000, guid: ea721564999c75441b5b3aa01ae88f76, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 5be343b145ab9dd42821b06c75f9a60c, type: 2} m_fontSharedMaterials: [] m_fontMaterial: {fileID: 0} m_fontMaterials: [] @@ -543,14 +600,14 @@ MonoBehaviour: m_outlineColor: serializedVersion: 2 rgba: 4278190080 - m_fontSize: 20 - m_fontSizeBase: 20 + m_fontSize: 14 + m_fontSizeBase: 14 m_fontWeight: 400 m_enableAutoSizing: 0 m_fontSizeMin: 18 m_fontSizeMax: 72 m_fontStyle: 0 - m_textAlignment: 514 + m_textAlignment: 257 m_isAlignmentEnumConverted: 1 m_characterSpacing: 0 m_wordSpacing: 0 @@ -560,7 +617,7 @@ MonoBehaviour: m_charWidthMaxAdj: 0 m_enableWordWrapping: 1 m_wordWrappingRatios: 0.4 - m_overflowMode: 3 + m_overflowMode: 0 m_firstOverflowCharacterIndex: -1 m_linkedTextComponent: {fileID: 0} m_isLinkedTextComponent: 0 @@ -582,15 +639,15 @@ MonoBehaviour: m_pageToDisplay: 1 m_margin: {x: 0, y: 0, z: 0, w: 0} m_textInfo: - textComponent: {fileID: 0} - characterCount: 0 + textComponent: {fileID: 114630463904937644} + characterCount: 18 spriteCount: 0 - spaceCount: 0 - wordCount: 0 + spaceCount: 3 + wordCount: 3 linkCount: 0 - lineCount: 0 - pageCount: 0 - materialCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 m_havePropertiesChanged: 1 m_isUsingLegacyAnimationComponent: 0 m_isVolumetricText: 0 @@ -609,18 +666,6 @@ MonoBehaviour: - {fileID: 0} m_baseMaterial: {fileID: 0} m_maskOffset: {x: 0, y: 0, z: 0, w: 0} ---- !u!114 &114261882201029984 -MonoBehaviour: - m_ObjectHideFlags: 1 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000013796857246} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: e93c342d881ae654d8d190dda4e84c44, type: 3} - m_Name: - m_EditorClassIdentifier: - m_DefaultToggle: {fileID: 114000013714903302} --- !u!114 &114691388261995722 MonoBehaviour: m_ObjectHideFlags: 1 @@ -643,12 +688,12 @@ MonoBehaviour: m_ChildForceExpandHeight: 1 m_ChildControlWidth: 1 m_ChildControlHeight: 0 ---- !u!114 &114735976065890330 +--- !u!114 &114926923194449542 MonoBehaviour: m_ObjectHideFlags: 1 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 100100000} - m_GameObject: {fileID: 1000011512978662} + m_GameObject: {fileID: 1000010398065086} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 1453722849, guid: 89f0137620f6af44b9ba852b4190e64e, type: 3} @@ -662,10 +707,10 @@ MonoBehaviour: m_Calls: [] m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_text: Blink + m_text: Fly m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: 76ff077e92eb4fe41aa26173a3d98fb6, type: 2} - m_sharedMaterial: {fileID: 2100000, guid: 54d3f6429fd638b4d9ca906c1354d050, type: 2} + m_fontAsset: {fileID: 11400000, guid: ea721564999c75441b5b3aa01ae88f76, type: 2} + m_sharedMaterial: {fileID: 2100000, guid: 5be343b145ab9dd42821b06c75f9a60c, type: 2} m_fontSharedMaterials: [] m_fontMaterial: {fileID: 0} m_fontMaterials: [] @@ -706,7 +751,7 @@ MonoBehaviour: m_charWidthMaxAdj: 0 m_enableWordWrapping: 1 m_wordWrappingRatios: 0.4 - m_overflowMode: 3 + m_overflowMode: 0 m_firstOverflowCharacterIndex: -1 m_linkedTextComponent: {fileID: 0} m_isLinkedTextComponent: 0 @@ -728,15 +773,15 @@ MonoBehaviour: m_pageToDisplay: 1 m_margin: {x: 0, y: 0, z: 0, w: 0} m_textInfo: - textComponent: {fileID: 0} - characterCount: 0 + textComponent: {fileID: 114926923194449542} + characterCount: 3 spriteCount: 0 spaceCount: 0 - wordCount: 0 + wordCount: 1 linkCount: 0 - lineCount: 0 - pageCount: 0 - materialCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 m_havePropertiesChanged: 1 m_isUsingLegacyAnimationComponent: 0 m_isVolumetricText: 0 @@ -863,8 +908,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: -0.000000007450581, y: 0} - m_SizeDelta: {x: -0.5, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!224 &224000011444372664 RectTransform: @@ -960,8 +1005,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: -0.000000007450581, y: 0} - m_SizeDelta: {x: -0.5, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!224 &224000013716393632 RectTransform: From f40e16d6841e53067361ecff4cfabae3505b541b Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 8 Dec 2017 11:42:26 -0800 Subject: [PATCH 78/89] don't do hover feedback for disabled toggles --- Menus/MainMenu/Scripts/MainMenuToggle.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Menus/MainMenu/Scripts/MainMenuToggle.cs b/Menus/MainMenu/Scripts/MainMenuToggle.cs index 425dddadc..79a4cd919 100644 --- a/Menus/MainMenu/Scripts/MainMenuToggle.cs +++ b/Menus/MainMenu/Scripts/MainMenuToggle.cs @@ -28,13 +28,13 @@ sealed class MainMenuToggle : MainMenuSelectable, IRayEnterHandler, IRayExitHand public void OnRayEnter(RayEventData eventData) { - if (hovered != null) + if (m_Toggle.isOn && hovered != null) hovered(eventData.rayOrigin); } public void OnRayExit(RayEventData eventData) { - if (hovered != null) + if (m_Toggle.isOn && hovered != null) hovered(eventData.rayOrigin); } From 06b18bd9b28e31f9fb3e606eeda0ebe470157b2b Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 8 Dec 2017 13:36:09 -0800 Subject: [PATCH 79/89] add toggle haptics to locomotion mode toggle --- Menus/MainMenu/MainMenu.cs | 1 + .../LocomotionTool/Prefabs/SettingsUI.prefab | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/Menus/MainMenu/MainMenu.cs b/Menus/MainMenu/MainMenu.cs index 4ad4cf241..b8099932e 100644 --- a/Menus/MainMenu/MainMenu.cs +++ b/Menus/MainMenu/MainMenu.cs @@ -381,6 +381,7 @@ public void AddSettingsMenuItem(ISettingsMenuItemProvider provider) var instance = m_MainMenuUI.CreateCustomButton(provider.settingsMenuItemPrefab, k_SettingsMenuSectionName); m_SettingsMenuItems[provider] = instance; provider.settingsMenuItemInstance = instance; + AddToggleHaptics(instance); } public void RemoveSettingsMenuItem(ISettingsMenuItemProvider provider) diff --git a/Tools/LocomotionTool/Prefabs/SettingsUI.prefab b/Tools/LocomotionTool/Prefabs/SettingsUI.prefab index 65e885bb9..3c214c745 100644 --- a/Tools/LocomotionTool/Prefabs/SettingsUI.prefab +++ b/Tools/LocomotionTool/Prefabs/SettingsUI.prefab @@ -71,6 +71,7 @@ GameObject: m_Component: - component: {fileID: 224000010858218954} - component: {fileID: 114000011920048442} + - component: {fileID: 114009511206996632} m_Layer: 5 m_Name: Blink m_TagString: Untagged @@ -121,6 +122,7 @@ GameObject: m_Component: - component: {fileID: 224000011444372664} - component: {fileID: 114000013714903302} + - component: {fileID: 114546748432515818} m_Layer: 5 m_Name: Fly m_TagString: Untagged @@ -430,6 +432,22 @@ MonoBehaviour: m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_IsOn: 1 +--- !u!114 &114009511206996632 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000011772923556} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 0} + m_Title: {fileID: 114251560024549528} + m_Toggle: {fileID: 114000011920048442} --- !u!114 &114251560024549528 MonoBehaviour: m_ObjectHideFlags: 1 @@ -554,6 +572,22 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_DefaultToggle: {fileID: 114000013714903302} +--- !u!114 &114546748432515818 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000013494423478} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 0} + m_Title: {fileID: 114926923194449542} + m_Toggle: {fileID: 114000013714903302} --- !u!114 &114630463904937644 MonoBehaviour: m_ObjectHideFlags: 1 From 7f6660ee8908939379bb3477ec588447529d8b41 Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 8 Dec 2017 13:38:43 -0800 Subject: [PATCH 80/89] add pulses to block select settings UI --- Tools/SelectionTool/Prefabs/SettingsUI.prefab | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/Tools/SelectionTool/Prefabs/SettingsUI.prefab b/Tools/SelectionTool/Prefabs/SettingsUI.prefab index e89bd2e1c..6c0cfc66d 100644 --- a/Tools/SelectionTool/Prefabs/SettingsUI.prefab +++ b/Tools/SelectionTool/Prefabs/SettingsUI.prefab @@ -71,6 +71,7 @@ GameObject: m_Component: - component: {fileID: 224000010858218954} - component: {fileID: 114000011920048442} + - component: {fileID: 114098223122120698} m_Layer: 5 m_Name: Sphere m_TagString: Untagged @@ -121,6 +122,7 @@ GameObject: m_Component: - component: {fileID: 224000011444372664} - component: {fileID: 114000013714903302} + - component: {fileID: 114941570635773572} m_Layer: 5 m_Name: Cuboid m_TagString: Untagged @@ -496,6 +498,22 @@ MonoBehaviour: m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_IsOn: 1 +--- !u!114 &114098223122120698 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000011772923556} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 0} + m_Title: {fileID: 0} + m_Toggle: {fileID: 114000011920048442} --- !u!114 &114210595956423184 MonoBehaviour: m_ObjectHideFlags: 1 @@ -563,6 +581,22 @@ MonoBehaviour: m_ChildForceExpandHeight: 1 m_ChildControlWidth: 1 m_ChildControlHeight: 0 +--- !u!114 &114941570635773572 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000013494423478} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 766c9196b7801da49b40f523eaa556e6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ClickPulse: {fileID: 11400000, guid: ad8089d07bd48a047b9d6b45f7a4fd57, type: 2} + m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2} + m_Description: {fileID: 0} + m_Title: {fileID: 0} + m_Toggle: {fileID: 114000013714903302} --- !u!222 &222000010570603678 CanvasRenderer: m_ObjectHideFlags: 1 From 79531500d39a1a6d37c51b044d46dccab43cb606 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Fri, 8 Dec 2017 14:35:22 -0800 Subject: [PATCH 81/89] Remove UpdatePreview call which was hard-setting object position without snapping when bringing back into the miniworld --- Scripts/Core/EditorVR.MiniWorlds.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Scripts/Core/EditorVR.MiniWorlds.cs b/Scripts/Core/EditorVR.MiniWorlds.cs index 4d53efbcd..628d0a68f 100644 --- a/Scripts/Core/EditorVR.MiniWorlds.cs +++ b/Scripts/Core/EditorVR.MiniWorlds.cs @@ -383,8 +383,6 @@ internal void UpdateMiniWorlds() directSelection.ResumeGrabbers(incomingPreview.node); } - miniWorldRay.UpdatePreview(); // Otherwise the object is in the wrong position for a frame - if (!isContained) m_RayWasContained[originalRayOrigin] = false; //Prevent ray from showing } From 68eea6657c360a4042d5fa855cbeaaf9b4ac43a5 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Fri, 8 Dec 2017 15:02:10 -0800 Subject: [PATCH 82/89] Code cleanup and style changes --- Menus/UndoMenu/Scripts/UndoMenuUI.cs | 11 ++++------- Menus/UndoMenu/UndoMenu.cs | 14 +++++++------- Scripts/Core/EditorVR.Menus.cs | 7 ++++--- Scripts/Core/EditorVR.Tools.cs | 1 - 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/Menus/UndoMenu/Scripts/UndoMenuUI.cs b/Menus/UndoMenu/Scripts/UndoMenuUI.cs index fa2037865..90892c570 100644 --- a/Menus/UndoMenu/Scripts/UndoMenuUI.cs +++ b/Menus/UndoMenu/Scripts/UndoMenuUI.cs @@ -25,6 +25,9 @@ sealed class UndoMenuUI : MonoBehaviour, IConnectInterfaces Coroutine m_EngageCoroutine; Coroutine m_UndoPerformedCoroutine; + bool m_Engaged; + bool m_Visible; + public Transform alternateMenuOrigin { get { return m_AlternateMenuOrigin; } @@ -55,8 +58,6 @@ public bool engaged } } - bool m_Engaged; - public bool visible { get { return m_Visible; } @@ -72,8 +73,6 @@ public bool visible } } - bool m_Visible; - void Awake() { m_UndoButtonMaterial = MaterialUtils.GetMaterialClone(m_UndoButtonMeshRenderer); @@ -116,9 +115,7 @@ public void StartPerformedAnimation(bool undo) IEnumerator AnimateUndoPerformed(bool undo) { - var targetMaterial = undo - ? m_UndoButtonMaterial - : m_RedoButtonMaterial; + var targetMaterial = undo ? m_UndoButtonMaterial : m_RedoButtonMaterial; var startingColor = m_UndoButtonMaterial.GetColor(k_MaterialColorProperty); var targetColor = startingColor; targetColor.a = k_UndoPerformedAlpha; diff --git a/Menus/UndoMenu/UndoMenu.cs b/Menus/UndoMenu/UndoMenu.cs index 30c26a4bc..09cd9ae3e 100644 --- a/Menus/UndoMenu/UndoMenu.cs +++ b/Menus/UndoMenu/UndoMenu.cs @@ -1,5 +1,4 @@ #if UNITY_EDITOR -using System; using System.Collections; using System.Collections.Generic; using UnityEditor.Experimental.EditorVR.Core; @@ -30,7 +29,6 @@ sealed class UndoMenu : MonoBehaviour, IInstantiateUI, IUsesMenuOrigins, ICustom HapticPulse m_UndoPulse; UndoMenuUI m_UndoMenuUI; - List m_MenuActions; Transform m_AlternateMenuOrigin; MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; float m_PrevNavigateX; @@ -107,16 +105,18 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon return; } - if (undoMenuInput.engage.wasJustReleased && !m_TrackpadController) + var engage = undoMenuInput.engage; + if (engage.wasJustReleased && !m_TrackpadController) this.RestartCoroutine(ref m_StillEngagedAfterStickReleasedCoroutine, AcceptInputAfterStickReleased()); - if (!(undoMenuInput.engage.wasJustPressed || !m_TrackpadController && (undoMenuInput.engage.isHeld || m_StillEngagedAfterStickRelease))) + if (!(engage.wasJustPressed || !m_TrackpadController && (engage.isHeld || m_StillEngagedAfterStickRelease))) return; - consumeControl(undoMenuInput.engage); + consumeControl(engage); m_UndoMenuUI.engaged = true; - var navigateX = undoMenuInput.navigateX.value; + var navigateXControl = undoMenuInput.navigateX; + var navigateX = navigateXControl.value; var undoRedoPerformed = false; if (navigateX < -k_UndoRedoThreshold && (m_TrackpadController || m_PrevNavigateX > -k_UndoRedoThreshold)) { @@ -137,7 +137,7 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon if (undoRedoPerformed) { - consumeControl(undoMenuInput.navigateX); + consumeControl(navigateXControl); this.StopCoroutine(ref m_StillEngagedAfterStickReleasedCoroutine); this.Pulse(node, m_UndoPulse); } diff --git a/Scripts/Core/EditorVR.Menus.cs b/Scripts/Core/EditorVR.Menus.cs index 06b8afd40..c143cf97a 100644 --- a/Scripts/Core/EditorVR.Menus.cs +++ b/Scripts/Core/EditorVR.Menus.cs @@ -135,7 +135,7 @@ public void DisconnectInterface(object target, object userData = null) var customAlternateMenu = target as IAlternateMenu; if (customAlternateMenu != null) - RemoveCustomAlternateMenu(customAlternateMenu, rayOrigin); + RemoveCustomAlternateMenu(customAlternateMenu); } static void AddCustomAlternateMenu(IAlternateMenu alternateMenu, Transform rayOrigin) @@ -147,14 +147,15 @@ static void AddCustomAlternateMenu(IAlternateMenu alternateMenu, Transform rayOr device.alternateMenus.Add(alternateMenu); var menuHideData = new MenuHideData(); - device.menuHideData[alternateMenu] = menuHideData; + device.menuHideData[alternateMenu] = menuHideData; + // Alternate menus must be visible the first frame or they are ignored in the priority list menuHideData.hideFlags = 0; break; } } - static void RemoveCustomAlternateMenu(IAlternateMenu customAlternateMenu, Transform rayOrigin) + static void RemoveCustomAlternateMenu(IAlternateMenu customAlternateMenu) { foreach (var device in evr.m_DeviceData) { diff --git a/Scripts/Core/EditorVR.Tools.cs b/Scripts/Core/EditorVR.Tools.cs index dc9dec36d..15cd8baeb 100644 --- a/Scripts/Core/EditorVR.Tools.cs +++ b/Scripts/Core/EditorVR.Tools.cs @@ -138,7 +138,6 @@ internal void SpawnDefaultTools(IProxy proxy) var undoMenu = menus.SpawnMenu(rayOrigin); var hideData = new Menus.MenuHideData(); menuHideData[undoMenu] = hideData; - hideData.hideFlags = 0; // Setup ToolsMenu var toolsMenu = ObjectUtils.AddComponent(evr.gameObject); From 566c51685dfbc22ed5dfb620b6e6eb98c6db75f5 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Fri, 8 Dec 2017 16:25:47 -0800 Subject: [PATCH 83/89] Rename customAlternateMenu to alternateMenu --- Scripts/Core/EditorVR.Menus.cs | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/Scripts/Core/EditorVR.Menus.cs b/Scripts/Core/EditorVR.Menus.cs index c143cf97a..34f604250 100644 --- a/Scripts/Core/EditorVR.Menus.cs +++ b/Scripts/Core/EditorVR.Menus.cs @@ -97,9 +97,9 @@ public void ConnectInterface(object target, object userData = null) } } - var customAlternateMenu = target as IAlternateMenu; - if (customAlternateMenu != null) - AddCustomAlternateMenu(customAlternateMenu, rayOrigin); + var alternateMenu = target as IAlternateMenu; + if (alternateMenu != null) + AddAlternateMenu(alternateMenu, rayOrigin); } public void DisconnectInterface(object target, object userData = null) @@ -133,12 +133,12 @@ public void DisconnectInterface(object target, object userData = null) if (mainMenu != null && rayOrigin != null) m_MainMenus.Remove(rayOrigin); - var customAlternateMenu = target as IAlternateMenu; - if (customAlternateMenu != null) - RemoveCustomAlternateMenu(customAlternateMenu); + var alternateMenu = target as IAlternateMenu; + if (alternateMenu != null) + RemoveAlternateMenu(alternateMenu); } - static void AddCustomAlternateMenu(IAlternateMenu alternateMenu, Transform rayOrigin) + static void AddAlternateMenu(IAlternateMenu alternateMenu, Transform rayOrigin) { foreach (var device in evr.m_DeviceData) { @@ -155,12 +155,12 @@ static void AddCustomAlternateMenu(IAlternateMenu alternateMenu, Transform rayOr } } - static void RemoveCustomAlternateMenu(IAlternateMenu customAlternateMenu) + static void RemoveAlternateMenu(IAlternateMenu alternateMenu) { foreach (var device in evr.m_DeviceData) { - device.alternateMenus.Remove(customAlternateMenu); - device.menuHideData.Remove(customAlternateMenu); + device.alternateMenus.Remove(alternateMenu); + device.menuHideData.Remove(alternateMenu); } } @@ -245,17 +245,12 @@ internal void UpdateMenuVisibilities() var mainMenu = deviceData.mainMenu; var customMenu = deviceData.customMenu; MenuHideData customMenuHideData = null; - MenuHideData alternateMenuData = null; var mainMenuVisible = mainMenu != null && menuHideData[mainMenu].hideFlags == 0; - var mainMenuSupressed = mainMenu != null && ((menuHideData[mainMenu].hideFlags & MenuHideFlags.Occluded) != 0); + var mainMenuSupressed = mainMenu != null && ((menuHideData[mainMenu].hideFlags & MenuHideFlags.Occluded) != 0); - var alternateMenuVisible = false; - if (alternateMenu != null) - { - alternateMenuData = menuHideData[alternateMenu]; - alternateMenuVisible = alternateMenuData.hideFlags == 0; - } + var alternateMenuData = menuHideData[alternateMenu]; + var alternateMenuVisible = alternateMenuData.hideFlags == 0; var customMenuVisible = false; if (customMenu != null) From 54fd725f33782fb6f88ba566e9e56bef5fd9848c Mon Sep 17 00:00:00 2001 From: Stella Cannefax Date: Fri, 8 Dec 2017 16:52:55 -0800 Subject: [PATCH 84/89] consume vacuum double click control --- Tools/VacuumTool/VacuumTool.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tools/VacuumTool/VacuumTool.cs b/Tools/VacuumTool/VacuumTool.cs index bf6ec2bb0..5a83805f0 100644 --- a/Tools/VacuumTool/VacuumTool.cs +++ b/Tools/VacuumTool/VacuumTool.cs @@ -59,6 +59,8 @@ public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeCon var realTime = Time.realtimeSinceStartup; if (UIUtils.IsDoubleClick(realTime - m_LastClickTime)) { + consumeControl(vacuumInput.vacuum); + Coroutine coroutine; if (m_VacuumingCoroutines.TryGetValue(vacuumableTransform, out coroutine)) StopCoroutine(coroutine); From f71e815a9df8138236b354ae9566b478c8584d05 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Fri, 8 Dec 2017 17:00:05 -0800 Subject: [PATCH 85/89] Clean up unused code and fix style; Fix UndoMenu visibility --- Scripts/Core/EditorVR.Menus.cs | 6 ++--- Scripts/Core/EditorVR.Tools.cs | 1 + Tools/AnnotationTool/AnnotationTool.cs | 25 ------------------- .../UserInterface/ColorPickerActivator.cs | 2 -- Tools/LocomotionTool/LocomotionTool.cs | 1 + Tools/TransformTool/TransformTool.cs | 4 +-- 6 files changed, 6 insertions(+), 33 deletions(-) diff --git a/Scripts/Core/EditorVR.Menus.cs b/Scripts/Core/EditorVR.Menus.cs index 34f604250..d00b1cc3a 100644 --- a/Scripts/Core/EditorVR.Menus.cs +++ b/Scripts/Core/EditorVR.Menus.cs @@ -147,7 +147,7 @@ static void AddAlternateMenu(IAlternateMenu alternateMenu, Transform rayOrigin) device.alternateMenus.Add(alternateMenu); var menuHideData = new MenuHideData(); - device.menuHideData[alternateMenu] = menuHideData; + device.menuHideData[alternateMenu] = menuHideData; // Alternate menus must be visible the first frame or they are ignored in the priority list menuHideData.hideFlags = 0; @@ -247,7 +247,7 @@ internal void UpdateMenuVisibilities() MenuHideData customMenuHideData = null; var mainMenuVisible = mainMenu != null && menuHideData[mainMenu].hideFlags == 0; - var mainMenuSupressed = mainMenu != null && ((menuHideData[mainMenu].hideFlags & MenuHideFlags.Occluded) != 0); + var mainMenuSupressed = mainMenu != null && ((menuHideData[mainMenu].hideFlags & MenuHideFlags.Occluded) != 0); var alternateMenuData = menuHideData[alternateMenu]; var alternateMenuVisible = alternateMenuData.hideFlags == 0; @@ -350,7 +350,7 @@ internal void UpdateMenuVisibilities() evr.GetModule().UpdatePlayerHandleMaps(); } - void CheckDirectSelection(DeviceData deviceData, Dictionary menuHideData, bool alternateMenuVisible) + static void CheckDirectSelection(DeviceData deviceData, Dictionary menuHideData, bool alternateMenuVisible) { var viewerScale = Viewer.GetViewerScale(); var directSelection = evr.GetNestedModule(); diff --git a/Scripts/Core/EditorVR.Tools.cs b/Scripts/Core/EditorVR.Tools.cs index 15cd8baeb..dc9dec36d 100644 --- a/Scripts/Core/EditorVR.Tools.cs +++ b/Scripts/Core/EditorVR.Tools.cs @@ -138,6 +138,7 @@ internal void SpawnDefaultTools(IProxy proxy) var undoMenu = menus.SpawnMenu(rayOrigin); var hideData = new Menus.MenuHideData(); menuHideData[undoMenu] = hideData; + hideData.hideFlags = 0; // Setup ToolsMenu var toolsMenu = ObjectUtils.AddComponent(evr.gameObject); diff --git a/Tools/AnnotationTool/AnnotationTool.cs b/Tools/AnnotationTool/AnnotationTool.cs index c04e5f086..b6b63dd52 100644 --- a/Tools/AnnotationTool/AnnotationTool.cs +++ b/Tools/AnnotationTool/AnnotationTool.cs @@ -108,14 +108,12 @@ public float brushSize Vector3 m_OriginalAnnotationPointerLocalScale; Coroutine m_AnnotationPointerVisibilityCoroutine; bool m_WasOverUI; - bool m_WasDoingUndoRedo; GameObject m_ColorPickerActivator; Toggle m_TransformToggle; Toggle m_MeshToggle; bool m_BlockValueChangedListener; - MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; public bool primary { private get; set; } public Transform rayOrigin { get; set; } @@ -132,27 +130,6 @@ public float brushSize public GameObject settingsMenuItemPrefab { get { return m_SettingsMenuItemPrefab; } } - public int menuPriority { get { return 2; } } - - public MenuHideFlags menuHideFlags - { - get { return m_MenuHideFlags; } - set - { - if (m_MenuHideFlags != value) - { - m_MenuHideFlags = value; - var visible = m_MenuHideFlags == 0; - - if (m_BrushSizeUI) - m_BrushSizeUI.gameObject.SetActive(visible); - } - } - } - - public GameObject menuContent { get { return gameObject; } } - public Bounds localBounds { get; private set; } - public GameObject settingsMenuItemInstance { set @@ -345,8 +322,6 @@ void SetupBrushUI() transform.localRotation = Quaternion.Euler(-90, 0, 0); transform.localScale = scale; - localBounds = ObjectUtils.GetBounds(transform); - m_BrushSizeUI.onValueChanged = value => { var sliderValue = Mathf.Lerp(MinBrushSize, MaxBrushSize, value); diff --git a/Tools/AnnotationTool/UserInterface/ColorPickerActivator.cs b/Tools/AnnotationTool/UserInterface/ColorPickerActivator.cs index 0961b1a04..d66f51b61 100644 --- a/Tools/AnnotationTool/UserInterface/ColorPickerActivator.cs +++ b/Tools/AnnotationTool/UserInterface/ColorPickerActivator.cs @@ -2,8 +2,6 @@ using System; using System.Collections; using UnityEditor.Experimental.EditorVR.Extensions; -using UnityEditor.Experimental.EditorVR.UI; -using UnityEditor.Experimental.EditorVR.Utilities; using UnityEngine; using UnityEngine.EventSystems; diff --git a/Tools/LocomotionTool/LocomotionTool.cs b/Tools/LocomotionTool/LocomotionTool.cs index fb5162cfb..55cd28889 100644 --- a/Tools/LocomotionTool/LocomotionTool.cs +++ b/Tools/LocomotionTool/LocomotionTool.cs @@ -597,6 +597,7 @@ bool DoTwoHandedScaling(ConsumeControlDelegate consumeControl) consumeControl(otherLocomotionInput.horizontal); consumeControl(otherLocomotionInput.vertical); + // Pre-emptively consume thumbstick press to override UndoMenu consumeControl(m_LocomotionInput.scaleReset); consumeControl(otherLocomotionInput.scaleReset); diff --git a/Tools/TransformTool/TransformTool.cs b/Tools/TransformTool/TransformTool.cs index cd2ebf556..615ce81cf 100644 --- a/Tools/TransformTool/TransformTool.cs +++ b/Tools/TransformTool/TransformTool.cs @@ -601,9 +601,7 @@ public void Resume(Node node) public Transform[] GetHeldObjects(Node node) { var grabData = GrabDataForNode(node); - var heldObjects = grabData == null ? null : grabData.grabbedObjects; - Debug.Log(node + ", " +heldObjects.Length); - return heldObjects; + return grabData == null ? null : grabData.grabbedObjects; } public void TransferHeldObjects(Transform rayOrigin, Transform destRayOrigin, Vector3 deltaOffset = default(Vector3)) From 29e0cd1b7f89fe1542aa7a525f2f8169ed2da26d Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Fri, 8 Dec 2017 18:44:23 -0800 Subject: [PATCH 86/89] Force HDR on because of a bug in the mirror view --- Scripts/Core/VRView.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Scripts/Core/VRView.cs b/Scripts/Core/VRView.cs index a488b0483..9a004b457 100644 --- a/Scripts/Core/VRView.cs +++ b/Scripts/Core/VRView.cs @@ -162,6 +162,8 @@ public void OnEnable() m_Camera.clearFlags = CameraClearFlags.SolidColor; m_Camera.stereoTargetEye = StereoTargetEyeMask.Both; + // Force HDR on because of a bug in the mirror view + m_Camera.allowHDR = true; } else { From ea541afee5716fb9341ff953fc348ba147e79386 Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Fri, 8 Dec 2017 19:30:25 -0800 Subject: [PATCH 87/89] Fix serialized preferences not loading properly --- Scripts/Modules/SerializedPreferencesModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/Modules/SerializedPreferencesModule.cs b/Scripts/Modules/SerializedPreferencesModule.cs index 365dafaec..3d5754920 100644 --- a/Scripts/Modules/SerializedPreferencesModule.cs +++ b/Scripts/Modules/SerializedPreferencesModule.cs @@ -95,7 +95,7 @@ public void RemoveSerializer(ISerializePreferences serializer) internal void SetupWithPreferences(string serializedPreferences) { - m_Preferences = DeserializePreferences(serializedPreferences); + m_Preferences = DeserializePreferences(serializedPreferences, m_Serializers); } internal static SerializedPreferences DeserializePreferences(string serializedPreferences, List serializers = null) From f3fb99c787e0cc6d35cd648456f1a0a237566fdf Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Fri, 8 Dec 2017 22:01:40 -0800 Subject: [PATCH 88/89] Fix a bug where the player head was blocking UI raycasts --- Scripts/Core/EditorVR.Rays.cs | 6 ++++-- Scripts/Core/EditorVR.cs | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Scripts/Core/EditorVR.Rays.cs b/Scripts/Core/EditorVR.Rays.cs index aa8f83cea..194aff2c1 100644 --- a/Scripts/Core/EditorVR.Rays.cs +++ b/Scripts/Core/EditorVR.Rays.cs @@ -18,7 +18,7 @@ partial class EditorVR [SerializeField] ProxyExtras m_ProxyExtras; - class Rays : Nested, IInterfaceConnector, IForEachRayOrigin, IConnectInterfaces + class Rays : Nested, IInterfaceConnector, IForEachRayOrigin, IConnectInterfaces, IStandardIgnoreList { internal delegate void ForEachProxyDeviceCallback(DeviceData deviceData); @@ -35,6 +35,8 @@ class Rays : Nested, IInterfaceConnector, IForEachRayOrigin, IConnectInterfaces internal Transform lastSelectionRayOrigin { get; private set; } + public List ignoreList { private get; set; } + public Rays() { ISetDefaultRayColorMethods.setDefaultRayColor = SetDefaultRayColor; @@ -204,7 +206,7 @@ void OnProxyActiveChanged(IProxy proxy) var uiDistance = source.eventData.pointerCurrentRaycast.distance; // If the distance to a scene object is less than the distance to the hovered UI, invalidate the UI raycast - if (!isManipulator && raycastObject && sceneObjectDistance < uiDistance) + if (!isManipulator && raycastObject && sceneObjectDistance < uiDistance && !ignoreList.Contains(raycastObject)) return false; } diff --git a/Scripts/Core/EditorVR.cs b/Scripts/Core/EditorVR.cs index 2714e7d7e..29c2535de 100644 --- a/Scripts/Core/EditorVR.cs +++ b/Scripts/Core/EditorVR.cs @@ -194,6 +194,8 @@ void Awake() var intersectionModule = AddModule(); this.ConnectInterfaces(intersectionModule); intersectionModule.Setup(spatialHashModule.spatialHash); + // TODO: Support module dependencies via ConnectInterfaces + GetNestedModule().ignoreList = intersectionModule.standardIgnoreList; AddModule(); From 61d98856e11a41bd90f3850a0e01c3c03d38a5ab Mon Sep 17 00:00:00 2001 From: Matt Schoen Date: Mon, 11 Dec 2017 15:40:04 -0800 Subject: [PATCH 89/89] Fix tests --- Editor/ProxyFeedbackEditor.cs | 4 ++- .../Core/Contexts/EditingContextManager.cs | 29 ++++++++++--------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/Editor/ProxyFeedbackEditor.cs b/Editor/ProxyFeedbackEditor.cs index 8dd5b1898..0e739d505 100644 --- a/Editor/ProxyFeedbackEditor.cs +++ b/Editor/ProxyFeedbackEditor.cs @@ -1,4 +1,5 @@ -using System; +#if UNITY_2017_2_OR_NEWER +using System; using System.Collections.Generic; using UnityEditor.Experimental.EditorVR.Modules; using UnityEditor.Experimental.EditorVR.Proxies; @@ -141,3 +142,4 @@ void SaveData() } } } +#endif diff --git a/Scripts/Core/Contexts/EditingContextManager.cs b/Scripts/Core/Contexts/EditingContextManager.cs index ab2f8f903..efd5fa17d 100644 --- a/Scripts/Core/Contexts/EditingContextManager.cs +++ b/Scripts/Core/Contexts/EditingContextManager.cs @@ -144,20 +144,6 @@ static void OnPlayModeStateChanged(PlayModeStateChange stateChange) } } - void Awake() - { - s_DefaultContext = m_DefaultContext; - - var availableContexts = GetAvailableEditingContexts(); - m_ContextNames = availableContexts.Select(c => c.name).ToArray(); - - if (s_AvailableContexts.Count == 0) - throw new Exception("You can't start EditorXR without at least one context. Try re-importing the package or use version control to restore the default context asset"); - - if (s_AvailableContexts.Count > 1) - VRView.afterOnGUI += OnVRViewGUI; - } - void OnEnable() { ISetEditingContextMethods.getAvailableEditingContexts = GetAvailableEditingContexts; @@ -201,6 +187,21 @@ void OnDisable() } #endif + + void Awake() + { + s_DefaultContext = m_DefaultContext; + + var availableContexts = GetAvailableEditingContexts(); + m_ContextNames = availableContexts.Select(c => c.name).ToArray(); + + if (s_AvailableContexts.Count == 0) + throw new Exception("You can't start EditorXR without at least one context. Try re-importing the package or use version control to restore the default context asset"); + + if (s_AvailableContexts.Count > 1) + VRView.afterOnGUI += OnVRViewGUI; + } + void OnVRViewGUI(VRView view) { var position = view.position;