diff --git a/src/game/g_window.pas b/src/game/g_window.pas
index bb20c47dd3feba89956de37b19402342bcbdecc8..ef1d362bd77362b5d5045ea3ffcea44b9ed24da7 100644 (file)
--- a/src/game/g_window.pas
+++ b/src/game/g_window.pas
implementation
uses
- SDL, GL, GLExt, e_graphics, e_log, g_main,
+ SDL2, GL, GLExt, e_graphics, e_log, g_main,
g_console, SysUtils, e_input, g_options, g_game,
g_basic, g_textures, e_sound, g_sound, g_menu, ENet, g_net;
var
- h_Wnd: PSDL_Surface;
+ h_Wnd: PSDL_Window;
+ h_GL: TSDL_GLContext;
wFlags: LongWord = 0;
Time, Time_Delta, Time_Old: Int64;
flag: Boolean;
+ wTitle: PChar = nil;
wNeedTimeReset: Boolean = False;
- wWindowCreated: Boolean = False;
+ //wWindowCreated: Boolean = False;
//wCursorShown: Boolean = False;
wMinimized: Boolean = False;
//wNeedFree: Boolean = True;
// TODO: make a transition table or something
function WCharToCP1251(wc: Word): Word;
+var
+ n: Word;
begin
- for Result := 0 to 127 do
- if CP1251[Result] = wc then
- break;
+ Result := 0;
+ for n := 0 to 127 do
+ if CP1251[n] = wc then begin Result := n; break end;
Result := Result + 128;
end;
function g_Window_SetDisplay(PreserveGL: Boolean = False): Boolean;
+var
+ mode, cmode: TSDL_DisplayMode;
begin
Result := False;
e_WriteLog('Setting display mode...', MSG_NOTIFY);
- if wWindowCreated and PreserveGL then
- e_SaveGLContext(); // we need this and restore because of a bug in SDL1.2, apparently
-
- wFlags := SDL_RESIZABLE or SDL_OPENGL;
- if gFullscreen then wFlags := wFlags or SDL_FULLSCREEN;
+ wFlags := SDL_WINDOW_OPENGL or SDL_WINDOW_RESIZABLE;
+ if gFullscreen then wFlags := wFlags or SDL_WINDOW_FULLSCREEN;
+ if gWinMaximized then wFlags := wFlags or SDL_WINDOW_MAXIMIZED;
+
+ if h_Wnd <> nil then
+ begin
+ SDL_DestroyWindow(h_Wnd);
+ h_Wnd := nil;
+ end;
+
+ if gFullscreen then
+ begin
+ mode.w := gScreenWidth;
+ mode.h := gScreenHeight;
+ mode.format := 0;
+ mode.refresh_rate := 0;
+ mode.driverdata := nil;
+ if SDL_GetClosestDisplayMode(0, @mode, @cmode) = nil then
+ begin
+ gScreenWidth := 800;
+ gScreenHeight := 600;
+ end
+ else
+ begin
+ gScreenWidth := cmode.w;
+ gScreenHeight := cmode.h;
+ end;
+ end;
- h_Wnd := SDL_SetVideoMode(gScreenWidth, gScreenHeight, gBPP, wFlags);
- SDL_EnableUNICODE(SDL_ENABLE);
- SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+ h_Wnd := SDL_CreateWindow(PChar(wTitle), gWinRealPosX, gWinRealPosY, gScreenWidth, gScreenHeight, wFlags);
+ if h_Wnd = nil then Exit;
+
+ SDL_GL_MakeCurrent(h_Wnd, h_GL);
SDL_ShowCursor(SDL_DISABLE);
- if wWindowCreated and PreserveGL then
- e_RestoreGLContext();
-
- Result := h_Wnd <> nil;
+ Result := True;
end;
procedure ReShowCursor();
function GetDisplayModes(dBPP: DWORD; var SelRes: DWORD): SArray;
var
- modesp: PPSDL_Rect;
- tmpp: PSDL_Rect;
- tmpr: SDL_Rect;
- i: Integer;
+ mode: TSDL_DisplayMode;
+ res, i, k, n, pw, ph: Integer;
begin
SetLength(Result, 0);
- modesp := SDL_ListModes(nil, SDL_FULLSCREEN or SDL_HWSURFACE);
- if modesp = nil then exit;
- if Pointer(-1) = modesp then exit;
- tmpp := modesp^;
- i := 0;
- while tmpp <> nil do
+ k := 0; SelRes := 0;
+ n := SDL_GetNumDisplayModes(0);
+ pw := 0; ph := 0;
+ for i := 0 to n do
begin
- tmpr := tmpp^;
- if (tmpr.w = gScreenWidth) and (tmpr.h = gScreenHeight) then
- SelRes := i;
- SetLength(Result, Length(Result) + 1);
- Result[i] := IntToStr(tmpr.w) + 'x' + IntToStr(tmpr.h);
-
- modesp := Pointer(Cardinal(modesp) + SizeOf(PSDL_Rect));
- tmpp := modesp^;
- Inc(i);
+ res := SDL_GetDisplayMode(0, i, @mode);
+ if res < 0 then continue;
+ if SDL_BITSPERPIXEL(mode.format) = gBPP then continue;
+ if (mode.w = pw) and (mode.h = ph) then continue;
+ if (mode.w = gScreenWidth) and (mode.h = gScreenHeight) then
+ SelRes := k;
+ Inc(k);
+ SetLength(Result, k);
+ Result[k-1] := IntToStr(mode.w) + 'x' + IntToStr(mode.h);
+ pw := mode.w; ph := mode.h
end;
- e_WriteLog('SDL: Got ' + IntToStr(Length(Result)) + ' resolutions.', MSG_NOTIFY);
+ e_WriteLog('SDL: Got ' + IntToStr(k) + ' resolutions.', MSG_NOTIFY);
end;
procedure Sleep(ms: LongWord);
end;
end;
-function EventHandler(ev: TSDL_Event): Boolean;
+function WindowEventHandler(ev: TSDL_WindowEvent): Boolean;
var
- key, keychr: Word;
- //joy: Integer;
+ wActivate, wDeactivate: Boolean;
begin
Result := False;
- case ev.type_ of
- SDL_VIDEORESIZE:
+ wActivate := False;
+ wDeactivate := False;
+
+ case ev.event of
+ SDL_WINDOWEVENT_MOVED:
begin
- g_Window_SetSize(ev.resize.w, ev.resize.h, gFullscreen);
- e_Clear();
+ if not (gFullscreen or gWinMaximized) then
+ begin
+ gWinRealPosX := ev.data1;
+ gWinRealPosY := ev.data2;
+ end;
end;
-
- SDL_ACTIVEEVENT:
+
+ SDL_WINDOWEVENT_MINIMIZED:
begin
- if (ev.active.gain = 0) then
+ if not wMinimized then
begin
- if g_debug_WinMsgs then
- begin
- g_Console_Add('Inactive');
- e_WriteLog('[DEBUG] WinMsgs: Inactive', MSG_NOTIFY);
- end;
-
- if LongBool(ev.active.state and SDL_APPINPUTFOCUS) and gWinActive then
- begin
- e_EnableInput := False;
- e_ClearInputBuffer();
-
- if gMuteWhenInactive then
- e_MuteChannels(True);
-
- if g_debug_WinMsgs then
- begin
- g_Console_Add('Inactive indeed');
- e_WriteLog('[DEBUG] WinMsgs: Inactive indeed', MSG_NOTIFY);
- end;
+ e_ResizeWindow(0, 0);
+ wMinimized := True;
- gWinActive := False;
- end;
-
- if LongBool(ev.active.state and SDL_APPACTIVE) and (not wMinimized) then
+ if g_debug_WinMsgs then
begin
- e_ResizeWindow(0, 0);
- wMinimized := True;
-
- if g_debug_WinMsgs then
- begin
- g_Console_Add('Minimized indeed');
- e_WriteLog('[DEBUG] WinMsgs: Minimized indeed', MSG_NOTIFY);
- end;
+ g_Console_Add('Now minimized');
+ e_WriteLog('[DEBUG] WinMsgs: Now minimized', MSG_NOTIFY);
end;
- end
- else
+ wDeactivate := True;
+ end;
+ end;
+
+ SDL_WINDOWEVENT_RESIZED:
+ begin
+ gScreenWidth := ev.data1;
+ gScreenHeight := ev.data2;
+ ChangeWindowSize();
+ SwapBuffers();
+ if g_debug_WinMsgs then
+ begin
+ g_Console_Add('Resized to ' + IntToStr(ev.data1) + 'x' + IntToStr(ev.data2));
+ e_WriteLog('[DEBUG] WinMsgs: Resized to ' + IntToStr(ev.data1) + 'x' + IntToStr(ev.data2), MSG_NOTIFY);
+ end;
+ end;
+
+ SDL_WINDOWEVENT_EXPOSED:
+ SwapBuffers();
+
+ SDL_WINDOWEVENT_MAXIMIZED:
+ begin
+ if wMinimized then
begin
+ e_ResizeWindow(gScreenWidth, gScreenHeight);
+ wMinimized := False;
+ wActivate := True;
+ end;
+ if not gWinMaximized then
+ begin
+ gWinMaximized := True;
if g_debug_WinMsgs then
begin
- g_Console_Add('Active');
- e_WriteLog('[DEBUG] WinMsgs: Active', MSG_NOTIFY);
+ g_Console_Add('Now maximized');
+ e_WriteLog('[DEBUG] WinMsgs: Now maximized', MSG_NOTIFY);
end;
+ end;
+ end;
+
+ SDL_WINDOWEVENT_RESTORED:
+ begin
+ if wMinimized then
+ begin
+ e_ResizeWindow(gScreenWidth, gScreenHeight);
+ wMinimized := False;
+ wActivate := True;
+ end;
+ if gWinMaximized then
+ gWinMaximized := False;
+ if g_debug_WinMsgs then
+ begin
+ g_Console_Add('Now restored');
+ e_WriteLog('[DEBUG] WinMsgs: Now restored', MSG_NOTIFY);
+ end;
+ end;
- // Åñëè îêíî áûëî íåàêòèâíûì:
- if LongBool(ev.active.state and SDL_APPINPUTFOCUS) and (not gWinActive) then
- begin
- e_EnableInput := True;
+ SDL_WINDOWEVENT_FOCUS_GAINED:
+ begin
+ wActivate := True;
+ //e_WriteLog('window gained focus!', MSG_NOTIFY);
+ end;
- if gMuteWhenInactive then
- e_MuteChannels(False);
+ SDL_WINDOWEVENT_FOCUS_LOST:
+ begin
+ wDeactivate := True;
+ //e_WriteLog('window lost focus!', MSG_NOTIFY);
+ end;
+ end;
- if g_debug_WinMsgs then
- begin
- g_Console_Add('Active indeed');
- e_WriteLog('[DEBUG] WinMsgs: Active indeed', MSG_NOTIFY);
- end;
+ if wDeactivate then
+ begin
+ if gWinActive then
+ begin
+ e_WriteLog('deactivating window', MSG_NOTIFY);
+ e_EnableInput := False;
+ e_ClearInputBuffer();
- gWinActive := True;
- end;
+ if gMuteWhenInactive then
+ begin
+ //e_WriteLog('deactivating sounds', MSG_NOTIFY);
+ e_MuteChannels(True);
+ end;
- if LongBool(ev.active.state and SDL_APPACTIVE) and wMinimized then
- begin
- e_ResizeWindow(gScreenWidth, gScreenHeight);
+ if g_debug_WinMsgs then
+ begin
+ g_Console_Add('Now inactive');
+ e_WriteLog('[DEBUG] WinMsgs: Now inactive', MSG_NOTIFY);
+ end;
- wMinimized := False;
+ gWinActive := False;
+ end;
+ end
+ else if wActivate then
+ begin
+ if not gWinActive then
+ begin
+ //e_WriteLog('activating window', MSG_NOTIFY);
+ e_EnableInput := True;
- if g_debug_WinMsgs then
- begin
- g_Console_Add('Restored indeed');
- e_WriteLog('[DEBUG] WinMsgs: Restored indeed', MSG_NOTIFY);
- end;
- end;
+ if gMuteWhenInactive then
+ begin
+ //e_WriteLog('activating sounds', MSG_NOTIFY);
+ e_MuteChannels(False);
end;
- end;
- SDL_VIDEOEXPOSE:
- begin
- // TODO: the fuck is this event?
- // Draw();
+ if g_debug_WinMsgs then
+ begin
+ g_Console_Add('Now active');
+ e_WriteLog('[DEBUG] WinMsgs: Now active', MSG_NOTIFY);
+ end;
+
+ gWinActive := True;
end;
+ end;
+end;
+
+function EventHandler(ev: TSDL_Event): Boolean;
+var
+ key, keychr: Word;
+ uc: UnicodeChar;
+ //joy: Integer;
+begin
+ Result := False;
+ case ev.type_ of
+ SDL_WINDOWEVENT:
+ Result := WindowEventHandler(ev.window);
SDL_QUITEV:
begin
SDL_KEYDOWN:
begin
- key := ev.key.keysym.sym;
- keychr := ev.key.keysym.unicode;
+ key := ev.key.keysym.scancode;
KeyPress(key);
- if (keychr > 7) and (key <> IK_BACKSPACE) then
- begin
- if (keychr >= 128) then
- keychr := WCharToCP1251(keychr);
- CharPress(Chr(keychr));
- end;
+ end;
+
+ SDL_TEXTINPUT:
+ begin
+ Utf8ToUnicode(@uc, PChar(ev.text.text), 1);
+ keychr := Word(uc);
+ if (keychr > 127) then
+ keychr := WCharToCP1251(keychr);
+ CharPress(Chr(keychr));
end;
- // key presses and joysticks are handled in e_input
+ // other key presses and joysticks are handled in e_input
end;
end;
procedure SwapBuffers();
begin
- SDL_GL_SwapBuffers();
+ SDL_GL_SwapWindow(h_Wnd);
end;
procedure KillGLWindow();
begin
- wWindowCreated := False;
+ if h_Wnd <> nil then SDL_DestroyWindow(h_Wnd);
+ if h_GL <> nil then SDL_GL_DeleteContext(h_GL);
+ h_Wnd := nil;
+ h_GL := nil;
+ //wWindowCreated := False;
end;
function CreateGLWindow(Title: PChar): Boolean;
gWinSizeX := gScreenWidth;
gWinSizeY := gScreenHeight;
+ wTitle := Title;
e_WriteLog('Creating window', MSG_NOTIFY);
if not g_Window_SetDisplay() then
exit;
end;
- SDL_WM_SetCaption(Title, Title);
- wWindowCreated := True;
+ h_Gl := SDL_GL_CreateContext(h_Wnd);
+ if h_Gl = nil then Exit;
+
+ //wWindowCreated := True;
e_ResizeWindow(gScreenWidth, gScreenHeight);
e_InitGL();
ev: TSDL_Event;
ID: DWORD;
begin
+ FillChar(ev, SizeOf(ev), 0);
//wNeedFree := False;
wLoadingProgress := True;
while SDL_PollEvent(@ev) > 0 do
ev: TSDL_Event;
begin
Result := False;
+ FillChar(ev, SizeOf(ev), 0);
while SDL_PollEvent(@ev) > 0 do
begin
v: Byte;
begin
if VSync then v := 1 else v := 0;
+ 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_SWAP_CONTROL, v);
+ SDL_GL_SetSwapInterval(v);
end;
function SDLMain(): Integer;