From dd27d72daeefca99519073fc2b75cf36a16ccf38 Mon Sep 17 00:00:00 2001 From: Nayanathara Palanivel <39957281+nayanatharap@users.noreply.github.com> Date: Wed, 29 Jan 2025 14:16:29 -0800 Subject: [PATCH 1/6] Introduce ScaleMaintainType Introduce different options for scaling bounds handles. The options include: - Maintaining global size (previously stored as a separate bool property) - Setting scale based on initial parent scale - Adjusting scale to retain same size --- .../BoundsControl/BoundsControlTypes.cs | 26 +++- .../BoundsControl/BoundsHandleInteractable.cs | 122 ++++++++++++++---- .../Editor/BoundsControl.meta | 8 ++ .../BoundsHandleInteractableEditor.cs | 49 +++++++ .../BoundsHandleInteractableEditor.cs.meta | 11 ++ 5 files changed, 186 insertions(+), 30 deletions(-) create mode 100644 org.mixedrealitytoolkit.spatialmanipulation/Editor/BoundsControl.meta create mode 100644 org.mixedrealitytoolkit.spatialmanipulation/Editor/BoundsControl/BoundsHandleInteractableEditor.cs create mode 100644 org.mixedrealitytoolkit.spatialmanipulation/Editor/BoundsControl/BoundsHandleInteractableEditor.cs.meta diff --git a/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsControlTypes.cs b/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsControlTypes.cs index 388a64eea..6da885e29 100644 --- a/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsControlTypes.cs +++ b/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsControlTypes.cs @@ -56,12 +56,12 @@ public enum HandleType /// A handle that is mounted to the edge of a , and can rotate the object. /// Rotation = 1 << 0, - + /// /// A handle that is mounted to the corner of a , and can scale the object. /// Scale = 1 << 1, - + /// /// A handle that is mounted to the face of a , and can move the object. /// @@ -109,4 +109,26 @@ public enum FlattenMode /// Always, } + + /// + /// Scale adjusting type that is used for determining how to maintain target scale of bounds control. + /// + public enum ScaleMaintainType + { + /// + /// Maintain global size, even as the object changes size. + /// + GlobalSize, + + /// + /// Adjust the handle's scale based on the initial parent scale. + /// + InitialParentScale, + + /// + /// Adjust the handle's scale to be the same size regardless of the + /// initial parent scale and clamp the scale to a min and max value + /// + ClampedSize + } } diff --git a/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsHandleInteractable.cs b/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsHandleInteractable.cs index 58f5b875d..9d7785ace 100644 --- a/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsHandleInteractable.cs +++ b/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsHandleInteractable.cs @@ -2,6 +2,7 @@ // Licensed under the BSD 3-Clause using System; +using UnityEditor; using UnityEngine; using UnityEngine.XR.Interaction.Toolkit; @@ -36,13 +37,34 @@ public BoundsControl BoundsControlRoot } [SerializeField] - [Tooltip("Should the handle maintain its global size, even as the object changes size?")] - private bool maintainGlobalSize = true; + [Tooltip("How should the handle scale be maintained?")] + private ScaleMaintainType scaleMaintainType = ScaleMaintainType.GlobalSize; + // For backward compatibilty, the scaleAdjustType is set according to the maintainGlobalSize property on start. + private bool maintainGlobalSize = true; /// /// Should the handle maintain its global size, even as the object changes size? /// - public bool MaintainGlobalSize { get => maintainGlobalSize; set => maintainGlobalSize = value;} + [Obsolete("Use ScaleMaintainType instead.")] + public bool MaintainGlobalSize + { + get => scaleMaintainType == ScaleMaintainType.GlobalSize; + set => scaleMaintainType = value ? ScaleMaintainType.GlobalSize : ScaleMaintainType.InitialParentScale; + } + + private float targetParentScale = 1f; + + [SerializeField] + [Tooltip("Target lossy scale for the handle. Set value only applicable if ScaleAdjustType is ClampedSize.")] + private float targetLossyScale = 2f; + + [SerializeField] + [Tooltip("Minimum lossy scale for the handle. Only applicable if ScaleAdjustType is ClampedSize.")] + private float minLossyScale = 1f; + + [SerializeField] + [Tooltip("Maximum lossy scale for the handle. Only applicable if ScaleAdjustType is ClampedSize.")] + private float maxLossyScale = 4f; #region ISnapInteractable @@ -89,10 +111,6 @@ public BoundsControl BoundsControlRoot private bool wasOccludedLastFrame = false; - private float initialParentScale; - - private float initialLocalScale; - /// protected override void Awake() { @@ -102,6 +120,7 @@ protected override void Awake() DisableInteractorType(typeof(IPokeInteractor)); handleRenderer = GetComponentInChildren(); + scaleMaintainType = maintainGlobalSize ? ScaleMaintainType.GlobalSize : ScaleMaintainType.InitialParentScale; } /// @@ -109,10 +128,14 @@ protected override void Awake() /// public void Start() { - // Record initial values at Start(), so that we - // capture the bounds sizing, etc. - initialParentScale = MaxComponent(transform.parent.lossyScale); - initialLocalScale = MaxComponent(transform.localScale); + if (scaleMaintainType == ScaleMaintainType.GlobalSize || + scaleMaintainType == ScaleMaintainType.InitialParentScale) + { + // Record initial values at Start(), so that we + // capture the bounds sizing, etc. + targetParentScale = MaxComponent(transform.parent.lossyScale); + targetLossyScale = MaxComponent(transform.localScale); + } } /// @@ -132,26 +155,69 @@ protected virtual void LateUpdate() } // Maintain the aspect ratio/proportion of the handles, globally. - // Setting localScale to ensure that lossyScale remains equal to initialLocalScale across all axes. + UpdateLocalScale(); + } + + protected virtual void UpdateLocalScale() + { transform.localScale = Vector3.one; - transform.localScale = new Vector3( - transform.lossyScale.x == 0 ? transform.localScale.x : (initialLocalScale / transform.lossyScale.x), - transform.lossyScale.y == 0 ? transform.localScale.y : (initialLocalScale / transform.lossyScale.y), - transform.lossyScale.z == 0 ? transform.localScale.z : (initialLocalScale / transform.lossyScale.z)); - - // If we don't want to maintain the overall *size*, we scale - // by the maximum component of the box so that the handles grow/shrink - // with the overall box manipulation. - if (!maintainGlobalSize && initialParentScale != 0) + + switch (scaleMaintainType) { - transform.localScale = transform.localScale * (MaxComponent(transform.parent.lossyScale) / initialParentScale); + case ScaleMaintainType.GlobalSize: + transform.localScale = GetLocalScale(targetLossyScale); + break; + + case ScaleMaintainType.InitialParentScale: + transform.localScale = GetLocalScale(targetLossyScale); + + // If we don't want to maintain the overall *size*, we scale + // by the maximum component of the box so that the handles grow/shrink + // with the overall box manipulation. + if (targetParentScale != 0) + { + transform.localScale = transform.localScale * (MaxComponent(transform.parent.lossyScale) / targetParentScale); + } + break; + + case ScaleMaintainType.ClampedSize: + // Find the local scale that would result in the target lossy + // scale (the desired scale if the parent scale is 1) + Vector3 targetScale = GetLocalScale(targetLossyScale); + Vector3 minScale = GetLocalScale(minLossyScale); + Vector3 maxScale = GetLocalScale(maxLossyScale); + + // We scale by the maximum component of the box so that + // the handles grow/shrink with the overall box manipulation. + transform.localScale = targetScale * (MaxComponent(transform.parent.lossyScale) / targetParentScale); + + // If this scale is greater than our desired lossy scale then clamp it to the max lossy scale + if (MaxComponent(transform.lossyScale) > maxLossyScale) + { + transform.localScale = maxScale; + } + // If this scale is less than our desired lossy scale then clamp it to the min lossy scale + else if (MinComponent(transform.lossyScale) < minLossyScale) + { + transform.localScale = minScale; + } + break; + + default: + break; } } - private float MaxComponent(Vector3 v) - { - return Mathf.Max(Mathf.Max(Mathf.Abs(v.x), Mathf.Abs(v.y)), Mathf.Abs(v.z)); - } + // Returns the local scale this transform needs to have in order to have the desired lossy scale + protected Vector3 GetLocalScale(float lossyScale) => new( + transform.lossyScale.x == 0 ? transform.localScale.x : (lossyScale / transform.lossyScale.x), + transform.lossyScale.y == 0 ? transform.localScale.y : (lossyScale / transform.lossyScale.y), + transform.lossyScale.z == 0 ? transform.localScale.z : (lossyScale / transform.lossyScale.z) + ); + + protected float MaxComponent(Vector3 v) => Mathf.Max(Mathf.Max(Mathf.Abs(v.x), Mathf.Abs(v.y)), Mathf.Abs(v.z)); + + protected float MinComponent(Vector3 v) => Mathf.Min(Mathf.Max(Mathf.Abs(v.x), Mathf.Abs(v.y)), Mathf.Abs(v.z)); /// /// Occludes the handle so it is not initially visible when it should start disabled. @@ -163,7 +229,7 @@ public void HideOnStartup() { handleRenderer.enabled = false; } - if (colliders.Count > 0 && colliders[0] != null) + if (colliders.Count > 0 && colliders[0] != null) { colliders[0].enabled = false; } @@ -183,7 +249,7 @@ internal void ForceOcclusion() { handleRenderer.enabled = false; } - if (colliders.Count > 0 && colliders[0] != null) + if (colliders.Count > 0 && colliders[0] != null) { colliders[0].enabled = false; } diff --git a/org.mixedrealitytoolkit.spatialmanipulation/Editor/BoundsControl.meta b/org.mixedrealitytoolkit.spatialmanipulation/Editor/BoundsControl.meta new file mode 100644 index 000000000..64681df1b --- /dev/null +++ b/org.mixedrealitytoolkit.spatialmanipulation/Editor/BoundsControl.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ddd4592e168845d4fb16f531e8cb14d0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/org.mixedrealitytoolkit.spatialmanipulation/Editor/BoundsControl/BoundsHandleInteractableEditor.cs b/org.mixedrealitytoolkit.spatialmanipulation/Editor/BoundsControl/BoundsHandleInteractableEditor.cs new file mode 100644 index 000000000..2bd685700 --- /dev/null +++ b/org.mixedrealitytoolkit.spatialmanipulation/Editor/BoundsControl/BoundsHandleInteractableEditor.cs @@ -0,0 +1,49 @@ +// Copyright (c) Mixed Reality Toolkit Contributors +// Licensed under the BSD 3-Clause + +using MixedReality.Toolkit.Editor; +using UnityEditor; + +namespace MixedReality.Toolkit.SpatialManipulation.Editor +{ + [CustomEditor(typeof(BoundsHandleInteractable), true)] + [CanEditMultipleObjects] + public class BoundsHandleInteractableEditor : StatefulInteractableEditor + { + private SerializedProperty scaleMaintainType; + private SerializedProperty targetLossyScale; + private SerializedProperty minLossyScale; + private SerializedProperty maxLossyScale; + private SerializedProperty handleType; + + protected override void OnEnable() + { + base.OnEnable(); + + scaleMaintainType = serializedObject.FindProperty("scaleMaintainType"); + targetLossyScale = serializedObject.FindProperty("targetLossyScale"); + minLossyScale = serializedObject.FindProperty("minLossyScale"); + maxLossyScale = serializedObject.FindProperty("maxLossyScale"); + handleType = serializedObject.FindProperty("handleType"); + } + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + serializedObject.Update(); + + EditorGUILayout.PropertyField(scaleMaintainType); + + if (scaleMaintainType.enumValueIndex == (int)ScaleMaintainType.ClampedSize) + { + EditorGUILayout.PropertyField(targetLossyScale); + EditorGUILayout.PropertyField(minLossyScale); + EditorGUILayout.PropertyField(maxLossyScale); + } + + EditorGUILayout.PropertyField(handleType); + + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/org.mixedrealitytoolkit.spatialmanipulation/Editor/BoundsControl/BoundsHandleInteractableEditor.cs.meta b/org.mixedrealitytoolkit.spatialmanipulation/Editor/BoundsControl/BoundsHandleInteractableEditor.cs.meta new file mode 100644 index 000000000..db2bb7329 --- /dev/null +++ b/org.mixedrealitytoolkit.spatialmanipulation/Editor/BoundsControl/BoundsHandleInteractableEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b2ed606a486b0a64cbf68858234ff39b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From eb486947be2b124d19aa0904a98bf52b8ccf4dde Mon Sep 17 00:00:00 2001 From: Nayanathara Palanivel <39957281+nayanatharap@users.noreply.github.com> Date: Fri, 31 Jan 2025 13:57:35 -0800 Subject: [PATCH 2/6] Update CHANGELOG.md --- org.mixedrealitytoolkit.spatialmanipulation/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/org.mixedrealitytoolkit.spatialmanipulation/CHANGELOG.md b/org.mixedrealitytoolkit.spatialmanipulation/CHANGELOG.md index 8073d0cc1..7aaeb53f9 100644 --- a/org.mixedrealitytoolkit.spatialmanipulation/CHANGELOG.md +++ b/org.mixedrealitytoolkit.spatialmanipulation/CHANGELOG.md @@ -4,6 +4,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## Unreleased +### Added + +* Added different types of maintaining scale for bounds handles. [PR #976](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/976) + ### Fixed * Fixed tap to place `StartPlacement()` when called just after instantiation of the component. [PR #785](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/785) From 80532dc8fcb744f859fc58f47735f3396ad97f55 Mon Sep 17 00:00:00 2001 From: Nayanathara Palanivel <39957281+nayanatharap@users.noreply.github.com> Date: Fri, 31 Jan 2025 16:15:41 -0800 Subject: [PATCH 3/6] Update package.json --- org.mixedrealitytoolkit.spatialmanipulation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.mixedrealitytoolkit.spatialmanipulation/package.json b/org.mixedrealitytoolkit.spatialmanipulation/package.json index b423ff90b..441a2029e 100644 --- a/org.mixedrealitytoolkit.spatialmanipulation/package.json +++ b/org.mixedrealitytoolkit.spatialmanipulation/package.json @@ -1,6 +1,6 @@ { "name": "org.mixedrealitytoolkit.spatialmanipulation", - "version": "3.3.1-development", + "version": "3.3.2-development", "description": "Spatial manipulation features, including ObjectManipulator, BoundsControl, and the Solvers/Constraints systems.", "displayName": "MRTK Spatial Manipulation", "msftFeatureCategory": "MRTK3", From e83071496bb35ea14d4353b2fe0359e88e21962f Mon Sep 17 00:00:00 2001 From: Nayanathara Palanivel <39957281+nayanatharap@users.noreply.github.com> Date: Fri, 31 Jan 2025 16:50:14 -0800 Subject: [PATCH 4/6] Rename options --- .../BoundsControl/BoundsControlTypes.cs | 13 ++++++++----- .../BoundsControl/BoundsHandleInteractable.cs | 16 ++++++++-------- .../BoundsHandleInteractableEditor.cs | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsControlTypes.cs b/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsControlTypes.cs index 6da885e29..29447d526 100644 --- a/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsControlTypes.cs +++ b/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsControlTypes.cs @@ -2,6 +2,7 @@ // Licensed under the BSD 3-Clause using System; +using UnityEngine; namespace MixedReality.Toolkit.SpatialManipulation { @@ -118,17 +119,19 @@ public enum ScaleMaintainType /// /// Maintain global size, even as the object changes size. /// + [Tooltip("Maintain global size, even as the object changes size.")] GlobalSize, /// - /// Adjust the handle's scale based on the initial parent scale. + /// Adjust the handle's scale based on the initial parent scale. /// - InitialParentScale, + [Tooltip("Adjust the handle's scale based on the initial parent scale.")] + FixedScale, /// - /// Adjust the handle's scale to be the same size regardless of the - /// initial parent scale and clamp the scale to a min and max value + /// Adjust the handle's scale to be the same size regardless of the initial parent scale and clamp the scale to a min and max value. /// - ClampedSize + [Tooltip("Adjust the handle's scale to be the same size regardless of the initial parent scale and clamp the scale to a min and max value.")] + Advanced } } diff --git a/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsHandleInteractable.cs b/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsHandleInteractable.cs index 9d7785ace..7f3256a47 100644 --- a/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsHandleInteractable.cs +++ b/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsHandleInteractable.cs @@ -49,21 +49,21 @@ public BoundsControl BoundsControlRoot public bool MaintainGlobalSize { get => scaleMaintainType == ScaleMaintainType.GlobalSize; - set => scaleMaintainType = value ? ScaleMaintainType.GlobalSize : ScaleMaintainType.InitialParentScale; + set => scaleMaintainType = value ? ScaleMaintainType.GlobalSize : ScaleMaintainType.FixedScale; } private float targetParentScale = 1f; [SerializeField] - [Tooltip("Target lossy scale for the handle. Set value only applicable if ScaleAdjustType is ClampedSize.")] + [Tooltip("Target lossy scale for the handle. Set value only applicable if ScaleAdjustType is Advanced.")] private float targetLossyScale = 2f; [SerializeField] - [Tooltip("Minimum lossy scale for the handle. Only applicable if ScaleAdjustType is ClampedSize.")] + [Tooltip("Minimum lossy scale for the handle. Only applicable if ScaleAdjustType is Advanced.")] private float minLossyScale = 1f; [SerializeField] - [Tooltip("Maximum lossy scale for the handle. Only applicable if ScaleAdjustType is ClampedSize.")] + [Tooltip("Maximum lossy scale for the handle. Only applicable if ScaleAdjustType is Advanced.")] private float maxLossyScale = 4f; #region ISnapInteractable @@ -120,7 +120,7 @@ protected override void Awake() DisableInteractorType(typeof(IPokeInteractor)); handleRenderer = GetComponentInChildren(); - scaleMaintainType = maintainGlobalSize ? ScaleMaintainType.GlobalSize : ScaleMaintainType.InitialParentScale; + scaleMaintainType = maintainGlobalSize ? ScaleMaintainType.GlobalSize : ScaleMaintainType.FixedScale; } /// @@ -129,7 +129,7 @@ protected override void Awake() public void Start() { if (scaleMaintainType == ScaleMaintainType.GlobalSize || - scaleMaintainType == ScaleMaintainType.InitialParentScale) + scaleMaintainType == ScaleMaintainType.FixedScale) { // Record initial values at Start(), so that we // capture the bounds sizing, etc. @@ -168,7 +168,7 @@ protected virtual void UpdateLocalScale() transform.localScale = GetLocalScale(targetLossyScale); break; - case ScaleMaintainType.InitialParentScale: + case ScaleMaintainType.FixedScale: transform.localScale = GetLocalScale(targetLossyScale); // If we don't want to maintain the overall *size*, we scale @@ -180,7 +180,7 @@ protected virtual void UpdateLocalScale() } break; - case ScaleMaintainType.ClampedSize: + case ScaleMaintainType.Advanced: // Find the local scale that would result in the target lossy // scale (the desired scale if the parent scale is 1) Vector3 targetScale = GetLocalScale(targetLossyScale); diff --git a/org.mixedrealitytoolkit.spatialmanipulation/Editor/BoundsControl/BoundsHandleInteractableEditor.cs b/org.mixedrealitytoolkit.spatialmanipulation/Editor/BoundsControl/BoundsHandleInteractableEditor.cs index 2bd685700..186fe2711 100644 --- a/org.mixedrealitytoolkit.spatialmanipulation/Editor/BoundsControl/BoundsHandleInteractableEditor.cs +++ b/org.mixedrealitytoolkit.spatialmanipulation/Editor/BoundsControl/BoundsHandleInteractableEditor.cs @@ -34,7 +34,7 @@ public override void OnInspectorGUI() EditorGUILayout.PropertyField(scaleMaintainType); - if (scaleMaintainType.enumValueIndex == (int)ScaleMaintainType.ClampedSize) + if (scaleMaintainType.enumValueIndex == (int)ScaleMaintainType.Advanced) { EditorGUILayout.PropertyField(targetLossyScale); EditorGUILayout.PropertyField(minLossyScale); From 1f360c69a5a2172aa754ae9b58d0d1064debe442 Mon Sep 17 00:00:00 2001 From: Nayanathara Palanivel <39957281+nayanatharap@users.noreply.github.com> Date: Fri, 7 Feb 2025 15:24:53 -0800 Subject: [PATCH 5/6] Cleanup code --- .../BoundsControl/BoundsHandleInteractable.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsHandleInteractable.cs b/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsHandleInteractable.cs index 7f3256a47..bb338cafd 100644 --- a/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsHandleInteractable.cs +++ b/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsHandleInteractable.cs @@ -2,7 +2,6 @@ // Licensed under the BSD 3-Clause using System; -using UnityEditor; using UnityEngine; using UnityEngine.XR.Interaction.Toolkit; @@ -128,8 +127,7 @@ protected override void Awake() /// public void Start() { - if (scaleMaintainType == ScaleMaintainType.GlobalSize || - scaleMaintainType == ScaleMaintainType.FixedScale) + if (scaleMaintainType != ScaleMaintainType.Advanced) { // Record initial values at Start(), so that we // capture the bounds sizing, etc. From 0c554bcf5477a2e798c7d6e3924c999cde8602f1 Mon Sep 17 00:00:00 2001 From: Nayanathara Palanivel <39957281+nayanatharap@users.noreply.github.com> Date: Thu, 13 Feb 2025 13:41:30 -0800 Subject: [PATCH 6/6] PR comment fixes --- .../BoundsControl/BoundsHandleInteractable.cs | 42 +++++++++++++------ .../MRTK.SpatialManipulation.asmdef | 35 ++++++++-------- .../package.json | 2 +- 3 files changed, 48 insertions(+), 31 deletions(-) diff --git a/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsHandleInteractable.cs b/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsHandleInteractable.cs index bb338cafd..e8725de96 100644 --- a/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsHandleInteractable.cs +++ b/org.mixedrealitytoolkit.spatialmanipulation/BoundsControl/BoundsHandleInteractable.cs @@ -4,6 +4,7 @@ using System; using UnityEngine; using UnityEngine.XR.Interaction.Toolkit; +using Unity.XR.CoreUtils; namespace MixedReality.Toolkit.SpatialManipulation { @@ -12,7 +13,7 @@ namespace MixedReality.Toolkit.SpatialManipulation /// Scale handles subclass this to implement custom occlusion + reorientation logic. /// [AddComponentMenu("MRTK/Spatial Manipulation/Bounds Handle Interactable")] - public class BoundsHandleInteractable : StatefulInteractable, ISnapInteractable + public class BoundsHandleInteractable : StatefulInteractable, ISnapInteractable, ISerializationCallbackReceiver { private BoundsControl boundsControlRoot; @@ -39,8 +40,15 @@ public BoundsControl BoundsControlRoot [Tooltip("How should the handle scale be maintained?")] private ScaleMaintainType scaleMaintainType = ScaleMaintainType.GlobalSize; - // For backward compatibilty, the scaleAdjustType is set according to the maintainGlobalSize property on start. + // A temporary variable used to migrate instances of FollowJoint to use the jointPoseSource class as the source of truth + // rather than its own separately serialized values. + // TODO: Remove this after some time to ensure users have successfully migrated. + [SerializeField, HideInInspector] + private bool migratedSuccessfully = false; + + [SerializeField, HideInInspector] private bool maintainGlobalSize = true; + /// /// Should the handle maintain its global size, even as the object changes size? /// @@ -51,6 +59,18 @@ public bool MaintainGlobalSize set => scaleMaintainType = value ? ScaleMaintainType.GlobalSize : ScaleMaintainType.FixedScale; } + public void OnBeforeSerialize() { } + + public void OnAfterDeserialize() + { + // Only update the scaleMaintainType if it hasn't been set and the old property was not migrated yet + if (!migratedSuccessfully && scaleMaintainType == ScaleMaintainType.GlobalSize) + { + scaleMaintainType = maintainGlobalSize ? ScaleMaintainType.GlobalSize : ScaleMaintainType.FixedScale; + migratedSuccessfully = true; + } + } + private float targetParentScale = 1f; [SerializeField] @@ -119,7 +139,6 @@ protected override void Awake() DisableInteractorType(typeof(IPokeInteractor)); handleRenderer = GetComponentInChildren(); - scaleMaintainType = maintainGlobalSize ? ScaleMaintainType.GlobalSize : ScaleMaintainType.FixedScale; } /// @@ -131,8 +150,8 @@ public void Start() { // Record initial values at Start(), so that we // capture the bounds sizing, etc. - targetParentScale = MaxComponent(transform.parent.lossyScale); - targetLossyScale = MaxComponent(transform.localScale); + targetParentScale = transform.parent.lossyScale.MaxComponent(); + targetLossyScale = transform.localScale.MaxComponent(); } } @@ -174,7 +193,7 @@ protected virtual void UpdateLocalScale() // with the overall box manipulation. if (targetParentScale != 0) { - transform.localScale = transform.localScale * (MaxComponent(transform.parent.lossyScale) / targetParentScale); + transform.localScale = transform.localScale * (transform.parent.lossyScale.MaxComponent() / targetParentScale); } break; @@ -187,15 +206,15 @@ protected virtual void UpdateLocalScale() // We scale by the maximum component of the box so that // the handles grow/shrink with the overall box manipulation. - transform.localScale = targetScale * (MaxComponent(transform.parent.lossyScale) / targetParentScale); + transform.localScale = targetScale * (transform.parent.lossyScale.MaxComponent() / targetParentScale); // If this scale is greater than our desired lossy scale then clamp it to the max lossy scale - if (MaxComponent(transform.lossyScale) > maxLossyScale) + if (transform.lossyScale.MaxComponent() > maxLossyScale) { transform.localScale = maxScale; } // If this scale is less than our desired lossy scale then clamp it to the min lossy scale - else if (MinComponent(transform.lossyScale) < minLossyScale) + else if (transform.lossyScale.MinComponent() < minLossyScale) { transform.localScale = minScale; } @@ -213,9 +232,6 @@ protected virtual void UpdateLocalScale() transform.lossyScale.z == 0 ? transform.localScale.z : (lossyScale / transform.lossyScale.z) ); - protected float MaxComponent(Vector3 v) => Mathf.Max(Mathf.Max(Mathf.Abs(v.x), Mathf.Abs(v.y)), Mathf.Abs(v.z)); - - protected float MinComponent(Vector3 v) => Mathf.Min(Mathf.Max(Mathf.Abs(v.x), Mathf.Abs(v.y)), Mathf.Abs(v.z)); /// /// Occludes the handle so it is not initially visible when it should start disabled. @@ -268,4 +284,4 @@ protected override void OnSelectExited(SelectExitEventArgs args) BoundsControlRoot.OnHandleSelectExited(this, args); } } -} +} \ No newline at end of file diff --git a/org.mixedrealitytoolkit.spatialmanipulation/MRTK.SpatialManipulation.asmdef b/org.mixedrealitytoolkit.spatialmanipulation/MRTK.SpatialManipulation.asmdef index 8cccb514c..e0c489081 100644 --- a/org.mixedrealitytoolkit.spatialmanipulation/MRTK.SpatialManipulation.asmdef +++ b/org.mixedrealitytoolkit.spatialmanipulation/MRTK.SpatialManipulation.asmdef @@ -1,18 +1,19 @@ { - "name": "MixedReality.Toolkit.SpatialManipulation", - "rootNamespace": "MixedReality.Toolkit.SpatialManipulation", - "references": [ - "MixedReality.Toolkit.Core", - "Unity.InputSystem", - "Unity.XR.Interaction.Toolkit" - ], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [], - "noEngineReferences": false -} \ No newline at end of file + "name": "MixedReality.Toolkit.SpatialManipulation", + "rootNamespace": "MixedReality.Toolkit.SpatialManipulation", + "references": [ + "MixedReality.Toolkit.Core", + "Unity.InputSystem", + "Unity.XR.CoreUtils", + "Unity.XR.Interaction.Toolkit" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} diff --git a/org.mixedrealitytoolkit.spatialmanipulation/package.json b/org.mixedrealitytoolkit.spatialmanipulation/package.json index 441a2029e..e86976bc5 100644 --- a/org.mixedrealitytoolkit.spatialmanipulation/package.json +++ b/org.mixedrealitytoolkit.spatialmanipulation/package.json @@ -1,6 +1,6 @@ { "name": "org.mixedrealitytoolkit.spatialmanipulation", - "version": "3.3.2-development", + "version": "3.4.0-development", "description": "Spatial manipulation features, including ObjectManipulator, BoundsControl, and the Solvers/Constraints systems.", "displayName": "MRTK Spatial Manipulation", "msftFeatureCategory": "MRTK3",