Subversion Repositories spacemission

Rev

Rev 1 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1 Rev 4
1
unit DXInput;
1
unit DXInput;
2
 
2
 
3
interface
3
interface
4
 
4
 
5
{$INCLUDE DelphiXcfg.inc}
5
{$INCLUDE DelphiXcfg.inc}
6
 
6
 
7
uses
7
uses
8
  Windows, Messages, SysUtils, Classes, Controls, Forms, MMSystem,
8
  Windows, Messages, SysUtils, Classes, Controls, Forms, MMSystem,
-
 
9
  DXClass, {$IFDEF VER17UP} Types, {$ENDIF}
-
 
10
{$IfDef StandardDX}
-
 
11
  {$IfDef DX9}
-
 
12
  DirectInput;
-
 
13
  {$Else}
-
 
14
    {$IfDef DX81}
9
  DirectX, DXClass;
15
  DirectInput8;
-
 
16
    {$Else}
-
 
17
  DirectInput;
-
 
18
    {$EndIf}
-
 
19
  {$EndIf}
-
 
20
{$Else}
-
 
21
  DirectX;
-
 
22
{$EndIf}
10
 
23
 
11
type
24
type
12
 
25
 
13
  {  EDXInputError  }
26
  {  EDXInputError  }
14
 
27
 
15
  EDXInputError = class(Exception);
28
  EDXInputError = class(Exception);
16
 
29
 
17
  {  EForceFeedbackEffectError  }
30
  {  EForceFeedbackEffectError  }
18
 
31
 
19
  EForceFeedbackEffectError = class(Exception);
32
  EForceFeedbackEffectError = class(Exception);
20
 
33
 
21
 
34
 
22
  {  TForceFeedbackEffect  }
35
  {  TForceFeedbackEffect  }
23
 
36
 
24
  TForceFeedbackEffectType = (etNone, etConstantForce, etPeriodic, etCondition);
37
  TForceFeedbackEffectType = (etNone, etConstantForce, etPeriodic, etCondition);
25
 
38
 
26
  TForceFeedbackEffect = class;
39
  TForceFeedbackEffect = class;
27
  TForceFeedbackEffects = class;
40
  TForceFeedbackEffects = class;
28
 
41
 
29
  TForceFeedbackEffectObject = class
42
  TForceFeedbackEffectObject = class
30
  private
43
  private
31
    FAxes: array[0..1] of DWORD;
44
    FAxes: array[0..1] of DWORD;
32
    FAxesCount: Integer;
45
    FAxesCount: Integer;
33
    Feff: TDIEffect;
46
    Feff: TDIEffect;
34
    FDirections: array[0..1] of DWORD;
47
    FDirections: array[0..1] of DWORD;
35
    FEnvelope: TDIEnvelope;
48
    FEnvelope: TDIEnvelope;
36
    FConstantForce: TDIConstantForce;
49
    FConstantForce: TDIConstantForce;
37
    FCondition: TDICondition;
50
    FCondition: TDICondition;
38
    FPeriodic: TDIPeriodic;
51
    FPeriodic: TDIPeriodic;
39
    FEffect: IDirectInputEffect;
52
    FEffect: IDirectInputEffect;
40
    procedure Clear;
53
    procedure Clear;
41
    procedure Init(Effect: TForceFeedbackEffect);
54
    procedure Init(Effect: TForceFeedbackEffect);
42
    procedure Release;
55
    procedure Release;
43
  public
56
  public
44
    destructor Destroy; override;
57
    destructor Destroy; override;
45
  end;
58
  end;
46
 
59
 
47
  TForceFeedbackEffect = class(TPersistent)
60
  TForceFeedbackEffect = class(TPersistent)
48
  private
61
  private
49
    FRoot: TForceFeedbackEffects;                
62
    FRoot: TForceFeedbackEffects;                
50
    FParent: TForceFeedbackEffect;
63
    FParent: TForceFeedbackEffect;
51
    FList: TList;
64
    FList: TList;
52
    FAttackLevel: Integer;
65
    FAttackLevel: Integer;
53
    FAttackTime: Integer;
66
    FAttackTime: Integer;
54
    FCondition: TPoint;
67
    FCondition: TPoint;
55
    FConstant: TPoint;
68
    FConstant: TPoint;
56
    FEffectType: TForceFeedbackEffectType;
69
    FEffectType: TForceFeedbackEffectType;
57
    FFadeLevel: Integer;
70
    FFadeLevel: Integer;
58
    FFadeTime: Integer;
71
    FFadeTime: Integer;
59
    FName: string;
72
    FName: string;
60
    FPeriod: Integer;
73
    FPeriod: Integer;
61
    FPlaying: Boolean;
74
    FPlaying: Boolean;
62
    FPower: Integer;
75
    FPower: Integer;
63
    FTime: Integer;
76
    FTime: Integer;
64
    FStartDelayTime: Integer;
77
    FStartDelayTime: Integer;
65
    FObject: TForceFeedbackEffectObject;
78
    FObject: TForceFeedbackEffectObject;
66
    FObject2: TForceFeedbackEffectObject;
79
    FObject2: TForceFeedbackEffectObject;
67
    FFindEffectFlag: Boolean;
80
    FFindEffectFlag: Boolean;
68
    FFindEffectGUID: TGUID;
81
    FFindEffectGUID: TGUID;
69
    procedure Acquire;
82
    procedure Acquire;
70
    procedure Finalize;
83
    procedure Finalize;
71
    procedure Initialize;
84
    procedure Initialize;
72
    procedure ChangeEffect;
85
    procedure ChangeEffect;
73
    procedure MakeEff;
86
    procedure MakeEff;
74
    procedure CreateEffect;
87
    procedure CreateEffect;
75
    function GetCount: Integer;
88
    function GetCount: Integer;
76
    function GetEffect(Index: Integer): TForceFeedbackEffect;
89
    function GetEffect(Index: Integer): TForceFeedbackEffect;
77
    function GetIndex: Integer;
90
    function GetIndex: Integer;
78
    function GetPlaying: Boolean;
91
    function GetPlaying: Boolean;
79
    procedure SetAttackLevel(Value: Integer);
92
    procedure SetAttackLevel(Value: Integer);
80
    procedure SetAttackTime(Value: Integer);
93
    procedure SetAttackTime(Value: Integer);
81
    procedure SetCondition(Value: TPoint);
94
    procedure SetCondition(Value: TPoint);
82
    procedure SetConstant(Value: TPoint);
95
    procedure SetConstant(Value: TPoint);
83
    procedure SetEffectType(Value: TForceFeedbackEffectType);
96
    procedure SetEffectType(Value: TForceFeedbackEffectType);
84
    procedure SetFadeLevel(Value: Integer);
97
    procedure SetFadeLevel(Value: Integer);
85
    procedure SetFadeTime(Value: Integer);
98
    procedure SetFadeTime(Value: Integer);
86
    procedure SetIndex(Value: Integer);
99
    procedure SetIndex(Value: Integer);
87
    procedure SetPeriod(Value: Integer);
100
    procedure SetPeriod(Value: Integer);
88
    procedure SetParent(Value: TForceFeedbackEffect);
101
    procedure SetParent(Value: TForceFeedbackEffect);
89
    procedure SetPower(Value: Integer);
102
    procedure SetPower(Value: Integer);
90
    procedure SetTime(Value: Integer);
103
    procedure SetTime(Value: Integer);
91
    procedure SetStartDelayTime(Value: Integer);
104
    procedure SetStartDelayTime(Value: Integer);
92
    function HasInterface: Boolean;
105
    function HasInterface: Boolean;
93
  protected
106
  protected
94
    function GetOwner: TPersistent; override;
107
    function GetOwner: TPersistent; override;
95
    property StartDelayTime: Integer read FStartDelayTime write SetStartDelayTime;
108
    property StartDelayTime: Integer read FStartDelayTime write SetStartDelayTime;
96
  public
109
  public
97
    constructor Create(AParent: TForceFeedbackEffect);
110
    constructor Create(AParent: TForceFeedbackEffect);
98
    destructor Destroy; override;
111
    destructor Destroy; override;
99
    procedure Assign(Source: TPersistent); override;
112
    procedure Assign(Source: TPersistent); override;
100
    procedure Clear;
113
    procedure Clear;
101
    function Find(const Name: string): TForceFeedbackEffect;
114
    function Find(const Name: string): TForceFeedbackEffect;
102
    function IndexOf(const Name: string): Integer;
115
    function IndexOf(const Name: string): Integer;
103
    procedure LoadFromFile(const FileName: string);
116
    procedure LoadFromFile(const FileName: string);
104
    procedure LoadFromStream(Stream: TStream);
117
    procedure LoadFromStream(Stream: TStream);
105
    procedure SaveToFile(const FileName: string);
118
    procedure SaveToFile(const FileName: string);
106
    procedure SaveToStream(Stream: TStream);
119
    procedure SaveToStream(Stream: TStream);
107
    procedure Start;
120
    procedure Start;
108
    procedure Stop;
121
    procedure Stop;
109
    procedure Unload(Recurse: Boolean);
122
    procedure Unload(Recurse: Boolean);
110
    property Count: Integer read GetCount;
123
    property Count: Integer read GetCount;
111
    property Effects[Index: Integer]: TForceFeedbackEffect read GetEffect; default;
124
    property Effects[Index: Integer]: TForceFeedbackEffect read GetEffect; default;
112
    property Index: Integer read GetIndex write SetIndex;
125
    property Index: Integer read GetIndex write SetIndex;
113
    property Playing: Boolean read GetPlaying;
126
    property Playing: Boolean read GetPlaying;
114
    property Parent: TForceFeedbackEffect read FParent write SetParent;
127
    property Parent: TForceFeedbackEffect read FParent write SetParent;
115
    property Name: string read FName write FName;
128
    property Name: string read FName write FName;
116
    property EffectType: TForceFeedbackEffectType read FEffectType write SetEffectType;
129
    property EffectType: TForceFeedbackEffectType read FEffectType write SetEffectType;
117
    property AttackLevel: Integer read FAttackLevel write SetAttackLevel;
130
    property AttackLevel: Integer read FAttackLevel write SetAttackLevel;
118
    property AttackTime: Integer read FAttackTime write SetAttackTime;
131
    property AttackTime: Integer read FAttackTime write SetAttackTime;
119
    property Condition: TPoint read FCondition write SetCondition;
132
    property Condition: TPoint read FCondition write SetCondition;
120
    property Constant: TPoint read FConstant write SetConstant;
133
    property Constant: TPoint read FConstant write SetConstant;
121
    property FadeLevel: Integer read FFadeLevel write SetFadeLevel;
134
    property FadeLevel: Integer read FFadeLevel write SetFadeLevel;
122
    property FadeTime: Integer read FFadeTime write SetFadeTime;
135
    property FadeTime: Integer read FFadeTime write SetFadeTime;
123
    property Period: Integer read FPeriod write SetPeriod;
136
    property Period: Integer read FPeriod write SetPeriod;
124
    property Power: Integer read FPower write SetPower;
137
    property Power: Integer read FPower write SetPower;
125
    property Time: Integer read FTime write SetTime;
138
    property Time: Integer read FTime write SetTime;
126
  end;
139
  end;
127
 
140
 
128
  {  TForceFeedbackEffects  }
141
  {  TForceFeedbackEffects  }
129
 
142
 
130
  TCustomInput = class;
143
  TCustomInput = class;
131
 
144
 
132
  TForceFeedbackEffects = class(TForceFeedbackEffect)
145
  TForceFeedbackEffects = class(TForceFeedbackEffect)
133
  private
146
  private
134
    FComponent: TComponent;
147
    FComponent: TComponent;
135
    FInput: TCustomInput;
148
    FInput: TCustomInput;
136
  protected
149
  protected
137
    procedure DefineProperties(Filer: TFiler); override;
150
    procedure DefineProperties(Filer: TFiler); override;
138
  public
151
  public
139
    constructor Create(Input: TCustomInput);
152
    constructor Create(Input: TCustomInput);
140
    destructor Destroy; override;
153
    destructor Destroy; override;
141
    property Input: TCustomInput read FInput;
154
    property Input: TCustomInput read FInput;
142
  end;
155
  end;
143
 
156
 
144
  {  TCustomInput  }
157
  {  TCustomInput  }
145
 
158
 
146
  TDXInputState = (isUp, isDown, isLeft, isRight, isButton1, isButton2, isButton3,
159
  TDXInputState = (isUp, isDown, isLeft, isRight, isButton1, isButton2, isButton3,
147
    isButton4, isButton5, isButton6, isButton7, isButton8, isButton9, isButton10, isButton11,
160
    isButton4, isButton5, isButton6, isButton7, isButton8, isButton9, isButton10, isButton11,
148
    isButton12, isButton13, isButton14, isButton15, isButton16, isButton17, isButton18,
161
    isButton12, isButton13, isButton14, isButton15, isButton16, isButton17, isButton18,
149
    isButton19, isButton20, isButton21, isButton22, isButton23, isButton24, isButton25,
162
    isButton19, isButton20, isButton21, isButton22, isButton23, isButton24, isButton25,
150
    isButton26, isButton27, isButton28, isButton29, isButton30, isButton31, isButton32);
163
    isButton26, isButton27, isButton28, isButton29, isButton30, isButton31, isButton32);
151
 
164
 
152
  TDXInputStates = set of TDXInputState;
165
  TDXInputStates = set of TDXInputState;
153
 
166
 
154
  TCustomDXInput = class;
167
  TCustomDXInput = class;
155
 
168
 
156
  TCustomInput = class(TPersistent)
169
  TCustomInput = class(TPersistent)
157
  private          
170
  private          
158
    FBindInputStates: Boolean;
171
    FBindInputStates: Boolean;
159
    FButtonCount: Integer;
172
    FButtonCount: Integer;
160
    FDataFormat: TDIDataFormat;
173
    FDataFormat: TDIDataFormat;
161
    FDataFormatObjects: array[0..255] of TDIObjectDataFormat;
174
    FDataFormatObjects: array[0..255] of TDIObjectDataFormat;
162
    FDataFormatGUIDs: array[0..255] of TGUID;
175
    FDataFormatGUIDs: array[0..255] of TGUID;
163
    FDevice: IDirectInputDevice;
176
    FDevice: IDirectInputDevice;
164
    FDevice2: IDirectInputDevice2;
177
    FDevice2: IDirectInputDevice2;
165
    FDXInput: TCustomDXInput;
178
    FDXInput: TCustomDXInput;
166
    FEffects: TForceFeedbackEffects;
179
    FEffects: TForceFeedbackEffects;
167
    FEnabled: Boolean;
180
    FEnabled: Boolean;
168
    FForceFeedback: Boolean;
181
    FForceFeedback: Boolean;
169
    FForceFeedbackDevice: Boolean;
182
    FForceFeedbackDevice: Boolean;
170
    FInitialized: Boolean;
183
    FInitialized: Boolean;
171
    FStates: TDXInputStates;
184
    FStates: TDXInputStates;
172
    procedure Acquire;
185
    procedure Acquire;
173
    procedure Finalize; virtual;
186
    procedure Finalize; virtual;
174
    procedure Initialize; virtual;
187
    procedure Initialize; virtual;
175
    function GetButton(Index: Integer): Boolean;
188
    function GetButton(Index: Integer): Boolean;
176
    function GetCooperativeLevel: Integer; virtual;
189
    function GetCooperativeLevel: Integer; virtual;
177
    function GetDeviceState(dwSize: Integer; var Data): Boolean;
190
    function GetDeviceState(dwSize: Integer; var Data): Boolean;
178
    function SetDataFormat: Boolean;
191
    function SetDataFormat: Boolean;
179
    procedure SetEffects(Value: TForceFeedbackEffects);
192
    procedure SetEffects(Value: TForceFeedbackEffects);
180
    procedure SetEnabled(Value: Boolean);
193
    procedure SetEnabled(Value: Boolean);
181
    procedure SetForceFeedback(Value: Boolean);
194
    procedure SetForceFeedback(Value: Boolean);
182
    procedure SetWindowHandle(Value: Integer);
195
    procedure SetWindowHandle(Value: Integer);
183
  public
196
  public
184
    constructor Create(DXInput: TCustomDXInput); virtual;
197
    constructor Create(DXInput: TCustomDXInput); virtual;
185
    destructor Destroy; override;
198
    destructor Destroy; override;
186
    procedure Update; virtual; abstract;
199
    procedure Update; virtual; abstract;
187
    property ButtonCount: Integer read FButtonCount;
200
    property ButtonCount: Integer read FButtonCount;
188
    property Buttons[Index: Integer]: Boolean read GetButton;
201
    property Buttons[Index: Integer]: Boolean read GetButton;
189
    property States: TDXInputStates read FStates;
202
    property States: TDXInputStates read FStates;
190
  published
203
  published
191
    property BindInputStates: Boolean read FBindInputStates write FBindInputStates;
204
    property BindInputStates: Boolean read FBindInputStates write FBindInputStates;
192
    property Effects: TForceFeedbackEffects read FEffects write SetEffects;
205
    property Effects: TForceFeedbackEffects read FEffects write SetEffects;
193
    property Enabled: Boolean read FEnabled write SetEnabled;
206
    property Enabled: Boolean read FEnabled write SetEnabled;
194
    property ForceFeedback: Boolean read FForceFeedback write SetForceFeedback;
207
    property ForceFeedback: Boolean read FForceFeedback write SetForceFeedback;
195
  end;
208
  end;
196
 
209
 
197
  {  TKeyboard  }
210
  {  TKeyboard  }
198
 
211
 
199
  PKeyAssign = ^TKeyAssign;
212
  PKeyAssign = ^TKeyAssign;
200
  TKeyAssign = array[0..2] of Integer;
213
  TKeyAssign = array[0..2] of Integer;
201
 
214
 
202
  TKeyAssignList = array[TDXInputState] of TKeyAssign;
215
  TKeyAssignList = array[TDXInputState] of TKeyAssign;
203
 
216
 
204
  TKeyboard = class(TCustomInput)
217
  TKeyboard = class(TCustomInput)
205
  private
218
  private
206
    FKeyStates: TKeyboardState;
219
    FKeyStates: TKeyboardState;
207
    procedure Finalize; override;
220
    procedure Finalize; override;
208
    procedure Initialize; override;
221
    procedure Initialize; override;
209
    function GetKey(Key: Integer): Boolean;
222
    function GetKey(Key: Integer): Boolean;
210
    procedure ReadAssigns(Stream: TStream);
223
    procedure ReadAssigns(Stream: TStream);
211
    procedure WriteAssigns(Stream: TStream);
224
    procedure WriteAssigns(Stream: TStream);
212
  protected
225
  protected
213
    procedure DefineProperties(Filer: TFiler); override;
226
    procedure DefineProperties(Filer: TFiler); override;
214
  public
227
  public
215
    KeyAssigns: TKeyAssignList;
228
    KeyAssigns: TKeyAssignList;
216
    constructor Create(DXInput: TCustomDXInput); override;
229
    constructor Create(DXInput: TCustomDXInput); override;
217
    procedure Update; override;
230
    procedure Update; override;
218
    property Keys[Key: Integer]: Boolean read GetKey;
231
    property Keys[Key: Integer]: Boolean read GetKey;
219
  end;
232
  end;
220
 
233
 
221
  {  TMouse  }
234
  {  TMouse  }
222
 
235
 
223
  TMouse = class(TCustomInput)
236
  TMouse = class(TCustomInput)
224
  private  
237
  private  
225
    Fdims: TDIMouseState;
238
    Fdims: TDIMouseState;
226
    procedure Finalize; override;
239
    procedure Finalize; override;
227
    procedure Initialize; override;
240
    procedure Initialize; override;
228
    function GetX: Integer;
241
    function GetX: Integer;
229
    function GetY: Integer;
242
    function GetY: Integer;
230
    function GetZ: Integer;
243
    function GetZ: Integer;
231
  public
244
  public
232
    constructor Create(DXInput: TCustomDXInput); override;
245
    constructor Create(DXInput: TCustomDXInput); override;
233
    procedure Update; override;
246
    procedure Update; override;
234
    property X: Integer read GetX;
247
    property X: Integer read GetX;
235
    property Y: Integer read GetY;
248
    property Y: Integer read GetY;
236
    property Z: Integer read GetZ;
249
    property Z: Integer read GetZ;
237
  end;
250
  end;
238
 
251
 
239
  {  TJoystick  }
252
  {  TJoystick  }
240
 
253
 
241
  TJoystick = class(TCustomInput)
254
  TJoystick = class(TCustomInput)
242
  private
255
  private
243
    Fdijs: TDIJoyState2;
256
    Fdijs: TDIJoyState2;
244
    FAutoCenter: Boolean;
257
    FAutoCenter: Boolean;
245
    FDeviceGUID: TGUID;
258
    FDeviceGUID: TGUID;
246
    FEnumFlag: Boolean;
259
    FEnumFlag: Boolean;
247
    FEnumIndex: Integer;
260
    FEnumIndex: Integer;
248
    FID: Integer;
261
    FID: Integer;
249
    FID2: Integer;
262
    FID2: Integer;
250
    FJoyCaps: TJoyCaps;
263
    FJoyCaps: TJoyCaps;
251
    FDeadZone: array[0..SizeOf(TDIJoyState2)-1] of Integer;
264
    FDeadZone: array[0..SizeOf(TDIJoyState2)-1] of Integer;
252
    FRange: array[0..SizeOf(TDIJoyState2)-1] of Integer;
265
    FRange: array[0..SizeOf(TDIJoyState2)-1] of Integer;
253
    procedure Finalize; override;
266
    procedure Finalize; override;
254
    procedure Initialize; override;
267
    procedure Initialize; override;
255
    function GetCooperativeLevel: Integer; override;
268
    function GetCooperativeLevel: Integer; override;
256
    function GetDeadZone(Obj: Integer): Integer;
269
    function GetDeadZone(Obj: Integer): Integer;
257
    function GetRange(Obj: Integer): Integer;
270
    function GetRange(Obj: Integer): Integer;
258
    function GetX: Integer;
