hedgewars/uTouch.pas
branchhedgeroid
changeset 5733 5ab22736bdb6
parent 5621 ea796c83ea47
child 5828 667fb58d7f18
equal deleted inserted replaced
5731:d3be88be2247 5733:5ab22736bdb6
    23 interface
    23 interface
    24 
    24 
    25 uses sysutils, math, uConsole, uVariables, SDLh, uTypes, uFloat, uConsts, uIO, uCommands, GLUnit, uCommandHandlers;
    25 uses sysutils, math, uConsole, uVariables, SDLh, uTypes, uFloat, uConsts, uIO, uCommands, GLUnit, uCommandHandlers;
    26 
    26 
    27 type
    27 type
       
    28     PTouch_Finger = ^Touch_Finger;
    28     Touch_Finger = record
    29     Touch_Finger = record
    29         id                       : SDL_FingerId;
    30         id                       : SDL_FingerId;
    30         x,y                      : LongInt;
    31         x,y                      : LongInt;
    31         historicalX, historicalY : LongInt;
    32         historicalX, historicalY : LongInt;
    32         timeSinceDown            : Longword;
    33         timeSinceDown            : Longword;
    37 procedure ProcessTouch;
    38 procedure ProcessTouch;
    38 procedure onTouchDown(x,y: Longword; pointerId: SDL_FingerId);
    39 procedure onTouchDown(x,y: Longword; pointerId: SDL_FingerId);
    39 procedure onTouchMotion(x,y: Longword; dx,dy: LongInt; pointerId: SDL_FingerId);
    40 procedure onTouchMotion(x,y: Longword; dx,dy: LongInt; pointerId: SDL_FingerId);
    40 procedure onTouchUp(x,y: Longword; pointerId: SDL_FingerId);
    41 procedure onTouchUp(x,y: Longword; pointerId: SDL_FingerId);
    41 function convertToCursor(scale: LongInt; xy: LongInt): LongInt;
    42 function convertToCursor(scale: LongInt; xy: LongInt): LongInt;
    42 function addFinger(x,y: Longword; id: SDL_FingerId): Touch_Finger;
    43 function addFinger(x,y: Longword; id: SDL_FingerId): PTouch_Finger;
    43 procedure deleteFinger(id: SDL_FingerId);
    44 procedure deleteFinger(id: SDL_FingerId);
    44 procedure onTouchClick(finger: Touch_Finger);
    45 procedure onTouchClick(finger: Touch_Finger);
    45 procedure onTouchDoubleClick(finger: Touch_Finger);
    46 procedure onTouchDoubleClick(finger: Touch_Finger);
    46 
    47 
    47 function findFinger(id: SDL_FingerId): Touch_Finger;
    48 function findFinger(id: SDL_FingerId): PTouch_Finger;
    48 procedure aim(finger: Touch_Finger);
    49 procedure aim(finger: Touch_Finger);
    49 function isOnCrosshair(finger: Touch_Finger): boolean;
    50 function isOnCrosshair(finger: Touch_Finger): boolean;
    50 function isOnCurrentHog(finger: Touch_Finger): boolean;
    51 function isOnCurrentHog(finger: Touch_Finger): boolean;
    51 function isOnFireButton(finger: Touch_Finger): boolean;
    52 function isOnFireButton(finger: Touch_Finger): boolean;
    52 procedure convertToWorldCoord(var x,y: hwFloat; finger: Touch_Finger);
    53 procedure convertToWorldCoord(var x,y: hwFloat; finger: Touch_Finger);
    53 function fingerHasMoved(finger: Touch_Finger): boolean;
    54 function fingerHasMoved(finger: Touch_Finger): boolean;
    54 function calculateDelta(finger1, finger2: Touch_Finger): hwFloat;
    55 function calculateDelta(finger1, finger2: Touch_Finger): hwFloat;
    55 function getSecondFinger(finger: Touch_Finger): Touch_Finger;
    56 function getSecondFinger(finger: Touch_Finger): PTouch_Finger;
       
    57 procedure printFinger(finger: Touch_Finger);
    56 implementation
    58 implementation
    57 
    59 
    58 const
    60 const
    59     clicktime = 200;
    61     clicktime = 200;
       
    62     nilFingerId = High(SDL_FingerId);
    60 var
    63 var
    61     leftButtonBoundary  : LongInt;
    64     leftButtonBoundary  : LongInt;
    62     rightButtonBoundary : LongInt;
    65     rightButtonBoundary : LongInt;
    63     topButtonBoundary   : LongInt;
    66     topButtonBoundary   : LongInt;
    64     
    67     
    81     targetAngle: LongInt;
    84     targetAngle: LongInt;
    82     stopFiring: boolean;
    85     stopFiring: boolean;
    83 
    86 
    84     //moving
    87     //moving
    85     stopLeft, stopRight, walkingLeft, walkingRight :  boolean;
    88     stopLeft, stopRight, walkingLeft, walkingRight :  boolean;
    86 procedure printFinger(finger: Touch_Finger);
       
    87 begin
       
    88     WriteToConsole(Format('id:%d, (%d,%d), (%d,%d), time: %d', [finger.id, finger.x, finger.y, finger.historicalX, finger.historicalY, finger.timeSinceDown]));
       
    89 end;
       
    90 
    89 
    91 
    90 
    92 procedure onTouchDown(x,y: Longword; pointerId: SDL_FingerId);
    91 procedure onTouchDown(x,y: Longword; pointerId: SDL_FingerId);
    93 var 
    92 var 
    94     finger: Touch_Finger;
    93     finger: PTouch_Finger;
    95 begin
    94 begin
    96     finger:= addFinger(x,y,pointerId);
    95     finger := addFinger(x,y,pointerId);
    97     finger.x := convertToCursor(cScreenWidth,x);
       
    98     finger.y := convertToCursor(cScreenHeight,y);
       
    99     
       
   100     printFinger(finger); 
       
   101     case pointerCount of
    96     case pointerCount of
   102         1:
    97         1:
   103         begin
    98         begin
   104             moveCursor:= false;
    99             moveCursor:= false;
   105             if bShowAmmoMenu then
   100             if bShowAmmoMenu then
   106             begin
   101             begin
   107                 moveCursor := true;
   102                 moveCursor := true;
   108                 exit;
   103                 exit;
   109             end;
   104             end;
   110 
   105 
   111             if isOnCrosshair(finger) then
   106             if isOnCrosshair(finger^) then
   112             begin
   107             begin
   113                 aiming:= true;
   108                 aiming:= true;
   114                 exit;
   109                 exit;
   115             end;
   110             end;
   116 
   111 
   117             if isOnFireButton(finger) then
   112             if isOnFireButton(finger^) then
   118             begin
   113             begin
   119                 stopFiring:= false;
   114                 stopFiring:= false;
   120                 ParseCommand('+attack', true);
   115                 ParseCommand('+attack', true);
   121                 exit;
   116                 exit;
   122             end;
   117             end;
   123             if (finger.x < leftButtonBoundary) and (finger.y < 390) then
   118             if (finger^.x < leftButtonBoundary) and (finger^.y < 390) then
   124             begin
   119             begin
   125                 ParseCommand('+left', true);
   120                 ParseCommand('+left', true);
   126                 walkingLeft := true;
   121                 walkingLeft := true;
   127                 exit;
   122                 exit;
   128             end;
   123             end;
   129             if finger.x > rightButtonBoundary then
   124             if finger^.x > rightButtonBoundary then
   130             begin
   125             begin
   131                 ParseCommand('+right', true);
   126                 ParseCommand('+right', true);
   132                 walkingRight:= true;
   127                 walkingRight:= true;
   133                 exit;
   128                 exit;
   134             end;
   129             end;
   135             if finger.y < topButtonBoundary then
   130             if finger^.y < topButtonBoundary then
   136             begin
   131             begin
   137                 ParseCommand('hjump', true);
   132                 ParseCommand('hjump', true);
   138                 exit;
   133                 exit;
   139             end;
   134             end;
   140             moveCursor:= true; 
   135             moveCursor:= true; 
   141         end;
   136         end;
   142         2:
   137         2:
   143         begin
   138         begin
   144             aiming:= false;
   139             aiming:= false;
   145             stopFiring:= true;
   140             stopFiring:= true;
   146             
   141             pinchSize := calculateDelta(finger^, getSecondFinger(finger^)^);
   147             pinchSize := calculateDelta(finger, getSecondFinger(finger));
       
   148             baseZoomValue := ZoomValue
   142             baseZoomValue := ZoomValue
   149         end;
   143         end;
   150     end;//end case pointerCount of
   144     end;//end case pointerCount of
   151 end;
   145 end;
   152 
   146 
   153 procedure onTouchMotion(x,y: Longword;dx,dy: LongInt; pointerId: SDL_FingerId);
   147 procedure onTouchMotion(x,y: Longword;dx,dy: LongInt; pointerId: SDL_FingerId);
   154 var
   148 var
   155     finger, secondFinger: Touch_Finger;
   149     finger, secondFinger: PTouch_Finger;
   156     currentPinchDelta, zoom : hwFloat;
   150     currentPinchDelta, zoom : hwFloat;
   157 begin
   151 begin
   158     finger:= findFinger(pointerId);
   152     finger:= findFinger(pointerId);
   159     finger.x := convertToCursor(cScreenWidth, x);
   153 
   160     finger.y := convertToCursor(cScreenHeight, y);
   154     finger^.x := convertToCursor(cScreenWidth, x);
   161     
   155     finger^.y := convertToCursor(cScreenHeight, y);
       
   156 
   162     case pointerCount of
   157     case pointerCount of
   163        1:
   158        1:
   164            begin
   159            begin
   165                if aiming then 
   160                if aiming then 
   166                begin
   161                begin
   167                    aim(finger);
   162                    aim(finger^);
   168                    exit
   163                    exit
   169                end;
   164                end;
   170                if moveCursor then
   165                if moveCursor then
   171                    if invertCursor then
   166                    if invertCursor then
   172                    begin
   167                    begin
   179                        CursorPoint.Y := CursorPoint.Y - convertToCursor(cScreenWidth,dy);
   174                        CursorPoint.Y := CursorPoint.Y - convertToCursor(cScreenWidth,dy);
   180                    end;
   175                    end;
   181            end;
   176            end;
   182        2:
   177        2:
   183            begin
   178            begin
   184                secondFinger := getSecondFinger(finger);
   179                secondFinger := getSecondFinger(finger^);
   185                currentPinchDelta := calculateDelta(finger, secondFinger)- pinchSize;
   180                currentPinchDelta := calculateDelta(finger^, secondFinger^) - pinchSize;
   186                zoom := currentPinchDelta/cScreenWidth;
   181                zoom := currentPinchDelta/cScreenWidth;
   187                ZoomValue := baseZoomValue - ((hwFloat2Float(zoom) * cMinMaxZoomLevelDelta));
   182                ZoomValue := baseZoomValue - ((hwFloat2Float(zoom) * cMinMaxZoomLevelDelta));
   188                if ZoomValue < cMaxZoomLevel then ZoomValue := cMaxZoomLevel;
   183                if ZoomValue < cMaxZoomLevel then ZoomValue := cMaxZoomLevel;
   189                if ZoomValue > cMinZoomLevel then ZoomValue := cMinZoomLevel;
   184                if ZoomValue > cMinZoomLevel then ZoomValue := cMinZoomLevel;
   190             end;
   185             end;
   246         ParseCommand('hjump', true);
   241         ParseCommand('hjump', true);
   247         exit;
   242         exit;
   248     end;
   243     end;
   249 end;
   244 end;
   250 
   245 
   251 function addFinger(x,y: Longword; id: SDL_FingerId): Touch_Finger;
   246 function addFinger(x,y: Longword; id: SDL_FingerId): PTouch_Finger;
   252 var 
   247 var 
   253     xCursor, yCursor, index : LongInt;
   248     xCursor, yCursor, index : LongInt;
   254 begin
   249 begin
   255     //Check array sizes
   250     //Check array sizes
   256     if length(fingers) < pointerCount then 
   251     if length(fingers) < pointerCount then 
   257     begin
   252     begin
   258         setLength(fingers, length(fingers)*2);
   253         setLength(fingers, length(fingers)*2);
   259         for index := length(fingers) div 2 to length(fingers) do fingers[index].id := -1;
   254         for index := length(fingers) div 2 to length(fingers) do fingers[index].id := nilFingerId;
   260     end;
   255     end;
   261     
   256     
   262     
   257     
   263     xCursor := convertToCursor(cScreenWidth, x);
   258     xCursor := convertToCursor(cScreenWidth, x);
   264     yCursor := convertToCursor(cScreenHeight, y);
   259     yCursor := convertToCursor(cScreenHeight, y);
   265     
   260     
   266     //on removing fingers all fingers are moved to the left, thus new fingers will be to the far right
   261     //on removing fingers, all fingers are moved to the left
   267     //with dynamic arrays being zero based, 'far right' is the old pointerCount    
   262     //with dynamic arrays being zero based, the new position of the finger is the old pointerCount
   268     fingers[pointerCount].id := id;
   263     fingers[pointerCount].id := id;
   269     fingers[pointerCount].historicalX := xCursor;
   264     fingers[pointerCount].historicalX := xCursor;
   270     fingers[pointerCount].historicalY := yCursor;
   265     fingers[pointerCount].historicalY := yCursor;
   271     fingers[pointerCount].x := xCursor;
   266     fingers[pointerCount].x := xCursor;
   272     fingers[pointerCount].y := yCursor;
   267     fingers[pointerCount].y := yCursor;
   273     fingers[pointerCount].timeSinceDown:= SDL_GetTicks;
   268     fingers[pointerCount].timeSinceDown:= SDL_GetTicks;
   274  
   269  
       
   270     addFinger:= @fingers[pointerCount];
   275     inc(pointerCount);
   271     inc(pointerCount);
   276     addFinger:= fingers[pointerCount];
       
   277 end;
   272 end;
   278 
   273 
   279 procedure deleteFinger(id: SDL_FingerId);
   274 procedure deleteFinger(id: SDL_FingerId);
   280 var
   275 var
   281     index : Longint;
   276     index : Longint;
   284     dec(pointerCount);
   279     dec(pointerCount);
   285     for index := 0 to pointerCount do
   280     for index := 0 to pointerCount do
   286     begin
   281     begin
   287          if fingers[index].id = id then
   282          if fingers[index].id = id then
   288          begin
   283          begin
   289              //Check for onTouchevent
   284              //Check for onTouchClick event
   290              if ((SDL_GetTicks - fingers[index].timeSinceDown) < clickTime) AND  not(fingerHasMoved(fingers[index])) then 
   285              if ((SDL_GetTicks - fingers[index].timeSinceDown) < clickTime) AND  
   291                  onTouchClick(fingers[index]);
   286                  not(fingerHasMoved(fingers[index])) then onTouchClick(fingers[index]);
   292              fingers[index].id := -1;
   287 
       
   288              //put the last finger into the spot of the finger to be removed, 
       
   289              //so that all fingers are packed to the far left
       
   290              if  pointerCount <> index then
       
   291              begin
       
   292                 fingers[index].id := fingers[pointerCount].id;    
       
   293                 fingers[index].x := fingers[pointerCount].x;    
       
   294                 fingers[index].y := fingers[pointerCount].y;    
       
   295                 fingers[index].historicalX := fingers[pointerCount].historicalX;    
       
   296                 fingers[index].historicalY := fingers[pointerCount].historicalY;    
       
   297                 fingers[index].timeSinceDown := fingers[pointerCount].timeSinceDown;
       
   298 
       
   299                 fingers[pointerCount].id := nilFingerId;
       
   300              end
       
   301              else fingers[index].id := nilFingerId;
   293              break;
   302              break;
   294          end;
   303          end;
   295     end;
       
   296     //put the last finger into the spot of the finger to be removed, so that all fingers are packed to the far left
       
   297     if fingers[pointerCount].id = -1 then
       
   298     begin
       
   299         fingers[index] := fingers[pointerCount];    
       
   300         fingers[pointerCount].id := -1;
       
   301     end;
   304     end;
   302 
   305 
   303 end;
   306 end;
   304 
   307 
   305 procedure ProcessTouch;
   308 procedure ProcessTouch;
   349         ParseCommand('-left', true);
   352         ParseCommand('-left', true);
   350     end;
   353     end;
   351     
   354     
   352 end;
   355 end;
   353 
   356 
   354 function findFinger(id: SDL_FingerId): Touch_Finger;
   357 function findFinger(id: SDL_FingerId): PTouch_Finger;
   355 begin
   358 var
   356    for findFinger in fingers do
   359     index: LongWord;
   357        if (findFinger.id = -1) and (findFinger.id = id) then break;
   360 begin
       
   361    for index := 0 to High(fingers) do
       
   362        if fingers[index].id = id then 
       
   363        begin
       
   364            findFinger := @fingers[index];
       
   365            break;
       
   366        end;
   358 end;
   367 end;
   359 
   368 
   360 procedure aim(finger: Touch_Finger);
   369 procedure aim(finger: Touch_Finger);
   361 var 
   370 var 
   362     hogX, hogY, touchX, touchY, deltaX, deltaY, tmpAngle: hwFloat;
   371     hogX, hogY, touchX, touchY, deltaX, deltaY, tmpAngle: hwFloat;
   433 function fingerHasMoved(finger: Touch_Finger): boolean;
   442 function fingerHasMoved(finger: Touch_Finger): boolean;
   434 begin
   443 begin
   435     fingerHasMoved := trunc(sqrt(Power(finger.X-finger.historicalX,2) + Power(finger.y-finger.historicalY, 2))) > 330;
   444     fingerHasMoved := trunc(sqrt(Power(finger.X-finger.historicalX,2) + Power(finger.y-finger.historicalY, 2))) > 330;
   436 end;
   445 end;
   437 
   446 
   438 function calculateDelta(finger1, finger2: Touch_Finger): hwFloat;
   447 function calculateDelta(finger1, finger2: Touch_Finger): hwFloat; inline;
   439 begin
   448 begin
   440 //    calculateDelta := Distance(xyCoord[id2*2] - xyCoord[id1*2], xyCoord[id2*2+1] - xyCoord[id1*2+1]);
   449     calculateDelta := DistanceI(finger2.x-finger1.x, finger2.y-finger1.y);
   441     calculateDelta := int2hwFloat(trunc(sqrt(Power(finger2.x-finger1.x, 2) + Power(finger2.y-finger1.y, 2))));
   450 end;
   442 end;
   451 
   443 
   452 // Under the premise that all pointer ids in pointerIds:SDL_FingerId are packed to the far left.
   444 // Under the premise that all pointer ids in pointerIds:SDL_FingerId are pack to the far left.
       
   445 // If the pointer to be ignored is not pointerIds[0] the second must be there
   453 // If the pointer to be ignored is not pointerIds[0] the second must be there
   446 function getSecondFinger(finger: Touch_Finger): Touch_Finger;
   454 function getSecondFinger(finger: Touch_Finger): PTouch_Finger;
   447 begin
   455 begin
   448     if fingers[0].id = finger.id then getSecondFinger := fingers[0]
   456     if fingers[0].id = finger.id then getSecondFinger := @fingers[1]
   449     else getSecondFinger := fingers[1];
   457     else getSecondFinger := @fingers[0];
       
   458 end;
       
   459 
       
   460 procedure printFinger(finger: Touch_Finger);
       
   461 begin
       
   462     WriteToConsole(Format('id:%d, (%d,%d), (%d,%d), time: %d', [finger.id, finger.x, finger.y, finger.historicalX, finger.historicalY, finger.timeSinceDown]));
   450 end;
   463 end;
   451 
   464 
   452 procedure initModule;
   465 procedure initModule;
   453 var
   466 var
   454     finger: Touch_Finger;
   467     index: Longword;
   455 begin
   468 begin
   456     movingCrosshair := false;
   469     movingCrosshair := false;
   457     stopFiring:= false;
   470     stopFiring:= false;
   458     walkingLeft := false;
   471     walkingLeft := false;
   459     walkingRight := false;
   472     walkingRight := false;
   460 
   473 
   461     leftButtonBoundary := cScreenWidth div 4;
   474     leftButtonBoundary := cScreenWidth div 4;
   462     rightButtonBoundary := cScreenWidth div 4*3;
   475     rightButtonBoundary := cScreenWidth div 4*3;
   463     topButtonBoundary := cScreenHeight div 6;
   476     topButtonBoundary := cScreenHeight div 6;
   464     
   477     
   465     setLength(fingers, 5);
   478     setLength(fingers, 4);
   466     for finger in fingers do finger.id := -1;
   479     for index := 0 to High(fingers) do 
       
   480         fingers[index].id := nilFingerId;
   467 end;
   481 end;
   468 
   482 
   469 begin
   483 begin
   470 end.
   484 end.