Touch and gestures

This is the working-out of my ponderings on touches in Simeon’s said (there or otherwhere) that they’ll expose Apple’s gesture API, but given that the updates to Codea are taking a while to get Apple’s approval then I’m not holding my breath on this one. So I’ve written a little bit of code to try to make it easier to deal with touches.

The idea is to work with all “active” touches in one go. We further divide them according to what object has “claimed” each touch. Then the resulting groups of touches are analysed to try to detect “gestures”. The “gesture” is then passed to the object that “claimed” the touches so that it can decide what to do with that information.

It’s possibly easier to explain by looking at the demo program than the class itself:

function setup()
    touches = Touches()
    reporter = TouchReporter()

function draw()

function touched(touch)

TouchReporter = class()

function TouchReporter:init()

function TouchReporter:isTouchedBy(t)
    return true

function TouchReporter:processTouches(g)
    local s = g.num .. " "
    if g.updated then
        if g.type.tap then
            s = s .. "tap, "
            s = s .. "touch, "
        if not g.type.long then
            s = s .. "not "
        s = s .. "long, "
        if not g.type.short then
            s = s .. "not "
        s = s .. "short, "
        if g.num > 1 then
            if g.type.pinch then
                s = s .. "pinch"
            elseif not g.type.tap then
                s = s .. "swipe"

We initialise an instance of the Touches class, then an instance of some random class that will respond to touches. This is registered as a “handler” of touches. This means that when a touch comes in, this object will be asked “Woz it you wot woz touched?”. The call to touches:addTouch() gathers each touch and touches:draw() does the heavy-duty analysis.

The TouchReporter has to have (at least) two methods: something that says whether or not it was touched, :isTouchedBy(touch), and something that handles the resulting morass of touches, :processTouches(g). The first takes a touch as its argument and returns true if it thinks that it was the object that was touched. In this case, it always returns true. The second takes a Gesture as its argument. A Gesture is a collection of active touches (only they’re super-touches) that has been analysed in some way. The answers to the questions that the analysis does can be deduced by looking at what tests get done, but I’ll explain that in a moment. This can also call a few methods on the Gesture, such as :noted() which basically says “I’ve looked at all of this, mark it as such so that I can test whether the next time round it is new data or just the old stuff reworked.”. It can also insert an “interrupt” which says, “I want the next touch no matter what it is.”. This can be useful for when a touch starts something which should be stopped at the next touch, no matter where that touch actually takes place.

The analysis of the Gesture works a bit like the following. We work out:

  1. How many active touches does it contain? (These can be “ENDED” touches if we’ve been told to remember them.)
  2. Have any of the touches moved? If not, they’re taps.
  3. Was there a significant pause before they all moved? If so, they’re long.
  4. Was the actual movement phase quite quick? If so, they’re short.
  5. If a multi-touch, did they move “as one” or independently? (Technically, we compare the individual movements with the movement of the barycentre.) If “as one” then it’s a swipe, otherwise it’s a “pinch”.

Note that a touch can be both “short” and “long”. A “flick” would be an example.

The class code can be downloaded from (note that the Touch.lua from the Cube is old; next plan is to use this to make that more interactive.)