271
    function GetX: Integer;
259
    function GetY: Integer;
272
    function GetY: Integer;
260
    function GetZ: Integer;
273
    function GetZ: Integer;
261
    procedure SetDeadZone(Obj: Integer; Value: Integer);
274
    procedure SetDeadZone(Obj: Integer; Value: Integer);
262
    procedure SetRange(Obj: Integer; Value: Integer);
275
    procedure SetRange(Obj: Integer; Value: Integer);
263
    procedure SetAutoCenter(Value: Boolean);
276
    procedure SetAutoCenter(Value: Boolean);
264
    procedure SetID(Value: Integer);
277
    procedure SetID(Value: Integer);
265
  public
278
  public
266
    constructor Create(DXInput: TCustomDXInput); override;
279
    constructor Create(DXInput: TCustomDXInput); override;
267
    procedure Update; override;
280
    procedure Update; override;
268
    property DeadZone[Obj: Integer]: Integer read GetDeadZone write SetDeadZone;
281
    property DeadZone[Obj: Integer]: Integer read GetDeadZone write SetDeadZone;
269
    property Range[Obj: Integer]: Integer read GetRange write SetRange;
282
    property Range[Obj: Integer]: Integer read GetRange write SetRange;
270
    property Joystate: TDIJoyState2 read Fdijs;
283
    property Joystate: TDIJoyState2 read Fdijs;
271
    property X: Integer read GetX;
284
    property X: Integer read GetX;
272
    property Y: Integer read GetY;
285
    property Y: Integer read GetY;
273
    property Z: Integer read GetZ;
286
    property Z: Integer read GetZ;
274
  published
287
  published
275
    property AutoCenter: Boolean read FAutoCenter write SetAutoCenter;
288
    property AutoCenter: Boolean read FAutoCenter write SetAutoCenter;
276
    property DeadZoneX: Integer index DIJOFS_X read GetDeadZone write SetDeadZone;
289
    property DeadZoneX: Integer index DIJOFS_X read GetDeadZone write SetDeadZone;
277
    property DeadZoneY: Integer index DIJOFS_Y read GetDeadZone write SetDeadZone;
290
    property DeadZoneY: Integer index DIJOFS_Y read GetDeadZone write SetDeadZone;
278
    property DeadZoneZ: Integer index DIJOFS_Z read GetDeadZone write SetDeadZone;
291
    property DeadZoneZ: Integer index DIJOFS_Z read GetDeadZone write SetDeadZone;
279
    property ID: Integer read FID write SetID;
292
    property ID: Integer read FID write SetID;
280
    property RangeX: Integer index DIJOFS_X read GetRange write SetRange;
293
    property RangeX: Integer index DIJOFS_X read GetRange write SetRange;
281
    property RangeY: Integer index DIJOFS_Y read GetRange write SetRange;
294
    property RangeY: Integer index DIJOFS_Y read GetRange write SetRange;
282
    property RangeZ: Integer index DIJOFS_Z read GetRange write SetRange;
295
    property RangeZ: Integer index DIJOFS_Z read GetRange write SetRange;
283
  end;
296
  end;
284
 
297
 
285
  {  TCustomDXInput  }
298
  {  TCustomDXInput  }
286
 
299
 
287
  TCustomDXInput = class(TComponent)
300
  TCustomDXInput = class(TComponent)
288
  private
301
  private
289
    FActiveOnly: Boolean;
302
    FActiveOnly: Boolean;
290
    FDevice: TList;
303
    FDevice: TList;
291
    FDInput: IDirectInput;
304
    FDInput: IDirectInput;
292
    FForm: TCustomForm;
305
    FForm: TCustomForm;
293
    FJoystick: TJoystick;
306
    FJoystick: TJoystick;
294
    FKeyboard: TKeyboard;
307
    FKeyboard: TKeyboard;
295
    FMouse: TMouse;
308
    FMouse: TMouse;
296
    FOldStates: TDXInputStates;
309
    FOldStates: TDXInputStates;
297
    FStates: TDXInputStates;
310
    FStates: TDXInputStates;
298
    FSubClass: TControlSubClass;
311
    FSubClass: TControlSubClass;
299
    FUseDirectInput: Boolean;
312
    FUseDirectInput: Boolean;
300
    procedure Finalize;
313
    procedure Finalize;
301
    procedure Initialize;
314
    procedure Initialize;
302
    procedure FormWndProc(var Message: TMessage; DefWindowProc: TWndMethod);
315
    procedure FormWndProc(var Message: TMessage; DefWindowProc: TWndMethod);
303
    procedure SetActiveOnly(Value: Boolean);
316
    procedure SetActiveOnly(Value: Boolean);
304
    procedure SetJoystick(Value: TJoystick);
317
    procedure SetJoystick(Value: TJoystick);
305
    procedure SetKeyboard(Value: TKeyboard);
318
    procedure SetKeyboard(Value: TKeyboard);
306
    procedure SetMouse(Value: TMouse);
319
    procedure SetMouse(Value: TMouse);
307
    procedure SetWindowHandle;
320
    procedure SetWindowHandle;
308
    procedure SetUseDirectInput(Value: Boolean);
321
    procedure SetUseDirectInput(Value: Boolean);
309
  protected
322
  protected
310
    procedure Loaded; override;
323
    procedure Loaded; override;
311
  public
324
  public
312
    constructor Create(AOwner: TComponent); override;
325
    constructor Create(AOwner: TComponent); override;
313
    destructor Destroy; override;
326
    destructor Destroy; override;
314
    procedure Update;
327
    procedure Update;
315
    property ActiveOnly: Boolean read FActiveOnly write SetActiveOnly;
328
    property ActiveOnly: Boolean read FActiveOnly write SetActiveOnly;
316
    property Joystick: TJoystick read FJoystick write SetJoystick;
329
    property Joystick: TJoystick read FJoystick write SetJoystick;
317
    property Keyboard: TKeyboard read FKeyboard write SetKeyboard;
330
    property Keyboard: TKeyboard read FKeyboard write SetKeyboard;
318
    property Mouse: TMouse read FMouse write SetMouse;
331
    property Mouse: TMouse read FMouse write SetMouse;
319
    property States: TDXInputStates read FStates write FStates;
332
    property States: TDXInputStates read FStates write FStates;
320
    property UseDirectInput: Boolean read FUseDirectInput write SetUseDirectInput;
333
    property UseDirectInput: Boolean read FUseDirectInput write SetUseDirectInput;
321
  end;
334
  end;
322
 
335
 
323
  {  TDXInput  }
336
  {  TDXInput  }
324
 
337
 
325
  TDXInput = class(TCustomDXInput)
338
  TDXInput = class(TCustomDXInput)
326
  published
339
  published
327
    property ActiveOnly;
340
    property ActiveOnly;
328
    property Joystick;
341
    property Joystick;
329
    property Keyboard;
342
    property Keyboard;
330
    property Mouse;
343
    property Mouse;
331
    property UseDirectInput;
344
    property UseDirectInput;
332
  end;
345
  end;
333
 
346
 
334
function DefKeyAssign: TKeyAssignList;
347
function DefKeyAssign: TKeyAssignList;
335
function DefKeyAssign2_1: TKeyAssignList;
348
function DefKeyAssign2_1: TKeyAssignList;
336
function DefKeyAssign2_2: TKeyAssignList;
349
function DefKeyAssign2_2: TKeyAssignList;
337
 
350
 
338
implementation
351
implementation
339
 
352
 
340
uses DXConsts;
353
uses DXConsts;
341
 
354
 
342
procedure AssignKey(var KeyAssignList: TKeyAssignList; State: TDXInputState;
355
procedure AssignKey(var KeyAssignList: TKeyAssignList; State: TDXInputState;
343
  const Keys: array of Integer);
356
  const Keys: array of Integer);
344
var
357
var
345
  i, i2: Integer;
358
  i, i2: Integer;
346
  KeyAssign: PKeyAssign;
359
  KeyAssign: PKeyAssign;
347
begin
360
begin
348
  KeyAssign := @KeyAssignList[State];
361
  KeyAssign := @KeyAssignList[State];
349
  FillChar(KeyAssign^, SizeOf(TKeyAssign), 0);
362
  FillChar(KeyAssign^, SizeOf(TKeyAssign), 0);
350
 
363
 
351
  i2 := 0;
364
  i2 := 0;
352
  for i:=LOW(Keys) to HIGH(Keys) do
365
  for i:=LOW(Keys) to HIGH(Keys) do
353
  begin
366
  begin
354
    if i2<3 then
367
    if i2<3 then
355
      KeyAssign^[i2] := Keys[i]
368
      KeyAssign^[i2] := Keys[i]
356
    else
369
    else
357
      Exit;
370
      Exit;
358
    Inc(i2);
371
    Inc(i2);
359
  end;
372
  end;
360
end;
373
end;
361
 
374
 
362
function DefKeyAssign: TKeyAssignList;
375
function DefKeyAssign: TKeyAssignList;
363
begin
376
begin
364
  FillChar(Result, SizeOf(Result), 0);
377
  FillChar(Result, SizeOf(Result), 0);
365
 
378
 
366
  AssignKey(Result, isUp,      [Ord('K'), VK_UP, VK_NUMPAD8]);
379
  AssignKey(Result, isUp,      [Ord('K'), VK_UP, VK_NUMPAD8]);
367
  AssignKey(Result, isDown,    [Ord('J'), VK_DOWN, VK_NUMPAD2]);
380
  AssignKey(Result, isDown,    [Ord('J'), VK_DOWN, VK_NUMPAD2]);
368
  AssignKey(Result, isLeft,    [Ord('H'), VK_LEFT, VK_NUMPAD4]);
381
  AssignKey(Result, isLeft,    [Ord('H'), VK_LEFT, VK_NUMPAD4]);
369
  AssignKey(Result, isRight,   [Ord('L'), VK_RIGHT, VK_NUMPAD6]);
382
  AssignKey(Result, isRight,   [Ord('L'), VK_RIGHT, VK_NUMPAD6]);
370
  AssignKey(Result, isButton1, [Ord('Z'), VK_SPACE]);
383
  AssignKey(Result, isButton1, [Ord('Z'), VK_SPACE]);
371
  AssignKey(Result, isButton2, [Ord('X'), VK_RETURN]);
384
  AssignKey(Result, isButton2, [Ord('X'), VK_RETURN]);
372
  AssignKey(Result, isButton9, [VK_F2]);
385
  AssignKey(Result, isButton9, [VK_F2]);
373
end;
386
end;
374
 
387
 
375
function DefKeyAssign2_1: TKeyAssignList;
388
function DefKeyAssign2_1: TKeyAssignList;
376
begin
389
begin
377
  FillChar(Result, SizeOf(Result), 0);
390
  FillChar(Result, SizeOf(Result), 0);
378
 
391
 
379
  AssignKey(Result, isUp,      [Ord('K'), VK_UP, VK_NUMPAD8]);
392
  AssignKey(Result, isUp,      [Ord('K'), VK_UP, VK_NUMPAD8]);
380
  AssignKey(Result, isDown,    [Ord('J'), VK_DOWN, VK_NUMPAD2]);
393
  AssignKey(Result, isDown,    [Ord('J'), VK_DOWN, VK_NUMPAD2]);
381
  AssignKey(Result, isLeft,    [Ord('H'), VK_LEFT, VK_NUMPAD4]);
394
  AssignKey(Result, isLeft,    [Ord('H'), VK_LEFT, VK_NUMPAD4]);
382
  AssignKey(Result, isRight,   [Ord('L'), VK_RIGHT, VK_NUMPAD6]);
395
  AssignKey(Result, isRight,   [Ord('L'), VK_RIGHT, VK_NUMPAD6]);
383
  AssignKey(Result, isButton1, [VK_SPACE , VK_NUMPAD0]);
396
  AssignKey(Result, isButton1, [VK_SPACE , VK_NUMPAD0]);
384
  AssignKey(Result, isButton2, [VK_RETURN, VK_NUMPAD5]);
397
  AssignKey(Result, isButton2, [VK_RETURN, VK_NUMPAD5]);
385
  AssignKey(Result, isButton9, [VK_F2]);
398
  AssignKey(Result, isButton9, [VK_F2]);
386
end;
399
end;
387
 
400
 
388
function DefKeyAssign2_2: TKeyAssignList;
401
function DefKeyAssign2_2: TKeyAssignList;
389
begin
402
begin
390
  FillChar(Result, SizeOf(Result), 0);
403
  FillChar(Result, SizeOf(Result), 0);
391
 
404
 
392
  AssignKey(Result, isUp,      [Ord('E')]);
405
  AssignKey(Result, isUp,      [Ord('E')]);
393
  AssignKey(Result, isDown,    [Ord('C')]);
406
  AssignKey(Result, isDown,    [Ord('C')]);
394
  AssignKey(Result, isLeft,    [Ord('S')]);
407
  AssignKey(Result, isLeft,    [Ord('S')]);
395
  AssignKey(Result, isRight,   [Ord('F')]);
408
  AssignKey(Result, isRight,   [Ord('F')]);
396
  AssignKey(Result, isButton1, [Ord('Z')]);
409
  AssignKey(Result, isButton1, [Ord('Z')]);
397
  AssignKey(Result, isButton2, [Ord('X')]);
410
  AssignKey(Result, isButton2, [Ord('X')]);
398
  AssignKey(Result, isButton9, [VK_F2]);
411
  AssignKey(Result, isButton9, [VK_F2]);
399
end;
412
end;
400
 
413
 
401
{  TForceFeedbackEffectObject  }
414
{  TForceFeedbackEffectObject  }
402
 
415
 
403
destructor TForceFeedbackEffectObject.Destroy;
416
destructor TForceFeedbackEffectObject.Destroy;
404
begin
417
begin
405
  Release;                      
418
  Release;                      
406
  inherited Destroy;
419
  inherited Destroy;
407
end;
420
end;
408
 
421
 
409
function ConvertTime(i: Integer): DWORD;
422
function ConvertTime(i: Integer): DWORD;
410
begin
423
begin
411
  if i=-1 then Result := INFINITE else Result := i*1000;
424
  if i=-1 then Result := INFINITE else Result := i*1000;
412
end;
425
end;
413
 
426
 
414
procedure TForceFeedbackEffectObject.Clear;
427
procedure TForceFeedbackEffectObject.Clear;
415
begin
428
begin
416
  FillChar(Feff, SizeOf(Feff), 0);
429
  FillChar(Feff, SizeOf(Feff), 0);
417
end;
430
end;
418
 
431
 
419
procedure TForceFeedbackEffectObject.Init(Effect: TForceFeedbackEffect);
432
procedure TForceFeedbackEffectObject.Init(Effect: TForceFeedbackEffect);
420
begin
433
begin
421
  with FEnvelope do
434
  with FEnvelope do
422
  begin
435
  begin
423
    dwSize := SizeOf(FEnvelope);
436
    dwSize := SizeOf(FEnvelope);
424
 
437
 
425
    dwAttackLevel := Effect.FAttackLevel;
438
    dwAttackLevel := Effect.FAttackLevel;
426
    if Effect.FTime<0 then
439
    if Effect.FTime<0 then
427
      dwAttackTime := Effect.FAttackTime*1000
440
      dwAttackTime := Effect.FAttackTime*1000
428
    else
441
    else
429
      dwAttackTime := Min(Effect.FAttackTime, Effect.FTime)*1000;
442
      dwAttackTime := Min(Effect.FAttackTime, Effect.FTime)*1000;
430
                                             
443
                                             
431
    if Effect.FTime<0 then
444
    if Effect.FTime<0 then
432
    begin
445
    begin
433
      dwFadeLevel := 0;
446
      dwFadeLevel := 0;
434
      dwFadeTime := 0;
447
      dwFadeTime := 0;
435
    end else
448
    end else
436
    begin
449
    begin
437
      dwFadeLevel := Effect.FFadeLevel;
450
      dwFadeLevel := Effect.FFadeLevel;
438
      dwFadeTime := Min(Effect.FFadeTime, Effect.FTime)*1000;
451
      dwFadeTime := Min(Effect.FFadeTime, Effect.FTime)*1000;
439
    end;
452
    end;
440
  end;
453
  end;
441
 
454
 
442
  FillChar(Feff, SizeOf(Feff), 0);
455
  FillChar(Feff, SizeOf(Feff), 0);
443
  with Feff do
456
  with Feff do
444
  begin
457
  begin
445
    dwSize := SizeOf(Feff);
458
    dwSize := SizeOf(Feff);
446
    dwFlags := DIEFF_CARTESIAN or DIEFF_OBJECTOFFSETS;
459
    dwFlags := DIEFF_CARTESIAN or DIEFF_OBJECTOFFSETS;
447
    dwDuration := ConvertTime(Effect.FTime);
460
    dwDuration := ConvertTime(Effect.FTime);
448
    dwSamplePeriod := 0;
461
    dwSamplePeriod := 0;
449
    dwGain := Effect.FPower;
462
    dwGain := Effect.FPower;
450
    dwTriggerButton := DIEB_NOTRIGGER;
463
    dwTriggerButton := DIEB_NOTRIGGER;
451
    dwTriggerRepeatInterval := 0;
464
    dwTriggerRepeatInterval := 0;
452
    cAxes := FAxesCount;
465
    cAxes := FAxesCount;
453
    rgdwAxes := @FAxes;
466
    rgdwAxes := @FAxes;
454
    rglDirection := @FDirections;
467
    rglDirection := @FDirections;
455
    lpEnvelope := @FEnvelope;
468
    lpEnvelope := @FEnvelope;
456
    //dwStartDelay := Effect.FStartDelayTime;
469
    //dwStartDelay := Effect.FStartDelayTime;
457
  end;
470
  end;
458
end;
471
end;
459
 
472
 
460
procedure TForceFeedbackEffectObject.Release;
473
procedure TForceFeedbackEffectObject.Release;
461
begin
474
begin
462
  FEffect := nil;
475
  FEffect := nil;
463
end;
476
end;
464
 
477
 
465
{  TForceFeedbackEffect  }
478
{  TForceFeedbackEffect  }
466
 
479
 
467
constructor TForceFeedbackEffect.Create(AParent: TForceFeedbackEffect);
480
constructor TForceFeedbackEffect.Create(AParent: TForceFeedbackEffect);
468
begin
481
begin
469
  inherited Create;
482
  inherited Create;
470
  FParent := AParent;
483
  FParent := AParent;
471
  FList := TList.Create;
484
  FList := TList.Create;
472
 
485
 
473
  if FParent<>nil then
486
  if FParent<>nil then
474
  begin
487
  begin
475
    FParent.FList.Add(Self);
488
    FParent.FList.Add(Self);
476
    FRoot := FParent.FRoot;
489
    FRoot := FParent.FRoot;
477
  end else
490
  end else
478
  begin
491
  begin
479
    FName := 'Effects';
492
    FName := 'Effects';
480
    FRoot := Self as TForceFeedbackEffects;
493
    FRoot := Self as TForceFeedbackEffects;
481
  end;
494
  end;
482
 
495
 
483
  FObject := TForceFeedbackEffectObject.Create;
496
  FObject := TForceFeedbackEffectObject.Create;
484
  FObject2 := TForceFeedbackEffectObject.Create;
497
  FObject2 := TForceFeedbackEffectObject.Create;
485
 
498
 
486
  AttackTime := 0;
499
  AttackTime := 0;
487
  Constant := Point(0, 0);
500
  Constant := Point(0, 0);
488
  EffectType := etNone;
501
  EffectType := etNone;
489
  FadeTime := 0;
502
  FadeTime := 0;
490
  Period := 50;
503
  Period := 50;
491
  Power := 10000;
504
  Power := 10000;
492
  Time := 1000;
505
  Time := 1000;
493
end;
506
end;
494
 
507
 
495
destructor TForceFeedbackEffect.Destroy;
508
destructor TForceFeedbackEffect.Destroy;
496
begin
509
begin
497
  Clear;
510
  Clear;
498
  FObject.Free;
511
  FObject.Free;
499
  FObject2.Free;
512
  FObject2.Free;
500
  FList.Free;
513
  FList.Free;
501
  if FParent<>nil then
514
  if FParent<>nil then
502
    FParent.FList.Remove(Self);
515
    FParent.FList.Remove(Self);
503
  inherited Destroy;
516
  inherited Destroy;
504
end;
517
end;
505
 
518
 
506
function TForceFeedbackEffect.GetOwner: TPersistent;
519
function TForceFeedbackEffect.GetOwner: TPersistent;
507
begin
520
begin
508
  Result := Parent;
521
  Result := Parent;
509
end;
522
end;
510
 
523
 
511
procedure TForceFeedbackEffect.Assign(Source: TPersistent);
524
procedure TForceFeedbackEffect.Assign(Source: TPersistent);
512
var
525
var
513
  i: Integer;
526
  i: Integer;
514
begin
527
begin
515
  if Source is TForceFeedbackEffect then
528
  if Source is TForceFeedbackEffect then
516
  begin
529
  begin
517
    if Source<>Self then
530
    if Source<>Self then
518
    begin
531
    begin
519
      Clear;
532
      Clear;
520
 
533
 
521
      EffectType := etNone;
534
      EffectType := etNone;
522
 
535
 
523
      Name := TForceFeedbackEffect(Source).Name;
536
      Name := TForceFeedbackEffect(Source).Name;
524
 
537
 
525
      AttackLevel := TForceFeedbackEffect(Source).AttackLevel;
538
      AttackLevel := TForceFeedbackEffect(Source).AttackLevel;
526
      AttackTime := TForceFeedbackEffect(Source).AttackTime;
539
      AttackTime := TForceFeedbackEffect(Source).AttackTime;
527
      Constant := TForceFeedbackEffect(Source).Constant;
540
      Constant := TForceFeedbackEffect(Source).Constant;
528
      Condition := TForceFeedbackEffect(Source).Condition;
541
      Condition := TForceFeedbackEffect(Source).Condition;
529
      EffectType := TForceFeedbackEffect(Source).EffectType;
542
      EffectType := TForceFeedbackEffect(Source).EffectType;
