Esempio n. 1
0
            public void StartScaling(GrabData otherGrab)
            {
                var thisPosition  = pivotPoint;
                var otherPosition = otherGrab.pivotPoint;
                var rayToRay      = otherPosition - thisPosition;

                m_StartMidPoint = thisPosition + rayToRay * 0.5f;
                m_StartDistance = Vector3.Distance(thisPosition, otherPosition);

                m_UseUp = Vector3.Dot(rayOrigin.forward, otherGrab.rayOrigin.forward) < -0.5f;
                var forward  = Vector3.Slerp(rayOrigin.forward, otherGrab.rayOrigin.forward, 0.5f);
                var upVector = Vector3.Slerp(rayOrigin.up, otherGrab.rayOrigin.up, 0.5f);

                m_UpRotationOffset      = Quaternion.Inverse(Quaternion.LookRotation(rayToRay, upVector));
                m_ForwardRotationOffset = Quaternion.Inverse(Quaternion.LookRotation(rayToRay, forward));

                for (var i = 0; i < grabbedTransforms.Length; i++)
                {
                    var grabbedObject = grabbedTransforms[i];
                    m_PositionOffsets[i] = grabbedObject.position - m_StartMidPoint;
                    m_RotationOffsets[i] = grabbedObject.rotation;
                }

                // Transfer the first grab's original transform data, for eventual cancel
                otherGrab.m_OriginalPositions = m_OriginalPositions;
                otherGrab.m_OriginalRotations = m_OriginalRotations;
                otherGrab.m_OriginalScales    = m_OriginalScales;
            }
Esempio n. 2
0
        public void DropHeldObjects(Node node)
        {
            if (!this.IsSharedUpdater(this))
            {
                return;
            }

            var grabData       = GrabDataForNode(node);
            var grabbedObjects = grabData.grabbedTransforms;
            var rayOrigin      = grabData.rayOrigin;

            if (objectsDropped != null)
            {
                objectsDropped(rayOrigin, grabbedObjects);
            }

            if (node == Node.LeftHand)
            {
                m_LeftGrabData = null;
            }
            else
            {
                m_RightGrabData = null;
            }

            m_ScaleFirstNode = Node.None;

            HideGrabFeedback();

            this.RemoveRayVisibilitySettings(grabData.rayOrigin, this);

            this.ClearSnappingState(rayOrigin);
        }
        public virtual void OnColliderEventPressDown(ColliderButtonEventData eventData)
        {
            GrabData grabData;

            if (eventData.button != m_grabButton)
            {
                return;
            }

            if (eventList.TryGetValue(eventData, out grabData))
            {
                switch (grabData.grabState)
                {
                case EventGrabState.JustReleased:
                    eventList.Remove(eventData);
                    if (m_toggleReleaseCheckedFrame == Time.frameCount)
                    {
                        // skip when this event just released at the same frame
                        return;
                    }
                    break;

                case EventGrabState.JustGrabbed:
                case EventGrabState.Grabbing:
                default:
                    return;
                }
            }

            if (!m_multipleGrabbers)
            {
                Release();
            }

            var casterPose = GetEventPose(eventData);
            var offsetPose = RigidPose.FromToPose(casterPose, new RigidPose(transform));

            if (alignPosition)
            {
                offsetPose.pos = Vector3.zero;
            }
            if (alignRotation)
            {
                offsetPose.rot = Quaternion.identity;
            }

            grabData = new GrabData()
            {
                offset    = offsetPose,
                grabState = isToggleReleaseCheckedThisFrame ? EventGrabState.Grabbing : EventGrabState.JustGrabbed,
            };

            eventList.AddUniqueKey(eventData, grabData);

            if (afterGrabbed != null)
            {
                afterGrabbed.Invoke(this);
            }
        }
Esempio n. 4
0
        private bool GrabDataUI(int frameIndex, object @object)
        {
            GrabData data     = (GrabData)@object;
            CubeData cubeData = data.cubeData;

            CubeDataUI(ref cubeData);
            data.cubeData = cubeData;
            Controller.SetCustomeSubData(frameIndex, data, FrameType.Grab);
            bool isDelete = SpaceWithButton(BtnDelete);

            if (isDelete)
            {
                Controller.DeleteCustomData(frameIndex, (int)data.index - 1, FrameType.Grab);
            }
            Space();
            return(isDelete);
        }
