// // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. // using UnityEngine; using System.Collections; using System.Collections.Generic; namespace HoloToolkit.Unity { /// <summary> /// SolverBodyLock provides a solver that follows the TrackedObject/TargetTransform. Adjusting "LerpTime" /// properties changes how quickly the object moves to the TracketObject/TargetTransform's position. /// </summary> public class SolverBodyLock : Solver { #region public enums public enum OrientationReference { /// <summary> /// Orient towards SolverHandler's tracked object or TargetTransform /// </summary> Default, /// <summary> /// Orient toward Camera.main instead of SolverHandler's properties. /// </summary> CameraFacing, } #endregion #region public members [Tooltip("The desired orientation of this object. Default sets the object to face the TrackedObject/TargetTransform. CameraFacing sets the object to always face the user.")] public OrientationReference Orientation = OrientationReference.Default; [Tooltip("XYZ offset for this object in relation to the TrackedObject/TargetTransform")] public Vector3 offset; [Tooltip("RotationTether snaps the object to be in front of TrackedObject regardless of the object's local rotation.")] public bool RotationTether = false; [Tooltip("TetherAngleSteps is the divison of steps this object can tether to. Higher the number, the more snapple steps.")] [Range(4, 12)] public int TetherAngleSteps = 6; #endregion public override void SolverUpdate() { Vector3 desiredPos = base.solverHandler.TransformTarget != null ? base.solverHandler.TransformTarget.position + offset : Vector3.zero; Quaternion desiredRot = Quaternion.identity; if (RotationTether) { float targetYRotation = GetOrientationRef().eulerAngles.y; float tetherYRotation = desiredRot.eulerAngles.y; float angleDiff = Mathf.DeltaAngle(targetYRotation, tetherYRotation); float tetherAngleLimit = 360f / TetherAngleSteps; if (Mathf.Abs(angleDiff) > tetherAngleLimit) { int numSteps = Mathf.RoundToInt(targetYRotation / tetherAngleLimit); tetherYRotation = numSteps * tetherAngleLimit; } desiredRot = Quaternion.Euler(0f, tetherYRotation, 0f); } desiredPos = solverHandler.TransformTarget.position + (desiredRot * offset); this.GoalPosition = desiredPos; this.GoalRotation = desiredRot; UpdateWorkingPosToGoal(); UpdateWorkingRotToGoal(); } private Transform GetOrientationRef() { if (Orientation == OrientationReference.CameraFacing) { return CameraCache.Main.transform; } return solverHandler.TransformTarget; } } }