530
      FadeLevel := TForceFeedbackEffect(Source).FadeLevel;
543
      FadeLevel := TForceFeedbackEffect(Source).FadeLevel;
531
      FadeTime := TForceFeedbackEffect(Source).FadeTime;
544
      FadeTime := TForceFeedbackEffect(Source).FadeTime;
532
      Period := TForceFeedbackEffect(Source).Period;
545
      Period := TForceFeedbackEffect(Source).Period;
533
      Power := TForceFeedbackEffect(Source).Power;
546
      Power := TForceFeedbackEffect(Source).Power;
534
      Time := TForceFeedbackEffect(Source).Time;
547
      Time := TForceFeedbackEffect(Source).Time;
535
      StartDelayTime := TForceFeedbackEffect(Source).StartDelayTime;
548
      StartDelayTime := TForceFeedbackEffect(Source).StartDelayTime;
536
 
549
 
537
      EffectType := TForceFeedbackEffect(Source).EffectType;
550
      EffectType := TForceFeedbackEffect(Source).EffectType;
538
 
551
 
539
      for i:=0 to TForceFeedbackEffect(Source).Count-1 do
552
      for i:=0 to TForceFeedbackEffect(Source).Count-1 do
540
        TForceFeedbackEffect.Create(Self).Assign(TForceFeedbackEffect(Source)[i]);
553
        TForceFeedbackEffect.Create(Self).Assign(TForceFeedbackEffect(Source)[i]);
541
    end;
554
    end;
542
  end else
555
  end else
543
    inherited Assign(Source);
556
    inherited Assign(Source);
544
end;
557
end;
545
 
558
 
546
procedure TForceFeedbackEffect.Acquire;
559
procedure TForceFeedbackEffect.Acquire;
547
var
560
var
548
  i: Integer;
561
  i: Integer;
549
begin
562
begin
550
  if Playing and (Time=-1) then
563
  if Playing and (Time=-1) then
551
    Start;
564
    Start;
552
 
565
 
553
  for i:=0 to Count-1 do
566
  for i:=0 to Count-1 do
554
    Effects[i].Initialize;
567
    Effects[i].Initialize;
555
end;
568
end;
556
 
569
 
557
procedure TForceFeedbackEffect.Clear;
570
procedure TForceFeedbackEffect.Clear;
558
begin
571
begin
559
  while Count>0 do
572
  while Count>0 do
560
    Effects[Count-1].Free;
573
    Effects[Count-1].Free;
561
end;
574
end;
562
 
575
 
563
procedure TForceFeedbackEffect.Initialize;
576
procedure TForceFeedbackEffect.Initialize;
564
var
577
var
565
  i: Integer;
578
  i: Integer;
566
begin
579
begin
567
  CreateEffect;
580
  CreateEffect;
568
  for i:=0 to Count-1 do
581
  for i:=0 to Count-1 do
569
    Effects[i].Initialize;
582
    Effects[i].Initialize;
570
end;
583
end;
571
 
584
 
572
procedure TForceFeedbackEffect.Finalize;
585
procedure TForceFeedbackEffect.Finalize;
573
var
586
var
574
  i: Integer;
587
  i: Integer;
575
begin
588
begin
576
  try
589
  try
577
    Stop;
590
    Stop;
578
    FObject.Release;
591
    FObject.Release;
579
    FObject2.Release;
592
    FObject2.Release;
580
  finally
593
  finally
581
    for i:=0 to Count-1 do
594
    for i:=0 to Count-1 do
582
      Effects[i].Finalize;
595
      Effects[i].Finalize;
583
  end;
596
  end;
584
end;
597
end;
585
 
598
 
586
function TForceFeedbackEffect.Find(const Name: string): TForceFeedbackEffect;
599
function TForceFeedbackEffect.Find(const Name: string): TForceFeedbackEffect;
587
var
600
var
588
  i, p: Integer;
601
  i, p: Integer;
589
  Effect: TForceFeedbackEffect;
602
  Effect: TForceFeedbackEffect;
590
  AName: string;
603
  AName: string;
591
begin
604
begin
592
  AName := Name;
605
  AName := Name;
593
  Effect := Self;
606
  Effect := Self;
594
 
607
 
595
  p := AnsiPos('.', AName);
608
  p := AnsiPos('.', AName);
596
  while p<>0 do
609
  while p<>0 do
597
  begin
610
  begin
598
    i := Effect.IndexOf(AName);
611
    i := Effect.IndexOf(AName);
599
    if i<>-1 then
612
    if i<>-1 then
600
    begin
613
    begin
601
      Result := Effect[i];
614
      Result := Effect[i];
602
      Exit;
615
      Exit;
603
    end else
616
    end else
604
    begin
617
    begin
605
      i := Effect.IndexOf(Copy(Name, 1, p-1));
618
      i := Effect.IndexOf(Copy(Name, 1, p-1));
606
      if i=-1 then
619
      if i=-1 then
607
        raise EForceFeedbackEffectError.CreateFmt(SEffectNotFound, [Name]);
620
        raise EForceFeedbackEffectError.CreateFmt(SEffectNotFound, [Name]);
608
      Effect := Effect[i];
621
      Effect := Effect[i];
609
      AName := Copy(Name, p+1, MaxInt);
622
      AName := Copy(Name, p+1, MaxInt);
610
      p := AnsiPos('.', AName);
623
      p := AnsiPos('.', AName);
611
    end;
624
    end;
612
  end;
625
  end;
613
 
626
 
614
  i := Effect.IndexOf(Name);
627
  i := Effect.IndexOf(Name);
615
  if i=-1 then
628
  if i=-1 then
616
    raise EForceFeedbackEffectError.CreateFmt(SEffectNotFound, [Name]);
629
    raise EForceFeedbackEffectError.CreateFmt(SEffectNotFound, [Name]);
617
  Result := Effect[i];
630
  Result := Effect[i];
618
end;
631
end;
619
 
632
 
620
function TForceFeedbackEffect.IndexOf(const Name: string): Integer;
633
function TForceFeedbackEffect.IndexOf(const Name: string): Integer;
621
var
634
var
622
  i: Integer;
635
  i: Integer;
623
begin
636
begin
624
  Result := -1;
637
  Result := -1;
625
  for i:=0 to Count-1 do
638
  for i:=0 to Count-1 do
626
    if Effects[i].Name=Name then
639
    if Effects[i].Name=Name then
627
    begin
640
    begin
628
      Result := i;
641
      Result := i;
629
      Break;
642
      Break;
630
    end;
643
    end;
631
end;
644
end;
632
 
645
 
633
function TForceFeedbackEffect.HasInterface: Boolean;
646
function TForceFeedbackEffect.HasInterface: Boolean;
634
begin
647
begin
635
  Result := (FEffectType<>etNone) and ((FObject.FEffect<>nil) or (FObject2.FEffect<>nil));
648
  Result := (FEffectType<>etNone) and ((FObject.FEffect<>nil) or (FObject2.FEffect<>nil));
636
end;
649
end;
637
 
650
 
638
procedure TForceFeedbackEffect.MakeEff;
651
procedure TForceFeedbackEffect.MakeEff;
639
var
652
var
640
  Constant2: TPoint;
653
  Constant2: TPoint;
641
begin
654
begin
642
  FObject.Clear;
655
  FObject.Clear;
643
  FObject2.Clear;
656
  FObject2.Clear;
644
 
657
 
645
  with Constant2 do
658
  with Constant2 do
646
  begin
659
  begin
647
    X := -FConstant.X;
660
    X := -FConstant.X;
648
    Y := -FConstant.Y;
661
    Y := -FConstant.Y;
649
  end;
662
  end;
650
 
663
 
651
  case FEffectType of
664
  case FEffectType of
652
    etConstantForce:  { etConstantForce }
665
    etConstantForce:  { etConstantForce }
653
        begin
666
        begin
654
          with FObject do
667
          with FObject do
655
          begin
668
          begin
656
            FDirections[0] := Constant2.X;
669
            FDirections[0] := Constant2.X;
657
            FDirections[1] := Constant2.Y;
670
            FDirections[1] := Constant2.Y;
658
 
671
 
659
            FAxesCount := 2;
672
            FAxesCount := 2;
660
            FAxes[0] := DIJOFS_X;
673
            FAxes[0] := DIJOFS_X;
661
            FAxes[1] := DIJOFS_Y;
674
            FAxes[1] := DIJOFS_Y;
662
 
675
 
663
            with Constant2 do
676
            with Constant2 do
664
              FConstantForce.lMagnitude := Trunc(Sqrt(X*X+Y*Y));
677
              FConstantForce.lMagnitude := Trunc(Sqrt(X*X+Y*Y));
665
 
678
 
666
            Init(Self);
679
            Init(Self);
667
            with Feff do
680
            with Feff do
668
            begin
681
            begin
669
              cbTypeSpecificParams := SizeOf(FConstantForce);
682
              cbTypeSpecificParams := SizeOf(FConstantForce);
670
              lpvTypeSpecificParams := @FConstantForce;
683
              lpvTypeSpecificParams := @FConstantForce;
671
            end;
684
            end;
672
          end;
685
          end;
673
        end;
686
        end;
674
    etPeriodic:       { etPeriodic }
687
    etPeriodic:       { etPeriodic }
675
        begin
688
        begin
676
          with FObject do
689
          with FObject do
677
          begin
690
          begin
678
            FDirections[0] := Constant2.X;
691
            FDirections[0] := Constant2.X;
679
            FDirections[1] := Constant2.Y;
692
            FDirections[1] := Constant2.Y;
680
 
693
 
681
            FAxesCount := 2;
694
            FAxesCount := 2;
682
            FAxes[0] := DIJOFS_X;
695
            FAxes[0] := DIJOFS_X;
683
            FAxes[1] := DIJOFS_Y;
696
            FAxes[1] := DIJOFS_Y;
684
 
697
 
685
            with FPeriodic do
698
            with FPeriodic do
686
            begin
699
            begin
687
              with Constant2 do
700
              with Constant2 do
688
                dwMagnitude := Trunc(Sqrt(X*X+Y*Y));
701
                dwMagnitude := Trunc(Sqrt(X*X+Y*Y));
689
              lOffset := 0;
702
              lOffset := 0;
690
              dwPhase := 0;
703
              dwPhase := 0;
691
              dwPeriod := ConvertTime(FPeriod);
704
              dwPeriod := ConvertTime(FPeriod);
692
            end;
705
            end;
693
 
706
 
694
            Init(Self);
707
            Init(Self);
695
            with Feff do
708
            with Feff do
696
            begin
709
            begin
697
              cbTypeSpecificParams := SizeOf(FPeriodic);
710
              cbTypeSpecificParams := SizeOf(FPeriodic);
698
              lpvTypeSpecificParams := @FPeriodic;
711
              lpvTypeSpecificParams := @FPeriodic;
699
            end;
712
            end;
700
          end;
713
          end;
701
        end;
714
        end;
702
    etCondition:      { etCondition }
715
    etCondition:      { etCondition }
703
        begin
716
        begin
704
          with FObject do
717
          with FObject do
705
          begin
718
          begin
706
            FillChar(FDirections, SizeOf(FDirections), 0);
719
            FillChar(FDirections, SizeOf(FDirections), 0);
707
 
720
 
708
            FAxesCount := 1;
721
            FAxesCount := 1;
709
            FAxes[0] := DIJOFS_X;
722
            FAxes[0] := DIJOFS_X;
710
                   
723
                   
711
            with FCondition do
724
            with FCondition do
712
            begin
725
            begin
713
              lOffset := -Constant2.X;
726
              lOffset := -Constant2.X;
714
              lPositiveCoefficient := Self.FCondition.X;
727
              lPositiveCoefficient := Self.FCondition.X;
715
              lNegativeCoefficient := -Self.FCondition.X;
728
              lNegativeCoefficient := -Self.FCondition.X;
716
              dwPositiveSaturation := 0;
729
              dwPositiveSaturation := 0;
717
              dwNegativeSaturation := 0;
730
              dwNegativeSaturation := 0;
718
              lDeadBand := 0;
731
              lDeadBand := 0;
719
            end;
732
            end;
720
 
733
 
721
            Init(Self);
734
            Init(Self);
722
            with Feff do
735
            with Feff do
723
            begin
736
            begin
724
              cbTypeSpecificParams := SizeOf(FCondition);
737
              cbTypeSpecificParams := SizeOf(FCondition);
725
              lpvTypeSpecificParams := @FCondition;
738
              lpvTypeSpecificParams := @FCondition;
726
            end;
739
            end;
727
          end;
740
          end;
728
 
741
 
729
          with FObject2 do
742
          with FObject2 do
730
          begin
743
          begin
731
            FillChar(FDirections, SizeOf(FDirections), 0);
744
            FillChar(FDirections, SizeOf(FDirections), 0);
732
 
745
 
733
            FAxesCount := 1;
746
            FAxesCount := 1;
734
            FAxes[0] := DIJOFS_Y;
747
            FAxes[0] := DIJOFS_Y;
735
 
748
 
736
            with FCondition do
749
            with FCondition do
737
            begin
750
            begin
738
              lOffset := -Constant2.Y;
751
              lOffset := -Constant2.Y;
739
              lPositiveCoefficient := Self.FCondition.Y;
752
              lPositiveCoefficient := Self.FCondition.Y;
740
              lNegativeCoefficient := -Self.FCondition.Y;
753
              lNegativeCoefficient := -Self.FCondition.Y;
741
              dwPositiveSaturation := 0;
754
              dwPositiveSaturation := 0;
742
              dwNegativeSaturation := 0;
755
              dwNegativeSaturation := 0;
743
              lDeadBand := 0;
756
              lDeadBand := 0;
744
            end;
757
            end;
745
 
758
 
746
            Init(Self);
759
            Init(Self);
747
            with Feff do
760
            with Feff do
748
            begin
761
            begin
749
              cbTypeSpecificParams := SizeOf(FCondition);
762
              cbTypeSpecificParams := SizeOf(FCondition);
750
              lpvTypeSpecificParams := @FCondition;
763
              lpvTypeSpecificParams := @FCondition;
751
            end;
764
            end;
752
          end;
765
          end;
753
        end;
766
        end;
754
  end;
767
  end;
755
end;
768
end;
756
 
769
 
757
procedure TForceFeedbackEffect.CreateEffect;
770
procedure TForceFeedbackEffect.CreateEffect;
758
                                           
771
                                           
759
  function FindEffectCallBack(const pdei: TDIEffectInfoA;
772
  function FindEffectCallBack(const pdei: TDIEffectInfoA;
760
    pvRef: Pointer): HRESULT; stdcall;
773
    pvRef: Pointer): HRESULT; stdcall;
761
  begin
774
  begin
762
    with TForceFeedbackEffect(pvRef) do
775
    with TForceFeedbackEffect(pvRef) do
763
    begin
776
    begin
764
      FFindEffectFlag := True;
777
      FFindEffectFlag := True;
765
      FFindEffectGUID := pdei.guid;
778
      FFindEffectGUID := pdei.guid;
766
    end;
779
    end;
767
 
780
 
768
    Result := DIENUM_STOP;
781
    Result := Integer(DIENUM_STOP);
769
  end;
782
  end;
770
 
783
 
771
  procedure CreateIEffectGuid(const GUID: TGUID;
784
  procedure CreateIEffectGuid(const GUID: TGUID;
772
    EffectObject: TForceFeedbackEffectObject);
785
    EffectObject: TForceFeedbackEffectObject);
773
  begin
786
  begin
774
    if EffectObject.Feff.dwSize=0 then Exit;
787
    if EffectObject.Feff.dwSize=0 then Exit;
775
 
788
 
776
    if FRoot.FInput.FDevice2<>nil then
789
    if FRoot.FInput.FDevice2<>nil then
777
      FRoot.FInput.FDevice2.CreateEffect(GUID, EffectObject.Feff, EffectObject.FEffect, nil);
790
      FRoot.FInput.FDevice2.CreateEffect(GUID, @EffectObject.Feff, EffectObject.FEffect, nil);
778
  end;
791
  end;
779
 
792
 
780
  procedure CreateIEffect(dwFlags: DWORD;
793
  procedure CreateIEffect(dwFlags: DWORD;
781
    EffectObject: TForceFeedbackEffectObject);
794
    EffectObject: TForceFeedbackEffectObject);
782
  begin
795
  begin
783
    if EffectObject.Feff.dwSize=0 then Exit;
796
    if EffectObject.Feff.dwSize=0 then Exit;
784
 
797
 
785
    if FRoot.FInput.FDevice2<>nil then
798
    if FRoot.FInput.FDevice2<>nil then
786
    begin
799
    begin
787
      FFindEffectFlag := False;
800
      FFindEffectFlag := False;
788
      FRoot.FInput.FDevice2.EnumEffects(@FindEffectCallBack,
801
      FRoot.FInput.FDevice2.EnumEffects(@FindEffectCallBack,
789
        Self, dwFlags);
802
        Self, dwFlags);
790
      if FFindEffectFlag then
803
      if FFindEffectFlag then
791
        CreateIEffectGuid(FFindEffectGUID, EffectObject);
804
        CreateIEffectGuid(FFindEffectGUID, EffectObject);
792
    end;
805
    end;
793
  end;
806
  end;
794
 
807
 
795
begin
808
begin
796
  FObject.Release;
809
  FObject.Release;
797
  FObject2.Release;
810
  FObject2.Release;
798
 
811
 
799
  if (FRoot.FInput=nil) or (FRoot.FInput.FDevice2=nil) or
812
  if (FRoot.FInput=nil) or (FRoot.FInput.FDevice2=nil) or
800
    (not FRoot.FInput.FForceFeedbackDevice) or
813
    (not FRoot.FInput.FForceFeedbackDevice) or
801
    (not FRoot.FInput.FForceFeedback) then Exit;
814
    (not FRoot.FInput.FForceFeedback) then Exit;
802
 
815
 
803
  if FEffectType=etNone then Exit;
816
  if FEffectType=etNone then Exit;
804
 
817
 
805
  MakeEff;
818
  MakeEff;
806
  case FEffectType of
819
  case FEffectType of
807
    etConstantForce:
820
    etConstantForce:
808
        begin
821
        begin
809
          CreateIEffectGUID(GUID_ConstantForce, FObject);
822
          CreateIEffectGUID(GUID_ConstantForce, FObject);
810
        end;
823
        end;
811
    etPeriodic:
824
    etPeriodic:
812
        begin
825
        begin
813
          CreateIEffect(DIEFT_PERIODIC, FObject);
826
          CreateIEffect(DIEFT_PERIODIC, FObject);
814
        end;
827
        end;
815
    etCondition:
828
    etCondition:
816
        begin
829
        begin
817
          CreateIEffect(DIEFT_CONDITION, FObject);
830
          CreateIEffect(DIEFT_CONDITION, FObject);
818
          CreateIEffect(DIEFT_CONDITION, FObject2);
831
          CreateIEffect(DIEFT_CONDITION, FObject2);
819
        end;
832
        end;
820
  end;
833
  end;
821
 
834
 
822
  if Playing and (Time=-1) then
835
  if Playing and (Time=-1) then
823
    Start;
836
    Start;
824
end;
837
end;
825
 
838
 
826
procedure TForceFeedbackEffect.ChangeEffect;
839
procedure TForceFeedbackEffect.ChangeEffect;
827
var
840
var
828
  dwFlags: DWORD;
841
  dwFlags: DWORD;
829
begin
842
begin
830
  if HasInterface then
843
  if HasInterface then
831
  begin
844
  begin
832
    MakeEff;
845
    MakeEff;
833
 
846
 
834
    dwFlags := DIEP_DIRECTION or DIEP_DURATION or DIEP_ENVELOPE or
847
    dwFlags := DIEP_DIRECTION or DIEP_DURATION or DIEP_ENVELOPE or
835
      DIEP_GAIN or DIEP_SAMPLEPERIOD or DIEP_TRIGGERBUTTON or
848
      DIEP_GAIN or DIEP_SAMPLEPERIOD or DIEP_TRIGGERBUTTON or
836
      DIEP_TRIGGERREPEATINTERVAL or DIEP_TYPESPECIFICPARAMS;
849
      DIEP_TRIGGERREPEATINTERVAL or DIEP_TYPESPECIFICPARAMS;
837
 
850
 
838
    if Playing then
851
    if Playing then
839
      dwFlags := dwFlags or DIEP_START;
852
      dwFlags := dwFlags or DIEP_START;
840
 
853
 
841
    if FObject.FEffect<>nil then FObject.FEffect.SetParameters(FObject.Feff, dwFlags);
854
    if FObject.FEffect<>nil then FObject.FEffect.SetParameters(FObject.Feff, dwFlags);
842
    if FObject2.FEffect<>nil then FObject2.FEffect.SetParameters(FObject2.Feff, dwFlags);
855
    if FObject2.FEffect<>nil then FObject2.FEffect.SetParameters(FObject2.Feff, dwFlags);
843
  end;
856
  end;
844
end;
857
end;
845
 
858
 
846
function TForceFeedbackEffect.GetPlaying: Boolean;
859
function TForceFeedbackEffect.GetPlaying: Boolean;
847
var
860
var
848
  dwFlags: DWORD;
861
  dwFlags: DWORD;
849
begin
862
begin
850
  Result := False;
863
  Result := False;
851
 
864
 
852
  if not FPlaying then Exit;
865
  if not FPlaying then Exit;
853
 
866
 
854
  if FPlaying and (FTime=-1) then
867
  if FPlaying and (FTime=-1) then
855
  begin
868
  begin
856
    Result := True;
869
    Result := True;
857
    Exit;
870
    Exit;
858
  end;
871
  end;
859
 
872
 
860
  if FObject.FEffect<>nil then
873
  if FObject.FEffect<>nil then
861
  begin
874
  begin
862
    dwFlags := 0;
875
    dwFlags := 0;
863
    FObject.FEffect.GetEffectStatus(dwFlags);
876
    FObject.FEffect.GetEffectStatus(dwFlags);
864
    if dwFlags and DIEGES_PLAYING<>0 then
