Topic: Drag with two fingers

Hello there!

I want to drag the map while zooming with two fingers, like Google maps does it. Is there an option for it?
If not, I can't find where you handle the touch input (when not connected to Fingers or EasyTouch), to add this option manually. In which script is the touch input handled?

Best,
Martin

Re: Drag with two fingers

Hello.

Something like:

using System;
using System.Reflection;
using UnityEngine;

public class DragOnSmoothZoom : MonoBehaviour
{
    private Vector2 lastInputPosition;
    private Vector2 inputPosition;
    private OnlineMapsControlBase control;
    private MethodInfo updatePosition;
    private FieldInfo lastInputField;
    private bool sendWrongTouchCount;

    private int OnGetTouchCount()
    {
        if (sendWrongTouchCount) return 1;

        if (Input.touchSupported)
        {
            if (Input.touchCount > 0) return Input.touchCount;
        }
        return Input.GetMouseButton(0) ? 1 : 0;
    }

    private void OnSmoothZoomBegin()
    {
        lastInputPosition = control.GetInputPosition();
        control.OnUpdateBefore += OnUpdateBefore;

        lastInputField.SetValue(control, control.GetInputPosition());
        control.UpdateLastPosition();
    }

    private void OnSmoothZoomFinish()
    {
        control.OnUpdateBefore -= OnUpdateBefore;

        lastInputField.SetValue(control, control.GetInputPosition());
        control.UpdateLastPosition();
    }

    private void OnUpdateBefore()
    {
        if (OnGetTouchCount() <= 1) return;

        inputPosition = control.GetInputPosition();
        if (lastInputPosition == inputPosition) return;

        lastInputField.SetValue(control, lastInputPosition);
        sendWrongTouchCount = true;
        updatePosition.Invoke(control, null);
        sendWrongTouchCount = false;

        lastInputPosition = inputPosition;
    }

    private void Start()
    {
        control = OnlineMapsControlBase.instance;
        control.OnSmoothZoomBegin += OnSmoothZoomBegin;
        control.OnSmoothZoomFinish += OnSmoothZoomFinish;
        control.OnGetTouchCount += OnGetTouchCount;

        Type controlType = typeof(OnlineMapsControlBase);
        updatePosition = controlType.GetMethod("UpdatePosition", BindingFlags.Instance | BindingFlags.NonPublic);
        lastInputField = controlType.GetField("lastInputPosition", BindingFlags.Instance | BindingFlags.NonPublic);
    }
}
Kind Regards,
Infinity Code Team.

Do not know the best way to thank the developer? Rate the asset in Asset Store!

3 (edited by MartinTinu 2019-07-29 16:41:20)

Re: Drag with two fingers

Cool, this almost works. big_smile

But it jumps when starting the zoom/drag. My guess is that it takes the last inputPosition and centers the pinch to it, which leads to the jump. Any idea how to solve this?

Thank you!


EDIT: Ooops, the following code doesn't work.
Additionally I added the following lines. Otherwise when starting not at {0,0}, it jumps to the african atlantic.

if(lastInputPosition == Vector2.zero)
            lastInputPosition = OnlineMaps.instance.position;

Re: Drag with two fingers

Updated script in post #2 to not produce a million versions of the same script.
lastInputPosition contains the position of a mouse or touch, and not geographical coordinates.

Kind Regards,
Infinity Code Team.

Do not know the best way to thank the developer? Rate the asset in Asset Store!

5 (edited by MartinTinu 2019-07-30 09:52:10)

Re: Drag with two fingers

Works like a charm now!
Thank you very much! smile

Now for me there is just one more thing that reduces the usability of the touch controls: Google maps has a smooth damping when zooming. This makes it much easier and faster to zoom in/out very quickly (and also adds a natural feel to it). Do you think it's also possible to implement this in Online Maps? (Should I have opened a new topic for this?)

Re: Drag with two fingers

"smooth damping" - do you mean inertia?
Yes, of course it is possible to implement.
It will take a couple of days (due to the release of Unity 2019.2).

