summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 3c277b2)
raw | patch | inline | side by side (parent: 3c277b2)
author | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Tue, 8 Oct 2019 19:59:52 +0000 (22:59 +0300) | ||
committer | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Sun, 13 Oct 2019 14:19:20 +0000 (17:19 +0300) |
src/engine/e_sound_sdl.inc | patch | blob | history | |
src/game/g_main.pas | patch | blob | history | |
src/game/sdl/g_system.pas | patch | blob | history | |
src/game/sdl2/g_system.pas | [new file with mode: 0644] | patch | blob |
src/game/sdl2/g_touch.pas | [new file with mode: 0644] | patch | blob |
src/game/stub/g_system.pas | patch | blob | history |
index 4d9eaba5d983da5fc644b7255be1923dfcce928f..ccfd9c4bc2715732e3d746db9f45e1f02065ff9d 100644 (file)
Result := False;
SoundInitialized := False;
+ {$IFDEF HEADLESS}
+ // HACK: shit this into env and hope for the best
+ SetEnvVar('SDL_AUDIODRIVER', 'dummy');
+ {$ELSEIF}
+
if NoOutput then begin Result := true; Exit end;
// wow, this is actually MIDI player!
diff --git a/src/game/g_main.pas b/src/game/g_main.pas
index 92c0ff5aa2a35d009fec83e43c69a688f6655cd5..222002baa53a1a312be411a51bcc1a3f6253431a 100644 (file)
--- a/src/game/g_main.pas
+++ b/src/game/g_main.pas
{$INCLUDE ../nogl/noGLuses.inc}
{$IFDEF ENABLE_HOLMES}
g_holmes, fui_wadread, fui_style, fui_gfx_gl,
-{$ENDIF}
-{$IFDEF USE_SDL2}
- SDL2,
{$ENDIF}
wadreader, e_log, g_window,
e_graphics, e_input, g_game, g_console, g_gui,
{$ENDIF}
e_WriteToStdOut := False; //{$IFDEF HEADLESS}True;{$ELSE}False;{$ENDIF}
-{$IFDEF USE_SDL2}
-{$IFDEF HEADLESS}
- {$IFDEF USE_SDLMIXER}
- sdlflags := SDL_INIT_TIMER or SDL_INIT_AUDIO or $00004000;
- // HACK: shit this into env and hope for the best
- SetEnvVar('SDL_AUDIODRIVER', 'dummy');
- {$ELSE}
- sdlflags := SDL_INIT_TIMER or $00004000;
- {$ENDIF}
-{$ELSE}
- {$IFDEF USE_SDLMIXER}
- {*sdlflags := SDL_INIT_EVERYTHING;*}
- sdlflags := SDL_INIT_JOYSTICK or SDL_INIT_TIMER or SDL_INIT_VIDEO;
- {$ELSE}
- sdlflags := SDL_INIT_JOYSTICK or SDL_INIT_TIMER or SDL_INIT_VIDEO;
- {$ENDIF}
-{$ENDIF}
-
- SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, '0');
-
- if SDL_Init(sdlflags) < 0 then
- raise Exception.Create('SDL: Init failed: ' + SDL_GetError());
-{$ENDIF}
-
e_WriteLog('Init Input', TMsgType.Notify);
e_InitInput;
e_WriteLog(gLanguage, TMsgType.Notify);
g_Language_Set(gLanguage);
-{$IFNDEF USE_SDL2}
sys_Init;
-{$ENDIF}
{$IF not DEFINED(HEADLESS) and DEFINED(ENABLE_HOLMES)}
flexloaded := true;
SDLMain();
{$WARNINGS ON}
-{$IFDEF USE_SDL2}
- e_WriteLog('Releasing SDL', TMsgType.Notify);
- SDL_Quit();
-{$ELSE}
sys_Final;
-{$ENDIF}
end;
procedure Init();
index 5caa9c9e5788a94044266a26f7ea8e8d6b692d70..5fe730283d1c6384f36ba8d46abcabca7a1a1abe 100644 (file)
e_log, e_graphics, e_input,
g_options, g_window, g_console, g_game, g_menu, g_gui, g_main;
+ const
+ GameTitle = 'Doom 2D: Forever (SDL 1.2)';
+
var
userResize: Boolean;
modeResize: Integer;
function sys_GetTicks (): Int64;
begin
- Result := SDL_GetTicks()
+ result := SDL_GetTicks()
end;
procedure sys_Delay (ms: Integer);
function InitWindow (w, h, bpp: Integer; fullScreen: Boolean): Boolean;
var flags: Uint32;
begin
- e_LogWritefln('InitWindow %s %s %s %s', [w, h, bpp, fullscreen]);
- Result := False;
+ e_LogWritefln('InitWindow %s %s %s %s', [w, h, bpp, fullScreen]);
+ result := False;
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
screen := SDL_SetVideoMode(w, h, bpp, flags);
if screen <> nil then
begin
- SDL_WM_SetCaption('Doom 2D: Forever (SDL 1.2)', nil);
+ SDL_WM_SetCaption(GameTitle, nil);
UpdateSize(w, h);
- Result := True
+ result := True
end
end
else
end
else if gConsoleShow or gChatShow or (g_ActiveWindow <> nil) then
begin
- KeyPress(key)
+ KeyPress(key) // key repeat in menus and shit
end;
if down and IsValid1251(ev.keysym.unicode) and IsPrintable1251(ch) then
CharPress(ch)
InitWindow(ev.resize.w, ev.resize.h, gBPP, gFullscreen)
end;
SDL_KEYUP, SDL_KEYDOWN: HandleKeyboard(ev.key);
+ SDL_VIDEOEXPOSE: sys_Repaint;
end
end
end;
procedure sys_Init;
var flags: Uint32; ok: Boolean;
begin
+ e_WriteLog('Init SDL', TMsgType.Notify);
flags := SDL_INIT_VIDEO or SDL_INIT_AUDIO or
SDL_INIT_TIMER or SDL_INIT_JOYSTICK
(*or SDL_INIT_NOPARACHUTE*);
if SDL_Init(flags) <> 0 then
- raise Exception.Create('SDL: Init failed: ' + SDL_GetError());
+ raise Exception.Create('SDL: Init failed: ' + SDL_GetError);
ok := InitWindow(gScreenWidth, gScreenHeight, gBPP, gFullScreen);
if not ok then
- raise Exception.Create('SDL: failed to set videomode: ' + SDL_GetError);
+ raise Exception.Create('SDL: Failed to set videomode: ' + SDL_GetError);
SDL_EnableUNICODE(1);
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
end;
diff --git a/src/game/sdl2/g_system.pas b/src/game/sdl2/g_system.pas
--- /dev/null
@@ -0,0 +1,449 @@
+(* Copyright (C) Doom 2D: Forever Developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License ONLY.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *)
+{$INCLUDE ../shared/a_modes.inc}
+unit g_system;
+
+interface
+
+ uses Utils;
+
+ (* --- Utils --- *)
+ function sys_GetTicks (): Int64;
+ procedure sys_Delay (ms: Integer);
+
+ (* --- Graphics --- *)
+ function sys_GetDispalyModes (bpp: Integer): SSArray;
+ function sys_SetDisplayMode (w, h, bpp: Integer; fullscreen: Boolean): Boolean;
+ procedure sys_EnableVSync (yes: Boolean);
+ procedure sys_Repaint;
+
+ (* --- Input --- *)
+ function sys_HandleInput (): Boolean;
+ procedure sys_RequestQuit;
+
+ (* --- Init --- *)
+ procedure sys_Init;
+ procedure sys_Final;
+
+implementation
+
+ uses
+ SysUtils, SDL2, GL, Math,
+ e_log, e_graphics, e_input,
+ g_touch,
+ g_options, g_window, g_console, g_game, g_menu, g_gui, g_main;
+
+ const
+ GameTitle = 'Doom 2D: Forever (SDL 2)';
+
+ var
+ window: PSDL_Window;
+ context: TSDL_GLContext;
+ display: Integer;
+ JoystickHandle: array [0..e_MaxJoys - 1] of PSDL_Joystick;
+ JoystickHatState: array [0..e_MaxJoys - 1, 0..e_MaxJoyHats - 1, HAT_LEFT..HAT_DOWN] of Boolean;
+ JoystickZeroAxes: array [0..e_MaxJoys - 1, 0..e_MaxJoyAxes - 1] of Integer;
+
+ (* --------- Utils --------- *)
+
+ function sys_GetTicks (): Int64;
+ begin
+ result := SDL_GetTicks()
+ end;
+
+ procedure sys_Delay (ms: Integer);
+ begin
+ SDL_Delay(ms)
+ end;
+
+ (* --------- Graphics --------- *)
+
+ procedure UpdateSize (w, h: Integer);
+ begin
+ gWinSizeX := w;
+ gWinSizeY := h;
+ gWinRealPosX := 0;
+ gWinRealPosY := 0;
+ gScreenWidth := w;
+ gScreenHeight := h;
+ {$IFDEF ENABLE_HOLMES}
+ fuiScrWdt := w;
+ fuiScrHgt := h;
+ {$ENDIF}
+ e_ResizeWindow(w, h);
+ e_InitGL;
+ g_Game_SetupScreenSize;
+ g_Menu_Reset;
+ g_Game_ClearLoading;
+ end;
+
+ function InitWindow (w, h, bpp: Integer; fullScreen: Boolean): Boolean;
+ var flags: UInt32;
+ begin
+ e_LogWritefln('InitWindow %s %s %s %s', [w, h, bpp, fullScreen]);
+ result := false;
+ if window = nil then
+ begin
+ {$IFDEF USE_GLES1}
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
+ {$ELSE}
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); // lights; it is enough to have 1-bit stencil buffer for lighting, but...
+ {$ENDIF}
+ flags := SDL_WINDOW_OPENGL or SDL_WINDOW_RESIZABLE;
+ if fullScreen then flags := flags or SDL_WINDOW_FULLSCREEN;
+ window := SDL_CreateWindow(GameTitle, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, flags);
+ if window <> nil then
+ begin
+ context := SDL_GL_CreateContext(window);
+ if context <> nil then
+ begin
+ UpdateSize(w, h);
+ result := true
+ end
+ else
+ begin
+ e_LogWritefln('SDL: unable to create OpenGL context: %s', [SDL_GetError])
+ end
+ end
+ else
+ begin
+ e_LogWritefln('SDL: unable to create window: %s', [SDL_GetError])
+ end
+ end
+ else
+ begin
+ if fullScreen then flags := SDL_WINDOW_FULLSCREEN else flags := 0;
+ SDL_SetWindowSize(window, w, h);
+ SDL_SetWindowFullscreen(window, flags);
+ UpdateSize(w, h);
+ result := true
+ end
+ end;
+
+ procedure sys_Repaint;
+ begin
+ SDL_GL_SwapWindow(window)
+ end;
+
+ procedure sys_EnableVSync (yes: Boolean);
+ begin
+ if yes then
+ SDL_GL_SetSwapInterval(1)
+ else
+ SDL_GL_SetSwapInterval(0)
+ end;
+
+ function sys_GetDispalyModes (bpp: Integer): SSArray;
+ var i, count, num, pw, ph: Integer; m: TSDL_DisplayMode;
+ begin
+ result := nil;
+ num := SDL_GetNumDisplayModes(display);
+ if num < 0 then
+ e_LogWritefln('SDL: unable to get numer of available display modes: %s', [SDL_GetError]);
+ if num > 0 then
+ begin
+ e_LogWritefln('Video modes for display %s:', [display]);
+ SetLength(result, num);
+ i := 0; count := 0; pw := 0; ph := 0;
+ while i < num do
+ begin
+ SDL_GetDisplayMode(display, i, @m);
+ if ((pw <> m.w) or (ph <> m.h)) then
+ begin
+ e_LogWritefln('* %sx%sx%s@%s', [m.w, m.h, SDL_BITSPERPIXEL(m.format), m.refresh_rate]);
+ pw := m.w; ph := m.h;
+ result[count] := IntToStr(m.w) + 'x' + IntToStr(m.h);
+ Inc(count);
+ end
+ else
+ begin
+ e_LogWritefln('- %sx%sx%s@%s', [m.w, m.h, SDL_BITSPERPIXEL(m.format), m.refresh_rate]);
+ end;
+ Inc(i)
+ end;
+ SetLength(result, count)
+ end
+ end;
+
+ function sys_SetDisplayMode (w, h, bpp: Integer; fullScreen: Boolean): Boolean;
+ begin
+ result := InitWindow(w, h, bpp, fullScreen)
+ end;
+
+ (* --------- Joystick --------- *)
+
+ procedure HandleJoyButton (var ev: TSDL_JoyButtonEvent);
+ var down: Boolean; key: Integer;
+ begin
+ if (ev.which < e_MaxJoys) and (ev.button < e_MaxJoyBtns) then
+ begin
+ key := e_JoyButtonToKey(ev.which, ev.button);
+ down := ev.type_ = SDL_JOYBUTTONDOWN;
+ if g_dbg_input then
+ e_LogWritefln('Input Debug: jbutton, joy=%s, button=%s, keycode=%s, press=%s', [ev.which, ev.button, key, down]);
+ e_KeyUpDown(key, down);
+ g_Console_ProcessBind(key, down)
+ end
+ else
+ begin
+ if g_dbg_input then
+ begin
+ down := ev.type_ = SDL_JOYBUTTONDOWN;
+ e_LogWritefln('Input Debug: NOT IN RANGE! jbutton, joy=%s, button=%s, press=%s', [ev.which, ev.button, down])
+ end
+ end
+ end;
+
+ procedure HandleJoyAxis (var ev: TSDL_JoyAxisEvent);
+ var key, minuskey: Integer;
+ begin
+ if (ev.which < e_MaxJoys) and (ev.axis < e_MaxJoyAxes) then
+ begin
+ key := e_JoyAxisToKey(ev.which, ev.axis, AX_PLUS);
+ minuskey := e_JoyAxisToKey(ev.which, ev.axis, AX_MINUS);
+
+ if g_dbg_input then
+ e_LogWritefln('Input Debug: jaxis, joy=%s, axis=%s, value=%s, zeroaxes=%s, deadzone=%s', [ev.which, ev.axis, ev.value, JoystickZeroAxes[ev.which, ev.axis], e_JoystickDeadzones[ev.which]]);
+
+ if ev.value < JoystickZeroAxes[ev.which, ev.axis] - e_JoystickDeadzones[ev.which] then
+ begin
+ if (e_KeyPressed(key)) then
+ begin
+ e_KeyUpDown(key, False);
+ g_Console_ProcessBind(key, False)
+ end;
+ e_KeyUpDown(minuskey, True);
+ g_Console_ProcessBind(minuskey, True)
+ end
+ else if ev.value > JoystickZeroAxes[ev.which, ev.axis] + e_JoystickDeadzones[ev.which] then
+ begin
+ if (e_KeyPressed(minuskey)) then
+ begin
+ e_KeyUpDown(minuskey, False);
+ g_Console_ProcessBind(minuskey, False)
+ end;
+ e_KeyUpDown(key, True);
+ g_Console_ProcessBind(key, True)
+ end
+ else
+ begin
+ if (e_KeyPressed(minuskey)) then
+ begin
+ e_KeyUpDown(minuskey, False);
+ g_Console_ProcessBind(minuskey, False)
+ end;
+ if (e_KeyPressed(key)) then
+ begin
+ e_KeyUpDown(key, False);
+ g_Console_ProcessBind(key, False)
+ end
+ end
+ end
+ else
+ begin
+ if g_dbg_input then
+ e_LogWritefln('Input Debug: NOT IN RANGE! jaxis, joy=%s, axis=%s, value=%s, zeroaxes=%s, deadzone=%s', [ev.which, ev.axis, ev.value, JoystickZeroAxes[ev.which, ev.axis], e_JoystickDeadzones[ev.which]])
+ end
+ end;
+
+ procedure HandleJoyHat (var ev: TSDL_JoyHatEvent);
+ var
+ down: Boolean;
+ i, key: Integer;
+ hat: array [HAT_LEFT..HAT_DOWN] of Boolean;
+ begin
+ if (ev.which < e_MaxJoys) and (ev.hat < e_MaxJoyHats) then
+ begin
+ if g_dbg_input then
+ e_LogWritefln('Input Debug: jhat, joy=%s, hat=%s, value=%s', [ev.which, ev.hat, ev.value]);
+ hat[HAT_UP] := LongBool(ev.value and SDL_HAT_UP);
+ hat[HAT_DOWN] := LongBool(ev.value and SDL_HAT_DOWN);
+ hat[HAT_LEFT] := LongBool(ev.value and SDL_HAT_LEFT);
+ hat[HAT_RIGHT] := LongBool(ev.value and SDL_HAT_RIGHT);
+ for i := HAT_LEFT to HAT_DOWN do
+ begin
+ if JoystickHatState[ev.which, ev.hat, i] <> hat[i] then
+ begin
+ down := hat[i];
+ key := e_JoyHatToKey(ev.which, ev.hat, i);
+ e_KeyUpDown(key, down);
+ g_Console_ProcessBind(key, down)
+ end
+ end;
+ JoystickHatState[ev.which, ev.hat] := hat
+ end
+ else
+ begin
+ if g_dbg_input then
+ e_LogWritefln('Input Debug: NOT IN RANGE! jhat, joy=%s, hat=%s, value=%s', [ev.which, ev.hat, ev.value])
+ end;
+ end;
+
+ procedure HandleJoyAdd (var ev: TSDL_JoyDeviceEvent);
+ var i: Integer;
+ begin
+ if (ev.which < e_MaxJoys) then
+ begin
+ JoystickHandle[ev.which] := SDL_JoystickOpen(ev.which);
+ if JoystickHandle[ev.which] <> nil then
+ begin
+ e_LogWritefln('Added Joystick %s', [ev.which]);
+ e_JoystickAvailable[ev.which] := True;
+ for i := 0 to Min(SDL_JoystickNumAxes(JoystickHandle[ev.which]), e_MaxJoyAxes) - 1 do
+ JoystickZeroAxes[ev.which, i] := SDL_JoystickGetAxis(JoystickHandle[ev.which], i)
+ end
+ else
+ begin
+ e_LogWritefln('Warning! Failed to open Joystick %s', [ev.which])
+ end
+ end
+ else
+ begin
+ e_LogWritefln('Warning! Added Joystick %s, but we support only <= %s', [ev.which, e_MaxJoys])
+ end
+ end;
+
+ procedure HandleJoyRemove (var ev: TSDL_JoyDeviceEvent);
+ begin
+ e_LogWritefln('Removed Joystick %s', [ev.which]);
+ if (ev.which < e_MaxJoys) then
+ begin
+ e_JoystickAvailable[ev.which] := False;
+ if JoystickHandle[ev.which] <> nil then
+ SDL_JoystickClose(JoystickHandle[ev.which]);
+ JoystickHandle[ev.which] := nil
+ end
+ end;
+
+ (* --------- Input --------- *)
+
+ function HandleWindow (var ev: TSDL_WindowEvent): Boolean;
+ begin
+ result := false;
+ case ev.event of
+ SDL_WINDOWEVENT_RESIZED: UpdateSize(ev.data1, ev.data2);
+ SDL_WINDOWEVENT_EXPOSED: sys_Repaint;
+ SDL_WINDOWEVENT_CLOSE: result := true;
+ end
+ end;
+
+ procedure HandleKeyboard (var ev: TSDL_KeyboardEvent);
+ var down: Boolean; key: Integer;
+ begin
+ key := ev.keysym.scancode;
+ down := (ev.type_ = SDL_KEYDOWN);
+ if key = SDL_SCANCODE_AC_BACK then
+ key := SDL_SCANCODE_ESCAPE;
+ if ev._repeat = 0 then
+ begin
+ if g_dbg_input then
+ e_LogWritefln('Input Debug: keysym, press=%s, scancode=%s', [down, key]);
+ e_KeyUpDown(key, down);
+ g_Console_ProcessBind(key, down);
+ end
+ else if gConsoleShow or gChatShow or (g_ActiveWindow <> nil) then
+ begin
+ KeyPress(key) // key repeat in menus and shit
+ end
+ end;
+
+ procedure HandleTextInput (var ev: TSDL_TextInputEvent);
+ var ch: UnicodeChar; sch: AnsiChar;
+ begin
+ if g_dbg_input then
+ e_LogWritefln('Input Debug: text, text=%s', [ev.text]);
+ Utf8ToUnicode(@ch, PChar(ev.text), 1);
+ if IsValid1251(Word(ch)) then
+ begin
+ sch := AnsiChar(wchar2win(ch));
+ CharPress(sch);
+ end;
+ end;
+
+ function sys_HandleInput (): Boolean;
+ var ev: TSDL_Event;
+ begin
+ result := false;
+ while SDL_PollEvent(@ev) <> 0 do
+ begin
+ case ev.type_ of
+ SDL_QUITEV: result := true;
+ SDL_WINDOWEVENT: result := HandleWindow(ev.window);
+ SDL_KEYUP, SDL_KEYDOWN: HandleKeyboard(ev.key);
+ SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP: HandleJoyButton(ev.jbutton);
+ SDL_JOYAXISMOTION: HandleJoyAxis(ev.jaxis);
+ SDL_JOYHATMOTION: HandleJoyHat(ev.jhat);
+ SDL_JOYDEVICEADDED: HandleJoyAdd(ev.jdevice);
+ SDL_JOYDEVICEREMOVED: HandleJoyRemove(ev.jdevice);
+ SDL_TEXTINPUT: HandleTextInput(ev.text);
+ SDL_FINGERMOTION, SDL_FINGERDOWN, SDL_FINGERUP: g_Touch_HandleEvent(ev.tfinger);
+ end
+ end
+ end;
+
+ procedure sys_RequestQuit;
+ var ev: TSDL_Event;
+ begin
+ ev.type_ := SDL_QUITEV;
+ SDL_PushEvent(@ev)
+ end;
+
+ (* --------- Init --------- *)
+
+ procedure sys_Init;
+ var flags: UInt32; ok: Boolean;
+ begin
+ e_WriteLog('Init SDL2', TMsgType.Notify);
+ {$IFDEF HEADLESS}
+ {$IFDEF USE_SDLMIXER}
+ flags := SDL_INIT_TIMER or SDL_INIT_AUDIO or $00004000;
+ {$ELSE}
+ flags := SDL_INIT_TIMER or $00004000;
+ {$ENDIF}
+ {$ELSE}
+ flags := SDL_INIT_JOYSTICK or SDL_INIT_TIMER or SDL_INIT_VIDEO;
+ {$ENDIF}
+ SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, '0');
+ if SDL_Init(flags) <> 0 then
+ raise Exception.Create('SDL: Init failed: ' + SDL_GetError);
+ ok := InitWindow(gScreenWidth, gScreenHeight, gBPP, gFullscreen);
+ if not ok then
+ raise Exception.Create('SDL: Failed to set videomode: ' + SDL_GetError);
+ end;
+
+ procedure sys_Final;
+ begin
+ e_WriteLog('Releasing SDL2', TMsgType.Notify);
+ if context <> nil then
+ SDL_GL_DeleteContext(context);
+ if window <> nil then
+ SDL_DestroyWindow(window);
+ window := nil;
+ context := nil;
+ SDL_Quit
+ end;
+
+initialization
+ conRegVar('sdl2_display_index', @display, 'use display index as base', '');
+end.
diff --git a/src/game/sdl2/g_touch.pas b/src/game/sdl2/g_touch.pas
--- /dev/null
@@ -0,0 +1,322 @@
+(* Copyright (C) Doom 2D: Forever Developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License ONLY.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *)
+{$INCLUDE ../shared/a_modes.inc}
+unit g_touch;
+
+interface
+
+ uses
+ SDL2;
+
+ var
+ g_touch_enabled: Boolean = False;
+ g_touch_size: Single = 1.0;
+ g_touch_offset: Single = 50.0;
+ g_touch_fire: Boolean = True;
+ g_touch_alt: Boolean = False;
+
+ procedure g_Touch_Init;
+ procedure g_Touch_ShowKeyboard(yes: Boolean);
+ procedure g_Touch_HandleEvent(const ev: TSDL_TouchFingerEvent);
+ procedure g_Touch_Draw;
+
+implementation
+
+ uses
+ SysUtils,
+ e_log, e_graphics, e_input, g_options, g_game, g_main, g_gui, g_weapons, g_console, g_window;
+
+ var
+ angleFire: Boolean;
+ keyFinger: array [VK_FIRSTKEY..VK_LASTKEY] of Integer;
+
+ procedure GetKeyRect(key: Integer; out x, y, w, h: Integer; out founded: Boolean);
+ var
+ sw, sh, sz: Integer;
+ dpi: Single;
+
+ procedure S (xx, yy, ww, hh: Single);
+ begin
+ x := Trunc(xx);
+ y := Trunc(yy);
+ w := Trunc(ww);
+ h := Trunc(hh);
+ founded := true;
+ end;
+
+ begin
+ founded := false;
+ if SDL_GetDisplayDPI(0, @dpi, nil, nil) <> 0 then
+ dpi := 96;
+
+ sz := Trunc(g_touch_size * dpi); sw := gScreenWidth; sh := gScreenHeight;
+ x := 0; y := Round(sh * g_touch_offset / 100);
+ w := sz; h := sz;
+
+ if SDL_IsTextInputActive() = SDL_True then
+ case key of
+ VK_HIDEKBD: S(sw - (sz/2), 0, sz / 2, sz / 2);
+ end
+ else if g_touch_alt then
+ case key of
+ (* top ------- x ------------------------------- y w ----- h -- *)
+ VK_CONSOLE: S(0, 0, sz / 2, sz / 2);
+ VK_ESCAPE: S(sw - 1*(sz/2) - 1, 0, sz / 2, sz / 2);
+ VK_SHOWKBD: S(sw - 2*(sz/2) - 1, 0, sz / 2, sz / 2);
+ VK_CHAT: S(sw / 2 - (sz/2) / 2 - (sz/2) - 1, 0, sz / 2, sz / 2);
+ VK_STATUS: S(sw / 2 - (sz/2) / 2 - 1, 0, sz / 2, sz / 2);
+ VK_TEAM: S(sw / 2 - (sz/2) / 2 + (sz/2) - 1, 0, sz / 2, sz / 2);
+ (* left --- x - y -------------- w - h --- *)
+ VK_PREV: S(0, sh - 3.0*sz - 1, sz, sz / 2);
+ VK_LEFT: S(0, sh - 2.0*sz - 1, sz, sz * 2);
+ VK_RIGHT: S(sz, sh - 2.0*sz - 1, sz, sz * 2);
+ (* right - x ------------ y -------------- w - h -- *)
+ VK_NEXT: S(sw - 1*sz - 1, sh - 3.0*sz - 1, sz, sz / 2);
+ VK_UP: S(sw - 2*sz - 1, sh - 2.0*sz - 1, sz, sz / 2);
+ VK_FIRE: S(sw - 2*sz - 1, sh - 1.5*sz - 1, sz, sz);
+ VK_DOWN: S(sw - 2*sz - 1, sh - 0.5*sz - 1, sz, sz / 2);
+ VK_JUMP: S(sw - 1*sz - 1, sh - 2.0*sz - 1, sz, sz);
+ VK_OPEN: S(sw - 1*sz - 1, sh - 1.0*sz - 1, sz, sz);
+ end
+ else
+ case key of
+ (* left ----- x ----- y -------------- w ----- h -- *)
+ VK_ESCAPE: S(0.0*sz, y - 1*sz - sz/2, sz, sz / 2);
+ VK_LSTRAFE: S(0.0*sz, y - 0*sz - sz/2, sz / 2, sz);
+ VK_LEFT: S(0.5*sz, y - 0*sz - sz/2, sz, sz);
+ VK_RIGHT: S(1.5*sz, y - 0*sz - sz/2, sz, sz);
+ VK_RSTRAFE: S(2.5*sz, y - 0*sz - sz/2, sz / 2, sz);
+ (* right - x ------------ y --------------- w - h *)
+ VK_UP: S(sw - 1*sz - 1, y - 1*sz - sz/2, sz, sz);
+ VK_FIRE: S(sw - 1*sz - 1, y - 0*sz - sz/2, sz, sz);
+ VK_DOWN: S(sw - 1*sz - 1, y - -1*sz - sz/2, sz, sz);
+ VK_NEXT: S(sw - 2*sz - 1, y - 1*sz - sz/2, sz, sz);
+ VK_JUMP: S(sw - 2*sz - 1, y - 0*sz - sz/2, sz, sz);
+ VK_PREV: S(sw - 3*sz - 1, y - 1*sz - sz/2, sz, sz);
+ VK_OPEN: S(sw - 3*sz - 1, y - 0*sz - sz/2, sz, sz);
+ (* bottom ---- x -------------------------- y ---------------- w ----- h -- *)
+ VK_CHAT: S(sw/2 - sz/4 - 2*(sz/2) - 1, sh - 2*(sz/2) - 1, sz / 2, sz / 2);
+ VK_CONSOLE: S(sw/2 - sz/4 - 1*(sz/2) - 1, sh - 2*(sz/2) - 1, sz / 2, sz / 2);
+ VK_STATUS: S(sw/2 - sz/4 - 0*(sz/2) - 1, sh - 2*(sz/2) - 1, sz / 2, sz / 2);
+ VK_TEAM: S(sw/2 - sz/4 - -1*(sz/2) - 1, sh - 2*(sz/2) - 1, sz / 2, sz / 2);
+ VK_SHOWKBD: S(sw/2 - sz/4 - -2*(sz/2) - 1, sh - 2*(sz/2) - 1, sz / 2, sz / 2);
+ VK_0: S(sw/2 - sz/4 - 5*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2);
+ VK_1: S(sw/2 - sz/4 - 4*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2);
+ VK_2: S(sw/2 - sz/4 - 3*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2);
+ VK_3: S(sw/2 - sz/4 - 2*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2);
+ VK_4: S(sw/2 - sz/4 - 1*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2);
+ VK_5: S(sw/2 - sz/4 - 0*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2);
+ VK_6: S(sw/2 - sz/4 - -1*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2);
+ VK_7: S(sw/2 - sz/4 - -2*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2);
+ VK_8: S(sw/2 - sz/4 - -3*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2);
+ VK_9: S(sw/2 - sz/4 - -4*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2);
+ VK_A: S(sw/2 - sz/4 - -5*(sz/2) - 1, sh - 1*(sz/2) - 1, sz / 2, sz / 2);
+ end
+ end;
+
+ function GetKeyName(key: Integer): String;
+ begin
+ case key of
+ VK_SHOWKBD: result := 'KBD';
+ VK_HIDEKBD: result := 'KBD';
+ VK_LEFT: result := 'LEFT';
+ VK_RIGHT: result := 'RIGHT';
+ VK_UP: result := 'UP';
+ VK_DOWN: result := 'DOWN';
+ VK_FIRE: result := 'FIRE';
+ VK_OPEN: result := 'OPEN';
+ VK_JUMP: result := 'JUMP';
+ VK_CHAT: result := 'CHAT';
+ VK_ESCAPE: result := 'ESC';
+ VK_0: result := '0';
+ VK_1: result := '1';
+ VK_2: result := '2';
+ VK_3: result := '3';
+ VK_4: result := '4';
+ VK_5: result := '5';
+ VK_6: result := '6';
+ VK_7: result := '7';
+ VK_8: result := '8';
+ VK_9: result := '9';
+ VK_A: result := '10';
+ VK_B: result := '11';
+ VK_C: result := '12';
+ VK_D: result := '13';
+ VK_E: result := '14';
+ VK_F: result := '15';
+ VK_CONSOLE: result := 'CON';
+ VK_STATUS: result := 'STAT';
+ VK_TEAM: result := 'TEAM';
+ VK_PREV: result := '<PREW';
+ VK_NEXT: result := 'NEXT>';
+ VK_LSTRAFE: result := '<';
+ VK_RSTRAFE: result := '>';
+ else
+ if (key > 0) and (key < e_MaxInputKeys) then
+ result := e_KeyNames[key]
+ else
+ result := '<' + IntToStr(key) + '>'
+ end
+ end;
+
+ function IntersectControl(ctl, xx, yy: Integer): Boolean;
+ var
+ x, y, w, h: Integer;
+ founded: Boolean;
+ begin
+ GetKeyRect(ctl, x, y, w, h, founded);
+ result := founded and (xx >= x) and (yy >= y) and (xx <= x + w) and (yy <= y + h);
+ end;
+
+ procedure g_Touch_Init;
+ begin
+{$IFNDEF HEADLESS}
+ g_Touch_ShowKeyboard(FALSE);
+ g_touch_enabled := SDL_GetNumTouchDevices() > 0
+{$ENDIF}
+ end;
+
+ procedure g_Touch_ShowKeyboard(yes: Boolean);
+ begin
+{$IFNDEF HEADLESS}
+ if g_dbg_input then
+ e_LogWritefln('g_Touch_ShowKeyboard(%s)', [yes]);
+ (* on desktop we always receive text (needed for cheats) *)
+ if yes or (SDL_HasScreenKeyboardSupport() = SDL_FALSE) then
+ SDL_StartTextInput
+ else
+ SDL_StopTextInput
+{$ENDIF}
+ end;
+
+ procedure g_Touch_HandleEvent(const ev: TSDL_TouchFingerEvent);
+ var
+ x, y, i, finger: Integer;
+
+ procedure KeyUp (finger, i: Integer);
+ begin
+ if g_dbg_input then
+ e_LogWritefln('Input Debug: g_touch.KeyUp, finger=%s, key=%s', [finger, i]);
+
+ keyFinger[i] := 0;
+ e_KeyUpDown(i, False);
+ g_Console_ProcessBind(i, False);
+
+ (* up/down + fire hack *)
+ if g_touch_fire and (gGameSettings.GameType <> GT_NONE) and (g_ActiveWindow = nil) and angleFire then
+ begin
+ if (i = VK_UP) or (i = VK_DOWN) then
+ begin
+ angleFire := False;
+ keyFinger[VK_FIRE] := 0;
+ e_KeyUpDown(VK_FIRE, False);
+ g_Console_ProcessBind(VK_FIRE, False)
+ end
+ end
+ end;
+
+ procedure KeyDown (finger, i: Integer);
+ begin
+ if g_dbg_input then
+ e_LogWritefln('Input Debug: g_touch.KeyDown, finger=%s, key=%s', [finger, i]);
+
+ keyFinger[i] := finger;
+ e_KeyUpDown(i, True);
+ g_Console_ProcessBind(i, True);
+
+ (* up/down + fire hack *)
+ if g_touch_fire and (gGameSettings.GameType <> GT_NONE) and (g_ActiveWindow = nil) then
+ begin
+ if i = VK_UP then
+ begin
+ angleFire := True;
+ keyFinger[VK_FIRE] := -1;
+ e_KeyUpDown(VK_FIRE, True);
+ g_Console_ProcessBind(VK_FIRE, True)
+ end
+ else if i = VK_DOWN then
+ begin
+ angleFire := True;
+ keyFinger[VK_FIRE] := -1;
+ e_KeyUpDown(VK_FIRE, True);
+ g_Console_ProcessBind(VK_FIRE, True)
+ end
+ end
+ end;
+
+ procedure KeyMotion (finger, i: Integer);
+ begin
+ if keyFinger[i] <> finger then
+ begin
+ KeyUp(finger, i);
+ KeyDown(finger, i)
+ end
+ end;
+
+ begin
+ if not g_touch_enabled then
+ Exit;
+
+ finger := ev.fingerId + 2;
+ x := Trunc(ev.x * gScreenWidth);
+ y := Trunc(ev.y * gScreenHeight);
+
+ for i := VK_FIRSTKEY to VK_LASTKEY do
+ begin
+ if IntersectControl(i, x, y) then
+ begin
+ if ev.type_ = SDL_FINGERUP then
+ KeyUp(finger, i)
+ else if ev.type_ = SDL_FINGERMOTION then
+ KeyMotion(finger, i)
+ else if ev.type_ = SDL_FINGERDOWN then
+ keyDown(finger, i)
+ end
+ else if keyFinger[i] = finger then
+ begin
+ if ev.type_ = SDL_FINGERUP then
+ KeyUp(finger, i)
+ else if ev.type_ = SDL_FINGERMOTION then
+ KeyUp(finger, i)
+ end
+ end
+ end;
+
+ procedure g_Touch_Draw;
+ var i, x, y, w, h: Integer; founded: Boolean;
+ begin
+{$IFNDEF HEADLESS}
+ if not g_touch_enabled then
+ Exit;
+
+ for i := VK_FIRSTKEY to VK_LASTKEY do
+ begin
+ GetKeyRect(i, x, y, w, h, founded);
+ if founded then
+ begin
+ e_DrawQuad(x, y, x + w, y + h, 0, 255, 0, 31);
+ e_TextureFontPrintEx(x, y, GetKeyName(i), gStdFont, 255, 255, 255, 1, True)
+ end
+ end
+{$ENDIF}
+ end;
+
+initialization
+ conRegVar('touch_enable', @g_touch_enabled, 'enable/disable virtual buttons', 'draw buttons');
+ conRegVar('touch_fire', @g_touch_fire, 'enable/disable fire when press virtual up/down', 'fire when press up/down');
+ conRegVar('touch_size', @g_touch_size, 0.1, 10, 'size of virtual buttons', 'button size');
+ conRegVar('touch_offset', @g_touch_offset, 0, 100, '', '');
+ conRegVar('touch_alt', @g_touch_alt, 'althernative virtual buttons layout', 'althernative layout');
+end.
index 84ae12138b5de86079efd98c67a04f8056169049..4e9fcedc40989b2414655f8572f1881a5daeacbf 100644 (file)
function sys_GetDispalyModes (bpp: Integer): SSArray;
begin
- SetLength(result, 0);
+ result := nil
end;
function sys_SetDisplayMode (w, h, bpp: Integer; fullscreen: Boolean): Boolean;
begin
- result := True
+ result := true
end;
(* --------- Input --------- *)