DEADSOFTWARE

changed some backslashes to forward slashes
[d2df-editor.git] / src / engine / e_input.pas
1 Unit e_input;
3 Interface
5 Uses
6 Windows,
7 SysUtils,
8 e_log,
9 DirectInput;
11 {type
12 TMouseInfo = record
13 X, Y: Integer;
14 Buttons: Array [0..3] of Boolean;
15 Accel: Real;
16 end;}
18 const
19 e_MaxInputKeys = 256 + 32 + 6 + 6 + 4 - 1;
20 // 0..255 - 256 Keyboard buttons/keys
21 // 256..287 - 32 Joystick buttons
22 // 288..293 - 3 Joystick axises +/-
23 // 294..299 - 3 Joystick axis rotations +/-
24 // 300..303 - 2 Joystick sliders +/-
26 e_WrongKey = 65535;
28 e_IKey_Escape = DIK_ESCAPE;
29 e_IKey_Backspace = DIK_BACK;
30 e_IKey_Tab = DIK_TAB;
31 e_IKey_Enter = DIK_RETURN;
32 e_IKey_Space = DIK_SPACE;
34 e_IKey_Up = DIK_UP;
35 e_IKey_Left = DIK_LEFT;
36 e_IKey_Right = DIK_RIGHT;
37 e_IKey_Down = DIK_DOWN;
39 {procedure e_PollMouse();}
40 function e_InitDirectInput(hWnd: HWND): Boolean;
41 procedure e_ReleaseDirectInput();
42 procedure e_ClearInputBuffer();
43 function e_PollInput(): Boolean;
44 function e_KeyPressed(Key: Word): Boolean;
45 function e_AnyKeyPressed(): Boolean;
46 function e_GetFirstKeyPressed(): Word;
47 function e_JoystickStateToString(mode: Integer): String;
49 var
50 {e_MouseInfo: TMouseInfo;}
51 e_EnableInput: Boolean = False;
52 e_JoystickAvailable: Boolean = False;
54 Implementation
56 const
57 CUSTOMIZABLE_JOYSTICK = True;
59 type
60 TJoystickCustomField = record
61 here: Boolean;
62 min, center, max: Integer;
63 end;
65 TJoystickCustom = record
66 X: TJoystickCustomField; (* x-axis position *)
67 Y: TJoystickCustomField; (* y-axis position *)
68 Z: TJoystickCustomField; (* z-axis position *)
70 Rx: TJoystickCustomField; (* x-axis rotation *)
71 Ry: TJoystickCustomField; (* y-axis rotation *)
72 Rz: TJoystickCustomField; (* z-axis rotation *)
74 Slider: Array [0..1] of TJoystickCustomField; (* extra axes positions *)
75 POV: Array [0..3] of TJoystickCustomField; (* POV directions *)
76 end;
78 var
79 lpDI8: IDirectInput8 = nil;
80 lpDIKeyboard: IDirectInputDevice8 = nil;
81 {lpDIMouse: IDirectInputDevice8 = nil;}
82 lpDIJoystick: IDirectInputDevice8 = nil;
83 ms: TDIMOUSESTATE;
84 _h_Wnd: HWND;
85 keyBuffer: Array [0..255] of Byte;
86 joystickState: TDIJoyState;
87 joystickCustomized: Boolean = False;
88 joystickCustom: TJoystickCustom;
91 function GetMaxFromCenter(center: Integer): Integer;
92 begin
93 Result := center * 2;
94 if (Result < center) or (Result > MaxInt) then
95 Result := MaxInt;
96 end;
98 function PosRelation(pos: Integer; field: TJoystickCustomField): Integer;
99 begin
100 if (not field.here) or (pos = field.center) then
101 Result := 0
102 else
103 if (field.center < pos) then
104 begin
105 if (pos > (field.center + ((field.max - field.center) div 3))) then
106 Result := 1
107 else
108 Result := 0;
109 end
110 else // pos < field.center
111 begin
112 if (pos < (field.center - ((field.center - field.min) div 3))) then
113 Result := -1
114 else
115 Result := 0;
116 end;
117 end;
119 procedure CustomizeJoystick();
120 var
121 i: Integer;
122 begin
123 joystickCustom.X.here := (joystickState.lX <> 0);
124 if (joystickCustom.X.here) then
125 begin
126 joystickCustom.X.center := joystickState.lX;
127 joystickCustom.X.min := 0;
128 joystickCustom.X.max := GetMaxFromCenter(joystickCustom.X.center);
129 end;
131 joystickCustom.Y.here := (joystickState.lY <> 0);
132 if (joystickCustom.Y.here) then
133 begin
134 joystickCustom.Y.center := joystickState.lY;
135 joystickCustom.Y.min := 0;
136 joystickCustom.Y.max := GetMaxFromCenter(joystickCustom.Y.center);
137 end;
139 joystickCustom.Z.here := (joystickState.lZ <> 0);
140 if (joystickCustom.Z.here) then
141 begin
142 joystickCustom.Z.center := joystickState.lZ;
143 joystickCustom.Z.min := 0;
144 joystickCustom.Z.max := GetMaxFromCenter(joystickCustom.Z.center);
145 end;
147 joystickCustom.Rx.here := (joystickState.lRx <> 0);
148 if (joystickCustom.Rx.here) then
149 begin
150 joystickCustom.Rx.center := joystickState.lRx;
151 joystickCustom.Rx.min := 0;
152 joystickCustom.Rx.max := GetMaxFromCenter(joystickCustom.Rx.center);
153 end;
155 joystickCustom.Ry.here := (joystickState.lRy <> 0);
156 if (joystickCustom.Ry.here) then
157 begin
158 joystickCustom.Ry.center := joystickState.lRy;
159 joystickCustom.Ry.min := 0;
160 joystickCustom.Ry.max := GetMaxFromCenter(joystickCustom.Ry.center);
161 end;
163 joystickCustom.Rz.here := (joystickState.lRz <> 0);
164 if (joystickCustom.Rz.here) then
165 begin
166 joystickCustom.Rz.center := joystickState.lRz;
167 joystickCustom.Rz.min := 0;
168 joystickCustom.Rz.max := GetMaxFromCenter(joystickCustom.Rz.center);
169 end;
171 for i := 0 to 1 do
172 begin
173 joystickCustom.Slider[i].here := (joystickState.rglSlider[i] <> 0);
174 if (joystickCustom.Slider[i].here) then
175 begin
176 joystickCustom.Slider[i].center := joystickState.rglSlider[i];
177 joystickCustom.Slider[i].min := 0;
178 joystickCustom.Slider[i].max := GetMaxFromCenter(joystickCustom.Slider[i].center);
179 end;
180 end;
182 // TODO: POV 0..3:
183 // * value = $FFFFFFFF - no POV or it is in its center
184 // * value = Angle_In_Degrees * 100
185 // * 0 - Up, 9000 - Right, 18000 - Down, 27000 - Left
186 // * How to customize it?
188 end;
190 {procedure e_PollMouse();
191 begin
192 if (GetForegroundWindow = _h_Wnd) then
193 if (lpDImouse.GetDeviceState(SizeOf(TDIMOUSESTATE), @ms) <> 0) then
194 begin
195 lpDIMouse.Acquire();
196 if FAILED(lpDImouse.GetDeviceState(SizeOf(TDIMOUSESTATE), @ms)) then
197 Exit;
198 end;
200 if ms.lX < 0 then ms.lX := Round(ms.lX * e_MouseInfo.Accel) else
201 if ms.lX > 0 then ms.lX := Round(ms.lX * e_MouseInfo.Accel);
203 if ms.lY < 0 then ms.lY := Round(ms.lY * e_MouseInfo.Accel) else
204 if ms.lY > 0 then ms.lY := Round(ms.lY * e_MouseInfo.Accel);
206 e_MouseInfo.X := e_MouseInfo.X + ms.lX;
207 e_MouseInfo.Y := e_MouseInfo.Y + ms.lY;
209 e_MouseInfo.Buttons[0] := ms.rgbButtons[0] = $080;
210 e_MouseInfo.Buttons[1] := ms.rgbButtons[1] = $080;
211 e_MouseInfo.Buttons[2] := ms.rgbButtons[2] = $080;
212 e_MouseInfo.Buttons[3] := ms.rgbButtons[3] = $080;
213 end;}
215 function PollKeyboard(): Boolean;
216 begin
217 Result := False;
219 if (GetForegroundWindow() = _h_Wnd) then
220 if (lpDIKeyboard.GetDeviceState(SizeOf(keyBuffer), @keyBuffer) <> 0) then
221 begin
222 lpDIKeyboard.Acquire();
223 if FAILED(lpDIKeyboard.GetDeviceState(SizeOf(keyBuffer), @keyBuffer)) then
224 Exit;
225 end;
227 Result := True;
228 end;
230 function PollJoystick(): Boolean;
231 begin
232 Result := False;
234 if (lpDIJoystick = nil) then
235 Exit;
237 if (GetForegroundWindow() = _h_Wnd) then
238 if (lpDIJoystick.GetDeviceState(SizeOf(TDIJoyState), @joystickState) <> 0) then
239 begin
240 lpDIJoystick.Acquire();
241 if FAILED(lpDIJoystick.GetDeviceState(SizeOf(TDIJoyState), @joystickState)) then
242 Exit;
243 end;
245 if (not joystickCustomized) and CUSTOMIZABLE_JOYSTICK then
246 begin
247 CustomizeJoystick();
248 joystickCustomized := True;
249 end;
251 Result := True;
252 end;
254 function InitJoystick(hWnd: HWND): Boolean;
255 begin
256 Result := False;
258 if FAILED(lpDI8.CreateDevice(GUID_Joystick, lpDIJoystick, nil)) then
259 Exit;
260 lpDIJoystick._AddRef();
262 if FAILED(lpDIJoystick.SetDataFormat(c_dfDIJoystick)) then
263 Exit;
265 if FAILED(lpDIJoystick.SetCooperativeLevel(hWnd, DISCL_FOREGROUND or
266 DISCL_NONEXCLUSIVE)) then
267 Exit;
268 lpDIJoystick.Acquire();
270 Result := True;
271 end;
273 function e_InitDirectInput(hWnd: HWND): Boolean;
274 begin
275 Result := False;
277 if FAILED(DirectInput8Create(GetModuleHandle(nil), DIRECTINPUT_VERSION,
278 IID_IDirectInput8, lpDI8, nil)) then
279 Exit;
280 lpDI8._AddRef();
282 // Keyboard:
283 if FAILED(lpDI8.CreateDevice(GUID_SysKeyboard, lpDIKeyboard, nil)) then
284 Exit;
285 lpDIKeyboard._AddRef();
287 if FAILED(lpDIKeyboard.SetDataFormat(c_dfDIKeyboard)) then
288 Exit;
290 if FAILED(lpDIKeyboard.SetCooperativeLevel(hWnd, DISCL_FOREGROUND or
291 DISCL_NONEXCLUSIVE)) then
292 Exit;
293 lpDIKeyboard.Acquire();
295 // Mouse:
296 { Since we don't actually need the mouse in the game, I commented this out.
297 if FAILED(lpDI8.CreateDevice(GUID_SysMouse, lpDIMouse, nil)) then
298 Exit;
299 lpDIMouse._AddRef();
301 if FAILED(lpDIMouse.SetDataFormat(c_dfDIMouse)) then
302 Exit;
304 if FAILED(lpDIMouse.SetCooperativeLevel(hWnd, DISCL_FOREGROUND or DISCL_NONEXCLUSIVE)) then
305 Exit;
306 lpDIMouse.Acquire();
309 // Joystick:
310 e_JoystickAvailable := InitJoystick(hWnd);
311 if (not e_JoystickAvailable) then
312 lpDIJoystick := nil;
314 e_EnableInput := True;
315 _h_Wnd := hWnd;
317 Result := True;
318 end;
320 procedure e_ReleaseDirectInput();
321 begin
322 if lpDIKeyboard <> nil then
323 begin
324 lpDIKeyboard.Unacquire();
325 lpDIKeyboard._Release();
326 lpDIKeyboard := nil;
327 end;
329 { if lpDIMouse <> nil then
330 begin
331 lpDIMouse.Unacquire();
332 lpDIMouse._Release();
333 lpDIMouse := nil;
334 end; }
336 if lpDIJoystick <> nil then
337 begin
338 lpDIJoystick.Unacquire();
339 lpDIJoystick._Release();
340 lpDIJoystick := nil;
341 end;
343 if lpDI8 <> nil then
344 begin
345 lpDI8._Release();
346 lpDI8 := nil;
347 end;
348 end;
350 procedure e_ClearInputBuffer();
351 var
352 i: Integer;
354 begin
355 for i := 0 to 255 do
356 keyBuffer[i] := 0;
358 FillChar(joystickState, SizeOf(TDIJoyState), 0);
359 end;
361 function e_PollInput(): Boolean;
362 var
363 kb, js: Boolean;
364 begin
365 kb := PollKeyboard();
366 js := PollJoystick();
368 Result := kb or js;
369 end;
371 function e_KeyPressed(Key: Word): Boolean;
372 begin
373 if ((Key >= 0) and (Key <= 255)) then
374 begin // Keyboard buttons/keys
375 Result := (keyBuffer[Key] = $80);
376 end
377 else if ((Key >= 256) and (Key <= 287)) then
378 begin // Joystick buttons
379 Key := Key - 256;
380 Result := (joystickState.rgbButtons[Key] = $80);
381 end
382 else if (CUSTOMIZABLE_JOYSTICK) then
383 begin // Joystick axises and sliders
384 case Key of
385 288: Result := (PosRelation(joystickState.lX, joystickCustom.X) = -1); // X-
386 289: Result := (PosRelation(joystickState.lX, joystickCustom.X) = 1); // X+
387 290: Result := (PosRelation(joystickState.lY, joystickCustom.Y) = -1); // Y-
388 291: Result := (PosRelation(joystickState.lY, joystickCustom.Y) = 1); // Y+
389 292: Result := (PosRelation(joystickState.lZ, joystickCustom.Z) = -1); // Z-
390 293: Result := (PosRelation(joystickState.lZ, joystickCustom.Z) = 1); // Z+
392 294: Result := (PosRelation(joystickState.lRx, joystickCustom.Rx) = -1); // Rx-
393 295: Result := (PosRelation(joystickState.lRx, joystickCustom.Rx) = 1); // Rx+
394 296: Result := (PosRelation(joystickState.lRy, joystickCustom.Ry) = -1); // Ry-
395 297: Result := (PosRelation(joystickState.lRy, joystickCustom.Ry) = 1); // Ry+
396 298: Result := (PosRelation(joystickState.lRz, joystickCustom.Rz) = -1); // Rz-
397 299: Result := (PosRelation(joystickState.lRz, joystickCustom.Rz) = 1); // Rz+
399 300: Result := (PosRelation(joystickState.rglSlider[0], joystickCustom.Slider[0]) = -1); // Slider1-
400 301: Result := (PosRelation(joystickState.rglSlider[0], joystickCustom.Slider[0]) = 1); // Slider1+
402 302: Result := (PosRelation(joystickState.rglSlider[1], joystickCustom.Slider[1]) = -1); // Slider2-
403 303: Result := (PosRelation(joystickState.rglSlider[1], joystickCustom.Slider[1]) = 1); // Slider2+
405 else Result := False;
406 end;
407 end
408 else
409 Result := False;
410 end;
412 function e_AnyKeyPressed(): Boolean;
413 var
414 k: Word;
415 begin
416 Result := False;
418 for k := 0 to e_MaxInputKeys do
419 if e_KeyPressed(k) then
420 begin
421 Result := True;
422 Break;
423 end;
424 end;
426 function e_GetFirstKeyPressed(): Word;
427 var
428 k: Word;
429 begin
430 Result := e_WrongKey;
432 for k := 0 to e_MaxInputKeys do
433 if e_KeyPressed(k) then
434 begin
435 Result := k;
436 Break;
437 end;
438 end;
440 ////////////////////////////////////////////////////////////////////////////////
442 function e_JoystickStateToString(mode: Integer): String;
443 var
444 i: Integer;
445 begin
446 Result := '';
448 if (mode = 1) then
449 begin
450 // 0..65535: Up/Left .. Down/Right:
451 Result := Result + 'X=' + IntToStr(joystickState.lX) + ', ';
452 Result := Result + 'Y=' + IntToStr(joystickState.lY) + ', ';
453 Result := Result + 'Z=' + IntToStr(joystickState.lZ) + '; ';
454 end
455 else if (mode = 2) then
456 begin
457 // 0..65535: Left .. Center .. Right:
458 Result := Result + 'Rx=' + IntToStr(joystickState.lRx) + ', ';
459 Result := Result + 'Ry=' + IntToStr(joystickState.lRy) + ', ';
460 Result := Result + 'Rz=' + IntToStr(joystickState.lRz) + '; ';
461 end
462 else if (mode = 3) then
463 begin
464 // 0..65535: Up .. Down:
465 Result := Result + 'Slider[0]=' + IntToStr(joystickState.rglSlider[0]) + ', ';
466 Result := Result + 'Slider[1]=' + IntToStr(joystickState.rglSlider[1]) + '; ';
467 end
468 else if (mode = 4) then
469 begin
470 // 0..35999: POV angle, Up = 0, Clockwise, Center = $FFFFFFFF:
471 Result := Result + 'POV[0]=' + IntToStr(joystickState.rgdwPOV[0]) + ', ';
472 Result := Result + 'POV[1]=' + IntToStr(joystickState.rgdwPOV[1]) + ', ';
473 Result := Result + 'POV[2]=' + IntToStr(joystickState.rgdwPOV[2]) + ', ';
474 Result := Result + 'POV[3]=' + IntToStr(joystickState.rgdwPOV[3]) + '; ';
475 end
476 else if (mode = 5) then
477 begin
478 // 0 or 128 ($80): NotPressed or Pressed:
479 for i := 0 to 7 do
480 Result := Result + 'B[' + IntToStr(i) + ']=' + IntToStr(joystickState.rgbButtons[i]) + ', ';
481 end
482 else if (mode = 6) then
483 begin
484 // 0 or 128 ($80): NotPressed or Pressed:
485 for i := 8 to 15 do
486 Result := Result + 'B[' + IntToStr(i) + ']=' + IntToStr(joystickState.rgbButtons[i]) + ', ';
487 end
488 else if (mode = 7) then
489 begin
490 // 0 or 128 ($80): NotPressed or Pressed:
491 for i := 16 to 23 do
492 Result := Result + 'B[' + IntToStr(i) + ']=' + IntToStr(joystickState.rgbButtons[i]) + ', ';
493 end
494 else if (mode = 8) then
495 begin
496 // 0 or 128 ($80): NotPressed or Pressed:
497 for i := 24 to 31 do
498 Result := Result + 'B[' + IntToStr(i) + ']=' + IntToStr(joystickState.rgbButtons[i]) + '; ';
499 end
500 end;
502 end.