hedgewars/uKeys.pas
changeset 2428 6800f8aa0184
parent 2407 9f413bd5150e
child 2436 246ef6271470
--- a/hedgewars/uKeys.pas	Mon Oct 12 13:56:07 2009 +0000
+++ b/hedgewars/uKeys.pas	Mon Oct 12 16:44:30 2009 +0000
@@ -32,10 +32,27 @@
 procedure SetBinds(var binds: TBinds);
 procedure SetDefaultBinds;
 
-var KbdKeyPressed: boolean;
+procedure ControllerInit;
+procedure ControllerClose;
+procedure ControllerAxisEvent(joy, axis: Byte; value: Integer);
+procedure ControllerHatEvent(joy, hat, value: Byte);
+procedure ControllerButtonEvent(joy, button: Byte; pressed: Boolean);
+
+var hideAmmoMenu: boolean;
 	wheelUp: boolean = false;
 	wheelDown: boolean = false;
 
+	ControllerNumControllers: Integer;
+    ControllerEnabled: Integer;
+    ControllerNumAxes: array[0..5] of Integer;
+    //ControllerNumBalls: array[0..5] of Integer;
+	ControllerNumHats: array[0..5] of Integer;
+	ControllerNumButtons: array[0..5] of Integer;
+	ControllerAxes: array[0..5] of array[0..19] of Integer;
+	//ControllerBalls: array[0..5] of array[0..19] of array[0..1] of Integer;
+	ControllerHats: array[0..5] of array[0..19] of Byte;
+	ControllerButtons: array[0..5] of array[0..19] of Byte;
+
 implementation
 uses SDLh, uTeams, uConsole, uMisc, uStore;
 const KeyNumber = 1024;
@@ -53,17 +70,22 @@
 KeyNameToCode:= Result
 end;
 
+
 procedure ProcessKbd;
-var  i: LongInt;
-     s: shortstring;
+var  i, j, k: LongInt;
      pkbd: PByteArray;
      Trusted: boolean;
+     s: shortstring;
 begin
-KbdKeyPressed:= false;
+
+hideAmmoMenu:= false;
 Trusted:= (CurrentTeam <> nil)
           and (not CurrentTeam^.ExtDriven)
           and (CurrentHedgehog^.BotLevel = 0);
 
+// move cursor/camera
+// TODO: Scale on screen dimensions and/or axis value (game controller)?
+movecursor(5 * CursorMovementX, 5 * CursorMovementY);
 {$IFDEF SDL13}
 pkbd := SDL_GetKeyboardState(nil);
 i    := SDL_GetMouseState(0, nil, nil);
@@ -71,7 +93,6 @@
 pkbd := SDL_GetKeyState(nil);
 i    := SDL_GetMouseState(nil, nil);
 {$ENDIF}
-
 // mouse buttons
 {$IFDEF DARWIN}
 pkbd^[1]:= ((i and 1) and not (pkbd^[306] or pkbd^[305]));
@@ -88,11 +109,36 @@
 wheelUp:= false;
 wheelDown:= false;
 
+// Controller(s)
+k:= 500; // should we test k for hitting the limit? sounds rather unlikely to ever reach it
+for j:= 0 to Pred(ControllerNumControllers) do
+	begin
+	for i:= 0 to Pred(ControllerNumAxes[j]) do
+		begin
+		if ControllerAxes[j][i] > 20000 then pkbd^[k + 0]:= 1 else pkbd^[k + 0]:= 0;
+		if ControllerAxes[j][i] < -20000 then pkbd^[k + 1]:= 1 else pkbd^[k + 1]:= 0;
+		inc(k, 2);
+		end;
+	for i:= 0 to Pred(ControllerNumHats[j]) do
+		begin
+		pkbd^[k + 0]:= ControllerHats[j][i] and SDL_HAT_UP;
+		pkbd^[k + 1]:= ControllerHats[j][i] and SDL_HAT_RIGHT;
+		pkbd^[k + 2]:= ControllerHats[j][i] and SDL_HAT_DOWN;
+		pkbd^[k + 3]:= ControllerHats[j][i] and SDL_HAT_LEFT;
+		inc(k, 4);
+		end;
+	for i:= 0 to Pred(ControllerNumButtons[j]) do
+		begin
+		pkbd^[k]:= ControllerButtons[j][i];
+		inc(k, 1);
+		end;
+	end;
+
 // now process strokes
 for i:= 1 to cKeyMaxIndex do
 if CurrentBinds[i][0] <> #0 then
 	begin
