Пример #1
0
 public GrabData(Transform rayOrigin, TransformInput input, Transform[] grabbedObjects)
 {
     this.rayOrigin      = rayOrigin;
     this.input          = input;
     this.grabbedObjects = grabbedObjects;
     Reset();
 }
Пример #2
0
            public GrabData(Transform rayOrigin, TransformInput input, Transform[] grabbedTransforms, Vector3 contactPoint)
            {
                this.rayOrigin         = rayOrigin;
                this.input             = input;
                this.grabbedTransforms = grabbedTransforms;
                var inverseRotation = Quaternion.Inverse(rayOrigin.rotation);

                m_GrabOffset = inverseRotation * (contactPoint - rayOrigin.position);
                CaptureInitialTransforms();
                Reset();
            }
Пример #3
0
        public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl)
        {
            m_Input = (TransformInput)input;

            if (!this.IsSharedUpdater(this))
            {
                return;
            }

            var hasObject             = false;
            var manipulatorGameObject = m_CurrentManipulator.gameObject;
            var gameObjects           = Selection.gameObjects;

            if (!m_CurrentManipulator.dragging)
            {
                var directSelection = this.GetDirectSelection();

                var hasLeft  = m_LeftGrabData != null;
                var hasRight = m_RightGrabData != null;
                hasObject = directSelection.Count > 0 || hasLeft || hasRight;

                var hoveringSelection = false;
                foreach (var kvp in directSelection)
                {
                    if (gameObjects.Contains(kvp.Value.gameObject))
                    {
                        hoveringSelection = true;
                        break;
                    }
                }

                // Disable manipulator on direct hover or drag
                if (manipulatorGameObject.activeSelf && (hoveringSelection || hasLeft || hasRight))
                {
                    manipulatorGameObject.SetActive(false);
                }

                var scaleHover = false;
                foreach (var kvp in directSelection)
                {
                    var directRayOrigin     = kvp.Key;
                    var directSelectionData = kvp.Value;

                    if (!(hasLeft || hasRight) && this.IsMainMenuVisible(directRayOrigin))
                    {
                        continue;
                    }

                    var directHoveredObject = directSelectionData.gameObject;

                    var selectionCandidate = this.GetSelectionCandidate(directHoveredObject, true);

                    // Can't select this object (it might be locked or static)
                    if (directHoveredObject && !selectionCandidate)
                    {
                        continue;
                    }

                    if (selectionCandidate)
                    {
                        directHoveredObject = selectionCandidate;
                    }

                    if (!this.CanGrabObject(directHoveredObject, directRayOrigin))
                    {
                        continue;
                    }

                    this.AddRayVisibilitySettings(directRayOrigin, this, false, true); // This will also disable ray selection

                    if (!this.IsConeVisible(directRayOrigin))
                    {
                        continue;
                    }

                    var grabbingNode  = this.RequestNodeFromRayOrigin(directRayOrigin);
                    var transformTool = linkedObjects.Cast <TransformTool>().FirstOrDefault(linkedObject => linkedObject.node == grabbingNode);
                    if (transformTool == null)
                    {
                        continue;
                    }

                    // Check if the other hand is already grabbing for two-handed scale
                    var otherData = grabbingNode == Node.LeftHand ? m_RightGrabData : m_LeftGrabData;

                    if (otherData != null && !otherData.grabbedTransforms.Contains(directHoveredObject.transform))
                    {
                        otherData = null;
                    }

                    if (otherData != null)
                    {
                        scaleHover = true;
                        if (m_ScaleFeedback.Count == 0)
                        {
                            ShowScaleFeedback(grabbingNode);
                        }
                    }

                    var transformInput = transformTool.m_Input;

                    if (transformInput.select.wasJustPressed)
                    {
                        this.ClearSnappingState(directRayOrigin);

                        consumeControl(transformInput.select);

                        var grabbedObjects = new HashSet <Transform> {
                            directHoveredObject.transform
                        };
                        grabbedObjects.UnionWith(Selection.transforms);

                        if (objectsGrabbed != null && !m_Scaling)
                        {
                            objectsGrabbed(directRayOrigin, grabbedObjects);
                        }

                        var grabData = new GrabData(directRayOrigin, transformInput, grabbedObjects.ToArray(), directSelectionData.contactPoint);
                        if (grabbingNode == Node.LeftHand)
                        {
                            m_LeftGrabData = grabData;
                        }
                        else
                        {
                            m_RightGrabData = grabData;
                        }

                        ShowGrabFeedback(grabbingNode);
                        if (otherData != null)
                        {
                            m_ScaleFirstNode = grabbingNode == Node.LeftHand ? Node.RightHand : Node.LeftHand;
                            otherData.StartScaling(grabData);
                            ShowScaleOptionsFeedback(otherData.twoHandedManipulateMode);
                            m_Scaling = true;
                        }

                        // A direct selection has been made. Hide the manipulator until the selection changes
                        m_DirectSelected = true;

#if UNITY_EDITOR
                        Undo.IncrementCurrentGroup();
#endif
                    }
                }

                if (!scaleHover)
                {
                    HideScaleFeedback();
                }

                hasLeft  = m_LeftGrabData != null;
                hasRight = m_RightGrabData != null;

                var leftInput  = m_LeftGrabData != null ? m_LeftGrabData.input : null;
                var leftHeld   = m_LeftGrabData != null && leftInput.select.isHeld;
                var rightInput = m_RightGrabData != null ? m_RightGrabData.input : null;
                var rightHeld  = m_RightGrabData != null && rightInput.select.isHeld;

                if (hasLeft)
                {
                    consumeControl(leftInput.cancel);
                    consumeControl(leftInput.suppressVertical);
                    if (!m_Scaling && leftInput.cancel.wasJustPressed)
                    {
                        m_LeftGrabData.Cancel();
                        DropHeldObjects(Node.LeftHand);
                        hasLeft = false;
                    }

                    if (leftInput.select.wasJustReleased)
                    {
                        if (rightInput != null && rightInput.select.wasJustReleased)
                        {
                            HideScaleOptionFeedback();
                            m_Scaling = false;
                        }

                        DropHeldObjects(Node.LeftHand);
                        hasLeft = false;
                        consumeControl(leftInput.select);
                    }
                }

                if (hasRight)
                {
                    consumeControl(rightInput.cancel);
                    consumeControl(rightInput.suppressVertical);
                    if (!m_Scaling && rightInput.cancel.wasJustPressed)
                    {
                        m_RightGrabData.Cancel();
                        DropHeldObjects(Node.RightHand);
                        hasRight = false;
                    }

                    if (rightInput.select.wasJustReleased)
                    {
                        if (leftInput != null && leftInput.select.wasJustReleased)
                        {
                            HideScaleOptionFeedback();
                            m_Scaling = false;
                        }

                        DropHeldObjects(Node.RightHand);
                        hasRight = false;
                        consumeControl(rightInput.select);
                    }
                }

                if (hasLeft && hasRight && leftHeld && rightHeld && m_Scaling) // Two-handed scaling
                {
                    var rightRayOrigin = m_RightGrabData.rayOrigin;
                    var leftRayOrigin  = m_LeftGrabData.rayOrigin;
                    var leftCancel     = leftInput.cancel;
                    var rightCancel    = rightInput.cancel;

                    var scaleGrabData = m_ScaleFirstNode == Node.LeftHand ? m_LeftGrabData : m_RightGrabData;
                    if (leftCancel.wasJustPressed)
                    {
                        if (scaleGrabData.twoHandedManipulateMode == TwoHandedManipulateMode.ScaleOnly)
                        {
                            scaleGrabData.twoHandedManipulateMode = TwoHandedManipulateMode.RotateAndScale;
                        }
                        else
                        {
                            scaleGrabData.twoHandedManipulateMode = TwoHandedManipulateMode.ScaleOnly;
                        }

                        ShowScaleOptionsFeedback(scaleGrabData.twoHandedManipulateMode);
                    }

                    if (rightCancel.wasJustPressed)
                    {
                        HideScaleOptionFeedback();
                        m_Scaling = false;
                        if (m_ScaleFirstNode == Node.LeftHand)
                        {
                            m_LeftGrabData.Cancel();
                        }
                        else
                        {
                            m_RightGrabData.Cancel();
                        }

                        DropHeldObjects(Node.RightHand);
                        DropHeldObjects(Node.LeftHand);
                    }
                    else if (m_ScaleFirstNode == Node.LeftHand)
                    {
                        m_LeftGrabData.ScaleObjects(m_RightGrabData);
                        this.ClearSnappingState(leftRayOrigin);
                    }
                    else
                    {
                        m_RightGrabData.ScaleObjects(m_LeftGrabData);
                        this.ClearSnappingState(rightRayOrigin);
                    }
                }
                else
                {
                    // If m_Scaling is true but both hands don't have a grab, we need to transfer back to one-handed manipulation
                    // Offsets will change while scaling. Whichever hand keeps holding the trigger after scaling is done will need to reset itself
                    if (m_Scaling)
                    {
                        if (hasLeft)
                        {
                            m_LeftGrabData.Reset();

                            if (objectsTransferred != null && m_ScaleFirstNode == Node.RightHand)
                            {
                                objectsTransferred(m_RightGrabData.rayOrigin, m_LeftGrabData.rayOrigin);
                            }
                        }

                        if (hasRight)
                        {
                            m_RightGrabData.Reset();

                            if (objectsTransferred != null && m_ScaleFirstNode == Node.LeftHand)
                            {
                                objectsTransferred(m_LeftGrabData.rayOrigin, m_RightGrabData.rayOrigin);
                            }
                        }

                        HideScaleOptionFeedback();
                        m_Scaling = false;
                    }

                    if (hasLeft && leftHeld)
                    {
                        m_LeftGrabData.UpdatePositions(this);
                    }

                    if (hasRight && rightHeld)
                    {
                        m_RightGrabData.UpdatePositions(this);
                    }
                }

                foreach (var linkedObject in linkedObjects)
                {
                    var transformTool = (TransformTool)linkedObject;
                    var rayOrigin     = transformTool.rayOrigin;
                    if (!(m_Scaling || directSelection.ContainsKey(rayOrigin) || GrabDataForNode(transformTool.node) != null))
                    {
                        this.RemoveRayVisibilitySettings(rayOrigin, this);
                    }
                }
            }

            // Manipulator is disabled while direct manipulation is happening
            if (hasObject || m_DirectSelected)
            {
                return;
            }

            if (gameObjects.Length > 0)
            {
                if (!m_CurrentManipulator.dragging)
                {
                    UpdateCurrentManipulator();
                }

                var deltaTime            = Time.deltaTime;
                var manipulatorTransform = manipulatorGameObject.transform;
                var lerp = m_CurrentlySnapping ? 1f : k_LazyFollowTranslate * deltaTime;
                manipulatorTransform.position = Vector3.Lerp(manipulatorTransform.position, m_TargetPosition, lerp);

                // Manipulator does not rotate when in global mode
                if (m_PivotRotation == PivotRotation.Local && m_CurrentManipulator == m_StandardManipulator)
                {
                    manipulatorTransform.rotation = Quaternion.Slerp(manipulatorTransform.rotation, m_TargetRotation, k_LazyFollowRotate * deltaTime);
                }

                var selectionTransforms = Selection.transforms;
#if UNITY_EDITOR
                Undo.RecordObjects(selectionTransforms, "Move");
#endif

                foreach (var t in selectionTransforms)
                {
                    var targetRotation = Quaternion.Slerp(t.rotation, m_TargetRotation * m_RotationOffsets[t], k_LazyFollowRotate * deltaTime);
                    if (t.rotation != targetRotation)
                    {
                        t.rotation = targetRotation;
                    }

                    Vector3 targetPosition;
                    if (m_PivotMode == PivotMode.Center) // Rotate the position offset from the manipulator when rotating around center
                    {
                        m_PositionOffsetRotation = Quaternion.Slerp(m_PositionOffsetRotation, m_TargetRotation * Quaternion.Inverse(m_StartRotation), k_LazyFollowRotate * deltaTime);
                        targetPosition           = manipulatorTransform.position + m_PositionOffsetRotation * m_PositionOffsets[t];
                    }
                    else
                    {
                        targetPosition = manipulatorTransform.position + m_PositionOffsets[t];
                    }

                    if (t.position != targetPosition)
                    {
                        t.position = targetPosition;
                    }

                    var targetScale = Vector3.Lerp(t.localScale, Vector3.Scale(m_TargetScale, m_ScaleOffsets[t]), k_LazyFollowTranslate * deltaTime);
                    if (t.localScale != targetScale)
                    {
                        t.localScale = targetScale;
                    }
                }
            }
        }