877
    if dwFlags and DIEGES_PLAYING<>0 then
865
    begin
878
    begin
866
      Result := True;
879
      Result := True;
867
      Exit;
880
      Exit;
868
    end;
881
    end;
869
  end;
882
  end;
870
 
883
 
871
  if FObject2.FEffect<>nil then
884
  if FObject2.FEffect<>nil then
872
  begin
885
  begin
873
    dwFlags := 0;
886
    dwFlags := 0;
874
    FObject2.FEffect.GetEffectStatus(dwFlags);
887
    FObject2.FEffect.GetEffectStatus(dwFlags);
875
    if dwFlags and DIEGES_PLAYING<>0 then
888
    if dwFlags and DIEGES_PLAYING<>0 then
876
    begin
889
    begin
877
      Result := True;
890
      Result := True;
878
      Exit;
891
      Exit;
879
    end;
892
    end;
880
  end;
893
  end;
881
 
894
 
882
  if not Result then
895
  if not Result then
883
    FPlaying := False;
896
    FPlaying := False;
884
end;
897
end;
885
 
898
 
886
function TForceFeedbackEffect.GetCount: Integer;
899
function TForceFeedbackEffect.GetCount: Integer;
887
begin
900
begin
888
  Result := FList.Count;
901
  Result := FList.Count;
889
end;
902
end;
890
 
903
 
891
function TForceFeedbackEffect.GetEffect(Index: Integer): TForceFeedbackEffect;
904
function TForceFeedbackEffect.GetEffect(Index: Integer): TForceFeedbackEffect;
892
begin
905
begin
893
  Result :=FList[Index];
906
  Result :=FList[Index];
894
end;
907
end;
895
 
908
 
896
function TForceFeedbackEffect.GetIndex: Integer;
909
function TForceFeedbackEffect.GetIndex: Integer;
897
begin
910
begin
898
  if FParent<>nil then
911
  if FParent<>nil then
899
    Result := FParent.FList.IndexOf(Self)
912
    Result := FParent.FList.IndexOf(Self)
900
  else
913
  else
901
    Result := 0;
914
    Result := 0;
902
end;
915
end;
903
 
916
 
904
procedure TForceFeedbackEffect.SetIndex(Value: Integer);
917
procedure TForceFeedbackEffect.SetIndex(Value: Integer);
905
begin
918
begin
906
  if FParent<>nil then
919
  if FParent<>nil then
907
  begin
920
  begin
908
    FParent.FList.Remove(Self);
921
    FParent.FList.Remove(Self);
909
    FParent.FList.Insert(Value, Self);
922
    FParent.FList.Insert(Value, Self);
910
  end;
923
  end;
911
end;
924
end;
912
 
925
 
913
procedure TForceFeedbackEffect.SetParent(Value: TForceFeedbackEffect);
926
procedure TForceFeedbackEffect.SetParent(Value: TForceFeedbackEffect);
914
begin
927
begin
915
  if Parent<>Value then
928
  if Parent<>Value then
916
  begin
929
  begin
917
    if (Value=nil) or (FRoot<>Value.FRoot) then
930
    if (Value=nil) or (FRoot<>Value.FRoot) then
918
      raise EForceFeedbackEffectError.CreateFmt(SCannotChanged, ['Parent']);
931
      raise EForceFeedbackEffectError.CreateFmt(SCannotChanged, ['Parent']);
919
 
932
 
920
    FParent.FList.Remove(Self);
933
    FParent.FList.Remove(Self);
921
    FParent := Value;
934
    FParent := Value;
922
    FParent.FList.Add(Self);
935
    FParent.FList.Add(Self);
923
  end;
936
  end;
924
end;
937
end;
925
 
938
 
926
procedure TForceFeedbackEffect.SetAttackLevel(Value: Integer);
939
procedure TForceFeedbackEffect.SetAttackLevel(Value: Integer);
927
begin
940
begin
928
  if Value<0 then Value := 0;
941
  if Value<0 then Value := 0;
929
  if Value>10000 then Value := 10000;
942
  if Value>10000 then Value := 10000;
930
 
943
 
931
  if FAttackLevel<>Value then
944
  if FAttackLevel<>Value then
932
  begin
945
  begin
933
    FAttackLevel := Value;
946
    FAttackLevel := Value;
934
    ChangeEffect;
947
    ChangeEffect;
935
  end;
948
  end;
936
end;
949
end;
937
 
950
 
938
procedure TForceFeedbackEffect.SetAttackTime(Value: Integer);
951
procedure TForceFeedbackEffect.SetAttackTime(Value: Integer);
939
begin
952
begin
940
  if Value<0 then Value := 0;
953
  if Value<0 then Value := 0;
941
 
954
 
942
  if FAttackTime<>Value then
955
  if FAttackTime<>Value then
943
  begin
956
  begin
944
    FAttackTime := Value;
957
    FAttackTime := Value;
945
    ChangeEffect;
958
    ChangeEffect;
946
  end;
959
  end;
947
end;
960
end;
948
 
961
 
949
procedure TForceFeedbackEffect.SetCondition(Value: TPoint);
962
procedure TForceFeedbackEffect.SetCondition(Value: TPoint);
950
begin
963
begin
951
  with Value do
964
  with Value do
952
  begin
965
  begin
953
    if X<-10000 then X := -10000;
966
    if X<-10000 then X := -10000;
954
    if X>+10000 then X := +10000;
967
    if X>+10000 then X := +10000;
955
 
968
 
956
    if Y<-10000 then Y := -10000;
969
    if Y<-10000 then Y := -10000;
957
    if Y>+10000 then Y := +10000;
970
    if Y>+10000 then Y := +10000;
958
  end;
971
  end;
959
 
972
 
960
  if not CompareMem(@FCondition, @Value, SizeOf(FCondition)) then
973
  if not CompareMem(@FCondition, @Value, SizeOf(FCondition)) then
961
  begin
974
  begin
962
    FCondition := Value;
975
    FCondition := Value;
963
 
976
 
964
    if HasInterface then
977
    if HasInterface then
965
      ChangeEffect;
978
      ChangeEffect;
966
  end;
979
  end;
967
end;
980
end;
968
 
981
 
969
procedure TForceFeedbackEffect.SetConstant(Value: TPoint);
982
procedure TForceFeedbackEffect.SetConstant(Value: TPoint);
970
begin
983
begin
971
  with Value do
984
  with Value do
972
  begin
985
  begin
973
    if X<-10000 then X := -10000;
986
    if X<-10000 then X := -10000;
974
    if X>+10000 then X := +10000;
987
    if X>+10000 then X := +10000;
975
 
988
 
976
    if Y<-10000 then Y := -10000;
989
    if Y<-10000 then Y := -10000;
977
    if Y>+10000 then Y := +10000;
990
    if Y>+10000 then Y := +10000;
978
  end;
991
  end;
979
 
992
 
980
  if not CompareMem(@FConstant, @Value, SizeOf(FConstant)) then
993
  if not CompareMem(@FConstant, @Value, SizeOf(FConstant)) then
981
  begin
994
  begin
982
    FConstant := Value;
995
    FConstant := Value;
983
 
996
 
984
    if HasInterface then
997
    if HasInterface then
985
      ChangeEffect;
998
      ChangeEffect;
986
  end;
999
  end;
987
end;
1000
end;
988
 
1001
 
989
procedure TForceFeedbackEffect.SetEffectType(Value: TForceFeedbackEffectType);
1002
procedure TForceFeedbackEffect.SetEffectType(Value: TForceFeedbackEffectType);
990
begin
1003
begin
991
  if FEffectType<>Value then
1004
  if FEffectType<>Value then
992
  begin
1005
  begin
993
    FEffectType := Value;
1006
    FEffectType := Value;
994
    Stop;
1007
    Stop;
995
    CreateEffect;
1008
    CreateEffect;
996
  end;
1009
  end;
997
end;
1010
end;
998
 
1011
 
999
procedure TForceFeedbackEffect.SetFadeLevel(Value: Integer);
1012
procedure TForceFeedbackEffect.SetFadeLevel(Value: Integer);
1000
begin
1013
begin
1001
  if Value<0 then Value := 0;
1014
  if Value<0 then Value := 0;
1002
  if Value>10000 then Value := 10000;
1015
  if Value>10000 then Value := 10000;
1003
 
1016
 
1004
  if FFadeLevel<>Value then
1017
  if FFadeLevel<>Value then
1005
  begin
1018
  begin
1006
    FFadeLevel := Value;
1019
    FFadeLevel := Value;
1007
    ChangeEffect;
1020
    ChangeEffect;
1008
  end;
1021
  end;
1009
end;
1022
end;
1010
 
1023
 
1011
procedure TForceFeedbackEffect.SetFadeTime(Value: Integer);
1024
procedure TForceFeedbackEffect.SetFadeTime(Value: Integer);
1012
begin
1025
begin
1013
  if Value<0 then Value := 0;
1026
  if Value<0 then Value := 0;
1014
 
1027
 
1015
  if FFadeTime<>Value then
1028
  if FFadeTime<>Value then
1016
  begin
1029
  begin
1017
    FFadeTime := Value;
1030
    FFadeTime := Value;
1018
    ChangeEffect;
1031
    ChangeEffect;
1019
  end;
1032
  end;
1020
end;
1033
end;
1021
 
1034
 
1022
procedure TForceFeedbackEffect.SetPeriod(Value: Integer);
1035
procedure TForceFeedbackEffect.SetPeriod(Value: Integer);
1023
begin
1036
begin
1024
  if Value<0 then Value := 0;
1037
  if Value<0 then Value := 0;
1025
 
1038
 
1026
  if FPeriod<>Value then
1039
  if FPeriod<>Value then
1027
  begin
1040
  begin
1028
    FPeriod := Value;
1041
    FPeriod := Value;
1029
    ChangeEffect;
1042
    ChangeEffect;
1030
  end;
1043
  end;
1031
end;
1044
end;
1032
 
1045
 
1033
procedure TForceFeedbackEffect.SetPower(Value: Integer);
1046
procedure TForceFeedbackEffect.SetPower(Value: Integer);
1034
begin
1047
begin
1035
  if Value<0 then Value := 0;
1048
  if Value<0 then Value := 0;
1036
  if Value>10000 then Value := 10000;
1049
  if Value>10000 then Value := 10000;
1037
 
1050
 
1038
  if FPower<>Value then
1051
  if FPower<>Value then
1039
  begin
1052
  begin
1040
    FPower := Value;
1053
    FPower := Value;
1041
    ChangeEffect;
1054
    ChangeEffect;
1042
  end;
1055
  end;
1043
end;
1056
end;
1044
 
1057
 
1045
procedure TForceFeedbackEffect.SetTime(Value: Integer);
1058
procedure TForceFeedbackEffect.SetTime(Value: Integer);
1046
begin
1059
begin
1047
  if (Value<>-1) and (Value<0) then Value := 0;
1060
  if (Value<>-1) and (Value<0) then Value := 0;
1048
 
1061
 
1049
  if FTime<>Value then
1062
  if FTime<>Value then
1050
  begin
1063
  begin
1051
    FTime := Value;
1064
    FTime := Value;
1052
    Stop;
1065
    Stop;
1053
    ChangeEffect;
1066
    ChangeEffect;
1054
  end;
1067
  end;
1055
end;
1068
end;
1056
 
1069
 
1057
procedure TForceFeedbackEffect.SetStartDelayTime(Value: Integer);
1070
procedure TForceFeedbackEffect.SetStartDelayTime(Value: Integer);
1058
begin
1071
begin
1059
  if Value<0 then Value := 0;
1072
  if Value<0 then Value := 0;
1060
 
1073
 
1061
  if FStartDelayTime<>Value then
1074
  if FStartDelayTime<>Value then
1062
  begin
1075
  begin
1063
    FStartDelayTime := Value;
1076
    FStartDelayTime := Value;
1064
    Stop;
1077
    Stop;
1065
    ChangeEffect;
1078
    ChangeEffect;
1066
  end;
1079
  end;
1067
end;
1080
end;
1068
 
1081
 
1069
procedure TForceFeedbackEffect.Start;
1082
procedure TForceFeedbackEffect.Start;
1070
 
1083
 
1071
  procedure StartEffect(Effect: IDirectInputEffect);
1084
  procedure StartEffect(Effect: IDirectInputEffect);
1072
  var
1085
  var
1073
    hr: HRESULT;
1086
    hr: HRESULT;
1074
  begin
1087
  begin
1075
    if Effect<>nil then
1088
    if Effect<>nil then
1076
    begin
1089
    begin
1077
      hr := Effect.Start(1, 0);
1090
      hr := Effect.Start(1, 0);
1078
      if (hr=DIERR_INPUTLOST) or (hr=DIERR_NOTACQUIRED) then
1091
      if (hr=DIERR_INPUTLOST) or (hr=DIERR_NOTACQUIRED) then
1079
      begin
1092
      begin
1080
        FRoot.FInput.Acquire;
1093
        FRoot.FInput.Acquire;
1081
        Effect.Start(1, 0);
1094
        Effect.Start(1, 0);
1082
      end;
1095
      end;
1083
    end;
1096
    end;
1084
  end;
1097
  end;
1085
 
1098
 
1086
var
1099
var
1087
  i: Integer;
1100
  i: Integer;
1088
begin
1101
begin
1089
  for i:=0 to Count-1 do
1102
  for i:=0 to Count-1 do
1090
    Effects[i].Start;
1103
    Effects[i].Start;
1091
 
1104
 
1092
  if not HasInterface then
1105
  if not HasInterface then
1093
  begin
1106
  begin
1094
    CreateEffect;
1107
    CreateEffect;
1095
    if not HasInterface then Exit;
1108
    if not HasInterface then Exit;
1096
  end;
1109
  end;
1097
 
1110
 
1098
  StartEffect(FObject.FEffect);
1111
  StartEffect(FObject.FEffect);
1099
  StartEffect(FObject2.FEffect);
1112
  StartEffect(FObject2.FEffect);
1100
 
1113
 
1101
  FPlaying := True;
1114
  FPlaying := True;
1102
end;
1115
end;
1103
 
1116
 
1104
procedure TForceFeedbackEffect.Stop;
1117
procedure TForceFeedbackEffect.Stop;
1105
var
1118
var
1106
  i: Integer;
1119
  i: Integer;
1107
begin
1120
begin
1108
  if Playing then
1121
  if Playing then
1109
  begin
1122
  begin
1110
    FPlaying := False;
1123
    FPlaying := False;
1111
    if FObject.FEffect<>nil then FObject.FEffect.Stop;
1124
    if FObject.FEffect<>nil then FObject.FEffect.Stop;
1112
    if FObject2.FEffect<>nil then FObject2.FEffect.Stop;
1125
    if FObject2.FEffect<>nil then FObject2.FEffect.Stop;
1113
  end;
1126
  end;
1114
 
1127
 
1115
  for i:=0 to Count-1 do
1128
  for i:=0 to Count-1 do
1116
    Effects[i].Stop;
1129
    Effects[i].Stop;
1117
end;
1130
end;
1118
 
1131
 
1119
procedure TForceFeedbackEffect.Unload(Recurse: Boolean);
1132
procedure TForceFeedbackEffect.Unload(Recurse: Boolean);
1120
var
1133
var
1121
  i: Integer;
1134
  i: Integer;
1122
begin
1135
begin
1123
  if Playing then
1136
  if Playing then
1124
  begin
1137
  begin
1125
    if FObject.FEffect<>nil then FObject.FEffect.Stop;
1138
    if FObject.FEffect<>nil then FObject.FEffect.Stop;
1126
    if FObject2.FEffect<>nil then FObject2.FEffect.Stop;
1139
    if FObject2.FEffect<>nil then FObject2.FEffect.Stop;
1127
  end;
1140
  end;
1128
 
1141
 
1129
  if FObject.FEffect<>nil then FObject.FEffect.Unload;
1142
  if FObject.FEffect<>nil then FObject.FEffect.Unload;
1130
  if FObject2.FEffect<>nil then FObject2.FEffect.Unload;
1143
  if FObject2.FEffect<>nil then FObject2.FEffect.Unload;
1131
 
1144
 
1132
  if Recurse then
1145
  if Recurse then
1133
  begin
1146
  begin
1134
    for i:=0 to Count-1 do
1147
    for i:=0 to Count-1 do
1135
      Effects[i].Unload(True);
1148
      Effects[i].Unload(True);
1136
  end;
1149
  end;
1137
end;
1150
end;
1138
 
1151
 
1139
type
1152
type
1140
  TForceFeedbackEffectItem = class(TCollectionItem)
1153
  TForceFeedbackEffectItem = class(TCollectionItem)
1141
  private
1154
  private
1142
    FName: string;
1155
    FName: string;
1143
    FEffectType: TForceFeedbackEffectType;
1156
    FEffectType: TForceFeedbackEffectType;
1144
    FAttackLevel: Integer;
1157
    FAttackLevel: Integer;
1145
    FAttackTime: Integer;
1158
    FAttackTime: Integer;
1146
    FConditionX: Integer;
1159
    FConditionX: Integer;
1147
    FConditionY: Integer;
1160
    FConditionY: Integer;
1148
    FConstantX: Integer;
1161
    FConstantX: Integer;
1149
    FConstantY: Integer;
1162
    FConstantY: Integer;
1150
    FFadeLevel: Integer;
1163
    FFadeLevel: Integer;
1151
    FFadeTime: Integer;
1164
    FFadeTime: Integer;
1152
    FPeriod: Integer;
1165
    FPeriod: Integer;
1153
    FPower: Integer;
1166
    FPower: Integer;
1154
    FTime: Integer;
1167
    FTime: Integer;
1155
    FStartDelayTime: Integer;
1168
    FStartDelayTime: Integer;
1156
    FEffects: TCollection;
1169
    FEffects: TCollection;
1157
    function GetStoredEffects: Boolean;
1170
    function GetStoredEffects: Boolean;
1158
  public
1171
  public
1159
    constructor Create(Collection: TCollection); override;
1172
    constructor Create(Collection: TCollection); override;
1160
    destructor Destroy; override;
1173
    destructor Destroy; override;
1161
    procedure Assign(Source: TPersistent); override;
1174
    procedure Assign(Source: TPersistent); override;
1162
    procedure AssignTo(Dest: TPersistent); override;
1175
    procedure AssignTo(Dest: TPersistent); override;
1163
  published
1176
  published
1164
    property Name: string read FName write FName;
1177
    property Name: string read FName write FName;
1165
    property EffectType: TForceFeedbackEffectType read FEffectType write FEffectType;
1178
    property EffectType: TForceFeedbackEffectType read FEffectType write FEffectType;
1166
    property AttackLevel: Integer read FAttackLevel write FAttackLevel default 0;
1179
    property AttackLevel: Integer read FAttackLevel write FAttackLevel default 0;
1167
    property AttackTime: Integer read FAttackTime write FAttackTime default 0;
1180
    property AttackTime: Integer read FAttackTime write FAttackTime default 0;
1168
    property ConditionX: Integer read FConditionX write FConditionX default 0;
1181
    property ConditionX: Integer read FConditionX write FConditionX default 0;
1169
    property ConditionY: Integer read FConditionY write FConditionY default 0;
1182
    property ConditionY: Integer read FConditionY write FConditionY default 0;
1170
    property ConstantX: Integer read FConstantX write FConstantX default 0;
1183
    property ConstantX: Integer read FConstantX write FConstantX default 0;
1171
    property ConstantY: Integer read FConstantY write FConstantY default 0;
1184
    property ConstantY: Integer read FConstantY write FConstantY default 0;
1172
    property FadeLevel: Integer read FFadeLevel write FFadeLevel default 0;
1185
    property FadeLevel: Integer read FFadeLevel write FFadeLevel default 0;
1173
    property FadeTime: Integer read FFadeTime write FFadeTime default 0;
1186
    property FadeTime: Integer read FFadeTime write FFadeTime default 0;
1174
    property Period: Integer read FPeriod write FPeriod;
1187
    property Period: Integer read FPeriod write FPeriod;
1175
    property Power: Integer read FPower write FPower;
1188
    property Power: Integer read FPower write FPower;
1176
    property Time: Integer read FTime write FTime;
1189
    property Time: Integer read FTime write FTime;
1177
    property StartDelayTime: Integer read FStartDelayTime write FStartDelayTime;
1190
    property StartDelayTime: Integer read FStartDelayTime write FStartDelayTime;
1178
    property Effects: TCollection read FEffects write FEffects stored GetStoredEffects;
1191
    property Effects: TCollection read FEffects write FEffects stored GetStoredEffects;
1179
  end;
1192
  end;
1180
 
1193
 
1181
  TForceFeedbackEffectComponent = class(TComponent)
1194
  TForceFeedbackEffectComponent = class(TComponent)
1182
  private
1195
  private
1183
    FEffects: TCollection;
1196
    FEffects: TCollection;
1184
  published
1197
  published
1185
    property Effects: TCollection read FEffects write FEffects;
1198
    property Effects: TCollection read FEffects write FEffects;
1186
  end;
1199
  end;
1187
 
1200
 
1188
constructor TForceFeedbackEffectItem.Create(Collection: TCollection);
1201
constructor TForceFeedbackEffectItem.Create(Collection: TCollection);
1189
begin
1202
begin
1190
  inherited Create(Collection);
1203
  inherited Create(Collection);
1191
  FEffects := TCollection.Create(TForceFeedbackEffectItem);
1204
  FEffects := TCollection.Create(TForceFeedbackEffectItem);
1192
end;
1205
end;
1193
 
1206
 
1194
destructor TForceFeedbackEffectItem.Destroy;
1207
destructor TForceFeedbackEffectItem.Destroy;
1195
begin
1208
begin
1196
  FEffects.Free;
1209
  FEffects.Free;
1197
  inherited Destroy;
1210
  inherited Destroy;
1198
end;
1211
end;
1199
 
1212
 
1200
procedure TForceFeedbackEffectItem.Assign(Source: TPersistent);
1213
procedure TForceFeedbackEffectItem.Assign(Source: TPersistent);
1201
var
1214
var
1202
  Effect: TForceFeedbackEffect;