-	if (i > 3) and (pkbd^[i] <> 0) then KbdKeyPressed:= true;
+	if (i > 3) and (pkbd^[i] <> 0) and not (hideAmmoMenu or (CurrentBinds[i] = 'put') or (CurrentBinds[i] = 'ammomenu') or (CurrentBinds[i] = '+cur_u') or (CurrentBinds[i] = '+cur_d') or (CurrentBinds[i] = '+cur_l') or (CurrentBinds[i] = '+cur_r')) then hideAmmoMenu:= true;
 	if (tkbd[i] = 0) and (pkbd^[i] <> 0) then ParseCommand(CurrentBinds[i], Trusted)
 	else if (CurrentBinds[i][1] = '+')
 			and (pkbd^[i] = 0)
@@ -103,11 +149,11 @@
 			ParseCommand(s, Trusted)
 			end;
 	tkbd[i]:= pkbd^[i]
-	end
+	end;
 end;
 
 procedure ResetKbd;
-var i, t: LongInt;
+var i, j, k, t: LongInt;
     pkbd: PByteArray;
 begin
 
@@ -118,12 +164,36 @@
 {$ENDIF}
 TryDo(i < cKeyMaxIndex, 'SDL keys number is more than expected (' + inttostr(i) + ')', true);
 
+k:= 500;
+for j:= 0 to Pred(ControllerNumControllers) do
+	begin
+	for i:= 0 to Pred(ControllerNumAxes[j]) do
+		begin
+		pkbd^[k + 0]:= 0;
+		pkbd^[k + 1]:= 0;
+		inc(k, 2);
+		end;
+	for i:= 0 to Pred(ControllerNumHats[j]) do
+		begin
+		pkbd^[k + 0]:= 0;
+		pkbd^[k + 1]:= 0;
+		pkbd^[k + 2]:= 0;
+		pkbd^[k + 3]:= 0;
+		inc(k, 4);
+		end;
+	for i:= 0 to Pred(ControllerNumButtons[j]) do
+		begin
+		pkbd^[k]:= 0;
+		inc(k, 1);
+		end;
+	end;
+
 for t:= 0 to Pred(i) do
     tkbd[i]:= pkbd^[i]
 end;
 
 procedure InitKbdKeyTable;
-var i, t: LongInt;
+var i, j, k, t: LongInt;
     s: string[15];
 begin
 KeyNames[1]:= 'mousel';
@@ -144,6 +214,31 @@
        end;
     end;
 
+// Controller(s)
+k:= 500;
+for j:= 0 to Pred(ControllerNumControllers) do
+	begin
+	for i:= 0 to Pred(ControllerNumAxes[j]) do
+		begin
+		keynames[k + 0]:= 'j' + inttostr(j) + 'a' + inttostr(i) + 'u';
+		keynames[k + 1]:= 'j' + inttostr(j) + 'a' + inttostr(i) + 'd';
+		inc(k, 2);
+		end;
+	for i:= 0 to Pred(ControllerNumHats[j]) do
+		begin
+		keynames[k + 0]:= 'j' + inttostr(j) + 'h' + inttostr(i) + 'u';
+		keynames[k + 1]:= 'j' + inttostr(j) + 'h' + inttostr(i) + 'r';
+		keynames[k + 2]:= 'j' + inttostr(j) + 'h' + inttostr(i) + 'd';
+		keynames[k + 3]:= 'j' + inttostr(j) + 'h' + inttostr(i) + 'l';
+		inc(k, 4);
+		end;
+	for i:= 0 to Pred(ControllerNumButtons[j]) do
+		begin
+		keynames[k]:= 'j' + inttostr(j) + 'b' + inttostr(i);
+		inc(k, 1);
+		end;
+	end;
+	
 DefaultBinds[ 27]:= 'quit';
 DefaultBinds[ 96]:= 'history';
 DefaultBinds[127]:= 'rotmask';
