Skip to content

Examples

Valentin Simonov edited this page Aug 1, 2017 · 14 revisions

TouchScript comes with many example scenes, each of them demonstrates how to use various framework features.

Camera

This example demonstrates how to use

  • ScreenTransformGesture,
  • Pointer limits,
  • FullscreenLayer.

Interaction

  • Drag with one finger to move the camera,
  • Drag with 2+ fingers to rotate the camera,
  • Pinch to zoom,
  • Rotate with 2 fingers to rotate around Z axis.

Explanation

/Scene GameObject has the main logic and 3 TouchScript components:

  1. FullscreenLayer — layer which just gets all pointers without doing any raycasts into the scene and sets their target to the GameObject it is attached to, in this case /Scene. A FullscreenLayer is usually put in the bottom of layers hierarchy to catch all remaining pointers, but in this example it is the only layer because we are not interested in "touching" any objects.
  2. ScreenTransformGesture which has Transform Type set to Translation only and Limit Pointers to 1. This gesture recognizes one-pointer pan movements only.
  3. Another ScreenTransformGesture which has Transform Type to Everything and Limit Pointers to >=2. This gesture recognizes all two-pointer transforms.
  4. CameraController subscribes to ScreenTransformGestures and controls camera movement like so:
private void OnEnable()
{
    TwoFingerMoveGesture.Transformed += twoFingerTransformHandler;
    ManipulationGesture.Transformed += manipulationTransformedHandler;
}

private void OnDisable()
{
    TwoFingerMoveGesture.Transformed -= twoFingerTransformHandler;
    ManipulationGesture.Transformed -= manipulationTransformedHandler;
}

private void manipulationTransformedHandler(object sender, System.EventArgs e)
{
    var rotation = Quaternion.Euler(ManipulationGesture.DeltaPosition.y/Screen.height*RotationSpeed,
        -ManipulationGesture.DeltaPosition.x/Screen.width*RotationSpeed,
        ManipulationGesture.DeltaRotation);
    pivot.localRotation *= rotation;
    cam.transform.localPosition += Vector3.forward*(ManipulationGesture.DeltaScale - 1f)*ZoomSpeed;
}

private void twoFingerTransformHandler(object sender, System.EventArgs e)
{
    pivot.localPosition += pivot.rotation*TwoFingerMoveGesture.DeltaPosition*PanSpeed;
}

Checkers

This example demonstrates how to use

  • TransformGesture,
  • PinnedTransformGesture,
  • Transformer,
  • OverHelper,
  • StandardLayer,
  • GestureManager.Instance.GlobalGestureDelegate.

Interaction

  • Drag a figure to move it,
  • Drag the board to rotate it,
  • Hold to disable gestures on all but one piece.

Explanation

/Scene/Camera GameObject has a StandardLayer with all options disabled but Hit 3D Objects in Hit test options property to raycast only for 3D objects in the scene, since this scene doesn't have any 2D or UI objects.

/Scenes/Board GameObject has two components attached:

  1. PinnedTransformGesture which has Transform Type set to Rotation and Projection to XZ Plane which is the ground plane. It means that this gesture will project screen pointers onto this plane and calculate all transformations within this plane.
  2. Board which listens to PinnedTransformGesture's events and rotates the board like so:
private void OnEnable()
{
    gesture = GetComponent<PinnedTransformGesture>();
    gesture.Transformed += transformedHandler;
}

private void OnDisable()
{
    gesture.Transformed -= transformedHandler;
}

private void transformedHandler(object sender, System.EventArgs e)
{
    transform.localRotation *= Quaternion.AngleAxis(gesture.DeltaRotation, gesture.RotationAxis);
}

/Scene/Board/Container/CheckerDark GameObjects have the following components attached:

  1. TransformGesture which has Transform Type set to Translation and Projection to XZ Plane.
  2. Transformer which listens to TransformGesture's events and moves the object.
  3. OverHelper which dispatches an event when a pointer is over the object.
  4. Highlight which listens to OverHelper's events and changes the object color.
  5. Checker which listens to TransformGesture's events and disables or enables Rigidbody on this object, while actual movement is done by Transformer component.

/scene GameObject has Exclusive component attached to it which implements IGestureDelegate interface and assigns itself to GestureManager.Instance.GlobalGestureDelegate. When a user presses Space this component prevents all gestures starting except the ones on Target GameObject using this code:

