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 | - |