{* UltraStar Deluxe - Karaoke Game
*
* UltraStar Deluxe is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*}
unit UJoystick;
interface
{$IFDEF FPC}
{$MODE Delphi}
{$ENDIF}
{$I switches.inc}
uses
SDL;
type
TJoyButton = record
State: integer;
Enabled: boolean;
Type_: byte;
Sym: cardinal;
end;
TJoyHatState = record
State: Boolean;
LastTick: Cardinal;
Enabled: boolean;
Type_: byte;
Sym: cardinal;
end;
TJoyUnit = record
Button: array[0..15] of TJoyButton;
HatState: Array[0..3] of TJoyHatState;
end;
TJoy = class
constructor Create;
procedure Update;
end;
var
Joy: TJoy;
JoyUnit: TJoyUnit;
SDL_Joy: PSDL_Joystick;
JoyEvent: TSDL_Event;
implementation
uses SysUtils,
ULog;
constructor TJoy.Create;
var
B: integer;
//N: integer;
begin
inherited;
//Old Corvus5 Method
{// joystick support
SDL_JoystickEventState(SDL_IGNORE);
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
if SDL_NumJoysticks <> 1 then
Log.LogStatus('Joystick count <> 1', 'TJoy.Create');
SDL_Joy := SDL_JoystickOpen(0);
if SDL_Joy = nil then
Log.LogError('SDL_JoystickOpen failed', 'TJoy.Create');
if SDL_JoystickNumButtons(SDL_Joy) <> 16 then
Log.LogStatus('Joystick button count <> 16', 'TJoy.Create');
// SDL_JoystickEventState(SDL_ENABLE);
// Events don't work - thay hang the whole application with SDL_JoystickEventState(SDL_ENABLE)
// clear states
for B := 0 to 15 do
JoyUnit.Button[B].State := 1;
// mapping
JoyUnit.Button[1].Enabled := true;
JoyUnit.Button[1].Type_ := SDL_KEYDOWN;
JoyUnit.Button[1].Sym := SDLK_RETURN;
JoyUnit.Button[2].Enabled := true;
JoyUnit.Button[2].Type_ := SDL_KEYDOWN;
JoyUnit.Button[2].Sym := SDLK_ESCAPE;
JoyUnit.Button[12].Enabled := true;
JoyUnit.Button[12].Type_ := SDL_KEYDOWN;
JoyUnit.Button[12].Sym := SDLK_LEFT;
JoyUnit.Button[13].Enabled := true;
JoyUnit.Button[13].Type_ := SDL_KEYDOWN;
JoyUnit.Button[13].Sym := SDLK_DOWN;
JoyUnit.Button[14].Enabled := true;
JoyUnit.Button[14].Type_ := SDL_KEYDOWN;
JoyUnit.Button[14].Sym := SDLK_RIGHT;
JoyUnit.Button[15].Enabled := true;
JoyUnit.Button[15].Type_ := SDL_KEYDOWN;
JoyUnit.Button[15].Sym := SDLK_UP;
}
//New Sarutas method
SDL_JoystickEventState(SDL_IGNORE);
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
if SDL_NumJoysticks < 1 then
begin
Log.LogError('No Joystick found');
exit;
end;
SDL_Joy := SDL_JoystickOpen(0);
if SDL_Joy = nil then
begin
Log.LogError('Could not Init Joystick');
exit;
end;
//N := SDL_JoystickNumButtons(SDL_Joy);
//if N < 6 then Log.LogStatus('Joystick button count < 6', 'TJoy.Create');
for B := 0 to 5 do begin
JoyUnit.Button[B].Enabled := true;
JoyUnit.Button[B].State := 1;
JoyUnit.Button[B].Type_ := SDL_KEYDOWN;
end;
JoyUnit.Button[0].Sym := SDLK_Return;
JoyUnit.Button[1].Sym := SDLK_Escape;
JoyUnit.Button[2].Sym := SDLK_M;
JoyUnit.Button[3].Sym := SDLK_R;
JoyUnit.Button[4].Sym := SDLK_RETURN;
JoyUnit.Button[5].Sym := SDLK_ESCAPE;
//Set HatState
for B := 0 to 3 do begin
JoyUnit.HatState[B].Enabled := true;
JoyUnit.HatState[B].State := False;
JoyUnit.HatState[B].Type_ := SDL_KEYDOWN;
end;
JoyUnit.HatState[0].Sym := SDLK_UP;
JoyUnit.HatState[1].Sym := SDLK_RIGHT;
JoyUnit.HatState[2].Sym := SDLK_DOWN;
JoyUnit.HatState[3].Sym := SDLK_LEFT;
end;
procedure TJoy.Update;
var
B: integer;
State: UInt8;
Tick: Cardinal;
Axes: Smallint;
begin
SDL_JoystickUpdate;
//Manage Buttons
for B := 0 to 15 do begin
if (JoyUnit.Button[B].Enabled) and (JoyUnit.Button[B].State <> SDL_JoystickGetButton(SDL_Joy, B)) and (JoyUnit.Button[B].State = 0) then begin
JoyEvent.type_ := JoyUnit.Button[B].Type_;
JoyEvent.key.keysym.sym := JoyUnit.Button[B].Sym;
SDL_PushEvent(@JoyEvent);
end;
end;
for B := 0 to 15 do begin
JoyUnit.Button[B].State := SDL_JoystickGetButton(SDL_Joy, B);
end;
//Get Tick
Tick := SDL_GetTicks();
//Get CoolieHat
if (SDL_JoystickNumHats(SDL_Joy)>=1) then
State := SDL_JoystickGetHat(SDL_Joy, 0)
else
State := 0;
//Get Axis
if (SDL_JoystickNumAxes(SDL_Joy)>=2) then
begin
//Down - Up (X- Axis)
Axes := SDL_JoystickGetAxis(SDL_Joy, 1);
If Axes >= 15000 then
State := State or SDL_HAT_Down
Else If Axes <= -15000 then
State := State or SDL_HAT_UP;
//Left - Right (Y- Axis)
Axes := SDL_JoystickGetAxis(SDL_Joy, 0);
If Axes >= 15000 then
State := State or SDL_HAT_Right
Else If Axes <= -15000 then
State := State or SDL_HAT_Left;
end;
//Manage Hat and joystick Events
if (SDL_JoystickNumHats(SDL_Joy)>=1) OR (SDL_JoystickNumAxes(SDL_Joy)>=2) then
begin
//Up Button
If (JoyUnit.HatState[0].Enabled) and ((SDL_HAT_UP AND State) = SDL_HAT_UP) then
begin //IF Button is newly Pressed or if he is Pressed longer than 500 msecs
if (JoyUnit.HatState[0].State = False) OR (JoyUnit.HatState[0].Lasttick < Tick) then
begin
//Set Tick and State
if JoyUnit.HatState[0].State then
JoyUnit.HatState[0].Lasttick := Tick + 200
else
JoyUnit.HatState[0].Lasttick := Tick + 500;
JoyUnit.HatState[0].State := True;
JoyEvent.type_ := JoyUnit.HatState[0].Type_;
JoyEvent.key.keysym.sym := JoyUnit.HatState[0].Sym;
SDL_PushEvent(@JoyEvent);
end;
end
else
JoyUnit.HatState[0].State := False;
//Right Button
If (JoyUnit.HatState[1].Enabled) and ((SDL_HAT_RIGHT AND State) = SDL_HAT_RIGHT) then
begin //IF Button is newly Pressed or if he is Pressed longer than 500 msecs
if (JoyUnit.HatState[1].State = False) OR (JoyUnit.HatState[1].Lasttick < Tick) then
begin
//Set Tick and State
if JoyUnit.HatState[1].State then
JoyUnit.HatState[1].Lasttick := Tick + 200
else
JoyUnit.HatState[1].Lasttick := Tick + 500;
JoyUnit.HatState[1].State := True;
JoyEvent.type_ := JoyUnit.HatState[1].Type_;
JoyEvent.key.keysym.sym := JoyUnit.HatState[1].Sym;
SDL_PushEvent(@JoyEvent);
end;
end
else
JoyUnit.HatState[1].State := False;
//Down button
If (JoyUnit.HatState[2].Enabled) and ((SDL_HAT_DOWN AND State) = SDL_HAT_DOWN) then
begin //IF Button is newly Pressed or if he is Pressed longer than 230 msecs
if (JoyUnit.HatState[2].State = False) OR (JoyUnit.HatState[2].Lasttick < Tick) then
begin
//Set Tick and State
if JoyUnit.HatState[2].State then
JoyUnit.HatState[2].Lasttick := Tick + 200
else
JoyUnit.HatState[2].Lasttick := Tick + 500;
JoyUnit.HatState[2].State := True;
JoyEvent.type_ := JoyUnit.HatState[2].Type_;
JoyEvent.key.keysym.sym := JoyUnit.HatState[2].Sym;
SDL_PushEvent(@JoyEvent);
end;
end
else
JoyUnit.HatState[2].State := False;
//Left Button
If (JoyUnit.HatState[3].Enabled) and ((SDL_HAT_LEFT AND State) = SDL_HAT_LEFT) then
begin //IF Button is newly Pressed or if he is Pressed longer than 230 msecs
if (JoyUnit.HatState[3].State = False) OR (JoyUnit.HatState[3].Lasttick < Tick) then
begin
//Set Tick and State
if JoyUnit.HatState[3].State then
JoyUnit.HatState[3].Lasttick := Tick + 200
else
JoyUnit.HatState[3].Lasttick := Tick + 500;
JoyUnit.HatState[3].State := True;
JoyEvent.type_ := JoyUnit.HatState[3].Type_;
JoyEvent.key.keysym.sym := JoyUnit.HatState[3].Sym;
SDL_PushEvent(@JoyEvent);
end;
end
else
JoyUnit.HatState[3].State := False;
end;
end;
end.