Multitouch table with photos

I am working on a multitouch table that a bunch of photos are layed out on. Users can then come up to the table, move the photos around, scale and rotate them. Everything is working good if one person is using the table. The issue I have is if multiple people are using the table. I was trying to go through and set up an int so anytime someone touches a game object that game object keeps track of how many fingers are touching it. This count is adding 1 on the OnFingerDown method. The issue I have is how to find out if someone removes there finger if that finger was touching the game object already or another game object. You can see OnFingerUp i tried to delete one from the fingercount but it is accounting for anyone’s finger anywhere on the table lifting and not if it was associated to that specific game object. The code I started with was from LeanFinger.

using UnityEngine;

// This script will rotate and scale the GameObject based on finger gestures
public class SimpleRotateScale : MonoBehaviour
{
    public LayerMask LayerMask = UnityEngine.Physics.DefaultRaycastLayers;

    private Lean.LeanFinger draggingFinger;

    public GameObject LocalObject;
    public GameObject ClickObject;
    public int fingerCount = 0;




    protected virtual void OnEnable()
    {
        // Hook into the OnFingerDown event
        Lean.LeanTouch.OnFingerDown += OnFingerDown;

        // Hook into the OnFingerUp event
        Lean.LeanTouch.OnFingerUp += OnFingerUp;

    }

    protected virtual void OnDisable()
    {
        // Unhook the OnFingerDown event
        Lean.LeanTouch.OnFingerDown -= OnFingerDown;

        // Unhook the OnFingerUp event
        Lean.LeanTouch.OnFingerUp -= OnFingerUp;
    }
    protected virtual void LateUpdate()
    {
        LocalObject = gameObject;

        if (draggingFinger != null && LocalObject == ClickObject && fingerCount>2) {
            // This will rotate the current transform based on a multi finger twist gesture
    //        Lean.LeanTouch.RotateObject (transform, Lean.LeanTouch.TwistDegrees);
            RotateObjectLocal(transform, Lean.LeanTouch.TwistDegrees);
            // This will scale the current transform based on a multi finger pinch gesture
            ScaleObjectLocal (transform, Lean.LeanTouch.PinchScale);
        }
    }


    public static void RotateObjectLocal(Transform transform, float deltaRotation, Camera camera = null)
    {
        if (transform != null && deltaRotation != 0.0f)
        {
            transform.rotation = RotateObjectLocalA(transform.rotation, deltaRotation, camera);
        }
    }

    public static Quaternion RotateObjectLocalA(Quaternion worldRotation, float deltaRotation, Camera camera = null)
    {
        if (deltaRotation != 0.0f)
        {
            if (camera == null) camera = Camera.main;

            if (camera != null)
            {
                worldRotation = Quaternion.AngleAxis(deltaRotation, camera.transform.forward) * worldRotation;
            }
        }

        return worldRotation;
    }


    public static void ScaleObjectLocal(Transform transform, float scale)
    {
        if (transform != null && scale != 1.0f)
        {
            //            transform.localScale *= scale;
            Vector3 tempScale;
            tempScale = transform.localScale;
            if (transform.localScale.x * scale < 17  && transform.localScale.x * scale >3) {
                tempScale.x = transform.localScale.x * scale;
                tempScale.y = transform.localScale.y * scale;
                transform.localScale = tempScale;
            }
        }
    }
       


    public void OnFingerDown(Lean.LeanFinger finger)
    {
        // Raycast information
        var ray = finger.GetRay ();
        var hit = default(RaycastHit);

        // Was this finger pressed down on a collider?
        if (Physics.Raycast (ray, out hit, float.PositiveInfinity, LayerMask) == true) {
            // Was that collider this one?
            ClickObject = hit.collider.gameObject;

            if (hit.collider.gameObject == gameObject) {
                // Set the current finger to this one
                draggingFinger = finger;
                fingerCount += 1;


            }
        }
    }



    public void OnFingerUp(Lean.LeanFinger finger)

    {
    //    fingerCount -= 1;

        // Was the current finger lifted from the screen?
        if (finger == draggingFinger)
        {
            // Unset the current finger
            draggingFinger = null;
        }
    }
}

