public void UpdatePositions() { Undo.RecordObjects(grabbedObjects, "Move"); for (int i = 0; i < grabbedObjects.Length; i++) { MathUtilsExt.SetTransformOffset(rayOrigin, grabbedObjects[i], positionOffsets[i], rotationOffsets[i]); } }
void Update() { m_TooltipsToHide.Clear(); foreach (var kvp in m_Tooltips) { var tooltip = kvp.Key; var tooltipData = kvp.Value; var hoverTime = Time.realtimeSinceStartup - tooltipData.startTime; if (hoverTime > k_Delay) { var placement = tooltip as ITooltipPlacement; var target = GetTooltipTarget(tooltip); var tooltipUI = tooltipData.tooltipUI; if (!tooltipUI) { var tooltipObject = Instantiate(m_TooltipPrefab, m_TooltipCanvas); tooltipUI = tooltipObject.GetComponent <TooltipUI>(); tooltipData.tooltipUI = tooltipUI; tooltipUI.highlight.material = m_HighlightMaterial; tooltipUI.background.material = m_TooltipBackgroundMaterial; var tooltipTransform = tooltipObject.transform; MathUtilsExt.SetTransformOffset(target, tooltipTransform, Vector3.zero, Quaternion.identity); tooltipTransform.localScale = Vector3.zero; if (placement == null) { ObjectUtils.Destroy(tooltipUI.dottedLine.gameObject); foreach (var sphere in tooltipUI.spheres) { ObjectUtils.Destroy(sphere.gameObject); } } } var lerp = Mathf.Clamp01((hoverTime - k_Delay) / k_TransitionDuration); UpdateVisuals(tooltip, tooltipUI, target, lerp); } if (!IsValidTooltip(tooltip)) { m_TooltipsToHide.Add(tooltip); } } foreach (var tooltip in m_TooltipsToHide) { HideTooltip(tooltip); } }
void UpdateVisuals(ITooltip tooltip, TooltipData tooltipData, float lerp) { var target = tooltipData.GetTooltipTarget(tooltip); var tooltipUI = tooltipData.tooltipUI; var placement = tooltipData.placement; var orientationWeight = tooltipData.orientationWeight; var tooltipTransform = tooltipUI.transform; lerp = MathUtilsExt.SmoothInOutLerpFloat(lerp); // shape the lerp for better presentation var transitionLerp = MathUtilsExt.SmoothInOutLerpFloat(1.0f - Mathf.Clamp01((Time.time - tooltipData.transitionTime) / k_ChangeTransitionDuration)); var viewerScale = this.GetViewerScale(); tooltipTransform.localScale = m_TooltipScale * lerp * viewerScale; // Adjust for alignment var offset = GetTooltipOffset(tooltipUI, placement, tooltipData.transitionOffset * transitionLerp); // The rectTransform expansion is handled in the Tooltip dynamically, based on alignment & text length var rotationOffset = Quaternion.identity; var camTransform = CameraUtils.GetMainCamera().transform; if (Vector3.Dot(camTransform.forward, target.forward) < 0) { rotationOffset *= k_FlipYRotation; } if (Vector3.Dot(camTransform.up, target.up) + orientationWeight < 0) { rotationOffset *= k_FlipZRotation; tooltipData.orientationWeight = -k_TextOrientationWeight; } else { tooltipData.orientationWeight = k_TextOrientationWeight; } MathUtilsExt.SetTransformOffset(target, tooltipTransform, offset * lerp, rotationOffset); if (placement != null) { //TODO: Figure out why rect gives us different height/width than GetWorldCorners tooltipUI.rectTransform.GetWorldCorners(k_Corners); var bottomLeft = k_Corners[0]; var halfWidth = (bottomLeft - k_Corners[2]).magnitude * 0.5f; var halfHeight = (bottomLeft - k_Corners[1]).magnitude * 0.5f; var source = placement.tooltipSource; var toSource = tooltipTransform.InverseTransformPoint(source.position); // Position spheres: one at source, one on the closest edge of the tooltip var spheres = tooltipUI.spheres; spheres[0].position = source.position; var attachedSphere = spheres[1]; var boxSlope = halfHeight / halfWidth; var toSourceSlope = Mathf.Abs(toSource.y / toSource.x); var parentScale = attachedSphere.parent.lossyScale; halfHeight *= Mathf.Sign(toSource.y) / parentScale.x; halfWidth *= Mathf.Sign(toSource.x) / parentScale.y; attachedSphere.localPosition = toSourceSlope > boxSlope ? new Vector3(0, halfHeight) : new Vector3(halfWidth, 0); // Align dotted line var attachedSpherePosition = attachedSphere.position; toSource = source.position - attachedSpherePosition; var midPoint = attachedSpherePosition + toSource * 0.5f; var dottedLine = tooltipUI.dottedLine; var length = toSource.magnitude; var uvRect = dottedLine.uvRect; var worldScale = 1 / viewerScale; uvRect.width = length * k_UVScale * worldScale; uvRect.xMin += k_UVScrollSpeed * Time.deltaTime; dottedLine.uvRect = uvRect; var dottedLineTransform = dottedLine.transform.parent.GetComponent <RectTransform>(); dottedLineTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, length / tooltipTransform.lossyScale.x); dottedLineTransform.position = midPoint; dottedLineTransform.rotation = Quaternion.LookRotation(toSource, -tooltipTransform.forward); } }
public void OnDragging() { if (m_Resizing) { var viewerScale = m_WorkspaceUI.GetViewerScale(); var pointerPosition = m_WorkspaceUI.GetPointerPosition(rayOrigin); var dragVector = (pointerPosition - m_DragStart) / viewerScale; var bounds = m_WorkspaceUI.bounds; var transform = m_WorkspaceUI.transform; var positionOffsetForward = Vector3.Dot(dragVector, transform.forward) * 0.5f; var positionOffsetRight = Vector3.Dot(dragVector, transform.right) * 0.5f; switch (m_Direction) { default: bounds.size = m_BoundsSizeStart + Vector3.back * Vector3.Dot(dragVector, transform.forward); positionOffsetRight = 0; break; case ResizeDirection.Back: bounds.size = m_BoundsSizeStart + Vector3.forward * Vector3.Dot(dragVector, transform.forward); positionOffsetRight = 0; break; case ResizeDirection.Left: bounds.size = m_BoundsSizeStart + Vector3.left * Vector3.Dot(dragVector, transform.right); positionOffsetForward = 0; break; case ResizeDirection.Right: bounds.size = m_BoundsSizeStart + Vector3.right * Vector3.Dot(dragVector, transform.right); positionOffsetForward = 0; break; case ResizeDirection.Front | ResizeDirection.Left: bounds.size = m_BoundsSizeStart + Vector3.left * Vector3.Dot(dragVector, transform.right) + Vector3.back * Vector3.Dot(dragVector, transform.forward); break; case ResizeDirection.Front | ResizeDirection.Right: bounds.size = m_BoundsSizeStart + Vector3.right * Vector3.Dot(dragVector, transform.right) + Vector3.back * Vector3.Dot(dragVector, transform.forward); break; case ResizeDirection.Back | ResizeDirection.Left: bounds.size = m_BoundsSizeStart + Vector3.left * Vector3.Dot(dragVector, transform.right) + Vector3.forward * Vector3.Dot(dragVector, transform.forward); break; case ResizeDirection.Back | ResizeDirection.Right: bounds.size = m_BoundsSizeStart + Vector3.right * Vector3.Dot(dragVector, transform.right) + Vector3.forward * Vector3.Dot(dragVector, transform.forward); break; } if (m_WorkspaceUI.resize != null) { m_WorkspaceUI.resize(bounds); } var currentExtents = m_WorkspaceUI.bounds.extents; var extents = bounds.extents; var absRight = Mathf.Abs(positionOffsetRight); var absForward = Mathf.Abs(positionOffsetForward); var positionOffset = transform.right * (absRight - (currentExtents.x - extents.x)) * Mathf.Sign(positionOffsetRight) + transform.forward * (absForward - (currentExtents.z - extents.z)) * Mathf.Sign(positionOffsetForward); m_WorkspaceUI.transform.parent.position = m_PositionStart + positionOffset * viewerScale; m_WorkspaceUI.OnResizing(rayOrigin); } else { MathUtilsExt.SetTransformOffset(rayOrigin, m_WorkspaceUI.transform.parent, m_PositionOffset, m_RotationOffset); m_WorkspaceUI.OnMoving(rayOrigin); } }
void UpdateVisuals(ITooltip tooltip, TooltipUI tooltipUI, Transform target, float lerp) { var tooltipTransform = tooltipUI.transform; var tooltipText = tooltipUI.text; if (tooltipText) { tooltipText.text = tooltip.tooltipText; } var viewerScale = getViewerScale(); tooltipTransform.localScale = m_TooltipScale * lerp * viewerScale; var placement = tooltip as ITooltipPlacement; // Adjust for alignment var offset = Vector3.zero; if (placement != null) { switch (placement.tooltipAlignment) { case TextAlignment.Right: offset = Vector3.left; break; case TextAlignment.Left: offset = Vector3.right; break; } } var rectTransform = tooltipUI.GetComponent <RectTransform>(); var rect = rectTransform.rect; var halfWidth = rect.width * 0.5f; var halfHeight = rect.height * 0.5f; if (placement != null) { offset *= halfWidth * rectTransform.lossyScale.x; } else { offset = Vector3.back * k_Offset; } MathUtilsExt.SetTransformOffset(target, tooltipTransform, offset * lerp, Quaternion.identity); if (placement != null) { var source = placement.tooltipSource; var toSource = tooltipTransform.InverseTransformPoint(source.position); // Position spheres: one at source, one on the closest edge of the tooltip var spheres = tooltipUI.spheres; spheres[0].position = source.position; var attachedSphere = spheres[1]; var boxSlope = halfHeight / halfWidth; var toSourceSlope = Mathf.Abs(toSource.y / toSource.x); halfHeight *= Mathf.Sign(toSource.y); halfWidth *= Mathf.Sign(toSource.x); attachedSphere.localPosition = toSourceSlope > boxSlope ? new Vector3(0, halfHeight) : new Vector3(halfWidth, 0); // Align dotted line var attachedSpherePosition = attachedSphere.position; toSource = source.position - attachedSpherePosition; var midPoint = attachedSpherePosition + toSource * 0.5f; var dottedLine = tooltipUI.dottedLine; var length = toSource.magnitude; var uvRect = dottedLine.uvRect; var worldScale = 1 / viewerScale; uvRect.width = length * k_UVScale * worldScale; uvRect.xMin += k_UVScrollSpeed * Time.unscaledDeltaTime; dottedLine.uvRect = uvRect; var dottedLineTransform = dottedLine.transform.parent.GetComponent <RectTransform>(); dottedLineTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, length / tooltipTransform.lossyScale.x); dottedLineTransform.position = midPoint; dottedLineTransform.rotation = Quaternion.LookRotation(toSource, -tooltipTransform.forward); } }
public void Update(Transform parent) { MathUtilsExt.SetTransformOffset(parent, transform, m_LocalPositionOffset, m_RotationOffset); }
internal void UpdateMiniWorlds(ConsumeControlDelegate consumeControl) { if (m_MiniWorldIgnoreListDirty) { UpdateMiniWorldIgnoreList(); m_MiniWorldIgnoreListDirty = false; } var objectsGrabber = evr.m_DirectSelection.objectsGrabber; foreach (var kvp in m_MiniWorldInputs) { kvp.Key.ProcessInput(kvp.Value, consumeControl); } // Update MiniWorldRays foreach (var ray in m_Rays) { var miniWorldRayOrigin = ray.Key; var miniWorldRay = ray.Value; if (!miniWorldRay.proxy.active) { miniWorldRay.tester.active = false; continue; } var miniWorld = miniWorldRay.miniWorld; var inverseScale = miniWorld.miniWorldTransform.lossyScale.Inverse(); if (float.IsInfinity(inverseScale.x) || float.IsNaN(inverseScale.x)) // Extreme scales cause transform errors { continue; } // Transform into reference space var originalRayOrigin = miniWorldRay.originalRayOrigin; var referenceTransform = miniWorld.referenceTransform; miniWorldRayOrigin.position = referenceTransform.position + Vector3.Scale(miniWorld.miniWorldTransform.InverseTransformPoint(originalRayOrigin.position), miniWorld.referenceTransform.localScale); miniWorldRayOrigin.rotation = referenceTransform.rotation * Quaternion.Inverse(miniWorld.miniWorldTransform.rotation) * originalRayOrigin.rotation; miniWorldRayOrigin.localScale = Vector3.Scale(inverseScale, referenceTransform.localScale); var directSelection = evr.m_DirectSelection; // Set miniWorldRayOrigin active state based on whether controller is inside corresponding MiniWorld var originalPointerPosition = originalRayOrigin.position + originalRayOrigin.forward * directSelection.GetPointerLength(originalRayOrigin); var isContained = miniWorld.Contains(originalPointerPosition); miniWorldRay.tester.active = isContained; miniWorldRayOrigin.gameObject.SetActive(isContained); var directSelectInput = (DirectSelectInput)miniWorldRay.directSelectInput; var dragObjects = miniWorldRay.dragObjects; if (dragObjects == null) { var heldObjects = objectsGrabber.GetHeldObjects(miniWorldRayOrigin); if (heldObjects != null) { // Only one ray can grab an object, otherwise PlaceObject is called on each trigger release // This does not prevent TransformTool from doing two-handed scaling var otherRayHasObject = false; foreach (var otherRay in m_Rays.Values) { if (otherRay != miniWorldRay && otherRay.dragObjects != null) { otherRayHasObject = true; } } if (!otherRayHasObject) { miniWorldRay.dragObjects = heldObjects; var scales = new Vector3[heldObjects.Length]; var dragGameObjects = new GameObject[heldObjects.Length]; for (var i = 0; i < heldObjects.Length; i++) { var dragObject = heldObjects[i]; scales[i] = dragObject.transform.localScale; dragGameObjects[i] = dragObject.gameObject; } var totalBounds = ObjectUtils.GetBounds(dragGameObjects); var maxSizeComponent = totalBounds.size.MaxComponent(); if (!Mathf.Approximately(maxSizeComponent, 0f)) { miniWorldRay.previewScaleFactor = Vector3.one * (k_PreviewScale * Viewer.GetViewerScale() / maxSizeComponent); } miniWorldRay.originalScales = scales; } } } // Transfer objects to and from original ray and MiniWorld ray (e.g. outside to inside mini world) if (directSelection != null && isContained != miniWorldRay.wasContained) { var pointerLengthDiff = directSelection.GetPointerLength(miniWorldRayOrigin) - directSelection.GetPointerLength(originalRayOrigin); var from = isContained ? originalRayOrigin : miniWorldRayOrigin; var to = isContained ? miniWorldRayOrigin : originalRayOrigin; if (isContained || miniWorldRay.dragObjects == null) { objectsGrabber.TransferHeldObjects(from, to, pointerLengthDiff * Vector3.forward); } } // Transfer objects between MiniWorlds if (dragObjects == null) { if (isContained) { foreach (var kvp in m_Rays) { var otherRayOrigin = kvp.Key; var otherRay = kvp.Value; var otherObjects = otherRay.dragObjects; if (otherRay != miniWorldRay && !otherRay.wasContained && otherObjects != null) { dragObjects = otherObjects; miniWorldRay.dragObjects = otherObjects; miniWorldRay.originalScales = otherRay.originalScales; miniWorldRay.previewScaleFactor = otherRay.previewScaleFactor; otherRay.dragObjects = null; if (directSelection != null) { var heldObjects = objectsGrabber.GetHeldObjects(otherRayOrigin); if (heldObjects != null) { objectsGrabber.TransferHeldObjects(otherRayOrigin, miniWorldRayOrigin, Vector3.zero); // Set the new offset to zero because the object will have moved (this could be improved by taking original offset into account) } } break; } } } } if (isContained && !miniWorldRay.wasContained) { Rays.HideRay(originalRayOrigin, true); Rays.LockRay(originalRayOrigin, this); } if (!isContained && miniWorldRay.wasContained) { Rays.UnlockRay(originalRayOrigin, this); Rays.ShowRay(originalRayOrigin, true); } if (dragObjects == null) { miniWorldRay.wasContained = isContained; continue; } var previewScaleFactor = miniWorldRay.previewScaleFactor; var positionOffsets = miniWorldRay.originalPositionOffsets; var rotationOffsets = miniWorldRay.originalRotationOffsets; var originalScales = miniWorldRay.originalScales; if (directSelectInput.select.isHeld) { if (isContained) { // Scale the object back to its original scale when it re-enters the MiniWorld if (!miniWorldRay.wasContained) { for (var i = 0; i < dragObjects.Length; i++) { var dragObject = dragObjects[i]; dragObject.localScale = originalScales[i]; MathUtilsExt.SetTransformOffset(miniWorldRayOrigin, dragObject, positionOffsets[i], rotationOffsets[i]); } // Add the object (back) to TransformTool if (directSelection != null) { objectsGrabber.GrabObjects(miniWorldRay.node, miniWorldRayOrigin, directSelectInput, dragObjects); } } } else { // Check for player head for (var i = 0; i < dragObjects.Length; i++) { var dragObject = dragObjects[i]; if (dragObject.CompareTag(k_VRPlayerTag)) { if (directSelection != null) { objectsGrabber.DropHeldObjects(miniWorldRayOrigin); } // Drop player at edge of MiniWorld miniWorldRay.dragObjects = null; dragObjects = null; break; } } if (dragObjects == null) { continue; } if (miniWorldRay.wasContained) { var containedInOtherMiniWorld = false; foreach (var world in m_Worlds) { if (miniWorld != world && world.Contains(originalPointerPosition)) { containedInOtherMiniWorld = true; } } // Don't switch to previewing the objects we are dragging if we are still in another mini world if (!containedInOtherMiniWorld) { for (var i = 0; i < dragObjects.Length; i++) { var dragObject = dragObjects[i]; // Store the original scale in case the object re-enters the MiniWorld originalScales[i] = dragObject.localScale; dragObject.localScale = Vector3.Scale(dragObject.localScale, previewScaleFactor); } // Drop from TransformTool to take control of object if (directSelection != null) { objectsGrabber.DropHeldObjects(miniWorldRayOrigin, out positionOffsets, out rotationOffsets); miniWorldRay.originalPositionOffsets = positionOffsets; miniWorldRay.originalRotationOffsets = rotationOffsets; miniWorldRay.wasHeld = true; } } } for (var i = 0; i < dragObjects.Length; i++) { var dragObject = dragObjects[i]; var rotation = originalRayOrigin.rotation; var position = originalRayOrigin.position + rotation * Vector3.Scale(previewScaleFactor, positionOffsets[i]); MathUtilsExt.LerpTransform(dragObject, position, rotation * rotationOffsets[i]); } } } // Release the current object if the trigger is no longer held if (directSelectInput.select.wasJustReleased) { var rayPosition = originalRayOrigin.position; for (var i = 0; i < dragObjects.Length; i++) { var dragObject = dragObjects[i]; // If the user has pulled an object out of the MiniWorld, use PlaceObject to grow it back to its original scale if (!isContained) { if (evr.m_Viewer.IsOverShoulder(originalRayOrigin)) { evr.m_SceneObjectModule.DeleteSceneObject(dragObject.gameObject); } else { dragObject.localScale = originalScales[i]; var rotation = originalRayOrigin.rotation; dragObject.position = rayPosition + rotation * positionOffsets[i]; dragObject.rotation = rotation * rotationOffsets[i]; } } } miniWorldRay.dragObjects = null; miniWorldRay.wasHeld = false; } miniWorldRay.wasContained = isContained; } }
void UpdateVisuals(ITooltip tooltip, TooltipUI tooltipUI, Transform target, float lerp) { var tooltipTransform = tooltipUI.transform; lerp = MathUtilsExt.SmoothInOutLerpFloat(lerp); // shape the lerp for better presentation var tooltipText = tooltipUI.text; if (tooltipText) { tooltipText.text = tooltip.tooltipText; tooltipText.color = Color.Lerp(Color.clear, Color.white, lerp); } var viewerScale = this.GetViewerScale(); tooltipTransform.localScale = m_TooltipScale * lerp * viewerScale; TooltipData toolTipData; m_Tooltips.TryGetValue(tooltip, out toolTipData); var highlightMaterial = toolTipData != null ? toolTipData.customHighlightMaterial : m_HighlightMaterial; tooltipUI.highlight.material = highlightMaterial; m_TooltipBackgroundMaterial.SetColor("_Color", Color.Lerp(UnityBrandColorScheme.darker, m_OriginalBackgroundColor, lerp)); var placement = tooltip as ITooltipPlacement; // Adjust for alignment var offset = Vector3.zero; if (placement != null) { switch (placement.tooltipAlignment) { case TextAlignment.Right: offset = Vector3.left; break; case TextAlignment.Left: offset = Vector3.right; break; } } var rectTransform = tooltipUI.GetComponent <RectTransform>(); var rect = rectTransform.rect; var halfWidth = rect.width * 0.5f; var halfHeight = rect.height * 0.5f; if (placement != null) { offset *= halfWidth * rectTransform.lossyScale.x; } else { offset = Vector3.back * k_Offset * this.GetViewerScale(); } MathUtilsExt.SetTransformOffset(target, tooltipTransform, offset * lerp, Quaternion.identity); if (placement != null) { var source = placement.tooltipSource; var toSource = tooltipTransform.InverseTransformPoint(source.position); // Position spheres: one at source, one on the closest edge of the tooltip var spheres = tooltipUI.spheres; spheres[0].position = source.position; var attachedSphere = spheres[1]; var boxSlope = halfHeight / halfWidth; var toSourceSlope = Mathf.Abs(toSource.y / toSource.x); halfHeight *= Mathf.Sign(toSource.y); halfWidth *= Mathf.Sign(toSource.x); attachedSphere.localPosition = toSourceSlope > boxSlope ? new Vector3(0, halfHeight) : new Vector3(halfWidth, 0); // Align dotted line var attachedSpherePosition = attachedSphere.position; toSource = source.position - attachedSpherePosition; var midPoint = attachedSpherePosition + toSource * 0.5f; var dottedLine = tooltipUI.dottedLine; var length = toSource.magnitude; var uvRect = dottedLine.uvRect; var worldScale = 1 / viewerScale; uvRect.width = length * k_UVScale * worldScale; uvRect.xMin += k_UVScrollSpeed * Time.deltaTime; dottedLine.uvRect = uvRect; var dottedLineTransform = dottedLine.transform.parent.GetComponent <RectTransform>(); dottedLineTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, length / tooltipTransform.lossyScale.x); dottedLineTransform.position = midPoint; dottedLineTransform.rotation = Quaternion.LookRotation(toSource, -tooltipTransform.forward); } }