Kind Regards,
Infinity Code Team.

Do not know the best way to thank the developer? Rate the asset in Asset Store!

Re: Drag with two fingers

Something like that:

using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace InfinityCode.OnlineMapsExamples
{
    public class DragAndZoomInertia : MonoBehaviour
    {
        /// <summary>
        /// Deceleration rate (0 - 1).
        /// </summary>
        public float friction = 0.9f;

        private bool isInteract;
        private List<double> speedX;
        private List<double> speedY;
        private List<float> speedZ;
        private double rsX;
        private double rsY;
        private float rsZ;
        private double ptx;
        private double pty;
        private float pz;
        private const int maxSamples = 5;

        private OnlineMaps map;
        private OnlineMapsControlBase control;

        private void FixedUpdate()
        {
            if (isInteract && control.GetTouchCount() == 0) isInteract = false;

            // If there is interaction with the map.
            if (isInteract)
            {
                // Calculates speeds.
                double tx, ty;
                map.GetTilePosition(out tx, out ty, 20);

                double cSpeedX = tx - ptx;
                double cSpeedY = ty - pty;
                float cSpeedZ = map.floatZoom - pz;

                int halfMax = 1 << 19;
                int max = 1 << 20;
                if (cSpeedX > halfMax) cSpeedX -= max;
                else if (cSpeedX < -halfMax) cSpeedX += max;

                while (speedX.Count >= maxSamples) speedX.RemoveAt(0);
                while (speedY.Count >= maxSamples) speedY.RemoveAt(0);
                while (speedZ.Count >= maxSamples) speedZ.RemoveAt(0);

                speedX.Add(cSpeedX);
                speedY.Add(cSpeedY);
                speedZ.Add(cSpeedZ);

                ptx = tx;
                pty = ty;
                pz = map.floatZoom;
            }
            // If no interaction with the map.
            else if (rsX * rsX + rsY * rsY > 0.001 || rsZ > 0.001)
            {
                // Continue to move the map with the current speed.
                double tx, ty;
                map.GetTilePosition(out tx, out ty, 20);

                tx += rsX;
                ty += rsY;

                int max = 1 << 20;
                if (tx >= max) tx -= max;
                else if (tx < 0) tx += max;

                map.SetTilePosition(tx, ty, 20);
                //control.ZoomOnPoint(rsZ, lastScreenPoint);
                map.floatZoom += rsZ;

                // Reduces the current speed.
                rsX *= friction;
                rsY *= friction;
                rsZ *= friction;
            }
        }

        /// <summary>
        /// This method is called when you press on the map.
        /// </summary>
        private void OnMapPress()
        {
            // Get tile coordinates of map
            map.GetTilePosition(out ptx, out pty, 20);
            pz = map.floatZoom;

            // Is marked, that is the interaction with the map.
            isInteract = true;
        }

        /// <summary>
        /// This method is called when you release on the map.
        /// </summary>
        private void OnMapRelease()
        {
            if (control.GetTouchCount() != 0) return;

            // Is marked, that ended the interaction with the map.
            isInteract = false;

            // Calculates the average speed.
            rsX = speedX.Count > 0 ? speedX.Average() : 0;
            rsY = speedY.Count > 0 ? speedY.Average() : 0;
            rsZ = speedZ.Count > 0 ? speedZ.Average() : 0;

            speedX.Clear();
            speedY.Clear();
            speedZ.Clear();
        }


        private void Start()
        {
            map = OnlineMaps.instance; ;
            control = OnlineMapsControlBase.instance;

            // Subscribe to map events
            control.OnMapPress += OnMapPress;
            control.OnMapRelease += OnMapRelease;

            // Initialize arrays of speed
            speedX = new List<double>(maxSamples);
            speedY = new List<double>(maxSamples);
            speedZ = new List<float>(maxSamples);
        }
    }
}
Kind Regards,
Infinity Code Team.

Do not know the best way to thank the developer? Rate the asset in Asset Store!