Esempio n. 5
0
    public void OnGrabAction(InputAction.CallbackContext ctx)
    {
        GrabData data = new GrabData
        {
            Cell     = TargetCell,
            Position = _grid.GetPosition(TargetCell),
            Valid    = TargetValid,
            Rabbit   = TargetRabbit
        };

        if (ctx.performed)
        {
            onTryGrab?.Invoke(this, data);
        }
        else if (ctx.canceled)
        {
            onDrop?.Invoke(this, data);
        }
    }
Esempio n. 6
0
 public void GrabObjects(Node node, Transform rayOrigin, ActionMapInput input, Transform[] objects)
 {
     m_GrabData[node] = new GrabData(rayOrigin, (DirectSelectInput)input, objects, this);
 }
Esempio n. 7
0
        public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl)
        {
            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 || hasObject))
                {
                    manipulatorGameObject.SetActive(false);
                }

                foreach (var kvp in directSelection)
                {
                    var directRayOrigin     = kvp.Key;
                    var directSelectionData = kvp.Value;
                    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;
                    }

                    var directSelectInput = (DirectSelectInput)directSelectionData.input;
                    if (directSelectInput.select.wasJustPressed)
                    {
                        this.ClearSnappingState(directRayOrigin);

                        if (objectGrabbed != null)
                        {
                            objectGrabbed(directHoveredObject);
                        }

                        consumeControl(directSelectInput.select);

                        var selectedNode = directSelectionData.node;

                        // Check if the other hand is already grabbing for two-handed scale
                        foreach (var grabData in m_GrabData)
                        {
                            var otherNode = grabData.Key;
                            if (otherNode != selectedNode)
                            {
                                var otherData = grabData.Value;
                                m_ScaleStartDistance = (directRayOrigin.position - otherData.rayOrigin.position).magnitude;
                                m_ScaleFirstNode     = otherNode;
                                for (int i = 0; i < otherData.grabbedObjects.Length; i++)
                                {
                                    otherData.positionOffsets[i] = otherData.grabbedObjects[i].position - otherData.rayOrigin.position;
                                }
                                break;
                            }
                        }

                        var grabbedObjects = new HashSet <Transform> {
                            directHoveredObject.transform
                        };
                        grabbedObjects.UnionWith(Selection.transforms);
                        m_GrabData[selectedNode] = new GrabData(directRayOrigin, directSelectInput, grabbedObjects.ToArray(), this);

                        this.HideDefaultRay(directRayOrigin, true);                         // This will also unhighlight the object
                        this.LockRay(directRayOrigin, this);

                        // Wait a frame since OnSelectionChanged is called at the end of the frame, and will set m_DirectSelected to false
                        EditorApplication.delayCall += () =>
                        {
                            // 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 && hasRight && leftHeld && rightHeld)                 // Two-handed scaling
                {
                    // Offsets will change while scaling. Whichever hand keeps holding the trigger after scaling is done will need to reset itself
                    m_WasScaling = true;

                    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
                {
                    if (m_WasScaling)
                    {
                        // Reset initial conditions
                        if (hasLeft)
                        {
                            leftData.Reset();
                        }
                        if (hasRight)
                        {
                            rightData.Reset();
                        }

                        m_WasScaling = false;
                    }

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

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

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

                    if (leftInput.select.wasJustReleased)
                    {
                        DropObjects(Node.LeftHand);
                        consumeControl(leftInput.select);
                    }
                }

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

                    if (rightInput.select.wasJustReleased)
                    {
                        DropObjects(Node.RightHand);
                        consumeControl(rightInput.select);
                    }
                }
            }

            // 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.unscaledDeltaTime;
                var manipulatorTransform = manipulatorGameObject.transform;
                manipulatorTransform.position = Vector3.Lerp(manipulatorTransform.position, m_TargetPosition, k_LazyFollowTranslate * deltaTime);
                if (m_PivotRotation == PivotRotation.Local)                 // Manipulator does not rotate when in global mode
                {
                    manipulatorTransform.rotation = Quaternion.Slerp(manipulatorTransform.rotation, m_TargetRotation, k_LazyFollowRotate * deltaTime);
                }

                Undo.RecordObjects(Selection.transforms, "Move");

                foreach (var t in Selection.transforms)
                {
                    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);
                }
            }
        }
