aboutsummaryrefslogblamecommitdiffstats
path: root/src/base/UJoystick.pas
blob: 25d1d663f14b79c35a36d262916e45ada1e86ac4 (plain) (tree)
























                                                                        



               


                
 
                 
 

      

















































































































































































































































































                                                                                                                                                  
{* 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, 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.