Topic: Smooth-er zoom

Hello, can we make somehow a smoother zoom? The problem is that it snaps to the int value of the zoom level. Can you compute the difference between the scale offset and the zoom level and set the scale to that difference so the images won't snap?

PS: I tried to do this but I couldn't quite figure out the correlation between the zoom and scale.

Thank you!

Re: Smooth-er zoom

Hello.

The current version of Online Maps, smooth zoom is available only for the Tileset.
But you can make a smooth zoom for other controls by using Online Maps API.
Example for uGUI:
http://forum.infinity-code.com/viewtopic.php?pid=67#p67

Kind Regards,
Infinity Code Team

Re: Smooth-er zoom

Hi, thank you for your fast response. I am using the smooth zoom on the Tileset, but the problem is that is not smooth enough:). if you are trying to change the zoom by just a little(like moving your finger for less than half a centimetre, maybe even less) you will see that the tileset snaps back. Can you do something so it wont?

Re: Smooth-er zoom

Unfortunately, zoom is integer.
It is very difficult (perhaps impossible) to fix it without losing compatibility.
We will try to find some way to solve this problem.

Kind Regards,
Infinity Code Team

Re: Smooth-er zoom

Is there any possibility to disconnect the app zoom from the google zoom? I know that the google zoom is an integer, but what I'm asking is not to snap the tiles, and just leave them there(even though they are bigger than the initial frame) and start download new images the corresponding integer of the app zoom(which is the scale of the tiles container) is changed?
This would mean that the approximation would have to go upward so you don't have any "grey" areas around the map.

My biggest issue is this: if the user only zooms in/out a small value, then it will snap back to the initial zoom. If they go a bit more, it will snap to the next zoom, which is not really smooth at all, and unfortunately we cannot release with this for is a major UX issue for us. Thank you!

Re: Smooth-er zoom

Hello.

Something like that?

using UnityEngine;

public class SmootherZoom : MonoBehaviour
{
    public float zoom;

    private float _zoom;
    private Vector3 position;
    private Vector2 tilesetSize;

    private bool needUpdate;
    private Vector3 newScale;
    private Vector3 newPosition;

    private void Start()
    {
        _zoom = zoom = OnlineMaps.instance.zoom;
        position = transform.position;
        tilesetSize = OnlineMaps.instance.tilesetSize;

        OnlineMaps.instance.OnMapUpdated += OnMapUpdated;
    }

    private void OnMapUpdated()
    {
        if (needUpdate)
        {
            transform.localScale = newScale;
            transform.position = newPosition;
            needUpdate = false;
        }
    }

    private void Update()
    {
        if (_zoom != zoom)
        {
            int iZoom = (int)zoom;
            if (OnlineMaps.instance.zoom != (int) zoom)
            {
                OnlineMaps.instance.zoom = iZoom;
                needUpdate = true;
            }
            float offset = zoom - iZoom;

            newScale = new Vector3(offset + 1, 1, offset + 1);
            newPosition = position - new Vector3(tilesetSize.x * offset / -2, 0, tilesetSize.y * offset / 2);

            if (!needUpdate)
            {
                transform.localScale = newScale;
                transform.position = newPosition;
            }

            _zoom = zoom;
        }
    }
}
Kind Regards,
Infinity Code Team

Re: Smooth-er zoom

Well....sort of...it's the right idea, but it doesn't work for some reason. It still snaps to the zoom level rather then keeping the scale with a floating point. I think it has to do with the fact that you don't assign the zoom variable anywhere during runtime. I tried something similar myself but I couldn't figure it out. Can you please help me some more? Thanks!

Re: Smooth-er zoom

OK.

Another example (requires Online Maps v2.4.0.54+):

using UnityEngine;

public class SmootherZoom2 : MonoBehaviour
{
    private Vector3 position;
    private Vector3 localScale;
    private Vector3 originalPosition;
    //private float zoom;
    private Vector3 originalScale;
    private Transform t;

