Touches update more frequently per draw cycle

I had occasion to compare code between two versions of Codea (one iPad is stuck on iOS 10.X so runs Codea 2.8(161), the other is up-to-date with the published version of Codea). In doing so, I noticed something odd happening with the touches.

Here’s the illustrative code:

function setup()
  parameter.watch("TouchesPerDraw")
  TouchesPerDraw = 0
  nt = 0
end

function draw()
  TouchesPerDraw = nt
  nt = 0
end

function touched(t)
  nt = nt + 1
end

It counts how many times the touched function is called per draw cycle. Run it with a single finger/stylus touching the screen and moving around. With the latest Codea, I got up to 3 touches per cycle. With the older version, I never got above 1.

My main question is: is this intentional and will it stay?

I have no complaint about this, I presume that more information is a good thing. However, it is useful to know about it because my touch handling code didn’t know about this extra and so, in particular, its use of the deltaX and deltaY was off: I’d assumed that deltaX and deltaY were relative to the last draw cycle rather than the last time touch information was gathered.

So if it is staying, some of my code needs updating and I’d just like reassuring that it won’t revert before making the change.

@LoopSpace When I run your code on my iPad Air 3 with Codea version 192, I never get above 1 for your count.

Here’s something I mentioned a long time ago about touches. The touches are buffered and not dependent on what draw is doing. In the draw function below, I have a very large for loop to really slow the draw cycle down. I increment a count in draw and also in touches. Even though the draw cycle is in a large for loop, tapping the screen will eventually be counted and the count will show when the draw function finishes each cycle. It will show 0 for the first loop, then when the draw cycle finishes the first loop, the touches will be counted and the count will show on the 2nd draw cycle. If the loop is taking too long, remove a 0 from the for limit.

function setup()
    cnt=0
    fill(255)
    loop=0
end

function draw()
    background(0)
    loop=loop+1
    text(loop,WIDTH/2,HEIGHT/2-100)
    for z=1,1000000000 do        
    end
    text(cnt,WIDTH/2,HEIGHT/2)
end

function touched(t)
    if t.state==BEGAN then
        cnt=cnt+1
    end
end

@LoopSpace this is intentional, modern iPads are able to process touches at up to 240hz. They can actually process touches at an even faster perceived rate by using touch prediction, which decreases touch latency even further by having the OS predict the future touch position in advance (and then subsequently correct it)

I haven’t exposed iOS touch prediction features (they are kind of hairy because you have to store predicted touch IDs in order to go back an “correct” them when the truth comes in), but the touched callback is intentionally decoupled from the draw loop for this reason

@dave1707 I was getting the high count on an iPad Pro. Thanks for your code, that helped figure out a few more details.

@Simeon Makes sense, and as I said I’m not against this, I was just unaware of it. The documentation could do with updating, in particular the description of deltaPos implies that it is the change since the last draw (it was this that led me to track this down, btw).

Also, one feature request. Using @dave1707 's code, I see that the touches are buffered and the touched function is called only after the draw function is done. This makes it impossible from within the program to get accurate timings of the touches. Could you add a timestamp to the touch userdata which records when the touch event actually occurred, possibly relative to the start of the program? I have some code that uses how fast the touch is travelling and at the moment I can’t use it with this more accurate touch data.

@LoopSpace I’ll add timestamps to touches on the next release, good idea

@LoopSpace Heres something else for you to think about. There seems to be 3 buffers that are used for the display. Each time you tap the screen, I increment count and set a flag to display the count at random places on the screen. You’ll see that there are 3 different values that show and that they don’t update in sequence.

displayMode(FULLSCREEN)

function setup()
    count=0
    fill(255)
end

function draw()
    if rtn then
        return      
    end
    rtn=true
    background(0)
    text(count,math.random(50,WIDTH-50),math.random(50,HEIGHT-50))
end

function touched(t)
    if t.state==BEGAN then
        count=count+1 
        rtn=false               
    end    
end