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; }
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); } }
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); }
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); } }
public void GrabObjects(Node node, Transform rayOrigin, ActionMapInput input, Transform[] objects) { m_GrabData[node] = new GrabData(rayOrigin, (DirectSelectInput)input, objects, this); }
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); } } }
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; } } } }
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); } } } }
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); } } }