    private void OnSmoothZoomBegin()
    {
        t.position = position;
        t.localScale = localScale;
    }

    private void OnSmoothZoomFinish()
    {
        t.position = position;
        t.localScale = localScale;
    }

    private void OnSmoothZoomInit()
    {
        t.position = originalPosition;
        t.localScale = originalScale;
    }

    private void OnSmoothZoomProcess()
    {
        Vector2 p1 = Input.GetTouch(0).position;
        Vector2 p2 = Input.GetTouch(1).position;

        Vector2 zoomPoint = Vector2.Lerp(p1, p2, 0.5f);

        while (t.localScale.x > 2 || t.localScale.x < 0.5)
        {
            if (t.localScale.x > 2)
            {
                OnlineMapsControlBase.instance.ZoomOnPoint(1, zoomPoint);
                t.position = (t.position - originalPosition) / 2 + originalPosition;
                t.localScale /= 2;
            }
            else if (t.localScale.x < 0.5)
            {
                OnlineMapsControlBase.instance.ZoomOnPoint(-1, zoomPoint);
                t.position = (originalPosition - t.position) * 2 + t.position;
                t.localScale *= 2;
            }
        }

        position = t.position;
        localScale = t.localScale;

        //zoom = localScale.x > 1 ? OnlineMaps.instance.zoom + localScale.x - 1 : OnlineMaps.instance.zoom - (1 - localScale.x) / 2;
    }

    private void Start()
    {
        //zoom = OnlineMaps.instance.zoom;
        t = OnlineMapsTileSetControl.instance.transform;

        originalPosition = position = t.position;
        originalScale = localScale = t.localScale;

        OnlineMapsTileSetControl.instance.OnSmoothZoomBegin += OnSmoothZoomBegin;
        OnlineMapsTileSetControl.instance.OnSmoothZoomProcess += OnSmoothZoomProcess;
        OnlineMapsTileSetControl.instance.OnSmoothZoomFinish += OnSmoothZoomFinish;
        OnlineMapsTileSetControl.instance.OnSmoothZoomInit += OnSmoothZoomInit;
    }
}
Kind Regards,
Infinity Code Team

Re: Smooth-er zoom

Hi....thanks for your replies but unfortunately this one is buggy. Really buggy.

10 (edited by gamar 2016-08-11 16:59:20)

Re: Smooth-er zoom

I have written my own tilesetcontrol that extends yours and it works now, still has a small glitch though.Is there a way one can change the pivot from top left to centre?

Here is my code:

using UnityEngine;
using System.Collections;

public class CustomTileSetControl : OnlineMapsTileSetControl
{
    private Vector3 m_originalPosition;
    private Quaternion m_originalRotation;
    private Vector3 m_originalScale;
    private Vector3 m_mapCenter;
    private float m_nextScaleModifier = 1;

    public void Awake ()
    {
        m_originalPosition = transform.localPosition;
        m_originalRotation = transform.localRotation;
        m_originalScale = transform.localScale;
    }

