43#define STB_IMAGE_WRITE_IMPLEMENTATION
46#define kOOLogUnconvertedNSLog @"unclassified.MyOpenGLView"
48extern int SaveEXRSnapshot(
const char* outfilename,
int width,
int height,
const float* rgb);
50static NSString *
kOOLogKeyUp =
@"input.keyMapping.keyPress.keyUp";
56#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
57#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
59HRESULT WINAPI DwmSetWindowAttribute (HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
61#define USE_UNDOCUMENTED_DARKMODE_API 1
63#if USE_UNDOCUMENTED_DARKMODE_API
64#ifndef LOAD_LIBRARY_SEARCH_SYSTEM32
65#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
67typedef DWORD(WINAPI* pfnSetPreferredAppMode)(DWORD appMode);
79@interface MyOpenGLView (OOPrivate)
82- (void) setWindowBorderless:(BOOL)borderless;
83- (void) handleStringInput: (SDL_KeyboardEvent *) kbd_event keyID:(Uint16)key_id;
91 int nativeDisplayWidth = 1024;
92 int nativeDisplayHeight = 768;
95 SDL_SysWMinfo dpyInfo;
96 SDL_VERSION(&dpyInfo.version);
97 if(SDL_GetWMInfo(&dpyInfo))
99 nativeDisplayWidth = DisplayWidth(dpyInfo.info.x11.display, 0);
100 nativeDisplayHeight = DisplayHeight(dpyInfo.info.x11.display, 0);
101 OOLog(
@"display.mode.list.native",
@"X11 native resolution detected: %d x %d", nativeDisplayWidth, nativeDisplayHeight);
105 OOLog(
@"display.mode.list.native.failed",
@"%@",
@"SDL_GetWMInfo failed, defaulting to 1024x768 for native size");
108 nativeDisplayWidth = GetSystemMetrics(SM_CXSCREEN);
109 nativeDisplayHeight = GetSystemMetrics(SM_CYSCREEN);
110 OOLog(
@"display.mode.list.native",
@"Windows native resolution detected: %d x %d", nativeDisplayWidth, nativeDisplayHeight);
112 OOLog(
@"display.mode.list.native.unknown",
@"Unknown architecture, defaulting to 1024x768");
114 [mode setValue: [
NSNumber numberWithInt: nativeDisplayWidth] forKey:kOODisplayWidth];
115 [mode setValue: [
NSNumber numberWithInt: nativeDisplayHeight] forKey: kOODisplayHeight];
116 [mode setValue: [
NSNumber numberWithInt: 0] forKey: kOODisplayRefreshRate];
118 return [mode autorelease];
125 const int videoModeFlags = SDL_HWSURFACE | SDL_OPENGL | SDL_RESIZABLE;
132 ShowWindow(SDL_Window,SW_SHOWMINIMIZED);
142 surface = SDL_SetVideoMode(8, 8, 32, videoModeFlags);
164 char * errStr = SDL_GetError();
165 OOLogWARN(
@"gamma.set.failed",
@"Could not set gamma: %s", errStr);
170 SDL_EnableUNICODE(1);
179 SDL_Surface *icon=NULL;
181 NSString *cmdLineArgsStr =
@"Startup command: ";
187 BOOL vSyncPreference = [
prefs oo_boolForKey:@"v-sync" defaultValue:YES];
188 int bitsPerColorComponent = [
prefs oo_boolForKey:@"hdr" defaultValue:NO] ? 16 : 8;
191 NSArray *arguments =
nil;
192 NSEnumerator *argEnum =
nil;
194 BOOL noSplashArgFound = NO;
205 for (argEnum = [arguments objectEnumerator]; (arg = [
argEnum nextObject]); )
207 if ([arg isEqual:
@"-nosplash"] || [arg isEqual:
@"--nosplash"])
210 noSplashArgFound = YES;
212 else if (([arg isEqual:
@"-splash"] || [arg isEqual:
@"--splash"]) && !noSplashArgFound)
218 if ([arg isEqual:
@"-novsync"] || [arg isEqual:
@"--novsync"]) vSyncPreference = NO;
220 if ([arg isEqual:
@"-hdr"]) bitsPerColorComponent = 16;
223 cmdLineArgsStr = [
cmdLineArgsStr stringByAppendingFormat:@"%@ ", arg];
226 OOLog(
@"process.args",
@"%@", cmdLineArgsStr);
232 OOLog(
@"sdl.init",
@"%@",
@"initialising SDL");
233 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0)
235 OOLog(
@"sdl.init.failed",
@"Unable to init SDL: %s\n", SDL_GetError());
240 SDL_putenv (
"SDL_VIDEO_WINDOW_POS=center");
246 if (![
OOSound isSoundOK])
OOLog(
@"sound.init",
@"%@",
@"Sound system disabled.");
249 static char windowCaption[128];
250 NSString *versionString = [
NSString stringWithFormat:@"Oolite v%@", [[[
NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]];
252 strcpy (windowCaption, [versionString UTF8String]);
253 strcat (windowCaption,
" - "__DATE__);
254 SDL_WM_SetCaption (windowCaption,
"Oolite");
258 SDL_EventState (SDL_SYSWMEVENT, SDL_ENABLE);
261 static SDL_SysWMinfo wInfo;
262 SDL_VERSION(&wInfo.version);
263 SDL_GetWMInfo(&wInfo);
264 SDL_Window = wInfo.window;
267 if (![
self getCurrentMonitorInfo:&monitorInfo])
269 OOLogWARN(
@"display.initGL.monitorInfoWarning",
@"Could not get current monitor information.");
272 atDesktopResolution = YES;
274#if USE_UNDOCUMENTED_DARKMODE_API
276 HMODULE hUxTheme = LoadLibraryExW(L
"uxtheme.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
280 pfnSetPreferredAppMode SetPreferredAppMode = (pfnSetPreferredAppMode)GetProcAddress(hUxTheme, MAKEINTRESOURCEA(135));
281 if (SetPreferredAppMode) SetPreferredAppMode(AllowDark);
282 FreeLibrary(hUxTheme);
284 [
self refreshDarKOrLightMode];
290 imagesDir = [[[
NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Images"];
291 icon = SDL_LoadBMP([[imagesDir stringByAppendingPathComponent:
@"WMicon.bmp"] UTF8String]);
295 colorkey = SDL_MapRGB(icon->format, 128, 0, 128);
296 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, colorkey);
297 SDL_WM_SetIcon(icon, NULL);
299 SDL_FreeSurface(icon);
301 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, bitsPerColorComponent);
302 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, bitsPerColorComponent);
303 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, bitsPerColorComponent);
304 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, bitsPerColorComponent);
305 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
306 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
312 _hdrMaxBrightness = [
prefs oo_floatForKey:@"hdr-max-brightness" defaultValue:1000.0f];
313 _hdrPaperWhiteBrightness = [
prefs oo_floatForKey:@"hdr-paperwhite-brightness" defaultValue:200.0f];
314 _hdrToneMapper =
OOHDRToneMapperFromString([prefs oo_stringForKey:
@"hdr-tone-mapper" defaultValue:
@"OOHDR_TONEMAPPER_ACES_APPROX"]);
315 if (bitsPerColorComponent == 16)
318 SDL_GL_SetAttribute(SDL_GL_PIXEL_TYPE_FLOAT, 1);
326 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, vSyncPreference);
327 OOLog(
@"display.initGL",
@"V-Sync %@requested.", vSyncPreference ?
@"" :
@"not ");
336 if ([prefs oo_boolForKey:
@"anti-aliasing" defaultValue:NO])
338 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
339 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
342 OOLog(
@"display.mode.list",
@"%@",
@"CREATING MODE LIST");
355 OOLog(
@"display.initGL",
@"Trying %d-bpcc, 24-bit depth buffer", bitsPerColorComponent);
361 OOLog(
@"display.initGL",
@"%@",
@"Trying 8-bpcc, 32-bit depth buffer");
362 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
363 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
364 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
365 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
366 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 32);
373 OOLog(
@"display.initGL",
@"%@",
@"Trying 5-bpcc, 16-bit depth buffer");
374 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
375 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
376 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
377 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
379 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
380 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
386 char * errStr = SDL_GetError();
387 OOLogERR(
@"display.mode.error",
@"Could not create display surface: %s", errStr);
391 [[
NSUserDefaults standardUserDefaults] setBool:NO forKey:@"splash-screen"];
393 OOLogWARN(
@"display.mode.conflict",
@"Possible incompatibility between the splash screen and video drivers detected.");
394 OOLogWARN(
@"display.mode.conflict",
@"Oolite will start without showing the splash screen from now on. Override with 'oolite.exe -splash'");
403 OOLog(
@"display.initGL",
@"%@",
@"Achieved color / depth buffer sizes (bits):");
404 SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &testAttrib);
405 OOLog(
@"display.initGL",
@"Red: %d", testAttrib);
406 SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &testAttrib);
407 OOLog(
@"display.initGL",
@"Green: %d", testAttrib);
408 SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &testAttrib);
409 OOLog(
@"display.initGL",
@"Blue: %d", testAttrib);
410 SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &testAttrib);
411 OOLog(
@"display.initGL",
@"Alpha: %d", testAttrib);
412 SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &testAttrib);
413 OOLog(
@"display.initGL",
@"Depth Buffer: %d", testAttrib);
415 SDL_GL_GetAttribute(SDL_GL_PIXEL_TYPE_FLOAT, &testAttrib);
416 OOLog(
@"display.initGL",
@"Pixel type is float : %d", testAttrib);
418 OOLog(
@"display.initGL",
@"Pixel format index: %d", GetPixelFormat(GetDC(SDL_Window)));
422 if (vSyncPreference && SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &vSyncValue) == -1)
424 OOLogWARN(
@"display.initGL",
@"Could not enable V-Sync. Please check that your graphics driver supports the %@_swap_control extension.",
458 if (MessageBox(NULL,
"No primary display in HDR mode was detected.\n\n"
459 "If you continue, graphics will not be rendered as intended.\n"
460 "Click OK to launch anyway, or Cancel to exit.",
"oolite.exe - HDR requested",
461 MB_OKCANCEL | MB_ICONWARNING) == IDCANCEL)
474 ShowWindow(SDL_Window,SW_RESTORE);
479 int videoModeFlags = SDL_HWSURFACE | SDL_OPENGL;
481 videoModeFlags |= (
fullScreen) ? SDL_FULLSCREEN : SDL_RESIZABLE;
487 videoModeFlags &= ~SDL_FULLSCREEN;
488 videoModeFlags |= SDL_RESIZABLE;
492 SDL_putenv (
"SDL_VIDEO_WINDOW_POS=none");
501 SDL_Event dummyEvent;
502 while (SDL_PollEvent(&dummyEvent))
528 NSString *kbd = [
prefs oo_stringForKey:@"keyboard-code" defaultValue:@"default"];
529 NSDictionary *subset = [
kmap objectForKey:kbd];
531 [keyMappings_normal release];
533 [keyMappings_shifted release];
541 [typedString release];
544 [screenSizes release];
548 SDL_FreeSurface(surface);
552 if (keyMappings_normal)
553 [keyMappings_normal release];
555 if (keyMappings_shifted)
556 [keyMappings_shifted release];
562 [matrixManager release];
573 if (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE)
574 SDL_ShowCursor(SDL_DISABLE);
578 if (SDL_ShowCursor(SDL_QUERY) == SDL_DISABLE)
579 SDL_ShowCursor(SDL_ENABLE);
589- (void) allowStringInput: (BOOL) value
611 [typedString setString:@""];
615- (void) setTypedString:(NSString*) value
617 [typedString setString:value];
682- (void) setFullScreenMode:(BOOL)fsm
687 [[NSUserDefaults standardUserDefaults]
688 setBool: fullScreen forKey:@"fullscreen"];
689 [[NSUserDefaults standardUserDefaults] synchronize];
693- (void) toggleScreenMode
695 [
self setFullScreenMode: !fullScreen];
697 [
self getCurrentMonitorInfo:&monitorInfo];
702 if(![
self isRunningOnPrimaryDisplayDevice])
704 [
self initialiseGLWithSize:NSMakeSize(monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left,
705 monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top)];
707 else [
self initialiseGLWithSize:[
self modeAsSize: currentSize]];
709 [
self initialiseGLWithSize:[
self modeAsSize: currentSize]];
713 [
self initialiseGLWithSize: currentWindowSize];
717 if ([PlayerEntity sharedPlayer])
724- (void) setDisplayMode:(
int)mode fullScreen:(BOOL)fsm
726 [
self setFullScreenMode: fsm];
729 [
self initialiseGLWithSize: [
self modeAsSize: mode]];
733- (
int) indexOfCurrentSize
739- (void) setScreenSize: (
int)sizeIndex
741 currentSize=sizeIndex;
743 [
self initialiseGLWithSize: [
self modeAsSize: currentSize]];
747- (NSMutableArray *)getScreenSizeArray
753- (NSSize) modeAsSize:(
int)sizeIndex
755 NSDictionary *
mode=[screenSizes objectAtIndex: sizeIndex];
769 [
self drawRect: NSMakeRect(0, 0, viewSize.width, viewSize.height)];
772- (void) drawRect:(NSRect)rect
777- (void) updateScreenWithVideoMode:(BOOL) v_mode
798 if (
UNIVERSE) [UNIVERSE drawUniverse];
802 glClearColor( 0.0, 0.0, 0.0, 0.0);
803 glClear( GL_COLOR_BUFFER_BIT);
806 SDL_GL_SwapBuffers();
814 SDL_Surface *image=NULL;
817 NSString *imagesDir = [[[
NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Images"];
819 image = SDL_LoadBMP([[imagesDir stringByAppendingPathComponent:
@"splash.bmp"] UTF8String]);
823 SDL_FreeSurface(image);
824 OOLogWARN(
@"sdl.gameStart",
@"%@",
@"image 'splash.bmp' not found!");
836 dest.x = (GetSystemMetrics(SM_CXSCREEN)- dest.w)/2;
837 dest.y = (GetSystemMetrics(SM_CYSCREEN)-dest.h)/2;
838 SetWindowLong(SDL_Window,GWL_STYLE,GetWindowLong(SDL_Window,GWL_STYLE) & ~WS_CAPTION & ~WS_THICKFRAME);
839 ShowWindow(SDL_Window,SW_RESTORE);
840 MoveWindow(SDL_Window,dest.x,dest.y,dest.w,dest.h,TRUE);
852 surface = SDL_SetVideoMode(dest.w, dest.h, 32, SDL_HWSURFACE | SDL_OPENGL);
858 glViewport( 0, 0, dest.w, dest.h);
860 glEnable( GL_TEXTURE_2D );
861 glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
862 glClear( GL_COLOR_BUFFER_BIT );
872 GLenum texture_format;
876 nOfColors = image->format->BytesPerPixel;
879 if (image->format->Rmask == 0x000000ff)
880 texture_format = GL_RGBA;
882 texture_format = GL_BGRA;
884 else if (nOfColors == 3)
886 if (image->format->Rmask == 0x000000ff)
887 texture_format = GL_RGB;
889 texture_format = GL_BGR;
891 SDL_FreeSurface(image);
892 OOLog(
@"Sdl.GameStart",
@"%@",
@"----- Encoding error within image 'splash.bmp'");
897 glGenTextures( 1, &texture );
898 glBindTexture( GL_TEXTURE_2D, texture );
901 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
902 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
905 glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, image->w, image->h, 0,
906 texture_format, GL_UNSIGNED_BYTE, image->pixels );
908 glBindTexture( GL_TEXTURE_2D, texture );
911 glTexCoord2i( 0, 0 );
913 glTexCoord2i( 1, 0 );
914 glVertex2i( dest.w, 0 );
915 glTexCoord2i( 1, 1 );
916 glVertex2i( dest.w, dest.h );
917 glTexCoord2i( 0, 1 );
918 glVertex2i( 0, dest.h );
922 SDL_GL_SwapBuffers();
927 SDL_FreeSurface( image );
929 glDeleteTextures(1, &texture);
931 glDisable( GL_TEXTURE_2D );
937- (MONITORINFOEX) currentMonitorInfo
943- (BOOL) getCurrentMonitorInfo:(MONITORINFOEX *)mInfo
945 HMONITOR hMon = MonitorFromWindow(SDL_Window, MONITOR_DEFAULTTOPRIMARY);
946 ZeroMemory(mInfo,
sizeof(MONITORINFOEX));
947 mInfo->cbSize =
sizeof(MONITORINFOEX);
948 if (GetMonitorInfo (hMon, (LPMONITORINFO)mInfo))
956- (BOOL) isRunningOnPrimaryDisplayDevice
959 [
self getCurrentMonitorInfo:&monitorInfo];
960 if (!(monitorInfo.dwFlags & MONITORINFOF_PRIMARY))
968- (void) grabMouseInsideGameWindow:(BOOL) value
973 GetWindowRect(SDL_Window, &gameWindowRect);
974 ClipCursor(&gameWindowRect);
980 grabMouseStatus = !!value;
984- (void) stringToClipboard:(NSString *)stringToCopy
988 const char *clipboardText = [stringToCopy cStringUsingEncoding:NSUTF8StringEncoding];
989 const size_t clipboardTextLength = strlen(clipboardText) + 1;
990 HGLOBAL clipboardMem = GlobalAlloc(GMEM_MOVEABLE, clipboardTextLength);
993 memcpy(GlobalLock(clipboardMem), clipboardText, clipboardTextLength);
994 GlobalUnlock(clipboardMem);
997 if (!SetClipboardData(CF_TEXT, clipboardMem))
999 OOLog(
@"stringToClipboard.failed",
@"Failed to copy string %@ to clipboard", stringToCopy);
1004 GlobalFree(clipboardMem);
1016 SDLMod modState = SDL_GetModState();
1017 Uint8 *keyState = SDL_GetKeyState(NULL);
1018 BYTE keyboardStatus[256];
1019 #define OO_RESET_SDLKEY_MODIFIER(vkCode, kModCode, sdlkCode) do {\
1020 if (keyboardStatus[vkCode] & 0x0080) \
1022 modState |= kModCode; \
1023 keyState[sdlkCode] = SDL_PRESSED; \
1027 modState &= ~kModCode; \
1028 keyState[sdlkCode] = SDL_RELEASED; \
1031 if (GetKeyboardState(keyboardStatus))
1044 OO_RESET_SDLKEY_MODIFIER(VK_LCONTROL, KMOD_LCTRL, SDLK_LCTRL);
1045 OO_RESET_SDLKEY_MODIFIER(VK_RCONTROL, KMOD_RCTRL, SDLK_RCTRL);
1046 ctrl = (modState & KMOD_LCTRL || modState & KMOD_RCTRL);
1049 OO_RESET_SDLKEY_MODIFIER(VK_LSHIFT, KMOD_LSHIFT, SDLK_LSHIFT);
1050 OO_RESET_SDLKEY_MODIFIER(VK_RSHIFT, KMOD_RSHIFT, SDLK_RSHIFT);
1051 shift = (modState & KMOD_LSHIFT || modState & KMOD_RSHIFT);
1054 if (GetKeyState(VK_CAPITAL) & 0x0001)
1056 modState |= KMOD_CAPS;
1057 keyState[SDLK_CAPSLOCK] = SDL_PRESSED;
1061 modState &= ~KMOD_CAPS;
1062 keyState[SDLK_CAPSLOCK] = SDL_RELEASED;
1066 SDL_SetModState(modState);
1070- (void) setWindowBorderless:(BOOL)borderless
1072 LONG currentWindowStyle = GetWindowLong(SDL_Window, GWL_STYLE);
1075 if ((!borderless && (currentWindowStyle & WS_CAPTION)) ||
1076 (borderless && !(currentWindowStyle & WS_CAPTION)))
return;
1080 SetWindowLong(SDL_Window, GWL_STYLE, currentWindowStyle & ~WS_CAPTION & ~WS_THICKFRAME);
1084 SetWindowLong(SDL_Window, GWL_STYLE, currentWindowStyle |
1085 WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX );
1086 [
self refreshDarKOrLightMode];
1088 SetWindowPos(SDL_Window, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
1092- (void) refreshDarKOrLightMode
1094 int shouldSetDarkMode = [
self isDarkModeOn];
1095 DwmSetWindowAttribute (SDL_Window, DWMWA_USE_IMMERSIVE_DARK_MODE, &shouldSetDarkMode,
sizeof(shouldSetDarkMode));
1099- (BOOL) isDarkModeOn
1102 DWORD bufferSize =
sizeof(buffer);
1105 HRESULT resultRegGetValue = RegGetValueW(HKEY_CURRENT_USER, L
"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
1106 L
"AppsUseLightTheme", RRF_RT_REG_DWORD, NULL, buffer, &bufferSize);
1107 if (resultRegGetValue != ERROR_SUCCESS)
1113 int i = (
int)(buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0]);
1120- (BOOL) atDesktopResolution
1122 return atDesktopResolution;
1132- (BOOL) isOutputDisplayHDREnabled
1134 UINT32 pathCount, modeCount;
1135 DISPLAYCONFIG_PATH_INFO *pPathInfoArray;
1136 DISPLAYCONFIG_MODE_INFO *pModeInfoArray;
1137 UINT32 flags = QDC_ONLY_ACTIVE_PATHS | QDC_VIRTUAL_MODE_AWARE;
1138 LONG tempResult = ERROR_SUCCESS;
1139 BOOL isAdvColorInfo2DetectionSuccess = NO;
1145 tempResult = GetDisplayConfigBufferSizes(flags, &pathCount, &modeCount);
1147 if (tempResult != ERROR_SUCCESS)
1149 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %ld", HRESULT_FROM_WIN32(tempResult));
1154 pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(pathCount *
sizeof(DISPLAYCONFIG_PATH_INFO));
1155 if (!pPathInfoArray)
1157 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: -1");
1161 pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(modeCount *
sizeof(DISPLAYCONFIG_MODE_INFO));
1162 if (!pModeInfoArray)
1165 free(pPathInfoArray);
1166 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: -1");
1171 tempResult = QueryDisplayConfig(flags, &pathCount, pPathInfoArray, &modeCount, pModeInfoArray, NULL);
1173 if (tempResult != ERROR_SUCCESS)
1175 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %ld", HRESULT_FROM_WIN32(tempResult));
1180 pPathInfoArray = realloc(pPathInfoArray, pathCount *
sizeof(DISPLAYCONFIG_PATH_INFO));
1181 if (!pPathInfoArray)
1183 OOLogERR(
@"gameView.isOutputDisplayHDREnabled",
@"Failed ro reallocate pPathInfoArray");
1186 pModeInfoArray = realloc(pModeInfoArray, modeCount *
sizeof(DISPLAYCONFIG_MODE_INFO));
1187 if (!pModeInfoArray)
1189 OOLogERR(
@"gameView.isOutputDisplayHDREnabled",
@"Failed to reallocate pModeInfoArray");
1195 }
while (tempResult == ERROR_INSUFFICIENT_BUFFER);
1197 if (tempResult != ERROR_SUCCESS)
1199 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %ld", HRESULT_FROM_WIN32(tempResult));
1205 wchar_t wcsPrimaryDeviceID[256] = L
"OOUnknownDevice";
1210 for (i = 0; i < pathCount; i++)
1213 char saveDeviceName[64];
1215 ZeroMemory(&dd,
sizeof(dd));
1217 EnumDisplayDevices(NULL, i, &dd, 0);
1218 if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
1221 strncpy(saveDeviceName, dd.DeviceName, 33);
1222 while (EnumDisplayDevices(saveDeviceName, j, &dd, 0x00000001))
1224 if (
EXPECT(dd.StateFlags & DISPLAY_DEVICE_ACTIVE))
1227 mbstowcs(wcsPrimaryDeviceID, dd.DeviceID, 129);
1233 OOLogWARN(
@"gameView.isOutputDisplayHDREnabled",
@"Primary monitor candidate %s (%s %s) not active.", dd.DeviceName, dd.DeviceString, dd.DeviceID);
1243 for (i = 0; i < pathCount; i++)
1245 DISPLAYCONFIG_PATH_INFO *path = &pPathInfoArray[i];
1247 DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {};
1248 targetName.header.adapterId = path->targetInfo.adapterId;
1249 targetName.header.id = path->targetInfo.id;
1250 targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
1251 targetName.header.size =
sizeof(targetName);
1252 tempResult = DisplayConfigGetDeviceInfo(&targetName.header);
1254 if (tempResult != ERROR_SUCCESS)
1256 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %ld", HRESULT_FROM_WIN32(tempResult));
1261 DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2 advColorInfo2 = {};
1262 advColorInfo2.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2;
1263 advColorInfo2.header.adapterId = path->targetInfo.adapterId;
1264 advColorInfo2.header.id = path->targetInfo.id;
1265 advColorInfo2.header.size =
sizeof(advColorInfo2);
1267 tempResult = DisplayConfigGetDeviceInfo(&advColorInfo2.header);
1269 if (tempResult == ERROR_SUCCESS) isAdvColorInfo2DetectionSuccess = YES;
1272 OOLogWARN(
@"gameView.isOutputDisplayHDREnabled",
@"Received 0x%08lX while attempting to detect HDR mode using Advanced Color Info 2 API. Retrying detection using legacy API.", HRESULT_FROM_WIN32(tempResult));
1277 DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO advColorInfo = {};
1278 advColorInfo.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO;
1279 advColorInfo.header.adapterId = path->targetInfo.adapterId;
1280 advColorInfo.header.id = path->targetInfo.id;
1281 advColorInfo.header.size =
sizeof(advColorInfo);
1283 tempResult = DisplayConfigGetDeviceInfo(&advColorInfo.header);
1285 if (tempResult != ERROR_SUCCESS)
1287 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"Error! Code: %ld", HRESULT_FROM_WIN32(tempResult));
1291 BOOL isPrimaryDisplayDevice = !wcscmp(targetName.monitorDevicePath, wcsPrimaryDeviceID);
1294 if (isPrimaryDisplayDevice &&
1295 ((isAdvColorInfo2DetectionSuccess && advColorInfo2.highDynamicRangeSupported && advColorInfo2.activeColorMode == DISPLAYCONFIG_ADVANCED_COLOR_MODE_HDR) ||
1296 (!isAdvColorInfo2DetectionSuccess && advColorInfo.advancedColorSupported && advColorInfo.advancedColorEnabled && !advColorInfo.wideColorEnforced)))
1303 OOLog(
@"gameView.isOutputDisplayHDREnabled",
@"HDR display output requested - checking availability: %@", result ?
@"YES" :
@"NO");
1305 free (pModeInfoArray);
1306 free (pPathInfoArray);
1312- (float) hdrMaxBrightness
1314 return _hdrMaxBrightness;
1318- (void) setHDRMaxBrightness: (
float)newMaxBrightness
1322 _hdrMaxBrightness = newMaxBrightness;
1324 [[NSUserDefaults standardUserDefaults] setFloat:_hdrMaxBrightness forKey:@"hdr-max-brightness"];
1328- (float) hdrPaperWhiteBrightness
1330 return _hdrPaperWhiteBrightness;
1334- (void) setHDRPaperWhiteBrightness: (
float)newPaperWhiteBrightness
1338 _hdrPaperWhiteBrightness = newPaperWhiteBrightness;
1340 [[NSUserDefaults standardUserDefaults] setFloat:_hdrPaperWhiteBrightness forKey:@"hdr-paperwhite-brightness"];
1346 return _hdrToneMapper;
1354 _hdrToneMapper = newToneMapper;
1367- (void) grabMouseInsideGameWindow:(BOOL) value
1373- (void) stringToClipboard:(NSString *)stringToCopy
1385- (void) setWindowBorderless:(BOOL)borderless
1419- (void) initialiseGLWithSize:(NSSize) v_size
1425- (void) initialiseGLWithSize:(NSSize) v_size useVideoMode:(BOOL) v_mode
1431 OOLog(
@"display.initGL",
@"Requested a new surface of %d x %d, %@.", (
int)
viewSize.width, (
int)
viewSize.height,(
fullScreen ?
@"fullscreen" :
@"windowed"));
1432 SDL_GL_SwapBuffers();
1435 if (!updateContext)
return;
1438 settings.dmSize =
sizeof(DEVMODE);
1439 settings.dmDriverExtra = 0;
1440 EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &settings);
1442 WINDOWPLACEMENT windowPlacement;
1443 windowPlacement.length =
sizeof(WINDOWPLACEMENT);
1444 GetWindowPlacement(SDL_Window, &windowPlacement);
1446 static BOOL lastWindowPlacementMaximized = NO;
1447 if (
fullScreen && (windowPlacement.showCmd == SW_SHOWMAXIMIZED))
1451 lastWindowPlacementMaximized = YES;
1455 if (lastWindowPlacementMaximized)
1457 windowPlacement.showCmd = SW_SHOWMAXIMIZED;
1464 (wasFullScreen && (settings.dmPelsWidth != [[[screenSizes objectAtIndex:0] objectForKey: kOODisplayWidth] intValue]
1465 || settings.dmPelsHeight != [[[screenSizes objectAtIndex:0] objectForKey: kOODisplayHeight] intValue])));
1477 [
self getCurrentMonitorInfo: &monitorInfo];
1479 settings.dmPelsWidth =
viewSize.width;
1480 settings.dmPelsHeight =
viewSize.height;
1481 settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1486 if(lastWindowPlacementMaximized)
1488 CopyRect(&lastGoodRect, &windowPlacement.rcNormalPosition);
1490 windowPlacement.showCmd = SW_SHOWNORMAL;
1491 SetWindowPlacement(SDL_Window, &windowPlacement);
1493 else GetWindowRect(SDL_Window, &lastGoodRect);
1496 SetForegroundWindow(SDL_Window);
1497 if (changingResolution)
1499 if (ChangeDisplaySettingsEx(monitorInfo.szDevice, &settings, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)
1502 OOLogERR(
@"displayMode.change.error",
@"Could not switch to requested display mode.");
1505 atDesktopResolution = settings.dmPelsWidth == [[[screenSizes objectAtIndex:0] objectForKey: kOODisplayWidth] intValue]
1506 && settings.dmPelsHeight == [[[screenSizes objectAtIndex:0] objectForKey: kOODisplayHeight] intValue];
1509 MoveWindow(SDL_Window, monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top, (
int)
viewSize.width, (
int)
viewSize.height, TRUE);
1516 else if ( wasFullScreen )
1518 if (changingResolution)
1521 if (ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL) == DISP_CHANGE_SUCCESSFUL)
1523 atDesktopResolution = YES;
1535 [
self getCurrentMonitorInfo: &monitorInfo];
1537 if (lastWindowPlacementMaximized) CopyRect(&windowPlacement.rcNormalPosition, &lastGoodRect);
1538 SetWindowPlacement(SDL_Window, &windowPlacement);
1539 if (!lastWindowPlacementMaximized)
1541 MoveWindow(SDL_Window, (monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left - (
int)
viewSize.width)/2 +
1542 monitorInfo.rcMonitor.left,
1543 (monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top - (
int)
viewSize.height)/2 +
1544 monitorInfo.rcMonitor.top,
1550 lastWindowPlacementMaximized = NO;
1551 ShowWindow(SDL_Window,SW_SHOW);
1555 saveSize = !wasFullScreen;
1557 GetClientRect(SDL_Window, &wDC);
1560 ||
bounds.size.height != wDC.bottom - wDC.top))
1569 RECT desiredClientRect;
1570 GetWindowRect(SDL_Window, &desiredClientRect);
1571 AdjustWindowRect(&desiredClientRect, WS_CAPTION | WS_THICKFRAME, FALSE);
1572 SetWindowPos(SDL_Window, NULL, desiredClientRect.left, desiredClientRect.top,
1573 desiredClientRect.right - desiredClientRect.left,
1574 desiredClientRect.bottom - desiredClientRect.top, 0);
1576 GetClientRect(SDL_Window, &wDC);
1577 viewSize.width = wDC.right - wDC.left;
1578 viewSize.height = wDC.bottom - wDC.top;
1587 bounds.origin.x = monitorInfo.rcMonitor.left;
1588 bounds.origin.y = monitorInfo.rcMonitor.top;
1594 int videoModeFlags = SDL_HWSURFACE | SDL_OPENGL;
1597 videoModeFlags |= SDL_NOFRAME;
1600 videoModeFlags |= SDL_FULLSCREEN;
1604 videoModeFlags |= SDL_RESIZABLE;
1612 videoModeFlags &= ~SDL_FULLSCREEN;
1613 videoModeFlags |= SDL_RESIZABLE;
1620 OOLogERR(
@"display.mode.error",
@"Unable to change display mode: %s",SDL_GetError());
1628 OOLog(
@"display.initGL",
@"Created a new surface of %d x %d, %@.", (
int)
viewSize.width, (
int)
viewSize.height,(
fullScreen ?
@"fullscreen" :
@"windowed"));
1645 SDL_GL_SwapBuffers();
1658- (void) adjustColorSaturation:(
float)colorSaturationAdjustment;
1665- (BOOL) snapShot:(NSString *)filename
1667 BOOL snapShotOK = YES;
1668 SDL_Surface* tmpSurface;
1671 NSString* originalDirectory = [[
NSFileManager defaultManager] currentDirectoryPath];
1676 static unsigned imageNo = 0;
1677 unsigned tmpImageNo = 0;
1678 NSString *pathToPic =
nil;
1679 NSString *baseName =
@"oolite";
1681#if SNAPSHOTS_PNG_FORMAT
1682 NSString *extension =
@".png";
1684 NSString *extension =
@".bmp";
1690 pathToPic = [filename stringByAppendingString:extension];
1694 tmpImageNo = imageNo;
1697 if (withFilename && [[NSFileManager defaultManager] fileExistsAtPath:pathToPic])
1699 OOLog(
@"screenshot.filenameExists",
@"Snapshot \"%@%@\
" already exists - adding numerical sequence.", pathToPic, extension);
1703 if (pathToPic ==
nil)
1708 pathToPic = [
NSString stringWithFormat:@"%@-%03d%@", baseName, tmpImageNo, extension];
1709 }
while ([[NSFileManager defaultManager] fileExistsAtPath:pathToPic]);
1714 imageNo = tmpImageNo;
1717 OOLog(
@"screenshot",
@"Saving screen shot \"%@\
" (%u x %u pixels).", pathToPic,
surface->w,
surface->h);
1720 unsigned char *pixls = malloc(pitch *
surface->h);
1724 if (
surface->w % 4) glPixelStorei(GL_PACK_ALIGNMENT,1);
1725 else glPixelStorei(GL_PACK_ALIGNMENT,4);
1726 for (
y=
surface->h-1, off=0;
y>=0;
y--, off+=pitch)
1728 glReadPixels(0,
y,
surface->w, 1, GL_RGB, GL_UNSIGNED_BYTE, pixls + off);
1731 tmpSurface=SDL_CreateRGBSurfaceFrom(pixls,
surface->w,
surface->h,24,
surface->w*3,0xFF,0xFF00,0xFF0000,0x0);
1732#if SNAPSHOTS_PNG_FORMAT
1733 if(![
self pngSaveSurface:pathToPic withSurface:tmpSurface])
1735 OOLog(
@"screenshotPNG",
@"Failed to save %@", pathToPic);
1739 if (SDL_SaveBMP(tmpSurface, [pathToPic UTF8String]) == -1)
1741 OOLog(
@"screenshotBMP",
@"Failed to save %@", pathToPic);
1745 SDL_FreeSurface(tmpSurface);
1751 NSString *fileExtension = [[
NSUserDefaults standardUserDefaults] oo_stringForKey:@"hdr-snapshot-format" defaultValue:SNAPSHOTHDR_EXTENSION_DEFAULT];
1754 if (![[fileExtension substringToIndex:1] isEqual:
@"."]) fileExtension = [@"."
stringByAppendingString:fileExtension];
1762 NSString *pathToPicHDR = [
pathToPic stringByReplacingString:@".png" withString:fileExtension];
1763 OOLog(
@"screenshot",
@"Saving screen shot \"%@\
" (%u x %u pixels).", pathToPicHDR,
surface->w,
surface->h);
1764 GLfloat *pixlsf = (GLfloat *)malloc(pitch *
surface->h *
sizeof(GLfloat));
1765 for (
y=
surface->h-1, off=0;
y>=0;
y--, off+=pitch)
1767 glReadPixels(0,
y,
surface->w, 1, GL_RGB, GL_FLOAT, pixlsf + off);
1773 OOLog(
@"screenshotHDR",
@"Failed to save %@", pathToPicHDR);
1781 [[
NSFileManager defaultManager] changeCurrentDirectoryPath:originalDirectory];
1786#if SNAPSHOTS_PNG_FORMAT
1788- (BOOL) pngSaveSurface:(NSString *)fileName withSurface:(SDL_Surface *)surf
1794 png_bytep *rowPointers;
1796 fp = fopen([fileName UTF8String],
"wb");
1799 OOLog(
@"pngSaveSurface.fileCreate.failed",
@"Failed to create output screenshot file %@", fileName);
1804 pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1810 infoPtr = png_create_info_struct(pngPtr);
1811 if (infoPtr == NULL) {
1812 png_destroy_write_struct(&pngPtr, (png_infopp)NULL);
1813 OOLog(
@"pngSaveSurface.info_struct.failed",
@"%@",
@"png_create_info_struct error");
1817 if (setjmp(png_jmpbuf(pngPtr)))
1819 png_destroy_write_struct(&pngPtr, &infoPtr);
1824 png_init_io(pngPtr, fp);
1826 colorType = PNG_COLOR_MASK_COLOR;
1827 if (surf->format->palette)
1829 colorType |= PNG_COLOR_MASK_PALETTE;
1831 else if (surf->format->Amask)
1833 colorType |= PNG_COLOR_MASK_ALPHA;
1836 png_set_IHDR(pngPtr, infoPtr, surf->w, surf->h, 8, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1840 if ([
self hdrOutput]) png_set_gAMA(pngPtr, infoPtr, 1.0f);
1843 png_write_info(pngPtr, infoPtr);
1844 png_set_packing(pngPtr);
1846 rowPointers = (png_bytep*) malloc(
sizeof(png_bytep)*surf->h);
1847 for (i = 0; i < surf->h; i++)
1849 rowPointers[
i] = (png_bytep)(Uint8 *)surf->pixels + i*surf->pitch;
1851 png_write_image(pngPtr, rowPointers);
1852 png_write_end(pngPtr, infoPtr);
1855 png_destroy_write_struct(&pngPtr, &infoPtr);
1864- (
int) translateKeyCode: (
int) input
1869 case NSUpArrowFunctionKey:
1873 case NSDownArrowFunctionKey:
1877 case NSLeftArrowFunctionKey:
1881 case NSRightArrowFunctionKey:
1885 case NSF1FunctionKey:
1889 case NSF2FunctionKey:
1893 case NSF3FunctionKey:
1897 case NSF4FunctionKey:
1901 case NSF5FunctionKey:
1905 case NSF6FunctionKey:
1909 case NSF7FunctionKey:
1913 case NSF8FunctionKey:
1917 case NSF9FunctionKey:
1921 case NSF10FunctionKey:
1925 case NSF11FunctionKey:
1929 case NSHomeFunctionKey:
1940- (void) setVirtualJoystick:(
double) vmx :(
double) vmy
1959 for (i = 0; i < [
self numKeys]; i++)
1966 keys[gvMouseDoubleClick] = NO;
1967 keys[gvMouseLeftButton] = NO;
1972- (void) clearKey: (
int)theKey
1974 if (theKey >= 0 && theKey < [
self numKeys])
1983 [
self setVirtualJoystick:0.0 :0.0];
2016- (BOOL) isDown: (
int) key
2060 return (SDL_GetModState() & KMOD_CAPS) == KMOD_CAPS;
2092- (void) setMouseWheelDelta: (
float) newWheelDelta
2119 SDL_KeyboardEvent *kbd_event;
2120 SDL_MouseButtonEvent *mbtn_event;
2121 SDL_MouseMotionEvent *mmove_event;
2122 int mxdelta, mydelta;
2125 NSTimeInterval timeNow = [
NSDate timeIntervalSinceReferenceDate];
2129 while (SDL_PollEvent(&event))
2131 switch (event.type) {
2132 case SDL_JOYAXISMOTION:
2133 case SDL_JOYBUTTONUP:
2134 case SDL_JOYBUTTONDOWN:
2135 case SDL_JOYHATMOTION:
2139 case SDL_MOUSEBUTTONDOWN:
2140 mbtn_event = (SDL_MouseButtonEvent*)&event;
2145 short inDelta = mbtn_event->wheelDelta;
2147 switch(mbtn_event->button)
2149 case SDL_BUTTON_LEFT:
2150 keys[gvMouseLeftButton] = YES;
2152 case SDL_BUTTON_RIGHT:
2164 case SDL_BUTTON_WHEELUP:
2167 case SDL_BUTTON_WHEELDOWN:
2170 case SDL_BUTTON_WHEELUP:
2171 case SDL_BUTTON_WHEELDOWN:
2180 else if (inDelta < 0)
2191 case SDL_MOUSEBUTTONUP:
2192 mbtn_event = (SDL_MouseButtonEvent*)&event;
2195 if (mbtn_event->button == SDL_BUTTON_LEFT)
2202 keys[gvMouseLeftButton] = NO;
2210 if (mbtn_event->button == SDL_BUTTON_WHEELUP || mbtn_event->button == SDL_BUTTON_WHEELDOWN)
2217 case SDL_MOUSEMOTION:
2230 SDL_GetRelativeMouseState(&mxdelta, &mydelta);
2231 double mxd=(double)mxdelta / mouseVirtualStickSensitivityX;
2232 double myd=(double)mydelta / mouseVirtualStickSensitivityY;
2261 mmove_event = (SDL_MouseMotionEvent*)&event;
2264 int h=
bounds.size.height;
2268 double mx = mmove_event->x - w/2.0;
2269 double my = mmove_event->y - h/2.0;
2281 [
self setVirtualJoystick:mx :my];
2292 kbd_event = (SDL_KeyboardEvent*)&event;
2293 key_id = (Uint16)kbd_event->keysym.unicode;
2294 scan_code = kbd_event->keysym.scancode;
2298 BOOL modifier_pressed = NO;
2299 BOOL special_key = NO;
2302 switch (kbd_event->keysym.sym)
2307 modifier_pressed = YES;
2313 modifier_pressed = YES;
2319 modifier_pressed = YES;
2339 case SDLK_HOME: key_id =
gvHomeKey; special_key = YES;
break;
2340 case SDLK_END: key_id =
gvEndKey; special_key = YES;
break;
2341 case SDLK_INSERT: key_id =
gvInsertKey; special_key = YES;
break;
2342 case SDLK_PAGEUP: key_id =
gvPageUpKey; special_key = YES;
break;
2343 case SDLK_PAGEDOWN: key_id =
gvPageDownKey; special_key = YES;
break;
2344 case SDLK_SPACE: key_id = 32; special_key = YES;
break;
2345 case SDLK_RETURN: key_id = 13; special_key = YES;
break;
2346 case SDLK_TAB: key_id = 9; special_key = YES;
break;
2347 case SDLK_UP: key_id =
gvArrowKeyUp; special_key = YES;
break;
2348 case SDLK_DOWN: key_id =
gvArrowKeyDown; special_key = YES;
break;
2349 case SDLK_LEFT: key_id =
gvArrowKeyLeft; special_key = YES;
break;
2351 case SDLK_PAUSE: key_id =
gvPauseKey; special_key = YES;
break;
2352 case SDLK_BACKSPACE: key_id =
gvBackspaceKey; special_key = YES;
break;
2353 case SDLK_DELETE: key_id =
gvDeleteKey; special_key = YES;
break;
2394 if (
ctrl && key_id >=1 && key_id <= 26)
2414 NSString *keyNormal = [keyMappings_normal objectForKey:[
NSString stringWithFormat:@"%d", scan_code]];
2415 if (keyNormal) key_id = [
keyNormal integerValue];
2419 NSString *keyShifted = [keyMappings_shifted objectForKey:[
NSString stringWithFormat:@"%d", scan_code]];
2420 if (keyShifted) key_id = [
keyShifted integerValue];
2432 OOLog(
kOOLogKeyDown,
@"Keydown scancode = %d, unicode = %i, sym = %i, character = %c, shift = %d, ctrl = %d, alt = %d", scan_code, key_id, kbd_event->keysym.sym, key_id,
shift,
ctrl,
opt);
2435 if (key_id > 0 && key_id <= [
self numKeys])
2447 kbd_event = (SDL_KeyboardEvent*)&event;
2448 scan_code = kbd_event->keysym.scancode;
2454 switch (kbd_event->keysym.sym)
2473 OOLog(
kOOLogKeyUp,
@"Keyup scancode = %d, unicode = %i, sym = %i, character = %c, shift = %d, ctrl = %d, alt = %d", scan_code, key_id, kbd_event->keysym.sym, key_id,
shift,
ctrl,
opt);
2477 switch (kbd_event->keysym.sym)
2496 case SDLK_HOME: key_id =
gvHomeKey;
break;
2497 case SDLK_END: key_id =
gvEndKey;
break;
2501 case SDLK_SPACE: key_id = 32;
break;
2502 case SDLK_RETURN: key_id = 13;
break;
2503 case SDLK_TAB: key_id = 9;
break;
2504 case SDLK_ESCAPE: key_id = 27;
break;
2521 case SDLK_F12: key_id = 327;
break;
2530 if (key_id > 0 && key_id <= [
self numKeys])
2540 case SDL_VIDEORESIZE:
2542 SDL_ResizeEvent *rsevt=(SDL_ResizeEvent *)&event;
2543 NSSize newSize=NSMakeSize(rsevt->w, rsevt->h);
2579 case SDL_ACTIVEEVENT:
2581 if ((event.active.state & SDL_APPACTIVE) &&
fullScreen)
2592 case SDL_SYSWMEVENT:
2594 DWORD dwLastError = 0;
2595 switch (event.syswm.msg->msg)
2597 case WM_WINDOWPOSCHANGING:
2617 wp.length =
sizeof(WINDOWPLACEMENT);
2618 GetWindowPlacement(SDL_Window, &wp);
2620 GetWindowRect(SDL_Window, &rDC);
2621 if (rDC.left != monitorInfo.rcMonitor.left || rDC.top != monitorInfo.rcMonitor.top)
2623 BOOL fullScreenMaximized = NO;
2624 if (wp.showCmd == SW_SHOWMAXIMIZED && !fullScreenMaximized)
2626 fullScreenMaximized = YES;
2627 wp.showCmd = SW_SHOWNORMAL;
2628 SetWindowPlacement(SDL_Window, &wp);
2631 if (wp.showCmd != SW_SHOWMINIMIZED && wp.showCmd != SW_MINIMIZE)
2633 MoveWindow(SDL_Window, monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top,
2637 if (fullScreenMaximized)
2639 GetWindowPlacement(SDL_Window, &wp);
2640 wp.showCmd = SW_SHOWMAXIMIZED;
2641 CopyRect(&wp.rcNormalPosition, &lastGoodRect);
2642 SetWindowPlacement(SDL_Window, &wp);
2645 else if (wp.showCmd == SW_SHOWMAXIMIZED)
2647 CopyRect(&wp.rcNormalPosition, &lastGoodRect);
2648 SetWindowPlacement(SDL_Window, &wp);
2663 case WM_ACTIVATEAPP:
2667 case WM_SETTINGCHANGE:
2677 [
self refreshDarKOrLightMode];
2689 if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL))
2691 dwLastError = GetLastError();
2692 OOLog(
@"wm_setfocus.message",
@"Setting thread priority to time critical failed! (error code: %ld)", dwLastError);
2697 if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL))
2699 dwLastError = GetLastError();
2700 OOLog(
@"wm_killfocus.message",
@"Setting thread priority to normal failed! (error code: %ld)", dwLastError);
2731- (void) handleStringInput: (SDL_KeyboardEvent *) kbd_event keyID:(Uint16)key_id;
2733 SDLKey key=kbd_event->keysym.sym;
2736 if((key == SDLK_BACKSPACE || key == SDLK_DELETE) && [typedString length] > 0)
2742 isAlphabetKeyDown=NO;
2745 if([typedString length] < 40)
2747 lastKeyShifted = shift;
2751 if(key >= SDLK_a && key <= SDLK_z)
2753 isAlphabetKeyDown=YES;
2762 if (key_id >= 32 && key_id <= 255)
2766 isAlphabetKeyDown=YES;
2780 NSMutableDictionary *
mode;
2787 [screenSizes addObject: mode];
2789 modes=SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE);
2790 if(modes == (SDL_Rect **)NULL)
2792 OOLog(
@"display.mode.list.none",
@"%@",
@"SDL didn't return any screen modes");
2796 if(modes == (SDL_Rect **)-1)
2798 OOLog(
@"display.mode.list.none",
@"%@",
@"SDL claims 'all resolutions available' which is unhelpful in the extreme");
2802 int lastw=[[mode objectForKey: kOODisplayWidth] intValue];
2803 int lasth=[[mode objectForKey: kOODisplayHeight] intValue];
2804 for(i=0; modes[
i]; i++)
2810 if(modes[i]->w != lastw || modes[i]->h != lasth)
2814 [mode setValue: [
NSNumber numberWithInt: (int)modes[
i]->w]
2815 forKey: kOODisplayWidth];
2816 [mode setValue: [
NSNumber numberWithInt: (int)modes[
i]->h]
2817 forKey: kOODisplayHeight];
2818 [mode setValue: [
NSNumber numberWithInt: 0]
2819 forKey: kOODisplayRefreshRate];
2822 [screenSizes addObject: mode];
2823 OOLog(
@"display.mode.list",
@"Added res %d x %d", modes[i]->w, modes[i]->h);
2833- (void) saveWindowSize: (NSSize) windowSize
2836 [
defaults setInteger: (int)windowSize.width forKey: @"window_width"];
2837 [
defaults setInteger: (int)windowSize.height forKey: @"window_height"];
2846 if([defaults objectForKey:
@"window_width"] && [defaults objectForKey:
@"window_height"])
2848 windowSize=NSMakeSize([defaults integerForKey:
@"window_width"],
2849 [defaults integerForKey:
@"window_height"]);
2863 int width=0, height=0, refresh=0;
2866 NSArray* cmdline_arguments = [[
NSProcessInfo processInfo] arguments];
2868 NSUserDefaults *userDefaults = [
NSUserDefaults standardUserDefaults];
2869 if ([userDefaults objectForKey:
@"display_width"])
2871 if ([userDefaults objectForKey:
@"display_height"])
2872 height = [
userDefaults integerForKey:@"display_height"];
2873 if ([userDefaults objectForKey:
@"display_refresh"])
2874 refresh = [
userDefaults integerForKey:@"display_refresh"];
2875 if([userDefaults objectForKey:
@"fullscreen"])
2883 if ([[cmdline_arguments objectAtIndex:i] isEqual:
@"-fullscreen"])
fullScreen = YES;
2884 if ([[cmdline_arguments objectAtIndex:i] isEqual:
@"-windowed"])
fullScreen = NO;
2896- (
int) findDisplayModeForWidth:(
unsigned int) d_width Height:(
unsigned int) d_height Refresh:(
unsigned int) d_refresh
2900 unsigned int modeWidth, modeHeight, modeRefresh;
2902 modeCount = [screenSizes count];
2904 for (i = 0; i < modeCount; i++)
2906 mode = [screenSizes objectAtIndex: i];
2907 modeWidth = [[mode objectForKey: kOODisplayWidth] intValue];
2908 modeHeight = [[mode objectForKey: kOODisplayHeight] intValue];
2909 modeRefresh = [[mode objectForKey: kOODisplayRefreshRate] intValue];
2910 if ((modeWidth == d_width)&&(modeHeight == d_height)&&(modeRefresh == d_refresh))
2912 OOLog(
@"display.mode.found",
@"Found mode %@",
mode);
2917 OOLog(
@"display.mode.found.failed",
@"Failed to find mode: width=%d height=%d refresh=%d", d_width, d_height, d_refresh);
2918 OOLog(
@"display.mode.found.failed.list",
@"Contents of list: %@",
screenSizes);
2925 NSDictionary *
mode=[screenSizes objectAtIndex: currentSize];
2932 OOLog(
@"display.mode.unknown",
@"%@",
@"Screen size unknown!");
2937- (void) setMouseInDeltaMode: (BOOL) inDelta
2943- (void) setGammaValue: (
float) value
2945 if (value < 0.2f) value = 0.2f;
2946 if (value > 4.0f) value = 4.0f;
2951 [[
NSUserDefaults standardUserDefaults] setFloat:_gamma forKey:@"gamma-value"];
2961- (void) setFov:(
float)value fromFraction:(BOOL)fromFraction
2963 _fov = fromFraction ? value : tan((value / 2) *
M_PI / 180);
2967- (float) fov:(BOOL)inFraction
2969 return inFraction ?
_fov : 2 * atan(
_fov) * 180 /
M_PI;
2979- (void) setMsaa:(BOOL)newMsaa
2994 return 0 != (SDL_GetModState() & (KMOD_LSHIFT | KMOD_RSHIFT));
2998 return 0 != (GetKeyState(VK_SHIFT) & 0x100);
3004- (void) dumpRGBAToFileNamed:(NSString *)name
3005 bytes:(uint8_t *)bytes
3006 width:(NSUInteger)width
3007 height:(NSUInteger)height
3008 rowBytes:(NSUInteger)rowBytes
3010 if (name ==
nil || bytes == NULL || width == 0 || height == 0 || rowBytes < width * 4)
return;
3013 NSString *dumpFile = [[
NSHomeDirectory() stringByAppendingPathComponent:@SAVEDIR] stringByAppendingPathComponent:@SNAPSHOTDIR];
3014 dumpFile = [
dumpFile stringByAppendingPathComponent: [
NSString stringWithFormat:@"%@.bmp", name]];
3017 SDL_Surface* tmpSurface = SDL_CreateRGBSurfaceFrom(bytes, width, height, 32, rowBytes, 0xFF, 0xFF00, 0xFF0000, 0xFF000000);
3018 SDL_SaveBMP(tmpSurface, [dumpFile UTF8String]);
3019 SDL_FreeSurface(tmpSurface);
3023- (void) dumpRGBToFileNamed:(NSString *)name
3024 bytes:(uint8_t *)bytes
3025 width:(NSUInteger)width
3026 height:(NSUInteger)height
3027 rowBytes:(NSUInteger)rowBytes
3029 if (name ==
nil || bytes == NULL || width == 0 || height == 0 || rowBytes < width * 3)
return;
3032 NSString *dumpFile = [[
NSHomeDirectory() stringByAppendingPathComponent:@SAVEDIR] stringByAppendingPathComponent:@SNAPSHOTDIR];
3033 dumpFile = [
dumpFile stringByAppendingPathComponent: [
NSString stringWithFormat:@"%@.bmp", name]];
3035 SDL_Surface* tmpSurface = SDL_CreateRGBSurfaceFrom(bytes, width, height, 24, rowBytes, 0xFF, 0xFF00, 0xFF0000, 0x0);
3036 SDL_SaveBMP(tmpSurface, [dumpFile UTF8String]);
3037 SDL_FreeSurface(tmpSurface);
3041- (void) dumpGrayToFileNamed:(NSString *)name
3042 bytes:(uint8_t *)bytes
3043 width:(NSUInteger)width
3044 height:(NSUInteger)height
3045 rowBytes:(NSUInteger)rowBytes
3047 if (name ==
nil || bytes == NULL || width == 0 || height == 0 || rowBytes < width)
return;
3050 NSString *dumpFile = [[
NSHomeDirectory() stringByAppendingPathComponent:@SAVEDIR] stringByAppendingPathComponent:@SNAPSHOTDIR];
3051 dumpFile = [
dumpFile stringByAppendingPathComponent: [
NSString stringWithFormat:@"%@.bmp", name]];
3053 SDL_Surface* tmpSurface = SDL_CreateRGBSurfaceFrom(bytes, width, height, 8, rowBytes, 0xFF, 0xFF, 0xFF, 0x0);
3054 SDL_SaveBMP(tmpSurface, [dumpFile UTF8String]);
3055 SDL_FreeSurface(tmpSurface);
3059- (void) dumpGrayAlphaToFileNamed:(NSString *)name
3060 bytes:(uint8_t *)bytes
3061 width:(NSUInteger)width
3062 height:(NSUInteger)height
3063 rowBytes:(NSUInteger)rowBytes
3065 if (name ==
nil || bytes == NULL || width == 0 || height == 0 || rowBytes < width * 2)
return;
3068 NSString *dumpFile = [[
NSHomeDirectory() stringByAppendingPathComponent:@SAVEDIR] stringByAppendingPathComponent:@SNAPSHOTDIR];
3069 dumpFile = [
dumpFile stringByAppendingPathComponent: [
NSString stringWithFormat:@"%@.bmp", name]];
3071 SDL_Surface* tmpSurface = SDL_CreateRGBSurfaceFrom(bytes, width, height, 16, rowBytes, 0xFF, 0xFF, 0xFF, 0xFF);
3072 SDL_SaveBMP(tmpSurface, [dumpFile UTF8String]);
3073 SDL_FreeSurface(tmpSurface);
3077- (void) dumpRGBAToRGBFileNamed:(NSString *)rgbName
3078 andGrayFileNamed:(NSString *)grayName
3079 bytes:(uint8_t *)bytes
3080 width:(NSUInteger)width
3081 height:(NSUInteger)height
3082 rowBytes:(NSUInteger)rowBytes
3084 if ((rgbName ==
nil && grayName ==
nil) || bytes == NULL || width == 0 || height == 0 || rowBytes < width * 4)
return;
3086 uint8_t *rgbBytes, *rgbPx, *grayBytes, *grayPx, *srcPx;
3088 BOOL trivalAlpha = YES;
3090 rgbPx = rgbBytes = malloc(width * height * 3);
3091 if (rgbBytes == NULL)
return;
3093 grayPx = grayBytes = malloc(width * height);
3094 if (grayBytes == NULL)
3100 for (
y = 0;
y < height;
y++)
3102 srcPx = bytes + rowBytes *
y;
3104 for (
x = 0;
x < width;
x++)
3106 *rgbPx++ = *srcPx++;
3107 *rgbPx++ = *srcPx++;
3108 *rgbPx++ = *srcPx++;
3109 trivalAlpha = trivalAlpha && ((*srcPx == 0xFF) || (*srcPx == 0x00));
3110 *grayPx++ = *srcPx++;
static NSString * kOOLogKeyDown
static NSString * kOOLogKeyUp
#define MAIN_GUI_PIXEL_WIDTH
#define MAIN_GUI_PIXEL_HEIGHT
OOSDRToneMapper OOSDRToneMapperFromString(NSString *string)
OOHDRToneMapper OOHDRToneMapperFromString(NSString *string)
#define OOLogWARN(class, format,...)
#define OOLogERR(class, format,...)
#define OOLog(class, format,...)
#define OOVerifyOpenGLState()
#define OOSetOpenGLState(STATE)
int SaveEXRSnapshot(const char *outfilename, int width, int height, const float *rgb)
#define MOUSE_DOUBLE_CLICK_INTERVAL
#define SNAPSHOTHDR_EXTENSION_HDR
@ OOHDR_TONEMAPPER_REINHARD
#define MAX_COLOR_SATURATION
@ OOSDR_TONEMAPPER_REINHARD
#define SNAPSHOTHDR_EXTENSION_DEFAULT
#define OOMOUSEWHEEL_EVENTS_DELAY_INTERVAL
#define WINDOW_SIZE_DEFAULT_HEIGHT
#define MIN_HDR_MAXBRIGHTNESS
#define MIN_HDR_PAPERWHITE
#define WINDOW_SIZE_DEFAULT_WIDTH
#define OOMOUSEWHEEL_DELTA
#define SNAPSHOTHDR_EXTENSION_EXR
#define MAX_HDR_MAXBRIGHTNESS
#define MAX_HDR_PAPERWHITE
int SaveEXRSnapshot(const char *outfilename, int width, int height, const float *rgb)
void resetSDLKeyModifiers()
void setUpBasicOpenGLStateWithSize:(NSSize viewSize)
void exitAppWithContext:(NSString *context)
BOOL m_glContextInitialized
void saveWindowSize:(NSSize windowSize)
void initialiseGLWithSize:(NSSize v_size)
void grabMouseInsideGameWindow:(BOOL value)
void handleStringInput:keyID:(SDL_KeyboardEvent *kbd_event, [keyID] Uint16 key_id)
void setFullScreenMode:(BOOL fsm)
void suppressKeysUntilKeyUp()
BOOL isOutputDisplayHDREnabled()
void drawRect:(NSRect rect)
void initKeyMappingData()
int loadFullscreenSettings()
NSMutableDictionary * getNativeSize()
NSDictionary * keyMappings_shifted
float _mouseVirtualStickSensitivityFactor
void populateFullScreenModelist()
int findDisplayModeForWidth:Height:Refresh:(unsigned int d_width,[Height] unsigned int d_height,[Refresh] unsigned int d_refresh)
NSMutableString * typedString
NSMutableArray * screenSizes
int scancode2Unicode[NUM_KEYS]
void setMouseInDeltaMode:(BOOL inDelta)
void initialiseGLWithSize:useVideoMode:(NSSize v_size,[useVideoMode] BOOL v_mode)
NSPoint virtualJoystickPosition
BOOL isRunningOnPrimaryDisplayDevice()
void setWindowBorderless:(BOOL borderless)
OOOpenGLMatrixManager * getOpenGLMatrixManager()
NSTimeInterval timeSinceLastMouseWheel
OOOpenGLMatrixManager * matrixManager
NSTimeInterval timeIntervalAtLastClick
NSSize currentScreenSize()
void updateScreenWithVideoMode:(BOOL v_mode)
void resetSDLKeyModifiers()
void dumpGrayToFileNamed:bytes:width:height:rowBytes:(NSString *name,[bytes] uint8_t *bytes,[width] NSUInteger width,[height] NSUInteger height,[rowBytes] NSUInteger rowBytes)
OOSDRToneMapper sdrToneMapper()
void dumpRGBToFileNamed:bytes:width:height:rowBytes:(NSString *name,[bytes] uint8_t *bytes,[width] NSUInteger width,[height] NSUInteger height,[rowBytes] NSUInteger rowBytes)
NSDictionary * keyMappings_normal
GameController * gameController
BOOL setStickHandlerClass:(Class aClass)
void orthoLeft:right:bottom:top:near:far:(double l,[right] double r,[bottom] double b,[top] double t,[near] double n,[far] double f)
BOOL handleSDLEvent:(SDL_Event *evt)
void doGuiScreenResizeUpdates()
PlayerEntity * sharedPlayer()
NSDictionary * dictionaryFromFilesNamed:inFolder:mergeMode:cache:(NSString *fileName,[inFolder] NSString *folderName,[mergeMode] OOResourceMergeMode mergeMode,[cache] BOOL useCache)
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data)