1215
  Effect: TForceFeedbackEffect;
1203
  i: Integer;
1216
  i: Integer;
1204
begin
1217
begin
1205
  Effect := Source as TForceFeedbackEffect;
1218
  Effect := Source as TForceFeedbackEffect;
1206
 
1219
 
1207
  FName := Effect.Name;
1220
  FName := Effect.Name;
1208
  FEffectType := Effect.EffectType;
1221
  FEffectType := Effect.EffectType;
1209
  FAttackLevel := Effect.AttackLevel;
1222
  FAttackLevel := Effect.AttackLevel;
1210
  FAttackTime := Effect.AttackTime;
1223
  FAttackTime := Effect.AttackTime;
1211
  FConditionX := Effect.Condition.X;
1224
  FConditionX := Effect.Condition.X;
1212
  FConditionY := Effect.Condition.Y;
1225
  FConditionY := Effect.Condition.Y;
1213
  FConstantX := Effect.Constant.X;
1226
  FConstantX := Effect.Constant.X;
1214
  FConstantY := Effect.Constant.Y;
1227
  FConstantY := Effect.Constant.Y;
1215
  FFadeLevel := Effect.FadeLevel;
1228
  FFadeLevel := Effect.FadeLevel;
1216
  FFadeTime := Effect.FadeTime;
1229
  FFadeTime := Effect.FadeTime;
1217
  FPeriod := Effect.Period;
1230
  FPeriod := Effect.Period;
1218
  FPower := Effect.Power;
1231
  FPower := Effect.Power;
1219
  FTime := Effect.Time;
1232
  FTime := Effect.Time;
1220
  FStartDelayTime := Effect.StartDelayTime;
1233
  FStartDelayTime := Effect.StartDelayTime;
1221
 
1234
 
1222
  for i:=0 to Effect.Count-1 do
1235
  for i:=0 to Effect.Count-1 do
1223
    TForceFeedbackEffectItem.Create(FEffects).Assign(Effect[i]);
1236
    TForceFeedbackEffectItem.Create(FEffects).Assign(Effect[i]);
1224
end;
1237
end;
1225
 
1238
 
1226
procedure TForceFeedbackEffectItem.AssignTo(Dest: TPersistent);
1239
procedure TForceFeedbackEffectItem.AssignTo(Dest: TPersistent);
1227
var
1240
var
1228
  Effect: TForceFeedbackEffect;
1241
  Effect: TForceFeedbackEffect;
1229
  i: Integer;
1242
  i: Integer;
1230
begin
1243
begin
1231
  Effect := Dest as TForceFeedbackEffect;
1244
  Effect := Dest as TForceFeedbackEffect;
1232
 
1245
 
1233
  Effect.EffectType := etNone;
1246
  Effect.EffectType := etNone;
1234
 
1247
 
1235
  Effect.Name := FName;
1248
  Effect.Name := FName;
1236
  Effect.AttackLevel := FAttackLevel;
1249
  Effect.AttackLevel := FAttackLevel;
1237
  Effect.AttackTime := FAttackTime;
1250
  Effect.AttackTime := FAttackTime;
1238
  Effect.Condition := Point(FConditionX, FConditionY);
1251
  Effect.Condition := Point(FConditionX, FConditionY);
1239
  Effect.Constant := Point(FConstantX, FConstantY);
1252
  Effect.Constant := Point(FConstantX, FConstantY);
1240
  Effect.FadeLevel := FFadeLevel;
1253
  Effect.FadeLevel := FFadeLevel;
1241
  Effect.FadeTime := FFadeTime;
1254
  Effect.FadeTime := FFadeTime;
1242
  Effect.Period := FPeriod;
1255
  Effect.Period := FPeriod;
1243
  Effect.Power := FPower;
1256
  Effect.Power := FPower;
1244
  Effect.Time := FTime;
1257
  Effect.Time := FTime;
1245
  Effect.StartDelayTime := FStartDelayTime;
1258
  Effect.StartDelayTime := FStartDelayTime;
1246
 
1259
 
1247
  Effect.EffectType := FEffectType;
1260
  Effect.EffectType := FEffectType;
1248
 
1261
 
1249
  for i:=0 to FEffects.Count-1 do
1262
  for i:=0 to FEffects.Count-1 do
1250
    TForceFeedbackEffectItem(FEffects.Items[i]).AssignTo(TForceFeedbackEffect.Create(Effect));
1263
    TForceFeedbackEffectItem(FEffects.Items[i]).AssignTo(TForceFeedbackEffect.Create(Effect));
1251
end;
1264
end;
1252
 
1265
 
1253
function TForceFeedbackEffectItem.GetStoredEffects: Boolean;
1266
function TForceFeedbackEffectItem.GetStoredEffects: Boolean;
1254
begin
1267
begin
1255
  Result := FEffects.Count>0;
1268
  Result := FEffects.Count>0;
1256
end;
1269
end;
1257
 
1270
 
1258
procedure TForceFeedbackEffect.LoadFromFile(const FileName: string);
1271
procedure TForceFeedbackEffect.LoadFromFile(const FileName: string);
1259
var
1272
var
1260
  Stream: TFileStream;
1273
  Stream: TFileStream;
1261
begin
1274
begin
1262
  Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
1275
  Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
1263
  try
1276
  try
1264
    LoadFromStream(Stream);
1277
    LoadFromStream(Stream);
1265
  finally
1278
  finally
1266
    Stream.Free;
1279
    Stream.Free;
1267
  end;
1280
  end;
1268
end;
1281
end;
1269
 
1282
 
1270
procedure TForceFeedbackEffect.LoadFromStream(Stream: TStream);
1283
procedure TForceFeedbackEffect.LoadFromStream(Stream: TStream);
1271
var
1284
var
1272
  Component: TForceFeedbackEffectComponent;
1285
  Component: TForceFeedbackEffectComponent;
1273
begin
1286
begin
1274
  Clear;
1287
  Clear;
1275
 
1288
 
1276
  Component := TForceFeedbackEffectComponent(FRoot.FComponent);
1289
  Component := TForceFeedbackEffectComponent(FRoot.FComponent);
1277
  try
1290
  try
1278
    Component.FEffects := TCollection.Create(TForceFeedbackEffectItem);
1291
    Component.FEffects := TCollection.Create(TForceFeedbackEffectItem);
1279
    Stream.ReadComponentRes(Component);
1292
    Stream.ReadComponentRes(Component);
1280
    TForceFeedbackEffectItem(Component.FEffects.Items[0]).AssignTo(Self);
1293
    TForceFeedbackEffectItem(Component.FEffects.Items[0]).AssignTo(Self);
1281
  finally
1294
  finally
1282
    Component.FEffects.Free;
1295
    Component.FEffects.Free;
1283
    Component.FEffects := nil;
1296
    Component.FEffects := nil;
1284
  end;
1297
  end;
1285
end;
1298
end;
1286
 
1299
 
1287
procedure TForceFeedbackEffect.SaveToFile(const FileName: string);
1300
procedure TForceFeedbackEffect.SaveToFile(const FileName: string);
1288
var
1301
var
1289
  Stream: TFileStream;
1302
  Stream: TFileStream;
1290
begin
1303
begin
1291
  Stream := TFileStream.Create(FileName, fmCreate);
1304
  Stream := TFileStream.Create(FileName, fmCreate);
1292
  try
1305
  try
1293
    SaveToStream(Stream);
1306
    SaveToStream(Stream);
1294
  finally
1307
  finally
1295
    Stream.Free;
1308
    Stream.Free;
1296
  end;
1309
  end;
1297
end;
1310
end;
1298
 
1311
 
1299
procedure TForceFeedbackEffect.SaveToStream(Stream: TStream);
1312
procedure TForceFeedbackEffect.SaveToStream(Stream: TStream);
1300
var
1313
var
1301
  Component: TForceFeedbackEffectComponent;
1314
  Component: TForceFeedbackEffectComponent;
1302
begin
1315
begin
1303
  Component := TForceFeedbackEffectComponent(FRoot.FComponent);
1316
  Component := TForceFeedbackEffectComponent(FRoot.FComponent);
1304
  try
1317
  try
1305
    Component.FEffects := TCollection.Create(TForceFeedbackEffectItem);
1318
    Component.FEffects := TCollection.Create(TForceFeedbackEffectItem);
1306
    TForceFeedbackEffectItem.Create(Component.FEffects).Assign(Self);
1319
    TForceFeedbackEffectItem.Create(Component.FEffects).Assign(Self);
1307
    Stream.WriteComponentRes('DelphiXForceFeedbackEffect', Component);
1320
    Stream.WriteComponentRes('DelphiXForceFeedbackEffect', Component);
1308
  finally
1321
  finally
1309
    Component.FEffects.Free;
1322
    Component.FEffects.Free;
1310
    Component.FEffects := nil;
1323
    Component.FEffects := nil;
1311
  end;
1324
  end;
1312
end;
1325
end;
1313
 
1326
 
1314
{  TForceFeedbackEffects  }
1327
{  TForceFeedbackEffects  }
1315
 
1328
 
1316
constructor TForceFeedbackEffects.Create(Input: TCustomInput);
1329
constructor TForceFeedbackEffects.Create(Input: TCustomInput);
1317
begin
1330
begin
1318
  inherited Create(nil);
1331
  inherited Create(nil);
1319
  FInput := Input;
1332
  FInput := Input;
1320
  FComponent := TForceFeedbackEffectComponent.Create(nil);
1333
  FComponent := TForceFeedbackEffectComponent.Create(nil);
1321
end;
1334
end;
1322
 
1335
 
1323
destructor TForceFeedbackEffects.Destroy;
1336
destructor TForceFeedbackEffects.Destroy;
1324
begin
1337
begin
1325
  FComponent.Free;
1338
  FComponent.Free;
1326
  inherited Destroy;
1339
  inherited Destroy;
1327
end;
1340
end;
1328
 
1341
 
1329
procedure TForceFeedbackEffects.DefineProperties(Filer: TFiler);
1342
procedure TForceFeedbackEffects.DefineProperties(Filer: TFiler);
1330
begin
1343
begin
1331
  inherited DefineProperties(Filer);
1344
  inherited DefineProperties(Filer);
1332
  Filer.DefineBinaryProperty('Effects', LoadFromStream, SaveToStream, True);
1345
  Filer.DefineBinaryProperty('Effects', LoadFromStream, SaveToStream, True);
1333
end;
1346
end;
1334
 
1347
 
1335
{  TCustomInput  }
1348
{  TCustomInput  }
1336
 
1349
 
1337
constructor TCustomInput.Create(DXInput: TCustomDXInput);
1350
constructor TCustomInput.Create(DXInput: TCustomDXInput);
1338
begin
1351
begin
1339
  inherited Create;
1352
  inherited Create;
1340
  FDXInput := DXInput;
1353
  FDXInput := DXInput;
1341
  FDXInput.FDevice.Add(Self);
1354
  FDXInput.FDevice.Add(Self);
1342
  FEffects := TForceFeedbackEffects.Create(Self);
1355
  FEffects := TForceFeedbackEffects.Create(Self);
1343
  FEnabled := True;
1356
  FEnabled := True;
1344
  FBindInputStates := True;
1357
  FBindInputStates := True;
1345
end;
1358
end;
1346
 
1359
 
1347
destructor TCustomInput.Destroy;
1360
destructor TCustomInput.Destroy;
1348
begin
1361
begin
1349
  Finalize;
1362
  Finalize;
1350
  FEffects.Free;
1363
  FEffects.Free;
1351
  FDXInput.FDevice.Remove(Self);
1364
  FDXInput.FDevice.Remove(Self);
1352
  inherited Destroy;
1365
  inherited Destroy;
1353
end;
1366
end;
1354
 
1367
 
1355
procedure TCustomInput.Acquire;
1368
procedure TCustomInput.Acquire;
1356
begin
1369
begin
1357
  if FDXInput.FActiveOnly and (GetForegroundWindow<>FDXInput.FForm.Handle) then
1370
  if FDXInput.FActiveOnly and (GetForegroundWindow<>FDXInput.FForm.Handle) then
1358
    Exit;
1371
    Exit;
1359
 
1372
 
1360
  if FDevice<>nil then
1373
  if FDevice<>nil then
1361
    FDevice.Acquire;
1374
    FDevice.Acquire;
1362
 
1375
 
1363
  FEffects.Acquire;
1376
  FEffects.Acquire;
1364
end;
1377
end;
1365
 
1378
 
1366
procedure TCustomInput.Finalize;
1379
procedure TCustomInput.Finalize;
1367
begin
1380
begin
1368
  if FDevice<>nil then FDevice.Unacquire;
1381
  if FDevice<>nil then FDevice.Unacquire;
1369
  FInitialized := False;
1382
  FInitialized := False;
1370
  FButtonCount := 0;
1383
  FButtonCount := 0;
1371
  FEffects.Finalize;
1384
  FEffects.Finalize;
1372
  FDevice := nil;
1385
  FDevice := nil;
1373
  FDevice2 := nil;
1386
  FDevice2 := nil;
1374
  FForceFeedbackDevice := False;
1387
  FForceFeedbackDevice := False;
1375
  FStates := [];
1388
  FStates := [];
1376
end;
1389
end;
1377
 
1390
 
1378
procedure TCustomInput.Initialize;
1391
procedure TCustomInput.Initialize;
1379
begin
1392
begin
1380
  FInitialized := True;
1393
  FInitialized := True;
1381
  FEffects.Initialize;
1394
  FEffects.Initialize;
1382
end;
1395
end;
1383
 
1396
 
1384
function TCustomInput.GetButton(Index: Integer): Boolean;
1397
function TCustomInput.GetButton(Index: Integer): Boolean;
1385
begin
1398
begin
1386
  if Index in [0..31] then
1399
  if Index in [0..31] then
1387
    Result := TDXInputState(Integer(isButton1)+Index) in FStates
1400
    Result := TDXInputState(Integer(isButton1)+Index) in FStates
1388
  else
1401
  else
1389
    Result := False;
1402
    Result := False;
1390
end;
1403
end;
1391
 
1404
 
1392
function TCustomInput.GetCooperativeLevel: Integer;
1405
function TCustomInput.GetCooperativeLevel: Integer;
1393
const
1406
const
1394
  Levels: array[Boolean] of Integer = (DISCL_NONEXCLUSIVE, DISCL_EXCLUSIVE);
1407
  Levels: array[Boolean] of Integer = (DISCL_NONEXCLUSIVE, DISCL_EXCLUSIVE);
1395
  Levels2: array[Boolean] of Integer = (DISCL_BACKGROUND, DISCL_FOREGROUND);
1408
  Levels2: array[Boolean] of Integer = (DISCL_BACKGROUND, DISCL_FOREGROUND);
1396
begin
1409
begin
1397
  Result := Levels[FForceFeedbackDevice and FForceFeedback] or Levels2[FDXInput.ActiveOnly];
1410
  Result := Levels[FForceFeedbackDevice and FForceFeedback] or Levels2[FDXInput.ActiveOnly];
1398
end;
1411
end;
1399
 
1412
 
1400
function TCustomInput.GetDeviceState(dwSize: Integer; var Data): Boolean;
1413
function TCustomInput.GetDeviceState(dwSize: Integer; var Data): Boolean;
1401
var
1414
var
1402
  hr: HRESULT;
1415
  hr: HRESULT;
1403
begin
1416
begin
1404
  FillChar(Data, dwSize, 0);
1417
  FillChar(Data, dwSize, 0);
1405
 
1418
 
1406
  if FDevice<>nil then
1419
  if FDevice<>nil then
1407
  begin
1420
  begin
1408
    hr := FDevice.GetDeviceState(dwSize, Data);
1421
    hr := FDevice.GetDeviceState(dwSize, @Data);
1409
    if (hr=DIERR_INPUTLOST) or (hr=DIERR_NOTACQUIRED) then
1422
    if (hr=DIERR_INPUTLOST) or (hr=DIERR_NOTACQUIRED) then
1410
    begin
1423
    begin
1411
      FDevice.Acquire;
1424
      FDevice.Acquire;
1412
      hr := FDevice.GetDeviceState(dwSize, Data);
1425
      hr := FDevice.GetDeviceState(dwSize, @Data);
1413
    end;
1426
    end;
1414
    Result := hr=DI_OK;
1427
    Result := hr=DI_OK;
1415
  end else
1428
  end else
1416
    Result := False;
1429
    Result := False;
1417
end;
1430
end;
1418
 
1431
 
1419
function TCustomInput.SetDataFormat: Boolean;
1432
function TCustomInput.SetDataFormat: Boolean;
1420
 
1433
 
1421
  function DIEnumDeviceObjectsProc(const peff: TDIDeviceObjectInstanceA;
1434
  function DIEnumDeviceObjectsProc(const peff: TDIDeviceObjectInstanceA;
1422
    pvRef: Pointer): HRESULT; stdcall;
1435
    pvRef: Pointer): HRESULT; stdcall;
1423
  begin
1436
  begin
1424
    Result := DIENUM_CONTINUE;
1437
    Result := Integer(DIENUM_CONTINUE);
1425
 
1438
 
1426
    if CompareMem(@peff.guidType, @GUID_Unknown, SizeOf(TGUID)) then Exit;
1439
    if CompareMem(@peff.guidType, @GUID_Unknown, SizeOf(TGUID)) then Exit;
1427
 
1440
 
1428
    with TCustomInput(pvRef) do
1441
    with TCustomInput(pvRef) do
1429
    begin
1442
    begin
1430
      if peff.dwOfs<FDataFormat.dwDataSize then
1443
      if peff.dwOfs<FDataFormat.dwDataSize then
1431
      begin
1444
      begin
1432
        FDataFormatGUIDs[FDataFormat.dwNumObjs] := peff.guidType;
1445
        FDataFormatGUIDs[FDataFormat.dwNumObjs] := peff.guidType;
1433
 
1446
 
1434
        with FDataFormatObjects[FDataFormat.dwNumObjs] do
1447
        with FDataFormatObjects[FDataFormat.dwNumObjs] do
1435
        begin
1448
        begin
1436
          pguid := @FDataFormatGUIDs[FDataFormat.dwNumObjs];
1449
          pguid := @FDataFormatGUIDs[FDataFormat.dwNumObjs];
1437
          dwOfs := peff.dwOfs;
1450
          dwOfs := peff.dwOfs;
1438
          dwType := peff.dwType;
1451
          dwType := peff.dwType;
1439
          dwFlags := 0;
1452
          dwFlags := 0;
1440
        end;
1453
        end;
1441
        Inc(FDataFormat.dwNumObjs);
1454
        Inc(FDataFormat.dwNumObjs);
1442
      end;
1455
      end;
1443
    end;
1456
    end;
1444
  end;
1457
  end;
1445
 
1458
 
1446
begin
1459
begin
1447
  Result := False;
1460
  Result := False;
1448
  if FDevice<>nil then
1461
  if FDevice<>nil then
1449
  begin
1462
  begin
1450
    with FDataFormat do
1463
    with FDataFormat do
1451
    begin
1464
    begin
1452
      dwSize := SizeOf(FDataFormat);
1465
      dwSize := SizeOf(FDataFormat);
1453
      dwObjSize := SizeOf(TDIObjectDataFormat);
1466
      dwObjSize := SizeOf(TDIObjectDataFormat);
1454
      dwNumObjs := 0;
1467
      dwNumObjs := 0;
1455
      rgodf := @FDataFormatObjects;
1468
      rgodf := @FDataFormatObjects;
1456
    end;
1469
    end;
1457
 
1470
 
1458
    FDevice.EnumObjects(@DIEnumDeviceObjectsProc, Self, DIDFT_ALL);
1471
    FDevice.EnumObjects(@DIEnumDeviceObjectsProc, Self, DIDFT_ALL);
1459
    if FDevice.SetDataFormat(FDataFormat)<>DI_OK then Exit;
1472
    if FDevice.SetDataFormat(FDataFormat)<>DI_OK then Exit;
1460
  end;
1473
  end;
1461
  Result := True;
1474
  Result := True;
1462
end;
1475
end;
1463
 
1476
 
1464
procedure TCustomInput.SetEffects(Value: TForceFeedbackEffects);
1477
procedure TCustomInput.SetEffects(Value: TForceFeedbackEffects);
1465
begin
1478
begin
1466
  FEffects.Assign(Value);
1479
  FEffects.Assign(Value);
1467
end;
1480
end;
1468
 
1481
 
1469
procedure TCustomInput.SetEnabled(Value: Boolean);
1482
procedure TCustomInput.SetEnabled(Value: Boolean);
1470
begin
1483
begin
1471
  if FEnabled<>Value then
1484
  if FEnabled<>Value then
1472
  begin
1485
  begin
1473
    FEnabled := Value;
1486
    FEnabled := Value;
1474
    if FDXInput.ComponentState*[csLoading, csReading]=[] then
1487
    if FDXInput.ComponentState*[csLoading, csReading]=[] then
1475
      Initialize;
1488
      Initialize;
1476
  end;
1489
  end;
1477
end;
1490
end;
1478
 
1491
 
1479
procedure TCustomInput.SetForceFeedback(Value: Boolean);
1492
procedure TCustomInput.SetForceFeedback(Value: Boolean);
1480
begin
1493
begin
1481
  if FForceFeedback<>Value then
1494
  if FForceFeedback<>Value then
1482
  begin
1495
  begin
1483
    FForceFeedback := Value;
1496
    FForceFeedback := Value;
1484
    if FDXInput.ComponentState*[csLoading, csReading]=[] then
1497
    if FDXInput.ComponentState*[csLoading, csReading]=[] then
1485
      Initialize;
1498
      Initialize;
1486
  end;
1499
  end;
1487
end;
1500
end;
1488
 
1501
 
1489
procedure TCustomInput.SetWindowHandle(Value: Integer);
1502
procedure TCustomInput.SetWindowHandle(Value: Integer);
1490
begin
1503
begin
1491
  if FDevice<>nil then
1504
  if FDevice<>nil then
1492
    FDevice.SetCooperativeLevel(Value, GetCooperativeLevel);
