// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using Microsoft.MixedReality.Toolkit.UI; using UnityEngine; namespace Microsoft.MixedReality.Toolkit.Utilities { /// /// Interface defining a migration handler, which is used to migrate assets as they /// upgrade to new versions of MRTK. /// public class ObjectManipulatorMigrationHandler : IMigrationHandler { /// public bool CanMigrate(GameObject gameObject) { return gameObject.GetComponent() != null; } /// public void Migrate(GameObject gameObject) { var manipHandler = gameObject.GetComponent(); gameObject.AddComponent(); var objManip = gameObject.AddComponent(); objManip.enabled = manipHandler.enabled; objManip.HostTransform = manipHandler.HostTransform; switch (manipHandler.ManipulationType) { case ManipulationHandler.HandMovementType.OneHandedOnly: objManip.ManipulationType = ManipulationHandFlags.OneHanded; break; case ManipulationHandler.HandMovementType.TwoHandedOnly: objManip.ManipulationType = ManipulationHandFlags.TwoHanded; break; case ManipulationHandler.HandMovementType.OneAndTwoHanded: objManip.ManipulationType = ManipulationHandFlags.OneHanded | ManipulationHandFlags.TwoHanded; break; } objManip.AllowFarManipulation = manipHandler.AllowFarManipulation; if (manipHandler.OneHandRotationModeNear == manipHandler.OneHandRotationModeFar) { MigrateOneHandRotationModes(ref objManip, manipHandler.OneHandRotationModeNear, ManipulationProximityFlags.Near | ManipulationProximityFlags.Far); } else { MigrateOneHandRotationModes(ref objManip, manipHandler.OneHandRotationModeNear, ManipulationProximityFlags.Near); MigrateOneHandRotationModes(ref objManip, manipHandler.OneHandRotationModeFar, ManipulationProximityFlags.Far); } switch (manipHandler.TwoHandedManipulationType) { case ManipulationHandler.TwoHandedManipulation.Scale: objManip.TwoHandedManipulationType = TransformFlags.Scale; break; case ManipulationHandler.TwoHandedManipulation.Rotate: objManip.TwoHandedManipulationType = TransformFlags.Rotate; break; case ManipulationHandler.TwoHandedManipulation.MoveScale: objManip.TwoHandedManipulationType = TransformFlags.Move | TransformFlags.Scale; break; case ManipulationHandler.TwoHandedManipulation.MoveRotate: objManip.TwoHandedManipulationType = TransformFlags.Move | TransformFlags.Rotate; break; case ManipulationHandler.TwoHandedManipulation.RotateScale: objManip.TwoHandedManipulationType = TransformFlags.Rotate | TransformFlags.Scale; break; case ManipulationHandler.TwoHandedManipulation.MoveRotateScale: objManip.TwoHandedManipulationType = TransformFlags.Move | TransformFlags.Rotate | TransformFlags.Scale; break; } objManip.ReleaseBehavior = (ObjectManipulator.ReleaseBehaviorType)manipHandler.ReleaseBehavior; if (manipHandler.ConstraintOnRotation != RotationConstraintType.None) { var rotateConstraint = objManip.EnsureComponent(); rotateConstraint.ConstraintOnRotation = RotationConstraintHelper.ConvertToAxisFlags(manipHandler.ConstraintOnRotation); } if (manipHandler.ConstraintOnMovement == MovementConstraintType.FixDistanceFromHead) { var moveConstraint = objManip.EnsureComponent(); moveConstraint.ConstraintTransform = CameraCache.Main.transform; } objManip.SmoothingFar = manipHandler.SmoothingActive; objManip.MoveLerpTime = manipHandler.SmoothingAmoutOneHandManip; objManip.RotateLerpTime = manipHandler.SmoothingAmoutOneHandManip; objManip.ScaleLerpTime = manipHandler.SmoothingAmoutOneHandManip; objManip.OnManipulationStarted = manipHandler.OnManipulationStarted; objManip.OnManipulationEnded = manipHandler.OnManipulationEnded; objManip.OnHoverEntered = manipHandler.OnHoverEntered; objManip.OnHoverExited = manipHandler.OnHoverExited; // finally check if there's a CursorContextManipulationHandler on the gameObject that we have to swap CursorContextManipulationHandler cursorContextManipHandler = gameObject.GetComponent(); if (cursorContextManipHandler) { gameObject.AddComponent(); // remove old component Object.DestroyImmediate(cursorContextManipHandler); } Object.DestroyImmediate(manipHandler); } private void MigrateOneHandRotationModes(ref ObjectManipulator objManip, ManipulationHandler.RotateInOneHandType oldMode, ManipulationProximityFlags proximity) { ObjectManipulator.RotateInOneHandType newMode = ObjectManipulator.RotateInOneHandType.RotateAboutGrabPoint; switch (oldMode) { case ManipulationHandler.RotateInOneHandType.MaintainRotationToUser: { newMode = ObjectManipulator.RotateInOneHandType.RotateAboutGrabPoint; var constraint = objManip.EnsureComponent(); constraint.HandType = ManipulationHandFlags.OneHanded; constraint.ProximityType = proximity; break; } case ManipulationHandler.RotateInOneHandType.GravityAlignedMaintainRotationToUser: { newMode = ObjectManipulator.RotateInOneHandType.RotateAboutGrabPoint; var rotConstraint = objManip.EnsureComponent(); rotConstraint.HandType = ManipulationHandFlags.OneHanded; rotConstraint.ProximityType = proximity; var axisConstraint = objManip.EnsureComponent(); axisConstraint.HandType = ManipulationHandFlags.OneHanded; axisConstraint.ProximityType = proximity; axisConstraint.ConstraintOnRotation = AxisFlags.XAxis | AxisFlags.ZAxis; break; } case ManipulationHandler.RotateInOneHandType.FaceUser: { newMode = ObjectManipulator.RotateInOneHandType.RotateAboutGrabPoint; var rotConstraint = objManip.EnsureComponent(); rotConstraint.HandType = ManipulationHandFlags.OneHanded; rotConstraint.ProximityType = proximity; rotConstraint.FaceAway = false; break; } case ManipulationHandler.RotateInOneHandType.FaceAwayFromUser: { newMode = ObjectManipulator.RotateInOneHandType.RotateAboutGrabPoint; var rotConstraint = objManip.EnsureComponent(); rotConstraint.HandType = ManipulationHandFlags.OneHanded; rotConstraint.ProximityType = proximity; rotConstraint.FaceAway = true; break; } case ManipulationHandler.RotateInOneHandType.MaintainOriginalRotation: { newMode = ObjectManipulator.RotateInOneHandType.RotateAboutGrabPoint; var rotConstraint = objManip.EnsureComponent(); rotConstraint.HandType = ManipulationHandFlags.OneHanded; rotConstraint.ProximityType = proximity; break; } case ManipulationHandler.RotateInOneHandType.RotateAboutObjectCenter: newMode = ObjectManipulator.RotateInOneHandType.RotateAboutObjectCenter; break; case ManipulationHandler.RotateInOneHandType.RotateAboutGrabPoint: newMode = ObjectManipulator.RotateInOneHandType.RotateAboutGrabPoint; break; } if (proximity.IsMaskSet(ManipulationProximityFlags.Near)) { objManip.OneHandRotationModeNear = newMode; } if (proximity.IsMaskSet(ManipulationProximityFlags.Far)) { objManip.OneHandRotationModeFar = newMode; } } } }