-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathtouchGestures.livecodescript
463 lines (385 loc) · 16.6 KB
/
touchGestures.livecodescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
script "community.ferruslogic.touchGestures.2.0.0"
/*
This library is in the public domain.
There are no restrictions whatsoever.
Original Author - Ferruslogic Ltd.
*/
on extensionInitialize
if the target is not me then
pass extensionInitialize
end if
insert the script of me into front
if the environment contains "development" then
set the _ideoverride of me to true
end if
end extensionInitialize
on extensionFinalize
if the target is not me then
pass extensionFinalize
end if
remove the script of me from front
end extensionFinalize
global gTouchs
local sChangerPinch, sAddressOfMovePinch, sDoubleTouchIDs, sAngleOfPinch
local sIsPinch = 0, sPinchId = 0
constant kDoubleClickInterval = 250
local sTouchDoubleDown, sLastTouchDown
local sTouchDoubleUp, sLastTouchUp
local tNumTouchs
local sPendingTouchStillDown, sStatTouchStillDown
constant kTouchStillDownTimeSec = 1
/////////////////////////////////////////////////////////////
//////****************** The magic ********************//////
/////////////////////////////////////////////////////////////
local sLongId
on touchStart pTouchID
local tLoc, tLocX, tLocY
put the mouseLoc into tLoc
put the millisec into gTouchs[pTouchID]["StartTime"]
put the long id of target into sLongId[pTouchID]
if the num of lines of keys of gTouchs is 1 then
/** TouchDoubleDown **/
add 1 to sTouchDoubleDown
if sTouchDoubleDown is 1 then
put gTouchs[pTouchID]["StartTime"] into sLastTouchDown["StartTime"]
else if (gTouchs[pTouchID]["StartTime"] - sLastTouchDown["StartTime"]) <= kDoubleClickInterval then
put 0 into sTouchDoubleDown
put item 1 of tLoc into tLocX
put item 2 of tLoc into tLocY
if there is sLongId[pTouchID] and "TouchDoubleDown" is not among the lines of the pendingMessages then
dispatch "TouchDoubleDown" to sLongId[pTouchID] with pTouchID
end if
pass touchStart
else
put gTouchs[pTouchID]["StartTime"] into sLastTouchDown["StartTime"]
end if
if sPendingTouchStillDown is a number then cancel sPendingTouchStillDown
put tLoc into sStatTouchStillDown
send "_DispatchTouchDoubleDown pTouchID" to the long id of me in kTouchStillDownTimeSec sec
put the result into sPendingTouchStillDown
end if
pass touchStart
end touchStart
on touchMove pTouchID, pTouchX, pTouchY
put "touchMove " & the keys of gTouchs into fld 2
/** Saving touch position **/
if gTouchs[pTouchID]["StartLoc"] is empty then
put pTouchX, pTouchY into gTouchs[pTouchID]["StartLoc"]
else
put pTouchX, pTouchY into gTouchs[pTouchID]["CurrentLoc"]
/** Changer in X **/
put item 1 of gTouchs[pTouchID]["StartLoc"] - pTouchX into gTouchs[pTouchID]["ChangedInX"]
/** Changer in Y **/
put item 2 of gTouchs[pTouchID]["StartLoc"] - pTouchY into gTouchs[pTouchID]["ChangedInY"]
/** Distance **/
put round(sqrt((gTouchs[pTouchID]["ChangedInX"]^2) + (gTouchs[pTouchID]["ChangedInY"]^2))) into gTouchs[pTouchID]["Changed"]
/** Angles and Rotation **/
put _AngleTouch(pTouchID) into gTouchs[pTouchID]["Angle"]
/** For the address **/
local tOldAddress = ""
if gTouchs[pTouchID]["AddressOfTouch"] is not empty then put gTouchs[pTouchID]["AddressOfTouch"] into tOldAddress
if gTouchs[pTouchID]["PrevLoc"] is a point then
put _AddressTouch(gTouchs[pTouchID]["PrevLoc"],gTouchs[pTouchID]["CurrentLoc"]) into gTouchs[pTouchID]["AddressOfTouch"]
else
put _AddressTouch(gTouchs[pTouchID]["StartLoc"],gTouchs[pTouchID]["CurrentLoc"]) into gTouchs[pTouchID]["AddressOfTouch"]
end if
if gTouchs[pTouchID]["AddressOfTouch"] is empty then put tOldAddress into gTouchs[pTouchID]["AddressOfTouch"]
end if
put the keys of gTouchs into sDoubleTouchIDs
/** If I have not moved the touch I do nothing **/
if gTouchs[pTouchID]["CurrentLoc"] is a point then
/** To know if it is a multitouch **/
if the num of lines of keys of gTouchs >= 2 then
/** PINCHSTART **/
if sIsPinch is 0 then
put 1 into sIsPinch
add 1 to sPinchId
put the long id of target into sLongId[sPinchId]
dispatch "PinchStart" to sLongId[sPinchId] with sPinchId
end if
local tInfoOfPinch, tChangerPinch
put _InfoOfPinch(pTouchID) into tInfoOfPinch
put item 1 of tInfoOfPinch into tChangerPinch
if sChangerPinch is not tChangerPinch then
if there is sLongId[sPinchId] then
dispatch "PinchMove" to sLongId[sPinchId] with sPinchId
end if
/** PINCHS ZOOMING **/
local tPrevAngle, tDoNotTurnFingers = true
if tPrevAngle is not a number then
put the item 2 of tInfoOfPinch into tPrevAngle
else
put the item 2 of tInfoOfPinch is tPrevAngle into tDoNotTurnFingers
end if
/** Messages generated when the screen is "pinched" **/
if item 3 of tInfoOfPinch is 0 and tDoNotTurnFingers then
if there is sLongId[sPinchId] then
dispatch "PinchZoomingDown" to sLongId[sPinchId] with sPinchId
end if
end if
if item 3 of tInfoOfPinch is 1 and tDoNotTurnFingers then
if there is sLongId[sPinchId] then
dispatch "PinchZoomingUp" to sLongId[sPinchId] with sPinchId
end if
end if
put the item 2 of tInfoOfPinch into tPrevAngle
end if
put item 1 of tInfoOfPinch into sChangerPinch
/** ROTATE **/
local tAngleOfPinch = 0
put item 2 of tInfoOfPinch into tAngleOfPinch
if abs(tAngleOfPinch) > 5 and sAngleOfPinch <> tAngleOfPinch then
if there is sLongId[sPinchId] then
--dispatch "PinchRotate" to sLongId[sPinchId] with sPinchId, tAngleOfPinch
end if
end if
put tAngleOfPinch into sAngleOfPinch
else
local tAngle = 0, tChanged
put gTouchs[pTouchID]["Angle"] into tAngle
if gTouchs[pTouchID]["Changed"] > 50 and gTouchs[pTouchID]["OldChanged"] <> gTouchs[pTouchID]["Changed"] then
put tAngle into fld 2
/** PUSH LEFT AND RIGHT **/
if ((tAngle >= 0 and tAngle <= 40) or (tAngle >= 320 and tAngle <= 360) or (tAngle >= 140 and tAngle <= 220)) then
put gTouchs[pTouchID]["ChangedInX"] into tChanged
if abs(tChanged) > 10 then
if tChanged > 1 then
dispatch "PushLeft" to sLongId[sPinchId] with pTouchID, tChanged
else
dispatch "PushRight" to sLongId[sPinchId] with pTouchID, tChanged
end if
end if
/** PUSH UP AND DOWN **/
else if (tAngle >= 50 and tAngle <= 130) or (tAngle >= 140 and tAngle <= 310) then
put gTouchs[pTouchID]["ChangedInY"] into tChanged
if abs(tChanged) > 10 then
if tChanged > 1 then
dispatch "PushUp" to sLongId[sPinchId] with pTouchID, tChanged
else
dispatch "PushDown" to sLongId[sPinchId] with pTouchID, tChanged
end if
end if
end if
/** Save changes to not send messages for pleasure **/
put gTouchs[pTouchID]["Changed"] into gTouchs[pTouchID]["OldChanged"]
end if
end if
end if
/** To know where I come from **/
put pTouchX, pTouchY into gTouchs[pTouchID]["PrevLoc"]
pass touchMove
end touchMove
on touchEnd pTouchID
delete variable gTouchs[ pTouchID ]
answer "touchEnd " & the keys of gTouchs
local tTime = 0, tTouchFast, tMillisec, tLoc, tChanger, tAddressOfTouch, tTouchX, tTouchY
put the millisec into tMillisec
put the num of lines of keys of gTouchs into tNumTouchs
put tMillisec - gTouchs[pTouchID]["StartTime"] into gTouchs[pTouchId]["CurrentTime"]
put round(gTouchs[pTouchId]["CurrentTime"]) into tTime
if gTouchs[pTouchID]["AddressOfTouch"] is empty then
put "none" into gTouchs[pTouchID]["AddressOfTouch"]
end if
if gTouchs[pTouchID]["Changed"] is empty then
put 0 into gTouchs[pTouchID]["Changed"]
end if
put gTouchs[pTouchID]["Changed"] into tChanger
put gTouchs[pTouchID]["AddressOfTouch"] into tAddressOfTouch
switch
case tTime <= 50
if there is sLongId[pTouchID] then
dispatch "TouchVeryFast" to sLongId[pTouchID] with pTouchID, tChanger, tAddressOfTouch
end if
put the result into tTouchFast
break
case tTime <= 250
if there is sLongId[pTouchID] then
dispatch "TouchFast" to sLongId[pTouchID] with pTouchID, tChanger, tAddressOfTouch
end if
put the result into tTouchFast
break
default
if tTime > 250 and tTime < 700 then
if there is sLongId[pTouchID] then
dispatch "TouchSlow" to sLongId[pTouchID] with pTouchID, tChanger, tAddressOfTouch
end if
put the result into tTouchFast
else
if there is sLongId[pTouchID] then
dispatch "TouchVerySlow" to sLongId[pTouchID] with pTouchID, tChanger, tAddressOfTouch
end if
put the result into tTouchFast
end if
end switch
local tLongId
put sLongId[pTouchID] into tLongId
/** remove the touch just ended in the array **/
delete global gTouchs[pTouchId]
delete local sLongId[pTouchID]
/** remove the touch just ended from the double touch list **/
filter sDoubleTouchIDs without pTouchID
if tNumTouchs <= 2 then
/** PINCHEND **/
if sIsPinch is 1 then
put 0 into sIsPinch
if there is sLongId[sPinchId] then
dispatch "PinchEnd" to sLongId[sPinchId] with sPinchId
end if
else
/** TOUCHDOUBLEUP **/
add 1 to sTouchDoubleUp
if sTouchDoubleUp is 1 then
put tMillisec into sLastTouchUp["StartTime"]
else if (tMillisec - sLastTouchUp["StartTime"]) <= kDoubleClickInterval then
put 0 into sTouchDoubleUp
put the mouseLoc into tLoc
put item 1 of tLoc into tTouchX
put item 2 of tLoc into tTouchY
if there is tLongId then
dispatch "TouchDoubleUp" to tLongId with pTouchID, tTouchX, tTouchY
end if
else
put tMillisec into sLastTouchUp["StartTime"]
end if
end if
end if
if tNumTouchs is 0 then delete global gTouchs
pass touchEnd
end touchEnd
on touchRelease pID
send "touchEnd pID" to me
pass touchRelease
end touchRelease
---------------------------------------------------------------------
--------------- Private functions and commands ----------------------
---------------------------------------------------------------------
private function _InfoOfPinch pTouchId
local tTouchList, tTouchNumberTwo
local tLocOneTouch, tLocTwoTouch
local tStartAngle, tEndAngle
local tStartDistance, tCurrentDistance, tPrevDistance
put the keys of gTouchs into tTouchList
if line 1 of tTouchList is pTouchId then
put line 2 of tTouchList into tTouchNumberTwo
else
put line 1 of tTouchList into tTouchNumberTwo
end if
put gTouchs[pTouchId]["StartLoc"] into tLocOneTouch
put gTouchs[tTouchNumberTwo]["StartLoc"] into tLocTwoTouch
put _ResizeDistance(tLocOneTouch, tLocTwoTouch) into tStartDistance
//put _TwoPointAngle(tLocOneTouch, tLocTwoTouch) into tStartAngle
put _AngleTouch(pTouchId) into tStartAngle
/** Current distance between the two touches. **/
put gTouchs[pTouchId]["CurrentLoc"] into tLocOneTouch
put gTouchs[tTouchNumberTwo]["CurrentLoc"] into tLocTwoTouch
put _ResizeDistance(tLocOneTouch, tLocTwoTouch) into tCurrentDistance
put _TwoPointAngle(tLocOneTouch, tLocTwoTouch) into tEndAngle
/** Distance of the points before this movement. **/
put gTouchs[pTouchId]["PrevLoc"] into tLocOneTouch
put gTouchs[tTouchNumberTwo]["PrevLoc"] into tLocTwoTouch
put _ResizeDistance(tLocOneTouch, tLocTwoTouch) into tPrevDistance
/** To know if it's a pinch up or down. **/
if tPrevDistance > tCurrentDistance then
put 0 into sAddressOfMovePinch
else if tPrevDistance < tCurrentDistance then
put 1 into sAddressOfMovePinch
end if
/** Radius, angle, pinch direction **/
return round((tCurrentDistance/ tStartDistance)* 100), (tEndAngle - tStartAngle), sAddressOfMovePinch
end _InfoOfPinch
/** Distance between two points **/
private function _ResizeDistance pLoc1, pLoc2
local dx = 0, dy = 0, tDistance = 0
put item 2 of pLoc1 - item 2 of pLoc2 into dy
put item 1 of pLoc1 - item 1 of pLoc2 into dx
put sqrt((dy^2) + (dx^2)) into tDistance
return tDistance
end _ResizeDistance
/** Angle formed between current and the center of the screen **/
private function _AngleTouch pTouchID
local tScreenCenter, tX, tY, tAngle, pX, pY, oppositeLeg, adjacentLeg, alpha
local foundAngle
put item 1 of the loc of me into pX
put item 2 of the loc of me into pY
// The center of the screen
put the loc of this cd into tScreenCenter
put the item 1 of tScreenCenter into tX
put the item 2 of tScreenCenter into tY
if tScreenCenter is (pX,pY) then
return 0
end if
put abs(tX- pX) into oppositeLeg
put abs(tY- pY) into adjacentLeg
if adjacentLeg <> 0 then
// Calculate the angle
put atan(oppositeleg/adjacentLeg) into alpha
// Convert to grade
put (alpha * 180)/pi into alpha
else
put 90 into alpha
end if
-- at this point, the angle will be between -180 and 180 degrees
switch
case tX <= pX and tY >= pY
put alpha into foundAngle
break
case tX <= pX and tY <= pY
put 180 - alpha into foundAngle
break
case tX >= pX and tY <= pY
put 180 + alpha into foundAngle
break
case tX >= pX and tY >= pY
put 360 - alpha into foundAngle
break
end switch
return abs(round(foundAngle,2))
end _AngleTouch
/** Touch address **/
private function _AddressTouch pLoc1, pLoc2
local Xo, X, Yo, Y, MovX, MovY
put the loc of this cd into pLoc1
put item 1 of pLoc1 into Xo
put item 2 of pLoc1 into Yo
put item 1 of pLoc2 into X
put item 2 of pLoc2 into Y
if Xo < X then
put "Right" into MovX
else if Xo > X then
put "Left" into MovX
else
put empty into MovX
end if
if Yo < Y then
put "Bottom" into MovY
else if Yo > Y then
put "Top" into MovY
else
put empty into MovY
end if
return MovX & MovY
end _AddressTouch
/** Angle between two points **/
private function _TwoPointAngle
local tX1, tY1, tX2, tY2, tAngle
put item 1 of Param(1) into tX1
put item 2 of Param(1) into tY1
put item 1 of Param(2) into tX2
put item 2 of Param(2) into tY2
put atan2(tY2 - tY1, tX2 - tX1) into tAngle
put trunc(tAngle*180/pi) into tAngle
return tAngle
end _TwoPointAngle
command _DispatchTouchDoubleDown pTouchID
local tTouchID, tLoc, tMove, tTouchX, tTouchY
put the mouseLoc into tLoc
put _ResizeDistance(tLoc, sStatTouchStillDown) into tMove
if sPendingTouchStillDown is a number then cancel sPendingTouchStillDown
if tMove > 33 or the mouse is not down or the num of lines of keys of gTouchs > 1 or (pTouchID is not tTouchID and tTouchID is a number) then exit _DispatchTouchDoubleDown
/** TouchStillDown **/
put item 1 of tLoc into tTouchX
put item 2 of tLoc into tTouchY
dispatch "TouchStillDown" to sLongId[pTouchID] //with pTouchID, tTouchX, tTouchY
send "_DispatchTouchDoubleDown pTouchID" to me in 0.1 sec
put pTouchID into tTouchID
end _DispatchTouchDoubleDown