1505
    FDevice.SetCooperativeLevel(Value, GetCooperativeLevel);
1493
end;
1506
end;
1494
 
1507
 
1495
{  TKeyboard  }
1508
{  TKeyboard  }
1496
 
1509
 
1497
constructor TKeyboard.Create(DXInput: TCustomDXInput);
1510
constructor TKeyboard.Create(DXInput: TCustomDXInput);
1498
begin
1511
begin
1499
  inherited Create(DXInput);
1512
  inherited Create(DXInput);
1500
  KeyAssigns := DefKeyAssign;
1513
  KeyAssigns := DefKeyAssign;
1501
end;
1514
end;
1502
 
1515
 
1503
procedure TKeyboard.DefineProperties(Filer: TFiler);
1516
procedure TKeyboard.DefineProperties(Filer: TFiler);
1504
begin
1517
begin
1505
  inherited DefineProperties(Filer);
1518
  inherited DefineProperties(Filer);
1506
  Filer.DefineBinaryProperty('Aissgns', ReadAssigns, WriteAssigns, False);
1519
  Filer.DefineBinaryProperty('Aissgns', ReadAssigns, WriteAssigns, False);
1507
  Filer.DefineBinaryProperty('Assigns', ReadAssigns, WriteAssigns, True);
1520
  Filer.DefineBinaryProperty('Assigns', ReadAssigns, WriteAssigns, True);
1508
end;
1521
end;
1509
 
1522
 
1510
function TKeyboard.GetKey(Key: Integer): Boolean;
1523
function TKeyboard.GetKey(Key: Integer): Boolean;
1511
begin
1524
begin
1512
  if Key in [1..255] then
1525
  if Key in [1..255] then
1513
    Result := FKeyStates[Key] and $80<>0
1526
    Result := FKeyStates[Key] and $80<>0
1514
  else
1527
  else
1515
    Result := False;
1528
    Result := False;
1516
end;
1529
end;
1517
 
1530
 
1518
procedure TKeyboard.Finalize;
1531
procedure TKeyboard.Finalize;
1519
begin
1532
begin
1520
  FillChar(FKeyStates, SizeOf(FKeyStates), 0);
1533
  FillChar(FKeyStates, SizeOf(FKeyStates), 0);
1521
  inherited Finalize;
1534
  inherited Finalize;
1522
end;
1535
end;
1523
 
1536
 
1524
procedure TKeyboard.Initialize;
1537
procedure TKeyboard.Initialize;
1525
begin
1538
begin
1526
  Finalize;
1539
  Finalize;
1527
 
1540
 
1528
  if (not FEnabled) or (csDesigning in FDXInput.ComponentState) then Exit;
1541
  if (not FEnabled) or (csDesigning in FDXInput.ComponentState) then Exit;
1529
 
1542
 
1530
  if FDXInput.FDInput<>nil then
1543
  if FDXInput.FDInput<>nil then
1531
  begin
1544
  begin
1532
    if FDXInput.FDInput.CreateDevice(GUID_SysKeyboard, FDevice, nil)<>DI_OK then Exit;
1545
    if FDXInput.FDInput.CreateDevice(GUID_SysKeyboard, FDevice, nil)<>DI_OK then Exit;
1533
    FDevice.SetDataFormat(c_dfDIKeyboard);
1546
    FDevice.SetDataFormat(c_dfDIKeyboard);
1534
  end;
1547
  end;
1535
 
1548
 
1536
  FButtonCount := 32;
1549
  FButtonCount := 32;
1537
 
1550
 
1538
  inherited Initialize;
1551
  inherited Initialize;
1539
end;
1552
end;
1540
 
1553
 
1541
procedure TKeyboard.Update;
1554
procedure TKeyboard.Update;
1542
 
1555
 
1543
  function DIKEYtoVK(Key: Byte): Integer;
1556
  function DIKEYtoVK(Key: Byte): Integer;
1544
  begin
1557
  begin
1545
    Result := 0;
1558
    Result := 0;
1546
    case Key of
1559
    case Key of
1547
      DIK_ESCAPE       : Result := VK_ESCAPE;
1560
      DIK_ESCAPE       : Result := VK_ESCAPE;
1548
      DIK_1            : Result := Ord('1');
1561
      DIK_1            : Result := Ord('1');
1549
      DIK_2            : Result := Ord('2');
1562
      DIK_2            : Result := Ord('2');
1550
      DIK_3            : Result := Ord('3');
1563
      DIK_3            : Result := Ord('3');
1551
      DIK_4            : Result := Ord('4');
1564
      DIK_4            : Result := Ord('4');
1552
      DIK_5            : Result := Ord('5');
1565
      DIK_5            : Result := Ord('5');
1553
      DIK_6            : Result := Ord('6');
1566
      DIK_6            : Result := Ord('6');
1554
      DIK_7            : Result := Ord('7');
1567
      DIK_7            : Result := Ord('7');
1555
      DIK_8            : Result := Ord('8');
1568
      DIK_8            : Result := Ord('8');
1556
      DIK_9            : Result := Ord('9');
1569
      DIK_9            : Result := Ord('9');
1557
      DIK_0            : Result := Ord('0');
1570
      DIK_0            : Result := Ord('0');
1558
      DIK_EQUALS       : Result := Ord('=');
1571
      DIK_EQUALS       : Result := Ord('=');
1559
      DIK_BACK         : Result := VK_BACK;
1572
      DIK_BACK         : Result := VK_BACK;
1560
      DIK_TAB          : Result := VK_TAB;
1573
      DIK_TAB          : Result := VK_TAB;
1561
      DIK_Q            : Result := Ord('Q');
1574
      DIK_Q            : Result := Ord('Q');
1562
      DIK_W            : Result := Ord('W');
1575
      DIK_W            : Result := Ord('W');
1563
      DIK_E            : Result := Ord('E');
1576
      DIK_E            : Result := Ord('E');
1564
      DIK_R            : Result := Ord('R');
1577
      DIK_R            : Result := Ord('R');
1565
      DIK_T            : Result := Ord('T');
1578
      DIK_T            : Result := Ord('T');
1566
      DIK_Y            : Result := Ord('Y');
1579
      DIK_Y            : Result := Ord('Y');
1567
      DIK_U            : Result := Ord('U');
1580
      DIK_U            : Result := Ord('U');
1568
      DIK_I            : Result := Ord('I');
1581
      DIK_I            : Result := Ord('I');
1569
      DIK_O            : Result := Ord('O');
1582
      DIK_O            : Result := Ord('O');
1570
      DIK_P            : Result := Ord('P');
1583
      DIK_P            : Result := Ord('P');
1571
      DIK_LBRACKET     : Result := Ord('[');
1584
      DIK_LBRACKET     : Result := Ord('[');
1572
      DIK_RBRACKET     : Result := Ord(']');
1585
      DIK_RBRACKET     : Result := Ord(']');
1573
      DIK_RETURN       : Result := VK_RETURN;
1586
      DIK_RETURN       : Result := VK_RETURN;
1574
      DIK_LCONTROL     : Result := VK_CONTROL;
1587
      DIK_LCONTROL     : Result := VK_CONTROL;
1575
      DIK_A            : Result := Ord('A');
1588
      DIK_A            : Result := Ord('A');
1576
      DIK_S            : Result := Ord('S');
1589
      DIK_S            : Result := Ord('S');
1577
      DIK_D            : Result := Ord('D');
1590
      DIK_D            : Result := Ord('D');
1578
      DIK_F            : Result := Ord('F');
1591
      DIK_F            : Result := Ord('F');
1579
      DIK_G            : Result := Ord('G');
1592
      DIK_G            : Result := Ord('G');
1580
      DIK_H            : Result := Ord('H');
1593
      DIK_H            : Result := Ord('H');
1581
      DIK_J            : Result := Ord('J');
1594
      DIK_J            : Result := Ord('J');
1582
      DIK_K            : Result := Ord('K');
1595
      DIK_K            : Result := Ord('K');
1583
      DIK_L            : Result := Ord('L');
1596
      DIK_L            : Result := Ord('L');
1584
      DIK_SEMICOLON    : Result := Ord(';');
1597
      DIK_SEMICOLON    : Result := Ord(';');
