diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e481f59 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Andres + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..86cb216 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# touchGestures + library for handling finger gestures on a screen. diff --git a/atc_TouchsGestures.dev.livecodescript b/atc_TouchsGestures.dev.livecodescript new file mode 100644 index 0000000..26d4e26 --- /dev/null +++ b/atc_TouchsGestures.dev.livecodescript @@ -0,0 +1,479 @@ +script "TouchsGestures" +/* + +* Autor: Andrés del Toro Cruz +* Correo: torocruzand@gmail.com +* Licencia: MIT +* Creación[Frcha: 7/14/19 || 10:21 PM] +* Rafael Freire - Holguín - CUBA + +* Esta mini Librería es par el comportamiento de algunos de los gestos más comunes +* que tenemos en los dispositivos móviles. + +* LiveCode nos permite capturar ciertos gestos específicos para los móviles. +* Como son el touchStart, touchEnd, touchRelease y touchMove... + +* Ahora Podemos capturar otros. +* Cuando se realice un pellizco en la pantalla (PinchMove, PinchZoomingUp, PinchZoomingDown y PinchRotate). +* Al usuario soltar un toque tendremos información de la duración del toque, +* distancia recorrida y la ultima dirección en que se movió el usuario. En el target se disparan los +* mensajes (TouchVeryFast, TouchFast, TouchSlow, TouchVerySlow ). +* Cuando se empuje o se deslicé un dedo de un lado a otro se genera uno de los +* siguientes mensajes (PushDown, PushLeft, PushUp, PushRight) + +* Nota_ +* Si usa uno de los gestos (touchStart, touchEnd, touchRelease o touchMove) debe de darle un pass para que +* los demás gestos que están aquí funcionen de forma correcta. + +*/ + +# MultiTouchs +global gTouchs +local sChangerPinch, sAddressOfMovePinch, sDoubleTouchIDs, sAngleOfPinch +local sIsPinch = 0, sPinchId = 0 + +# TouchDouble +constant kDoubleClickInterval = 250 +local sTouchDoubleDown, sLastTouchDown +local sTouchDoubleUp, sLastTouchUp +local tNumTouchs + +# Long touch +local sPendingTouchStillDown, sStatTouchStillDown + +before touchStart pTouchID + local tLoc + put the mouseLoc into tLoc + put the millisec into gTouchs[pTouchID]["StartTime"] + + 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 the mouseLoc into tLoc + send "TouchDoubleDown" to the long id of target with pTouchID, item 1 of tLoc, item 2 of tLoc + 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 me in 1 sec + put the result into sPendingTouchStillDown + + end if + pass touchStart +end touchStart + +before touchEnd pTouchID + local tTime = 0, tTouchFast, tMillisec, tLoc + + 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 + send "TouchVeryFast pTouchID, tChanger, tAddressOfTouch" to the long id of target in 0 + put the result into tTouchFast + break + case tTime <= 250 + send "Touchfast pTouchID, tChanger, tAddressOfTouch" to the long id of target in 0 + put the result into tTouchFast + break + default + if tTime > 250 and tTime < 700 then + send "Touchslow pTouchID, tChanger, tAddressOfTouch" to the long id of target in 0 + put the result into tTouchFast + else + send "TouchVerySlow pTouchID, tChanger, tAddressOfTouch" to the long id of target in 0 + put the result into tTouchFast + end if + end switch + + # remove the touch just ended in the array + delete global gTouchs[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 + send "PinchEnd sPinchId" to the long id of target in 0 + 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 + send "TouchDoubleUp pTouchID, tTouchX, tTouchY" to the long id of target + else + put tMillisec into sLastTouchUp["StartTime"] + end if + end if + end if + + if tNumTouchs is 0 then delete global gTouchs + pass touchEnd +end touchEnd + +before touchRelease pID + touchEnd pID + pass touchRelease +end touchRelease + +before touchMove pTouchID, pTouchX, pTouchY + if the mouse is not down then pass touchMove + + // Salvo la posición del toque + 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"] + + // Para la dirección + 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 + + // Si no he movido el toque no hago nada + if gTouchs[pTouchID]["CurrentLoc"] is a point then + + // Para saber si es un multitoques + 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 + send "PinchStart sPinchId" to the long id of target in 0 + end if + + local tInfoOfPinch + put _InfoOfPinch(pTouchID) into tInfoOfPinch + put item 1 of tInfoOfPinch into tChangerPinch + + if sChangerPinch is not tChangerPinch then + send "PinchMove sPinchId, tChangerPinch" to the long id of target with + # PINCHS ZOOMING + + // Mensajes generado cuando se "pellizca" la pantalla + if item 3 of tInfoOfPinch is 0 then send "PinchZoomingDown sPinchId, tChangerPinch" to the long id of target in 0 + if item 3 of tInfoOfPinch is 1 then send "PinchZoomingUp sPinchId, tChangerPinch" to the long id of target in 0 + + 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 + send "PinchRotate sPinchId, tAngleOfPinch" to the long id of target in 0 + end if + put tAngleOfPinch into sAngleOfPinch + + else + + local tAngle = 0 + put gTouchs[pTouchID]["Angle"] into tAngle + + if gTouchs[pTouchID]["Changed"] > 50 and gTouchs[pTouchID]["OldChanged"] <> gTouchs[pTouchID]["Changed"] then + local tChanged = 0 + + # 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 + send "PushLeft pTouchID, tChanged" to the long id of target in 0 + else + send "PushRight pTouchID, tChanged" to the long id of target in 0 + 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 + send "PushUp pTouchID, tChanged" to the long id of target in 0 + + else + send "PushDown pTouchID, tChanged" to the long id of target in 0 + end if + end if + end if + // Salvo los cambios para no estar renviando mensajes por gusto + put gTouchs[pTouchID]["Changed"] into gTouchs[pTouchID]["OldChanged"] + end if + end if + end if + + // Para saber la posición de donde vengo + put pTouchX, pTouchY into gTouchs[pTouchID]["PrevLoc"] + pass touchMove +end touchMove + +-------------------------------------------------------------------------- +------------------ MENSAJES GENERADOS PARA CADA GESTO--------------------- +-------------------------------------------------------------------------- +# Toque prolongado * +on TouchStillDown + +end TouchStillDown + +# Doble toque presionado +on TouchDoubleDown + +end TouchDoubleDown + +# Doble toque liberado +on TouchDoubleUp + +end TouchDoubleUp + +# Comienza un pellizco +on PinchStart pPinchId + # pPinchId. Id del pellizco. +end PinchStart + +# Pellizco en la pantalla +on PinchMove pPinchId, pRadioOfTouches , pType + # pPinchId. Id del pellizco. + # pRadioOfTouches. Radio entre de los toques. El que se mueve y cualquier otro. + # pType. Tipo de pellizco. Asia arriba(1), abajo (0) o simplemente moviendo los dedos a la misma distancia(null) +end PinchMove + +# Pellizco hacia abajo +on PinchZoomingDown pPinchId, pRadioOfTouches + # pPinchId. Id del pellizco. + # pRadioOfTouches. Radio entre de los toques. El que se mueve y cualquier otro. +end PinchZoomingDown + +# Pellizco hacia abajo +on PinchZoomingUp pPinchId, pRadioOfTouches + # pPinchId. Id del pellizco. + # pRadioOfTouches. Radio entre de los toques. El que se mueve y cualquier otro. +end PinchZoomingUp + +# Pellizco rotando +on PinchRotate pPinchId, pRotation + # pPinchId. Id del pellizco. + # pRotation. Es lo que se ha rotado los toques en la pantalla +end PinchRotate + +# Fin del pellizco +on PinchEnd pPinchId + # pPinchId. Id del pellizco. +end PinchEnd + +# Empujar para la izquierda +on PushLeft pTouchID, pDistance + # pTouchID. El id del toque. + # pDistance. La distancia recorrida por el toque. +end PushLeft + +# Empujar para la derecha +on PushRight pTouchID, pDistance + # pTouchID. El id del toque. + # pDistance. La distancia recorrida por el toque. +end PushRight + +# Empujar para arriba +on PushUp pTouchID, pDistance + # pTouchID. El id del toque. + # pDistance. La distancia recorrida por el toque. +end PushUp + +# Empujar para abajo +on PushDown pTouchID, pDistance + # pTouchID. El id del toque. + # pDistance. La distancia recorrida por el toque. +end PushDown + +# Toque muy rápido +on TouchVeryFast pTouchID, pDistance, pMoveAddress + # pTouchID. El id del toque + # pDistance. La distancia recorrida por el toque + # pMoveAddress. Dirección en la que se mueve el toque por ultima vez +end TouchVeryFast + +# toque rápido +on TouchFast pTouchID, pDistance, pMoveAddress + # pTouchID. El id del toque + # pDistance. La distancia recorrida por el toque + # pMoveAddress. Dirección en la que se mueve el toque por ultima vez +end TouchFast + +# Toque lento +on TouchSlow pTouchID, pDistance, pMoveAddress + # pTouchID. El id del toque + # pDistance. La distancia recorrida por el toque + # pMoveAddress. Dirección en la que se mueve el toque por ultima vez +end TouchSlow + +# Toque muy lento +on TouchVerySlow pTouchID, pDistance, pMoveAddress + # pTouchID. El id del toque + # pDistance. La distancia recorrida por el toque + # pMoveAddress. Dirección en la que se mueve el toque por ultima vez +end TouchVerySlow + +--------------------------------------------------------------------- +--------------- Funciones y comandos privados ----------------------- +--------------------------------------------------------------------- + +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 + + // Distancia actual entre los dos toques + put gTouchs[pTouchId]["CurrentLoc"] into tLocOneTouch + put gTouchs[tTouchNumberTwo]["CurrentLoc"] into tLocTwoTouch + put _ResizeDistance(tLocOneTouch, tLocTwoTouch) into tCurrentDistance + put _TwoPointAngle(tLocOneTouch, tLocTwoTouch) into tEndAngle + + // Distancia de los puntos antes de este movimiento. + put gTouchs[pTouchId]["PrevLoc"] into tLocOneTouch + put gTouchs[tTouchNumberTwo]["PrevLoc"] into tLocTwoTouch + put _ResizeDistance(tLocOneTouch, tLocTwoTouch) into tPrevDistance + + // para saber si es un pellizco para arriba o abajo. + if tPrevDistance > tCurrentDistance then + put 0 into sAddressOfMovePinch + else if tPrevDistance < tCurrentDistance then + put 1 into sAddressOfMovePinch + end if + + # Radio, Ángulo, Dirección del pellizco + return round((tCurrentDistance/ tStartDistance)* 100), (tEndAngle - tStartAngle), sAddressOfMovePinch +end _InfoOfPinch + +# Distancia entre dos puntos +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 + +# Angulo formado entre la posición actual y la inicial +private function _AngleTouch pTouchID + return _TwoPointAngle( gTouchs[pTouchID]["StartLoc"],gTouchs[pTouchID]["CurrentLoc"]) +end _AngleTouch + +# Dirección del toque +private function _AddressTouch pLoc1, pLoc2 + local Xo, X, Yo, Y, MovX, MovY + + 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 + send "TouchStillDown pTouchID, tTouchX, tTouchY" to the long id of target + send "_DispatchTouchDoubleDown pTouchID" to me in 0.1 sec + put pTouchID into tTouchID +end _DispatchTouchDoubleDown