Input.GetTouch can give you information about a specific touch Index. There may be an equivalent in “LeanTouch” but I’m not familiar with that API. That index will not change until you remove the touch. You can use that index to associate specific touches with gameobjects, so that once a touch is registered to a gameObject, that touch wont affect anything else.

The two finger interactions must have both touches be registered to the same object somehow. Either by touching a ui widget that appears on the first touch, or by having both fingers touch the same object.

The Touch i get can with my above code its. When the touch is removed I dont know how to say which touch was removed. Is there no easy way to do it like I did with he OnFingerDown?

If your LeanTouch “LeanFinger” has an index within it, you can use that to associate with objects.

So instead of just keeping a count, perhaps keep a dictionary of Finger index to GameObject. So you can know what objects are being affected by what touches.

Using Unity’s Input class:

You can check the status of each touch using Input.GetTouch(). It will return a Touch struct which has a “phase” property.

if(Input.touchCount > 0) {
    Touch firstTouch = Input.GetTouch(0);
    switch(firstTouch.phase) {
        case TouchPhase.Began:
            // first touch just started
            break;
        case TouchPhase.Moved:
            // first touch moved
            // how much: firstTouch.deltaPosition
            // where it is now: firstTouch.position
            break;
        case TouchPhase.Stationary:
            // first touch has not moved at all
            break;
        case TouchPhase.Canceled:
        case TouchPhase.Ended:
            // on first touch ended
            break;
    }
}

If you wanted to, you could create your own events which return the index of the touch for each phase.

You can get all the touches by using “Touch[ ] myTouches = Input.touches;” and then looping through them.

https://docs.unity3d.com/Manual/MobileInput.html

So I would put this code in where it checks

if(hit.collider.gameObject== gameObject){
}

so it would only keep track of the touches on that object itself/

Yes, ideally you would do the RayCast on FingerDown, if the hit gameObject is this one, store some sort of Finger ID, and then OnFingerUp, check if that lifted finger is the one controlling this gameObject, and react accordingly.

ooof I will give it a shot. Sorry my programming is not that strong. Im more of a 3d modeler.

Don’t worry, it should be fairly straightforward. Check out what is available to you inside the “finger” variable that gets passed into OnFingerDown. If theres a finger index, or finger ID, or some unique identifier for that finger, then you can create a variable to hold that value as the “active touch” or something of the sort. Then check if the OnFingerUp “finger” parameter has that same value.

You just have to be sure and always associate the gameObject with the touch somehow. Otherwise you won’t know which touch is meant for which object.

So I have been trying implement this and was wondering why the following does not take my int down at all… I can see it adding up but when I life up it does not delete.

    public void OnFingerDown(Lean.LeanFinger finger)
    {
        // Raycast information
        var ray = finger.GetRay ();
        var hit = default(RaycastHit);

        // Was this finger pressed down on a collider?
        if (Physics.Raycast (ray, out hit, float.PositiveInfinity, LayerMask) == true) {
            // Was that collider this one?
            ClickObject = hit.collider.gameObject;

            if (hit.collider.gameObject == gameObject) {
                // Set the current finger to this one
                draggingFinger = finger;
                //        fingerCount += 1;

                if (Input.touchCount > 0) {
                    Touch firstTouch = Input.GetTouch (0);
                    switch (firstTouch.phase) {
                    case TouchPhase.Began:
                        fingerCount += 1;

                        break;

                    case TouchPhase.Ended:
                        fingerCount -= 1;

                        break;
                    }
                }






            }
        }
    }



    public void OnFingerUp(Lean.LeanFinger finger)

    {
    //    fingerCount -= 1;

        // Was the current finger lifted from the screen?
        if (finger == draggingFinger)
        {
            // Unset the current finger
            draggingFinger = null;
        }
    }
}

It’s probably because the two “finger” parameters are not the same, because they contain different sets of data. You should see if “finger” has something like an ID or index to identify it. Type “finger” follow by a period and see what is available to you.

You should either use LeanTouch or Unity’s Input, mixing them doesn’t seem like the best thing to do. I’m sure LeanTouch has some way to identify which finger was put down, and which finger was lifted.

there is an .index but when i run it with debug.log it is always 0

not sure there is an index. When I talked to the developer of leantouch he said to do it by calculating the distance between the fingers but how my program is set distance will not work

ok sorry so when i compile it and run it the .index does change. But not to sure what to do with that.