private void Update() { // First case handles when the map is selected and being dragged and/or zoomed. var isPanning = _pointer != null; if (isPanning && CoreServices.InputSystem.FocusProvider.TryGetFocusDetails(_pointer, out FocusDetails focusDetails)) { // Now we can raycast an imaginary plane orignating from the updated _targetPointInLocalSpace. var rayPositionInMapLocalSpace = _mapRenderer.transform.InverseTransformPoint(_pointer.Position); var rayDirectionInMapLocalSpace = _mapRenderer.transform.InverseTransformDirection(_pointer.Rotation * Vector3.forward).normalized; var rayInMapLocalSpace = new Ray(rayPositionInMapLocalSpace, rayDirectionInMapLocalSpace.normalized); var hitPlaneInMapLocalSpace = new Plane(Vector3.up, _targetPointInLocalSpace); if (hitPlaneInMapLocalSpace.Raycast(rayInMapLocalSpace, out float enter)) { // This point will be used to determine how much to translate the map. // Decaying the resulting position applies some smoothing to the input. var panSmoothness = Mathf.Lerp(0.0f, 0.5f, _panSmoothness); _currentPointInLocalSpace = DynamicExpDecay(_currentPointInLocalSpace, rayInMapLocalSpace.GetPoint(enter), panSmoothness); } // Reconstruct ray from pointer position to focus details. var rayTargetPoint = _mapRenderer.transform.TransformPoint(_currentPointInLocalSpace); var ray = new Ray(_pointer.Position, (rayTargetPoint - _pointer.Position).normalized); var zoomToApply = ComputeZoomToApply(); _mapInteractionController.PanAndZoom(ray, _targetPointInMercator, _startingAltitudeInMeters, zoomToApply); // Update starting point so that the focus point tracks with this point. _targetPointInLocalSpace = _mapRenderer.TransformMercatorWithAltitudeToLocalPoint(_targetPointInMercator, _startingAltitudeInMeters); // Also override the FocusDetails so that the pointer ray tracks the target coordinate. focusDetails.Point = _mapRenderer.transform.TransformPoint(_targetPointInLocalSpace); focusDetails.PointLocalSpace = _targetPointInLocalSpace; CoreServices.InputSystem.FocusProvider.TryOverrideFocusDetails(_pointer, focusDetails); } else if (_zoomPointer != null && _isFocused) // This case handles when the map is just focused, not selected, and being zoomed. { var zoomToApply = ComputeZoomToApply(); if (zoomToApply != 0) { var pointerRayPosition = _zoomPointer.Position; var pointerRayDirection = (_zoomPointer.Rotation * Vector3.forward).normalized; _mapInteractionController.Zoom(zoomToApply, new Ray(pointerRayPosition, pointerRayDirection)); } } }
private void Update() { // First case handles when the map is selected and being dragged and/or zoomed. if (_isInteracting && _pointer != null && CoreServices.InputSystem.FocusProvider.TryGetFocusDetails(_pointer, out var focusDetails) && focusDetails.Object == gameObject) { // The current point the ray is targeting has been calculated in OnPointerDragged. Smooth it here. var panSmoothness = Mathf.Lerp(0.0f, 0.5f, _panSmoothness); _smoothedPointInLocalSpace = DynamicExpDecay(_smoothedPointInLocalSpace, _currentPointInLocalSpace, panSmoothness); // Reconstruct ray from pointer position to focus details. var rayTargetPoint = MapRenderer.transform.TransformPoint(_smoothedPointInLocalSpace); var ray = new Ray(_pointer.Position, (rayTargetPoint - _pointer.Position).normalized); MapInteractionController.PanAndZoom(ray, _targetPointInMercator, _targetAltitudeInMeters, ComputeZoomToApply()); // Update starting point so that the focus point tracks with this point. _targetPointInLocalSpace = MapRenderer.TransformMercatorWithAltitudeToLocalPoint(_targetPointInMercator, _targetAltitudeInMeters); // Also override the FocusDetails so that the pointer ray tracks the target coordinate. focusDetails.Point = MapRenderer.transform.TransformPoint(_targetPointInLocalSpace); focusDetails.PointLocalSpace = _targetPointInLocalSpace; CoreServices.InputSystem.FocusProvider.TryOverrideFocusDetails(_pointer, focusDetails); // Reset timings used for tap-and-hold and double tap. _lastPointerDownTime = float.MaxValue; _lastClickTime = float.MinValue; } else if (_zoomPointer != null && _isFocused) // This case handles when the map is just focused, not selected, and being zoomed. { var zoomToApply = ComputeZoomToApply(); if (zoomToApply != 0) { if (!_isInteracting) { _isInteracting = true; MapInteractionController.OnInteractionStarted?.Invoke(); } var pointerRayPosition = _zoomPointer.Position; var pointerRayDirection = (_zoomPointer.Rotation * Vector3.forward).normalized; MapInteractionController.Zoom(zoomToApply, new Ray(pointerRayPosition, pointerRayDirection)); // Reset timings used for tap-and-hold and double tap. _lastPointerDownTime = float.MaxValue; _lastClickTime = float.MinValue; } else { if (_zoomPointer != null && _isInteracting) { // We were zooming last frame. End the interaction. MapInteractionController.OnInteractionEnded?.Invoke(); _isInteracting = false; _zoomPointer = null; } } } else { if (_isInteracting) { // Last frame there was interaction happening. This is the first frame where the interaction has ended. MapInteractionController.OnInteractionEnded?.Invoke(); _isInteracting = false; } } // Check for a tap and hold. if (_pointer != null && (Time.time - _lastPointerDownTime) > TapAndHoldThresholdInSeconds) { MapInteractionController.OnTapAndHold?.Invoke(new LatLonAlt(_targetPointInMercator.ToLatLon(), _targetAltitudeInMeters)); // Reset timings used for tap-and-hold and double tap. _lastPointerDownTime = float.MaxValue; _lastClickTime = float.MinValue; } }