AsphyreJoystick.pas
上传用户:ctlcnc
上传日期:2021-12-10
资源大小:4933k
文件大小:14k
- unit AsphyreJoystick;
- //---------------------------------------------------------------------------
- // AsphyreJoystick.pas Modified: 28-Jan-2007
- // Joystick/Gamepad DirectInput wrapper for Asphyre Version 1.04
- //---------------------------------------------------------------------------
- // Important Notice:
- //
- // If you modify/use this code or one of its parts either in original or
- // modified form, you must comply with Mozilla Public License v1.1,
- // specifically section 3, "Distribution Obligations". Failure to do so will
- // result in the license breach, which will be resolved in the court.
- // Remember that violating author's rights is considered a serious crime in
- // many countries. Thank you!
- //
- // !! Please *read* Mozilla Public License 1.1 document located at:
- // http://www.mozilla.org/MPL/
- //
- // If you require any clarifications about the license, feel free to contact
- // us or post your question on our forums at: http://www.afterwarp.net
- //---------------------------------------------------------------------------
- // The contents of this file are subject to the Mozilla Public License
- // Version 1.1 (the "License"); you may not use this file except in
- // compliance with the License. You may obtain a copy of the License at
- // http://www.mozilla.org/MPL/
- //
- // Software distributed under the License is distributed on an "AS IS"
- // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
- // License for the specific language governing rights and limitations
- // under the License.
- //
- // The Original Code is AsphyreJoystick.pas.
- //
- // The Initial Developer of the Original Code is M. Sc. Yuriy Kotsarenko.
- // Portions created by M. Sc. Yuriy Kotsarenko are Copyright (C) 2007,
- // Afterwarp Interactive. All Rights Reserved.
- //---------------------------------------------------------------------------
- interface
- //---------------------------------------------------------------------------
- uses
- Windows, DirectInput, AsphyreAsserts;
- //---------------------------------------------------------------------------
- type
- TAsphyreJoysticks = class;
- //---------------------------------------------------------------------------
- TAsphyreJoystick = class
- private
- FOwner: TAsphyreJoysticks;
-
- FInitialized: Boolean;
- FInputDevice: IDirectInputDevice8;
- FJoyState : TDIJoyState2;
- FButtonCount: Integer;
- FAxisCount : Integer;
- FPOVCount : Integer;
- FDeviceCaps : TDIDevCaps;
- FForeground : Boolean;
- procedure SetForeground(const Value: Boolean);
- public
- property Owner: TAsphyreJoysticks read FOwner;
-
- property Initialized: Boolean read FInitialized;
- property InputDevice: IDirectInputDevice8 read FInputDevice;
- property DeviceCaps : TDIDevCaps read FDeviceCaps;
- property JoyState : TDIJoyState2 read FJoyState;
- property Foreground : Boolean read FForeground write SetForeground;
- property ButtonCount: Integer read FButtonCount;
- property AxisCount : Integer read FAxisCount;
- property POVCount : Integer read FPOVCount;
- function Initialize(ddi: PDIDeviceInstance; hWnd: Integer): Boolean;
- procedure Finalize();
- function Poll(): Boolean;
- constructor Create(AOwner: TAsphyreJoysticks);
- destructor Destroy(); override;
- published
- end;
- //---------------------------------------------------------------------------
- TAsphyreJoysticks = class
- private
- FOwnerInput: TObject;
- Data: array of TAsphyreJoystick;
- FForeground : Boolean;
- FInitialized: Boolean;
- function GetCount(): Integer;
- function GetJoystick(Num: Integer): TAsphyreJoystick;
- procedure ReleaseJoysticks();
- protected
- function AddJoy(): TAsphyreJoystick;
- public
- // A reference to owner of this component; it must be TAsphyreInput.
- property OwnerInput: TObject read FOwnerInput;
- // Indicates whether the component has been initialized properly.
- property Initialized: Boolean read FInitialized;
- // This indicates whether the component should have joysticks acquired
- // even when the application has no focus.
- property Foreground: Boolean read FForeground write FForeground;
- property Count: Integer read GetCount;
- property Joystick[Num: Integer]: TAsphyreJoystick read GetJoystick; default;
- function Update(): Boolean;
- function Initialize(): Boolean;
- procedure Finalize();
- constructor Create(AOwnerInput: TObject);
- destructor Destroy(); override;
- end;
- //---------------------------------------------------------------------------
- implementation
- //---------------------------------------------------------------------------
- uses
- AsphyreInputs;
- //---------------------------------------------------------------------------
- type
- PJoysEnumRef = ^TJoysEnumRef;
- TJoysEnumRef = record
- Referrer: TAsphyreJoysticks;
- Success : Boolean;
- end;
- //---------------------------------------------------------------------------
- PJoyEnumRef = ^TJoyEnumRef;
- TJoyEnumRef = record
- Referrer: TAsphyreJoystick;
- Success : Boolean;
- end;
- //---------------------------------------------------------------------------
- function AxisEnumCallback(var ddoi: TDIDeviceObjectInstance;
- Ref: Pointer): Boolean; stdcall;
- var
- DIPropRange: TDIPropRange;
- EnumRef : PJoyEnumRef;
- Res : Integer;
- begin
- // (1) Retreive enumeration reference for further use.
- EnumRef:= Ref;
- // (2) Configure the axis.
- DIPropRange.diph.dwSize:= SizeOf(TDIPropRange);
- DIPropRange.diph.dwHeaderSize:= SizeOf(TDIPropHeader);
- DIPropRange.diph.dwHow:= DIPH_BYID;
- DIPropRange.diph.dwObj:= ddoi.dwType;
- // -> use range [-32768..32767]
- DIPropRange.lMin:= Low(SmallInt);
- DIPropRange.lMax:= High(SmallInt);
- // (3) Set axis properties.
- Res:= EnumRef.Referrer.InputDevice.SetProperty(DIPROP_RANGE,
- DIPropRange.diph);
- if (Res <> DI_OK) then
- begin
- Result:= DIENUM_STOP;
- EnumRef.Success:= False;
- end else Result:= DIENUM_CONTINUE;
- end;
- //---------------------------------------------------------------------------
- function JoyEnumCallback(ddi: PDIDeviceInstance;
- Ref: Pointer): Boolean; stdcall;
- var
- EnumRef : PJoysEnumRef;
- Joystick: TAsphyreJoystick;
- begin
- // (1) Retreive enumeration reference for further use.
- EnumRef:= Ref;
- // (2) Create new TJoystick class.
- Joystick:= EnumRef.Referrer.AddJoy();
- // (3) Initialize the created joystick.
- EnumRef.Success:= Joystick.Initialize(ddi,
- TAsphyreInput(EnumRef.Referrer.FOwnerInput).WindowHandle);
- if (not EnumRef.Success) then
- Result:= DIENUM_STOP else Result:= DIENUM_CONTINUE;
- end;
- //---------------------------------------------------------------------------
- constructor TAsphyreJoystick.Create(AOwner: TAsphyreJoysticks);
- begin
- inherited Create();
- FOwner:= AOwner;
- Assert(FOwner <> nil, msgNoOwnerSpecified);
- FInitialized:= False;
- FForeground := True;
- end;
- //---------------------------------------------------------------------------
- destructor TAsphyreJoystick.Destroy();
- begin
- if (FInitialized) then Finalize();
- inherited;
- end;
- //---------------------------------------------------------------------------
- procedure TAsphyreJoystick.SetForeground(const Value: Boolean);
- begin
- if (not FInitialized) then FForeground:= Value;
- end;
- //---------------------------------------------------------------------------
- function TAsphyreJoystick.Initialize(ddi: PDIDeviceInstance;
- hWnd: Integer): Boolean;
- var
- Input : TAsphyreInput;
- EnumRef: TJoyEnumRef;
- Flags : Cardinal;
- begin
- // (1) Retreive a valid reference to TAsphyreInput from the owner.
- Input:= TAsphyreInput(FOwner.OwnerInput);
- // (2) Create input device.
- Result:= Succeeded(Input.DirectInput8.CreateDevice(ddi.guidInstance,
- FInputDevice, nil));
- if (not Result) then Exit;
- // (3) Set data format.
- Result:= Succeeded(FInputDevice.SetDataFormat(c_dfDIJoystick2));
- if (not Result) then
- begin
- FInputDevice:= nil;
- Exit;
- end;
- // (4) Prepare cooperative flags.
- Flags:= DISCL_FOREGROUND or DISCL_EXCLUSIVE;
- if (not FForeground) then Flags:= DISCL_BACKGROUND or DISCL_NONEXCLUSIVE;
- // (5) Set joystick cooperative level.
- Result:= Succeeded(FInputDevice.SetCooperativeLevel(hWnd, Flags));
- if (not Result) then
- begin
- FInputDevice:= nil;
- Exit;
- end;
- // (6) Enumerate joystick axes.
- EnumRef.Referrer:= Self;
- EnumRef.Success := True;
- Result:= Succeeded(FInputDevice.EnumObjects(@AxisEnumCallback, @EnumRef,
- DIDFT_AXIS))and(EnumRef.Success);
- if (not Result) then
- begin
- FInputDevice:= nil;
- Exit;
- end;
- // (7) Get device capabilities.
- FillChar(FDeviceCaps, SizeOf(TDIDevCaps), 0);
- FDeviceCaps.dwSize:= SizeOf(TDIDevCaps);
- Result:= Succeeded(FInputDevice.GetCapabilities(FDeviceCaps));
- if (not Result) then
- begin
- FInputDevice:= nil;
- Exit;
- end;
- // (8) Retreive useful info.
- FButtonCount:= FDeviceCaps.dwButtons;
- FAxisCount := FDeviceCaps.dwAxes;
- FPOVCount := FDeviceCaps.dwPOVs;
- // (9) Set status to [Initialized].
- FInitialized:= True;
- end;
- //---------------------------------------------------------------------------
- procedure TAsphyreJoystick.Finalize();
- begin
- if (FInputDevice <> nil) then
- begin
- FInputDevice.Unacquire();
- FInputDevice:= nil;
- end;
- FInitialized:= False;
- end;
- //---------------------------------------------------------------------------
- function TAsphyreJoystick.Poll(): Boolean;
- var
- Res: Integer;
- begin
- Result:= True;
-
- // (1) Attempt polling Joystick.
- Res:= FInputDevice.Poll();
- // failures?
- if (Res <> DI_OK)and(Res <> DI_NOEFFECT) then
- begin
- // we can handle Lost Input & Non-Acquired problems
- if (Res <> DIERR_INPUTLOST)and(Res <> DIERR_NOTACQUIRED) then
- begin
- Result:= False;
- Exit;
- end;
- // Acquire the device!
- Result:= Succeeded(FInputDevice.Acquire());
- if (Result) then
- begin
- Res:= FInputDevice.Poll();
- if (Res <> DI_OK)and(Res <> DI_NOEFFECT) then
- begin
- Result:= False;
- Exit;
- end;
- end else Exit;
- end;
- // (2) Retreive joystick state.
- Res:= FInputDevice.GetDeviceState(SizeOf(TDIJoyState2), @FJoyState);
- if (Res <> DI_OK) then
- begin
- // we can handle Lost Input & Non-Acquired problems
- if (Res <> DIERR_INPUTLOST)and(Res <> DIERR_NOTACQUIRED) then
- begin
- Result:= False;
- Exit;
- end;
- // Again, try to acquire the device.
- Result:= Succeeded(FInputDevice.Acquire());
- if (Result) then
- begin
- Result:= Succeeded(FInputDevice.GetDeviceState(SizeOf(TDIJoyState2),
- @FJoyState));
- if (not Result) then Exit;
- end;
- end;
- end;
- //---------------------------------------------------------------------------
- constructor TAsphyreJoysticks.Create(AOwnerInput: TObject);
- begin
- inherited Create();
- FOwnerInput:= AOwnerInput;
- Assert((FOwnerInput <> nil)and(FOwnerInput is TAsphyreInput), msgNoOwnerInput);
- FForeground := True;
- FInitialized:= False;
- end;
- //---------------------------------------------------------------------------
- destructor TAsphyreJoysticks.Destroy();
- begin
- if (FInitialized) then Finalize();
- inherited;
- end;
- //---------------------------------------------------------------------------
- procedure TAsphyreJoysticks.ReleaseJoysticks();
- var
- i: Integer;
- begin
- for i:= 0 to Length(Data) - 1 do
- if (Data[i] <> nil) then
- begin
- Data[i].Free();
- Data[i]:= nil;
- end;
-
- SetLength(Data, 0);
- end;
- //---------------------------------------------------------------------------
- function TAsphyreJoysticks.GetCount(): Integer;
- begin
- Result:= Length(Data);
- end;
- //---------------------------------------------------------------------------
- function TAsphyreJoysticks.GetJoystick(Num: Integer): TAsphyreJoystick;
- begin
- Assert((Num >= 0)and(Num < Length(Data)), msgIndexOutOfBounds);
- Result:= nil;
- if (Num >= 0)and(Num < Length(Data)) then
- Result:= Data[Num];
- end;
- //---------------------------------------------------------------------------
- function TAsphyreJoysticks.AddJoy(): TAsphyreJoystick;
- var
- Index: Integer;
- begin
- Index:= Length(Data);
- SetLength(Data, Length(Data) + 1);
- Data[Index]:= TAsphyreJoystick.Create(Self);
- Data[Index].Foreground:= FForeground;
- Result:= Data[Index];
- end;
- //---------------------------------------------------------------------------
- function TAsphyreJoysticks.Initialize(): Boolean;
- var
- EnumRef: TJoysEnumRef;
- Input : TAsphyreInput;
- begin
- Assert(not FInitialized, msgAlreadyInitialized);
- // (1) Acquire a valid TAsphyreInput reference.
- Input:= TAsphyreInput(FOwnerInput);
- // (2) Make sure that TAsphyreInput is also initialized
- if (not Input.Initialized) then
- begin
- Result:= Input.Initialize();
- if (not Result) then Exit;
- end;
- // (2) Release any previously created joysticks.
- ReleaseJoysticks();
- // (3) Enumerate joysticks.
- EnumRef.Referrer:= Self;
- EnumRef.Success := False;
- Result:= Succeeded(Input.DirectInput8.EnumDevices(DI8DEVCLASS_GAMECTRL,
- @JoyEnumCallback, @EnumRef, DIEDFL_ATTACHEDONLY))and(EnumRef.Success);
- if (not Result) then ReleaseJoysticks();
- // (4) Set status to [Initialized]
- FInitialized:= Result;
- end;
- //---------------------------------------------------------------------------
- procedure TAsphyreJoysticks.Finalize();
- begin
- ReleaseJoysticks();
- FInitialized:= False;
- end;
- //---------------------------------------------------------------------------
- function TAsphyreJoysticks.Update(): Boolean;
- var
- i: Integer;
- begin
- Result:= True;
- if (not FInitialized) then
- begin
- Result:= Initialize();
- if (not Result) then Exit;
- end;
- for i:= 0 to Length(Data) - 1 do
- if (Data[i] <> nil)and(Data[i].Initialized) then
- begin
- Result:= Data[i].Poll();
- if (not Result) then Break;
- end;
- end;
- //---------------------------------------------------------------------------
- end.