Пример #4
0
        public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl)
        {
            m_Input = (TransformInput)input;

            if (!this.IsSharedUpdater(this))
            {
                return;
            }

            var hasObject             = false;
            var manipulatorGameObject = m_CurrentManipulator.gameObject;

            if (!m_CurrentManipulator.dragging)
            {
                var directSelection = this.GetDirectSelection();

                var hasLeft  = m_GrabData.ContainsKey(Node.LeftHand);
                var hasRight = m_GrabData.ContainsKey(Node.RightHand);
                hasObject = directSelection.Count > 0 || hasLeft || hasRight;

                var hoveringSelection = false;
                foreach (var selection in directSelection.Values)
                {
                    if (Selection.gameObjects.Contains(selection.gameObject))
                    {
                        hoveringSelection = true;
                        break;
                    }
                }

                // Disable manipulator on direct hover or drag
                if (manipulatorGameObject.activeSelf && (hoveringSelection || hasLeft || hasRight))
                {
                    manipulatorGameObject.SetActive(false);
                }

                foreach (var kvp in directSelection)
                {
                    var directRayOrigin = kvp.Key;

                    if (m_GrabData.Count == 0 && this.IsMainMenuVisible(directRayOrigin))
                    {
                        continue;
                    }

                    var directHoveredObject = kvp.Value;

                    var selectionCandidate = this.GetSelectionCandidate(directHoveredObject, true);

                    // Can't select this object (it might be locked or static)
                    if (directHoveredObject && !selectionCandidate)
                    {
                        continue;
                    }

                    if (selectionCandidate)
                    {
                        directHoveredObject = selectionCandidate;
                    }

                    if (!this.CanGrabObject(directHoveredObject, directRayOrigin))
                    {
                        continue;
                    }

                    this.AddRayVisibilitySettings(directRayOrigin, this, false, true);                     // This will also disable ray selection

                    if (!this.IsConeVisible(directRayOrigin))
                    {
                        continue;
                    }

                    var grabbingNode  = this.RequestNodeFromRayOrigin(directRayOrigin);
                    var transformTool = linkedObjects.Cast <TransformTool>().FirstOrDefault(linkedObject => linkedObject.node == grabbingNode);
                    if (transformTool == null)
                    {
                        continue;
                    }

                    var transformInput = transformTool.m_Input;

                    if (transformInput.select.wasJustPressed)
                    {
                        this.ClearSnappingState(directRayOrigin);

                        consumeControl(transformInput.select);

                        // Check if the other hand is already grabbing for two-handed scale
                        foreach (var grabData in m_GrabData)
                        {
                            var otherNode = grabData.Key;
                            var otherData = grabData.Value;

                            if (otherNode != grabbingNode && otherData.grabbedObjects.Contains(directHoveredObject.transform))
                            {
                                m_ScaleStartDistance = (directRayOrigin.position - otherData.rayOrigin.position).magnitude;
                                m_ScaleFirstNode     = otherNode;
                                otherData.StartScaling();
                                m_Scaling = true;
                                break;
                            }
                        }

                        var grabbedObjects = new HashSet <Transform> {
                            directHoveredObject.transform
                        };
                        grabbedObjects.UnionWith(Selection.transforms);

                        if (objectsGrabbed != null && !m_Scaling)
                        {
                            objectsGrabbed(directRayOrigin, grabbedObjects);
                        }

                        m_GrabData[grabbingNode.Value] = new GrabData(directRayOrigin, transformInput, grabbedObjects.ToArray());

                        // A direct selection has been made. Hide the manipulator until the selection changes
                        m_DirectSelected = true;

                        Undo.IncrementCurrentGroup();
                    }
                }

                GrabData leftData;
                hasLeft = m_GrabData.TryGetValue(Node.LeftHand, out leftData);

                GrabData rightData;
                hasRight = m_GrabData.TryGetValue(Node.RightHand, out rightData);

                var leftInput  = leftData != null ? leftData.input : null;
                var leftHeld   = leftData != null && leftInput.select.isHeld;
                var rightInput = rightData != null ? rightData.input : null;
                var rightHeld  = rightData != null && rightInput.select.isHeld;

                if (hasLeft)
                {
                    if (leftInput.cancel.wasJustPressed)
                    {
                        DropHeldObjects(Node.LeftHand);
                        hasLeft = false;
                        consumeControl(leftInput.cancel);
                        Undo.PerformUndo();
                    }

                    if (leftInput.select.wasJustReleased)
                    {
                        DropHeldObjects(Node.LeftHand);
                        hasLeft = false;
                        consumeControl(leftInput.select);
                    }
                }

                if (hasRight)
                {
                    if (rightInput.cancel.wasJustPressed)
                    {
                        DropHeldObjects(Node.RightHand);
                        hasRight = false;
                        consumeControl(rightInput.cancel);
                        Undo.PerformUndo();
                    }

                    if (rightInput.select.wasJustReleased)
                    {
                        DropHeldObjects(Node.RightHand);
                        hasRight = false;
                        consumeControl(rightInput.select);
                    }
                }

                if (hasLeft && hasRight && leftHeld && rightHeld && m_Scaling)                 // Two-handed scaling
                {
                    var rightRayOrigin = rightData.rayOrigin;
                    var leftRayOrigin  = leftData.rayOrigin;
                    m_ScaleFactor = (leftRayOrigin.position - rightRayOrigin.position).magnitude / m_ScaleStartDistance;
                    if (m_ScaleFactor > 0 && m_ScaleFactor < Mathf.Infinity)
                    {
                        if (m_ScaleFirstNode == Node.LeftHand)
                        {
                            leftData.ScaleObjects(m_ScaleFactor);
                            this.ClearSnappingState(leftRayOrigin);
                        }
                        else
                        {
                            rightData.ScaleObjects(m_ScaleFactor);
                            this.ClearSnappingState(rightRayOrigin);
                        }
                    }
                }
                else
                {
                    // Offsets will change while scaling. Whichever hand keeps holding the trigger after scaling is done will need to reset itself
                    if (m_Scaling)
                    {
                        if (hasLeft)
                        {
                            leftData.Reset();

                            if (objectsTransferred != null && m_ScaleFirstNode == Node.RightHand)
                            {
                                objectsTransferred(rightData.rayOrigin, leftData.rayOrigin);
                            }
                        }
                        if (hasRight)
                        {
                            rightData.Reset();

                            if (objectsTransferred != null && m_ScaleFirstNode == Node.LeftHand)
                            {
                                objectsTransferred(leftData.rayOrigin, rightData.rayOrigin);
                            }
                        }

                        m_Scaling = false;
                    }

                    if (hasLeft && leftHeld)
                    {
                        leftData.UpdatePositions(this);
                    }

                    if (hasRight && rightHeld)
                    {
                        rightData.UpdatePositions(this);
                    }
                }

                foreach (var linkedObject in linkedObjects)
                {
                    var transformTool = (TransformTool)linkedObject;
                    var rayOrigin     = transformTool.rayOrigin;
                    if (!(m_Scaling || directSelection.ContainsKey(rayOrigin) || m_GrabData.ContainsKey(transformTool.node.Value)))
                    {
                        this.RemoveRayVisibilitySettings(rayOrigin, this);
                    }
                }
            }

            // Manipulator is disabled while direct manipulation is happening
            if (hasObject || m_DirectSelected)
            {
                return;
            }

            if (Selection.gameObjects.Length > 0)
            {
                if (!m_CurrentManipulator.dragging)
                {
                    UpdateCurrentManipulator();
                }

                var deltaTime            = Time.deltaTime;
                var manipulatorTransform = manipulatorGameObject.transform;
                var lerp = m_CurrentlySnapping ? 1f : k_LazyFollowTranslate * deltaTime;
                manipulatorTransform.position = Vector3.Lerp(manipulatorTransform.position, m_TargetPosition, lerp);
                // Manipulator does not rotate when in global mode
                if (m_PivotRotation == PivotRotation.Local && m_CurrentManipulator == m_StandardManipulator)
                {
                    manipulatorTransform.rotation = Quaternion.Slerp(manipulatorTransform.rotation, m_TargetRotation, k_LazyFollowRotate * deltaTime);
                }

                var selectionTransforms = Selection.transforms;
                Undo.RecordObjects(selectionTransforms, "Move");

                foreach (var t in selectionTransforms)
                {
                    t.rotation = Quaternion.Slerp(t.rotation, m_TargetRotation * m_RotationOffsets[t], k_LazyFollowRotate * deltaTime);

                    if (m_PivotMode == PivotMode.Center)                     // Rotate the position offset from the manipulator when rotating around center
                    {
                        m_PositionOffsetRotation = Quaternion.Slerp(m_PositionOffsetRotation, m_TargetRotation * Quaternion.Inverse(m_StartRotation), k_LazyFollowRotate * deltaTime);
                        t.position = manipulatorTransform.position + m_PositionOffsetRotation * m_PositionOffsets[t];
                    }
                    else
                    {
                        t.position = manipulatorTransform.position + m_PositionOffsets[t];
                    }

                    t.localScale = Vector3.Lerp(t.localScale, Vector3.Scale(m_TargetScale, m_ScaleOffsets[t]), k_LazyFollowTranslate * deltaTime);
                }
            }
        }
Пример #5
0
 private void Awake()
 {
     trInput = GetComponent <TransformInput>();
 }