1585
      DIK_APOSTROPHE   : Result := Ord('''');
1598
      DIK_APOSTROPHE   : Result := Ord('''');
1586
      DIK_LSHIFT       : Result := VK_SHIFT;
1599
      DIK_LSHIFT       : Result := VK_SHIFT;
1587
      DIK_BACKSLASH    : Result := Ord('\');
1600
      DIK_BACKSLASH    : Result := Ord('\');
1588
      DIK_Z            : Result := Ord('Z');
1601
      DIK_Z            : Result := Ord('Z');
1589
      DIK_X            : Result := Ord('X');
1602
      DIK_X            : Result := Ord('X');
1590
      DIK_C            : Result := Ord('C');
1603
      DIK_C            : Result := Ord('C');
1591
      DIK_V            : Result := Ord('V');
1604
      DIK_V            : Result := Ord('V');
1592
      DIK_B            : Result := Ord('B');
1605
      DIK_B            : Result := Ord('B');
1593
      DIK_N            : Result := Ord('N');
1606
      DIK_N            : Result := Ord('N');
1594
      DIK_M            : Result := Ord('M');
1607
      DIK_M            : Result := Ord('M');
1595
      DIK_COMMA        : Result := Ord(',');
1608
      DIK_COMMA        : Result := Ord(',');
1596
      DIK_PERIOD       : Result := Ord('.');
1609
      DIK_PERIOD       : Result := Ord('.');
1597
      DIK_SLASH        : Result := Ord('/');
1610
      DIK_SLASH        : Result := Ord('/');
1598
      DIK_RSHIFT       : Result := VK_SHIFT;
1611
      DIK_RSHIFT       : Result := VK_SHIFT;
1599
      DIK_MULTIPLY     : Result := Ord('*');
1612
      DIK_MULTIPLY     : Result := Ord('*');
1600
      DIK_LMENU        : Result := VK_MENU;
1613
      DIK_LMENU        : Result := VK_MENU;
1601
      DIK_SPACE        : Result := VK_SPACE;
1614
      DIK_SPACE        : Result := VK_SPACE;
1602
      DIK_CAPITAL      : Result := VK_CAPITAL;
1615
      DIK_CAPITAL      : Result := VK_CAPITAL;
1603
      DIK_F1           : Result := VK_F1;
1616
      DIK_F1           : Result := VK_F1;
1604
      DIK_F2           : Result := VK_F2;
1617
      DIK_F2           : Result := VK_F2;
1605
      DIK_F3           : Result := VK_F3;
1618
      DIK_F3           : Result := VK_F3;
1606
      DIK_F4           : Result := VK_F4;
1619
      DIK_F4           : Result := VK_F4;
1607
      DIK_F5           : Result := VK_F5;
1620
      DIK_F5           : Result := VK_F5;
1608
      DIK_F6           : Result := VK_F6;
1621
      DIK_F6           : Result := VK_F6;
1609
      DIK_F7           : Result := VK_F7;
1622
      DIK_F7           : Result := VK_F7;
1610
      DIK_F8           : Result := VK_F8;
1623
      DIK_F8           : Result := VK_F8;
1611
      DIK_F9           : Result := VK_F9;
1624
      DIK_F9           : Result := VK_F9;
1612
      DIK_F10          : Result := VK_F10;
1625
      DIK_F10          : Result := VK_F10;
1613
      DIK_NUMLOCK      : Result := VK_NUMLOCK;
1626
      DIK_NUMLOCK      : Result := VK_NUMLOCK;
1614
      DIK_SCROLL       : Result := VK_SCROLL;
1627
      DIK_SCROLL       : Result := VK_SCROLL;
1615
      DIK_NUMPAD7      : Result := VK_NUMPAD7;
1628
      DIK_NUMPAD7      : Result := VK_NUMPAD7;
1616
      DIK_NUMPAD8      : Result := VK_NUMPAD8;
1629
      DIK_NUMPAD8      : Result := VK_NUMPAD8;
1617
      DIK_NUMPAD9      : Result := VK_NUMPAD9;
1630
      DIK_NUMPAD9      : Result := VK_NUMPAD9;
1618
      DIK_SUBTRACT     : Result := VK_SUBTRACT;
1631
      DIK_SUBTRACT     : Result := VK_SUBTRACT;
1619
      DIK_NUMPAD4      : Result := VK_NUMPAD4;
1632
      DIK_NUMPAD4      : Result := VK_NUMPAD4;
1620
      DIK_NUMPAD5      : Result := VK_NUMPAD5;
1633
      DIK_NUMPAD5      : Result := VK_NUMPAD5;
1621
      DIK_NUMPAD6      : Result := VK_NUMPAD6;
1634
      DIK_NUMPAD6      : Result := VK_NUMPAD6;
1622
      DIK_ADD          : Result := VK_ADD;
1635
      DIK_ADD          : Result := VK_ADD;
1623
      DIK_NUMPAD1      : Result := VK_NUMPAD1;
1636
      DIK_NUMPAD1      : Result := VK_NUMPAD1;
1624
      DIK_NUMPAD2      : Result := VK_NUMPAD2;
1637
      DIK_NUMPAD2      : Result := VK_NUMPAD2;
1625
      DIK_NUMPAD3      : Result := VK_NUMPAD3;
1638
      DIK_NUMPAD3      : Result := VK_NUMPAD3;
1626
      DIK_NUMPAD0      : Result := VK_NUMPAD0;
1639
      DIK_NUMPAD0      : Result := VK_NUMPAD0;
1627
      DIK_DECIMAL      : Result := VK_DECIMAL;
1640
      DIK_DECIMAL      : Result := VK_DECIMAL;
1628
      DIK_F11          : Result := VK_F11;
1641
      DIK_F11          : Result := VK_F11;
1629
      DIK_F12          : Result := VK_F12;
1642
      DIK_F12          : Result := VK_F12;
1630
      DIK_NUMPADENTER  : Result := VK_RETURN;
1643
      DIK_NUMPADENTER  : Result := VK_RETURN;
1631
      DIK_RCONTROL     : Result := VK_CONTROL;
1644
      DIK_RCONTROL     : Result := VK_CONTROL;
1632
      DIK_DIVIDE       : Result := VK_DIVIDE;
1645
      DIK_DIVIDE       : Result := VK_DIVIDE;
1633
      DIK_RMENU        : Result := VK_MENU;
1646
      DIK_RMENU        : Result := VK_MENU;
1634
      DIK_HOME         : Result := VK_HOME;
1647
      DIK_HOME         : Result := VK_HOME;
1635
      DIK_UP           : Result := VK_UP;
1648
      DIK_UP           : Result := VK_UP;
1636
      DIK_PRIOR        : Result := VK_PRIOR;
1649
      DIK_PRIOR        : Result := VK_PRIOR;
1637
      DIK_LEFT         : Result := VK_LEFT;
1650
      DIK_LEFT         : Result := VK_LEFT;
1638
      DIK_RIGHT        : Result := VK_RIGHT;
1651
      DIK_RIGHT        : Result := VK_RIGHT;
1639
      DIK_END          : Result := VK_END;
1652
      DIK_END          : Result := VK_END;
1640
      DIK_DOWN         : Result := VK_DOWN;
1653
      DIK_DOWN         : Result := VK_DOWN;
1641
      DIK_NEXT         : Result := VK_NEXT;
1654
      DIK_NEXT         : Result := VK_NEXT;
1642
      DIK_INSERT       : Result := VK_INSERT;
1655
      DIK_INSERT       : Result := VK_INSERT;
1643
      DIK_DELETE       : Result := VK_DELETE;
1656
      DIK_DELETE       : Result := VK_DELETE;
1644
      DIK_LWIN         : Result := VK_LWIN;
1657
      DIK_LWIN         : Result := VK_LWIN;
1645
      DIK_RWIN         : Result := VK_RWIN;
1658
      DIK_RWIN         : Result := VK_RWIN;
1646
      DIK_APPS         : Result := VK_APPS;
1659
      DIK_APPS         : Result := VK_APPS;
1647
    end;
1660
    end;
1648
  end;
1661
  end;
-
 
1662
{$IFDEF StandardDX}
1649
 
1663
type
-
 
1664
  TDIKeyboardState = array[0..255] of Byte;
-
 
1665
{$ENDIF}
1650
var      
1666
var
1651
  j: Integer;
1667
  j: Integer;
1652
  i: TDXInputState;
1668
  i: TDXInputState;
1653
  dikb: TDIKeyboardState;
1669
  dikb: TDIKeyboardState;
1654
begin
1670
begin
1655
  FillChar(FKeyStates, SizeOf(FKeyStates), 0);
1671
  FillChar(FKeyStates, SizeOf(FKeyStates), 0);
1656
  FStates := [];
1672
  FStates := [];
1657
 
1673
 
1658
  if (not FInitialized) or FDXInput.FActiveOnly and (GetForegroundWindow<>FDXInput.FForm.Handle) then
1674
  if (not FInitialized) or FDXInput.FActiveOnly and (GetForegroundWindow<>FDXInput.FForm.Handle) then
1659
    Exit;
1675
    Exit;
1660
 
1676
 
1661
  if FDevice<>nil then
1677
  if FDevice<>nil then
1662
  begin
1678
  begin
1663
    FillChar(dikb, SizeOf(dikb), 0);
1679
    FillChar(dikb, SizeOf(dikb), 0);
1664
 
1680
 
1665
    if GetDeviceState(SizeOf(dikb), dikb) then
1681
    if GetDeviceState(SizeOf(dikb), dikb) then
1666
    begin
1682
    begin
1667
      {  The DirectInput key code is converted into the Windows virtual key code.  }
1683
      {  The DirectInput key code is converted into the Windows virtual key code.  }
1668
      for j:=Low(dikb) to High(dikb) do
1684
      for j:=Low(dikb) to High(dikb) do
1669
        if dikb[j] and $80<>0 then
1685
        if dikb[j] and $80<>0 then
1670
          FKeyStates[Byte(DIKEYtoVK(j))] := $80;
1686
          FKeyStates[Byte(DIKEYtoVK(j))] := $80;
1671
    end;
1687
    end;
1672
  end else
1688
  end else
1673
  begin          
1689
  begin          
1674
    GetKeyboardState(FKeyStates);
1690
    GetKeyboardState(FKeyStates);
1675
  end;
1691
  end;
1676
 
1692
 
1677
  for i:=LOW(TDXInputState) to HIGH(TDXInputState) do
1693
  for i:=LOW(TDXInputState) to HIGH(TDXInputState) do
1678
  begin
1694
  begin
1679
    for j:=0 to 2 do
1695
    for j:=0 to 2 do
1680
      if Keys[KeyAssigns[i, j]] then
1696
      if Keys[KeyAssigns[i, j]] then
1681
      begin
1697
      begin
1682
        FStates := FStates + [i];
1698
        FStates := FStates + [i];
1683
        Break;
1699
        Break;
1684
      end;
1700
      end;
1685
  end;
1701
  end;
1686
end;
1702
end;
1687
 
1703
 
1688
procedure TKeyboard.ReadAssigns(Stream: TStream);
1704
procedure TKeyboard.ReadAssigns(Stream: TStream);
1689
begin
1705
begin
1690
  Stream.ReadBuffer(KeyAssigns, SizeOf(KeyAssigns));
1706
  Stream.ReadBuffer(KeyAssigns, SizeOf(KeyAssigns));
1691
end;
1707
end;
1692
 
1708
 
1693
procedure TKeyboard.WriteAssigns(Stream: TStream);
1709
procedure TKeyboard.WriteAssigns(Stream: TStream);
1694
begin
1710
begin
1695
  Stream.WriteBuffer(KeyAssigns, SizeOf(KeyAssigns));
1711
  Stream.WriteBuffer(KeyAssigns, SizeOf(KeyAssigns));
1696
end;
1712
end;
1697
 
1713
 
1698
{  TMouse  }
1714
{  TMouse  }
1699
 
1715
 
1700
constructor TMouse.Create(DXInput: TCustomDXInput);
1716
constructor TMouse.Create(DXInput: TCustomDXInput);
1701
begin
1717
begin
1702
  inherited Create(DXInput);
1718
  inherited Create(DXInput);
1703
  BindInputStates := False;
1719
  BindInputStates := False;
1704
  Enabled := False;
1720
  Enabled := False;
1705
end;              
1721
end;              
1706
 
1722
 
1707
function TMouse.GetX: Integer;
1723
function TMouse.GetX: Integer;
1708
begin
1724
begin
1709
  Result := Fdims.lX;
1725
  Result := Fdims.lX;
1710
end;
1726
end;
1711
 
1727
 
1712
function TMouse.GetY: Integer;
1728
function TMouse.GetY: Integer;
1713
begin
1729
begin
1714
  Result := Fdims.lY;
1730
  Result := Fdims.lY;
1715
end;
1731
end;
1716
 
1732
 
1717
function TMouse.GetZ: Integer;
1733
function TMouse.GetZ: Integer;
1718
begin
1734
begin
1719
  Result := Fdims.lZ;
1735
  Result := Fdims.lZ;
1720
end;
1736
end;
1721
 
1737
 
1722
procedure TMouse.Finalize;
1738
procedure TMouse.Finalize;
1723
begin
1739
begin
1724
  FillChar(Fdims, SizeOf(Fdims), 0);
1740
  FillChar(Fdims, SizeOf(Fdims), 0);
1725
  inherited Finalize;
1741
  inherited Finalize;
1726
end;
1742
end;
1727
 
1743
 
1728
procedure TMouse.Initialize;
1744
procedure TMouse.Initialize;
1729
begin
1745
begin
1730
  Finalize;
1746
  Finalize;
1731
 
1747
 
1732
  if (not FEnabled) or (csDesigning in FDXInput.ComponentState) then Exit;
1748
  if (not FEnabled) or (csDesigning in FDXInput.ComponentState) then Exit;
1733
 
1749
 
1734
  if FDXInput.FDInput<>nil then
1750
  if FDXInput.FDInput<>nil then
1735
  begin
1751
  begin
1736
    if FDXInput.FDInput.CreateDevice(GUID_SysMouse, FDevice, nil)<>DI_OK then Exit;
1752
    if FDXInput.FDInput.CreateDevice(GUID_SysMouse, FDevice, nil)<>DI_OK then Exit;
1737
    FDevice.SetDataFormat(c_dfDIMouse);
1753
    FDevice.SetDataFormat(c_dfDIMouse);
1738
  end else
1754
  end else
1739
    raise EDXInputError.Create(SNecessaryDirectInputUseMouse);
1755
    raise EDXInputError.Create(SNecessaryDirectInputUseMouse);
1740
 
1756
 
1741
  FButtonCount := 3;
1757
  FButtonCount := 3;
1742
 
1758
 
1743
  inherited Initialize;
1759
  inherited Initialize;
1744
end;
1760
end;
1745
 
1761
 
1746
procedure TMouse.Update;
1762
procedure TMouse.Update;
1747
begin
1763
begin
1748
  FillChar(Fdims, SizeOf(Fdims), 0);
1764
  FillChar(Fdims, SizeOf(Fdims), 0);
1749
  FStates := [];
1765
  FStates := [];
1750
 
1766
 
1751
  if (not FInitialized) or FDXInput.FActiveOnly and (GetForegroundWindow<>FDXInput.FForm.Handle) then
1767
  if (not FInitialized) or FDXInput.FActiveOnly and (GetForegroundWindow<>FDXInput.FForm.Handle) then
1752
    Exit;
1768
    Exit;
1753
 
1769
 
1754
  if FDevice<>nil then
1770
  if FDevice<>nil then
1755
  begin
1771
  begin
1756
    FillChar(Fdims, SizeOf(Fdims), 0);
1772
    FillChar(Fdims, SizeOf(Fdims), 0);
1757
    GetDeviceState(SizeOf(Fdims), Fdims);
1773
    GetDeviceState(SizeOf(Fdims), Fdims);
1758
  end;
1774
  end;
1759
 
1775
 
1760
  if Fdims.lX<0 then FStates := FStates + [isLeft];
1776
  if Fdims.lX<0 then FStates := FStates + [isLeft];
1761
  if Fdims.lX>0 then FStates := FStates + [isRight];
1777
  if Fdims.lX>0 then FStates := FStates + [isRight];
1762
  if Fdims.lY<0 then FStates := FStates + [isUp];
1778
  if Fdims.lY<0 then FStates := FStates + [isUp];
1763
  if Fdims.lY>0 then FStates := FStates + [isDown];
1779
  if Fdims.lY>0 then FStates := FStates + [isDown];
1764
 
1780
 
1765
  if Fdims.rgbButtons[0] and $80<>0 then FStates := FStates + [isButton1];
1781
  if Fdims.rgbButtons[0] and $80<>0 then FStates := FStates + [isButton1];
1766
  if Fdims.rgbButtons[1] and $80<>0 then FStates := FStates + [isButton2];
1782
  if Fdims.rgbButtons[1] and $80<>0 then FStates := FStates + [isButton2];
1767
  if Fdims.rgbButtons[2] and $80<>0 then FStates := FStates + [isButton3];
1783
  if Fdims.rgbButtons[2] and $80<>0 then FStates := FStates + [isButton3];
1768
end;
1784
end;
1769
 
1785
 
1770
{  TJoystick  }
1786
{  TJoystick  }
1771
 
1787
 
1772
function SetDWORDProperty(pdev: IDirectInputDevice; guidProperty: PGUID;
1788
function SetDWORDProperty(pdev: IDirectInputDevice; guidProperty: PGUID;
1773
  dwObject, dwHow, dwValue: DWORD): HResult;
1789
  dwObject, dwHow, dwValue: DWORD): HResult;
1774
var
1790
var
1775
  dipdw: TDIPropDWORD;
1791
  dipdw: TDIPropDWORD;
1776
begin
1792
begin
1777
  dipdw.diph.dwSize       := SizeOf(dipdw);
1793
  dipdw.diph.dwSize       := SizeOf(dipdw);
1778
  dipdw.diph.dwHeaderSize := SizeOf(dipdw.diph);
1794
  dipdw.diph.dwHeaderSize := SizeOf(dipdw.diph);
1779
  dipdw.diph.dwObj        := dwObject;
1795
  dipdw.diph.dwObj        := dwObject;
1780
  dipdw.diph.dwHow        := dwHow;
1796
  dipdw.diph.dwHow        := dwHow;
1781
  dipdw.dwData            := dwValue;
1797
  dipdw.dwData            := dwValue;
1782
 
1798
 
1783
  Result := pdev.SetProperty(guidProperty, dipdw.diph);
1799
  Result := pdev.SetProperty(guidProperty, dipdw.diph);
1784
end;
1800
end;
1785
 
1801
 
1786
function SetRangeProperty(pdev: IDirectInputDevice; guidProperty: PGUID;
1802
function SetRangeProperty(pdev: IDirectInputDevice; guidProperty: PGUID;
1787
  dwObject, dwHow, Value: DWORD): HResult;
1803
  dwObject, dwHow, Value: DWORD): HResult;
1788
var
1804
var
1789
  diprg: TDIPropRange;
1805
  diprg: TDIPropRange;
1790
begin
1806
begin
1791
  diprg.diph.dwSize       := SizeOf(diprg);
1807
  diprg.diph.dwSize       := SizeOf(diprg);
1792
  diprg.diph.dwHeaderSize := SizeOf(diprg.diph);
1808
  diprg.diph.dwHeaderSize := SizeOf(diprg.diph);
1793
  diprg.diph.dwObj        := dwObject;
1809
  diprg.diph.dwObj        := dwObject;
1794
  diprg.diph.dwHow        := dwHow;
1810
  diprg.diph.dwHow        := dwHow;
1795
  diprg.lMin              := -Value;
1811
  diprg.lMin              := -Value;
1796
  diprg.lMax              := +Value;
1812
  diprg.lMax              := +Value;
1797
 
1813
 
1798
  Result := pdev.SetProperty(guidProperty, diprg.diph);
1814
  Result := pdev.SetProperty(guidProperty, diprg.diph);
1799
end;
1815
end;
1800
 
1816
 
1801
constructor TJoystick.Create(DXInput: TCustomDXInput);
1817
constructor TJoystick.Create(DXInput: TCustomDXInput);
1802
begin
1818
begin
1803
  inherited Create(DXInput);
1819
  inherited Create(DXInput);
1804
  FAutoCenter := True;
1820
  FAutoCenter := True;
1805
 
1821
 
1806
  FID := 0;
1822
  FID := 0;
1807
 
1823
 
1808
  DeadZoneX := 50;
1824
  DeadZoneX := 50;
1809
  DeadZoneY := 50;
1825
  DeadZoneY := 50;
1810
  DeadZoneZ := 50;
1826
  DeadZoneZ := 50;
1811
 
1827
 
1812
  RangeX := 1000;
1828
  RangeX := 1000;
1813
  RangeY := 1000;
1829
  RangeY := 1000;
1814
  RangeZ := 1000;
1830
  RangeZ := 1000;
1815
end;
1831
end;
1816
 
1832
 
1817
function TJoystick.GetX: Integer;
1833
function TJoystick.GetX: Integer;
1818
begin
1834
begin
1819
  Result := Fdijs.lX;
1835
  Result := Fdijs.lX;
1820
end;
1836
end;
1821
 
1837
 
1822
function TJoystick.GetY: Integer;
1838
function TJoystick.GetY: Integer;
1823
begin
1839
begin
1824
  Result := Fdijs.lY;
1840
  Result := Fdijs.lY;
1825
end;
1841
end;
1826
 
1842
 
1827
function TJoystick.GetZ: Integer;
1843
function TJoystick.GetZ: Integer;
1828
begin
1844
begin
1829
  Result := Fdijs.lZ;
1845
  Result := Fdijs.lZ;
1830
end;
1846
end;
1831
 
1847
 
1832
procedure TJoystick.Finalize;
1848
procedure TJoystick.Finalize;
1833
begin
1849
begin
1834
  FID2 := -1;
1850
  FID2 := -1;
1835
  FillChar(Fdijs, SizeOf(Fdijs), 0);
1851
  FillChar(Fdijs, SizeOf(Fdijs), 0);
1836
  FillChar(FJoyCaps, SizeOf(FJoyCaps), 0);
1852
  FillChar(FJoyCaps, SizeOf(FJoyCaps), 0);
1837
  inherited Finalize;
1853
  inherited Finalize;
1838
end;
1854
end;
1839
 
1855
 
1840
function TJoystick.GetCooperativeLevel: Integer;
1856
function TJoystick.GetCooperativeLevel: Integer;
1841
begin
1857
begin
1842
  if not FAutoCenter then
1858
  if not FAutoCenter then
1843
    Result := DISCL_EXCLUSIVE or DISCL_FOREGROUND
1859
    Result := DISCL_EXCLUSIVE or DISCL_FOREGROUND
1844
  else
1860
  else
1845
    Result := inherited GetCooperativeLevel;
1861
    Result := inherited GetCooperativeLevel;
1846
end;
1862
end;
1847
                                                       
1863
                                                       
1848
function TJoystick_EnumJoysticksCallback(const lpddi: TDIDeviceInstanceA;
1864
function TJoystick_EnumJoysticksCallback(const lpddi: TDIDeviceInstanceA;
1849
  pvRef: Pointer): HRESULT; stdcall;
1865
  pvRef: Pointer): HRESULT; stdcall;
1850
begin
1866
begin
1851
  Result := DIENUM_CONTINUE;
1867
  Result := Integer(DIENUM_CONTINUE);
1852
 
1868
 
1853
  with TJoystick(pvRef) do
1869
  with TJoystick(pvRef) do
1854
  begin
1870
  begin
1855
    if FEnumIndex=FID then
1871
    if FEnumIndex=FID then
1856
    begin
1872
    begin
1857
      FDeviceGUID := lpddi.guidInstance;
1873
      FDeviceGUID := lpddi.guidInstance;
1858
      FEnumFlag := True;
1874
      FEnumFlag := True;
1859
      Result := DIENUM_STOP;
1875
      Result := Integer(DIENUM_STOP);
1860
      Exit;
1876
      Exit;
1861
    end;
1877
    end;
1862
    Inc(FEnumIndex);
1878
    Inc(FEnumIndex);
1863
  end;
1879
  end;
1864
end;
1880
end;
1865
 
1881
 
1866
procedure TJoystick.Initialize;
1882
procedure TJoystick.Initialize;
1867
var
1883
var
1868
  i, j: Integer;
1884
  i, j: Integer;
1869
  devcaps: TDIDevCaps;
1885
  devcaps: TDIDevCaps;
1870
begin        
1886
begin        
1871
  Finalize;
1887
  Finalize;
1872
 
1888
 
1873
  if (not FEnabled) or (FID<0) or (csDesigning in FDXInput.ComponentState) then Exit;
1889
  if (not FEnabled) or (FID<0) or (csDesigning in FDXInput.ComponentState) then Exit;
1874
 
1890
 
1875
  try
1891
  try
1876
    try
1892
    try
1877
      if FDXInput.FDInput<>nil then
1893
      if FDXInput.FDInput<>nil then
1878
      begin
1894
      begin
1879
        {  Device search.  }
1895
        {  Device search.  }
1880
        FEnumFlag := False;
1896
        FEnumFlag := False;
1881
        FEnumIndex := 0;
1897
        FEnumIndex := 0;
1882
 
1898
 
1883
        FDXInput.FDInput.EnumDevices(DIDEVTYPE_JOYSTICK, @TJoystick_EnumJoysticksCallback,
1899
        FDXInput.FDInput.EnumDevices({DIDEVTYPE_JOYSTICK}4, @TJoystick_EnumJoysticksCallback,
1884
          Self, DIEDFL_ATTACHEDONLY);
1900
          Self, DIEDFL_ATTACHEDONLY);
1885
 
1901
 
1886
        if not FEnumFlag then Exit;
1902
        if not FEnumFlag then Exit;
1887
 
1903
 
1888
        {  Device making.  }
1904
        {  Device making.  }
1889
        if FDXInput.FDInput.CreateDevice(FDeviceGUID, FDevice, nil)<>DI_OK then Exit;
1905
        if FDXInput.FDInput.CreateDevice(FDeviceGUID, FDevice, nil)<>DI_OK then Exit;
1890
 
1906
 
1891
        devcaps.dwSize := SizeOf(devcaps);
1907
        devcaps.dwSize := SizeOf(devcaps);
1892
        if FDevice.GetCapabilities(devcaps)=DI_OK then
1908
        if FDevice.GetCapabilities(devcaps)=DI_OK then
1893
        begin
1909
        begin
1894
          FButtonCount := devcaps.dwButtons;
1910
          FButtonCount := devcaps.dwButtons;
1895
          if devcaps.dwFlags and DIDC_FORCEFEEDBACK<>0 then
1911
          if devcaps.dwFlags and DIDC_FORCEFEEDBACK<>0 then
1896
            FForceFeedbackDevice := True;
1912
            FForceFeedbackDevice := True;
1897
        end;
1913
        end;
1898
 
1914
 
1899
        if FDXInput.FDInput.CreateDevice(GUID_Joystick, FDevice, nil)<>DI_OK then Exit;
1915
        //if FDXInput.FDInput.CreateDevice(GUID_Joystick, FDevice, nil)<>DI_OK then Exit;   get out by Paul van Dinther
1900
 
1916
 
1901
        {  Device data format (TDIDataFormat) making.  }
1917
        {  Device data format (TDIDataFormat) making.  }
1902
 
1918
 
1903
        with FDataFormat do
1919
        with FDataFormat do
1904
        begin
1920
        begin
1905
          dwFlags := DIDF_ABSAXIS;
1921
          dwFlags := DIDF_ABSAXIS;
1906
          dwDataSize := SizeOf(Fdijs);
1922
          dwDataSize := SizeOf(Fdijs);
1907
        end;            
1923
        end;            
1908
 
1924
 
1909
        if not SetDataFormat then
1925
        if not SetDataFormat then
1910
        begin
1926
        begin
1911
          FDevice := nil;
1927
          FDevice := nil;
1912
          Exit;
1928
          Exit;
1913
        end;
1929
        end;
1914
         
1930
         
1915
        AutoCenter := FAutoCenter;
1931
        AutoCenter := FAutoCenter;
1916
 
1932
 
1917
        for i:=Low(FDeadZone) to High(FDeadZone) do
1933
        for i:=Low(FDeadZone) to High(FDeadZone) do
1918
          SetDeadZone(i, FDeadZone[i]);
1934
          SetDeadZone(i, FDeadZone[i]);
1919
 
1935
 
1920
        for i:=Low(FRange) to High(FRange) do
1936
        for i:=Low(FRange) to High(FRange) do
1921
          SetRange(i, FRange[i]);
1937
          SetRange(i, FRange[i]);
1922
 
1938
 
1923
        FDevice2 := FDevice as IDirectInputDevice2;
1939
        FDevice2 := FDevice as IDirectInputDevice2;
1924
      end;
1940
      end;
1925
    except
1941
    except
1926
      Finalize;
1942
      Finalize;
1927
      raise;
1943
      raise;
1928
    end;
1944
    end;
1929
  finally
1945
  finally
1930
    if FDevice=nil then
1946
    if FDevice=nil then
1931
    begin
1947
    begin
1932
      {  Because DirectInput cannot be used,  the GetJoyPosEx function is used.  }
1948
      {  Because DirectInput cannot be used,  the GetJoyPosEx function is used.  }
1933
      FID2 := -1;
1949
      FID2 := -1;
1934
 
1950
 
1935
      j := 0;
1951
      j := 0;
1936
      for i:=0 to 255 do
1952
      for i:=0 to 255 do
1937
      begin
1953
      begin
1938
        FillChar(FJoyCaps, SizeOf(FJoyCaps), 0);
1954
        FillChar(FJoyCaps, SizeOf(FJoyCaps), 0);
1939
        if joyGetDevCaps(i, @FJoyCaps, SizeOf(FJoyCaps))=JOYERR_NOERROR then
1955
        if joyGetDevCaps(i, @FJoyCaps, SizeOf(FJoyCaps))=JOYERR_NOERROR then
1940
        begin
1956
        begin
1941
          if FID=j then
1957
          if FID=j then
1942
          begin
1958
          begin
1943
            FID2 := i;
1959
            FID2 := i;
1944
            Break;
1960
            Break;
1945
          end;
1961
          end;
1946
          Inc(j);
1962
          Inc(j);
1947
        end;
1963
        end;
1948
      end;
1964
      end;
1949
 
1965
 
1950
      if FID2<>-1 then
1966
      if FID2<>-1 then
1951
      begin
1967
      begin
1952
        if joyGetDevCaps(FID2, @FJoyCaps, SizeOf(FJoyCaps))=JOYERR_NOERROR then
1968
        if joyGetDevCaps(FID2, @FJoyCaps, SizeOf(FJoyCaps))=JOYERR_NOERROR then
1953
        begin
1969
        begin
1954
          FButtonCount := FJoyCaps.wNumButtons;
1970
          FButtonCount := FJoyCaps.wNumButtons;
1955
        end else
1971
        end else
1956
        begin
1972
        begin
1957
          FID2 := -1;
1973
          FID2 := -1;
1958
        end;
1974
        end;
1959
      end;
1975
      end;
1960
    end;
1976
    end;
1961
  end;
1977
  end;
1962
 
1978
 
1963
  inherited Initialize;
1979
  inherited Initialize;
1964
end;
1980
end;
1965
 
1981
 
1966
procedure TJoystick.SetAutoCenter(Value: Boolean);
1982
procedure TJoystick.SetAutoCenter(Value: Boolean);
1967
begin
1983
begin
1968
  FAutoCenter := Value;
1984
  FAutoCenter := Value;
1969
 
1985
 
1970
  if FDevice<>nil then
1986
  if FDevice<>nil then
1971
    SetDWORDProperty(FDevice, DIPROP_AUTOCENTER, 0, DIPH_DEVICE, Ord(Value));
1987
    SetDWORDProperty(FDevice, DIPROP_AUTOCENTER, 0, DIPH_DEVICE, Ord(Value));
1972
end;
1988
end;
1973
 
1989
 
1974
procedure TJoystick.SetID(Value: Integer);
1990
procedure TJoystick.SetID(Value: Integer);
1975
begin
1991
begin
1976
  if Value<>FID then
1992
  if Value<>FID then
1977
  begin
1993
  begin
1978
    FID := Value;
1994
    FID := Value;
1979
    Initialize;
1995
    Initialize;
1980
  end;
1996
  end;
1981
end;
1997
end;
1982
 
1998
 
1983
function TJoystick.GetDeadZone(Obj: Integer): Integer;
1999
function TJoystick.GetDeadZone(Obj: Integer): Integer;
1984
begin
2000
begin
1985
  Result := 0;
2001
  Result := 0;
1986
  if (Obj>=Low(FDeadZone)) and (Obj<High(FDeadZone)) then
2002
  if (Obj>=Low(FDeadZone)) and (Obj<High(FDeadZone)) then
1987
    Result := FDeadZone[Obj];
2003
    Result := FDeadZone[Obj];
1988
end;
2004
end;
1989
 
2005
 
1990
function TJoystick.GetRange(Obj: Integer): Integer;
2006
function TJoystick.GetRange(Obj: Integer): Integer;
1991
begin
2007
begin
1992
  Result := 0;
2008
  Result := 0;
1993
  if (Obj>=Low(FRange)) and (Obj<High(FRange)) then
2009
  if (Obj>=Low(FRange)) and (Obj<High(FRange)) then
1994
    Result := FRange[Obj];
2010
    Result := FRange[Obj];
1995
end;
2011
end;
1996
 
2012
 
1997
procedure TJoystick.SetDeadZone(Obj: Integer; Value: Integer);
2013
procedure TJoystick.SetDeadZone(Obj: Integer; Value: Integer);
1998
begin
2014
begin
1999
  if (Obj<Low(FDeadZone)) or (Obj>=High(FDeadZone)) then Exit;
2015
  if (Obj<Low(FDeadZone)) or (Obj>=High(FDeadZone)) then Exit;
2000
 
2016
 
2001
  if Value<0 then Value := 0;
2017
  if Value<0 then Value := 0;
2002
  if Value>100 then Value := 100;
2018
  if Value>100 then Value := 100;
2003
 
2019
 
2004
  if Obj=Integer(@PDIJoyState2(nil).rgdwPOV[0]) then
2020
  if Obj=Integer(@PDIJoyState2(nil).rgdwPOV[0]) then
2005
  begin
2021
  begin
2006
    FDeadZone[Obj] := -1;
2022
    FDeadZone[Obj] := -1;
2007
    Exit;
2023
    Exit;
2008
  end;
2024
  end;
2009
 
2025
 
2010
  FDeadZone[Obj] := Value;
2026
  FDeadZone[Obj] := Value;
2011
 
2027
 
2012
  if FDevice<>nil then
2028
  if FDevice<>nil then
2013
  begin
2029
  begin
2014
    if SetDWORDProperty(FDevice, DIPROP_DEADZONE, Obj, DIPH_BYOFFSET, Value*100)<>DI_OK then
2030
    if SetDWORDProperty(FDevice, DIPROP_DEADZONE, Obj, DIPH_BYOFFSET, Value*100)<>DI_OK then
2015
      FDeadZone[Obj] := -1;
2031
      FDeadZone[Obj] := -1;
2016
  end;
2032
  end;
2017
end;
2033
end;
2018
 
2034
 
2019
procedure TJoystick.SetRange(Obj: Integer; Value: Integer);
2035
procedure TJoystick.SetRange(Obj: Integer; Value: Integer);
2020
begin
2036
begin
2021
  if (Obj<Low(FRange)) or (Obj>=High(FRange)) then Exit;
2037
  if (Obj<Low(FRange)) or (Obj>=High(FRange)) then Exit;
2022
 
2038
 
2023
  if Value<0 then Value := 0;
2039
  if Value<0 then Value := 0;
2024
 
2040
 
2025
  if Obj=Integer(@PDIJoyState2(nil).rgdwPOV[0]) then
2041
  if Obj=Integer(@PDIJoyState2(nil).rgdwPOV[0]) then
2026
  begin
2042
  begin
2027
    FRange[Obj] := -1;
2043
    FRange[Obj] := -1;
2028
    Exit;
2044
    Exit;
2029
  end;
2045
  end;
2030
 
2046
 
2031
  FRange[Obj] := Value;
2047
  FRange[Obj] := Value;
2032
 
2048
 
2033
  if FDevice<>nil then
2049
  if FDevice<>nil then
2034
  begin
2050
  begin
2035
    if SetRangeProperty(FDevice, DIPROP_RANGE, Obj, DIPH_BYOFFSET, Value)<>DI_OK then
2051
    if SetRangeProperty(FDevice, DIPROP_RANGE, Obj, DIPH_BYOFFSET, Value)<>DI_OK then
2036
      FRange[Obj] := -1;
2052
      FRange[Obj] := -1;
2037
  end;
2053
  end;
2038
end;
2054
end;
2039
 
2055
 
2040
procedure TJoystick.Update;
2056
procedure TJoystick.Update;
2041
 
2057
 
2042
  function ConvertValue(Value, wXmax, wXmin, DeadZone, Range: Integer): Integer;
2058
  function ConvertValue(Value, wXmax, wXmin, DeadZone, Range: Integer): Integer;
2043
  var
2059
  var
2044
    c, w: Integer;
2060
    c, w: Integer;
2045
  begin
2061
  begin
2046
    Result := 0;
2062
    Result := 0;
2047
 
2063
 
2048
    c := (wXmax - wXmin) div 2;
2064
    c := (wXmax - wXmin) div 2;
2049
    Value := Value-c;
2065
    Value := Value-c;
2050
 
2066
 
2051
    w := c*DeadZone div 100;
2067
    w := c*DeadZone div 100;
2052
    c := c - w;
2068
    c := c - w;
2053
 
2069
 
2054
    if c=0 then Exit;
2070
    if c=0 then Exit;
2055
 
2071
 
2056
    if Abs(Value)>w then
2072
    if Abs(Value)>w then
2057
    begin
2073
    begin
2058
      if Value>0 then
2074
      if Value>0 then
2059
        Result := MulDiv(Value-w, Range, c)
2075
        Result := MulDiv(Value-w, Range, c)
2060
      else
2076
      else
2061
        Result := MulDiv(Value+w, Range, c);
2077
        Result := MulDiv(Value+w, Range, c);
2062
    end;
2078
    end;
2063
  end;
2079
  end;
2064
 
2080
 
2065
var
2081
var
2066
  i: Integer;
2082
  i: Integer;
2067
  JoyInfo: TJoyInfoEx;
2083
  JoyInfo: TJoyInfoEx;
2068
begin
2084
begin
2069
  FillChar(Fdijs, SizeOf(Fdijs), 0);
2085
  FillChar(Fdijs, SizeOf(Fdijs), 0);
2070
  FStates := [];
2086
  FStates := [];
2071
 
2087
 
2072
  if (not FInitialized) or FDXInput.FActiveOnly and (GetForegroundWindow<>FDXInput.FForm.Handle) then
2088
  if (not FInitialized) or FDXInput.FActiveOnly and (GetForegroundWindow<>FDXInput.FForm.Handle) then
2073
    Exit;
2089
    Exit;
2074
 
2090
 
2075
  if FDevice<>nil then
2091
  if FDevice<>nil then
2076
  begin
2092
  begin
2077
    FDevice2.Poll;
2093
    FDevice2.Poll;
2078
    GetDeviceState(SizeOf(Fdijs), Fdijs);
2094
    GetDeviceState(SizeOf(Fdijs), Fdijs);
2079
  end else
2095
  end else
2080
  begin
2096
  begin
2081
    if FID2<>-1 then
2097
    if FID2<>-1 then
2082
    begin
2098
    begin
2083
      JoyInfo.dwSize := SizeOf(JoyInfo);
2099
      JoyInfo.dwSize := SizeOf(JoyInfo);
2084
      JoyInfo.dwFlags := JOY_RETURNX or JOY_RETURNY or JOY_RETURNZ or JOY_RETURNPOV or
2100
      JoyInfo.dwFlags := JOY_RETURNX or JOY_RETURNY or JOY_RETURNZ or JOY_RETURNPOV or
2085
        JOY_RETURNBUTTONS or JOY_RETURNCENTERED;
2101
        JOY_RETURNBUTTONS or JOY_RETURNCENTERED;
2086
 
2102
 
2087
      joyGetPosEx(FID2, @JoyInfo);
2103
      joyGetPosEx(FID2, @JoyInfo);
2088
 
2104
 
2089
      with FJoyCaps do
2105
      with FJoyCaps do
2090
        Fdijs.lX := ConvertValue(JoyInfo.wXpos, wXmax, wXmin, FDeadZone[DIJOFS_X], FRange[DIJOFS_X]);
2106
        Fdijs.lX := ConvertValue(JoyInfo.wXpos, wXmax, wXmin, FDeadZone[DIJOFS_X], FRange[DIJOFS_X]);
2091
 
2107
 
2092
      with FJoyCaps do
2108
      with FJoyCaps do
2093
        Fdijs.lY := ConvertValue(JoyInfo.wYpos, wYmax, wYmin, FDeadZone[DIJOFS_Y], FRange[DIJOFS_Y]);
2109
        Fdijs.lY := ConvertValue(JoyInfo.wYpos, wYmax, wYmin, FDeadZone[DIJOFS_Y], FRange[DIJOFS_Y]);
2094
 
2110
 
2095
      with FJoyCaps do
2111
      with FJoyCaps do
2096
        Fdijs.lZ := ConvertValue(JoyInfo.wZpos, wZmax, wZmin, FDeadZone[DIJOFS_Z], FRange[DIJOFS_Z]);
2112
        Fdijs.lZ := ConvertValue(JoyInfo.wZpos, wZmax, wZmin, FDeadZone[DIJOFS_Z], FRange[DIJOFS_Z]);
2097
 
2113
 
2098
      Fdijs.rgdwPOV[0] := JoyInfo.dwPOV;
2114
      Fdijs.rgdwPOV[0] := JoyInfo.dwPOV;
2099
 
2115
 
2100
      for i:=0 to FJoyCaps.wNumButtons-1 do
2116
      for i:=0 to FJoyCaps.wNumButtons-1 do
2101
        if JoyInfo.wButtons and (1 shl i)<>0 then
2117
        if JoyInfo.wButtons and (1 shl i)<>0 then
2102
          Fdijs.rgbButtons[i] := $80;
2118
          Fdijs.rgbButtons[i] := $80;
2103
    end;
2119
    end;
2104
  end;
2120
  end;
2105
 
2121
 
2106
  for i:=0 to 31 do
2122
  for i:=0 to 31 do
2107
    if Fdijs.rgbButtons[i] and $80<>0 then
2123
    if Fdijs.rgbButtons[i] and $80<>0 then
2108
      FStates := FStates + [TDXInputState(Ord(isButton1)+i)];
2124
      FStates := FStates + [TDXInputState(Ord(isButton1)+i)];
2109
 
2125
 
2110
  if Fdijs.lX<0 then FStates := FStates + [isLeft];
2126
  if Fdijs.lX<0 then FStates := FStates + [isLeft];
2111
  if Fdijs.lX>0 then FStates := FStates + [isRight];
2127
  if Fdijs.lX>0 then FStates := FStates + [isRight];
2112
  if Fdijs.lY<0 then FStates := FStates + [isUp];
2128
  if Fdijs.lY<0 then FStates := FStates + [isUp];
2113
  if Fdijs.lY>0 then FStates := FStates + [isDown];
2129
  if Fdijs.lY>0 then FStates := FStates + [isDown];
2114
end;
2130
end;
2115
 
2131
 
2116
{  TCustomDXInput  }
2132
{  TCustomDXInput  }
2117
 
2133
 
2118
var
2134
var
2119
  FDirectInput: IDirectInput;
2135
  FDirectInput: IDirectInput;
2120
  FDirectInputCount: Integer;
2136
  FDirectInputCount: Integer;
2121
 
2137
 
2122
procedure InitDirectInput(out DI: IDirectInput);
2138
procedure InitDirectInput(out DI: IDirectInput);
2123
type
2139
type
2124
  TDirectInputCreate = function(hinst: THandle; dwVersion: DWORD;
2140
  TDirectInputCreate = function(hinst: THandle; dwVersion: DWORD;
2125
    out ppDI: IDirectInputA; punkOuter: IUnknown): HRESULT; stdcall;
2141
    out ppDI: {$IFDEF UNICODE}IDirectInputW{$ELSE}IDirectInputA{$ENDIF}; punkOuter: IUnknown): HRESULT; stdcall;
2126
begin
2142
begin
2127
  if FDirectInput=nil then
2143
  if FDirectInput=nil then
2128
  begin
2144
  begin
2129
    try
2145
    try
2130
      TDirectInputCreate(DXLoadLibrary('DInput.dll', 'DirectInputCreateA'))
2146
      TDirectInputCreate(DXLoadLibrary('DInput.dll', 'DirectInputCreateA'))
2131
        (HInstance, DIRECTINPUT_VERSION, FDirectInput, nil);
2147
        (HInstance, DIRECTINPUT_VERSION, FDirectInput, nil);
2132
    except
2148
    except
2133
      FDirectInput := nil;
2149
      FDirectInput := nil;
2134
    end;
2150
    end;
2135
  end;
2151
  end;
2136
 
2152
 
2137
  DI := FDirectInput;
2153
  DI := FDirectInput;
2138
  if FDirectInput<>nil then
2154
  if FDirectInput<>nil then
2139
    Inc(FDirectInputCount);
2155
    Inc(FDirectInputCount);
2140
end;
2156
end;
2141
 
2157
 
2142
procedure FinDirectInput(var DI: IDirectInput);
2158
procedure FinDirectInput(var DI: IDirectInput);
2143
begin
2159
begin
2144
  if DI<>nil then
2160
  if DI<>nil then
2145
  begin
2161
  begin
2146
    DI := nil;
2162
    DI := nil;
2147
    Dec(FDirectInputCount);
2163
    Dec(FDirectInputCount);
2148
    if FDirectInputCount<=0 then
2164
    if FDirectInputCount<=0 then
2149
    begin
2165
    begin
2150
      FDirectInputCount := 0;
2166
      FDirectInputCount := 0;
2151
      FDirectInput := nil;
2167
      FDirectInput := nil;
2152
    end;
2168
    end;
2153
  end;
2169
  end;
2154
end;
2170
end;
2155
 
2171
 
2156
constructor TCustomDXInput.Create(AOwner: TComponent);
2172
constructor TCustomDXInput.Create(AOwner: TComponent);
2157
var
2173
var
2158
  Component: TComponent;
2174
  Component: TComponent;
2159
begin
2175
begin
2160
  inherited Create(AOwner);
2176
  inherited Create(AOwner);
2161
 
2177
 
2162
  FDevice := TList.Create;
2178
  FDevice := TList.Create;
2163
 
2179
 
2164
  FActiveOnly := True;
2180
  FActiveOnly := True;
2165
  FJoystick := TJoystick.Create(Self);
2181
  FJoystick := TJoystick.Create(Self);
2166
  FKeyboard := TKeyboard.Create(Self);
2182
  FKeyboard := TKeyboard.Create(Self);
2167
  FMouse := TMouse.Create(Self);
2183
  FMouse := TMouse.Create(Self);
2168
  FUseDirectInput := True;
2184
  FUseDirectInput := True;
2169
 
2185
 
2170
  Component := Owner;
2186
  Component := Owner;
2171
  while (Component<>nil) and (not (Component is TCustomForm)) do
2187
  while (Component<>nil) and (not (Component is TCustomForm)) do
2172
    Component := Component.Owner;
2188
    Component := Component.Owner;
2173
  if Component=nil then
2189
  if Component=nil then
2174
    raise EDXInputError.CreateFmt(SNoForm, ['Owner']);
2190
    raise EDXInputError.CreateFmt(SNoForm, ['Owner']);
2175
  FForm := TCustomForm(Component);
2191
  FForm := TCustomForm(Component);
2176
 
2192
 
2177
  FSubClass := TControlSubClass.Create(FForm, FormWndProc);
2193
  FSubClass := TControlSubClass.Create(FForm, FormWndProc);
2178
end;
2194
end;
2179
 
2195
 
2180
destructor TCustomDXInput.Destroy;
2196
destructor TCustomDXInput.Destroy;
2181
begin
2197
begin
2182
  Finalize;
2198
  Finalize;
2183
  FJoystick.Free;
2199
  FJoystick.Free;
2184
  FKeyboard.Free;
2200
  FKeyboard.Free;
2185
  FMouse.Free;
2201
  FMouse.Free;
2186
  FSubClass.Free;
2202
  FSubClass.Free;
2187
  while FDevice.Count>0 do
2203
  while FDevice.Count>0 do
2188
    TCustomInput(FDevice[FDevice.Count-1]).Free;
2204
    TCustomInput(FDevice[FDevice.Count-1]).Free;
2189
  FDevice.Free;
2205
  FDevice.Free;
2190
  inherited Destroy;
2206
  inherited Destroy;
2191
end;
2207
end;
2192
 
2208
 
2193
procedure TCustomDXInput.FormWndProc(var Message: TMessage; DefWindowProc: TWndMethod);
2209
procedure TCustomDXInput.FormWndProc(var Message: TMessage; DefWindowProc: TWndMethod);
2194
 
2210
 
2195
  procedure AcquireDevice;
2211
  procedure AcquireDevice;
2196
  var
2212
  var
2197
    i: Integer;
2213
    i: Integer;
2198
  begin
2214
  begin
2199
    for i:=0 to FDevice.Count-1 do
2215
    for i:=0 to FDevice.Count-1 do
2200
      TCustomInput(FDevice[i]).Acquire;
2216
      TCustomInput(FDevice[i]).Acquire;
2201
  end;
2217
  end;
2202
 
2218
 
2203
begin
2219
begin
2204
  case Message.Msg of
2220
  case Message.Msg of
2205
    WM_CREATE:
2221
    WM_CREATE:
2206
        begin
2222
        begin
2207
          {  Window handle of Form changed.  }
2223
          {  Window handle of Form changed.  }
2208
          DefWindowProc(Message);
2224
          DefWindowProc(Message);
2209
          SetWindowHandle;
2225
          SetWindowHandle;
2210
          Exit;
2226
          Exit;
2211
        end;
2227
        end;
2212
    WM_ACTIVATEAPP:
2228
    WM_ACTIVATEAPP:
2213
        begin
2229
        begin
2214
          DefWindowProc(Message);
2230
          DefWindowProc(Message);
2215
          if TWMActivateApp(Message).Active then
2231
          if TWMActivateApp(Message).Active then
2216
            AcquireDevice;
2232
            AcquireDevice;
2217
          Exit;
2233
          Exit;
2218
        end;
2234
        end;
2219
    WM_ACTIVATE:
2235
    WM_ACTIVATE:
2220
        begin
2236
        begin
2221
          DefWindowProc(Message);
2237
          DefWindowProc(Message);
2222
          if TWMActivate(Message).Active<>WA_INACTIVE then
2238
          if TWMActivate(Message).Active<>WA_INACTIVE then
2223
            AcquireDevice;
2239
            AcquireDevice;
2224
          Exit;
2240
          Exit;
2225
        end;
2241
        end;
2226
  end;
2242
  end;
2227
  DefWindowProc(Message);
2243
  DefWindowProc(Message);
2228
end;
2244
end;
2229
 
2245
 
2230
procedure TCustomDXInput.Finalize;
2246
procedure TCustomDXInput.Finalize;
2231
var
2247
var
2232
  i: Integer;
2248
  i: Integer;
2233
begin
2249
begin
2234
  for i:=0 to FDevice.Count-1 do
2250
  for i:=0 to FDevice.Count-1 do
2235
    TCustomInput(FDevice[i]).Finalize;
2251
    TCustomInput(FDevice[i]).Finalize;
2236
  FinDirectInput(FDInput);
2252
  FinDirectInput(FDInput);
2237
end;
2253
end;
2238
 
2254
 
2239
procedure TCustomDXInput.Loaded;
2255
procedure TCustomDXInput.Loaded;
2240
begin
2256
begin
2241
  Initialize;
2257
  Initialize;
2242
end;
2258
end;
2243
 
2259
 
2244
procedure TCustomDXInput.Initialize;
2260
procedure TCustomDXInput.Initialize;
2245
var
2261
var
2246
  i: Integer;
2262
  i: Integer;
2247
begin
2263
begin
2248
  Finalize;
2264
  Finalize;
2249
  if not (csDesigning in ComponentState) then
2265
  if not (csDesigning in ComponentState) then
2250
  begin
2266
  begin
2251
    if FUseDirectInput then InitDirectInput(FDInput);
2267
    if FUseDirectInput then InitDirectInput(FDInput);
2252
 
2268
 
2253
    for i:=0 to FDevice.Count-1 do
2269
    for i:=0 to FDevice.Count-1 do
2254
      TCustomInput(FDevice[i]).Initialize;
2270
      TCustomInput(FDevice[i]).Initialize;
2255
 
2271
 
2256
    SetWindowHandle;
2272
    SetWindowHandle;
2257
 
2273
 
2258
    Update;
2274
    Update;
2259
  end;
2275
  end;
2260
end;
2276
end;
2261
 
2277
 
2262
procedure TCustomDXInput.SetActiveOnly(Value: Boolean);
2278
procedure TCustomDXInput.SetActiveOnly(Value: Boolean);
2263
begin
2279
begin
2264
  if Value<>FActiveOnly then
2280
  if Value<>FActiveOnly then
2265
  begin
2281
  begin
2266
    FActiveOnly := Value;
2282
    FActiveOnly := Value;
2267
    if [csLoading, csReading]*ComponentState=[] then SetWindowHandle;
2283
    if [csLoading, csReading]*ComponentState=[] then SetWindowHandle;
2268
  end;
2284
  end;
2269
end;
2285
end;
2270
 
2286
 
2271
procedure TCustomDXInput.SetJoystick(Value: TJoystick);
2287
procedure TCustomDXInput.SetJoystick(Value: TJoystick);
2272
begin
2288
begin
2273
  FJoystick.Assign(Value);
2289
  FJoystick.Assign(Value);
2274
end;
2290
end;
2275
 
2291
 
2276
procedure TCustomDXInput.SetKeyboard(Value: TKeyboard);
2292
procedure TCustomDXInput.SetKeyboard(Value: TKeyboard);
2277
begin
2293
begin
2278
  FKeyboard.Assign(Value);
2294
  FKeyboard.Assign(Value);
2279
end;
2295
end;
2280
 
2296
 
2281
procedure TCustomDXInput.SetMouse(Value: TMouse);
2297
procedure TCustomDXInput.SetMouse(Value: TMouse);
2282
begin
2298
begin
2283
  FMouse.Assign(Value);
2299
  FMouse.Assign(Value);
2284
end;
2300
end;
2285
 
2301
 
2286
procedure TCustomDXInput.SetUseDirectInput(Value: Boolean);
2302
procedure TCustomDXInput.SetUseDirectInput(Value: Boolean);
2287
begin
2303
begin
2288
  if FUseDirectInput<>Value then
2304
  if FUseDirectInput<>Value then
2289
  begin
2305
  begin
2290
    FUseDirectInput := Value;
2306
    FUseDirectInput := Value;
2291
    Initialize;
2307
    Initialize;
2292
  end;
2308
  end;
2293
end;
2309
end;
2294
 
2310
 
2295
procedure TCustomDXInput.SetWindowHandle;
2311
procedure TCustomDXInput.SetWindowHandle;
2296
var
2312
var
2297
  i: Integer;
2313
  i: Integer;
2298
begin
2314
begin
2299
  for i:=0 to FDevice.Count-1 do
2315
  for i:=0 to FDevice.Count-1 do
2300
    TCustomInput(FDevice[i]).SetWindowHandle(FForm.Handle);
2316
    TCustomInput(FDevice[i]).SetWindowHandle(FForm.Handle);
2301
end;
2317
end;
2302
 
2318
 
2303
procedure TCustomDXInput.Update;
2319
procedure TCustomDXInput.Update;
2304
var
2320
var
2305
  j: Integer;
2321
  j: Integer;
2306
  i: TDXInputState;
2322
  i: TDXInputState;
2307
  s: TDXInputStates;
2323
  s: TDXInputStates;
2308
begin
2324
begin
2309
  s := [];
2325
  s := [];
2310
 
2326
 
2311
  for j:=0 to FDevice.Count-1 do
2327
  for j:=0 to FDevice.Count-1 do
2312
  begin
2328
  begin
2313
    TCustomInput(FDevice[j]).Update;
2329
    TCustomInput(FDevice[j]).Update;
2314
    if TCustomInput(FDevice[j]).FBindInputStates then
2330
    if TCustomInput(FDevice[j]).FBindInputStates then
2315
      s := s + TCustomInput(FDevice[j]).States;
2331
      s := s + TCustomInput(FDevice[j]).States;
2316
  end;
2332
  end;
2317
 
2333
 
2318
  for i:=Low(TDXInputState) to High(TDXInputState) do
2334
  for i:=Low(TDXInputState) to High(TDXInputState) do
2319
  begin
2335
  begin
2320
    if (i in s) and (not (i in FOldStates)) then
2336
    if (i in s) and (not (i in FOldStates)) then
2321
      FStates := FStates + [i];
2337
      FStates := FStates + [i];
2322
    if (not (i in s)) and (i in FOldStates) then
2338
    if (not (i in s)) and (i in FOldStates) then
2323
      FStates := FStates - [i];
2339
      FStates := FStates - [i];
2324
  end;
2340
  end;
2325
 
2341
 
2326
  FOldStates := s;
2342
  FOldStates := s;
2327
end;
2343
end;
2328
 
2344
 
2329
end.
2345
end.
2330
 
-