    protected override void UpdateGestureZoom ()
    {
        if (!smoothZoom) {
            base.UpdateGestureZoom ();
            return;
        }
        
        if (!allowUserControl)
            return;
        
        if (Input.touchCount == 2) {
            isMapDrag = false;
            if (!smoothZoomStarted) {
                smoothZoomStarted = true;
            }
            Vector2 p1 = Input.GetTouch (0).position;
            Vector2 p2 = Input.GetTouch (1).position;
            float distance = (p1 - p2).magnitude;
            
            if (lastGestureDistance != 0) {
                Vector2 center = Vector2.Lerp (p1, p2, 0.5f);

                RaycastHit hit;
                if (!cl.Raycast (activeCamera.ScreenPointToRay (center), out hit, OnlineMapsUtils.maxRaycastDistance))
                    return;

                float scale = 1;
                
                if (!invertTouchZoom)
                    scale = distance / lastGestureDistance;
                else
                    scale = lastGestureDistance / distance;

                float initialScale = transform.localScale.x;
                transform.localScale *= scale * m_nextScaleModifier;

                float floatOffset = (float)Mathf.Log (transform.localScale.x, 2);
                int offset = floatOffset > 0 ? Mathf.FloorToInt (floatOffset) : Mathf.CeilToInt (floatOffset);
                m_nextScaleModifier = 1;
                if (offset != 0) {
                    ZoomOnPoint (offset, center);
                    m_nextScaleModifier = Mathf.Pow (2, -floatOffset);
                }
                
                if (transform.localScale.x < 0.9) {
                    ZoomOnPoint (offset - 1, center);
                    m_nextScaleModifier = 2;
                }

                float scaleDifference = (transform.localScale.x / initialScale) - 1;
                    Vector3 smoothZoomOffset = transform.position - hit.point;
                    transform.position -= new Vector3 (-smoothZoomOffset.x, 0, -smoothZoomOffset.z) * scaleDifference;
            }
            lastGestureDistance = distance;
        } else {
            if (smoothZoomStarted) {
                lastGestureDistance = 0;
                Vector2 center = new Vector2 (Screen.width / 2, Screen.height / 2);
                double ox, oy;
                if (GetCoords (out ox, out oy, center)) {
                    api.SetPosition (ox, oy);
                    float scaleDifference = m_originalScale.x - transform.localScale.x;
                    transform.localPosition = m_originalPosition + new Vector3 (api.tilesetSize.x / -2, 0, api.tilesetSize.y / 2) * scaleDifference;
                }
            }
            smoothZoomStarted = false;
        }
    }

    public void ResetZoom ()
    {
        transform.localPosition = m_originalPosition;
        transform.localRotation = m_originalRotation;
        transform.localScale = m_originalScale;
    }
}

and editor in case you need it:

using UnityEngine;
using System.Collections;
using UnityEditor;

[CustomEditor(typeof (CustomTileSetControl))]
public class CustomTileSetControlEditor : OnlineMapsTilesetControlEditor {


}

Re: Smooth-er zoom

Hello.

No, in the current version, you can not change the pivot.
There are a lot of code that use Tileset from the top-left corner.

I think it will be very useful in some cases, and we will add the ability to change the pivot.

Kind Regards,
Infinity Code Team

Re: Smooth-er zoom

Hi. I have another question if you can help me. I have made that script up there and it work great. Well, almost. It has a small snap when changing the zoom scale and I can't wrap my head around it since everything looks inline. Do you have some time to explore why this is happening? Also, when zooming in/out very fast it creates a short flash and I have no idea why this happens but I think is texture related. Do you have any ideas?

Thank you very much!

Re: Smooth-er zoom

Hello.

Most likely this happens when you change the zoom over 3 levels.
Online Maps uses the current zoom level + 3 parent zoom level.
When you change the zoom, Online Maps unload unused tiles.
When you quickly change the zoom, can be a situation where you do not have loaded tiles. In this moment you can see a short flash.

Kind Regards,
Infinity Code Team

14 (edited by guruhenry 2016-11-16 19:16:45)

Re: Smooth-er zoom

Hello,
I reopen this thread because I'm trying to support a smooth zoom like google maps and I'm encountering a glitch during the zoom update.

To perform a smooth zoom within the UpdateGestureZoom method,  I apply an api.zoom increment/decrement and a transform localscale and position update together. All seems to work right, map zoom and position update is correct but a glitch happens when api.zoom changes.

Now, after several tests, I noticed (or it seems to be) that transform updates occur immediately after the current Update chain while the real map zoom update, when old tiles are shown at double or half size (depending on zoom offset applied) waiting for the new tiles loading completion, occurs in the following frame.
This cause a glitch because the map scale is reset at the new scale and position while the tiles are still not updated.