Esempio n. 8
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;
                    }
                }
            }
        }
Esempio n. 9
0
            public void ScaleObjects(GrabData otherGrab)
            {
                if (suspended)
                {
                    return;
                }

#if UNITY_EDITOR
                Undo.RecordObjects(grabbedTransforms, "Move");
#endif

                var thisPosition  = pivotPoint;
                var otherPosition = otherGrab.pivotPoint;
                var distance      = Vector3.Distance(thisPosition, otherPosition);
                var scaleFactor   = distance / m_StartDistance;
                if (scaleFactor > 0 && scaleFactor < Mathf.Infinity)
                {
                    var rayToRay = otherPosition - thisPosition;
                    var midPoint = thisPosition + rayToRay * 0.5f;
                    var forward  = Vector3.Slerp(rayOrigin.forward, otherGrab.rayOrigin.forward, 0.5f);
                    var upVector = Vector3.Slerp(rayOrigin.up, otherGrab.rayOrigin.up, 0.5f);

                    var grabRotation   = Quaternion.LookRotation(rayToRay, m_UseUp ? upVector : forward);
                    var rotationOffset = grabRotation * (m_UseUp ? m_UpRotationOffset : m_ForwardRotationOffset);

                    for (var i = 0; i < grabbedTransforms.Length; i++)
                    {
                        var grabbedObject = grabbedTransforms[i];

                        if (twoHandedManipulateMode == TwoHandedManipulateMode.RotateOnly)
                        {
                            var targetPosition  = midPoint + rotationOffset * m_PositionOffsets[i];
                            var currentPosition = grabbedObject.position;
                            if (currentPosition != targetPosition)
                            {
                                grabbedObject.position = Vector3.Lerp(currentPosition, targetPosition, k_DirectLazyFollowTranslate);
                            }

                            var targetScale = m_InitialScales[i];
                            if (grabbedObject.localScale != targetScale)
                            {
                                grabbedObject.localScale = targetScale;
                            }
                        }
                        else
                        {
                            var offset = m_PositionOffsets[i] * scaleFactor;
                            if (twoHandedManipulateMode != TwoHandedManipulateMode.ScaleOnly)
                            {
                                offset = rotationOffset * offset;
                            }

                            var targetPosition  = midPoint + offset;
                            var currentPosition = grabbedObject.position;
                            if (currentPosition != targetPosition)
                            {
                                grabbedObject.position = Vector3.Lerp(currentPosition, targetPosition, k_DirectLazyFollowTranslate);
                            }

                            var targetScale = m_InitialScales[i] * scaleFactor;
                            if (grabbedObject.localScale != targetScale)
                            {
                                grabbedObject.localScale = targetScale;
                            }
                        }

                        if (twoHandedManipulateMode == TwoHandedManipulateMode.ScaleOnly)
                        {
                            grabbedObject.rotation = Quaternion.Lerp(grabbedObject.rotation, m_RotationOffsets[i], k_DirectLazyFollowRotate);
                        }
                        else
                        {
                            grabbedObject.rotation = Quaternion.Lerp(grabbedObject.rotation, rotationOffset * m_RotationOffsets[i], k_DirectLazyFollowRotate);
                        }
                    }
                }
            }
