コード例 #1
0
        private void LinearAnimation(double t, out float zoomLevel, out LatLon location)
        {
            // First, update the zoom.
            zoomLevel = (float)(_startZoomLevel + (_endZoomLevel - _startZoomLevel) * t);

            // Update the location.
            if (_startMercatorCenter != _endMercatorCenter)
            {
                if (_startZoomLevel != _endZoomLevel)
                {
                    // Adjust t so that it depends on the zoom level. This keeps the position animating correctly at a logarthmic scale to
                    // match how zoom level is being calculated.
                    var adjustedT          = (_startHeightInMercator - ZoomLevelToMercatorAltitude(zoomLevel)) / (_startHeightInMercator - _endHeightInMercator);
                    var mercatorCoordinate = Interpolate(_startMercatorCenter, _endMercatorCenter, adjustedT);
                    location = mercatorCoordinate.ToLatLon();
                }
                else
                {
                    var mercatorCoordinate = Interpolate(_startMercatorCenter, _endMercatorCenter, t);
                    location = mercatorCoordinate.ToLatLon();
                }
            }
            else
            {
                location = _endMercatorCenter.ToLatLon();
            }
        }
コード例 #2
0
    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;
        }
    }
コード例 #3
0
    private void Update()
    {
        var isInteractingWithMap = _panningPointer != null;

        if (isInteractingWithMap &&
            CoreServices.InputSystem.FocusProvider.TryGetFocusDetails(_panningPointer, out FocusDetails focusDetails))
        {
            // Determine amount to zoom in or out.
            var directionalZoomAmount = 0.0f;
            var zoomMagnitude         = _currentZoomValue.magnitude;
            if (zoomMagnitude > JoystickDeadZone)
            {
                var angle = Mathf.Rad2Deg * Mathf.Abs(Mathf.Atan2(_currentZoomValue.y, _currentZoomValue.x));
                if (Mathf.Abs(90.0f - angle) < 75)
                {
                    directionalZoomAmount = _currentZoomValue.y;
                }
            }

            // Compute more terms if there is any zoom to apply.
            var zoomRatio = 1.0;
            var zoomLevelToUseForInteraction = _mapRenderer.ZoomLevel;
            if (directionalZoomAmount != 0)
            {
                var zoomSpeed    = Mathf.Lerp(0.01f, 0.045f, _zoomSpeed);
                var zoomToApply  = zoomSpeed * directionalZoomAmount;
                var oldZoomLevel = _mapRenderer.ZoomLevel;
                var newZoomLevel =
                    Math.Min(
                        _mapRenderer.MaximumZoomLevel,
                        Math.Max(_mapRenderer.MinimumZoomLevel, oldZoomLevel + zoomToApply));
                zoomRatio = Math.Pow(2, oldZoomLevel - 1) / Math.Pow(2, newZoomLevel - 1);
                zoomLevelToUseForInteraction = newZoomLevel;
            }

            // The _startingPointInLocalSpace can be updated now as zoom changed so it's altitude may change as well.
            // A future improvement to make here is to actually requery the altitude of the _startingPointInMercatorSpace,
            // as this altitude can also change based on the level of detail being shown.
            var offsetAltitudeInMeters = _startingAltitudeInMeters - _mapRenderer.ElevationBaseline;
            var equatorialCircumferenceInLocalSpace = Math.Pow(2, zoomLevelToUseForInteraction - 1);
            var altitudeInLocalSpace =
                offsetAltitudeInMeters *
                _startingMercatorScale *
                (equatorialCircumferenceInLocalSpace / MapRendererTransformExtensions.EquatorialCircumferenceInWgs84Meters);
            _startingPointInLocalSpace.y = (float)(_mapRenderer.LocalMapBaseHeight + altitudeInLocalSpace);

            // Now we can raycast an imaginary plane orignating from the updated _startingPointInLocalSpace.
            var rayPositionInMapLocalSpace  = _mapRenderer.transform.InverseTransformPoint(_panningPointer.Position);
            var rayDirectionInMapLocalSpace = _mapRenderer.transform.InverseTransformDirection(_panningPointer.Rotation * Vector3.forward).normalized;
            var rayInMapLocalSpace          = new Ray(rayPositionInMapLocalSpace, rayDirectionInMapLocalSpace.normalized);
            var hitPlaneInMapLocalSpace     = new Plane(Vector3.up, _startingPointInLocalSpace);
            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);

                // Also override the FocusDetails so that the pointer ray tracks with the map.
                // Otherwise, it would remain fixed in world space.
                focusDetails.Point           = _mapRenderer.transform.TransformPoint(_currentPointInLocalSpace);
                focusDetails.PointLocalSpace = _currentPointInLocalSpace;
                CoreServices.InputSystem.FocusProvider.TryOverrideFocusDetails(_panningPointer, focusDetails);
            }

            // Apply zoom now, if needed.
            if (directionalZoomAmount != 0)
            {
                _mapRenderer.ZoomLevel = zoomLevelToUseForInteraction;
                var deltaToCenterInMercatorSpace         = _startingPointInMercator - _startingMapCenterInMercator;
                var adjustedDeltaToCenterInMercatorSpace = zoomRatio * deltaToCenterInMercatorSpace;
                _startingMapCenterInMercator = _startingPointInMercator - adjustedDeltaToCenterInMercatorSpace;
            }

            // Apply pan translation.
            var deltaInLocalSpace          = _currentPointInLocalSpace - _startingPointInLocalSpace;
            var deltaInMercatorSpace       = MapRendererTransformExtensions.TransformLocalDirectionToMercator(deltaInLocalSpace, zoomLevelToUseForInteraction);
            var newCenterInMercator        = _startingMapCenterInMercator - deltaInMercatorSpace;
            var newClampedCenterInMercator = new MercatorCoordinate(newCenterInMercator.X, Math.Max(Math.Min(0.5, newCenterInMercator.Y), -0.5));

            _mapRenderer.Center = newClampedCenterInMercator.ToLatLon();
        }
    }