unit DirectInputUnit;

interface
Uses
  DirectInput,
  GraphUtils;
{$I Keys.inc}
TYPE
  TDirectInput = class
    protected
      Game         : TGame;

      DirectInput  : IDirectInput8;
      Keyboard     : IDirectInputDevice8;
      Mouse        : IDirectInputDevice8;

      KeysState    : packed array[0..255] of byte;
      MouseState   : TDIMOUSESTATE2; //Значения статуса мышки

    private
    public

      MouseOfsX    : Longint;
      MouseOfsY    : Longint;
      MouseOfsZ    : Longint;

      MouseX       : Longint;
      MouseY       : Longint;

      Constructor Create(GameObj : TGame); 
      Procedure Free;
      Procedure Update;
      Function KeyDown(KeyNum : Byte) : LongBool;
      Function MouseDown(KeyNum : Byte) : LongBool;
  end;

implementation

uses Direct3D9;

//============================================================================//
//============================================================================//
//============================================================================//

Constructor TDirectInput.Create(GameObj : TGame);
Var
  dipdw : TDIPROPDWORD;
  hRet : Longint;
begin
  DirectInput := nil;
  Keyboard    := nil;
  Mouse       := nil;
  Game:=GameObj;

  FillChar(KeysState,SizeOf(KeysState),$00);
  FillChar(MouseState,SizeOf(MouseState),$00);

  MouseOfsX    := 0;
  MouseOfsY    := 0;
  MouseOfsZ    := 0;

  MouseX       := 0;
  MouseY       := 0;

  hRet := DirectInput8Create (hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, DirectInput, nil);
  if hRet<>DI_Ok then Exit;

  //Клавиатура:
  hRet := DirectInput.CreateDevice (GUID_SysKeyboard, Keyboard, nil);
  if hRet<>DI_Ok then Exit;

  hRet := Keyboard.SetCooperativeLevel(Game.GetWindowHandle, DISCL_NONEXCLUSIVE or DISCL_FOREGROUND);
  if hRet<>DI_Ok then Exit;

  hRet := Keyboard.SetDataFormat(c_dfDIKeyboard);
  if hRet<>DI_Ok then Exit;
(*
  ZeroMemory (@dipdw, SizeOf (dipdw));
  with dipdw do begin
       diph.dwSize       := SizeOf(TDIPROPDWORD);
       diph.dwHeaderSize := SizeOf(TDIPROPHEADER);
       diph.dwObj        := 0;
       diph.dwHow        := DIPH_DEVICE;
       dwData            := KEYBOARD_BUFFER_SIZE;
  end;

  hRet := DIKeyboard^^.SetProperty(DIKeyboard,DIPROP_BUFFERSIZE, dipdw.diph);
  if hRet<>dd_ok then begin
     Result := hRet;
     Exit
  end;
*)
  HRet := Keyboard.Acquire;
  if hRet<>DI_Ok then Exit;

  //Мышь:
  hRet := DirectInput.CreateDevice(GUID_SysMouse, Mouse, nil);
  if hRet<>DI_Ok then Exit;

  hRet := Mouse.SetCooperativeLevel(Game.GetWindowHandle, DISCL_NONEXCLUSIVE or DISCL_FOREGROUND);
  if hRet<>DI_Ok then Exit;

  hRet := Mouse.SetDataFormat(c_dfDIMouse2);
  if hRet<>DI_Ok then Exit;

  hRet := Mouse.Acquire;
  if hRet<>DI_Ok then Exit;

end;

//============================================================================//

Procedure TDirectInput.Free;
begin
  if Mouse<>nil then
    begin
      Mouse.Unacquire;
      Mouse := nil;
    end;

  if Keyboard<>nil then
  begin
    Keyboard.Unacquire;
    Keyboard:=nil;
  end;

  if DirectInput<>nil then
  begin
    DirectInput:=nil;
  end;
end;

//============================================================================//

Procedure TDirectInput.Update;
Var
  hRet : Longint;
begin
  if Keyboard<>nil then
  begin
     hRet:=Keyboard.GetDeviceState(256,@KeysState);
     if hRet<>DI_Ok then
     begin
       Keyboard.Acquire;
     end;
  end;

  if Mouse<>nil then
  begin
     FillChar(MouseState,SizeOf(MouseState),$00);
     hRet:=Mouse.GetDeviceState(SizeOf(MouseState),@MouseState);
     if hRet<>DI_Ok then
     begin
       Mouse.Acquire;
     end;
     MouseOfsX    := MouseState.lX;
     MouseOfsY    := MouseState.lY;
     MouseOfsZ    := MouseState.lZ;

     MouseX       := MouseX+MouseOfsX;
     if MouseX<0 then MouseX:=0 else
     if MouseX>Game.GetD3DPRESENTPARAMETERS.BackBufferWidth then MouseX:=Game.GetD3DPRESENTPARAMETERS.BackBufferWidth;
     MouseY       := MouseY+MouseOfsY;
     if MouseY<0 then MouseY:=0 else
     if MouseY>Game.GetD3DPRESENTPARAMETERS.BackBufferHeight then MouseY:=Game.GetD3DPRESENTPARAMETERS.BackBufferHeight;
  end;

end;

//============================================================================//

Function TDirectInput.KeyDown(KeyNum : Byte) : LongBool;
begin
  Result:=LongBool(KeysState[KeyNum] and $80);
end;

//============================================================================//

Function TDirectInput.MouseDown(KeyNum : Byte) : LongBool;
begin
  if KeyNum>7 then
  begin
    Result:=False;
    Exit;
  end;
  Result:=LongBool(MouseState.rgbButtons[KeyNum] and $80);
end;

//============================================================================//
//============================================================================//
//============================================================================//

end.