Esempio n. 10
0
    public void ProcessInput(ActionMapInput input, Action <InputControl> consumeControl)
    {
        var hasObject = false;

        var manipulatorGameObject = m_CurrentManipulator.gameObject;

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

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

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

            foreach (var selection in m_HoverObjects.Values)
            {
                if (selection)
                {
                    setHighlight(selection, false);
                }
            }

            m_HoverObjects.Clear();

            foreach (var kvp in directSelection)
            {
                var rayOrigin     = kvp.Key;
                var selection     = kvp.Value;
                var hoveredObject = selection.gameObject;

                var selectionCandidate = getSelectionCandidate(hoveredObject, true);

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

                if (selectionCandidate)
                {
                    hoveredObject = selectionCandidate;
                }

                if (!canGrabObject(hoveredObject, rayOrigin))
                {
                    continue;
                }

                m_HoverObjects[rayOrigin] = hoveredObject;                 // Store actual hover object to unhighlight next frame

                setHighlight(hoveredObject, true);

                var directSelectInput = (DirectSelectInput)selection.input;
                if (directSelectInput.select.wasJustPressed)
                {
                    objectGrabbed(hoveredObject);

                    // Only add to selection, don't remove
                    if (!Selection.objects.Contains(hoveredObject))
                    {
                        selectObject(hoveredObject, rayOrigin, directSelectInput.multiSelect.isHeld);
                    }

                    consumeControl(directSelectInput.select);

                    var selectedNode = selection.node;

                    // Check if the other hand is already grabbing for two-handed scale
                    foreach (var grabData in m_GrabData)
                    {
                        var otherNode = grabData.Key;
                        if (otherNode != selectedNode)
                        {
                            var otherData = grabData.Value;
                            m_ScaleStartDistance = (rayOrigin.position - otherData.rayOrigin.position).magnitude;
                            m_ScaleFirstNode     = otherNode;
                            for (int i = 0; i < otherData.grabbedObjects.Length; i++)
                            {
                                otherData.positionOffsets[i] = otherData.grabbedObjects[i].position - otherData.rayOrigin.position;
                            }
                            break;
                        }
                    }

                    m_GrabData[selectedNode] = new GrabData(rayOrigin, directSelectInput, Selection.transforms);

                    setHighlight(hoveredObject, false);

                    hideDefaultRay(rayOrigin, true);
                    lockRay(rayOrigin, this);

                    // Wait a frame since OnSelectionChanged is called after setting m_DirectSelected to true
                    EditorApplication.delayCall += () =>
                    {
                        // A direct selection has been made. Hide the manipulator until the selection changes
                        m_DirectSelected = true;
                    };
                }
            }

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

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

            var leftHeld  = leftData != null && leftData.input.select.isHeld;
            var rightHeld = rightData != null && rightData.input.select.isHeld;
            if (hasLeft && hasRight && leftHeld && rightHeld)             // Two-handed scaling
            {
                // Offsets will change while scaling. Whichever hand keeps holding the trigger after scaling is done will need to reset itself
                m_WasScaling = true;

                m_ScaleFactor = (leftData.rayOrigin.position - rightData.rayOrigin.position).magnitude / m_ScaleStartDistance;
                if (m_ScaleFactor > 0 && m_ScaleFactor < Mathf.Infinity)
                {
                    if (m_ScaleFirstNode == Node.LeftHand)
                    {
                        leftData.ScaleObjects(m_ScaleFactor);
                    }
                    else
                    {
                        rightData.ScaleObjects(m_ScaleFactor);
                    }
                }
            }
            else
            {
                if (m_WasScaling)
                {
                    // Reset initial conditions
                    if (hasLeft)
                    {
                        leftData.Reset();
                    }
                    if (hasRight)
                    {
                        rightData.Reset();
                    }

                    m_WasScaling = false;
                }

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

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

            if (hasLeft && leftData.input.select.wasJustReleased)
            {
                DropObjects(Node.LeftHand);
                consumeControl(leftData.input.select);
            }

            if (hasRight && rightData.input.select.wasJustReleased)
            {
                DropObjects(Node.RightHand);
                consumeControl(rightData.input.select);
            }
        }

        // 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.unscaledDeltaTime;
            var manipulatorTransform = manipulatorGameObject.transform;
            manipulatorTransform.position = Vector3.Lerp(manipulatorTransform.position, m_TargetPosition, kLazyFollowTranslate * deltaTime);

#if UNITY_EDITOR
            if (m_PivotRotation == PivotRotation.Local)             // Manipulator does not rotate when in global mode
            {
                manipulatorTransform.rotation = Quaternion.Slerp(manipulatorTransform.rotation, m_TargetRotation, kLazyFollowRotate * deltaTime);
            }
#endif

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

#if UNITY_EDITOR
                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), kLazyFollowRotate * deltaTime);
                    t.position = manipulatorTransform.position + m_PositionOffsetRotation * m_PositionOffsets[t];
                }
                else
#endif
                {
                    t.position = manipulatorTransform.position + m_PositionOffsets[t];
                }

                t.localScale = Vector3.Lerp(t.localScale, Vector3.Scale(m_TargetScale, m_ScaleOffsets[t]), kLazyFollowTranslate * deltaTime);
            }
        }
    }