# How to make a gui button follow a path after a touch?

I would like a button in my gui menu to follow a specific path if we selected it, I am wondering how I could do it: if we touch the button, then it can only move on the specific path, it is an arc such as this path : Would you know how to achieve this? I am using Unity, but I think the theory should be the same for other software/language ?

__

EDIT:

here is the code for the bezier curve in unity : Where should I put the script?

using UnityEngine;
using System.Collections;

public class DrawBezierHandle extends Editor {

public Transform startT;
public Transform endT;

function Start(){
startT = GameObject.Find("start").GetComponent("Transform") as Transform;
endT = GameObject.Find("end").GetComponent("Transform") as Transform;
}

function OnSceneGUI() {

var width : float = HandleUtility.GetHandleSize(Vector3.zero) * 0.1;
Handles.DrawBezier(startT.position,
endT.position,
startT.position * 5 * Vector.up,
endT.position * 5 * Vector.up,
Color.red,
null,
width);
}
}


Well, first of all you need a way to descrive such path.

I would use some spline curves like Bezier curves or Hermite Splines to describe the path, and let the button follow that path once pressed. Unfortunately these curves are not available as is, you need to implement them. If you are interested here you can find 2 nice Herman Tulleken's articles(fundamentals and some algorithms), that contains a basic bezier spline implementation for Unity3D too:

If you want to go another way you can define some points the button should pass through and interpolate position (and eventually orientation) of the object while updating its position. You can interpolate Vector3 position using Lerp or Slerp methods.

EDIT

If you attach your script you should be able to see the Bezier curve drawn. (Pay attention that your control and tangent points are coincident, so it will be always a straight line). Unity just let you draw such parametric curves, you have to evaluate it on your own.

The article I linked to you gives you the code. For example:

Vector3 CalculateBezierPoint(float t,
Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
{
float u = 1 – t;
float tt = t*t;
float uu = u*u;
float uuu = uu * u;
float ttt = tt * t;

Vector3 p = uuu * p0; //first term
p += 3 * uu * t * p1; //second term
p += 3 * u * tt * p2; //third term
p += ttt * p3; //fourth term

return p;
}


You can move a GameObject along the curve you can varying t parameter inside your Update function. For example:

float time = 0f;
void Update()
{

if (time < 1f)
{
time += Time.deltaTime;

transform .position = CalculateBezierPoint(time,startP, startT, endT, endP );

}
}


how could I clamp the coordinates so that the button only slide on the curve, exactly where the touch is (without any delay)? I thought about creating a list of 50 Vector2, and compare the x/y with the touch pos, but it might be too heavy... Would you have any idea about that?

Well, the curve parameter domain is [0,1]. You could for example start recording a gesture when a touch is detected near the start control point. Supposing you gesture length is [0,N], what you can to is to map the gesture interval domain to the curve one.

• thank you very much Heisenbug, I am trying the first way, I am wondering how I could find the right "controller" coordinates for the bezier curve, the one that make the curve (so p1 and p2, in a "p0,p1,p2,p3" scheme). I have gimp or Flash, would you know how to find them easily? Thanks again – Paul Mar 6 '13 at 9:24
• Well, they are just points in a 2d/3d space. So if you can obtain the coordinates from tools such gimp use them. Btw, with Unity you can draw such curves using Handles.DrawBezier method: docs.unity3d.com/Documentation/ScriptReference/…. I think it's better to try directly inside unity since you can visualize and interactively modify them. – Heisenbug Mar 6 '13 at 9:41
• Thanks, I am just wondering: how could I clamp the coordinates so that the button only slide on the curve, exactly where the touch is (without any delay)? I thought about creating a list of 50 Vector2, and compare the x/y with the touch pos, but it might be too heavy... Would you have any idea about that? Thanks again – Paul Mar 7 '13 at 1:10
• Thank you very much, for edit#1: yes I found out the code in one of your links, that let me create the curve points depending on "segments", Thanks! About the last edit, do you mean proportionally compare the gesture with the curve? Let's say I move right, the button has to follow the curve in the Y-axis. How could I find the right "y" coordinate for such x, without a loop through my list of Vector2? – Paul Mar 7 '13 at 10:09
• No. I mean something like that: suppose you travel a distance DIST with your finger in a range [0,MAX_FINGER_DIST], then linear map this value to parameter t (DIST / MAX_FINGER_DIST) so that the dist is in the range [0,1] too. use the normalized value to evaluate the curve. That's just an example, if you want something more complicated (es. using 2 dimensions) I think you have to figure it out by yourself. – Heisenbug Mar 7 '13 at 10:14

Just for what concern GUI you can use UIToolkit. It's free and opensource and already have the methods that you need for doing simple gui movement (you can call the delegate with the Action onTouchUpInside). There are also a demo scene that reproduce what you want to do, and with this library you can make all your GUI's element with a single draw call (pretty useful if you play to make a game runnable also in mobile).

I know that there are also excellent substitutes of UIToolkit (search in Assets Store for more info), but i've experience just with that for now :)

• Thanks, yes I am using it, but with a curve, I did not find any function in UIToolkit (UISlider, or such) – Paul Mar 6 '13 at 21:59
• First of all, the solution of Heisenbug is surely correct but it take surely a bit of time for the implementation. Another possible solution could be (it depends by what you plaining to do) using a simple Lerp function and give more points for following the curve that you want. For doing this you will not need any other implementation, but it will need some attention in giving that points. – Max Mar 7 '13 at 9:03
• Thanks, I have just found out that UIContinuousButton contains a onTouchIsDown "event" linked with the onTouchMoved( Touch touch, Vector2 touchPos ) function (github.com/prime31/UIToolkit/blob/master/Assets/Plugins/…), would you know how to use the "touchPos" parameter? It seems that we have to use the "event", but the second parameter of this function seems to be the one I need, to make the image follow the touch position of the finger. Any idea? – Paul Mar 7 '13 at 9:54
• Wait, im not totally sure to have understand what you want to do. The curve that your gui's element must follow is static or it depends from the user input? If it is static you can give a bunch of point and make the gui following it (must be pretty clear with the script exemple in UItoolkit). If you need to track the user's input you should use an Update method where you track the Touch.position and than moving the gui's element according to it. – Max Mar 7 '13 at 13:55