hedgewars/uTouch.pas
changeset 6693 b6a69c0bc541
parent 6687 98be933770e0
child 6695 32de8965c62c
equal deleted inserted replaced
6692:029c27660dd2 6693:b6a69c0bc541
    22 
    22 
    23 interface
    23 interface
    24 
    24 
    25 uses sysutils, math, uConsole, uVariables, SDLh, uFloat, uConsts, uIO, GLUnit, uTypes;
    25 uses sysutils, math, uConsole, uVariables, SDLh, uFloat, uConsts, uIO, GLUnit, uTypes;
    26 
    26 
    27 // TODO: this type should be Int64
       
    28 // TODO: this type should be named TSDL_FingerId
       
    29 type SDL_FingerId = LongInt;
       
    30 
       
    31 type
       
    32     PTouch_Finger = ^Touch_Finger;
       
    33     Touch_Finger = record
       
    34         id                       : SDL_FingerId;
       
    35         x,y                      : LongInt;
       
    36         dx,dy                    : LongInt;
       
    37         historicalX, historicalY : LongInt;
       
    38         timeSinceDown            : Longword;
       
    39         end;
       
    40 
    27 
    41 procedure initModule;
    28 procedure initModule;
    42 
    29 
    43 procedure ProcessTouch;
    30 procedure ProcessTouch;
    44 procedure onTouchDown(x,y: Longword; pointerId: SDL_FingerId);
    31 procedure onTouchDown(x,y: Longword; pointerId: TSDL_FingerId);
    45 procedure onTouchMotion(x,y: Longword; dx,dy: LongInt; pointerId: SDL_FingerId);
    32 procedure onTouchMotion(x,y: Longword; dx,dy: LongInt; pointerId: TSDL_FingerId);
    46 procedure onTouchUp(x,y: Longword; pointerId: SDL_FingerId);
    33 procedure onTouchUp(x,y: Longword; pointerId: TSDL_FingerId);
    47 function convertToCursorX(x: LongInt): LongInt;
    34 function convertToCursorX(x: LongInt): LongInt;
    48 function convertToCursorY(y: LongInt): LongInt;
    35 function convertToCursorY(y: LongInt): LongInt;
    49 function convertToCursorDeltaX(x: LongInt): LongInt;
    36 function convertToCursorDeltaX(x: LongInt): LongInt;
    50 function convertToCursorDeltaY(y: LongInt): LongInt;
    37 function convertToCursorDeltaY(y: LongInt): LongInt;
    51 function addFinger(x,y: Longword; id: SDL_FingerId): PTouch_Finger;
    38 function addFinger(x,y: Longword; id: TSDL_FingerId): PTouch_Data;
    52 function updateFinger(x,y,dx,dy: Longword; id: SDL_FingerId): PTouch_Finger;
    39 function updateFinger(x,y,dx,dy: Longword; id: TSDL_FingerId): PTouch_Data;
    53 procedure deleteFinger(id: SDL_FingerId);
    40 procedure deleteFinger(id: TSDL_FingerId);
    54 procedure onTouchClick(finger: Touch_Finger);
    41 procedure onTouchClick(finger: TTouch_Data);
    55 procedure onTouchDoubleClick(finger: Touch_Finger);
    42 procedure onTouchDoubleClick(finger: TTouch_Data);
    56 
    43 
    57 function findFinger(id: SDL_FingerId): PTouch_Finger;
    44 function findFinger(id: TSDL_FingerId): PTouch_Data;
    58 procedure aim(finger: Touch_Finger);
    45 procedure aim(finger: TTouch_Data);
    59 function isOnCrosshair(finger: Touch_Finger): boolean;
    46 function isOnCrosshair(finger: TTouch_Data): boolean;
    60 function isOnCurrentHog(finger: Touch_Finger): boolean;
    47 function isOnCurrentHog(finger: TTouch_Data): boolean;
    61 procedure convertToWorldCoord(var x,y: hwFloat; finger: Touch_Finger);
    48 procedure convertToWorldCoord(var x,y: hwFloat; finger: TTouch_Data);
    62 procedure convertToFingerCoord(var x,y: hwFloat; oldX, oldY: hwFloat);
    49 procedure convertToFingerCoord(var x,y: hwFloat; oldX, oldY: hwFloat);
    63 function fingerHasMoved(finger: Touch_Finger): boolean;
    50 function fingerHasMoved(finger: TTouch_Data): boolean;
    64 function calculateDelta(finger1, finger2: Touch_Finger): hwFloat;
    51 function calculateDelta(finger1, finger2: TTouch_Data): hwFloat;
    65 function getSecondFinger(finger: Touch_Finger): PTouch_Finger;
    52 function getSecondFinger(finger: TTouch_Data): PTouch_Data;
    66 function isOnRect(widget: TOnScreenWidget; finger: Touch_Finger): boolean;
    53 function isOnRect(widget: TOnScreenWidget; finger: TTouch_Data): boolean;
    67 function isOnRect(rect: TSDL_Rect; finger: Touch_Finger): boolean;
    54 function isOnRect(rect: TSDL_Rect; finger: TTouch_Data): boolean;
    68 procedure printFinger(finger: Touch_Finger);
    55 procedure printFinger(finger: TTouch_Data);
    69 implementation
    56 implementation
    70 
    57 
    71 const
    58 const
    72     clicktime = 200;
    59     clicktime = 200;
    73     nilFingerId = High(SDL_FingerId);
    60     nilFingerId = High(TSDL_FingerId);
    74 
    61 
    75 var
    62 var
    76     pointerCount : Longword;
    63     pointerCount : Longword;
    77     fingers: array of Touch_Finger;
    64     fingers: array of TTouch_Data;
    78     moveCursor : boolean;
    65     moveCursor : boolean;
    79     invertCursor : boolean;
    66     invertCursor : boolean;
    80 
    67 
    81     xTouchClick,yTouchClick : LongInt;
    68     xTouchClick,yTouchClick : LongInt;
    82     timeSinceClick : Longword;
    69     timeSinceClick : Longword;
    92     stopFiring: boolean;
    79     stopFiring: boolean;
    93 
    80 
    94     //moving
    81     //moving
    95     stopLeft, stopRight, walkingLeft, walkingRight :  boolean;
    82     stopLeft, stopRight, walkingLeft, walkingRight :  boolean;
    96 
    83 
    97 procedure onTouchDown(x,y: Longword; pointerId: SDL_FingerId);
    84 procedure onTouchDown(x,y: Longword; pointerId: TSDL_FingerId);
    98 var 
    85 var 
    99     finger: PTouch_Finger;
    86     finger: PTouch_Data;
   100 begin
    87 begin
   101 {$IFDEF USE_TOUCH_INTERFACE}
    88 {$IFDEF USE_TOUCH_INTERFACE}
   102 finger := addFinger(x,y,pointerId);
    89 finger := addFinger(x,y,pointerId);
   103 case pointerCount of
    90 case pointerCount of
   104         1:
    91         1:
   170         end;
   157         end;
   171     end;//end case pointerCount of
   158     end;//end case pointerCount of
   172 {$ENDIF}
   159 {$ENDIF}
   173 end;
   160 end;
   174 
   161 
   175 procedure onTouchMotion(x,y: Longword;dx,dy: LongInt; pointerId: SDL_FingerId);
   162 procedure onTouchMotion(x,y: Longword;dx,dy: LongInt; pointerId: TSDL_FingerId);
   176 var
   163 var
   177     finger, secondFinger: PTouch_Finger;
   164     finger, secondFinger: PTouch_Data;
   178     currentPinchDelta, zoom : hwFloat;
   165     currentPinchDelta, zoom : hwFloat;
   179 begin
   166 begin
   180 finger:= updateFinger(x,y,dx,dy,pointerId);
   167 finger:= updateFinger(x,y,dx,dy,pointerId);
   181 
   168 
   182 if moveCursor then
   169 if moveCursor then
   212            ZoomValue := cMinZoomLevel;
   199            ZoomValue := cMinZoomLevel;
   213     end;
   200     end;
   214 
   201 
   215 end;
   202 end;
   216 
   203 
   217 procedure onTouchUp(x,y: Longword; pointerId: SDL_FingerId);
   204 procedure onTouchUp(x,y: Longword; pointerId: TSDL_FingerId);
   218 var
   205 var
   219     finger: PTouch_Finger;
   206     finger: PTouch_Data;
   220 begin
   207 begin
   221 x := x;
   208 x := x;
   222 y := y;
   209 y := y;
   223 aiming:= false;
   210 aiming:= false;
   224 stopFiring:= true;
   211 stopFiring:= true;
   251     downKey:= false;
   238     downKey:= false;
   252     aimingDown:= false;
   239     aimingDown:= false;
   253     end;
   240     end;
   254 end;
   241 end;
   255 
   242 
   256 procedure onTouchDoubleClick(finger: Touch_Finger);
   243 procedure onTouchDoubleClick(finger: TTouch_Data);
   257 begin
   244 begin
   258 finger := finger;//avoid compiler hint
   245 finger := finger;//avoid compiler hint
   259 end;
   246 end;
   260 
   247 
   261 procedure onTouchClick(finger: Touch_Finger);
   248 procedure onTouchClick(finger: TTouch_Data);
   262 begin
   249 begin
   263 if (RealTicks - timeSinceClick < 300) and (DistanceI(finger.X-xTouchClick, finger.Y-yTouchClick) < _30) then
   250 if (RealTicks - timeSinceClick < 300) and (DistanceI(finger.X-xTouchClick, finger.Y-yTouchClick) < _30) then
   264     begin
   251     begin
   265     onTouchDoubleClick(finger);
   252     onTouchDoubleClick(finger);
   266     timeSinceClick:= 0;//we make an assumption there won't be an 'click' in the first 300 ticks(milliseconds) 
   253     timeSinceClick:= 0;//we make an assumption there won't be an 'click' in the first 300 ticks(milliseconds) 
   290     bShowAmmoMenu := true;
   277     bShowAmmoMenu := true;
   291     exit;
   278     exit;
   292     end;
   279     end;
   293 end;
   280 end;
   294 
   281 
   295 function addFinger(x,y: Longword; id: SDL_FingerId): PTouch_Finger;
   282 function addFinger(x,y: Longword; id: TSDL_FingerId): PTouch_Data;
   296 var 
   283 var 
   297     xCursor, yCursor, index : LongInt;
   284     xCursor, yCursor, index : LongInt;
   298 begin
   285 begin
   299     //Check array sizes
   286     //Check array sizes
   300     if length(fingers) < Integer(pointerCount) then 
   287     if length(fingers) < Integer(pointerCount) then 
   321  
   308  
   322     addFinger:= @fingers[pointerCount];
   309     addFinger:= @fingers[pointerCount];
   323     inc(pointerCount);
   310     inc(pointerCount);
   324 end;
   311 end;
   325 
   312 
   326 function updateFinger(x,y,dx,dy: Longword; id: SDL_FingerId): PTouch_Finger;
   313 function updateFinger(x,y,dx,dy: Longword; id: TSDL_FingerId): PTouch_Data;
   327 begin
   314 begin
   328    updateFinger:= findFinger(id);
   315    updateFinger:= findFinger(id);
   329 
   316 
   330    updateFinger^.x:= convertToCursorX(x);
   317    updateFinger^.x:= convertToCursorX(x);
   331    updateFinger^.y:= convertToCursorY(y);
   318    updateFinger^.y:= convertToCursorY(y);
   332    updateFinger^.dx:= convertToCursorDeltaX(dx);
   319    updateFinger^.dx:= convertToCursorDeltaX(dx);
   333    updateFinger^.dy:= convertToCursorDeltaY(dy);
   320    updateFinger^.dy:= convertToCursorDeltaY(dy);
   334 end;
   321 end;
   335 
   322 
   336 procedure deleteFinger(id: SDL_FingerId);
   323 procedure deleteFinger(id: TSDL_FingerId);
   337 var
   324 var
   338     index : Longword;
   325     index : Longword;
   339 begin
   326 begin
   340     
   327     
   341     dec(pointerCount);
   328     dec(pointerCount);
   442     leftKey:= false;
   429     leftKey:= false;
   443     end;
   430     end;
   444     
   431     
   445 end;
   432 end;
   446 
   433 
   447 function findFinger(id: SDL_FingerId): PTouch_Finger;
   434 function findFinger(id: TSDL_FingerId): PTouch_Data;
   448 var
   435 var
   449     index: LongWord;
   436     index: LongWord;
   450 begin
   437 begin
   451     for index := 0 to High(fingers) do
   438     for index := 0 to High(fingers) do
   452         if fingers[index].id = id then 
   439         if fingers[index].id = id then 
   454             findFinger := @fingers[index];
   441             findFinger := @fingers[index];
   455             break;
   442             break;
   456             end;
   443             end;
   457 end;
   444 end;
   458 
   445 
   459 procedure aim(finger: Touch_Finger);
   446 procedure aim(finger: TTouch_Data);
   460 var 
   447 var 
   461     hogX, hogY, touchX, touchY, deltaX, deltaY, tmpAngle: hwFloat;
   448     hogX, hogY, touchX, touchY, deltaX, deltaY, tmpAngle: hwFloat;
   462 begin
   449 begin
   463     if CurrentHedgehog^.Gear <> nil then
   450     if CurrentHedgehog^.Gear <> nil then
   464         begin
   451         begin
   474         tmpAngle:= DeltaY / Distance(deltaX, deltaY) *_2048;
   461         tmpAngle:= DeltaY / Distance(deltaX, deltaY) *_2048;
   475         targetAngle:= (hwRound(tmpAngle) + 2048) div 2;
   462         targetAngle:= (hwRound(tmpAngle) + 2048) div 2;
   476         end; //if CurrentHedgehog^.Gear <> nil
   463         end; //if CurrentHedgehog^.Gear <> nil
   477 end;
   464 end;
   478 
   465 
   479 //These 4 convertToCursor functions convert xy coords from the SDL coordinate system to our CursorPoint coor system
   466 // These 4 convertToCursor functions convert xy coords from the SDL coordinate system to our CursorPoint coor system:
   480 // the SDL coordinate system goes from 0 to 32768 on the x axis and 0 to 32768 on the y axis, (0,0) being top left.
   467 // - the SDL coordinate system goes from 0 to 32768 on the x axis and 0 to 32768 on the y axis, (0,0) being top left;
   481 // the CursorPoint coordinate system goes from -cScreenWidth/2 to cScreenWidth/2 on the x axis 
   468 // - the CursorPoint coordinate system goes from -cScreenWidth/2 to cScreenWidth/2 on the x axis
   482 //  and 0 to cScreenHeight on the x axis, (-cScreenWidth, cScreenHeight) being top left,
   469 //   and 0 to cScreenHeight on the x axis, (-cScreenWidth, cScreenHeight) being top left.
   483 function convertToCursorX(x: LongInt): LongInt;
   470 function convertToCursorX(x: LongInt): LongInt;
   484 begin
   471 begin
   485     convertToCursorX := round((x/32768)*cScreenWidth) - (cScreenWidth shr 1);
   472     convertToCursorX := round((x/32768)*cScreenWidth) - (cScreenWidth shr 1);
   486 end;
   473 end;
   487 
   474 
   498 function convertToCursorDeltaY(y: LongInt): LongInt;
   485 function convertToCursorDeltaY(y: LongInt): LongInt;
   499 begin
   486 begin
   500     convertToCursorDeltaY := round(y/32768*cScreenHeight)
   487     convertToCursorDeltaY := round(y/32768*cScreenHeight)
   501 end;
   488 end;
   502 
   489 
   503 function isOnCrosshair(finger: Touch_Finger): boolean;
   490 function isOnCrosshair(finger: TTouch_Data): boolean;
   504 var
   491 var
   505     x,y : hwFloat;
   492     x,y : hwFloat;
   506 begin
   493 begin
   507     x := _0;//avoid compiler hint
   494     x := _0;//avoid compiler hint
   508     y := _0;
   495     y := _0;
   509     convertToFingerCoord(x, y, int2hwFloat(CrosshairX), int2hwFloat(CrosshairY));
   496     convertToFingerCoord(x, y, int2hwFloat(CrosshairX), int2hwFloat(CrosshairY));
   510     isOnCrosshair:= Distance(int2hwFloat(finger.x)-x, int2hwFloat(finger.y)-y) < _50;
   497     isOnCrosshair:= Distance(int2hwFloat(finger.x)-x, int2hwFloat(finger.y)-y) < _50;
   511 end;
   498 end;
   512 
   499 
   513 function isOnCurrentHog(finger: Touch_Finger): boolean;
   500 function isOnCurrentHog(finger: TTouch_Data): boolean;
   514 var
   501 var
   515     x,y : hwFloat;
   502     x,y : hwFloat;
   516 begin
   503 begin
   517     x := _0;
   504     x := _0;
   518     y := _0;
   505     y := _0;
   524 begin
   511 begin
   525     x := oldX + int2hwFloat(WorldDx);
   512     x := oldX + int2hwFloat(WorldDx);
   526     y := int2hwFloat(cScreenHeight) - (oldY + int2hwFloat(WorldDy));
   513     y := int2hwFloat(cScreenHeight) - (oldY + int2hwFloat(WorldDy));
   527 end;
   514 end;
   528 
   515 
   529 procedure convertToWorldCoord(var x,y: hwFloat; finger: Touch_Finger);
   516 procedure convertToWorldCoord(var x,y: hwFloat; finger: TTouch_Data);
   530 begin
   517 begin
   531 //if x <> nil then 
   518 //if x <> nil then 
   532     x := int2hwFloat((finger.x-WorldDx));
   519     x := int2hwFloat((finger.x-WorldDx));
   533 //if y <> nil then 
   520 //if y <> nil then 
   534     y := int2hwFloat((cScreenHeight - finger.y)-WorldDy);
   521     y := int2hwFloat((cScreenHeight - finger.y)-WorldDy);
   535 end;
   522 end;
   536 
   523 
   537 //Method to calculate the distance this finger has moved since the downEvent
   524 //Method to calculate the distance this finger has moved since the downEvent
   538 function fingerHasMoved(finger: Touch_Finger): boolean;
   525 function fingerHasMoved(finger: TTouch_Data): boolean;
   539 begin
   526 begin
   540     fingerHasMoved := trunc(sqrt(Power(finger.X-finger.historicalX,2) + Power(finger.y-finger.historicalY, 2))) > 330;
   527     fingerHasMoved := trunc(sqrt(Power(finger.X-finger.historicalX,2) + Power(finger.y-finger.historicalY, 2))) > 330;
   541 end;
   528 end;
   542 
   529 
   543 function calculateDelta(finger1, finger2: Touch_Finger): hwFloat; inline;
   530 function calculateDelta(finger1, finger2: TTouch_Data): hwFloat; inline;
   544 begin
   531 begin
   545     calculateDelta := DistanceI(finger2.x-finger1.x, finger2.y-finger1.y);
   532     calculateDelta := DistanceI(finger2.x-finger1.x, finger2.y-finger1.y);
   546 end;
   533 end;
   547 
   534 
   548 // Under the premise that all pointer ids in pointerIds:SDL_FingerId are packed to the far left.
   535 // Under the premise that all pointer ids in pointerIds:TSDL_FingerId are packed to the far left.
   549 // If the pointer to be ignored is not pointerIds[0] the second must be there
   536 // If the pointer to be ignored is not pointerIds[0] the second must be there
   550 function getSecondFinger(finger: Touch_Finger): PTouch_Finger;
   537 function getSecondFinger(finger: TTouch_Data): PTouch_Data;
   551 begin
   538 begin
   552     if fingers[0].id = finger.id then
   539     if fingers[0].id = finger.id then
   553         getSecondFinger := @fingers[1]
   540         getSecondFinger := @fingers[1]
   554     else
   541     else
   555         getSecondFinger := @fingers[0];
   542         getSecondFinger := @fingers[0];
   556 end;
   543 end;
   557 
   544 
   558 function isOnRect(rect: TSDL_Rect; finger: Touch_Finger): boolean;
   545 function isOnRect(rect: TSDL_Rect; finger: TTouch_Data): boolean;
   559 var widget: TOnScreenWidget;
   546 var widget: TOnScreenWidget;
   560 begin
   547 begin
   561     widget.x:= rect.x;
   548     widget.x:= rect.x;
   562     widget.y:= rect.y;
   549     widget.y:= rect.y;
   563     widget.width:= rect.w;
   550     widget.width:= rect.w;
   565     widget.hOffset:= 0;
   552     widget.hOffset:= 0;
   566     widget.vOffset:= 0;
   553     widget.vOffset:= 0;
   567     exit(isOnRect(widget, finger));
   554     exit(isOnRect(widget, finger));
   568 end;
   555 end;
   569 
   556 
   570 function isOnRect(widget: TOnScreenWidget; finger: Touch_Finger): boolean;
   557 function isOnRect(widget: TOnScreenWidget; finger: TTouch_Data): boolean;
   571 begin
   558 begin
   572 with widget do
   559 with widget do
   573     isOnRect:= (finger.x > x + hOffset)   and
   560     isOnRect:= (finger.x > x + hOffset)   and
   574                (finger.x < x + width + hOffset) and
   561                (finger.x < x + width + hOffset) and
   575                (cScreenHeight - finger.y > y + vOffset)   and
   562                (cScreenHeight - finger.y > y + vOffset)   and
   576                (cScreenHeight - finger.y < y + height + vOffset);
   563                (cScreenHeight - finger.y < y + height + vOffset);
   577 end;
   564 end;
   578 
   565 
   579 procedure printFinger(finger: Touch_Finger);
   566 procedure printFinger(finger: TTouch_Data);
   580 begin
   567 begin
   581     WriteToConsole(Format('id:%d, (%d,%d), (%d,%d), time: %d', [finger.id, finger.x, finger.y, finger.historicalX, finger.historicalY, finger.timeSinceDown]));
   568     WriteToConsole(Format('id:%d, (%d,%d), (%d,%d), time: %d', [finger.id, finger.x, finger.y, finger.historicalX, finger.historicalY, finger.timeSinceDown]));
   582 end;
   569 end;
   583 
   570 
   584 procedure initModule;
   571 procedure initModule;