@@ -182,6 +277,87 @@
 tkbd[271]:= 1
 end;
 
+var Controller: array [0..5] of PSDLJoystick;
+	
+procedure ControllerInit;
+var i, j: Integer;
+begin
+ControllerEnabled:= 0;
+ControllerNumControllers:= SDL_NumJoysticks;
+
+if ControllerNumControllers > 6 then ControllerNumControllers:= 6;
+
+WriteLnToConsole('Number of game controllers: ' + inttostr(ControllerNumControllers));
+
+if ControllerNumControllers > 0 then
+	begin
+	for j:= 0 to pred(ControllerNumControllers) do
+		begin
+		WriteLnToConsole('Using game controller: ' + SDL_JoystickName(j));
+		Controller[j]:= SDL_JoystickOpen(j);
+		if Controller[j] = nil then
+			WriteLnToConsole('* Failed to open game controller!')
+		else
+			begin
+			ControllerNumAxes[j]:= SDL_JoystickNumAxes(Controller[j]);
+			//ControllerNumBalls[j]:= SDL_JoystickNumBalls(Controller[j]);
+			ControllerNumHats[j]:= SDL_JoystickNumHats(Controller[j]);
+			ControllerNumButtons[j]:= SDL_JoystickNumButtons(Controller[j]);
+			WriteLnToConsole('* Number of axes: ' + inttostr(ControllerNumAxes[j]));
+			//WriteLnToConsole('* Number of balls: ' + inttostr(ControllerNumBalls[j]));
+			WriteLnToConsole('* Number of hats: ' + inttostr(ControllerNumHats[j]));
+			WriteLnToConsole('* Number of buttons: ' + inttostr(ControllerNumButtons[j]));
+			ControllerEnabled:= 1;
+			
+			if ControllerNumAxes[j] > 20 then ControllerNumAxes[j]:= 20;
+			//if ControllerNumBalls[j] > 20 then ControllerNumBalls[j]:= 20;
+			if ControllerNumHats[j] > 20 then ControllerNumHats[j]:= 20;
+			if ControllerNumButtons[j] > 20 then ControllerNumButtons[j]:= 20;
+			
+			// reset all buttons/axes
+			for i:= 0 to pred(ControllerNumAxes[j]) do
+				ControllerAxes[j][i]:= 0;
+			(*for i:= 0 to pred(ControllerNumBalls[j]) do
+				begin
+				ControllerBalls[j][i][0]:= 0;
+				ControllerBalls[j][i][1]:= 0;
+				end;*)
+			for i:= 0 to pred(ControllerNumHats[j]) do
+				ControllerHats[j][i]:= SDL_HAT_CENTERED;
+			for i:= 0 to pred(ControllerNumButtons[j]) do
+				ControllerButtons[j][i]:= 0;
+			end;
+		end;
+	// enable event generation/controller updating
+	SDL_JoystickEventState(1);
+	end
+else	
+	WriteLnToConsole('Not using any game controller');
+end;
+
+procedure ControllerClose;
+var j: Integer;
+begin
+if ControllerEnabled > 0 then
+	for j:= 0 to pred(ControllerNumControllers) do
+		SDL_JoystickClose(Controller[j]);
+end;
+
+procedure ControllerAxisEvent(joy, axis: Byte; value: Integer);
+begin
+	ControllerAxes[joy][axis]:= value;
+end;
+
+procedure ControllerHatEvent(joy, hat, value: Byte);
+begin
+	ControllerHats[joy][hat]:= value;
+end;
+
+procedure ControllerButtonEvent(joy, button: Byte; pressed: Boolean);
+begin
+	if pressed then ControllerButtons[joy][button]:= 1 else ControllerButtons[joy][button]:= 0;
+end;
+
 initialization
 
 end.