public bool ShouldBegin(Gesture gesture)
{
    if (exclusive) return gesture == Target;
    return true;
}

public bool ShouldReceivePointer(Gesture gesture, Pointer pointer)
{
    if (exclusive) return gesture == Target;
    return true;
}

Colors

This example demonstrates how to use

  • 2D objects,
  • Gesture.Cancel() to cancel a gesture and return its pointers to the system.

Interaction

  • Drag circles around. When overlapped they will spawn another circle of combined volume,
  • Use two fingers to scale circles.

Explanation

/Scene/Camera GameObject has a StandardLayer with all options disabled but Hit 2D Objects in Hit test options property to raycast only for 2D objects in the scene, since this scene doesn't have any 3D or UI objects.

Circle prefab has the following components attached:

  1. TransformGesture with Transform Type set to Everything so a user can move, scale and rotate circles (though rotating circles doesn't really make much sense).
  2. Transformer which listens to TransformGesture's events.
  3. Circle which handles circles intersection in OnTriggerEnter2D and uses this code to cancel currently active TransformGesture:
GetComponent<TransformGesture>().Cancel(true, true);

(true, true) means that the pointers should be returned to the system, like they were just pressed. At this point cancelled pointers are caught by the new (bigger) circle and its TransformGesture so the user can continue moving and resizing the new circle.

Cube

This example demonstrates how to use

  • TouchLayer.Delegate,
  • Implementing a custom Input Source.

Interaction

  • Drag, scale, rotate the cat picture.

Notice how you are touching the Cube but are able to move the image far away in the scene.

Explanation

This example shows how extensible TouchScript is. There's a cube in the scene which has a RenderTexture from an offscreen camera assigned to its material. But you can still move and resize this image with your fingers.

/Scene/Scene Camera/Image GameObject has TransformGesture and Transformer components to move it around. This is the image you see on the Cube.

/Scene/Cube GameObject has the following components attached:

  1. MetaGesture which catches pointers on the object and dispatches events.
  2. RedirectInput which listens to MetaGesture's events. But it also inherits from InputSource which means that it can inject pointers into the system. It does this like so:
private void pointerPressedHandler(object sender, MetaGestureEventArgs metaGestureEventArgs)
{
    var pointer = metaGestureEventArgs.Pointer;
    if (pointer.InputSource == (IInputSource)this) return;

If this pointer is generated by this script, stop processing it.

    var newPointer = PointerFactory.Create(pointer.Type, this);
    newPointer.CopyFrom(pointer);
    newPointer.Position = processCoords(pointer.GetPressData().RaycastHit.textureCoord);
    newPointer.Flags = pointer.Flags | Pointer.FLAG_ARTIFICIAL | Pointer.FLAG_INTERNAL;
    addPointer(newPointer);
    pressPointer(newPointer);
    map.Add(pointer.Id, newPointer);
}

Next, the code creates a copy pointer, adds FLAG_INTERNAL to hide it from Cursor Visualizer, then adds and presses it. At this point the touch is injected into the system.

/Scene GameObject has the following components attached:

  1. LayerDelegate which implements ILayerDelegate and is set to TouchLayer.Delegate of all layers in the scene by Init script.
  2. Init which sets up LayerDelegate.

This is the code inside LayerDelegate:

public RedirectInput Source;
public TouchLayer RenderTextureLayer;

public bool ShouldReceivePointer(TouchLayer layer, IPointer pointer)
{
    if (layer == RenderTextureLayer)
        return pointer.InputSource == (IInputSource)Source;
    return pointer.InputSource != (IInputSource)Source;
}

Which basically says: "The layer on RenderTexture Camera should receive fake pointers, while others don't".

Multiuser

This example demonstrates how to use

  • Multiple layers,
  • TapGesture.

Interaction

  • Drag halves of the screen,
  • Drag checkers,
  • Drag boards to rotate them,
  • Tap Unity logos.

Explanation

The scene contains 5 layers. Check TouchManager GameObject with TouchManager script attached which has a list of layers. The layers must be sorted in the specific order: 2D, Right and Left 3D Camera, Right and Left Fullscreen layers. This is because layers are iterated from top to bottom when trying to determine what object a pointer hits.

/Scene/2D/Unity_Logo GameObjects have TapGesture on them which are used by Logo component to change color on tap.

/Scene/Left/Board and /Scene/Right/Board are the same as in Checkers example.

Photos

This example demonstrates how to use

  • Working with UI controls,
  • PressGesture,
  • TransformGesture and Transformer.

Interaction

  • Move, scale and rotate photos,
  • Tap ADD button to add photos,
  • Tap colored buttons to change color.

Explanation

/Scene/World Space Plane/World Space Canvas/Field/Image # GameObjects have the following components attached:

  1. TransformGesture and Transformer to move/scale/rotate cat images.
  2. PressGesture which is used to bring the pressed image up.

/Scene/World Space Plane/World Space Canvas/Field/Image #/Close is just a UI Button which TouchScript sends pointer input.

/Scene/ScreenSpace Canvas/Panel/Button is just a set of UI Buttons which interact with TouchScript. No special components or code is required.

Portal

This example demonstrates how to use

  • Gesture.Cancel(),
  • TransformGesture and Transformer,
  • LayerManager.SetExclusive().

Interaction

  • Press a Unity logo to spawn a planet,
  • Drag a planet into portal.

Explanation

This example demonstrates how to do the following:

  1. Cancel a gesture on some condition,
  2. "Give" pointers from one object to another.

/Game Canvas/Spawner# GameObjects have the following components attached:

  1. PressGesture which is used by Spawner.
  2. Spawner which creates a planet when logo is pressed and "gives" it pointer from PressGesture by doing the following:
var target = Instantiate(Prefab, Position.parent);
target.position = Position.position;
LayerManager.Instance.SetExclusive(target);
press.Cancel(true, true);
LayerManager.Instance.ClearExclusive();

This code creates an instance of Prefab and sets it exclusive so no other object can receive pointers. After that the code cancels the gesture and returns its pointers to the system which immediately go our object.

/Scene/Camera/Stuff/Vortex has a script attached which calls planet.Fall(); on every planet which comes close. This method basically does the following:

var gesture = GetComponent<TransformGesture>();
if (gesture != null) gesture.Cancel();

It cancels the gesture but doesn't cancel its pointers, so the planes just fall into the vortex if the user doesn't catch them quickly.

RawInput

This example demonstrates how to use

  • Pointer input.

Interaction

  • Touch the screen.

Explanation

This example shows how to use raw pointer input with no gesture logic. /Scene/Camera has Spawner script attached which spawns prefab instances using this code:

private void OnEnable()
{
    if (TouchManager.Instance != null)
        TouchManager.Instance.PointersPressed += pointersPressedHandler;
}

private void OnDisable()
{
    if (TouchManager.Instance != null)
        TouchManager.Instance.PointersPressed -= pointersPressedHandler;
}

private void pointersPressedHandler(object sender, PointerEventArgs e)
{
    foreach (var pointer in e.Pointers)
        spawnPrefabAt(pointer.Position);
}

Taps

This example demonstrates how to use

  • TapGesture,
  • LongPressGesture.

Interaction

  • Double tap the table to spawn a new crate,
  • Tap a crate to kick it,
  • Hold a crate to blow it up.

Explanation

/Scene/Container/Cube GameObjects have the following components attached:

  1. LongPressGesture which is used by Break script to blow up the cube,
  2. PressGesture which is used by Break script to start the color tween,
  3. TapGesture which is used by Kick script to push the cube,
  4. Kick which kicks the cube on tap,
  5. Break which breaks the cube into 8 small cubes. It shows how to use StateChanged event:
longPressGesture.StateChanged += longPressedHandler;

private void longPressedHandler(object sender, GestureStateChangeEventArgs e)
{
    if (e.State == Gesture.GestureState.Recognized)
    {
        ...
    }
    else if (e.State == Gesture.GestureState.Failed)
    {
        stopGrowing();
    }
}

We use StateChanged event here instead of simpler LongPressed because we need to handle GestureState.Failed.

/Scene/table_and_chair GameObject has a TapGesture component attached with Number of Taps Required set to Two and Limit Time to 1 sec. This means that we want a double-tab with 1 sec max interval between taps. Spawn component uses the TapGesture to spawn new cubes.

Pull

This example shows how to write and use custom gestures.
It is available as a separate tutorial.