I tried a deferred transform update waiting a frame before applying the new transform, and this reduce the glitch but it does not solve the problem.

Could you give me an advice, please?

Thanks in advance.

Re: Smooth-er zoom

Hello.

Try this (attached).
This is the latest version of the custom tileset by Gamar.

P.S. In Online Maps v2.5 it will not work because we have renamed «api» to «map».
So for Online Maps v2.5 this script need a little bit fix.

Post's attachments

Attachment icon CustomTileSetControl.zip 1.73 kb, 28 downloads since 2016-11-18 

Kind Regards,
Infinity Code Team

16 (edited by guruhenry 2016-11-21 19:16:38)

Re: Smooth-er zoom

Hello,
I tried your code in the Tileset scene and it shows the same glitch I mentioned.

When the integer zoom factor changes, the map often flashes (not always).

Basically in my app I use the code of the method ZoomInPoint with the addition of mesh scaling and positioning in a way similar to your code, and the result is the same.

Now suppose we are zooming in. When we reach a scale = 2, we have to change the zoom factor with an offset = +1 and reset the mesh scale to 1.
What I saw is that the mesh scaling is performed at the end of the current update, at the end of the UpdateGestureZoom method, while the map update due to api.zoom changes, where a zoomed tiled is shown waiting for the new tiles set to be loaded, is performed in the next frame. So for an instant, we can see the mesh rescaled to 1 but with the tiles not zoomed nor updated, and this is the glitch/flash I mentioned.

What do you think about it?

Thanks

Re: Smooth-er zoom

Hello.

Try to use:
Online Maps / Troubleshooting / Render In Thread - OFF.

Kind Regards,
Infinity Code Team

Re: Smooth-er zoom

Hello,

Render In Thread option OFF does not solve the problem.

Re: Smooth-er zoom

I just checked the changelog.
This problem is fixed in Online Maps v2.5.0.9.
Please update Online Maps to the latest beta version through the built-in update system.

Kind Regards,
Infinity Code Team

Re: Smooth-er zoom

Hello,

I updated my projects and I perfomed new tests with my app and with the test app compiled using Tileset scene with and
without your CustomTilesetControl code.

The result is the same with previous Online Maps stable version (2.4): the map flashes as I mentioned in my previous posts.

For this specific project I work with Unity 4.7.0f1 and the target platform is Android.

21 (edited by guruhenry 2016-11-22 11:00:08)

Re: Smooth-er zoom

Hello,

I performed a new test with Unity editor, Tileset scene, using the game preview. Zooming in with the mouse wheel you can occasionally see the flash, and it occurs prior the real tiles update.

So it is really simple to reproduce and I believe it's the same problem.

Re: Smooth-er zoom

Hello.

We found the problem and fixed it for Render in Thread - OFF.
But in fact, it created a few new problems.
I think there is only one right solution - is make a really true float zoom, without playing with transform.
We will try to implement it, but I do not know how much time it will take.

Kind Regards,
Infinity Code Team

23 (edited by guruhenry 2016-11-23 17:57:52)

Re: Smooth-er zoom

Hello Alex,

the flash impacts the look and feel, and with this unresolved issue I can't add the map feature to the app I'm developing with my team.

The quality of user interactions support and the UI/map view quality and response are key features for us to offer in apps that use maps.

Your plugin has really good features, but this is a serious problem and it is unexpected for us.

Feel free to ask us tests if you think it could help you to find a solution.

Re: Smooth-er zoom

As I said, the best solution is to make a true float zoom.
But it takes some time.

Within 1-2 days we will release the next beta version with fixed flash (for Render in Thread - OFF).
Try to use it with Render in Thread - OFF.
If it will suits your needs, it's good.
If not, then unfortunately you need to wait for true float zoom feature.

Kind Regards,
Infinity Code Team

Re: Smooth-er zoom

Hello Alex,

Ok, I will wait for the new beta!

Thanks

Enrico